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)