Getting ready for release...

This commit is contained in:
Jeroen Domburg
2014-10-14 21:06:13 +02:00
parent 290fe32e46
commit aef27aaa5b
20 changed files with 149 additions and 776 deletions
+29 -176
View File
@@ -2,6 +2,16 @@
Some random cgi routines.
*/
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
* this notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return.
* ----------------------------------------------------------------------------
*/
#include <string.h>
#include <osapi.h>
#include "user_interface.h"
@@ -11,6 +21,10 @@ Some random cgi routines.
#include "io.h"
#include "espmissingincludes.h"
//cause I can't be bothered to write an ioGetLed()
static char currLedState=0;
//Cgi that turns the LED on or off according to the 'led' param in the POST data
int ICACHE_FLASH_ATTR cgiLed(HttpdConnData *connData) {
int len;
char buff[1024];
@@ -21,169 +35,35 @@ int ICACHE_FLASH_ATTR cgiLed(HttpdConnData *connData) {
}
len=httpdFindArg(connData->postBuff, "led", buff, sizeof(buff));
if (len!=0) ioLed(atoi(buff));
if (len!=0) {
currLedState=atoi(buff);
ioLed(currLedState);
}
httpdRedirect(connData, "led.html");
return HTTPD_CGI_DONE;
}
//WiFi access point data
typedef struct {
char ssid[32];
char rssi;
char enc;
} ApData;
//Scan resolt
typedef struct {
char scanInProgress;
ApData **apData;
int noAps;
} ScanResultData;
//Template code for the led page.
void ICACHE_FLASH_ATTR tplLed(HttpdConnData *connData, char *token, void **arg) {
char buff[128];
if (token==NULL) return;
//Static scan status storage.
ScanResultData cgiWifiAps;
void ICACHE_FLASH_ATTR wifiScanDoneCb(void *arg, STATUS status) {
int n;
struct bss_info *bss_link = (struct bss_info *)arg;
os_printf("wifiScanDoneCb %d\n", status);
if (status!=OK) {
cgiWifiAps.scanInProgress=0;
wifi_station_disconnect(); //test HACK
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;
//Copy access point data to the static struct
n=0;
bss_link = (struct bss_info *)arg;
while (bss_link != NULL) {
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);
bss_link = bss_link->next.stqe_next;
n++;
}
os_printf("Scan done: found %d APs\n", n);
//We're done.
cgiWifiAps.scanInProgress=0;
}
static void ICACHE_FLASH_ATTR wifiStartScan() {
int x;
cgiWifiAps.scanInProgress=1;
x=wifi_station_get_connect_status();
if (x!=STATION_GOT_IP) {
//Unit probably is trying to connect to a bogus AP. This messes up scanning. Stop that.
os_printf("STA status = %d. Disconnecting STA...\n", x);
wifi_station_disconnect();
}
wifi_station_scan(NULL, wifiScanDoneCb);
}
int ICACHE_FLASH_ATTR cgiWiFiScan(HttpdConnData *connData) {
int len;
int i;
char buff[1024];
httpdStartResponse(connData, 200);
httpdHeader(connData, "Content-Type", "text/json");
httpdEndHeaders(connData);
if (cgiWifiAps.scanInProgress==1) {
len=os_sprintf(buff, "{\n \"result\": { \n\"inProgress\": \"1\"\n }\n}\n");
espconn_sent(connData->conn, (uint8 *)buff, len);
} else {
len=os_sprintf(buff, "{\n \"result\": { \n\"inProgress\": \"0\", \n\"APs\": [\n");
espconn_sent(connData->conn, (uint8 *)buff, len);
if (cgiWifiAps.apData==NULL) cgiWifiAps.noAps=0;
for (i=0; i<cgiWifiAps.noAps; i++) {
len=os_sprintf(buff, "{\"essid\": \"%s\", \"rssi\": \"%d\", \"enc\": \"%d\"}%s\n",
cgiWifiAps.apData[i]->ssid, cgiWifiAps.apData[i]->rssi,
cgiWifiAps.apData[i]->enc, (i==cgiWifiAps.noAps-1)?"":",");
espconn_sent(connData->conn, (uint8 *)buff, len);
os_strcpy(buff, "Unknown");
if (os_strcmp(token, "ledstate")==0) {
if (currLedState) {
os_strcpy(buff, "on");
} else {
os_strcpy(buff, "off");
}
len=os_sprintf(buff, "]\n}\n}\n");
espconn_sent(connData->conn, (uint8 *)buff, len);
wifiStartScan();
}
return HTTPD_CGI_DONE;
}
static struct station_config stconf;
static void ICACHE_FLASH_ATTR resetTimerCb(void *arg) {
int x=wifi_station_get_connect_status();
if (x==STATION_GOT_IP) {
//Go to STA mode. This needs a reset, so do that.
wifi_set_opmode(1);
system_restart();
} else {
os_printf("Connect fail. Not going into STA-only mode.\n");
}
espconn_sent(connData->conn, (uint8 *)buff, os_strlen(buff));
}
static void ICACHE_FLASH_ATTR reassTimerCb(void *arg) {
int x;
static ETSTimer resetTimer;
wifi_station_disconnect();
wifi_station_set_config(&stconf);
wifi_station_connect();
x=wifi_get_opmode();
if (x!=1) {
//Schedule disconnect/connect
os_timer_disarm(&resetTimer);
os_timer_setfn(&resetTimer, resetTimerCb, NULL);
os_timer_arm(&resetTimer, 4000, 0);
}
}
int ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData) {
char essid[128];
char passwd[128];
static ETSTimer reassTimer;
if (connData->conn==NULL) {
//Connection aborted. Clean up.
return HTTPD_CGI_DONE;
}
httpdFindArg(connData->postBuff, "essid", essid, sizeof(essid));
httpdFindArg(connData->postBuff, "passwd", passwd, sizeof(passwd));
os_strncpy((char*)stconf.ssid, essid, 32);
os_strncpy((char*)stconf.password, passwd, 64);
//Schedule disconnect/connect
os_timer_disarm(&reassTimer);
os_timer_setfn(&reassTimer, reassTimerCb, NULL);
os_timer_arm(&reassTimer, 1000, 0);
httpdRedirect(connData, "connecting.html");
return HTTPD_CGI_DONE;
}
//Cgi that reads the SPI flash. Assumes 512KByte flash.
int ICACHE_FLASH_ATTR cgiReadFlash(HttpdConnData *connData) {
@@ -206,30 +86,3 @@ int ICACHE_FLASH_ATTR cgiReadFlash(HttpdConnData *connData) {
if (*pos>=0x40200000+(512*1024)) return HTTPD_CGI_DONE; else return HTTPD_CGI_MORE;
}
int ICACHE_FLASH_ATTR cgiTest(HttpdConnData *connData) {
return HTTPD_CGI_DONE;
}
void ICACHE_FLASH_ATTR tplWlan(HttpdConnData *connData, char *token, void **arg) {
char buff[1024];
int x;
static struct station_config stconf;
if (token==NULL) return;
wifi_station_get_config(&stconf);
os_strcpy(buff, "Unknown");
if (os_strcmp(token, "WiFiMode")==0) {
x=wifi_get_opmode();
if (x==1) os_strcpy(buff, "Client");
if (x==2) os_strcpy(buff, "SoftAP");
if (x==3) os_strcpy(buff, "STA+AP");
} else if (os_strcmp(token, "currSsid")==0) {
os_strcpy(buff, (char*)stconf.ssid);
} else if (os_strcmp(token, "WiFiPasswd")==0) {
os_strcpy(buff, (char*)stconf.password);
}
espconn_sent(connData->conn, (uint8 *)buff, os_strlen(buff));
}
+1 -5
View File
@@ -4,11 +4,7 @@
#include "httpd.h"
int cgiLed(HttpdConnData *connData);
void tplLed(HttpdConnData *connData, char *token, void **arg);
int cgiReadFlash(HttpdConnData *connData);
int cgiTest(HttpdConnData *connData);
int cgiWiFiScan(HttpdConnData *connData);
void ICACHE_FLASH_ATTR tplWlan(HttpdConnData *connData, char *token, void **arg);
int ICACHE_FLASH_ATTR cgiWiFi(HttpdConnData *connData);
int ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData);
#endif
+30 -12
View File
@@ -4,9 +4,22 @@ mkespfsimg tool, and can use that block to do abstracted operations on the files
It's written for use with httpd, but doesn't need to be used as such.
*/
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
* this notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return.
* ----------------------------------------------------------------------------
*/
//These routines can also be tested by comping them in with the espfstest tool. This
//simplifies debugging, but needs some slightly different headers. The #ifdef takes
//care of that.
#ifdef __ets__
//esp build
#include "driver/uart.h"
#include "c_types.h"
#include "user_interface.h"
#include "espconn.h"
@@ -51,7 +64,7 @@ struct EspFsFile {
/*
Available locations, at least in my flash, with boundaries partially guessed. This
is using 0.9.1 SDK on a not-too-new module.
is using 0.9.1/0.9.2 SDK on a not-too-new module.
0x00000 (0x10000): Code/data (RAM data?)
0x10000 (0x02000): Gets erased by something?
0x12000 (0x2E000): Free (filled with zeroes) (parts used by ESPCloud and maybe SSL)
@@ -83,7 +96,7 @@ void ICACHE_FLASH_ATTR memcpyAligned(char *dst, char *src, int len) {
}
//Open a file and return a pointer to the file desc struct.
EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) {
#ifdef __ets__
char *p=(char *)(ESPFS_POS+0x40200000);
@@ -94,11 +107,12 @@ EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) {
char namebuf[256];
EspFsHeader h;
EspFsFile *r;
//Skip initial slashes
//Strip initial slashes
while(fileName[0]=='/') fileName++;
//Go find that file!
while(1) {
hpos=p;
//Grab the next file header.
os_memcpy(&h, p, sizeof(EspFsHeader));
if (h.magic!=0x73665345) {
os_printf("Magic mismatch. EspFS image broken.\n");
@@ -108,13 +122,15 @@ EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) {
os_printf("End of image.\n");
return NULL;
}
p+=sizeof(EspFsHeader);
//Grab the name of the file.
p+=sizeof(EspFsHeader);
os_memcpy(namebuf, p, sizeof(namebuf));
os_printf("Found file '%s'. Namelen=%x fileLenComp=%x, compr=%d flags=%d\n",
namebuf, (unsigned int)h.nameLen, (unsigned int)h.fileLenComp, h.compression, h.flags);
if (os_strcmp(namebuf, fileName)==0) {
p+=h.nameLen;
r=(EspFsFile *)os_malloc(sizeof(EspFsFile));
//Yay, this is the file we need!
p+=h.nameLen; //Skip to content.
r=(EspFsFile *)os_malloc(sizeof(EspFsFile)); //Alloc file desc mem
if (r==NULL) return NULL;
r->header=(EspFsHeader *)hpos;
r->decompressor=h.compression;
@@ -125,6 +141,7 @@ EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) {
r->decompData=NULL;
#ifdef EFS_HEATSHRINK
} else if (h.compression==COMPRESS_HEATSHRINK) {
//File is compressed with Heatshrink.
char parm;
heatshrink_decoder *dec;
//Decoder params are stored in 1st byte.
@@ -132,7 +149,6 @@ EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) {
r->posComp++;
os_printf("Heatshrink compressed file; decode parms = %x\n", parm);
dec=heatshrink_decoder_alloc(16, (parm>>4)&0xf, parm&0xf);
heatshrink_decoder_reset(dec);
r->decompData=dec;
#endif
} else {
@@ -141,18 +157,19 @@ EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) {
}
return r;
}
//Skip name and file
//We don't need this file. Skip name and file
p+=h.nameLen+h.fileLenComp;
if ((int)p&3) p+=4-((int)p&3); //align to next 32bit val
// os_printf("Next addr = %x\n", (int)p);
}
}
//Read len bytes from the given file into buff. Returns the actual amount of bytes read.
int ICACHE_FLASH_ATTR espFsRead(EspFsFile *fh, char *buff, int len) {
int flen;
if (fh==NULL) return 0;
memcpyAligned((char*)&flen, (char*)&fh->header->fileLenComp, 4);
//Cache file length.
memcpyAligned((char*)&flen, (char*)&fh->header->fileLenComp, 4);
//Do stuff depending on the way the file is compressed.
if (fh->decompressor==COMPRESS_NONE) {
int toRead;
toRead=flen-(fh->posComp-fh->posStart);
@@ -194,6 +211,7 @@ int ICACHE_FLASH_ATTR espFsRead(EspFsFile *fh, char *buff, int len) {
return 0;
}
//Close the file.
void ICACHE_FLASH_ATTR espFsClose(EspFsFile *fh) {
if (fh==NULL) return;
#ifdef EFS_HEATSHRINK
+1
View File
@@ -1,3 +1,4 @@
//Heatshrink config for the decompressor.
#ifndef HEATSHRINK_CONFIG_H
#define HEATSHRINK_CONFIG_H
+32 -9
View File
@@ -1,5 +1,16 @@
//Esp8266 http server - core routines
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
* this notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return.
* ----------------------------------------------------------------------------
*/
#include "espmissingincludes.h"
#include "driver/uart.h"
#include "c_types.h"
#include "user_interface.h"
#include "espconn.h"
@@ -11,7 +22,7 @@
#include "io.h"
#include "espfs.h"
//Max length of head (plus POST data)
//Max length of request head
#define MAX_HEAD_LEN 1024
//Max amount of connections
#define MAX_CONN 8
@@ -41,6 +52,8 @@ typedef struct {
const char *mimetype;
} MimeMap;
//The mappings from file extensions to mime types. If you need an extra mime type,
//add it here.
static const MimeMap mimeTypes[]={
{"htm", "text/htm"},
{"html", "text/html"},
@@ -49,9 +62,10 @@ static const MimeMap mimeTypes[]={
{"jpg", "image/jpeg"},
{"jpeg", "image/jpeg"},
{"png", "image/png"},
{NULL, "text/html"},
{NULL, "text/html"}, //default value
};
//Returns a static char* to a mime type for a given url to a file.
const char ICACHE_FLASH_ATTR *httpdGetMimetype(char *url) {
int i=0;
//Go find the extension
@@ -63,7 +77,7 @@ const char ICACHE_FLASH_ATTR *httpdGetMimetype(char *url) {
return mimeTypes[i].mimetype;
}
//Looks up the connData info for a specific esp connection
static HttpdConnData ICACHE_FLASH_ATTR *httpdFindConnData(void *arg) {
int i;
for (i=0; i<MAX_CONN; i++) {
@@ -73,7 +87,7 @@ static HttpdConnData ICACHE_FLASH_ATTR *httpdFindConnData(void *arg) {
return NULL; //WtF?
}
//Retires a connection for re-use
static void ICACHE_FLASH_ATTR httpdRetireConn(HttpdConnData *conn) {
if (conn->postBuff!=NULL) os_free(conn->postBuff);
conn->postBuff=NULL;
@@ -81,6 +95,7 @@ static void ICACHE_FLASH_ATTR httpdRetireConn(HttpdConnData *conn) {
conn->conn=NULL;
}
//Stupid li'l helper function that returns the value of a hex char.
static int httpdHexVal(char c) {
if (c>='0' && c<='9') return c-'0';
if (c>='A' && c<='F') return c-'A'+10;
@@ -88,7 +103,10 @@ static int httpdHexVal(char c) {
return 0;
}
//Decode a percent-encoded value
//Decode a percent-encoded value.
//Takes the valLen bytes stored in val, and converts it into at most retLen bytes that
//are stored in the ret buffer. Returns the actual amount of bytes used in ret. Also
//zero-terminates the ret buffer.
int httpdUrlDecode(char *val, int valLen, char *ret, int retLen) {
int s=0, d=0;
int esced=0, escVal=0;
@@ -114,7 +132,9 @@ int httpdUrlDecode(char *val, int valLen, char *ret, int retLen) {
}
//Find a specific arg in a string of get- or post-data.
//Returns len of arg or -1 if not found.
//Line is the string of post/get-data, arg is the name of the value to find. The
//zero-terminated result is written in buff, with at most buffLen bytes used. The
//function returns the length of the result, or -1 if the value wasn't found.
int ICACHE_FLASH_ATTR httpdFindArg(char *line, char *arg, char *buff, int buffLen) {
char *p, *e;
if (line==NULL) return 0;
@@ -135,8 +155,8 @@ int ICACHE_FLASH_ATTR httpdFindArg(char *line, char *arg, char *buff, int buffLe
return -1; //not found
}
static const char *httpNotFoundHeader="HTTP/1.0 404 Not Found\r\nServer: esp8266-httpd/0.1\r\nContent-Type: text/plain\r\n\r\nNot Found.\r\n";
//Start the response headers.
void ICACHE_FLASH_ATTR httpdStartResponse(HttpdConnData *conn, int code) {
char buff[128];
int l;
@@ -144,7 +164,7 @@ void ICACHE_FLASH_ATTR httpdStartResponse(HttpdConnData *conn, int code) {
espconn_sent(conn->conn, (uint8 *)buff, l);
}
//Send a http header.
void ICACHE_FLASH_ATTR httpdHeader(HttpdConnData *conn, const char *field, const char *val) {
char buff[256];
int l;
@@ -152,6 +172,7 @@ void ICACHE_FLASH_ATTR httpdHeader(HttpdConnData *conn, const char *field, const
espconn_sent(conn->conn, (uint8 *)buff, l);
}
//Finish the headers.
void ICACHE_FLASH_ATTR httpdEndHeaders(HttpdConnData *conn) {
espconn_sent(conn->conn, (uint8 *)"\r\n", 2);
}
@@ -193,6 +214,8 @@ static void ICACHE_FLASH_ATTR httpdSentCb(void *arg) {
}
}
static const char *httpNotFoundHeader="HTTP/1.0 404 Not Found\r\nServer: esp8266-httpd/0.1\r\nContent-Type: text/plain\r\n\r\nNot Found.\r\n";
static void ICACHE_FLASH_ATTR httpdSendResp(HttpdConnData *conn) {
int i=0;
int r;
+2 -4
View File
@@ -26,10 +26,8 @@ struct HttpdConnData {
char *postBuff;
};
//A struct describing an url that's not in the filesystem or otherwise available.
//Also the way cgi functions get connected to an URL.
//A struct describing an url. This is the main struct that's used to send different URL requests to
//different routines.
typedef struct {
const char *url;
cgiSendCallback cgiCb;
+14
View File
@@ -2,6 +2,15 @@
Connector to let httpd use the espfs filesystem to serve the files in that.
*/
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
* this notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return.
* ----------------------------------------------------------------------------
*/
#include "espmissingincludes.h"
#include <string.h>
#include <osapi.h>
@@ -15,6 +24,9 @@ Connector to let httpd use the espfs filesystem to serve the files in that.
#include "httpdespfs.h"
//This is a catch-all cgi function. It takes the url passed to it, looks up the corresponding
//path in the filesystem and if it exists, passes the file through. This simulates what a normal
//webserver would do with static files.
int ICACHE_FLASH_ATTR cgiEspFsHook(HttpdConnData *connData) {
EspFsFile *file=connData->cgiData;
int len;
@@ -52,6 +64,8 @@ int ICACHE_FLASH_ATTR cgiEspFsHook(HttpdConnData *connData) {
}
//cgiEspFsTemplate can be used as a template.
typedef struct {
EspFsFile *file;
void *tplArg;
+11
View File
@@ -1,3 +1,14 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
* this notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return.
* ----------------------------------------------------------------------------
*/
#include "espmissingincludes.h"
#include "c_types.h"
#include "user_interface.h"
+18 -3
View File
@@ -1,30 +1,45 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
* this notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return.
* ----------------------------------------------------------------------------
*/
#include "espmissingincludes.h"
#include "ets_sys.h"
#include "driver/uart.h"
#include "osapi.h"
#include "httpd.h"
#include "io.h"
#include "httpdespfs.h"
#include "cgi.h"
#include "cgiwifi.h"
#include "stdout.h"
HttpdBuiltInUrl builtInUrls[]={
{"/", cgiRedirect, "/test2.html"},
{"/flash.bin", cgiReadFlash, NULL},
{"/led.tpl", cgiEspFsTemplate, tplLed},
{"/led.cgi", cgiLed, NULL},
//Routines to make the /wifi URL and everything beneath it work.
{"/wifi", cgiRedirect, "/wifi/wifi.tpl"},
{"/wifi/", cgiRedirect, "/wifi/wifi.tpl"},
{"/wifi/wifiscan.cgi", cgiWiFiScan, NULL},
{"/wifi/wifi.tpl", cgiEspFsTemplate, tplWlan},
{"/wifi/connect.cgi", cgiWiFiConnect},
{"*", cgiEspFsHook, NULL},
{"*", cgiEspFsHook, NULL}, //Catch-all cgi function for the filesystem
{NULL, NULL, NULL}
};
void user_init(void) {
uart_init(BIT_RATE_115200, BIT_RATE_115200);
stdoutInit();
ioInit();
httpdInit(builtInUrls, 80);
os_printf("\nReady\n");