multiple fixes
This commit is contained in:
parent
940d88d301
commit
1835e0a7b0
@ -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) {}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "homekit_mqtt",
|
||||
"version": "1.0.10",
|
||||
"version": "1.0.11",
|
||||
"build": {
|
||||
"flags": "-I../../include"
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "homekit_mqtt_module_relay",
|
||||
"version": "1.0.4",
|
||||
"version": "1.0.5",
|
||||
"build": {
|
||||
"flags": "-I../../include"
|
||||
},
|
||||
|
@ -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())
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ void setup() {
|
||||
main::setup();
|
||||
|
||||
relay::init();
|
||||
relay::off();
|
||||
|
||||
#if CONFIG_MODULE == HOMEKIT_SI7021
|
||||
sensor = new temphum::Si7021();
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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()
|
||||
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)
|
@ -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()
|
||||
|
Loading…
x
Reference in New Issue
Block a user