Course materials · Microprocessor Applications

An HTTP API for sensor data

English translation

Learning objectives

A running server does not imply correct request handling. First test paths, missing inputs, and safe responses.

Execution conditions

Requires fastapi and httpx. Use uvicorn additionally only if you choose browser testing.

If the required package is missing, run %pip install fastapi==0.162.0 httpx==0.28.1 in a Colab or Jupyter code cell.

Test requests through function calls

Starting conditions

The FastAPI /readings path accepts device, start, and end. TestClient sends requests without starting an actual server.

Procedure

  1. Execute the provided valid request and check the status code and JSON fields.
  2. Execute a start>end request and distinguish it from a normal response.

Results to retain

from fastapi import FastAPI,HTTPException
from fastapi.testclient import TestClient
app=FastAPI()
readings=[{'device':'m1','time_s':0.,'value':20.},{'device':'m1','time_s':1.,'value':21.}]
@app.get('/readings')
def get_readings(device:str,start:float=0,end:float=10):
    if start>end:raise HTTPException(status_code=400,detail='start must not exceed end')
    return [row for row in readings if row['device']==device and start<=row['time_s']<=end]
client=TestClient(app)
for query in ['/readings?device=m1','/readings?device=m1&start=2&end=1']:
    result=client.get(query);print(result.status_code,result.json())

Record results and self-check

Request:

Status code:

Key JSON fields:

Points to check

Distinguish invalid requests

Starting conditions

Test a missing device, start=abc, nonexistent device m9, and nonexistent path /unknown.

Procedure

  1. Tabulate the status codes and response bodies for the four requests.
  2. Decide which situation to handle as an empty list: absent data or an invalid request.
  3. Use asserts to fix two valid and invalid request cases for checking after later changes.

Results to retain

for path in ['/readings','/readings?device=m1&start=abc','/readings?device=m9','/unknown']:
    response=client.get(path);print(path,response.status_code,response.json())
# TODO: Add assert checks for valid and invalid requests.

Record results and self-check

Request:

Status code:

Meaning:

Client's next action:

Points to check

The storage integration boundary

Starting conditions

You want to call the SQLite query function from the previous unit inside the API.

Procedure

  1. Mark where to replace reading from a temporary list with a storage function call.
  2. Separate API input validation from DB query responsibilities.
  3. Check whether one response identifies the device, time, and unit clearly enough for a user to interpret it.

Results to retain

# TODO: Modify the code to call query(device,start,end) from the previous unit.
# Run uvicorn locally only when testing in a browser.

Record results and self-check

Components:

Received input:

Return value:

Failure handling:

Points to check

Official examples and data