MQTT connection options

Posted on
  • I am running v1.87 on an esp8266. I am able to subscribe to an MQTT broker running on my local network. I can publish and subscribe successfully.

    I am attempting to publish from one esp8266 and subscribe from another. I believe that both boards use the same default client_id, because when I connect the second one, the first is disconnected.

    I would expect to be able to work around this by setting a client_id in the MQTT connection options, as described here: http://www.espruino.com/MQTT

    My code looks like this:

    var server = "192.168.2.10";
    
            mqtt = require("MQTT").create(server);
            mqtt.connect({
                client_id: 'webmos02'
            });
    
            mqtt.on('connected', function() {
                mqtt.publish('led', 'webmos02 start');
                mqtt.subscribe("led");
                print('subscribed to led');
            });
    
            mqtt.on('publish', function(pub) {
                print("topic: " + pub.topic);
                print("message: " + pub.message);
            });
    
    

    I get these errors:

    Uncaught Error: Function "write" not found!
     at line 1 col 35
    ....log("Client connected");a.write(b.mqttConnect(b.clie­nt_id))...
                                  ^
    in function "e" called from line 3 col 353
    ..."close")});b.client=a};a?e():a=requir­e("net").connect({host:...
                                  ^
    in function "connect" called from line 1 col 131
    ...nect({client_id:'webmos02'}),mqtt.on(­'connected',function(){...
                                  ^
    in function called from system
    

    I have tried putting in other things in the connection options, like _protocolname: "MQTT" and get the same result. I get errors regardless of what I put in as a connection option.

    If I leave out the connection option I am able to connect and both publish and subscribe.

    1. Am I correct in assuming that two different esp8266s without a client_id set will use the same client_id and thus collide?
    2. How do I set a client_id?
    3. Is there possible another way to resolve this issue?

  • In the code above protocolname, should be protocol_name...

  • Well, I believe that I have proved one of my assumptions wrong.
    I decided to try it 'one more time', and it worked.
    Last night I had one esp8266 setup to publish to the 'led' topic, and the other to subscribe.
    The idea was that I could change the LED color on webmos01 and it would publish the colour as a message. The other es8266, aka webmos02 would subscribe to the led topic and then change it's LED colour appropriately.
    The problem was, when I would turn on the second of the two the first would no longer be able to publish or subscribe. It did not matter which one I powered up first.

    So for my one last test I removed the connection options from my code and powered them both up for a test. And now they work as expected. I've done several power cycles on both and cannot get a failure. I don't know what I did right, but I like the result.

    I would still like to know how to set a client_id and/or set connection options.

  • Just a thought on this. Espruino on ESP8266 now has many more JSvars available to it than the early versions of the port did - and I've been meaning to try the core espruino MQTT module on it to see if it runs - but, back in day, on the development versions, the module was just too big to load and then run any sort of application on the back of.

    The errors you mention here would suggest to me that it is still too big. Just wondering if merely dumping the connections options as you did was enough to keep within memory..

    Can you check process.memory when your code is loaded/running? It would be interesting to know what "free" is.

  • Here is the code that works without error:

    var
        led = NodeMCU.D7,
        relay = NodeMCU.D6;
    
    pinMode(led, "output");
    pinMode(relay, "output");
    
    
    
    function onInit() {
        setupWifi();
        setLed(led, 0);
    }
    
    
    
    function setupWifi() {
        var
            ssid = "ssid",
            options = {
                password: "password"
            },
            wifi = require("Wifi");
    
    
        wifi.connect(ssid, options, function() {
            print(wifi.getIP());
    
            server = "192.168.2.10";
            mqtt = require("MQTT").create(server);
            mqtt.connect();
    
            mqtt.on('connected', function() {
                mqtt.publish('esp8266/status', 'sonoff01 start');
                mqtt.subscribe("esp8266/sonoff01");
    
            });
    
            mqtt.on('publish', function(pub) {
                mqtt.publish('esp8266/status', 'sonoff01 ' + pub.message);
    
                switch (pub.message) {
                    case 'on':
                        setLed(led, 1);
                        setRelay(relay, 1);
                        break;
                    case 'off':
                        setLed(led, 0);
                        setRelay(relay, 0);
                        break;
                }
            });
    
        });
    }
    
    
    
    
    function setLed(led, state) {
        state = !state;
        digitalWrite(led, state);
    }
    
    function setRelay(relay, state) {
        digitalWrite(relay, state);
    }
    

    Here is what process.memory() shows:

    process.memory();
    ={ "free": 849, "usage": 851, "total": 1700, "history": 434 }
    

    Change line 31 from:

    mqtt.connect();
    

    to:

    mqtt.connect({client_id:"booger"});
    

    This is the result:

    Running onInit()...
    {
      "ip": "192.168.2.16",
      "netmask": "255.255.255.0",
      "gw": "192.168.2.1",
      "mac": "60:01:94:07:ab:1e"
     }
    Client connected
    Uncaught Error: Function "write" not found!
     at line 1 col 35
    ....log("Client connected");a.write(b.mqttConnect(b.clie­nt_id))...
                                  ^
    in function "e" called from line 3 col 353
    ..."close")});b.client=a};a?e():a=requir­e("net").connect({host:...
                                  ^
    in function "connect" called from line 1 col 109
    ...onnect({client_id:'booger'}),mqtt.on(­'connected',function(){...
                                  ^
    in function called from system
    

    Here is what process.memory() shows:

    process.memory();
    ={ "free": 1120, "usage": 580, "total": 1700, "history": 436 }
    
  • My MQTT broker is Mosquitto running on a Raspberry Pi. I have three different esp8266s running that use the same wifi and MQTT connection code. 2 of the 3 devices get a different client_id assigned from Mosquitto. The third device ( a Sonoff wifi switch) gets the same client_id as one of the other devices, which disconnects the first device with that client_id to be connected.

    I understand that this is default and desirable configuration for Mosquitto. I looked at the documentation for the conf file to see if there was a way to have it generate other types of client_ids if the clients are anonymous. I found no way to do this. It looks like my only hope is to be able to set the client_id on the es8266 when the mqtt.connect() happens.

    I thought that maybe I would have luck with a different MQTT broker. I tried http://andsel.github.io/moquette/. Which runs and appears to work just fine, but it behaves exactly like Mosquitto.

  • I thought that maybe the client_id that Mosquitto provided to anonymous clients may somehow be tied to the hardware, MAC address, or IP address. I tried loading the code on to yet another esp8266 that I have. When it does the mqtt.connect() it gets the same client_id from Mosquitto as the other two.

    I have my router configured to assign each esp8266 (I have six of them so far) a different IP address. But each device gets the same IP each time it connects. Apparently Mosquitto does not pay attention to the IP address of the clients.

  • I tried two other things to get Mosquitto to use totally unique client_ids.
    First I tried setting a different host name for each esp8266 with wifi.setHostname(hostname)
    This made no difference.
    Then I tried setting the time with wifi.setSNTP(server, tz_offset)
    This made no difference.

    Then I took out the code that set the hostname and time and uploaded to the sonoff again.
    Now I get a different client_id for each device. I have no idea why. I LOVE Heisenbugs!

    1477452360: New connection from 192.168.2.11 on port 1883.
    1477452360: New client connected from 192.168.2.11 as b0a38163976b (c1, k60).
    1477452386: New connection from 192.168.2.12 on port 1883.
    1477452386: New client connected from 192.168.2.12 as 8e0660e041fa (c1, k60).
    1477452398: New connection from 192.168.2.16 on port 1883.
    1477452398: New client connected from 192.168.2.16 as e14751c9fb06 (c1, k60).
    
  • I found the cause. WHITESPACE! Yep, if I change the number of spaces at the end of the line of code, after the ; mqtt.connect(); and upload/flash, I will get a different client_id from Mosquitto.
    Other changes to whitespace may have the same result. Further experiments will follow.

    I am using the Web IDE. I have my source code in Atom (because I edit everything in Atom) and then copy/paste the code into the Web IDE. I use the 'Send to Espruino' icon to upload/flash the code to the esp8266. I connect to the esp8266 over wifi to upload/flash. I reset() before every upload/flash and save() after.

    In WebIDE under Communications I have Reset before Send set, and Set Current Time set.

    Minification Settings:
    Minification and Module Minification are both set to 'Esprima (offline)'
    All check boxes are checked.

    Later I may toggle some settings and see if I get different results.

  • Strange... If you're minifying then whitespace shouldn't have an effect - perhaps you could check in the 'setting->console' area and see if it does change what gets sent to Espruino...

    I'm not sure how well tested the upload over Wifi is... I guess it's possible that you could upload code so quickly over WiFi that buffers get full and Espruino ends up dropping characters...

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

MQTT connection options

Posted by Avatar for jfox @jfox

Actions