Weather from owm c++

hello,
i 'm trying to build an esphome app, working without home-assistant .
i need to get the weather from openweathermap api but it’s too hard to me, i don’t know c++ or how to achieve this.
i have tried http_request . i have checked platform.io ,i’ve tried to include *.h files.i have tried lot of things but i can’t get something work because i havn’t enough knowledge.
i don’t know neither write some lambda to get the rest api works in esphome.
could you help me? thx u

hello
i found this :

it seems to work
i had to download HttpClient from platform.io
and modify some line to get it work:

#include "HttpClient.h"

and

WiFiClient client;
HTTPClient http;
http.begin(client, serverName);

then i added this to my esphome yaml:

sensor:
  - platform: custom
    lambda: |-
      auto my_sensor = new OWSensor();
      App.register_component(my_sensor);
      return {my_sensor->temperature_sensor, my_sensor->rain_sensor, my_sensor->wind_sensor, my_sensor->weatherid_sensor};

    sensors:
    - name: "here_Temperature_Sensor"
      unit_of_measurement: °C
      accuracy_decimals: 1
    - name: "here_ rain_sensor"
    - name: "here_wind_sensor"
      unit_of_measurement: km/h
      accuracy_decimals: 1
    - name: "here_weatherid"

One minute after boot i can read this in logs:

[02:14:14][D][owsensor:049]: HTTP Response code: '200'
[02:14:14][D][sensor:092]: 'here_ rain_sensor': Sending state 5.00000  with 0 decimals of accuracy
[02:14:14][D][sensor:092]: 'here_wind_sensor': Sending state 4.63000 km/h with 1 decimals of accuracy
[02:14:14][D][sensor:092]: 'here_weatherid': Sending state 500.00000  with 0 decimals of accuracy

but next minutes it report only 0

[D][owsensor:049]: HTTP Response code: '200'e
[D][sensor:092]: 'here Temperature Sensor': Sending state 0.00000 °C with 1 decimals of accuracye
[D][sensor:092]: 'here_ rain_sensor': Sending state 0.00000  with 0 decimals of accuracye
[D][sensor:092]: 'here_wind_sensor': Sending state 0.00000 km/h with 1 decimals of accuracye
[D][sensor:092]: 'here_weatherid': Sending state 0.00000  with 0 decimals of accuracye

could you help me thx

You can also add HttpClient to the libraries section in your yaml (see ESPHome Core Configuration — ESPHome). The same effect but it more automated for the future.

Not sure why that happens. One idea I had was: Maybe there some kind of rate limiting to limit the requests you can make in a short time?

Also the C++ code in the feature request has a memory leak (quite a big one actually, the payload array created with new[] never gets deleted), that may cause the issue not sure.

Can you post the exact same C++ code you are using. Then we can fix the memory leak and maybe that fixes it.

hi, thanks u
the code i use

#include "esphome.h"
#include "HttpClient.h"
#include "ArduinoJson.h"

class OWSensor : public PollingComponent {
public:
	Sensor *temperature_sensor = new Sensor();
	Sensor *rain_sensor = new Sensor();
	Sensor *wind_sensor = new Sensor();
	Sensor *weatherid_sensor = new Sensor();
  
	OWSensor() : PollingComponent(60000) { }
	
	const char *TAG = "owsensor";
	String openWeatherMapApiKey = "f53c8bdxxxxxxxxx";
	String lat = "45.6067";
	String lon = "4.8399";
	String serverPath = "http://api.openweathermap.org/data/2.5/onecall?lat=" + lat + "&lon=" + lon + "&exclude=minutely,hourly,alerts" + "&units=metric" + "&APPID=" + openWeatherMapApiKey;

	void setup() override {

	}

	void update() override {
		
		float *data = getWeatherData();
		
		temperature_sensor->publish_state(data[0]);
		
		rain_sensor->publish_state(data[1]);
		
		wind_sensor->publish_state(data[2]);
		
		weatherid_sensor->publish_state(data[3]);

	}
	
	char *httpGETRequest(const char* serverName) {
		
		WiFiClient client;
		HTTPClient http;
		http.begin(client, serverName);

		int httpResponseCode = http.GET();

		String temp = "{}"; 

		if (httpResponseCode>0) {
			ESP_LOGD(TAG, "HTTP Response code: '%i'", httpResponseCode);
			temp = http.getString();
		}
		else {
			ESP_LOGW(TAG, "Error code: '%i'", httpResponseCode);
		}
		
		http.end();
		
		char *payload = new char[temp.length()+1];
		strcpy(payload, temp.c_str());

		return payload;

	}
	
	float *getWeatherData() {
		
		char *global_json_build_buffer = nullptr;
		global_json_buffer.clear();
		JsonObject &root = global_json_buffer.parseObject(httpGETRequest(serverPath.c_str()));
		
		float *data = new float[4];
		
		data[0] = root["current"]["temp"];
		
		data[1] = root["daily"][0]["pop"];
		data[1] = data[1]*100;
		
		data[2] = root["current"]["wind_speed"];
		
		data[3] = root["current"]["weather"][0]["id"];
		
		return data;
		
	}
  
};

open weather map say 60 requests per minutes on the free plan.
after a few min…an error showing

[W][owsensor:053]: Error code: '-11'

seems to be http 411: Content-Length header

I made a few changes. It is still not very nice code, but the memory leak should be fixed. Let’s see if that makes a difference.

#include "esphome.h"
#include "HttpClient.h"
#include "ArduinoJson.h"

class OWSensor : public PollingComponent {
public:
	Sensor *temperature_sensor = new Sensor();
	Sensor *rain_sensor = new Sensor();
	Sensor *wind_sensor = new Sensor();
	Sensor *weatherid_sensor = new Sensor();
  
	OWSensor() : PollingComponent(60000) { }
	
	const char *TAG = "owsensor";
	String openWeatherMapApiKey = "f53c8bdxxxxxxxxx";
	String lat = "45.6067";
	String lon = "4.8399";
	String serverPath = "http://api.openweathermap.org/data/2.5/onecall?lat=" + lat + "&lon=" + lon + "&exclude=minutely,hourly,alerts" + "&units=metric" + "&APPID=" + openWeatherMapApiKey;
	WiFiClient client;
        float data[4] = {};

	void setup() override {

	}

	void update() override {
		
		bool success = getWeatherData();
		if(!success)
			return;                
		
		temperature_sensor->publish_state(data[0]);
		
		rain_sensor->publish_state(data[1]);
		
		wind_sensor->publish_state(data[2]);
		
		weatherid_sensor->publish_state(data[3]);

	}
	
	String httpGETRequest(const char* serverName) {
		
		
		HTTPClient http;
		http.begin(client, serverName);

		int httpResponseCode = http.GET();

		String temp = "{}"; 

		if (httpResponseCode>0) {
			ESP_LOGD(TAG, "HTTP Response code: '%i'", httpResponseCode);
			temp = http.getString();
		}
		else {
			ESP_LOGW(TAG, "Error code: '%i'", httpResponseCode);
		}
		
		http.end();
		
		return tmp;

	}
	
	bool getWeatherData() {
		global_json_buffer.clear();
		JsonObject &root = global_json_buffer.parseObject(httpGETRequest(serverPath.c_str()));
		if(!root.success()) {
			return false;
		}
		
		
		data[0] = root["current"]["temp"];
		
		data[1] = root["daily"][0]["pop"];
		data[1] = data[1]*100;
		
		data[2] = root["current"]["wind_speed"];
		
		data[3] = root["current"]["weather"][0]["id"];
		return true;
		
	}
  
};

I did not test if it compile. So there may be errors. If you can not fix those, please report back with the detailed compile errors.

The code is still missing error handling for the result. For example if there is no value for “current” because some temporary issue in the source api you will get “0”. The simplest way to handle this would be a filter in your yaml to filter out values of “0”.

thanks you.
i ll see that as soon as possible maybe tonight.

first i corrected the line 61

return tmp; 
return temp;

then i moved back to line 45 :

WiFiClient client;

now it start, i have an http code 200 ,but no data (0) and it reboot as soon it publish this 200 code

Hi,
I’m struggling to get openweather data in my esp32 using the code above, but with no luck.
I mean it doesn’t even compile …
Could you help me with some information / guidance?

using HTTPClient http; gives this error when compiling:

Compiling /data/ic-05/.pioenvs/ic-05/src/main.cpp.o
In file included from src/main.cpp:25:0:
src/openweather.h: In member function 'char* OWSensor::httpGETRequest(const char*)':
src/openweather.h:41:3: error: 'HTTPClient' was not declared in this scope
   HTTPClient http;
   ^
src/openweather.h:42:3: error: 'http' was not declared in this scope
   http.begin(client, serverName);
   ^
src/openweather.h: In member function 'float* OWSensor::getWeatherData()':
src/openweather.h:68:3: error: 'global_json_buffer' was not declared in this scope
   global_json_buffer.clear();
   ^
*** [/data/ic-05/.pioenvs/ic-05/src/main.cpp.o] Error 1

changing to HttpClient http; gives this error:

Compiling /data/ic-05/.pioenvs/ic-05/src/main.cpp.o
In file included from src/main.cpp:25:0:
src/openweather.h: In member function 'char* OWSensor::httpGETRequest(const char*)':
src/openweather.h:41:14: error: no matching function for call to 'HttpClient::HttpClient()'
   HttpClient http;
              ^
In file included from src/openweather.h:2:0,
                 from src/main.cpp:25:
/data/ic-05/.piolibdeps/ic-05/HttpClient/HttpClient.h:50:5: note: candidate: HttpClient::HttpClient(Client&)
     HttpClient(Client& aClient);
     ^
/data/ic-05/.piolibdeps/ic-05/HttpClient/HttpClient.h:50:5: note:   candidate expects 1 argument, 0 provided
/data/ic-05/.piolibdeps/ic-05/HttpClient/HttpClient.h:37:7: note: candidate: constexpr HttpClient::HttpClient(const HttpClient&)
 class HttpClient : public Client
       ^
/data/ic-05/.piolibdeps/ic-05/HttpClient/HttpClient.h:37:7: note:   candidate expects 1 argument, 0 provided
/data/ic-05/.piolibdeps/ic-05/HttpClient/HttpClient.h:37:7: note: candidate: constexpr HttpClient::HttpClient(HttpClient&&)
/data/ic-05/.piolibdeps/ic-05/HttpClient/HttpClient.h:37:7: note:   candidate expects 1 argument, 0 provided
In file included from src/main.cpp:25:0:
src/openweather.h:42:8: error: 'class HttpClient' has no member named 'begin'
   http.begin(client, serverName);
        ^
src/openweather.h:44:31: error: 'class HttpClient' has no member named 'GET'
   int httpResponseCode = http.GET();
                               ^
src/openweather.h:50:16: error: 'class HttpClient' has no member named 'getString'
    temp = http.getString();
                ^
src/openweather.h:56:8: error: 'class HttpClient' has no member named 'end'
   http.end();
        ^
src/openweather.h: In member function 'float* OWSensor::getWeatherData()':
src/openweather.h:68:3: error: 'global_json_buffer' was not declared in this scope
   global_json_buffer.clear();
   ^
*** [/data/ic-05/.pioenvs/ic-05/src/main.cpp.o] Error 1

thanks