In this ESP32 tutorial we will check how to serve JSON content from a Picoweb app. The tests shown here were performed using a DFRobot’s ESP32 module device integrated in a ESP32 development board.
Introduction
In this ESP32 tutorial we will check how to serve JSON content from a Picoweb app. For an introduction on Picoweb, please consult this previous post. For an explanation on how to work with JSON on MicroPython, please check here.
The tests were performed using a DFRobot’s ESP32module device integrated in a ESP32 development board. The code development was done on uPyCraft, a MicroPython IDE. You can check how to use uPyCraft in this previous post.
The code
The code for this will be very simple and most of the functionalities used have already been covered in previous posts.
So we start our script by importing the picoweb module and the ujson module, which are needed to create our app and to process the JSON we are going to send back to the client. Additionally, we will import the network module, which we will use to connect the ESP32 to a WiFi network.
import picoweb
import network
import ujson
In the previous posts about Picoweb we were statically assigning to the app the IP obtained when connecting to a WiFi network, but in this tutorial we will see how to do it dynamically. Thanks to Siva Kumar for pointing this method out.
You can also check in more detail the description of the functions we will use to connect to the WiFi network on this previous post.
So, we will store in two variables both the WiFi network SSID (network name) and password needed to connect to it. Next, we will obtain an instance of the WiFi station interface, which we will then need to connect to the network.
Then we activate the network interface with a call to the active method and passing as input the Boolean value True. Finally, we call the connect method and pass as input the SSID and the password of the network, stored in the previously declared variables.
ssid = "yourNetworkName"
password = "yourNetworkPass"
station = network.WLAN(network.STA_IF)
station.active(True)
station.connect(ssid, password)
Since it will take a while for the connection to be established, we will now poll the network interface until the procedure is complete, in order to proceed to the remaining code. We can check if the connection is already established with a call to the isconnected method.
After that, we will get the IP assigned to our ESP32 on the network with a call to the ifconfig function. We will store the result in a variable, since we will later use it to bind our Picoweb app to the IP assigned.
while station.isconnected() == False:
pass
ip = station.ifconfig()
Once we finish the WiFi network connection related procedures, we will now take care of creating our Picoweb app. So, we will follow what we have seen in previous posts and start by creating an instance of the Picoweb app.
Then we will declare a dictionary variable to hold the data we are going to send to the client in JSON format. For this simple example we will hard code the values in this data structure, but in a real application we could get them from sensors, for example.
Our dictionary will be very simple and will have an entry to represent the type of sensor and another to represent a measurement. You can play with other structures for the data and check the results.
app = picoweb.WebApp(__name__)
jsonData = {"sensor":"temperature","value": "10"}
For simplicity, our app will only have a route to serve the JSON content and thus we can use the index one, which corresponds to the “/” URL.
In the route handling function, we will convert the dictionary object to a JSON string representation. To do it, we simply need to call the dumps method of the ujson module, passing as input the dictionary object we defined before.
Then we start the response to the received request with a call to the start_response method from the picoweb module, which will take care of sending the first parts of the HTTP protocol response to the client.
One of the parameters that it sends back to the client is the content-type. As can be seen from this previous post, the default value for the content-type is “text/html” and thus we need to change it to “application/json”, which is the data format we will return. This is done by simply passing the “application/json” string as the content_type parameter.
Finally, we send the JSON string to the client, passing it as input of the awrite method of the response object. Remember that the response object is one of the inputs of the route handling function.
@app.route("/")
def index(req, resp):
encoded = ujson.dumps(jsonData)
yield from picoweb.start_response(resp, content_type = "application/json")
yield from resp.awrite(encoded)
To finish the script we simply call the run method on the app object, specifying the IP address where it should listen. The IP assigned to the ESP32 is available on the first position of the data structure returned by the ifconfig function, which we stored in a variable called ip.
The final script code can be seen below and already includes the call to the run method.
import picoweb
import network
import ujson
ssid = "yourNetworkName"
password = "yourNetworkPass"
station = network.WLAN(network.STA_IF)
station.active(True)
station.connect(ssid, password)
while station.isconnected() == False:
pass
ip = station.ifconfig()
app = picoweb.WebApp(__name__)
jsonData = {"sensor":"temperature","value": "10"}
@app.route("/")
def index(req, resp):
encoded = ujson.dumps(jsonData)
yield from picoweb.start_response(resp, content_type = "application/json")
yield from resp.awrite(encoded)
app.run(debug=True, host =ip[0])
Testing the code
To test the code, simply upload the script to your ESP32. If you are on uPyCraft, this should be as easy as saving the file and hitting the upload button. After the upload via this IDE, the code automatically runs.So, after our app starts, an URL gets printed to the MicroPython console. To test our code, we simply need to copy it and paste it on a web browser. You should get an output similar to figure 1, which shows the returned JSON, which has the same structure we defined for the dictionary, in our code.
Figure 1 – JSON returned by the endpoint on the Picoweb app.