2017年6月7日 星期三

「Arduino」MQTT踩到一個坑

紀錄一下使用MQTT時採到的一個坑,在爬回平地前先來

看看Pubsubclient lib裡面一個基本的範例 ,不可否認的,這範例寫的很清楚。

我的MQTT Broker是mosquitto 1.4.x 版


#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>

// Update these with values suitable for your network.
byte mac[]    = {  0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
IPAddress ip(172, 16, 0, 100);
IPAddress server(172, 16, 0, 2);

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();
}

EthernetClient ethClient;
PubSubClient client(ethClient);

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("arduinoClient")) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("outTopic","hello world");
      // ... and resubscribe
      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);
    }
  }
}

void setup()
{
  Serial.begin(57600);

  client.setServer(server, 1883);
  client.setCallback(callback);

  Ethernet.begin(mac, ip);
  // Allow the hardware to sort itself out
  delay(1500);
}

void loop()
{
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
}

單一台裝置運作時,非常順利,但是同樣的程式碼,在二個arduino上執行時會出現

漏訊息,而且拼命和MQTT Broker Reconnect問題。

查詢了一下錯誤代碼,rc=-4表示 Connection Timeout , 在MQTT中,client與server之間會

有一個keepalive的參數,這個lib預設是15秒,也就是在15內,client有義務和server保持連

接,當超過keepalive所設定的秒數內沒有傳送資料,client必須發送一個心跳訊號,而server

在收到心跳訊號後,必須回覆,這個client才能確認與server是保持連通的。


後來確認後發現是這一行程式碼導致的問題

if (client.connect("arduinoClient"))

一眼瞄過去我也不覺得那裡有異,直到去查詢後才發現"arduinoClient" 其實是

ClientID  , 所以不應該重覆,否則Server會無法正確識別與client連線狀態,導致Client

可能沒有正確收到Server response 的keepalive回覆,誤以為斷線。

1 則留言: