much further progress :)
Able to have sustained and queued websockets connections at ~500 Hz. Commands pass over said connection.
This commit is contained in:
parent
bba28c688f
commit
666d8077ab
|
@ -61,17 +61,25 @@ static void ICACHE_FLASH_ATTR scandone(void *arg, STATUS status)
|
|||
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR issue_command(void *arg, char *pusrdata, unsigned short len)
|
||||
int ICACHE_FLASH_ATTR issue_command(char * buffer, int retsize, char *pusrdata, unsigned short len)
|
||||
{
|
||||
pespconn = (struct espconn *)arg;
|
||||
//We accept commands on this.
|
||||
char * buffend = buffer;
|
||||
|
||||
switch( pusrdata[0] )
|
||||
{
|
||||
case 'e': case 'E': //Echo
|
||||
if( retsize > len )
|
||||
{
|
||||
ets_memcpy( buffend, pusrdata, len );
|
||||
return len;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
case 'f': case 'F': //Flashing commands (F_)
|
||||
{
|
||||
flashchip->chip_size = 0x01000000;
|
||||
// ets_printf( "PC%p\n", &pusrdata[2] );
|
||||
const char * colon = (const char *) ets_strstr( (char*)&pusrdata[2], ":" );
|
||||
int nr = my_atoi( &pusrdata[2] );
|
||||
|
||||
|
@ -79,51 +87,33 @@ void ICACHE_FLASH_ATTR issue_command(void *arg, char *pusrdata, unsigned short l
|
|||
{
|
||||
case 'e': case 'E': //(FE#\n) <- # = sector.
|
||||
{
|
||||
char __attribute__ ((aligned (16))) buffer[50];
|
||||
char * buffend;
|
||||
buffend = buffer;
|
||||
|
||||
EnterCritical();
|
||||
spi_flash_erase_sector( nr ); //SPI_FLASH_SEC_SIZE 4096
|
||||
ExitCritical();
|
||||
|
||||
buffend += ets_sprintf(buffend, "FE%d\r\n", nr );
|
||||
espconn_sent( pespconn, buffer, ets_strlen( buffer ) );
|
||||
break;
|
||||
}
|
||||
|
||||
case 'b': case 'B': //(FE#\n) <- # = sector.
|
||||
{
|
||||
char __attribute__ ((aligned (16))) buffer[50];
|
||||
char * buffend;
|
||||
buffend = buffer;
|
||||
//spi_flash_erase_sector( nr ); //SPI_FLASH_SEC_SIZE 4096
|
||||
|
||||
EnterCritical();
|
||||
SPIEraseBlock( nr );
|
||||
ExitCritical();
|
||||
|
||||
buffend += ets_sprintf(buffend, "FB%d\r\n", nr );
|
||||
espconn_sent( pespconn, buffer, ets_strlen( buffer ) );
|
||||
break;
|
||||
}
|
||||
|
||||
case 'm': case 'M': //Execute the flash re-writer
|
||||
{
|
||||
char ret[128];
|
||||
int n = ets_sprintf( ret, "FM" );
|
||||
espconn_sent( pespconn, ret, n );
|
||||
int r = (*GlobalRewriteFlash)( &pusrdata[2], len-2 );
|
||||
n = ets_sprintf( ret, "!FM%d", r );
|
||||
espconn_sent( pespconn, ret, n );
|
||||
buffend += ets_sprintf( buffend, "!FM%d\r\n", r );
|
||||
break;
|
||||
}
|
||||
case 'w': case 'W': //Flash Write (FW#\n) <- # = byte pos.
|
||||
if( colon )
|
||||
{
|
||||
char __attribute__ ((aligned (32))) buffer[1300];
|
||||
char * buffend;
|
||||
buffend = buffer;
|
||||
buffer[0] = 0;
|
||||
colon++;
|
||||
const char * colon2 = (const char *) ets_strstr( (char*)colon, ":" );
|
||||
if( colon2 )
|
||||
|
@ -136,50 +126,37 @@ void ICACHE_FLASH_ATTR issue_command(void *arg, char *pusrdata, unsigned short l
|
|||
spi_flash_write( nr, (uint32*)buffer, (datlen/4)*4 );
|
||||
ExitCritical();
|
||||
|
||||
//SPIWrite( nr, (uint32_t*)buffer, (datlen/4)*4 );
|
||||
|
||||
buffend = buffer;
|
||||
buffend += ets_sprintf(buffend, "FW%d\r\n", nr );
|
||||
if( ets_strlen( buffer ) )
|
||||
espconn_sent( pespconn, buffer, ets_strlen( buffer ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
buffend += ets_sprintf(buffend, "!FW\r\n" );
|
||||
break;
|
||||
case 'r': case 'R': //Flash Read (FR#\n) <- # = sector.
|
||||
if( colon )
|
||||
{
|
||||
char __attribute__ ((aligned (16))) buffer[1300];
|
||||
char * buffend;
|
||||
buffend = buffer;
|
||||
buffer[0] = 0;
|
||||
colon++;
|
||||
int datlen = my_atoi( colon );
|
||||
datlen = (datlen/4)*4; //Must be multiple of 4 bytes
|
||||
if( datlen <= 1280 )
|
||||
{
|
||||
buffend += ets_sprintf(buffend, "FR%08d:%04d:", nr, datlen );
|
||||
int frontlen = buffend - buffer;
|
||||
spi_flash_read( nr, (uint32*)buffend, (datlen/4)*4 );
|
||||
espconn_sent( pespconn, buffer, frontlen + datlen );
|
||||
buffer[0] = 0;
|
||||
if( ets_strlen( buffer ) )
|
||||
espconn_sent( pespconn, buffer, ets_strlen( buffer ) );
|
||||
buffend += ets_sprintf(buffend, "FR%08d:%04d:", nr, datlen ); //Caution: This string must be a multiple of 4 bytes.
|
||||
spi_flash_read( nr, (uint32*)buffend, datlen );
|
||||
break;
|
||||
}
|
||||
}
|
||||
buffend += ets_sprintf(buffend, "!FR\r\n" );
|
||||
break;
|
||||
}
|
||||
|
||||
flashchip->chip_size = 0x00080000;
|
||||
break;
|
||||
return buffend - buffer;
|
||||
}
|
||||
case 'w': case 'W': // (W1:SSID:PASSWORD) (To connect) or (W2) to be own base station. ...or WI, to get info... or WS to scan.
|
||||
{
|
||||
char * colon = (char *) ets_strstr( (char*)&pusrdata[2], ":" );
|
||||
char * colon2 = (colon)?((char *)ets_strstr( (char*)(colon+1), ":" )):0;
|
||||
char * extra = colon2;
|
||||
char __attribute__ ((aligned (16))) buffer[1300];
|
||||
char * buffend;
|
||||
buffend = buffer;
|
||||
buffer[0] = 0;
|
||||
|
||||
if( extra )
|
||||
{
|
||||
|
@ -196,59 +173,65 @@ void ICACHE_FLASH_ATTR issue_command(void *arg, char *pusrdata, unsigned short l
|
|||
switch (pusrdata[1])
|
||||
{
|
||||
case '1': //Station mode
|
||||
case '2': //AP Mode
|
||||
if( colon && colon2 )
|
||||
{
|
||||
int c1l = 0;
|
||||
int c2l = 0;
|
||||
struct station_config stationConf;
|
||||
*colon = 0; colon++;
|
||||
*colon2 = 0; colon2++;
|
||||
c1l = ets_strlen( colon );
|
||||
c2l = ets_strlen( colon2 );
|
||||
if( c1l > 32 ) c1l = 32;
|
||||
if( c2l > 32 ) c2l = 32;
|
||||
os_bzero( &stationConf, sizeof( stationConf ) );
|
||||
|
||||
printf( "Switching to: \"%s\"/\"%s\".\n", colon, colon2 );
|
||||
|
||||
os_memcpy(&stationConf.ssid, colon, c1l);
|
||||
os_memcpy(&stationConf.password, colon2, c2l);
|
||||
if( pusrdata[1] == '1' )
|
||||
{
|
||||
struct station_config stationConf;
|
||||
os_bzero( &stationConf, sizeof( stationConf ) );
|
||||
|
||||
wifi_set_opmode( 1 );
|
||||
wifi_station_set_config(&stationConf);
|
||||
wifi_station_connect();
|
||||
espconn_sent( pespconn, "W1\r\n", 4 );
|
||||
os_memcpy(&stationConf.ssid, colon, c1l);
|
||||
os_memcpy(&stationConf.password, colon2, c2l);
|
||||
|
||||
printf( "Switching.\n" );
|
||||
}
|
||||
break;
|
||||
case '2':
|
||||
{
|
||||
wifi_set_opmode_current( 1 );
|
||||
wifi_set_opmode( 2 );
|
||||
espconn_sent( pespconn, "W2\r\n", 4 );
|
||||
wifi_set_opmode( 1 );
|
||||
wifi_station_set_config(&stationConf);
|
||||
wifi_station_connect();
|
||||
|
||||
buffend += ets_sprintf( buffend, "W1\r\n" );
|
||||
printf( "Switching.\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
wifi_set_opmode_current( 1 );
|
||||
wifi_set_opmode( 2 );
|
||||
buffend += ets_sprintf( buffend, "W2\r\n" );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'I':
|
||||
{
|
||||
struct station_config sc;
|
||||
int mode = wifi_get_opmode();
|
||||
char buffer[200];
|
||||
char * buffend = &buffer[0];
|
||||
|
||||
buffend += ets_sprintf( buffend, "WI%d", mode );
|
||||
|
||||
wifi_station_get_config( &sc );
|
||||
|
||||
buffend += ets_sprintf( buffend, ":%s:%s", sc.ssid, sc.password );
|
||||
|
||||
espconn_sent( pespconn, buffer, buffend - buffer );
|
||||
if( mode == 2 )
|
||||
{
|
||||
struct softap_config ap;
|
||||
wifi_softap_get_config( &ap );
|
||||
buffend += ets_sprintf( buffend, "\t%s\t%s\t%s\t%d", ap.ssid, ap.password, enctypes[ap.authmode], ap.channel );
|
||||
}
|
||||
else
|
||||
{
|
||||
struct station_config sc;
|
||||
wifi_station_get_config( &sc );
|
||||
buffend += ets_sprintf( buffend, "\t%s\t%s\tna\t%d", sc.ssid, sc.password, wifi_get_channel() );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'S': case 's':
|
||||
{
|
||||
char buffer[1024];
|
||||
char * buffend = &buffer[0];
|
||||
int i, r;
|
||||
|
||||
scanplace = 0;
|
||||
|
@ -267,34 +250,41 @@ void ICACHE_FLASH_ATTR issue_command(void *arg, char *pusrdata, unsigned short l
|
|||
buffend += ets_sprintf( buffend, "WS%d\n", r );
|
||||
uart0_sendStr(buffer);
|
||||
|
||||
espconn_sent( pespconn, buffer, buffend - buffer );
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'R': case 'r':
|
||||
{
|
||||
char buffer[1024];
|
||||
char * buffend = &buffer[0];
|
||||
int i, r;
|
||||
|
||||
buffend += ets_sprintf( buffend, "WR%d\n", scanplace );
|
||||
|
||||
for( i = 0; i < scanplace; i++ )
|
||||
for( i = 0; i < scanplace && buffend - buffer < retsize - 64; i++ )
|
||||
{
|
||||
buffend += ets_sprintf( buffend, "#%s\t%s\t%d\t%d\t%s\n",
|
||||
totalscan[i].name, totalscan[i].mac, totalscan[i].rssi, totalscan[i].channel, enctypes[totalscan[i].encryption] );
|
||||
}
|
||||
|
||||
espconn_sent( pespconn, buffer, buffend - buffer );
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
return buffend - buffer;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR issue_command_udp(void *arg, char *pusrdata, unsigned short len)
|
||||
{
|
||||
char __attribute__ ((aligned (32))) retbuf[1300];
|
||||
int r = issue_command( retbuf, 1300, pusrdata, len );
|
||||
if( r > 0 )
|
||||
{
|
||||
espconn_sent( (struct espconn *)arg, retbuf, r );
|
||||
}
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR CSInit()
|
||||
|
@ -304,7 +294,7 @@ void ICACHE_FLASH_ATTR CSInit()
|
|||
pUdpServer->type = ESPCONN_UDP;
|
||||
pUdpServer->proto.udp = (esp_udp *)os_zalloc(sizeof(esp_udp));
|
||||
pUdpServer->proto.udp->local_port = 7878;
|
||||
espconn_regist_recvcb(pUdpServer, issue_command);
|
||||
espconn_regist_recvcb(pUdpServer, issue_command_udp);
|
||||
espconn_create( pUdpServer );
|
||||
|
||||
pHTTPServer = (struct espconn *)os_zalloc(sizeof(struct espconn));
|
||||
|
|
|
@ -6,6 +6,12 @@
|
|||
|
||||
#include "c_types.h"
|
||||
|
||||
//Returns nr bytes to return. You must allocate retdata.
|
||||
//It MUST be at least 1,300 bytes large and it MUST be 32-bit aligned.
|
||||
//NOTE: It is SAFE to use pusrdata and retdata as the same buffer.
|
||||
int ICACHE_FLASH_ATTR issue_command(char * retdata, int retsize, char *pusrdata, unsigned short len);
|
||||
|
||||
|
||||
//Includes UDP Control + HTTP Interfaces
|
||||
void ICACHE_FLASH_ATTR CSInit();
|
||||
void ICACHE_FLASH_ATTR CSTick( int slowtick );
|
||||
|
|
|
@ -11,6 +11,9 @@ struct HTTPConnection HTTPConnections[HTTP_CONNECTIONS];
|
|||
struct HTTPConnection * curhttp;
|
||||
uint8 * curdata;
|
||||
uint16 curlen;
|
||||
uint8 wsmask[4];
|
||||
uint8 wsmaskplace;
|
||||
|
||||
|
||||
ICACHE_FLASH_ATTR void InternalStartHTTP( );
|
||||
ICACHE_FLASH_ATTR void HTTPHandleInternalCallback( );
|
||||
|
@ -29,7 +32,7 @@ void ICACHE_FLASH_ATTR HTTPGotData( )
|
|||
|
||||
while( curlen-- )
|
||||
{
|
||||
c = POP;
|
||||
c = HTTPPOP;
|
||||
// sendhex2( h->state ); sendchr( ' ' );
|
||||
|
||||
switch( curhttp->state )
|
||||
|
@ -97,8 +100,15 @@ void ICACHE_FLASH_ATTR HTTPGotData( )
|
|||
WebSocketGotData( c );
|
||||
break;
|
||||
case HTTP_WAIT_CLOSE:
|
||||
//printf( "__HTTPCLose1\n" );
|
||||
HTTPClose( );
|
||||
if( curhttp->keep_alive )
|
||||
{
|
||||
curhttp->state = HTTP_STATE_WAIT_METHOD;
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf( "__HTTPCLose1\n" );
|
||||
HTTPClose( );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -130,8 +140,15 @@ static void DoHTTP( uint8_t timed )
|
|||
case HTTP_WAIT_CLOSE:
|
||||
if( TCPDoneSend( curhttp->socket ) )
|
||||
{
|
||||
//printf( "HTTPCLose2\n");
|
||||
HTTPClose( );
|
||||
if( curhttp->keep_alive )
|
||||
{
|
||||
curhttp->state = HTTP_STATE_WAIT_METHOD;
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf( "HTTPCLose2\n");
|
||||
HTTPClose( );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HTTP_STATE_DATA_WEBSOCKET:
|
||||
|
@ -187,14 +204,21 @@ void ICACHE_FLASH_ATTR HTTPHandleInternalCallback( )
|
|||
|
||||
START_PACK;
|
||||
//TODO: Content Length? MIME-Type?
|
||||
PushString("HTTP/1.1 200 Ok\r\nConnection: close");
|
||||
PushString("HTTP/1.1 200 Ok\r\n");
|
||||
|
||||
if( curhttp->bytesleft < 0xfffffffe )
|
||||
{
|
||||
PushString("\r\nContent-Length: ");
|
||||
PushString("Connection: keep-alive\r\nContent-Length: ");
|
||||
Uint32To10Str( stto, curhttp->bytesleft );
|
||||
PushBlob( stto, os_strlen( stto ) );
|
||||
curhttp->keep_alive = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
PushString("Connection: close\r\n");
|
||||
curhttp->keep_alive = 0;
|
||||
}
|
||||
|
||||
PushString( "\r\nContent-Type: " );
|
||||
//Content-Type?
|
||||
while( slen && ( curhttp->pathbuffer[--slen] != '.' ) );
|
||||
|
@ -203,6 +227,10 @@ void ICACHE_FLASH_ATTR HTTPHandleInternalCallback( )
|
|||
{
|
||||
PushString( "audio/mpeg3" );
|
||||
}
|
||||
else if( strcmp( k, "gz" ) == 0 )
|
||||
{
|
||||
PushString( "text/plain\r\nContent-Encoding: gzip\r\nCache-Control: public, max-age=3600" );
|
||||
}
|
||||
else if( curhttp->bytesleft == 0xfffffffe )
|
||||
{
|
||||
PushString( "text/plain" );
|
||||
|
@ -410,6 +438,7 @@ void ICACHE_FLASH_ATTR WebSocketGotData( uint8_t c )
|
|||
|
||||
#define WS_KEY_LEN 36
|
||||
#define WS_KEY "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
|
||||
#define WS_RETKEY_SIZEM1 32
|
||||
|
||||
while( curlen > 1 )
|
||||
{
|
||||
|
@ -449,14 +478,16 @@ void ICACHE_FLASH_ATTR WebSocketGotData( uint8_t c )
|
|||
SHA1_Update( &c, inkey, i );
|
||||
SHA1_Final( hash, &c );
|
||||
|
||||
if( SHA1_HASH_LEN * 2 > MAX_PATHLEN )
|
||||
{
|
||||
HTDEBUG( "Pathlen too short.\n" );
|
||||
curhttp->state = HTTP_WAIT_CLOSE;
|
||||
return;
|
||||
}
|
||||
#if (WS_RETKEY_SIZE > MAX_PATHLEN - 10 )
|
||||
#error MAX_PATHLEN too short.
|
||||
#endif
|
||||
|
||||
my_base64_encode( hash, SHA1_HASH_LEN, curhttp->pathbuffer );
|
||||
my_base64_encode( hash, SHA1_HASH_LEN, curhttp->pathbuffer + (MAX_PATHLEN-WS_RETKEY_SIZEM1) );
|
||||
|
||||
curhttp->bytessofar = 0;
|
||||
curhttp->bytesleft = 0;
|
||||
|
||||
NewWebSocket();
|
||||
|
||||
//Respond...
|
||||
curhttp->state_deets = 1;
|
||||
|
@ -507,7 +538,16 @@ void ICACHE_FLASH_ATTR WebSocketGotData( uint8_t c )
|
|||
{
|
||||
payloadlen &= 0x7f;
|
||||
}
|
||||
WebSocketData( curdata, payloadlen );
|
||||
|
||||
wsmask[0] = curdata[0];
|
||||
wsmask[1] = curdata[1];
|
||||
wsmask[2] = curdata[2];
|
||||
wsmask[3] = curdata[3];
|
||||
curdata += 4;
|
||||
curlen -= 4;
|
||||
wsmaskplace = 0;
|
||||
|
||||
WebSocketData( payloadlen );
|
||||
curlen -= payloadlen;
|
||||
curdata += payloadlen;
|
||||
|
||||
|
@ -525,13 +565,11 @@ void ICACHE_FLASH_ATTR WebSocketTickInternal()
|
|||
case 4: //Has key full HTTP header, etc. wants response.
|
||||
START_PACK;
|
||||
PushString( "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: " );
|
||||
PushString( curhttp->pathbuffer );
|
||||
PushString( curhttp->pathbuffer + (MAX_PATHLEN-WS_RETKEY_SIZEM1) );
|
||||
PushString( "\r\n\r\n" );
|
||||
EndTCPWrite( curhttp->socket );
|
||||
curhttp->state_deets = 5;
|
||||
curhttp->bytessofar = 0;
|
||||
curhttp->bytesleft = 0;
|
||||
NewWebSocket();
|
||||
curhttp->keep_alive = 0;
|
||||
break;
|
||||
case 5:
|
||||
WebSocketTick();
|
||||
|
@ -557,4 +595,11 @@ void ICACHE_FLASH_ATTR WebSocketSend( uint8_t * data, int size )
|
|||
EndTCPWrite( curhttp->socket );
|
||||
}
|
||||
|
||||
uint8_t WSPOPMASK()
|
||||
{
|
||||
uint8_t mask = wsmask[wsmaskplace];
|
||||
wsmaskplace = (wsmaskplace+1)&3;
|
||||
return (*curdata++)^(mask);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -22,15 +22,18 @@
|
|||
void ICACHE_FLASH_ATTR HTTPCustomStart( );
|
||||
void ICACHE_FLASH_ATTR HTTPCustomCallback( ); //called when we can send more data
|
||||
|
||||
void ICACHE_FLASH_ATTR WebSocketData( uint8_t * data, int len );
|
||||
void ICACHE_FLASH_ATTR WebSocketData( int len );
|
||||
void ICACHE_FLASH_ATTR WebSocketTick( );
|
||||
void ICACHE_FLASH_ATTR WebSocketNew();
|
||||
|
||||
extern struct HTTPConnection * curhttp;
|
||||
extern uint8 * curdata;
|
||||
extern uint16 curlen;
|
||||
extern uint8 wsmask[4];
|
||||
extern uint8 wsmaskplace;
|
||||
|
||||
#define POP (*curdata++)
|
||||
uint8_t WSPOPMASK();
|
||||
#define HTTPPOP (*curdata++)
|
||||
|
||||
#define HTTP_STATE_NONE 0
|
||||
#define HTTP_STATE_WAIT_METHOD 1
|
||||
|
@ -49,7 +52,10 @@ struct HTTPConnection
|
|||
{
|
||||
uint8_t state:4;
|
||||
uint8_t state_deets;
|
||||
uint8_t pathbuffer[MAX_PATHLEN]; //Also used for temporary and handshake information when using websockets.
|
||||
|
||||
//Provides path, i.e. "/index.html" but, for websockets, the last
|
||||
//32 bytes of the buffer are used for the websockets key.
|
||||
uint8_t pathbuffer[MAX_PATHLEN];
|
||||
uint8_t is_dynamic:1;
|
||||
uint16_t timeout;
|
||||
|
||||
|
@ -60,6 +66,7 @@ struct HTTPConnection
|
|||
} data;
|
||||
|
||||
void * rcb;
|
||||
void * rcbDat; //For websockets primarily.
|
||||
|
||||
uint32_t bytesleft;
|
||||
uint32_t bytessofar;
|
||||
|
@ -67,6 +74,7 @@ struct HTTPConnection
|
|||
uint8_t is404:1;
|
||||
uint8_t isdone:1;
|
||||
uint8_t isfirst:1;
|
||||
uint8_t keep_alive:1;
|
||||
uint8_t need_resend:1;
|
||||
|
||||
struct espconn * socket;
|
||||
|
|
|
@ -34,11 +34,16 @@ static ICACHE_FLASH_ATTR void echo()
|
|||
|
||||
static ICACHE_FLASH_ATTR void issue()
|
||||
{
|
||||
char mydat[512];
|
||||
int len = URLDecode( mydat, 512, curhttp->pathbuffer+9 );
|
||||
|
||||
issue_command(curhttp->socket, mydat, len );
|
||||
uint8_t __attribute__ ((aligned (32))) buf[1300];
|
||||
int len = URLDecode( buf, 1300, curhttp->pathbuffer+9 );
|
||||
|
||||
int r = issue_command(buf, 1300, buf, len );
|
||||
if( r > 0 )
|
||||
{
|
||||
START_PACK;
|
||||
PushBlob( buf, r );
|
||||
EndTCPWrite( curhttp->socket );
|
||||
}
|
||||
curhttp->state = HTTP_WAIT_CLOSE;
|
||||
}
|
||||
|
||||
|
@ -72,6 +77,7 @@ void ICACHE_FLASH_ATTR HTTPCustomStart( )
|
|||
}
|
||||
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR HTTPCustomCallback( )
|
||||
{
|
||||
if( curhttp->rcb )
|
||||
|
@ -80,18 +86,91 @@ void ICACHE_FLASH_ATTR HTTPCustomCallback( )
|
|||
curhttp->isdone = 1;
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR WebSocketTick()
|
||||
|
||||
|
||||
|
||||
static void ICACHE_FLASH_ATTR WSEchoData( int len )
|
||||
{
|
||||
char cbo[len];
|
||||
int i;
|
||||
for( i = 0; i < len; i++ )
|
||||
{
|
||||
cbo[i] = WSPOPMASK();
|
||||
}
|
||||
WebSocketSend( cbo, len );
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR WebSocketData( uint8_t * data, int len )
|
||||
|
||||
static void ICACHE_FLASH_ATTR WSEvalData( int len )
|
||||
{
|
||||
char stout[128];
|
||||
int stl = ets_sprintf( stout, "output.innerHTML = %d; doSend('x' );\n", curhttp->bytessofar++ );
|
||||
WebSocketSend( stout, stl );
|
||||
char cbo[128];
|
||||
int l = ets_sprintf( cbo, "output.innerHTML = %d; doSend('x' );", curhttp->bytessofar++ );
|
||||
|
||||
WebSocketSend( cbo, l );
|
||||
}
|
||||
|
||||
|
||||
static void ICACHE_FLASH_ATTR WSCommandData( int len )
|
||||
{
|
||||
uint8_t __attribute__ ((aligned (32))) buf[1300];
|
||||
int i;
|
||||
|
||||
for( i = 0; i < len; i++ )
|
||||
{
|
||||
buf[i] = WSPOPMASK();
|
||||
}
|
||||
|
||||
i = issue_command(buf, 1300, buf, len );
|
||||
|
||||
if( i < 0 ) i = 0;
|
||||
|
||||
WebSocketSend( buf, i );
|
||||
}
|
||||
|
||||
|
||||
// output.innerHTML = msg++ + " " + lasthz;
|
||||
// doSend('x' );
|
||||
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR NewWebSocket()
|
||||
{
|
||||
if( strcmp( (const char*)curhttp->pathbuffer, "/d/ws/echo" ) == 0 )
|
||||
{
|
||||
curhttp->rcb = 0;
|
||||
curhttp->rcbDat = (void*)&WSEchoData;
|
||||
}
|
||||
else if( strcmp( (const char*)curhttp->pathbuffer, "/d/ws/evaltest" ) == 0 )
|
||||
{
|
||||
curhttp->rcb = 0;
|
||||
curhttp->rcbDat = (void*)&WSEvalData;
|
||||
}
|
||||
else if( strcmp( (const char*)curhttp->pathbuffer, "/d/ws/issue" ) == 0 )
|
||||
{
|
||||
curhttp->rcb = 0;
|
||||
curhttp->rcbDat = (void*)&WSCommandData;
|
||||
}
|
||||
else
|
||||
{
|
||||
curhttp->is404 = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR WebSocketTick()
|
||||
{
|
||||
if( curhttp->rcb )
|
||||
{
|
||||
((void(*)())curhttp->rcb)();
|
||||
}
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR WebSocketData( int len )
|
||||
{
|
||||
if( curhttp->rcbDat )
|
||||
{
|
||||
((void(*)( int ))curhttp->rcbDat)( len );
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
68
embedded8266/web/page/colorchord.html
Normal file
68
embedded8266/web/page/colorchord.html
Normal file
|
@ -0,0 +1,68 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>ColorChord Control Panel</title>
|
||||
<script language="javascript" type="text/javascript" src=jquery-2.1.4.min.js.gz></script>
|
||||
<script language="javascript" type="text/javascript" src=colorchord.js></script>
|
||||
<meta charset="UTF-8">
|
||||
<style>
|
||||
table { width: 100%; }
|
||||
td { vertical-align: top; }
|
||||
.collapsible { display:none; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h2>ColorChord: Embedded</h2>
|
||||
<hr>
|
||||
|
||||
<table>
|
||||
|
||||
<tr><td width=1>
|
||||
<input type=submit onclick="ShowHideEvent( 'SystemStatus' );" value="System Status" id=SystemStatusClicker></td><td>
|
||||
<div id=SystemStatus class="collapsible">
|
||||
<table width=100% border=1><tr><td>
|
||||
<div id=output></div>
|
||||
</td></tr></table></td></tr>
|
||||
|
||||
<tr><td width=1>
|
||||
<input type=submit onclick="ShowHideEvent( 'Introduction' );" value="Introduction"></td><td>
|
||||
<div id=Introduction class="collapsible">
|
||||
<table border=1><tr><td>
|
||||
System Info...<br>line2<br>line3
|
||||
</td></tr></table></td></tr>
|
||||
|
||||
<tr><td width=1>
|
||||
<input type=submit onclick="ShowHideEvent( 'WifiSettings' );" value="Wifi Settings"></td><td>
|
||||
<div id=WifiSettings class="collapsible">
|
||||
<table width=100% border=1><tr><td>
|
||||
Current Configuration:<form name="wifisection" action="javascript:ChangeWifiConfig();">
|
||||
<table border=1 width=1%>
|
||||
<tr><td width=1>Type:</td><td><input type="radio" name="wifitype" value=1>Station (Connect to infrastructure)<br><input type="radio" name="wifitype" value=2>AP (Broadcast a new AP)</td></tr>
|
||||
<tr><td>SSID:</td><td><input type="text" id="wificurname"></td></tr>
|
||||
<tr><td>PASS:</td><td><input type="text" id="wificurpassword"></td></tr>
|
||||
<tr><td>Enc:</td><td><input type="radio" name="wificurenctype" value="open">Open<br><input type="radio" name="wificurenctype" value="wpa-wpa2">WPA2-PSK (Ignored in Station mode)</td></tr>
|
||||
<tr><td>Chan:</td><td><input type="text" id="wificurchannel"> (Ignored in Station mode)</td></tr></tr>
|
||||
<tr><td></td><td><input type=submit value="Change Settings"></td></tr>
|
||||
</form></table>
|
||||
|
||||
Scanned Stations:
|
||||
<div id=WifiStations></div>
|
||||
<input type=submit onclick="QueueOperation('ws', null);" value="Scan For Stations (Will disconnect!)">
|
||||
</td></tr></table></td></tr>
|
||||
|
||||
<tr><td width=1>
|
||||
<input type=submit onclick="ShowHideEvent( 'CustomCommand' );" value="Custom Command"></td><td>
|
||||
<div id=CustomCommand class="collapsible">
|
||||
<table width=100% border=1><tr><td>
|
||||
Command: <input type=text id=custom_command>
|
||||
<input type=submit value="Submit" onclick="IssueCustomCommand()"><br>
|
||||
<textarea id=custom_command_response readonly rows=15 cols=80></textarea>
|
||||
</td></tr></table></td></tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
208
embedded8266/web/page/colorchord.js
Normal file
208
embedded8266/web/page/colorchord.js
Normal file
|
@ -0,0 +1,208 @@
|
|||
var wsUri = "ws://" + location.host + "/d/ws/issue";
|
||||
var output;
|
||||
var websocket;
|
||||
var commsup = 0;
|
||||
|
||||
//Push objects that have:
|
||||
// .request
|
||||
// .callback = function( ref (this object), data );
|
||||
|
||||
var workqueue = [];
|
||||
var lastitem;
|
||||
|
||||
function QueueOperation( command, callback )
|
||||
{
|
||||
var vp = new Object();
|
||||
vp.callback = callback;
|
||||
vp.request = command;
|
||||
workqueue.push( vp );
|
||||
}
|
||||
|
||||
|
||||
function init()
|
||||
{
|
||||
$( ".collapsible" ).each(function( index ) {
|
||||
if( localStorage["sh" + this.id] > 0.5 )
|
||||
{
|
||||
$( this ).show().toggleClass( 'opened' );
|
||||
}
|
||||
});
|
||||
|
||||
$("#custom_command_response").val( "" );
|
||||
|
||||
output = document.getElementById("output");
|
||||
Ticker();
|
||||
|
||||
|
||||
WifiDataTicker();
|
||||
}
|
||||
|
||||
function StartWebSocket()
|
||||
{
|
||||
output.innerHTML = "Connecting...";
|
||||
if( websocket ) websocket.close();
|
||||
workqueue = [];
|
||||
lastitem = null;
|
||||
websocket = new WebSocket(wsUri);
|
||||
websocket.onopen = function(evt) { onOpen(evt) };
|
||||
websocket.onclose = function(evt) { onClose(evt) };
|
||||
websocket.onmessage = function(evt) { onMessage(evt) };
|
||||
websocket.onerror = function(evt) { onError(evt) };
|
||||
}
|
||||
|
||||
function onOpen(evt)
|
||||
{
|
||||
doSend('e' );
|
||||
}
|
||||
|
||||
function onClose(evt)
|
||||
{
|
||||
$('#SystemStatusClicker').css("color", "red" );
|
||||
commsup = 0;
|
||||
}
|
||||
|
||||
var msg = 0;
|
||||
var tickmessage = 0;
|
||||
var lasthz = 0;
|
||||
|
||||
function Ticker()
|
||||
{
|
||||
lasthz = (msg - tickmessage);
|
||||
tickmessage = msg;
|
||||
if( lasthz == 0 )
|
||||
{
|
||||
$('#SystemStatusClicker').css("color", "red" );
|
||||
commsup = 0;
|
||||
StartWebSocket();
|
||||
}
|
||||
|
||||
setTimeout( Ticker, 1000 );
|
||||
}
|
||||
|
||||
function onMessage(evt)
|
||||
{
|
||||
msg++;
|
||||
output.innerHTML = "<p>Messages: " + msg + "</p><p>Hz:" + lasthz + "</p>";
|
||||
if( commsup != 1 )
|
||||
{
|
||||
commsup = 1;
|
||||
$('#SystemStatusClicker').css("color", "green" );
|
||||
}
|
||||
|
||||
if( lastitem && lastitem.callback )
|
||||
{
|
||||
lastitem.callback( lastitem, evt.data );
|
||||
lastitem = null;
|
||||
}
|
||||
|
||||
if( workqueue.length )
|
||||
{
|
||||
var elem = workqueue.shift();
|
||||
if( elem.request )
|
||||
{
|
||||
doSend( elem.request );
|
||||
lastitem = elem;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
doSend('e');
|
||||
}
|
||||
|
||||
function onError(evt)
|
||||
{
|
||||
$('#SystemStatusClicker').css("color", "red" );
|
||||
commsup = 0;
|
||||
}
|
||||
|
||||
function doSend(message)
|
||||
{
|
||||
websocket.send(message);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function ShowHideEvent( objname )
|
||||
{
|
||||
var obj = $( "#" + objname );
|
||||
obj.slideToggle( 'fast' ).toggleClass( 'opened' );
|
||||
var opened = obj.is( '.opened' );
|
||||
localStorage["sh" + objname] = opened?1:0;
|
||||
}
|
||||
|
||||
|
||||
function IssueCustomCommand()
|
||||
{
|
||||
QueueOperation( $("#custom_command").val(), function( req,data) { $("#custom_command_response").val( data ); } );
|
||||
}
|
||||
|
||||
|
||||
|
||||
window.addEventListener("load", init, false);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////// Various functions that are not core appear down here.
|
||||
|
||||
|
||||
did_wifi_get_config = false;
|
||||
|
||||
function WifiDataTicker()
|
||||
{
|
||||
if( !did_wifi_get_config )
|
||||
{
|
||||
QueueOperation( "WI", function(req,data)
|
||||
{
|
||||
var params = data.split( "\t" );
|
||||
|
||||
document.wifisection.wifitype.value = Number( params[0].substr(2) );
|
||||
document.wifisection.wificurname.value = params[1];
|
||||
document.wifisection.wificurpassword.value = params[2];
|
||||
document.wifisection.wificurenctype.value = params[3];
|
||||
document.wifisection.wificurchannel.value = Number( params[4] );
|
||||
|
||||
did_wifi_get_config = true;
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
QueueOperation( "WR", function(req,data) {
|
||||
var lines = data.split( "\n" );
|
||||
var innerhtml;
|
||||
if( lines.length < 3 )
|
||||
{
|
||||
innerhtml = "No APs found. Did you scan?";
|
||||
}
|
||||
else
|
||||
{
|
||||
innerhtml = "<TABLE border=1><TR><TH>SSID</TH><TH>MAC</TH><TH>RS</TH><TH>Ch</TH><TH>Enc</TH></TR>"
|
||||
for( i = 1; i < lines.length-1; i++ )
|
||||
{
|
||||
var dats = lines[i].split( "\t" );
|
||||
innerhtml += "<TR><TD>" + dats[0] + "</TD><TD>" + dats[1] + "</TD><TD>" + dats[2] + "</TD><TD>" + dats[3] + "</TD><TD>" + dats[4] + "</TD></TR>";
|
||||
}
|
||||
}
|
||||
innerhtml += "</HTML>";
|
||||
document.getElementById("WifiStations").innerHTML = innerhtml;
|
||||
} );
|
||||
|
||||
setTimeout( WifiDataTicker, 1000 );
|
||||
}
|
||||
|
||||
function ChangeWifiConfig()
|
||||
{
|
||||
|
||||
var st = "W";
|
||||
st += document.wifisection.wifitype.value;
|
||||
st += ":" + document.wifisection.wificurname.value;
|
||||
st += ":" + document.wifisection.wificurpassword.value;
|
||||
QueueOperation( st );
|
||||
did_wifi_get_config = false;
|
||||
}
|
||||
|
||||
|
BIN
embedded8266/web/page/jquery-2.1.4.min.js.gz
Normal file
BIN
embedded8266/web/page/jquery-2.1.4.min.js.gz
Normal file
Binary file not shown.
|
@ -1,7 +1,7 @@
|
|||
<HTML>
|
||||
<HEAD>
|
||||
<title>WebSocket Test</title>
|
||||
<script language="javascript" type="text/javascript" src=websocket.js></script>
|
||||
<script language="javascript" type="text/javascript" src=wstest.js></script>
|
||||
</HEAD>
|
||||
<BODY>
|
||||
<h2>WebSocket Test</h2>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
var wsUri = "ws://" + location.host + "/d/ws";
|
||||
var wsUri = "ws://" + location.host + "/d/ws/echo";
|
||||
|
||||
var output;
|
||||
|
||||
|
@ -37,9 +37,24 @@ function onClose(evt)
|
|||
writeToScreen("DISCONNECTED");
|
||||
}
|
||||
|
||||
var msg = 0;
|
||||
var tickmessage = 0;
|
||||
var lasthz = 0;
|
||||
|
||||
function Ticker()
|
||||
{
|
||||
lasthz = msg - tickmessage;
|
||||
tickmessage = msg;
|
||||
setTimeout( Ticker, 1000 );
|
||||
}
|
||||
|
||||
function onMessage(evt)
|
||||
{
|
||||
eval( evt.data );
|
||||
// eval( evt.data );
|
||||
|
||||
output.innerHTML = msg++ + " " + lasthz;
|
||||
doSend('x' );
|
||||
|
||||
// obj = JSON.parse(evt.data);
|
||||
// console.log( obj );
|
||||
// writeToScreen('<span style="color: blue;">RESPONSE: ' + evt.data+'</span>');
|
||||
|
@ -67,3 +82,5 @@ function writeToScreen(message)
|
|||
|
||||
window.addEventListener("load", init, false);
|
||||
|
||||
Ticker();
|
||||
|
Loading…
Reference in a new issue