Introduction: NODEMCU LUA ESP8266 Get Weather for Your City (Updated)
To use these programs, you need to have the sjson and rtctime modules installed in your firmware.
You need to create an account with openweathermap.org to get an API key.
I have included 2 programs, one demonstrates how to decode various json strings and the other gets weather details from a server.
The weather program is pretty much a standard GET request from a server and then decoding a json string.
Step 1: Building the Modules
I find the Cloud Build Service very easy to use at https://nodemcu-build.com/
You need to ensure that you have got the sjson and rtctime modules in your build - sjson has now replaced cjson in the build. When building the firmware, you seem to max out at 24 modules, so you have to be selective.
Load your new build into 0x00000.
Note: Load esp_init_data_default.bin at 0x3FC000 otherwise your flash will not work!
More info here https://nodemcu.readthedocs.io/en/dev/en/flash/
I am using a WeMos D1 mini for this project, although it should work on any ESP8266.
Step 2: JSON Files
JSON stands for JavaScript Object Notation, they are strings of text in a special format.
JSON syntax is derived from JavaScript object notation syntax:
- Data is in name/value pairs
- Data is separated by commas
- Curly braces hold objects
- Square brackets hold arrays
A simple example is myObj = {"name":"John", "age":34}
In nodemcu it is declared as:
myObj = '{"name":"John", "age":34}' myObj = [[{"name":"John", "age":34}]] myObj = "{\"name\":\"John\", \"age\":34}"
The important thing to remember is that json strings use double quotes, so we have to hold them in single quotes, double square brackets or escape the double quote (\"). All 3 lines have the same meaning in nodemcu.
myObj1 = '{"name":"John", "age":34}' myObj2 = [[{"name":"John", "age":34}]] myObj3 = "{\"name\":\"John\", \"age\":34}" print(myObj1) print(myObj2) print(myObj3)
result
{"name":"John", "age":34} {"name":"John", "age":34} {"name":"John", "age":34}
I have included a file (json.lua) with some examples of JSON strings and how to manipulate them. Take a bit of time to study how they work.
One example from the program is
posn = '{"lon":-2.47,"lat":53.67}' t = sjson.decode(posn) for k,v in pairs(t) do print(k,v) end print("Longitude = "..t.lon) print("Latitude = "..t.lat)
The variable posn holds the json string.
posn is decoded to variable t
It can be read in two different ways: inside a for loop or as t.lon or t.lat.
result
lon -2.47 lat 53.67 Longitude = -2.47 Latitude = 53.67
Step 3: Create an Account
To get a weather update, you need to set up an account with a weather provider and get an API key so we can access their site.
You get your API key here: https://home.openweathermap.org/api_keys. The API key is 32 characters long and looks something like 74563a891225dce1a5796d1faddc5e41.
You can also get your city code from their website or Cities' ID List. It decrompresses into a json file of over 18Mb and contains cities from all over the world and includes their Latitude and Longitude positions.
For example in the UK, city code for Rishton is 2639310, and Preston is 2639912.
The weather program uses an API key and a city code.
Step 4: Programming
The program weather.lua gets the weather information from openweathermap.org and displays the contents of the json payload.This is an example of what is returned.
{"coord":{"lon":-2.41,"lat":53.77}, "weather":[{"id":803,"main":"Clouds","description":"broken clouds","icon":"04d"}], "base":"stations", "main":{"temp":14.8,"pressure":996,"humidity":82,"temp_min":14,"temp_max":16}, "visibility":10000, "wind":{"speed":7.7,"deg":320}, "clouds":{"all":75}, "dt":1498755000, "sys":{"type":1,"id":5098,"message":0.0041,"country":"GB","sunrise":1498707755,"sunset":1498769020}, "id":2639310, "name":"Rishton", "cod":200}
You have to make sense of all this information and my program tries to do that.
Sample output from weather program.
Connected to openweathermap.org Weather for Rishton GB Long -2.41 Lat 53.77 ID 2639310 Temperature 16.25 °C Max Temp 17 °C Min Temp 15 °C Pressure 1008 hPa Humidity 82% Visibility 10000 m id 500 Main Rain Description light rain Windspeed 7.2 Wind dir 320 Sunrise 3.43 Sunset 20.43 Date 14.50 30/6/2017
One thing to notice with the array is that it is indexed before the final item forecast.weather[1].id.
Attachments
Step 5: Additional Material
Since I wrote this instructable, I have taken the project further and can now display the weather in a browser.
Key 192.168.0.50 into your browser once you have successfully run weather2.lua.
Weather2.lua is an extension of weather.lua.
Attachments
Step 6: Conclusion
The programs show how to decode a json string and make some sense of it.
The program could be taken further and a weather icon could be displayed on a LCD screen with the weather information, instead of in a browser.
You don't have to use openweathermap.org, as other API weather providers give similar information. The json string is just encoded differently, so you have to tweak the code to match this.
I have included another program here that works with apixu.com API weather. It is not as refined as the other 2, but you will get the general idea. I find that apixu is an easier site to navigate than openweathermap.org.
Instead of displaying all the individual items with a caption, I have dumped all the data into 2 arrays (key{} and value{}) and then displayed their contents. There are no arrays in the json string from apixu.com making for simpler decoding.