前回までの記事でSkyWayのJavaScriptでの動作確認を行いました。またRaspberry Piでの動作も確認出来ました。そうすると今回はSkyWayを利用してRaspberry Piの遠隔操作をしてみようという内容です。今回はまずはRaspberry Pi側でのブラウザ(JavaScript)からMQTT over WebSocketを使ってRaspberry PiのGPIOを操作するという内容です。
全体的な遠隔操作の方法について
以前に以下から始まる一連の記事でもRaspberry Piでの遠隔操作について書きました。これらの記事で書いた方法はMQTTをインターネット上で利用して遠隔操作を行うという方法です。
Raspberry PiでIoT(MQTTで遠隔操作編 その1)MQTTでの通信
今回の遠隔操作の方法は、MQTTはローカルのRaspberry Pi内で利用して、インターネット上はSkyWayを利用します。この方法のメリットはSkyWayのP2Pのイメージの延長線で遠隔操作が出来るということです。より直接的な遠隔操作のイメージになると思います。

最終的にはリモート側で以下のように遠隔操作と映像モニターが出来ます。

MQTT over WebSocketを利用する
そこでまず今回は、そのRaspberry PiローカルでのMQTTの通信の確認です。上の図で左下のRaspberry Piローカルの部分です。要点はブラウザからMQTT over WebSocketを利用してRaspberry Piと通信してGPIOを操作するということです。
以下のような構成(キーボード、マウスもUSBで接続しています。)で画面上のブラウザのボタンをクリックするとRaspberry Piに接続されたLEDのオンとオフを操作出来ます。

Raspberry Pi側ではPythonプログラムでMQTTのsubscribeをしています。ブラウザでボタンをクリックしたらローカルのRaspberry Piにpublishします。これでGPIOを操作します。
Raspberry Piでの準備
実際にやってみます。
Mosiquitto関連のインストール
まずは、Raspberry PiでMosquitto(Broker)をインストールします。
$ sudo apt-get install mosquitto
以下のように状態を確認します。activeが確認出来ます。
$ sudo service mosquitto status
次にMosquittoクライアントをインストールします。
$ sudo apt-get install mosquitto-clients
インストール時のスクリーンショットや基本的な動作確認は以下で書きました。必要な場合はこちらも参照して下さい。
Raspberry PiでIoT(MQTTで遠隔操作編 その1)MQTTでの通信
設定ファイルの編集(重要です。)
/etc/mosquitto/mosquitto.conf を編集します。
以下の内容を追記します。
listener 1883
listener 9090
protocol websockets
これは、以下を指定しています。
MQTTが1883番ポート
WebSocketが9090番ポート
これがないとブラウザと通信出来ないので必ず指定しておきます。
もちろんポート番号は何でもいいですが、この番号が比較的既定のようです。ここから先はこのポート番号を前提にして進みます。
この設定を変更したら以下でmosquittoサービスを再起動します
$sudo systemctl restart mosquitto
Raspberry PiのGPIO操作(Lチカ)のためのsubscribe
python3のプログラムを作成して利用します。
paho-mqttというライブラリを使用しますので以下のようにインストールしておきます。
$sudo pip3 install paho-mqtt
以下のようなpythonプログラムを作成しました。
import paho.mqtt.client as mqtt
import RPi.GPIO as GPIO
import time
def on_connect(client, userdata, flag, rc):
print("Connected with result code "+str(rc))
client.subscribe("isyjp/gpio21")
def on_message(client, userdata, msg):
print(msg.topic+" "+str(msg.payload))
GPIO.output(21,1)
if msg.payload == b"on":
GPIO.output(21,1)
print("on")
else:
GPIO.output(21,0)
print("off")
def on_disconnect():
pass
GPIO.setmode(GPIO.BCM)
GPIO.setup(21, GPIO.OUT)
client = mqtt.Client()
client.on_connect = on_connect
client.on_disconnect = on_disconnect
client.on_message = on_message
client.connect("localhost",1883,60)
client.loop_forever()
コメントが全くないですが、プログラムの説明は後にして先に動作確認をします。
ここまでのmosquittoの準備が出来ているという前提でこのsubscribeプログラムを起動します。特にGPIOには何も接続されていなくていいです。

待ちの状態になります。
別のターミナルでpublishをします。ホスト、ポート、topicを指定してonというメッセージを送信します。すぐに終了します。

subscribe側に戻ります。

確かにメッセージを受け取りました。
プログラムの説明を書きます。
mqttの処理とgpioの処理で構成されています。
mqttの操作はpaho-mqttのclientを利用しています。clientを生成してmqttのbrokerに対しての接続、切断時とメッセージ到着時の処理を準備してローカルのブローカーに接続して待機しています。
gpioの処理はgpioを出力に設定して、clientのメッセージ到着時の処理で、onが来たらgpio21をonにしてoffが来たらgpio21をoffにしています。
これでgpioにLEDを正確に接続しておけばLチカが出来ます。
ローカル上で稼働するという前提でsslは考慮していないです。
以上でRaspberry Pi側の準備は完了です。
ここではターミナルからpublishして動作確認しましたが以下からはブラウザから同様のことをやります。
ブラウザからのメッセージ送信
ブラウザで表示するページの作成
以下のようなページを作成して利用可能なWebサーバに公開します。Webサーバはどこで稼働していても問題ないです。
ソースは以下です。
<html lang=ja>
<head>
<title>MQTT over WebSocket test</title>
<meta charset="UTF-8">
<style></style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.js" type="text/javascript"></script>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script type="text/javascript">
var mqtt;
$(function()
{
mqtt = new Paho.MQTT.Client("localhost", 9090, "cli01");
console.log("conncting");
var options = {
timeout: 60,
onSuccess: onConnect,
onFailure: onFailure,
};
mqtt.onMessageArrived = onMessageArrived;
mqtt.connect(options);
});
function onConnect()
{
console.log("on Connect");
mqtt.subscribe("isyjp/tp01");
}
function onMessageArrived(msg)
{
console.log("on Arrived");
console.log(msg.payloadString)
$('#message').text(msg.payloadString);
}
function onFailure()
{
}
function ledon()
{
message = new Paho.MQTT.Message("on");
message.destinationName = "isyjp/gpio21";
mqtt.send(message);
console.log("led on.");
}
function ledoff()
{
message = new Paho.MQTT.Message("off");
message.destinationName = "isyjp/gpio21";
mqtt.send(message);
console.log("led off.");
}
</script>
</head>
<body>
websocket test <br/>
<p><button type="button" onclick="ledon()">ローカル接続のled on</button></p>
<p><button type="button" onclick="ledoff()">ローカル接続のled off</button></p>
<p><div id="message">受信データ</div></p>
</body>
</html>
コメントが何も書いていないですが、Raspberry Piのpythonプログラムと同様にpaho-mqttのライブラリ(こちらはJavaScript)を利用しています。
Raspberry Piのローカルのmqtt brokerと通信するためのclientを生成して(ポート番号はwebsocketの9090の方です。)接続時の処理、メッセージ到着時の処理を定義しています。今回はボタンからのメッセージ送信がメインですが、一応メッセージ到着時を想定して画面に表示するようにしています。
GPIOのボタン処理ですが、mqttのclientで直接送信しています。このように直接送信が出来るのでプログラムも簡単になると思います。これがMQTT over WebSocketを利用するポイントです。
これをRaspberry Pi上でブラウザから操作すると写真の構成でLEDのオンとオフが確認出来ました。これもローカル上で稼働するという前提でsslは考慮していないです。
以上で今回のテーマのMQTT over WebSocketでの動作が確認出来ました。次回は今回の操作をSkyWayを経由して遠隔のブラウザから操作してカメラでモニタしてみます。
