-
-
Notifications
You must be signed in to change notification settings - Fork 0
How it works
BirdNET-Pi, BirdNET-Go ──▶ Featherframe server ──▶ Frame (ESP32-S3) ──▶ E-paper screen
or BirdWeather (FastAPI) GET /api/frame
The repository has two parts:
-
server/: a Python (FastAPI) service. It reads detections, chooses illustrations, renders a picture for each frame's screen, and runs the Featherframe webapp. All the logic is here. -
firmware/: an ESP32-S3 program. It downloads its picture from the server and shows it. It makes no decisions.
- It only reads from your detector. It never writes to or locks BirdNET's database.
- It renders a new picture only when a detection qualifies. By default it does nothing, to keep screen changes few.
- It renders pictures in the background. A web request only sends a picture that's already rendered.
There are two pictures: Individual detections (one species at a time) and Collage. Each is composed once, then fitted, matted, dithered, and packed for each frame that shows it.
- On USB: the frame keeps a WebSocket open to the server. The server tells it as soon as its picture changes.
-
On battery: the frame wakes on a timer or a button press. It sends the ETag of its current picture. The server answers
304if nothing changed, or sends the new picture.
The picture format (FFF) is a 16-byte header followed by 4-bit pixels. For the EE03 kit it's 1872 × 1404 landscape, rotated by the server.
Self-hosted only. Any device that can show an image from a URL can show the picture:
http://<your-server>/api/view.png?w=1072&h=1448&format=gray256
| Parameter | Values |
|---|---|
w, h
|
Width and height in pixels. |
format |
color, gray256, gray16, gray2, or mono. |
A landscape screen shows the picture rotated, so you can hang it in portrait.
Self-hosted only. You can change any frame's settings with curl:
# List frames and their IDs
curl http://<your-server>/api/status | jq '.frames.list[] | {id, title, summary}'
# Name a frame, show the collage, and rotate it
curl -X POST http://<your-server>/api/frames/<ID> \
-H 'Content-Type: application/json' \
-d '{"name": "Hall TRMNL", "shows": "collage", "rotation": 270}'
# Remove a frame
curl -X POST http://<your-server>/api/frames/<ID> \
-H 'Content-Type: application/json' -d '{"forget": true}'Featherframe ignores settings a frame doesn't support. For example, a tablet can't be rotated, and a TRMNL has no mat.
Other addresses for each frame:
- Its current picture:
/api/frames/<ID>/preview.png - Its battery readings:
/api/battery?frame=<ID>
AGENTS.md describes the architecture in detail, for contributors and coding agents.
Your Featherframe
Use
- Settings
- Add a frame
- Detection sources
- Other screens
- Species and illustrations
- AI illustrations
- How AI illustrations are made
Build your own
- Quickstart
- Kits and screens
- BirdNET hardware
- Build the frame
- Status LED
- Battery
- Flash the frame
- Install the server
About
Develop