improve wifi, use 11g; fix serial pull-up issue

v0.9.0
Thorsten von Eicken 10 years ago
parent f3fe029705
commit ef94f504bb
  1. 2
      html/wifi/wifi.tpl
  2. 7
      serial/uart.c
  3. 194
      user/cgiwifi.c
  4. 2
      user/cgiwifi.h
  5. 2
      user/console.c
  6. 45
      user/status.c
  7. 1
      user/status.h

@ -79,7 +79,7 @@ window.onload=function(e) {
<h1>ESP Link - Wifi Configuration</h1> <h1>ESP Link - Wifi Configuration</h1>
<p> <p>
Current WiFi mode: %WiFiMode%<br> Current WiFi mode: %WiFiMode%<br>
Current network: %currSsid% Current network: %currSsid% Status: %currStatus% Phy:%currPhy%
</p> </p>
<p> <p>
Note: %WiFiapwarn% Note: %WiFiapwarn%

@ -50,11 +50,14 @@ uart_config(uint8 uart_no)
PIN_PULLDWN_DIS(PERIPHS_IO_MUX_GPIO2_U); PIN_PULLDWN_DIS(PERIPHS_IO_MUX_GPIO2_U);
PIN_PULLUP_DIS(PERIPHS_IO_MUX_GPIO2_U); PIN_PULLUP_DIS(PERIPHS_IO_MUX_GPIO2_U);
} else { } else {
/* rcv_buff size if 0x100 */ /* rcv_buff size is 0x100 */
ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, &(UartDev.rcv_buff)); ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, &(UartDev.rcv_buff));
PIN_PULLUP_DIS (PERIPHS_IO_MUX_U0TXD_U); PIN_PULLUP_DIS (PERIPHS_IO_MUX_U0TXD_U);
PIN_PULLDWN_DIS(PERIPHS_IO_MUX_U0TXD_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD); PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS); PIN_PULLUP_DIS (PERIPHS_IO_MUX_U0RXD_U);
PIN_PULLDWN_DIS(PERIPHS_IO_MUX_U0RXD_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, 0); // FUNC_U0RXD==0
} }
uart_div_modify(uart_no, UART_CLK_FREQ / (UartDev.baut_rate)); uart_div_modify(uart_no, UART_CLK_FREQ / (UartDev.baut_rate));

@ -14,10 +14,74 @@ Cgi/template routines for the /wifi url.
#include <esp8266.h> #include <esp8266.h>
#include "cgiwifi.h" #include "cgiwifi.h"
#include "status.h"
//Enable this to disallow any changes in AP settings //Enable this to disallow any changes in AP settings
//#define DEMO_MODE //#define DEMO_MODE
// ===== wifi status change callback
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" };
static char* ICACHE_FLASH_ATTR wifiGetReason(void) {
if (wifiReason <= 24) return wifiReasons[wifiReason];
if (wifiReason >= 200 && wifiReason <= 201) return wifiReasons[wifiReason-200+25];
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;
os_printf("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;
os_printf("Wifi disconnected from ssid %s, reason %s\n",
evt->event_info.disconnected.ssid, wifiGetReason());
statusWifiUpdate(wifiState);
break;
case EVENT_STAMODE_AUTHMODE_CHANGE:
os_printf("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;
os_printf("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);
break;
case EVENT_SOFTAPMODE_STACONNECTED:
os_printf("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:
os_printf("Wifi AP: station " MACSTR " left, AID = %d\n",
MAC2STR(evt->event_info.sta_disconnected.mac), evt->event_info.sta_disconnected.aid);
break;
default:
break;
}
}
// ===== wifi scanning
//WiFi access point data //WiFi access point data
typedef struct { typedef struct {
char ssid[32]; char ssid[32];
@ -35,14 +99,6 @@ typedef struct {
//Static scan status storage. //Static scan status storage.
static ScanResultData cgiWifiAps; static ScanResultData cgiWifiAps;
#define CONNTRY_IDLE 0
#define CONNTRY_WORKING 1
#define CONNTRY_SUCCESS 2
#define CONNTRY_FAIL 3
//Connection result var
static int connTryStatus=CONNTRY_IDLE;
static ETSTimer resetTimer;
//Callback the code calls when a wlan ap scan is done. Basically stores the result in //Callback the code calls when a wlan ap scan is done. Basically stores the result in
//the cgiWifiAps struct. //the cgiWifiAps struct.
void ICACHE_FLASH_ATTR wifiScanDoneCb(void *arg, STATUS status) { void ICACHE_FLASH_ATTR wifiScanDoneCb(void *arg, STATUS status) {
@ -95,7 +151,6 @@ void ICACHE_FLASH_ATTR wifiScanDoneCb(void *arg, STATUS status) {
cgiWifiAps.scanInProgress=0; cgiWifiAps.scanInProgress=0;
} }
//Routine to start a WiFi access point scan. //Routine to start a WiFi access point scan.
static void ICACHE_FLASH_ATTR wifiStartScan() { static void ICACHE_FLASH_ATTR wifiStartScan() {
// int x; // int x;
@ -152,74 +207,62 @@ int ICACHE_FLASH_ATTR cgiWiFiScan(HttpdConnData *connData) {
} }
} }
//Temp store for new ap info. // ===== timers to change state and rescue from failed associations
static struct station_config stconf;
//#define CONNTRY_IDLE 0
//#define CONNTRY_WORKING 1
//#define CONNTRY_SUCCESS 2
//#define CONNTRY_FAIL 3
//Connection result var
//static int connTryStatus=CONNTRY_IDLE;
// reset timer changes back to STA+AP if we can't associate
#define RESET_TIMEOUT (15000) // 15 seconds
static ETSTimer resetTimer;
//This routine is ran some time after a connection attempt to an access point. If //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. //the connect succeeds, this gets the module in STA-only mode.
static void ICACHE_FLASH_ATTR resetTimerCb(void *arg) { static void ICACHE_FLASH_ATTR resetTimerCb(void *arg) {
int x = wifi_station_get_connect_status(); int x = wifi_station_get_connect_status();
int m = wifi_get_opmode(); int m = wifi_get_opmode();
os_printf("Wifi check: mode=%d status=%d\n", m, x);
if (x == STATION_GOT_IP) { if (x == STATION_GOT_IP) {
//Go to STA mode. This needs a reset, so do that.
connTryStatus=CONNTRY_SUCCESS;
if (m != 1) { if (m != 1) {
os_printf("Got IP. Going into STA mode..\n"); // We're happily connected, go to STA mode
os_printf("Wifi got IP. Going into STA mode..\n");
wifi_set_opmode(1); wifi_set_opmode(1);
os_timer_arm(&resetTimer, RESET_TIMEOUT, 0);
} }
} else { } else if (m != 3) {
connTryStatus=CONNTRY_FAIL; os_printf("Wifi connect failed. Going into STA+AP mode..\n");
if (m != 3) {
os_printf("Connect fail. Going into STA+AP mode..\n");
wifi_set_opmode(3); wifi_set_opmode(3);
os_timer_arm(&resetTimer, RESET_TIMEOUT, 0);
} }
//Maybe also pass this through on the webpage?
}
os_timer_arm(&resetTimer, 15000, 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
//Actually connect to a station. This routine is timed because I had problems
//with immediate connections earlier. It probably was something else that caused it,
//but I can't be arsed to put the code back :P
static void ICACHE_FLASH_ATTR reassTimerCb(void *arg) { static void ICACHE_FLASH_ATTR reassTimerCb(void *arg) {
int x; os_printf("Wifi changing association\n");
os_printf("Try to connect to AP....\n");
wifi_station_disconnect(); wifi_station_disconnect();
wifi_station_set_config(&stconf); wifi_station_set_config(&stconf);
//wifi_station_connect(); wifi_station_connect();
x=wifi_get_opmode(); // Schedule check
connTryStatus=CONNTRY_WORKING;
if (x == 1) {
//Schedule disconnect/connect
os_timer_disarm(&resetTimer); os_timer_disarm(&resetTimer);
os_timer_setfn(&resetTimer, resetTimerCb, NULL); os_timer_setfn(&resetTimer, resetTimerCb, NULL);
os_timer_arm(&resetTimer, 15000, 0); //time out after 15 secs of trying to connect os_timer_arm(&resetTimer, RESET_TIMEOUT, 0);
}
}
// 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() {
int x=wifi_get_opmode();
os_printf("Wifi init, mode=%d\n", x);
if (x == 1) {
// STA-only mode, reset into STA+AP after a timeout
os_timer_disarm(&resetTimer);
os_timer_setfn(&resetTimer, resetTimerCb, NULL);
os_timer_arm(&resetTimer, 15000, 0);
}
} }
//This cgi uses the routines above to connect to a specific access point with the //This cgi uses the routines above to connect to a specific access point with the
//given ESSID using the given password. //given ESSID using the given password.
int ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData) { int ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData) {
char essid[128]; char essid[128];
char passwd[128]; char passwd[128];
static ETSTimer reassTimer;
if (connData->conn==NULL) { if (connData->conn==NULL) {
//Connection aborted. Clean up. //Connection aborted. Clean up.
@ -231,7 +274,7 @@ int ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData) {
os_strncpy((char*)stconf.ssid, essid, 32); os_strncpy((char*)stconf.ssid, essid, 32);
os_strncpy((char*)stconf.password, passwd, 64); os_strncpy((char*)stconf.password, passwd, 64);
os_printf("Try to connect to AP %s pw %s\n", essid, passwd); os_printf("Wifi try to connect to AP %s pw %s\n", essid, passwd);
//Schedule disconnect/connect //Schedule disconnect/connect
os_timer_disarm(&reassTimer); os_timer_disarm(&reassTimer);
@ -246,8 +289,7 @@ int ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData) {
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
} }
//This cgi uses the routines above to connect to a specific access point with the //This cgi changes the operating mode: STA / AP / STA+AP
//given ESSID using the given password.
int ICACHE_FLASH_ATTR cgiWiFiSetMode(HttpdConnData *connData) { int ICACHE_FLASH_ATTR cgiWiFiSetMode(HttpdConnData *connData) {
int len; int len;
char buff[1024]; char buff[1024];
@ -260,14 +302,14 @@ int ICACHE_FLASH_ATTR cgiWiFiSetMode(HttpdConnData *connData) {
len=httpdFindArg(connData->getArgs, "mode", buff, sizeof(buff)); len=httpdFindArg(connData->getArgs, "mode", buff, sizeof(buff));
if (len!=0) { if (len!=0) {
int m = atoi(buff); int m = atoi(buff);
os_printf("Switching to wifi mode %d\n", m); os_printf("Wifi switching to mode %d\n", m);
#ifndef DEMO_MODE #ifndef DEMO_MODE
wifi_set_opmode(m); wifi_set_opmode(m);
if (m == 1) { if (m == 1) {
// STA-only mode, reset into STA+AP after a timeout // STA-only mode, reset into STA+AP after a timeout
os_timer_disarm(&resetTimer); os_timer_disarm(&resetTimer);
os_timer_setfn(&resetTimer, resetTimerCb, NULL); os_timer_setfn(&resetTimer, resetTimerCb, NULL);
os_timer_arm(&resetTimer, 15000, 0); os_timer_arm(&resetTimer, RESET_TIMEOUT, 0);
} }
#endif #endif
} }
@ -276,7 +318,7 @@ int ICACHE_FLASH_ATTR cgiWiFiSetMode(HttpdConnData *connData) {
} }
char *connStatuses[] = { "idle", "connecting", "wrong password", "AP not found", char *connStatuses[] = { "idle", "connecting", "wrong password", "AP not found",
"failed", "success" }; "failed", "got IP address" };
int ICACHE_FLASH_ATTR cgiWiFiConnStatus(HttpdConnData *connData) { int ICACHE_FLASH_ATTR cgiWiFiConnStatus(HttpdConnData *connData) {
char buff[1024]; char buff[1024];
@ -287,27 +329,32 @@ int ICACHE_FLASH_ATTR cgiWiFiConnStatus(HttpdConnData *connData) {
httpdHeader(connData, "Content-Type", "text/json"); httpdHeader(connData, "Content-Type", "text/json");
httpdEndHeaders(connData); httpdEndHeaders(connData);
len = os_sprintf(buff, "{\"status\": \"")-1; len = os_sprintf(buff, "{\"status\": \"");
if (st > 0 && st < sizeof(connStatuses)) { if (st > 0 && st < sizeof(connStatuses)) {
len += os_sprintf(buff+len, "%s", connStatuses[st])-1; len += os_sprintf(buff+len, connStatuses[st]);
} else { } else {
len += os_sprintf(buff+len, "unknown")-1; len += os_sprintf(buff+len, "unknown");
}
if (wifiReason != 0) {
len += os_sprintf(buff+len, " -- %s", wifiGetReason());
} }
if (st == STATION_GOT_IP) { if (st == STATION_GOT_IP) {
wifi_get_ip_info(0, &info); wifi_get_ip_info(0, &info);
len+=os_sprintf(buff, "\", \"ip\": \"%d.%d.%d.%d\" }\n", len+=os_sprintf(buff+len, "\", \"ip\": \"%d.%d.%d.%d\" }\n",
(info.ip.addr>>0)&0xff, (info.ip.addr>>8)&0xff, (info.ip.addr>>0)&0xff, (info.ip.addr>>8)&0xff,
(info.ip.addr>>16)&0xff, (info.ip.addr>>24)&0xff); (info.ip.addr>>16)&0xff, (info.ip.addr>>24)&0xff);
if (connTryStatus==CONNTRY_WORKING || connTryStatus==CONNTRY_SUCCESS) { if (wifi_get_opmode() != 1) {
//Reset into AP-only mode sooner. //Reset into AP-only mode sooner.
os_timer_disarm(&resetTimer); os_timer_disarm(&resetTimer);
os_timer_setfn(&resetTimer, resetTimerCb, NULL); os_timer_setfn(&resetTimer, resetTimerCb, NULL);
os_timer_arm(&resetTimer, 1000, 0); os_timer_arm(&resetTimer, 1000, 0);
} }
} else { } else {
len+=os_sprintf(buff, "\" }\n"); len+=os_sprintf(buff+len, "\" }\n");
} }
buff[len] = 0;
os_printf(" -> %s\n", buff);
httpdSend(connData, buff, len); httpdSend(connData, buff, len);
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
} }
@ -328,6 +375,15 @@ int ICACHE_FLASH_ATTR tplWlan(HttpdConnData *connData, char *token, void **arg)
if (x==3) os_strcpy(buff, "STA+AP"); if (x==3) os_strcpy(buff, "STA+AP");
} else if (os_strcmp(token, "currSsid")==0) { } else if (os_strcmp(token, "currSsid")==0) {
os_strcpy(buff, (char*)stconf.ssid); os_strcpy(buff, (char*)stconf.ssid);
} else if (os_strcmp(token, "currStatus")==0) {
int st=wifi_station_get_connect_status();
if (st > 0 && st < sizeof(connStatuses))
os_strcpy(buff, connStatuses[st]);
else
os_strcpy(buff, "unknown");
} else if (os_strcmp(token, "currPhy")==0) {
int m = wifi_get_phy_mode();
os_sprintf(buff, "%d", m);
} else if (os_strcmp(token, "WiFiPasswd")==0) { } else if (os_strcmp(token, "WiFiPasswd")==0) {
os_strcpy(buff, (char*)stconf.password); os_strcpy(buff, (char*)stconf.password);
} else if (os_strcmp(token, "WiFiapwarn")==0) { } else if (os_strcmp(token, "WiFiapwarn")==0) {
@ -348,4 +404,18 @@ int ICACHE_FLASH_ATTR tplWlan(HttpdConnData *connData, char *token, void **arg)
return HTTPD_CGI_DONE; 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() {
int x = wifi_get_opmode();
os_printf("Wifi init, mode=%d\n", x);
wifi_set_phy_mode(2);
wifi_set_event_handler_cb(wifiHandleEventCb);
if (x == 1) {
// STA-only mode, reset into STA+AP after a timeout
os_timer_disarm(&resetTimer);
os_timer_setfn(&resetTimer, resetTimerCb, NULL);
os_timer_arm(&resetTimer, RESET_TIMEOUT, 0);
}
}

@ -3,6 +3,8 @@
#include "httpd.h" #include "httpd.h"
enum { wifiIsDisconnected, wifiIsConnected, wifiGotIP };
int cgiWiFiScan(HttpdConnData *connData); int cgiWiFiScan(HttpdConnData *connData);
int tplWlan(HttpdConnData *connData, char *token, void **arg); int tplWlan(HttpdConnData *connData, char *token, void **arg);
int cgiWiFi(HttpdConnData *connData); int cgiWiFi(HttpdConnData *connData);

@ -31,7 +31,7 @@ console_read(void) {
static void ICACHE_FLASH_ATTR static void ICACHE_FLASH_ATTR
console_write_char(char c) { console_write_char(char c) {
uart0_write_char(c); //uart0_write_char(c);
if (c == '\n') console_write('\r'); if (c == '\n') console_write('\r');
console_write(c); console_write(c);
} }

@ -1,66 +1,71 @@
#include <esp8266.h> #include <esp8266.h>
#include "cgiwifi.h"
#define LEDGPIO 0 #define LEDGPIO 0
static ETSTimer ledTimer; static ETSTimer ledTimer;
void ICACHE_FLASH_ATTR setLed(int on) { void ICACHE_FLASH_ATTR setLed(int on) {
// LED is active-low
if (on) { if (on) {
gpio_output_set((1<<LEDGPIO), 0, (1<<LEDGPIO), 0);
} else {
gpio_output_set(0, (1<<LEDGPIO), (1<<LEDGPIO), 0); gpio_output_set(0, (1<<LEDGPIO), (1<<LEDGPIO), 0);
} else {
gpio_output_set((1<<LEDGPIO), 0, (1<<LEDGPIO), 0);
} }
} }
static uint8_t ledState = 0; static uint8_t ledState = 0;
static uint8_t wifiState = 0;
static void ICACHE_FLASH_ATTR ledTimerCb(void *arg) { static void ICACHE_FLASH_ATTR ledTimerCb(void *v) {
int m = wifi_get_opmode();
int c = m == 2 ? 0 : wifi_station_get_connect_status();
if (c != 5) os_printf("Status: mode=%d conn=%d\n", m, c);
int time = 1000; int time = 1000;
if (wifiState == wifiGotIP) {
if (c == STATION_GOT_IP) {
// connected, all is good, solid light // connected, all is good, solid light
ledState = 1-ledState; ledState = 1-ledState;
time = ledState ? 2900 : 100; time = ledState ? 2900 : 100;
} else if (c == STATION_CONNECTING) { } else if (wifiState == wifiIsConnected) {
// connecting, go on/off every second // connecting, go on/off every second
ledState = 1 - ledState; ledState = 1 - ledState;
time = 1000; time = 1000;
} else if (c > STATION_CONNECTING) {
// some failure, rapid blinking
ledState = 1-ledState;
time = 100;
} else { } else {
// idle // idle
switch (m) { switch (wifi_get_opmode()) {
case 1: // STA case 1: // STA
ledState = 0; ledState = 0;
break; break;
case 2: // AP case 2: // AP
ledState = 1-ledState; ledState = 1-ledState;
time = ledState ? 100 : 1900; time = ledState ? 50 : 1950;
break; break;
case 3: // STA+AP case 3: // STA+AP
ledState = 1-ledState; ledState = 1-ledState;
time = ledState ? 100 : 900; time = ledState ? 50 : 950;
break; break;
} }
} }
setLed(1-ledState); // low=on setLed(ledState);
os_timer_arm(&ledTimer, time, 0); os_timer_arm(&ledTimer, time, 0);
} }
void statusInit() { // change the wifi state
void ICACHE_FLASH_ATTR statusWifiUpdate(uint8_t state) {
wifiState = state;
// schedule an update (don't want to run into concurrency issues)
os_timer_disarm(&ledTimer);
os_timer_setfn(&ledTimer, ledTimerCb, NULL);
os_timer_arm(&ledTimer, 500, 0);
}
void ICACHE_FLASH_ATTR statusInit() {
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0); PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0);
gpio_output_set(0, 0, (1<<LEDGPIO), 0); gpio_output_set(0, 0, (1<<LEDGPIO), 0);
setLed(1);
os_timer_disarm(&ledTimer); os_timer_disarm(&ledTimer);
os_timer_setfn(&ledTimer, ledTimerCb, NULL); os_timer_setfn(&ledTimer, ledTimerCb, NULL);
os_timer_arm(&ledTimer, 500, 0); os_timer_arm(&ledTimer, 2000, 0);
} }

@ -1,6 +1,7 @@
#ifndef STATUS_H #ifndef STATUS_H
#define STATUS_H #define STATUS_H
void statusWifiUpdate(uint8_t state);
void statusInit(void); void statusInit(void);
#endif #endif

Loading…
Cancel
Save