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\", "
         "\"&#xb5;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