diff --git a/ELClient/ELClient.cpp b/ELClient/ELClient.cpp index f688a42..5f84297 100644 --- a/ELClient/ELClient.cpp +++ b/ELClient/ELClient.cpp @@ -65,8 +65,26 @@ ELClientPacket* ELClient::protoCompletedCb(void) { _debug->print("RESP_V: "); _debug->println(packet->value); } + _longPacket = 0; return packet; + case CMD_RESP_CB_CONTINUE: + // response callback, but one of the parts of a long packet --> just prepare assembly + // Currently just a copy (without notes) of the code below... + + { + // Serial.print("CMD_RESP_CB_CONTINUE\n"); + _longPacket = 1; + FP *fp; + fp = (FP*)packet->value; + if (fp->attached()) { + ELClientResponse resp(packet); + (*fp)(&resp); + } + return NULL; + } + case CMD_RESP_CB: // response callback: perform the callback! + { FP *fp; // callback reponse if (_debugEn) { @@ -75,12 +93,15 @@ ELClientPacket* ELClient::protoCompletedCb(void) { _debug->print(" "); _debug->println(packet->argc); } + + _longPacket = 0; fp = (FP*)packet->value; if (fp->attached()) { ELClientResponse resp(packet); (*fp)(&resp); } return NULL; + } case CMD_SYNC: // esp-link is not in sync, it may have reset, signal up the stack _debug->println("NEED_SYNC!"); if (resetCb != NULL) (*resetCb)(); diff --git a/ELClient/ELClient.h b/ELClient/ELClient.h index 5a9c73d..ca7ec99 100644 --- a/ELClient/ELClient.h +++ b/ELClient/ELClient.h @@ -40,6 +40,9 @@ typedef enum { CMD_SOCKET_SETUP = 40, /**< Setup socket connection */ CMD_SOCKET_SEND, /**< Send socket packet */ + + CMD_RESP_CB_CONTINUE = 70, // RESP_CB for a long packet + } CmdName; /**< Enumeration of commands supported by esp-link, this needs to match the definition in esp-link! */ enum WIFI_STATUS { @@ -126,6 +129,7 @@ class ELClient { uint16_t crc; /**< CRC checksum */ ELClientProtocol _proto; /**< Protocol structure */ uint8_t _protoBuf[128]; /**< Protocol buffer */ + uint16_t _longPacket; /**< Packet length in case of long packet */ void init(); void DBG(const char* info); diff --git a/ELClient/ELClientRest.cpp b/ELClient/ELClientRest.cpp index c08d075..34543d1 100644 --- a/ELClient/ELClientRest.cpp +++ b/ELClient/ELClientRest.cpp @@ -43,13 +43,26 @@ void ELClientRest::restCallback(void *res) ELClientResponse *resp = (ELClientResponse *)res; - resp->popArg(&_status, sizeof(_status)); - if (_elc->_debugEn) { - _elc->_debug->print("REST code "); - _elc->_debug->println(_status); - } + if (_elc->_longPacket == 0) { + resp->popArg(&_status, sizeof(_status)); + + if (_elc->_debugEn) { + _elc->_debug->print("REST code "); + _elc->_debug->println(_status); + } + + _len = resp->popArgPtr(&_data); - _len = resp->popArgPtr(&_data); + // Serial.print("restCallback status "); Serial.print(_status); Serial.print(", len "); Serial.println(_len); + } else { + int16_t lp; + resp->popArg(&lp, sizeof(lp)); + _elc->_longPacket = lp; + _status = 200; // Hack + _len = resp->popArgPtr(&_data); + + // Serial.print("restCallback LONG totalLength "); Serial.print(_elc->_longPacket); Serial.print(", len "); Serial.println(_len); + } } /*! begin(const char* host, uint16_t port, boolean security) @@ -379,3 +392,63 @@ uint16_t ELClientRest::waitResponse(char* data, uint16_t maxLen, uint32_t timeou } return getResponse(data, maxLen); } + +/*! waitResponse2(char* data, uint16_t maxLen, uint32_t timeout, uint16_t *totalLength, uint16_t packetLength) +@brief Wait for the response, cope with long packets +@details Wait for the response from the remote server for time_out, + returns the HTTP status code, 0 if no response (may need to wait longer) +@warning Blocks the Arduino code for 5 seconds! not recommended to use. + Received packet is NOT null-terminated +@param data + Pointer to buffer for received packet +@param maxLen + Size of buffer for received packet. If the received packet is larger than the buffer, the received packet will be truncated. +@param timeout + Timout in milli seconds to wait for a response. +@param totalLength + if non-NULL, used to return the total length of the multi-packet data +@param packetLength + if non-NULL, used to return the length of this chunk of data (typically 100 if not the last packet) +@return uint16_t + Size of received packet or number of sent bytes or 0 if no response +@par Example +@code + static char *buf = 0; + static int bufsiz = 700; + buf = (char *)malloc(bufsiz); + uint16_t datalen = 0, packetlen = 0; + memset(buf, 0, bufsiz); + char *ptr = buf; + err = rest->waitResponse2(ptr, bufsiz-1, DEFAULT_REST_TIMEOUT, &datalen, &packetlen); + while (datalen) { + ptr += packetlen; + err = rest->waitResponse2(ptr, bufsiz-1, DEFAULT_REST_TIMEOUT, &datalen, &packetlen); + } + ... + free(buf); + buf = 0; +@endcode +*/ +uint16_t ELClientRest::waitResponse2(char* data, uint16_t maxLen, uint16_t *totalLength, uint16_t *packetLength, uint32_t timeout) +{ + uint32_t wait = millis(); + while (_status == 0 && (millis() - wait < timeout)) { + _elc->Process(); + } + return getResponse2(data, maxLen, totalLength, packetLength); +} + +uint16_t ELClientRest::getResponse2(char* data, uint16_t maxLen, uint16_t *totalLength, uint16_t *packetLength) +{ + if (_status == 0) + return 0; + if (totalLength != 0) + *totalLength = _elc->_longPacket; + if (packetLength != 0) + *packetLength = _len; + memcpy(data, _data, _len>maxLen?maxLen:_len); + int16_t s = _status; + _status = 0; + return s; +} + diff --git a/ELClient/ELClientRest.h b/ELClient/ELClientRest.h index 51546f9..9ff5a9b 100644 --- a/ELClient/ELClientRest.h +++ b/ELClient/ELClientRest.h @@ -67,11 +67,13 @@ class ELClientRest { // Retrieve the response from the remote server, returns the HTTP status code, 0 if no // response (may need to wait longer) uint16_t getResponse(char* data, uint16_t maxLen); + uint16_t getResponse2(char* data, uint16_t maxLen, uint16_t *totalLength, uint16_t *packetLength); // Wait for the response from the remote server, returns the HTTP status code, 0 if no // response (timeout occurred). This is not recommended except for quick demos, use // getResponse periodically instead. uint16_t waitResponse(char* data, uint16_t maxLen, uint32_t timeout=DEFAULT_REST_TIMEOUT); + uint16_t waitResponse2(char* data, uint16_t maxLen, uint16_t *totalLength, uint16_t *packetLength, uint32_t timeout = DEFAULT_REST_TIMEOUT); // Set the user-agent for all subsequent requests void setUserAgent(const char* value);