123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- #include "common.h"
- #include "WiFi.h"
- #include "wifi.h"
- #include "config.h"
- #include "httpd.h"
- #include <lwip/dns.h>
- #include <lwip/inet.h>
- #include <lwip/apps/sntp.h>
- #include <esp_sntp.h>
- #include <esp_wifi.h>
- static wifi_mode_t mode;
- static String ssid, password, hostname, dnsserver, sntpserver;
- 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 (re)connect */
- const ip_addr_t *dns_ip = dns_getserver(0);
- if (invalid_ip(dns_ip) || mode == WIFI_AP ||
- getenv_bool("ip4.dhcp.nodns")) {
- /* Static DNS server configuration */
- ip_addr_t addr;
- if (dnsserver != "" && 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) || mode == WIFI_AP ||
- getenv_bool("ip4.dhcp.nosntp")) {
- if (sntpserver != "")
- 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;
- static int ap_clients = 0;
- 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");
- ap_clients = 0;
- connected = true;
- break;
- case ARDUINO_EVENT_WIFI_AP_STOP:
- printf("[WIFI] Access point stopped\n");
- ap_clients = 0;
- connected = false;
- break;
- case ARDUINO_EVENT_WIFI_AP_STACONNECTED:
- printf("[WIFI] Client connected\n");
- ap_clients++;
- break;
- case ARDUINO_EVENT_WIFI_AP_STADISCONNECTED:
- printf("[WIFI] Client disconnected\n");
- ap_clients--;
- break;
- case ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED:
- printf("[WIFI] Assigned IP address %s to client\n",
- inet_ntoa(info.wifi_ap_staipassigned.ip));
- 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();
- }
- }
- static void wifi_config(void)
- {
- ssid = getenv("wifi.ssid");
- password = getenv("wifi.psk");
- hostname = getenv("hostname");
- sntpserver = getenv_bool("sntp") ? getenv("sntp.server") : "";
- dnsserver = getenv("ip4.dns");
- WiFi.persistent(false);
- if (hostname != "")
- WiFi.hostname(hostname);
- if (ssid == "") {
- uint8_t mac[6];
- char ssid_buf[64];
- mode = WIFI_AP;
- password = "";
- WiFi.macAddress(mac);
- /* Skip first 4 bytes of MAC */
- snprintf(ssid_buf, sizeof ssid_buf, "MAX80_%02X%02X", mac[4], mac[5]);
- ssid = String(ssid_buf);
- } else {
- mode = WIFI_STA;
- }
- printf("[WIFI] SSID [%s]: %s\n",
- mode == WIFI_AP ? "AP" : "STA", ssid.c_str());
- if (WiFi.getMode() != mode) {
- WiFi.mode(mode);
- delay(10);
- }
- if (mode == WIFI_AP) {
- /* No network configuration set */
- IPAddress AP_IP = IPAddress(192,168,0,1);
- IPAddress AP_Netmask = IPAddress(255,255,255,0);
- IPAddress AP_Gateway = IPAddress(0,0,0,0); // No gateway
- unsigned int channel = time(NULL) % 11;
- printf("[WIFI] AP IP %s netmask %s channel %u\n",
- AP_IP.toString(), AP_Netmask.toString(), channel+1);
- WiFi.softAP(ssid.c_str(), password.c_str(), channel+1, 0, 4, true);
- //
- // Conservative settings: 20 MHz, maximum power; this is for
- // reliability, not performance.
- //
- WiFi.setTxPower((wifi_power_t)0);
- esp_wifi_set_bandwidth((wifi_interface_t)ESP_IF_WIFI_AP, WIFI_BW_HT20);
- WiFi.softAPsetHostname(ssid.c_str());
- WiFi.softAPConfig(AP_IP, AP_Gateway, AP_Netmask);
- } else {
- WiFi.begin(ssid.c_str(), password.c_str());
- WiFi.setAutoConnect(true);
- WiFi.setAutoReconnect(true);
- }
- }
- void SetupWiFi() {
- services_started = false;
- WiFi.onEvent(WiFiEvent);
- my_sntp_start();
- printf("[INFO] Setting up WiFi\n");
- wifi_config();
- }
|