ESP8266,.. 'client.available' causes i2c corruption

Hi Guys,…
I need some deeper knowledge and under standing,… I am trying to receive information back from a
“/Wire/connector/get?id=” + devId + “&THRESHOLD”; issued type command to the server at https://www.ic2cloud.com/

using

  while (client.connected() && !client.available()) delay(1);          // wait for data

  while (client.connected() || client.available()) {
    String line = client.readStringUntil('\r');
    }

Now although the code ‘basically’ works,… I think it is also getting information from, or interfering with the i2c bus to,… as periodically the data stream written to the i2c bus is being corrupted,… causing the display to crash,… the core program continues to run,… but the display becomes no-operative, showing just random characters…

I suspect my client.available command is the culprit, but not sure which command I should use,… I have tried ‘WiFi.available’ but there is no such class… So am am unsure as to where to go next.

With the ‘get?id’ from web code included,… display will run for only a matter of hours before it becomes corrupt,. yet with it commented out,… will run for days without issue,… ( I have not gone beyond 3 days ). A full listing is attached,…

Many tx for looking,…

Temp_Freezer_alarmV0.40.ino (15.3 KB)

  while (client.connected() || client.available()) {

That should be AND, not OR.

  while (client.connected() && !client.available()) delay(1);          // wait for data

Do NOT even THINK of doing this. Let loop() loop, if there is nothing to read.

THAT is what is interfering with I2C.

    String line = client.readStringUntil('\r');

And that, and any other blocking code you have.

Paul,.. many tx for your feedback,.. Yes your thoughts have provoked my thinking to trap situations where I am trying to read data and nothing comes,... edits so far have fixed the i2c corruption,.. but I would like to learn more form my errors.

So I assume your comment is that although the syntax is OK,.. there is just no escape if no data...

And I assume this corrupted the i2c because the system spent too long waiting for none present data,.. and just crashed during i2c writing,.. but not enough to fully trash itself... ( struggling to get my head around this a little )

I have modified my code now to include a "get out of jail card",... after 1 second... is this too generous,.. but I am unsure as to what to do the:-

   String line = client.readStringUntil('\r');

As this is the line that receives the input stream from the cloud server,..

My modified code now looks as follows:-

  int ClientGetCount = 0;
  while ( client.connected() && !client.available() ) {
    delay(2);          // wait for data
    ClientGetCount++;
    if ( ClientGetCount > 500 ) {
      break;
    }
  }

  while (client.connected() && client.available()) {
    String line = client.readStringUntil('\r');

    //    Serial.print("Lines of text recived from Server as follows:- ");
    //    Serial.println(line);

    // Process In-coming stream
    splitCommand(line);
  }

Do I just need to include some more "get out of jail" cards during the read and write cycles so it cannot disappear into oblivion,.. and gracefully return to normal running..
Again,.. thankyou for your advice..

That is a piss-poor way of waiting only so long for data. The better approach is

unsigned long waitStart = millis();
unsigned long tooLong = 60000UL; // Don't wait more than 60 seconds for all data
while(client.connected() && millis()-waitStart < tooLong)
{
   while(client.available() > 0)
   {
      char c = client.read();
      if(c == '\r')
      {
         // The end of the line arrived.
         useTheData();
         break;
      }
      else
      {
         // Save c in an array, if there is room, and increment the array index
         // Don't forget the NULL terminator
      }
   }
}

Each time there is a character to read, you could reset startTime, if the goal was to wait no more than 60 seconds after the last character, rather than no more than 60 seconds total.

Create an array to store the data in, and an index variable, and ditch the String class forever.

Many tx Paul,… I have done some re-coding around your framework,… and YES,… it really does work a whole lot better. Its been running pretty much constant now for a couple of weeks.
I see what you mean,. and now understand more about blocking code,… and how my previous attempt was prone to be un-reliable and doomed to failure.

For those following here is the updated read procedure, using a while loop construct, with some extra stuff to write a semi-status/progress to the LCD display.

Again thanks for your help…

void goReadThreshold() {

  lcd.setCursor(16, 0);
  lcd.print("R");
  lcd.write(1);   // write filling bar to top right

  Serial.print("connecting to ");
  Serial.println(host);

  digitalWrite(LEDoutput, HIGH);

  lcd.setCursor(17, 0);
  lcd.write(2);   // write filling bar to top right

  // Use WiFiClient class to create TCP connections
  WiFiClient client;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }
  lcd.setCursor(17, 0);
  lcd.write(3);   // write filling bar to top right

  // We now create a URI for the request
  //  String url = "/Wire/connector/set?id=" + devId + "&TEMPERATURE=" + getTemperature();
  //                      /Wire/connector/get?id=8a997a8b-0b0a-4e66-8460-705656f85e11&THRESHOLD

  String url = "/Wire/connector/get?id=" + devId + "&THRESHOLD";

  lcd.setCursor(17, 0);
  lcd.write(3);   // write filling bar to top right

  Serial.print("Requesting URL: ");
  Serial.println(url);

  // This will send the request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Authorization: Basic " + auth + "\r\n" +
               "Host: " + host + "\r\n" +
               "Connection: close\r\n\r\n");

  //  delay(10);
  lcd.setCursor(17, 0);
  lcd.write(4);   // write filling bar to top right

  Serial.println("try reading serial available");

  // Read all the lines of the reply from server and print them to Serial


  // ---------------------------

  unsigned long waitStart = millis();     // Initialise start time for Reading

  unsigned long tooLong = 5000UL; // Don't wait more than 5 seconds for all data
  while (client.connected() && millis() - waitStart < tooLong)  {
    while (client.available() > 0)   {
      char c = client.read();

      WebInputString[indx] = c;
      indx++;

      // Check if input stream will overflow buffer
      if ( indx > (SizeInputString - 1) ) {
        break;
      }

      if ( c == '\r' || c == '\n' )    {
        // The end of the line or New Line arrived.
        WebInputString[indx - 1 ] = '\0';
        indx = 0;

        splitCommand();
        break;

      }
    } // while client available
  }  // while client connected

  lcd.setCursor(17, 0);
  lcd.write(5);   // write filling bar to top right

  Serial.println();
  Serial.println("closing connection\n");

  lcd.setCursor(17, 0);
  lcd.write(6);   // write filling bar to top right

  digitalWrite(LEDoutput, LOW);

  lcd.setCursor(16, 0);
  lcd.print("  ");   // write filling bar to top right

} // End goREADthreshold