Skip to content
Dave edited this page Oct 13, 2022 · 24 revisions

Welcome to the Thimble wiki!

Here you will find a step by step guide to using the Thimble web framework to add a REST API to your MicroPython projects.

Getting Started

You'll need a microcontroller running MicroPython and you'll need to have it configured to access your wifi network. There are plenty of examples on the web covering how to do that. You can also have a look at the boot.py I use on my ESP32.

Once you're booting and connected to wifi, you'll need a copy of thimble.py. It can go in the /lib directory or directly in the root of your flash storage.

Now you're ready to start using Thimble.

Creating a Simple Example

Hello World! It's everybody's favorite. Here's how you do it with Thimble:

from thimble import Thimble

app = Thimble(default_content_type='application/json')

@app.route('/')
def say_hello(req):
    return 'Hello World!'

app.run()

Save the code above as main.py and reboot your microcontroller. You should see something like this when Thimble starts up:

Listening on 0.0.0.0:80

0.0.0.0 represents the default interface and :80 indicates the port.

All you have to do is point your web browser to the IP address of your microcontroller. In your browser, you should see Hello World! displayed.

Creating Additional Routes

Thimble works on the concept of linking functions to routes. If you've ever written an app with Python Flask or NodeJS Express, you should be familiar with the concept. If not, don't worry, it's not hard.

You can think of a route as a url. In the Hello World example, there's only one route for / (or the root). Let's add a route to say "Hello Cleveland" in addition to "Hello World".

The code in main.py becomes this:

from thimble import Thimble

app = Thimble(default_content_type='application/json')

@app.route('/')
def say_hello(req):
    return 'Hello World!'

@app.route('/cleveland')
def say_hello_cleveland(req):
    return 'Hello Cleveland!'

app.run()

Notice what was added:

@app.route('/cleveland')
def say_hello_cleveland(req):
    return 'Hello Cleveland!'

Let's take a closer look, line by line, to understand what's going on.

At the top, we have @app.route('/cleveland'). The technical term for this is "function decorator". Just think of it as the way to tell Thimble the URL path that will trigger your function. There's a little more to it, but we'll get to that a little later on.

The next line, def say_hello_cleveland(req): , defines the function. You're probably already familiar with this if you've been using Python for more than five minutes.

What's important to note here is the parameter req that gets passed to the function. This is how Thimble communicates the details of the HTTP request to your function. Like the example above, you don't have to use it, but you do have to include it. Otherwise, you're going to get an error.

The last line, return 'Hello Cleveland!' is the body of the response to the HTTP request. Thimble takes care of the HTTP status code and headers, but it's up to your function to supply the body of the reply. In this case, it's just a simple "Hello Cleveland!"

Try it out with a browser or REST API client.

Controlling GPIO

I'm going to guess you didn't by a microcontroller to send "Hello World" to a web browser. You bought it to read sensors and control LEDs and myriad other use cases. Thimble can be used to add a REST API to that project.

from machine import Pin
from thimble import Thimble

gpio_2 = Pin(2, Pin.OUT)

app = Thimble()

@app.route('/gpio/2', methods=['GET'])
def get_gpio_2(req):
    return gpio_2.value()

@app.route('/gpio/2', methods=['PUT'])
def set_gpio_2(req):
    if (body == 1 or body == 'on'):
        gpio_2.on()
    elif (body == 0 or body == 'off'):
        gpio_2.off()
    return gpio_2.value()

app.run(debug=True)

The code above lets you control one of the digital GPIO pins. Several microcontrollers have a built-in LED attached to GPIO2, so you should be able to get visual confirmation that things are working. If you don't have a built-in LED, you can still see the results in the REST API client.

Notice how the the routes now have a methods parameter and last line changes from app.run() to app.run(debug=True)

The methods parameter tells Thimble what HTTP verbs to consider for when looking for routes. The default for routes is to use methods=['GET'], which is how the Hello World example worked without explicitly specifying it. But, you can also use POST, PUT, DELETE, or any other HTTP request method. However, in REST APIs, GET is generally used for reading values while PUT is for changing, so that's what is used here.

Notice how the route for /gpio/2 GET isn't much different than the Hello World example. The only major change is return gpio_2.value() to use the current value of GPIO 2 as the body of the response.

Things get a little more complex with the /gpio/2 PUT route. Here we need to examine the req parameter to see what was passed in the body of the request. If it was a 1 or the word on, the GPIO value is set to on (logic high). A 0 or off will set the value to off (logic low.)

Because the LED is an active low device, the visual representation of on and off is actually reversed.

Clone this wiki locally