advent is a C#-first LED matrix scene runner for Raspberry Pi.
It started life as a festive matrix display and gradually picked up a few extra hobbies: clocks, weather, pixel-art chaos, message overlays, rail boards, web control, and just enough automation to behave like a tiny appliance.
If you like the idea of a 64x32 RGB panel acting somewhere between "seasonal art installation" and "tiny control room", this repo is for you.
If you want the "how would we design this properly now that it has grown up?" version, see docs/architecture-proposal.md.
- C# all the way down for app logic and rendering
- works on both Raspberry Pi 4 and Raspberry Pi 5
- simulator mode for development on macOS/Linux without touching real hardware
- image-driven scenes from checked-in assets and local-only private overlays
- a lightweight LAN web UI for scene control and message injection
- appliance-friendly deployment with GitHub Actions and
systemd
Out of the box, advent can rotate through things like:
- weather cards
- snowfall and rainbow snowfall
- Santa in December
- cat mode
- Donkey Kong
- Space Invaders
- Bonkers Parade
- Synthwave Grid
- Orbital
- Fireworks
- image scenes from your own files
- an optional UK rail board scene
There is also a --test-mode that runs the full catalogue in sequence instead of picking seasonal scenes at random.
| Backend | Stack | Notes |
|---|---|---|
pi4 |
local bindings over rpi-rgb-led-matrix |
expects librgbmatrix.so next to the app |
pi5 |
Pi5MatrixSharp |
bundled native runtime, Pi 5 friendly |
simulator |
terminal framebuffer preview | great for hacking on scenes locally |
The app currently assumes a 64x32 render target even though the Pi 5 backend can support broader geometry options underneath.
dotnet run -c Release --no-launch-profile -- --simulatordotnet run -c Release --no-launch-profile -- --simulator --test-modeADVENT_MATRIX_BACKEND=pi5 \
ADVENT_PI5_PINOUT=AdafruitMatrixBonnet \
dotnet run -c Release --no-launch-profile -- --backend=pi5dotnet run -c Release --no-launch-profile -- --led-slowdown-gpio=4 --led-gpio-mapping=adafruit-hatdotnet run -c Release --no-launch-profile -- --led-slowdown-gpio=4 --led-gpio-mapping=adafruit-hat --test-modeChecked-in image scenes live in advent-images/.
Private, personal, or employer-specific assets should live in advent-images.local/, which is:
- loaded automatically when present
- ignored by git
- compatible with the same folder layout and
manifest.jsonformat
That means you can keep custom banners, logos, and one-off local scenes on your Pi or dev machine without smuggling them into the public repo.
A starter manifest is included at advent-images.local.example/manifest.json.
You can also add extra image roots with:
ADVENT_EXTRA_IMAGE_DIRECTORIES
- files in
advent-images/are available all year - files in
advent-images/<month>/only load in that month .giffiles become animated scenes- wide static images become scrolling banner scenes
- other static images become fade-in/out scenes
Manifest overrides support:
file: relative image pathname: custom scene nametype:auto,animated/gif,static, orscrollmonths: month whitelist (1-12)durationSeconds: custom duration, capped at20
The app exposes a simple control UI on:
http://<pi-hostname-or-ip>:8080
Useful endpoints:
GET /api/scenesGET /api/statusPOST /api/scene/playwith{ "name": "Fireworks" }POST /api/scene/nextPOST /api/message/showwith{ "text": "Dinner in 5", "durationSeconds": 8 }POST /api/modewith{ "mode": "normal" | "test" }POST /api/queue/clear
Web UI environment variables:
ADVENT_WEB_ENABLED(trueby default)ADVENT_WEB_BIND(0.0.0.0by default)ADVENT_WEB_PORT(8080by default)ADVENT_WEB_TOKEN(optional but strongly recommended on a real network)
Pi 5 support comes from Pi5MatrixSharp, which wraps the Adafruit PioMatter path in a C#-friendly API.
Useful Pi 5 settings:
ADVENT_MATRIX_BACKEND=pi5ADVENT_PI5_PINOUT=AdafruitMatrixBonnetorActive3ADVENT_PI5_ADDR_LINES=4ADVENT_PI5_SERPENTINE=trueADVENT_PI5_ORIENTATION=NormalADVENT_PI5_PLANES=10ADVENT_PI5_TEMPORAL_PLANES=2
Pi 4 uses local bindings in MatrixApi/ over rpi-rgb-led-matrix.
If you need to rebuild the native library on the Pi:
./scripts/rebuild-librgbmatrix.shOptional overrides:
RGBMATRIX_REF=<branch-or-tag>RGBMATRIX_REPO_URL=<git-url>
Weather scene:
ADVENT_WEATHER_LATITUDEADVENT_WEATHER_LONGITUDE
UK rail board scene:
ADVENT_RAIL_ENABLEDADVENT_RAIL_LDB_BASE_URLADVENT_RAIL_LDB_CONSUMER_KEYADVENT_RAIL_LDB_CONSUMER_SECRETADVENT_RAIL_LDB_AUTH_HEADER_NAMEADVENT_RAIL_LDB_AUTH_HEADER_VALUEADVENT_RAIL_LDB_USERNAMEADVENT_RAIL_LDB_PASSWORDADVENT_RAIL_ORIGIN_CRS(ADVENT_RAIL_CAMBRIDGE_CRSstill works)ADVENT_RAIL_DESTINATION_CRS(ADVENT_RAIL_LONDON_CRSandADVENT_RAIL_KINGS_CROSS_CRSstill work)ADVENT_RAIL_ORIGIN_LABEL(optional)ADVENT_RAIL_DESTINATION_LABEL(optional)
The rail env var names are legacy from the original corridor this scene targeted; the scene itself is now just a configurable corridor board.
This repo includes a GitHub Actions deployment path aimed at a self-hosted runner living on the Pi itself.
Included workflows:
.github/workflows/ci.yml: build and test.github/workflows/deploy-pi.yml: manual Pi deploy
Deploy flow:
- publish the app for
linux-arm64 - stage source and app output into
~/advent-next-* - promote them into
~/advent-* - write or refresh
/etc/systemd/system/advent.service - restart the service
By default the installed service runs as the self-hosted runner user, not root.
One-time setup checklist:
- Register the Pi as a self-hosted runner with labels
self-hosted,linux,arm64,advent. - Ensure the runner user has passwordless
sudofor thesystemctlwork this deploy needs. - Put machine-local secrets in
/etc/advent/advent.env. - Protect the
advent-piGitHub environment so deploys require approval. - Keep the repo on manual deploys only for the Pi workflow.
Useful repo variables:
ADVENT_LED_ARGSADVENT_SERVICE_UNITADVENT_SERVICE_USERADVENT_SERVICE_GROUPADVENT_SERVICE_SUPPLEMENTARY_GROUPSADVENT_ENV_FILEADVENT_STABLE_APP_DIRADVENT_STABLE_SRC_DIRADVENT_NEXT_APP_DIRADVENT_NEXT_SRC_DIR
Recommended secret file shape:
sudo install -d -m 700 -o root -g root /etc/advent
sudo sh -c 'umask 077; cat > /etc/advent/advent.env <<EOF
ADVENT_RAIL_LDB_CONSUMER_KEY=put-the-api-key-here
ADVENT_RAIL_LDB_CONSUMER_SECRET=optional-consumer-secret
ADVENT_RAIL_ORIGIN_CRS=CBG
ADVENT_RAIL_DESTINATION_CRS=KGX
ADVENT_RAIL_ORIGIN_LABEL="Cambridge"
ADVENT_RAIL_DESTINATION_LABEL="London Kings Cross"
EOF'
sudo chown root:root /etc/advent/advent.env
sudo chmod 600 /etc/advent/advent.envValidate the checked-in assets and manifest references with:
./scripts/validate-assets.shThe simulator is usually the fastest way to iterate on scene timing, layout, and legibility before moving to real hardware.
Because writing C# for a Raspberry Pi LED matrix is more fun than it has any right to be.