robust mqtt publish freezes randomly on Nb-IoT



  • I've been having an intermittent problem that will occur randomly within 10 minutes to a couple hours where it will freeze. I've troubleshooted it to getting stuck on simple mqtt's socket write of the payload:

            def publish(self, topic, msg, retain=False, qos=0):
                    ....
                    self.sock.write(msg)
    

    I've observed that the pycom will keep sending publishes even though the payload wouldn't make it to the broker. It would continue to do this (34 publishes) until it eventually freezes on the socket write. I'm not getting any error messages and it appears to stay stuck for 7 minutes before it's able to send payloads again. I can reboot the device and it will connect broker first time and successfully send the payloads. I've altered the sleep time to 5 seconds but I still experience the same issue. Does anyone have some insight as I'd like some method to be able to catch this issue and attempt a disconnect and reconnect to the broker. Below is the code I'm using:

    lte = LTE()
    
    def connectNbIoT():
        try:
            print("Connecting to NB-IoT...")
            pycom.rgbled(0x7f7f00)  # yellow
    
            if lte.isconnected():
                print('Disconnecting...')
                lte.disconnect()
    
                time.sleep(1.5)
    
            if lte.isattached():
                print('Dettaching...')
                lte.dettach()
    
                time.sleep(1.5)
    
            while not lte.isattached():
                print('Attaching...')
                pycom.rgbled(0xff7f00)  # yellow
                lte.attach()
                time.sleep(20)
    
            while not lte.isconnected():
                print('Connecting...')
                pycom.rgbled(0x7f007f)  # purple
                lte.connect()
                time.sleep(2.5)
    
            print("Connected to NB-IoT")
            pycom.rgbled(0x00007f)  # blue
        except:
            print("Could not connect to Nb-IoT")
            return False
    
        return True
    
    
    def checkNbIoTConnection():
        if (lte.isconnected()):
            return
        connectNbIoT()
    
    
    while True:
        if connectNbIoT():
            break
    
    client = MQTTClient("123456789", "<url>", port=1883, keepalive=180)
    
    def connectMQTT():
        try:
            pycom.rgbled(0x00007f)  # blue
            print("Connecting to MQTT broker...")
            client.connect()
            print("Connected to MQTT broker...")
            pycom.rgbled(0x007f00)  # green
            return True
        except OSError as e:
            print("MQTT error occurred: %r" % e)
            return False
    
    while True:
        if connectMQTT():
            break
    
    topic = "devices/Pysense.12345"
    
    payload = {}
    
    while True:
    
        checkNbIoTConnection()
    
        while True:
            try:
                pitch = acc.pitch()
                roll = acc.roll()
                temperature = si.temperature()
                humidity = si.humidity()
                battery_voltage = py.read_battery_voltage()
                battery_level = int(((battery_voltage - PYSENSE_MIN_VOLTAGE) /
                                     (PYSENSE_MAX_VOLTAGE - PYSENSE_MIN_VOLTAGE)) * 100)
                if (battery_level > 100):
                    battery_level = 100
                elif (battery_level < 0):
                    battery_level = 0
            except OSError as e:
                print("error with bus")
                continue
            break
    
        payload["data"] = {"roll": roll, "pitch": pitch, "humidity": humidity, "temperature": temperature, "batteryLevel": battery_level, "batteryVoltage": battery_voltage}
    
        print("Sending " + json.dumps(payload))
        try:
            client.publish(topic=topic, msg=json.dumps(payload))
        except:
            print("MQTT Publish exception")
            connectMQTT()
    
        print("Finish Send")
        time.sleep(0.2)
    


  • I've done some further troubleshooting and tried the following methods to get it to send consistently:

    1. Change QoS to 1. I found that I still encountered the same issue before where it got stuck after a random amount of time. This also delayed each additional message by about 1 - 5 seconds so I removed the time.sleep(0.2)

    2. Wait for ping message after every 10 publishes. I found that this also ended up getting stuck as well. Again I removed the sleep cause the delay was between 1-5 seconds on the ping.

    if (count == 10):
        client.ping()
        client.wait_msg()
        count = 0
    count += 1
    
    1. Ping message after every publish. This didn't suffer the problem of freezing during the hour that I tried. I did find however that the duration for it to get a successful ping took longer as time went on. From about 1-3 seconds average to about 7-10 seconds average after about an hour.

    2. Connect and disconnect the client after every publish. This seems to working the best, it hasn't frozen within the 30 minutes I've been testing it and each message is taking 3-5 seconds to send to the broker.

    If anyone has any further suggestions it would be appreciated.


Log in to reply
 

Pycom on Twitter