おかんウォッチャ(見守りIoT)
これはInfocom Advent Calendar 2022 17日目の記事です.
TWELITE, ESP8266, AWS Lambdaを使って,おかんの見守りシステム「おかんウォッチャ」を作りました. 時間がなかったので,とりあえずブレッドボードに組んで,サーバにデータを飛ばすところまでです. ユニバーサル基盤実装とサーバロジック作成は後日やります.
システム構成
ドア開閉センサのセンサデータをサーバにアップロードし,異常事態発生時(1日以上ドアの開閉が無いとか)に家族に通知します. よく聞くアレ(電気ポットの使用をトリガに生存確認する仕組み)の模倣です.
要件
独居おかんの家に設置するため,以下のような要件を定義しました.
- ゲートウェイはいつでも電源抜き差しOK
- ゲートウェイは既設のWi-Fi経由でデータをアップロードする
- エンドデバイス(ドア開閉センサ)は1年以上バッテリ交換不要
コンポーネント構成
上図はコンポーネントの構造と,コンポーネントの間のプロトコルの図です.それぞれ以下に説明していきます.
ハードウェア
エンドデバイス
TWELITE PALを使います.TWELITE PALは,電子回路素人(私)にはハードルの高い電源回路が仕上がっているので,とっても重宝しています!おすすめ.
今回は以下3つがセットになった商品をそのまま使います.
- TWELITE BLUE PAL (MW-B-PAL-P)
- 開閉センサPAL (MW-PAL-MAG-0)
- ケース (MW-PAL-CAS-0)
電池はCR2032を使うので,これも忘れずに.磁石は100均とかのでOKですが,設置場所への固定方法を考慮して形状や大きさを決めるとよいです.
ゲートウェイ
TWELITE DIPとAE-ESP-WROOM-02を使います. AE-ESP-WROOM-02はESP8266EXを搭載したWi-Fiモジュールです.
とりあえずブレッドボードへの仮実装ですが,こんな感じです. (左側はUART-USB変換なので,ゲートウェイとしての実質的な構成は右側だけ.)
後日,電源とかインジケータとか含めて回路設計してユニバーサル基盤に実装します.
ソフトウェア
TWELITE DIP
TWELITE DIPにはもともとApp_Tweliteというファームウェアが書き込まれていますが, ESP-WROOM-02に渡すオリジナルのフレームを作るために,App_Wingsをベースに改変したファームウェアを作り書き込みました. 開発にはMWSDKというモノワイヤレス社純正のSDKを使います.
App_Wingsに対しては,ざっくり次のような変更を行っています.
- データ受信時のコールバック関数
cbToCoNet_vRxEvent()
でApp_Wingsデフォルトの処理に加えて,カスタム処理を実装 - 開閉センサPALの場合のみ,受信パケットをパースしてESP-WROOM-02に渡すオリジナルフレームを構築
- UART1にオリジナルフレームを出力
App_Wingsとのソースコードの差分はこちらを参照してください.
cf. App_WingへOkan_Watcher用の改変を入れる · ottijp/okan-watcher@6e4b957
なお,ESP-WROOM-02に送るオリジナルフレームは,次のようなフォーマットを設計しました.STX,ETX以外はバイナリデータを16進文字列にシリアライズしたものです.
(例えば[STX]81000000081B0001[ETX]
)
また,TWELITE PALと通信するために,TWELITE PAL, TWELITE DIPそれぞれにUART接続し,チャネル,アプリケーションID,暗号化キーが同じになるように設定しました.
ESP-WROOM-02
Arduinoで開発します.ソースコードはこちらです.
cf. add: ESP8266プログラム · ottijp/okan-watcher@d4c1eb5
やっていることは単純で,TWELITE DIPから受信したフレームをパースし,JSONを構築してサーバにHTTPSでPOSTしています.
構築されるJSONは次のようになります.
{
"type": "magnet",
"src_address": "81XXXXXX",
"battery": 2075,
"pole": 0,
"changed": true
}
サーバサイド
AWSのSAM (Serverless Application Model)を使って,Lambdaファンクションを作りました. SAMは,直接CloudFormationのコードを書いたり,ロールやポリシを考えたりしなくても,簡単にサーバレスのリソースを作成・更新でき,ビジネスロジックの開発に集中できる便利なフレームワークです.
ソースコードはこちらです.
cf. add: サーバ側プログラム · ottijp/okan-watcher@91c6c04
template.yamlにAWS::Serverless::Api
のリソースを定義し,HTTPヘッダのx-api-key
で認証を行うようにしているのがポイントです.
ESP-WROOM-02のプログラムで,この認証用のx-api-key
をセットしています.
Resources:
OkanWatcherApi:
Type: AWS::Serverless::Api
Properties:
StageName: Prod
Auth:
ApiKeyRequired: true
UsagePlan:
CreateUsagePlan: PER_API
UsagePlanName: GatewayAuthorization
動作のチェック
TWELITE PALに磁石を近づけることで,TWELITE DIP,ESP-WROOM-02を経由してAWS Lambdaにデータが送信されました.
$ sam logs --stack-name okan-watcher --tail
2022/12/16/[$LATEST]edaed414aefe428888c3416a3d511568 2022-12-16T14:53:21.621000 START RequestId: d8fbf8dc-4a08-41a5-885e-fbeb9b841281 Version: $LATEST
2022/12/16/[$LATEST]edaed414aefe428888c3416a3d511568 2022-12-16T14:53:21.622000 2022-12-16T14:53:21.622Z d8fbf8dc-4a08-41a5-885e-fbeb9b841281 INFO {"resource":"/sensordata","path":"/sensordata","httpMethod":"POST","headers":{"Accept-Encoding":"identity;q=1,chunked;q=0.1,*;q=0","Host":"xxxxxxxxxxxxxxxxxxxxxxx","User-Agent":"ESP8266HTTPClient","X-Amzn-Trace-Id":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx","x-api-key":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx","X-Forwarded-For":"xxxxxxxxxxxxxx","X-Forwarded-Port":"443","X-Forwarded-Proto":"https"},"multiValueHeaders":{"Accept-Encoding":["identity;q=1,chunked;q=0.1,*;q=0"],"Host":["xxxxxxxxxxxxxxxxxxxxxxx"],"User-Agent":["ESP8266HTTPClient"],"X-Amzn-Trace-Id":["xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"],"x-api-key":["xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"],"X-Forwarded-For":["xxxxxxxxxxxxxx"],"X-Forwarded-Port":["443"],"X-Forwarded-Proto":["https"]},"queryStringParameters":null,"multiValueQueryStringParameters":null,"pathParameters":null,"stageVariables":null,"requestContext":{"resourceId":"xxxxxx","resourcePath":"/sensordata","httpMethod":"POST","extendedRequestId":"xxxxxxxxxxxxxxxx","requestTime":"16/Dec/2022:14:53:21 +0000","path":"/sensordata","accountId":"xxxxxxxxxxxx","protocol":"HTTP/1.1","stage":"Prod","domainPrefix":"xxxxxxxxxxxx","requestTimeEpoch":1671202401319,"requestId":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx","identity":{"cognitoIdentityPoolId":null,"cognitoIdentityId":null,"apiKey":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx","principalOrgId":null,"cognitoAuthenticationType":null,"userArn":null,"apiKeyId":"xxxxxxxxxx","userAgent":"ESP8266HTTPClient","accountId":null,"caller":null,"sourceIp":"xxxxxxxxxxxxxx","accessKey":null,"cognitoAuthenticationProvider":null,"user":null},"domainName":"xxxxxxxxxxxxxxxxxxxxxxx","apiId":"xxxxxxxxxx"},"body":"{\"type\":\"magnet\",\"src_address\":\"81XXXXXX\",\"battery\":1950,\"pole\":2,\"changed\":false}","isBase64Encoded":false}
2022/12/16/[$LATEST]edaed414aefe428888c3416a3d511568 2022-12-16T14:53:21.633000 END RequestId: d8fbf8dc-4a08-41a5-885e-fbeb9b841281
2022/12/16/[$LATEST]edaed414aefe428888c3416a3d511568 2022-12-16T14:53:21.633000 REPORT RequestId: d8fbf8dc-4a08-41a5-885e-fbeb9b841281 Duration: 12.04 ms Billed Duration: 13 ms Memory Size: 128 MB Max Memory Used: 57 MB Init Duration: 134.96 ms
Todo
おかん家に設置するまでにやること
- ユニバーサル基板への回路実装,ケース詰め.
それ以後にやること
- サーバのSSL証明書検証
- SSLクライアント認証
- ゲートウェイからサーバに向けたハートビートメッセージの送信
引っかかったところ
MWSDKでビルドがエラーになる
MWSTAGEを使わずにターミナルでビルドしようとした時にエラーが発生しました.
$ make TWELITE=BLUE
Makefile:58: /MkFiles/mw.mk: No such file or directory
make: *** No rule to make target `/MkFiles/mw.mk'. Stop.
これは,パスを通すことで解決しました.
$ MWSDK_ROOT=/path/to/MWSTAGE/MWSDK make TWELITE=BLUE
I2Cがうまく動かない
はじめ,TWELITEとESP-WROOM-02の通信はI2Cで行おうとしていましたが,色々試してもうまくいかなかったのでUARTに変更しました.
どうやらESP8266のI2Cスレーブ動作は不安定?なようで,それが関係しているのかもしれません. 通信速度を20kHzにして試してもみましたが,それでもダメでした. (TWELITEの関数は(結線してなくても)TRUEで返ってくるので,本当に送信できているのか,送信できているけど受信がうまくいっていないのか,原因が特定できず疲弊したので,UARTに変更しました.)
cf. c++ - ESP8266 I2C slave does not acknowledge data - Stack Overflow
cf. ESP8266 to ESP8266 i2c · Issue #3046 · esp8266/Arduino