logo elektroda
logo elektroda
X
logo elektroda

ESP32 and touch display - tutorial part 4 - weather from the internet, API, JSON

p.kaczmarek2  3 5376 Cool? (+16)
📢 Listen (AI):

TL;DR

  • ESP32-2432S028R touch display project shows a simple weather station that pulls current conditions from OpenWeatherMap instead of using DHT11 or BMP280 sensors.
  • It connects over WiFi, builds an HTTP GET with latitude, longitude, and an API key, then parses the JSON response with ArduinoJSON and prints it on the TFT.
  • The example JSON for Warsaw includes 25.39°C, 43% humidity, and the description 'scattered clouds'.
  • After the API key propagates on OpenWeatherMap's servers, the request succeeds and the displayed weather matches Google closely.
  • OpenWeatherMap requires an account, API key, and rate-limit awareness, and newly created keys may take time to become active.
Generated by the language model.
.
Today we will make a simple weather display based on the ESP32. The weather will be retrieved from the internet by using one of the many free weather API type services. The project will not use any DHT11 or BMP280 type sensors, all information will be retrieved from the web via a simple HTTP request. We will also learn here how to use the API keys of the example service and process the response in JSON format.

This topic continues the series on the ESP32-2432S028R:
ESP32 and touchscreen display - tutorial - part 1 - how to program? Basics .
ESP32 and touch display - part 2 - how to draw pixels, lines, shapes, performance issues
ESP32 and touch display - tutorial part 3 - interactions, games and fun .

I have not yet decided to introduce LVGL here, LVGL will appear in the next part.


First we need to decide which of the services available for free we will use. There should be no problem here. Many of these services have some more or less restrictive limits imposed. First of all, the creation of an account is required, which only then gives us access to the so-called "API key". API here is the "application programming interface", i.e. what the application offers to us (what is externally accessible, the interface).
Additionally, even after registration there will probably be some limits, like the maximum number of API requests allowed per e.g. one hour of time, but this is not a problem for us - we are not creating a commercial product, just a small demo for our own use.
So, we look for a 'weather API' on the web and browse the offers....
One that caught my eye: https://openweathermap.org
Their offer is really rich, and there is of course also a paid API:
https://openweathermap.org/api
but we are interested in the free one. Specifically, I chose the 'CurrentWeather' API, described here:
https://openweathermap.org/current
See the documentation for the expected query format:

https://api.openweathermap.org/data/2.5/weather?lat={lat}&lon={lon}&appid={API key}
.
as well as an example response:
Code: JSON
Log in, to see the code
.
So, all we need to do is provide the latitude and longitude (along with our API key) and we already know what the weather is. This can also be plugged into a GPS, but in this theme it will implement the query "rigidly" and display the result.

Step 2 - Registration .
So we create an account on openweathermap and according to the instructions on this page we get the API key:
.
Our key will be visible in the API Keys, after a while it should have a status of "Active", but this is deceptive - more on that in a moment.
.
Now that we have the key, it's time to send the HTTP GET.... We already know the format of the arguments and responses from the documentation


Step 3 - Sending HTTP GET .
Examples of sending GET on the web abound. At PlatformIO we have libraries ready for this. It is only up to us to assemble the request URL from our key and the desired location. Sprintf will suffice for this, or perhaps better snprintf (sprintf additionally accepting the size of the target buffer):
Code: C / C++
Log in, to see the code
.
The code above just connects to WiFi and sends an HTTP request with our data. Our key is included. Will it work? What do we get?

Connecting to WiFi...
Connected to WiFi
{"cod":401, "message": "Invalid API key. Please see https://openweathermap.org/faq#error401 for more info."}
.
Surprise, it doesn't work .
Now the question is, what is wrong? This is where familiarity helps.
It is in vain that we are looking for an error in the code.
It is simply that the API key, although marked as active, needs some time to "propagate" to the service provider's servers/CDN, so we just have to wait. When I did this type of project for the first time, I was heavily surprised to find the bug in-house and then find out that it was worth the wait.

Only after some time will the JSON download correctly for us:
.
Success!

Step 4 - Arduino JSON .
Now we need to parse this text in JSON format somehow. After all, we're not going to manually write a parser that respects brackets, commas and nested objects. We have a ready-made library for this - the ArduinoJSON library, downloadable via PlatformIO:
.
.
.
I leave the installation itself without much comment, I have shown it in detail several times.
Now we need to convert our received text (String) into a JSON representation that is convenient to process.
We use the DynamicJsonDocument class, a class that uses heap memory, but we'll skip the details of how it works. The main thing is that it allows us to dynamically match any object and field of the received JSON text, such as "message":
Code: C / C++
Log in, to see the code
.

Step 5 - Transfer the data to the screen .
Now all we need to do is skilfully retrieve the data from the objects loaded from the JSON.
Let's consider an example response:
Code: JSON
Log in, to see the code
.
How do we get to the 'description' from 'weather'?
First we need to get to the 'weather' array, then to the first element from that array, and then to its 'description' field. In code, it looks like this:
Code: C / C++
Log in, to see the code
.
Analogously for the temperature and humidity fields, for example:
Code: C / C++
Log in, to see the code
.
It remains to display them on the screen - but rather we already know tft.printf ?

I don't think there's much to discuss, here's the complete demo:
Code: C / C++
Log in, to see the code

Still let's take a look at some JSON not from the documentation examples, but downloaded by me at the time of writing the code. Here is an excerpt from the console log:

{"coord":{"lon":21.0118,"lat":52.2298},"weather":[{"id":802,"main":"Clouds","description":"scattered clouds","icon":"03d"}],"base":"stations","main":{"temp":25.39,"feels_like":25.11,"temp_min":22.44,"temp_max":27.19,"pressure":1010,"humidity":43},"visibility":10000,"wind":{"speed":3.09,"deg":230},"clouds":{"all":40},"dt":1716205773,"sys":{"type":2,"id":2032856,"country":"PL","sunrise":1716172416,"sunset":1716229901},"timezone":7200,"id":756135,"name":"Warsaw","cod":200}
Weather: scattered clouds
.
.
And let's compare with the result from Google:
.
It more or less agrees. The system works!

Summary .
This is how we can download current weather information from the Internet. We can also retrieve various other information in a similar way, as long as we find the right API. Of course, the rules of the API to be used must be respected - we must not exceed the limits imposed on us. In our program, you have to follow this too - as if we were to continue with this project, the delay in the loop would have to be increased. Details are in the API documentation.
For more serious applications, a paid API should be purchased - if only calculated on the number of requests. Then you pay as much as you use. This will certainly be useful for larger and commercial applications.
Similar APIs are also offered by e.g. maps - e.g. downloading information about the map at a given coordinate point (what city, street, etc.).
I invite you to continue the project , you have the code base from me, maybe to modify the display to show the weather as graphics? An icon of clouds, sunshine? Maybe an animation of a thermometer? What do you think?
I invite you to comment, has anyone created this type of reproducible "weather station"? .
PS: I guess the biggest pitfall with projects like this is that there is sometimes a bit of a wait to activate the API key, and it's worth being patient rather than looking for a non-existent bug in the code....

About Author
p.kaczmarek2
p.kaczmarek2 wrote 14460 posts with rating 12470 , helped 650 times. Been with us since 2014 year.

Comments

Erbit 23 Jul 2024 11:13

. I don't want to look in the documentation... ;) Do I understand correctly that we can use our key to check the weather anywhere in the world (given the relevant geographical data)? [Read more]

p.kaczmarek2 23 Jul 2024 11:26

Yes, you can check any location. The key is not assigned to a location and your location is not checked in any way at the registration stage. The only thing that limits you is the query limit, which... [Read more]

p.kaczmarek2 03 Dec 2024 15:43

Due to a lot of interest, I decided to make up an additional presentation - using the OpenWeatherMap API on pure sockets and JSON parsing without external libraries . I invite interested parties to... [Read more]

FAQ

TL;DR: A working ESP32 weather display can show 3 live values and, as the author notes, "The system works!" It targets ESP32-2432S028R users who want internet weather on a touch screen using OpenWeatherMap, HTTP GET, and ArduinoJson, while avoiding common setup traps like the temporary 401 key error. [#21161471]

Why it matters: This project shows the shortest path from Wi-Fi connection to a usable on-screen weather UI without adding local sensors.

Approach Data source Hardware dependency Typical output in thread Main trade-off
OpenWeatherMap API Internet HTTP request Wi-Fi only Weather, temperature, humidity Needs API key and request limits
DHT11/BMP280 sensors Local sensor reading Extra sensor required Not used in this project No internet, but no web data
Pure sockets + manual JSON parsing Internet HTTP over sockets Wi-Fi only Mentioned as an extra tutorial More control, more coding effort

Key insight: The biggest practical pitfall is not the ESP32 code but the API key delay. A key can appear Active yet still return 401 Invalid API key until the provider finishes propagation.

Quick Facts

  • The demo targets the ESP32-2432S028R touch display board and uses TFT_eSPI, XPT2046_Touchscreen, WiFi.h, HTTPClient.h, and ArduinoJson in one project stack. [#21161471]
  • The example allocates a 256-byte URL buffer with snprintf and a 1024-byte DynamicJsonDocument, which is enough for the shown weather fields. [#21161471]
  • The first polling loop waits 10,000 ms, while the finished demo delays for 60 × 60 × 1000 ms, reducing request frequency to about once per hour. [#21161471]
  • A real sample response shown in the thread reports 25.39 C temperature and 43 % humidity for Warsaw, confirming the parser and display path work end to end. [#21161471]
  • One free OpenWeatherMap key can query weather for any location in the world; the practical limit is the service’s request quota, not account location binding. [#21164637]

How do I build a simple weather display on an ESP32-2432S028R touch screen using OpenWeatherMap and JSON?

Build it in three steps. 1. Connect the ESP32-2432S028R to Wi-Fi with WiFi.begin(). 2. Send an OpenWeatherMap HTTP GET using your city or coordinates plus appid. 3. Parse the JSON and print weather, temperature, and humidity with tft.printf(). The thread’s complete demo uses TFT_eSPI, HTTPClient.h, and ArduinoJson, then refreshes roughly once per hour with delay(60 * 60 * 1000). [#21161471]

Why does OpenWeatherMap return a 401 "Invalid API key" error on ESP32 even when the key is marked Active?

It returns 401 because the key may be marked Active before it has fully propagated across the provider’s servers or CDN. The thread shows this exact case: the ESP32 sends a correct request, receives {"cod":401,"message":"Invalid API key"}, and then starts working later without code changes. The practical fix is to wait and retest instead of debugging a non-existent firmware bug. [#21161471]

What is an API key in OpenWeatherMap, and how is it used in an ESP32 HTTP weather request?

An API key is the credential that authorizes your ESP32 to use the weather service. "API key" is an access credential that identifies your application to a web API, authorizes requests, and lets the provider enforce limits such as the maximum number of calls per hour. In the thread, the key is inserted into the request URL as appid=%s and combined with the city name or coordinates before http.GET(). [#21161471]

What is JSON parsing in ArduinoJson, and why is it useful for ESP32 weather projects?

JSON parsing converts the text returned by the server into fields your ESP32 code can read directly. "JSON parsing" is a data-processing step that turns a JSON text response into structured objects and arrays, so code can access nested fields like weather[0].description without writing a manual parser for braces, commas, and child objects. That saves time and reduces errors in weather projects. [#21161471]

How do I send an HTTP GET request from ESP32 with WiFi.h and HTTPClient.h to read current weather data?

Connect to Wi-Fi, build the URL, call http.begin(url), then run http.GET(). In the thread, the ESP32 first loops until WiFi.status() == WL_CONNECTED, then creates a HTTPClient, formats a 256-byte URL buffer with snprintf, and reads the response with http.getString(). If httpCode > 0, the payload is ready for JSON parsing; otherwise, print the HTTP error code. [#21161471]

What is the correct OpenWeatherMap request URL format for querying weather by city or by latitude and longitude?

The thread shows two valid patterns. By city, it uses http://api.openweathermap.org/data/2.5/weather?q=%s&appid=%s&units=metric. By coordinates, it cites the documented format .../weather?lat={lat}&lon={lon}&appid={API key}. The city form is simpler for a fixed location, while the latitude and longitude form is better when GPS or precise positioning is available. [#21161471]

How do I extract the weather description, temperature, and humidity from an OpenWeatherMap JSON response with ArduinoJson?

Read them from the parsed document using the field paths shown in the thread. The weather description comes from doc["weather"][0]["description"], temperature from doc["main"]["temp"], and humidity from doc["main"]["humidity"]. The sample live output confirms this works: Warsaw returned 25.39 C and 43 % humidity, and the console printed Weather: scattered clouds. [#21161471]

Why is snprintf used to build the OpenWeatherMap URL on ESP32 instead of sprintf?

snprintf is used because it also takes the destination buffer size, which makes URL construction safer on a microcontroller. The thread explicitly recommends it over sprintf for this reason and demonstrates snprintf(url, sizeof(url), apiUrl, city, apiKey); with a 256-byte char url[256]. That helps prevent buffer overflow when combining city names, keys, and query parameters. [#21161471]

How should I display parsed weather data on a TFT_eSPI screen with tft.printf on the ESP32-2432S028R?

Clear the screen, set text style, then print the parsed values line by line with tft.printf(). The demo uses tft.fillScreen(TFT_WHITE), tft.setTextColor(TFT_BLACK, TFT_WHITE), tft.setTextSize(2), and tft.setCursor(0, 0), then prints Weather, Temp, and Humidity. If the API returns an error instead of cod = 200, it prints the server message on the display instead. [#21161471]

What causes JSON parse errors on ESP32 when reading weather data from OpenWeatherMap, and how do I troubleshoot them?

JSON parse errors happen when the payload is not valid JSON for the expected structure or when you try to parse the wrong response. First check the HTTP result and print the raw payload. In this project, a common failure case is a 401 response with an error message instead of weather data. Next, verify the key, wait for activation propagation, and confirm your DynamicJsonDocument(1024) is large enough for the fields you read. [#21161471]

How do OpenWeatherMap free API limits affect an ESP32 weather station, and how often should I poll the service?

Free API limits mean your ESP32 must avoid frequent polling, especially if you plan to scale beyond a demo. The author states you must respect the provider’s limits and notes that a commercial product will start exceeding free usage faster than a hobby build. In the finished example, the refresh delay is increased from 10,000 ms to 60 × 60 × 1000 ms, which is a practical low-frequency pattern for a simple weather station. [#21164637]

What are the differences between using OpenWeatherMap with ArduinoJson and parsing JSON manually over pure sockets in C?

ArduinoJson is faster to implement, while pure sockets with manual parsing offer more control and fewer external dependencies. The main tutorial uses HTTPClient.h plus ArduinoJson to decode nested fields cleanly. A later follow-up thread adds a second method: using the OpenWeatherMap API on pure sockets and parsing JSON without external libraries. Choose ArduinoJson for quick results and the socket-only path when you want a lower-level C implementation. [#21330955]

How can I query weather for any location in the world with one OpenWeatherMap API key using city names or GPS coordinates?

Use the same key for any location and change only the query parameters. The follow-up discussion states clearly that the key is not tied to one place and registration does not bind it to your location. You can query by city, as in q=Warsaw, or by latitude and longitude, which makes GPS integration possible. The real limit is request quota, not geography. [#21164637]

Which approach is better for an ESP32 weather display: internet API data from OpenWeatherMap or local sensors like DHT11 and BMP280?

Internet API data is better when you want ready-made current weather without adding sensors. The thread explicitly avoids DHT11 and BMP280 and pulls all data from the web through one HTTP request. That simplifies hardware and gives fields like weather description, not just local measurements. Local sensors are better only when you need purely on-device readings and no network dependency. [#21161471]

What are some practical ways to extend this ESP32 touch weather project with icons, animations, GPS input, or LVGL?

You can extend it by adding weather graphics, animated indicators, GPS-based coordinates, or a richer GUI layer. The author suggests icons for clouds and sunshine, a thermometer animation, and notes that GPS can feed the latitude and longitude query. The post also says LVGL was not used yet and was planned for the next part, making it the natural UI upgrade path for this touch display project. [#21161471]
Generated by the language model.
%}