mqtt: various fixes

This commit is contained in:
Evgeny Zinoviev 2023-09-24 02:49:12 +03:00
parent bdbb296697
commit 3623e770b6
5 changed files with 67 additions and 13 deletions

View File

@ -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()
@ -26,15 +51,21 @@ if __name__ == '__main__':
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')
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()

View File

@ -105,7 +105,7 @@ 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'}
}
},

View File

@ -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:

View File

@ -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(),

View File

@ -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,8 @@ 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!')
# defines
defines = {