summaryrefslogtreecommitdiff
path: root/platformio/relayctl/src/main.cpp
diff options
context:
space:
mode:
authorEvgeny Zinoviev <me@ch1p.io>2022-11-28 05:45:20 +0300
committerEvgeny Zinoviev <me@ch1p.io>2022-12-18 00:00:27 +0300
commit7bb6daa4bf09947142e38ff468b7f62baae110fd (patch)
treec120e9ec800525116ad922e6c4cff21064a40538 /platformio/relayctl/src/main.cpp
parent16d47968b4938f3b60b97f374d45ad39bb0071b1 (diff)
esp8266 relay controller wip
Diffstat (limited to 'platformio/relayctl/src/main.cpp')
-rw-r--r--platformio/relayctl/src/main.cpp170
1 files changed, 170 insertions, 0 deletions
diff --git a/platformio/relayctl/src/main.cpp b/platformio/relayctl/src/main.cpp
new file mode 100644
index 0000000..4a634d6
--- /dev/null
+++ b/platformio/relayctl/src/main.cpp
@@ -0,0 +1,170 @@
+#include <Arduino.h>
+#include <ESP8266WiFi.h>
+#include <DNSServer.h>
+#include <Ticker.h>
+
+#include "mqtt.h"
+#include "config.h"
+#include "logging.h"
+#include "http_server.h"
+#include "led.h"
+#include "config.def.h"
+#include "wifi.h"
+#include "relay.h"
+#include "stopwatch.h"
+
+using namespace homekit;
+
+static Led board_led(BOARD_LED_PIN);
+static Led esp_led(ESP_LED_PIN);
+
+enum class WorkingMode {
+ RECOVERY, // AP mode, http server with configuration
+ NORMAL, // MQTT client
+};
+static enum WorkingMode working_mode = WorkingMode::NORMAL;
+
+enum class WiFiConnectionState {
+ WAITING = 0,
+ JUST_CONNECTED = 1,
+ CONNECTED = 2
+};
+
+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 StopWatch blinkStopWatch;
+
+static DNSServer* dnsServer;
+
+static void onWifiConnected(const WiFiEventStationModeGotIP& event);
+static void onWifiDisconnected(const WiFiEventStationModeDisconnected& event);
+
+static void wifiConnect() {
+ 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.setHostname(hostname);
+ WiFi.begin(ssid, psk);
+
+ PRINT("connecting to wifi..");
+ while (WiFi.status() != WL_CONNECTED) {
+ esp_led.blink(2, 50);
+ delay(1000);
+ PRINT('.');
+ }
+ PRINT(' ');
+}
+
+static void wifiHotspot() {
+ esp_led.on();
+
+ auto scanResults = wifi::scan();
+
+ WiFi.mode(WIFI_AP);
+ WiFi.softAP(wifi::WIFI_AP_SSID);
+
+ dnsServer = new DNSServer();
+ dnsServer->start(53, "*", WiFi.softAPIP());
+
+ service = new HttpServer(scanResults);
+ ((HttpServer*)service)->start();
+}
+
+void setup() {
+#ifdef DEBUG
+ Serial.begin(115200);
+#endif
+
+ relay::init();
+
+ pinMode(FLASH_BUTTON_PIN, INPUT_PULLUP);
+ for (uint16_t i = 0; i < recovery_boot_detection_ms; i += recovery_boot_delay_ms) {
+ delay(recovery_boot_delay_ms);
+ if (digitalRead(FLASH_BUTTON_PIN) == LOW) {
+ working_mode = WorkingMode::RECOVERY;
+ break;
+ }
+ }
+
+ auto cfg = config::read();
+ if (config::isDirty(cfg)) {
+ PRINTLN("config is dirty, erasing...");
+ config::erase(cfg);
+ board_led.blink(10, 50);
+ }
+
+ switch (working_mode) {
+ case WorkingMode::RECOVERY:
+ wifiHotspot();
+ break;
+
+ case WorkingMode::NORMAL:
+ wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnected);
+ wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnected);
+ wifiConnect();
+ break;
+ }
+}
+
+void loop() {
+ if (working_mode == WorkingMode::NORMAL) {
+ if (wifi_state == WiFiConnectionState::JUST_CONNECTED) {
+ board_led.blink(3, 300);
+ wifi_state = WiFiConnectionState::CONNECTED;
+
+ if (service == nullptr)
+ service = new mqtt::MQTT();
+
+ ((mqtt::MQTT*)service)->connect();
+ blinkStopWatch.save();
+ }
+
+ auto mqtt = (mqtt::MQTT*)service;
+ if (static_cast<int>(wifi_state) >= 1
+ && mqtt != nullptr) {
+ if (!mqtt->loop()) {
+ PRINTLN("mqtt::loop() returned false");
+ // FIXME do something here
+ }
+
+ if (mqtt->statStopWatch.elapsed(10000)) {
+ mqtt->sendStat();
+ }
+
+ // periodically blink board led
+ if (blinkStopWatch.elapsed(5000)) {
+ board_led.blink(1, 10);
+ blinkStopWatch.save();
+ }
+ }
+
+ delay(500);
+ } else {
+ if (dnsServer != nullptr)
+ dnsServer->processNextRequest();
+ }
+}
+
+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);
+} \ No newline at end of file