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 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; }
//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; } }
/* 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; }
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; }
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; }
void ICACHE_FLASH_ATTR httpdSendResponse(HttpdConnData *connData, int code, char *message, int len) { char sendBuff[MAX_SENDBUFF_LEN]; httpdSetSendBuffer(connData, sendBuff, sizeof(sendBuff)); httpdStartResponse(connData, code); httpdEndHeaders(connData); httpdSend(connData, message, len); httpdFlushSendBuffer(connData); httpdCgiIsDone(connData); }
int ICACHE_FLASH_ATTR cgiNFCSet(HttpdConnData *connData) { if (connData->conn==NULL) return HTTPD_CGI_DONE; // handle NFC server settings int8_t nfc_server = 0; // accumulator for changes/errors nfc_server |= getStringArg(connData, "nfc-url", flashConfig.nfc_url, sizeof(flashConfig.nfc_url)); if (nfc_server < 0) return HTTPD_CGI_DONE; nfc_server |= getStringArg(connData, "nfc-device-id", flashConfig.nfc_device_id, sizeof(flashConfig.nfc_device_id)); if (nfc_server < 0) return HTTPD_CGI_DONE; nfc_server |= getStringArg(connData, "nfc-device-secret", flashConfig.nfc_device_secret, sizeof(flashConfig.nfc_device_secret)); if (nfc_server < 0) return HTTPD_CGI_DONE; char buff[16]; // handle nfc counter if (httpdFindArg(connData->getArgs, "nfc-counter", buff, sizeof(buff)) > 0) { uint32_t counter = atoi(buff); if (counter > 0 && counter < 4294967295) { flashConfig.nfc_counter = counter; nfc_server |= 1; } else { errorResponse(connData, 400, "Invalid NFC counter!"); return HTTPD_CGI_DONE; } } DBG("Saving config\n"); if (configSave()) { httpdStartResponse(connData, 200); httpdEndHeaders(connData); } else { httpdStartResponse(connData, 500); httpdEndHeaders(connData); httpdSend(connData, "Failed to save config", -1); } return HTTPD_CGI_DONE; }
// Cgi to change choice of pin assignments int ICACHE_FLASH_ATTR cgiTcpSet(HttpdConnData *connData) { if (connData->conn==NULL) return HTTPD_CGI_DONE; // Handle tcp_enable flag char buff[128]; int len = httpdFindArg(connData->getArgs, "tcp_enable", buff, sizeof(buff)); if (len <= 0) { jsonHeader(connData, 400); return HTTPD_CGI_DONE; } flashConfig.tcp_enable = os_strcmp(buff, "true") == 0; // Handle rssi_enable flag len = httpdFindArg(connData->getArgs, "rssi_enable", buff, sizeof(buff)); if (len <= 0) { jsonHeader(connData, 400); return HTTPD_CGI_DONE; } flashConfig.rssi_enable = os_strcmp(buff, "true") == 0; // Handle api_key flag len = httpdFindArg(connData->getArgs, "api_key", buff, sizeof(buff)); if (len < 0) { jsonHeader(connData, 400); return HTTPD_CGI_DONE; } buff[sizeof(flashConfig.api_key)-1] = 0; // ensure we don't get an overrun os_strcpy(flashConfig.api_key, buff); if (configSave()) { httpdStartResponse(connData, 200); httpdEndHeaders(connData); } else { httpdStartResponse(connData, 500); httpdEndHeaders(connData); httpdSend(connData, "Failed to save config", -1); } 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; }
// 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 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; } }
// Handle request to reboot into the new firmware int ICACHE_FLASH_ATTR cgiRebootFirmware(HttpdConnData *connData) { if (connData->conn==NULL) { //Connection aborted. Clean up. return HTTPD_CGI_DONE; } // TODO: sanity-check that the 'next' partition actually contains something that looks like // valid firmware // This should probably be forked into a separate task that waits a second to let the // current HTTP request finish... system_upgrade_flag_set(UPGRADE_FLAG_FINISH); system_upgrade_reboot(); httpdStartResponse(connData, 200); httpdEndHeaders(connData); return HTTPD_CGI_DONE; }
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; }
//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; }
//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; } }
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 {
// 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; }
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; }
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; }
// Cgi to change choice of pin assignments int ICACHE_FLASH_ATTR cgiPinsSet(HttpdConnData *connData) { if (connData->conn==NULL) { return HTTPD_CGI_DONE; // Connection aborted } int8_t ok = 0; int8_t reset, isp, conn, ser; bool swap, rxpup; ok |= getInt8Arg(connData, "reset", &reset); ok |= getInt8Arg(connData, "isp", &isp); ok |= getInt8Arg(connData, "conn", &conn); ok |= getInt8Arg(connData, "ser", &ser); ok |= getBoolArg(connData, "swap", &swap); ok |= getBoolArg(connData, "rxpup", &rxpup); if (ok < 0) return HTTPD_CGI_DONE; char *coll; if (ok > 0) { // check whether two pins collide uint16_t pins = 0; if (reset >= 0) pins = 1 << reset; if (isp >= 0) { if (pins & (1<<isp)) { coll = "ISP/Flash"; goto collision; } pins |= 1 << isp; } if (conn >= 0) { if (pins & (1<<conn)) { coll = "Conn LED"; goto collision; } pins |= 1 << conn; } if (ser >= 0) { if (pins & (1<<ser)) { coll = "Serial LED"; goto collision; } pins |= 1 << ser; } if (swap) { if (pins & (1<<15)) { coll = "Uart TX"; goto collision; } if (pins & (1<<13)) { coll = "Uart RX"; goto collision; } } else { if (pins & (1<<1)) { coll = "Uart TX"; goto collision; } if (pins & (1<<3)) { coll = "Uart RX"; goto collision; } } // we're good, set flashconfig flashConfig.reset_pin = reset; flashConfig.isp_pin = isp; flashConfig.conn_led_pin = conn; flashConfig.ser_led_pin = ser; flashConfig.swap_uart = swap; flashConfig.rx_pullup = rxpup; os_printf("Pins changed: reset=%d isp=%d conn=%d ser=%d swap=%d rx-pup=%d\n", reset, isp, conn, ser, swap, rxpup); // apply the changes serbridgeInitPins(); serledInit(); statusInit(); // save to flash if (configSave()) { httpdStartResponse(connData, 204); httpdEndHeaders(connData); } else { httpdStartResponse(connData, 500); httpdEndHeaders(connData); httpdSend(connData, "Failed to save config", -1); } } return HTTPD_CGI_DONE; collision: { char buff[128]; os_sprintf(buff, "Pin assignment for %s collides with another assignment", coll); errorResponse(connData, 400, buff); 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) { 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; } }
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"); }
//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; } }