Raspberry Piがあれば簡単にスマートフォンで家電を操作できる

MQTTノード
Node-REDでは簡単にネットサービスを作れます。
Raspberry Piを使ってGoogle Homeと赤外線リモコンをつなぐことができました。次はスマートフォンと赤外線リモコンをつないでIoTごっこをしたいです。

Raspberry PiをMQTTブローカーにしてスマートフォンとメッセージのやり取りをすれば赤外線リモコンのコントロールもできそうです。


Rapberry PiにはNode-REDというjavascriptのプログラミングツールがあります。データの流れをグラフィカルに表しGUI上で多彩なライブラリを使いネットワークサービスを作ることができます。
以前の記事ではGoogle Homeへの音声で赤外線リモコンを発光させてテレビやエアコンのコントロールをしました。
関連記事:Google HomeとRaspberry PiのNode-REDで赤外線リモコンのコントロールをする


今回はスマートフォンから赤外線リモコンを動かして家電をコントロールしてみます。
スマートフォンとRaspberry PiとはMQTTプロトコルを使ってつないでみます。

MQTTでRaspberry Piとスマホをつなぐ

MQTTの詳しいことは知りませんので他のサイト様にお任せです。検索してください。

簡単に解説をしておきます。
MQTTにはブローカーというサーバーが必要です。あとはブローカーへつながるクライアントです。クライアントはブローカーへメッセージを投げたり受け取ったりします。

クライアント同士が直接つながる事はありません。クライアントは他にクライアントが存在するかどうか判りませんし知る必要もありません。メッセージはすべてブローカーとだけやり取りされます。

メッセージにはトピックという名前のようなものを付けます。メッセージはトピックによって整理され、クライアントはトピックを指定してメッセージを受けたり送ったりします。
サーバーがメッセージの加工をする事はありません。トピックに従いメッセージを右から左へ流します。

スマートフォンはアプリを入れるとMQTTクライアントにできます。いろいろなアプリが公開されています。画面にボタンやスイッチを配置したり、温度計やグラフを表示するものもあります。
Raspberry PiはNode-REDを使うとすぐにMQTTクライアントにできます。また、Node-REDから赤外線リモコンを動かす事は以前の記事でやりました。

足りないのはMQTTブローカーです。インターネット上にはMQTTブローカーのサービスを提供している所もあります。お手軽にはそういったサービスを使うのもありです。
今回はRaspberry Piにブローカーとクライアント両方の役割をしてもらいます。Node-REDのライブラリからMQTTブローカーのノードを追加します。

Raspberry PiをMQTTブローカーにする

Node-REDのライブラリを検索するとMQTTブローカーのノードがあります。
node-red-contrib-mqtt-broker | Node-RED
MQTT Broker server on Node-RED
これを追加します。

node-red-contrib-mqtt-brokerのインストール


Node-RED パレットの管理
Node-REDのメニューからパレットの管理をクリックします。

mqtt brokerの検索
"ノードを追加"タブで"mqtt-broker"と入力します。
node-red-contrib-mqtt-brokerが見つかります。"ノードの追加"をクリックするとインストールが始まります。
数分かかりインストールが終わります。

MQTTブローカー
入力パレットにノードが追加されました。
早速使ってみましょう。

moscaノード編集
ノードをflow編集画面へドロップした後にダブルクリックすると編集画面が表示されます。MQTTで使うポート番号を指定します。デフォルトは1883になっています。
MQTT WS portはWebSocket用と思われるポート番号を入れます。ですが使い方がわかりませんでした。
何も変更することなく"完了"を押します。

これでデプロイすればMQTTブローカーは動き始めます。何か変化が見られるわけでもありませんが動いてます。

Raspberry PiをMQTTクライアントにする

MQTTクライアントを作ってメッセージのやりとりをしてみます。

MQTTフロー
injectノードとMQTT outノードをつなぎます。MQTT inノードとデバッグノードをつなぎます。
injectノードは現在時刻を整数の文字列で出力します。MQTT outノードはその文字列をメッセージとしてパブリッシュします。パブリッシュとはブローカーへ送信する事です。
MQTT inノードはブローカーからメッセージをサブスクライブします。サブスクライブとは受信する事です。

MQTTのノードにはマークが付きエラーがある事がわかります。メッセージのトピックを設定していないからです。また、どこのブローカーへせつぞくするのかをまだ設定していません。ブローカーのアドレスとトピックを設定しなくてはなりません。
MQTT outノードをダブルクリックします。

mqtt設定
サーバー(ブローカー)とトピックを設定します。
まずはサーバーを設定します。"新規にmqtt-brokerを追加..."を選び右横の鉛筆マークをクリックします。

ブローカーの指定
サーバーのアドレスを入れる画面が表示されます。
ブローカーはRaspberry Pi自身で動かしていますので、サーバーへ"localhost"と入れます。インターネット上のMQTTサービスを使う場合はサービス会社指定のURLとポート番号を入れます。
余談ですがクライアントではSSL/TLSの暗号化を指定できるようですが、今回使うブローカー側が暗号化に対応していないので使えませんでした。

”追加”をクリックし閉じます。
その後、トピックを記入します。トピックはメッセージの名前のようなものです。今回は時刻データをメッセージで送るので”date"としてみます。
"完了"を押し閉じます。

同様にMQTT inノードを設定します。
サーバーは先ほど登録したのでドロップダウンリストにlocalhostが表れます。それを選択します。
トピックは先ほどの"date"を指定すると時刻メッセージを受け取る事になります。トピックが異なれば受け取る事はありません。

MQTTでメッセージをやり取りしてみる


MQTTフロー
フローは上図のようになるでしょう。
ここまでのフローを次に置いておきます。
[{"id":"fabd6c4a.debf2","type":"mosca in","z":"763db2ee.d579ac","mqtt_port":1883,"mqtt_ws_port":8080,"name":"","username":"","password":"","dburl":"","x":172,"y":81,"wires":[["f9749f97.29f6e"]]},{"id":"f9749f97.29f6e","type":"debug","z":"763db2ee.d579ac","name":"","active":true,"console":"false","complete":"false","x":388,"y":80,"wires":[]},{"id":"c5cd8b99.278158","type":"inject","z":"763db2ee.d579ac","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":341,"y":204,"wires":[["aaf3dcfc.c3535"]]},{"id":"aaf3dcfc.c3535","type":"mqtt out","z":"763db2ee.d579ac","name":"","topic":"date","qos":"","retain":"","broker":"c57ac545.162c28","x":518,"y":203,"wires":[]},{"id":"e9d3b047.a0c0f","type":"comment","z":"763db2ee.d579ac","name":"MQTTブローカー","info":"","x":161,"y":35,"wires":[]},{"id":"68d530cf.60421","type":"comment","z":"763db2ee.d579ac","name":"MQTTクライアント","info":"","x":164,"y":161,"wires":[]},{"id":"2f6e13a7.9b4d1c","type":"mqtt in","z":"763db2ee.d579ac","name":"","topic":"date","qos":"2","broker":"c57ac545.162c28","x":322,"y":258,"wires":[["ea277f0d.1f517"]]},{"id":"ea277f0d.1f517","type":"debug","z":"763db2ee.d579ac","name":"","active":true,"console":"false","complete":"false","x":531,"y":258,"wires":[]},{"id":"8da07442.b9d4f8","type":"comment","z":"763db2ee.d579ac","name":"パブリッシュ","info":"","x":148,"y":203,"wires":[]},{"id":"11b3986a.3721e8","type":"comment","z":"763db2ee.d579ac","name":"サブスクライブ","info":"","x":156,"y":260,"wires":[]},{"id":"c57ac545.162c28","type":"mqtt-broker","z":"","broker":"localhost","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"willTopic":"","willQos":"0","willPayload":"","birthTopic":"","birthQos":"0","birthPayload":""}]

デプロイして動かしてみましょう。
injectノード左横のボタンをクリックするとデバック画面に時刻データが表示されるでしょう。

MQTTのメッセージはトピックで区別してパブリッシュ/サブスクライブします。トピック名を変えるとメッセージが受信できなくなります。実験してみてください。

Raspberry PiでMQTTのメッセージの送受信ができるようになりました。次はスマートフォンとメッセージをやり取りしましょう。

スマートフォンのMQTTクライアントアプリを使う

私はAndroidしか使わないのでAndroidの場合で説明します。iPhoneのアプリでも基本的に同じ設定をする事になるでしょう。

スマートフォンは家のWiFiに接続しRaspberry Piと同じLAN内にあるとします。Raspberry PiのIPアドレスを調べてください。ここでは192.168.11.11がRaspberry Piのアドレスだとします。

スマートフォンでMQTTのメッセージを扱うアプリは沢山あります。Google Play StoreでMQTTと入れて検索してみてください。Dashboardと書いてあるアプリがいろいろなボタン、スイッチやメーターを配置できそうです。
MQTT Dash (IoT, Smart Home)が高機能なのですが、高機能過ぎて設定項目が多く説明が大変です。
今回は
IoT MQTT Dashboard
を使ってみます。
インストールしてアプリを動かします。
iotmqttdashboard初期画面

プラスボタンを押すとブローカーの設定画面が開きます。
iotmqttdashboardブローカー設定
IDは適当に、サーバーはRaspberry PiのIPアドレス、Portは1883です。
入力したら右上の"CREATE"をタップします。
するとブローカーが登録され画面に表示されるのでタップして選択します。
するとこんな画面が出ました。
iotmqttdashboardクライアント画面
SBSCRIBEがメッセージを受ける方、PUBLISHはメッセージを送る方ですね。
SUBSCRIBEで画面右上の"+"をタップします。

iotmqttdashboardサブスクライブ設定
Friendly nameは適当に、Topicには先ほどNode-REDで実験した"date"を設定します。
画面右上の”CREATE”を押します。

iotmqttdashboardサブスクライブ画面
パネルが追加されました。

先ほどのNode-REDでinjectノードのボタンを押してみます。
iotmqttdashboardメッセージの表示
メッセージを受け取り表示しました。

同様にPUBLISHにトピック"date"で追加してみましょう。
iotmqttdashboardパブリッシュパネルの追加
何かパネルの種類が選択できるようです。今回はButtonにしてみましょう。

iotmqttdashboardパブリッシュボタン
トピックに今までと同じく”date”を設定します。
メッセージは"テストメッセージ"にしてみます。

iotmqttdashboardパブリッシュパネル
パネルにボタンが追加されました。
押してみましょう。

受信したメッセージ
SUBSCRIBEパネルへ戻ると"テストメッセージ"と表示されているでしょう。
Node-REDのデバッグペインに"テストメッセージ"と表示されます。

MQTTは簡単にメッセージのやり取りができます。
トピックで指定したメッセージを表示したり送信したりできます。送信する側も受信する側も相手がいくついるか、どこから来るのかを意識する必要はありません。トピックで指定したメッセージをブローカーとやり取りするだけです。

このアプリはNode-REDでデプロイすると接続が切れて再接続してくれないのかな?再接続してください。

スマートフォンから赤外線リモコンを動かす

ここまで試せば赤外線リモコンを動かすのは簡単です。
スマホのボタンが押されたらNode-REDのMQTT inノードへメッセージが届きます。そのflowに赤外線リモコンを動かすノードを配置するだけです。

flow
[{"id":"b5741709.aea1c8","type":"template","z":"763db2ee.d579ac","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"Light1_ON.dat","output":"str","x":235,"y":367,"wires":[["b3c43e58.429d1"]]},{"id":"b3c43e58.429d1","type":"exec","z":"763db2ee.d579ac","command":"/home/pi/Downloads/ADRSIR/File2IR.sh","addpay":true,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"","x":482,"y":367,"wires":[["468bc47b.359e3c"],["468bc47b.359e3c"],["468bc47b.359e3c"]]},{"id":"468bc47b.359e3c","type":"debug","z":"763db2ee.d579ac","name":"","active":true,"console":"false","complete":"false","x":748,"y":367,"wires":[]},{"id":"63fc965.5e2d768","type":"mqtt in","z":"763db2ee.d579ac","name":"","topic":"date","qos":"2","broker":"c57ac545.162c28","x":91,"y":367,"wires":[["b5741709.aea1c8"]]},{"id":"c57ac545.162c28","type":"mqtt-broker","z":"","broker":"localhost","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"willTopic":"","willQos":"0","willPayload":"","birthTopic":"","birthQos":"0","birthPayload":""}]
MQTT入力のトピックを"date"にしてテンプレートノードへ渡します。テンプレートノードでは赤外線コードの入ったファイル名が書かれています。そして赤外線を光らせる外部プログラムを呼び出しています。

これで先ほどのスマートフォンのパブリッシュボタンを押してみましょう。赤外線リモコンが動くはずです。

簡単ですね。ボタンと赤外線コードを増やすにはボタンのトピックを変えて増やていきます。トピックに対応したMQTT inノードも配置します。
トピックには"/"を使って階層表現のような指定もできます。例えば "Living/Light1/OnOff"とか"Living/TV/VolumeUp"とかです。トピックの階層指定にワイルドカードを使えます。ワイルドカードについて詳細は他のサイト様へお任せです。検索してみてください。
これらのメッセージを受けてflowが流れ始めればよいので、次のように作れば良さそうです。
flow
スマートフォンの方にも対応したトピックでボタンを追加します。
もちろんスマートフォンへのメッセージも簡単に送れ、表示もできますね。
これでスマートフォンから動かす事ができると思いますが、MQTTの説明のため冗長な使い方をしました。
これではリモコンボタンを増やす都度にFlowも変更しなくてはなりません。

トピックをリモコンの設置場所と結び付けてメッセージに赤外線コードのファイル名を流せば一本道のflowが作れそうです。例えばトピックを"IR/Livingroom", "IR/Bedroom"とかにします。

すると前回の赤外線コントロールのFlowは次のようになります。
関連記事:Google HomeとRaspberry PiのNode-REDで赤外線リモコンのコントロールをする
MQTTで赤外線リモコンを動かすフロー
[{"id":"acd7d897.06b688","type":"http in","z":"1c942494.59789b","name":"","url":"/ifttt","method":"post","upload":false,"swaggerDoc":"","x":117,"y":228,"wires":[["5e68d82b.5ac728","c8eca294.afc7b","56f2a4d.4de5a5c"]]},{"id":"5e68d82b.5ac728","type":"http response","z":"1c942494.59789b","name":"","statusCode":"","headers":{},"x":327,"y":228,"wires":[]},{"id":"2ff2f101.890fde","type":"exec","z":"1c942494.59789b","command":"/home/pi/Downloads/ADRSIR/File2IR.sh","addpay":true,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"","x":476,"y":332,"wires":[["abc12dd2.9556e"],["abc12dd2.9556e"],["abc12dd2.9556e"]]},{"id":"abc12dd2.9556e","type":"debug","z":"1c942494.59789b","name":"","active":true,"console":"false","complete":"false","x":779,"y":334,"wires":[]},{"id":"c8eca294.afc7b","type":"debug","z":"1c942494.59789b","name":"","active":false,"console":"false","complete":"false","x":347,"y":268,"wires":[]},{"id":"56f2a4d.4de5a5c","type":"function","z":"1c942494.59789b","name":"FileName as String","func":"\nmsg.payload = msg.payload.FileName.toString();\nreturn msg;","outputs":1,"noerr":0,"x":177,"y":332,"wires":[["2ff2f101.890fde"]]},{"id":"c0b24e16.e8e4a","type":"mqtt in","z":"1c942494.59789b","name":"","topic":"IR/Living","qos":"0","broker":"c57ac545.162c28","x":149,"y":410,"wires":[["2ff2f101.890fde"]]},{"id":"60a33034.d324a","type":"mosca in","z":"1c942494.59789b","mqtt_port":1883,"mqtt_ws_port":8080,"name":"","username":"","password":"","dburl":"","x":143,"y":114,"wires":[["5ba0585c.d55ab8"]]},{"id":"5ba0585c.d55ab8","type":"debug","z":"1c942494.59789b","name":"","active":false,"console":"false","complete":"false","x":359,"y":113,"wires":[]},{"id":"8c48c0a4.3564e","type":"comment","z":"1c942494.59789b","name":"MQTTブローカー","info":"","x":132,"y":68,"wires":[]},{"id":"1489b19a.d6600e","type":"comment","z":"1c942494.59789b","name":"iftttからのpost処理","info":"","x":145,"y":176,"wires":[]},{"id":"6a7808c9.62b288","type":"comment","z":"1c942494.59789b","name":"MQTTからのメッセージ","info":"","x":197,"y":458,"wires":[]},{"id":"c57ac545.162c28","type":"mqtt-broker","z":"","broker":"localhost","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"willTopic":"","willQos":"0","willPayload":"","birthTopic":"","birthQos":"0","birthPayload":""}]
ブローカーを動かしてメッセージのファイル名を受け取るだけです。Node-RED、簡単すぎます。
スマートフォンのアプリではトピックを"IR/Living"に、メッセージ内容を赤外線コードのファイル名にしてボタンを追加しまくりましょう。

まとめ

MQTTブローカーをRaspberry Piで動かしてスマートフォンから赤外線リモコンを制御し家電をコントロールできるのがわかったと思います。MQTTは簡単にメッセージの交換ができます。
MQTTを使うとIoTってどんなものかより判ってくるでしょう。温度センサーを付けてスマホで見たくなります。まぁ意味はないけど・・・。

こうなるともう一台Raspberry Piと赤外線リモコンを追加して他の部屋もIoT化をしたくなりますが、費用高めなのが欠点です。zeroを使うにしても赤外線学習リモコンが高い。IoTな安価なリモコンとの組み合わせも必要ですね。

今回はLAN内で動かしましたが、インターネットへMQTTブローカーのIPアドレスとポートを公開すればそのまま動きます。世界中のどこからでも家のテレビの操作ができます。でも、安全ではないのでやらないでください。暗号化できるMQTTブローカーを使いましょう。
node-red-contrib-mqtt-brokerを使いMQTTブローカーを動かしましたが暗号化通信の設定はできないようです。セキュリティ設定ができればインターネットへ公開して使おうかと思ったのですがね。MQTTブローカーにインターネットのサービス会社のものを使えば暗号化して使うこともできるでしょう。暗号化するとパケットサイズが膨れ上がりMQTTのメリットが無くなっていくというのもあります。
node-red-contrib-mqtt-brokerとの接続でユーザーIDとパスワードの設定はできるようですが、すべて平文でやり取りされるのでセキュリティとしての意味はないでしょう。

Node-REDはネットにつながるもの同士を簡単に結び付けられておもしろいですね。スマートホームへまた一歩近づきました。

コメント

最近のコメント

Threaded Recent Comments will be here.