#include "wifi.h" #include "log.h" #include #include #define NTP_SERVER "pool.ntp.org" #define TIMEZONE_OFFSET 3600 #define DST_OFFSET 3600 #define MIN_EPOCH_SECONDS 1712675973 uint8_t otaLastLogStep = 0; bool wifiConnected = false; bool timeSet = false; time_t preTimeOffset = 0; unsigned long wifiLastConnectTry = 0; void otaSetup(); void bootDelay(); void wifiSetup() { WiFi.softAPdisconnect(); WiFi.setAutoReconnect(false); wifiConnect(); otaSetup(); configTime(TIMEZONE_OFFSET, DST_OFFSET, NTP_SERVER, WiFi.gatewayIP().toString().c_str()); bootDelay(); } void wifiConnect() { WiFi.disconnect(); yield(); wifiLastConnectTry = millis(); info("WIFI", "Connecting: %s", WIFI_SSID); WiFi.begin(WIFI_SSID, WIFI_PKEY); yield(); } void otaSetup() { ArduinoOTA.onStart([] { info("OTA", "Start!"); otaLastLogStep = 0; }); ArduinoOTA.onProgress([](unsigned int received, unsigned int total) { uint8_t currentStep = 20 * received / total; if (otaLastLogStep != currentStep) { info("OTA", "Progress: %3d%%", currentStep * 5); otaLastLogStep = currentStep; } }); ArduinoOTA.onEnd([] { info("OTA", "Complete!"); }); ArduinoOTA.onError([](ota_error_t e) { const char *name; switch (e) { case OTA_AUTH_ERROR: name = "AUTH"; break; case OTA_BEGIN_ERROR: name = "BEGIN"; break; case OTA_CONNECT_ERROR: name = "CONNECT"; break; case OTA_RECEIVE_ERROR: name = "RECEIVE"; break; case OTA_END_ERROR: name = "END"; break; default: name = "[???]"; break; } error("OTA", name); }); ArduinoOTA.begin(); } void bootDelay() { #ifdef BOOT_DELAY info("BOOT DELAY", "Waiting for WiFi..."); while ((uint32_t) WiFi.localIP() == 0) { delay(100); yield(); wifiLoop(); } info("BOOT DELAY", "WiFi connected!"); unsigned long begin = millis(); while (millis() - begin < 10000) { delay(100); yield(); wifiLoop(); } info("BOOT DELAY", "Completed."); #endif } void wifiLoop() { const time_t epochSeconds = getTime(); if (!timeSet) { timeSet = epochSeconds >= MIN_EPOCH_SECONDS; if (!timeSet) { preTimeOffset = epochSeconds; } else { info("NTP", "Time set!"); } } const bool hasIp = static_cast(WiFi.localIP()) != 0; if (wifiConnected) { if (!hasIp) { wifiConnected = false; info("WIFI", "Disconnected!"); wifiConnect(); } } else { if (hasIp) { wifiConnected = true; info("WIFI", "Connected as: %s", WiFi.localIP().toString().c_str()); } else if (millis() - wifiLastConnectTry > 10000) { info("WIFI", "Timeout!"); wifiConnect(); } } } bool isTimeSet() { return timeSet; } time_t getTime() { time_t epochSeconds; time(&epochSeconds); return epochSeconds; } time_t correctTime(const time_t value) { if (!timeSet) { return value; } if (value < MIN_EPOCH_SECONDS) { return getTime() - preTimeOffset + value; } return value; } bool isOlderThan(time_t time, time_t seconds) { return getTime() > correctTime(time) + seconds; }