int ICACHE_FLASH_ATTR cgiMenu(HttpdConnData *connData) { if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. char buff[1024]; // don't use jsonHeader so the response does get cached httpdStartResponse(connData, 200); httpdHeader(connData, "Cache-Control", "max-age=3600, must-revalidate"); httpdHeader(connData, "Content-Type", "application/json"); httpdEndHeaders(connData); // limit hostname to 12 chars char name[13]; os_strncpy(name, flashConfig.hostname, 12); name[12] = 0; // construct json response os_sprintf(buff, "{ " "\"menu\": [ " "\"Overview\", \"/home.html\", " "\"WiFi Console\", \"/console.html\", " "\"WiFi\", \"/wifi/wifi.html\", " #ifdef MQTT "\"Connectivity\", \"/mqtt.html\", " #endif "\"Debug log\", \"/log.html\"" " ], " "\"version\": \"%s\", " "\"name\": \"%s\"" " }", esp_link_version, name); httpdSend(connData, buff, -1); return HTTPD_CGI_DONE; }
// Cgi to query which firmware needs to be uploaded next int ICACHE_FLASH_ATTR cgiGetFirmwareNext(HttpdConnData *connData) { if (connData->conn==NULL) { //Connection aborted. Clean up. return HTTPD_CGI_DONE; } uint8 id = system_upgrade_userbin_check(); httpdStartResponse(connData, 200); httpdHeader(connData, "Content-Type", "text/plain"); httpdHeader(connData, "Content-Length", "9"); httpdEndHeaders(connData); char *next = id == 1 ? "user1.bin" : "user2.bin"; httpdSend(connData, next, -1); os_printf("Next firmware: %s (got %d)\n", next, id); return HTTPD_CGI_DONE; }
//This CGI is called from the bit of AJAX-code in wifi.tpl. It will initiate a //scan for access points and if available will return the result of an earlier scan. //The result is embedded in a bit of JSON parsed by the javascript in wifi.tpl. 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); } len=os_sprintf(buff, "]\n}\n}\n"); espconn_sent(connData->conn, (uint8 *)buff, len); wifiStartScan(); } return HTTPD_CGI_DONE; }
//Sends Content-encoding header if the requested file was GZIP compressed //If the client does not sent the Accept-encoding, send out a static html message. const char* sendGZIPEncodingIfNeeded(HttpdConnData *connData) { int i=0; char acceptEncodingBuffer[64]; //Go find the extension char *ext=connData->url+(strlen(connData->url)-1); while (ext!=connData->url && *ext!='.') ext--; if (*ext=='.') ext++; //ToDo: os_strcmp is case sensitive; we may want to do case-intensive matching here... while (gzippedFileTypes[i]!=NULL) { if (os_strcmp(ext, gzippedFileTypes[i])==0) { //when serving gzipped files check the browser's "Accept-Encoding" header //if the client does not advertises that he accepts GZIP send a warning message (telnet users for e.g.) httpdGetHeader(connData, "Accept-Encoding", acceptEncodingBuffer, 64); if (os_strstr(acceptEncodingBuffer, "gzip") == NULL) { //No Accept-Encoding: gzip header present return gzipNonSupportedMessage; } else { httpdHeader(connData, "Content-Encoding", "gzip"); return NULL; } } i++; } return NULL; }
int ICACHE_FLASH_ATTR cgiPWM(HttpdConnData *connData) { int len; char buff[128]; if (connData->conn==NULL) { //Connection aborted. Clean up. return HTTPD_CGI_DONE; } httpdStartResponse(connData, 200); httpdHeader(connData, "Content-Type", "text/json"); httpdEndHeaders(connData); len=httpdFindArg(connData->getArgs, "duty", buff, sizeof(buff)); if (len>0) { pwm_set_duty(atoi(buff), 0); pwm_start(); len=os_sprintf(buff, "OK"); httpdSend(connData, buff, -1); return HTTPD_CGI_DONE; } else { //with no parameters returns JSON with state len=os_sprintf(buff, "{\"pwm\": %d\n}\n", pwm_get_duty(0) ); httpdSend(connData, buff, -1); return HTTPD_CGI_DONE; } }
//This CGI is called from the bit of AJAX-code in wifi.tpl. It will initiate a //scan for access points and if available will return the result of an earlier scan. //The result is embedded in a bit of JSON parsed by the javascript in wifi.tpl. 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) { //We're still scanning. Tell Javascript code that. len=os_sprintf(buff, "{\n \"result\": { \n\"inProgress\": \"1\"\n }\n}\n"); espconn_sent(connData->conn, (uint8 *)buff, len); } else { //We have a scan result. Pass it on. 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++) { //Fill in json code for an access point 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); } len=os_sprintf(buff, "]\n}\n}\n"); espconn_sent(connData->conn, (uint8 *)buff, len); //Also start a new scan. wifiStartScan(); } return HTTPD_CGI_DONE; }
/* cgiGetAppVer */ int ICACHE_FLASH_ATTR cgiGetAppVer(HttpdConnection * ptConnection) { /* initialization */ int iRet = 0; if (NULL == ptConnection->ptEspConnection) { /* connection aborted - clean up */ iRet = HTTPD_CGI_DONE; goto lblCleanup; } char bVersion[1] = { 0 }; /* set and send app version */ os_sprintf(bVersion, "%d", system_upgrade_userbin_check() + 1); httpdStartResponse(ptConnection, 200); httpdHeader(ptConnection, CONTENT_LENGTH_STRING, "1"); httpdEndHeaders(ptConnection); httpdSend(ptConnection, bVersion, 1); iRet = HTTPD_CGI_DONE; lblCleanup: return iRet; }
//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; char buff[1024]; if (connData->conn==NULL) { //Connection aborted. Clean up. espFsClose(file); return HTTPD_CGI_DONE; } if (file==NULL) { //First call to this cgi. Open the file so we can read it. file=espFsOpen(connData->url); if (file==NULL) { return HTTPD_CGI_NOTFOUND; } connData->cgiData=file; httpdStartResponse(connData, 200); httpdHeader(connData, "Content-Type", httpdGetMimetype(connData->url)); httpdEndHeaders(connData); return HTTPD_CGI_MORE; } len=espFsRead(file, buff, 1024); if (len>0) espconn_sent(connData->conn, (uint8 *)buff, len); if (len!=1024) { //We're done. espFsClose(file); return HTTPD_CGI_DONE; } else { //Ok, till next time. return HTTPD_CGI_MORE; } }
int ICACHE_FLASH_ATTR settingsCGI(HttpdConnData *connData) { char buff[256]; float * r = readDHT(); float lastTemp = r[0]; float lastHum = r[1]; os_sprintf(buff, "{\"power\":\"%s\",\"mode\":\"%s\",\"temp\":\"%d\",\"fan\":\"%s\",\"swing\":\"%s\",\"dht_temp\":\"%d\",\"dht_humid\":\"%d\"}", sysCfg.power, sysCfg.mode, sysCfg.temp, sysCfg.fan, sysCfg.swing, (int)(lastTemp * 100), (int)(lastHum * 100) ); httpdStartResponse(connData, 200); httpdHeader(connData, "Content-Type", "text/html"); httpdEndHeaders(connData); httpdSend(connData, buff, -1); return HTTPD_CGI_DONE; }
//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; char buff[1024]; #ifdef GZIP_COMPRESSION const char *gzipSendResult = NULL; #endif if (connData->conn==NULL) { //Connection aborted. Clean up. espFsClose(file); return HTTPD_CGI_DONE; } if (file==NULL) { //First call to this cgi. Open the file so we can read it. file=espFsOpen(connData->url); if (file==NULL) { return HTTPD_CGI_NOTFOUND; } connData->cgiData=file; httpdStartResponse(connData, 200); httpdHeader(connData, "Content-Type", httpdGetMimetype(connData->url)); #ifdef GZIP_COMPRESSION gzipSendResult = sendGZIPEncodingIfNeeded(connData); if (gzipSendResult != NULL) { httpdEndHeaders(connData); httpdSend(connData, gzipSendResult, os_strlen(gzipSendResult)); return HTTPD_CGI_DONE; } #endif httpdHeader(connData, "Cache-Control", "max-age=3600, must-revalidate"); httpdEndHeaders(connData); return HTTPD_CGI_MORE; } len=espFsRead(file, buff, 1024); if (len>0) espconn_sent(connData->conn, (uint8 *)buff, len); if (len!=1024) { //We're done. espFsClose(file); return HTTPD_CGI_DONE; } else { //Ok, till next time. return HTTPD_CGI_MORE; } }
int ICACHE_FLASH_ATTR cgiDHT22(HttpdConnData *connData) { char buff[256]; char temp[32]; char humi[32]; httpdStartResponse(connData, 200); httpdHeader(connData, "Content-Type", "text/json"); httpdHeader(connData, "Access-Control-Allow-Origin", "*"); httpdEndHeaders(connData); dht_temp_str(temp); dht_humi_str(humi); os_sprintf(buff, "{ \n\"temperature\": \"%s\"\n , \n\"humidity\": \"%s\"\n}\n", temp, humi ); httpdSend(connData, buff, -1); return HTTPD_CGI_DONE; }
CgiStatus ICACHE_FLASH_ATTR authBasic(HttpdConnData *connData) { const char *unauthorized = "401 Unauthorized."; int no=0; int r; char hdr[(AUTH_MAX_USER_LEN+AUTH_MAX_PASS_LEN+2)*10]; char userpass[AUTH_MAX_USER_LEN+AUTH_MAX_PASS_LEN+2]; char user[AUTH_MAX_USER_LEN]; char pass[AUTH_MAX_PASS_LEN]; if(connData->isConnectionClosed) { //Connection closed. Clean up. return HTTPD_CGI_DONE; } r=httpdGetHeader(connData, "Authorization", hdr, sizeof(hdr)); if (r && strncmp(hdr, "Basic", 5)==0) { r=libesphttpd_base64_decode(strlen(hdr)-6, hdr+6, sizeof(userpass), (unsigned char *)userpass); if (r<0) r=0; //just clean out string on decode error userpass[r]=0; //zero-terminate user:pass string // printf("Auth: %s\n", userpass); while (((AuthGetUserPw)(connData->cgiArg))(connData, no, user, AUTH_MAX_USER_LEN, pass, AUTH_MAX_PASS_LEN)) { //Check user/pass against auth header if (strlen(userpass)==strlen(user)+strlen(pass)+1 && strncmp(userpass, user, strlen(user))==0 && userpass[strlen(user)]==':' && strcmp(userpass+strlen(user)+1, pass)==0) { //Authenticated. Yay! return HTTPD_CGI_AUTHENTICATED; } no++; //Not authenticated with this user/pass. Check next user/pass combo. } } //Not authenticated. Go bug user with login screen. httpdStartResponse(connData, 401); httpdHeader(connData, "Content-Type", "text/plain"); httpdHeader(connData, "WWW-Authenticate", "Basic realm=\""HTTP_AUTH_REALM"\""); httpdEndHeaders(connData); httpdSend(connData, unauthorized, -1); //Okay, all done. return HTTPD_CGI_DONE; }
int ICACHE_FLASH_ATTR cgiMenu(HttpdConnData *connData) { if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. char buff[1024]; // don't use jsonHeader so the response does get cached noCacheHeaders(connData, 200); httpdHeader(connData, "Content-Type", "application/json"); httpdEndHeaders(connData); // limit hostname to 12 chars char name[13]; os_strncpy(name, flashConfig.hostname, 12); name[12] = 0; // construct json response // limit menu dependend on menu level if( flashConfig.menu_level > 0) os_sprintf(buff, "{ " "\"menu\": [ " "\"goDMD\", \"/godmd/index.html\", " "\"Home\", \"/home.html\", " "\"WiFi Station\", \"/wifi/wifiSta.html\", " "\"WiFi Soft-AP\", \"/wifi/wifiAp.html\", " "\"µC Console\", \"/console.html\", " "\"Services\", \"/services.html\", " #ifdef MQTT "\"REST/MQTT\", \"/mqtt.html\", " #endif "\"Debug log\", \"/log.html\"," "\"Upgrade Firmware\", \"/flash.html\"," "\"Web Server\", \"/web-server.html\"" "%s" " ], " "\"version\": \"%s\", " "\"name\": \"%s\"" " }", WEB_UserPages(), esp_link_version, name); else os_sprintf(buff, "{ " "\"menu\": [ " "\"goDMD\", \"/godmd/index.html\", " "\"Home\", \"/home.html\", " "\"WiFi Station\", \"/wifi/wifiSta.html\", " "\"WiFi Soft-AP\", \"/wifi/wifiAp.html\", " "\"Upgrade Firmware\", \"/flash.html\"" "%s" " ], " "\"version\": \"%s\", " "\"name\": \"%s\"" " }", WEB_UserPages(), esp_link_version, name); httpdSend(connData, buff, -1); return HTTPD_CGI_DONE; }
//Cgi that turns the Relays on or off according to the 'relayX' param in the GET data int ICACHE_FLASH_ATTR cgiGPIO(HttpdConnData *connData) { int len; char buff[128]; int gotcmd=0; if (connData->conn==NULL) { //Connection aborted. Clean up. return HTTPD_CGI_DONE; } len=httpdFindArg(connData->getArgs, "relay1", buff, sizeof(buff)); if (len>0) { currGPIO12State=atoi(buff); ioGPIO(currGPIO12State,12); gotcmd=1; //Manually switching relays means switching the thermostat off if(sysCfg.thermostat1state!=0) { sysCfg.thermostat1state=0; } } if(gotcmd==1) { if( sysCfg.relay_latching_enable) { sysCfg.relay_1_state=currGPIO12State; CFG_Save(); } httpdRedirect(connData, "relay.tpl"); return HTTPD_CGI_DONE; } else { //with no parameters returns JSON with relay state httpdStartResponse(connData, 200); httpdHeader(connData, "Content-Type", "text/json"); httpdHeader(connData, "Access-Control-Allow-Origin", "*"); httpdEndHeaders(connData); len=os_sprintf(buff, "{\"relay1\": %d\n,\"relay1name\":\"%s\"}\n", currGPIO12State,(char *)sysCfg.relay1name ); httpdSend(connData, buff, -1); return HTTPD_CGI_DONE; } }
// Send build info int ICACHE_FLASH_ATTR cgiBuildInfo(HttpdConnData *connData) { char buff[1536]; int len; // Check if connection exists if(connData->conn==NULL) { return HTTPD_CGI_DONE; } // HTTP Header httpdStartResponse(connData, 200); httpdHeader(connData, "Content-Type", "text/plain"); httpdHeader(connData, "Pragma", "no-cache"); httpdHeader(connData, "Expires", "0"); httpdEndHeaders(connData); // AJAX data len=os_sprintf(buff, "espweather %s\nCompiled on %s, %s\n%s (GCC %s)\n", VERSTRING, __DATE__, __TIME__, HOSTSTRING, __VERSION__); httpdSend(connData, buff, len); // Return return HTTPD_CGI_DONE; }
/* cgiReadFlash */ int ICACHE_FLASH_ATTR cgiReadFlash(HttpdConnection * ptConnection) { /* initialization */ int iRet = 0; int * iFlashOffset = NULL; iFlashOffset = (int *)&ptConnection->pbCgiData; if (NULL == ptConnection->ptEspConnection) { /* connection aborted - clean up */ iRet = HTTPD_CGI_DONE; goto lblCleanup; } if (0 == *iFlashOffset) { #ifdef CGIFLASH_DEBUG os_printf("cgiReadFlash: begin flash download\n"); #endif httpdStartResponse(ptConnection, 200); httpdHeader(ptConnection, "Content-Type", "application/bin"); httpdEndHeaders(ptConnection); /* update offset */ *iFlashOffset = 0x40200000; iRet = HTTPD_CGI_MORE; goto lblCleanup; } /* send 1K of flash per call, will be called again if haven't sent 512K yet */ espconn_sent(ptConnection->ptEspConnection, (uint8 *)(*iFlashOffset), 1024); *iFlashOffset += 1024; if (*iFlashOffset >= 0x40200000 + (512 * 1024)) { iRet = HTTPD_CGI_DONE; goto lblCleanup; } else { iRet = HTTPD_CGI_MORE; goto lblCleanup; } lblCleanup: return iRet; }
int ICACHE_FLASH_ATTR cgiEnv(HttpdConnData *connData) { char buff[2048]; int len=0; httpdStartResponse(connData, 200); httpdHeader(connData, "Content-Type", "application/json"); httpdHeader(connData, "Access-Control-Allow-Origin", "*"); httpdEndHeaders(connData); if (connData->conn==NULL) { //Connection aborted. Clean up. return HTTPD_CGI_DONE; } //os_strcpy(buff, "Unknown"); //os_strcpy(temp, "N/A"); //os_strcpy(humi, "N/A"); len=httpdFindArg(connData->getArgs, "param", buff, sizeof(buff)); if (len>0) { if(os_strcmp(buff,"temp")==0) { len=os_sprintf(buff, "%d",tempF); httpdSend(connData, buff, -1); tempF = tempF - 2; hudP = hudP + 2; os_printf("\nTemp val = %d\n",tempF); } if(os_strcmp(buff,"hud")==0) { len=os_sprintf(buff, "%d",hudP); httpdSend(connData, buff, -1); hudP = hudP - 2; tempF = tempF + 2; os_printf("\nHud val = %d\n",hudP); } } return HTTPD_CGI_DONE; }
//This CGI is called from the bit of AJAX-code in wifi.tpl. It will initiate a //scan for access points and if available will return the result of an earlier scan. //The result is embedded in a bit of JSON parsed by the javascript in wifi.tpl. int ICACHE_FLASH_ATTR cgiWiFiScan(HttpdConnData *connData) { int pos=(int)connData->cgiData; int len; char buff[1024]; if (!cgiWifiAps.scanInProgress && pos!=0) { //Fill in json code for an access point if (pos-1<cgiWifiAps.noAps) { len=os_sprintf(buff, "{\"essid\": \"%s\", \"rssi\": \"%d\", \"enc\": \"%d\"}%s\n", cgiWifiAps.apData[pos-1]->ssid, cgiWifiAps.apData[pos-1]->rssi, cgiWifiAps.apData[pos-1]->enc, (pos-1==cgiWifiAps.noAps-1)?"":","); httpdSend(connData, buff, len); } pos++; if ((pos-1)>=cgiWifiAps.noAps) { len=os_sprintf(buff, "]\n}\n}\n"); httpdSend(connData, buff, len); //Also start a new scan. wifiStartScan(); return HTTPD_CGI_DONE; } else { connData->cgiData=(void*)pos; return HTTPD_CGI_MORE; } } httpdStartResponse(connData, 200); httpdHeader(connData, "Content-Type", "text/json"); httpdEndHeaders(connData); if (cgiWifiAps.scanInProgress==1) { //We're still scanning. Tell Javascript code that. len=os_sprintf(buff, "{\n \"result\": { \n\"inProgress\": \"1\"\n }\n}\n"); httpdSend(connData, buff, len); return HTTPD_CGI_DONE; } else { //We have a scan result. Pass it on. len=os_sprintf(buff, "{\n \"result\": { \n\"inProgress\": \"0\", \n\"APs\": [\n"); httpdSend(connData, buff, len); if (cgiWifiAps.apData==NULL) cgiWifiAps.noAps=0; connData->cgiData=(void *)1; return HTTPD_CGI_MORE; } }
//Cgi that reads the SPI flash. Assumes 512KByte flash. int ICACHE_FLASH_ATTR cgiReadFlash(HttpdConnData *connData) { int *pos=(int *)&connData->cgiData; if (connData->conn==NULL) { //Connection aborted. Clean up. return HTTPD_CGI_DONE; } if (*pos==0) { //os_printf("Start flash download.\n"); httpdStartResponse(connData, 200); httpdHeader(connData, "Content-Type", "application/bin"); httpdEndHeaders(connData); *pos=0x40200000; return HTTPD_CGI_MORE; } espconn_sent(connData->conn, (uint8 *)(*pos), 1024); *pos+=1024; if (*pos>=0x40200000+(512*1024)) return HTTPD_CGI_DONE; else return HTTPD_CGI_MORE; }
int ICACHE_FLASH_ATTR cgiWiFiConnStatus(HttpdConnData *connData) { char buff[1024]; int len; struct ip_info info; int st=wifi_station_get_connect_status(); httpdStartResponse(connData, 200); httpdHeader(connData, "Content-Type", "text/json"); httpdEndHeaders(connData); if (connTryStatus==CONNTRY_IDLE) { len=os_sprintf(buff, "{\n \"status\": \"idle\"\n }\n"); } else if (connTryStatus==CONNTRY_WORKING || connTryStatus==CONNTRY_SUCCESS) { if (st==STATION_GOT_IP) { wifi_get_ip_info(0, &info); len=os_sprintf(buff, "{\n \"status\": \"success\",\n \"ip\": \"%d.%d.%d.%d\" }\n", (info.ip.addr>>0)&0xff, (info.ip.addr>>8)&0xff, (info.ip.addr>>16)&0xff, (info.ip.addr>>24)&0xff); //Reset into AP-only mode sooner. os_timer_disarm(&resetTimer); os_timer_setfn(&resetTimer, resetTimerCb, NULL); os_timer_arm(&resetTimer, 1000, 0); } else {
int ICACHE_FLASH_ATTR cgiJson(HttpdConnData *connData) { struct jsontree_context *json = (struct jsontree_context *)connData->cgiData; char buf[6]; if (connData->conn == NULL) { if (json) { free(json); } return HTTPD_CGI_DONE; } currentConnData = connData; if (json == NULL) { json = malloc(sizeof(struct jsontree_context)); jsontree_setup(json, (struct jsontree_value *)connData->cgiArg, httpdPutchar); if (httpdFindArg(connData->getArgs, "id", buf, sizeof(buf)) > 0) { json->index[JSONTREE_MAX_DEPTH - 1] = atoi(buf); } else { json->index[JSONTREE_MAX_DEPTH - 1] = 65535; } httpdStartResponse(connData, 200); httpdHeader(connData, "Content-Type", "application/json"); httpdEndHeaders(connData); connData->cgiData = json; } while (jsontree_print_next(json) && json->path <= json->depth) { if (connData->priv->sendBuffLen > MAX_SENDBUFF_LEN - (MAX_SENDBUFF_LEN / 4)) { return HTTPD_CGI_MORE; } } free(json); return HTTPD_CGI_DONE; }
int ICACHE_FLASH_ATTR cgiBms(HttpdConnData *connData) /* by JJC */ { int len_tot; char buff[1024]; char single_val_buf[8]; if (connData->conn==NULL) { //Connection aborted. Clean up. return HTTPD_CGI_DONE; } httpdStartResponse(connData, 200); httpdHeader(connData, "Content-Type", "text/json"); httpdEndHeaders(connData); /* new JSON structure: * { "bms_values" : [ 5, 6, 7, 8, 999 ] } */ len_tot = sprintf(buff, "{\"bms_values\":["); int i, numel; numel = bms_numel_get(); for(i = 0; i < numel - 1; i++) { len_tot += sprintf(single_val_buf, "%d,", bms_value_get(i)); strcat(buff, single_val_buf); } if(numel > 1) { // no comma after printed number for last element. len_tot += sprintf(single_val_buf, "%d", bms_value_get(numel-1)); strcat(buff, single_val_buf); } len_tot += sprintf(single_val_buf, "]}"); strcat(buff, single_val_buf); httpdSend(connData, buff, len_tot); return HTTPD_CGI_DONE; }
// CGI to set settings int ICACHE_FLASH_ATTR saveCGI(HttpdConnData *connData) { int len; char buff[10]; //char bin[10]; if (connData->conn == NULL) { //Connection aborted. Clean up. return HTTPD_CGI_DONE; } len = httpdFindArg(connData->getArgs, "power", buff, sizeof(buff)); if (len != 0) ac_set_power(buff); len = httpdFindArg(connData->getArgs, "mode", buff, sizeof(buff)); if (len != 0) ac_set_mode(buff); len = httpdFindArg(connData->getArgs, "temp", buff, sizeof(buff)); if (len != 0) ac_set_temp(buff); len = httpdFindArg(connData->getArgs, "fan", buff, sizeof(buff)); if (len != 0) ac_set_fan(buff); len = httpdFindArg(connData->getArgs, "swing", buff, sizeof(buff)); if (len != 0) ac_set_swing(buff); ir_send(); mqttPublishSettings(0); CFG_Save(); httpdStartResponse(connData, 200); httpdHeader(connData, "Content-Type", "text/html"); httpdEndHeaders(connData); os_strcpy(buff, "OK"); httpdSend(connData, buff, -1); return HTTPD_CGI_DONE; }
//Cgi that turns the LED on or off according to the 'led' param in the POST data int ICACHE_FLASH_ATTR cgiButton(HttpdConnData *connData) { int len; char buff[1024]; if (connData->conn==NULL) { //Connection aborted. Clean up. return HTTPD_CGI_DONE; } httpdStartResponse(connData, 200); httpdHeader(connData, "Content-Type", "application/json"); httpdEndHeaders(connData); /* This will return JSON: * {"button": * {"status":"on"} * } */ len = os_sprintf(buff, "{\n \"button\": { \n\"status\":\"%s\"\n}\n}\n", (GPIO_INPUT_GET(0)) ? "off" : "on"); espconn_sent(connData->conn, (uint8 *)buff, len); return HTTPD_CGI_DONE; }
void ICACHE_FLASH_ATTR jsonHeader(HttpdConnData *connData, int code) { noCacheHeaders(connData, code); httpdHeader(connData, "Content-Type", "application/json"); httpdEndHeaders(connData); }
void ICACHE_FLASH_ATTR noCacheHeaders(HttpdConnData *connData, int code) { httpdStartResponse(connData, code); httpdHeader(connData, "Cache-Control", "no-cache, no-store, must-revalidate"); httpdHeader(connData, "Pragma", "no-cache"); httpdHeader(connData, "Expires", "0"); }
int ICACHE_FLASH_ATTR cgiApi(HttpdConnData *connData) { struct ApiData *api = (struct ApiData *)connData->cgiPrivData; int nbytes, status; char type; if (connData->conn == NULL) { goto done; } if (connData->requestType != HTTPD_METHOD_POST) { httpdStartResponse(connData, 501); httpdHeader(connData, "Content-Type", "text/html"); httpdEndHeaders(connData); return HTTPD_CGI_DONE; } if (connData->post->received <= MAX_POST) { api = malloc(sizeof(struct ApiData)); jsonparse_setup(&api->state, api->buff, MAX_POST); api->buffLen = 0; api->depth = 0; api->status = API_OK; connData->cgiPrivData = api; } if (api->status < API_OK) { goto finish; } while (true) { nbytes = API_MAX_BUFF - api->buffLen - 1; nbytes = connData->post->buffLen < nbytes ? connData->post->buffLen : nbytes; memcpy(&api->buff[api->buffLen], connData->post->buff, nbytes); api->buffLen += nbytes; memmove(connData->post->buff, &connData->post->buff[nbytes], connData->post->buffLen - nbytes); connData->post->buffLen -= nbytes; if (connData->post->buffLen == 0) { if (connData->post->received < connData->post->len) { return HTTPD_CGI_MORE; } break; } while (api->state.pos < API_MIN_CHUNK) { type = jsonparse_next(&api->state); if (type == ',') { /* do nothing */ } else if (type == '[') { api->depth = api->state.depth; } else { api->status = API_ERROR_PARSE; goto finish; } if ((status = api_parse(&api->state)) != API_OK) { api->status = status; if (status < API_OK) { goto finish; } } while (api->state.depth > api->depth) { if (!jsonparse_next(&api->state)) { api->status = API_ERROR_PARSE; goto finish; } } } memmove(api->buff, &api->buff[api->state.pos], api->buffLen - api->state.pos); api->buffLen -= api->state.pos; api->state.pos = 0; } api->buff[api->buffLen] = '\0'; api->state.len = api->buffLen; while (true) { type = jsonparse_next(&api->state); if (type == ',') { /* do nothing */ } else if (type == '[') { api->depth = api->state.depth; } else { if (api->state.error != JSON_ERROR_OK) { api->status = API_ERROR_PARSE; } goto finish; } if ((status = api_parse(&api->state)) != API_OK) { api->status = status; if (status < API_OK) { goto finish; } } while (api->state.depth > api->depth) { if (!jsonparse_next(&api->state)) { api->status = API_ERROR_PARSE; goto finish; } } } finish: if (connData->post->received < connData->post->len) { return HTTPD_CGI_MORE; } if (api->status < API_OK) { httpdStartResponse(connData, 500); httpdHeader(connData, "Content-Type", "text/html"); httpdEndHeaders(connData); goto done; } httpdStartResponse(connData, 200); httpdHeader(connData, "Content-Type", "application/json"); httpdEndHeaders(connData); httpdSend(connData, api->status == API_OK ? "true" : "false", -1); if (api_update) { api_update = false; master_update(true); } if (status_dirty) { status_save(); } done: free(api); connData->cgiPrivData = NULL; return HTTPD_CGI_DONE; }
int ICACHE_FLASH_ATTR cgiEspFsTemplate(HttpdConnData *connData) { TplData *tpd=connData->cgiData; int len; int x, sp=0; char *e=NULL; char buff[1025]; if (connData->conn==NULL) { //Connection aborted. Clean up. ((TplCallback)(connData->cgiArg))(connData, NULL, &tpd->tplArg); espFsClose(tpd->file); os_free(tpd); return HTTPD_CGI_DONE; } if (tpd==NULL) { //First call to this cgi. Open the file so we can read it. tpd=(TplData *)os_malloc(sizeof(TplData)); tpd->file=espFsOpen(connData->url); tpd->tplArg=NULL; tpd->tokenPos=-1; if (tpd->file==NULL) { return HTTPD_CGI_NOTFOUND; } connData->cgiData=tpd; httpdStartResponse(connData, 200); httpdHeader(connData, "Content-Type", httpdGetMimetype(connData->url)); httpdEndHeaders(connData); return HTTPD_CGI_MORE; } len=espFsRead(tpd->file, buff, 1024); if (len>0) { sp=0; e=buff; for (x=0; x<len; x++) { if (tpd->tokenPos==-1) { //Inside ordinary text. if (buff[x]=='%') { //Send raw data up to now if (sp!=0) espconn_sent(connData->conn, (uint8 *)e, sp); sp=0; //Go collect token chars. tpd->tokenPos=0; } else { sp++; } } else { if (buff[x]=='%') { tpd->token[tpd->tokenPos++]=0; //zero-terminate token ((TplCallback)(connData->cgiArg))(connData, tpd->token, &tpd->tplArg); //Go collect normal chars again. e=&buff[x+1]; tpd->tokenPos=-1; } else { if (tpd->tokenPos<(sizeof(tpd->token)-1)) tpd->token[tpd->tokenPos++]=buff[x]; } } } } //Send remaining bit. if (sp!=0) espconn_sent(connData->conn, (uint8 *)e, sp); if (len!=1024) { //We're done. ((TplCallback)(connData->cgiArg))(connData, NULL, &tpd->tplArg); espFsClose(tpd->file); return HTTPD_CGI_DONE; } else { //Ok, till next time. return HTTPD_CGI_MORE; } }
//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; char buff[1024]; char acceptEncodingBuffer[64]; int isGzip; if (connData->conn==NULL) { //Connection aborted. Clean up. espFsClose(file); return HTTPD_CGI_DONE; } if (file==NULL) { //First call to this cgi. Open the file so we can read it. file=espFsOpen(connData->url); if (file==NULL) { return HTTPD_CGI_NOTFOUND; } // The gzip checking code is intentionally without #ifdefs because checking // for FLAG_GZIP (which indicates gzip compressed file) is very easy, doesn't // mean additional overhead and is actually safer to be on at all times. // If there are no gzipped files in the image, the code bellow will not cause any harm. // Check if requested file was GZIP compressed isGzip = espFsFlags(file) & FLAG_GZIP; if (isGzip) { // Check the browser's "Accept-Encoding" header. If the client does not // advertise that he accepts GZIP send a warning message (telnet users for e.g.) httpdGetHeader(connData, "Accept-Encoding", acceptEncodingBuffer, 64); if (os_strstr(acceptEncodingBuffer, "gzip") == NULL) { //No Accept-Encoding: gzip header present httpdSend(connData, gzipNonSupportedMessage, -1); espFsClose(file); return HTTPD_CGI_DONE; } } connData->cgiData=file; httpdStartResponse(connData, 200); httpdHeader(connData, "Content-Type", httpdGetMimetype(connData->url)); if (isGzip) { httpdHeader(connData, "Content-Encoding", "gzip"); } httpdHeader(connData, "Cache-Control", "max-age=3600, must-revalidate"); httpdEndHeaders(connData); return HTTPD_CGI_MORE; } len=espFsRead(file, buff, 1024); if (len>0) espconn_sent(connData->conn, (uint8 *)buff, len); if (len!=1024) { //We're done. espFsClose(file); return HTTPD_CGI_DONE; } else { //Ok, till next time. return HTTPD_CGI_MORE; } }
int ICACHE_FLASH_ATTR cgiEspFsTemplate(HttpdConnData *connData) { TplData *tpd=connData->cgiData; int len; int x, sp=0; char *e=NULL; char buff[1025]; if (connData->conn==NULL) { //Connection aborted. Clean up. ((TplCallback)(connData->cgiArg))(connData, NULL, &tpd->tplArg); espFsClose(tpd->file); os_free(tpd); return HTTPD_CGI_DONE; } if (tpd==NULL) { //First call to this cgi. Open the file so we can read it. tpd=(TplData *)os_malloc(sizeof(TplData)); tpd->file=espFsOpen(connData->url); tpd->tplArg=NULL; tpd->tokenPos=-1; if (tpd->file==NULL) { espFsClose(tpd->file); os_free(tpd); return HTTPD_CGI_NOTFOUND; } if (espFsFlags(tpd->file) & FLAG_GZIP) { debug("cgiEspFsTemplate: Trying to use gzip-compressed file %s as template!\n", connData->url); espFsClose(tpd->file); os_free(tpd); return HTTPD_CGI_NOTFOUND; } connData->cgiData=tpd; httpdStartResponse(connData, 200); httpdHeader(connData, "Content-Type", httpdGetMimetype(connData->url)); httpdEndHeaders(connData); return HTTPD_CGI_MORE; } len=espFsRead(tpd->file, buff, 1024); if (len>0) { sp=0; e=buff; for (x=0; x<len; x++) { if (tpd->tokenPos==-1) { //Inside ordinary text. if (buff[x]=='%') { //Send raw data up to now if (sp!=0) httpdSend(connData, e, sp); sp=0; //Go collect token chars. tpd->tokenPos=0; } else { sp++; } } else { if (buff[x]=='%') { if (tpd->tokenPos==0) { //This is the second % of a %% escape string. //Send a single % and resume with the normal program flow. httpdSend(connData, "%", 1); } else { //This is an actual token. tpd->token[tpd->tokenPos++]=0; //zero-terminate token ((TplCallback)(connData->cgiArg))(connData, tpd->token, &tpd->tplArg); } //Go collect normal chars again. e=&buff[x+1]; tpd->tokenPos=-1; } else { if (tpd->tokenPos<(sizeof(tpd->token)-1)) tpd->token[tpd->tokenPos++]=buff[x]; } } } } //Send remaining bit. if (sp!=0) httpdSend(connData, e, sp); if (len!=1024) { //We're done. ((TplCallback)(connData->cgiArg))(connData, NULL, &tpd->tplArg); espFsClose(tpd->file); os_free(tpd); return HTTPD_CGI_DONE; } else { //Ok, till next time. return HTTPD_CGI_MORE; } }