logo elektroda
logo elektroda
X
logo elektroda

How to get the weather from the OpenWeatherMap API on sockets alone? API tutorial, JSON, C

p.kaczmarek2 
📢 Listen (AI):
OpenWeather logo with an orange sun and text. .
OpenWeatherMap is a service that offers, among other things, access to current weather information for a given position on a map. This data can be easily retrieved with a single GET query, although we will need an API key beforehand, which fortunately can be obtained for free. Here I will show how to send just such a GET query, but this time without external libraries.

This topic is essentially based on my earlier OWM presentation:
ESP32 and touchscreen display - tutorial part 4 - web weather, API, JSON .
There will be a key difference here, however, and that is that I won't be using Arduino libraries here, I'll try to run the whole thing in pure C on the simplest sockets, which should be available on most platforms - including Windows (Winsock). I will also implement JSON parsing in the simplest possible way, without external libraries.

The motivation behind the topic is simple - I wanted to run my weather download on a microcontroller in an efficient and cost-effective way, reducing the use of Flash memory as much as possible. Ultimately I want to run the code on sockets with LWIP , a solution available on many embedded systems.

Running on Windows .
So let's get started. The first rather positive observation for us is that the sockets are also on Windows, so we'll do the prototype normally on a PC... .
Let's recall the previous code:
Code: C / C++
Log in, to see the code
.
Basically, we only need to implement this fragment:
Code: C / C++
Log in, to see the code
.
And here is the first surprise - behind http.GET there is not one request, but two:
- first we have to turn the domain name api.openweathermap.org into an IP address (if we don't have that in the cache)
- then we need to send a GET request to this IP address, which is basically a short HTTP packet via TCP protocol.
To retrieve the IP for a domain name, the function gethostbyname is used, which is available both on Windows/Linux and, for example, in the popular LWIP network library.
Running sockets on Windows still requires a call to WSAStartup, which I have also included in the code:
Code: C / C++
Log in, to see the code
.
Result:
Console screen showing IP address 141.95.47.140. .
We already have the IP, now it's time to send the GET request....
First we open a TCP socket (SOCK_STREAM) and establish a connection:
Code: C / C++
Log in, to see the code
.
The above condition will result in an error if there is no TCP listening on the destination IP address on the specified port. Once the connection has been successfully established, we can send a GET request, i.e. successively an HTTP 1.1 compliant GET header along with the address of the resource of interest and then permission to close the connection after the transaction:
Code: C / C++
Log in, to see the code
.
Ultimately, we'll assemble the resource address using sprintf (or better - snprintf, respecting the buffer size), but for now I've given a stiff one for a test.

Then all that was left was to receive the response and display it on the screen:
Code: C / C++
Log in, to see the code
.
Of course, let's not forget to close the socket:
Code: C / C++
Log in, to see the code
.
Result:
Windows console with weather information from OpenWeatherMap .

Now it is time to process the response. In the case of the off-the-shelf library-based method, we were getting the JSON file itself straight away, but here the response also contains an HTTP header. We have to skip it. The matter is simple - two passes to the next line in a row mark the end of it:
Code: C / C++
Log in, to see the code
.
A screenshot, this time from the Visual Studio debugger:
Screenshot of C code with Visual Studio debugger

Now it's time to extract the data from this JSON string....
Let's consider its structure (without artificial formatting):

{"coord":{"lon":-74.0059,"lat":40.7127},"weather":[{"id":804,"main":"Clouds","description":"overcast clouds","icon":"04d"}],"base":"stations","main":{"temp":274.3,"feels_like":269.25,"temp_min":272.46,"temp_max":275.13,"pressure":1024,"humidity":71,"sea_level":1024,"grnd_level":1022},"visibility":10000,"wind":{"speed":5.81,"deg":311,"gust":5.81},"clouds":{"all":100},"dt":1733227560,"sys":{"type":1,"id":4610,"country":"US","sunrise":1733227402,"sunset":1733261345},"timezone":-18000,"id":5128581,"name":"New York","cod":200}
.
The whole thing looks very simple, the key from temperature ("temp") is taken in inverted commas, followed by a colon and its value. We can search for it in the character string using strstr , but before that we will add the inverted commas and this colon. The result can be converted from a string to a floating point number using atof :
Code: C / C++
Log in, to see the code
.
Example of function use:
Code: C / C++
Log in, to see the code
.
Result:
Screenshot showing weather data from an API, including temperature and humidity for New York in JSON format. .
It works! Just why is this temperature value so strange?

Correct the temperature unit .
OpenWeatherMap sends the temperature in Kelvin by default. According to the documentation:
Quote:
.
Temperature is available in Fahrenheit, Celsius and Kelvin units. Kelvin is used by default, with no need to use the units parameter in API calls.

For temperature in Fahrenheit, use "units=imperial".

For temperature in Celsius, use "units=metric".

You can find examples of API calls in the documentation for the service you are interested in.
.
To obtain results in °C, please add your choice of unit to the query:
Screenshot showing JSON code and data processing result. .
Slightly better, is it really one degree in New York now?
Current weather forecast for New York, showing temperature, chance of precipitation, and wind speed. .
Well, almost. Let's just say it's right.


Starting on the microcontroller (here for the BK7231 example) .
In the case of the BK7231 I mainly had to include other headers, here the sockets are provided by the aforementioned LWIP:
Code: C / C++
Log in, to see the code
.
In addition, I had to put the whole thing in a thread, because the send, recv and even connect operations are blocking here:
Code: C / C++
Log in, to see the code
.
The result (on my OBK platform):
Screenshot displaying the results of an application retrieving weather data from OpenWeatherMap using an HTTP request. .
The JSON is correctly received, it is now left to parse it as desired.

Summary .
As you can see, you don't need external libraries at all to be able to quickly and efficiently run the retrieval of the current weather situation from the OpenWeatherMap API. What's more, the whole thing can often be run normally on a Windows machine (or Linux there too - there are sockets compatible with my presentation) and then conveniently ported to the embedded platform we are using.... in my case the target platform was BK7231 with LWIP , but I think that not only BK this way can apply to.
Also, extracting measurements from JSON itself has proven to be straightforward. There are off-the-shelf, advanced libraries for this such as cJSON , but as you can see, they are not always necessarily needed....
Do you see any use for this API? Perhaps a display of some sort? .
PS: Obviously the code presented is simplified, it could be improved, e.g. to protect against buffer size overruns in the JSON search function, or it could be optimised, e.g. by creating the search string manually, as the sprintf used there at the moment is quite heavy... .

About Author
p.kaczmarek2
p.kaczmarek2 wrote 12198 posts with rating 10145 , helped 580 times. Been with us since 2014 year.

Comments

metalMANiu 03 Dec 2024 22:25

. I have an idea. With information about the current cloud cover, one could compare the performance of a photovoltaic installation having actuators that follow the sun to a classic stationary installation.... [Read more]

krzbor 04 Dec 2024 00:32

Has anyone tested OpenWeather's weather forecasts over an extended period? As I used to analyse it, it didn't work very well. In any case, Google weather was much more accurate. [Read more]

pier 04 Dec 2024 09:41

A couple of years ago I made a weatherman with a colour display and esp8266 that downloaded data from OpenWeatherMap. It worked fine but a few months ago it stopped, not sure why but I suspect they changed... [Read more]

krzbor 04 Dec 2024 09:49

. I see you have been testing this for an extended period of time. What was the verifiability of the weather forecast? Was it different from other forecasts? [Read more]

pier 04 Dec 2024 09:55

. The correspondence with reality is, as we know, varied but compared to other services it was rather not different. [Read more]

Duch__ 08 Dec 2024 21:18

I only download information about the level of cloud cover based on the weather forecast from openweathermap. If it is sunny(ID 800 and 801), I lower the temperature in the house by -1 deg C on the thermostat.... [Read more]

%}