Example #1
0
/** 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;  
}
Example #2
0
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;
  }
}
Example #3
0
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;
}
Example #4
0
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;
}
Example #5
0
// 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;
}