Most of these rely on API calls to OpenWeatherMap or Weather Underground (Wunderground), and both are great. OpenWeatherMap allows users to build their own weather stations and push data to their servers to be accessed by anyone. Wunderground is owned by The Weather Company and also lets users connect weather stations and contribute to weather/forecast data.
The one downside to pulling data from those two is that you are forced to create an account and use API keys. While I recommend using OpenWeatherMap or Wunderground for most of your needs (they support citizen science contributions!), if you need to obtain weather information without API keys (e.g., classroom), then another alternative exists: Yahoo Weather API.
There are limitations on its use, like noncommercial and 2,000 calls per day, but it still works well for an open API to get weather information. If you click on the link below, you can check out how to craft HTTP calls to the API:
It relies on a query language called “Yahoo Query Language (YQL)” that works similarly to SQL. If I enter the following into the query box, I can get a 10-day forecast for Boulder:
select item.forecast from weather.forecast where woeid in (select woeid from geo.places(1) where text="boulder, co")
The Endpoint also changes (see screenshot), which gives me an HTTP GET request that I can just paste into my code. Note that you might have to click “Test” a few times to get the correct response to show up instead of a
"results": null
. The YQL test page seems to be slow as of late.
Yahoo’s Weather API seems to pull its information from weather.com, which is owned by The Weather Channel, so it’s a fairly reliable source.
It would seem that the Yahoo Weather API was originally intended for website-embedded content, but we’re going to use it for a different kind of embedded content: microcontrollers!
For this demo, you’ll just need a SparkFun ESP8266 Thing Dev Board. Follow the hookup guide to install the Arduino library and copy in the following code (changing
ssid
and password
to your WiFi’s SSID and password, respectively):#include <ESP8266WiFi.h>
// WiFi config
const char ssid[] = "<SSID>";
const char password[] = "<PASSWORD>";
// Server, file, port
const char hostname[] = "query.yahooapis.com";
const String url = "/v1/public/yql?q=select%20item.condition.temp%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22boulder%2C%20co%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&diagnostics=true";
const int port = 80;
// Timeout
unsigned long timeout = 10000; // ms
// WiFi Client
WiFiClient client;
void setup() {
// Init Serial
Serial.begin(9600);
delay(100);
// Connect to WiFi
Serial.print("Connecting to ");
Serial.print(ssid);
WiFi.begin(ssid, password);
while ( WiFi.status() != WL_CONNECTED ) {
delay(500);
Serial.print(".");
}
Serial.println();
// Show we are connected
Serial.println("Connected!");
}
void loop() {
unsigned long timestamp;
int temp;
// Establish TCP connection
Serial.print("Connecting to ");
Serial.println(hostname);
if ( !client.connect(hostname, port) ) {
Serial.println("Connection failed");
}
// Send GET request
String req = "GET " + url + " HTTP/1.1\r\n" +
"Host: " + hostname + "\r\n" +
"Connection: close\r\n" +
"\r\n";
client.print(req);
// Wait for response from server
delay(500);
timestamp = millis();
while ( !client.available() && (millis() < timestamp + timeout) ) {
delay(1);
}
// Parse temperature
if ( client.find("temp\":") ) {
temp = client.parseInt();
Serial.print("Local temperature: ");
Serial.print(temp);
Serial.println(" F");
}
// Flush receive buffer
while ( client.available() ) {
client.readStringUntil('\r');
}
// Close TCP connection
client.stop();
Serial.println();
Serial.println("Connection closed");
delay(30000);
}
You can change the URL to whatever you’d like from the Yahoo Weather API page in order to, for example, find the temperature in a different city. Here, I’m fetching the current temperature in Boulder, CO. Open a Serial monitor to get the parsed temperature:
#include <ESP8266WiFi.h>
//高雄市天氣
// WiFi config
const char ssid[] = "PTS-2F";
const char password[] = "";
// Server, file, port
const char hostname[] = "query.yahooapis.com";
const String url = "/v1/public/yql?q=select%20item.condition.temp%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22kaohsiung%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&diagnostics=true";
const int port = 80;
/*
//select item.forecast from weather.forecast where woeid in (select woeid from geo.places(1) where text="boulder, co") 美國波得市
//kaohsiung-city-2306180
// Server, file, port
const char hostname[] = "query.yahooapis.com";
const String url = "/v1/public/yql?q=select%20item.condition.temp%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22boulder%2C%20co%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&diagnostics=true";
const int port = 80; */
// Timeout
unsigned long timeout = 10000; // ms
// WiFi Client
WiFiClient client;
void setup() {
// Init Serial
Serial.begin(115200);
delay(100);
// Connect to WiFi
Serial.print("Connecting to ");
Serial.print(ssid);
WiFi.begin(ssid, password);
while ( WiFi.status() != WL_CONNECTED ) {
delay(500);
Serial.print(".");
}
Serial.println();
// Show we are connected
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void loop() {
unsigned long timestamp;
int temp;
// Establish TCP connection
Serial.print("Connecting to ");
Serial.println(hostname);
if ( !client.connect(hostname, port) ) {
Serial.println("Connection failed");
}
// Send GET request
String req = "GET " + url + " HTTP/1.1\r\n" +
"Host: " + hostname + "\r\n" +
"Connection: close\r\n" +
"\r\n";
client.print(req);
// Wait for response from server
delay(500);
timestamp = millis();
while ( !client.available() && (millis() < timestamp + timeout) ) {
delay(1);
}
// Parse temperature
if ( client.find("temp\":") ) {
temp = client.parseInt();
Serial.print(" kaohsiung-city temperature: ");
Serial.print(temp);
Serial.print(" F , ");
float t1= (temp-32) * 5 /9; //攝氏 = (華氏-32)*5/9
Serial.print(t1,2);
Serial.print(" C ");
}
// Flush receive buffer
while ( client.available() ) {
client.readStringUntil('\r');
}
// Close TCP connection
client.stop();
Serial.println();
Serial.println("Connection closed");
delay(30000);
}
沒有留言:
張貼留言