From-Scratch Build · Physical Computing
A web server that drives a long run of addressable LED strips mounted on a lighting truss, with a library of animated effects you can trigger over an API or from a smart-home dashboard. I built this from scratch to learn how software talks to physical light.
What it is
The hardware is a row of individually-addressable LEDs strung along a truss — each pixel can be any colour at any moment. The software is a FastAPI server that owns those pixels: it exposes endpoints to list available effects, start one, tweak its parameters, or clear the strip entirely. Point a browser, a script, or a home-automation dashboard at it and the truss responds.
I built it to demystify physical computing. Turning "make a wave of colour roll down the truss" into actual electrical signals on a strip is the kind of thing that looks intimidating until you see it's just a clean API in front of a hardware driver.
The core idea I wanted to learn: a good hardware project hides the hardware. Behind one tidy REST interface, the difference between "rainbow" and "sparkle" is just which effect class is running its loop — the wiring underneath never changes.
The stack
The point of this rebuild was the toolchain. Here is what each piece actually does in the system.
The web framework. It serves the control and effects routes, validates incoming requests, and returns clean JSON responses.
The driver layer that talks to the addressable LED strip — setting pixel colours and pushing frames to the physical hardware.
A set of animations — rainbow, colour wipe, wave, sparkle, theater chase, glow, fade and more — each a small class with its own render loop.
Two route groups: one lists and launches effects, the other handles direct colour and on/off control.
A JSON file that maps effect names to their parameters, so new animations can be registered without rewiring the API.
Home-automation config exposes the API as switches, sliders and selectors, so the truss becomes a controllable smart device.
Architecture
A request flows through the same layered path every time, ending at the physical strip.
A client calls an endpoint — list effects, start one, set a colour, or clear.
FastAPI validates the request and dispatches it to the effects or control router.
The effect loader looks up the named animation and its parameters from the effect map.
The chosen effect class computes pixel colours frame by frame.
The truss controller pushes each frame to the addressable LED strip.
A systemd unit keeps the server running on the host and restarts it on boot.
The effect library
Every animation inherits from a shared base, which is what makes the effect list easy to grow:
In my rebuild, adding a new effect meant writing one small class against the base interface and registering it in the map — the API and hardware layers stayed untouched.
Reflection