Мое приложение включает в себя ESP8266 с питанием от батареи, работающий с NodeMCU, с целью периодического обновления значений датчиков над MQTT.С Lua/NodeMCU, как я могу дождаться, пока> 1 mqtt публичные вызовы были сделаны до запуска блока кода?
Чтобы сэкономить время работы от батарей, я хочу позвонить dsleep()
, как только закончите с моей работой. Эта работа может включать более 1 вызова 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()
вызовов в один вызов, но чувствует, как уродливые взломать, и будет иметь другие неблагоприятные последствия.Если мои два сообщения концептуально различны, этот подход заставит логику отделить их от подписчика - yuck. И если им нужно идти по разным темам, это будет еще хуже. Должен быть лучший способ .
Я думал, возможно mqqt.Client.close()
wo uld ждет моих разных 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 заставляет меня искажать поведение системы по ограничениям клиента. В частности, если мои сообщения отличаются по своей природе (они есть) и, следовательно, требуют отдельной обработки (возможно, даже разных подписчиков), я оставил повторную реализацию логики темы (эффективно) внутри абонента. (Например, скажем, я публикую временные данные и данные о присутствии в комнате, и я хочу, чтобы совершенно другая логика на стороне абонента справлялась с этими двумя вещами.) – jrheling
Вариант 2 звучит неплохо, но я не вижу, как его реализовать как обратный вызов ведет себя на 'publish()'. Буквально точно такая же логика запускается для каждого вызова, так как я могу проверить, завершен ли первый вызов? Можете ли вы привести пример того, как это может работать, пожалуйста? – jrheling
вы используете ту же логику с помощью инструкции if, чтобы проверить, выполнены ли вы или нет. вы используете его, если я предполагаю, что вы знакомы с условными утверждениями ... вам не нужно знать, выполняется ли первый вызов. все, что вам нужно знать, это то, что все звонки выполняются до того, как вы можете заснуть. – Piglet