-
-
Save bbx10/149bba466b1e2cd887bf to your computer and use it in GitHub Desktop.
/**************************** | |
The MIT License (MIT) | |
Copyright (c) 2015 by bbx10node@gmail.com | |
Permission is hereby granted, free of charge, to any person obtaining a copy | |
of this software and associated documentation files (the "Software"), to deal | |
in the Software without restriction, including without limitation the rights | |
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
copies of the Software, and to permit persons to whom the Software is | |
furnished to do so, subject to the following conditions: | |
The above copyright notice and this permission notice shall be included in all | |
copies or substantial portions of the Software. | |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
SOFTWARE. | |
******************************/ | |
#include <ESP8266WiFi.h> | |
#ifndef min | |
#define min(x,y) (((x)<(y))?(x):(y)) | |
#endif | |
#ifndef max | |
#define max(x,y) (((x)>(y))?(x):(y)) | |
#endif | |
#include <ArduinoJson.h> | |
const char SSID[] = "********"; | |
const char PASSWORD[] = "***************"; | |
// Use your own API key by signing up for a free developer account. | |
// http://www.wunderground.com/weather/api/ | |
#define WU_API_KEY "****************" | |
// Specify your favorite location one of these ways. | |
//#define WU_LOCATION "CA/HOLLYWOOD" | |
// US ZIP code | |
//#define WU_LOCATION "" | |
#define WU_LOCATION "90210" | |
// Country and city | |
//#define WU_LOCATION "Australia/Sydney" | |
// 5 minutes between update checks. The free developer account has a limit | |
// on the number of calls so don't go wild. | |
#define DELAY_NORMAL (5*60*1000) | |
// 20 minute delay between updates after an error | |
#define DELAY_ERROR (20*60*1000) | |
#define WUNDERGROUND "api.wunderground.com" | |
// HTTP request | |
const char WUNDERGROUND_REQ[] = | |
"GET /api/" WU_API_KEY "/conditions/q/" WU_LOCATION ".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"; | |
void setup() | |
{ | |
Serial.begin(115200); | |
// We start by connecting to a WiFi network | |
Serial.println(); | |
Serial.println(); | |
Serial.print(F("Connecting to ")); | |
Serial.println(SSID); | |
WiFi.begin(SSID, PASSWORD); | |
while (WiFi.status() != WL_CONNECTED) { | |
delay(500); | |
Serial.print(F(".")); | |
} | |
Serial.println(); | |
Serial.println(F("WiFi connected")); | |
Serial.println(F("IP address: ")); | |
Serial.println(WiFi.localIP()); | |
} | |
static char respBuf[4096]; | |
void loop() | |
{ | |
// TODO check for disconnect from AP | |
// Open socket to WU server port 80 | |
Serial.print(F("Connecting to ")); | |
Serial.println(WUNDERGROUND); | |
// Use WiFiClient class to create TCP connections | |
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); | |
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"]; | |
const float temp_f = current["temp_f"]; | |
Serial.print(temp_f, 1); Serial.print(F(" F, ")); | |
const float temp_c = current["temp_c"]; | |
Serial.print(temp_c, 1); Serial.print(F(" C, ")); | |
const char *humi = current[F("relative_humidity")]; | |
Serial.print(humi); Serial.println(F(" RH")); | |
const char *weather = current["weather"]; | |
Serial.println(weather); | |
const char *pressure_mb = current["pressure_mb"]; | |
Serial.println(pressure_mb); | |
const char *observation_time = current["observation_time_rfc822"]; | |
Serial.println(observation_time); | |
// Extract local timezone fields | |
const char *local_tz_short = current["local_tz_short"]; | |
Serial.println(local_tz_short); | |
const char *local_tz_long = current["local_tz_long"]; | |
Serial.println(local_tz_long); | |
const char *local_tz_offset = current["local_tz_offset"]; | |
Serial.println(local_tz_offset); | |
return true; | |
} |
instead of defining location, you can just put in autoip
where do you download the esp library?
Basic Infos
i am writing a code that give weather forecast from wunderground.com website with HTTP request, and i want send to me this forecast in telegram. i use UniversalTelegramBot library to send message in telegram. so this code have to part:
1- give weather forecast from wunderground.com
2- send this forecast in telegram Bot
Each part work as well , but when i merge two part i give Exception (29) error :(
Hardware
Hardware: NodeMcu Lua WIFI Board Based on ESP8266 CP2102 Module (ESP-12E)
Core Version: I do not know!!!
because i flash my esp with ESP8266Flasher.exe
my setings in ESP8266Flasher is in this picture:
Settings in IDE
Module: Adafruit HUZZAH esp8266
Flash Size: 4MB(3MB SPIFFS)
CPU Frequency: 80Mhz
Upload Using: SERIAL 115200
Sketch
Debug Messages
Thank you for the code! Everything work fine for me.
Maybe you can help with one question: "how can correct parse /forecast/ .json?"
Compiling your sketch on my Arduino IDE, I encountered errors in the part concerning Json (upgrade from Json 5 to Json 6 was the message on IDE!).
I made some changes to the sketch, as follow:
< bool showWeather (char * json)
{
StaticJsonDocument <3 * 1024> doc;
// Skip characters until first '{' found
// Ignore chunked length, if present
char * jsonstart = strchr (json, '{');
if (jsonstart == NULL) {
Serial.println (F ("JSON data missing"));
return false;
}
json = jsonstart;
// Parse JSON
// JsonObject & root = doc.parseObject (json);
DeserializationError error = deserializeJson (doc, json);
if (error) {
Serial.print ("deserializeJson () failed with code";
Serial.println (error.c_str ());
return false;
}
// Extract weather info from parsed JSON
JsonObject current = doc ["current_observation"; >
and no more errors.
Then, after uploaded the sketch on my nodeMCU, on Serial monitor I get:
11:18:46.083 -> Connecting to api.wunderground.com
11:18:46.130 -> GET /api/030daeaxxxxxxxxxxxxxxx154fuyt6/conditions/q/Italy/Casacalenda.json HTTP/1.1
11:18:46.130 -> User-Agent: ESP8266/0.1
11:18:46.130 -> Accept: /
11:18:46.130 -> Host: api.wunderground.com
11:18:46.130 -> Connection: close
11:18:46.130 ->
11:18:46.516 -> bytesIn 179
11:18:46.516 -> respLen 180
11:18:46.516 -> JSON data missing
11:21:46.521 -> Connecting to api.wunderground.com
11:21:46.568 -> GET /api/030daeaxxxxxxxxxxxx5yut0f6/conditions/q/Italy/Casacalenda.json HTTP/1.1
Could you help me? I'm a beginner.
Thank you!
Apparently, the Weather Underground API was shut down back in 2018:
https://apicommunity.wunderground.com/weatherapi/topics/end-of-service-for-the-weather-underground-api
so this sketch cannot work.
OpenWeatherMap offers similar functionality and free APIs (for infrequent use).
Maybe worth trying?
Hello,
I am thinking of doing a project with the Adafruit Feather HUZZAH with ESP8266.
Will this code work with this development board?
Thanks in advance!