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

Attachments

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.

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.

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.