This is the code I ended up with to get latitiude, longitude, and timezone. It stores the lat, lon in EEPROM if they are different from whats already saved and the timezone is used to set the physical RTC with the blynk RTC in a separate function. I adapted my code from structure7 's example that was posted earlier in the post.
// HTTP request const char WUNDERGROUND_REQ[] = "GET /api/*API Key*/conditions/q/autoip.json HTTP/1.1\r\n" "User-Agent: ESP8266/0.1\r\n" "Accept: */*\r\n" "Host: " WUNDERGROUND "\r\n" "Connection: close\r\n" "\r\n";
static char respBuf[4096];
bool showWeather(char *json);
void LocSync() { // Open socket to WU server port 80 Serial.print(F("Connecting to ")); Serial.println(WUNDERGROUND);
// Use WiFiClient class to create TCP connections (A LITTLE WORRIED HOW THIS WILL WORK WITH BLYNK) WiFiClient httpclient; const int httpPort = 80; if (!httpclient.connect(WUNDERGROUND, httpPort)) { Serial.println(F("connection failed")); delay(DELAY_ERROR); return; }
// This will send the http request to the server Serial.print(WUNDERGROUND_REQ); httpclient.print(WUNDERGROUND_REQ); httpclient.flush();
// Collect http response headers and content from Weather Underground // HTTP headers are discarded. // The content is formatted in JSON and is left in respBuf. int respLen = 0; bool skip_headers = true; while (httpclient.connected() || httpclient.available()) { if (skip_headers) { String aLine = httpclient.readStringUntil('\n'); //Serial.println(aLine); // Blank line denotes end of headers if (aLine.length() <= 1) { skip_headers = false; } } else { int bytesIn; bytesIn = httpclient.read((uint8_t *)&respBuf[respLen], sizeof(respBuf) - respLen); Serial.print(F("bytesIn ")); Serial.println(bytesIn); if (bytesIn > 0) { respLen += bytesIn; if (respLen > sizeof(respBuf)) respLen = sizeof(respBuf); } else if (bytesIn < 0) { Serial.print(F("read error ")); Serial.println(bytesIn); } } delay(1); } httpclient.stop();
if (respLen >= sizeof(respBuf)) { Serial.print(F("respBuf overflow ")); Serial.println(respLen); delay(DELAY_ERROR); return; } // Terminate the C string respBuf[respLen++] = '\0'; Serial.print(F("respLen ")); Serial.println(respLen); //Serial.println(respBuf);
// This part will be removed in favor of the timer feature. Probably remove delay_error and just report ERR. if (showWeather(respBuf)) { delay(DELAY_NORMAL); } else { delay(DELAY_ERROR); }
}
bool showWeather(char *json) { StaticJsonBuffer<3*1024> jsonBuffer;
// Skip characters until first '{' found // Ignore chunked length, if present char *jsonstart = strchr(json, '{'); //Serial.print(F("jsonstart ")); Serial.println(jsonstart); if (jsonstart == NULL) { Serial.println(F("JSON data missing")); return false; } json = jsonstart;
// Parse JSON JsonObject& root = jsonBuffer.parseObject(json); if (!root.success()) { Serial.println(F("jsonBuffer.parseObject() failed")); return false; }
// Extract weather info from parsed JSON JsonObject& current = root["current_observation"]; latitude = current["display_location"]["latitude"]; // Was `const float temp_f = current["temp_f"];` Serial.print(latitude);// Serial.print(F(" F ")); longitude = current["display_location"]["longitude"]; Serial.print(longitude); timezone = current["local_tz_offset"]; timezone = timezone/100; Serial.print(timezone);
int SaveFlag = 0; double Hold; Hold = ReadCoor(1); if (latitude != Hold){ WriteCoor(latitude,1); SaveFlag = 1; } Hold = ReadCoor(4); if (longitude != Hold){ WriteCoor(longitude,4); SaveFlag = 1; } if (SaveFlag ==1){ EEPROM.commit(); }
return true; }
double ReadCoor(int address){ double Hold = EEPROM.read(address); double HoldDec = EEPROM.read(address + 1); int Sign = EEPROM.read(address + 2); if (Sign == 1){ return (-(Hold +(HoldDec/100))); } else{ return (Hold + (HoldDec/100)); } }
void WriteCoor(double Coor, int address){ int Hold = abs(Coor); int HoldDec = ((abs(Coor) - Hold) * 100); EEPROM.write(address, Hold); EEPROM.write((address + 1), HoldDec); if (Coor < 0){ EEPROM.write((address + 2), 1); } else{ EEPROM.write((address + 2), 0); } }