|
|
|
@ -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; |
|
|
|
|
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.
|
|
|
|
|
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++; |
|
|
|
|
} |
|
|
|
|
// 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); |
|
|
|
|
|
|
|
|
|
len = os_sprintf(buff, "{\"result\": {\"inProgress\": \"0\", \"APs\": [\n"); |
|
|
|
|
connData->cgiData = (void *)1; // start with first result next time we're called
|
|
|
|
|
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]; |
|
|
|
|
|
|
|
|
|
char essid[128]; |
|
|
|
|
char passwd[128]; |
|
|
|
|
|
|
|
|
|
if (connData->conn==NULL) return HTTPD_CGI_DONE; |
|
|
|
|
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)); |
|
|
|
|
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); |
|
|
|
|
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); |
|
|
|
|
} |
|
|
|
|
//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; |
|
|
|
|
char dhcp[8]; |
|
|
|
|
char staticip[20]; |
|
|
|
|
char netmask[20]; |
|
|
|
|
char gateway[20]; |
|
|
|
|
|
|
|
|
|
// 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)); |
|
|
|
|
if (connData->conn==NULL) return HTTPD_CGI_DONE; |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
// dynamic IP
|
|
|
|
|
flashConfig.staticip = 0; |
|
|
|
|
os_sprintf(url, "{\"url\": \"http://%s\"}", flashConfig.hostname); |
|
|
|
|
} |
|
|
|
|
// 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)); |
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
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
|
|
|
|
@ -528,7 +520,7 @@ int ICACHE_FLASH_ATTR cgiApSettingsChange(HttpdConnData *connData) { |
|
|
|
|
// 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) { |
|
|
|
|
int len; |
|
|
|
|
char buff[1024]; |
|
|
|
|
int previous_mode = wifi_get_opmode(); |
|
|
|
|
if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up.
|
|
|
|
|
|
|
|
|
|
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)); |
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
char buff[1024]; |
|
|
|
|
int len; |
|
|
|
|
|
|
|
|
|
if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up.
|
|
|
|
|
jsonHeader(connData, 200); |
|
|
|
|
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, ", "); |
|
|
|
|
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 (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]; |
|
|
|
|
char buff[1024]; |
|
|
|
|
|
|
|
|
|
if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up.
|
|
|
|
|
if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up.
|
|
|
|
|
|
|
|
|
|
os_strcpy(buff, "{"); |
|
|
|
|
printWifiInfo(buff+1); |
|
|
|
|
os_strcat(buff, "}"); |
|
|
|
|
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
|
|
|
|
@ -864,17 +848,17 @@ void ICACHE_FLASH_ATTR wifiInit() { |
|
|
|
|
// 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); |
|
|
|
|
// 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); |
|
|
|
|
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); |
|
|
|
|
} |
|
|
|
|
// wifi_set_phy_mode(2); // limit to 802.11b/g 'cause n is flaky
|
|
|
|
|
stconf.bssid_set = 0; |
|
|
|
|
wifi_station_set_config(&stconf); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
@ -948,4 +932,3 @@ void ICACHE_FLASH_ATTR wifiInit() { |
|
|
|
|
os_timer_setfn(&resetTimer, resetTimerCb, NULL); |
|
|
|
|
os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|