GR-ROSE でローカルネットワーク内での MQTT通信（MQTTブローカーは shiftr.io のデスクトップアプリ）

[IDE for GR](https://www.renesas.com/jp/ja/products/gadget-renesas/ide-gr) のサンプルスケッチを見てたら、


<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">GR-ROSE用のサンプルスケッチに、MQTT を使うものがあるのか！<br><br>AP の接続情報と、MQTTブローカーの IPアドレスを指定したら、あっさり動いた。<br>MQTTブローカーは、<a href="https://t.co/8lBLAbVM2k">https://t.co/8lBLAbVM2k</a> のデスクトップアプリで、宅内のローカルネットワークを通じて通信する構成にしました。 <a href="https://t.co/MK4vuML7ti">pic.twitter.com/MK4vuML7ti</a></p>&mdash; you (@youtoy) <a href="https://twitter.com/youtoy/status/1452994245904764937?ref_src=twsrc%5Etfw">October 26, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## MQTT通信
今回、GR-ROSE が MQTT で通信する先は、GR-ROSE のプログラム開発を行う環境でもある Mac にしました。
それら両方のデバイスが同じローカルネットワークにいる状態にして進めていきます。

### MQTTブローカーを準備する
MQTTブローカーは、上で構成について書いた部分で登場していた Mac を使います。

その Mac上で、過去に書いた記事の中でも何度も使っている [shiftr.io のデスクトップアプリ](https://www.shiftr.io/desktop/)を動作させました。
とりあえず、このアプリを動かせば、デフォルトのポートで MQTT の通信を待ち受ける MQTTブローカーが用意された状態になります。

Mac内の MQTTクライアントからつなぐ形であれば、クライアント側で指定する接続先は「localhost」等を指定すれあ良いですが、今回は Mac の外（GR-ROSE）から通信する構成なので、「接続先として指定する IPアドレス ＝ Mac の IPアドレス」を確認しておきます。

### GR-ROSE関連の部分
#### 用いたプログラム
GR-ROSE側は、以下のツイートにも書いている「PubSubClient」の「mqtt_basic」というサンプルを使いました。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">GR-ROSE側は、サンプルスケッチの「PubSubClient」の「mqtt_basic」というのを使いました。 <a href="https://t.co/a7wW9miIqZ">pic.twitter.com/a7wW9miIqZ</a></p>&mdash; you (@youtoy) <a href="https://twitter.com/youtoy/status/1452995915569111050?ref_src=twsrc%5Etfw">October 26, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

以下のプログラムになるのですが、変更を加えたのは「アクセスポイントの SSID・パスワード」を指定する行と、MQTTブローカーの IPアドレス（上で確認しておいた Mac の IPアドレス）を指定する部分だけです。

```cpp
/* 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 のトピック・メッセージ等を指定しているのは、以下となっているようです。

```cpp
      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'` という内容にしました。

それを実行した結果は以下のとおりで、無事に数値のデータを受信できました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">GR-ROSE からの MQTT による通信を<br>npx mqtt sub -t &#39;【トピック】&#39; -h &#39;【ホスト名】&#39; <br>というコマンドで Subscribe！<br><br>（過去に、以下の記事で書いていた方法です）<a href="https://t.co/yvTqyyac5P">https://t.co/yvTqyyac5P</a><br><br>そして、MQTTブローカー経由で受けとった、カウントアップされる数字が表示されるのを確認できました。 <a href="https://t.co/ohVxpATtwX">pic.twitter.com/ohVxpATtwX</a></p>&mdash; you (@youtoy) <a href="https://twitter.com/youtoy/status/1453001807484133379?ref_src=twsrc%5Etfw">October 26, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

元のプログラムでいうと、以下の部分が上記の数値を送っている部分になります。

```cpp
  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」という文字列を受信できているのを確認できました。
<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">GR-ROSE が受信する方向の MQTT通信、これも<br>npx mqtt pub -t &#39;【トピック】&#39; -h &#39;【ホスト名】&#39; -m &#39;【メッセージ】&#39;<br>という単発のコマンドで実行してみた。<br><br>無事、シリアルモニタに送った文字列が表示されたのを確認できました。 <a href="https://t.co/gO07vYOsmf">pic.twitter.com/gO07vYOsmf</a></p>&mdash; you (@youtoy) <a href="https://twitter.com/youtoy/status/1453002835843506184?ref_src=twsrc%5Etfw">October 26, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## おわりに
GR-ROSE絡みのプログラムは、基本的にはサンプルをそのまま用いる形で MQTT を試せました。

その際に必要になる MQTTブローカーはローカルに用意し、GR-ROSE とは別の MQTTクライアントは、npm さえ使える状態ならパッケージを用意してない状態でもコマンド実行のみで動かせるようなコマンドで準備しました。

進めていく中で特にはまるポイントもなかったため、お試しから記事を書くまで短い時間でできて良かったです。