首页 > 解决方案 > Wemos D1 ESP8266、ioBroker (Raspberry Pi 3 Model B) MQTT 连接失败

问题描述

我有一个带有 ioBroker(Raspbian light Stretch)的 Raspberry Pi 3 Model B 作为 MQTT 代理和带有测试脚本的 Wemos D1 ESP 8266。两台设备都通过 Wi-Fi 连接到网络。

好消息:

1)我可以从手机(myMQTT应用程序)发送MQTT信号,它将显示在ioBroker日志中(手机连接到Wi-Fi,MicroTik)。我可以从我的笔记本电脑(连接到 Wi-Fi 或以太网)发送 MQTT 信号。我可以从 Debian 虚拟服务器(在 vmware 上)发送成功的 MQTT 信号。

2)Wemos D1成功连接到测试服务器test.mosquitto.org。

坏消息:Wemos D1 不想连接本地网络上的 ioBroker 并报告错误“Attempting MQTT connection ... failed, rc = -2 try again in 5 seconds”。

为什么除 Wemos D1 ESP 8266 以外的所有设备都成功连接到 mqtt 代理?防火墙中可能是这种情况吗?请告诉我,我应该怎么做才能解决这个问题。

/*
 Basic ESP8266 MQTT example

 This sketch demonstrates the capabilities of the pubsub library in combination
 with the ESP8266 board/library.

 It connects to an MQTT server then:
  - publishes "hello world" to the topic "outTopic" every two seconds
  - subscribes to the topic "inTopic", printing out any messages
    it receives. NB - it assumes the received payloads are strings not binary
  - If the first character of the topic "inTopic" is an 1, switch ON the ESP Led,
    else switch it off

 It will reconnect to the server if the connection is lost using a blocking
 reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to
 achieve the same result without blocking the main loop.

 To install the ESP8266 board, (using Arduino 1.6.4+):
  - Add the following 3rd party board manager under "File -> Preferences -> Additional Boards Manager URLs":
       http://arduino.esp8266.com/stable/package_esp8266com_index.json
  - Open the "Tools -> Board -> Board Manager" and click install for the ESP8266"
  - Select your ESP8266 in "Tools -> Board"

*/

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

// Update these with values suitable for your network.

const char* ssid = "XXX";
const char* password = "XXX";
const char* mqtt_server = "test.mosquitto.org";

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;

void setup_wifi() {

  delay(5000);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.mode (WIFI_STA);
  WiFi.begin(ssid, password);

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

  randomSeed(micros());

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

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

  // Switch on the LED if an 1 was received as first character
  if ((char)payload[0] == '1') {
    digitalWrite(BUILTIN_LED, LOW);   // Turn the LED on (Note that LOW is the voltage level
    // but actually the LED is on; this is because
    // it is active low on the ESP-01)
  } else {
    digitalWrite(BUILTIN_LED, HIGH);  // Turn the LED off by making the voltage HIGH
  }

}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str())) {
      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(1000);
    }
  }
}

void setup() {
  pinMode(BUILTIN_LED, OUTPUT);     // Initialize the BUILTIN_LED pin as an output
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void loop() {

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

  long now = millis();
  if (now - lastMsg > 2000) {
    lastMsg = now;
    ++value;
    snprintf (msg, 50, "hello world #%ld", value);
    Serial.print("Publish message: ");
    Serial.println(msg);
    client.publish("outTopic", msg);
  }
}

截图:1) netstat -tulpn | grep 听

2) ioBrocker 日志

3) Arduino IDE

更新:

我没有找到可以更改或禁用监听端口 1883 tcp6 的位置。

但我设法通过用 Keenetic 替换 Mikrotik 路由器来建立设备之间的连接。

现在我们需要弄清楚路由器的设置有什么问题。

标签: arduinomqttraspbianesp8266mikrotik

解决方案


你的截图:

在此处输入图像描述

显示 ioBroker 正在 IPv4 环回接口 (127.0.0.1) 上侦听端口 9000 和 9001,并在 tcp6 (IPv6) 接口上侦听端口 8081、8082 和 1883。

这意味着它只能通过 IPv4 从与它相同的服务器上运行的程序访问,或者从能够说 IPv6 的计算机上运行的程序访问。

ESP8266 不能说 IPv6。

您需要重新配置 ioBroker 以侦听 0.0.0.0:mqtt 以便 IPv4 软件可以访问它。


推荐阅读