我的应用程序涉及一个运行NodeMCU的电池供电的ESP8266,用于在MQTT上定期更新传感器值。
为了节省电池寿命,我想在完成工作后立即致电dsleep()
。该工作可能涉及对mqqt.Client.publish()
的多次调用。这就把我们带到了我面临的问题。
我是Lua新手,但据我了解,在publish()
完成后运行某些代码的正确方法是给它一个PUBACK回调:
m = mqtt.Client(...)
m.publish("/my/topic", "some message", 1, 0, callback_func)
在上面这样简单的情况下,这很有效 - 即使MQTT消息的实际发送与publish()
调用的实际发送是异步的(请参阅对此here的详细讨论),上述示例中的callback_func()
仅在publish()
完成时被调用。
但是当我有一个以上的publish()
来电并希望我的回叫a)在他们全部完成后被调用,而b)只被叫一次,我就被卡住了。
这种天真的方法是将回调(可选)仅放在第N publish()
次呼叫上:
m = mqtt.Client(...)
m.publish("/my/topic", "some message", 1, 0)
m.publish("/another/topic", "unrelated message", 1, 0, callback_func)
但这不符合预期。正如documented:
注意:多次调用publish()时,将为所有发布命令调用最后定义的回调函数。
因此,在上面的示例中,callback_func()
最终会被调用两次(每次成功publish()
一次。
我可以将多个publish()
调用合并为一个调用,但这感觉就像一个丑陋的黑客,并会产生其他不利影响。如果我的两条消息在概念上是截然不同的,那么这种方法会推动逻辑将它们分成订阅者 - 哎呀。如果他们需要去讨论不同的话题,那就更糟了。必须有更好的方法。
我想也许mqqt.Client.close()
会等待我的不同publish()
来电完成,但事实并非如此。
我没有想法,希望有更多Lua和/或NodeMCU + mqqt经验的人可以给我一个正确方向的推动。
这是我的实际代码,如果它有帮助:
-- prior to this, we've gotten on the wifi network and acquired an IP
dofile("temp.lua") -- provides get_temp()
m = mqtt.Client("clientid", 120, "8266test", "password")
function mainloop(client)
print("connected - at top of loop")
m:publish("uptime",tmr.time(),1,0, function(client) print("sent uptime") end)
temp, humi = get_temp()
if (temp ~= nil) then
print(string.format("temp: %d", temp))
print(string.format("humi: %d", humi))
m:publish("temp",temp,1,0)
m:publish("humi",humi,1,0, function(client) -- note: this callback will be used for all publish() calls
rtctime.dsleep(SLEEP_USEC)
end)
end
end
m:on("connect", mainloop)
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)
答案 0 :(得分:1)
选项1: 一次发布所有数据,然后进入睡眠状态。
选项2: 将回调分为两部分。第一部分检查你是否完成,如果你完成,第二部分会进入休眠状态。 当然,你可以用不同的方式解决这个问题,计算剩下的数量,计算你发送的数量,发送和删除列表中的项目,直到列表为空,...
当然还有更多选择,但这些选择既简单又充足。
编辑:按要求提供的示例
local totalItemCount = 5
function publishCallback()
itemsPublished = (itemsPublished or 0) + 1
print("item published")
if itemsPublished == totalItemCount then
print("I'm done, good night!")
end
end
for i = 1, totalItemCount do
publishCallback()
end
项目已发布
项目已发布
项目已发布
项目已发布
项目已发布
我已经完成了,晚安!