Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
有了Lua/NodeMCU,我怎么能等到>;1运行代码块之前是否已进行mqtt发布调用?_Lua_Mqtt_Nodemcu - Fatal编程技术网

有了Lua/NodeMCU,我怎么能等到>;1运行代码块之前是否已进行mqtt发布调用?

有了Lua/NodeMCU,我怎么能等到>;1运行代码块之前是否已进行mqtt发布调用?,lua,mqtt,nodemcu,Lua,Mqtt,Nodemcu,我的应用程序涉及一个运行NodeMCU的电池供电的ESP8266,用于通过MQTT定期更新传感器值 为了节省电池寿命,我想在完成工作后立即调用dsleep()。这项工作可能涉及对mqt.Client.publish()的多个调用。这就引出了我面临的问题 我是Lua新手,但据我所知,在publish()完成后运行某些代码的正确方法是给它一个PUBACK回调: m = mqtt.Client(...) m.publish("/my/topic", "some message", 1, 0, call

我的应用程序涉及一个运行NodeMCU的电池供电的ESP8266,用于通过MQTT定期更新传感器值

为了节省电池寿命,我想在完成工作后立即调用
dsleep()
。这项工作可能涉及对
mqt.Client.publish()
的多个调用。这就引出了我面临的问题

我是Lua新手,但据我所知,在
publish()
完成后运行某些代码的正确方法是给它一个PUBACK回调:

m = mqtt.Client(...)
m.publish("/my/topic", "some message", 1, 0, callback_func)
在上面这样一个简单的例子中,这非常有效——即使MQTT消息的实际发送对于
publish()
调用是异步的(请参阅对此的详细讨论),
callback\u func()
仅在
publish()
完成时才会被调用

但是当我有一个以上的调用
publish()
并且希望我的回调在它们全部完成后被调用,而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\u func()
最终会被调用两次(每次成功调用
publish()

我可以组合多个
publish()
调用一个呼叫,但这感觉像是一个丑陋的黑客行为,并会产生其他不利影响。如果我的两条消息在概念上不同,这种方法会推动逻辑将它们分为订阅者-糟糕。如果它们需要转到不同的主题,这将更糟。必须有更好的方法

我以为
mqt.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)
备选案文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

发布的项目

发布的项目

发布的项目

发布的项目

发布的项目

我做完了,晚安


谢谢!不过,我认为这两个选项都不能真正满足我的需求。选项1迫使我围绕客户端的限制扭曲系统行为。具体来说,如果我的消息本质不同(它们是不同的),因此需要单独处理(甚至可能由不同的订阅者处理),我将重新实现主题逻辑(有效地)在订阅者内。(例如,假设我正在发布临时数据和房间状态数据,我希望完全不同的订阅者端逻辑来处理这两件事。)选项2听起来不错,但鉴于回调在
publish()上的行为方式,我看不到如何实现它
。每个调用都会运行完全相同的逻辑,那么我如何检查第一个调用是否完成?请给出一个如何工作的示例?您可以使用if语句运行相同的逻辑来检查是否完成。如果是,您已经使用了if。我假设您熟悉条件语句……您不必知道第一次呼叫已完成。您所要知道的是,所有呼叫都已在您睡觉之前完成。啊,是的!谢谢-出于某种原因,我没有想到只计算回拨的呼叫数。这非常有效。