/** Reset the device (soft reset) */ byte ESP8266_Simple::reset() { byte remainingAttempts = 5; //this->sendCommand(F("AT+IPR=9600")); while ( this->sendCommand(F("AT+RST")) != ESP8266_OK ) { if(--remainingAttempts == 0) return ESP8266_ERROR; delay(1000); } remainingAttempts = 5; // delay(4000); // Once the reset is issued OK, try to issue an AT command // and wait until that works while ( this->sendCommand("AT") != ESP8266_OK ) { if(--remainingAttempts == 0) return ESP8266_ERROR; delay(1000); } ESP82336_DEBUGLN("RESET OK"); return ESP8266_OK; }
byte ESP8266_Simple::unlinkConnection() { char cmdBuffer[8]; memset(cmdBuffer, 0, sizeof(cmdBuffer)); ESP82336_DEBUGLN(); ESP82336_DEBUGLN("UNLINKING"); // Blindly send a CIPCLOSE to try and kill the connection now // NOTE: Nope, this tends to cause the ESP to crash out // this->espSerial->println(F("AT+CIPCLOSE")); // Dump everything else until we see "Unlink" or nothing else seems to be available do { if(this->espSerial->waitUntilAvailable() == 0 || !this->espSerial->readBytesUntilAndIncluding('\n', cmdBuffer, sizeof(cmdBuffer)-1)) { return ESP8266_TIMEOUT; // Caller might want to do a reset() } ESP82336_DEBUG(cmdBuffer); } while( // We really need to keep up and not have any overflow, so not using string comparison here cmdBuffer[0] != 'U' || cmdBuffer[1] != 'n' || cmdBuffer[2] != 'l' || cmdBuffer[3] != 'i' || cmdBuffer[4] != 'n' || cmdBuffer[5] != 'k' ); if(strncmp_P(cmdBuffer, PSTR("Unlink"), 6) == 0) { return ESP8266_OK; } else { return ESP8266_ERROR; } }
unsigned int ESP8266_Simple::readIPD(char *responseBuffer, int responseBufferLength, int bodyResponseOnlyFromLine, int *parseHttpResponse, int *muxChannel) { if(!this->espSerial->waitUntilAvailable()) return 0; // Serial.print("BRFL: "); // Serial.println(bodyResponseOnlyFromLine); unsigned long startTime = millis(); unsigned long firstPacketWait = this->generalCommandTimeoutMicroseconds/1000; // If we don't get a packet in this time, abort char cmdBuffer[128]; memset(cmdBuffer,0,sizeof(cmdBuffer)); memset(responseBuffer,0,responseBufferLength); int cmdBufferIndex = 0; int responseBufferIndex = 0; int packetLength = -1; int bytesRead = 0; int lineNumber = -1; int packetCount = 0; // For HTTP parsing only byte headerEnd = 0; do { ESP82336_DEBUG("TIME: "); ESP82336_DEBUG(millis() - startTime); ESP82336_DEBUG(" COUNT:"); ESP82336_DEBUG(packetCount); ESP82336_DEBUG(" UNTIL:"); ESP82336_DEBUGLN((!packetCount ? firstPacketWait : (this->generalCommandTimeoutMicroseconds/1000))); if(!this->espSerial->waitUntilAvailable()) continue; if(packetLength == -1) { // Look for the +IPD response from the ESP8266 to get the number of bytes to read // note that we might also pick up an "OK" and other sillyness from the trailing of // a previous +IPD segment (each +IPD is a packet's contents, maximum MTU of your network // limits it (less a bit for TCP/IP overheads)). if((bytesRead = this->espSerial->readBytesUntilAndIncluding(':', cmdBuffer, sizeof(cmdBuffer), 1)) > 4) { // This is probably a bit brittle, but we don't want to waste time // while the serial buffer is filling. Ideally we would check that // there is a series of digits before the : and the characters "+IPD," before those if(cmdBuffer[bytesRead-1] == ':') { // There might be whitespace at the start of this line, we are looking at // +IPD[,mux#],1234 // where 1234 is the number of bytes to follow, // so we will walk backwards to find the , and then from that point forward // convert to an integer for(cmdBufferIndex = bytesRead-1; cmdBufferIndex >= 0; cmdBufferIndex--) { if(cmdBuffer[cmdBufferIndex-1] == ',') break; } packetLength = atoi(cmdBuffer+cmdBufferIndex); packetCount++; // We also might want to find a mux channel for(cmdBufferIndex = cmdBufferIndex-2; cmdBufferIndex >= 0; cmdBufferIndex--) { if(cmdBuffer[cmdBufferIndex-1] == ',') break; } if(cmdBufferIndex) { // If we get a mux channel, compare it to the request one, if it // isn't a match, skip this packet (but we keep the packetCount) if(muxChannel && (*muxChannel < 0)) *muxChannel = atoi(cmdBuffer+cmdBufferIndex); else if(muxChannel && (*muxChannel != atoi(cmdBuffer+cmdBufferIndex))) { // ignore this packet, it's not for us this->clearSerialBuffer(); packetLength = -1; } } ESP82336_DEBUG("Packet Length: "); ESP82336_DEBUGLN(packetLength); } else if(cmdBuffer[0] == 'O') // "OK" - signals end of packet data { // fall through for next packet } else if(cmdBuffer[0] == 'U' && cmdBuffer[5] == 'k') // "Unlink" - signals end of stream 0.9.2.4 { break; } else if(cmdBuffer[0] == 'C' && cmdBuffer[5] == 'D') // "CLOSED" - signals end of stream 0.9.5.2 { break; } else { ESP82336_DEBUG("Unknown IPD?: "); ESP82336_DEBUGLN(cmdBuffer); break; } } memset(cmdBuffer,0,sizeof(cmdBuffer)); cmdBufferIndex = 0; continue; } else { startTime = millis(); // Reset the start time every time we read in (part of) a packet // If packet is empty, or responseBuffer is full, just // finish up now and discard everything if(min(packetLength,responseBufferLength-responseBufferIndex-1) <= 0) { break; } if(this->espSerial->overflow()) { ESP82336_DEBUGLN("OVERFLOW"); } ESP82336_DEBUGLN("READ BYTES"); // Read up to the next newline, or all the remaining response, or as much as we can fit in the buffer, whichever comes first bytesRead = this->espSerial->readBytesUntilAndIncluding('\n', responseBuffer+responseBufferIndex, min(packetLength,responseBufferLength-responseBufferIndex-1)); ESP82336_DEBUGLN("DONE READING"); // If we read 1 byte, the index for the next write goes up one (effectivly responseBufferIndex is always the trailing null position // or if you prefer, the number of bytes stored in the buffer) responseBufferIndex += bytesRead; // Reduce the remaining response by the # of bytes read packetLength -= bytesRead; // The first time round, lineNumber will still be zero if(lineNumber == -1) { // First line of first packet should be status code (hopefully nobody out there has preceeding whitespace) if(parseHttpResponse) { if(strcmp_P(responseBuffer, PSTR("HTTP/")) == 0) { *parseHttpResponse = atoi(responseBuffer+9); // 9 == strlen("HTTP/1.1 ") } else { *parseHttpResponse = 0; // Unknown } } // And now we will rename line 0 to be line 1 lineNumber = 1; } // if we are parsing HttpResponse, we are getting headers, see if // we should skip them // If bodyResponseOnlyFromLine is 1 or more and we have headers, we need to skip the headers if(parseHttpResponse && bodyResponseOnlyFromLine > 0 && !headerEnd ) { // Because we are discarding lines up to the trailing \r\n, we can // just test from the start of the buffer if(responseBufferIndex > 1 && responseBuffer[0] == '\n' && (responseBuffer[2] == '\n' || responseBuffer[1] == '\n')) { // \r\n\r\n is found headerEnd = true; memset(responseBuffer,0,responseBufferLength); responseBufferIndex = 0; lineNumber = 1; } else { //ESP82336_DEBUGLN(responseBuffer); /* ESP82336_DEBUG("0=") ESP82336_DEBUG((byte)responseBuffer[0]); ESP82336_DEBUG("; 1=") ESP82336_DEBUG((byte)responseBuffer[1]); ESP82336_DEBUG("; 2=") ESP82336_DEBUG((byte)responseBuffer[2]); ESP82336_DEBUG("; X=") ESP82336_DEBUGLN((byte)responseBuffer[responseBufferIndex-1]); */ responseBuffer[0] = responseBuffer[responseBufferIndex-1]; //ESP82336_DEBUG("L=") //ESP82336_DEBUGLN((byte)responseBuffer[responseBufferIndex-1]); memset(responseBuffer+1,0,responseBufferIndex); responseBufferIndex = 1; // Increment the line number for the next round if we finished on a newline // otherwise the next round is a continuation of this line if(responseBuffer[responseBufferIndex-1] == '\n') { lineNumber++; } } } // A "negative" bodyResponseOnlyFromLine means skip this many headers and then include the rest // provided that headers are avalable (which will be the case only if httpHost is defined) // if we have not reached the minimum line yet, empty the buffer else if( abs(bodyResponseOnlyFromLine) > lineNumber) { /* Serial.print("SKIP "); Serial.print(lineNumber); Serial.print(" :"); Serial.println(responseBuffer); */ // Increment the line number for the next round if we finished on a newline // otherwise the next round is a continuation of this line if(responseBuffer[responseBufferIndex-1] == '\n') { lineNumber++; } memset(responseBuffer,0,responseBufferLength); responseBufferIndex = 0; } else if(bodyResponseOnlyFromLine < 0) { // A negative response means get ONLY headers (from the abs line) if( responseBuffer[responseBufferIndex-1] == '\n' && ( (strlen(responseBuffer) >= 2 && responseBuffer[responseBufferIndex-2] == '\n') // \n\n[NULL] || (strlen(responseBuffer) >= 4 && responseBuffer[responseBufferIndex-3] == '\n') // \r\n\r\n[NULL] ) ) { // done break; } } // If there is room in the buffer and more to be got, try to get more if(packetLength > 0 && responseBufferIndex < (responseBufferLength - 1)) { this->espSerial->waitUntilAvailable(); continue; } else if(packetLength <= 0 && responseBufferIndex < (responseBufferLength - 1)) { // Try for the next packet packetLength = -1; continue; } break; } } while(millis() - startTime < (packetCount ? firstPacketWait : (this->generalCommandTimeoutMicroseconds/1000))); // Timeout to go here ESP82336_DEBUGLN("READING AL DONE"); return responseBufferIndex; }
byte ESP8266_Simple::serveHttpRequest() { if(!this->espSerial->available()) return ESP8266_OK; // Nothing to do char cmdBuffer[64]; char hdrBuffer[64]; char dataBuffer[this->httpServerMaxBufferSize]; int requestLength; byte responseCode; unsigned long httpStatusCodeAndType; int muxChannel = -1; // This will be set by readIPD(), we need to start with -1 // to indicate we will accept any channel, we will get // packet data for whatever channel is first off the block // any inter-mingled packet data from other channels is discarded // for best results, only issue one request at a time! memset(dataBuffer,0,sizeof(dataBuffer)); if((requestLength = this->readIPD(dataBuffer,sizeof(dataBuffer),-1,NULL,&muxChannel))) { // Call the handler, note we reserve the last byte of the data buffer // it will always be null for safety if(this->httpServerRequestHandler) { httpStatusCodeAndType = (*(this->httpServerRequestHandler))(dataBuffer,sizeof(dataBuffer)-1); } else { httpStatusCodeAndType = this->httpServerRequestHandler_Builtin(dataBuffer, sizeof(dataBuffer)-1); } // Ensure that the last byte of the buffer is null for safety dataBuffer[sizeof(dataBuffer)-1] = 0; // Clear header and command buffer memset(hdrBuffer, 0, sizeof(hdrBuffer)); memset(cmdBuffer,0,sizeof(cmdBuffer)); // If it's not a raw response, make some headers if(!(httpStatusCodeAndType & ESP8266_RAW)) { strncpy_P(hdrBuffer, PSTR("HTTP/1.0 "), sizeof(hdrBuffer)-1); itoa( httpStatusCodeAndType & 0x00FFFFFF,hdrBuffer+strlen(hdrBuffer), 10); strncpy_P(hdrBuffer+strlen(hdrBuffer), PSTR("\r\nContent-type: "), sizeof(hdrBuffer)-strlen(hdrBuffer)-1); switch(httpStatusCodeAndType & 0xFF000000) { case ESP8266_HTML: strncpy_P(hdrBuffer+strlen(hdrBuffer), PSTR("text/html"), sizeof(hdrBuffer)-strlen(hdrBuffer)-1); break; case ESP8266_TEXT: strncpy_P(hdrBuffer+strlen(hdrBuffer), PSTR("text/plain"), sizeof(hdrBuffer)-strlen(hdrBuffer)-1); break; } strncpy_P(hdrBuffer + strlen(hdrBuffer), PSTR("\r\nContent-Length: "), sizeof(hdrBuffer) - strlen(hdrBuffer) - 1); itoa(strlen(dataBuffer), hdrBuffer + strlen(hdrBuffer), 10); strncpy_P(hdrBuffer+strlen(hdrBuffer), PSTR("\r\n\r\n"), sizeof(hdrBuffer)-strlen(hdrBuffer)-1); } // Create the send command which specifies the mux channel and data length strncpy_P(cmdBuffer,PSTR("AT+CIPSEND="),sizeof(cmdBuffer)); itoa(muxChannel,cmdBuffer+strlen(cmdBuffer),10); // With Mux cmdBuffer[strlen(cmdBuffer)]=','; itoa(strlen(hdrBuffer)+min(sizeof(dataBuffer)-1,strlen(dataBuffer)), cmdBuffer+strlen(cmdBuffer),10); if((responseCode = this->sendCommand(cmdBuffer)) != ESP8266_OK) { return responseCode; } this->espSerial->print(hdrBuffer); this->espSerial->print(dataBuffer); memset(cmdBuffer,0,sizeof(cmdBuffer)); strncpy_P(cmdBuffer, PSTR("AT+CIPCLOSE="), sizeof(cmdBuffer)-1); itoa(muxChannel, cmdBuffer+strlen(cmdBuffer),10); if((responseCode = this->sendCommand(cmdBuffer)) != ESP8266_OK) { return responseCode; } else { ESP82336_DEBUGLN("SERVER COMPLETED OK"); } } return ESP8266_OK; }
// Send command and get response into a buffer byte ESP8266_Simple::sendCommand(const char **cmdPartsToConcatenate, byte numParts, char *responseBuffer, int responseBufferLength, byte getResponseFromLine) { char statusBuffer[64]; unsigned long waitingMicroSeconds = 0; int responseBufferIndex = 0; byte statusBufferIndex = 0; byte responseLineNum = 0; int bytesRead = 0; // Clear response buffer if(responseBufferLength) { memset(responseBuffer,0,responseBufferLength); } // Clear status buffer memset(statusBuffer,0,sizeof(statusBuffer)); this->clearSerialBuffer(); // this->espSerial->print("AT+"); // this->espSerial->println(cmd); ESP82336_DEBUGLN() ESP82336_DEBUG("SEND {{{"); for(bytesRead = 0; bytesRead < numParts; bytesRead++) { ESP82336_DEBUG(cmdPartsToConcatenate[bytesRead]); this->espSerial->print((const char *)cmdPartsToConcatenate[bytesRead]); this->clearSerialBuffer(); // The character echo will fill up the buffer and overflow, we just clear them out. // the last println() we keave so that we don't accidentally clear any response. } this->espSerial->println(); ESP82336_DEBUGLN("}}}"); bytesRead = 0; do { #if ESP8266_SERIALMODE == ESP8266_SOFTWARESERIAL // There is no overflow() in the HardwareSerial code, guess we'll just // hope it never happens if(this->espSerial->overflow()) { ESP82336_DEBUG("Overflow"); this->clearSerialBuffer(); return ESP8266_OVERFLOW; } #endif if(this->espSerial->available()) { memset(statusBuffer,0,sizeof(statusBuffer)); if(!responseLineNum) { // read bytes up until the first \n and discard them, this is just the echo // incidentally, the echo contains the string sent, including the CR but not the LF, // followed by a second CRLF pair, eg if you send // AT+RST[CR][LF] the first response back is // AT+RST[CR][CR][LF] // the [CR] you send actually seems to form part of the command (if no CR is sent, // the command is not successful, if no LF is sent, the command is not even attempted if((bytesRead = this->espSerial->readBytesUntil('\n',statusBuffer,sizeof(statusBuffer)-1))) { ESP82336_DEBUG("DISCARD: "); ESP82336_DEBUG(statusBuffer); // readBytesUntil does NOT include the terminator, conveniently as we are getting // CRLF termination, we can check for the CR instead. if(statusBuffer[bytesRead-1] == '\r') { ESP82336_DEBUG('\n'); responseLineNum = 1; } } } else { // Fill status buffer if((bytesRead = this->espSerial->readBytesUntil('\n',statusBuffer,sizeof(statusBuffer)-1))) { ESP82336_DEBUG(statusBuffer); if(statusBuffer[bytesRead-1] == '\r') { ESP82336_DEBUG('\n'); } if(strncmp_P(statusBuffer, PSTR("SEND OK"), 7) == 0) return ESP8266_OK; if(strncmp_P(statusBuffer, PSTR("OK"), 2) == 0) return ESP8266_OK; if(strncmp_P(statusBuffer, PSTR(">"), 1) == 0) return ESP8266_OK; if(strncmp_P(statusBuffer, PSTR("ERROR"), 5) == 0) return ESP8266_ERROR; if(strncmp_P(statusBuffer, PSTR("nochange"), 8) == 0) return ESP8266_OK; if(strncmp_P(statusBuffer, PSTR("no change"),9) == 0) return ESP8266_OK; if(strncmp_P(statusBuffer, PSTR("ready"), 5) == 0) return ESP8266_READY; if(strncmp_P(statusBuffer, PSTR("busy"), 4) == 0) return ESP8266_BUSY; if(strncmp_P(statusBuffer, PSTR("Unlink"), 6) == 0) return ESP8266_OK; if(strncmp_P(statusBuffer, PSTR("Link is builded"), 15) == 0) return ESP8266_OK; // Not sure about this, it appears to happen // when you issue CIPCLOSE but the browser/client has already // closed the connection. I think. if(strncmp_P(statusBuffer, PSTR("link is not"), 11) == 0) return ESP8266_OK; // If we are using a response buffer, and we have reached the start line // requested (defaults to line 1) if(responseBufferLength && ( getResponseFromLine <= responseLineNum)) { // If there is room in the response buffer less one byte, copy the statusbuffer there if(responseBufferIndex < responseBufferLength-1) { // Some query commands come back as something like // +{COMMAND}:"{RESPONSE}" // in which case we only want to give back the stuff between the quotes if(responseBufferIndex == 0 && statusBuffer[0] == '+' && statusBuffer[1] == 'C' && *(((const char *)cmdPartsToConcatenate[0])+3) == 'C') { // Find length of the command for(statusBufferIndex = 1; statusBuffer[statusBufferIndex]; statusBufferIndex++) { if(statusBuffer[statusBufferIndex] == ':' && statusBuffer[statusBufferIndex+1] == '"' ) { break; } } if(statusBuffer[statusBufferIndex]) { // Looks like we found such a pattern and the current index is going to be ':' // advance it to the character after '"' and trim off the trailing '"' statusBufferIndex += 2; if(statusBuffer[bytesRead-2] == '"' && statusBuffer[bytesRead-1] == '\r') { statusBuffer[bytesRead-2] = '\r'; statusBuffer[bytesRead-1] = 0; } } else { // Didn't find the pattern, so use the full response statusBufferIndex = 0; } } memcpy(responseBuffer+responseBufferIndex, statusBuffer+statusBufferIndex, min(bytesRead-statusBufferIndex, responseBufferLength-1-responseBufferIndex)); responseBufferIndex += min(bytesRead-statusBufferIndex, responseBufferLength-1-responseBufferIndex); statusBufferIndex = 0; if(statusBuffer[bytesRead-1] == '\r') { if(responseBufferIndex<responseBufferLength-1) { responseBuffer[responseBufferIndex++]='\n'; } } } } // readBytesUntil does NOT include the terminator, conveniently as we are getting // CRLF termination, we can check for the CR instead. if(statusBuffer[bytesRead-1] == '\r') { responseLineNum++; } } } } // At 9600bps, I think we should keep this below 100uS to be able to keep up with certainty delayMicroseconds(100); waitingMicroSeconds += 100; } while(waitingMicroSeconds < this->generalCommandTimeoutMicroseconds); ESP82336_DEBUGLN("TIMED OUT"); // If we got here, we never say an OK or ERROR in the time allowed return ESP8266_TIMEOUT; }
// Send command and get response into a buffer byte ESP8266_Simple::sendCommand(const char **cmdPartsToConcatenate, byte numParts, char *responseBuffer, int responseBufferLength, byte getResponseFromLine) { char statusBuffer[64]; unsigned long waitingMicroSeconds = 0; int responseBufferIndex = 0; byte statusBufferIndex = 0; byte responseLineNum = 0; int bytesRead = 0; // Clear response buffer if(responseBufferLength) { memset(responseBuffer,0,responseBufferLength); } // Clear status buffer memset(statusBuffer,0,sizeof(statusBuffer)); this->clearSerialBuffer(); // this->espSerial->print("AT+"); // this->espSerial->println(cmd); ESP82336_DEBUGLN() ESP82336_DEBUG("SEND {{{"); for(bytesRead = 0; bytesRead < numParts; bytesRead++) { ESP82336_DEBUG(cmdPartsToConcatenate[bytesRead]); this->espSerial->print((const char *)cmdPartsToConcatenate[bytesRead]); this->clearSerialBuffer(); // The character echo will fill up the buffer and overflow, we just clear them out. // the last println() we keave so that we don't accidentally clear any response. } this->espSerial->println(); ESP82336_DEBUGLN("}}}"); bytesRead = 0; do { #if ESP8266_SERIALMODE == ESP8266_SOFTWARESERIAL // There is no overflow() in the HardwareSerial code, guess we'll just // hope it never happens if(this->espSerial->overflow()) { Serial.println("Overflow in HERE"); this->clearSerialBuffer(); return ESP8266_OVERFLOW; } #endif if(this->espSerial->available()) { memset(statusBuffer,0,sizeof(statusBuffer)); if(!responseLineNum) { // read bytes up until the first \n and discard them, this is just the echo // incidentally, the echo contains the string sent, including the CR but not the LF, // followed by a second CRLF pair, eg if you send // AT+RST[CR][LF] the first response back is // AT+RST[CR][CR][LF] // the [CR] you send actually seems to form part of the command (if no CR is sent, // the command is not successful, if no LF is sent, the command is not even attempted if((bytesRead = this->espSerial->readBytesUntil('\n',statusBuffer,sizeof(statusBuffer)-1))) { ESP82336_DEBUG(statusBuffer); // readBytesUntil does NOT include the terminator, conveniently as we are getting // CRLF termination, we can check for the CR instead. if(statusBuffer[bytesRead-1] == '\r') { ESP82336_DEBUG('\n'); responseLineNum = 1; } } } else { // Fill status buffer if((bytesRead = this->espSerial->readBytesUntil('\n',statusBuffer,sizeof(statusBuffer)-1))) { ESP82336_DEBUG(statusBuffer); if(statusBuffer[bytesRead-1] == '\r') { ESP82336_DEBUG('\n'); } if(strncmp_P(statusBuffer, PSTR("SEND OK"), 7) == 0) return ESP8266_OK; if(strncmp_P(statusBuffer, PSTR("OK"), 2) == 0) return ESP8266_OK; if(strncmp_P(statusBuffer, PSTR(">"), 1) == 0) return ESP8266_OK; if(strncmp_P(statusBuffer, PSTR("ERROR"), 5) == 0) return ESP8266_ERROR; if(strncmp_P(statusBuffer, PSTR("nochange"), 8) == 0) return ESP8266_OK; if(strncmp_P(statusBuffer, PSTR("no change"),9) == 0) return ESP8266_OK; if(strncmp_P(statusBuffer, PSTR("ready"), 5) == 0) return ESP8266_READY; if(strncmp_P(statusBuffer, PSTR("busy"), 4) == 0) return ESP8266_BUSY; if(strncmp_P(statusBuffer, PSTR("Unlink"), 6) == 0) return ESP8266_OK; if(strncmp_P(statusBuffer, PSTR("Link is builded"), 15) == 0) return ESP8266_OK; // If we are using a response buffer, and we have reached the start line // requested (defaults to line 1) if(responseBufferLength && ( getResponseFromLine <= responseLineNum)) { // If there is room in the response buffer less one byte, copy the statusbuffer there if(responseBufferIndex < responseBufferLength-1) { memcpy(responseBuffer+responseBufferIndex, statusBuffer, min(bytesRead, responseBufferLength-1-responseBufferIndex)); responseBufferIndex += min(bytesRead, responseBufferLength-1-responseBufferIndex); if(statusBuffer[bytesRead-1] == '\r') { if(responseBufferIndex<responseBufferLength-1) { responseBuffer[responseBufferIndex++]='\n'; } } } } // readBytesUntil does NOT include the terminator, conveniently as we are getting // CRLF termination, we can check for the CR instead. if(statusBuffer[bytesRead-1] == '\r') { responseLineNum++; } } } } // At 9600bps, I think we should keep this below 100uS to be able to keep up with certainty delayMicroseconds(100); waitingMicroSeconds += 100; } while(waitingMicroSeconds < this->generalCommandTimeoutMicroseconds); ESP82336_DEBUGLN("TIMED OUT"); // If we got here, we never say an OK or ERROR in the time allowed return ESP8266_TIMEOUT; }