diff options
author | Evgeny Zinoviev <me@ch1p.io> | 2023-09-27 00:54:57 +0300 |
---|---|---|
committer | Evgeny Zinoviev <me@ch1p.io> | 2023-09-27 00:54:57 +0300 |
commit | d3a295872c49defb55fc8e4e43e55550991e0927 (patch) | |
tree | b9dca15454f9027d5a9dad0d4443a20de04dbc5d /include/pio/libs/main/homekit/main.cpp | |
parent | b7cbc2571c1870b4582ead45277d0aa7f961bec8 (diff) | |
parent | bdbb296697f55f4c3a07af43c9aaf7a9ea86f3d0 (diff) |
Merge branch 'master' of ch1p.io:homekit
Diffstat (limited to 'include/pio/libs/main/homekit/main.cpp')
-rw-r--r-- | include/pio/libs/main/homekit/main.cpp | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/include/pio/libs/main/homekit/main.cpp b/include/pio/libs/main/homekit/main.cpp new file mode 100644 index 0000000..816c764 --- /dev/null +++ b/include/pio/libs/main/homekit/main.cpp @@ -0,0 +1,213 @@ +#include "./main.h" +#include <homekit/led.h> +#include <homekit/mqtt/mqtt.h> +#include <homekit/mqtt/module/diagnostics.h> +#include <homekit/mqtt/module/ota.h> + +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; + +static volatile enum WiFiConnectionState wifi_state = WiFiConnectionState::WAITING; +static void* service = nullptr; +static WiFiEventHandler wifiConnectHandler, wifiDisconnectHandler; +static Ticker wifiTimer; +static mqtt::MqttDiagnosticsModule* mqttDiagModule; +static mqtt::MqttOtaModule* mqttOtaModule; + +#if MQTT_BLINK +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); + +static void wifiConnect() { + const char *ssid, *psk, *hostname; + auto cfg = config::read(); + wifi::getConfig(cfg, &ssid, &psk, &hostname); + + PRINTF("Wi-Fi STA creds: ssid=%s, psk=%s, hostname=%s\n", ssid, psk, hostname); + + wifi_state = WiFiConnectionState::WAITING; + + WiFi.mode(WIFI_STA); + WiFi.hostname(hostname); + WiFi.begin(ssid, psk); + + PRINT("connecting to wifi.."); +} + +#ifndef CONFIG_TARGET_ESP01 +#ifndef CONFIG_NO_RECOVERY +static void wifiHotspot() { + led::mcu_led->on(); + + auto scanResults = wifi::scan(); + + WiFi.mode(WIFI_AP); + WiFi.softAP(wifi::AP_SSID); + + dnsServer = new DNSServer(); + dnsServer->start(53, "*", WiFi.softAPIP()); + + service = new HttpServer(scanResults); + ((HttpServer*)service)->start(); +} + +static void waitForRecoveryPress() { + pinMode(CONFIG_FLASH_GPIO, INPUT_PULLUP); + for (uint16_t i = 0; i < recovery_boot_detection_ms; i += recovery_boot_delay_ms) { + delay(recovery_boot_delay_ms); + if (digitalRead(CONFIG_FLASH_GPIO) == LOW) { + working_mode = WorkingMode::RECOVERY; + break; + } + } +} +#endif +#endif + + +void setup() { + WiFi.disconnect(); +#ifndef CONFIG_NO_RECOVERY +#ifndef CONFIG_TARGET_ESP01 + homekit::main::waitForRecoveryPress(); +#endif +#endif + +#ifdef DEBUG + Serial.begin(115200); +#endif + + auto cfg = config::read(); + if (config::isDirty(cfg)) { + PRINTLN("config is dirty, erasing..."); + config::erase(cfg); +#ifdef CONFIG_TARGET_NODEMCU + led::board_led->blink(10, 50); +#else + led::mcu_led->blink(10, 50); +#endif + } + +#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("."); + led::mcu_led->blink(2, 50); + delay(1000); + return; + } + + if (wifi_state == WiFiConnectionState::JUST_CONNECTED) { +#ifdef CONFIG_TARGET_NODEMCU + led::board_led->blink(3, 300); +#else + led::mcu_led->blink(3, 300); +#endif + wifi_state = WiFiConnectionState::CONNECTED; + + if (service == nullptr) { + service = new mqtt::Mqtt(); + mqttDiagModule = new mqtt::MqttDiagnosticsModule(); + mqttOtaModule = new mqtt::MqttOtaModule(); + + ((mqtt::Mqtt*)service)->addModule(mqttDiagModule); + ((mqtt::Mqtt*)service)->addModule(mqttOtaModule); + + if (config != nullptr) + config->onMqttCreated(*(mqtt::Mqtt*)service); + } + + ((mqtt::Mqtt*)service)->connect(); +#if MQTT_BLINK + blinkStopWatch.save(); +#endif + } + + auto mqtt = (mqtt::Mqtt*)service; + if (static_cast<int>(wifi_state) >= 1 && mqtt != nullptr) { + mqtt->loop(); + + if (mqttOtaModule != nullptr && mqttOtaModule->isReadyToRestart()) { + mqtt->disconnect(); + } + +#if MQTT_BLINK + // periodically blink board led + if (blinkStopWatch.elapsed(5000)) { +#ifdef CONFIG_TARGET_NODEMCU + board_led->blink(1, 10); +#endif + blinkStopWatch.save(); + } +#endif + } +#ifndef CONFIG_NO_RECOVERY +#ifndef CONFIG_TARGET_ESP01 + } else { + if (dnsServer != nullptr) + dnsServer->processNextRequest(); + + auto httpServer = (HttpServer*)service; + if (httpServer != nullptr) + httpServer->loop(); + } +#endif +#endif +} + +static void onWifiConnected(const WiFiEventStationModeGotIP& event) { + PRINTF("connected (%s)\n", WiFi.localIP().toString().c_str()); + wifi_state = WiFiConnectionState::JUST_CONNECTED; +} + +static void onWifiDisconnected(const WiFiEventStationModeDisconnected& event) { + PRINTLN("disconnected from wi-fi"); + wifi_state = WiFiConnectionState::WAITING; + if (service != nullptr) + ((mqtt::Mqtt*)service)->disconnect(); + wifiTimer.once(2, wifiConnect); +} + +} |