ああ、ゴミが。否、ゴミでなくとも不要なものは全て。しかし、不要なものをゴミというなら、たとえほんのちょっと前まで部屋のすみで偉そうにしていた、それであっても。


承前。

 

センサーノードで生じた問題というのは、実行時に生じるOut of memory エラー。Stationモードで通常動作していても、APモードに切り替えた途端、起動しなかったりする。
しなかったりする、というがこれまた微妙なところで、一見うまくいったように見えても、電波出して端末と接続して(手製の)HTTPサーバーまで動いているのに、突然PANICで終わる。

 

コールバックスタイルなので、プログラム動作中でもシリアルコンソールは動きます。なので、ここからヒープやグローバルの内容を調べて原因を探ることになりますが、まあ、どこをどう攻めていいやら、手がかりがつかめず難儀しました。

開発者向けのFAQ(https://github.com/TerryE/nodemcu-firmware/blob/b094e382ee23e8fa74a6c8d4a129c1ef14905c8b/docs/en/lua-developer-faq.md)があって、英文なのでGoogle翻訳にかけて(こちらも容量オーバーで一括翻訳できないので、適当に区切ってコピペ)熟読してようやく解決の兆しが見えてきました。

 

話は逸れますが、Google翻訳は最近は本当に良くなって驚くほど的確な訳を出してくれるのですが、それでも時々おかしい訳がでてくることがあります。また、「知っていて当然」な成句なんかもそのままで、これはワタシの語学力の無さもあって何かの呪文のような文章になることもあります。
今回はそこまで酷くなかったのですが、それでも"catch22"と"close the barn door"については改めて調べなくてはなりませんでした。
それでも、コピペ作業のおかげもあって完全に内容を理解することができたので良しとしましょう。機械翻訳などという便利な世の中になりましたが、手間をかけるに越したことはないということで。

 

話を戻します。

 

Luaのガベージコレクタは徹底していて、使われなくなったものは何でも回収してしまいます。ガベコレ、というと8ビットパソコン世代の悲しさで変数しか思い浮かばないのですが、Luaでは関数やモジュールも対象になります。
最初FAQにこれを見つけた時ピンとこなかったのですが、すぐにこの仕組みでsoライブラリやDLLなんかに近い動作を実現していることに気づきました。
実はLuaのドキュメント(http://milkpot.sakura.ne.jp/lua/lua51_manual_ja.html)にはガベージコレクションについて詳細に書かれています。丁寧な日本語訳がアップされているにも関わらず斜め読みで済ましてきたツケを払わされた気分ですね。ワタシが悪いんですが。

 

具体的には、ガベージコレクタはpackage.loadedに登録されているモジュールは使用中と見なして回収しないので、任意のタイミングで登録を解除しておいて、後はガベコレにまかせる、というものです。簡単ですね。
注意しなくてはならないのは登録を解除するタイミングで、解除したいモジュールや関数の外部からは解除できません。解除するモジュールの実行コードの先頭でやります。これでモジュールを抜けて呼び出し側に戻った後にガベコレが回収してくれるという訳です。

 

モジュールのアクセスはテーブルを介して行うのが普通ですが、テーブルの取り込みが無駄(何せ直後に不要になる)になるので、関数を返す方法もあります。

書き方は 

conn:on("receive", function(sck,data) require("httpserver")(sck,data) end)

等とします。最初、requireしたhttpserver(自作)が関数を返すようにしたのでonの第2引数にそのまま書いたのですが動きませんでしたので、functionの中に書いています。
しかし、コードの見た目が個人的には地味にインパクトあります。今までrequireをCのinclude の親戚くらいにしか考えてこなかったので。

 

ちなみにこのhttpserverですが、APモードで端末側に送るhtmlがそこそこの量あります。APモード自体、初期設定の為に1回くらいしか動かさないので、使用後に抜去してしまうのは合理的といえます。

 

 

ワタシはこういう芸の細かいのは大好きなので多少手間がかかっても苦になりません。nodemcu(と、esp8266)はソフト屋的にもかなり遊べるデバイスではないでしょうか。

 

 

 

トレースバックを効かせていると、こんなにド派手なエラー画面が表示される。(右下の時計はxfceのパネルです、念の為。)

 

とりあえず、サーバーに問い合わせることでグラフを描いて返すようにはなった。余り格好良くないけど。

しかし肝心のセンサーノード側で問題が生じており、結構深刻な状況だったりするのですよ。

何らかの形でコンピュータに関わっていれば計算誤差については解りきった事だけれど、一般の人には理解しずらいらしい。無理数と勘違いすることが多くて、こちらとしても面倒くさいのでそのまま放置している。一般事務で無理数なんか使わない。消費税等料率が関係してくる場合に発生するが都度丸める(円未満切り捨て、切り上げ、四捨五入のいずれか、消費税の場合はいずれかを一度選択したら以後変更できなかった、はず)ので、冷静に考えれば気がつくと思うのだけれど。

 

コンピュータでの内部表現に基づくので、例えば整数しか扱わないのなら結構な数まで問題ない。厳密にはBCDにしてきちんと管理すれば良い(とはいえいつか誤差は生じるので本質的な解決にはならない)のだけれど、処理が重くなることと、実は2進のままでも問題無いかのようにごまかせるので余り積極的に採用されないようだ。最初からBCDにしていたのはポケコンに搭載されていたBASICくらいか。

 

いずれにせよ桁数の管理は利用者で責任を持たなくてはならないし、そのためには計算機の挙動を理解する必要があるので、ちょっと調べてみました。

 

実行環境は Thinkpad R500(CPU core2duo),OSはLinuxMint17.3(amd64, xfce)です。

 

例題は1.2から1.1を引いて差の0.1を求める、というもの。そして、求めた差のコピペをどのように扱うか、です。

 

 

Libreoffice5.3のcalc


一見正しく計算しているように見えますが、計算結果(D)のコピーで馬脚を現しています。内部的に誤差を抱えたままで表示の際に丸めているようです。

 

 

gnumeric 1.10.17


gnumericの旧バージョン、gtk2時代の最終版です。
これはちょっと分かりにくいです。計算結果(D)の時点で誤差を表示していれば話は簡単なのですが、そこでは見かけ上丸めておいて、後段の計算(C-D)では誤差を含んだまま計算しています。さらに、値のコピペは丸めた後の値を持ってきています。表が大きくなった場合、誤差がどこで生じたか見つけるのが大変そうです。

 

 

Googleスプレッドシート

Libreofficeと同じ。誤差どうのこうのより、手元の環境ではレスポンスが悪くて使う気になりません。

 


Python2.7


これはちょっと考えものです。生で表示すると誤差あり、printを通すと誤差丸め、当然丸めきれないこともある、さらに書式指定だと桁数が不足して符号だけ示して終わる、もうバラバラです。いろいろできるようにしておいたからユーザーの責任で選んで使え、ということでしょうか。

 

 

Lua5.1.5


Python2.7と同じですが、結果を表示するにはprint()を要するので混乱は多少緩和されています。

 

 

Python3.4.3


自分では使わないのだけれどインストールした何かが使っているのか、HDDに存在するので試してみました。これは流石に首尾一貫しているようです。

 

 

Processing 3.3.3


インストールしたはいいが、まったく使っていないProcessingです。Pycairoに辟易しているのでいい加減こちらに移動したいのですが。
折角なのでコンソールではなくてウィンドウに表示してみました。nfの使い方を間違えたのか、誤差の様子が他と違うようです。
「浮動小数点(float)は小数点以下4桁くらいまで精度が保たれます。」(※)と明確にされていますのでこれで問題ないと言えます。

 

 

しかし、結構な金額を出して買ったPCが小学生でも間違えないような引き算を(事情はどうあれ)間違えるというのは情けないですね。

 

 

 

 

※Processingをはじめよう第2版 オライリー・ジャパン / オーム社 p227(Processingクイックリファレンス - データ型)

esp8266(EP-WROOM-02)ではLua(eLua,nodemcu)、データを受けとるPC側ではPython、そして今度はSQL(SQLite3)も扱わなくてはなりません。


また、日頃はシェルスクリプトも書く(書き流す)し、使っているOSがLinuxなので何か問題があれば延々と他人の書いたCやC++のソースを読まなくてはならず、最悪の場合自分で改変することもあります。

 

そんな訳で時々頭がコンガラガッてしまうのですね。例えばLuaで do done とか書いてみたり、Cのifで条件式に()つけなかったり。どの言語使ってもやることは一緒なんですが。

 

ミクスドランゲージプログラミング、というのは例えばCで書いていてハードを直接叩きたい時にアセンブラを使う、とかPythonで書いたら遅すぎてものにならないので部分的にCで書きなおすとか、そういった形態を指すと思うのですが、一つの仕掛けを得るのにあれやこれや言語を動員してプログラムする、というのも広い意味でそのように呼んで良いのかも知れません。

 

まあ、今回はハードウェア要件が単純ですし、socket使えて且つファイアウォールなんかは然程考慮しないで済んでいるので全体としては楽な部類でしょう。

 

ワタシはアマチュアなのでこんなふうにマイペースでやれますが、同年代のプロも少なからずいる訳で、本当にお疲れ様ですと心底申し上げたいですね。

しつこく、esp8266(ESP-WROOM-02)とnodemcuに取り組んでいます。

 

アプリケーションは相変わらず温度計(と気圧計)ですが、ようやくAPモードになって端末からLAN情報をもらって、その後STAモードに遷移する、という一連の動作ができるようになりました。途中、メモリエラーを吐きまくるようになり、どうしたものかと悩みました。node.heap()でチェックすると10kBくらい残っているのですが、APモードでLAN情報をもらう際に正規表現使ったりしていますのでその為かも知れません。htmlも当初ヒアテキストにしていたのですが、listen時にoutofmemoryを吐きましたので、ドキュメントのサンプルにあるように細切れにしてtableにしました。

 

さらに、APモードの設定にてwifi.WPA_WPA2_PSK としていたところをwifi.WPA2_PSKとしてみました。

 

これらはsdkやeLuaの挙動を完全に理解している訳ではなく、当て推量がほとんどなのですが、どうにかエラーを吐かなくなりましたので効果はあったようです。

 

 

データを受け取るPC側のCGIも修正し、CSVファイルに追加するのを止めてsqlite3(pythonモジュール)に変えました。sqlは以前仕事(一般事務)でデータ処理するのに少し弄ったことがあるくらいで完全に忘れています。そもそも、MSAccessが動くのでGUI頼みで真面目に覚えようとしませんでしたから。

 

データベースにした理由は、センサーノードが増えた(といっても2,3つ)場合、抽出の手間が増えるのとデータが蓄積された後の集計や解析のことを考えたことによります。

 

 

それからテーブルやクエリを対話操作で確認したいので、ツールとしてPalemoonのアドオンをインストールしました。

 

データベースを導入したのでグラフの作成プログラムも最初から書き直しです。こうなったら、これもCGIにしてリモートからはWeb経由で確認できるようにしようと考えています。

 

何かどんどん大げさになってきたような。sqlの参考書を探してこなくては。

 

自分宛てメモ

 

/pale-moon-localization forked from MoonchildProductions/pale-moon-localization

 

https://github.com/JustOff/pale-moon-localization/releases

 

 

天気予報で久しぶりの猛暑日と予報されていたので覚悟していたが。

 

 

例によって室温のグラフ。午前中外出、一旦部屋に戻って午後再度外出。なので時間軸は飛んでいます。Y軸のレンジを上限35度に固定にしているのだが、午後の外出から戻った直後は天井を突破しています。ちなみに水銀体温計によれば本日の最高室温は38.9度。

 

なお、本記事では更新ネタとしてグラフを晒しているが、こんな具合に室温の変化から在室しているか否かが読み取れてしまう。外部サーバーにデータを送るようであればセキュリティに充分な注意が必要でしょう。

 

 

 

 


Search

Calendar

S M T W T F S
  12345
6789101112
13141516171819
20212223242526
2728293031  
<< August 2017 >>

Archive

Mobile

qrcode

Selected Entry

Link

Profile

Search

Other

Powered

無料ブログ作成サービス JUGEM