WeMosを使ってみる

RaspberryとのMQTT通信(WeMos→Raspberry)

mosquitto-clients編


前回前々回と RaspberryとWeMosのSocket通信 を紹介しました。
そこで、今回はRaspberryとWeMosのMQTT通信を紹介します。
最初にRaspberry側に「mosquitto-clients」をインストールします。

$ sudo apt-get install mosquitto-clients

次に簡単な通信テストを行います。
MQTT Brokerは公開サーバーの「broker.hivemq.com」 を使いました。
Raspberryで2つのターミナルを開いて以下を実行します。

ターミナル1
$ mosquitto_sub -h broker.hivemq.com -p 1883 -t "nopnop2002"


ターミナル2
$ mosquitto_pub -h broker.hivemq.com -p 1883 -t "nopnop2002" -m "Hello nopnop2002"

以下のように表示されれば通信テストは終了です。





次に以下のページよりArduinoのMQTTクライアントライブラリ(pubsubclient-master.zip)をダウンロードしま す。
https://github.com/knolleary/pubsubclient

ZIPファイルを展開したらArduino-IDEの「libraries」フォルダーにコピーします。

WeMos側のスケッチは以下の通りです。
MQTTクライアントライブラリに含まれている「pubsubclient\examples\mqtt_esp8266」を元に作りました。
10秒毎にトピックを送信します。
特に注意が必要なのはconnect関数で指定するコネクトID(クライアントID)です。
コネクトIDが他の誰かに既に使われている場合、正しく接続できなかったり、既に接続済のクライアントの接続が切れたりします。
これはこのライブラリに限らず、MQTTの仕様みたいです。
そこで、コネクトIDにはESP8266のCHIPIDを指定しています。これなら必ずユニークになります。
SSIDとPASSWORDは自分の環境に合わせて変更してください。

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

#define INTERVAL        10
#define SSID            "APのSSID"
#define PASSWORD        "APのパスワード"
//#define MQTT_SERVER     "192.168.10.40"
//#define MQTT_SERVER     "broker.mqtt-dashboard.com"
#define MQTT_SERVER     "broker.hivemq.com"
#define MQTT_PORT       1883
#define MQTT_TOPIC      "nopnop2002" // You can change
#define MQTT_WILL_MSG   "I am leaving..." // You can change

WiFiClient espClient;
PubSubClient client(espClient);

unsigned long lastTime = 0;

void setup_wifi() {

  delay(10);

  // We start by connecting to a WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Wait for WiFi...");
  WiFi.begin(SSID, PASSWORD);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

void errorDisplay(char* buff) {
  Serial.print("Error:");
  Serial.println(buff);
  int led = 0;
  while(1) {
    digitalWrite(BUILTIN_LED,led);
    led = ~led;
    delay(200);
  }
}

void setup() {
  Serial.begin(9600);
  pinMode(BUILTIN_LED, OUTPUT);
  setup_wifi();
  client.setServer(MQTT_SERVER, MQTT_PORT);

  char clientid[20];
  sprintf(clientid,"ESP8266-%06x",ESP.getChipId());
  Serial.print("clientid=");
  Serial.println(clientid);
  Serial.print("Attempting MQTT connection...");
  // Attempt to connect
//  if (!client.connect(clientid)) {
  if (!client.connect(clientid,MQTT_TOPIC,0,0,MQTT_WILL_MSG)) {
    errorDisplay("connect Fail");
  }
  Serial.println("connected");
  lastTime = millis();
}

void loop() {
  static int counter=0;
  static int value = 0;
  char msg[50];

  if (Serial.available() > 0) {
    char inChar = Serial.read();
    Serial.println("KeyIn");
    client.disconnect();
    Serial.println("Publish end");
    while(1) { }
  }

  if (!client.connected()) {
    errorDisplay("not connect");
  }
  client.loop();

  long now = millis();
  if (now - lastTime > 1000) {
    lastTime = now;
    counter++;
    if (counter > INTERVAL) {
      ++value;
      snprintf (msg, 75, "hello world #%ld", value);
      Serial.print("Publish message: ");
      Serial.println(msg);
      if (!client.publish(MQTT_TOPIC, msg)) {
        errorDisplay("publish fail");
      }
      counter=0;
    }
  }
}

このスケッチを実行するとArduino-IDEのシリアルモニターはこのように表示されます。


RaspberryのSubscriberには以下のように表示されます。


WeMosの電源を切ってしばらく(最後にPublishしてから90秒以上)放置するとWillメッセージが届きます。


次は、Raspberry側のSubscriberをPythonで作ってみます。

続く....