import numpy as np import json import os import serial import subprocess import threading import time from humidifier import Humidifier, HumidifierV2 from humidifier_v3 import HumidifierV3 from controller import Controller import utils from utils import start_process, send_update SERIAL_PATH = "/dev/ttyACM0" SERIAL_BAUD = 115200 SAMPLE_PERIOD = 0.5 DECIMATION_RATE = 1 try: is_mock = os.environ['MOCK'] except KeyError: is_mock = False print("controller start") start_process() if is_mock: import mock_serial s = mock_serial.MockSerial() else: s = serial.Serial(SERIAL_PATH, SERIAL_BAUD, timeout = 0.3) print("pausing for bootloader...") time.sleep(10) print("pause done") def reset_serial(): global s if not is_mock: s.close() s = serial.Serial(SERIAL_PATH, SERIAL_BAUD, timeout = 0.3) time.sleep(10) humidifier = HumidifierV3() controller = Controller([humidifier]) exiting = False # run thread to process data from process's stdout def stdout_loop(): global process, controller, humidifier, humidifier2 while not exiting: msg = utils.process.stdout.readline() if len(msg) <= 1: continue print("got message ", msg) try: msg_js = json.loads(msg) if "query_params" in msg_js: if msg_js["query_params"]: send_update({"params": { "target_lower": controller.target_lower, "target_upper": controller.target_upper, "feedforward_coeff": controller.feedforward_coeff, "manual_timeout": controller.manual_timeout, "manual_duration_s": controller.manual_duration, "manual_mode": 1.0 if controller.manual_mode else 0.0, "manual_hum_on": 1.0 if controller.manual_on else 0.0, "off_threshold_volts": humidifier.off_threshold, "on_threshold_volts": humidifier.on_threshold, "toggle_cooldown": humidifier.toggle_cooldown } }) elif "set_params" in msg_js: if type(msg_js["set_params"]) is dict: set_params = msg_js["set_params"] if "name" in set_params and "value" in set_params: name, value = set_params["name"], set_params["value"] if type(value) is float: if name == "target_lower": controller.target_lower = value elif name == "target_upper": controller.target_upper = value elif name == "feedforward_coeff": controller.feedforward_coeff = value elif name == "manual_timeout": controller.manual_timeout = value elif name == "manual_duration_s": controller.manual_duration = value elif name == "off_threshold_volts": humidifier.off_threshold = value elif name == "on_threshold_volts": humidifier.on_threshold = value elif name == "toggle_cooldown": humidifier.toggle_cooldown = value elif name == "off_threshold_volts2": humidifier2.off_threshold = value elif name == "on_threshold_volts2": humidifier2.on_threshold = value elif name == "toggle_cooldown2": humidifier2.toggle_cooldown = value elif "manual_mode" in msg_js: controller.manual_mode = msg_js["manual_mode"] if controller.manual_mode: controller.manual_timeout = time.time() + controller.manual_duration elif "manual_mode_on" in msg_js: controller.manual_on = msg_js["manual_mode_on"] except json.JSONDecodeError as e: print("received bad json ", msg) stdout_thread = threading.Thread(target=stdout_loop) stdout_thread.start() frame_num = 0 last_sample = 0 try: while True: now = time.time() if now - last_sample < SAMPLE_PERIOD: time.sleep(SAMPLE_PERIOD - (now - last_sample) + 0.001) continue last_sample = now #print("write s") s.write(b"s") s.flush() resp = s.read(120) #print("read", resp) if len(resp) == 0: reset_serial() time.sleep(5) continue parts = resp.split(b",") humidity = float(parts[0]) temp = float(parts[1]) #volts = float(parts[2]) #volts2 = float(parts[3]) #print(parts) try: controller.update(s, humidity) if frame_num == 0: #print(humidity, temp, volts) update = { "data": { "time": int(now*1000), "temp": temp, "hum": humidity, "hv": 1 if humidifier.on else 0, "hv2": 1 if humidifier.on else 0, } } send_update(update) frame_num = (frame_num + 1) % DECIMATION_RATE except Exception as e: print("pipe errored out, restarting: ", e) # restart the process I guess exiting = True utils.process.kill() time.sleep(0.1) stdout_thread.join() exiting = False start_process() stdout_thread = threading.Thread(target=stdout_loop) stdout_thread.start() finally: # kill ssh connection exiting = True utils.process.kill() stdout_thread.join()