aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeny Zinoviev <me@ch1p.io>2023-05-31 22:27:46 +0300
committerEvgeny Zinoviev <me@ch1p.io>2023-05-31 22:27:46 +0300
commit52db06e0c81bf7f5ec75da40250ddb700d333db2 (patch)
tree730c0db16580a42487cf46b60cdb346571beee3b
parentc976495222858c4921454c9294ff73794ae56277 (diff)
save
-rw-r--r--platformio/common/libs/main/homekit/main.cpp21
-rw-r--r--platformio/common/libs/main/homekit/main.h4
-rw-r--r--platformio/common/libs/main/library.json2
-rw-r--r--src/home/mqtt/relay.py59
-rwxr-xr-xsrc/pio_ini.py10
-rwxr-xr-xtest/mqtt_relay_server_util.py18
-rwxr-xr-xtest/mqtt_relay_util.py39
7 files changed, 150 insertions, 3 deletions
diff --git a/platformio/common/libs/main/homekit/main.cpp b/platformio/common/libs/main/homekit/main.cpp
index fd08925..816c764 100644
--- a/platformio/common/libs/main/homekit/main.cpp
+++ b/platformio/common/libs/main/homekit/main.cpp
@@ -6,7 +6,12 @@
namespace homekit::main {
+#ifndef CONFIG_TARGET_ESP01
+#ifndef CONFIG_NO_RECOVERY
enum WorkingMode working_mode = WorkingMode::NORMAL;
+#endif
+#endif
+
static const uint16_t recovery_boot_detection_ms = 2000;
static const uint8_t recovery_boot_delay_ms = 100;
@@ -22,8 +27,10 @@ static StopWatch blinkStopWatch;
#endif
#ifndef CONFIG_TARGET_ESP01
+#ifndef CONFIG_NO_RECOVERY
static DNSServer* dnsServer = nullptr;
#endif
+#endif
static void onWifiConnected(const WiFiEventStationModeGotIP& event);
static void onWifiDisconnected(const WiFiEventStationModeDisconnected& event);
@@ -45,6 +52,7 @@ static void wifiConnect() {
}
#ifndef CONFIG_TARGET_ESP01
+#ifndef CONFIG_NO_RECOVERY
static void wifiHotspot() {
led::mcu_led->on();
@@ -71,13 +79,16 @@ static void waitForRecoveryPress() {
}
}
#endif
+#endif
void setup() {
WiFi.disconnect();
+#ifndef CONFIG_NO_RECOVERY
#ifndef CONFIG_TARGET_ESP01
homekit::main::waitForRecoveryPress();
#endif
+#endif
#ifdef DEBUG
Serial.begin(115200);
@@ -95,6 +106,7 @@ void setup() {
}
#ifndef CONFIG_TARGET_ESP01
+#ifndef CONFIG_NO_RECOVERY
switch (working_mode) {
case WorkingMode::RECOVERY:
wifiHotspot();
@@ -102,19 +114,24 @@ void setup() {
case WorkingMode::NORMAL:
#endif
+#endif
wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnected);
wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnected);
wifiConnect();
+#ifndef CONFIG_NO_RECOVERY
#ifndef CONFIG_TARGET_ESP01
break;
}
#endif
+#endif
}
void loop(LoopConfig* config) {
+#ifndef CONFIG_NO_RECOVERY
#ifndef CONFIG_TARGET_ESP01
if (working_mode == WorkingMode::NORMAL) {
#endif
+#endif
if (wifi_state == WiFiConnectionState::WAITING) {
PRINT(".");
led::mcu_led->blink(2, 50);
@@ -166,6 +183,7 @@ void loop(LoopConfig* config) {
}
#endif
}
+#ifndef CONFIG_NO_RECOVERY
#ifndef CONFIG_TARGET_ESP01
} else {
if (dnsServer != nullptr)
@@ -176,6 +194,7 @@ void loop(LoopConfig* config) {
httpServer->loop();
}
#endif
+#endif
}
static void onWifiConnected(const WiFiEventStationModeGotIP& event) {
@@ -191,4 +210,4 @@ static void onWifiDisconnected(const WiFiEventStationModeDisconnected& event) {
wifiTimer.once(2, wifiConnect);
}
-} \ No newline at end of file
+}
diff --git a/platformio/common/libs/main/homekit/main.h b/platformio/common/libs/main/homekit/main.h
index a503dd0..78a0695 100644
--- a/platformio/common/libs/main/homekit/main.h
+++ b/platformio/common/libs/main/homekit/main.h
@@ -10,8 +10,10 @@
#include <homekit/config.h>
#include <homekit/logging.h>
#ifndef CONFIG_TARGET_ESP01
+#ifndef CONFIG_NO_RECOVERY
#include <homekit/http_server.h>
#endif
+#endif
#include <homekit/wifi.h>
#include <homekit/mqtt/mqtt.h>
@@ -20,6 +22,7 @@
namespace homekit::main {
#ifndef CONFIG_TARGET_ESP01
+#ifndef CONFIG_NO_RECOVERY
enum class WorkingMode {
RECOVERY, // AP mode, http server with configuration
NORMAL, // MQTT client
@@ -27,6 +30,7 @@ enum class WorkingMode {
extern enum WorkingMode working_mode;
#endif
+#endif
enum class WiFiConnectionState {
WAITING = 0,
diff --git a/platformio/common/libs/main/library.json b/platformio/common/libs/main/library.json
index 04eedab..728d4f8 100644
--- a/platformio/common/libs/main/library.json
+++ b/platformio/common/libs/main/library.json
@@ -1,6 +1,6 @@
{
"name": "homekit_main",
- "version": "1.0.8",
+ "version": "1.0.10",
"build": {
"flags": "-I../../include"
},
diff --git a/src/home/mqtt/relay.py b/src/home/mqtt/relay.py
new file mode 100644
index 0000000..cf657f7
--- /dev/null
+++ b/src/home/mqtt/relay.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python3
+import paho.mqtt.client as mqtt
+import re
+import logging
+
+from .mqtt import MQTTBase
+
+
+class MQTTRelayClient(MQTTBase):
+ _home_id: str
+
+ def __init__(self, home_id: str):
+ super().__init__(clean_session=True)
+ self._home_id = home_id
+
+ def on_connect(self, client: mqtt.Client, userdata, flags, rc):
+ super().on_connect(client, userdata, flags, rc)
+
+ topic = f'home/{self._home_id}/#'
+ self._logger.info(f"subscribing to {topic}")
+
+ client.subscribe(topic, qos=1)
+
+ def on_message(self, client: mqtt.Client, userdata, msg):
+ try:
+ match = re.match(r'^home/(.*?)/relay/(stat|power)(?:/(.+))?$', msg.topic)
+ self._logger.info(f'topic: {msg.topic}')
+ if not match:
+ return
+
+ name = match.group(1)
+ subtopic = match.group(2)
+
+ if name != self._home_id:
+ return
+
+ if subtopic == 'stat':
+ stat_name, stat_value = match.group(3).split('/')
+ self._logger.info(f'stat: {stat_name} = {stat_value}')
+
+ except Exception as e:
+ self._logger.exception(str(e))
+
+
+class MQTTRelayController(MQTTBase):
+ _home_id: str
+
+ def __init__(self, home_id: str):
+ super().__init__(clean_session=True)
+ self._home_id = home_id
+
+ def set_power(self, enable: bool):
+ self._client.publish(f'home/{self._home_id}/relay/power',
+ payload=int(enable),
+ qos=1)
+ self._client.loop_write()
+
+ def send_stat(self, stat: dict):
+ pass
diff --git a/src/pio_ini.py b/src/pio_ini.py
index 19dd707..920c3e5 100755
--- a/src/pio_ini.py
+++ b/src/pio_ini.py
@@ -54,12 +54,17 @@ def bsd_parser(product_config: dict,
arg_kwargs['type'] = int
elif kwargs['type'] == 'int':
arg_kwargs['type'] = int
+ elif kwargs['type'] == 'bool':
+ arg_kwargs['action'] = 'store_true'
+ arg_kwargs['required'] = False
else:
raise TypeError(f'unsupported type {kwargs["type"]} for define {define_name}')
else:
arg_kwargs['action'] = 'store_true'
- parser.add_argument(f'--{define_name}', required=True, **arg_kwargs)
+ if 'required' not in arg_kwargs:
+ arg_kwargs['required'] = True
+ parser.add_argument(f'--{define_name}', **arg_kwargs)
bsd_walk(product_config, f)
@@ -76,6 +81,9 @@ def bsd_get(product_config: dict,
enums.append(f'CONFIG_{define_name}')
defines[f'CONFIG_{define_name}'] = f'HOMEKIT_{attr_value.upper()}'
return
+ if kwargs['type'] == 'bool':
+ defines[f'CONFIG_{define_name}'] = True
+ return
defines[f'CONFIG_{define_name}'] = str(attr_value)
bsd_walk(product_config, f)
return defines, enums
diff --git a/test/mqtt_relay_server_util.py b/test/mqtt_relay_server_util.py
new file mode 100755
index 0000000..e6c5255
--- /dev/null
+++ b/test/mqtt_relay_server_util.py
@@ -0,0 +1,18 @@
+#!/usr/bin/env python3
+import sys
+import os.path
+sys.path.extend([
+ os.path.realpath(
+ os.path.join(os.path.dirname(os.path.join(__file__)), '..')
+ )
+])
+
+from src.home.config import config
+from src.home.mqtt.relay import MQTTRelayClient
+
+
+if __name__ == '__main__':
+ config.load('test_mqtt_relay_server')
+ relay = MQTTRelayClient('test')
+ relay.configure_tls()
+ relay.connect_and_loop()
diff --git a/test/mqtt_relay_util.py b/test/mqtt_relay_util.py
new file mode 100755
index 0000000..c1096cc
--- /dev/null
+++ b/test/mqtt_relay_util.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python3
+import sys
+import os.path
+sys.path.extend([
+ os.path.realpath(
+ os.path.join(os.path.dirname(os.path.join(__file__)), '..')
+ )
+])
+
+from argparse import ArgumentParser
+from src.home.config import config
+from src.home.mqtt.relay import MQTTRelayController
+
+
+if __name__ == '__main__':
+ parser = ArgumentParser()
+ parser.add_argument('--on', action='store_true')
+ parser.add_argument('--off', action='store_true')
+ parser.add_argument('--stat', action='store_true')
+
+ config.load('test_mqtt_relay', parser=parser)
+ arg = parser.parse_args()
+
+ relay = MQTTRelayController('test')
+ relay.configure_tls()
+ relay.connect_and_loop(loop_forever=False)
+
+ if arg.on:
+ relay.set_power(True)
+
+ elif arg.off:
+ relay.set_power(False)
+
+ elif arg.stat:
+ relay.send_stat(dict(
+ state=False,
+ signal=-59,
+ fw_v=1.0
+ )) \ No newline at end of file