Arduino Uno R4 WifiにてMQTT通信してみた。

# 概要
- Arduino Uno R4 WifiでMQTTで通信してみた。
- ArduinoMQTTClientを使えば通信可能

# 構成

MQTTXをPCにインストールし、Shiftr.io経由でデータを送ってみた。
ArduinoがSubscriberになってデータを取得していくイメージ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271381/ba00788a-85b0-8d84-c741-bdf6d1b41602.png)

# ArduinoMQTTClient

こちらのリンクを参照。似たような名前のライブラリが多いため注意。

https://www.arduino.cc/reference/en/libraries/arduinomqttclient/

# コード

MQTTXから送られた文字列に応じてArduinoボード上のLEDが点灯する。

```cpp
#include "WiFiS3.h"
#include "ArduinoGraphics.h"
#include "Arduino_LED_Matrix.h"
#include <ArduinoMqttClient.h>
#include <string.h>
#include <stdlib.h>

char ssid[] = "";                              // WifiのSSID
char pass[] = "";                            // Wifiのパス

char mqtt_user[] = "public";
char mqtt_pass[] = "public";

WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);

const char broker[] = "public.cloud.shiftr.io";         //ブローカーのIDやURL
int        port     = 1883;                             //PORT
const char subscribe_topic[]  = "/led_arduino_switch";  //トピックID
const int LED_PIN = 0;

ArduinoLEDMatrix matrix;

byte frame[8][12] = {
  { 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0 },
  { 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0 },
  { 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 },
  { 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
  { 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};

// 文字を描写するやつ
void drawText(const char text[]){
  matrix.beginDraw();

  matrix.stroke(0xFFFFFFFF);
  matrix.textScrollSpeed(50);

  // add the text
  matrix.textFont(Font_5x7);
  matrix.beginText(0, 1, 0xFFFFFF);
  matrix.println(text);
  matrix.endText(SCROLL_LEFT);

  matrix.endDraw();
}


void setup() {
  // シリアル待機
  Serial.begin(9600);
  while (!Serial) {
    ; 
  }

  // Wifiに接続
  Serial.print("Attempting to connect to WPA SSID: ");
  Serial.println(ssid);
  while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
    // failed, retry
    Serial.print(".");
    delay(5000);
  }

  // ネットワークに接続
  Serial.println("You're connected to the network");
  Serial.println();

  // MQTTに接続
  mqttClient.setUsernamePassword(mqtt_user, mqtt_pass);

  Serial.print("Attempting to connect to the MQTT broker.");

  if (!mqttClient.connect(broker, port)) {
    Serial.print("MQTT connection failed! Error code = ");
    Serial.println(mqttClient.connectError());

    while (1);
  }

  Serial.println("You're connected to the MQTT broker!");

  Serial.print("Subscribing to topic: ");
  Serial.println(subscribe_topic);

  // トピック購読
  mqttClient.subscribe(subscribe_topic);

  // 購読やめるときはこちら
  // mqttClient.unsubscribe(topic);

  Serial.print("Waiting for messages on topic: ");
  Serial.println(subscribe_topic);

  digitalWrite(LED_PIN, LOW);

  matrix.begin();
  matrix.renderBitmap(frame, 8, 12);
}

void loop() {
  int messageSize = mqttClient.parseMessage();
  char *str;
  int i = 0;
  if (messageSize) {
    str = (char*)calloc(messageSize+1,sizeof(char));
    
    // メッセージ受信
    Serial.print("Received a message with topic '");
    Serial.print(mqttClient.messageTopic());
    Serial.print("', length ");
    Serial.print(messageSize);
    Serial.println(" bytes:");

    // メッセージの受信をやり切る
    while (mqttClient.available()) {
      *(str+i) = (char)mqttClient.read();
      i++;
    }
    *(str+i) = '\0';

    Serial.println(str);

    // 判定して表示！
    if(strcmp(str,"on") == 0){
      drawText("  ON!  ");
    }else if(strcmp(str,"off") == 0){
      drawText("  OFF!  ");
    }

    free(str);
    i = 0;
    
    Serial.println();
  }

}
```

# Node-REDフロー

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271381/c1213123-5c5a-6239-f2c1-e8997a7f8c71.png)


```json
[{"id":"8c6bb9a64f5626a8","type":"mqtt out","z":"48f0dd45f4685c27","name":"","topic":"led_arduino_switch","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"82a75067279577ee","x":470,"y":120,"wires":[]},{"id":"9e0180f01150d975","type":"inject","z":"48f0dd45f4685c27","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"on","payloadType":"str","x":170,"y":40,"wires":[["8c6bb9a64f5626a8"]]},{"id":"a7f828fbc09f36c9","type":"inject","z":"48f0dd45f4685c27","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"off","payloadType":"str","x":350,"y":40,"wires":[["8c6bb9a64f5626a8"]]},{"id":"260d0eec9665b4e2","type":"inject","z":"48f0dd45f4685c27","name":"heart","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"ledmatrix\":[[0,0,1,1,0,0,0,1,1,0,0,0],[0,1,0,0,1,0,1,0,0,1,0,0],[0,1,0,0,0,1,0,0,0,1,0,0],[0,0,1,0,0,0,0,0,1,0,0,0],[0,0,0,1,0,0,0,1,0,0,0,0],[0,0,0,0,1,0,1,0,0,0,0,0],[0,0,0,0,0,1,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0]]}","payloadType":"json","x":170,"y":120,"wires":[["8c6bb9a64f5626a8"]]},{"id":"27e59c1d84842cbf","type":"inject","z":"48f0dd45f4685c27","name":"neutral","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"ledmatrix\":[[0,0,0,0,1,1,1,0,0,0,0,0],[0,0,0,1,0,0,0,1,0,0,0,0],[0,0,1,0,0,0,0,0,1,0,0,0],[0,1,0,0,1,0,1,0,0,1,0,0],[1,0,0,0,0,0,0,0,0,0,1,0],[1,0,0,0,1,1,1,0,0,0,1,0],[0,1,1,0,0,0,0,0,1,1,0,0],[0,0,0,1,1,1,1,1,0,0,0,0]]}","payloadType":"json","x":170,"y":180,"wires":[["8c6bb9a64f5626a8"]]},{"id":"73aa618749ab8ebb","type":"inject","z":"48f0dd45f4685c27","name":"happy","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"ledmatrix\":[[0,0,0,0,1,1,1,0,0,0,0,0],[0,0,0,1,0,0,0,1,0,0,0,0],[0,0,1,0,1,0,1,0,1,0,0,0],[0,1,0,0,0,0,0,0,0,1,0,0],[1,0,0,1,0,0,0,1,0,0,1,0],[1,0,0,0,1,1,1,0,0,0,1,0],[0,1,1,0,0,0,0,0,1,1,0,0],[0,0,0,1,1,1,1,1,0,0,0,0]]}","payloadType":"json","x":170,"y":240,"wires":[["8c6bb9a64f5626a8"]]},{"id":"c03751e1af63a141","type":"inject","z":"48f0dd45f4685c27","name":"unhappy","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"ledmatrix\":[[0,0,0,0,1,1,1,0,0,0,0,0],[0,0,0,1,0,0,0,1,0,0,0,0],[0,0,1,0,1,0,1,0,1,0,0,0],[0,1,0,0,0,0,0,0,0,1,0,0],[1,0,0,0,1,1,1,0,0,0,1,0],[1,0,0,1,0,0,0,1,0,0,1,0],[0,1,0,0,0,0,0,0,0,1,0,0],[0,0,1,1,1,1,1,1,1,0,0,0]]}","payloadType":"json","x":180,"y":300,"wires":[["8c6bb9a64f5626a8"]]},{"id":"82a75067279577ee","type":"mqtt-broker","name":"shiftr.io","broker":"public.cloud.shiftr.io","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""}]
```

## neutral, happy, unhappyについて

JSONに二次元配列を渡して、その配列で真になっている箇所を点灯させている。
たとえばneutralであればこんな感じ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271381/5b00dc2b-8d60-ed1c-11a4-dc34899151b0.png)


```json
{
    "ledmatrix": [
        [0,0,0,0,1,1,1,0,0,0,0,0],
        [0,0,0,1,0,0,0,1,0,0,0,0],
        [0,0,1,0,0,0,0,0,1,0,0,0],
        [0,1,0,0,1,0,1,0,0,1,0,0],
        [1,0,0,0,0,0,0,0,0,0,1,0],
        [1,0,0,0,1,1,1,0,0,0,1,0],
        [0,1,1,0,0,0,0,0,1,1,0,0],
        [0,0,0,1,1,1,1,1,0,0,0,0]
    ]
}
```




# 結果

うごいたー。いえーい。

<iframe width="560" height="315" src="https://www.youtube.com/embed/fwXO6JmjtFA?si=9c8VZDDb16K_mRgD" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>


<iframe width="560" height="315" src="https://www.youtube.com/embed/ApM2zRxRDC0?si=WOeGpX3qlihmOGP7" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>


# おわりに

- Arduino上のコードは少し複雑だけど、受信さえできれば後は普通のコードにできそう。面倒な部分は別途ライブラリ化したほうが楽かも。
- Arduino社純正ボードでの知見はまだまだ少ない。もっと盛り上げていこう～！


# 参考

こちらのリンクで先程のライブラリを知った。Moheeb Zara氏に感謝。

https://www.hackster.io/virgilvox/mqtt-with-the-arduino-uno-r4-wifi-and-emqx-2639f9