#include "common.h" #include "WiFi.h" #include "wifi.h" #include "storage.h" #include "httpd.h" #include #include #include #include static String ssid = ""; static String password = ""; static String otaPassword = ""; static String hostname = "max80"; static String DNSServer = ""; static String SNTPServer = ""; static String TimeZone = "CET-1CEST,M3.5.0,M10.5.0/3"; // Sweden static void sntp_sync_cb(struct timeval *tv) { static uint8_t prev_sync_status = SNTP_SYNC_STATUS_RESET; uint8_t sync_status = sntp_get_sync_status(); switch (sync_status) { case SNTP_SYNC_STATUS_RESET: sntp_set_sync_mode(SNTP_SYNC_MODE_IMMED); // Until first sync if (prev_sync_status != sync_status) { printf("[SNTP] time synchronization lost\n"); } break; case SNTP_SYNC_STATUS_COMPLETED: sntp_set_sync_mode(SNTP_SYNC_MODE_SMOOTH); // After successful sync if (prev_sync_status != sync_status) { char timebuf[64]; const struct tm *tm = localtime(&tv->tv_sec); strftime(timebuf, sizeof timebuf, "%a %Y-%m-%d %H:%M:%S %z", tm); printf("[SNTP] Time synchronized: %s\n", timebuf); } break; default: break; } prev_sync_status = sync_status; } static void my_sntp_start() { sntp_set_time_sync_notification_cb(sntp_sync_cb); sntp_setoperatingmode(SNTP_OPMODE_POLL); sntp_servermode_dhcp(1); sntp_set_sync_mode(SNTP_SYNC_MODE_IMMED); // Until first sync sntp_init(); } static bool services_started; static void stop_services(void) { if (services_started) { esp_unregister_shutdown_handler(stop_services); my_httpd_stop(); services_started = false; } } static inline bool invalid_ip(const ip_addr_t *ip) { return !memcmp(ip, &ip_addr_any, sizeof *ip); } static void start_services(void) { /* Always run after connect */ const ip_addr_t *dns_ip = dns_getserver(0); if (invalid_ip(dns_ip)) { /* No DNS server from DHCP? */ ip_addr_t addr; if (inet_aton(DNSServer.c_str(), &addr)) { dns_setserver(0, &addr); } } dns_ip = dns_getserver(0); printf("[DNS] DNS server: %s\n", inet_ntoa(*dns_ip)); // If Arduino supported both of these at the same that would be // awesome, but it requires ESP-IDF reconfiguration... const ip_addr_t *sntp_ip = sntp_getserver(0); if (invalid_ip(sntp_ip) && !SNTPServer.isEmpty()) sntp_setservername(0, SNTPServer.c_str()); sntp_ip = sntp_getserver(0); printf("[SNTP] Time server: %s\n", inet_ntoa(*sntp_ip)); /* Only run on first start */ if (!services_started) { services_started = true; my_httpd_start(); esp_register_shutdown_handler(stop_services); } } static String wifi_local_ip(void) { return WiFi.localIP().toString(); } static void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) { bool retry = false; bool connected = false; switch (event) { case ARDUINO_EVENT_WIFI_READY: printf("[WIFI] Interface ready\n"); break; case ARDUINO_EVENT_WIFI_SCAN_DONE: printf("[WIFI] Completed scan for access points\n"); break; case ARDUINO_EVENT_WIFI_STA_START: printf("[WIFI] Client started\n"); break; case ARDUINO_EVENT_WIFI_STA_STOP: printf("[WIFI] Clients stopped\n"); break; case ARDUINO_EVENT_WIFI_STA_CONNECTED: printf("[WIFI] Connected to access point\n"); break; case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: printf("[WIFI] Disconnected from WiFi access point\n"); retry = true; break; case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE: printf("[WIFI] Authentication mode of access point has changed\n"); break; case ARDUINO_EVENT_WIFI_STA_GOT_IP: printf("[WIFI] Obtained IP address: %s\n", wifi_local_ip().c_str()); connected = true; break; case ARDUINO_EVENT_WIFI_STA_LOST_IP: printf("[WIFI] Lost IP address and IP address is reset to 0\n"); retry = true; break; case ARDUINO_EVENT_WPS_ER_SUCCESS: printf("[WIFI] WiFi Protected Setup (WPS): succeeded in enrollee mode\n"); break; case ARDUINO_EVENT_WPS_ER_FAILED: printf("[WIFI] WiFi Protected Setup (WPS): failed in enrollee mode\n"); break; case ARDUINO_EVENT_WPS_ER_TIMEOUT: printf("[WIFI] WiFi Protected Setup (WPS): timeout in enrollee mode\n"); break; case ARDUINO_EVENT_WPS_ER_PIN: printf("[WIFI] WiFi Protected Setup (WPS): pin code in enrollee mode\n"); break; case ARDUINO_EVENT_WIFI_AP_START: printf("[WIFI] Access point started\n"); break; case ARDUINO_EVENT_WIFI_AP_STOP: printf("[WIFI] Access point stopped\n"); break; case ARDUINO_EVENT_WIFI_AP_STACONNECTED: printf("[WIFI] Client connected\n"); break; case ARDUINO_EVENT_WIFI_AP_STADISCONNECTED: printf("[WIFI] Client disconnected\n"); break; case ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED: printf("[WIFI] Assigned IP address to client\n"); break; case ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED: printf("[WIFI] Received probe request\n"); break; case ARDUINO_EVENT_WIFI_AP_GOT_IP6: printf("[WIFI] AP IPv6 is preferred\n"); break; case ARDUINO_EVENT_WIFI_STA_GOT_IP6: printf("[WIFI] STA IPv6 is preferred\n"); connected = true; break; case ARDUINO_EVENT_ETH_GOT_IP6: printf("[ETH] Ethernet IPv6 is preferred\n"); connected = true; break; case ARDUINO_EVENT_ETH_START: printf("[ETH] Ethernet started\n"); break; case ARDUINO_EVENT_ETH_STOP: printf("[ETH] Ethernet stopped\n"); break; case ARDUINO_EVENT_ETH_CONNECTED: printf("[ETH] Ethernet connected\n"); break; case ARDUINO_EVENT_ETH_DISCONNECTED: printf("[ETH] Ethernet disconnected\n"); retry = true; break; case ARDUINO_EVENT_ETH_GOT_IP: printf("[ETH] Obtained IP address: %s\n", wifi_local_ip().c_str()); connected = true; break; default: break; } /* Maybe need to do these in a different thread? */ if (connected) { start_services(); } if (retry) { WiFi.disconnect(); WiFi.begin(); } } void SetupWiFi() { services_started = false; ssid = GetWifiSSID(); password = GetWifiPassword(); hostname = GetHostname(); if (!TimeZone.isEmpty()) { printf("[INFO] Setting TZ = %s\n", TimeZone.c_str()); setenv("TZ", TimeZone.c_str(), 1); tzset(); } my_sntp_start(); printf("[INFO] Setting up WiFi\n"); printf("[INFO] SSID: %s\n", ssid.c_str()); WiFi.onEvent(WiFiEvent); if (WiFi.getMode() != WIFI_STA) { WiFi.mode(WIFI_STA); delay(10); } if (WiFi.SSID() != ssid || WiFi.psk() != password) { printf("[INFO] WiFi config changed.\n"); // ... Try to connect to WiFi station. WiFi.begin(ssid.c_str(), password.c_str()); } else { WiFi.begin(); } WiFi.setAutoReconnect(true); WiFi.setHostname(hostname.c_str()); }