MQTT on ESP8266 with NodeMCU - problems with publishing

你。 提交于 2019-12-12 02:56:57

问题


I'm building a battery powered IoT device based on ESP8266 with NodeMCU. I use mqtt to periodically perform measurements and publish results. I know, that to allow network stack running, I should avoid tight loops and rely on callback functions. Therefore it seemed to me that the right organization of my measurement code should be:

interval=60000000

function sleep_till_next_sample()
 node.dsleep(interval)
end

function close_after_sending()
  m:close()
  sleep_till_next_sample()
end

function publish_meas()
   m:publish("/test",result,1,0,close_after_sending)
   print("published:"..result)
end

function measurement()
   -- The omitted part of the function accesses
   -- the hardware and places results
   -- in the "result" variable
   m = mqtt.Client("clientid", 120, "user", "password")
   m:connect("172.19.1.254",1883,0, publish_meas)
end

The init.lua ensures, that the node has connected to the WiFi AP (if not, it retries up to 20 times, and if no connection is established, it puts the node on sleep until the next measurement time). After WiFi connection is done, it calls the measurement function.

The interesting thing is, that the above code doesn't work. There are no errors displayed in the console, but the mqtt broker does not receive published messages. To make it working, i had to add additional idle time, by adding timers in the callback functions.

The finally working code looks like below:

interval=60000000

function sleep_till_next_sample()
 node.dsleep(interval)
end

function close_after_sending()
  m:close()
  tmr.alarm(1,500,0,function() sleep_till_next_sample() end)
end

function publish_meas()
   m:publish("/test",result,1,0,function() tmr.alarm(1,500,0,close_after_sending) end)
   print("published:"..result)
end

function measurement()
   -- The omitted part of the function accesses
   -- the hardware and places results
   -- in the "result" variable
   m = mqtt.Client("clientid", 120, "user", "password")
   m:connect("172.19.1.254",1883,0, function() tmr.alarm(1,500,0, publish_meas) end)
end

The above works, but I'm not sure if it is optimal. To conserve the battery power I'd like to minimize the time before the node is put on sleep after the measurement is completed and results published.

Is there any better way to chain the necessary calls to m:connect, m:publish, m:close and finally node.dsleep so, that the results are correctly published in the minimal time?


回答1:


Perhaps this was solved by more recent firmware. I am working through a problem that I thought might be somewhat explained by this issue, so tried to reproduce the problem as described.

My simplified test code is substantially similar; it calls dsleep() from the PUBACK callback of mqtt.Client.publish():

m = mqtt.Client("clientid", 120, "8266test", "password")

m:lwt("/lwt", "offline", 0, 0) 

function main(client) 
    print("connected - at top of main")

m:publish("someval",12345,1,0, function(client)  
    rtctime.dsleep(SLEEP_USEC)      
    end)
end

m:on("connect", main)
m:on("offline", function(client) is_connected = false print ("offline") end)

m:connect(MQQT_SVR, 1883, 0, mainloop, 
                         function(client, reason) print("failed reason: "..reason) end)

and when run, does successfully publish to my MQTT broker.

I am using:

    NodeMCU custom build by frightanic.com
            branch: master
            commit: 81ec3665cb5fe68eb8596612485cc206b65659c9
            SSL: false
            modules: dht,file,gpio,http,mdns,mqtt,net,node,rtctime,sntp,tmr,uart,wifi
     build  built on: 2017-01-01 20:51
     powered by Lua 5.1.4 on SDK 1.5.4.1(39cb9a32)


来源:https://stackoverflow.com/questions/34382676/mqtt-on-esp8266-with-nodemcu-problems-with-publishing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!