Pi3からAmbientに送って可視化します。Pi3のプログラムはPythonで記述しました。UV、音の6種類のデーターを測定し、BLEで送信するセンサー端末です。ボタン電池(CR2032)1個で動作します。ウェザーニュース社の「WxBeacon2」も中身は同じもののようです。今回はこの「WxBeacon2」を使いました。Manual」という資料で公開されています。(BLE)で送ります。Pi3をゲートウェイにしてBLEでデーターを受信し、Ambientに送信して可視化します。BLEではセンサー端末をペリフェラル、ペリフェラルにデーターを取りにいくものをセントラルといいます。Pi3がセントラルになります。Energyの通信モジュールが搭載されているので、追加するハードウェアはありません。(stretch)を使いました。jessieでも動作すると思います。プログラミング言語では、Pythonとnode.jsにBLEを扱うライブラリーがあります。今回はPythonを使うことにします。stretchにはPython2.7とPython3がインストールされていますが、pyenvを導入し、環境を切り替えて使います。pyenvの使い方は「RaspberryPiにpyenvを導入」などをご覧ください。Pythonのバージョンは3.6.5を使いました。PythonでBLEを扱うライブラリーはいくつかあります。その中でドキュメントが一番しっかりしているbluepyを使いました。次のようにインストールします。Pi3上のコマンド実行です。pip3としてください。Pi3のBluetoothのバージョンは5.43です。5.43「2JCIE-BL01」に電池を入れ、hcitoolコマンドでBLEのスキャンをしてみます。Envスキャンで見つかったBLE端末が複数表示されます。その中で名前が「Env」のものが「2JCIE-BL01」です。名前の左(例ではEC:B3:46:BA:78:75)が「2JCIE-BL01」のアドレスです。次にgatttoolコマンドで「2JCIE-BL01」にコネクトし、サービスを調べます。hcitoolで見つけた「2JCIE-BL01」のアドレスを-bオプションで指定します。最後の「-I」は大文字の「i」です。successful」が表示されればコネクトに成功しています。「primary」コマンドを入力すると「2JCIE-BL01」で定義されているサービスが確認できます。Service」というサービスUUIDで、端末の名前などが取得できます。詳細は「2JCIE-BL01」のマニュアルをご覧ください。プログラム1(コネクトモード)「2JCIE-BL01」はアドバタイズして、セントラルに見つけてもらい、セントラルからコネクトされてデーターのやり取りやモード設定などをおこなうモード(コネクトモードと呼ぶことにします)と、アドバタイズデーターにセンサー値を載せて送ってしまうモード(ブロードキャストモードと呼びます)があります。Pi3のプログラムを作ります。PythonのBLEライブラリーbluepyのクラス定義の資料を参照しながらお読みください。スキャンをおこなうにはScannerクラスのオブジェクトを作り、scanメソッドを呼びます。このとき、withDelegateでスキャンハンドラーを指定しておくと、デバイスを見つけ次第ハンドラーが呼ばれます。スキャンとスキャンハンドラーは次のようなプログラムになります。スキャンハンドラーに渡されるdevはScanEntryクラスのオブジェクトで、getScanDataでアドバタイズデーターを取り出せます。次のようにすると「2JCIE-BL01」を見つけられます。見つけたあとは「2JCIE-BL01」にコネクトしてセンサーデーターを取得するので、そのためにスレッドを起動しています。BLEデバイスと通信するためにbluepyではPeripheralというクラスが用意されています。今回は5分ごとに「2JCIE-BL01」にコネクトしてセンサーデーターを取得し、Ambientに送るスレッドを作るので、PeripheralクラスとThreadクラスを多重継承したEnvSensorというクラスを作りました。コンストラクターでは親クラスのコンストラクターを呼び、Ambientの初期化もおこないます。スレッドの処理はrunメソッドに記述します。中身はデバイスにコネクトして、センサーデーターを取得し、Ambientに送信して300秒(5分)待つという処理の繰り返しです。data)というCharacteristicがあり、これをreadすると温度、湿度などの最新データーが取得できます。デフォルトの測定間隔は300秒(5分)です。dataのUUID(0x3001)を指定してCharacteristicを取得し、readして、最新のセンサーデーターを取得しています。データーは温度、湿度などが19バイトにまとめららたbytesタイプです。それをそのままAmbientに送る関数send2ambientに渡しています。send2ambientで19バイトにまとめられたbytesタイプのデーターをstruct.unpackを使って温度、湿度など個々のデーターに分解し、Ambientに送信しています。scanやconnect、getCharacteristics、readなどのメソッドの中でBLEデバイスと通信します。通信に失敗した時などには例外が発生するので、実際のプログラムには例外処理が加えてあります。プログラム全体はGithubに公開しました。Pi3のBLEモジュールにアクセスするにはroot権限が必要なので、プログラムは次のように起動します。Pi3からログアウトしてもプログラムが終了しないようにするには、次のように起動します。&Ambientのチャネルページを見ると、送られたデーターを確認できます。「2JCIE-BL01」にはアドバタイズデーターにセンサー値を載せて送るブロードキャストモードがあります。ブロードキャストモードの動作として一定間隔(デフォルトで1.285秒間隔)で発信するモードと10秒発信して50秒休むというように間欠動作するモードの二つがあります。発信と休止の時間幅も変更できます。休止中は通信モジュールをオフにしているようで、コネクトもリード/ライトもできなくなり、消費電力を抑えています。「2JCIE-BL01」を間欠動作のブロードキャストモードに設定し、送られたデーターを取得してAmbientに送信するプログラムを作ります。0x3042)でおこないます。プログラムを作ってもいいのですが、スマホアプリでやってみます。Scanner」を使います。Scanner」を立ち上げると、スキャンして見つかったBLEデバイスが表示されます。「EnvSensor-BL01」と表示されたものが環境センサー「2JCIE-BL01」です。それをタップするとアドバタイズデーターとサービスが表示されます。これをタップすると、Characteristicが表示されます。値が「0x0808a0000a0032000800」と表示されています。9バイト目がビーコンモードで「08」はEventBeaconを表します。1が間欠動作モードです。このCharacteristicをタップして、値を0808a0000a0032000300にして書き込みます。値を書き込んだら「2JCIE-BL01」の電池を入れ直してリセットすると、新しいモードで動き出します。Scanner」を立ち上げると、デバイスの名前がIM-BL01に変わっていることが確認できます。Pi3側のプログラムもまずスキャンをします。スキャンハンドラーを指定してスキャンを起動するところまではコネクトモードの時のプログラムと同じです。スキャンハンドラーに渡されるdevのgetScanDataメソッドを呼び、アドバタイズデーターを取り出します。ブロードキャストモードの時「2JCIE-BL01」はアドバタイズデーターの中にデータータイプが’Manufacturer’で、その時の値の先頭の文字列が’d502’という情報を送るので、次のようにすると「2JCIE-BL01」のアドバタイズデーターを見つけられます。値の5文字目、6文字目(value[4:6])はシーケンス番号で、測定をおこなうごとに値が一つ増やされます。デフォルトの測定間隔は300秒(5分)なので、5分に1回値が増えます。シーケンス番号が更新されたらデーターをAmbientに送信します。Ambientに送信する関数send2ambientもコネクトモードの時とほぼ同じです。コネクトモードの時はCharacteristicをreadした値はbytesタイプでしたが、スキャンで得られるデーターは文字列なので、bytes.fromhexでbytesタイプに変換し、温度、湿度などのデーターに分解しています。プログラムは次のように起動します。env2ambientBS.pyプログラム全体はGithubに公開しました。