我刚从Github下载了最新的Arduino库代码,它破坏了我的MQTT客户端程序 . 我在Arduino上使用PubSubClient 1.91,在Mac OSX上使用Mosquitto 1.1.2(Build 2013-03-07) . (我也在Windows 7上针对Mosquitto进行了测试,同样的问题 . )
提供的Mosquitto客户端运行良好,(Mac到Windows,Windows到Mac),因此Arduino端的问题就出现了问题 . wireshark跟踪显示Arduino客户端发送以下数据包:
10:15:FF:FF:4D:51:49:73:64:70:03:02:00:0F:00:07:41:72:64:75:69:6E:1207米
并且Mosquitto代理显示:10.0.0.115上的新连接客户端上的Socket读取错误(null),断开连接 .
在我开始浏览MQTT规范之前,任何人都可以看到正在发送的数据包有什么问题吗?它必须与新的Arduino库代码有关...
*更新进一步调查后,似乎是avr-g的代码生成问题,尽管生活经验告诉我事实并非如此 . 以下是PubSubClient.cpp的代码片段
boolean PubSubClient::connect(char *id, char *user, char *pass, char* willTopic, uint8_t willQos, uint8_t willRetain, char* willMessage) {
if (!connected()) {
int result = 0;
if (domain != NULL) {
result = _client->connect(this->domain, this->port);
} else {
result = _client->connect(this->ip, this->port);
}
if (result) {
nextMsgId = 1;
uint8_t d[9] = { 0x00, 0x06, 'M','Q','I','s','d','p',MQTTPROTOCOLVERSION};
// d[0] = 0;
// d[1] = 6;
Serial.print("d[0]="); Serial.println(d[0],HEX);
现在,Serial.print的结果就在上面,结果是0xFF!因此,uint8_t数组未正确初始化 . @knoleary你指向坏FF字节的指针引导我这个 .
如果我现在取消注释上面的两行,并手动将前2个字节初始化为0和6,则一切正常,我的程序与Mosquitto愉快地通信 .
我查看了生成的代码,但我不是Atmel的专家 .
有没有人知道为什么会这样?
我正在使用Eclipse中的Arduino 1.05的AVR-G工具集进行编译 .
我要去喝啤酒了!
2 回答
好的,我找到了 . 这是一个相对微妙的错误 . 基本上,当编译以下源代码行时;
9个字节作为常量存储在图像的数据部分中 . 在运行时,一个小循环将9个字节复制到数组中(d [])通过查看组合的汇编程序/源列表,我可以看到数据部分中存储了9个字节的位置,然后定期打印出来直到我发现什么是覆盖它们 . (有点原始,我知道!)
事实证明,WiFi.cpp中存在一个错误,即Arduino WiFi代码 . 这是代码:
事实证明_sock变量实际上是这样初始化的:
并且MAX_SOCK_NUM是4,而不是255.因此,WiFiClient :: status返回true,而不是未使用的Socket的false .
MQTT客户端调用此方法,如下所示:
并且,由于_client-> connected()方法错误地返回true,因此调用了_client_stop()方法 . 这导致写入一个不存在的套接字数组元素,因此覆盖了我的字符串数据 .
@knolleary,我想知道,你的PubSubClient :: connected()方法是否有任何特定的原因断开连接?我在循环中使用:: connected方法来检查我是否仍然连接,当然,这导致我每次循环时都会断开连接/重新连接 . 我们有可能只使连接返回true / false,并处理PuBSubClient :: connect中的断开连接吗?
差不多一年半之后,我遇到了同样的问题 . 删除
来自PubSubClient正文连接方法的_client-> stop()为我解决了这个问题 . 但是,我不确定这实际上是一个解决方案,还是只是一个非常脏的快速黑客来解决问题 .
你做了什么来解决这个问题 - 你对上述问题的解释很好,但我无法轻易提取解决方案;-)