#include "WebServer.h" #include "Arduino.h" #define RESUBSCRIBE_LIMIT 1000 WebServer * WebServer::instance = NULL; void webServerCallback(CmdRequest *req) { WebServer::getInstance()->handleRequest(req); } WebServer::WebServer(Stream &streamIn, const WebMethod * PROGMEM methodsIn):espLink(streamIn, webServerCallback),methods(methodsIn),stream(streamIn),esplink_cb(NULL) { instance = this; } void WebServer::init() { registerCallback(); } void WebServer::loop() { // resubscribe periodically uint32_t elapsed = millis() - last_connect_ts; if( elapsed > RESUBSCRIBE_LIMIT ) registerCallback(); espLink.readLoop(); } void WebServer::registerCallback() { espLink.sendPacketStart(CMD_CB_ADD, 100, 1); espLink.sendPacketArg(5, (uint8_t *)"webCb"); espLink.sendPacketEnd(); last_connect_ts = millis(); } void WebServer::invokeMethod(RequestReason reason, WebMethod * method, CmdRequest *req) { switch(reason) { case WS_BUTTON: { uint16_t len = espLink.cmdArgLen(req); char bf[len+1]; bf[len] = 0; espLink.cmdPopArg(req, bf, len); method->callback(BUTTON_PRESS, bf, len); } break; case WS_SUBMIT: { int arg_len = espLink.cmdGetArgc( req ); int cnt = 4; while( cnt < arg_len ) { uint16_t len = espLink.cmdArgLen(req); char bf[len+1]; bf[len] = 0; espLink.cmdPopArg(req, bf, len); value_ptr = bf + 2 + strlen(bf+1); method->callback(SET_FIELD, bf+1, strlen(bf+1)); cnt++; } } return; case WS_LOAD: case WS_REFRESH: break; default: return; } espLink.sendPacketStart(CMD_WEB_DATA, 100, 255); espLink.sendPacketArg(4, remote_ip); espLink.sendPacketArg(2, (uint8_t *)&remote_port); method->callback( reason == WS_LOAD ? LOAD : REFRESH, NULL, 0); espLink.sendPacketArg(0, NULL); espLink.sendPacketEnd(); } void WebServer::handleRequest(CmdRequest *req) { if( req->cmd->cmd != CMD_WEB_REQ_CB ) { if( esplink_cb != NULL ) esplink_cb(req); return; } uint16_t shrt; espLink.cmdPopArg(req, &shrt, 2); RequestReason reason = (RequestReason)shrt; espLink.cmdPopArg(req, &remote_ip, 4); espLink.cmdPopArg(req, &remote_port, 2); { uint16_t len = espLink.cmdArgLen(req); char bf[len+1]; bf[len] = 0; espLink.cmdPopArg(req, bf, len); const WebMethod * meth = methods; do { WebMethod m; memcpy_P(&m, meth, sizeof(WebMethod)); if( m.url == NULL || m.callback == NULL ) break; if( strcmp_P(bf, m.url) == 0 ) { invokeMethod(reason, &m, req); return; } meth++; }while(1); } if( reason == WS_SUBMIT ) return; // empty response espLink.sendPacketStart(CMD_WEB_DATA, 100, 2); espLink.sendPacketArg(4, remote_ip); espLink.sendPacketArg(2, (uint8_t *)&remote_port); espLink.sendPacketEnd(); } void WebServer::setArgString(const char * name, const char * value) { uint8_t nlen = strlen(name); uint8_t vlen = strlen(value); char buf[nlen + vlen + 3]; buf[0] = WEB_STRING; strcpy(buf+1, name); strcpy(buf+2+nlen, value); espLink.sendPacketArg(nlen+vlen+2, (uint8_t *)buf); } void WebServer::setArgStringP(const char * name, const char * value) { uint8_t nlen = strlen(name); uint8_t vlen = strlen_P(value); char buf[nlen + vlen + 3]; buf[0] = WEB_STRING; strcpy(buf+1, name); strcpy_P(buf+2+nlen, value); espLink.sendPacketArg(nlen+vlen+2, (uint8_t *)buf); } void WebServer::setArgBoolean(const char * name, uint8_t value) { uint8_t nlen = strlen(name); char buf[nlen + 4]; buf[0] = WEB_BOOLEAN; strcpy(buf+1, name); buf[2 + nlen] = value; espLink.sendPacketArg(nlen+3, (uint8_t *)buf); } void WebServer::setArgJson(const char * name, const char * value) { uint8_t nlen = strlen(name); uint8_t vlen = strlen(value); char buf[nlen + vlen + 3]; buf[0] = WEB_JSON; strcpy(buf+1, name); strcpy(buf+2+nlen, value); espLink.sendPacketArg(nlen+vlen+2, (uint8_t *)buf); } void WebServer::setArgInt(const char * name, int32_t value) { uint8_t nlen = strlen(name); char buf[nlen + 7]; buf[0] = WEB_INTEGER; strcpy(buf+1, name); memcpy(buf+2+nlen, &value, 4); espLink.sendPacketArg(nlen+6, (uint8_t *)buf); } int32_t WebServer::getArgInt() { return (int32_t)atol(value_ptr); } char * WebServer::getArgString() { return value_ptr; } uint8_t WebServer::getArgBoolean() { if( strcmp_P(value_ptr, PSTR("on")) == 0 ) return 1; if( strcmp_P(value_ptr, PSTR("true")) == 0 ) return 1; if( strcmp_P(value_ptr, PSTR("yes")) == 0 ) return 1; if( strcmp_P(value_ptr, PSTR("1")) == 0 ) return 1; return 0; }