diff options
-rwxr-xr-x | bin/mqtt_node_util.py | 53 | ||||
-rw-r--r-- | include/pio/libs/mqtt/homekit/mqtt/mqtt.cpp | 2 | ||||
-rw-r--r-- | include/pio/libs/mqtt/library.json | 2 | ||||
-rw-r--r-- | include/pio/libs/temphum/library.json | 2 | ||||
-rw-r--r-- | include/py/homekit/mqtt/_config.py | 9 | ||||
-rw-r--r-- | include/py/homekit/mqtt/_wrapper.py | 21 | ||||
-rw-r--r-- | include/py/homekit/mqtt/module/ota.py | 2 | ||||
-rw-r--r-- | include/py/homekit/mqtt/module/relay.py | 3 | ||||
-rw-r--r-- | include/py/homekit/pio/products.py | 10 |
9 files changed, 85 insertions, 19 deletions
diff --git a/bin/mqtt_node_util.py b/bin/mqtt_node_util.py index cf451fd..68d3bd1 100755 --- a/bin/mqtt_node_util.py +++ b/bin/mqtt_node_util.py @@ -7,12 +7,37 @@ from typing import Optional from argparse import ArgumentParser, ArgumentError from homekit.config import config -from homekit.mqtt import MqttNode, MqttWrapper, get_mqtt_modules -from homekit.mqtt import MqttNodesConfig +from homekit.mqtt import MqttNode, MqttWrapper, get_mqtt_modules, MqttNodesConfig +from homekit.mqtt.module.relay import MqttRelayModule +from homekit.mqtt.module.ota import MqttOtaModule mqtt_node: Optional[MqttNode] = None mqtt: Optional[MqttWrapper] = None +relay_module: Optional[MqttOtaModule] = None +relay_val = None + +ota_module: Optional[MqttRelayModule] = None +ota_val = False + +no_wait = False +stop_loop = False + + +def on_mqtt_connect(): + global stop_loop + + if relay_module: + relay_module.switchpower(relay_val == 1) + + if ota_val: + if not os.path.exists(arg.push_ota): + raise OSError(f'--push-ota: file \"{arg.push_ota}\" does not exists') + ota_module.push_ota(arg.push_ota, 1) + + if no_wait: + stop_loop = True + if __name__ == '__main__': nodes_config = MqttNodesConfig() @@ -25,16 +50,22 @@ if __name__ == '__main__': help='send relay state') parser.add_argument('--legacy-relay', action='store_true') parser.add_argument('--push-ota', type=str, metavar='OTA_FILENAME', - help='push OTA, receives path to firmware.bin') + help='push OTA, receives path to firmware.bin (not .elf!)') + parser.add_argument('--no-wait', action='store_true', + help='execute command and exit') config.load_app(parser=parser, no_config=True) arg = parser.parse_args() + if arg.no_wait: + no_wait = True + if arg.switch_relay is not None and 'relay' not in arg.modules: raise ArgumentError(None, '--relay is only allowed when \'relay\' module included in --modules') mqtt = MqttWrapper(randomize_client_id=True, client_id='mqtt_node_util') + mqtt.add_connect_callback(on_mqtt_connect) mqtt_node = MqttNode(node_id=arg.node_id, node_secret=nodes_config.get_node(arg.node_id)['password']) @@ -42,6 +73,8 @@ if __name__ == '__main__': # must-have modules ota_module = mqtt_node.load_module('ota') + ota_val = arg.push_ota + mqtt_node.load_module('diagnostics') if arg.modules: @@ -51,18 +84,16 @@ if __name__ == '__main__': kwargs['legacy_topics'] = True module_instance = mqtt_node.load_module(m, **kwargs) if m == 'relay' and arg.switch_relay is not None: - module_instance.switchpower(arg.switch_relay == 1) + relay_module = module_instance + relay_val = arg.switch_relay try: mqtt.connect_and_loop(loop_forever=False) - - if arg.push_ota: - if not os.path.exists(arg.push_ota): - raise OSError(f'--push-ota: file \"{arg.push_ota}\" does not exists') - ota_module.push_ota(arg.push_ota, 1) - - while True: + while not stop_loop: sleep(0.1) except KeyboardInterrupt: + pass + + finally: mqtt.disconnect() diff --git a/include/pio/libs/mqtt/homekit/mqtt/mqtt.cpp b/include/pio/libs/mqtt/homekit/mqtt/mqtt.cpp index aa769a5..83764ca 100644 --- a/include/pio/libs/mqtt/homekit/mqtt/mqtt.cpp +++ b/include/pio/libs/mqtt/homekit/mqtt/mqtt.cpp @@ -119,7 +119,7 @@ void Mqtt::reconnect() { void Mqtt::disconnect() { // TODO test how this works??? reconnectTimer.detach(); - client.disconnect(); + client.disconnect(true); } void Mqtt::loop() { diff --git a/include/pio/libs/mqtt/library.json b/include/pio/libs/mqtt/library.json index f3f2504..6238c21 100644 --- a/include/pio/libs/mqtt/library.json +++ b/include/pio/libs/mqtt/library.json @@ -1,6 +1,6 @@ { "name": "homekit_mqtt", - "version": "1.0.11", + "version": "1.0.12", "build": { "flags": "-I../../include" } diff --git a/include/pio/libs/temphum/library.json b/include/pio/libs/temphum/library.json index 329b7ca..4cf5c63 100644 --- a/include/pio/libs/temphum/library.json +++ b/include/pio/libs/temphum/library.json @@ -1,6 +1,6 @@ { "name": "homekit_temphum", - "version": "1.0.3", + "version": "1.0.4", "build": { "flags": "-I../../include" } diff --git a/include/py/homekit/mqtt/_config.py b/include/py/homekit/mqtt/_config.py index 9ba9443..4916d8a 100644 --- a/include/py/homekit/mqtt/_config.py +++ b/include/py/homekit/mqtt/_config.py @@ -105,11 +105,16 @@ class MqttNodesConfig(ConfigUnit): 'relay': { 'type': 'dict', 'schema': { - 'device_type': {'type': 'string', 'allowed': ['lamp', 'pump', 'solenoid'], 'required': True}, + 'device_type': {'type': 'string', 'allowed': ['lamp', 'pump', 'solenoid', 'cooler'], 'required': True}, 'legacy_topics': {'type': 'boolean'} } }, - 'password': {'type': 'string'} + 'password': {'type': 'string'}, + 'defines': { + 'type': 'dict', + 'keysrules': {'type': 'string'}, + 'valuesrules': {'type': ['string', 'integer']} + } } } } diff --git a/include/py/homekit/mqtt/_wrapper.py b/include/py/homekit/mqtt/_wrapper.py index 3c2774c..5fc33fe 100644 --- a/include/py/homekit/mqtt/_wrapper.py +++ b/include/py/homekit/mqtt/_wrapper.py @@ -7,6 +7,8 @@ from ..util import strgen class MqttWrapper(Mqtt): _nodes: list[MqttNode] + _connect_callbacks: list[callable] + _disconnect_callbacks: list[callable] def __init__(self, client_id: str, @@ -18,17 +20,30 @@ class MqttWrapper(Mqtt): super().__init__(clean_session=clean_session, client_id=client_id) self._nodes = [] + self._connect_callbacks = [] + self._disconnect_callbacks = [] self._topic_prefix = topic_prefix def on_connect(self, client: mqtt.Client, userdata, flags, rc): super().on_connect(client, userdata, flags, rc) for node in self._nodes: node.on_connect(self) + for f in self._connect_callbacks: + try: + f() + except Exception as e: + self._logger.exception(e) def on_disconnect(self, client: mqtt.Client, userdata, rc): super().on_disconnect(client, userdata, rc) for node in self._nodes: node.on_disconnect() + for f in self._disconnect_callbacks: + try: + f() + except Exception as e: + self._logger.exception(e) + def on_message(self, client: mqtt.Client, userdata, msg): try: @@ -40,6 +55,12 @@ class MqttWrapper(Mqtt): except Exception as e: self._logger.exception(str(e)) + def add_connect_callback(self, f: callable): + self._connect_callbacks.append(f) + + def add_disconnect_callback(self, f: callable): + self._disconnect_callbacks.append(f) + def add_node(self, node: MqttNode): self._nodes.append(node) if self._connected: diff --git a/include/py/homekit/mqtt/module/ota.py b/include/py/homekit/mqtt/module/ota.py index cd34332..2f9b216 100644 --- a/include/py/homekit/mqtt/module/ota.py +++ b/include/py/homekit/mqtt/module/ota.py @@ -74,4 +74,4 @@ class MqttOtaModule(MqttModule): if not self._initialized: self._ota_request = (filename, qos) else: - self.do_push_ota(filename, qos) + self.do_push_ota(self._mqtt_node_ref.secret, filename, qos) diff --git a/include/py/homekit/mqtt/module/relay.py b/include/py/homekit/mqtt/module/relay.py index e968031..5cbe09b 100644 --- a/include/py/homekit/mqtt/module/relay.py +++ b/include/py/homekit/mqtt/module/relay.py @@ -69,8 +69,7 @@ class MqttRelayModule(MqttModule): mqtt.subscribe_module(self._get_switch_topic(), self) mqtt.subscribe_module('relay/status', self) - def switchpower(self, - enable: bool): + def switchpower(self, enable: bool): payload = MqttPowerSwitchPayload(secret=self._mqtt_node_ref.secret, state=enable) self._mqtt_node_ref.publish(self._get_switch_topic(), diff --git a/include/py/homekit/pio/products.py b/include/py/homekit/pio/products.py index a0e7a1f..3d5034f 100644 --- a/include/py/homekit/pio/products.py +++ b/include/py/homekit/pio/products.py @@ -3,6 +3,7 @@ import logging from io import StringIO from collections import OrderedDict +from ..mqtt import MqttNodesConfig _logger = logging.getLogger(__name__) @@ -37,6 +38,13 @@ def platformio_ini(product_config: dict, debug=False, debug_network=False) -> str: node_id = build_specific_defines['CONFIG_NODE_ID'] + if node_id not in MqttNodesConfig().get_nodes().keys(): + raise ValueError(f'node id "{node_id}" is not specified in the config!') + + try: + node_defines = MqttNodesConfig().get_node(node_id)['defines'] + except KeyError: + node_defines = None # defines defines = { @@ -63,6 +71,8 @@ def platformio_ini(product_config: dict, if build_specific_defines: for k, v in build_specific_defines.items(): defines[k] = v + if node_defines: + defines = {**defines, **node_defines} defines = OrderedDict(sorted(defines.items(), key=lambda t: t[0])) # libs |