Last mod: 2025.01.26

Raspberry Pi - REST API based on Flask (deprecated library)

What is the best way to achieve simple and clear communication between IoT devices and other systems? One of the most effective solutions is REST APIs. They provide a lightweight and flexible method for exchanging data, making them perfect for IoT devices like Raspberry Pi and other small computers. Most IoT devices come with libraries for easy integration in Python, which is why using Python to create REST APIs makes the system much simpler. Python’s simplicity and extensive support for IoT protocols enable efficient development of scalable and robust solutions, ideal for IoT ecosystems.

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 Flask library to easily create web applications with a REST API

Software

Any OS for the Rapsberry Pi should have Python installed by default. Let's verify this:

python -V

python -V

If we have Python, we can proceed to install the Flask framework:

sudo apt -y upgrade
sudo apt install -y python3-flask

"Hello World" example

Create first app "Hello World". Write file app_restapi_helloworld.py with body:

from flask import Flask

# Create a Flask app
app = Flask(__name__)

# Route for the root URL '/'
@app.route("/")
def hello_world():
    return "Hello World"

# Run the application
if __name__ == "__main__":
    app.run(host='0.0.0.0', port=5000, debug=True)

Complete file: app_restapi_helloworld.py

And run:

python app_restapi_helloworld.py

python rest_api_hello_world.py

If the application has started, type http://RASPBERRY_PI_IP:5000/ into the browser.
We should see a screen:

http://RASPBERRY_PI_IP:5000/

GET method with JSON response

Let's take a more important data, system parameters: CPU load, RAM consumption, disk usage. We need to install the package for reading system data:

sudo apt install python3-psutil

Prepare a Python function to read system data:

def get_system_info():
    # CPU usage
    cpu_usage = psutil.cpu_percent(interval=1)

    # Memory usage
    memory_info = psutil.virtual_memory()
    ram_total = memory_info.total / (1024 * 1024)  # Convert bytes to MB
    ram_used = memory_info.used / (1024 * 1024)    # Convert bytes to MB
    ram_percent = memory_info.percent

    # Disk usage
    disk_info = psutil.disk_usage('/')
    disk_total = disk_info.total / (1024 * 1024 * 1024)  # Convert bytes to GB
    disk_used = disk_info.used / (1024 * 1024 * 1024)    # Convert bytes to GB
    disk_percent = disk_info.percent

    # Create a dictionary for JSON
    system_info = {
        "cpu": {
            "usage_percent": cpu_usage
        },
        "memory": {
            "total_mb": round(ram_total, 2),
            "used_mb": round(ram_used, 2),
            "usage_percent": ram_percent
        },
        "disk": {
            "total_gb": round(disk_total, 2),
            "used_gb": round(disk_used, 2),
            "usage_percent": disk_percent
        }
    }

    return system_info

Complete file: app_restapi_psutil.py

Add routing to app:

@app.route("/system_info")
def system_info():
   return get_system_info()

Open in browser http://RASPBERRY_PI_IP:5000/system_info:

http://RASPBERRY_PI_IP:5000/system_info

POST request with JSON body

We should use the POST method to send commands change server status. The parameters can be sent in several ways, the most flexible, lightweight and most commonly used is the JSON format.

Add import request:

from flask import Flask, request

and post method:

@app.route("/motors", methods=['POST'])
def post():
    if not request.is_json:
        return jsonify({"error": "Invalid JSON!"}), 400
    data = request.json
    left_motor_value = float(data.get('left'))
    right_motor_value = float(data.get('right'))
    print("Left:", round(left_motor_value, 2))
    print("Right: ", round(right_motor_value, 2))
    # TODO Add motor control implementation
    return {"status" : "ok"}, 200

Complete file: app_restapi_psutil_and_post.py

Restart the application. The POST method cannot be called simply from the browser, let's use the curl command line tool from bash:

curl -X POST http://RASPBERRY_PI_IP:5000/motors \
-H "Content-Type: application/json" \
-d '{"left": 35.0, "right" : 90.5}'

From the client side we should see:

curl -X POST http://192.168.3.106:5000/motors -H "Content-Type: application/json" -d '{"left": 35.0, "right" : 90.5}'

From the server side:

Response: http://192.168.3.106:5000/motors

Links

https://www.python.org/
https://flask.palletsprojects.com/
https://restfulapi.net/
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
https://pypi.org/project/psutil/