https://github.com/stuttgart-things/homerun2-led-catcher
RGB LED matrix catcher for homerun2 - consumes Redis Streams messages and displays on LED matrix hardware with embedded HTMX simulator
https://github.com/stuttgart-things/homerun2-led-catcher
homerun2 iot led-matrix python
Last synced: about 13 hours ago
JSON representation
RGB LED matrix catcher for homerun2 - consumes Redis Streams messages and displays on LED matrix hardware with embedded HTMX simulator
- Host: GitHub
- URL: https://github.com/stuttgart-things/homerun2-led-catcher
- Owner: stuttgart-things
- License: other
- Created: 2026-03-17T04:09:40.000Z (4 months ago)
- Default Branch: main
- Last Pushed: 2026-04-15T15:08:19.000Z (3 months ago)
- Last Synced: 2026-04-15T15:24:11.818Z (3 months ago)
- Topics: homerun2, iot, led-matrix, python
- Language: Python
- Homepage:
- Size: 87.9 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# homerun2-led-catcher
RGB LED matrix catcher for the [homerun2](https://github.com/stuttgart-things) ecosystem — consumes messages from Redis Streams and displays them on a 64x64 RGB LED matrix with an embedded HTMX web simulator.
## Architecture
```
Redis Streams → RedisConsumer → log_handler (structured JSON logging)
→ led_handler (64x64 RGB LED matrix via rpi-rgb-led-matrix)
→ web_handler (HTMX browser simulator)
```
| Mode | Description |
|------|-------------|
| `led` | Hardware LED matrix only (Raspberry Pi) |
| `web` | HTMX simulator only (browser, no hardware needed) |
| `full` | Both LED matrix and web simulator |
## Quick Start (Development)
```bash
# Clone
git clone https://github.com/stuttgart-things/homerun2-led-catcher.git
cd homerun2-led-catcher
# Install
pip install -e ".[dev]"
# Run in web-only mode (no Raspberry Pi needed)
LED_MODE=web LOG_FORMAT=text REDIS_ADDR=localhost python -m led_catcher
```
The health endpoint is available at `http://localhost:8080/healthz`.
## Raspberry Pi Hardware Setup
### Requirements
- Raspberry Pi (3B+ or newer recommended)
- 64x64 RGB LED Matrix panel
- Adafruit RGB Matrix HAT or Bonnet
- Raspberry Pi OS (Legacy) Lite — Debian Bullseye, 32-bit
- Python 3.11+
### Build rpi-rgb-led-matrix
```bash
git clone https://github.com/hzeller/rpi-rgb-led-matrix.git
cd rpi-rgb-led-matrix
# Configure for Adafruit HAT with PWM
sed -i 's/^HARDWARE_DESC?=regular/#HARDWARE_DESC?=regular/; s/^#HARDWARE_DESC=adafruit-hat-pwm/HARDWARE_DESC=adafruit-hat-pwm/' lib/Makefile
# Build and install Python bindings
cd bindings/python
make build-python && sudo make install-python
```
### Disable audio driver (interferes with LED matrix)
```bash
echo "snd_bcm2835" | sudo tee /etc/modprobe.d/blacklist-rgb-matrix.conf
sudo update-initramfs -u
sudo reboot
```
### Run on Pi
```bash
pip install .
# With hardware LED matrix
sudo LED_MODE=led REDIS_ADDR= PROFILE_PATH=profile.yaml python -m led_catcher
# With hardware + web simulator
sudo LED_MODE=full REDIS_ADDR= PROFILE_PATH=profile.yaml python -m led_catcher
```
> **Note:** `sudo` is required for GPIO access on the Raspberry Pi.
## Configuration
All configuration is via environment variables:
| Variable | Default | Description |
|----------|---------|-------------|
| `REDIS_ADDR` | `localhost` | Redis host |
| `REDIS_PORT` | `6379` | Redis port |
| `REDIS_PASSWORD` | *(empty)* | Redis password |
| `REDIS_STREAM` | `messages` | Redis stream to consume |
| `CONSUMER_GROUP` | `homerun2-led-catcher` | Consumer group name |
| `CONSUMER_NAME` | hostname | Consumer name within group |
| `LED_MODE` | `full` | Operating mode: `led`, `web`, `full` |
| `HEALTH_PORT` | `8080` | Health/web server port |
| `PROFILE_PATH` | `profile.yaml` | Path to display rules YAML |
| `LOG_FORMAT` | `json` | Log format: `json` or `text` |
| `LOG_LEVEL` | `info` | Log level: `debug`, `info`, `warning`, `error` |
## Display Profile
Display rules are defined in a YAML profile that maps (system, severity) to display modes:
```yaml
displayRules:
github-error:
systems: [github, gitlab]
severity: [ERROR]
kind: gif
image: sunset.gif
duration: 5
scale-weight:
systems: [scale]
severity: [INFO]
kind: static
text: "{{ message | replace('WEIGHT: ','') }}g"
font: myfont.bdf
duration: 3
default-info:
systems: ["*"]
severity: [INFO, SUCCESS]
kind: text
text: "{{ system }}: {{ title }}"
font: myfont.bdf
duration: 5
colors:
error: [255, 0, 0]
warning: [255, 165, 0]
success: [0, 255, 0]
info: [0, 100, 255]
```
## Docker
```bash
# Build
docker build -t homerun2-led-catcher:local .
# Run (web mode)
docker run -p 8080:8080 \
-e LED_MODE=web \
-e REDIS_ADDR=host.docker.internal \
homerun2-led-catcher:local
```
## Kubernetes (KCL)
```bash
# Render manifests
kcl run kcl/ -D config.image=ghcr.io/stuttgart-things/homerun2-led-catcher:latest \
-D config.namespace=homerun2 \
-D config.redisAddr=redis-stack.homerun2.svc.cluster.local
# Or use a deploy profile
kcl run kcl/ -y tests/kcl-deploy-profile.yaml
```
## Development
```bash
# Install with dev dependencies
pip install -e ".[dev]"
# Install pre-commit hook (runs before every git commit)
task setup-precommit
```
### Pre-commit Hook
A git pre-commit hook ensures code quality before every commit. It runs:
1. `ruff check` — linting
2. `ruff format --check` — formatting validation
3. `pytest` — 28 unit tests
Commits are blocked if any check fails. Run manually with `task precommit`.
### Task Commands
```bash
# Local checks (fast, no Docker/Dagger needed)
task precommit # lint + format-check + test (same as pre-commit hook)
task lint # ruff check
task format # ruff format (auto-fix)
task format-check # ruff format --check
task test # pytest
# Stage 1: Push — validation via Dagger (same as GH Actions on push)
task ci # lint + format-check + test + security-scan
# Stage 2: PR — full verification (same as GH Actions on PR)
task ci-pr # Stage 1 + docker build → ttl.sh → trivy scan
# Stage 3: Release — full release (same as GH Actions release)
task ci-release # Stage 2 + kustomize OCI push
# Individual Dagger tasks
task ci-lint # ruff via dagger
task ci-format-check # ruff format via dagger
task ci-test # pytest via dagger
task ci-security-scan # bandit via dagger
task ci-docker-build # docker build via dagger
task ci-docker-push # build + push to ttl.sh
task ci-trivy-scan # trivy scan image on ttl.sh
task ci-push-kustomize # KCL → kustomize OCI to ttl.sh
# Other
task run # LED_MODE=web, no hardware needed
task build-image # docker build locally
task pages-local # build mkdocs locally
```
### CI/CD Pipeline
Every stage runs the same Dagger modules locally (`task`) and in GitHub Actions:
```
Pre-commit (git hook)
│ ruff check + ruff format --check + pytest
│
├─► Push to branch (Stage 1: build-test.yaml)
│ Lint, Format-Check, Test, Security-Scan
│ Local: task ci
│
├─► Pull Request (Stage 2: build-scan-image.yaml + push-kustomize-pr.yaml)
│ Docker build → push GHCR `pr--` → Trivy scan
│ Kustomize OCI → push GHCR `-kustomize:pr--`
│ ArgoCD AppSet spins up a preview env at
│ `led-pr-.homerun2-dev.sthings-vsphere.labul.sva.de`
│ (add the `preview` label to the PR to opt in)
│ Local: task ci-pr
│
├─► Merge to main (Stage 3: release.yaml)
│ Semantic release → Docker push GHCR → KCL kustomize OCI push
│ Local: task ci-release
│
└─► After release (pages.yaml)
mkdocs-material → GitHub Pages
Local: task pages-local
```
All CI uses reusable Dagger modules from [`stuttgart-things/dagger`](https://github.com/stuttgart-things/dagger):
| Module | Functions |
|--------|-----------|
| `python` | lint, format-check, test, security-scan, build-image |
| `docker` | build, push |
| `trivy` | scan-image |
| `kcl` | push-kustomize-base |
| `release` | semantic |
## Related Projects
| Project | Description |
|---------|-------------|
| [homerun2-omni-pitcher](https://github.com/stuttgart-things/homerun2-omni-pitcher) | HTTP producer — sends messages to Redis Streams |
| [homerun2-core-catcher](https://github.com/stuttgart-things/homerun2-core-catcher) | Core consumer — log/CLI/web display modes |
| [homerun2-light-catcher](https://github.com/stuttgart-things/homerun2-light-catcher) | WLED light consumer — triggers LED strip effects |
| [homerun2-git-pitcher](https://github.com/stuttgart-things/homerun2-git-pitcher) | GitHub watcher — polls GitHub API for events and pitches them to Redis Streams |
| [homerun2-notification-catcher](https://github.com/stuttgart-things/homerun2-notification-catcher) | Notification consumer — routes messages to MS Teams / webhooks via YAML-configured filters |
| [homerun-library](https://github.com/stuttgart-things/homerun-library) | Shared Go library for message types and Redis ops |
## License
Apache-2.0