diff options
20 files changed, 128 insertions, 67 deletions
diff --git a/platformio/common/libs/mqtt/homekit/mqtt/module.cpp b/platformio/common/libs/mqtt/homekit/mqtt/module.cpp index e78ff12..0ac7637 100644 --- a/platformio/common/libs/mqtt/homekit/mqtt/module.cpp +++ b/platformio/common/libs/mqtt/homekit/mqtt/module.cpp @@ -21,6 +21,6 @@ void MqttModule::handlePayload(Mqtt& mqtt, String& topic, uint16_t packetId, con void MqttModule::handleOnPublish(uint16_t packetId) {} -void MqttModule::handleOnDisconnect(espMqttClientTypes::DisconnectReason reason) {} +void MqttModule::onDisconnect(Mqtt& mqtt, espMqttClientTypes::DisconnectReason reason) {} } diff --git a/platformio/common/libs/mqtt/homekit/mqtt/module.h b/platformio/common/libs/mqtt/homekit/mqtt/module.h index abf7d94..0a328f3 100644 --- a/platformio/common/libs/mqtt/homekit/mqtt/module.h +++ b/platformio/common/libs/mqtt/homekit/mqtt/module.h @@ -28,24 +28,25 @@ public: , receiveOnPublish(_receiveOnPublish) , receiveOnDisconnect(_receiveOnDisconnect) {} - virtual void init(Mqtt& mqtt) = 0; virtual void tick(Mqtt& mqtt) = 0; + virtual void onConnect(Mqtt& mqtt) = 0; + virtual void onDisconnect(Mqtt& mqtt, espMqttClientTypes::DisconnectReason reason); + virtual void handlePayload(Mqtt& mqtt, String& topic, uint16_t packetId, const uint8_t *payload, size_t length, size_t index, size_t total); virtual void handleOnPublish(uint16_t packetId); - virtual void handleOnDisconnect(espMqttClientTypes::DisconnectReason reason); inline void setInitialized() { initialized = true; } - inline void unsetInitialized() { + inline void unsetInitialized() { initialized = false; } - inline short getTickInterval() { - return tickInterval; - } + inline short getTickInterval() const { + return tickInterval; + } friend class Mqtt; }; diff --git a/platformio/common/libs/mqtt/homekit/mqtt/mqtt.cpp b/platformio/common/libs/mqtt/homekit/mqtt/mqtt.cpp index 0e58833..aa769a5 100644 --- a/platformio/common/libs/mqtt/homekit/mqtt/mqtt.cpp +++ b/platformio/common/libs/mqtt/homekit/mqtt/mqtt.cpp @@ -34,7 +34,7 @@ Mqtt::Mqtt() { for (auto* module: modules) { if (!module->initialized) { - module->init(*this); + module->onConnect(*this); module->setInitialized(); } } @@ -50,9 +50,7 @@ Mqtt::Mqtt() { #endif for (auto* module: modules) { - if (module->receiveOnDisconnect) { - module->handleOnDisconnect(reason); - } + module->onDisconnect(*this, reason); module->unsetInitialized(); } @@ -151,7 +149,7 @@ uint16_t Mqtt::subscribe(const String& topic, uint8_t qos) { void Mqtt::addModule(MqttModule* module) { modules.emplace_back(module); if (connected) { - module->init(*this); + module->onConnect(*this); module->setInitialized(); } } diff --git a/platformio/common/libs/mqtt/library.json b/platformio/common/libs/mqtt/library.json index 2712fb8..f3f2504 100644 --- a/platformio/common/libs/mqtt/library.json +++ b/platformio/common/libs/mqtt/library.json @@ -1,6 +1,6 @@ { "name": "homekit_mqtt", - "version": "1.0.10", + "version": "1.0.11", "build": { "flags": "-I../../include" } diff --git a/platformio/common/libs/mqtt_module_diagnostics/homekit/mqtt/module/diagnostics.cpp b/platformio/common/libs/mqtt_module_diagnostics/homekit/mqtt/module/diagnostics.cpp index d36a7e9..e0f797e 100644 --- a/platformio/common/libs/mqtt_module_diagnostics/homekit/mqtt/module/diagnostics.cpp +++ b/platformio/common/libs/mqtt_module_diagnostics/homekit/mqtt/module/diagnostics.cpp @@ -7,12 +7,21 @@ namespace homekit::mqtt { static const char TOPIC_DIAGNOSTICS[] = "diag"; static const char TOPIC_INITIAL_DIAGNOSTICS[] = "d1ag"; -void MqttDiagnosticsModule::init(Mqtt& mqtt) {} +void MqttDiagnosticsModule::onConnect(Mqtt &mqtt) { + sendDiagnostics(mqtt); +} + +void MqttDiagnosticsModule::onDisconnect(Mqtt &mqtt, espMqttClientTypes::DisconnectReason reason) { + initialSent = false; +} void MqttDiagnosticsModule::tick(Mqtt& mqtt) { if (!tickElapsed()) return; + sendDiagnostics(mqtt); +} +void MqttDiagnosticsModule::sendDiagnostics(Mqtt& mqtt) { auto cfg = config::read(); if (!initialSent) { diff --git a/platformio/common/libs/mqtt_module_diagnostics/homekit/mqtt/module/diagnostics.h b/platformio/common/libs/mqtt_module_diagnostics/homekit/mqtt/module/diagnostics.h index 055c179..bb7a81a 100644 --- a/platformio/common/libs/mqtt_module_diagnostics/homekit/mqtt/module/diagnostics.h +++ b/platformio/common/libs/mqtt_module_diagnostics/homekit/mqtt/module/diagnostics.h @@ -32,12 +32,15 @@ class MqttDiagnosticsModule: public MqttModule { private: bool initialSent; + void sendDiagnostics(Mqtt& mqtt); + public: MqttDiagnosticsModule() : MqttModule(30) , initialSent(false) {} - void init(Mqtt& mqtt) override; + void onConnect(Mqtt& mqtt) override; + void onDisconnect(Mqtt& mqtt, espMqttClientTypes::DisconnectReason reason) override; void tick(Mqtt& mqtt) override; }; diff --git a/platformio/common/libs/mqtt_module_diagnostics/library.json b/platformio/common/libs/mqtt_module_diagnostics/library.json index 8df306d..a3d3244 100644 --- a/platformio/common/libs/mqtt_module_diagnostics/library.json +++ b/platformio/common/libs/mqtt_module_diagnostics/library.json @@ -1,10 +1,10 @@ { "name": "homekit_mqtt_module_diagnostics", - "version": "1.0.1", + "version": "1.0.2", "build": { "flags": "-I../../include" }, "dependencies": { - "homekit_mqtt": "file://../common/libs/mqtt" + "homekit_mqtt": "file://../common/libs/mqtt" } } diff --git a/platformio/common/libs/mqtt_module_ota/homekit/mqtt/module/ota.cpp b/platformio/common/libs/mqtt_module_ota/homekit/mqtt/module/ota.cpp index 2f5f814..4e976cd 100644 --- a/platformio/common/libs/mqtt_module_ota/homekit/mqtt/module/ota.cpp +++ b/platformio/common/libs/mqtt_module_ota/homekit/mqtt/module/ota.cpp @@ -12,7 +12,7 @@ using homekit::led::mcu_led; static const char TOPIC_OTA[] = "ota"; static const char TOPIC_OTA_RESPONSE[] = "otares"; -void MqttOtaModule::init(Mqtt& mqtt) { +void MqttOtaModule::onConnect(Mqtt& mqtt) { String topic(TOPIC_OTA); mqtt.subscribeModule(topic, this); } @@ -140,17 +140,15 @@ uint16_t MqttOtaModule::sendResponse(Mqtt& mqtt, OtaResult status, uint8_t error return mqtt.publish(TOPIC_OTA_RESPONSE, reinterpret_cast<uint8_t*>(&resp), sizeof(resp)); } -void MqttOtaModule::handleOnDisconnect(espMqttClientTypes::DisconnectReason reason) { - if (ota.started()) { +void MqttOtaModule::onDisconnect(Mqtt& mqtt, espMqttClientTypes::DisconnectReason reason) { + if (ota.readyToRestart) { + restartTimer.once(1, restart); + } else if (ota.started()) { PRINTLN("mqtt: update was in progress, canceling.."); ota.clean(); Update.end(); Update.clearError(); } - - if (ota.readyToRestart) { - restartTimer.once(1, restart); - } } void MqttOtaModule::handleOnPublish(uint16_t packetId) { diff --git a/platformio/common/libs/mqtt_module_ota/homekit/mqtt/module/ota.h b/platformio/common/libs/mqtt_module_ota/homekit/mqtt/module/ota.h index 53613c3..df4f7ce 100644 --- a/platformio/common/libs/mqtt_module_ota/homekit/mqtt/module/ota.h +++ b/platformio/common/libs/mqtt_module_ota/homekit/mqtt/module/ota.h @@ -57,11 +57,14 @@ private: public: MqttOtaModule() : MqttModule(0, true, true) {} - void init(Mqtt& mqtt) override; + void onConnect(Mqtt& mqtt) override; + void onDisconnect(Mqtt& mqtt, espMqttClientTypes::DisconnectReason reason) override; + void tick(Mqtt& mqtt) override; + void handlePayload(Mqtt& mqtt, String& topic, uint16_t packetId, const uint8_t *payload, size_t length, size_t index, size_t total) override; void handleOnPublish(uint16_t packetId) override; - void handleOnDisconnect(espMqttClientTypes::DisconnectReason reason) override; + inline bool isReadyToRestart() const { return ota.readyToRestart; } diff --git a/platformio/common/libs/mqtt_module_ota/library.json b/platformio/common/libs/mqtt_module_ota/library.json index 30db7d2..4f40a47 100644 --- a/platformio/common/libs/mqtt_module_ota/library.json +++ b/platformio/common/libs/mqtt_module_ota/library.json @@ -1,11 +1,11 @@ { "name": "homekit_mqtt_module_ota", - "version": "1.0.2", + "version": "1.0.5", "build": { "flags": "-I../../include" }, "dependencies": { "homekit_led": "file://../common/libs/led", - "homekit_mqtt": "file://../common/libs/mqtt" + "homekit_mqtt": "file://../common/libs/mqtt" } } diff --git a/platformio/common/libs/mqtt_module_relay/homekit/mqtt/module/relay.cpp b/platformio/common/libs/mqtt_module_relay/homekit/mqtt/module/relay.cpp index ab40727..90c57f9 100644 --- a/platformio/common/libs/mqtt_module_relay/homekit/mqtt/module/relay.cpp +++ b/platformio/common/libs/mqtt_module_relay/homekit/mqtt/module/relay.cpp @@ -5,19 +5,28 @@ namespace homekit::mqtt { static const char TOPIC_RELAY_SWITCH[] = "relay/switch"; +static const char TOPIC_RELAY_STATUS[] = "relay/status"; -void MqttRelayModule::init(Mqtt &mqtt) { - String topic(TOPIC_RELAY_SWITCH); - mqtt.subscribeModule(topic, this, 1); +void MqttRelayModule::onConnect(Mqtt &mqtt) { + String topic(TOPIC_RELAY_SWITCH); + mqtt.subscribeModule(topic, this, 1); +} + +void MqttRelayModule::onDisconnect(Mqtt &mqtt, espMqttClientTypes::DisconnectReason reason) { +#ifdef CONFIG_RELAY_OFF_ON_DISCONNECT + if (relay::state()) { + relay::off(); + } +#endif } void MqttRelayModule::tick(homekit::mqtt::Mqtt& mqtt) {} void MqttRelayModule::handlePayload(Mqtt& mqtt, String& topic, uint16_t packetId, const uint8_t *payload, size_t length, size_t index, size_t total) { - if (topic != TOPIC_RELAY_SWITCH) - return; + if (topic != TOPIC_RELAY_SWITCH) + return; - if (length != sizeof(MqttRelaySwitchPayload)) { + if (length != sizeof(MqttRelaySwitchPayload)) { PRINTF("error: size of payload (%ul) does not match expected (%ul)\n", length, sizeof(MqttRelaySwitchPayload)); return; @@ -29,6 +38,8 @@ void MqttRelayModule::handlePayload(Mqtt& mqtt, String& topic, uint16_t packetId return; } + MqttRelayStatusPayload resp{}; + if (pd->state == 1) { PRINTLN("mqtt: turning relay on"); relay::on(); @@ -38,6 +49,10 @@ void MqttRelayModule::handlePayload(Mqtt& mqtt, String& topic, uint16_t packetId } else { PRINTLN("error: unexpected state value"); } + + resp.opened = relay::state(); + mqtt.publish(TOPIC_RELAY_STATUS, reinterpret_cast<uint8_t*>(&resp), sizeof(resp)); } } + diff --git a/platformio/common/libs/mqtt_module_relay/homekit/mqtt/module/relay.h b/platformio/common/libs/mqtt_module_relay/homekit/mqtt/module/relay.h index 1e80987..e245527 100644 --- a/platformio/common/libs/mqtt_module_relay/homekit/mqtt/module/relay.h +++ b/platformio/common/libs/mqtt_module_relay/homekit/mqtt/module/relay.h @@ -17,9 +17,10 @@ struct MqttRelayStatusPayload { class MqttRelayModule : public MqttModule { public: MqttRelayModule() : MqttModule(0) {} - void init(Mqtt& mqtt) override; + void onConnect(Mqtt& mqtt) override; + void onDisconnect(Mqtt& mqtt, espMqttClientTypes::DisconnectReason reason) override; void tick(Mqtt& mqtt) override; - void handlePayload(Mqtt& mqtt, String& topic, uint16_t packetId, const uint8_t *payload, size_t length, size_t index, size_t total) override; + void handlePayload(Mqtt& mqtt, String& topic, uint16_t packetId, const uint8_t *payload, size_t length, size_t index, size_t total) override; }; } diff --git a/platformio/common/libs/mqtt_module_relay/library.json b/platformio/common/libs/mqtt_module_relay/library.json index 431bb49..6cbbfb0 100644 --- a/platformio/common/libs/mqtt_module_relay/library.json +++ b/platformio/common/libs/mqtt_module_relay/library.json @@ -1,6 +1,6 @@ { "name": "homekit_mqtt_module_relay", - "version": "1.0.4", + "version": "1.0.5", "build": { "flags": "-I../../include" }, diff --git a/platformio/common/libs/mqtt_module_temphum/homekit/mqtt/module/temphum.cpp b/platformio/common/libs/mqtt_module_temphum/homekit/mqtt/module/temphum.cpp index 82f1d74..409f38f 100644 --- a/platformio/common/libs/mqtt_module_temphum/homekit/mqtt/module/temphum.cpp +++ b/platformio/common/libs/mqtt_module_temphum/homekit/mqtt/module/temphum.cpp @@ -4,7 +4,7 @@ namespace homekit::mqtt { static const char TOPIC_TEMPHUM_DATA[] = "temphum/data"; -void MqttTemphumModule::init(Mqtt &mqtt) {} +void MqttTemphumModule::onConnect(Mqtt &mqtt) {} void MqttTemphumModule::tick(homekit::mqtt::Mqtt& mqtt) { if (!tickElapsed()) diff --git a/platformio/common/libs/mqtt_module_temphum/homekit/mqtt/module/temphum.h b/platformio/common/libs/mqtt_module_temphum/homekit/mqtt/module/temphum.h index 5c41cef..7b28afc 100644 --- a/platformio/common/libs/mqtt_module_temphum/homekit/mqtt/module/temphum.h +++ b/platformio/common/libs/mqtt_module_temphum/homekit/mqtt/module/temphum.h @@ -19,7 +19,7 @@ private: public: MqttTemphumModule(temphum::Sensor* _sensor) : MqttModule(10), sensor(_sensor) {} - void init(Mqtt& mqtt) override; + void onConnect(Mqtt& mqtt) override; void tick(Mqtt& mqtt) override; }; diff --git a/platformio/common/libs/mqtt_module_temphum/library.json b/platformio/common/libs/mqtt_module_temphum/library.json index 9bb8cf1..068debd 100644 --- a/platformio/common/libs/mqtt_module_temphum/library.json +++ b/platformio/common/libs/mqtt_module_temphum/library.json @@ -1,11 +1,11 @@ { "name": "homekit_mqtt_module_temphum", - "version": "1.0.9", + "version": "1.0.10", "build": { "flags": "-I../../include" }, "dependencies": { - "homekit_mqtt": "file://../common/libs/mqtt", + "homekit_mqtt": "file://../common/libs/mqtt", "homekit_temphum": "file://../common/libs/temphum" } } diff --git a/platformio/temphum_relayctl/src/main.cpp b/platformio/temphum_relayctl/src/main.cpp index 0b05316..7f0945e 100644 --- a/platformio/temphum_relayctl/src/main.cpp +++ b/platformio/temphum_relayctl/src/main.cpp @@ -27,6 +27,7 @@ void setup() { main::setup(); relay::init(); + relay::off(); #if CONFIG_MODULE == HOMEKIT_SI7021 sensor = new temphum::Si7021(); diff --git a/src/home/mqtt/_node.py b/src/home/mqtt/_node.py index 9e39911..f34da0c 100644 --- a/src/home/mqtt/_node.py +++ b/src/home/mqtt/_node.py @@ -1,7 +1,7 @@ import paho.mqtt.client as mqtt from .mqtt import MqttBase -from typing import List +from typing import List, Optional from ._module import MqttModule from ._payload import MqttPayload @@ -92,7 +92,10 @@ class MqttNode(MqttBase): self._module_subscriptions[topic] = module self._client.subscribe(f'hk/{self._node_id}/{topic}', qos) - def publish(self, topic: str, payload: bytes, qos: int = 1): + def publish(self, + topic: str, + payload: bytes, + qos: int = 1): self._client.publish(f'hk/{self._node_id}/{topic}', payload, qos) self._client.loop_write() diff --git a/src/home/mqtt/module/ota.py b/src/home/mqtt/module/ota.py index 86d6839..5a1a309 100644 --- a/src/home/mqtt/module/ota.py +++ b/src/home/mqtt/module/ota.py @@ -41,27 +41,41 @@ class OtaPayload(MqttPayload): class MqttOtaModule(MqttModule): + _ota_request: Optional[tuple[str, str, int]] + _mqtt_ref: Optional[MqttNode] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._ota_request = None + self._mqtt_ref = None + def init(self, mqtt: MqttNode): mqtt.subscribe_module("otares", self) + self._mqtt_ref = mqtt + + if self._ota_request is not None: + secret, filename, qos = self._ota_request + self._ota_request = None + self.do_push_ota(secret, filename, qos) + def handle_payload(self, mqtt: MqttNode, topic: str, payload: bytes) -> Optional[MqttPayload]: if topic == 'otares': message = OtaResultPayload.unpack(payload) self._logger.debug(message) return message - # def push_ota(self, - # node_id, - # filename: str, - # publish_callback: callable, - # qos: int): - # device = next(d for d in self._devices if d.id == device_id) - # assert device.secret is not None, 'device secret not specified' - # - # self._ota_publish_callback = publish_callback - # payload = OtaPayload(secret=device.secret, filename=filename) - # publish_result = self._client.publish(f'hk/{device.id}/{self.TOPIC_LEAF}/admin/ota', - # payload=payload.pack(), - # qos=qos) - # self._ota_mid = publish_result.mid - # self._client.loop_write()
\ No newline at end of file + def do_push_ota(self, secret: str, filename: str, qos: int): + payload = OtaPayload(secret=secret, filename=filename) + self._mqtt_ref.publish('ota', + payload=payload.pack(), + qos=qos) + + def push_ota(self, + secret: str, + filename: str, + qos: int): + if not self._initialized: + self._ota_request = (secret, filename, qos) + else: + self.do_push_ota(secret, filename, qos)
\ No newline at end of file diff --git a/src/mqtt_node_util.py b/src/mqtt_node_util.py index 674b60c..0352c8f 100755 --- a/src/mqtt_node_util.py +++ b/src/mqtt_node_util.py @@ -1,4 +1,6 @@ #!/usr/bin/env python3 +import os.path +from time import sleep from typing import Optional from argparse import ArgumentParser, ArgumentError @@ -25,34 +27,47 @@ if __name__ == '__main__': help='mqtt modules to include') parser.add_argument('--switch-relay', choices=[0, 1], type=int, help='send relay state') - parser.add_argument('--switch-relay-secret', type=str, - help='secret password to switch relay') + parser.add_argument('--push-ota', type=str, metavar='OTA_FILENAME', + help='push ota, argument receives filename') + parser.add_argument('--node-secret', type=str, + help='node admin password') config.load('mqtt_util', parser=parser) arg = parser.parse_args() - if (arg.switch_relay is not None or arg.switch_relay_secret is not None) and 'relay' not in arg.modules: + if (arg.switch_relay is not None or arg.node_secret is not None) and 'relay' not in arg.modules: raise ArgumentError(None, '--relay is only allowed when \'relay\' module included in --modules') - if (arg.switch_relay is not None and arg.switch_relay_secret is None) or (arg.switch_relay is None and arg.switch_relay_secret is not None): - raise ArgumentError(None, 'both --switch-relay and --switch-relay-secret are required') - mqtt = MqttNode(node_id=arg.node_id) # must-have modules - add_module('ota') + ota_module = add_module('ota') add_module('diagnostics') if arg.modules: for m in arg.modules: module_instance = add_module(m) if m == 'relay' and arg.switch_relay is not None: + if not arg.node_secret: + raise ArgumentError(None, '--switch-relay requires --node-secret') module_instance.switchpower(mqtt, arg.switch_relay == 1, - arg.switch_relay_secret) + arg.node_secret) mqtt.configure_tls() try: - mqtt.connect_and_loop() + 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') + if not arg.node_secret: + raise ArgumentError(None, 'pushing OTA requires --node-secret') + + ota_module.push_ota(arg.node_secret, arg.push_ota, 1) + + while True: + sleep(0.1) + except KeyboardInterrupt: mqtt.disconnect() |