123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- #include "common.h"
- #include "WiFi.h"
- #include "wifi.h"
- #include "storage.h"
- #include "httpd.h"
- #include <lwip/dns.h>
- #include <lwip/inet.h>
- #include <lwip/apps/sntp.h>
- #include <esp_sntp.h>
- 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());
- }
|