Last mod: 2025.02.04
Raspberry Pi - REST API based on FastAPI
Introduction
In my opinion, Python is the best language for building REST APIs for small portable systems like the Raspberry Pi. This is determined by several elements:
- Most of the IoT devices communicates have written libraries in Python
- Python allows you to create lightweight applications
- Python is a high-level language where we do not need to focus on implementation details
- We can use the FastAPI library to easily create web applications with a REST API with self-documentation by Swagger
Software
Any OS for the Rapsberry Pi should have Python installed by default. Let's verify this:
python -V
Install virtual environments venv:
sudo apt update
sudo apt install python3-venv -y
Create and run virtual environment:
python -m venv ~/.venv
source ~/.venv/bin/activate
Install FastAPI and Uvicorn:
pip install fastapi uvicorn
"Hello World" app example
Create first web app "Hello World". Write file app_fastapi_helloworld.py with body:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def index():
return "Hello World"
And run:
uvicorn app_fastapi_helloworld:app --host 0.0.0.0 --port 8000
Open in browser http://RASPBERRY_PI_IP:8000:
REST API method
Now let's write a real REST API method, create file app_fastapi_time.py:
from fastapi import APIRouter, FastAPI
from datetime import datetime
app = FastAPI()
router = APIRouter(prefix='/api')
@router.get("/get_time")
def get_time():
return {"current_time": datetime.now().isoformat()}
app.include_router(router)
Run:
uvicorn app_fastapi_time:app --host 0.0.0.0 --port 8000
Open in browser http://RASPBERRY_PI_IP:8000/api/get_time:
POST request and defining request structure
We can define a JSON format in the request and in the response. Create new app app_fastapi_post.py with POST method:
from fastapi import APIRouter, FastAPI, Response
from pydantic import BaseModel, Field
app = FastAPI()
router = APIRouter(prefix='/api')
class MotorsDto(BaseModel):
left: int = Field(ge=-100, le=100, description="The left motor can have values from -100 to 100.")
right: int = Field(ge=-100, le=100, description="The right motor can have values from -100 to 100.")
@router.post("/motors")
def motors_set(data: MotorsDto):
print("Left:", data.left)
print("Right: ", data.right)
return Response(status_code=200)
app.include_router(router)
Run:
uvicorn app_fastapi_post:app --host 0.0.0.0 --port 8000
Call POST method:
curl -X POST http://192.168.3.106:8000/api/motors -H "Content-Type: application/json" -d '{"left": 35, "right" : 90}'
Server side result:
We used the curl tool to make the call. However, the FastAPI framework has another feature that makes building REST APIs easier, it has a built-in Swagger library. When you type http://RASPBERRY_PI_IP:8000/docs into your browser, you will get a page with the HTTP methods available in our application. There are also structures defined to handle requests and responses, built-in and ours.
From this interface, we can call any available REST API method with parameters of our choice:
Uvicorn
We can simplify the way applications run on the Uvicorn server. Let's add a line at the end of our application:
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
Now instead of a command:
uvicorn application_file_name:app --host 0.0.0.0 --port 8000
we can start the application by calling:
python application_file_name.py
Links
https://www.python.org/
https://docs.python.org/3/library/venv.html
https://fastapi.tiangolo.com/
https://pypi.org/project/uvicorn/
https://restfulapi.net/
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
https://pypi.org/project/psutil/
https://swagger.io/