From 9d597476247e908452ff601e480e168ebbe298f0 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Tue, 31 Dec 2024 13:53:47 +0100 Subject: [PATCH] Bocktherm: Refactor --- bocktherm/burrow-bocktherm.py | 141 +++++++++++++++++----------------- 1 file changed, 70 insertions(+), 71 deletions(-) diff --git a/bocktherm/burrow-bocktherm.py b/bocktherm/burrow-bocktherm.py index 4e28182..9be09fd 100755 --- a/bocktherm/burrow-bocktherm.py +++ b/bocktherm/burrow-bocktherm.py @@ -12,9 +12,10 @@ import time class Thermostat: connected = False ident = "" - in_topic = "" - out_topic = "" - # mqc = mqtt client + bock_mqtt: 'BockMQTT' + + def __init__(self, config): + self.ident = str(config['uniqueIdentifier']).rjust(6, '0') def process_message(self, m): if len(m) > 6 and m[0] == 0x30 and m[1] == 0x0a: @@ -55,47 +56,69 @@ class Thermostat: logger.info(f'Temp: desired={t_desired} actual={t_actual} analog={analog} manual={t_manual} auto={t_auto}') -def on_connect(mqc, therm, flags, rc): - if rc == 0: - logger.info('MQTT connected') - therm.connected = True - mqc.subscribe(therm.in_topic, 0) - mqc.subscribe(therm.out_topic, 0) - else: - logger.warning(f'MQTT connect failed: rc={rc}') - - -def on_disconnect(mqc, therm, rc): - logger.info(f'MQTT disconnected: rc={rc}') - therm.connected = False - - -def on_message(mqc, therm, msg): - logger.debug(f'<< {msg.topic} ' + msg.payload.hex(' ')) - - if msg.topic == therm.out_topic: - err = therm.process_message(msg.payload) - if err: - logger.warning(f'Cannot parse message ({err}): {msg.payload.hex(" ")}') - - -def on_subscribe(mqc, therm, mid, granted_qos): - logger.debug(f'MQTT subscribed: mid={mid}, granted={granted_qos}') - - -def on_log(mqc, therm, level, string): - if level == mqtt.MQTT_LOG_DEBUG: - logger.debug(f'MQTT: {string}') - elif level == mqtt.MQTT_LOG_WARNING: - logger.warning(f'MQTT: {string}') - elif level == mqtt.MQTT_LOG_ERROR: - logger.error(f'MQTT: {string}') - else: - logger.info(f'MQTT: {string}') +class BockMQTT: + + def __init__(self, therm: Thermostat): + self.therm = therm + self.in_topic = f'TSWIFI/I/{therm.ident}' + self.out_topic = f'TSWIFI/O/{therm.ident}' + self.connected = False + + mqc = mqtt.Client(transport='websockets', client_id=self.gen_client_id()) + self.mqc = mqc + mqc.on_message = self.on_message + mqc.on_connect = self.on_connect + mqc.on_disconnect = self.on_disconnect + mqc.on_subscribe = self.on_subscribe + mqc.on_log = self.on_log + + mqc.ws_set_options("/wss") + mqc.tls_set_context() + mqc.username_pw_set(f'TSWIFI_{therm.ident}', config['mqttPass']) + mqc.connect("mqtt.elbock.cz", 8081, 60) + mqc.loop_start() + + def on_connect(self, mqc, userdata, flags, rc): + if rc == 0: + logger.info('MQTT connected') + self.connected = True + mqc.subscribe(self.in_topic, 0) + mqc.subscribe(self.out_topic, 0) + else: + logger.warning(f'MQTT connect failed: rc={rc}') + + def on_disconnect(self, mqc, userdata, rc): + logger.info(f'MQTT disconnected: rc={rc}') + self.connected = False + + def on_message(self, mqc, userdata, msg): + logger.debug(f'<< {msg.topic} ' + msg.payload.hex(' ')) + + if msg.topic == self.out_topic: + err = self.therm.process_message(msg.payload) + if err: + logger.warning(f'Cannot parse message ({err}): {msg.payload.hex(" ")}') + + def on_subscribe(self, mqc, userdata, mid, granted_qos): + logger.debug(f'MQTT subscribed: mid={mid}') + + def on_log(self, mqc, userdata, level, string): + if level == mqtt.MQTT_LOG_DEBUG: + logger.debug(f'MQTT: {string}') + elif level == mqtt.MQTT_LOG_WARNING: + logger.warning(f'MQTT: {string}') + elif level == mqtt.MQTT_LOG_ERROR: + logger.error(f'MQTT: {string}') + else: + logger.info(f'MQTT: {string}') + def gen_client_id(self): + return 'APP_' + "".join(["abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRTUVWXYZ1234567890"[random.randrange(60)] for _ in range(18)]) -def gen_client_id(): - return 'APP_' + "".join(["abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRTUVWXYZ1234567890"[random.randrange(60)] for _ in range(18)]) + def send_request(self): + # Request message sent by the web interface, but with a random message ID + request = b'\x10\x0a' + random.randbytes(2) + b'\x00\x24\x20\x01\x00\x00\x20\x02\x00\x00\x20\x03\x00\x00\x20\x06\x00\x00\x20\x07\x00\x00\x20\x05\x00\x00\x20\x09\x00\x00\x20\x0b\x00\x00\x20\x0c\x00\x00' + self.mqc.publish('TSWIFI/I/024299', request) def read_device_config(config_file, device_name): @@ -110,30 +133,6 @@ def read_device_config(config_file, device_name): sys.exit(1) -def init_therm(config): - therm = Thermostat() - therm.ident = str(config['uniqueIdentifier']).rjust(6, '0') - therm.in_topic = f'TSWIFI/I/{therm.ident}' - therm.out_topic = f'TSWIFI/O/{therm.ident}' - - mqc = mqtt.Client(transport='websockets', client_id=gen_client_id(), userdata=therm) - mqc.on_message = on_message - mqc.on_connect = on_connect - mqc.on_disconnect = on_disconnect - mqc.on_subscribe = on_subscribe - mqc.on_log = on_log - - mqc.ws_set_options("/wss") - mqc.tls_set_context() - mqc.username_pw_set(f'TSWIFI_{therm.ident}', config['mqttPass']) - mqc.connect("mqtt.elbock.cz", 8081, 60) - - mqc.loop_start() - - therm.mqc = mqc - return therm - - parser = argparse.ArgumentParser(description='A daemon watching Elektrobock thermostats') parser.add_argument('--config', required=True, type=str, help='Configuration file from the web app (devices.json)') parser.add_argument('--device', required=True, type=str, help='Device name as in the configuration file') @@ -152,15 +151,15 @@ logging.basicConfig( logger = logging.getLogger('bocktherm') -therm = init_therm(config) +therm = Thermostat(config) +therm.bock_mqtt = BockMQTT(therm) + time.sleep(1) while True: - if therm.connected: + if therm.bock_mqtt.connected: logger.debug('Sending request') - # Request message sent by the web interface, but with a random message ID - request = b'\x10\x0a' + random.randbytes(2) + b'\x00\x24\x20\x01\x00\x00\x20\x02\x00\x00\x20\x03\x00\x00\x20\x06\x00\x00\x20\x07\x00\x00\x20\x05\x00\x00\x20\x09\x00\x00\x20\x0b\x00\x00\x20\x0c\x00\x00' - therm.mqc.publish('TSWIFI/I/024299', request) + therm.bock_mqtt.send_request() time.sleep(60) else: time.sleep(5) -- 2.39.5