Я не могу подписаться на брокера MQTT на Lua для ESP8266 - PullRequest
0 голосов
/ 14 марта 2020

Прежде всего, я использую следующее:

  • ESP8266 (ESP12E)
  • Стандартная прошивка от Git (построена с linux со всеми соответствующими конфигами, согласно с документацией nodemcu)
  • ESPlorer IDE

Моя конкретная проблема c (я думаю) заключается в том, что я не могу подключить свой клиент MQTT к брокеру adafruit.io. Я думаю, что я успешно подключился к WiFi (определяется двумя отдельными SSID). Проблема возникает при создании MQTT-клиента и его подключении к его брокеру.

-- INITIAL DEFINES
-- defines
station_cfg={}
station_cfg.ssid        = "<my wifi>"    -- my personal ssid
station_cfg.pwd         = "<wifi pwd>"   -- my wifi pwd
--station_cfg.ssid        = "IoT"        -- campus' ssid
--station_cfg.pwd         = "<wifi pwd>" -- campus' wifi pwd, I tried this first, then my home's. It 
                                            worked as it should
station_cfg.auto        = false
station_cfg.save        = false

mqtt_client_cfg = {}
mqtt_client_cfg.clientid    = "alro"          -- any ID
mqtt_client_cfg.keepalive   = 120             -- went for the example's value
mqtt_client_cfg.username    = "AlvaRocha"     -- obviously a paranoic Ctrl+C/V from adafruit
mqtt_client_cfg.password    = "aio_KO<safety edit>sXwbgtWCboCal" -- obviously a paranoic Ctrl+C/V 
                                                                 -- from adafruit

wifi.setmode(wifi.STATION)
wifi.sta.config(station_cfg)
wifi.sta.connect(connect)         -- so far so good

iot_test = mqtt.Client(mqtt_client_cfg) -- open client, apparently OK
--iot_test:lwt("/lwt", "offline", 0, 0) -- this line is on examples, doesn't affect outputs

iot_test:on("connect", function(client) print("client connected") end)
iot_test:on("offline", function(client) print("client offline") end) -- this event is called
                                                                     -- always (line 27)

function connect(params)
    print('Connected to:', params.SSID) -- I understant from documentation that this is called IF 
                                        -- successfull wifi connection. Double checked with 
                                        -- campus' and home wifi
end

function disconnect(params)
    print('Disconnected from:', params.SSID) -- ignore this function
end

function get_broker(mqtt_client)
    mqtt_client:connect("io.adafruit.com", 1883, false, false, --Found this double 'false' on 
                                                   --https://www.electronicwings.com/nodemcu/nodemcu- 
                                                   --mqtt-client-with-esplorer-ide 
           function(client) -- CONNECTED CALLBACK
            print('connected to broker') 
            --break
            -- continue
            client:subscribe("/Test", 0, function(client) print("Succesfull sub.") end) -- (LINE 42)
            --break
      --- continue
      end,
      function(_reason) -- OFFLINE CALLBACK not called (called if I don't write the 'double false' 
                        -- from the example)
            print('connection failed', reason) 
      end)
 end

 get_broker(iot_test) -- connect to broker

ПРОБЛЕМА: несмотря на то, что вызывается строка 27, вызывается CONNECTED CALLBACK. Там нет согласованности.

ВЫПУСК: Вывод строки 42: PANI C: незащищенная ошибка при вызове Lua API (init. lua: 42: не подключено)

Надеемся на комментарии полезны, я хочу заявить очевидное:

  • Я впервые использую ESP8266, LUA и MQTT
  • Я прочитал столько, сколько мне было удобно (вы никогда не смогу прочитать достаточно)
  • Мне не нравится Arduino IDE (но я попробую, когда ответят)

Я подозреваю следующее:

  • Я где-то напутал в конфигурации прошивки.
  • WiFi на самом деле не подключен.
  • Я упускаю что-то очевидное.

С уважением, Alvaro R .

1 Ответ

0 голосов
/ 15 марта 2020

В вашем сценарии есть пара ошибок; некоторые фундаментальные, некоторые специфические c.

Основы

NodeMCU является асинхронным

Модель программирования NodeMCU аналогично Node.js, только в Lua. Это асинхронный и управляемый событиями. Поэтому многие функции имеют параметры для функций обратного вызова.

-> https://nodemcu.readthedocs.io/en/latest/#programming -модель

Это означает, что вы не можете предполагать, что оператор находится на линии N завершено, как только выполнение продолжается в строке N + 1. Это относится, например, к wifi.sta.connect(), как намекнул @darius в комментарии. Вы можете зарегистрировать обратный вызов, который сработает, когда ваше устройство получит IP-адрес от DHCP. Мы поддерживаем шаблон для одного из возможных способов обработки этого в документации.

Доверяйте только официальной документации

Вы, очевидно, получили некоторые фрагменты кода из целого rnet ресурса, который является неправильным или устаревшим. Обычно лучше обратиться к официальной документации API. Мы стремимся сделать его полезным и актуальным.

Особенности

Инициализация клиента MQTT

В отличие от wifi.sta.config() который ожидает один Lua табличный параметр mqtt.Client() ожидает отдельные параметры. Следовательно, mqtt.Client(mqtt_client_cfg) неверно.

-> https://nodemcu.readthedocs.io/en/latest/modules/mqtt/#mqttclient

MQTT-клиентское соединение

Подпись вашей подписи mqtt.client:connect() неправильно. Это connect(host[, port[, secure]][, function(client) с secure, являющимся логическим, а не двумя логическими значениями, которые вы передаете.

-> https://nodemcu.readthedocs.io/en/latest/modules/mqtt/#mqttclientconnect

Возможное исправление

Вот один из способов исправить ваш скрипт:

station_cfg = {}
station_cfg.ssid = "***"
station_cfg.pwd  = "***"

station_cfg.auto = false
station_cfg.save = false

mqtt_cfg = {}
mqtt_cfg.host      = "io.adafruit.com"
mqtt_cfg.port      = 1883
mqtt_cfg.clientid  = "alro"
mqtt_cfg.keepalive = 120
mqtt_cfg.username  = "AlvaRocha"
mqtt_cfg.password  = "aio_KO<safety edit>sXwbgtWCboCal"

wifi.setmode(wifi.STATION)
wifi.sta.config(station_cfg)

iot_test = mqtt.Client(mqtt_cfg.clientid, mqtt_cfg.keepalive, mqtt_cfg.username, mqtt_cfg.password)
iot_test:on("offline", function(client)
  print("client offline")
end)
iot_test:on("message", function(client, topic, data)
  print("MQTT msg received on '" .. topic .. "':")
  if data ~= nil then
    print("\t" .. data)
  end
end)

function get_broker(mqtt_client)
  mqtt_client:connect(mqtt_cfg.host, mqtt_cfg.port, false,
    function(client)
      client:subscribe("/topic", 0, function(client)
        print("subscribe success")
      end)
      client:publish("/topic", "hello", 0, 0, function(client)
        print("sent")
      end)
    end,
    function(client, reason)
      print('connection failed', reason)
    end)
end

function startup()
  if file.open("init.lua") == nil then
    print("init.lua deleted or renamed")
  else
    print("Running")
    file.close("init.lua")
    get_broker(iot_test)
  end
end

wifi_connect_event = function(T)
  print("Connection to AP(" .. T.SSID .. ") established!")
  print("Waiting for IP address...")
  if disconnect_ct ~= nil then
    disconnect_ct = nil
  end
end

wifi_got_ip_event = function(T)
  -- Note: Having an IP address does not mean there is internet access!
  -- Internet connectivity can be determined with net.dns.resolve().
  print("Wifi connection is ready! IP address is: " .. T.IP)
  print("Startup will resume momentarily, you have 3 seconds to abort.")
  print("Waiting...")
  tmr.create():alarm(3000, tmr.ALARM_SINGLE, startup)
end

wifi.eventmon.register(wifi.eventmon.STA_CONNECTED, wifi_connect_event)
wifi.eventmon.register(wifi.eventmon.STA_GOT_IP, wifi_got_ip_event)

wifi.sta.connect()
...