Parsing incoming data

Hi,
My sketch gets weather data from openweathermap.org and I am attempting to parse the data to get just the temperature and humidity.

I am using a MKR1000.

I have it almost working but think I am running out of memory.

I have two almost identical functions called parseTemp() and parseHumidity().
parseTemp() works every time. parseHumidity() only works the first time.
The next time and any subsequent times I always get 0 as the humidity.

Here is my whole code.

/*
  Wifi with MKR 1000 getting weather data
1/30/17
 */
#include <SPI.h>
#include <WiFi101.h>

#define RBUFFSIZE 705
char responseBuffer[RBUFFSIZE];
int  rbindex = 0;
byte loopCounter = 0;
char key[] = "temp:";

char ssid[] = "xxxxxxxx"; //  your network SSID (name)
char pass[] = "xxxxxxxx";    // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0;            // your network key Index number (needed only for WEP)
byte index2 = 0;
int y = 0;

unsigned long previousMillis = 0;
const long interval = 240000;
byte x = 0;

int status = WL_IDLE_STATUS;
// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
//IPAddress server(74,125,232,128);  // numeric IP for Google (no DNS)

char server[] = "api.openweathermap.org";    // name address for Open Weather Map (using DNS)

// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
WiFiClient client;

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);

  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    // don't continue:
    while (true);
  }

  // attempt to connect to WiFi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
    delay(10000);
  }
  Serial.println("Connected to wifi");
  printWiFiStatus();

}



void loop() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    x = 0;
  }
  if (x == 0) {
    previousMillis = currentMillis;
    Serial.println("\nStarting connection to server...");
    // if you get a connection, report back via serial:
    if (client.connect(server, 80)) {
      Serial.println(F("Connected to server"));
      Serial.println(F("Making GET request"));
      // Make a HTTP request:
      client.println("GET /data/2.5/weather?zip=27604,us&units=imperial&APPID=05907f1eaa33a09802c4e35c8f3c549a HTTP/1.1");
      client.println("Host: api.openweathermap.org.com");
      client.println("Connection: close");
      client.println();
    }
    while (client.available()) {
      char c = client.read();
      Serial.write(c);

      if (rbindex < RBUFFSIZE) {
        responseBuffer[rbindex] = c;
        rbindex++;
      }

    }

    // if the server's disconnected, stop the client:
    if (!client.connected()) {
      Serial.println();
      Serial.println("disconnecting from server.");
      client.stop();

      Serial.println(F("Current Weather"));
      parseHumidity();
      parseTemp();

    }
  }

}

void printWiFiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

void printBuffer() {
  Serial.println("");
  Serial.print(F("Buffer Length = "));
  Serial.println(strlen(responseBuffer));
  Serial.println(F("Buffer ---------------------------"));
  Serial.println("");
  Serial.println(responseBuffer);
}

void parseTemp() {
  char *az = strstr(responseBuffer, "temp");
  az += strlen("temp:'");
  char *azval = strtok(az, ".");
  int valAZ = atoi(azval);
  Serial.print(F("Temp = "));
  Serial.println(valAZ);
  x = 1;
}

void parseHumidity() {
  char *ah = strstr(responseBuffer, "humidity");
  ah += strlen("humidity':");
  char *ahval = strtok(ah, ".");
  int valAH = atoi(ahval);
  Serial.print(F("Humidity = "));
  Serial.println(valAH);
}
void getWeather() {

  Serial.println("\nStarting connection to server...");
  // if you get a connection, report back via serial:
  if (client.connect(server, 80)) {
    Serial.println(F("connected to server"));
    Serial.println(F("Making GET request"));
    // Make a HTTP request:
    client.println("GET /data/2.5/weather?zip=27604,us&units=imperial&APPID=05907f1eaa33a09802c4e35c8f3c549a HTTP/1.1");
    client.println("Host: api.openweathermap.org.com");
    client.println("Connection: close");
    client.println();
  }
  while (client.available()) {
    char c = client.read();
    Serial.write(c);

    if (rbindex < RBUFFSIZE) {
      responseBuffer[rbindex] = c;
      rbindex++;
    }

  }

  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting from server.");
    client.stop();

    Serial.println(F("Current Weather"));
    parseHumidity();
    parseTemp();

  }
}

Here is what I am getting back from open weather and parsing.

HTTP/1.1 200 OK
Server: openresty
Date: Mon, 30 Jan 2017 14:02:18 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 437
Connection: close
X-Cache-Key: /data/2.5/weather?APPID=05907f1eaa33a09802c4e35c8f3c549a&units=imperial&zip=27604,us
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST

{“coord”:{“lon”:-78.63,“lat”:35.78},“weather”:[{“id”:801,“main”:“Clouds”,“description”:“few clouds”,“icon”:“02d”}],“base”:“stations”,“main”:{“temp”:32.72,“pressure”:1014,“humidity”:50,“temp_min”:28.4,“temp_max”:35.6},“visibility”:16093,“wind”:{“speed”:4.7},“clouds”:{“all”:20},“dt”:1485782100,“sys”:{“type”:1,“id”:1812,“message”:0.1709,“country”:“US”,“sunrise”:1485778536,“sunset”:1485816043},“id”:4497286,“name”:“Wake County”,“cod”:200}

How can I get parseHumidty() to work every time?
Is my issue with the strstr() function or am I running out of memory?

Thank you.

Do you need to put the whole response into a buffer before parsing it ? Could you read characters and discard them until you find "temp" then read the temperature and so on for "humidity" ?

Why are you not resetting rbindex ?

Mark

Why are you parsing a char array? strtok() expects a string, not a char array. A string is a NULL terminated array of chars, NOT just an array of chars. Your array of chars is NOT NULL terminated, so it is NOT a string, and should not be passed to functions that expect strings.

Since the temp value is a floating point value, why are you using atoi() to convert it?

You realize, I hope, that strtok() modifies the input string. If you wish to continue parsing the same string, you need to call strtok() with NULL as the first argument. Calling it with the string that has been mangled may not work.

Why do you need two functions to parse the same string? You can use reference arguments and make one function that gets two values that it shares with the caller.

Thanks for the suggestions. I'll try implementing them.