summaryrefslogtreecommitdiff
path: root/platformio/temphum/src/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'platformio/temphum/src/main.cpp')
-rw-r--r--platformio/temphum/src/main.cpp183
1 files changed, 183 insertions, 0 deletions
diff --git a/platformio/temphum/src/main.cpp b/platformio/temphum/src/main.cpp
new file mode 100644
index 0000000..1fa7e66
--- /dev/null
+++ b/platformio/temphum/src/main.cpp
@@ -0,0 +1,183 @@
+#include <Arduino.h>
+#include <ESP8266WiFi.h>
+#include <DNSServer.h>
+#include <Ticker.h>
+#include <Wire.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 "temphum.h"
+#include "stopwatch.h"
+
+using namespace homekit;
+
+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;
+#if MQTT_BLINK
+static StopWatch blinkStopWatch;
+#endif
+
+static DNSServer* dnsServer = nullptr;
+
+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..");
+}
+
+static void wifiHotspot() {
+ esp_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(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;
+ }
+ }
+}
+
+void setup() {
+ WiFi.disconnect();
+ waitForRecoveryPress();
+
+ temphum::setup();
+
+#ifdef DEBUG
+ Serial.begin(115200);
+#endif
+
+ 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::WAITING) {
+ PRINT(".");
+ esp_led.blink(2, 50);
+ delay(1000);
+ return;
+ }
+
+ 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();
+#if MQTT_BLINK
+ blinkStopWatch.save();
+#endif
+ }
+
+ auto mqtt = (mqtt::MQTT*)service;
+ if (static_cast<int>(wifi_state) >= 1 && mqtt != nullptr) {
+ mqtt->loop();
+
+ if (mqtt->ota.readyToRestart) {
+ mqtt->disconnect();
+ } else if (mqtt->diagnosticsStopWatch.elapsed(10000)) {
+ mqtt->sendDiagnostics();
+
+ auto data = temphum::read();
+ mqtt->sendTempHumData(data.temp, data.rh);
+ }
+
+#if MQTT_BLINK
+ // periodically blink board led
+ if (blinkStopWatch.elapsed(5000)) {
+ board_led.blink(1, 10);
+ blinkStopWatch.save();
+ }
+#endif
+ }
+ } else {
+ if (dnsServer != nullptr)
+ dnsServer->processNextRequest();
+
+ auto httpServer = (HttpServer*)service;
+ if (httpServer != nullptr)
+ httpServer->loop();
+ }
+}
+
+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