I've set-up a Raspberry Pi to be a manually configured thing as described here. The example works fine and demonstrates how to connect to the cloud and interact with cloud variables. That's all good; mission accomplished.
However, in the example the client() blocks completely the script which has left me wondering how best to structure a script to contain some user defined functionality.
The best I could come up with is to put client() on its own thread to leave the main thread for my stuff as in the script below.
I'm new to multi-threaded scripting and was wondering if communicating between the threads as I have is unconditionally safe. It does seem to work, but is it correct? Could it be done better?
I'd very much like to hear the opinion of someone with experience of threads.
I'd also be interested to get other ideas as to how a script might be structured. I've loosely followed the standard Arduino approach of a set-up and a loop.
"""
A script that implements a very simplistic model of a heating system
to demonstrate how a script of a manually configured Thing might be
structured.
"""
import time
import logging
import threading
import sys
sys.path.append("lib")
from arduino_iot_cloud import ArduinoCloudClient
DEVICE_ID = b"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
SECRET_KEY = b"YYYYYYYYYYYYYYYYYYYYYYY"
# These variables hold the state of the
temperature = 0.0
heating_switch = False
thermostat = 0.0
def logging_func():
logging.basicConfig(
datefmt="%H:%M:%S",
format="%(asctime)s.%(msecs)03d %(message)s",
level=logging.INFO,
)
#
def on_heating_switch_changed(client, value):
""" This function is executed each time the "heating_switch" variable changes """
global heating_switch
heating_switch = value
if value:
logging.info("Heating Switched On")
else:
logging.info("Heating Switched Off")
def on_thermostat_changed(client, value):
""" This function is executed whenever the "thermostat" variable value changes.
Simply copy the Cloud value to the python variable of the same name
"""
global thermostat
thermostat = value
logging.info("thermostat = {}".format(thermostat))
def client_thread_func(client):
""" This behaviour of the client thread is defined in this function """
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("temperature")
client.register("heating_switch", value=None, on_write=on_heating_switch_changed)
client.register("thermostat", value=None, on_write=on_thermostat_changed)
client_thread_func = threading.Thread(target=client_thread_func, args=(client,), daemon=True)
client_thread_func.start()
##################################################################################################
# Execution loop - Do interesting stuff here
##################################################################################################
while True:
# Simplistic model of heating
if heating_switch:
if temperature < thermostat:
temperature += 0.1
else:
temperature -= 0.1
# Send Python temperature value to the Cloud variable of the same name
client["temperature"] = temperature
# Write back value to make graph more readable
client["thermostat"] = thermostat
logging.info("temperature = {}".format(temperature))
logging.info("thermostat = {}".format(thermostat))
time.sleep(1)
pass