]> mj.ucw.cz Git - home-hw.git/commitdiff
Bocktherm: Refactor
authorMartin Mares <mj@ucw.cz>
Tue, 31 Dec 2024 12:53:47 +0000 (13:53 +0100)
committerMartin Mares <mj@ucw.cz>
Tue, 31 Dec 2024 12:53:47 +0000 (13:53 +0100)
bocktherm/burrow-bocktherm.py

index 4e28182a20ff6f5900e2e4bd6c445b63f88188e3..9be09fd8edc394d1f80eb83cff29b81c83b07fe4 100755 (executable)
@@ -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)