This commit is contained in:
Evgeny Zinoviev 2023-05-31 22:27:46 +03:00
parent c976495222
commit 52db06e0c8
7 changed files with 150 additions and 3 deletions

View File

@ -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,25 +106,31 @@ void setup() {
}
#ifndef CONFIG_TARGET_ESP01
#ifndef CONFIG_NO_RECOVERY
switch (working_mode) {
case WorkingMode::RECOVERY:
wifiHotspot();
break;
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(".");
@ -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) {

View File

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

View File

@ -1,6 +1,6 @@
{
"name": "homekit_main",
"version": "1.0.8",
"version": "1.0.10",
"build": {
"flags": "-I../../include"
},

59
src/home/mqtt/relay.py Normal file
View File

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

View File

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

18
test/mqtt_relay_server_util.py Executable file
View File

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

39
test/mqtt_relay_util.py Executable file
View File

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