IRKitってすばらしい! その2
注意
過去の記憶を遡って記載しています。20150624記
何はともあれ、ドキュメント
を確認します。
といっても、全てがIRKitのサイトに書いてある(しかも日本語!)ので、大して時間はかかりません。
15分もあれば、一通り目を通すことができます。
具体的には、IRKit-Device-APIです。
ハックステップ概要
任意のリモコンコマンドを発行するまでのハックステップは、ざっくり下記の通り。
- 機器発見 : IRKitをネットワーク上で発見する。
- 学習 : IRKitにリモコンコマンドを学習させる。
- GET data : 学習した結果(コマンドデータ)をIRKitから取得する。
- POST data : 取得したコマンドデータをIRKitへ送る。
- 発行 : IRKitが2.の赤外線コマンドを発行する。
順を追って記録に残していきます。
ハックステップ詳細
1. 機器発見
IRKitをおうちのネットワークに繋いだ状態からスタートします。
IRKitのAPIはIPアドレスがわかれば即座に叩けるので、まずは、IPアドレスを取得したいです。
この方法は世の中には幾つかありますが、IRKitでは、Appleさん謹製のBonjourという機器発見プロトコルを使って見つけられるそうです。
最近めちゃくちゃ動作の遅いMacMiniのターミナルから、Bonjour!と挨拶してみました。
手順書通りで確かに取得できました。
% dns-sd -B _irkit._tcp (中略) Instance Name 23:12:55.768 Add 2 4 local. _irkit._tcp. irkitd2a4 ^C % dns-sd -G v4 irkitd2a4.local (中略) Hostname Address irkitd2a4.local. 10.0.1.2
この例ですと、IPアドレスとして、 10.0.1.2がとれています。
2. 学習
IRKitは常に学習Readyとなっていますので、IRKitに向かってリモコンを向けて、リモコンのボタンを押すだけです。
簡単。
IRKitのLEDが点滅したら、(たぶん)学習出来ています。
おうちではカウンターの下に貼り付けてます。
3. 学習データのGET
それでは、2.で学習させたリモコンコードを読み出してみたいと思います。
やることは単純です。(手段はともかく)1.で取得したIPアドレス/messagesに対してGET発行するだけです。
GET from http://10.0.1.2/messages
すると、以下のような値(★1)が返ってきます。後でコピペするだけなので、データを理解する必要はありません。
{"format":"raw","freq":38,"data":[18031,(中略), 4400,1190]}
リモコン学習データがとれたので、いよいよ、発行してみます。
4. IRKitへデータを送る
これも簡単です。GETと同じ口に★1のデータをPOSTするだけです。
POST to http://10.0.1.2/messages ★1
5. リモコンコマンド発行(発光)
これで、めでたくIRKitからリモコンコマンドが発行され、おうちの中の何かが動いたと思います。
ツールを作る。
コマンドラインからばっかりだと、データをコピペするのも面倒になってくるので、ツールを作ります。
こだわりはないので、一番速く実現出来そうな、html/jsで書いてみます。
chromeブラウザでは動作確認済み。
単純なプログラムですが、家中の機器をブラウザから制御できるのは、新感覚。 実にスマートホームっぽいです。
これを使って、リモコンコードデータベースも出来上がったので、いよいよスマホアプリに実装してみようかと思います。
その他ノウハウ
- 得られたリモコンコードは、毎回少しずつ違っている事がある。でも、どれも動く。
- 長いデータだな、と思って良く見ると、同じコードの繰り返し(3回位)だったりする。繰り返し部は削除して、最初の部分だけにしても、動作した。
- 窓の近く、お昼過ぎにコウコウと太陽の光が注ぐと、IRKitから発行しても届かない(?)場合がある。
コードはこちら
index.html
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>IRKit JavaScript Test</title> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script> </head> <body> <br> <br> <textarea name="log_textarea" cols="50" rows="5"></textarea> <br> <br> <div id="Rows" ></div> <!--div id="test" > <input type="text" readonly name="command_label_1"> <input type="button" disabled name="btGet_1" value="GET" onclick="onClickedGet( 1 );"> <input type="button" name="btPost_1" value="POST" onclick="onClickedPost( 1 );"> <input type="text" name="gotten_data_1"> <br> <br> <input type="text" readonly name="command_label_2"> <input type="button" disabled name="btGet_2" value="GET" onclick="onClickedGet( 2 );"> <input type="button" name="btPost_2" value="POST" onclick="onClickedPost( 2 );"> <input type="text" name="gotten_data_2"> <br> <br> <input type="text" name="command_label_3"> <input type="button" name="btGet_3" value="GET" onclick="onClickedGet( 3 );"> <br> <br> </div--> <script src="./js/irkit_test.js"></script> </body> </html>
irkit_test.js
var gCurrentRowNum = 0; var gArrayRowCmdName = new Array(20); var gArrayRowData = new Array(20); initialize(); function initialize(){ output_textarea("initialize is called!"); var elm = document.getElementById( "Rows" ); elm.innerHTML = ''; addRow(); }; function output_textarea( text ){ var objTextarea = document.getElementsByName('log_textarea')[0]; objTextarea.value += text; objTextarea.value += "\n"; } function onClickedGet( currentIndex ){ output_textarea( "onClickedGet is called." ); output_textarea( "currentIndex is " + currentIndex ); if( document.getElementsByName('command_label_' + currentIndex)[0].value == "" ){ alert("Please Enter command name."); return; } if( currentIndex > 20 ){ output_textarea( "Fully registrated..." ); alert("Fully registrated... Please Reflesh by F5!" ); return; }else{ addRow(); } preparePost( currentIndex ); getIRData( currentIndex ); } function onClickedPost( currentIndex ){ output_textarea( "onClickedPost is called." ); output_textarea( "currentIndex is " + currentIndex ); sendIRData( currentIndex ); } function addRow(){ var i = 0; var numNextIndex = gCurrentRowNum + 1; var elm = document.getElementById( "Rows" ); var obj = '<div id="Row_' + numNextIndex + '"><input type="text" name="command_label_' + numNextIndex + '">' + '<input type="button" name="btGet_' + numNextIndex + '" value="GET" onclick="onClickedGet( ' + numNextIndex + ' );"></div>' + '<br>'; for( i = 1; i < gCurrentRowNum + 1; i++ ){ gArrayRowCmdName[i-1] = document.getElementsByName('command_label_' + i)[0].value; if( gCurrentRowNum != i ){ gArrayRowData[i-1] = document.getElementsByName('command_data_' + i)[0].value; } } elm.innerHTML += obj; for( i = 1; i < gCurrentRowNum + 1; i++ ){ document.getElementsByName('command_label_' + i)[0].value = gArrayRowCmdName[i-1]; if( gCurrentRowNum != i ){ document.getElementsByName('command_data_' + i)[0].value = gArrayRowData[i-1]; } } gCurrentRowNum++; } function preparePost( currentIndex ){ document.getElementsByName('command_label_' + currentIndex)[0].readOnly = true; document.getElementsByName('btGet_' + currentIndex)[0].disabled = true; var elm = document.getElementById( "Row_" + currentIndex ); var obj = '<input type="button" name="btPost_' + currentIndex + '" value="POST" onclick="onClickedPost( ' + currentIndex + ' );">'; obj += '<input type="text" name="command_data_' + currentIndex + '">' elm.innerHTML += obj; document.getElementsByName('command_label_' + currentIndex)[0].value = gArrayRowCmdName[currentIndex-1]; } /* Constants */ var HTTP_SCHEME_STRING = "http://"; var IRKIT_IP_ADDR = "10.0.1.2"; var API_CONTROL_PORT = "/messages"; function getIRKitURL() { return HTTP_SCHEME_STRING + IRKIT_IP_ADDR + API_CONTROL_PORT; } function postWebAPI( webAPI_command, callback_func ) { var url = getIRKitURL(); jQuery.ajax( url, { crossDomain: true, type: "POST", dataType: 'text', data: webAPI_command , success: function(result){ output_textarea( "Post Success" ); } }); } function sendIRData( currentIndex ) { output_textarea( "sendIRData is called." ); var data = document.getElementsByName('command_data_' + currentIndex)[0].value; var webAPI_command = JSON.stringify( data ); postWebAPI( webAPI_command, sendIRDataCallback ); } // getIRData function getIRData( currentIndex ) { output_textarea( "getIRData is called." ); output_textarea( "currentIndex is " + currentIndex ); var url = getIRKitURL(); jQuery.ajax( url, { crossDomain: true, type: "GET", dataType: 'text', success: function(text){ output_textarea( text ); document.getElementsByName('command_data_' + currentIndex)[0].value = text; output_textarea( "GET method success!" ); }}); } // unused.... function sendIRDataCallback( responseText ) { output_textarea("sendIRDataCallback is called."); output_textarea("responseText is " + responseText); }