ブロックを積みながら(26) BBC micro:bitとラズパイでサウンドモニタ その3

Joseph Halfmoon

前回、約5日間の実証実験もどき?のフィードバックを得て、BBC micro:bit、BLEパケットをMQTTブローカに接続するPython3コード、そしてnodeREDのフローのすべてに手をいれました。そして再度の実証実験を起動したつもりでした。しかし、「思った通りに上手く行くと思うな実証実験」、金言であります。一週間のつもりが約1日で終わってました。

※「ブロックを積みながら」投稿順 index はこちら

失敗の原因はちゃんと見張っていなかった事につきます。前回同様、micro:bitは電池での運用で、その電池が尽きるまで約1週間ほどの「夜間頻尿モニタリング」実験期間を想定しておりました。本格運用ともなれば電源を用意してAC利用とするつもりなのですが、実験時は設置が簡単なので電池としております。「設置場所であるトイレの中の棚の上」においてあるmicro:bitは、ドアの開閉に応じてLEDマトリックスが点滅いたします。目で見ているので「動いている」ことに何の疑いも持ちませなんだ。

前回のときは、NodeREDダッシュボードも毎日何度か確認しておりましたが、2度目となると手抜きで、他にもいろいろやることあって、ホッタラカシでした。昨晩、micro:bitのLEDが弱弱しくなっている事に気づきました。そろそろ実験終了ね。ドアを閉めると音響に反応して点灯するも、消灯しません。ついに電圧レベル低下し、誤動作したようです。前回は5日ほどでピクリとも動かなくなっていましたが、今回は7日ほど電池がもった計算になります。多少micro:bitのプログラムを変更しておこなった消費電力削減策が効いた?という感触を持ちました。

しかし、NodeREDダッシュボードに確認にいって愕然、起動の翌日くらいを最後に停止しています。その後のデータは取れていないです。エラーコードは2が表示されています。慌ててBLEとMQTTの橋渡しをするPython3のスクリプトを見ると、確かにエラーを検出してとっくの昔に落ちてました。送り先との接続が切れたままmicro:bitは検出作業のみを1週間近く続けていたようです。

エラーのリカバリより、記録する方が先か

乏しい状況証拠から、何等かの理由でBLEのコネクションが切れたことが原因であるように推定されました。コネクションが切れるとmicro:bitは「鳴く」のですが、トイレの中でひとり「鳴いて」も気づきませぬ。対策としてPythonスクリプト側に

コネクションが切れたことを検出したら再コネクションする

機能を追加すれば良い、と考えました。無線だしね、そういう機能が入っているのが普通であろうと。ただし、今回、記録の乏しさに閉口しました。ちょっと悔やまれるのが、前回のフィードバックのリストの中で唯一対応していなかった、

データベースへの記録機能

です。SQL書くの面倒だし、もそっと本格運用になってから付け加えればいいか、などと甘く見てました。しかし、トラブルおきてから欲しくなるのが過去の記録。記録は大事です。記録無では振り返って何が起こったのか確かめることができません。だいたいコネクション切れもどのくらいの頻度で起こるのかわからないし。少し冗長に記録しておく方がいいんでないかい。「実験」なんだし。実際には機械が勝手に記録してくれるんだし。まずは記録機能追加しよう、と。

記録するデータベースの構造

そんなこんなで、Node-REDで受け取ったイベントをDashboardに表示するだけではなく、DBに格納する機能を追加いたしました。再コネクション機能などは、今回の再々起動の結果を見てから追加の予定。

DBは既に作成済のSQLiteでアクセスできるものを使用しました。DBの作成、管理などはNode-REDの外で DB Browser for SQLite で行っております。インタラクティブなGUIなのでお手軽。DBの構造は以下のような感じ。テーブル3個の簡単なものです。

  1. devicesテーブル データ取得用の装置のデバイスID番号と名前のテーブル。
  2. keysテーブル ユニークなキーID番号と保持するデータの内容を表すKey文字列の対応関係を保持するためのテーブル。
  3. kvdataテーブル 取得データの実体テーブル。タイムスタンプ、デバイスID、きーID、実データをレコードとして記録するもの。

DBstruct
devicesテーブルは以下のような感じです。既に6台ほど装置が登録されており、今回実験に使用しているボードはmicrobitV2という名で登録されているid=6のボード。一応、装置を何台追加しようとこれで仕切れるはず。

DeviceTableさて、記録するデータの種別を表す keyですが、現状は4個のみの登録です。最初の1個は、開発時のTEST用、以下の3個は、今回の実験で使用するキーです。

  1. TEMPERATURE、温度。
  2. STATUS、装置のステータス、稼働中とか、エラーとか、USERにより停止されたとか
  3. EVENT、今回は、ここに1というイベントが入ると、トイレを利用、という解釈です。このフィールドは「頻尿モニタ」特有のフィールドだから専用のキーにした方がいいかも。でもま、今はそのまま。

KeyTable最後に実際のデータテーブル、時刻、報告したデバイス番号、キー番号、そしてデータが記録されとります。

KVTable

nodeRED のフローの変更

DBをおさらいしたので、Node-REDのフローの変更です。基本的な部分は前回と変わっていません。ダッシュボードのStatus, Temp Chart, Event Chartにそれぞれ対応する3本のフローです。修正点は

  1. 各フローにSQLiteでDBに1レコード追加するノードを追加した
  2. Eventフローの末尾に統計情報を出力する機能を接続した

FlowDBaddedすでに見たようにDBの形式は定まっているので、基本的にはダッシュボードに表示する情報と同じものをDBのレコード形式にして挿入していくだけです。また、前回は、統計情報(それも本日の集計分のみ)を個別の出力先にバラバラなタイマで書き込んでいました。あまりにカッコ悪いので、イベント発生時にテンプレート使って本日、昨日の統計情報を一度に更新することにいたしました。

その下はフローに大域な情報の初期化部分です。

FlowDBadded2前回からClear sumという、集計用の大域変数の手動初期化がありました。今回それに追加して、DBからデバイスID、キーIDを読み出して大域変数化するようにいたしました。フローの中ではこの大域変数を使用してDBにアクセスするようにします。なお手動初期化にしたのは、NodeRedの再起動時だけでなく何か変更して再開、などということを想定しているためです。落ち着いたら起動時に1度だけでよいかもしれない。また、統計情報は暦日毎に集計ということにしているので、毎日1度のお仕事に設定。本日分を昨日分に移動させた後、本日分を初期化しています。

更新されたnodeRedダッシュボード

ダッシュボードは前回と大きく変更はありません。統計情報のところ「STAT」欄に昨日分の情報量も表示されるようになった、という点くらい。

dashboardDBadded今回は、「せっかくの」エラー発生など見逃さないように、スマホいじるときにはダッシュボードをながめるよう心がけたいと思います。

Python3とteeでちと困った

上記のようにNode-RED側での情報の記録は前回に比べてかなり充実させた(前回は皆無だった)のです。直接BLEパケットを受けているところでも記録しておきたいです。「とりあえず」Python3のスクリプトから画面に出力している内容をそのままファイルに落としておけばいいんじゃね。ただ、前回のこともあるので、コンソールにも常時表示しておきたいです。定石どおり、スクリプトの標準出力をパイプでteeコマンドに接続したのです。しかし、ここで問題が。

標準出力に表示されません。

teeで書き込んでいる筈のファイルもデキていましたが、空のままです。なぜ?teeコマンドの使い方間違えた?ちょっと焦りました。簡単なコマンドほど動かなかったときの衝撃が大きいです。でも検索したら直ぐに解決。以下のブログのお陰であります。なんだそうだったのか。

Python3 と tee コマンドを組み合わせたときにハマった

Python3に-uオプションを与えて、teeしながら走らせているところがこちら。

tee

次こそ、ソフトの問題でなく、「実証実験的な本題」に入れるよね。。。別シリーズになるけれども。今のところは「問題なく」走っているみたいです。

ブロックを積みながら(25) BBC micro:bitとラズパイでサウンドモニタ その2 へ戻る

ブロックを積みながら(27) BBC micro:bitとラズパイでサウンドモニタ その3 へ進む