Manually Configured Device - Maximum of 2^16 Variable Updates

I have a number of environment sensors that pass values to Arduino IoT Cloud variables via a Raspberry Pi 4b set up as a Manually Configured Device. It runs Python 3.8.0.

When I boot the RPi, everything works fine with updates displaying in the dashboard widgets. However, after a few days, sometimes a week, the updates stop and the widget values freeze.

So I went back to a simpler model and I ran a test case that produces updates to an integer cloud variable with a count starting at 0 and incrementing once per second.

I executed it as a service under systemctl until the variable updates stopped working and the widget values froze, then repeated it another four times, noting the widget values. The frozen values indicated in the dashboard were 43684, 65551, 50579, 65534 and 65536.

Three of the values are very close to 2^16, too close for coincidence, so my immediate thought was whether there is a 16-bit thing going on somewhere.

The code runs the client on its own thread, client_thread, with the count generated by the main thread. I put in a check to log a client_thread mortality, but it was never triggered.

Interestingly, the systemctl log indicates that the client continues to push new values even after the widget value freezes.

I then repeated the test with the count starting at 100000 to try to flush out where the problem might be. The updates handle the larger values to start with, so it's not a value limit, but then the widget froze with the value 165532.

That points more towards the number of updates is being limited to about 2^16 for some reason. Is this to be expected?

The code is below. I'd be grateful for any ideas.

"""
    A simple producer.
    Sends an incrementing integer to an AIoT Cloud variable, int_producer.
"""

import time
import logging
import threading
import sys
sys.path.append("lib")
from arduino_iot_cloud import ArduinoCloudClient

DEVICE_ID   = b"XXXXXXXXXXXXXXXXXXXX"
SECRET_KEY = b"YYYYYYYYYYYYYYYYYYYYY"

def logging_func():
    logging.basicConfig(
        datefmt="%H:%M:%S",
        format="%(asctime)s.%(msecs)03d %(message)s",
        level=logging.DEBUG,
    )   

def int_producer_changed(client, value):
    """ This function is executed each time the cloud variable "int1" changes """
    int1 = value
    logging.info("int_producer = {}".format(value))

def client_thread_func(client):
    """ This function defines the client thread functionality """
    client.start()

if __name__ == "__main__":

    # Set up stuff here
    logging_func()
    client = ArduinoCloudClient(device_id=DEVICE_ID, username=DEVICE_ID, password=SECRET_KEY)
    client.register("int_producer", value=None, on_write=int_producer_changed)
    client_thread = threading.Thread(target=client_thread_func, args=(client,), daemon=True)
    client_thread.start()
    
    number = 100000
    
    while True:
        if client.started:
            number += 1
            client["int_producer"] = number
        if not client_thread.is_alive():
            logging.info("The client is a gonner!")
        time.sleep(1)

I've got around the issue by having the script terminate at midnight and letting systemctl restart it automatically. But this isn't curing the underlying issue and only works because my required variable update rate is less than 2^16 per day.

I won't pursue this further as I reckon this is more likely a cloud implementation issue rather than something I'm doing.

Update 28/09/2023:

I ran a slower test with an update every 8 seconds. Multiple days to reach 2^16 but fast enough to prevent the client pings. This time the updates stopped at 65544, again very close to 2^16.

The client is still sending updates, so my guess is that the problem lies on the cloud (server) side.