使用 Lua/NodeMCU,我如何才能等到在 运行 一个代码块之前进行了 >1 个 mqtt 发布调用?
With Lua/NodeMCU, how can I wait until >1 mqtt publish calls have been made before running a block of code?
我的应用程序涉及电池供电的 ESP8266 运行ning NodeMCU,目的是通过 MQTT 定期更新传感器值。
为了节省电池寿命,我想在完成工作后立即致电 dsleep()
。这项工作可能涉及对 mqqt.Client.publish()
的 1 次以上调用。这就引出了我面临的问题。
我是一个 Lua 新手,但据我所知,在 publish()
完成后 运行 一些代码的正确方法是给它一个 PUBACK 回调:
m = mqtt.Client(...)
m.publish("/my/topic", "some message", 1, 0, callback_func)
在像上面这样的简单情况下,效果很好——即使 MQTT 消息的实际发送相对于 publish()
调用是异步的(参见对此 的很好的讨论), 上例中的 callback_func()
只会在 publish()
完成时调用。
但是当我对 publish()
进行了 1 次以上的调用并希望我的回调 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:
NOTE: When calling publish() more than once, the last callback function defined will be called for ALL publish commands.
所以在上面的例子中,callback_func()
最终被调用了两次(每次成功调用一次 publish()
。
我可以将多个 publish()
调用组合成一个调用,但这感觉就像一个丑陋的 hack,并且会产生其他不利影响。如果我的两条消息在概念上是不同的,这种方法将推动逻辑将它们分离到订阅者中 - 糟糕。如果他们需要讨论不同的主题,情况会更糟。一定有更好的办法。
我想也许 mqqt.Client.close()
会等待我不同的 publish()
调用完成,但事实并非如此。
我没有想法,希望有更多 Lua and/or 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)
选项 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
item published
item published
item published
item published
item published
I'm done, good night!
我的应用程序涉及电池供电的 ESP8266 运行ning NodeMCU,目的是通过 MQTT 定期更新传感器值。
为了节省电池寿命,我想在完成工作后立即致电 dsleep()
。这项工作可能涉及对 mqqt.Client.publish()
的 1 次以上调用。这就引出了我面临的问题。
我是一个 Lua 新手,但据我所知,在 publish()
完成后 运行 一些代码的正确方法是给它一个 PUBACK 回调:
m = mqtt.Client(...)
m.publish("/my/topic", "some message", 1, 0, callback_func)
在像上面这样的简单情况下,效果很好——即使 MQTT 消息的实际发送相对于 publish()
调用是异步的(参见对此 callback_func()
只会在 publish()
完成时调用。
但是当我对 publish()
进行了 1 次以上的调用并希望我的回调 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:
NOTE: When calling publish() more than once, the last callback function defined will be called for ALL publish commands.
所以在上面的例子中,callback_func()
最终被调用了两次(每次成功调用一次 publish()
。
我可以将多个 publish()
调用组合成一个调用,但这感觉就像一个丑陋的 hack,并且会产生其他不利影响。如果我的两条消息在概念上是不同的,这种方法将推动逻辑将它们分离到订阅者中 - 糟糕。如果他们需要讨论不同的主题,情况会更糟。一定有更好的办法。
我想也许 mqqt.Client.close()
会等待我不同的 publish()
调用完成,但事实并非如此。
我没有想法,希望有更多 Lua and/or 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)
选项 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
item published
item published
item published
item published
item published
I'm done, good night!