前回のあらすじ
前回のその1では、プロトコルについての概要や、ゲームアプリケーションにおけるアプリケーションプロトコルについて触れました。今回は、PCとかゲームではない部分で身近なプロトコルに触れたいと思います。
家電を操作するプロトコル
エアコンとかテレビとか、リモコンで操作できる家電製品は多くありますが、これらもリモコンと家電製品が通信することで遠隔操作を実現しています。通信しているということは、そこにはプロトコルがあるはずです。
我が家にあるリモコン操作可能な家電の内、リモコンのボタン数が少なくて簡単にプロトコル解析できそうなものは無いかな~と探してみたところ、ちょうど良さそうなLED照明があったのでコレのプロトコルを解析して、PCやスマホのWEBブラウザから操作できるようにしてみようと思います。
この製品のリモコンには点灯/消灯ボタンの他に、点灯箇所(上面と下面)の切り替え、色調切り替え、明るさ切り替えのボタンが付いています。更に、リモコンの側面にはチャンネルの切り替えスイッチ(1ch/2ch)が付いています。
本体側にも同様のチャンネル切り替えスイッチが付いていて、これは同じ製品が近くにある場合に1つのリモコンで複数の本体を一括制御したいニーズと、個別のリモコンで別々に制御したいニーズの両方に応えるためのもので、リモコン側で設定したチャンネルと同一チャンネルに設定された本体だけが制御対象になるような仕組みになっています。
照明器具にしてはボタン数は多そうですが、テレビやエアコンに比べればボタン数は少なく、シンプルな部類かと思います。
プロトコルの事前調査
多くの家電製品のリモコンは赤外線によって製品本体と通信しています。ほとんどの場合リモコン側には受信機は無く、リモコンから本体側への一方向の通信を行います。
赤外線を使ってデータを送信するプロトコルはいくつもあり、統一された規格みたいなものは無いようです。調べてみると、国内で流通している家電では以下のいずれかのプロトコルが多く使用されているようです。
- NECフォーマット
- 家電製品協会(AEHA)フォーマット
- SONYフォーマット
おそらく今回のターゲットであるLED照明も、これらのいずれかのプロトコルを使って命令データを送信していることだろうと思います。そして、そのプロトコルによって送信されている実際の命令データがどういう構造になっているのか(このLED照明のアプリケーションプロトコル)を解析し、それと同じプロトコルで赤外線シグナルを発するような機構を作るわけです。
まずは上で挙げた3つのプロトコルについての情報を集めることにしました。
赤外線の波長がどうだとか、変調がどうだとか、デューティー比がどうだとか、そういった小難しい話はここではバッサリ省略しますが、ざっくりと説明すると、これらのプロトコルは一定のリズムで赤外線がONの期間とOFFの期間を切り替えることでデータを表現するわけです(細かいところが気になる方はググったら出てくるので調べてみてください)。
…で、これって前回「その1」で登場した「鐘プロトコル」と似てますよね。一定リズムで鐘を叩くかわりに、赤外線をON/OFFするわけです。「鐘プロトコル 2.0」と違い、送信するのが文字列ではなくビット列になるので、0 の表現方法と 1 の表現方法を押さえればデータを読み取ることができそうです。ただ、データの開始と終了を示す特別なパターンでサンドイッチする必要があります。
鐘プロトコルと同様に、一定のリズムで赤外線をON/OFFします。O
は赤外線が ON のタイミングで、-
は OFF のタイミングです。このリズムの1拍分の長さはプロトコルごとに異なっており、それぞれ上の表に示す長さとなっています。
上の表を見ると、どのプロトコルでも 0 を示すパターンよりも 1 を示すパターンの方が長いため、送信データの中に 1 が立っているビットが多く含まれると、送信にかかる時間が延びることになります。
開始コードから終了コードまでの区間をフレームと呼びます。リモコンのボタンを押しっぱなしにしている場合、終了コードの後に続けて一定の周期でリピートコードと呼ばれる特定のパターンを送信する機器と、一定の周期でフレームを再送し続ける機器が存在します。この周期と、リピートコードの内容もプロトコルによって異なりますが、この記事ではそのあたりは割愛します。
開始コードと終了コードに挟まれた実際のデータ部のサイズはプロトコルによって異なります。また、データ部全体をアプリケーションが自由に利用できるわけではなく、プロトコルごとにデータフォーマットが決められています。
NECフォーマット
データ部は 32bit 固定長。データ部の先頭 16bit に「カスタムコード」と呼ばれるメーカーや製品の識別コードが来ます。リモコン操作時に無関係な家電製品が反応しないのはこの情報のおかげですね。
次の 8bit がペイロード(アプリケーションプロトコルで送信可能なデータの実体)であり、最後の 8bit はペイロードをビット反転したデータとなります(エラーチェック用)。
家電製品協会(AEHA)フォーマット
データ部は可変長。データ部の先頭 16bit にカスタムコードが来て、その直後 4bit にはカスタムコードのパリティ(カスタムコードを 4bit 単位でXORをとったもの)が来ます。それ以降の部分はすべてペイロードです。ペイロードのエラーチェック方法はアプリケーションに委ねられます。
SONYフォーマット
データ部は 12bit, 15bit, 20bit のいずれかの固定長。データ部の先頭 7bit にペイロードが来て、残りはカスタムコードです。
赤外線の波形データを解析する
さて、私は電子工作とかやらない人間なので、ロジックアナライザとかオシロスコープとかそういった類のものは持っていません。じゃあどうやって解析するんだよって話なんですが、だいぶ前に購入してお家に転がっていた M5StickC Plus と赤外線ユニットがあったので、これを使うことにします。
M5StickC Plus は M5Stack シリーズの小型のマイコンモジュールで、カラー液晶ディスプレイ, Wi-Fi, Bluetooth, 赤外線LED, RTC, マイク, 物理ボタン など様々なデバイスが詰め込まれています。更に、外付けでモジュールを接続して機能追加することもできます。
今回は赤外線の送信だけでなく受信も行うため、外付けで送受信可能な赤外線ユニットを接続しています。この記事ではこれ以降、省略のために M5StickC Plus を指して M5Stick と呼称します。
幸いなことに、M5Stick に搭載されている SoC(ESP32)向けの赤外線通信をサポートするライブラリ(IRremoteESP8266)を見つけ、その中に受信した赤外線シグナルをダンプするサンプルプログラム(IRrecvDumpV3)がありました。ソースコード中の赤外線の受信に使われるIOピンを示す定数を適切な値に書き換え、M5Stick にこのプログラムを書き込んで実行し、LED照明のリモコンの「点灯/消灯」ボタンを押してみます。
プログラムが赤外線シグナルを検知すると、何やらダンプされました。ダンプにはC言語の配列データのようなものが含まれています。
Protocol : UNKNOWN Code : 0x31CFC23B (126 Bits) uint16_t rawData[251] = {3350, 1618, 414, 1244, 414, 1240, 412, 1242, (...略)}; // UNKNOWN 31CFC23B
この配列は「赤外線がONの期間が何μs続いて、次にOFFの期間が何μs続いて、次にONの期間が何μs続いて、次にOFFの期間が何μs続いて…」というように赤外線がON/OFFされている期間の長さの羅列です。
このプログラムは既知のプロトコルであればプロトコル判定までやってくれるようですが、出力されたプロトコル名を見ると “UNKNOWN” と表示されていますね。少なくともメジャーな3大プロトコルのいずれにも該当はしないということでしょう。ググってももちろんこの製品の赤外線のプロトコルなんて出てこないし…ナンテコッタ。
まぁ、実は解析なんてしなくてもリモコンの挙動を模倣することはできます。先ほどのダンプで得られた赤外線パターンをそのまま送信するプログラムを組めばいいだけです。鐘プロトコルでたとえるなら、鐘の音を録音しておいて大音量で再生するようなものですね。
ただ、今回この記事はプロトコルに関するお話なので、ちゃんとどういうプロトコルで通信されているのか解析までしたいと思います。
まずは数値の列のままだとわかりづらいので、可視化してみましょう。グラフ化するプログラムをわざわざ書いたけど、別にExcelとかでもできそうだなと後で思った。見づらい人は画像をクリック(タップ)して拡大してください。
波の高い部分が赤外線がONの期間です。開始コードらしきもの(ONの期間が長い部分)は目立っていてわかりやすいですね。どうやら同じフレームが3回分リピートされていたようです。
ON/OFFにはなにか一定のリズムがあるはずなので(そう信じたい)、それがわかりやすいように一定間隔でガイド線を引きたいですね。どれくらいの間隔なら波形にマッチするか間隔を変えながら探してみると、411μs 間隔でガイド線を引くと波形パターンと概ね合っているように見えます。
開始コードらしき部分を除けばONの期間の長さはどうやら1拍分で固定のようで、OFFの期間の長さは1拍分か3拍分のどちらかしか無さそうです。フレームの最後には終了コードらしきものもありますね。3大メジャープロトコルでは 0 の表現方法より 1 の表現方法の方が長くなってたな~という経験則から、以下のような仮説を立てました。
あれ? これってほぼ NEC フォーマットで、1拍の長さだけが違う?? やっぱり3大プロトコル(の亜種)だったのか。この仮定に基づいてちょっとデコードしてみましょう。ビット列はバイト単位で最下位ビットから順に送信される点に注意が必要です(LSB first)。
NEC フォーマットとはデータ長が異なるようですね。32bit ではなく 40bit です。ただ、NEC フォーマットのようにペイロードをビット反転したと思しきセクションが見えますね。最後の F1
と 0E
です。恐らくこの F1
か 0E
のどちらかがこのプロトコルにおけるペイロードなのだと思います(順当に考えると F1
がペイロードかな?)。
ペイロードの中身についてはこの時点ではまだよくわからないので、他のボタンも押してみて同様にデコードしてみましょう。
末尾の 2byte だけが変化しているので、どうやらこれが 8bit のペイロードと、それをビット反転したもので間違いなさそうです。どちらがペイロードなのかはこれだけでは何とも言えません。
もう1つ、リモコンにはチャンネル切り替えのスイッチがついているので、これを切り替えてデータがどう変化するか見てみましょう。先ほどまでは 1ch が選択された状態だったので、2ch に切り替えて調べてみます。
うーん、結局どちらがペイロードかは断定できないままですが、わからなくても特に問題はありません。好きな方をペイロードってことにしてしまいましょう。いずれにせよペイロードの上位 4bit がチャンネルを示す値で、下位 4bit がコマンド種別のようです。ペイロード以外の部分は恐らくメーカー識別子や製品識別子のようなものだと思われますので、この値をこのまま利用するものとしましょう。
これでプロトコルの解析は完了です!
赤外線データを送信する
いよいよ M5Stick からこれらの赤外線パターンを送信できるようにします。M5Stick には液晶ディスプレイもあるし物理ボタンもあるので、M5Stick 単体でリモコンの代替品とすることも可能なのですが、物理ボタンが2つしかなくて不便そうなので、PCやスマホからWEBブラウザ経由で操作したいところです。
M5Stick には Wi-Fi モジュールが搭載されているため、これで自宅の Wi-Fi に接続することができます。また、M5Stick 自体をHTTPサーバとして扱うために必要なライブラリも用意されているので、簡単にWEBブラウザから M5Stick にコマンドを送ることができます。
このあたりは今回の話題と関係ない部分なので詳細は割愛します。
こんな感じです。さて、うまくいくかな~。
ポチっとな。
…ん? あれ??
反応が無い。
なぜだ?? 赤外線出てない??
赤外線は人間には見えませんが、可視光の波長に近いため一部のスマホのカメラやデジカメなどで撮影するとバッチリ可視化することができます。赤外線ユニットを手元にあったWEBカメラで見ながら M5Stick に命令を送ってみると、赤外線LEDがしっかり点灯していることがわかりました。
うーむ、強度が弱いのか??
じゃあ照明本体に近づけてみるか…脚立持ってきて…と。
ポチっとな。
お、反応した!!!
やったぁーー!!!
って、これじゃ使えねぇ~~~!!!
完。
お知らせ
株式会社グレッゾではエンジニアを募集しております!
もしご興味がありましたら是非、下記リンクより応募よろしくお願いします。
https://www.grezzo.co.jp/jp/careers/