I to returned to an application which was working prior to the yahoo weather shakeup.
After some effort I have a method of accessing data on the yahoo weather API.
I found this useful as a starting point;
https://www.igorkromin.net/
The new weather server is query.yahooapis.com
Essentually you need to send a get request.
This will return everything from the location in xml format and metric units:
String location ="/v1/public/yql?format=xml&q=select+*+from+weather.forecast+where+woeid=30079+and+u='c'";
You can also be selective, with a much smaller transfer overhead:
String location = "/v1/public/yql?format=xml&q=select+location,units.temperature,units.speed,wind.direction,wind.speed,item.condition+from+weather.forecast+where+woeid=30079+and+u='c'";
This returns details on units, wind speed, wind direction and current conditions.
The woeid parameter is the location which can be looked up here:
http://woeid.rosselliot.co.nz/
.
David
.
The code uses the new wifi101 library.
I am sure interested parties will be able to adjust for other hardware.
Sample output is attached.
/*
yifi101weather.ino
Extracted from a larger application
D.R.Patterson
19/4/2016
*/
#include <SPI.h>
#include <SdFat.h>
#include <WiFi101.h>
char ssid[] = "DRP3"; // network name
int port = 8082;
WiFiServer server(port);
int wifistatus = WL_IDLE_STATUS; // the Wifi radio's status
byte wifiSelect = 10;
SdFat sd; // file system object
Sd2Card card;
byte sdSelect = 53;
// ********************** yahoo weather data **************************
// old server ended 15/4/2016
//char wserver[] = "xml.weather.yahoo.com";
//String location = "/forecastrss?p=UKXX1695&u=c"; // newcastle upon tyne in degrees C (metric)
// new server
char wserver[] = "query.yahooapis.com";
String location = "/v1/public/yql?format=xml&q=select+location,units.temperature,units.speed,wind.direction,wind.speed,item.condition+from+weather.forecast+where+woeid=30079+and+u='c'";
// get all is slower!
//String location ="/v1/public/yql?format=xml&q=select+*+from+weather.forecast+where+woeid=30079+and+u='c'";
boolean showall = true; // show all from yahoo weather on monitor
// ********************************************************************
boolean useserial = true; // toggle serial output
void setup(){
pinMode(wifiSelect, OUTPUT);
pinMode(sdSelect, OUTPUT);
Serial.begin(115200);
if(!sd.begin(sdSelect, SPI_FULL_SPEED)) Serial.println(F("sd.begin failed"));
if (!card.init(SPI_FULL_SPEED, sdSelect)) Serial.println(F("card.init failed!"));
// connect to ssid
if (!ssidConnect(ssid) ) while(1);
}
void loop(){
getweather(showall);
delay(300000);
}
void getweather(boolean fullprint){
float fspeed, ftemp, fdirection;
String synopsis, date, wlocation;
int icode;
icode = 3200; // in case weather code is not found
String timestring;
WiFiClient myclient;
String wunits, tunits, wdirection, wspeed, temp, thiscode;
unsigned long timenow;
if (useserial){
Serial.print(F("\nStarting connection to server.. "));
Serial.println(wserver);
//Serial.println(location);
}
if (myclient.connect(wserver, 80)) {
if(useserial) Serial.println(F("Connected to server.."));
// Make a HTTP request:
myclient.println("GET " + location + " HTTP/1.1");
myclient.println("Host: " + String(wserver));
myclient.println(F("Connection: close"));
myclient.println();
timenow = millis();
String recline = "";
while(myclient.connected()) {
while (myclient.available()) {
char c = myclient.read();
if(c==62) recline = recline + ">";
if (c == 10 || c == 62) { // use ">" as a line terminator
if(useserial && fullprint) Serial.println(recline);
if (recline.indexOf(F("weather:location")) > 0 ) {
wlocation = par(recline, F("city"));
}
if (recline.indexOf(F("weather:units")) > 0 ) {
wunits = par(recline, F("speed"));
tunits = par(recline, F("temperature"));
}
if (recline.indexOf(F("weather:condition")) > 0 ) {
date = par(recline, F("date"));
synopsis = par(recline, F("text"));
thiscode = par(recline, F("code"));
icode = thiscode.toInt();
temp = par(recline, F("temp"));
ftemp = temp.toFloat();
}
if (recline.indexOf(F("weather:wind")) > 0 ) {
wdirection = par(recline, F("direction"));
fdirection = wdirection.toFloat();
wspeed = par(recline, F("speed"));
fspeed = wspeed.toFloat();
}
recline = "";
}else if (c>31 && c<127) recline = recline + String(c);
}
if (millis()-timenow > 30000) break; // get out if stuck
}
if(useserial)Serial.println(F("disconnecting from server."));
myclient.stop();
if(tunits != "C") ftemp = (ftemp - 32.0) * 5.0 / 9.0; // convert to Centigrade
if(wunits == "km/h") fspeed = fspeed * 0.621371; // mph
if(useserial){
Serial.println();
Serial.print(wlocation + ", ");
Serial.println(date);
Serial.print(synopsis);
Serial.print(". (" + thiscode + ")");
Serial.print(F(".\nWind: Direction "));
Serial.print(fdirection, 1);
Serial.print(F(", Speed "));
Serial.print(fspeed, 2);
Serial.print(F(" m/h, Temp "));
Serial.print(ftemp, 1);
Serial.println(F(" C"));
}
}else if (useserial) Serial.println(F("Connection failed"));
}
String par(String thisline, String search){ // extract search parameter from xml thisline
byte e = search.length() + 2;
int p = thisline.indexOf(search);
int l = thisline.indexOf("\"", p + e);
return thisline.substring(p + e, l);
}
boolean ssidConnect(String thessid){
byte mytry = 0;
// attempt to connect to Wifi network:
do { // try 3 times
mytry ++;
if (useserial){
Serial.println(F("Connect attempt ")); Serial.print(mytry);
Serial.print(F(" to SSID: ")); Serial.println(thessid);
}
// Connect to network.
wifistatus = WiFi.begin(thessid);
// wait 10 seconds for connection:
unsigned long starttime = millis();
do { // check status every 2 seconds
delay(2000);
wifistatus = WiFi.status();
} while (wifistatus != WL_CONNECTED && millis() - starttime < 10000);
} while (wifistatus != WL_CONNECTED && mytry < 3); // 3 attempts
if (wifistatus != WL_CONNECTED){
if (useserial){
Serial.print(F("Unable to connect to ")); Serial.println(thessid);
}
return false;
}
if (useserial) {
Serial.print(F("Connected, commencing server on port "));
Serial.println(port);
}
server.begin();
return true;
}