Refactored: don't use json for MCU, it's too resouce consuming

pull/193/head
Karai Csaba 9 years ago committed by Thorsten von Eicken
parent 3b8d321859
commit 31c64a8141
  1. 30
      examples/arduino/EspLinkSample/EspLinkSample.ino
  2. 202
      web-server/web-server.c
  3. 10
      web-server/web-server.h

@ -42,7 +42,6 @@ void packetReceived(CmdRequest *req)
switch( reason ) switch( reason )
{ {
case BUTTON: case BUTTON:
case SUBMIT:
{ {
uint16_t len = espLink.cmdArgLen(req); uint16_t len = espLink.cmdArgLen(req);
char bf[len+1]; char bf[len+1];
@ -50,19 +49,38 @@ void packetReceived(CmdRequest *req)
espLink.cmdPopArg(req, bf, len); espLink.cmdPopArg(req, bf, len);
Serial.print("Arg: "); Serial.print("Arg: ");
Serial.println(bf); Serial.println(bf);
}
break;
case SUBMIT:
{
int arg = 4;
while( espLink.cmdGetArgc(req) > arg )
{
arg++;
if( reason == SUBMIT ) uint16_t len = espLink.cmdArgLen(req);
char bf[len+1];
bf[len] = 0;
espLink.cmdPopArg(req, bf, len);
Serial.print(bf + 1);
Serial.print(" -> ");
Serial.println(bf + strlen(bf+1) + 2);
}
return; return;
} }
break;
} }
char * json = "{\"last_name\": \"helloka\"}";
espLink.sendPacketStart(CMD_WEB_JSON_DATA, 100, 3); espLink.sendPacketStart(CMD_WEB_JSON_DATA, 100, 3);
espLink.sendPacketArg(4, ip); espLink.sendPacketArg(4, ip);
espLink.sendPacketArg(2, (uint8_t *)&port); espLink.sendPacketArg(2, (uint8_t *)&port);
espLink.sendPacketArg(strlen(json), (uint8_t *)json);
char outBuf[30];
outBuf[0] = 0;
strcpy(outBuf+1, "last_name");
strcpy(outBuf+11,"helloka");
espLink.sendPacketArg(19, (uint8_t *)outBuf);
espLink.sendPacketEnd(); espLink.sendPacketEnd();
} }

@ -10,6 +10,8 @@
#define WEB_CB "webCb" #define WEB_CB "webCb"
#define MAX_VARS 20
static char* web_server_reasons[] = { static char* web_server_reasons[] = {
"load", "refresh", "button", "submit" "load", "refresh", "button", "submit"
}; };
@ -84,36 +86,6 @@ void ICACHE_FLASH_ATTR WEB_Init()
WEB_BrowseFiles(); WEB_BrowseFiles();
} }
int ICACHE_FLASH_ATTR WEB_addJsonString(char * str, char * buf, int maxLen)
{
char * start = buf;
if( maxLen < 10 )
return -1;
char * endp = start + maxLen - 10;
*buf++ = '"';
int len = os_strlen(str);
char avalbuf[len*2+1];
char * valbuf = avalbuf;
valbuf[len*2] = 0;
httpdUrlDecode(str, len, valbuf, len * 2);
while(*valbuf)
{
if( *valbuf == '"' || *valbuf == '\\' )
*buf++ = '\\';
*buf++ = *(valbuf++);
if( buf > endp )
return -1;
}
*buf++ = '"';
return buf - start;
}
int ICACHE_FLASH_ATTR WEB_CgiJsonHook(HttpdConnData *connData) int ICACHE_FLASH_ATTR WEB_CgiJsonHook(HttpdConnData *connData)
{ {
if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up.
@ -161,18 +133,23 @@ int ICACHE_FLASH_ATTR WEB_CgiJsonHook(HttpdConnData *connData)
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
} }
char body[1024]; char body[1024];
int bodyLen = -1; int bodyPtr = 0;
int argNum = 0;
char *argPos[MAX_VARS];
int argLen[MAX_VARS];
switch(reason) switch(reason)
{ {
case BUTTON: case BUTTON:
bodyLen = httpdFindArg(connData->getArgs, "id", body, sizeof(body)); argLen[0] = httpdFindArg(connData->getArgs, "id", body, sizeof(body));
if( bodyLen <= 0 ) if( argLen[0] <= 0 )
{ {
errorResponse(connData, 400, "No button ID specified!"); errorResponse(connData, 400, "No button ID specified!");
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
} }
argPos[0] = body;
argNum++;
break; break;
case SUBMIT: case SUBMIT:
{ {
@ -182,14 +159,16 @@ int ICACHE_FLASH_ATTR WEB_CgiJsonHook(HttpdConnData *connData)
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
} }
bodyLen = 0;
int bptr = 0; int bptr = 0;
body[bodyLen++] = '{';
while( bptr < connData->post->len ) while( bptr < connData->post->len )
{ {
if( argNum >= MAX_VARS )
{
errorResponse(connData, 400, "Too many variables!");
return HTTPD_CGI_DONE;
}
char * line = connData->post->buff + bptr; char * line = connData->post->buff + bptr;
char * eo = os_strchr(line, '&' ); char * eo = os_strchr(line, '&' );
@ -216,26 +195,29 @@ int ICACHE_FLASH_ATTR WEB_CgiJsonHook(HttpdConnData *connData)
char * name = line; char * name = line;
char * value = val+1; char * value = val+1;
int alen = WEB_addJsonString(name, body + bodyLen, sizeof(body) - bodyLen); int namLen = os_strlen(name);
if( alen == -1 ) int valLen = os_strlen(value);
{
errorResponse(connData, 400, "Post too large!"); int totallen = namLen + valLen + 2;
return HTTPD_CGI_DONE; if( bodyPtr + totallen > sizeof(body) - 10 )
}
bodyLen += alen;
body[bodyLen++] = ':';
alen = WEB_addJsonString(value, body + bodyLen, sizeof(body) - bodyLen);
if( alen == -1 )
{ {
errorResponse(connData, 400, "Post too large!"); errorResponse(connData, 400, "Post too large!");
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
} }
bodyLen += alen;
body[bodyLen++] = ','; argPos[argNum] = body + bodyPtr;
body[bodyPtr++] = (char)WEB_STRING;
os_strcpy( body + bodyPtr, name );
bodyPtr += namLen;
body[bodyPtr++] = 0;
os_strcpy( body + bodyPtr, value );
bodyPtr += valLen;
argLen[argNum++] = totallen;
} }
} }
body[bodyLen++] = '}';
} }
break; break;
case LOAD: case LOAD:
@ -246,14 +228,17 @@ int ICACHE_FLASH_ATTR WEB_CgiJsonHook(HttpdConnData *connData)
os_printf("Web callback to MCU: %s\n", reasonBuf); os_printf("Web callback to MCU: %s\n", reasonBuf);
cmdResponseStart(CMD_WEB_REQ_CB, (uint32_t)cb->callback, bodyLen >= 0 ? 5 : 4); cmdResponseStart(CMD_WEB_REQ_CB, (uint32_t)cb->callback, 4 + argNum);
uint16_t r = (uint16_t)reason; uint16_t r = (uint16_t)reason;
cmdResponseBody(&r, sizeof(uint16_t)); cmdResponseBody(&r, sizeof(uint16_t));
cmdResponseBody(&connData->conn->proto.tcp->remote_ip, 4); cmdResponseBody(&connData->conn->proto.tcp->remote_ip, 4);
cmdResponseBody(&connData->conn->proto.tcp->remote_port, sizeof(uint16_t)); cmdResponseBody(&connData->conn->proto.tcp->remote_port, sizeof(uint16_t));
cmdResponseBody(connData->url, os_strlen(connData->url)); cmdResponseBody(connData->url, os_strlen(connData->url));
if( bodyLen >= 0 )
cmdResponseBody(body, bodyLen); int j;
for( j=0; j < argNum; j++ )
cmdResponseBody(argPos[j], argLen[j]);
cmdResponseEnd(); cmdResponseEnd();
if( reason == SUBMIT ) if( reason == SUBMIT )
@ -268,13 +253,107 @@ int ICACHE_FLASH_ATTR WEB_CgiJsonHook(HttpdConnData *connData)
if( connData->cgiArg != NULL ) // arrived data from MCU if( connData->cgiArg != NULL ) // arrived data from MCU
{ {
char jsonBuf[1500];
int jsonPtr = 0;
jsonBuf[jsonPtr++] = '{';
CmdRequest * req = (CmdRequest *)(connData->cgiArg);
int c = 2;
while( c++ < cmdGetArgc(req) )
{
if( c < 3 ) // skip the first argument
jsonBuf[jsonPtr++] = ',';
int len = cmdArgLen(req);
char buf[len+1];
buf[len] = 0;
cmdPopArg(req, buf, len);
if( jsonPtr + 20 + len > sizeof(jsonBuf) )
{
errorResponse(connData, 500, "Response too large!");
return HTTPD_CGI_DONE;
}
WebValueType type = (WebValueType)buf[0];
int nameLen = os_strlen(buf+1);
jsonBuf[jsonPtr++] = '"';
os_memcpy(jsonBuf + jsonPtr, buf + 1, nameLen);
jsonPtr += nameLen;
jsonBuf[jsonPtr++] = '"';
jsonBuf[jsonPtr++] = ':';
char * value = buf + 2 + nameLen;
switch(type)
{
case WEB_NULL:
os_memcpy(jsonBuf + jsonPtr, "null", 4);
jsonPtr += 4;
break;
case WEB_INTEGER:
{
int v;
os_memcpy( &v, value, 4);
char intbuf[20];
os_sprintf(intbuf, "%d", v);
os_strcpy(jsonBuf + jsonPtr, intbuf);
jsonPtr += os_strlen(intbuf);
}
break;
case WEB_BOOLEAN:
if( value ) {
os_memcpy(jsonBuf + jsonPtr, "true", 4);
jsonPtr += 4;
} else {
os_memcpy(jsonBuf + jsonPtr, "false", 5);
jsonPtr += 5;
}
break;
case WEB_FLOAT:
{
float f;
os_memcpy( &f, value, 4);
char intbuf[20];
os_sprintf(intbuf, "%f", f);
os_strcpy(jsonBuf + jsonPtr, intbuf);
jsonPtr += os_strlen(intbuf);
}
break;
case WEB_STRING:
jsonBuf[jsonPtr++] = '"';
while(*value)
{
if( *value == '\\' || *value == '"' )
jsonBuf[jsonPtr++] = '\\';
jsonBuf[jsonPtr++] = *(value++);
}
jsonBuf[jsonPtr++] = '"';
break;
case WEB_JSON:
os_memcpy(jsonBuf + jsonPtr, value, len - 2 - nameLen);
jsonPtr += len - 2 - nameLen;
break;
}
}
jsonBuf[jsonPtr++] = '}';
noCacheHeaders(connData, 200); noCacheHeaders(connData, 200);
httpdHeader(connData, "Content-Type", "application/json"); httpdHeader(connData, "Content-Type", "application/json");
char cl[16]; char cl[16];
os_sprintf(cl, "%d", os_strlen(connData->cgiArg)); os_sprintf(cl, "%d", jsonPtr);
httpdHeader(connData, "Content-Length", cl); httpdHeader(connData, "Content-Length", cl);
httpdEndHeaders(connData); httpdEndHeaders(connData);
httpdSend(connData, connData->cgiArg, os_strlen(connData->cgiArg));
httpdSend(connData, jsonBuf, jsonPtr);
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
} }
@ -286,7 +365,7 @@ void ICACHE_FLASH_ATTR WEB_JsonData(CmdPacket *cmd)
CmdRequest req; CmdRequest req;
cmdRequest(&req, cmd); cmdRequest(&req, cmd);
if (cmdGetArgc(&req) != 3) return; if (cmdGetArgc(&req) < 3) return;
uint8_t ip[4]; uint8_t ip[4];
cmdPopArg(&req, ip, 4); cmdPopArg(&req, ip, 4);
@ -294,10 +373,5 @@ void ICACHE_FLASH_ATTR WEB_JsonData(CmdPacket *cmd)
uint16_t port; uint16_t port;
cmdPopArg(&req, &port, 2); cmdPopArg(&req, &port, 2);
int16_t len = cmdArgLen(&req); httpdNotify(ip, port, &req);
uint8_t json[len+1];
json[len] = 0;
cmdPopArg(&req, json, len);
httpdNotify(ip, port, json);
} }

@ -16,6 +16,16 @@ typedef enum
INVALID=-1, INVALID=-1,
} RequestReason; } RequestReason;
typedef enum
{
WEB_STRING=0,
WEB_NULL,
WEB_INTEGER,
WEB_BOOLEAN,
WEB_FLOAT,
WEB_JSON
} WebValueType;
void WEB_Init(); void WEB_Init();
char * WEB_UserPages(); char * WEB_UserPages();

Loading…
Cancel
Save