WebResponse WebRequest::Post() { #ifndef EMSCRIPTEN #ifdef USE_CURL if (m_cookies.GetEncoded().length() != 0) m_session.SetCookies(m_cookies); if (!m_header.empty()) m_session.SetHeader(m_header); if (!m_parameters.content.empty()) m_session.SetParameters(m_parameters); if (!m_payload.content.empty()) m_session.SetPayload(m_payload); if (m_multipart.parts.size() != 0) m_session.SetMultipart(m_multipart); // response auto resp = m_session.Post(); //for (auto &it : resp.header) m_response.header[it.first] = it.second; //for (auto &it : resp.cookies) m_response.cookies[it.first] = it.second; m_response.elapsed = resp.elapsed; m_response.error = (WebErrorCode) (int) resp.error.code; m_response.status_code = resp.status_code; m_response.text = resp.text; m_response.url = resp.url; return m_response; #endif #endif return WebResponse(); }
void processHTTP() { bIncoming=true; timeout=millis(); while (bIncoming) { if (millis()-timeout>100) { bIncoming=false; //for (int a=0;a<32;a++) pushbuffer(0); } if (WIFI_SERIAL.available()>0) { pushbuffer(WIFI_SERIAL.read()); timeout=millis(); } } if (authStr[0]==0) auth=true; if (auth) { auth=false; switch ( reqtype ) { case REQ_ROOT: { WebResponse(SERVER_DEFAULT, sizeof(SERVER_DEFAULT) - 1); break; } // REQ_ROOT case REQ_WIFI: { WebResponse(SERVER_RA, sizeof(SERVER_RA) - 1); break; } // REQ_WIFI case REQ_RELAY: { if (weboption<10) break; byte o_relay=weboption/10; byte o_type=weboption%10; if (o_type==0) // Turn port off { if ( o_relay < 9 ) { bitClear(ReefAngel.Relay.RelayMaskOn,o_relay-1); bitClear(ReefAngel.Relay.RelayMaskOff,o_relay-1); } #ifdef RelayExp if ( (o_relay > 10) && (o_relay < 89) ) { byte EID = byte(o_relay/10); bitClear(ReefAngel.Relay.RelayMaskOnE[EID-1],(o_relay%10)-1); bitClear(ReefAngel.Relay.RelayMaskOffE[EID-1],(o_relay%10)-1); } #endif // RelayExp } else if (o_type==1) // Turn port on { if ( o_relay < 9 ) { bitSet(ReefAngel.Relay.RelayMaskOn,o_relay-1); bitSet(ReefAngel.Relay.RelayMaskOff,o_relay-1); } #ifdef RelayExp if ( (o_relay > 10) && (o_relay < 89) ) { byte EID = byte(o_relay/10); bitSet(ReefAngel.Relay.RelayMaskOnE[EID-1],(o_relay%10)-1); bitSet(ReefAngel.Relay.RelayMaskOffE[EID-1],(o_relay%10)-1); } #endif // RelayExp } else if (o_type==2) // Set port back to Auto { if ( o_relay < 9 ) { bitClear(ReefAngel.Relay.RelayMaskOn,o_relay-1); bitSet(ReefAngel.Relay.RelayMaskOff,o_relay-1); } #ifdef RelayExp if ( (o_relay > 10) && (o_relay < 89) ) { byte EID = byte(o_relay/10); bitClear(ReefAngel.Relay.RelayMaskOnE[EID-1],(o_relay%10)-1); bitSet(ReefAngel.Relay.RelayMaskOffE[EID-1],(o_relay%10)-1); } #endif // RelayExp } ReefAngel.Relay.Write(); // Force update of the Portal after relay change // ReefAngel.Timer[PORTAL_TIMER].ForceTrigger(); } case REQ_RA_STATUS: case REQ_R_STATUS: { char temp[6]; int s=132; //<RA><T1></T1><T2></T2><T3></T3><PH></PH><R></R><RON></RON><ROFF></ROFF><ATOLOW></ATOLOW><ATOHIGH></ATOHIGH><EM></EM><REM></REM></RA> s += intlength(ReefAngel.Params.Temp[T1_PROBE]); s += intlength(ReefAngel.Params.Temp[T2_PROBE]); s += intlength(ReefAngel.Params.Temp[T3_PROBE]); s += intlength(ReefAngel.Params.PH); s += intlength(ReefAngel.EM); s += intlength(ReefAngel.REM); s += 2; // one digit for each ATO s += intlength(ReefAngel.Relay.RelayData); s += intlength(ReefAngel.Relay.RelayMaskOn); s += intlength(ReefAngel.Relay.RelayMaskOff); #ifdef DisplayLEDPWM s += 26; //<PWMA></PWMA><PWMD></PWMD> s += intlength(ReefAngel.PWM.GetDaylightValue()); s += intlength(ReefAngel.PWM.GetActinicValue()); #endif // DisplayLEDPWM #ifdef RelayExp s += 296; //<R0></R0><RON0></RON0><ROFF0></ROFF0><R1></R1><RON1></RON1><ROFF1></ROFF1><R2></R2><RON2></RON2><ROFF2></ROFF2><R3></R3><RON3></RON3><ROFF3></ROFF3><R4></R4><RON4></RON4><ROFF4></ROFF4><R5></R5><RON5></RON5><ROFF5></ROFF5><R6></R6><RON6></RON6><ROFF6></ROFF6><R7></R7><RON7></RON7><ROFF7></ROFF7> for ( byte EID = 0; EID < MAX_RELAY_EXPANSION_MODULES; EID++ ) { s += intlength(ReefAngel.Relay.RelayDataE[EID]); s += intlength(ReefAngel.Relay.RelayMaskOnE[EID]); s += intlength(ReefAngel.Relay.RelayMaskOffE[EID]); } #endif // RelayExp #ifdef PWMEXPANSION s += 90; //<PWME0></PWME0><PWME1></PWME1><PWME2></PWME2><PWME3></PWME3><PWME4></PWME4><PWME5></PWME5> for ( byte EID = 0; EID < PWM_EXPANSION_CHANNELS; EID++ ) s += intlength(ReefAngel.PWM.ExpansionChannel[EID]); #endif // PWMEXPANSION #ifdef RFEXPANSION s += 101; //<RFM></RFM><RFS></RFS><RFD></RFD><RFW></RFW><RFRB></RFRB><RFR></RFR><RFG></RFG><RFB></RFB><RFI></RFI> for ( byte EID = 0; EID < RF_CHANNELS; EID++ ) s += intlength(ReefAngel.RF.GetChannel(EID)); s += intlength(ReefAngel.RF.Mode); s += intlength(ReefAngel.RF.Speed); s += intlength(ReefAngel.RF.Duration); #endif // RFEXPANSION #ifdef AI_LED s += 35; //<AIW></AIW><AIB></AIB><AIRB></AIRB> for ( byte EID = 0; EID < AI_CHANNELS; EID++ ) s += intlength(ReefAngel.AI.GetChannel(EID)); #endif // AI_LED #ifdef SALINITYEXPANSION s += 11; //<SAL></SAL> s += intlength(ReefAngel.Params.Salinity); #endif // SALINITYEXPANSION #ifdef ORPEXPANSION s += 11; //<ORP></ORP> s += intlength(ReefAngel.Params.ORP); #endif // ORPEXPANSION #ifdef PHEXPANSION s += 11; //<PHE></PHE> s += intlength(ReefAngel.Params.PHExp); #endif // PHEXPANSION #ifdef WATERLEVELEXPANSION s += 9; //<WL></WL> s += intlength(ReefAngel.WaterLevel.GetLevel()); #endif // WATERLEVELEXPANSION #ifdef IOEXPANSION s += 9; //<IO></IO> s += intlength(ReefAngel.IO.GetChannel()); #endif // IOEXPANSION #ifdef CUSTOM_VARIABLES s += 72; //<C0></C0><C1></C1><C2></C2><C3></C3><C4></C4><C5></C5><C6></C6><C7></C7> for ( byte EID = 0; EID < 8; EID++ ) s += intlength(ReefAngel.CustomVar[EID]); #endif // CUSTOM_VARIABLES #ifdef ENABLE_ATO_LOGGING if ( reqtype == REQ_RA_STATUS ) { // we send all the ato logging events both high & low /* The XML code will be like this. This is 1 event. There are 8 events total (4 low / 4 high). <AL#ON>DWORD</AL#ON> <AL#OFF>DWORD</AL#OFF> Each event is 40 bytes (32 bytes for text, 8 bytes for dword values total) */ s += 320; } #endif // ENABLE_ATO_LOGGING PrintHeader(s,1); #ifdef ENABLE_ATO_LOGGING if ( reqtype == REQ_RA_STATUS ) SendXMLData(true); else SendXMLData(); #else SendXMLData(); #endif // ENABLE_ATO_LOGGING break; } // REQ_RELAY case REQ_M_BYTE: case REQ_M_INT: { int s; // if memory location is > 800 it means app is trying to pull/set old memory location. // we decrease 600 to start using new memory map // this is a temporary solution until we get all apps to point to new memory location int newweboption2=weboption2; if ( weboption2>=800 ) newweboption2-=600; // weboption2 is location // weboption is value if ( bHasSecondValue && (weboption2 >= 0) ) { // if we have a second value, we write the value to memory if ( reqtype == REQ_M_BYTE ) InternalMemory.write(newweboption2, weboption); else InternalMemory.write_int(newweboption2, weboption); // check if we have to reload any timers if ( weboption2 == Mem_I_FeedingTimer ) { ReefAngel.Timer[FEEDING_TIMER].SetInterval(weboption); } else if ( weboption2 == Mem_I_LCDTimer ) { ReefAngel.Timer[LCD_TIMER].SetInterval(weboption); } //#ifdef DisplayLEDPWM // else if ( weboption2 == Mem_B_LEDPWMActinic ) // { // ReefAngel.PWM.SetActinic(weboption); // // Force update of the Portal after change // ReefAngel.Timer[PORTAL_TIMER].ForceTrigger(); // } // else if ( weboption2 == Mem_B_LEDPWMDaylight ) // { // ReefAngel.PWM.SetDaylight(weboption); // // Force update of the Portal after change // ReefAngel.Timer[PORTAL_TIMER].ForceTrigger(); // } //#endif // DisplayLEDPWM s = 9; // <M>OK</M> // add in the location, twice s += (intlength(weboption2)*2); PrintHeader(s,1); PROGMEMprint(XML_M_OPEN); WIFI_SERIAL.print(weboption2, DEC); PROGMEMprint(XML_CLOSE_TAG); PROGMEMprint(XML_OK); PROGMEMprint(XML_M_CLOSE); WIFI_SERIAL.print(weboption2, DEC); PROGMEMprint(XML_CLOSE_TAG); } else if ( !bHasSecondValue && (weboption2 >= 0) && (bCommaCount==0) ) { // get the length first s = 7; // <M></M> // length of the memory location, twice since it's in the open & close tag s += (intlength(weboption2)*2); // length of the value from memory if ( reqtype == REQ_M_BYTE ) s += intlength(InternalMemory.read(newweboption2)); else s += intlength(InternalMemory.read_int(newweboption2)); PrintHeader(s,1); // no second value and no comma, so we read the value from memory PROGMEMprint(XML_M_OPEN); WIFI_SERIAL.print(weboption2, DEC); PROGMEMprint(XML_CLOSE_TAG); if ( reqtype == REQ_M_BYTE ) WIFI_SERIAL.print(InternalMemory.read(newweboption2),DEC); else WIFI_SERIAL.print(InternalMemory.read_int(newweboption2),DEC); PROGMEMprint(XML_M_CLOSE); WIFI_SERIAL.print(weboption2, DEC); PROGMEMprint(XML_CLOSE_TAG); } else { s = 10; // <M>ERR</M> PrintHeader(s,1); PROGMEMprint(XML_M_OPEN); PROGMEMprint(XML_CLOSE_TAG); PROGMEMprint(XML_ERR); PROGMEMprint(XML_M_CLOSE); PROGMEMprint(XML_CLOSE_TAG); } break; } // REQ_M_BYTE || REQ_M_INT case REQ_M_RAW: { int s = 11; // start with the base size of the mem tags s += (VarsEnd-VarsStart)*2; PrintHeader(s,1); PROGMEMprint(XML_MEM_OPEN); byte m; for ( int x = VarsStart; x < VarsEnd; x++ ) { m=InternalMemory.read(x); if (m<16) WIFI_SERIAL.print("0"); WIFI_SERIAL.print(m,HEX); } // for x PROGMEMprint(XML_MEM_CLOSE); break; } // REQ_M_RAW case REQ_M_ALL: { // TODO update all memory function //int s = 123; // start with the base size of the headers plus the mem tags int s = 11; // start with the base size of the mem tags /* Send all the data to the client requesting it. The values will be sent as follows: - wrapped in <MEM></MEM> XML tags - individual memory values wrapped in their location XML tags Memory 800, value 20 - <M800>20</M800> An example would be: <MEM> <M800>20</M800> <M801>0</M801> <M802>16</M802> ... </MEM> */ uint8_t offsets[] = {1,1,1,1,1,1,1,1,2,2,1,1,2,2,2,1,1,2,2,2,2,1,2,2,1,1,1,1,1,1,1,1,2,2}; uint8_t num = sizeof(offsets)/sizeof(uint8_t); // add in the memory location sizes, 13 bytes if the memory location is 3 digits <MXXX></MXXX> s += num*13; uint16_t count = VarsStart; uint8_t x; for ( x = 0; x < num; x++ ) { if ( offsets[x] == 1 ) s += intlength(InternalMemory.read(count)); else s += intlength(InternalMemory.read_int(count)); count += offsets[x]; } // for x PrintHeader(s,1); PROGMEMprint(XML_MEM_OPEN); /* Loop through all the memory locations starting at VarsStart Check the offset for each location to tell us how many bytes to read and how much to increment the memory locations. Currently there are only 1 and 2 byte locations, so when we check we just check for 1 and read a byte, otherwise we read 2 bytes (an int) Then we increment the memory position by the offset. We could be thrown off if somebody accidentally put a value larger than 2 in the offset array */ for ( x = 0, count = VarsStart; x < num; x++ ) { PROGMEMprint(XML_M_OPEN); WIFI_SERIAL.print(count+600,DEC); // 600 was added as temp fix - issue #26 PROGMEMprint(XML_CLOSE_TAG); if ( offsets[x] == 1 ) WIFI_SERIAL.print(InternalMemory.read(count),DEC); else WIFI_SERIAL.print(InternalMemory.read_int(count),DEC); PROGMEMprint(XML_M_CLOSE); WIFI_SERIAL.print(count+600,DEC); // 600 was added as temp fix - issue #26 PROGMEMprint(XML_CLOSE_TAG); count += offsets[x]; } // for x PROGMEMprint(XML_MEM_CLOSE); break; } // REQ_M_ALL case REQ_VERSION: { int s = 7; s += strlen(ReefAngel_Version); PrintHeader(s,1); WIFI_SERIAL.print("<V>"ReefAngel_Version"</V>"); break; } // REQ_VERSION case REQ_DATE: { uint8_t s = 10; uint8_t hr, min, mon, mday; if ( weboption > -1 ) { /* Numbers must be formatted as follows, add leading space if a single digit weboption contains YY (years since 2000) weboption2 contains HHMM weboption3 contains MMDD */ hr = weboption2 / 100; min = weboption2 % 100; mon = weboption3 / 100; mday = weboption3 % 100; /* Simple sanity checks. Ensure that the values are within "normal" ranges. This will obviously fail if somebody tries to set the 30th day of February or with the months that only have 30 days. We will rely on the client sending the request to ensure the date is in proper range. We will just check for the simple checks. */ if ( ( hr > 23 || hr < 0 ) || ( min > 59 || min < 0 ) || ( mon > 12 || mon < 1 ) || ( mday > 31 || mday < 1 ) ) { weboption = -1; } else { s--; } } else if ( weboption == -2 ) { // sending controller date/time // 51 = rest of xml tags // 12 = data being sent (already have 3 extra in s) // 7 = base xml tags (open & close d) s += 60; } PrintHeader(s,1); PROGMEMprint(XML_DATE_OPEN); if ( weboption == -1 ) { PROGMEMprint(XML_ERR); } else if ( weboption == -2 ) { time_t n = now(); WIFI_SERIAL.print("<HR>"); WIFI_SERIAL.print(hour(n), DEC); WIFI_SERIAL.print("</HR><MIN>"); WIFI_SERIAL.print(minute(n), DEC); WIFI_SERIAL.print("</MIN><MON>"); WIFI_SERIAL.print(month(n), DEC); WIFI_SERIAL.print("</MON><DAY>"); WIFI_SERIAL.print(day(n), DEC); WIFI_SERIAL.print("</DAY><YR>"); WIFI_SERIAL.print(year(n), DEC); WIFI_SERIAL.print("</YR>"); } else { PROGMEMprint(XML_OK); setTime(hr, min, 0, mday, mon, weboption); now(); RTC.set(now()); } PROGMEMprint(XML_DATE_CLOSE); break; } // REQ_DATE case REQ_HTTP: { // When using the WebBanner and sending to reefangel.com, ra.com replies back to us that the command was successful // If we process that command (which we will), we end up not recognizing it and send off an uknown request response // back to the server. Then the server will send another response back to us and we end up getting in an almost // infinite loop. We will mark it as an HTTP request and ignore it break; } case REQ_FEEDING: { // Start up the feeding mode only if we are on the home screen or from Water change if ( ReefAngel.DisplayedMenu == DEFAULT_MENU || ReefAngel.DisplayedMenu==WATERCHANGE_MODE ) { //ReefAngel.ClearScreen(DefaultBGColor); ReefAngel.FeedingModeStart(); ModeResponse(true); } else { ModeResponse(false); } break; } case REQ_WATER: { // Start up the water change mode only if we are on the home screen if ( ReefAngel.DisplayedMenu == DEFAULT_MENU ) { //ReefAngel.ClearScreen(DefaultBGColor); ReefAngel.WaterChangeModeStart(); ModeResponse(true); } else { ModeResponse(false); } break; } case REQ_BTN_PRESS: { // Simulate a button press to stop the modes ButtonPress++; ModeResponse(true); break; } // case REQ_CAL_RELOAD: // { // // Reload calibration values from memory // ReefAngel.PHMin = InternalMemory.PHMin_read(); // ReefAngel.PHMax = InternalMemory.PHMax_read(); //#ifdef SALINITYEXPANSION // ReefAngel.SalMax = InternalMemory.SalMax_read(); //#endif // SALINITYEXPANSION //#ifdef ORPEXPANSION // ReefAngel.ORPMin = InternalMemory.ORPMin_read(); // ReefAngel.ORPMax = InternalMemory.ORPMax_read(); //#endif // ORPEXPANSION // PROGMEMprint(XML_OK); // break; // } case REQ_ALARM_ATO: { ReefAngel.ATOClear(); ModeResponse(true); break; } case REQ_ALARM_OVERHEAT: { ReefAngel.OverheatClear(); ModeResponse(true); break; } default: case REQ_UNKNOWN: { //P(WebBodyMsg) = SERVER_UKNOWN; //WebResponse(WebBodyMsg, sizeof(WebBodyMsg) - 1); break; } } // switch reqtype } else { if (reqtype>0) { // P(WebBodyMsg) = SERVER_DENY; PROGMEMprint(SERVER_DENY); } } WIFI_SERIAL.flush(); m_pushbackindex=0; reqtype=0; weboption=0; }
WebResponse WebResponse::createHTML(const char* body) { return WebResponse(200, "text/html", body); }
WebResponse WebResponse::createText(const char* body) { return WebResponse(200, "text/plain", body); }
WebResponse WebResponse::createNull() { return WebResponse(0, "", ""); }
WebResponse WebResponse::createNotFound(const char* body) { return WebResponse(404, "text/html", body); }