【发布时间】:2016-05-03 21:09:45
【问题描述】:
我正在使用 Arduino Uno 和 Wi-Fi shield。我正在尝试实现 MQTT 协议进行通信,并为 Arduino 尝试了两个库。第一个是 Knolleary 的 PubSubClient:http://pubsubclient.knolleary.net/。我稍微修改了原始示例以使用 WiFi 模块而不是以太网。发送有效,但不是每次都发送(有时发送消息,有时不发送)。但是通过回调函数接收根本不起作用。
这是我的代码:
/*
Basic MQTT example with Authentication
- connects to an MQTT server, providing username
and password
- publishes "hello world" to the desired topic
- subscribes to the desired topic
*/
#include <WiFi.h>
#include <PubSubClient.h>
char ssid[] = "[DELETED]"; // your network SSID (name)
char pass[] = "[DELETED]"; // your network password
int status = WL_IDLE_STATUS; // the Wifi radio's status
// Update these with values suitable for your network.
IPAddress server(85, 119, 83, 194);
WiFiClient WifiClient;
void callbackFunc(char* topic, byte* payload, unsigned int length) {
Serial.println("test message received");
/*Serial.println();
Serial.println("=============== MESSAGE RECEIVED ================================");
Serial.print("Topic: ");
Serial.print(topic);
Serial.println();
Serial.println((const char *) payload);*/
}
PubSubClient client(server, 1883, callbackFunc, WifiClient);
void setup()
{
delay(2000);
Serial.begin(9600);
Serial.println("Starting....");
Serial.println("Initializing Wifi...");
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
}
// attempt to connect using WPA2 encryption:
Serial.println("Attempting to connect to WPA network...");
status = WiFi.begin(ssid, pass);
// if you're not connected, stop here:
if (status != WL_CONNECTED) {
Serial.println("Couldn't get a wifi connection");
while(true);
}
// If you are connected, print out success message
else
Serial.println("Connected to network");
if (client.connect("arduinoClient")) {
Serial.println("Connected to server! Sending message...");
client.publish("randy/test","hello world");
client.subscribe("randy/test");
Serial.println("Sent!");
}
else
{
Serial.println("ERROR: Cannot connect to MQTT server!");
Serial.println(client.state());
}
}
void loop()
{
client.loop();
delay(1000);
if (!client.connected())
{
if(!client.connect("arduinoClient"))
{
Serial.println("ERROR: Cannot connect to MQTT server!");
Serial.println(client.state());
}
else
{
client.subscribe("randy/test");
Serial.println("INFO: reconnected!");
}
}
}
如您所见,我使用http://test.mosquitto.org/ 进行测试。我还在 Ubuntu 上使用 mosquitto,我订阅了同一个主题,并且从哪里(另一个终端窗口)发布到同一个主题。这是两个窗口的图片:
如您所见,来自 Arduino 的“hello world”消息已成功接收(但不是每次),当我从另一个窗口发布“bla”消息时,它已在 mosquitto(图像上)上成功接收,但在 Arduino 上没有.我的代码有问题吗?我在这里发现了类似的问题:Arduino Knolleary PubSubClient will publish messages but can't receive them
值得注意的是,它一直在重新连接。如您所见,在 loop() 中,我放置了一部分代码,如果连接丢失,它将重新连接和订阅。在串行监视器上,我得到“信息:重新连接!”每 2-3 秒发送一次消息。
Adafruit 库 然后我尝试了 Adafruit 库,但它根本无法连接!我从他们的示例中尝试使用 test.mosquitto.org 和 io.adafruit.com,但我只是不断收到“连接失败!”错误。我尝试进行许多更改和组合,但到目前为止没有运气。一旦我设法得到“订阅失败”而不是“连接失败”,但这只是一次又一次使用相同的代码,我再次得到“连接失败”。
这是我的代码:
/*
Basic MQTT example with Authentication
- connects to an MQTT server, providing username
and password
- publishes "hello world" to the topic "outTopic"
- subscribes to the topic "inTopic"
*/
#include <WiFi.h>
#include <PubSubClient.h>
char ssid[] = "[DELETED]"; // your network SSID (name)
char pass[] = "[DELETED]"; // your network password
int status = WL_IDLE_STATUS; // the Wifi radio's status
// Update these with values suitable for your network.
IPAddress server(85, 119, 83, 194);
WiFiClient WifiClient;
void callbackFunc(char* topic, byte* payload, unsigned int length) {
Serial.println("test message received");
/*Serial.println();
Serial.println("=============== MESSAGE RECEIVED ================================");
Serial.print("Topic: ");
Serial.print(topic);
Serial.println();
Serial.println((const char *) payload);*/
}
PubSubClient client(server, 1883, callbackFunc, WifiClient);
void setup()
{
delay(2000);
Serial.begin(9600);
Serial.println("Starting....");
Serial.println("Initializing Wifi...");
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
}
// attempt to connect using WPA2 encryption:
Serial.println("Attempting to connect to WPA network...");
status = WiFi.begin(ssid, pass);
// if you're not connected, stop here:
if (status != WL_CONNECTED) {
Serial.println("Couldn't get a wifi connection");
while(true);
}
// Ff you are connected, print out success message
else
Serial.println("Connected to network");
if (client.connect("arduinoClient")) {
Serial.println("Connected to server! Sending message...");
client.publish("randy/test","hello world");
client.subscribe("randy/test");
Serial.println("Sent!");
}
else
{
Serial.println("ERROR: Cannot connect to MQTT server!");
Serial.println(client.state());
}
}
void loop()
{
client.loop();
delay(1000);
if (!client.connected())
{
if(!client.connect("arduinoClient"))
{
Serial.println("ERROR: Cannot connect to MQTT server!");
Serial.println(client.state());
}
else
{
client.subscribe("randy/test");
Serial.println("INFO: reconnected!");
}
}
}
知道这些库或我的代码有什么问题吗?
【问题讨论】:
-
快速建议,如果可能,请尝试使用您自己的本地经纪人进行测试。如果没有,请将 client_id(当前为“arduinoClient”)更改为随机值,以确保它不会与可能使用这些公共代理的其他任何人发生冲突
-
正如 hardillb 所说,在公共代理上使用像 arduinoClient 这样的通用客户端 ID 可能会发生冲突并导致断开/重新连接周期。如果它不断断开/重新连接,那么它很可能会丢失消息。选择一个唯一的客户 ID,然后重试。
-
好吧,我真傻:) 我什至没有注意客户ID,我只是把它放在示例中。老实说,我可能会再花几十个小时,而且可能永远不会想到这个。谢谢,现在它就像一个魅力!由于另一个图书馆,我将把问题留在那里。我正在为我的大学做一些研究,所以我想比较这些图书馆。知道是否可以查看消息大小和发送 PubSubClient 库所花费的时间吗?