MQTT / ESP8266 / NodeMCU / Lua code not publishing

2019-08-13 00:53发布

问题:

I have a problem with the following Lua code on an ESP8266...

function sendData(humidity,temperature)
    -- Setup MQTT client and events
    print("sendData() entered")
    print("Setting up mqtt.Client...")
    m = mqtt.Client(mqtt_client_id, 120, username, password)
    print("Attempting client connect...")
    m:connect(mqtt_broker_ip , mqtt_broker_port, 0, function(conn)
        print("Connected to MQTT")
        print("  IP: " .. mqtt_broker_ip)
        print("  Port: " .. mqtt_broker_port)
        print("  Client ID: " .. mqtt_client_id)
        print("  Username: " .. mqtt_username)

        payload = "Temp: " .. temperature .. " Hmdy: " .. humidity
        m:publish("pt/env",payload, 0, 0, function(conn)
            print("Going to deep sleep for " .. (DSLEEPTIME/1000) .. " seconds")
            node.dsleep(DSLEEPTIME*1000,4)             
        end)
    end)
end

The code is being successfully called with the following...

-- Connect to network
wifi.setmode(wifi.STATION)
wifi.setphymode(wifi_signal_mode)
wifi.sta.config(wifi_SSID, wifi_password) 
wifi.sta.connect()

print("Attempting to connect...")
ip = wifi.sta.getip()
if ip ~= nil then
    print("Got IP: " .. ip)
    print("About to call sendData()...")
    sendData(humidity, temperature)
    print("Returned from sendData()...")
end

Using ESPlorer I see the following...

Attempting to connect...
Attempting to connect...
Attempting to connect...
Attempting to connect...
Attempting to connect...
Attempting to connect...
Got IP: 192.168.0.39
About to call sendData()...
sendData() entered
Setting up mqtt.Client...
Attempting client connect...
Returned from sendData()...

So it basically enters sendData(...) and I see the output from the line...

print("Attempting client connect...")

...but I never see the logging in the m:connect(...) block such as...

print("Connected to MQTT")

...it seems it simply returns immediately.

The MQTT broker is a Raspberry Pi running Mosquitto and I've tested it with apps on my Android phone and tablet. I get successful publishing / subscription between phone and tablet in both directions.

I'm a Lua novice and only understand the basics of MQTT and I'm at a loss for what's wrong with the m:connect(...) block if anyone can help it would be appreciated.

UPDATE: PROBLEM SOLVED - Apologies for not getting back to this thread sooner. The problem was simply down to the version of Mosquitto I was running on my RPi (which complied to MQTT v3.1). The NodeMCU MQTT library supports MQTT v3.1.1 and is NOT backward compatible. In essence there wasn't very much wrong with my code although I did make some changes - it was simply down to MQTT versions being incompatible.

回答1:

You didn't tell us what NodeMCU version you use. Warning: do NOT use any of the pre-built 0.9.x binaries available at https://github.com/nodemcu/nodemcu-firmware/releases. Build your own firmware as per http://nodemcu.readthedocs.io/en/dev/en/build/.

I always helps to strip a failing function and to make use of all available callback functions. I can confirm the following works on a nearly 2 months old firmware from the dev branch sending data to cloudmqtt.com:

function sendData(humidity, temperature)
    print("Setting up mqtt.Client...")
    m = mqtt.Client("SO-36667049", 120, "user", "password")
    print("Attempting client connect...")
    m:connect("m20.cloudmqtt.com", 12703, 0, 0,
        function(conn)
            print("Connected to MQTT")
            payload = "Temp: " .. temperature .. " Hmdy: " .. humidity
            m:publish("topic", payload, 0, 0, 
                function(client) 
                    print("Message sent") 
                end)
        end,
        function(client, reason)
            print("Connection failed, reason: " .. reason)
        end)
end

Differences:

  • m:connect defines secure y/n and autoreconnect y/n explicitly. It always confuses me if only a subset of all optional parameters is set. Is your 0 in m:connect interpreted as secure or as autoreconnect? I don't know Lua well enough to tell why I code it explicitly.
  • Make use of the extra callback for function for failed connection attempts. See http://nodemcu.readthedocs.org/en/dev/en/modules/mqtt/#connection-failure-callback-reason-codes for failure reason codes.
  • Do NOT use the same name for variables in callback functions as used in "parent" functions. Note how you use m:connect(..., function(conn) and then inside that function you use m:publish(..., function(conn) again. You don't interact with the conn object in your code, so no harm done. However, this may bite you in other projects.


回答2:

Your code is looking fine. If m:connect fails nothing will happen as you did not provide a callback function for failed connection attempts.

Also you don't check m:connect's return value for success.

Refer to http://nodemcu.readthedocs.org/en/dev/en/modules/mqtt/#mqttclientconnect

And check if your connection attempt fails.