ファームウェアエンジニアの中林 (id:tomo-wait-for-it-yuki) です。 昨日より Nature Remo BLE マクロのベータテストを実施しています。 本エントリでは、ベータテストで使える機能 (nRF Connect マクロのオペレーション) について、ちょっとだけ深堀りしてみます。
これまでどおりリファレンスデバイスとして Philips Hue を使います。 Hue を操作するマクロを例にベータテストで試せる機能を紹介します。
マクロの作成例はこちらです。
利用可能なオペレーション
nRF Connect のマクロでは、XML のエレメント (下記 XML では write
の部分) を「オペレーション」と呼んでいるので、便宜上、BLE マクロで行う各操作をオペレーションと表記します。
<write description="Write 0x01 to 932c32bd-0002-47a2-835a-a8d455b859dd" characteristic-uuid="932c32bd-0002-47a2-835a-a8d455b859dd" service-uuid="932c32bd-0000-47a2-835a-a8d455b859dd" value="01" type="WRITE_REQUEST"/>
nRF Connect では、write 以外にも様々なオペレーションがサポートされています。 完全なリストは公式ドキュメントをご参照ください。
2023年12月現在、Nature Remo BLE マクロのベータテストに取り込めるオペレーションは次の通りです。
- assert-service
- write
- write descriptor
- read
- wait-for-notification
- sleep
1つずつ簡単に紹介します。
assert-service
対象のサービス、キャラクタリスティクス、ディスクリプターが存在しているかどうかをチェックします。 事前にマクロ内で使うサービスをチェックしておくことで、以降のマクロ実行時にサービスやキャラクタリスティクスが存在することを確定できます。 マクロを手書きするときは、最初に書いておきましょう。
<assert-service description="Ensure 932c32bd-0000-47a2-835a-a8d455b859dd service" uuid="932c32bd-0000-47a2-835a-a8d455b859dd"> <assert-characteristic description="Ensure 932c32bd-0002-47a2-835a-a8d455b859dd characteristic" uuid="932c32bd-0002-47a2-835a-a8d455b859dd"> <assert-cccd description="Ensure CCCD"/> <property name="READ" requirement="MANDATORY"/> <property name="WRITE" requirement="MANDATORY"/> <property name="NOTIFY" requirement="MANDATORY"/> </assert-characteristic> </assert-service>
write
対象のキャラクタリスティック characteristic-uuid
に value
を書き込みます。
<write description="Write 0x01 to 932c32bd-0002-47a2-835a-a8d455b859dd" characteristic-uuid="932c32bd-0002-47a2-835a-a8d455b859dd" service-uuid="932c32bd-0000-47a2-835a-a8d455b859dd" value="01" type="WRITE_REQUEST"/>
type アトリビュートで WRITE_REQUEST
もしくは WRITE_COMMAND
を選択できます。
これは書き込みに対して、返答を期待するか (WRITE_REQUEST) 、返答なしか (WRITE_COMMAND) を意味します。
書き込み後に対象デバイスが意図通り動かない場合は、REQUEST / COMMAND の指定が異なっている場合があります。
<!-- The type value is case-sensitive and may have one of the following values: - WRITE_REQUEST (default) - Write With Response - WRITE_COMMAND - Write Without Response -->
write descriptor
対象のディスクリプター uuid
に value
を書き込みます。
GATT サーバーからの通知を有効にする enable notification に使うことがほとんどでしょう。
nRF Connect では下矢印3つのマークをタップしたときに、このオペレーションが実行されます。
<write-descriptor description="Enable notifications for 932c32bd-0002-47a2-835a-a8d455b859dd" characteristic-uuid="932c32bd-0002-47a2-835a-a8d455b859dd" service-uuid="932c32bd-0000-47a2-835a-a8d455b859dd" uuid="00002902-0000-1000-8000-00805f9b34fb" value="0100"/>
read
対象のキャラクタリスティック characteristic-uuid
から値を読み込みます。
assert-value
に有効な value
を指定している場合、読み込んだ値がその値と一致しているかチェックします。
<read description="Read value of 932c32bd-0002-47a2-835a-a8d455b859dd" characteristic-uuid="932c32bd-0002-47a2-835a-a8d455b859dd" service-uuid="932c32bd-0000-47a2-835a-a8d455b859dd"> <assert-value description="Assert value equals 0x00" value="00"/> </read>
センサー値の読み込みに使うことも多いですが、読み込んだ値を利用する機能は今後実装する計画となっています。
wait-for-notification
GATT サーバーからの通知を1つ待ちます。
assert-value
に有効な value
を指定している場合、通知で届いた値がその値と一致しているかチェックします。
<wait-for-notification description="Wait for notification to 932c32bd-0002-47a2-835a-a8d455b859dd" characteristic-uuid="932c32bd-0002-47a2-835a-a8d455b859dd" service-uuid="932c32bd-0000-47a2-835a-a8d455b859dd"> <assert-value description="Assert value equals 0x01" value="01"/> </wait-for-notification>
通知はセンサー値が更新されたときの通知などに使われることも多いですが、読み込んだ値を利用する機能は今後実装する計画となっています。
sleep
その名の通り、マクロの実行を timeout
ミリ秒停止します。
タイミングの調整にご使用ください。
<sleep description="Sleep 500 ms" timeout="500"/>
Philips Hue を操作するマクロの意味を理解してみよう!
初級編 blink
まずはこちらの blink.xml です。
<macro name="blink" icon="PLAY"> <assert-service description="Ensure 932c32bd-0000-47a2-835a-a8d455b859dd service" uuid="932c32bd-0000-47a2-835a-a8d455b859dd"> <assert-characteristic description="Ensure 932c32bd-0002-47a2-835a-a8d455b859dd characteristic" uuid="932c32bd-0002-47a2-835a-a8d455b859dd"> <property name="WRITE" requirement="MANDATORY"/> </assert-characteristic> </assert-service> <write description="Write 0x01 to 932c32bd-0002-47a2-835a-a8d455b859dd" characteristic-uuid="932c32bd-0002-47a2-835a-a8d455b859dd" service-uuid="932c32bd-0000-47a2-835a-a8d455b859dd" value="01" type="WRITE_REQUEST"/> <sleep description="Sleep 500 ms" timeout="500"/> <write description="Write 0x00 to 932c32bd-0002-47a2-835a-a8d455b859dd" characteristic-uuid="932c32bd-0002-47a2-835a-a8d455b859dd" service-uuid="932c32bd-0000-47a2-835a-a8d455b859dd" value="00" type="WRITE_REQUEST"/> <sleep description="Sleep 500 ms" timeout="500"/> </macro>
Philips Hue はキャラクタリスティック 932c32bd-0002-47a2-835a-a8d455b859dd
に 0x01
を書き込むと点灯、0x00
を書き込むと消灯します。
そのため、このマクロはまず、キャラクタリスティック 932c32bd-0002-47a2-835a-a8d455b859dd
が存在するかどうかを assert-service
でチェックしています。
マクロの残りは Hue を点灯して、500ミリ秒待って、 Hue を消灯して、500ミリ秒待つ、というマクロになっている、と読むことができます。
ちなみに Hue の操作は WRITE_REQUEST
で値を書き込む必要があるようで、 write
オペレーションの type
を WRITE_COMMAND
にすると動きません。
上級編 turn on if off
では次は turn_on_if_off.xml です。
ファイル名でネタバレしていますが、このマクロは、マクロを実行しようとしたときに Hue が消灯状態だった場合のみ、点灯操作を行うマクロとなっています *1 。
また、キャラクタリスティックの通知を write-descriptor
で有効にすることで、値を書き込んだあと、その値がそのまま通知されてくるかどうかを wait-for-notification
でチェックしています。
<macro name="turn_on_if_off" icon="PLAY"> <assert-service description="Ensure 932c32bd-0000-47a2-835a-a8d455b859dd service" uuid="932c32bd-0000-47a2-835a-a8d455b859dd"> <assert-characteristic description="Ensure 932c32bd-0002-47a2-835a-a8d455b859dd characteristic" uuid="932c32bd-0002-47a2-835a-a8d455b859dd"> <assert-cccd description="Ensure CCCD"/> <property name="READ" requirement="MANDATORY"/> <property name="WRITE" requirement="MANDATORY"/> <property name="NOTIFY" requirement="MANDATORY"/> </assert-characteristic> </assert-service> <read description="Read value of 932c32bd-0002-47a2-835a-a8d455b859dd" characteristic-uuid="932c32bd-0002-47a2-835a-a8d455b859dd" service-uuid="932c32bd-0000-47a2-835a-a8d455b859dd"> <assert-value description="Assert value equals 0x00" value="00"/> </read> <write-descriptor description="Enable notifications for 932c32bd-0002-47a2-835a-a8d455b859dd" characteristic-uuid="932c32bd-0002-47a2-835a-a8d455b859dd" service-uuid="932c32bd-0000-47a2-835a-a8d455b859dd" uuid="00002902-0000-1000-8000-00805f9b34fb" value="0100"/> <write description="Write 0x01 to 932c32bd-0002-47a2-835a-a8d455b859dd" characteristic-uuid="932c32bd-0002-47a2-835a-a8d455b859dd" service-uuid="932c32bd-0000-47a2-835a-a8d455b859dd" value="01" type="WRITE_REQUEST"/> <wait-for-notification description="Wait for notification to 932c32bd-0002-47a2-835a-a8d455b859dd" characteristic-uuid="932c32bd-0002-47a2-835a-a8d455b859dd" service-uuid="932c32bd-0000-47a2-835a-a8d455b859dd"> <assert-value description="Assert value equals 0x01" value="01"/> </wait-for-notification> </macro>
マクロを最初から読んでいきましょう。
このマクロでもまず、キャラクタリスティック 932c32bd-0002-47a2-835a-a8d455b859dd
が存在するかどうかをチェックしています。
blink.xml と比べると、さらに追加でディスクリプターが存在するかどうかを <assert-cccd description="Ensure CCCD"/>
の部分でチェックしています。
次の read
オペレーションでは、キャラクタリスティック 932c32bd-0002-47a2-835a-a8d455b859dd
の値を読み込んで、00
(つまり消灯状態) であるかどうかチェックしています。
ここで、01
が読めてしまった場合は、その時点でマクロの実行が失敗となります。
続く write-descriptor
では、キャラクタリスティック 932c32bd-0002-47a2-835a-a8d455b859dd
の通知を有効にしています。
これで、キャラクタリスティック 932c32bd-0002-47a2-835a-a8d455b859dd
の値が更新されれば、通知を受信できます。
write
は blink.xml のときと同様です。
最後に wait-for-notification
で自分が更新した値で、通知が届くことをチェックしています。
このとき、01
を書き込んでいるので、値が 01
になっていることをチェックします。
BLE マクロ完全に理解した
ここまで本エントリを読んでくださった方は、現時点での BLE マクロを完全に理解したと言っても過言ではありません! 現状ではまだまだできることに限りがありますが、今後も機能を改善していきますので、ぜひ遊び方を様々考えていただけるとうれしいです。
BLE マクロベータテスト実施中
もし本エントリを見て Nature Remo BLE マクロに興味を持った場合は、Nature Developer Community にてベータテストの様子を見ることができます。 ぜひ覗きにきてください。
*1:点灯状態だった場合、途中でマクロ実行が失敗します