はじめに
12/8にRaspberryPi向けのMESH Hubアプリケーションが公開されました。
これでiPadがお散歩に出ていてもMESHを使い続けることが出来るようになったので、自宅を制御しているRaspberryPi上のNode-REDとつなぎこんでみました。
この記事はNode-RED UG勉強会2017年末パーティでLTさせていただいた内容をもう少し詳細に書いたものです。
前提
raspbian Stretch Linux kernel 4.9.59-v7+
Node-RED v0.17.5
mesh_1.0.0_armhf.deb
で確認しています。
基本方針
Node−REDを動かしているRaspberryPi上にMESH Hubを追加インストールしてRaspberryPi内でつなぎます。
Node-REDの方が細かな制御を書けるのと、既に家の制御を取り仕切っているのでMESH側は各タグの情報を取得して同じRaspberryPi上のNode-RED httpノードに投げるだけの実装にします。
今回はMESHに出力する方向(LEDタグとGPIOタグの出力)に関しては対応していません。
家庭内LANの中で使う分にはそれほど問題無いかと思いますが、セキュリティ的に厳重にする必要がある場合は別途対策してください。
MESH側の対応
基本的にはMESHのweb pageに書かれている通りになります。
判りにくいところだけ書いておきますので、MESHのページをよく読んで下さい。
- MESH Hubのインストール
- カスタムタグの作成
- Node-REDに投げるためのレシピの作成
を順番にしていきます。
MESH Hubのインストール
MESH Hubのページの「MESHハブのインストール方法はこちら」の
- MESHハブのインストールと起動
- 初期セットアップ
の手順を行ってください。
RaspberryPiのI2C,UART,PCMIFを使用している場合
MESHハブ用status boardはGPIO2,3,4,14,15を使用しているようです。I2C,UART,PCMIFを使用している場合は使えません。
また、これらのI/Fを使用している場合、MESHハブのアプリケーションからアクセスさせない設定をする必要があります。
「1.MESHハブのインストールと起動」の中の「③MESHハブアプリケーションの起動」の前に以下を実行してファイルを作成してください。
echo "false" > /opt/mesh/local/DISABLE_GPIO_CONTROL
先にmesh startをしてしまった場合、IOの設定が変わっていると思うのでファイルを作成後、再起動してください。
MESH-SDKでカスタムタグ作成
MESH SDKのページの「リファレンスマニュアルを確認する」にざっと目を通してください。
今回はNode-REDと接続するカスタムタグを用意してますのでImportの仕方と、SaveしたあとのタブレットのMESHアプリケーションへの追加の仕方(開発方法ー>追加)の部分を読んでおいてください。
次に「MESH SDKを使う」に入ります。ログインアカウントはMESHハブのものと同じです。
作成画面に入ったら「Create New Tag」でタグの作成画面に入ります。
Importを開いて、Imported JSON Dataに下のjsonデータをcopy&pasteします。
{"formatVersion":"1.0","tagData":{"name":"Node-RED","icon":"data:image/png;base64,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","description":"Connect to Node-RED","functions":[{"id":"function_0","name":"New Function","connector":{"inputs":[{"label":""}],"outputs":[{"label":""}]},"properties":[{"name":"Node-RED URL","referenceName":"NodeRedURL","type":"string","defaultValue":"mesh-if"}],"extension":{"initialize":"","receive":"","execute":"ajax ({\n url : \"http://localhost:1880/\" + properties.NodeRedURL,\n type : \"post\",\n data : JSON.stringify( messageValues ),\n contentType : \"application/json\",\n dataType : \"json\",\n timeout : 5000,\n success : function ( contents ) {\n\t\t callbackSuccess( {\n\t\t\tmessageValues: contents,\n\t\t\tresultType : \"continue\"\n\t\t});\n\t},\n\terror : function ( request, errorMessage ) {\n log(errorMessage);\n callbackSuccess( { resultType : \"continue\" }); \n },\n});\nreturn { resultType : \"pause\" };","result":""}}]}}
入力があった時に実行されるのはExecuteの部分で下記のコードになります。上で作成したタグからの抜粋です。
ajax ({
url : "http://localhost:1880/" + properties.NodeRedURL,
type : "post",
data : JSON.stringify( messageValues ),
contentType : "application/json",
dataType : "json",
timeout : 5000,
success : function ( contents ) {
callbackSuccess( {
messageValues: contents,
resultType : "continue"
});
},
error : function ( request, errorMessage ) {
log(errorMessage);
callbackSuccess( { resultType : "continue" });
},
});
return { resultType : "pause" };
修正が必要なければ、そのままSaveを実行してください。
MESHのレシピの作成
最初にタブレットのMESHアプリを開き、右上の端末マークのボタンを開いて操作する端末がRaspberryPiになっていることを確認してください。
次に右上の「・・・」から「アカウント」選んでSDKのアカウントでサインインしてください。
新しいレシピを選んでレシピを作成します。
接続したいMESHタグを使いたいタスク全ての種類分並べます。それぞれのタスクの設定も忘れずに。
作成したNode-REDタグもURLを設定します。defaultはmesh-ifになっていて、http://localhost:1880/mesh-ifにpostする仕様になっています。Node-RED側の環境に合わせて変更してください。

MESH側の設定は以上になります。
Node-RED側の対応
Node-RED側はやりたいことを実装するので実際には照明やエアコンを制御したり、鍵を制御したりすることが出来るのですが、ここでは本題ではないので処理の代わりにdebugノードを置いておきます。
MESHからのhttp postを受けてhttp responseを返し、最新状態のステータスをまとめてdebugノードに出力されます。debugノードの出力をみるとpayloadにどのようなデータが来ているか判るのでいろいろなものに繋ぎこんでみてください。

以下、それぞれのノードの設定を説明します。
http inノード
メソッドはpostで来るのでpostを選択してください。
URLはMESH側で設定したものを設定します。Node-REDのconfigによってルートURLが変わっている場合があるので動かない場合はconfigも確認してください。ここではhttp://localhost:1880/mesh-ifを想定しています。
名前は適当にMESHとでもつけておいてください。

http responseノード
応答する状態コードだけ正常の200に設定してください。

switchノード
名前は適当につけてください。
msg.payload.functionIdにMESHタグのタスクの種類が入ってきますのでその種別ごとに出力を分離します。
ここでは動きタグの出力をShake,Orientation,Flipに分離しています。

joinノード
動作を手動に、結合をmsg.payloadに、出力を統合オブジェクトに設定します。
メッセージ送信は指定数のメッセージパーツを受信後を1、後続のメッセージ毎をチェックします。
これで、入力されたメッセージのpayloadを合成したものが出力されます。
わざわざswitchで分離してなんでまたjoinするのかというと、http postで来るpayloadは、それぞれのタスクの出力ごとにバラバラに時間差で来るため何処かで最終的なステータスを保持していないと後段の処理がやりにくいためです。
ここで一度分離後joinしておけば最初のデータが来た後は常にタスクごとの最終値が入ったpayloadが来るためあまり面倒な処理をせずに済みます。

まとめ
家電や設備の制御などのIoTとMESHは非常に相性が良く色々な応用ができます。
例として、MESHの動きタグを使って照明などのシーン切り替えをするサイコロをつくってみました。
MESHの向きが変わったことを検知して上の面に描かれているシーンに合うように照明やTVなどを制御するものです。
サイコロの作り方については結構手順が複雑なので別途書こうかと思います。
サイコロの作り方について書きました。
SonyのMESHを入れるサイコロを作ってみた


他にも人感タグや温湿度タグ、明るさタグなどいろいろ応用できそうなタグがありますので、是非いろいろな応用を考えてみてください。