#include "./main.h" #include #include #include #include namespace homekit::main { enum WorkingMode working_mode = WorkingMode::NORMAL; 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 static DNSServer* dnsServer = nullptr; #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 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 void setup() { WiFi.disconnect(); #ifndef CONFIG_TARGET_ESP01 homekit::main::waitForRecoveryPress(); #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 switch (working_mode) { case WorkingMode::RECOVERY: wifiHotspot(); break; case WorkingMode::NORMAL: #endif wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnected); wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnected); wifiConnect(); #ifndef CONFIG_TARGET_ESP01 break; } #endif } void loop(LoopConfig* config) { #ifndef CONFIG_TARGET_ESP01 if (working_mode == WorkingMode::NORMAL) { #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(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_TARGET_ESP01 } else { if (dnsServer != nullptr) dnsServer->processNextRequest(); auto httpServer = (HttpServer*)service; if (httpServer != nullptr) httpServer->loop(); } #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); } }