From ff5a74b20aeb72ac5c882f65ed617e213969aab5 Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Thu, 24 Dec 2015 14:03:15 +0100 Subject: [PATCH 01/29] Added SOFTAP hard-coded settings Set the values of SOFTAP config straight in the Makefile --- Makefile | 75 +++- esp-link/cgiwifi.c | 1012 ++++++++++++++++++++++++-------------------- esp-link/main.c | 22 - 3 files changed, 604 insertions(+), 505 deletions(-) diff --git a/Makefile b/Makefile index 3a6dfbb..95e2b82 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,7 @@ # Makefile heavily adapted to esp-link and wireless flashing by Thorsten von Eicken # Lots of work, in particular to support windows, by brunnels # Original from esphttpd and others... +# Added support for SOFTAP hard-coded configuration by KatAst # VERBOSE=1 # # Start by setting the directories for the toolchain a few lines down @@ -19,9 +20,37 @@ # The Wifi station configuration can be hard-coded here, which makes esp-link come up in STA+AP # mode trying to connect to the specified AP *only* if the flash wireless settings are empty! # This happens on a full serial flash and avoids having to hunt for the AP... -# STA_SSID ?= +# STA_SSID ?= # STA_PASS ?= +# The SOFTAP configuration can be hard-coded here, the minimum parameters to set are AP_SSID && AP_PASS +# The AP SSID has to be at least 8 characters long, same for AP PASSWORD +# The AP AUTH MODE can be set to ( default = AUTH_WPA_WPA2_PSK ) +# AUTH_OPEN = 0, +# AUTH_WEP, +# AUTH_WPA_PSK, +# AUTH_WPA2_PSK, +# AUTH_WPA_WPA2_PSK +# SSID hidden default 0, ( 0 | 1 ) +# Max connections default 4, ( 1 ~ 4 ) +# Beacon interval default 100, ( 100 ~ 60000ms ) + +AP_SSID ?=esp-link-test +AP_PASS ?=esp-link-test +# AP_AUTH_MODE ?=AUTH_WPA_WPA2_PSK +# AP_SSID_HIDDEN ?=0 +# AP_MAX_CONN ?=3 +# AP_BEACON_INTERVAL ?=150 + + +# If CHANGE_TO_STA is set to "yes" the esp-link module will switch to station mode +# once successfully connected to an access point. Else it will stay in STA+AP mode. + +CHANGE_TO_STA ?= no + +# hostname or IP address for wifi flashing +ESP_HOSTNAME ?= esp-link + # --------------- toolchain configuration --------------- # Base directory for the compiler. Needs a / at the end. @@ -30,7 +59,7 @@ XTENSA_TOOLS_ROOT ?= $(abspath ../esp-open-sdk/xtensa-lx106-elf/bin)/ # Base directory of the ESP8266 SDK package, absolute # Typically you'll download from Espressif's BBS, http://bbs.espressif.com/viewforum.php?f=5 -SDK_BASE ?= $(abspath ../esp_iot_sdk_v1.5.0) +SDK_BASE ?= $(abspath ../esp-open-sdk/esp_iot_sdk_v1.5.0) # Esptool.py path and port, only used for 1-time serial flashing # Typically you'll use https://github.com/themadinventor/esptool @@ -39,15 +68,6 @@ ESPTOOL ?= $(abspath ../esp-open-sdk/esptool/esptool.py) ESPPORT ?= /dev/ttyUSB0 ESPBAUD ?= 460800 -# The Wifi station configuration can be hard-coded here, which makes esp-link come up in STA+AP -# mode trying to connect to the specified AP *only* if the flash wireless settings are empty! -# This happens on a full serial flash and avoids having to hunt for the AP... -# STA_SSID ?= -# STA_PASS ?= - -# hostname or IP address for wifi flashing -ESP_HOSTNAME ?= esp-link - # --------------- chipset configuration --------------- # Pick your flash size: "512KB", "1MB", or "4MB" @@ -64,14 +84,9 @@ LED_CONN_PIN ?= 0 # GPIO pin used for "serial activity" LED, active low LED_SERIAL_PIN ?= 14 -# --------------- esp-link config options --------------- +# --------------- esp-link modules config options --------------- -# If CHANGE_TO_STA is set to "yes" the esp-link module will switch to station mode -# once successfully connected to an access point. Else it will stay in AP+STA mode. - -CHANGE_TO_STA ?= yes - -# Optional Modules +# Optional Modules mqtt MODULES ?= mqtt rest syslog # --------------- esphttpd config options --------------- @@ -268,6 +283,30 @@ ifneq ($(strip $(STA_PASS)),) CFLAGS += -DSTA_PASS="$(STA_PASS)" endif +ifneq ($(strip $(AP_SSID)),) +CFLAGS += -DAP_SSID="$(AP_SSID)" +endif + +ifneq ($(strip $(AP_PASS)),) +CFLAGS += -DAP_PASS="$(AP_PASS)" +endif + +ifneq ($(strip $(AP_AUTH_MODE)),) +CFLAGS += -DAP_AUTH_MODE="$(AP_AUTH_MODE)" +endif + +ifneq ($(strip $(AP_SSID_HIDDEN)),) +CFLAGS += -DAP_SSID_HIDDEN="$(AP_SSID_HIDDEN)" +endif + +ifneq ($(strip $(AP_MAX_CONN)),) +CFLAGS += -DAP_MAX_CONN="$(AP_MAX_CONN)" +endif + +ifneq ($(strip $(AP_BEACON_INTERVAL)),) +CFLAGS += -DAP_BEACON_INTERVAL="$(AP_BEACON_INTERVAL)" +endif + ifeq ("$(GZIP_COMPRESSION)","yes") CFLAGS += -DGZIP_COMPRESSION endif diff --git a/esp-link/cgiwifi.c b/esp-link/cgiwifi.c index b83a330..cf36135 100644 --- a/esp-link/cgiwifi.c +++ b/esp-link/cgiwifi.c @@ -1,6 +1,6 @@ /* -Cgi/template routines for the /wifi url. -*/ + Cgi/template routines for the /wifi url. + */ /* * ---------------------------------------------------------------------------- @@ -26,21 +26,30 @@ Cgi/template routines for the /wifi url. #define DBG(format, ...) do { } while(0) #endif +# define VERS_STR_STR(V) #V +# define VERS_STR(V) VERS_STR_STR(V) + bool mdns_started = false; // ===== wifi status change callbacks static WifiStateChangeCb wifi_state_change_cb[4]; +// Temp store for new ap info. +static struct station_config stconf; + +// Temp store for new ap config +static struct softap_config apconf; + uint8_t wifiState = wifiIsDisconnected; // reasons for which a connection failed uint8_t wifiReason = 0; static char *wifiReasons[] = { - "", "unspecified", "auth_expire", "auth_leave", "assoc_expire", "assoc_toomany", "not_authed", - "not_assoced", "assoc_leave", "assoc_not_authed", "disassoc_pwrcap_bad", "disassoc_supchan_bad", - "ie_invalid", "mic_failure", "4way_handshake_timeout", "group_key_update_timeout", - "ie_in_4way_differs", "group_cipher_invalid", "pairwise_cipher_invalid", "akmp_invalid", - "unsupp_rsn_ie_version", "invalid_rsn_ie_cap", "802_1x_auth_failed", "cipher_suite_rejected", - "beacon_timeout", "no_ap_found" }; + "", "unspecified", "auth_expire", "auth_leave", "assoc_expire", "assoc_toomany", "not_authed", + "not_assoced", "assoc_leave", "assoc_not_authed", "disassoc_pwrcap_bad", "disassoc_supchan_bad", + "ie_invalid", "mic_failure", "4way_handshake_timeout", "group_key_update_timeout", + "ie_in_4way_differs", "group_cipher_invalid", "pairwise_cipher_invalid", "akmp_invalid", + "unsupp_rsn_ie_version", "invalid_rsn_ie_cap", "802_1x_auth_failed", "cipher_suite_rejected", + "beacon_timeout", "no_ap_found" }; static char *wifiMode[] = { 0, "STA", "AP", "AP+STA" }; static char *wifiPhy[] = { 0, "11b", "11g", "11n" }; @@ -48,100 +57,100 @@ static char *wifiPhy[] = { 0, "11b", "11g", "11n" }; void (*wifiStatusCb)(uint8_t); // callback when wifi status changes static char* ICACHE_FLASH_ATTR wifiGetReason(void) { - if (wifiReason <= 24) return wifiReasons[wifiReason]; - if (wifiReason >= 200 && wifiReason <= 201) return wifiReasons[wifiReason-200+24]; - return wifiReasons[1]; + if (wifiReason <= 24) return wifiReasons[wifiReason]; + if (wifiReason >= 200 && wifiReason <= 201) return wifiReasons[wifiReason-200+24]; + return wifiReasons[1]; } // handler for wifi status change callback coming in from espressif library static void ICACHE_FLASH_ATTR wifiHandleEventCb(System_Event_t *evt) { - switch (evt->event) { - case EVENT_STAMODE_CONNECTED: - wifiState = wifiIsConnected; - wifiReason = 0; - DBG("Wifi connected to ssid %s, ch %d\n", evt->event_info.connected.ssid, - evt->event_info.connected.channel); - statusWifiUpdate(wifiState); - break; - case EVENT_STAMODE_DISCONNECTED: - wifiState = wifiIsDisconnected; - wifiReason = evt->event_info.disconnected.reason; - DBG("Wifi disconnected from ssid %s, reason %s (%d)\n", - evt->event_info.disconnected.ssid, wifiGetReason(), evt->event_info.disconnected.reason); - statusWifiUpdate(wifiState); - break; - case EVENT_STAMODE_AUTHMODE_CHANGE: - DBG("Wifi auth mode: %d -> %d\n", - evt->event_info.auth_change.old_mode, evt->event_info.auth_change.new_mode); - break; - case EVENT_STAMODE_GOT_IP: - wifiState = wifiGotIP; - wifiReason = 0; - DBG("Wifi got ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR "\n", - IP2STR(&evt->event_info.got_ip.ip), IP2STR(&evt->event_info.got_ip.mask), - IP2STR(&evt->event_info.got_ip.gw)); - statusWifiUpdate(wifiState); - if (!mdns_started) - wifiStartMDNS(evt->event_info.got_ip.ip); - break; - case EVENT_SOFTAPMODE_STACONNECTED: - DBG("Wifi AP: station " MACSTR " joined, AID = %d\n", - MAC2STR(evt->event_info.sta_connected.mac), evt->event_info.sta_connected.aid); - break; - case EVENT_SOFTAPMODE_STADISCONNECTED: - DBG("Wifi AP: station " MACSTR " left, AID = %d\n", - MAC2STR(evt->event_info.sta_disconnected.mac), evt->event_info.sta_disconnected.aid); - break; - default: - break; - } - - for (int i = 0; i < 4; i++) { - if (wifi_state_change_cb[i] != NULL) (wifi_state_change_cb[i])(wifiState); - } + switch (evt->event) { + case EVENT_STAMODE_CONNECTED: + wifiState = wifiIsConnected; + wifiReason = 0; + DBG("Wifi connected to ssid %s, ch %d\n", evt->event_info.connected.ssid, + evt->event_info.connected.channel); + statusWifiUpdate(wifiState); + break; + case EVENT_STAMODE_DISCONNECTED: + wifiState = wifiIsDisconnected; + wifiReason = evt->event_info.disconnected.reason; + DBG("Wifi disconnected from ssid %s, reason %s (%d)\n", + evt->event_info.disconnected.ssid, wifiGetReason(), evt->event_info.disconnected.reason); + statusWifiUpdate(wifiState); + break; + case EVENT_STAMODE_AUTHMODE_CHANGE: + DBG("Wifi auth mode: %d -> %d\n", + evt->event_info.auth_change.old_mode, evt->event_info.auth_change.new_mode); + break; + case EVENT_STAMODE_GOT_IP: + wifiState = wifiGotIP; + wifiReason = 0; + DBG("Wifi got ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR "\n", + IP2STR(&evt->event_info.got_ip.ip), IP2STR(&evt->event_info.got_ip.mask), + IP2STR(&evt->event_info.got_ip.gw)); + statusWifiUpdate(wifiState); + if (!mdns_started) + wifiStartMDNS(evt->event_info.got_ip.ip); + break; + case EVENT_SOFTAPMODE_STACONNECTED: + DBG("Wifi AP: station " MACSTR " joined, AID = %d\n", + MAC2STR(evt->event_info.sta_connected.mac), evt->event_info.sta_connected.aid); + break; + case EVENT_SOFTAPMODE_STADISCONNECTED: + DBG("Wifi AP: station " MACSTR " left, AID = %d\n", + MAC2STR(evt->event_info.sta_disconnected.mac), evt->event_info.sta_disconnected.aid); + break; + default: + break; + } + + for (int i = 0; i < 4; i++) { + if (wifi_state_change_cb[i] != NULL) (wifi_state_change_cb[i])(wifiState); + } } void ICACHE_FLASH_ATTR wifiAddStateChangeCb(WifiStateChangeCb cb) { - for (int i = 0; i < 4; i++) { - if (wifi_state_change_cb[i] == cb) return; - if (wifi_state_change_cb[i] == NULL) { - wifi_state_change_cb[i] = cb; - return; + for (int i = 0; i < 4; i++) { + if (wifi_state_change_cb[i] == cb) return; + if (wifi_state_change_cb[i] == NULL) { + wifi_state_change_cb[i] = cb; + return; + } } - } - DBG("WIFI: max state change cb count exceeded\n"); + DBG("WIFI: max state change cb count exceeded\n"); } void ICACHE_FLASH_ATTR wifiStartMDNS(struct ip_addr ip) { - if (flashConfig.mdns_enable) { - struct mdns_info *mdns_info = (struct mdns_info *)os_zalloc(sizeof(struct mdns_info)); - mdns_info->host_name = flashConfig.hostname; - mdns_info->server_name = flashConfig.mdns_servername; - mdns_info->server_port = 80; - mdns_info->ipAddr = ip.addr; - espconn_mdns_init(mdns_info); - } - else { - espconn_mdns_server_unregister(); - espconn_mdns_close(); - } - mdns_started = true; + if (flashConfig.mdns_enable) { + struct mdns_info *mdns_info = (struct mdns_info *)os_zalloc(sizeof(struct mdns_info)); + mdns_info->host_name = flashConfig.hostname; + mdns_info->server_name = flashConfig.mdns_servername; + mdns_info->server_port = 80; + mdns_info->ipAddr = ip.addr; + espconn_mdns_init(mdns_info); + } + else { + espconn_mdns_server_unregister(); + espconn_mdns_close(); + } + mdns_started = true; } // ===== wifi scanning //WiFi access point data typedef struct { - char ssid[32]; - sint8 rssi; - char enc; + char ssid[32]; + sint8 rssi; + char enc; } ApData; //Scan result typedef struct { - char scanInProgress; //if 1, don't access the underlying stuff from the webpage. - ApData **apData; - int noAps; + char scanInProgress; //if 1, don't access the underlying stuff from the webpage. + ApData **apData; + int noAps; } ScanResultData; //Static scan status storage. @@ -150,129 +159,129 @@ static ScanResultData cgiWifiAps; //Callback the code calls when a wlan ap scan is done. Basically stores the result in //the cgiWifiAps struct. void ICACHE_FLASH_ATTR wifiScanDoneCb(void *arg, STATUS status) { - int n; - struct bss_info *bss_link = (struct bss_info *)arg; - - if (status!=OK) { - DBG("wifiScanDoneCb status=%d\n", status); - cgiWifiAps.scanInProgress=0; - return; - } - - //Clear prev ap data if needed. - if (cgiWifiAps.apData!=NULL) { - for (n=0; n<cgiWifiAps.noAps; n++) os_free(cgiWifiAps.apData[n]); - os_free(cgiWifiAps.apData); - } - - //Count amount of access points found. - n=0; - while (bss_link != NULL) { - bss_link = bss_link->next.stqe_next; - n++; - } - //Allocate memory for access point data - cgiWifiAps.apData=(ApData **)os_malloc(sizeof(ApData *)*n); - cgiWifiAps.noAps=n; - DBG("Scan done: found %d APs\n", n); - - //Copy access point data to the static struct - n=0; - bss_link = (struct bss_info *)arg; - while (bss_link != NULL) { - if (n>=cgiWifiAps.noAps) { - //This means the bss_link changed under our nose. Shouldn't happen! - //Break because otherwise we will write in unallocated memory. - DBG("Huh? I have more than the allocated %d aps!\n", cgiWifiAps.noAps); - break; + int n; + struct bss_info *bss_link = (struct bss_info *)arg; + + if (status!=OK) { + DBG("wifiScanDoneCb status=%d\n", status); + cgiWifiAps.scanInProgress=0; + return; } - //Save the ap data. - cgiWifiAps.apData[n]=(ApData *)os_malloc(sizeof(ApData)); - cgiWifiAps.apData[n]->rssi=bss_link->rssi; - cgiWifiAps.apData[n]->enc=bss_link->authmode; - strncpy(cgiWifiAps.apData[n]->ssid, (char*)bss_link->ssid, 32); - DBG("bss%d: %s (%d)\n", n+1, (char*)bss_link->ssid, bss_link->rssi); - - bss_link = bss_link->next.stqe_next; - n++; - } - //We're done. - cgiWifiAps.scanInProgress=0; + + //Clear prev ap data if needed. + if (cgiWifiAps.apData!=NULL) { + for (n=0; n<cgiWifiAps.noAps; n++) os_free(cgiWifiAps.apData[n]); + os_free(cgiWifiAps.apData); + } + + //Count amount of access points found. + n=0; + while (bss_link != NULL) { + bss_link = bss_link->next.stqe_next; + n++; + } + //Allocate memory for access point data + cgiWifiAps.apData=(ApData **)os_malloc(sizeof(ApData *)*n); + cgiWifiAps.noAps=n; + DBG("Scan done: found %d APs\n", n); + + //Copy access point data to the static struct + n=0; + bss_link = (struct bss_info *)arg; + while (bss_link != NULL) { + if (n>=cgiWifiAps.noAps) { + //This means the bss_link changed under our nose. Shouldn't happen! + //Break because otherwise we will write in unallocated memory. + DBG("Huh? I have more than the allocated %d aps!\n", cgiWifiAps.noAps); + break; + } + //Save the ap data. + cgiWifiAps.apData[n]=(ApData *)os_malloc(sizeof(ApData)); + cgiWifiAps.apData[n]->rssi=bss_link->rssi; + cgiWifiAps.apData[n]->enc=bss_link->authmode; + strncpy(cgiWifiAps.apData[n]->ssid, (char*)bss_link->ssid, 32); + DBG("bss%d: %s (%d)\n", n+1, (char*)bss_link->ssid, bss_link->rssi); + + bss_link = bss_link->next.stqe_next; + n++; + } + //We're done. + cgiWifiAps.scanInProgress=0; } static ETSTimer scanTimer; static void ICACHE_FLASH_ATTR scanStartCb(void *arg) { - DBG("Starting a scan\n"); - wifi_station_scan(NULL, wifiScanDoneCb); + DBG("Starting a scan\n"); + wifi_station_scan(NULL, wifiScanDoneCb); } static int ICACHE_FLASH_ATTR cgiWiFiStartScan(HttpdConnData *connData) { - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - jsonHeader(connData, 200); - if (!cgiWifiAps.scanInProgress) { - cgiWifiAps.scanInProgress = 1; - os_timer_disarm(&scanTimer); - os_timer_setfn(&scanTimer, scanStartCb, NULL); - os_timer_arm(&scanTimer, 200, 0); - } - return HTTPD_CGI_DONE; + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + jsonHeader(connData, 200); + if (!cgiWifiAps.scanInProgress) { + cgiWifiAps.scanInProgress = 1; + os_timer_disarm(&scanTimer); + os_timer_setfn(&scanTimer, scanStartCb, NULL); + os_timer_arm(&scanTimer, 200, 0); + } + return HTTPD_CGI_DONE; } static int ICACHE_FLASH_ATTR cgiWiFiGetScan(HttpdConnData *connData) { - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - char buff[1460]; - const int chunk = 1460/64; // ssid is up to 32 chars - int len = 0; - - os_printf("GET scan: cgiData=%d noAps=%d\n", (int)connData->cgiData, cgiWifiAps.noAps); - - // handle continuation call, connData->cgiData-1 is the position in the scan results where we - // we need to continue sending from (using -1 'cause 0 means it's the first call) - if (connData->cgiData) { - int next = (int)connData->cgiData-1; - int pos = next; - while (pos < cgiWifiAps.noAps && pos < next+chunk) { - len += os_sprintf(buff+len, "{\"essid\": \"%s\", \"rssi\": %d, \"enc\": \"%d\"}%c\n", - cgiWifiAps.apData[pos]->ssid, cgiWifiAps.apData[pos]->rssi, cgiWifiAps.apData[pos]->enc, - (pos+1 == cgiWifiAps.noAps) ? ' ' : ','); - pos++; + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + char buff[1460]; + const int chunk = 1460/64; // ssid is up to 32 chars + int len = 0; + + os_printf("GET scan: cgiData=%d noAps=%d\n", (int)connData->cgiData, cgiWifiAps.noAps); + + // handle continuation call, connData->cgiData-1 is the position in the scan results where we + // we need to continue sending from (using -1 'cause 0 means it's the first call) + if (connData->cgiData) { + int next = (int)connData->cgiData-1; + int pos = next; + while (pos < cgiWifiAps.noAps && pos < next+chunk) { + len += os_sprintf(buff+len, "{\"essid\": \"%s\", \"rssi\": %d, \"enc\": \"%d\"}%c\n", + cgiWifiAps.apData[pos]->ssid, cgiWifiAps.apData[pos]->rssi, cgiWifiAps.apData[pos]->enc, + (pos+1 == cgiWifiAps.noAps) ? ' ' : ','); + pos++; + } + // done or more? + if (pos == cgiWifiAps.noAps) { + len += os_sprintf(buff+len, "]}}\n"); + httpdSend(connData, buff, len); + return HTTPD_CGI_DONE; + } else { + connData->cgiData = (void*)(pos+1); + httpdSend(connData, buff, len); + return HTTPD_CGI_MORE; + } } - // done or more? - if (pos == cgiWifiAps.noAps) { - len += os_sprintf(buff+len, "]}}\n"); - httpdSend(connData, buff, len); - return HTTPD_CGI_DONE; - } else { - connData->cgiData = (void*)(pos+1); - httpdSend(connData, buff, len); - return HTTPD_CGI_MORE; + + jsonHeader(connData, 200); + + if (cgiWifiAps.scanInProgress==1) { + //We're still scanning. Tell Javascript code that. + len = os_sprintf(buff, "{\n \"result\": { \n\"inProgress\": \"1\"\n }\n}\n"); + httpdSend(connData, buff, len); + return HTTPD_CGI_DONE; } - } - - jsonHeader(connData, 200); - - if (cgiWifiAps.scanInProgress==1) { - //We're still scanning. Tell Javascript code that. - len = os_sprintf(buff, "{\n \"result\": { \n\"inProgress\": \"1\"\n }\n}\n"); + + len = os_sprintf(buff, "{\"result\": {\"inProgress\": \"0\", \"APs\": [\n"); + connData->cgiData = (void *)1; // start with first result next time we're called httpdSend(connData, buff, len); - return HTTPD_CGI_DONE; - } - - len = os_sprintf(buff, "{\"result\": {\"inProgress\": \"0\", \"APs\": [\n"); - connData->cgiData = (void *)1; // start with first result next time we're called - httpdSend(connData, buff, len); - return HTTPD_CGI_MORE; + return HTTPD_CGI_MORE; } int ICACHE_FLASH_ATTR cgiWiFiScan(HttpdConnData *connData) { - if (connData->requestType == HTTPD_METHOD_GET) { - return cgiWiFiGetScan(connData); - } else if (connData->requestType == HTTPD_METHOD_POST) { - return cgiWiFiStartScan(connData); - } else { - jsonHeader(connData, 404); - return HTTPD_CGI_DONE; - } + if (connData->requestType == HTTPD_METHOD_GET) { + return cgiWiFiGetScan(connData); + } else if (connData->requestType == HTTPD_METHOD_POST) { + return cgiWiFiStartScan(connData); + } else { + jsonHeader(connData, 404); + return HTTPD_CGI_DONE; + } } // ===== timers to change state and rescue from failed associations @@ -285,235 +294,242 @@ static ETSTimer resetTimer; // the connect succeeds, this gets the module in STA-only mode. If it fails, it ensures // that the module is in STA+AP mode so the user has a chance to recover. static void ICACHE_FLASH_ATTR resetTimerCb(void *arg) { - int x = wifi_station_get_connect_status(); - int m = wifi_get_opmode() & 0x3; - DBG("Wifi check: mode=%s status=%d\n", wifiMode[m], x); - - if (x == STATION_GOT_IP) { - if (m != 1) { + int x = wifi_station_get_connect_status(); + int m = wifi_get_opmode() & 0x3; + DBG("Wifi check: mode=%s status=%d\n", wifiMode[m], x); + + if (x == STATION_GOT_IP) { + if (m != 1) { #ifdef CHANGE_TO_STA - // We're happily connected, go to STA mode - DBG("Wifi got IP. Going into STA mode..\n"); - wifi_set_opmode(1); - os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); // check one more time after switching to STA-only + // We're happily connected, go to STA mode + DBG("Wifi got IP. Going into STA mode..\n"); + wifi_set_opmode(1); + os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); // check one more time after switching to STA-only #endif + } + log_uart(false); + // no more resetTimer at this point, gotta use physical reset to recover if in trouble + } else { + + if (m != 3) { + DBG("Wifi connect failed. Going into STA+AP mode..\n"); + // Set STA+AP mode + wifi_set_opmode(3); +#ifdef AP_SSID + // Call ap set after mode change to AP or STA+AP + wifi_softap_set_config(&apconf); +#endif + } + log_uart(true); + DBG("Enabling/continuing uart log\n"); + os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); } - log_uart(false); - // no more resetTimer at this point, gotta use physical reset to recover if in trouble - } else { - if (m != 3) { - DBG("Wifi connect failed. Going into STA+AP mode..\n"); - wifi_set_opmode(3); - } - log_uart(true); - DBG("Enabling/continuing uart log\n"); - os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); - } } -// Temp store for new ap info. -static struct station_config stconf; // Reassociate timer to delay change of association so the original request can finish static ETSTimer reassTimer; // Callback actually doing reassociation static void ICACHE_FLASH_ATTR reassTimerCb(void *arg) { - DBG("Wifi changing association\n"); - wifi_station_disconnect(); - stconf.bssid_set = 0; - wifi_station_set_config(&stconf); - wifi_station_connect(); - // Schedule check, we give some extra time (4x) 'cause the reassociation can cause the AP - // to have to change channel, and then the client needs to follow before it can see the - // IP address - os_timer_disarm(&resetTimer); - os_timer_setfn(&resetTimer, resetTimerCb, NULL); - os_timer_arm(&resetTimer, 4*RESET_TIMEOUT, 0); + DBG("Wifi changing association\n"); + wifi_station_disconnect(); + stconf.bssid_set = 0; + wifi_station_set_config(&stconf); + wifi_station_connect(); + // Schedule check, we give some extra time (4x) 'cause the reassociation can cause the AP + // to have to change channel, and then the client needs to follow before it can see the + // IP address + os_timer_disarm(&resetTimer); + os_timer_setfn(&resetTimer, resetTimerCb, NULL); + os_timer_arm(&resetTimer, 4*RESET_TIMEOUT, 0); } // This cgi uses the routines above to connect to a specific access point with the // given ESSID using the given password. int ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData) { - char essid[128]; - char passwd[128]; - - if (connData->conn==NULL) return HTTPD_CGI_DONE; - - int el = httpdFindArg(connData->getArgs, "essid", essid, sizeof(essid)); - int pl = httpdFindArg(connData->getArgs, "passwd", passwd, sizeof(passwd)); - - if (el > 0 && pl >= 0) { - //Set to 0 if you want to disable the actual reconnecting bit - os_strncpy((char*)stconf.ssid, essid, 32); - os_strncpy((char*)stconf.password, passwd, 64); - DBG("Wifi try to connect to AP %s pw %s\n", essid, passwd); - - //Schedule disconnect/connect - os_timer_disarm(&reassTimer); - os_timer_setfn(&reassTimer, reassTimerCb, NULL); - os_timer_arm(&reassTimer, 1000, 0); // 1 second for the response of this request to make it - jsonHeader(connData, 200); - } else { - jsonHeader(connData, 400); - httpdSend(connData, "Cannot parse ssid or password", -1); - } - return HTTPD_CGI_DONE; + char essid[128]; + char passwd[128]; + + if (connData->conn==NULL) return HTTPD_CGI_DONE; + + int el = httpdFindArg(connData->getArgs, "essid", essid, sizeof(essid)); + int pl = httpdFindArg(connData->getArgs, "passwd", passwd, sizeof(passwd)); + + if (el > 0 && pl >= 0) { + //Set to 0 if you want to disable the actual reconnecting bit + os_strncpy((char*)stconf.ssid, essid, 32); + os_strncpy((char*)stconf.password, passwd, 64); + DBG("Wifi try to connect to AP %s pw %s\n", essid, passwd); + + //Schedule disconnect/connect + os_timer_disarm(&reassTimer); + os_timer_setfn(&reassTimer, reassTimerCb, NULL); + os_timer_arm(&reassTimer, 1000, 0); // 1 second for the response of this request to make it + jsonHeader(connData, 200); + } else { + jsonHeader(connData, 400); + httpdSend(connData, "Cannot parse ssid or password", -1); + } + return HTTPD_CGI_DONE; } static bool ICACHE_FLASH_ATTR parse_ip(char *buff, ip_addr_t *ip_ptr) { - char *next = buff; // where to start parsing next integer - int found = 0; // number of integers parsed - uint32_t ip = 0; // the ip addres parsed - for (int i=0; i<32; i++) { // 32 is just a safety limit - char c = buff[i]; - if (c == '.' || c == 0) { - // parse the preceding integer and accumulate into IP address - bool last = c == 0; - buff[i] = 0; - uint32_t v = atoi(next); - ip = ip | ((v&0xff)<<(found*8)); - next = buff+i+1; // next integer starts after the '.' - found++; - if (last) { // if at end of string we better got 4 integers - ip_ptr->addr = ip; - return found == 4; - } - continue; + char *next = buff; // where to start parsing next integer + int found = 0; // number of integers parsed + uint32_t ip = 0; // the ip addres parsed + for (int i=0; i<32; i++) { // 32 is just a safety limit + char c = buff[i]; + if (c == '.' || c == 0) { + // parse the preceding integer and accumulate into IP address + bool last = c == 0; + buff[i] = 0; + uint32_t v = atoi(next); + ip = ip | ((v&0xff)<<(found*8)); + next = buff+i+1; // next integer starts after the '.' + found++; + if (last) { // if at end of string we better got 4 integers + ip_ptr->addr = ip; + return found == 4; + } + continue; + } + if (c < '0' || c > '9') return false; } - if (c < '0' || c > '9') return false; - } - return false; + return false; } #ifdef DEBUGIP static void ICACHE_FLASH_ATTR debugIP() { - struct ip_info info; - if (wifi_get_ip_info(0, &info)) { - os_printf("\"ip\": \"%d.%d.%d.%d\"\n", IP2STR(&info.ip.addr)); - os_printf("\"netmask\": \"%d.%d.%d.%d\"\n", IP2STR(&info.netmask.addr)); - os_printf("\"gateway\": \"%d.%d.%d.%d\"\n", IP2STR(&info.gw.addr)); - os_printf("\"hostname\": \"%s\"\n", wifi_station_get_hostname()); - } else { - os_printf("\"ip\": \"-none-\"\n"); - } + struct ip_info info; + if (wifi_get_ip_info(0, &info)) { + os_printf("\"ip\": \"%d.%d.%d.%d\"\n", IP2STR(&info.ip.addr)); + os_printf("\"netmask\": \"%d.%d.%d.%d\"\n", IP2STR(&info.netmask.addr)); + os_printf("\"gateway\": \"%d.%d.%d.%d\"\n", IP2STR(&info.gw.addr)); + os_printf("\"hostname\": \"%s\"\n", wifi_station_get_hostname()); + } else { + os_printf("\"ip\": \"-none-\"\n"); + } } #endif // configure Wifi, specifically DHCP vs static IP address based on flash config void ICACHE_FLASH_ATTR configWifiIP() { - if (flashConfig.staticip == 0) { - // let's DHCP! - wifi_station_set_hostname(flashConfig.hostname); - if (wifi_station_dhcpc_status() == DHCP_STARTED) - wifi_station_dhcpc_stop(); - wifi_station_dhcpc_start(); - DBG("Wifi uses DHCP, hostname=%s\n", flashConfig.hostname); - } else { - // no DHCP, we got static network config! - wifi_station_dhcpc_stop(); - struct ip_info ipi; - ipi.ip.addr = flashConfig.staticip; - ipi.netmask.addr = flashConfig.netmask; - ipi.gw.addr = flashConfig.gateway; - wifi_set_ip_info(0, &ipi); - DBG("Wifi uses static IP %d.%d.%d.%d\n", IP2STR(&ipi.ip.addr)); - } + if (flashConfig.staticip == 0) { + // let's DHCP! + wifi_station_set_hostname(flashConfig.hostname); + if (wifi_station_dhcpc_status() == DHCP_STARTED) + wifi_station_dhcpc_stop(); + wifi_station_dhcpc_start(); + DBG("Wifi uses DHCP, hostname=%s\n", flashConfig.hostname); + } else { + // no DHCP, we got static network config! + wifi_station_dhcpc_stop(); + struct ip_info ipi; + ipi.ip.addr = flashConfig.staticip; + ipi.netmask.addr = flashConfig.netmask; + ipi.gw.addr = flashConfig.gateway; + wifi_set_ip_info(0, &ipi); + DBG("Wifi uses static IP %d.%d.%d.%d\n", IP2STR(&ipi.ip.addr)); + } #ifdef DEBUGIP - debugIP(); + debugIP(); #endif } // Change special settings int ICACHE_FLASH_ATTR cgiWiFiSpecial(HttpdConnData *connData) { - char dhcp[8]; - char staticip[20]; - char netmask[20]; - char gateway[20]; - - if (connData->conn==NULL) return HTTPD_CGI_DONE; - - // get args and their string lengths - int dl = httpdFindArg(connData->getArgs, "dhcp", dhcp, sizeof(dhcp)); - int sl = httpdFindArg(connData->getArgs, "staticip", staticip, sizeof(staticip)); - int nl = httpdFindArg(connData->getArgs, "netmask", netmask, sizeof(netmask)); - int gl = httpdFindArg(connData->getArgs, "gateway", gateway, sizeof(gateway)); - - if (!(dl > 0 && sl >= 0 && nl >= 0 && gl >= 0)) { - jsonHeader(connData, 400); - httpdSend(connData, "Request is missing fields", -1); - return HTTPD_CGI_DONE; - } - - char url[64]; // redirect URL - if (os_strcmp(dhcp, "off") == 0) { - // parse static IP params - struct ip_info ipi; - bool ok = parse_ip(staticip, &ipi.ip); - if (nl > 0) ok = ok && parse_ip(netmask, &ipi.netmask); - else IP4_ADDR(&ipi.netmask, 255, 255, 255, 0); - if (gl > 0) ok = ok && parse_ip(gateway, &ipi.gw); - else ipi.gw.addr = 0; - if (!ok) { - jsonHeader(connData, 400); - httpdSend(connData, "Cannot parse static IP config", -1); - return HTTPD_CGI_DONE; + char dhcp[8]; + char staticip[20]; + char netmask[20]; + char gateway[20]; + + if (connData->conn==NULL) return HTTPD_CGI_DONE; + + // get args and their string lengths + int dl = httpdFindArg(connData->getArgs, "dhcp", dhcp, sizeof(dhcp)); + int sl = httpdFindArg(connData->getArgs, "staticip", staticip, sizeof(staticip)); + int nl = httpdFindArg(connData->getArgs, "netmask", netmask, sizeof(netmask)); + int gl = httpdFindArg(connData->getArgs, "gateway", gateway, sizeof(gateway)); + + if (!(dl > 0 && sl >= 0 && nl >= 0 && gl >= 0)) { + jsonHeader(connData, 400); + httpdSend(connData, "Request is missing fields", -1); + return HTTPD_CGI_DONE; } - // save the params in flash - flashConfig.staticip = ipi.ip.addr; - flashConfig.netmask = ipi.netmask.addr; - flashConfig.gateway = ipi.gw.addr; - // construct redirect URL - os_sprintf(url, "{\"url\": \"http://%d.%d.%d.%d\"}", IP2STR(&ipi.ip)); - - } else { - // dynamic IP - flashConfig.staticip = 0; - os_sprintf(url, "{\"url\": \"http://%s\"}", flashConfig.hostname); - } - - configSave(); // ignore error... - // schedule change-over - os_timer_disarm(&reassTimer); - os_timer_setfn(&reassTimer, configWifiIP, NULL); - os_timer_arm(&reassTimer, 1000, 0); // 1 second for the response of this request to make it - // return redirect info - jsonHeader(connData, 200); - httpdSend(connData, url, -1); - return HTTPD_CGI_DONE; + + char url[64]; // redirect URL + if (os_strcmp(dhcp, "off") == 0) { + // parse static IP params + struct ip_info ipi; + bool ok = parse_ip(staticip, &ipi.ip); + if (nl > 0) ok = ok && parse_ip(netmask, &ipi.netmask); + else IP4_ADDR(&ipi.netmask, 255, 255, 255, 0); + if (gl > 0) ok = ok && parse_ip(gateway, &ipi.gw); + else ipi.gw.addr = 0; + if (!ok) { + jsonHeader(connData, 400); + httpdSend(connData, "Cannot parse static IP config", -1); + return HTTPD_CGI_DONE; + } + // save the params in flash + flashConfig.staticip = ipi.ip.addr; + flashConfig.netmask = ipi.netmask.addr; + flashConfig.gateway = ipi.gw.addr; + // construct redirect URL + os_sprintf(url, "{\"url\": \"http://%d.%d.%d.%d\"}", IP2STR(&ipi.ip)); + + } else { + // dynamic IP + flashConfig.staticip = 0; + os_sprintf(url, "{\"url\": \"http://%s\"}", flashConfig.hostname); + } + + configSave(); // ignore error... + // schedule change-over + os_timer_disarm(&reassTimer); + os_timer_setfn(&reassTimer, configWifiIP, NULL); + os_timer_arm(&reassTimer, 1000, 0); // 1 second for the response of this request to make it + // return redirect info + jsonHeader(connData, 200); + httpdSend(connData, url, -1); + return HTTPD_CGI_DONE; } //This cgi changes the operating mode: STA / AP / STA+AP int ICACHE_FLASH_ATTR cgiWiFiSetMode(HttpdConnData *connData) { - int len; - char buff[1024]; - - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - - len=httpdFindArg(connData->getArgs, "mode", buff, sizeof(buff)); - if (len!=0) { - int m = atoi(buff); - DBG("Wifi switching to mode %d\n", m); - wifi_set_opmode(m&3); - if (m == 1) { - // STA-only mode, reset into STA+AP after a timeout if we don't get an IP address - os_timer_disarm(&resetTimer); - os_timer_setfn(&resetTimer, resetTimerCb, NULL); - os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); + int len; + char buff[1024]; + + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + + len=httpdFindArg(connData->getArgs, "mode", buff, sizeof(buff)); + if (len!=0) { + int m = atoi(buff); + DBG("Wifi switching to mode %d\n", m); + wifi_set_opmode(m&3); + // Call softap set after changing to AP or STA+AP + wifi_softap_set_config(&apconf); + + if (m == 1) { + // STA-only mode, reset into STA+AP after a timeout if we don't get an IP address + os_timer_disarm(&resetTimer); + os_timer_setfn(&resetTimer, resetTimerCb, NULL); + os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); + } + jsonHeader(connData, 200); + } else { + jsonHeader(connData, 400); } - jsonHeader(connData, 200); - } else { - jsonHeader(connData, 400); - } - return HTTPD_CGI_DONE; + return HTTPD_CGI_DONE; } static char *connStatuses[] = { "idle", "connecting", "wrong password", "AP not found", - "failed", "got IP address" }; + "failed", "got IP address" }; static char *wifiWarn[] = { 0, - "Switch to <a href=\\\"#\\\" onclick=\\\"changeWifiMode(3)\\\">STA+AP mode</a>", - "<b>Can't scan in this mode!</b> Switch to <a href=\\\"#\\\" onclick=\\\"changeWifiMode(3)\\\">STA+AP mode</a>", - "Switch to <a href=\\\"#\\\" onclick=\\\"changeWifiMode(1)\\\">STA mode</a>", + "Switch to <a href=\\\"#\\\" onclick=\\\"changeWifiMode(3)\\\">STA+AP mode</a>", + "<b>Can't scan in this mode!</b> Switch to <a href=\\\"#\\\" onclick=\\\"changeWifiMode(3)\\\">STA+AP mode</a>", + "Switch to <a href=\\\"#\\\" onclick=\\\"changeWifiMode(1)\\\">STA mode</a>", }; #ifdef CHANGE_TO_STA @@ -524,114 +540,180 @@ static char *wifiWarn[] = { 0, // print various Wifi information into json buffer int ICACHE_FLASH_ATTR printWifiInfo(char *buff) { - int len; - - struct station_config stconf; - wifi_station_get_config(&stconf); - - uint8_t op = wifi_get_opmode() & 0x3; - char *mode = wifiMode[op]; - char *status = "unknown"; - int st = wifi_station_get_connect_status(); - if (st >= 0 && st < sizeof(connStatuses)) status = connStatuses[st]; - int p = wifi_get_phy_mode(); - char *phy = wifiPhy[p&3]; - char *warn = wifiWarn[op]; - sint8 rssi = wifi_station_get_rssi(); - if (rssi > 0) rssi = 0; - uint8 mac_addr[6]; - wifi_get_macaddr(0, mac_addr); - uint8_t chan = wifi_get_channel(); - - len = os_sprintf(buff, - "\"mode\": \"%s\", \"modechange\": \"%s\", \"ssid\": \"%s\", \"status\": \"%s\", \"phy\": \"%s\", " - "\"rssi\": \"%ddB\", \"warn\": \"%s\", \"mac\":\"%02x:%02x:%02x:%02x:%02x:%02x\", \"chan\":%d", - mode, MODECHANGE, (char*)stconf.ssid, status, phy, rssi, warn, - mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5], chan); - - struct ip_info info; - if (wifi_get_ip_info(0, &info)) { - len += os_sprintf(buff+len, ", \"ip\": \"%d.%d.%d.%d\"", IP2STR(&info.ip.addr)); - len += os_sprintf(buff+len, ", \"netmask\": \"%d.%d.%d.%d\"", IP2STR(&info.netmask.addr)); - len += os_sprintf(buff+len, ", \"gateway\": \"%d.%d.%d.%d\"", IP2STR(&info.gw.addr)); - len += os_sprintf(buff+len, ", \"hostname\": \"%s\"", flashConfig.hostname); - } else { - len += os_sprintf(buff+len, ", \"ip\": \"-none-\""); - } - len += os_sprintf(buff+len, ", \"staticip\": \"%d.%d.%d.%d\"", IP2STR(&flashConfig.staticip)); - len += os_sprintf(buff+len, ", \"dhcp\": \"%s\"", flashConfig.staticip > 0 ? "off" : "on"); - - return len; + int len; + + struct station_config stconf; + wifi_station_get_config(&stconf); + + uint8_t op = wifi_get_opmode() & 0x3; + char *mode = wifiMode[op]; + char *status = "unknown"; + int st = wifi_station_get_connect_status(); + if (st >= 0 && st < sizeof(connStatuses)) status = connStatuses[st]; + int p = wifi_get_phy_mode(); + char *phy = wifiPhy[p&3]; + char *warn = wifiWarn[op]; + sint8 rssi = wifi_station_get_rssi(); + if (rssi > 0) rssi = 0; + uint8 mac_addr[6]; + wifi_get_macaddr(0, mac_addr); + uint8_t chan = wifi_get_channel(); + + len = os_sprintf(buff, + "\"mode\": \"%s\", \"modechange\": \"%s\", \"ssid\": \"%s\", \"status\": \"%s\", \"phy\": \"%s\", " + "\"rssi\": \"%ddB\", \"warn\": \"%s\", \"mac\":\"%02x:%02x:%02x:%02x:%02x:%02x\", \"chan\":%d", + mode, MODECHANGE, (char*)stconf.ssid, status, phy, rssi, warn, + mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5], chan); + + struct ip_info info; + if (wifi_get_ip_info(0, &info)) { + len += os_sprintf(buff+len, ", \"ip\": \"%d.%d.%d.%d\"", IP2STR(&info.ip.addr)); + len += os_sprintf(buff+len, ", \"netmask\": \"%d.%d.%d.%d\"", IP2STR(&info.netmask.addr)); + len += os_sprintf(buff+len, ", \"gateway\": \"%d.%d.%d.%d\"", IP2STR(&info.gw.addr)); + len += os_sprintf(buff+len, ", \"hostname\": \"%s\"", flashConfig.hostname); + } else { + len += os_sprintf(buff+len, ", \"ip\": \"-none-\""); + } + len += os_sprintf(buff+len, ", \"staticip\": \"%d.%d.%d.%d\"", IP2STR(&flashConfig.staticip)); + len += os_sprintf(buff+len, ", \"dhcp\": \"%s\"", flashConfig.staticip > 0 ? "off" : "on"); + + return len; } int ICACHE_FLASH_ATTR cgiWiFiConnStatus(HttpdConnData *connData) { - char buff[1024]; - int len; - - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - jsonHeader(connData, 200); - - len = os_sprintf(buff, "{"); - len += printWifiInfo(buff+len); - len += os_sprintf(buff+len, ", "); - - if (wifiReason != 0) { - len += os_sprintf(buff+len, "\"reason\": \"%s\", ", wifiGetReason()); - } - + char buff[1024]; + int len; + + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + jsonHeader(connData, 200); + + len = os_sprintf(buff, "{"); + len += printWifiInfo(buff+len); + len += os_sprintf(buff+len, ", "); + + if (wifiReason != 0) { + len += os_sprintf(buff+len, "\"reason\": \"%s\", ", wifiGetReason()); + } + #if 0 - // commented out 'cause often the client that requested the change can't get a request in to - // find out that it succeeded. Better to just wait the std 15 seconds... - int st=wifi_station_get_connect_status(); - if (st == STATION_GOT_IP) { - if (wifi_get_opmode() != 1) { - // Reset into AP-only mode sooner. - os_timer_disarm(&resetTimer); - os_timer_setfn(&resetTimer, resetTimerCb, NULL); - os_timer_arm(&resetTimer, 1000, 0); + // commented out 'cause often the client that requested the change can't get a request in to + // find out that it succeeded. Better to just wait the std 15 seconds... + int st=wifi_station_get_connect_status(); + if (st == STATION_GOT_IP) { + if (wifi_get_opmode() != 1) { + // Reset into AP-only mode sooner. + os_timer_disarm(&resetTimer); + os_timer_setfn(&resetTimer, resetTimerCb, NULL); + os_timer_arm(&resetTimer, 1000, 0); + } } - } #endif - - len += os_sprintf(buff+len, "\"x\":0}\n"); - //DBG(" -> %s\n", buff); - httpdSend(connData, buff, len); - return HTTPD_CGI_DONE; + + len += os_sprintf(buff+len, "\"x\":0}\n"); + //DBG(" -> %s\n", buff); + httpdSend(connData, buff, len); + return HTTPD_CGI_DONE; } // Cgi to return various Wifi information int ICACHE_FLASH_ATTR cgiWifiInfo(HttpdConnData *connData) { - char buff[1024]; - - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - - os_strcpy(buff, "{"); - printWifiInfo(buff+1); - os_strcat(buff, "}"); - - jsonHeader(connData, 200); - httpdSend(connData, buff, -1); - return HTTPD_CGI_DONE; + char buff[1024]; + + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + + os_strcpy(buff, "{"); + printWifiInfo(buff+1); + os_strcat(buff, "}"); + + jsonHeader(connData, 200); + httpdSend(connData, buff, -1); + return HTTPD_CGI_DONE; } // Init the wireless, which consists of setting a timer if we expect to connect to an AP // so we can revert to STA+AP mode if we can't connect. void ICACHE_FLASH_ATTR wifiInit() { - // wifi_set_phy_mode(2); // limit to 802.11b/g 'cause n is flaky - int x = wifi_get_opmode() & 0x3; - x = x; - DBG("Wifi init, mode=%s\n", wifiMode[x]); - configWifiIP(); - - // The default sleep mode should be modem_sleep, but we set it here explicitly for good - // measure. We can't use light_sleep because that powers off everthing and we would loose - // all connections. - wifi_set_sleep_type(MODEM_SLEEP_T); - - wifi_set_event_handler_cb(wifiHandleEventCb); - // check on the wifi in a few seconds to see whether we need to switch mode - os_timer_disarm(&resetTimer); - os_timer_setfn(&resetTimer, resetTimerCb, NULL); - os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); + + // Check te wifi opmode + int x = wifi_get_opmode() & 0x3; + +#ifdef CGIWIFI_DBG + os_printf("Wifi init, mode=%s\n",wifiMode[x]); +#endif + + // STATION parameters only on a full flash +#if defined(STA_SSID) && defined(STA_PASS) + if( x == 2 ){ + // Create struct for station config + struct station_config stconf; + // Call it + wifi_station_get_config(&stconf); + // Set parameters + if (os_strlen((char*)stconf.ssid) == 0 && os_strlen((char*)stconf.password) == 0) { + os_strncpy((char*)stconf.ssid, VERS_STR(STA_SSID), 32); + os_strncpy((char*)stconf.password, VERS_STR(STA_PASS), 64); +#ifdef CGIWIFI_DBG + os_printf("Wifi pre-config trying to connect to AP %s pw %s\n",(char*)stconf.ssid, (char*)stconf.password); +#endif + // wifi_set_phy_mode(2); // limit to 802.11b/g 'cause n is flaky + // Set wifi mode + wifi_set_opmode(3); // sta+ap, will switch to sta-only 15 secs after connecting + stconf.bssid_set = 0; + wifi_station_set_config(&stconf); + } + } +#endif + + // SOFT_AP parameters +#if defined(AP_SSID) && defined(AP_PASS) + // Call it + wifi_softap_get_config(&apconf); + // Clean memory and set the value of SSID + memset(apconf.ssid, 0, sizeof(apconf.ssid)); + os_memcpy(apconf.ssid, VERS_STR(AP_SSID), strlen(VERS_STR(AP_SSID))); + // Clean memory and set the value of PASS + memset(apconf.password, 0, sizeof(apconf.password)); + os_memcpy(apconf.password, VERS_STR(AP_PASS), strlen(VERS_STR(AP_PASS))); + // Specify the length of pass + apconf.ssid_len= os_strlen((char*)VERS_STR(AP_PASS)); +#ifdef AP_AUTH_MODE + // If set, use specified auth mode + apconf.authmode = AP_AUTH_MODE; +#else + // If not, use wpa wpa2 psk + apconf.authmode = AUTH_WPA_WPA2_PSK; +#endif +#ifdef AP_SSID_HIDDEN + // If set, use specified ssid hidden parameter + apconf.ssid_hidden = AP_SSID_HIDDEN; +#endif +#ifdef AP_MAX_CONN + // If set, use specified max conn number + apconf.max_connection = AP_MAX_CONN; +#endif +#ifdef AP_BEACON_INTERVAL + // If set use specified beacon interval + apconf.beacon_interval = AP_BEACON_INTERVAL; +#endif + // Set to use the new conf +#ifdef CGIWIFI_DBG + os_printf("Wifi AP parameters: %s pw %s\n",(char*)apconf.ssid, (char*)apconf.password); +#endif + // MUST BE called after enabling AP or STA+AP mode + wifi_softap_set_config(&apconf); +#endif // AP_SSID && AP_PASS + + configWifiIP(); + + // The default sleep mode should be modem_sleep, but we set it here explicitly for good + // measure. We can't use light_sleep because that powers off everthing and we would loose + // all connections. + wifi_set_sleep_type(MODEM_SLEEP_T); + + wifi_set_event_handler_cb(wifiHandleEventCb); + // check on the wifi in a few seconds to see whether we need to switch mode + os_timer_disarm(&resetTimer); + os_timer_setfn(&resetTimer, resetTimerCb, NULL); + os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); } diff --git a/esp-link/main.c b/esp-link/main.c index 09904e1..bfbea0f 100644 --- a/esp-link/main.c +++ b/esp-link/main.c @@ -123,28 +123,6 @@ void user_init(void) { os_printf("\n\n** %s\n", esp_link_version); os_printf("Flash config restore %s\n", restoreOk ? "ok" : "*FAILED*"); -#if defined(STA_SSID) && defined(STA_PASS) - int x = wifi_get_opmode() & 0x3; - if (x == 2) { - // we only force the STA settings when a full flash of the module has been made, which - // resets the wifi settings not to have anything configured - struct station_config stconf; - wifi_station_get_config(&stconf); - - if (os_strlen((char*)stconf.ssid) == 0 && os_strlen((char*)stconf.password) == 0) { - os_strncpy((char*)stconf.ssid, VERS_STR(STA_SSID), 32); - os_strncpy((char*)stconf.password, VERS_STR(STA_PASS), 64); -#ifdef CGIWIFI_DBG - os_printf("Wifi pre-config trying to connect to AP %s pw %s\n", - (char*)stconf.ssid, (char*)stconf.password); -#endif - wifi_set_opmode(3); // sta+ap, will switch to sta-only 15 secs after connecting - stconf.bssid_set = 0; - wifi_station_set_config(&stconf); - } - } -#endif - // Status LEDs statusInit(); serledInit(); From 896693b5b2173379e5e43f9189d9d5d19e5afada Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Sun, 27 Dec 2015 13:11:03 +0100 Subject: [PATCH 02/29] Soft-AP Settings Added Soft-AP settings support both in Makefile and web interface --- Makefile | 12 +- esp-link/cgi.c | 5 +- esp-link/cgiwifi.c | 1155 ++++++++++++++----------- esp-link/cgiwifi.h | 2 + esp-link/main.c | 20 +- html/wifi/wifiAp.html | 124 +++ html/wifi/wifiAp.js | 98 +++ html/wifi/{wifi.html => wifiSta.html} | 8 +- html/wifi/{wifi.js => wifiSta.js} | 0 9 files changed, 918 insertions(+), 506 deletions(-) create mode 100644 html/wifi/wifiAp.html create mode 100644 html/wifi/wifiAp.js rename html/wifi/{wifi.html => wifiSta.html} (96%) rename html/wifi/{wifi.js => wifiSta.js} (100%) diff --git a/Makefile b/Makefile index 95e2b82..98660ae 100644 --- a/Makefile +++ b/Makefile @@ -35,12 +35,12 @@ # Max connections default 4, ( 1 ~ 4 ) # Beacon interval default 100, ( 100 ~ 60000ms ) -AP_SSID ?=esp-link-test -AP_PASS ?=esp-link-test -# AP_AUTH_MODE ?=AUTH_WPA_WPA2_PSK -# AP_SSID_HIDDEN ?=0 -# AP_MAX_CONN ?=3 -# AP_BEACON_INTERVAL ?=150 +# AP_SSID ?= +# AP_PASS ?= +# AP_AUTH_MODE ?= +# AP_SSID_HIDDEN ?= +# AP_MAX_CONN ?= +# AP_BEACON_INTERVAL ?= # If CHANGE_TO_STA is set to "yes" the esp-link module will switch to station mode diff --git a/esp-link/cgi.c b/esp-link/cgi.c index 081ef49..c658fb6 100644 --- a/esp-link/cgi.c +++ b/esp-link/cgi.c @@ -106,7 +106,7 @@ int8_t ICACHE_FLASH_ATTR getUInt16Arg(HttpdConnData *connData, char *name, uint1 return 1; } -int8_t ICACHE_FLASH_ATTR getBoolArg(HttpdConnData *connData, char *name, bool *config) { +int8_t ICACHE_FLASH_ATTR getBoolArg(HttpdConnData *connData, char *name, uint8_t *config) { char buff[16]; int len = httpdFindArg(connData->getArgs, name, buff, sizeof(buff)); if (len < 0) return 0; // not found, skip @@ -206,7 +206,8 @@ int ICACHE_FLASH_ATTR cgiMenu(HttpdConnData *connData) { "{ " "\"menu\": [ " "\"Home\", \"/home.html\", " - "\"WiFI\", \"/wifi/wifi.html\", " + "\"WiFi Station\", \"/wifi/wifiSta.html\", " + "\"WiFi Soft-AP\", \"/wifi/wifiAp.html\", " "\"µC Console\", \"/console.html\", " "\"Services\", \"/services.html\", " #ifdef MQTT diff --git a/esp-link/cgiwifi.c b/esp-link/cgiwifi.c index cf36135..be63d85 100644 --- a/esp-link/cgiwifi.c +++ b/esp-link/cgiwifi.c @@ -1,7 +1,3 @@ -/* - Cgi/template routines for the /wifi url. - */ - /* * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): @@ -11,6 +7,8 @@ * ---------------------------------------------------------------------------- * Heavily modified and enhanced by Thorsten von Eicken in 2015 * ---------------------------------------------------------------------------- + * Once again heavily modified to add soft-ap settings by KatAst in 2015 + * ---------------------------------------------------------------------------- */ #include <esp8266.h> @@ -34,22 +32,23 @@ bool mdns_started = false; // ===== wifi status change callbacks static WifiStateChangeCb wifi_state_change_cb[4]; -// Temp store for new ap info. -static struct station_config stconf; +// Temp store for new staion config +struct station_config stconf; // Temp store for new ap config -static struct softap_config apconf; +struct softap_config apconf; uint8_t wifiState = wifiIsDisconnected; + // reasons for which a connection failed uint8_t wifiReason = 0; static char *wifiReasons[] = { - "", "unspecified", "auth_expire", "auth_leave", "assoc_expire", "assoc_toomany", "not_authed", - "not_assoced", "assoc_leave", "assoc_not_authed", "disassoc_pwrcap_bad", "disassoc_supchan_bad", - "ie_invalid", "mic_failure", "4way_handshake_timeout", "group_key_update_timeout", - "ie_in_4way_differs", "group_cipher_invalid", "pairwise_cipher_invalid", "akmp_invalid", - "unsupp_rsn_ie_version", "invalid_rsn_ie_cap", "802_1x_auth_failed", "cipher_suite_rejected", - "beacon_timeout", "no_ap_found" }; + "", "unspecified", "auth_expire", "auth_leave", "assoc_expire", "assoc_toomany", "not_authed", + "not_assoced", "assoc_leave", "assoc_not_authed", "disassoc_pwrcap_bad", "disassoc_supchan_bad", + "ie_invalid", "mic_failure", "4way_handshake_timeout", "group_key_update_timeout", + "ie_in_4way_differs", "group_cipher_invalid", "pairwise_cipher_invalid", "akmp_invalid", + "unsupp_rsn_ie_version", "invalid_rsn_ie_cap", "802_1x_auth_failed", "cipher_suite_rejected", + "beacon_timeout", "no_ap_found" }; static char *wifiMode[] = { 0, "STA", "AP", "AP+STA" }; static char *wifiPhy[] = { 0, "11b", "11g", "11n" }; @@ -57,100 +56,100 @@ static char *wifiPhy[] = { 0, "11b", "11g", "11n" }; void (*wifiStatusCb)(uint8_t); // callback when wifi status changes static char* ICACHE_FLASH_ATTR wifiGetReason(void) { - if (wifiReason <= 24) return wifiReasons[wifiReason]; - if (wifiReason >= 200 && wifiReason <= 201) return wifiReasons[wifiReason-200+24]; - return wifiReasons[1]; + if (wifiReason <= 24) return wifiReasons[wifiReason]; + if (wifiReason >= 200 && wifiReason <= 201) return wifiReasons[wifiReason-200+24]; + return wifiReasons[1]; } // handler for wifi status change callback coming in from espressif library static void ICACHE_FLASH_ATTR wifiHandleEventCb(System_Event_t *evt) { - switch (evt->event) { - case EVENT_STAMODE_CONNECTED: - wifiState = wifiIsConnected; - wifiReason = 0; - DBG("Wifi connected to ssid %s, ch %d\n", evt->event_info.connected.ssid, - evt->event_info.connected.channel); - statusWifiUpdate(wifiState); - break; - case EVENT_STAMODE_DISCONNECTED: - wifiState = wifiIsDisconnected; - wifiReason = evt->event_info.disconnected.reason; - DBG("Wifi disconnected from ssid %s, reason %s (%d)\n", - evt->event_info.disconnected.ssid, wifiGetReason(), evt->event_info.disconnected.reason); - statusWifiUpdate(wifiState); - break; - case EVENT_STAMODE_AUTHMODE_CHANGE: - DBG("Wifi auth mode: %d -> %d\n", - evt->event_info.auth_change.old_mode, evt->event_info.auth_change.new_mode); - break; - case EVENT_STAMODE_GOT_IP: - wifiState = wifiGotIP; - wifiReason = 0; - DBG("Wifi got ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR "\n", - IP2STR(&evt->event_info.got_ip.ip), IP2STR(&evt->event_info.got_ip.mask), - IP2STR(&evt->event_info.got_ip.gw)); - statusWifiUpdate(wifiState); - if (!mdns_started) - wifiStartMDNS(evt->event_info.got_ip.ip); - break; - case EVENT_SOFTAPMODE_STACONNECTED: - DBG("Wifi AP: station " MACSTR " joined, AID = %d\n", - MAC2STR(evt->event_info.sta_connected.mac), evt->event_info.sta_connected.aid); - break; - case EVENT_SOFTAPMODE_STADISCONNECTED: - DBG("Wifi AP: station " MACSTR " left, AID = %d\n", - MAC2STR(evt->event_info.sta_disconnected.mac), evt->event_info.sta_disconnected.aid); - break; - default: - break; - } - - for (int i = 0; i < 4; i++) { - if (wifi_state_change_cb[i] != NULL) (wifi_state_change_cb[i])(wifiState); - } + switch (evt->event) { + case EVENT_STAMODE_CONNECTED: + wifiState = wifiIsConnected; + wifiReason = 0; + DBG("Wifi connected to ssid %s, ch %d\n", evt->event_info.connected.ssid, + evt->event_info.connected.channel); + statusWifiUpdate(wifiState); + break; + case EVENT_STAMODE_DISCONNECTED: + wifiState = wifiIsDisconnected; + wifiReason = evt->event_info.disconnected.reason; + DBG("Wifi disconnected from ssid %s, reason %s (%d)\n", + evt->event_info.disconnected.ssid, wifiGetReason(), evt->event_info.disconnected.reason); + statusWifiUpdate(wifiState); + break; + case EVENT_STAMODE_AUTHMODE_CHANGE: + DBG("Wifi auth mode: %d -> %d\n", + evt->event_info.auth_change.old_mode, evt->event_info.auth_change.new_mode); + break; + case EVENT_STAMODE_GOT_IP: + wifiState = wifiGotIP; + wifiReason = 0; + DBG("Wifi got ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR "\n", + IP2STR(&evt->event_info.got_ip.ip), IP2STR(&evt->event_info.got_ip.mask), + IP2STR(&evt->event_info.got_ip.gw)); + statusWifiUpdate(wifiState); + if (!mdns_started) + wifiStartMDNS(evt->event_info.got_ip.ip); + break; + case EVENT_SOFTAPMODE_STACONNECTED: + DBG("Wifi AP: station " MACSTR " joined, AID = %d\n", + MAC2STR(evt->event_info.sta_connected.mac), evt->event_info.sta_connected.aid); + break; + case EVENT_SOFTAPMODE_STADISCONNECTED: + DBG("Wifi AP: station " MACSTR " left, AID = %d\n", + MAC2STR(evt->event_info.sta_disconnected.mac), evt->event_info.sta_disconnected.aid); + break; + default: + break; + } + + for (int i = 0; i < 4; i++) { + if (wifi_state_change_cb[i] != NULL) (wifi_state_change_cb[i])(wifiState); + } } void ICACHE_FLASH_ATTR wifiAddStateChangeCb(WifiStateChangeCb cb) { - for (int i = 0; i < 4; i++) { - if (wifi_state_change_cb[i] == cb) return; - if (wifi_state_change_cb[i] == NULL) { - wifi_state_change_cb[i] = cb; - return; - } + for (int i = 0; i < 4; i++) { + if (wifi_state_change_cb[i] == cb) return; + if (wifi_state_change_cb[i] == NULL) { + wifi_state_change_cb[i] = cb; + return; } - DBG("WIFI: max state change cb count exceeded\n"); + } + DBG("WIFI: max state change cb count exceeded\n"); } void ICACHE_FLASH_ATTR wifiStartMDNS(struct ip_addr ip) { - if (flashConfig.mdns_enable) { - struct mdns_info *mdns_info = (struct mdns_info *)os_zalloc(sizeof(struct mdns_info)); - mdns_info->host_name = flashConfig.hostname; - mdns_info->server_name = flashConfig.mdns_servername; - mdns_info->server_port = 80; - mdns_info->ipAddr = ip.addr; - espconn_mdns_init(mdns_info); - } - else { - espconn_mdns_server_unregister(); - espconn_mdns_close(); - } - mdns_started = true; + if (flashConfig.mdns_enable) { + struct mdns_info *mdns_info = (struct mdns_info *)os_zalloc(sizeof(struct mdns_info)); + mdns_info->host_name = flashConfig.hostname; + mdns_info->server_name = flashConfig.mdns_servername; + mdns_info->server_port = 80; + mdns_info->ipAddr = ip.addr; + espconn_mdns_init(mdns_info); + } + else { + espconn_mdns_server_unregister(); + espconn_mdns_close(); + } + mdns_started = true; } // ===== wifi scanning //WiFi access point data typedef struct { - char ssid[32]; - sint8 rssi; - char enc; + char ssid[32]; + sint8 rssi; + char enc; } ApData; //Scan result typedef struct { - char scanInProgress; //if 1, don't access the underlying stuff from the webpage. - ApData **apData; - int noAps; + char scanInProgress; //if 1, don't access the underlying stuff from the webpage. + ApData **apData; + int noAps; } ScanResultData; //Static scan status storage. @@ -159,126 +158,135 @@ static ScanResultData cgiWifiAps; //Callback the code calls when a wlan ap scan is done. Basically stores the result in //the cgiWifiAps struct. void ICACHE_FLASH_ATTR wifiScanDoneCb(void *arg, STATUS status) { - int n; - struct bss_info *bss_link = (struct bss_info *)arg; - - if (status!=OK) { - DBG("wifiScanDoneCb status=%d\n", status); - cgiWifiAps.scanInProgress=0; - return; - } - - //Clear prev ap data if needed. - if (cgiWifiAps.apData!=NULL) { - for (n=0; n<cgiWifiAps.noAps; n++) os_free(cgiWifiAps.apData[n]); - os_free(cgiWifiAps.apData); - } - - //Count amount of access points found. - n=0; - while (bss_link != NULL) { - bss_link = bss_link->next.stqe_next; - n++; - } - //Allocate memory for access point data - cgiWifiAps.apData=(ApData **)os_malloc(sizeof(ApData *)*n); - cgiWifiAps.noAps=n; - DBG("Scan done: found %d APs\n", n); - - //Copy access point data to the static struct - n=0; - bss_link = (struct bss_info *)arg; - while (bss_link != NULL) { - if (n>=cgiWifiAps.noAps) { - //This means the bss_link changed under our nose. Shouldn't happen! - //Break because otherwise we will write in unallocated memory. - DBG("Huh? I have more than the allocated %d aps!\n", cgiWifiAps.noAps); - break; - } - //Save the ap data. - cgiWifiAps.apData[n]=(ApData *)os_malloc(sizeof(ApData)); - cgiWifiAps.apData[n]->rssi=bss_link->rssi; - cgiWifiAps.apData[n]->enc=bss_link->authmode; - strncpy(cgiWifiAps.apData[n]->ssid, (char*)bss_link->ssid, 32); - DBG("bss%d: %s (%d)\n", n+1, (char*)bss_link->ssid, bss_link->rssi); - - bss_link = bss_link->next.stqe_next; - n++; - } - //We're done. + int n; + struct bss_info *bss_link = (struct bss_info *)arg; + + if (status!=OK) { + DBG("wifiScanDoneCb status=%d\n", status); cgiWifiAps.scanInProgress=0; + return; + } + + //Clear prev ap data if needed. + if (cgiWifiAps.apData!=NULL) { + for (n=0; n<cgiWifiAps.noAps; n++) os_free(cgiWifiAps.apData[n]); + os_free(cgiWifiAps.apData); + } + + //Count amount of access points found. + n=0; + while (bss_link != NULL) { + bss_link = bss_link->next.stqe_next; + n++; + } + //Allocate memory for access point data + cgiWifiAps.apData=(ApData **)os_malloc(sizeof(ApData *)*n); + cgiWifiAps.noAps=n; + DBG("Scan done: found %d APs\n", n); + + //Copy access point data to the static struct + n=0; + bss_link = (struct bss_info *)arg; + while (bss_link != NULL) { + if (n>=cgiWifiAps.noAps) { + //This means the bss_link changed under our nose. Shouldn't happen! + //Break because otherwise we will write in unallocated memory. + DBG("Huh? I have more than the allocated %d aps!\n", cgiWifiAps.noAps); + break; + } + //Save the ap data. + cgiWifiAps.apData[n]=(ApData *)os_malloc(sizeof(ApData)); + cgiWifiAps.apData[n]->rssi=bss_link->rssi; + cgiWifiAps.apData[n]->enc=bss_link->authmode; + strncpy(cgiWifiAps.apData[n]->ssid, (char*)bss_link->ssid, 32); + DBG("bss%d: %s (%d)\n", n+1, (char*)bss_link->ssid, bss_link->rssi); + + bss_link = bss_link->next.stqe_next; + n++; + } + //We're done. + cgiWifiAps.scanInProgress=0; } static ETSTimer scanTimer; static void ICACHE_FLASH_ATTR scanStartCb(void *arg) { - DBG("Starting a scan\n"); - wifi_station_scan(NULL, wifiScanDoneCb); + DBG("Starting a scan\n"); + wifi_station_scan(NULL, wifiScanDoneCb); } static int ICACHE_FLASH_ATTR cgiWiFiStartScan(HttpdConnData *connData) { - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - jsonHeader(connData, 200); - if (!cgiWifiAps.scanInProgress) { - cgiWifiAps.scanInProgress = 1; - os_timer_disarm(&scanTimer); - os_timer_setfn(&scanTimer, scanStartCb, NULL); - os_timer_arm(&scanTimer, 200, 0); - } - return HTTPD_CGI_DONE; + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + jsonHeader(connData, 200); + if (!cgiWifiAps.scanInProgress) { + cgiWifiAps.scanInProgress = 1; + os_timer_disarm(&scanTimer); + os_timer_setfn(&scanTimer, scanStartCb, NULL); + os_timer_arm(&scanTimer, 200, 0); + } + return HTTPD_CGI_DONE; } static int ICACHE_FLASH_ATTR cgiWiFiGetScan(HttpdConnData *connData) { - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - char buff[1460]; - const int chunk = 1460/64; // ssid is up to 32 chars - int len = 0; - - os_printf("GET scan: cgiData=%d noAps=%d\n", (int)connData->cgiData, cgiWifiAps.noAps); - - // handle continuation call, connData->cgiData-1 is the position in the scan results where we - // we need to continue sending from (using -1 'cause 0 means it's the first call) - if (connData->cgiData) { - int next = (int)connData->cgiData-1; - int pos = next; - while (pos < cgiWifiAps.noAps && pos < next+chunk) { - len += os_sprintf(buff+len, "{\"essid\": \"%s\", \"rssi\": %d, \"enc\": \"%d\"}%c\n", - cgiWifiAps.apData[pos]->ssid, cgiWifiAps.apData[pos]->rssi, cgiWifiAps.apData[pos]->enc, - (pos+1 == cgiWifiAps.noAps) ? ' ' : ','); - pos++; - } - // done or more? - if (pos == cgiWifiAps.noAps) { - len += os_sprintf(buff+len, "]}}\n"); - httpdSend(connData, buff, len); - return HTTPD_CGI_DONE; - } else { - connData->cgiData = (void*)(pos+1); - httpdSend(connData, buff, len); - return HTTPD_CGI_MORE; - } + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + char buff[1460]; + const int chunk = 1460/64; // ssid is up to 32 chars + int len = 0; + + os_printf("GET scan: cgiData=%d noAps=%d\n", (int)connData->cgiData, cgiWifiAps.noAps); + + // handle continuation call, connData->cgiData-1 is the position in the scan results where we + // we need to continue sending from (using -1 'cause 0 means it's the first call) + if (connData->cgiData) { + int next = (int)connData->cgiData-1; + int pos = next; + while (pos < cgiWifiAps.noAps && pos < next+chunk) { + len += os_sprintf(buff+len, "{\"essid\": \"%s\", \"rssi\": %d, \"enc\": \"%d\"}%c\n", + cgiWifiAps.apData[pos]->ssid, cgiWifiAps.apData[pos]->rssi, cgiWifiAps.apData[pos]->enc, + (pos+1 == cgiWifiAps.noAps) ? ' ' : ','); + pos++; } - - jsonHeader(connData, 200); - - if (cgiWifiAps.scanInProgress==1) { - //We're still scanning. Tell Javascript code that. - len = os_sprintf(buff, "{\n \"result\": { \n\"inProgress\": \"1\"\n }\n}\n"); - httpdSend(connData, buff, len); - return HTTPD_CGI_DONE; + // done or more? + if (pos == cgiWifiAps.noAps) { + len += os_sprintf(buff+len, "]}}\n"); + httpdSend(connData, buff, len); + return HTTPD_CGI_DONE; + } else { + connData->cgiData = (void*)(pos+1); + httpdSend(connData, buff, len); + return HTTPD_CGI_MORE; } - - len = os_sprintf(buff, "{\"result\": {\"inProgress\": \"0\", \"APs\": [\n"); - connData->cgiData = (void *)1; // start with first result next time we're called + } + + jsonHeader(connData, 200); + + if (cgiWifiAps.scanInProgress==1) { + //We're still scanning. Tell Javascript code that. + len = os_sprintf(buff, "{\n \"result\": { \n\"inProgress\": \"1\"\n }\n}\n"); httpdSend(connData, buff, len); - return HTTPD_CGI_MORE; + return HTTPD_CGI_DONE; + } + + len = os_sprintf(buff, "{\"result\": {\"inProgress\": \"0\", \"APs\": [\n"); + connData->cgiData = (void *)1; // start with first result next time we're called + httpdSend(connData, buff, len); + return HTTPD_CGI_MORE; } int ICACHE_FLASH_ATTR cgiWiFiScan(HttpdConnData *connData) { + if (connData->requestType == HTTPD_METHOD_GET) { return cgiWiFiGetScan(connData); - } else if (connData->requestType == HTTPD_METHOD_POST) { - return cgiWiFiStartScan(connData); - } else { + }else if(connData->requestType == HTTPD_METHOD_POST) + { + // DO NOT start APs scan in AP mode + int mode = wifi_get_opmode(); + if(mode==2){ + jsonHeader(connData, 400); + return HTTPD_CGI_DONE; + }else{ + return cgiWiFiStartScan(connData); + } + }else{ jsonHeader(connData, 404); return HTTPD_CGI_DONE; } @@ -290,39 +298,32 @@ int ICACHE_FLASH_ATTR cgiWiFiScan(HttpdConnData *connData) { #define RESET_TIMEOUT (15000) // 15 seconds static ETSTimer resetTimer; -// This routine is ran some time after a connection attempt to an access point. If -// the connect succeeds, this gets the module in STA-only mode. If it fails, it ensures -// that the module is in STA+AP mode so the user has a chance to recover. +/* + * This routine is ran some time after a connection attempt to an access point. + * If the connection succeeds and Makefile hard-coded CHANGE_TO_STA is set to yes, this gets the module in STA-only mode. + * If it fails and only STA mode is set, it ensures that the module is in STA+AP mode so the user has a chance to recover. + */ static void ICACHE_FLASH_ATTR resetTimerCb(void *arg) { + int x = wifi_station_get_connect_status(); int m = wifi_get_opmode() & 0x3; DBG("Wifi check: mode=%s status=%d\n", wifiMode[m], x); - if (x == STATION_GOT_IP) { - if (m != 1) { -#ifdef CHANGE_TO_STA - // We're happily connected, go to STA mode - DBG("Wifi got IP. Going into STA mode..\n"); - wifi_set_opmode(1); - os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); // check one more time after switching to STA-only -#endif - } - log_uart(false); - // no more resetTimer at this point, gotta use physical reset to recover if in trouble - } else { - - if (m != 3) { - DBG("Wifi connect failed. Going into STA+AP mode..\n"); - // Set STA+AP mode - wifi_set_opmode(3); -#ifdef AP_SSID - // Call ap set after mode change to AP or STA+AP - wifi_softap_set_config(&apconf); -#endif + if(m!=2){ + if( x == STATION_GOT_IP ){ + #ifdef CHANGE_TO_STA + wifi_set_opmode(1); + #endif + log_uart(false); + }else{ + log_uart(true); + DBG("Enabling/continuing uart log\n"); + if (m==1){ + wifi_set_opmode(3); + wifi_softap_set_config(&apconf); + } + os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); } - log_uart(true); - DBG("Enabling/continuing uart log\n"); - os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); } } @@ -331,191 +332,347 @@ static ETSTimer reassTimer; // Callback actually doing reassociation static void ICACHE_FLASH_ATTR reassTimerCb(void *arg) { - DBG("Wifi changing association\n"); - wifi_station_disconnect(); - stconf.bssid_set = 0; - wifi_station_set_config(&stconf); - wifi_station_connect(); - // Schedule check, we give some extra time (4x) 'cause the reassociation can cause the AP - // to have to change channel, and then the client needs to follow before it can see the - // IP address - os_timer_disarm(&resetTimer); - os_timer_setfn(&resetTimer, resetTimerCb, NULL); - os_timer_arm(&resetTimer, 4*RESET_TIMEOUT, 0); + DBG("Wifi changing association\n"); + wifi_station_disconnect(); + stconf.bssid_set = 0; + wifi_station_set_config(&stconf); + wifi_station_connect(); + // Schedule check, we give some extra time (4x) 'cause the reassociation can cause the AP + // to have to change channel, and then the client needs to follow before it can see the + // IP address + os_timer_disarm(&resetTimer); + os_timer_setfn(&resetTimer, resetTimerCb, NULL); + os_timer_arm(&resetTimer, 4*RESET_TIMEOUT, 0); } // This cgi uses the routines above to connect to a specific access point with the // given ESSID using the given password. int ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData) { - char essid[128]; - char passwd[128]; - - if (connData->conn==NULL) return HTTPD_CGI_DONE; - - int el = httpdFindArg(connData->getArgs, "essid", essid, sizeof(essid)); - int pl = httpdFindArg(connData->getArgs, "passwd", passwd, sizeof(passwd)); - - if (el > 0 && pl >= 0) { - //Set to 0 if you want to disable the actual reconnecting bit - os_strncpy((char*)stconf.ssid, essid, 32); - os_strncpy((char*)stconf.password, passwd, 64); - DBG("Wifi try to connect to AP %s pw %s\n", essid, passwd); - - //Schedule disconnect/connect - os_timer_disarm(&reassTimer); - os_timer_setfn(&reassTimer, reassTimerCb, NULL); - os_timer_arm(&reassTimer, 1000, 0); // 1 second for the response of this request to make it - jsonHeader(connData, 200); - } else { + + int mode = wifi_get_opmode(); + if(mode == 2){ jsonHeader(connData, 400); - httpdSend(connData, "Cannot parse ssid or password", -1); + httpdSend(connData, "Can't associate to an AP en SoftAP mode", -1); + return HTTPD_CGI_DONE; } - return HTTPD_CGI_DONE; + + char essid[128]; + char passwd[128]; + + if (connData->conn==NULL) return HTTPD_CGI_DONE; + + int el = httpdFindArg(connData->getArgs, "essid", essid, sizeof(essid)); + int pl = httpdFindArg(connData->getArgs, "passwd", passwd, sizeof(passwd)); + + if (el > 0 && pl >= 0) { + //Set to 0 if you want to disable the actual reconnecting bit + os_strncpy((char*)stconf.ssid, essid, 32); + os_strncpy((char*)stconf.password, passwd, 64); + DBG("Wifi try to connect to AP %s pw %s\n", essid, passwd); + + //Schedule disconnect/connect + os_timer_disarm(&reassTimer); + os_timer_setfn(&reassTimer, reassTimerCb, NULL); + os_timer_arm(&reassTimer, 1000, 0); // 1 second for the response of this request to make it + jsonHeader(connData, 200); + } else { + jsonHeader(connData, 400); + httpdSend(connData, "Cannot parse ssid or password", -1); + } + jsonHeader(connData, 400); + httpdSend(connData, "Invalid ssid or password", -1); + return HTTPD_CGI_DONE; } static bool ICACHE_FLASH_ATTR parse_ip(char *buff, ip_addr_t *ip_ptr) { - char *next = buff; // where to start parsing next integer - int found = 0; // number of integers parsed - uint32_t ip = 0; // the ip addres parsed - for (int i=0; i<32; i++) { // 32 is just a safety limit - char c = buff[i]; - if (c == '.' || c == 0) { - // parse the preceding integer and accumulate into IP address - bool last = c == 0; - buff[i] = 0; - uint32_t v = atoi(next); - ip = ip | ((v&0xff)<<(found*8)); - next = buff+i+1; // next integer starts after the '.' - found++; - if (last) { // if at end of string we better got 4 integers - ip_ptr->addr = ip; - return found == 4; - } - continue; - } - if (c < '0' || c > '9') return false; + char *next = buff; // where to start parsing next integer + int found = 0; // number of integers parsed + uint32_t ip = 0; // the ip addres parsed + for (int i=0; i<32; i++) { // 32 is just a safety limit + char c = buff[i]; + if (c == '.' || c == 0) { + // parse the preceding integer and accumulate into IP address + bool last = c == 0; + buff[i] = 0; + uint32_t v = atoi(next); + ip = ip | ((v&0xff)<<(found*8)); + next = buff+i+1; // next integer starts after the '.' + found++; + if (last) { // if at end of string we better got 4 integers + ip_ptr->addr = ip; + return found == 4; + } + continue; } - return false; + if (c < '0' || c > '9') return false; + } + return false; } #ifdef DEBUGIP static void ICACHE_FLASH_ATTR debugIP() { - struct ip_info info; - if (wifi_get_ip_info(0, &info)) { - os_printf("\"ip\": \"%d.%d.%d.%d\"\n", IP2STR(&info.ip.addr)); - os_printf("\"netmask\": \"%d.%d.%d.%d\"\n", IP2STR(&info.netmask.addr)); - os_printf("\"gateway\": \"%d.%d.%d.%d\"\n", IP2STR(&info.gw.addr)); - os_printf("\"hostname\": \"%s\"\n", wifi_station_get_hostname()); - } else { - os_printf("\"ip\": \"-none-\"\n"); - } + struct ip_info info; + if (wifi_get_ip_info(0, &info)) { + os_printf("\"ip\": \"%d.%d.%d.%d\"\n", IP2STR(&info.ip.addr)); + os_printf("\"netmask\": \"%d.%d.%d.%d\"\n", IP2STR(&info.netmask.addr)); + os_printf("\"gateway\": \"%d.%d.%d.%d\"\n", IP2STR(&info.gw.addr)); + os_printf("\"hostname\": \"%s\"\n", wifi_station_get_hostname()); + } else { + os_printf("\"ip\": \"-none-\"\n"); + } } #endif // configure Wifi, specifically DHCP vs static IP address based on flash config void ICACHE_FLASH_ATTR configWifiIP() { - if (flashConfig.staticip == 0) { - // let's DHCP! - wifi_station_set_hostname(flashConfig.hostname); - if (wifi_station_dhcpc_status() == DHCP_STARTED) - wifi_station_dhcpc_stop(); - wifi_station_dhcpc_start(); - DBG("Wifi uses DHCP, hostname=%s\n", flashConfig.hostname); - } else { - // no DHCP, we got static network config! - wifi_station_dhcpc_stop(); - struct ip_info ipi; - ipi.ip.addr = flashConfig.staticip; - ipi.netmask.addr = flashConfig.netmask; - ipi.gw.addr = flashConfig.gateway; - wifi_set_ip_info(0, &ipi); - DBG("Wifi uses static IP %d.%d.%d.%d\n", IP2STR(&ipi.ip.addr)); - } + if (flashConfig.staticip == 0) { + // let's DHCP! + wifi_station_set_hostname(flashConfig.hostname); + if (wifi_station_dhcpc_status() == DHCP_STARTED) + wifi_station_dhcpc_stop(); + wifi_station_dhcpc_start(); + DBG("Wifi uses DHCP, hostname=%s\n", flashConfig.hostname); + } else { + // no DHCP, we got static network config! + wifi_station_dhcpc_stop(); + struct ip_info ipi; + ipi.ip.addr = flashConfig.staticip; + ipi.netmask.addr = flashConfig.netmask; + ipi.gw.addr = flashConfig.gateway; + wifi_set_ip_info(0, &ipi); + DBG("Wifi uses static IP %d.%d.%d.%d\n", IP2STR(&ipi.ip.addr)); + } #ifdef DEBUGIP - debugIP(); + debugIP(); #endif } // Change special settings int ICACHE_FLASH_ATTR cgiWiFiSpecial(HttpdConnData *connData) { - char dhcp[8]; - char staticip[20]; - char netmask[20]; - char gateway[20]; - - if (connData->conn==NULL) return HTTPD_CGI_DONE; + char dhcp[8]; + char staticip[20]; + char netmask[20]; + char gateway[20]; + + if (connData->conn==NULL) return HTTPD_CGI_DONE; + + // get args and their string lengths + int dl = httpdFindArg(connData->getArgs, "dhcp", dhcp, sizeof(dhcp)); + int sl = httpdFindArg(connData->getArgs, "staticip", staticip, sizeof(staticip)); + int nl = httpdFindArg(connData->getArgs, "netmask", netmask, sizeof(netmask)); + int gl = httpdFindArg(connData->getArgs, "gateway", gateway, sizeof(gateway)); + + if (!(dl > 0 && sl >= 0 && nl >= 0 && gl >= 0)) { + jsonHeader(connData, 400); + httpdSend(connData, "Request is missing fields", -1); + return HTTPD_CGI_DONE; + } + + char url[64]; // redirect URL + if (os_strcmp(dhcp, "off") == 0) { + // parse static IP params + struct ip_info ipi; + bool ok = parse_ip(staticip, &ipi.ip); + if (nl > 0) ok = ok && parse_ip(netmask, &ipi.netmask); + else IP4_ADDR(&ipi.netmask, 255, 255, 255, 0); + if (gl > 0) ok = ok && parse_ip(gateway, &ipi.gw); + else ipi.gw.addr = 0; + if (!ok) { + jsonHeader(connData, 400); + httpdSend(connData, "Cannot parse static IP config", -1); + return HTTPD_CGI_DONE; + } + // save the params in flash + flashConfig.staticip = ipi.ip.addr; + flashConfig.netmask = ipi.netmask.addr; + flashConfig.gateway = ipi.gw.addr; + // construct redirect URL + os_sprintf(url, "{\"url\": \"http://%d.%d.%d.%d\"}", IP2STR(&ipi.ip)); + + } else { + // dynamic IP + flashConfig.staticip = 0; + os_sprintf(url, "{\"url\": \"http://%s\"}", flashConfig.hostname); + } + + configSave(); // ignore error... + // schedule change-over + os_timer_disarm(&reassTimer); + os_timer_setfn(&reassTimer, configWifiIP, NULL); + os_timer_arm(&reassTimer, 1000, 0); // 1 second for the response of this request to make it + // return redirect info + jsonHeader(connData, 200); + httpdSend(connData, url, -1); + return HTTPD_CGI_DONE; +} + +// ==== Soft-AP related functions + +// Change Soft-AP main settings +int ICACHE_FLASH_ATTR cgiApSettingsChange(HttpdConnData *connData) { - // get args and their string lengths - int dl = httpdFindArg(connData->getArgs, "dhcp", dhcp, sizeof(dhcp)); - int sl = httpdFindArg(connData->getArgs, "staticip", staticip, sizeof(staticip)); - int nl = httpdFindArg(connData->getArgs, "netmask", netmask, sizeof(netmask)); - int gl = httpdFindArg(connData->getArgs, "gateway", gateway, sizeof(gateway)); + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - if (!(dl > 0 && sl >= 0 && nl >= 0 && gl >= 0)) { + // No changes for Soft-AP in STA mode + int mode = wifi_get_opmode(); + if ( mode == 1 ){ jsonHeader(connData, 400); - httpdSend(connData, "Request is missing fields", -1); + httpdSend(connData, "No changes allowed in STA mode", -1); return HTTPD_CGI_DONE; } + // Get Soft-Ap config, just in case + wifi_softap_get_config(&apconf); + + char buff[96]; + int len; - char url[64]; // redirect URL - if (os_strcmp(dhcp, "off") == 0) { - // parse static IP params - struct ip_info ipi; - bool ok = parse_ip(staticip, &ipi.ip); - if (nl > 0) ok = ok && parse_ip(netmask, &ipi.netmask); - else IP4_ADDR(&ipi.netmask, 255, 255, 255, 0); - if (gl > 0) ok = ok && parse_ip(gateway, &ipi.gw); - else ipi.gw.addr = 0; - if (!ok) { + // Check extra security measure + len=httpdFindArg(connData->getArgs, "100", buff, sizeof(buff)); + if(len>0){ + if(atoi(buff)!=1){ jsonHeader(connData, 400); - httpdSend(connData, "Cannot parse static IP config", -1); return HTTPD_CGI_DONE; } - // save the params in flash - flashConfig.staticip = ipi.ip.addr; - flashConfig.netmask = ipi.netmask.addr; - flashConfig.gateway = ipi.gw.addr; - // construct redirect URL - os_sprintf(url, "{\"url\": \"http://%d.%d.%d.%d\"}", IP2STR(&ipi.ip)); + } + // Get the new SSID and set + len=httpdFindArg(connData->getArgs, "ap_ssid", buff, sizeof(buff)); + if(len>7 && len<30){ + // STRING PREPROCESSING DONE IN CLIENT SIDE + memset(apconf.ssid, 0, 32); + os_memcpy(apconf.ssid, buff, len); + }else{ + jsonHeader(connData, 400); + httpdSend(connData, "SSID name out of range", -1); + return HTTPD_CGI_DONE; + } + // Set new PASSWORD + len=httpdFindArg(connData->getArgs, "ap_password", buff, sizeof(buff)); + if(len>7 && len<62){ + // STRING PREPROCESSING DONE IN CLIENT SIDE + memset(apconf.password, 0, 64); + os_memcpy(apconf.password, buff, len); + }else{ + jsonHeader(connData, 400); + httpdSend(connData, "PASSWORD out of range", -1); + return HTTPD_CGI_DONE; + } + // Set max connection number + len=httpdFindArg(connData->getArgs, "ap_maxconn", buff, sizeof(buff)); + if(len>0){ - } else { - // dynamic IP - flashConfig.staticip = 0; - os_sprintf(url, "{\"url\": \"http://%s\"}", flashConfig.hostname); + int value = atoi(buff); + if(value > 0 && value <= 4){ + apconf.max_connection = value; + }else{ + // If out of range set by default + apconf.max_connection = 4; + } } + // Set beacon interval value + len=httpdFindArg(connData->getArgs, "ap_beacon", buff, sizeof(buff)); + if(len>0){ + int value = atoi(buff); + if(value >= 100 && value <= 60000){ + apconf.beacon_interval = value; + }else{ + // If out of range set by default + apconf.beacon_interval = 100; + } + } + // Set authentication mode + len=httpdFindArg(connData->getArgs, "ap_authmode", buff, sizeof(buff)); + if(len>0){ + int value = atoi(buff); + if(value >= 0 && value <= 4){ + apconf.authmode = value; + }else{ + // If out of range set by default + apconf.authmode = 4; + } + } + // Set ssid to be hidden or not + len=httpdFindArg(connData->getArgs, "ap_hidden", buff, sizeof(buff)); + if(len>0){ + int value = atoi(buff); + if(value == 0 || value == 1){ + apconf.ssid_hidden = value; + }else{ + // If out of range set by default + apconf.ssid_hidden = 0; + } + } + // Store new configuration + // This should apply new config values + wifi_softap_set_config(&apconf); + + jsonHeader(connData, 200); + return HTTPD_CGI_DONE; +} + +// Get current Soft-AP settings +int ICACHE_FLASH_ATTR cgiApSettingsInfo(HttpdConnData *connData) { + + char buff[1024]; + if (connData->conn == NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + os_sprintf(buff, + "{ " + "\"ap_ssid\": \"%s\", " + "\"ap_password\": \"%s\", " + "\"ap_authmode\": %d, " + "\"ap_maxconn\": %d, " + "\"ap_beacon\": %d, " + "\"ap_hidden\": \"%s\" " + " }", + apconf.ssid, + apconf.password, + apconf.authmode, + apconf.max_connection, + apconf.beacon_interval, + apconf.ssid_hidden ? "enabled" : "disabled" + ); - configSave(); // ignore error... - // schedule change-over - os_timer_disarm(&reassTimer); - os_timer_setfn(&reassTimer, configWifiIP, NULL); - os_timer_arm(&reassTimer, 1000, 0); // 1 second for the response of this request to make it - // return redirect info jsonHeader(connData, 200); - httpdSend(connData, url, -1); + httpdSend(connData, buff, -1); return HTTPD_CGI_DONE; } +// ===== Wifi set mode end info functions + //This cgi changes the operating mode: STA / AP / STA+AP int ICACHE_FLASH_ATTR cgiWiFiSetMode(HttpdConnData *connData) { + + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. int len; char buff[1024]; - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + int previous_mode = wifi_get_opmode(); len=httpdFindArg(connData->getArgs, "mode", buff, sizeof(buff)); + + int next_mode = atoi(buff); + if (len!=0) { - int m = atoi(buff); - DBG("Wifi switching to mode %d\n", m); - wifi_set_opmode(m&3); - // Call softap set after changing to AP or STA+AP - wifi_softap_set_config(&apconf); - - if (m == 1) { - // STA-only mode, reset into STA+AP after a timeout if we don't get an IP address + if (next_mode == 2){ + // moving to AP mode, so disconnect before leave STA mode + wifi_station_disconnect(); + } + + DBG("Wifi switching to mode %d\n", next_mode); + wifi_set_opmode(next_mode&3); + + if (previous_mode == 2) { + // movint to STA-only mode from AP, so reset into STA+AP after a timeout if we don't get an IP address + stconf.bssid_set = 0; + wifi_station_set_config(&stconf); + wifi_station_connect(); os_timer_disarm(&resetTimer); os_timer_setfn(&resetTimer, resetTimerCb, NULL); os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); } + if(previous_mode == 1){ + // moving to STA or STA+AP, so softap config call needed + wifi_softap_set_config(&apconf); + } jsonHeader(connData, 200); } else { jsonHeader(connData, 400); @@ -523,15 +680,30 @@ int ICACHE_FLASH_ATTR cgiWiFiSetMode(HttpdConnData *connData) { return HTTPD_CGI_DONE; } +// Collection of wifi info variables + static char *connStatuses[] = { "idle", "connecting", "wrong password", "AP not found", - "failed", "got IP address" }; + "failed", "got IP address" }; static char *wifiWarn[] = { 0, "Switch to <a href=\\\"#\\\" onclick=\\\"changeWifiMode(3)\\\">STA+AP mode</a>", - "<b>Can't scan in this mode!</b> Switch to <a href=\\\"#\\\" onclick=\\\"changeWifiMode(3)\\\">STA+AP mode</a>", + "Switch to <a href=\\\"#\\\" onclick=\\\"changeWifiMode(3)\\\">STA+AP mode</a>", "Switch to <a href=\\\"#\\\" onclick=\\\"changeWifiMode(1)\\\">STA mode</a>", }; +static char *apWifiWarn[] = { 0, + "Switch to <a href=\\\"#\\\" onclick=\\\"changeWifiMode(3)\\\">STA+AP mode</a>", + "Switch to <a href=\\\"#\\\" onclick=\\\"changeWifiMode(3)\\\">STA+AP mode</a>", + "Switch to <a href=\\\"#\\\" onclick=\\\"changeWifiMode(2)\\\">AP mode</a>", +}; + +static char *apAuthMode[] = { "OPEN", + "WEP", + "WPA_PSK", + "WPA2_PSK", + "WPA_WPA2_PSK", +}; + #ifdef CHANGE_TO_STA #define MODECHANGE "yes" #else @@ -540,176 +712,191 @@ static char *wifiWarn[] = { 0, // print various Wifi information into json buffer int ICACHE_FLASH_ATTR printWifiInfo(char *buff) { - int len; - - struct station_config stconf; - wifi_station_get_config(&stconf); - - uint8_t op = wifi_get_opmode() & 0x3; - char *mode = wifiMode[op]; - char *status = "unknown"; - int st = wifi_station_get_connect_status(); - if (st >= 0 && st < sizeof(connStatuses)) status = connStatuses[st]; - int p = wifi_get_phy_mode(); - char *phy = wifiPhy[p&3]; - char *warn = wifiWarn[op]; - sint8 rssi = wifi_station_get_rssi(); - if (rssi > 0) rssi = 0; - uint8 mac_addr[6]; - wifi_get_macaddr(0, mac_addr); - uint8_t chan = wifi_get_channel(); - - len = os_sprintf(buff, - "\"mode\": \"%s\", \"modechange\": \"%s\", \"ssid\": \"%s\", \"status\": \"%s\", \"phy\": \"%s\", " - "\"rssi\": \"%ddB\", \"warn\": \"%s\", \"mac\":\"%02x:%02x:%02x:%02x:%02x:%02x\", \"chan\":%d", - mode, MODECHANGE, (char*)stconf.ssid, status, phy, rssi, warn, - mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5], chan); - - struct ip_info info; - if (wifi_get_ip_info(0, &info)) { - len += os_sprintf(buff+len, ", \"ip\": \"%d.%d.%d.%d\"", IP2STR(&info.ip.addr)); - len += os_sprintf(buff+len, ", \"netmask\": \"%d.%d.%d.%d\"", IP2STR(&info.netmask.addr)); - len += os_sprintf(buff+len, ", \"gateway\": \"%d.%d.%d.%d\"", IP2STR(&info.gw.addr)); - len += os_sprintf(buff+len, ", \"hostname\": \"%s\"", flashConfig.hostname); - } else { - len += os_sprintf(buff+len, ", \"ip\": \"-none-\""); - } - len += os_sprintf(buff+len, ", \"staticip\": \"%d.%d.%d.%d\"", IP2STR(&flashConfig.staticip)); - len += os_sprintf(buff+len, ", \"dhcp\": \"%s\"", flashConfig.staticip > 0 ? "off" : "on"); - - return len; + + int len; + //struct station_config stconf; + wifi_station_get_config(&stconf); + //struct softap_config apconf; + wifi_softap_get_config(&apconf); + + uint8_t op = wifi_get_opmode() & 0x3; + char *mode = wifiMode[op]; + char *status = "unknown"; + int st = wifi_station_get_connect_status(); + if (st >= 0 && st < sizeof(connStatuses)) status = connStatuses[st]; + int p = wifi_get_phy_mode(); + char *phy = wifiPhy[p&3]; + char *warn = wifiWarn[op]; + char *apwarn = apWifiWarn[op]; + char *apauth = apAuthMode[apconf.authmode]; + sint8 rssi = wifi_station_get_rssi(); + if (rssi > 0) rssi = 0; + uint8 mac_addr[6]; + uint8 apmac_addr[6]; + wifi_get_macaddr(0, mac_addr); + wifi_get_macaddr(1, apmac_addr); + uint8_t chan = wifi_get_channel(); + + len = os_sprintf(buff, + "\"mode\": \"%s\", \"modechange\": \"%s\", \"ssid\": \"%s\", \"status\": \"%s\", \"phy\": \"%s\", " + "\"rssi\": \"%ddB\", \"warn\": \"%s\", \"apwarn\": \"%s\",\"mac\":\"%02x:%02x:%02x:%02x:%02x:%02x\", \"chan\":\"%d\", \"apssid\": \"%s\", " + "\"appass\": \"%s\", \"apchan\": \"%d\", \"apmaxc\": \"%d\", \"aphidd\": \"%s\", \"apbeac\": \"%d\", \"apauth\": \"%s\",\"apmac\":\"%02x:%02x:%02x:%02x:%02x:%02x\"", + mode, MODECHANGE, (char*)stconf.ssid, status, phy, rssi, warn, apwarn, + mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5], chan, (char*)apconf.ssid,(char*)apconf.password,apconf.channel,apconf.max_connection,apconf.ssid_hidden?"enabled":"disabled",apconf.beacon_interval, apauth,apmac_addr[0], apmac_addr[1], apmac_addr[2], apmac_addr[3], apmac_addr[4], apmac_addr[5]); + + struct ip_info info; + if (wifi_get_ip_info(0, &info)) { + len += os_sprintf(buff+len, ", \"ip\": \"%d.%d.%d.%d\"", IP2STR(&info.ip.addr)); + len += os_sprintf(buff+len, ", \"netmask\": \"%d.%d.%d.%d\"", IP2STR(&info.netmask.addr)); + len += os_sprintf(buff+len, ", \"gateway\": \"%d.%d.%d.%d\"", IP2STR(&info.gw.addr)); + len += os_sprintf(buff+len, ", \"hostname\": \"%s\"", flashConfig.hostname); + } else { + len += os_sprintf(buff+len, ", \"ip\": \"-none-\""); + } + len += os_sprintf(buff+len, ", \"staticip\": \"%d.%d.%d.%d\"", IP2STR(&flashConfig.staticip)); + len += os_sprintf(buff+len, ", \"dhcp\": \"%s\"", flashConfig.staticip > 0 ? "off" : "on"); + + return len; } int ICACHE_FLASH_ATTR cgiWiFiConnStatus(HttpdConnData *connData) { - char buff[1024]; - int len; - - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - jsonHeader(connData, 200); - - len = os_sprintf(buff, "{"); - len += printWifiInfo(buff+len); - len += os_sprintf(buff+len, ", "); - - if (wifiReason != 0) { - len += os_sprintf(buff+len, "\"reason\": \"%s\", ", wifiGetReason()); - } - + char buff[1024]; + int len; + + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + jsonHeader(connData, 200); + + len = os_sprintf(buff, "{"); + len += printWifiInfo(buff+len); + len += os_sprintf(buff+len, ", "); + + if (wifiReason != 0) { + len += os_sprintf(buff+len, "\"reason\": \"%s\", ", wifiGetReason()); + } + #if 0 - // commented out 'cause often the client that requested the change can't get a request in to - // find out that it succeeded. Better to just wait the std 15 seconds... - int st=wifi_station_get_connect_status(); - if (st == STATION_GOT_IP) { - if (wifi_get_opmode() != 1) { - // Reset into AP-only mode sooner. - os_timer_disarm(&resetTimer); - os_timer_setfn(&resetTimer, resetTimerCb, NULL); - os_timer_arm(&resetTimer, 1000, 0); - } + // commented out 'cause often the client that requested the change can't get a request in to + // find out that it succeeded. Better to just wait the std 15 seconds... + int st=wifi_station_get_connect_status(); + if (st == STATION_GOT_IP) { + if (wifi_get_opmode() != 1) { + // Reset into AP-only mode sooner. + os_timer_disarm(&resetTimer); + os_timer_setfn(&resetTimer, resetTimerCb, NULL); + os_timer_arm(&resetTimer, 1000, 0); } + } #endif - - len += os_sprintf(buff+len, "\"x\":0}\n"); - //DBG(" -> %s\n", buff); - httpdSend(connData, buff, len); - return HTTPD_CGI_DONE; + + len += os_sprintf(buff+len, "\"x\":0}\n"); + DBG(" -> %s\n", buff); + httpdSend(connData, buff, len); + return HTTPD_CGI_DONE; } // Cgi to return various Wifi information int ICACHE_FLASH_ATTR cgiWifiInfo(HttpdConnData *connData) { - char buff[1024]; - - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - - os_strcpy(buff, "{"); - printWifiInfo(buff+1); - os_strcat(buff, "}"); - - jsonHeader(connData, 200); - httpdSend(connData, buff, -1); - return HTTPD_CGI_DONE; + char buff[1024]; + + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + + os_strcpy(buff, "{"); + printWifiInfo(buff+1); + os_strcat(buff, "}"); + + jsonHeader(connData, 200); + httpdSend(connData, buff, -1); + return HTTPD_CGI_DONE; } -// Init the wireless, which consists of setting a timer if we expect to connect to an AP -// so we can revert to STA+AP mode if we can't connect. +/* Init the wireless + * + * Call both Soft-AP and Station default config + * Change values according to Makefile hard-coded variables + * Anyway set wifi opmode to STA+AP, it will change to STA if CHANGE_TO_STA is set to yes in Makefile + * Call a timer to check the STA connection + */ void ICACHE_FLASH_ATTR wifiInit() { - + // Check te wifi opmode int x = wifi_get_opmode() & 0x3; -#ifdef CGIWIFI_DBG - os_printf("Wifi init, mode=%s\n",wifiMode[x]); -#endif + // Set opmode to 3 to let system scan aps, otherwise it won't scan + wifi_set_opmode(3); - // STATION parameters only on a full flash -#if defined(STA_SSID) && defined(STA_PASS) + // Call both STATION and SOFTAP default config + wifi_station_get_config_default(&stconf); + wifi_softap_get_config_default(&apconf); + + #ifdef CGIWIFI_DBG + os_printf("Wifi init, mode=%s\n",wifiMode[x]); + #endif + + // STATION parameters only on a full flash, because default opmode is 2 + #if defined(STA_SSID) && defined(STA_PASS) if( x == 2 ){ - // Create struct for station config - struct station_config stconf; - // Call it - wifi_station_get_config(&stconf); // Set parameters if (os_strlen((char*)stconf.ssid) == 0 && os_strlen((char*)stconf.password) == 0) { os_strncpy((char*)stconf.ssid, VERS_STR(STA_SSID), 32); os_strncpy((char*)stconf.password, VERS_STR(STA_PASS), 64); -#ifdef CGIWIFI_DBG + #ifdef CGIWIFI_DBG os_printf("Wifi pre-config trying to connect to AP %s pw %s\n",(char*)stconf.ssid, (char*)stconf.password); -#endif + #endif // wifi_set_phy_mode(2); // limit to 802.11b/g 'cause n is flaky - // Set wifi mode - wifi_set_opmode(3); // sta+ap, will switch to sta-only 15 secs after connecting stconf.bssid_set = 0; wifi_station_set_config(&stconf); } } -#endif - - // SOFT_AP parameters -#if defined(AP_SSID) && defined(AP_PASS) - // Call it - wifi_softap_get_config(&apconf); - // Clean memory and set the value of SSID - memset(apconf.ssid, 0, sizeof(apconf.ssid)); - os_memcpy(apconf.ssid, VERS_STR(AP_SSID), strlen(VERS_STR(AP_SSID))); - // Clean memory and set the value of PASS - memset(apconf.password, 0, sizeof(apconf.password)); - os_memcpy(apconf.password, VERS_STR(AP_PASS), strlen(VERS_STR(AP_PASS))); - // Specify the length of pass - apconf.ssid_len= os_strlen((char*)VERS_STR(AP_PASS)); -#ifdef AP_AUTH_MODE - // If set, use specified auth mode - apconf.authmode = AP_AUTH_MODE; -#else - // If not, use wpa wpa2 psk - apconf.authmode = AUTH_WPA_WPA2_PSK; -#endif -#ifdef AP_SSID_HIDDEN - // If set, use specified ssid hidden parameter - apconf.ssid_hidden = AP_SSID_HIDDEN; -#endif -#ifdef AP_MAX_CONN - // If set, use specified max conn number - apconf.max_connection = AP_MAX_CONN; -#endif -#ifdef AP_BEACON_INTERVAL - // If set use specified beacon interval - apconf.beacon_interval = AP_BEACON_INTERVAL; -#endif - // Set to use the new conf -#ifdef CGIWIFI_DBG - os_printf("Wifi AP parameters: %s pw %s\n",(char*)apconf.ssid, (char*)apconf.password); -#endif - // MUST BE called after enabling AP or STA+AP mode - wifi_softap_set_config(&apconf); -#endif // AP_SSID && AP_PASS - + #endif + + // Change SOFT_AP parameters if defined + #if defined(AP_SSID) && defined(AP_PASS) + // Clean memory and set the value of SSID + memset(apconf.ssid, 0, 32); + os_memcpy(apconf.ssid, VERS_STR(AP_SSID), strlen(VERS_STR(AP_SSID))); + + // Clean memory and set the value of PASS + memset(apconf.password, 0, 64); + os_memcpy(apconf.password, VERS_STR(AP_PASS), strlen(VERS_STR(AP_PASS))); + + // Specify the length of pass + apconf.ssid_len= os_strlen((char*)VERS_STR(AP_PASS)); + #ifdef AP_AUTH_MODE + // If set, use specified auth mode + apconf.authmode = AP_AUTH_MODE; + #else + // If not, use wpa wpa2 psk + apconf.authmode = AUTH_WPA_WPA2_PSK; + #endif + #ifdef AP_SSID_HIDDEN + // If set, use specified ssid hidden parameter + apconf.ssid_hidden = AP_SSID_HIDDEN; + #endif + #ifdef AP_MAX_CONN + // If set, use specified max conn number + apconf.max_connection = AP_MAX_CONN; + #endif + #ifdef AP_BEACON_INTERVAL + // If set use specified beacon interval + apconf.beacon_interval = AP_BEACON_INTERVAL; + #endif + // Check save softap config + bool softap_set_conf = wifi_softap_set_config(&apconf); + #ifdef CGIWIFI_DBG + // Debug info + os_printf("Wifi AP parameters: %s pw %s\n",(char*)apconf.ssid, (char*)apconf.password); + os_printf("Wifi Soft-AP parameters set: %s\n",softap_set_conf? "success":"fail"); + #endif + + #endif // AP_SSID && AP_PASS + configWifiIP(); - + // The default sleep mode should be modem_sleep, but we set it here explicitly for good // measure. We can't use light_sleep because that powers off everthing and we would loose // all connections. wifi_set_sleep_type(MODEM_SLEEP_T); - + wifi_set_event_handler_cb(wifiHandleEventCb); // check on the wifi in a few seconds to see whether we need to switch mode os_timer_disarm(&resetTimer); diff --git a/esp-link/cgiwifi.h b/esp-link/cgiwifi.h index e2e98bc..5fa177c 100644 --- a/esp-link/cgiwifi.h +++ b/esp-link/cgiwifi.h @@ -13,6 +13,8 @@ int cgiWiFiConnect(HttpdConnData *connData); int cgiWiFiSetMode(HttpdConnData *connData); int cgiWiFiConnStatus(HttpdConnData *connData); int cgiWiFiSpecial(HttpdConnData *connData); +int cgiApSettingsChange(HttpdConnData *connData); +int cgiApSettingsInfo(HttpdConnData *connData); void configWifiIP(); void wifiInit(void); void wifiAddStateChangeCb(WifiStateChangeCb cb); diff --git a/esp-link/main.c b/esp-link/main.c index bfbea0f..1bbf3b6 100644 --- a/esp-link/main.c +++ b/esp-link/main.c @@ -72,6 +72,8 @@ HttpdBuiltInUrl builtInUrls[] = { { "/wifi/connstatus", cgiWiFiConnStatus, NULL }, { "/wifi/setmode", cgiWiFiSetMode, NULL }, { "/wifi/special", cgiWiFiSpecial, NULL }, + { "/wifi/apinfo", cgiApSettingsInfo, NULL }, + { "/wifi/apchange", cgiApSettingsChange, NULL }, { "/system/info", cgiSystemInfo, NULL }, { "/system/update", cgiSystemSet, NULL }, { "/services/info", cgiServicesInfo, NULL }, @@ -86,7 +88,6 @@ HttpdBuiltInUrl builtInUrls[] = { #ifdef SHOW_HEAP_USE static ETSTimer prHeapTimer; - static void ICACHE_FLASH_ATTR prHeapTimerCb(void *arg) { os_printf("Heap: %ld\n", (unsigned long)system_get_free_heap_size()); } @@ -109,26 +110,25 @@ void user_rf_pre_init(void) { // Main routine to initialize esp-link. void user_init(void) { + // get the flash config so we know how to init things -// configWipe(); // uncomment to reset the config for testing purposes + // configWipe(); // uncomment to reset the config for testing purposes bool restoreOk = configRestore(); - // init gpio pin registers + // Init gpio pin registers gpio_init(); gpio_output_set(0, 0, 0, (1<<15)); // some people tie it to GND, gotta ensure it's disabled // init UART uart_init(flashConfig.baud_rate, 115200); logInit(); // must come after init of uart - // say hello (leave some time to cause break in TX after boot loader's msg + // Say hello (leave some time to cause break in TX after boot loader's msg os_delay_us(10000L); os_printf("\n\n** %s\n", esp_link_version); os_printf("Flash config restore %s\n", restoreOk ? "ok" : "*FAILED*"); - // Status LEDs statusInit(); serledInit(); // Wifi wifiInit(); - // init the flash filesystem with the html stuff espFsInit(&_binary_espfs_img_start); //EspFsInitResult res = espFsInit(&_binary_espfs_img_start); @@ -153,16 +153,14 @@ void user_init(void) { NOTICE("Flash map %s, manuf 0x%02lX chip 0x%04lX", flash_maps[system_get_flash_size_map()], fid & 0xff, (fid&0xff00)|((fid>>16)&0xff)); NOTICE("** esp-link ready"); - + + // Init SNTP service cgiServicesSNTPInit(); - #ifdef MQTT NOTICE("initializing MQTT"); mqtt_client_init(); #endif - NOTICE("initializing user application"); app_init(); - - NOTICE("waiting for work to do..."); + NOTICE("Waiting for work to do..."); } diff --git a/html/wifi/wifiAp.html b/html/wifi/wifiAp.html new file mode 100644 index 0000000..e93e54d --- /dev/null +++ b/html/wifi/wifiAp.html @@ -0,0 +1,124 @@ + <div id="main"> + <div class="header"> + <h1>WiFi Soft-AP Configuration</h1> + </div> + + <div class="content"> + <div class="pure-g"> + <div class="pure-u-1 pure-u-md-1-2"> + <div class="card"> + <h1>Soft-AP State</h1> + <div id="wifi-spinner" class="spinner spinner-small"> + </div> + <table id="wifi-table" class="pure-table pure-table-horizontal" hidden><tbody> + <tr><td>WiFi mode</td><td id="wifi-mode"></td></tr> + <tr><td>Soft-AP SSID</td><td id="wifi-apssid"></td></tr> + <tr><td>Soft-AP Password</td><td id="wifi-appass"></td></tr> + <tr><td>Soft-AP Channel</td><td id="wifi-apchan"></td></tr> + <tr><td>Soft-AP Max Conn</td><td id="wifi-apmaxc"></td></tr> + <tr><td>Soft-AP Hidden</td><td id="wifi-aphidd"></td></tr> + <tr><td>Soft-AP Beacon Int</td><td id="wifi-apbeac"></td></tr> + <tr><td>Soft-AP Auth Mode</td><td id="wifi-apauth"></td></tr> + <tr><td>Soft-AP MAC</td><td id="wifi-apmac"></td></tr> + <tr><td colspan="2" id="wifi-apwarn"></td></tr> + </tbody> </table> + </div><!-- card--> + </div><!-- pure-u-1 --> + <div class="pure-u-1 pure-u-md-1-2"> + + <div class="card"> + <h1>Soft-AP Settings</h1> + <div id="AP_Settings-spinner" class="spinner spinner-small"></div> + + <form action="#" id="AP_Settings-form" class="pure-form" hidden> + <!-- <input type="text" id="conn_check" name="ap_connex" value="0" hidden>--> + <legend>Soft-AP main settings, use with care!</legend> + + <div class="pure-form-stacked"> + <label>Soft-AP SSID</label> + <input type="text" name="ap_ssid" /> + <div class="popup">Change the name of your AP!</div> + </div> + + <div class="pure-form-stacked"> + <label>Soft-AP Password</label> + <input type="text" name="ap_password" /> + <div class="popup">Password must be at least 8 chars long!</div> + </div> + + <div class="pure-form-stacked"> + <legend>Soft-AP Advanced Settings</legend> + </div> + + <div class="form-horizontal"> + <label for="AP_Settings-ron" style="margin-right:1em"> + <input type="radio" name="ap" value="on" id="AP_Settings-ron"/> + Show </label> + <label for="AP_Settings-roff" style="margin-right:1em"> + <input type="radio" name="ap" value="off" id="AP_Settings-roff"/> + Hide </label> + </div> + + <div id="AP_Settings-off" class="pure-form-stacked"></div> + <div id="AP_Settings-on" class="pure-form-stacked"> + + <div class="pure-form-stacked"> + <label>Soft-AP Max Connections</label> + <input type="text" name="ap_maxconn" /> + <div class="popup">Max 4 ( default 4 )</div> + </div> + + <div class="pure-form-stacked"> + <label>Soft-AP Beacon Interval</label> + <input type="text" name="ap_beacon" /> + <div class="popup">Between 100 - 60000 ms ( default 100ms )</div> + </div> + + <div class="pure-form-stacked"> + <label>Soft-AP Auth Mode</label> + <select name="ap_authmode" href="#"> + <option value="0">OPEN</option> + <option value="1">WEP</option> + <option value="2">WPA_PSK</option> + <option value="3">WPA2_PSK</option> + <option value="4">WPA_WPA2_PSK</option> + </select> + <div class="popup">Default WPA_WPA2_PSK</div> + </div> + + <div class="form-horizontal"> + <label><input type="checkbox" name="ap_hidden" />Soft-AP SSID hidden</label> + <div class="popup">Check this box to hide you Soft-AP SSID ( default Not Hidden )</div> + </div> + + </div> + + <button id="AP_Settings-button" type="submit" class="pure-button button-primary"> + Change Soft-AP settings! + </button> + + </form> + </div> + </div><!-- pure-u-1 --> + </div><!-- pure-g --> + </div><!-- content --> + </div><!-- main --> +</div><!-- layout --> + +<script type="text/javascript"> +</script> +<script src="wifiAp.js"></script> +<script type="text/javascript"> +onLoad(function() { + // Show info about AP + getWifiInfo(); + // Fetch actual settings + fetchApSettings(); + // Hide advanced settings + undoApAdvanced(); + bnd($("#AP_Settings-ron"), "click", doApAdvanced); + bnd($("#AP_Settings-roff"), "click", undoApAdvanced); + bnd($("#AP_Settings-form"), "submit", changeApSettings); +}); +</script> +</body></html> diff --git a/html/wifi/wifiAp.js b/html/wifi/wifiAp.js new file mode 100644 index 0000000..e2fef60 --- /dev/null +++ b/html/wifi/wifiAp.js @@ -0,0 +1,98 @@ +var specials = []; +specials["ap_ssid"] = "SSID name"; +specials["ap_password"] = "PASSWORD"; +specials["ap_maxconn"] = "Max Connections number"; +specials["ap_beacon"] = "Beacon Interval"; + +function changeWifiMode(m) { + blockScan = 1; + hideWarning(); + ajaxSpin("POST", "setmode?mode=" + m, function(resp) { + showNotification("Mode changed"); + window.setTimeout(getWifiInfo, 100); + blockScan = 0; + }, function(s, st) { + showWarning("Error changing mode: " + st); + window.setTimeout(getWifiInfo, 100); + blockScan = 0; + }); +} + +function changeApSettings(e) { + e.preventDefault(); + var url = "/wifi/apchange?100=1"; + var i, inputs = document.querySelectorAll("#" + e.target.id + " input,select"); + for (i = 0; i < inputs.length; i++) { + if (inputs[i].type == "checkbox") { + var val = (inputs[i].checked) ? 1 : 0; + url += "&" + inputs[i].name + "=" + val; + } + else{ + var clean = inputs[i].value.replace(/[^\w]/gi, ""); + var comp = clean.localeCompare(inputs[i].value); + if ( comp != 0 ){ + showWarning("Invalid characters in " + specials[inputs[i].name]); + return; + } + url += "&" + inputs[i].name + "=" + clean; + } + }; + + hideWarning(); + var n = e.target.id.replace("-form", ""); + var cb = $("#" + n + "-button"); + addClass(cb, "pure-button-disabled"); + ajaxSpin("POST", url, function (resp) { + showNotification(n + " updated"); + removeClass(cb, "pure-button-disabled"); + window.setTimeout(getWifiInfo, 100); + }, function (s, st) { + showWarning(st); + removeClass(cb, "pure-button-disabled"); + window.setTimeout(fetchApSettings, 2000); + }); +} + +function displayApSettings(data) { + Object.keys(data).forEach(function (v) { + el = $("#" + v); + if (el != null) { + if (el.nodeName === "INPUT") el.value = data[v]; + else el.innerHTML = data[v]; + return; + } + + el = document.querySelector('input[name="' + v + '"]'); + if (el == null) + el = document.querySelector('select[name="' + v + '"]'); + + if (el != null) { + if (el.type == "checkbox") { + el.checked = data[v] == "enabled"; + } else el.value = data[v]; + } + }); + + $("#AP_Settings-spinner").setAttribute("hidden", ""); + $("#AP_Settings-form").removeAttribute("hidden"); + showWarning("Don't modify SOFTAP parameters with active connections"); + window.setTimeout(hideWarning(), 2000); +} + +function fetchApSettings() { + ajaxJson("GET", "/wifi/apinfo", displayApSettings, function () { + window.setTimeout(fetchApSettings, 1000); + }); +} + +function doApAdvanced() { + $('#AP_Settings-on').removeAttribute('hidden'); + $("#AP_Settings-off").setAttribute("hidden", ""); + $("#AP_Settings-roff").removeAttribute("checked"); +} + +function undoApAdvanced(){ + $("#AP_Settings-on").setAttribute("hidden", ""); + $("#AP_Settings-off").removeAttribute("hidden"); + $("#AP_Settings-roff").setAttribute("checked", ""); +} \ No newline at end of file diff --git a/html/wifi/wifi.html b/html/wifi/wifiSta.html similarity index 96% rename from html/wifi/wifi.html rename to html/wifi/wifiSta.html index f6d6646..bdc6dca 100644 --- a/html/wifi/wifi.html +++ b/html/wifi/wifiSta.html @@ -1,6 +1,6 @@ <div id="main"> <div class="header"> - <h1>WiFi Configuration</h1> + <h1>WiFi Station Configuration</h1> </div> <div class="content"> @@ -19,7 +19,9 @@ <tr><td>WiFi MAC</td><td id="wifi-mac"></td></tr> <tr><td colspan="2" id="wifi-warn"></td></tr> </tbody> </table> - </div></div> + </div> + + </div> <div class="pure-u-1 pure-u-md-1-2"><div class="card"> <h1>WiFi Association</h1> <p id="reconnect" style="color: #600" hidden></p> @@ -70,7 +72,7 @@ <script type="text/javascript"> </script> -<script src="wifi.js"></script> +<script src="wifiSta.js"></script> <script type="text/javascript"> onLoad(function() { getWifiInfo(); diff --git a/html/wifi/wifi.js b/html/wifi/wifiSta.js similarity index 100% rename from html/wifi/wifi.js rename to html/wifi/wifiSta.js From 887c5a66cc7b5f0f0b01b8f3a223745019520823 Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Sun, 27 Dec 2015 13:11:59 +0100 Subject: [PATCH 03/29] Compiler error Even if I use the same compiler those errors show up. I had to change some bool to uint8_t to make it works --- esp-link/cgi.h | 2 +- esp-link/cgipins.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esp-link/cgi.h b/esp-link/cgi.h index cb897b0..330a5e6 100644 --- a/esp-link/cgi.h +++ b/esp-link/cgi.h @@ -26,7 +26,7 @@ int8_t getUInt16Arg(HttpdConnData *connData, char *name, uint16_t *config); // Get the HTTP query-string param 'name' and store it boolean value at 'config', // supports 1/true and 0/false, returns -1 on error, 0 if not found, 1 if found -int8_t getBoolArg(HttpdConnData *connData, char *name, bool *config); +int8_t getBoolArg(HttpdConnData *connData, char *name, uint8_t *config); int cgiMenu(HttpdConnData *connData); diff --git a/esp-link/cgipins.c b/esp-link/cgipins.c index 8455a16..6273389 100644 --- a/esp-link/cgipins.c +++ b/esp-link/cgipins.c @@ -49,7 +49,7 @@ int ICACHE_FLASH_ATTR cgiPinsSet(HttpdConnData *connData) { int8_t ok = 0; int8_t reset, isp, conn, ser; - bool swap, rxpup; + uint8_t swap, rxpup; ok |= getInt8Arg(connData, "reset", &reset); ok |= getInt8Arg(connData, "isp", &isp); ok |= getInt8Arg(connData, "conn", &conn); From 793506fdd154d7b9ca312d030aa7f9ac4c142556 Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Sun, 27 Dec 2015 23:10:07 +0100 Subject: [PATCH 04/29] Small changes --- Makefile | 14 +++++++------- esp-link/main.c | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 98660ae..589c0fa 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ # The SOFTAP configuration can be hard-coded here, the minimum parameters to set are AP_SSID && AP_PASS # The AP SSID has to be at least 8 characters long, same for AP PASSWORD # The AP AUTH MODE can be set to ( default = AUTH_WPA_WPA2_PSK ) -# AUTH_OPEN = 0, +# AUTH_OPEN, # AUTH_WEP, # AUTH_WPA_PSK, # AUTH_WPA2_PSK, @@ -35,12 +35,12 @@ # Max connections default 4, ( 1 ~ 4 ) # Beacon interval default 100, ( 100 ~ 60000ms ) -# AP_SSID ?= -# AP_PASS ?= -# AP_AUTH_MODE ?= -# AP_SSID_HIDDEN ?= -# AP_MAX_CONN ?= -# AP_BEACON_INTERVAL ?= +# AP_SSID ?=esp_link_test +# AP_PASS ?=esp_link_test +# AP_AUTH_MODE ?=AUTH_WPA_WPA2_PSK +# AP_SSID_HIDDEN ?=0 +# AP_MAX_CONN ?=4 +# AP_BEACON_INTERVAL ?=100 # If CHANGE_TO_STA is set to "yes" the esp-link module will switch to station mode diff --git a/esp-link/main.c b/esp-link/main.c index 1bbf3b6..da1f83a 100644 --- a/esp-link/main.c +++ b/esp-link/main.c @@ -112,7 +112,7 @@ void user_rf_pre_init(void) { void user_init(void) { // get the flash config so we know how to init things - // configWipe(); // uncomment to reset the config for testing purposes + configWipe(); // uncomment to reset the config for testing purposes bool restoreOk = configRestore(); // Init gpio pin registers gpio_init(); From a7b6358bae963fab5e132922385c1d378a43c1bc Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Mon, 28 Dec 2015 18:28:05 +0100 Subject: [PATCH 05/29] New function to check string If there are only alphanumeric chars (including underscore) return 1 else return 0 --- esp-link/cgiwifi.h | 1 + 1 file changed, 1 insertion(+) diff --git a/esp-link/cgiwifi.h b/esp-link/cgiwifi.h index 5fa177c..667f27d 100644 --- a/esp-link/cgiwifi.h +++ b/esp-link/cgiwifi.h @@ -19,6 +19,7 @@ void configWifiIP(); void wifiInit(void); void wifiAddStateChangeCb(WifiStateChangeCb cb); void wifiStartMDNS(struct ip_addr); +int checkString(char *str); extern uint8_t wifiState; extern bool mdns_started; From 58ece6b45292433c9c52fd717be91f91c97cb55b Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Mon, 28 Dec 2015 18:29:15 +0100 Subject: [PATCH 06/29] Auth_Mode var in numbers instead of string --- Makefile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 589c0fa..6e98b5e 100644 --- a/Makefile +++ b/Makefile @@ -25,19 +25,19 @@ # The SOFTAP configuration can be hard-coded here, the minimum parameters to set are AP_SSID && AP_PASS # The AP SSID has to be at least 8 characters long, same for AP PASSWORD -# The AP AUTH MODE can be set to ( default = AUTH_WPA_WPA2_PSK ) -# AUTH_OPEN, -# AUTH_WEP, -# AUTH_WPA_PSK, -# AUTH_WPA2_PSK, -# AUTH_WPA_WPA2_PSK +# The AP AUTH MODE can be set to: +# 0 = AUTH_OPEN, +# 1 = AUTH_WEP, +# 2 = AUTH_WPA_PSK, +# 3 = AUTH_WPA2_PSK, +# 4 = AUTH_WPA_WPA2_PSK # SSID hidden default 0, ( 0 | 1 ) # Max connections default 4, ( 1 ~ 4 ) # Beacon interval default 100, ( 100 ~ 60000ms ) # AP_SSID ?=esp_link_test # AP_PASS ?=esp_link_test -# AP_AUTH_MODE ?=AUTH_WPA_WPA2_PSK +# AP_AUTH_MODE ?=0 # AP_SSID_HIDDEN ?=0 # AP_MAX_CONN ?=4 # AP_BEACON_INTERVAL ?=100 From d6dae6888a77e230aa5e1a4483765e86e08d6705 Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Mon, 28 Dec 2015 18:30:40 +0100 Subject: [PATCH 07/29] Disable configWipe --- esp-link/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp-link/main.c b/esp-link/main.c index da1f83a..5d5cefc 100644 --- a/esp-link/main.c +++ b/esp-link/main.c @@ -112,7 +112,7 @@ void user_rf_pre_init(void) { void user_init(void) { // get the flash config so we know how to init things - configWipe(); // uncomment to reset the config for testing purposes + //configWipe(); // uncomment to reset the config for testing purposes bool restoreOk = configRestore(); // Init gpio pin registers gpio_init(); From e268db7e8405d8a3be6303a975b684f7dfb3210c Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Mon, 28 Dec 2015 18:38:31 +0100 Subject: [PATCH 08/29] Soft-AP server side variables check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Proper check of Soft-AP setting’s variables values on server side. Only alphanumeric values and underscore are allowed in SSID and Password. Now you can set Soft-AP as OPEN AP with custom SSID. --- esp-link/cgiwifi.c | 1005 +++++++++++++++++++++++--------------------- 1 file changed, 530 insertions(+), 475 deletions(-) diff --git a/esp-link/cgiwifi.c b/esp-link/cgiwifi.c index be63d85..290e055 100644 --- a/esp-link/cgiwifi.c +++ b/esp-link/cgiwifi.c @@ -43,12 +43,12 @@ uint8_t wifiState = wifiIsDisconnected; // reasons for which a connection failed uint8_t wifiReason = 0; static char *wifiReasons[] = { - "", "unspecified", "auth_expire", "auth_leave", "assoc_expire", "assoc_toomany", "not_authed", - "not_assoced", "assoc_leave", "assoc_not_authed", "disassoc_pwrcap_bad", "disassoc_supchan_bad", - "ie_invalid", "mic_failure", "4way_handshake_timeout", "group_key_update_timeout", - "ie_in_4way_differs", "group_cipher_invalid", "pairwise_cipher_invalid", "akmp_invalid", - "unsupp_rsn_ie_version", "invalid_rsn_ie_cap", "802_1x_auth_failed", "cipher_suite_rejected", - "beacon_timeout", "no_ap_found" }; + "", "unspecified", "auth_expire", "auth_leave", "assoc_expire", "assoc_toomany", "not_authed", + "not_assoced", "assoc_leave", "assoc_not_authed", "disassoc_pwrcap_bad", "disassoc_supchan_bad", + "ie_invalid", "mic_failure", "4way_handshake_timeout", "group_key_update_timeout", + "ie_in_4way_differs", "group_cipher_invalid", "pairwise_cipher_invalid", "akmp_invalid", + "unsupp_rsn_ie_version", "invalid_rsn_ie_cap", "802_1x_auth_failed", "cipher_suite_rejected", + "beacon_timeout", "no_ap_found" }; static char *wifiMode[] = { 0, "STA", "AP", "AP+STA" }; static char *wifiPhy[] = { 0, "11b", "11g", "11n" }; @@ -56,100 +56,100 @@ static char *wifiPhy[] = { 0, "11b", "11g", "11n" }; void (*wifiStatusCb)(uint8_t); // callback when wifi status changes static char* ICACHE_FLASH_ATTR wifiGetReason(void) { - if (wifiReason <= 24) return wifiReasons[wifiReason]; - if (wifiReason >= 200 && wifiReason <= 201) return wifiReasons[wifiReason-200+24]; - return wifiReasons[1]; + if (wifiReason <= 24) return wifiReasons[wifiReason]; + if (wifiReason >= 200 && wifiReason <= 201) return wifiReasons[wifiReason-200+24]; + return wifiReasons[1]; } // handler for wifi status change callback coming in from espressif library static void ICACHE_FLASH_ATTR wifiHandleEventCb(System_Event_t *evt) { - switch (evt->event) { - case EVENT_STAMODE_CONNECTED: - wifiState = wifiIsConnected; - wifiReason = 0; - DBG("Wifi connected to ssid %s, ch %d\n", evt->event_info.connected.ssid, - evt->event_info.connected.channel); - statusWifiUpdate(wifiState); - break; - case EVENT_STAMODE_DISCONNECTED: - wifiState = wifiIsDisconnected; - wifiReason = evt->event_info.disconnected.reason; - DBG("Wifi disconnected from ssid %s, reason %s (%d)\n", - evt->event_info.disconnected.ssid, wifiGetReason(), evt->event_info.disconnected.reason); - statusWifiUpdate(wifiState); - break; - case EVENT_STAMODE_AUTHMODE_CHANGE: - DBG("Wifi auth mode: %d -> %d\n", - evt->event_info.auth_change.old_mode, evt->event_info.auth_change.new_mode); - break; - case EVENT_STAMODE_GOT_IP: - wifiState = wifiGotIP; - wifiReason = 0; - DBG("Wifi got ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR "\n", - IP2STR(&evt->event_info.got_ip.ip), IP2STR(&evt->event_info.got_ip.mask), - IP2STR(&evt->event_info.got_ip.gw)); - statusWifiUpdate(wifiState); - if (!mdns_started) - wifiStartMDNS(evt->event_info.got_ip.ip); - break; - case EVENT_SOFTAPMODE_STACONNECTED: - DBG("Wifi AP: station " MACSTR " joined, AID = %d\n", - MAC2STR(evt->event_info.sta_connected.mac), evt->event_info.sta_connected.aid); - break; - case EVENT_SOFTAPMODE_STADISCONNECTED: - DBG("Wifi AP: station " MACSTR " left, AID = %d\n", - MAC2STR(evt->event_info.sta_disconnected.mac), evt->event_info.sta_disconnected.aid); - break; - default: - break; - } - - for (int i = 0; i < 4; i++) { - if (wifi_state_change_cb[i] != NULL) (wifi_state_change_cb[i])(wifiState); - } + switch (evt->event) { + case EVENT_STAMODE_CONNECTED: + wifiState = wifiIsConnected; + wifiReason = 0; + DBG("Wifi connected to ssid %s, ch %d\n", evt->event_info.connected.ssid, + evt->event_info.connected.channel); + statusWifiUpdate(wifiState); + break; + case EVENT_STAMODE_DISCONNECTED: + wifiState = wifiIsDisconnected; + wifiReason = evt->event_info.disconnected.reason; + DBG("Wifi disconnected from ssid %s, reason %s (%d)\n", + evt->event_info.disconnected.ssid, wifiGetReason(), evt->event_info.disconnected.reason); + statusWifiUpdate(wifiState); + break; + case EVENT_STAMODE_AUTHMODE_CHANGE: + DBG("Wifi auth mode: %d -> %d\n", + evt->event_info.auth_change.old_mode, evt->event_info.auth_change.new_mode); + break; + case EVENT_STAMODE_GOT_IP: + wifiState = wifiGotIP; + wifiReason = 0; + DBG("Wifi got ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR "\n", + IP2STR(&evt->event_info.got_ip.ip), IP2STR(&evt->event_info.got_ip.mask), + IP2STR(&evt->event_info.got_ip.gw)); + statusWifiUpdate(wifiState); + if (!mdns_started) + wifiStartMDNS(evt->event_info.got_ip.ip); + break; + case EVENT_SOFTAPMODE_STACONNECTED: + DBG("Wifi AP: station " MACSTR " joined, AID = %d\n", + MAC2STR(evt->event_info.sta_connected.mac), evt->event_info.sta_connected.aid); + break; + case EVENT_SOFTAPMODE_STADISCONNECTED: + DBG("Wifi AP: station " MACSTR " left, AID = %d\n", + MAC2STR(evt->event_info.sta_disconnected.mac), evt->event_info.sta_disconnected.aid); + break; + default: + break; + } + + for (int i = 0; i < 4; i++) { + if (wifi_state_change_cb[i] != NULL) (wifi_state_change_cb[i])(wifiState); + } } void ICACHE_FLASH_ATTR wifiAddStateChangeCb(WifiStateChangeCb cb) { - for (int i = 0; i < 4; i++) { - if (wifi_state_change_cb[i] == cb) return; - if (wifi_state_change_cb[i] == NULL) { - wifi_state_change_cb[i] = cb; - return; - } - } - DBG("WIFI: max state change cb count exceeded\n"); + for (int i = 0; i < 4; i++) { + if (wifi_state_change_cb[i] == cb) return; + if (wifi_state_change_cb[i] == NULL) { + wifi_state_change_cb[i] = cb; + return; + } + } + DBG("WIFI: max state change cb count exceeded\n"); } void ICACHE_FLASH_ATTR wifiStartMDNS(struct ip_addr ip) { - if (flashConfig.mdns_enable) { - struct mdns_info *mdns_info = (struct mdns_info *)os_zalloc(sizeof(struct mdns_info)); - mdns_info->host_name = flashConfig.hostname; - mdns_info->server_name = flashConfig.mdns_servername; - mdns_info->server_port = 80; - mdns_info->ipAddr = ip.addr; - espconn_mdns_init(mdns_info); - } - else { - espconn_mdns_server_unregister(); - espconn_mdns_close(); - } - mdns_started = true; + if (flashConfig.mdns_enable) { + struct mdns_info *mdns_info = (struct mdns_info *)os_zalloc(sizeof(struct mdns_info)); + mdns_info->host_name = flashConfig.hostname; + mdns_info->server_name = flashConfig.mdns_servername; + mdns_info->server_port = 80; + mdns_info->ipAddr = ip.addr; + espconn_mdns_init(mdns_info); + } + else { + espconn_mdns_server_unregister(); + espconn_mdns_close(); + } + mdns_started = true; } // ===== wifi scanning //WiFi access point data typedef struct { - char ssid[32]; - sint8 rssi; - char enc; + char ssid[32]; + sint8 rssi; + char enc; } ApData; //Scan result typedef struct { - char scanInProgress; //if 1, don't access the underlying stuff from the webpage. - ApData **apData; - int noAps; + char scanInProgress; //if 1, don't access the underlying stuff from the webpage. + ApData **apData; + int noAps; } ScanResultData; //Static scan status storage. @@ -158,122 +158,122 @@ static ScanResultData cgiWifiAps; //Callback the code calls when a wlan ap scan is done. Basically stores the result in //the cgiWifiAps struct. void ICACHE_FLASH_ATTR wifiScanDoneCb(void *arg, STATUS status) { - int n; - struct bss_info *bss_link = (struct bss_info *)arg; - - if (status!=OK) { - DBG("wifiScanDoneCb status=%d\n", status); + int n; + struct bss_info *bss_link = (struct bss_info *)arg; + + if (status!=OK) { + DBG("wifiScanDoneCb status=%d\n", status); + cgiWifiAps.scanInProgress=0; + return; + } + + //Clear prev ap data if needed. + if (cgiWifiAps.apData!=NULL) { + for (n=0; n<cgiWifiAps.noAps; n++) os_free(cgiWifiAps.apData[n]); + os_free(cgiWifiAps.apData); + } + + //Count amount of access points found. + n=0; + while (bss_link != NULL) { + bss_link = bss_link->next.stqe_next; + n++; + } + //Allocate memory for access point data + cgiWifiAps.apData=(ApData **)os_malloc(sizeof(ApData *)*n); + cgiWifiAps.noAps=n; + DBG("Scan done: found %d APs\n", n); + + //Copy access point data to the static struct + n=0; + bss_link = (struct bss_info *)arg; + while (bss_link != NULL) { + if (n>=cgiWifiAps.noAps) { + //This means the bss_link changed under our nose. Shouldn't happen! + //Break because otherwise we will write in unallocated memory. + DBG("Huh? I have more than the allocated %d aps!\n", cgiWifiAps.noAps); + break; + } + //Save the ap data. + cgiWifiAps.apData[n]=(ApData *)os_malloc(sizeof(ApData)); + cgiWifiAps.apData[n]->rssi=bss_link->rssi; + cgiWifiAps.apData[n]->enc=bss_link->authmode; + strncpy(cgiWifiAps.apData[n]->ssid, (char*)bss_link->ssid, 32); + DBG("bss%d: %s (%d)\n", n+1, (char*)bss_link->ssid, bss_link->rssi); + + bss_link = bss_link->next.stqe_next; + n++; + } + //We're done. cgiWifiAps.scanInProgress=0; - return; - } - - //Clear prev ap data if needed. - if (cgiWifiAps.apData!=NULL) { - for (n=0; n<cgiWifiAps.noAps; n++) os_free(cgiWifiAps.apData[n]); - os_free(cgiWifiAps.apData); - } - - //Count amount of access points found. - n=0; - while (bss_link != NULL) { - bss_link = bss_link->next.stqe_next; - n++; - } - //Allocate memory for access point data - cgiWifiAps.apData=(ApData **)os_malloc(sizeof(ApData *)*n); - cgiWifiAps.noAps=n; - DBG("Scan done: found %d APs\n", n); - - //Copy access point data to the static struct - n=0; - bss_link = (struct bss_info *)arg; - while (bss_link != NULL) { - if (n>=cgiWifiAps.noAps) { - //This means the bss_link changed under our nose. Shouldn't happen! - //Break because otherwise we will write in unallocated memory. - DBG("Huh? I have more than the allocated %d aps!\n", cgiWifiAps.noAps); - break; - } - //Save the ap data. - cgiWifiAps.apData[n]=(ApData *)os_malloc(sizeof(ApData)); - cgiWifiAps.apData[n]->rssi=bss_link->rssi; - cgiWifiAps.apData[n]->enc=bss_link->authmode; - strncpy(cgiWifiAps.apData[n]->ssid, (char*)bss_link->ssid, 32); - DBG("bss%d: %s (%d)\n", n+1, (char*)bss_link->ssid, bss_link->rssi); - - bss_link = bss_link->next.stqe_next; - n++; - } - //We're done. - cgiWifiAps.scanInProgress=0; } static ETSTimer scanTimer; static void ICACHE_FLASH_ATTR scanStartCb(void *arg) { - DBG("Starting a scan\n"); - wifi_station_scan(NULL, wifiScanDoneCb); + DBG("Starting a scan\n"); + wifi_station_scan(NULL, wifiScanDoneCb); } static int ICACHE_FLASH_ATTR cgiWiFiStartScan(HttpdConnData *connData) { - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - jsonHeader(connData, 200); - if (!cgiWifiAps.scanInProgress) { - cgiWifiAps.scanInProgress = 1; - os_timer_disarm(&scanTimer); - os_timer_setfn(&scanTimer, scanStartCb, NULL); - os_timer_arm(&scanTimer, 200, 0); - } - return HTTPD_CGI_DONE; + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + jsonHeader(connData, 200); + if (!cgiWifiAps.scanInProgress) { + cgiWifiAps.scanInProgress = 1; + os_timer_disarm(&scanTimer); + os_timer_setfn(&scanTimer, scanStartCb, NULL); + os_timer_arm(&scanTimer, 200, 0); + } + return HTTPD_CGI_DONE; } static int ICACHE_FLASH_ATTR cgiWiFiGetScan(HttpdConnData *connData) { - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - char buff[1460]; - const int chunk = 1460/64; // ssid is up to 32 chars - int len = 0; - - os_printf("GET scan: cgiData=%d noAps=%d\n", (int)connData->cgiData, cgiWifiAps.noAps); - - // handle continuation call, connData->cgiData-1 is the position in the scan results where we - // we need to continue sending from (using -1 'cause 0 means it's the first call) - if (connData->cgiData) { - int next = (int)connData->cgiData-1; - int pos = next; - while (pos < cgiWifiAps.noAps && pos < next+chunk) { - len += os_sprintf(buff+len, "{\"essid\": \"%s\", \"rssi\": %d, \"enc\": \"%d\"}%c\n", - cgiWifiAps.apData[pos]->ssid, cgiWifiAps.apData[pos]->rssi, cgiWifiAps.apData[pos]->enc, - (pos+1 == cgiWifiAps.noAps) ? ' ' : ','); - pos++; - } - // done or more? - if (pos == cgiWifiAps.noAps) { - len += os_sprintf(buff+len, "]}}\n"); - httpdSend(connData, buff, len); - return HTTPD_CGI_DONE; - } else { - connData->cgiData = (void*)(pos+1); - httpdSend(connData, buff, len); - return HTTPD_CGI_MORE; + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + char buff[1460]; + const int chunk = 1460/64; // ssid is up to 32 chars + int len = 0; + + os_printf("GET scan: cgiData=%d noAps=%d\n", (int)connData->cgiData, cgiWifiAps.noAps); + + // handle continuation call, connData->cgiData-1 is the position in the scan results where we + // we need to continue sending from (using -1 'cause 0 means it's the first call) + if (connData->cgiData) { + int next = (int)connData->cgiData-1; + int pos = next; + while (pos < cgiWifiAps.noAps && pos < next+chunk) { + len += os_sprintf(buff+len, "{\"essid\": \"%s\", \"rssi\": %d, \"enc\": \"%d\"}%c\n", + cgiWifiAps.apData[pos]->ssid, cgiWifiAps.apData[pos]->rssi, cgiWifiAps.apData[pos]->enc, + (pos+1 == cgiWifiAps.noAps) ? ' ' : ','); + pos++; + } + // done or more? + if (pos == cgiWifiAps.noAps) { + len += os_sprintf(buff+len, "]}}\n"); + httpdSend(connData, buff, len); + return HTTPD_CGI_DONE; + } else { + connData->cgiData = (void*)(pos+1); + httpdSend(connData, buff, len); + return HTTPD_CGI_MORE; + } } - } - - jsonHeader(connData, 200); - - if (cgiWifiAps.scanInProgress==1) { - //We're still scanning. Tell Javascript code that. - len = os_sprintf(buff, "{\n \"result\": { \n\"inProgress\": \"1\"\n }\n}\n"); + + jsonHeader(connData, 200); + + if (cgiWifiAps.scanInProgress==1) { + //We're still scanning. Tell Javascript code that. + len = os_sprintf(buff, "{\n \"result\": { \n\"inProgress\": \"1\"\n }\n}\n"); + httpdSend(connData, buff, len); + return HTTPD_CGI_DONE; + } + + len = os_sprintf(buff, "{\"result\": {\"inProgress\": \"0\", \"APs\": [\n"); + connData->cgiData = (void *)1; // start with first result next time we're called httpdSend(connData, buff, len); - return HTTPD_CGI_DONE; - } - - len = os_sprintf(buff, "{\"result\": {\"inProgress\": \"0\", \"APs\": [\n"); - connData->cgiData = (void *)1; // start with first result next time we're called - httpdSend(connData, buff, len); - return HTTPD_CGI_MORE; + return HTTPD_CGI_MORE; } int ICACHE_FLASH_ATTR cgiWiFiScan(HttpdConnData *connData) { - + if (connData->requestType == HTTPD_METHOD_GET) { return cgiWiFiGetScan(connData); }else if(connData->requestType == HTTPD_METHOD_POST) @@ -298,22 +298,22 @@ int ICACHE_FLASH_ATTR cgiWiFiScan(HttpdConnData *connData) { #define RESET_TIMEOUT (15000) // 15 seconds static ETSTimer resetTimer; -/* +/* * This routine is ran some time after a connection attempt to an access point. * If the connection succeeds and Makefile hard-coded CHANGE_TO_STA is set to yes, this gets the module in STA-only mode. * If it fails and only STA mode is set, it ensures that the module is in STA+AP mode so the user has a chance to recover. */ static void ICACHE_FLASH_ATTR resetTimerCb(void *arg) { - + int x = wifi_station_get_connect_status(); int m = wifi_get_opmode() & 0x3; DBG("Wifi check: mode=%s status=%d\n", wifiMode[m], x); if(m!=2){ if( x == STATION_GOT_IP ){ - #ifdef CHANGE_TO_STA - wifi_set_opmode(1); - #endif +#ifdef CHANGE_TO_STA + wifi_set_opmode(1); +#endif log_uart(false); }else{ log_uart(true); @@ -332,23 +332,23 @@ static ETSTimer reassTimer; // Callback actually doing reassociation static void ICACHE_FLASH_ATTR reassTimerCb(void *arg) { - DBG("Wifi changing association\n"); - wifi_station_disconnect(); - stconf.bssid_set = 0; - wifi_station_set_config(&stconf); - wifi_station_connect(); - // Schedule check, we give some extra time (4x) 'cause the reassociation can cause the AP - // to have to change channel, and then the client needs to follow before it can see the - // IP address - os_timer_disarm(&resetTimer); - os_timer_setfn(&resetTimer, resetTimerCb, NULL); - os_timer_arm(&resetTimer, 4*RESET_TIMEOUT, 0); + DBG("Wifi changing association\n"); + wifi_station_disconnect(); + stconf.bssid_set = 0; + wifi_station_set_config(&stconf); + wifi_station_connect(); + // Schedule check, we give some extra time (4x) 'cause the reassociation can cause the AP + // to have to change channel, and then the client needs to follow before it can see the + // IP address + os_timer_disarm(&resetTimer); + os_timer_setfn(&resetTimer, resetTimerCb, NULL); + os_timer_arm(&resetTimer, 4*RESET_TIMEOUT, 0); } // This cgi uses the routines above to connect to a specific access point with the // given ESSID using the given password. int ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData) { - + int mode = wifi_get_opmode(); if(mode == 2){ jsonHeader(connData, 400); @@ -358,152 +358,152 @@ int ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData) { char essid[128]; char passwd[128]; - - if (connData->conn==NULL) return HTTPD_CGI_DONE; - - int el = httpdFindArg(connData->getArgs, "essid", essid, sizeof(essid)); - int pl = httpdFindArg(connData->getArgs, "passwd", passwd, sizeof(passwd)); - - if (el > 0 && pl >= 0) { - //Set to 0 if you want to disable the actual reconnecting bit - os_strncpy((char*)stconf.ssid, essid, 32); - os_strncpy((char*)stconf.password, passwd, 64); - DBG("Wifi try to connect to AP %s pw %s\n", essid, passwd); - - //Schedule disconnect/connect - os_timer_disarm(&reassTimer); - os_timer_setfn(&reassTimer, reassTimerCb, NULL); - os_timer_arm(&reassTimer, 1000, 0); // 1 second for the response of this request to make it - jsonHeader(connData, 200); - } else { - jsonHeader(connData, 400); - httpdSend(connData, "Cannot parse ssid or password", -1); - } + + if (connData->conn==NULL) return HTTPD_CGI_DONE; + + int el = httpdFindArg(connData->getArgs, "essid", essid, sizeof(essid)); + int pl = httpdFindArg(connData->getArgs, "passwd", passwd, sizeof(passwd)); + + if (el > 0 && pl >= 0) { + //Set to 0 if you want to disable the actual reconnecting bit + os_strncpy((char*)stconf.ssid, essid, 32); + os_strncpy((char*)stconf.password, passwd, 64); + DBG("Wifi try to connect to AP %s pw %s\n", essid, passwd); + + //Schedule disconnect/connect + os_timer_disarm(&reassTimer); + os_timer_setfn(&reassTimer, reassTimerCb, NULL); + os_timer_arm(&reassTimer, 1000, 0); // 1 second for the response of this request to make it + jsonHeader(connData, 200); + } else { + jsonHeader(connData, 400); + httpdSend(connData, "Cannot parse ssid or password", -1); + } jsonHeader(connData, 400); httpdSend(connData, "Invalid ssid or password", -1); - return HTTPD_CGI_DONE; + return HTTPD_CGI_DONE; } static bool ICACHE_FLASH_ATTR parse_ip(char *buff, ip_addr_t *ip_ptr) { - char *next = buff; // where to start parsing next integer - int found = 0; // number of integers parsed - uint32_t ip = 0; // the ip addres parsed - for (int i=0; i<32; i++) { // 32 is just a safety limit - char c = buff[i]; - if (c == '.' || c == 0) { - // parse the preceding integer and accumulate into IP address - bool last = c == 0; - buff[i] = 0; - uint32_t v = atoi(next); - ip = ip | ((v&0xff)<<(found*8)); - next = buff+i+1; // next integer starts after the '.' - found++; - if (last) { // if at end of string we better got 4 integers - ip_ptr->addr = ip; - return found == 4; - } - continue; - } - if (c < '0' || c > '9') return false; - } - return false; + char *next = buff; // where to start parsing next integer + int found = 0; // number of integers parsed + uint32_t ip = 0; // the ip addres parsed + for (int i=0; i<32; i++) { // 32 is just a safety limit + char c = buff[i]; + if (c == '.' || c == 0) { + // parse the preceding integer and accumulate into IP address + bool last = c == 0; + buff[i] = 0; + uint32_t v = atoi(next); + ip = ip | ((v&0xff)<<(found*8)); + next = buff+i+1; // next integer starts after the '.' + found++; + if (last) { // if at end of string we better got 4 integers + ip_ptr->addr = ip; + return found == 4; + } + continue; + } + if (c < '0' || c > '9') return false; + } + return false; } #ifdef DEBUGIP static void ICACHE_FLASH_ATTR debugIP() { - struct ip_info info; - if (wifi_get_ip_info(0, &info)) { - os_printf("\"ip\": \"%d.%d.%d.%d\"\n", IP2STR(&info.ip.addr)); - os_printf("\"netmask\": \"%d.%d.%d.%d\"\n", IP2STR(&info.netmask.addr)); - os_printf("\"gateway\": \"%d.%d.%d.%d\"\n", IP2STR(&info.gw.addr)); - os_printf("\"hostname\": \"%s\"\n", wifi_station_get_hostname()); - } else { - os_printf("\"ip\": \"-none-\"\n"); - } + struct ip_info info; + if (wifi_get_ip_info(0, &info)) { + os_printf("\"ip\": \"%d.%d.%d.%d\"\n", IP2STR(&info.ip.addr)); + os_printf("\"netmask\": \"%d.%d.%d.%d\"\n", IP2STR(&info.netmask.addr)); + os_printf("\"gateway\": \"%d.%d.%d.%d\"\n", IP2STR(&info.gw.addr)); + os_printf("\"hostname\": \"%s\"\n", wifi_station_get_hostname()); + } else { + os_printf("\"ip\": \"-none-\"\n"); + } } #endif // configure Wifi, specifically DHCP vs static IP address based on flash config void ICACHE_FLASH_ATTR configWifiIP() { - if (flashConfig.staticip == 0) { - // let's DHCP! - wifi_station_set_hostname(flashConfig.hostname); - if (wifi_station_dhcpc_status() == DHCP_STARTED) - wifi_station_dhcpc_stop(); - wifi_station_dhcpc_start(); - DBG("Wifi uses DHCP, hostname=%s\n", flashConfig.hostname); - } else { - // no DHCP, we got static network config! - wifi_station_dhcpc_stop(); - struct ip_info ipi; - ipi.ip.addr = flashConfig.staticip; - ipi.netmask.addr = flashConfig.netmask; - ipi.gw.addr = flashConfig.gateway; - wifi_set_ip_info(0, &ipi); - DBG("Wifi uses static IP %d.%d.%d.%d\n", IP2STR(&ipi.ip.addr)); - } + if (flashConfig.staticip == 0) { + // let's DHCP! + wifi_station_set_hostname(flashConfig.hostname); + if (wifi_station_dhcpc_status() == DHCP_STARTED) + wifi_station_dhcpc_stop(); + wifi_station_dhcpc_start(); + DBG("Wifi uses DHCP, hostname=%s\n", flashConfig.hostname); + } else { + // no DHCP, we got static network config! + wifi_station_dhcpc_stop(); + struct ip_info ipi; + ipi.ip.addr = flashConfig.staticip; + ipi.netmask.addr = flashConfig.netmask; + ipi.gw.addr = flashConfig.gateway; + wifi_set_ip_info(0, &ipi); + DBG("Wifi uses static IP %d.%d.%d.%d\n", IP2STR(&ipi.ip.addr)); + } #ifdef DEBUGIP - debugIP(); + debugIP(); #endif } // Change special settings int ICACHE_FLASH_ATTR cgiWiFiSpecial(HttpdConnData *connData) { - char dhcp[8]; - char staticip[20]; - char netmask[20]; - char gateway[20]; - - if (connData->conn==NULL) return HTTPD_CGI_DONE; - - // get args and their string lengths - int dl = httpdFindArg(connData->getArgs, "dhcp", dhcp, sizeof(dhcp)); - int sl = httpdFindArg(connData->getArgs, "staticip", staticip, sizeof(staticip)); - int nl = httpdFindArg(connData->getArgs, "netmask", netmask, sizeof(netmask)); - int gl = httpdFindArg(connData->getArgs, "gateway", gateway, sizeof(gateway)); - - if (!(dl > 0 && sl >= 0 && nl >= 0 && gl >= 0)) { - jsonHeader(connData, 400); - httpdSend(connData, "Request is missing fields", -1); + char dhcp[8]; + char staticip[20]; + char netmask[20]; + char gateway[20]; + + if (connData->conn==NULL) return HTTPD_CGI_DONE; + + // get args and their string lengths + int dl = httpdFindArg(connData->getArgs, "dhcp", dhcp, sizeof(dhcp)); + int sl = httpdFindArg(connData->getArgs, "staticip", staticip, sizeof(staticip)); + int nl = httpdFindArg(connData->getArgs, "netmask", netmask, sizeof(netmask)); + int gl = httpdFindArg(connData->getArgs, "gateway", gateway, sizeof(gateway)); + + if (!(dl > 0 && sl >= 0 && nl >= 0 && gl >= 0)) { + jsonHeader(connData, 400); + httpdSend(connData, "Request is missing fields", -1); + return HTTPD_CGI_DONE; + } + + char url[64]; // redirect URL + if (os_strcmp(dhcp, "off") == 0) { + // parse static IP params + struct ip_info ipi; + bool ok = parse_ip(staticip, &ipi.ip); + if (nl > 0) ok = ok && parse_ip(netmask, &ipi.netmask); + else IP4_ADDR(&ipi.netmask, 255, 255, 255, 0); + if (gl > 0) ok = ok && parse_ip(gateway, &ipi.gw); + else ipi.gw.addr = 0; + if (!ok) { + jsonHeader(connData, 400); + httpdSend(connData, "Cannot parse static IP config", -1); + return HTTPD_CGI_DONE; + } + // save the params in flash + flashConfig.staticip = ipi.ip.addr; + flashConfig.netmask = ipi.netmask.addr; + flashConfig.gateway = ipi.gw.addr; + // construct redirect URL + os_sprintf(url, "{\"url\": \"http://%d.%d.%d.%d\"}", IP2STR(&ipi.ip)); + + } else { + // dynamic IP + flashConfig.staticip = 0; + os_sprintf(url, "{\"url\": \"http://%s\"}", flashConfig.hostname); + } + + configSave(); // ignore error... + // schedule change-over + os_timer_disarm(&reassTimer); + os_timer_setfn(&reassTimer, configWifiIP, NULL); + os_timer_arm(&reassTimer, 1000, 0); // 1 second for the response of this request to make it + // return redirect info + jsonHeader(connData, 200); + httpdSend(connData, url, -1); return HTTPD_CGI_DONE; - } - - char url[64]; // redirect URL - if (os_strcmp(dhcp, "off") == 0) { - // parse static IP params - struct ip_info ipi; - bool ok = parse_ip(staticip, &ipi.ip); - if (nl > 0) ok = ok && parse_ip(netmask, &ipi.netmask); - else IP4_ADDR(&ipi.netmask, 255, 255, 255, 0); - if (gl > 0) ok = ok && parse_ip(gateway, &ipi.gw); - else ipi.gw.addr = 0; - if (!ok) { - jsonHeader(connData, 400); - httpdSend(connData, "Cannot parse static IP config", -1); - return HTTPD_CGI_DONE; - } - // save the params in flash - flashConfig.staticip = ipi.ip.addr; - flashConfig.netmask = ipi.netmask.addr; - flashConfig.gateway = ipi.gw.addr; - // construct redirect URL - os_sprintf(url, "{\"url\": \"http://%d.%d.%d.%d\"}", IP2STR(&ipi.ip)); - - } else { - // dynamic IP - flashConfig.staticip = 0; - os_sprintf(url, "{\"url\": \"http://%s\"}", flashConfig.hostname); - } - - configSave(); // ignore error... - // schedule change-over - os_timer_disarm(&reassTimer); - os_timer_setfn(&reassTimer, configWifiIP, NULL); - os_timer_arm(&reassTimer, 1000, 0); // 1 second for the response of this request to make it - // return redirect info - jsonHeader(connData, 200); - httpdSend(connData, url, -1); - return HTTPD_CGI_DONE; } // ==== Soft-AP related functions @@ -513,6 +513,7 @@ int ICACHE_FLASH_ATTR cgiApSettingsChange(HttpdConnData *connData) { if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + // No changes for Soft-AP in STA mode int mode = wifi_get_opmode(); if ( mode == 1 ){ @@ -525,6 +526,8 @@ int ICACHE_FLASH_ATTR cgiApSettingsChange(HttpdConnData *connData) { char buff[96]; int len; + // Do we need a password? + int pass_need=1; // Check extra security measure len=httpdFindArg(connData->getArgs, "100", buff, sizeof(buff)); @@ -536,25 +539,50 @@ int ICACHE_FLASH_ATTR cgiApSettingsChange(HttpdConnData *connData) { } // Get the new SSID and set len=httpdFindArg(connData->getArgs, "ap_ssid", buff, sizeof(buff)); - if(len>7 && len<30){ + if(checkString(buff) && len>7 && len<32){ // STRING PREPROCESSING DONE IN CLIENT SIDE memset(apconf.ssid, 0, 32); os_memcpy(apconf.ssid, buff, len); + apconf.ssid_len = len; + pass_need = 1; }else{ + pass_need = 0; jsonHeader(connData, 400); - httpdSend(connData, "SSID name out of range", -1); + httpdSend(connData, "SSID not valid or out of range", -1); return HTTPD_CGI_DONE; } // Set new PASSWORD - len=httpdFindArg(connData->getArgs, "ap_password", buff, sizeof(buff)); - if(len>7 && len<62){ - // STRING PREPROCESSING DONE IN CLIENT SIDE - memset(apconf.password, 0, 64); - os_memcpy(apconf.password, buff, len); + if( pass_need ){ + len=httpdFindArg(connData->getArgs, "ap_password", buff, sizeof(buff)); + if(checkString(buff) && len>7 && len<62){ + // STRING PREPROCESSING DONE IN CLIENT SIDE + memset(apconf.password, 0, 64); + os_memcpy(apconf.password, buff, len); + pass_need = 1; + }else if (len == 0){ + pass_need = 0; + memset(apconf.password, 0, 64); + }else{ + jsonHeader(connData, 400); + httpdSend(connData, "PASSWORD not valid or out of range", -1); + return HTTPD_CGI_DONE; + } + } + // Set auth mode + if(pass_need){ + // Set authentication mode, before password to check open settings + len=httpdFindArg(connData->getArgs, "ap_authmode", buff, sizeof(buff)); + if(len>0){ + int value = atoi(buff); + if(value >= 0 && value <= 4){ + apconf.authmode = value; + }else{ + // If out of range set by default + apconf.authmode = 4; + } + } }else{ - jsonHeader(connData, 400); - httpdSend(connData, "PASSWORD out of range", -1); - return HTTPD_CGI_DONE; + apconf.authmode = 0; } // Set max connection number len=httpdFindArg(connData->getArgs, "ap_maxconn", buff, sizeof(buff)); @@ -579,17 +607,6 @@ int ICACHE_FLASH_ATTR cgiApSettingsChange(HttpdConnData *connData) { apconf.beacon_interval = 100; } } - // Set authentication mode - len=httpdFindArg(connData->getArgs, "ap_authmode", buff, sizeof(buff)); - if(len>0){ - int value = atoi(buff); - if(value >= 0 && value <= 4){ - apconf.authmode = value; - }else{ - // If out of range set by default - apconf.authmode = 4; - } - } // Set ssid to be hidden or not len=httpdFindArg(connData->getArgs, "ap_hidden", buff, sizeof(buff)); if(len>0){ @@ -640,7 +657,7 @@ int ICACHE_FLASH_ATTR cgiApSettingsInfo(HttpdConnData *connData) { //This cgi changes the operating mode: STA / AP / STA+AP int ICACHE_FLASH_ATTR cgiWiFiSetMode(HttpdConnData *connData) { - + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. int len; char buff[1024]; @@ -656,10 +673,10 @@ int ICACHE_FLASH_ATTR cgiWiFiSetMode(HttpdConnData *connData) { // moving to AP mode, so disconnect before leave STA mode wifi_station_disconnect(); } - + DBG("Wifi switching to mode %d\n", next_mode); wifi_set_opmode(next_mode&3); - + if (previous_mode == 2) { // movint to STA-only mode from AP, so reset into STA+AP after a timeout if we don't get an IP address stconf.bssid_set = 0; @@ -683,7 +700,7 @@ int ICACHE_FLASH_ATTR cgiWiFiSetMode(HttpdConnData *connData) { // Collection of wifi info variables static char *connStatuses[] = { "idle", "connecting", "wrong password", "AP not found", - "failed", "got IP address" }; + "failed", "got IP address" }; static char *wifiWarn[] = { 0, "Switch to <a href=\\\"#\\\" onclick=\\\"changeWifiMode(3)\\\">STA+AP mode</a>", @@ -712,101 +729,124 @@ static char *apAuthMode[] = { "OPEN", // print various Wifi information into json buffer int ICACHE_FLASH_ATTR printWifiInfo(char *buff) { - - int len; - //struct station_config stconf; - wifi_station_get_config(&stconf); - //struct softap_config apconf; - wifi_softap_get_config(&apconf); - - uint8_t op = wifi_get_opmode() & 0x3; - char *mode = wifiMode[op]; - char *status = "unknown"; - int st = wifi_station_get_connect_status(); - if (st >= 0 && st < sizeof(connStatuses)) status = connStatuses[st]; - int p = wifi_get_phy_mode(); - char *phy = wifiPhy[p&3]; - char *warn = wifiWarn[op]; + + int len; + //struct station_config stconf; + wifi_station_get_config(&stconf); + //struct softap_config apconf; + wifi_softap_get_config(&apconf); + + uint8_t op = wifi_get_opmode() & 0x3; + char *mode = wifiMode[op]; + char *status = "unknown"; + int st = wifi_station_get_connect_status(); + if (st >= 0 && st < sizeof(connStatuses)) status = connStatuses[st]; + int p = wifi_get_phy_mode(); + char *phy = wifiPhy[p&3]; + char *warn = wifiWarn[op]; char *apwarn = apWifiWarn[op]; char *apauth = apAuthMode[apconf.authmode]; - sint8 rssi = wifi_station_get_rssi(); - if (rssi > 0) rssi = 0; - uint8 mac_addr[6]; - uint8 apmac_addr[6]; - wifi_get_macaddr(0, mac_addr); + sint8 rssi = wifi_station_get_rssi(); + if (rssi > 0) rssi = 0; + uint8 mac_addr[6]; + uint8 apmac_addr[6]; + wifi_get_macaddr(0, mac_addr); wifi_get_macaddr(1, apmac_addr); - uint8_t chan = wifi_get_channel(); - - len = os_sprintf(buff, - "\"mode\": \"%s\", \"modechange\": \"%s\", \"ssid\": \"%s\", \"status\": \"%s\", \"phy\": \"%s\", " - "\"rssi\": \"%ddB\", \"warn\": \"%s\", \"apwarn\": \"%s\",\"mac\":\"%02x:%02x:%02x:%02x:%02x:%02x\", \"chan\":\"%d\", \"apssid\": \"%s\", " - "\"appass\": \"%s\", \"apchan\": \"%d\", \"apmaxc\": \"%d\", \"aphidd\": \"%s\", \"apbeac\": \"%d\", \"apauth\": \"%s\",\"apmac\":\"%02x:%02x:%02x:%02x:%02x:%02x\"", - mode, MODECHANGE, (char*)stconf.ssid, status, phy, rssi, warn, apwarn, - mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5], chan, (char*)apconf.ssid,(char*)apconf.password,apconf.channel,apconf.max_connection,apconf.ssid_hidden?"enabled":"disabled",apconf.beacon_interval, apauth,apmac_addr[0], apmac_addr[1], apmac_addr[2], apmac_addr[3], apmac_addr[4], apmac_addr[5]); - - struct ip_info info; - if (wifi_get_ip_info(0, &info)) { - len += os_sprintf(buff+len, ", \"ip\": \"%d.%d.%d.%d\"", IP2STR(&info.ip.addr)); - len += os_sprintf(buff+len, ", \"netmask\": \"%d.%d.%d.%d\"", IP2STR(&info.netmask.addr)); - len += os_sprintf(buff+len, ", \"gateway\": \"%d.%d.%d.%d\"", IP2STR(&info.gw.addr)); - len += os_sprintf(buff+len, ", \"hostname\": \"%s\"", flashConfig.hostname); - } else { - len += os_sprintf(buff+len, ", \"ip\": \"-none-\""); - } - len += os_sprintf(buff+len, ", \"staticip\": \"%d.%d.%d.%d\"", IP2STR(&flashConfig.staticip)); - len += os_sprintf(buff+len, ", \"dhcp\": \"%s\"", flashConfig.staticip > 0 ? "off" : "on"); - - return len; + uint8_t chan = wifi_get_channel(); + + len = os_sprintf(buff, + "\"mode\": \"%s\", \"modechange\": \"%s\", \"ssid\": \"%s\", \"status\": \"%s\", \"phy\": \"%s\", " + "\"rssi\": \"%ddB\", \"warn\": \"%s\", \"apwarn\": \"%s\",\"mac\":\"%02x:%02x:%02x:%02x:%02x:%02x\", \"chan\":\"%d\", \"apssid\": \"%s\", " + "\"appass\": \"%s\", \"apchan\": \"%d\", \"apmaxc\": \"%d\", \"aphidd\": \"%s\", \"apbeac\": \"%d\", \"apauth\": \"%s\",\"apmac\":\"%02x:%02x:%02x:%02x:%02x:%02x\"", + mode, MODECHANGE, (char*)stconf.ssid, status, phy, rssi, warn, apwarn, + mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5], chan, (char*)apconf.ssid,(char*)apconf.password,apconf.channel,apconf.max_connection,apconf.ssid_hidden?"enabled":"disabled",apconf.beacon_interval, apauth,apmac_addr[0], apmac_addr[1], apmac_addr[2], apmac_addr[3], apmac_addr[4], apmac_addr[5]); + + struct ip_info info; + if (wifi_get_ip_info(0, &info)) { + len += os_sprintf(buff+len, ", \"ip\": \"%d.%d.%d.%d\"", IP2STR(&info.ip.addr)); + len += os_sprintf(buff+len, ", \"netmask\": \"%d.%d.%d.%d\"", IP2STR(&info.netmask.addr)); + len += os_sprintf(buff+len, ", \"gateway\": \"%d.%d.%d.%d\"", IP2STR(&info.gw.addr)); + len += os_sprintf(buff+len, ", \"hostname\": \"%s\"", flashConfig.hostname); + } else { + len += os_sprintf(buff+len, ", \"ip\": \"-none-\""); + } + len += os_sprintf(buff+len, ", \"staticip\": \"%d.%d.%d.%d\"", IP2STR(&flashConfig.staticip)); + len += os_sprintf(buff+len, ", \"dhcp\": \"%s\"", flashConfig.staticip > 0 ? "off" : "on"); + + return len; } int ICACHE_FLASH_ATTR cgiWiFiConnStatus(HttpdConnData *connData) { - char buff[1024]; - int len; - - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - jsonHeader(connData, 200); - - len = os_sprintf(buff, "{"); - len += printWifiInfo(buff+len); - len += os_sprintf(buff+len, ", "); - - if (wifiReason != 0) { - len += os_sprintf(buff+len, "\"reason\": \"%s\", ", wifiGetReason()); - } - + char buff[1024]; + int len; + + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + jsonHeader(connData, 200); + + len = os_sprintf(buff, "{"); + len += printWifiInfo(buff+len); + len += os_sprintf(buff+len, ", "); + + if (wifiReason != 0) { + len += os_sprintf(buff+len, "\"reason\": \"%s\", ", wifiGetReason()); + } + #if 0 - // commented out 'cause often the client that requested the change can't get a request in to - // find out that it succeeded. Better to just wait the std 15 seconds... - int st=wifi_station_get_connect_status(); - if (st == STATION_GOT_IP) { - if (wifi_get_opmode() != 1) { - // Reset into AP-only mode sooner. - os_timer_disarm(&resetTimer); - os_timer_setfn(&resetTimer, resetTimerCb, NULL); - os_timer_arm(&resetTimer, 1000, 0); - } - } + // commented out 'cause often the client that requested the change can't get a request in to + // find out that it succeeded. Better to just wait the std 15 seconds... + int st=wifi_station_get_connect_status(); + if (st == STATION_GOT_IP) { + if (wifi_get_opmode() != 1) { + // Reset into AP-only mode sooner. + os_timer_disarm(&resetTimer); + os_timer_setfn(&resetTimer, resetTimerCb, NULL); + os_timer_arm(&resetTimer, 1000, 0); + } + } #endif - - len += os_sprintf(buff+len, "\"x\":0}\n"); - DBG(" -> %s\n", buff); - httpdSend(connData, buff, len); - return HTTPD_CGI_DONE; + + len += os_sprintf(buff+len, "\"x\":0}\n"); + DBG(" -> %s\n", buff); + httpdSend(connData, buff, len); + return HTTPD_CGI_DONE; } // Cgi to return various Wifi information int ICACHE_FLASH_ATTR cgiWifiInfo(HttpdConnData *connData) { - char buff[1024]; - - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - - os_strcpy(buff, "{"); - printWifiInfo(buff+1); - os_strcat(buff, "}"); + char buff[1024]; + + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + + os_strcpy(buff, "{"); + printWifiInfo(buff+1); + os_strcat(buff, "}"); + + jsonHeader(connData, 200); + httpdSend(connData, buff, -1); + return HTTPD_CGI_DONE; +} - jsonHeader(connData, 200); - httpdSend(connData, buff, -1); - return HTTPD_CGI_DONE; +// Check string againt invalid characters +int ICACHE_FLASH_ATTR checkString(char *str){ + unsigned char strStripped[50]; + int i = 0, c = 0; + for(; i < os_strlen(str); i++) + { + // Alphanumeric and underscore allowed + if (isalnum((unsigned char)str[i]) || str[i] == '_') + { + strStripped[c] = str[i]; + c++; + } + } + strStripped[c] = '\0'; + + if (os_strcmp((char *)str,(char *)&strStripped) == 0){ + return 1; + }else{ + os_printf("Error: String has non alphanumeric chars\n"); + return 0; + } } /* Init the wireless @@ -817,7 +857,7 @@ int ICACHE_FLASH_ATTR cgiWifiInfo(HttpdConnData *connData) { * Call a timer to check the STA connection */ void ICACHE_FLASH_ATTR wifiInit() { - + // Check te wifi opmode int x = wifi_get_opmode() & 0x3; @@ -827,76 +867,91 @@ void ICACHE_FLASH_ATTR wifiInit() { // Call both STATION and SOFTAP default config wifi_station_get_config_default(&stconf); wifi_softap_get_config_default(&apconf); - - #ifdef CGIWIFI_DBG - os_printf("Wifi init, mode=%s\n",wifiMode[x]); - #endif + +#ifdef CGIWIFI_DBG + os_printf("Wifi init, mode=%s\n",wifiMode[x]); +#endif // STATION parameters only on a full flash, because default opmode is 2 - #if defined(STA_SSID) && defined(STA_PASS) +#if defined(STA_SSID) && defined(STA_PASS) if( x == 2 ){ // Set parameters if (os_strlen((char*)stconf.ssid) == 0 && os_strlen((char*)stconf.password) == 0) { os_strncpy((char*)stconf.ssid, VERS_STR(STA_SSID), 32); os_strncpy((char*)stconf.password, VERS_STR(STA_PASS), 64); - #ifdef CGIWIFI_DBG +#ifdef CGIWIFI_DBG os_printf("Wifi pre-config trying to connect to AP %s pw %s\n",(char*)stconf.ssid, (char*)stconf.password); - #endif +#endif // wifi_set_phy_mode(2); // limit to 802.11b/g 'cause n is flaky stconf.bssid_set = 0; wifi_station_set_config(&stconf); } } - #endif +#endif - // Change SOFT_AP parameters if defined - #if defined(AP_SSID) && defined(AP_PASS) + // Change SOFT_AP settings if defined +#if defined(AP_SSID) && defined(AP_PASS) + // Check if both ssid and pass are alphanumeric values + if(checkString(VERS_STR(AP_SSID)) && checkString(VERS_STR(AP_PASS))){ // Clean memory and set the value of SSID memset(apconf.ssid, 0, 32); - os_memcpy(apconf.ssid, VERS_STR(AP_SSID), strlen(VERS_STR(AP_SSID))); - - // Clean memory and set the value of PASS - memset(apconf.password, 0, 64); - os_memcpy(apconf.password, VERS_STR(AP_PASS), strlen(VERS_STR(AP_PASS))); - + os_memcpy(apconf.ssid, VERS_STR(AP_SSID), os_strlen(VERS_STR(AP_SSID))); // Specify the length of pass - apconf.ssid_len= os_strlen((char*)VERS_STR(AP_PASS)); - #ifdef AP_AUTH_MODE - // If set, use specified auth mode - apconf.authmode = AP_AUTH_MODE; - #else - // If not, use wpa wpa2 psk - apconf.authmode = AUTH_WPA_WPA2_PSK; - #endif - #ifdef AP_SSID_HIDDEN - // If set, use specified ssid hidden parameter + apconf.ssid_len= os_strlen((char*)VERS_STR(AP_SSID)); + // If pass is at least 8 and less than 64 + int passlen = os_strlen(VERS_STR(AP_PASS)); + if( passlen > 7 && passlen < 64 ){ + // Clean memory and set the value of PASS + memset(apconf.password, 0, 64); + os_memcpy(apconf.password, VERS_STR(AP_PASS), passlen); + + // Can't choose auth mode without a valid ssid and password +#ifdef AP_AUTH_MODE + // If set, use specified auth mode + if(AP_AUTH_MODE >= 0 && AP_AUTH_MODE <=4) + apconf.authmode = AP_AUTH_MODE; +#else + // If not, use OPEN + apconf.authmode = AUTH_OPEN; +#endif + }else if ( passlen == 0){ + // If ssid is ok and no pass set auth open + apconf.authmode = AUTH_OPEN; + // Remove stored password + memset(apconf.password, 0, 64); + } + }// end of ssid and pass check +#ifdef AP_SSID_HIDDEN + // If set, use specified ssid hidden parameter + if(AP_SSID_HIDDEN == 0 || AP_SSID_HIDDEN ==1) apconf.ssid_hidden = AP_SSID_HIDDEN; - #endif - #ifdef AP_MAX_CONN - // If set, use specified max conn number +#endif +#ifdef AP_MAX_CONN + // If set, use specified max conn number + if(AP_MAX_CONN > 0 && AP_MAX_CONN <5) apconf.max_connection = AP_MAX_CONN; - #endif - #ifdef AP_BEACON_INTERVAL - // If set use specified beacon interval +#endif +#ifdef AP_BEACON_INTERVAL + // If set use specified beacon interval + if(AP_BEACON_INTERVAL >= 100 && AP_BEACON_INTERVAL <= 60000) apconf.beacon_interval = AP_BEACON_INTERVAL; - #endif - // Check save softap config - bool softap_set_conf = wifi_softap_set_config(&apconf); - #ifdef CGIWIFI_DBG - // Debug info - os_printf("Wifi AP parameters: %s pw %s\n",(char*)apconf.ssid, (char*)apconf.password); - os_printf("Wifi Soft-AP parameters set: %s\n",softap_set_conf? "success":"fail"); - #endif - - #endif // AP_SSID && AP_PASS - +#endif + // Check save softap config + bool softap_set_conf = wifi_softap_set_config(&apconf); +#ifdef CGIWIFI_DBG + // Debug info + //os_printf("Wifi AP parameters: %s pw %s\n",(char*)apconf.ssid, (char*)apconf.password); + os_printf("Wifi Soft-AP parameters change: %s\n",softap_set_conf? "success":"fail"); +#endif +#endif // AP_SSID && AP_PASS + configWifiIP(); - + // The default sleep mode should be modem_sleep, but we set it here explicitly for good // measure. We can't use light_sleep because that powers off everthing and we would loose // all connections. wifi_set_sleep_type(MODEM_SLEEP_T); - + wifi_set_event_handler_cb(wifiHandleEventCb); // check on the wifi in a few seconds to see whether we need to switch mode os_timer_disarm(&resetTimer); From b3ed6e8588adf08ad817db5e634cf44e6588ed96 Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Sat, 2 Jan 2016 12:25:39 +0100 Subject: [PATCH 09/29] Back to original config I forgot to restore to original --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 6e98b5e..2166eeb 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,7 @@ # AP_SSID ?=esp_link_test # AP_PASS ?=esp_link_test -# AP_AUTH_MODE ?=0 +# AP_AUTH_MODE ?=4 # AP_SSID_HIDDEN ?=0 # AP_MAX_CONN ?=4 # AP_BEACON_INTERVAL ?=100 @@ -46,7 +46,7 @@ # If CHANGE_TO_STA is set to "yes" the esp-link module will switch to station mode # once successfully connected to an access point. Else it will stay in STA+AP mode. -CHANGE_TO_STA ?= no +CHANGE_TO_STA ?= yes # hostname or IP address for wifi flashing ESP_HOSTNAME ?= esp-link @@ -59,7 +59,7 @@ XTENSA_TOOLS_ROOT ?= $(abspath ../esp-open-sdk/xtensa-lx106-elf/bin)/ # Base directory of the ESP8266 SDK package, absolute # Typically you'll download from Espressif's BBS, http://bbs.espressif.com/viewforum.php?f=5 -SDK_BASE ?= $(abspath ../esp-open-sdk/esp_iot_sdk_v1.5.0) +SDK_BASE ?= $(abspath ../esp_iot_sdk_v1.5.0) # Esptool.py path and port, only used for 1-time serial flashing # Typically you'll use https://github.com/themadinventor/esptool From 5787fcf8a4af8e04e8edb099b2122b7f6bd2dad6 Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Sat, 2 Jan 2016 12:43:52 +0100 Subject: [PATCH 10/29] Added to avoid possible hiccup when opmode already 1 --- esp-link/cgiwifi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/esp-link/cgiwifi.c b/esp-link/cgiwifi.c index 290e055..bfa362e 100644 --- a/esp-link/cgiwifi.c +++ b/esp-link/cgiwifi.c @@ -312,6 +312,7 @@ static void ICACHE_FLASH_ATTR resetTimerCb(void *arg) { if(m!=2){ if( x == STATION_GOT_IP ){ #ifdef CHANGE_TO_STA + if(m != 1) wifi_set_opmode(1); #endif log_uart(false); From 4d09a0088ac7fc17c8b5455a9eb28ce8a2d6d913 Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Sat, 2 Jan 2016 12:44:55 +0100 Subject: [PATCH 11/29] After test it results useless, so removed --- esp-link/cgiwifi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/esp-link/cgiwifi.c b/esp-link/cgiwifi.c index bfa362e..84171a0 100644 --- a/esp-link/cgiwifi.c +++ b/esp-link/cgiwifi.c @@ -522,9 +522,7 @@ int ICACHE_FLASH_ATTR cgiApSettingsChange(HttpdConnData *connData) { httpdSend(connData, "No changes allowed in STA mode", -1); return HTTPD_CGI_DONE; } - // Get Soft-Ap config, just in case - wifi_softap_get_config(&apconf); - + char buff[96]; int len; // Do we need a password? From d1152588a8d7189b99adb66d8c49b7abb5e1f4f4 Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Sat, 2 Jan 2016 12:46:12 +0100 Subject: [PATCH 12/29] Changed to standard os_memset(), instead of memset() --- esp-link/cgiwifi.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/esp-link/cgiwifi.c b/esp-link/cgiwifi.c index 84171a0..bb170ff 100644 --- a/esp-link/cgiwifi.c +++ b/esp-link/cgiwifi.c @@ -540,7 +540,7 @@ int ICACHE_FLASH_ATTR cgiApSettingsChange(HttpdConnData *connData) { len=httpdFindArg(connData->getArgs, "ap_ssid", buff, sizeof(buff)); if(checkString(buff) && len>7 && len<32){ // STRING PREPROCESSING DONE IN CLIENT SIDE - memset(apconf.ssid, 0, 32); + os_memset(apconf.ssid, 0, 32); os_memcpy(apconf.ssid, buff, len); apconf.ssid_len = len; pass_need = 1; @@ -555,12 +555,12 @@ int ICACHE_FLASH_ATTR cgiApSettingsChange(HttpdConnData *connData) { len=httpdFindArg(connData->getArgs, "ap_password", buff, sizeof(buff)); if(checkString(buff) && len>7 && len<62){ // STRING PREPROCESSING DONE IN CLIENT SIDE - memset(apconf.password, 0, 64); + os_memset(apconf.password, 0, 64); os_memcpy(apconf.password, buff, len); pass_need = 1; }else if (len == 0){ pass_need = 0; - memset(apconf.password, 0, 64); + os_memset(apconf.password, 0, 64); }else{ jsonHeader(connData, 400); httpdSend(connData, "PASSWORD not valid or out of range", -1); @@ -893,7 +893,7 @@ void ICACHE_FLASH_ATTR wifiInit() { // Check if both ssid and pass are alphanumeric values if(checkString(VERS_STR(AP_SSID)) && checkString(VERS_STR(AP_PASS))){ // Clean memory and set the value of SSID - memset(apconf.ssid, 0, 32); + os_memset(apconf.ssid, 0, 32); os_memcpy(apconf.ssid, VERS_STR(AP_SSID), os_strlen(VERS_STR(AP_SSID))); // Specify the length of pass apconf.ssid_len= os_strlen((char*)VERS_STR(AP_SSID)); @@ -901,7 +901,7 @@ void ICACHE_FLASH_ATTR wifiInit() { int passlen = os_strlen(VERS_STR(AP_PASS)); if( passlen > 7 && passlen < 64 ){ // Clean memory and set the value of PASS - memset(apconf.password, 0, 64); + os_memset(apconf.password, 0, 64); os_memcpy(apconf.password, VERS_STR(AP_PASS), passlen); // Can't choose auth mode without a valid ssid and password @@ -917,7 +917,7 @@ void ICACHE_FLASH_ATTR wifiInit() { // If ssid is ok and no pass set auth open apconf.authmode = AUTH_OPEN; // Remove stored password - memset(apconf.password, 0, 64); + os_memset(apconf.password, 0, 64); } }// end of ssid and pass check #ifdef AP_SSID_HIDDEN From 5f8da7e2b0c9a3a7e9acda0b08482e5968115fe8 Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Sat, 2 Jan 2016 12:49:59 +0100 Subject: [PATCH 13/29] Redundant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added an if statement to APs scans cgi to avoid scan in AP mode. Reduced to one set of warnings and add a fourth line to cover the only AP mode option in Soft-AP setting´s page --- esp-link/cgiwifi.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/esp-link/cgiwifi.c b/esp-link/cgiwifi.c index bb170ff..8c6b33e 100644 --- a/esp-link/cgiwifi.c +++ b/esp-link/cgiwifi.c @@ -705,11 +705,6 @@ static char *wifiWarn[] = { 0, "Switch to <a href=\\\"#\\\" onclick=\\\"changeWifiMode(3)\\\">STA+AP mode</a>", "Switch to <a href=\\\"#\\\" onclick=\\\"changeWifiMode(3)\\\">STA+AP mode</a>", "Switch to <a href=\\\"#\\\" onclick=\\\"changeWifiMode(1)\\\">STA mode</a>", -}; - -static char *apWifiWarn[] = { 0, - "Switch to <a href=\\\"#\\\" onclick=\\\"changeWifiMode(3)\\\">STA+AP mode</a>", - "Switch to <a href=\\\"#\\\" onclick=\\\"changeWifiMode(3)\\\">STA+AP mode</a>", "Switch to <a href=\\\"#\\\" onclick=\\\"changeWifiMode(2)\\\">AP mode</a>", }; @@ -743,7 +738,8 @@ int ICACHE_FLASH_ATTR printWifiInfo(char *buff) { int p = wifi_get_phy_mode(); char *phy = wifiPhy[p&3]; char *warn = wifiWarn[op]; - char *apwarn = apWifiWarn[op]; + if (op == 3) op = 4; // Done to use only one set of warnings + char *apwarn = wifiWarn[op]; char *apauth = apAuthMode[apconf.authmode]; sint8 rssi = wifi_station_get_rssi(); if (rssi > 0) rssi = 0; From 8adfcb6e6007a2cedca89dad5b3fc933f0c2c12d Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Sat, 2 Jan 2016 12:51:35 +0100 Subject: [PATCH 14/29] Reduced to essential It was to much code to such a tiny task --- esp-link/cgiwifi.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/esp-link/cgiwifi.c b/esp-link/cgiwifi.c index 8c6b33e..f61ca0e 100644 --- a/esp-link/cgiwifi.c +++ b/esp-link/cgiwifi.c @@ -823,25 +823,17 @@ int ICACHE_FLASH_ATTR cgiWifiInfo(HttpdConnData *connData) { // Check string againt invalid characters int ICACHE_FLASH_ATTR checkString(char *str){ - unsigned char strStripped[50]; - int i = 0, c = 0; + int i = 0; for(; i < os_strlen(str); i++) { // Alphanumeric and underscore allowed - if (isalnum((unsigned char)str[i]) || str[i] == '_') + if (!(isalnum((unsigned char)str[i]) || str[i] == '_')) { - strStripped[c] = str[i]; - c++; + os_printf("Error: String has non alphanumeric chars\n"); + return 0; } } - strStripped[c] = '\0'; - - if (os_strcmp((char *)str,(char *)&strStripped) == 0){ - return 1; - }else{ - os_printf("Error: String has non alphanumeric chars\n"); - return 0; - } + return 1; } /* Init the wireless From 6f4cead19973ff0c6e7a67f903e9a5fa9cc63645 Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Sat, 2 Jan 2016 12:53:21 +0100 Subject: [PATCH 15/29] Changed to Macro debug --- esp-link/cgiwifi.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/esp-link/cgiwifi.c b/esp-link/cgiwifi.c index f61ca0e..64c551d 100644 --- a/esp-link/cgiwifi.c +++ b/esp-link/cgiwifi.c @@ -855,9 +855,9 @@ void ICACHE_FLASH_ATTR wifiInit() { wifi_station_get_config_default(&stconf); wifi_softap_get_config_default(&apconf); -#ifdef CGIWIFI_DBG - os_printf("Wifi init, mode=%s\n",wifiMode[x]); -#endif + + DBG("Wifi init, mode=%s\n",wifiMode[x]); + // STATION parameters only on a full flash, because default opmode is 2 #if defined(STA_SSID) && defined(STA_PASS) @@ -866,9 +866,9 @@ void ICACHE_FLASH_ATTR wifiInit() { if (os_strlen((char*)stconf.ssid) == 0 && os_strlen((char*)stconf.password) == 0) { os_strncpy((char*)stconf.ssid, VERS_STR(STA_SSID), 32); os_strncpy((char*)stconf.password, VERS_STR(STA_PASS), 64); -#ifdef CGIWIFI_DBG - os_printf("Wifi pre-config trying to connect to AP %s pw %s\n",(char*)stconf.ssid, (char*)stconf.password); -#endif + + DBG("Wifi pre-config trying to connect to AP %s pw %s\n",(char*)stconf.ssid, (char*)stconf.password); + // wifi_set_phy_mode(2); // limit to 802.11b/g 'cause n is flaky stconf.bssid_set = 0; wifi_station_set_config(&stconf); @@ -923,13 +923,11 @@ void ICACHE_FLASH_ATTR wifiInit() { if(AP_BEACON_INTERVAL >= 100 && AP_BEACON_INTERVAL <= 60000) apconf.beacon_interval = AP_BEACON_INTERVAL; #endif - // Check save softap config + // Check softap config bool softap_set_conf = wifi_softap_set_config(&apconf); -#ifdef CGIWIFI_DBG // Debug info - //os_printf("Wifi AP parameters: %s pw %s\n",(char*)apconf.ssid, (char*)apconf.password); - os_printf("Wifi Soft-AP parameters change: %s\n",softap_set_conf? "success":"fail"); -#endif + + DBG("Wifi Soft-AP parameters change: %s\n",softap_set_conf? "success":"fail"); #endif // AP_SSID && AP_PASS configWifiIP(); From c8aab7611bc77ee7161a9546d5ce39bee29841e4 Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Sat, 2 Jan 2016 13:01:42 +0100 Subject: [PATCH 16/29] Set Station parameters if defined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To allow changes both in STA or AP settings, they should be active. Opmode is set to 3 few lines above, so changes allowed in both STA and AP. Because the above opmode set, this “if” is useless. --- esp-link/cgiwifi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esp-link/cgiwifi.c b/esp-link/cgiwifi.c index 64c551d..8a99645 100644 --- a/esp-link/cgiwifi.c +++ b/esp-link/cgiwifi.c @@ -859,9 +859,9 @@ void ICACHE_FLASH_ATTR wifiInit() { DBG("Wifi init, mode=%s\n",wifiMode[x]); - // STATION parameters only on a full flash, because default opmode is 2 + // STATION parameters #if defined(STA_SSID) && defined(STA_PASS) - if( x == 2 ){ + // Set parameters if (os_strlen((char*)stconf.ssid) == 0 && os_strlen((char*)stconf.password) == 0) { os_strncpy((char*)stconf.ssid, VERS_STR(STA_SSID), 32); @@ -873,7 +873,7 @@ void ICACHE_FLASH_ATTR wifiInit() { stconf.bssid_set = 0; wifi_station_set_config(&stconf); } - } + #endif // Change SOFT_AP settings if defined From 0f1ddae28eb48dac86e01610a6869843d8b0f954 Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Sat, 2 Jan 2016 13:33:49 +0100 Subject: [PATCH 17/29] Modified to cover all possible options Case scenario: -new AP SSID without password, keep old password and auth mode -new AP SSID with password empty, auth mode set to OPEN -new AP SSID with password, default auth mode WPA2 --- esp-link/cgiwifi.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/esp-link/cgiwifi.c b/esp-link/cgiwifi.c index 8a99645..d1c2466 100644 --- a/esp-link/cgiwifi.c +++ b/esp-link/cgiwifi.c @@ -877,17 +877,19 @@ void ICACHE_FLASH_ATTR wifiInit() { #endif // Change SOFT_AP settings if defined -#if defined(AP_SSID) && defined(AP_PASS) - // Check if both ssid and pass are alphanumeric values - if(checkString(VERS_STR(AP_SSID)) && checkString(VERS_STR(AP_PASS))){ +#if defined(AP_SSID) + // Check if ssid and pass are alphanumeric values + int ssidlen = os_strlen(VERS_STR(AP_SSID)); + if(checkString(VERS_STR(AP_SSID)) && ssidlen > 7 && ssidlen < 32){ // Clean memory and set the value of SSID os_memset(apconf.ssid, 0, 32); os_memcpy(apconf.ssid, VERS_STR(AP_SSID), os_strlen(VERS_STR(AP_SSID))); // Specify the length of pass - apconf.ssid_len= os_strlen((char*)VERS_STR(AP_SSID)); + apconf.ssid_len= ssidlen; +#if defined(AP_PASS) // If pass is at least 8 and less than 64 int passlen = os_strlen(VERS_STR(AP_PASS)); - if( passlen > 7 && passlen < 64 ){ + if( checkString(VERS_STR(AP_PASS)) && passlen > 7 && passlen < 64 ){ // Clean memory and set the value of PASS os_memset(apconf.password, 0, 64); os_memcpy(apconf.password, VERS_STR(AP_PASS), passlen); @@ -898,15 +900,16 @@ void ICACHE_FLASH_ATTR wifiInit() { if(AP_AUTH_MODE >= 0 && AP_AUTH_MODE <=4) apconf.authmode = AP_AUTH_MODE; #else - // If not, use OPEN - apconf.authmode = AUTH_OPEN; + // If not, use WPA2 + apconf.authmode = AUTH_WPA_WPA2_PSK; #endif }else if ( passlen == 0){ - // If ssid is ok and no pass set auth open + // If ssid is ok and no pass, set auth open apconf.authmode = AUTH_OPEN; // Remove stored password os_memset(apconf.password, 0, 64); } +#endif }// end of ssid and pass check #ifdef AP_SSID_HIDDEN // If set, use specified ssid hidden parameter From 70f5903abd66a5e0835178bfa0ecb00dadd0546b Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Sat, 2 Jan 2016 13:50:08 +0100 Subject: [PATCH 18/29] Int to bool --- esp-link/cgiwifi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/esp-link/cgiwifi.c b/esp-link/cgiwifi.c index d1c2466..3603fd0 100644 --- a/esp-link/cgiwifi.c +++ b/esp-link/cgiwifi.c @@ -526,7 +526,7 @@ int ICACHE_FLASH_ATTR cgiApSettingsChange(HttpdConnData *connData) { char buff[96]; int len; // Do we need a password? - int pass_need=1; + bool pass_need=true; // Check extra security measure len=httpdFindArg(connData->getArgs, "100", buff, sizeof(buff)); @@ -543,9 +543,9 @@ int ICACHE_FLASH_ATTR cgiApSettingsChange(HttpdConnData *connData) { os_memset(apconf.ssid, 0, 32); os_memcpy(apconf.ssid, buff, len); apconf.ssid_len = len; - pass_need = 1; + pass_need = true; }else{ - pass_need = 0; + pass_need = false; jsonHeader(connData, 400); httpdSend(connData, "SSID not valid or out of range", -1); return HTTPD_CGI_DONE; @@ -557,9 +557,9 @@ int ICACHE_FLASH_ATTR cgiApSettingsChange(HttpdConnData *connData) { // STRING PREPROCESSING DONE IN CLIENT SIDE os_memset(apconf.password, 0, 64); os_memcpy(apconf.password, buff, len); - pass_need = 1; + pass_need = true; }else if (len == 0){ - pass_need = 0; + pass_need = false; os_memset(apconf.password, 0, 64); }else{ jsonHeader(connData, 400); From 132f4ccd585013bbacd141c93101fda2622b0d83 Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Sat, 2 Jan 2016 14:04:07 +0100 Subject: [PATCH 19/29] Add default WPA2 when a password was specified --- esp-link/cgiwifi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esp-link/cgiwifi.c b/esp-link/cgiwifi.c index 3603fd0..fac5a03 100644 --- a/esp-link/cgiwifi.c +++ b/esp-link/cgiwifi.c @@ -579,6 +579,8 @@ int ICACHE_FLASH_ATTR cgiApSettingsChange(HttpdConnData *connData) { // If out of range set by default apconf.authmode = 4; } + }else{ + apconf.authmode = 4; } }else{ apconf.authmode = 0; From 62c5f4fc1792ef8b293b676e675e511c4aa0a129 Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Sat, 2 Jan 2016 14:09:54 +0100 Subject: [PATCH 20/29] Modified comments to match actions --- esp-link/cgiwifi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esp-link/cgiwifi.c b/esp-link/cgiwifi.c index fac5a03..6ca78d8 100644 --- a/esp-link/cgiwifi.c +++ b/esp-link/cgiwifi.c @@ -679,7 +679,7 @@ int ICACHE_FLASH_ATTR cgiWiFiSetMode(HttpdConnData *connData) { wifi_set_opmode(next_mode&3); if (previous_mode == 2) { - // movint to STA-only mode from AP, so reset into STA+AP after a timeout if we don't get an IP address + // moving to STA or STA+AP mode from AP stconf.bssid_set = 0; wifi_station_set_config(&stconf); wifi_station_connect(); @@ -688,7 +688,7 @@ int ICACHE_FLASH_ATTR cgiWiFiSetMode(HttpdConnData *connData) { os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); } if(previous_mode == 1){ - // moving to STA or STA+AP, so softap config call needed + // moving to AP or STA+AP, so softap config call needed wifi_softap_set_config(&apconf); } jsonHeader(connData, 200); From a10cc380dcb5964218af9b0421c838acfb229137 Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Mon, 4 Jan 2016 14:33:26 +0100 Subject: [PATCH 21/29] Back to default --- esp-link/cgi.c | 2 +- esp-link/cgi.h | 2 +- esp-link/cgipins.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esp-link/cgi.c b/esp-link/cgi.c index c658fb6..6879cd6 100644 --- a/esp-link/cgi.c +++ b/esp-link/cgi.c @@ -106,7 +106,7 @@ int8_t ICACHE_FLASH_ATTR getUInt16Arg(HttpdConnData *connData, char *name, uint1 return 1; } -int8_t ICACHE_FLASH_ATTR getBoolArg(HttpdConnData *connData, char *name, uint8_t *config) { +int8_t ICACHE_FLASH_ATTR getBoolArg(HttpdConnData *connData, char *name, bool *config) { char buff[16]; int len = httpdFindArg(connData->getArgs, name, buff, sizeof(buff)); if (len < 0) return 0; // not found, skip diff --git a/esp-link/cgi.h b/esp-link/cgi.h index 330a5e6..cb897b0 100644 --- a/esp-link/cgi.h +++ b/esp-link/cgi.h @@ -26,7 +26,7 @@ int8_t getUInt16Arg(HttpdConnData *connData, char *name, uint16_t *config); // Get the HTTP query-string param 'name' and store it boolean value at 'config', // supports 1/true and 0/false, returns -1 on error, 0 if not found, 1 if found -int8_t getBoolArg(HttpdConnData *connData, char *name, uint8_t *config); +int8_t getBoolArg(HttpdConnData *connData, char *name, bool *config); int cgiMenu(HttpdConnData *connData); diff --git a/esp-link/cgipins.c b/esp-link/cgipins.c index 6273389..8455a16 100644 --- a/esp-link/cgipins.c +++ b/esp-link/cgipins.c @@ -49,7 +49,7 @@ int ICACHE_FLASH_ATTR cgiPinsSet(HttpdConnData *connData) { int8_t ok = 0; int8_t reset, isp, conn, ser; - uint8_t swap, rxpup; + bool swap, rxpup; ok |= getInt8Arg(connData, "reset", &reset); ok |= getInt8Arg(connData, "isp", &isp); ok |= getInt8Arg(connData, "conn", &conn); From 8351fb45994b41e700aa091090d0f16342672565 Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Mon, 4 Jan 2016 14:36:52 +0100 Subject: [PATCH 22/29] Back to default --- Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile b/Makefile index 2166eeb..8de4074 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,6 @@ # Makefile heavily adapted to esp-link and wireless flashing by Thorsten von Eicken # Lots of work, in particular to support windows, by brunnels # Original from esphttpd and others... -# Added support for SOFTAP hard-coded configuration by KatAst # VERBOSE=1 # # Start by setting the directories for the toolchain a few lines down From 9dd3eac8042c6935f770652333f0a3838b80e788 Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Mon, 4 Jan 2016 15:13:51 +0100 Subject: [PATCH 23/29] Fix indentation --- esp-link/cgiwifi.c | 813 ++++++++++++++++++++++----------------------- 1 file changed, 398 insertions(+), 415 deletions(-) mode change 100644 => 100755 esp-link/cgiwifi.c diff --git a/esp-link/cgiwifi.c b/esp-link/cgiwifi.c old mode 100644 new mode 100755 index 6ca78d8..af496ee --- a/esp-link/cgiwifi.c +++ b/esp-link/cgiwifi.c @@ -1,3 +1,7 @@ +/* +Cgi/template routines for the /wifi url. +*/ + /* * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): @@ -7,8 +11,6 @@ * ---------------------------------------------------------------------------- * Heavily modified and enhanced by Thorsten von Eicken in 2015 * ---------------------------------------------------------------------------- - * Once again heavily modified to add soft-ap settings by KatAst in 2015 - * ---------------------------------------------------------------------------- */ #include <esp8266.h> @@ -39,16 +41,15 @@ struct station_config stconf; struct softap_config apconf; uint8_t wifiState = wifiIsDisconnected; - // reasons for which a connection failed uint8_t wifiReason = 0; static char *wifiReasons[] = { - "", "unspecified", "auth_expire", "auth_leave", "assoc_expire", "assoc_toomany", "not_authed", - "not_assoced", "assoc_leave", "assoc_not_authed", "disassoc_pwrcap_bad", "disassoc_supchan_bad", - "ie_invalid", "mic_failure", "4way_handshake_timeout", "group_key_update_timeout", - "ie_in_4way_differs", "group_cipher_invalid", "pairwise_cipher_invalid", "akmp_invalid", - "unsupp_rsn_ie_version", "invalid_rsn_ie_cap", "802_1x_auth_failed", "cipher_suite_rejected", - "beacon_timeout", "no_ap_found" }; + "", "unspecified", "auth_expire", "auth_leave", "assoc_expire", "assoc_toomany", "not_authed", + "not_assoced", "assoc_leave", "assoc_not_authed", "disassoc_pwrcap_bad", "disassoc_supchan_bad", + "ie_invalid", "mic_failure", "4way_handshake_timeout", "group_key_update_timeout", + "ie_in_4way_differs", "group_cipher_invalid", "pairwise_cipher_invalid", "akmp_invalid", + "unsupp_rsn_ie_version", "invalid_rsn_ie_cap", "802_1x_auth_failed", "cipher_suite_rejected", + "beacon_timeout", "no_ap_found" }; static char *wifiMode[] = { 0, "STA", "AP", "AP+STA" }; static char *wifiPhy[] = { 0, "11b", "11g", "11n" }; @@ -56,100 +57,100 @@ static char *wifiPhy[] = { 0, "11b", "11g", "11n" }; void (*wifiStatusCb)(uint8_t); // callback when wifi status changes static char* ICACHE_FLASH_ATTR wifiGetReason(void) { - if (wifiReason <= 24) return wifiReasons[wifiReason]; - if (wifiReason >= 200 && wifiReason <= 201) return wifiReasons[wifiReason-200+24]; - return wifiReasons[1]; + if (wifiReason <= 24) return wifiReasons[wifiReason]; + if (wifiReason >= 200 && wifiReason <= 201) return wifiReasons[wifiReason-200+24]; + return wifiReasons[1]; } // handler for wifi status change callback coming in from espressif library static void ICACHE_FLASH_ATTR wifiHandleEventCb(System_Event_t *evt) { - switch (evt->event) { - case EVENT_STAMODE_CONNECTED: - wifiState = wifiIsConnected; - wifiReason = 0; - DBG("Wifi connected to ssid %s, ch %d\n", evt->event_info.connected.ssid, - evt->event_info.connected.channel); - statusWifiUpdate(wifiState); - break; - case EVENT_STAMODE_DISCONNECTED: - wifiState = wifiIsDisconnected; - wifiReason = evt->event_info.disconnected.reason; - DBG("Wifi disconnected from ssid %s, reason %s (%d)\n", - evt->event_info.disconnected.ssid, wifiGetReason(), evt->event_info.disconnected.reason); - statusWifiUpdate(wifiState); - break; - case EVENT_STAMODE_AUTHMODE_CHANGE: - DBG("Wifi auth mode: %d -> %d\n", - evt->event_info.auth_change.old_mode, evt->event_info.auth_change.new_mode); - break; - case EVENT_STAMODE_GOT_IP: - wifiState = wifiGotIP; - wifiReason = 0; - DBG("Wifi got ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR "\n", - IP2STR(&evt->event_info.got_ip.ip), IP2STR(&evt->event_info.got_ip.mask), - IP2STR(&evt->event_info.got_ip.gw)); - statusWifiUpdate(wifiState); - if (!mdns_started) - wifiStartMDNS(evt->event_info.got_ip.ip); - break; - case EVENT_SOFTAPMODE_STACONNECTED: - DBG("Wifi AP: station " MACSTR " joined, AID = %d\n", - MAC2STR(evt->event_info.sta_connected.mac), evt->event_info.sta_connected.aid); - break; - case EVENT_SOFTAPMODE_STADISCONNECTED: - DBG("Wifi AP: station " MACSTR " left, AID = %d\n", - MAC2STR(evt->event_info.sta_disconnected.mac), evt->event_info.sta_disconnected.aid); - break; - default: - break; - } - - for (int i = 0; i < 4; i++) { - if (wifi_state_change_cb[i] != NULL) (wifi_state_change_cb[i])(wifiState); - } + switch (evt->event) { + case EVENT_STAMODE_CONNECTED: + wifiState = wifiIsConnected; + wifiReason = 0; + DBG("Wifi connected to ssid %s, ch %d\n", evt->event_info.connected.ssid, + evt->event_info.connected.channel); + statusWifiUpdate(wifiState); + break; + case EVENT_STAMODE_DISCONNECTED: + wifiState = wifiIsDisconnected; + wifiReason = evt->event_info.disconnected.reason; + DBG("Wifi disconnected from ssid %s, reason %s (%d)\n", + evt->event_info.disconnected.ssid, wifiGetReason(), evt->event_info.disconnected.reason); + statusWifiUpdate(wifiState); + break; + case EVENT_STAMODE_AUTHMODE_CHANGE: + DBG("Wifi auth mode: %d -> %d\n", + evt->event_info.auth_change.old_mode, evt->event_info.auth_change.new_mode); + break; + case EVENT_STAMODE_GOT_IP: + wifiState = wifiGotIP; + wifiReason = 0; + DBG("Wifi got ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR "\n", + IP2STR(&evt->event_info.got_ip.ip), IP2STR(&evt->event_info.got_ip.mask), + IP2STR(&evt->event_info.got_ip.gw)); + statusWifiUpdate(wifiState); + if (!mdns_started) + wifiStartMDNS(evt->event_info.got_ip.ip); + break; + case EVENT_SOFTAPMODE_STACONNECTED: + DBG("Wifi AP: station " MACSTR " joined, AID = %d\n", + MAC2STR(evt->event_info.sta_connected.mac), evt->event_info.sta_connected.aid); + break; + case EVENT_SOFTAPMODE_STADISCONNECTED: + DBG("Wifi AP: station " MACSTR " left, AID = %d\n", + MAC2STR(evt->event_info.sta_disconnected.mac), evt->event_info.sta_disconnected.aid); + break; + default: + break; + } + + for (int i = 0; i < 4; i++) { + if (wifi_state_change_cb[i] != NULL) (wifi_state_change_cb[i])(wifiState); + } } void ICACHE_FLASH_ATTR wifiAddStateChangeCb(WifiStateChangeCb cb) { - for (int i = 0; i < 4; i++) { - if (wifi_state_change_cb[i] == cb) return; - if (wifi_state_change_cb[i] == NULL) { - wifi_state_change_cb[i] = cb; - return; - } - } - DBG("WIFI: max state change cb count exceeded\n"); + for (int i = 0; i < 4; i++) { + if (wifi_state_change_cb[i] == cb) return; + if (wifi_state_change_cb[i] == NULL) { + wifi_state_change_cb[i] = cb; + return; + } + } + DBG("WIFI: max state change cb count exceeded\n"); } void ICACHE_FLASH_ATTR wifiStartMDNS(struct ip_addr ip) { - if (flashConfig.mdns_enable) { - struct mdns_info *mdns_info = (struct mdns_info *)os_zalloc(sizeof(struct mdns_info)); - mdns_info->host_name = flashConfig.hostname; - mdns_info->server_name = flashConfig.mdns_servername; - mdns_info->server_port = 80; - mdns_info->ipAddr = ip.addr; - espconn_mdns_init(mdns_info); - } - else { - espconn_mdns_server_unregister(); - espconn_mdns_close(); - } - mdns_started = true; + if (flashConfig.mdns_enable) { + struct mdns_info *mdns_info = (struct mdns_info *)os_zalloc(sizeof(struct mdns_info)); + mdns_info->host_name = flashConfig.hostname; + mdns_info->server_name = flashConfig.mdns_servername; + mdns_info->server_port = 80; + mdns_info->ipAddr = ip.addr; + espconn_mdns_init(mdns_info); + } + else { + espconn_mdns_server_unregister(); + espconn_mdns_close(); + } + mdns_started = true; } // ===== wifi scanning //WiFi access point data typedef struct { - char ssid[32]; - sint8 rssi; - char enc; + char ssid[32]; + sint8 rssi; + char enc; } ApData; //Scan result typedef struct { - char scanInProgress; //if 1, don't access the underlying stuff from the webpage. - ApData **apData; - int noAps; + char scanInProgress; //if 1, don't access the underlying stuff from the webpage. + ApData **apData; + int noAps; } ScanResultData; //Static scan status storage. @@ -158,126 +159,124 @@ static ScanResultData cgiWifiAps; //Callback the code calls when a wlan ap scan is done. Basically stores the result in //the cgiWifiAps struct. void ICACHE_FLASH_ATTR wifiScanDoneCb(void *arg, STATUS status) { - int n; - struct bss_info *bss_link = (struct bss_info *)arg; - - if (status!=OK) { - DBG("wifiScanDoneCb status=%d\n", status); - cgiWifiAps.scanInProgress=0; - return; - } - - //Clear prev ap data if needed. - if (cgiWifiAps.apData!=NULL) { - for (n=0; n<cgiWifiAps.noAps; n++) os_free(cgiWifiAps.apData[n]); - os_free(cgiWifiAps.apData); - } - - //Count amount of access points found. - n=0; - while (bss_link != NULL) { - bss_link = bss_link->next.stqe_next; - n++; - } - //Allocate memory for access point data - cgiWifiAps.apData=(ApData **)os_malloc(sizeof(ApData *)*n); - cgiWifiAps.noAps=n; - DBG("Scan done: found %d APs\n", n); - - //Copy access point data to the static struct - n=0; - bss_link = (struct bss_info *)arg; - while (bss_link != NULL) { - if (n>=cgiWifiAps.noAps) { - //This means the bss_link changed under our nose. Shouldn't happen! - //Break because otherwise we will write in unallocated memory. - DBG("Huh? I have more than the allocated %d aps!\n", cgiWifiAps.noAps); - break; - } - //Save the ap data. - cgiWifiAps.apData[n]=(ApData *)os_malloc(sizeof(ApData)); - cgiWifiAps.apData[n]->rssi=bss_link->rssi; - cgiWifiAps.apData[n]->enc=bss_link->authmode; - strncpy(cgiWifiAps.apData[n]->ssid, (char*)bss_link->ssid, 32); - DBG("bss%d: %s (%d)\n", n+1, (char*)bss_link->ssid, bss_link->rssi); - - bss_link = bss_link->next.stqe_next; - n++; - } - //We're done. + int n; + struct bss_info *bss_link = (struct bss_info *)arg; + + if (status!=OK) { + DBG("wifiScanDoneCb status=%d\n", status); cgiWifiAps.scanInProgress=0; + return; + } + + //Clear prev ap data if needed. + if (cgiWifiAps.apData!=NULL) { + for (n=0; n<cgiWifiAps.noAps; n++) os_free(cgiWifiAps.apData[n]); + os_free(cgiWifiAps.apData); + } + + //Count amount of access points found. + n=0; + while (bss_link != NULL) { + bss_link = bss_link->next.stqe_next; + n++; + } + //Allocate memory for access point data + cgiWifiAps.apData=(ApData **)os_malloc(sizeof(ApData *)*n); + cgiWifiAps.noAps=n; + DBG("Scan done: found %d APs\n", n); + + //Copy access point data to the static struct + n=0; + bss_link = (struct bss_info *)arg; + while (bss_link != NULL) { + if (n>=cgiWifiAps.noAps) { + //This means the bss_link changed under our nose. Shouldn't happen! + //Break because otherwise we will write in unallocated memory. + DBG("Huh? I have more than the allocated %d aps!\n", cgiWifiAps.noAps); + break; + } + //Save the ap data. + cgiWifiAps.apData[n]=(ApData *)os_malloc(sizeof(ApData)); + cgiWifiAps.apData[n]->rssi=bss_link->rssi; + cgiWifiAps.apData[n]->enc=bss_link->authmode; + strncpy(cgiWifiAps.apData[n]->ssid, (char*)bss_link->ssid, 32); + DBG("bss%d: %s (%d)\n", n+1, (char*)bss_link->ssid, bss_link->rssi); + + bss_link = bss_link->next.stqe_next; + n++; + } + //We're done. + cgiWifiAps.scanInProgress=0; } static ETSTimer scanTimer; static void ICACHE_FLASH_ATTR scanStartCb(void *arg) { - DBG("Starting a scan\n"); - wifi_station_scan(NULL, wifiScanDoneCb); + DBG("Starting a scan\n"); + wifi_station_scan(NULL, wifiScanDoneCb); } static int ICACHE_FLASH_ATTR cgiWiFiStartScan(HttpdConnData *connData) { - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - jsonHeader(connData, 200); - if (!cgiWifiAps.scanInProgress) { - cgiWifiAps.scanInProgress = 1; - os_timer_disarm(&scanTimer); - os_timer_setfn(&scanTimer, scanStartCb, NULL); - os_timer_arm(&scanTimer, 200, 0); - } - return HTTPD_CGI_DONE; + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + jsonHeader(connData, 200); + if (!cgiWifiAps.scanInProgress) { + cgiWifiAps.scanInProgress = 1; + os_timer_disarm(&scanTimer); + os_timer_setfn(&scanTimer, scanStartCb, NULL); + os_timer_arm(&scanTimer, 200, 0); + } + return HTTPD_CGI_DONE; } static int ICACHE_FLASH_ATTR cgiWiFiGetScan(HttpdConnData *connData) { - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - char buff[1460]; - const int chunk = 1460/64; // ssid is up to 32 chars - int len = 0; - - os_printf("GET scan: cgiData=%d noAps=%d\n", (int)connData->cgiData, cgiWifiAps.noAps); - - // handle continuation call, connData->cgiData-1 is the position in the scan results where we - // we need to continue sending from (using -1 'cause 0 means it's the first call) - if (connData->cgiData) { - int next = (int)connData->cgiData-1; - int pos = next; - while (pos < cgiWifiAps.noAps && pos < next+chunk) { - len += os_sprintf(buff+len, "{\"essid\": \"%s\", \"rssi\": %d, \"enc\": \"%d\"}%c\n", - cgiWifiAps.apData[pos]->ssid, cgiWifiAps.apData[pos]->rssi, cgiWifiAps.apData[pos]->enc, - (pos+1 == cgiWifiAps.noAps) ? ' ' : ','); - pos++; - } - // done or more? - if (pos == cgiWifiAps.noAps) { - len += os_sprintf(buff+len, "]}}\n"); - httpdSend(connData, buff, len); - return HTTPD_CGI_DONE; - } else { - connData->cgiData = (void*)(pos+1); - httpdSend(connData, buff, len); - return HTTPD_CGI_MORE; - } - } - - jsonHeader(connData, 200); - - if (cgiWifiAps.scanInProgress==1) { - //We're still scanning. Tell Javascript code that. - len = os_sprintf(buff, "{\n \"result\": { \n\"inProgress\": \"1\"\n }\n}\n"); - httpdSend(connData, buff, len); - return HTTPD_CGI_DONE; + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + char buff[1460]; + const int chunk = 1460/64; // ssid is up to 32 chars + int len = 0; + + os_printf("GET scan: cgiData=%d noAps=%d\n", (int)connData->cgiData, cgiWifiAps.noAps); + + // handle continuation call, connData->cgiData-1 is the position in the scan results where we + // we need to continue sending from (using -1 'cause 0 means it's the first call) + if (connData->cgiData) { + int next = (int)connData->cgiData-1; + int pos = next; + while (pos < cgiWifiAps.noAps && pos < next+chunk) { + len += os_sprintf(buff+len, "{\"essid\": \"%s\", \"rssi\": %d, \"enc\": \"%d\"}%c\n", + cgiWifiAps.apData[pos]->ssid, cgiWifiAps.apData[pos]->rssi, cgiWifiAps.apData[pos]->enc, + (pos+1 == cgiWifiAps.noAps) ? ' ' : ','); + pos++; + } + // done or more? + if (pos == cgiWifiAps.noAps) { + len += os_sprintf(buff+len, "]}}\n"); + httpdSend(connData, buff, len); + return HTTPD_CGI_DONE; + } else { + connData->cgiData = (void*)(pos+1); + httpdSend(connData, buff, len); + return HTTPD_CGI_MORE; } - - len = os_sprintf(buff, "{\"result\": {\"inProgress\": \"0\", \"APs\": [\n"); - connData->cgiData = (void *)1; // start with first result next time we're called + } + + jsonHeader(connData, 200); + + if (cgiWifiAps.scanInProgress==1) { + //We're still scanning. Tell Javascript code that. + len = os_sprintf(buff, "{\n \"result\": { \n\"inProgress\": \"1\"\n }\n}\n"); httpdSend(connData, buff, len); - return HTTPD_CGI_MORE; + return HTTPD_CGI_DONE; + } + + len = os_sprintf(buff, "{\"result\": {\"inProgress\": \"0\", \"APs\": [\n"); + connData->cgiData = (void *)1; // start with first result next time we're called + httpdSend(connData, buff, len); + return HTTPD_CGI_MORE; } int ICACHE_FLASH_ATTR cgiWiFiScan(HttpdConnData *connData) { - if (connData->requestType == HTTPD_METHOD_GET) { return cgiWiFiGetScan(connData); - }else if(connData->requestType == HTTPD_METHOD_POST) - { + }else if(connData->requestType == HTTPD_METHOD_POST) { // DO NOT start APs scan in AP mode int mode = wifi_get_opmode(); if(mode==2){ @@ -298,13 +297,10 @@ int ICACHE_FLASH_ATTR cgiWiFiScan(HttpdConnData *connData) { #define RESET_TIMEOUT (15000) // 15 seconds static ETSTimer resetTimer; -/* - * This routine is ran some time after a connection attempt to an access point. - * If the connection succeeds and Makefile hard-coded CHANGE_TO_STA is set to yes, this gets the module in STA-only mode. - * If it fails and only STA mode is set, it ensures that the module is in STA+AP mode so the user has a chance to recover. - */ +// This routine is ran some time after a connection attempt to an access point. If +// the connect succeeds, this gets the module in STA-only mode. If it fails, it ensures +// that the module is in STA+AP mode so the user has a chance to recover. static void ICACHE_FLASH_ATTR resetTimerCb(void *arg) { - int x = wifi_station_get_connect_status(); int m = wifi_get_opmode() & 0x3; DBG("Wifi check: mode=%s status=%d\n", wifiMode[m], x); @@ -312,8 +308,8 @@ static void ICACHE_FLASH_ATTR resetTimerCb(void *arg) { if(m!=2){ if( x == STATION_GOT_IP ){ #ifdef CHANGE_TO_STA - if(m != 1) - wifi_set_opmode(1); + if(m != 1) + wifi_set_opmode(1); #endif log_uart(false); }else{ @@ -333,178 +329,174 @@ static ETSTimer reassTimer; // Callback actually doing reassociation static void ICACHE_FLASH_ATTR reassTimerCb(void *arg) { - DBG("Wifi changing association\n"); - wifi_station_disconnect(); - stconf.bssid_set = 0; - wifi_station_set_config(&stconf); - wifi_station_connect(); - // Schedule check, we give some extra time (4x) 'cause the reassociation can cause the AP - // to have to change channel, and then the client needs to follow before it can see the - // IP address - os_timer_disarm(&resetTimer); - os_timer_setfn(&resetTimer, resetTimerCb, NULL); - os_timer_arm(&resetTimer, 4*RESET_TIMEOUT, 0); + DBG("Wifi changing association\n"); + wifi_station_disconnect(); + stconf.bssid_set = 0; + wifi_station_set_config(&stconf); + wifi_station_connect(); + // Schedule check, we give some extra time (4x) 'cause the reassociation can cause the AP + // to have to change channel, and then the client needs to follow before it can see the + // IP address + os_timer_disarm(&resetTimer); + os_timer_setfn(&resetTimer, resetTimerCb, NULL); + os_timer_arm(&resetTimer, 4*RESET_TIMEOUT, 0); } // This cgi uses the routines above to connect to a specific access point with the // given ESSID using the given password. int ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData) { - int mode = wifi_get_opmode(); if(mode == 2){ jsonHeader(connData, 400); httpdSend(connData, "Can't associate to an AP en SoftAP mode", -1); return HTTPD_CGI_DONE; } - - char essid[128]; - char passwd[128]; - - if (connData->conn==NULL) return HTTPD_CGI_DONE; - - int el = httpdFindArg(connData->getArgs, "essid", essid, sizeof(essid)); - int pl = httpdFindArg(connData->getArgs, "passwd", passwd, sizeof(passwd)); - - if (el > 0 && pl >= 0) { - //Set to 0 if you want to disable the actual reconnecting bit - os_strncpy((char*)stconf.ssid, essid, 32); - os_strncpy((char*)stconf.password, passwd, 64); - DBG("Wifi try to connect to AP %s pw %s\n", essid, passwd); - - //Schedule disconnect/connect - os_timer_disarm(&reassTimer); - os_timer_setfn(&reassTimer, reassTimerCb, NULL); - os_timer_arm(&reassTimer, 1000, 0); // 1 second for the response of this request to make it - jsonHeader(connData, 200); - } else { - jsonHeader(connData, 400); - httpdSend(connData, "Cannot parse ssid or password", -1); - } + char essid[128]; + char passwd[128]; + + if (connData->conn==NULL) return HTTPD_CGI_DONE; + + int el = httpdFindArg(connData->getArgs, "essid", essid, sizeof(essid)); + int pl = httpdFindArg(connData->getArgs, "passwd", passwd, sizeof(passwd)); + + if (el > 0 && pl >= 0) { + //Set to 0 if you want to disable the actual reconnecting bit + os_strncpy((char*)stconf.ssid, essid, 32); + os_strncpy((char*)stconf.password, passwd, 64); + DBG("Wifi try to connect to AP %s pw %s\n", essid, passwd); + + //Schedule disconnect/connect + os_timer_disarm(&reassTimer); + os_timer_setfn(&reassTimer, reassTimerCb, NULL); + os_timer_arm(&reassTimer, 1000, 0); // 1 second for the response of this request to make it + jsonHeader(connData, 200); + } else { jsonHeader(connData, 400); - httpdSend(connData, "Invalid ssid or password", -1); - return HTTPD_CGI_DONE; + httpdSend(connData, "Cannot parse ssid or password", -1); + } + return HTTPD_CGI_DONE; } static bool ICACHE_FLASH_ATTR parse_ip(char *buff, ip_addr_t *ip_ptr) { - char *next = buff; // where to start parsing next integer - int found = 0; // number of integers parsed - uint32_t ip = 0; // the ip addres parsed - for (int i=0; i<32; i++) { // 32 is just a safety limit - char c = buff[i]; - if (c == '.' || c == 0) { - // parse the preceding integer and accumulate into IP address - bool last = c == 0; - buff[i] = 0; - uint32_t v = atoi(next); - ip = ip | ((v&0xff)<<(found*8)); - next = buff+i+1; // next integer starts after the '.' - found++; - if (last) { // if at end of string we better got 4 integers - ip_ptr->addr = ip; - return found == 4; - } - continue; - } - if (c < '0' || c > '9') return false; - } - return false; + char *next = buff; // where to start parsing next integer + int found = 0; // number of integers parsed + uint32_t ip = 0; // the ip addres parsed + for (int i=0; i<32; i++) { // 32 is just a safety limit + char c = buff[i]; + if (c == '.' || c == 0) { + // parse the preceding integer and accumulate into IP address + bool last = c == 0; + buff[i] = 0; + uint32_t v = atoi(next); + ip = ip | ((v&0xff)<<(found*8)); + next = buff+i+1; // next integer starts after the '.' + found++; + if (last) { // if at end of string we better got 4 integers + ip_ptr->addr = ip; + return found == 4; + } + continue; + } + if (c < '0' || c > '9') return false; + } + return false; } #ifdef DEBUGIP static void ICACHE_FLASH_ATTR debugIP() { - struct ip_info info; - if (wifi_get_ip_info(0, &info)) { - os_printf("\"ip\": \"%d.%d.%d.%d\"\n", IP2STR(&info.ip.addr)); - os_printf("\"netmask\": \"%d.%d.%d.%d\"\n", IP2STR(&info.netmask.addr)); - os_printf("\"gateway\": \"%d.%d.%d.%d\"\n", IP2STR(&info.gw.addr)); - os_printf("\"hostname\": \"%s\"\n", wifi_station_get_hostname()); - } else { - os_printf("\"ip\": \"-none-\"\n"); - } + struct ip_info info; + if (wifi_get_ip_info(0, &info)) { + os_printf("\"ip\": \"%d.%d.%d.%d\"\n", IP2STR(&info.ip.addr)); + os_printf("\"netmask\": \"%d.%d.%d.%d\"\n", IP2STR(&info.netmask.addr)); + os_printf("\"gateway\": \"%d.%d.%d.%d\"\n", IP2STR(&info.gw.addr)); + os_printf("\"hostname\": \"%s\"\n", wifi_station_get_hostname()); + } else { + os_printf("\"ip\": \"-none-\"\n"); + } } #endif // configure Wifi, specifically DHCP vs static IP address based on flash config void ICACHE_FLASH_ATTR configWifiIP() { - if (flashConfig.staticip == 0) { - // let's DHCP! - wifi_station_set_hostname(flashConfig.hostname); - if (wifi_station_dhcpc_status() == DHCP_STARTED) - wifi_station_dhcpc_stop(); - wifi_station_dhcpc_start(); - DBG("Wifi uses DHCP, hostname=%s\n", flashConfig.hostname); - } else { - // no DHCP, we got static network config! - wifi_station_dhcpc_stop(); - struct ip_info ipi; - ipi.ip.addr = flashConfig.staticip; - ipi.netmask.addr = flashConfig.netmask; - ipi.gw.addr = flashConfig.gateway; - wifi_set_ip_info(0, &ipi); - DBG("Wifi uses static IP %d.%d.%d.%d\n", IP2STR(&ipi.ip.addr)); - } + if (flashConfig.staticip == 0) { + // let's DHCP! + wifi_station_set_hostname(flashConfig.hostname); + if (wifi_station_dhcpc_status() == DHCP_STARTED) + wifi_station_dhcpc_stop(); + wifi_station_dhcpc_start(); + DBG("Wifi uses DHCP, hostname=%s\n", flashConfig.hostname); + } else { + // no DHCP, we got static network config! + wifi_station_dhcpc_stop(); + struct ip_info ipi; + ipi.ip.addr = flashConfig.staticip; + ipi.netmask.addr = flashConfig.netmask; + ipi.gw.addr = flashConfig.gateway; + wifi_set_ip_info(0, &ipi); + DBG("Wifi uses static IP %d.%d.%d.%d\n", IP2STR(&ipi.ip.addr)); + } #ifdef DEBUGIP - debugIP(); + debugIP(); #endif } // Change special settings int ICACHE_FLASH_ATTR cgiWiFiSpecial(HttpdConnData *connData) { - char dhcp[8]; - char staticip[20]; - char netmask[20]; - char gateway[20]; - - if (connData->conn==NULL) return HTTPD_CGI_DONE; - - // get args and their string lengths - int dl = httpdFindArg(connData->getArgs, "dhcp", dhcp, sizeof(dhcp)); - int sl = httpdFindArg(connData->getArgs, "staticip", staticip, sizeof(staticip)); - int nl = httpdFindArg(connData->getArgs, "netmask", netmask, sizeof(netmask)); - int gl = httpdFindArg(connData->getArgs, "gateway", gateway, sizeof(gateway)); - - if (!(dl > 0 && sl >= 0 && nl >= 0 && gl >= 0)) { - jsonHeader(connData, 400); - httpdSend(connData, "Request is missing fields", -1); - return HTTPD_CGI_DONE; - } - - char url[64]; // redirect URL - if (os_strcmp(dhcp, "off") == 0) { - // parse static IP params - struct ip_info ipi; - bool ok = parse_ip(staticip, &ipi.ip); - if (nl > 0) ok = ok && parse_ip(netmask, &ipi.netmask); - else IP4_ADDR(&ipi.netmask, 255, 255, 255, 0); - if (gl > 0) ok = ok && parse_ip(gateway, &ipi.gw); - else ipi.gw.addr = 0; - if (!ok) { - jsonHeader(connData, 400); - httpdSend(connData, "Cannot parse static IP config", -1); - return HTTPD_CGI_DONE; - } - // save the params in flash - flashConfig.staticip = ipi.ip.addr; - flashConfig.netmask = ipi.netmask.addr; - flashConfig.gateway = ipi.gw.addr; - // construct redirect URL - os_sprintf(url, "{\"url\": \"http://%d.%d.%d.%d\"}", IP2STR(&ipi.ip)); - - } else { - // dynamic IP - flashConfig.staticip = 0; - os_sprintf(url, "{\"url\": \"http://%s\"}", flashConfig.hostname); - } - - configSave(); // ignore error... - // schedule change-over - os_timer_disarm(&reassTimer); - os_timer_setfn(&reassTimer, configWifiIP, NULL); - os_timer_arm(&reassTimer, 1000, 0); // 1 second for the response of this request to make it - // return redirect info - jsonHeader(connData, 200); - httpdSend(connData, url, -1); + char dhcp[8]; + char staticip[20]; + char netmask[20]; + char gateway[20]; + + if (connData->conn==NULL) return HTTPD_CGI_DONE; + + // get args and their string lengths + int dl = httpdFindArg(connData->getArgs, "dhcp", dhcp, sizeof(dhcp)); + int sl = httpdFindArg(connData->getArgs, "staticip", staticip, sizeof(staticip)); + int nl = httpdFindArg(connData->getArgs, "netmask", netmask, sizeof(netmask)); + int gl = httpdFindArg(connData->getArgs, "gateway", gateway, sizeof(gateway)); + + if (!(dl > 0 && sl >= 0 && nl >= 0 && gl >= 0)) { + jsonHeader(connData, 400); + httpdSend(connData, "Request is missing fields", -1); return HTTPD_CGI_DONE; + } + + char url[64]; // redirect URL + if (os_strcmp(dhcp, "off") == 0) { + // parse static IP params + struct ip_info ipi; + bool ok = parse_ip(staticip, &ipi.ip); + if (nl > 0) ok = ok && parse_ip(netmask, &ipi.netmask); + else IP4_ADDR(&ipi.netmask, 255, 255, 255, 0); + if (gl > 0) ok = ok && parse_ip(gateway, &ipi.gw); + else ipi.gw.addr = 0; + if (!ok) { + jsonHeader(connData, 400); + httpdSend(connData, "Cannot parse static IP config", -1); + return HTTPD_CGI_DONE; + } + // save the params in flash + flashConfig.staticip = ipi.ip.addr; + flashConfig.netmask = ipi.netmask.addr; + flashConfig.gateway = ipi.gw.addr; + // construct redirect URL + os_sprintf(url, "{\"url\": \"http://%d.%d.%d.%d\"}", IP2STR(&ipi.ip)); + + } else { + // dynamic IP + flashConfig.staticip = 0; + os_sprintf(url, "{\"url\": \"http://%s\"}", flashConfig.hostname); + } + + configSave(); // ignore error... + // schedule change-over + os_timer_disarm(&reassTimer); + os_timer_setfn(&reassTimer, configWifiIP, NULL); + os_timer_arm(&reassTimer, 1000, 0); // 1 second for the response of this request to make it + // return redirect info + jsonHeader(connData, 200); + httpdSend(connData, url, -1); + return HTTPD_CGI_DONE; } // ==== Soft-AP related functions @@ -522,13 +514,13 @@ int ICACHE_FLASH_ATTR cgiApSettingsChange(HttpdConnData *connData) { httpdSend(connData, "No changes allowed in STA mode", -1); return HTTPD_CGI_DONE; } - + char buff[96]; int len; // Do we need a password? bool pass_need=true; - // Check extra security measure + // Check extra security measure, this must be 1 len=httpdFindArg(connData->getArgs, "100", buff, sizeof(buff)); if(len>0){ if(atoi(buff)!=1){ @@ -543,9 +535,9 @@ int ICACHE_FLASH_ATTR cgiApSettingsChange(HttpdConnData *connData) { os_memset(apconf.ssid, 0, 32); os_memcpy(apconf.ssid, buff, len); apconf.ssid_len = len; - pass_need = true; + pass_need = true; // ssid ok, look for a valid password }else{ - pass_need = false; + pass_need = false; // ssid wrong, neither pass not auth mode are needed jsonHeader(connData, 400); httpdSend(connData, "SSID not valid or out of range", -1); return HTTPD_CGI_DONE; @@ -553,13 +545,13 @@ int ICACHE_FLASH_ATTR cgiApSettingsChange(HttpdConnData *connData) { // Set new PASSWORD if( pass_need ){ len=httpdFindArg(connData->getArgs, "ap_password", buff, sizeof(buff)); - if(checkString(buff) && len>7 && len<62){ + if(checkString(buff) && len>7 && len<64){ // STRING PREPROCESSING DONE IN CLIENT SIDE os_memset(apconf.password, 0, 64); os_memcpy(apconf.password, buff, len); - pass_need = true; + pass_need = true; // pass ok, look for auth mode }else if (len == 0){ - pass_need = false; + pass_need = false; // pass wrong, no need to look for an auth mode os_memset(apconf.password, 0, 64); }else{ jsonHeader(connData, 400); @@ -654,19 +646,14 @@ int ICACHE_FLASH_ATTR cgiApSettingsInfo(HttpdConnData *connData) { return HTTPD_CGI_DONE; } -// ===== Wifi set mode end info functions - //This cgi changes the operating mode: STA / AP / STA+AP int ICACHE_FLASH_ATTR cgiWiFiSetMode(HttpdConnData *connData) { - - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - int len; - char buff[1024]; - - int previous_mode = wifi_get_opmode(); - - len=httpdFindArg(connData->getArgs, "mode", buff, sizeof(buff)); - + int len; + char buff[1024]; + int previous_mode = wifi_get_opmode(); + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + + len=httpdFindArg(connData->getArgs, "mode", buff, sizeof(buff)); int next_mode = atoi(buff); if (len!=0) { @@ -698,10 +685,8 @@ int ICACHE_FLASH_ATTR cgiWiFiSetMode(HttpdConnData *connData) { return HTTPD_CGI_DONE; } -// Collection of wifi info variables - static char *connStatuses[] = { "idle", "connecting", "wrong password", "AP not found", - "failed", "got IP address" }; + "failed", "got IP address" }; static char *wifiWarn[] = { 0, "Switch to <a href=\\\"#\\\" onclick=\\\"changeWifiMode(3)\\\">STA+AP mode</a>", @@ -725,8 +710,7 @@ static char *apAuthMode[] = { "OPEN", // print various Wifi information into json buffer int ICACHE_FLASH_ATTR printWifiInfo(char *buff) { - - int len; + int len; //struct station_config stconf; wifi_station_get_config(&stconf); //struct softap_config apconf; @@ -774,53 +758,53 @@ int ICACHE_FLASH_ATTR printWifiInfo(char *buff) { } int ICACHE_FLASH_ATTR cgiWiFiConnStatus(HttpdConnData *connData) { - char buff[1024]; - int len; - - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - jsonHeader(connData, 200); - - len = os_sprintf(buff, "{"); - len += printWifiInfo(buff+len); - len += os_sprintf(buff+len, ", "); - - if (wifiReason != 0) { - len += os_sprintf(buff+len, "\"reason\": \"%s\", ", wifiGetReason()); - } - + char buff[1024]; + int len; + + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + jsonHeader(connData, 200); + + len = os_sprintf(buff, "{"); + len += printWifiInfo(buff+len); + len += os_sprintf(buff+len, ", "); + + if (wifiReason != 0) { + len += os_sprintf(buff+len, "\"reason\": \"%s\", ", wifiGetReason()); + } + #if 0 - // commented out 'cause often the client that requested the change can't get a request in to - // find out that it succeeded. Better to just wait the std 15 seconds... - int st=wifi_station_get_connect_status(); - if (st == STATION_GOT_IP) { - if (wifi_get_opmode() != 1) { - // Reset into AP-only mode sooner. - os_timer_disarm(&resetTimer); - os_timer_setfn(&resetTimer, resetTimerCb, NULL); - os_timer_arm(&resetTimer, 1000, 0); - } - } + // commented out 'cause often the client that requested the change can't get a request in to + // find out that it succeeded. Better to just wait the std 15 seconds... + int st=wifi_station_get_connect_status(); + if (st == STATION_GOT_IP) { + if (wifi_get_opmode() != 1) { + // Reset into AP-only mode sooner. + os_timer_disarm(&resetTimer); + os_timer_setfn(&resetTimer, resetTimerCb, NULL); + os_timer_arm(&resetTimer, 1000, 0); + } + } #endif - - len += os_sprintf(buff+len, "\"x\":0}\n"); - DBG(" -> %s\n", buff); - httpdSend(connData, buff, len); - return HTTPD_CGI_DONE; + + len += os_sprintf(buff+len, "\"x\":0}\n"); + //DBG(" -> %s\n", buff); + httpdSend(connData, buff, len); + return HTTPD_CGI_DONE; } // Cgi to return various Wifi information int ICACHE_FLASH_ATTR cgiWifiInfo(HttpdConnData *connData) { - char buff[1024]; - - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - - os_strcpy(buff, "{"); - printWifiInfo(buff+1); - os_strcat(buff, "}"); - - jsonHeader(connData, 200); - httpdSend(connData, buff, -1); - return HTTPD_CGI_DONE; + char buff[1024]; + + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + + os_strcpy(buff, "{"); + printWifiInfo(buff+1); + os_strcat(buff, "}"); + + jsonHeader(connData, 200); + httpdSend(connData, buff, -1); + return HTTPD_CGI_DONE; } // Check string againt invalid characters @@ -857,24 +841,24 @@ void ICACHE_FLASH_ATTR wifiInit() { wifi_station_get_config_default(&stconf); wifi_softap_get_config_default(&apconf); - + DBG("Wifi init, mode=%s\n",wifiMode[x]); - + // STATION parameters #if defined(STA_SSID) && defined(STA_PASS) - - // Set parameters - if (os_strlen((char*)stconf.ssid) == 0 && os_strlen((char*)stconf.password) == 0) { - os_strncpy((char*)stconf.ssid, VERS_STR(STA_SSID), 32); - os_strncpy((char*)stconf.password, VERS_STR(STA_PASS), 64); - - DBG("Wifi pre-config trying to connect to AP %s pw %s\n",(char*)stconf.ssid, (char*)stconf.password); - - // wifi_set_phy_mode(2); // limit to 802.11b/g 'cause n is flaky - stconf.bssid_set = 0; - wifi_station_set_config(&stconf); - } + + // Set parameters + if (os_strlen((char*)stconf.ssid) == 0 && os_strlen((char*)stconf.password) == 0) { + os_strncpy((char*)stconf.ssid, VERS_STR(STA_SSID), 32); + os_strncpy((char*)stconf.password, VERS_STR(STA_PASS), 64); + + DBG("Wifi pre-config trying to connect to AP %s pw %s\n",(char*)stconf.ssid, (char*)stconf.password); + + // wifi_set_phy_mode(2); // limit to 802.11b/g 'cause n is flaky + stconf.bssid_set = 0; + wifi_station_set_config(&stconf); + } #endif @@ -931,7 +915,7 @@ void ICACHE_FLASH_ATTR wifiInit() { // Check softap config bool softap_set_conf = wifi_softap_set_config(&apconf); // Debug info - + DBG("Wifi Soft-AP parameters change: %s\n",softap_set_conf? "success":"fail"); #endif // AP_SSID && AP_PASS @@ -947,5 +931,4 @@ void ICACHE_FLASH_ATTR wifiInit() { os_timer_disarm(&resetTimer); os_timer_setfn(&resetTimer, resetTimerCb, NULL); os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); -} - +} \ No newline at end of file From cf7635dad75e78dfd971a442f60e60af138f6018 Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Mon, 4 Jan 2016 15:27:42 +0100 Subject: [PATCH 24/29] Fix Indentation --- esp-link/cgiwifi.c | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/esp-link/cgiwifi.c b/esp-link/cgiwifi.c index af496ee..7a4bbd0 100755 --- a/esp-link/cgiwifi.c +++ b/esp-link/cgiwifi.c @@ -301,27 +301,33 @@ static ETSTimer resetTimer; // the connect succeeds, this gets the module in STA-only mode. If it fails, it ensures // that the module is in STA+AP mode so the user has a chance to recover. static void ICACHE_FLASH_ATTR resetTimerCb(void *arg) { - int x = wifi_station_get_connect_status(); - int m = wifi_get_opmode() & 0x3; - DBG("Wifi check: mode=%s status=%d\n", wifiMode[m], x); + int x = wifi_station_get_connect_status(); + int m = wifi_get_opmode() & 0x3; + DBG("Wifi check: mode=%s status=%d\n", wifiMode[m], x); - if(m!=2){ - if( x == STATION_GOT_IP ){ + if(m!=2){ + if ( x == STATION_GOT_IP ) { + if (m != 1) { #ifdef CHANGE_TO_STA - if(m != 1) - wifi_set_opmode(1); + // We're happily connected, go to STA mode + DBG("Wifi got IP. Going into STA mode..\n"); + wifi_set_opmode(1); + os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); // check one more time after switching to STA-only #endif - log_uart(false); - }else{ - log_uart(true); - DBG("Enabling/continuing uart log\n"); - if (m==1){ - wifi_set_opmode(3); - wifi_softap_set_config(&apconf); - } - os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); - } } + log_uart(false); + // no more resetTimer at this point, gotta use physical reset to recover if in trouble + } else { + if (m != 3) { + DBG("Wifi connect failed. Going into STA+AP mode..\n"); + wifi_set_opmode(3); + wifi_softap_set_config(&apconf); + } + log_uart(true); + DBG("Enabling/continuing uart log\n"); + os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); + } + } } // Reassociate timer to delay change of association so the original request can finish From 05699cb4897e6dec17d401f4bb28a024845616e4 Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Mon, 4 Jan 2016 15:31:50 +0100 Subject: [PATCH 25/29] Fix indent --- esp-link/cgiwifi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esp-link/cgiwifi.c b/esp-link/cgiwifi.c index 7a4bbd0..9c79f86 100755 --- a/esp-link/cgiwifi.c +++ b/esp-link/cgiwifi.c @@ -309,10 +309,10 @@ static void ICACHE_FLASH_ATTR resetTimerCb(void *arg) { if ( x == STATION_GOT_IP ) { if (m != 1) { #ifdef CHANGE_TO_STA - // We're happily connected, go to STA mode - DBG("Wifi got IP. Going into STA mode..\n"); - wifi_set_opmode(1); - os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); // check one more time after switching to STA-only + // We're happily connected, go to STA mode + DBG("Wifi got IP. Going into STA mode..\n"); + wifi_set_opmode(1); + os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); // check one more time after switching to STA-only #endif } log_uart(false); From 0cec56712f08cf426df0e9a77b40ee703317a25d Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Mon, 4 Jan 2016 15:33:10 +0100 Subject: [PATCH 26/29] Fix indent --- esp-link/cgiwifi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esp-link/cgiwifi.c b/esp-link/cgiwifi.c index 9c79f86..bd6e4d8 100755 --- a/esp-link/cgiwifi.c +++ b/esp-link/cgiwifi.c @@ -309,10 +309,10 @@ static void ICACHE_FLASH_ATTR resetTimerCb(void *arg) { if ( x == STATION_GOT_IP ) { if (m != 1) { #ifdef CHANGE_TO_STA - // We're happily connected, go to STA mode - DBG("Wifi got IP. Going into STA mode..\n"); - wifi_set_opmode(1); - os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); // check one more time after switching to STA-only + // We're happily connected, go to STA mode + DBG("Wifi got IP. Going into STA mode..\n"); + wifi_set_opmode(1); + os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); // check one more time after switching to STA-only #endif } log_uart(false); From 7fea51185a6f61f3c3bb673f3ccdfc12eff94288 Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Mon, 4 Jan 2016 15:46:32 +0100 Subject: [PATCH 27/29] Fix indent --- esp-link/main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/esp-link/main.c b/esp-link/main.c index 5d5cefc..4f7de35 100644 --- a/esp-link/main.c +++ b/esp-link/main.c @@ -110,7 +110,6 @@ void user_rf_pre_init(void) { // Main routine to initialize esp-link. void user_init(void) { - // get the flash config so we know how to init things //configWipe(); // uncomment to reset the config for testing purposes bool restoreOk = configRestore(); From e3d150a6c5d8788960e636fe13835594dbd888bf Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Mon, 4 Jan 2016 15:57:03 +0100 Subject: [PATCH 28/29] From os_printf to DBG --- esp-link/cgiwifi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp-link/cgiwifi.c b/esp-link/cgiwifi.c index bd6e4d8..43c4c69 100755 --- a/esp-link/cgiwifi.c +++ b/esp-link/cgiwifi.c @@ -821,7 +821,7 @@ int ICACHE_FLASH_ATTR checkString(char *str){ // Alphanumeric and underscore allowed if (!(isalnum((unsigned char)str[i]) || str[i] == '_')) { - os_printf("Error: String has non alphanumeric chars\n"); + DBG("Error: String has non alphanumeric chars\n"); return 0; } } From 4d0f652bc848083de0dcc211e153fd9bf4f0576b Mon Sep 17 00:00:00 2001 From: KatAst <iLux@MiniLux.local> Date: Mon, 4 Jan 2016 20:07:46 +0100 Subject: [PATCH 29/29] Comments review --- esp-link/cgiwifi.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/esp-link/cgiwifi.c b/esp-link/cgiwifi.c index 43c4c69..f5da2a3 100755 --- a/esp-link/cgiwifi.c +++ b/esp-link/cgiwifi.c @@ -512,7 +512,6 @@ int ICACHE_FLASH_ATTR cgiApSettingsChange(HttpdConnData *connData) { if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - // No changes for Soft-AP in STA mode int mode = wifi_get_opmode(); if ( mode == 1 ){ @@ -523,7 +522,7 @@ int ICACHE_FLASH_ATTR cgiApSettingsChange(HttpdConnData *connData) { char buff[96]; int len; - // Do we need a password? + // Do we need a password or auth mode? bool pass_need=true; // Check extra security measure, this must be 1 @@ -534,7 +533,7 @@ int ICACHE_FLASH_ATTR cgiApSettingsChange(HttpdConnData *connData) { return HTTPD_CGI_DONE; } } - // Get the new SSID and set + // Set new SSID len=httpdFindArg(connData->getArgs, "ap_ssid", buff, sizeof(buff)); if(checkString(buff) && len>7 && len<32){ // STRING PREPROCESSING DONE IN CLIENT SIDE @@ -543,7 +542,7 @@ int ICACHE_FLASH_ATTR cgiApSettingsChange(HttpdConnData *connData) { apconf.ssid_len = len; pass_need = true; // ssid ok, look for a valid password }else{ - pass_need = false; // ssid wrong, neither pass not auth mode are needed + pass_need = false; // ssid wrong, neither pass nor auth mode are needed jsonHeader(connData, 400); httpdSend(connData, "SSID not valid or out of range", -1); return HTTPD_CGI_DONE; @@ -552,12 +551,12 @@ int ICACHE_FLASH_ATTR cgiApSettingsChange(HttpdConnData *connData) { if( pass_need ){ len=httpdFindArg(connData->getArgs, "ap_password", buff, sizeof(buff)); if(checkString(buff) && len>7 && len<64){ - // STRING PREPROCESSING DONE IN CLIENT SIDE + // String preprocessing done in client side, wifiap.js line 31 os_memset(apconf.password, 0, 64); os_memcpy(apconf.password, buff, len); pass_need = true; // pass ok, look for auth mode }else if (len == 0){ - pass_need = false; // pass wrong, no need to look for an auth mode + pass_need = false; // pass wrong, don't look for auth mode os_memset(apconf.password, 0, 64); }else{ jsonHeader(connData, 400); @@ -578,6 +577,7 @@ int ICACHE_FLASH_ATTR cgiApSettingsChange(HttpdConnData *connData) { apconf.authmode = 4; } }else{ + // Valid password but wrong auth mode, default 4 apconf.authmode = 4; } }else{ @@ -591,7 +591,7 @@ int ICACHE_FLASH_ATTR cgiApSettingsChange(HttpdConnData *connData) { if(value > 0 && value <= 4){ apconf.max_connection = value; }else{ - // If out of range set by default + // If out of range, set by default apconf.max_connection = 4; } } @@ -602,7 +602,7 @@ int ICACHE_FLASH_ATTR cgiApSettingsChange(HttpdConnData *connData) { if(value >= 100 && value <= 60000){ apconf.beacon_interval = value; }else{ - // If out of range set by default + // If out of range, set by default apconf.beacon_interval = 100; } } @@ -613,12 +613,11 @@ int ICACHE_FLASH_ATTR cgiApSettingsChange(HttpdConnData *connData) { if(value == 0 || value == 1){ apconf.ssid_hidden = value; }else{ - // If out of range set by default + // If out of range, set by default apconf.ssid_hidden = 0; } } // Store new configuration - // This should apply new config values wifi_softap_set_config(&apconf); jsonHeader(connData, 200); @@ -672,7 +671,7 @@ int ICACHE_FLASH_ATTR cgiWiFiSetMode(HttpdConnData *connData) { wifi_set_opmode(next_mode&3); if (previous_mode == 2) { - // moving to STA or STA+AP mode from AP + // moving to STA or STA+AP mode from AP, try to connect and set timer stconf.bssid_set = 0; wifi_station_set_config(&stconf); wifi_station_connect(); @@ -681,7 +680,7 @@ int ICACHE_FLASH_ATTR cgiWiFiSetMode(HttpdConnData *connData) { os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); } if(previous_mode == 1){ - // moving to AP or STA+AP, so softap config call needed + // moving to AP or STA+AP from STA, so softap config call needed wifi_softap_set_config(&apconf); } jsonHeader(connData, 200); @@ -730,7 +729,7 @@ int ICACHE_FLASH_ATTR printWifiInfo(char *buff) { int p = wifi_get_phy_mode(); char *phy = wifiPhy[p&3]; char *warn = wifiWarn[op]; - if (op == 3) op = 4; // Done to use only one set of warnings + if (op == 3) op = 4; // Done to let user switch to AP only mode from Soft-AP settings page, using only one set of warnings char *apwarn = wifiWarn[op]; char *apauth = apAuthMode[apconf.authmode]; sint8 rssi = wifi_station_get_rssi(); @@ -847,13 +846,10 @@ void ICACHE_FLASH_ATTR wifiInit() { wifi_station_get_config_default(&stconf); wifi_softap_get_config_default(&apconf); - DBG("Wifi init, mode=%s\n",wifiMode[x]); - // STATION parameters #if defined(STA_SSID) && defined(STA_PASS) - // Set parameters if (os_strlen((char*)stconf.ssid) == 0 && os_strlen((char*)stconf.password) == 0) { os_strncpy((char*)stconf.ssid, VERS_STR(STA_SSID), 32); @@ -865,7 +861,6 @@ void ICACHE_FLASH_ATTR wifiInit() { stconf.bssid_set = 0; wifi_station_set_config(&stconf); } - #endif // Change SOFT_AP settings if defined @@ -876,7 +871,7 @@ void ICACHE_FLASH_ATTR wifiInit() { // Clean memory and set the value of SSID os_memset(apconf.ssid, 0, 32); os_memcpy(apconf.ssid, VERS_STR(AP_SSID), os_strlen(VERS_STR(AP_SSID))); - // Specify the length of pass + // Specify the length of ssid apconf.ssid_len= ssidlen; #if defined(AP_PASS) // If pass is at least 8 and less than 64 @@ -885,7 +880,6 @@ void ICACHE_FLASH_ATTR wifiInit() { // Clean memory and set the value of PASS os_memset(apconf.password, 0, 64); os_memcpy(apconf.password, VERS_STR(AP_PASS), passlen); - // Can't choose auth mode without a valid ssid and password #ifdef AP_AUTH_MODE // If set, use specified auth mode