MQTT with Deep Sleep needs some module enhancements

Posted on
  • For a battery operated IoT device which requires infrequent updates, it would be great to enter deep sleep, wake up every so often, connect to an mqtt broker and publish update(s), then disconnect and go back to deep sleep.

    In trying to accomplish this goal, using the 'MQTT' module, the first hurdle is knowing when all the messages have been published so that we can go back to sleep. Even for QOS 0, it's not easy knowing exactly when the code can issue the setDeepSleep(1) command.

    Using QOS 1, I thought I could register a 'puback' handler, and sleep on that, but it turns out the current 'MQTT' module doesn't do anything with a PUBACK.

    I don't know if the forum is the right place to suggest this, but what about emitting a puback if that has been received from the broker? Something like...

    else if (type === TYPE.PUBACK) {
        mqo.emit('puback', data.charCodeAt(2) << 8 | data.charCodeAt(3));
    }
    

    Then in the user code, a handler would be something like...

    mqtt.on('puback', (pid) => {
         mqtt.disconnect();
         wifi.disconnect();
         setDeepSleep(1);
    });
    

    (not doing anything with pid right now, since the user code has no method to get the outgoing pid anyway)

  • I guess a flexible solution might be to just emit any unhandled packets as an event, and you can pick those up?

    Could you provide a bit of info about your setup though? What device are you using, and what are you using to connect to the network?

    Usually something like WiFi or Ethernet will use enough power when connected that the actual power draw of the Espruino device when connected is negligible, so there's not been much effort put into making the device sleep properly when there's a connection active.

    It depends on how you're connecting, but if it's using something like a serial connection then deep sleep will stop the Espruino device listening for any incoming serial data, which will mean that you not only lose any incoming data but also potentially get out of sync.

  • Yes, sorry, I should have provided more context. In my particular case, I am using an Espruino WiFi, however I can see how some sort of notification might be helpful in other situations.

    In my case, I have a long setInterval of a half-hour or more. At the interval time, the program exits deep sleep, the WiFi connects, then the MQTT connects, and then the message can publish. After the message is published, everything disconnects and the board is put back into deep sleep. The real issue is being sure the message was sent before slipping back into dreamland.

    My issue is actually tangent to the main protocol. Right now, although the module accepts a QoS option, it doesn't really do anything different in such cases. I can see that it does accept PUBREC and PUBREL and replies correctly in those cases, but PUBACK and PUBCOMP are ignored. There should be a mechanism for retransmission if with a duplicate message if the broker doesn't acknowledge receipt. Then maybe the side benefit is emitting an event of success so that the user program can do something useful (such as go back to sleep in my case).

    The good news is that most of the scaffolding is already in place to correctly handle QoS 1 and 2. It just needs to store and retransmit duplicate messages until the proper acknowledgment is received.

  • The other day I looked for a repository for the MQTT module but didn't find it. Now I just discovered it with the EspruinoDocs repo. Perhaps it would be better to make an enhancement issue there to get it in the queue and better track the discussion and changes. Yes?

  • Thanks for the explanation - yes, that makes loads of sense. I've just added your suggestion of the extra events and published a new module.

    The issue is that the MQTT module was only originally designed for QoS 0 (because the TCPIP that's used most of the time basically has its own QoS anyway) and extra QoS levels have been partially tacked on over time to handle specific peoples' use cases...

    Yours seems like a great reason for having QoS 1 though.

    If someone really does needs QoS 2 then I think we should probably look at adding a new module for it (possibly just using a proper JS library from elsewhere) - I've already had several complaints that the standard MQTT one is too big, leading to https://www.espruino.com/tinyMQTT

  • Awesome, thanks! I'm not sure where you find the time to attend to such trivial matters however.

  • @ScottyMT tinyMQTT works great.

    I use the Save & load from Storage variant, because it saves heap using it this way :)

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

MQTT with Deep Sleep needs some module enhancements

Posted by Avatar for ScottyMT @ScottyMT

Actions