使用 Lua/NodeMCU,在运行代码块之前如何等待超过1个 MQTT 发布调用?
我的应用程序涉及使用电池供电的 ESP8266 运行 NodeMCU,目的是通过 MQTT 定期更新传感器值。
为了节省电池寿命,我希望在完成工作后立即调用 dsleep()。这项工作可能涉及多次调用 mqqt.Client.publish()。这就是我面临的问题。
我是 Lua 的新手,但是在我理解的方式中,运行某些代码的正确方法是在 publish() 完成后给它一个 PUBACK 回调:
m = mqtt.Client(...)
m.publish("/my/topic", "some message", 1, 0, callback_func)
在上面的简单案例中,即使实际发送 MQTT 消息与 publish() 调用异步(请参见这里的很好的讨论[https://stackoverflow.com/questions/33414441/nodemcu-and-esp8266-slow-mqtt-publish]),`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)
但这将不能达到预期的结果。正如文档所述:
注意:在调用 publish() 多次时,最后一个定义的回调函数将为所有 publish 命令调用。
因此,在上面的示例中,callback_func() 最终会被调用两次(分别用于每个成功的 publish())。
我可以将多个 publish() 调用合并为单个调用,但这感觉像一个丑陋的 hack,并且会有其他不良影响。如果我的两条消息在概念上是不同的,这种方法将把逻辑推向将它们分离成订阅者 - yuck。如果它们需要进入不同的主题,那将更糟糕。必须有更好的方法。
我曾经以为 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)
- Lua 虚拟机加密load(string.dump(function)) 后执行失败问题如何解决
- 我想创建一个 Nginx 规则,禁止访问
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?

选项 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