janbenes
(Jan Benes)
April 30, 2021, 11:15am
1
Hello. I would like to make esphome sensor independent on Home Assistant in that it reads weather forecast from openweathermap and controls some switches (roolls up exterior blinds if wind is coming).
I can read forecast by http_request.get and it is in JSON, XML or HTTP format. Can I convert from these formats to variables in esphome, or do I need to do it in C++ lambda?
Thanks, Jan
Troon
(Troon)
April 30, 2021, 11:53am
2
Paste the response that you’re getting here and we’ll have a shot. Use the preformatted text button in the editor when posting code.
{"your code": "should end up looking like this"}
{“not”: “like this”}
janbenes
(Jan Benes)
April 30, 2021, 3:45pm
3
Thanks. The response looks like this, forecast is in section “weather” and I am looking for value “list.wind.speed”:
{"cod":"200","message":0,"cnt":1,"list":[{"dt":1619805600,"main":{"temp":287.83,"feels_like":286.5,"temp_min":284.84,"temp_max":287.83,"pressure":1010,"sea_level":1010,"grnd_level":987,"humidity":44,"temp_kf":2.99},"weather":[{"id":801,"main":"Clouds","description":"few clouds","icon":"02d"}],"clouds":{"all":24},"wind":{"speed":4.43,"deg":18,"gust":8.14},"visibility":10000,"pop":0,"sys":{"pod":"d"},"dt_txt":"2021-04-30 18:00:00"}],"city":{"id":3067696,"name":"Prague","coord":{"lat":50.088,"lon":14.4208},"country":"CZ","population":1165581,"timezone":7200,"sunrise":1619753998,"sunset":1619806732}}
janbenes
(Jan Benes)
April 30, 2021, 11:27pm
4
Solved it! Following code works. It finds third forecast of hourly wind speed, which is 1-2 hours ahead of current time:
(please note that I was getting some crashes on ESP8266, but not on ESP32. Seems to be memory problem)
sensor:
- platform: template
name: "Predicted wind"
id: predicted_wind
http_request:
useragent: esphome/device
timeout: 10s
time:
- platform: sntp
on_time:
- seconds: 0
minutes: /15
then:
- lambda: |-
HTTPClient http;
http.begin("http://api.openweathermap.org/data/2.5/onecall?lat=51&lon=14&appid=974---------------8c0d&lang=cz&exclude=minutely,daily,alerts");
http.GET();
DynamicJsonBuffer doc(31000); //cannot be smaller, response is big!
JsonObject& root = doc.parseObject(http.getStream());
float ws = atof(root["hourly"][2]["wind_speed"].as<char*>());
id(predicted_wind).publish_state(ws);
//ESP_LOGD("main", "############## %s", root["hourly"][2]["wind_speed"].as<char*>()); //.as<char*>());
4 Likes
Troon
(Troon)
May 1, 2021, 7:10am
5
Great job! These little devices really can do a lot, can’t they?
Is this code up to date with the last version? I’m getting an error
esphome.yaml:119:7: error: 'HTTPClient' was not declared in this scope
janbenes
(Jan Benes)
June 7, 2021, 6:23pm
7
Do you have this declaration in yaml?
http_request:
useragent: esphome/device
timeout: 5s #30s
N1rv9
November 15, 2021, 9:36am
8
It’s not working for me, esp is restarting with the following error:
Guru Meditation Error: Core 1 panic’ed (LoadProhibited). Exception was unhandled
janbenes
(Jan Benes)
November 15, 2021, 4:16pm
9
Do you use esp32? It did not work for me very well with esp8266.
N1rv9
November 15, 2021, 4:39pm
10
I am using a esp32.
I’m trying to make a GET request from the following site:
http://ip-api.com/json/
I have a feeling it has to do with the buffer
janbenes
(Jan Benes)
November 15, 2021, 6:11pm
11
That should not be a problem give me email and I will send you whole script that uses weather json
N1rv9
November 15, 2021, 7:24pm
12
janbenes:
DynamicJsonBuffer
Thank you, I sent you a PM.
Where does the DynamicJsonBuffer come from? that’s definitely what’s cousing the trouble.
Hello,
I am interrested also in getting the public IP and displaying as a sensor value. The API I would like to use is https://wasab.is/ but the other mentioned here should work as well. Is it possible to get an example code snippet on how is this done?
Thank You!
Did the following:
http_request:
esp8266_disable_ssl_support: true
time:
...
- seconds: 0
minutes: /15
then:
- lambda: |-
HTTPClient http;
http.begin("http://wasab.is/json");
http.GET();
DynamicJsonBuffer doc(12000);
JsonObject& root = doc.parseObject(http.getStream());
float ip = atof(root["ip"].as<char*>());
id(public_ip_test).publish_state(ip);
sensor:
- platform: template
name: "Public IP"
id: public_ip_test
icon: mdi:wan
Unfortunately this does return only the first 4 characters from the IP address in the “sensor” value. I don’t have developer experienc so this is somewhat above my knowledge.
brendann
(Brendan)
January 6, 2022, 5:15am
15
@eisengrau Not sure if you ended up getting it solved yourself but the below works.
Main changes is a “text_sensor” rathar than just a sensor and chagning the ip variable to a const char* rather than float. Note I am fairly new to C++ so there may be a more correct way
http_request:
esp8266_disable_ssl_support: true
time:
...
- seconds: 0
minutes: /15
then:
- lambda: |-
HTTPClient http;
http.begin("http://wasab.is/json");
http.GET();
DynamicJsonBuffer doc(12000);
JsonObject& root = doc.parseObject(http.getStream());
const char* ip = root["ip"].as<char*>();
id(public_ip_test).publish_state(ip);
text_sensor:
- platform: template
name: "Public IP"
id: public_ip_test
icon: mdi:wan
ploto22
(Paolo)
March 4, 2022, 11:14pm
16
Hello janbenes
great job.
Can i use your support for extract “description” field in json array ?
Sorry but i am not expert in lambda language.
This is the json complete:
{"coord":{"lon":14,"lat":51},"weather":[{"id":800,"main":"Clear","description":"cielo sereno","icon":"01n"}],"base":"stations","main":{"temp":-0.75,"feels_like":-0.75,"temp_min":-2.12,"temp_max":0.64,"pressure":1022,"humidity":89},"visibility":10000,"wind":{"speed":0.45,"deg":337,"gust":0.89},"clouds":{"all":10},"dt":1646435168,"sys":{"type":2,"id":2008644,"country":"DE","sunrise":1646458837,"sunset":1646499047},"timezone":3600,"id":2867920,"name":"Mühlsdorf","cod":200}
Where can i find some documentation to study this function
Thanks a lot for your support
I used the HTTP Request docs on ESPHome.io as a basis and ended up with this (simpler) code:
http_request:
useragent: esphome/esp32dev
id: http_request_data
sensor:
- platform: template
name: "Air temperature"
id: air_temp
time:
- platform: sntp
id: sntp_time
on_time:
# Every 5 minutes
- seconds: 0
minutes: /5
then:
- http_request.get:
url: https://api.openweathermap.org/data/2.5/weather?q=oulu&appid=******************************************&units=metric
headers:
Content-Type: application/json
verify_ssl: false
on_response:
then:
- lambda: |-
json::parse_json(id(http_request_data).get_string(), [](JsonObject root) {
id(air_temp).publish_state(root["main"]["temp"]);
});
Every five minutes, it fetches my local weather info from OpenWeather and extracts the air temperature from the JSON object. It works to perfection.
2 Likes
Hello, sorry for the late reply. Unfortunately this did not work for me. I’m getting the following errors before complie:
/root/esphome/iot-esp8266-test.yaml:80:11: warning: unknown escape sequence: '\/'
80 | DynamicJsonBuffer doc(12000);
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/root/esphome/iot-esp8266-test.yaml:80:11: error: DynamicJsonBuffer is a class from ArduinoJson 5. Please see https://arduinojson.org/upgrade to learn how to upgrade your program to ArduinoJson version 6
Compiling .pioenvs/iot-esp8266-test/lib4d9/ESP8266WiFi/CertStoreBearSSL.cpp.o
/root/esphome/iot-esp8266-test.yaml: In lambda function:
/root/esphome/iot-esp8266-test.yaml:80:25: error: 'doc' was not declared in this scope
80 | DynamicJsonBuffer doc(12000);
| ^~~
This is with latest ESPhome 2022.5.1.
Disregard, my last comment. Managed to do it by @epollari 's example above My final config looks like:
# Time config & External IP
http_request:
esp8266_disable_ssl_support: true
useragent: esphome/esp32dev
id: http_request_test
time:
- platform: homeassistant
timezone: Europe/Amsterdam
on_time:
- seconds: 0
minutes: /30
then:
- http_request.get:
url: http://wasab.is/json
headers:
Content-Type: application/json
verify_ssl: false
on_response:
then:
- lambda: |-
json::parse_json(id(http_request_test).get_string(),[](JsonObject root){id(public_ip_test).publish_state(root["ip"]);});
text_sensor:
- platform: template
name: "Public IP"
id: public_ip_test
icon: mdi:wan
Thank you for your awesomeness!
1 Like