■センサを増やす前にデバイス側を能動的に使うためには、デバイス側でトリガを引けるような仕掛けが必要になる。デバイス側は何かをきっかけにしてXBeeのコーディネーターにメッセージを送信するだけだけど、それを受けるサーバー側がそのメッセージを処理できるようにしないといけない。今まではサーバー側で動くプログラムが出すメッセージを送って、デバイスから応答を受信するだけだったけど、デバイス側でトリガを引くということは、逆に、デバイスからのメッセージに応じて、サーバー側でプログラムを動かすことになる。
作りたいものは計画はあるし、部材も購入しているのだけど、とりあえず簡単なターゲットとして、「PS3の電源が入ると連動してテレビとアンプの入力が切り替わる」というシーケンスを実装することにした。
PS3の電源ラインには電流センサが設置済みで、PS3が起動することで増える消費電流量を検出することができる。デバイスでは電流センサの出力をADコンバーターに通してデジタル化して把握する。肝心なのは電源オンの状態でメッセージを流すのではなく、「オフからオンになったとき」メッセージを流すこと。電源オンの状態でメッセージを流すようにすると、PS3がオンになっている間、メッセージが流れ続けることになってしまう。
また、アナログセンサなので、出力がぶれることが予想され、誤動作されてしまうのも困る。瞬間的にセンサ出力があっただけで反応しないようにしたい。
もっとも、この問題はアナログスイッチを扱う世界では「チャタリング」として良く知られている現象で、その対策もだいたい決まっている。今回はデバイスのファームウェアでソフトウェア的に処理することにした。
処理方式は簡単で、ADコンバーターの出力を格納する配列を10個ほど用意し、定期的にサンプリングした結果を順番に格納していく。そして、ある閾値を越えた(あるいは下回った)回数をカウントする。条件に合わないサンプリングが出たらゼロカウントに戻す。そしてカウント数が規定数以上、配列数以下の時にトリガが発生する、とすると、過去に遡ってスイッチが入ってからある程度安定した出力が続いた時にトリガがひかれることになる。
サーバー側はメッセージを受信して、それがトリガであることを示す、つまりアサーションメッセージであることを判定すると、メッセージに応じたリアクションを起こすプログラムを起動する。fork/execで処理するのが定番だけど、PHPなのであまり重たい実装にはせず、atコマンドを経由して即時実行する実装とした。atコマンドを経由すると、プロセスの親子関係が作られず、全くの非同期動作となるけど、サーバーはデバイスにメッセージを返す必要がないので問題ない。
動作試験は良好。だいぶ便利。PS3を起動した時にアサーション発生の条件を「起動」から「停止」に切り替えて、停止時にテレビを外部入力からデフォルトのチャンネルに戻すようにした。この手の家電連動はなくてもなんとかなるけど、あると便利です。