IDE for GR のサンプルスケッチを見てたら、
GR-ROSE用のサンプルスケッチに、MQTT を使うものがあるのか!
— you (@youtoy) October 26, 2021
AP の接続情報と、MQTTブローカーの IPアドレスを指定したら、あっさり動いた。
MQTTブローカーは、https://t.co/8lBLAbVM2k のデスクトップアプリで、宅内のローカルネットワークを通じて通信する構成にしました。 pic.twitter.com/MK4vuML7ti
MQTT通信
今回、GR-ROSE が MQTT で通信する先は、GR-ROSE のプログラム開発を行う環境でもある Mac にしました。
それら両方のデバイスが同じローカルネットワークにいる状態にして進めていきます。
MQTTブローカーを準備する
MQTTブローカーは、上で構成について書いた部分で登場していた Mac を使います。
その Mac上で、過去に書いた記事の中でも何度も使っている shiftr.io のデスクトップアプリを動作させました。
とりあえず、このアプリを動かせば、デフォルトのポートで MQTT の通信を待ち受ける MQTTブローカーが用意された状態になります。
Mac内の MQTTクライアントからつなぐ形であれば、クライアント側で指定する接続先は「localhost」等を指定すれあ良いですが、今回は Mac の外(GR-ROSE)から通信する構成なので、「接続先として指定する IPアドレス = Mac の IPアドレス」を確認しておきます。
GR-ROSE関連の部分
用いたプログラム
GR-ROSE側は、以下のツイートにも書いている「PubSubClient」の「mqtt_basic」というサンプルを使いました。
GR-ROSE側は、サンプルスケッチの「PubSubClient」の「mqtt_basic」というのを使いました。 pic.twitter.com/a7wW9miIqZ
— you (@youtoy) October 26, 2021
以下のプログラムになるのですが、変更を加えたのは「アクセスポイントの SSID・パスワード」を指定する行と、MQTTブローカーの IPアドレス(上で確認しておいた Mac の IPアドレス)を指定する部分だけです。
/* MQTT example: mqtt_basic (for GR-ROSE)
*/
#include <WiFiEsp.h>
#include <WiFiEspClient.h>
#include <WiFiEspUdp.h>
#include <PubSubClient.h>
char ssid[] = "【AP の SSID】"; // your network SSID (name)
char pass[] = "【AP のパスワード】"; // your network password
int status = WL_IDLE_STATUS; // the Wifi radio's status
IPAddress server(【MQTTブローカーの IPアドレス】); // server for broker
WiFiEspClient espClient;
void callback(char* topic, byte* payload, unsigned int length);
PubSubClient client(server, 1883, callback, espClient);
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i=0;i<length;i++) {
Serial.print((char)payload[i]);
}
Serial.println();
}
void setup() {
// initialize serial for debugging
Serial.begin(115200);
// initialize serial for ESP module
Serial6.begin(115200);
// initialize ESP module
WiFi.init(&Serial6);
// check for the presence of the shield
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue
while (true);
}
// attempt to connect to WiFi network
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network
status = WiFi.begin(ssid, pass);
}
// you're connected now, so print out the data
Serial.println("You're connected to the network");
}
void loop() {
// put your main code here, to run repeatedly:
if (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("GR-ROSE")) {
Serial.println("connected");
// Once connected, publish an announcement...
client.publish("outTopic","hello world");
client.subscribe("inTopic");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
} else {
static uint32_t last_time = millis();
if((millis()-last_time) > 100) client.loop();
}
if(client.connected()){
static int count = 0;
char buffer [50];
sprintf(buffer, "%d", count);
client.publish("outTopic", buffer);
count++;
delay(500);
}
}
プログラム内の Pub/Sub に関する部分
プログラムの中を見てみると、MQTT のトピック・メッセージ等を指定しているのは、以下となっているようです。
client.publish("outTopic","hello world");
client.subscribe("inTopic");
GR-ROSE から外向きへの通信となるところでは、MQTT のトピックに「outTopic」を指定しているようです。
その逆の内向きへの通信では、MQTT のトピックに「inTopic」が指定されています。
GR-ROSEと別に、もう 1つクライアントを準備して、さらなるお試しをやってみます。
もう 1つの MQTTクライアントを準備する
過去に書いた MQTT関連の記事の中の 1つに、以下の内容のものがあります。
●MQTTクライアントをコマンドラインで簡単に実行する(npx と MQTT.js) - Qiita
https://qiita.com/youtoy/items/edeaa9cc316d5f47c0e8
ここで登場する方法で、MQTT の Pub/Sub を試すことにします。
Subscribe
まずは、Subscribe(GR-ROSE からのメッセージを受けとる方向)です。
npx mqtt sub -t '【トピック】' -h '【ホスト名】'
というコマンドを使います(※ npm が使える環境が必要です)。
具体的には npx mqtt sub -t 'outTopic' -h 'localhost'
という内容にしました。
それを実行した結果は以下のとおりで、無事に数値のデータを受信できました。
GR-ROSE からの MQTT による通信を
— you (@youtoy) October 26, 2021
npx mqtt sub -t '【トピック】' -h '【ホスト名】'
というコマンドで Subscribe!
(過去に、以下の記事で書いていた方法です)https://t.co/yvTqyyac5P
そして、MQTTブローカー経由で受けとった、カウントアップされる数字が表示されるのを確認できました。 pic.twitter.com/ohVxpATtwX
元のプログラムでいうと、以下の部分が上記の数値を送っている部分になります。
if(client.connected()){
static int count = 0;
char buffer [50];
sprintf(buffer, "%d", count);
client.publish("outTopic", buffer);
count++;
delay(500);
}
Publish
今度は、Publish(GR-ROSE へメッセージを送る方向)です。
今度も先ほどと似たような方法で、 npx mqtt pub -t '【トピック】' -h '【ホスト名】' -m '【メッセージ】'
というコマンドを使います。
具体的には npx mqtt pub -t 'inTopic' -h 'localhost' -m 'test message'
というコマンドにして、単発のメッセージ送信を行いました。
その後、シリアルモニタ上で「test message」という文字列を受信できているのを確認できました。
GR-ROSE が受信する方向の MQTT通信、これも
— you (@youtoy) October 26, 2021
npx mqtt pub -t '【トピック】' -h '【ホスト名】' -m '【メッセージ】'
という単発のコマンドで実行してみた。
無事、シリアルモニタに送った文字列が表示されたのを確認できました。 pic.twitter.com/gO07vYOsmf
おわりに
GR-ROSE絡みのプログラムは、基本的にはサンプルをそのまま用いる形で MQTT を試せました。
その際に必要になる MQTTブローカーはローカルに用意し、GR-ROSE とは別の MQTTクライアントは、npm さえ使える状態ならパッケージを用意してない状態でもコマンド実行のみで動かせるようなコマンドで準備しました。
進めていく中で特にはまるポイントもなかったため、お試しから記事を書くまで短い時間でできて良かったです。