NodeMCU(ESP8266)上的MQTT保活计时器无响应

亲爱的各位, 我正在尝试在NodeMCU上构建MQTT。目前我正在使用自定义版本(https://nodemcu-build.com/index.php

所使用的模块:adc,enduser_setup,file,gpio,http,mqtt,net,node,ow,pwm,tmr,uart,wifi

版本:使用Lua 5.1.4和SDK 1.5.1(e67da894)

function connect_to_mqtt_broker()

    print("连接到代理...")
    m:connect(BROKER, PORT, 0, 1, function(client)
                                    print("已连接")
                                    print("["..tmr.time().."(s)] - 客户端连接到代理:"..BROKER)
                                    m:subscribe(SUB_TOPIC,0, function(conn)
                                        print("订阅了 "..SUB_TOPIC.." 主题")
                                        led(0,204,0,150)
                                    end)
                                    m:publish(PUB_TOPIC,"Hello from: "..node.chipid()..RESTART_REASON,0,0, function(conn)
                                        print("发送成功")
                                    end)
                                  end,
                                  function(client, reason)
                                    print("连接失败,原因: "..reason)
                                  end)

end

---MQTT客户端---
print("--------------> 创建mqtt client")
--设置MQTT客户端
-- 初始化带有保活计时器为120秒的mqtt客户端
m = mqtt.Client("ESP"..node.chipid(), KEEP_ALIVE_TMR, USER, PASSWORD)
m:lwt(PUB_TOPIC, "offline", 0, 0)
m:on("offline", function(conn)
        print("["..tmr.time().."(s)] - MQTT客户端已离线")

end)
m:on("message", function(conn, topic, data)
        --receive_data(data, topic)
        print("接收到的数据:"..data)
        led(200,50,50,30)
        receive_data(data, topic)
        led(0,204,0,150)
end)

因此,在程序初始化时,我调用了**connect_to_mqtt_broker()**,它完美地工作,我可以订阅和发布主题。

问题在于保活计时器不正确。让我用一个例子来说明这个问题。我设置KEEP_ALIVE_TMR=120秒,当ESP8266成功连接到MQTT代理后,我关闭了我的路由器上的WiFi并开始计时。根据KEEP_ALIVE_TMR,离线事件:

m:on("offline", function(conn)
        print("["..tmr.time().."(s)] - MQTT客户端已离线")

end)

应该在我禁用WiFi后的120秒内准确触发,但由于某种未知原因,这并不会发生。通常,事件会在10-15分钟后触发。 我正在努力了解这种延迟的原因,但却毫无成功。 请问您是否有任何关于这种奇怪情况发生的想法?

点赞
用户3082873
用户3082873

当设置了 autoreconnect 标志时,我也遇到了相同的问题。这个标志破坏了代理之间离线事件的运行。

尝试不设置 autoreconnect,其默认值为 0:

m:connect(BROKER, PORT, 0, function(client)
2016-10-24 05:19:08
用户5523111
用户5523111

如果你是通过打开/关闭你的 MQTT broker 进行测试,而且这种方式可行。但如果是通过切换 Wi-Fi 连接进行测试,则可能是 NodeMCU 的 MQTT 库出现问题。

我相信在 Wi-Fi 连接断开时是没有离线/disconnect 事件的。这里的解决方法是添加连接的看门狗。

tmr.alarm(1, 3000, 1, function()
  if wifi.sta.getip() == nil then
   --标记为需要重启 MQTT
   restart = true
 else
   --检测到 Wi-Fi 重新连接,则重新启动 MQTT 连接
   if restart == true then
     --重置标志、清理对象、初始化新对象
     restart = false
     m = nil
     mqtt_init()
     connect()
   end
 end
end)

这里是完整的代码示例

2016-12-05 16:25:10