diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b4d238a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +FROM python:3.12-alpine + +WORKDIR /app + +# Runtime deps only +RUN apk add --no-cache tini + +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY app/ ./ + +# Non-root +RUN adduser -D -u 1000 animator +USER animator + +ENV PYTHONUNBUFFERED=1 \ + LOG_LEVEL=INFO + +ENTRYPOINT ["/sbin/tini", "--"] +CMD ["python", "main.py"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..f06bc7b --- /dev/null +++ b/README.md @@ -0,0 +1,122 @@ +# Shelly RGBW2 Animator + +Leichter Python-Dienst, der Animationen direkt am Shelly RGBW2 (Gen1) abspielt. +openHAB sendet nur noch den gewünschten Modus per MQTT – der Pi wird dadurch +deutlich entlastet. + +## Features + +- Direkte HTTP-Ansteuerung des Shelly (kein openHAB-Event-Bus) +- Steuerung per MQTT (`shelly-animator/set`) +- Einfach neue Animationen hinzufügen +- Läuft als Docker-Container **oder** systemd-Service + +## Schnellstart (Docker – empfohlen) + +```bash +cd shelly-animator +docker compose up -d --build +``` + +Logs: +```bash +docker logs -f shelly-animator +``` + +## Alternative: systemd (ohne Docker) + +```bash +sudo mkdir -p /opt/shelly-animator +sudo cp -r app requirements.txt /opt/shelly-animator/ +cd /opt/shelly-animator +python3 -m venv venv +./venv/bin/pip install -r requirements.txt + +sudo cp systemd/shelly-animator.service /etc/systemd/system/ +sudo systemctl daemon-reload +sudo systemctl enable --now shelly-animator +``` + +## MQTT-Steuerung + +| Topic | Richtung | Payload | +|--------------------------|----------|----------------------------------| +| `shelly-animator/set` | write | `chill` / `party` / `gaming` / `stop` | +| `shelly-animator/state` | read | aktueller Modus oder `off` | + +Beispiele: +```bash +mosquitto_pub -h localhost -p 1884 -t shelly-animator/set -m "party" +mosquitto_pub -h localhost -p 1884 -t shelly-animator/set -m "stop" +``` + +## openHAB Anbindung + +Ersetze die drei JS-Animation-Rules durch **eine** einfache Rule: + +```javascript +// Rule: Status → Shelly Animator (MQTT) +const { items, actions } = require('openhab'); + +const status = items.getItem('Status').state.toString(); +const mqtt = actions.get('mqtt', 'mqtt:broker:72a3b87ef9'); // ggf. anpassen + +const map = { + 'Chillmode': 'chill', + 'Partymode': 'party', + 'Gamingmode': 'gaming', +}; + +const anim = map[status] || 'stop'; +mqtt.publishMQTT('shelly-animator/set', anim); +``` + +Trigger: `Status` Item State Change. + +## Neue Animation hinzufügen + +1. Datei anlegen: `app/animations/meine_anim.py` + +```python +from .base import Animation +import colorsys + +class MeineAnimation(Animation): + name = "meine" + interval = 0.15 # Sekunden zwischen Ticks + + def on_start(self): + super().on_start() + self._t = 0 + + def tick(self): + self._t += 0.05 + # ... Farbe berechnen ... + r, g, b = 255, 0, 128 + self.shelly.set_color(r, g, b, gain=60) +``` + +2. In `app/animations/__init__.py` registrieren: + +```python +from .meine_anim import MeineAnimation + +REGISTRY = { + ... + "meine": MeineAnimation, +} +``` + +3. Container neu bauen / Service neu starten. + +## Umgebungsvariablen + +| Variable | Default | Beschreibung | +|----------------|--------------------------|---------------------------| +| `SHELLY_HOST` | `192.168.178.151` | IP des Shelly | +| `SHELLY_USER` | `shelly@till.immers.ch` | Digest-Auth User | +| `SHELLY_PASS` | `...` | Digest-Auth Passwort | +| `MQTT_HOST` | `localhost` | MQTT Broker | +| `MQTT_PORT` | `1884` | MQTT Port | +| `MQTT_PREFIX` | `shelly-animator` | Topic-Prefix | +| `LOG_LEVEL` | `INFO` | DEBUG / INFO / WARNING | diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..0891ab3 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,17 @@ +services: + shelly-animator: + build: . + container_name: shelly-animator + restart: unless-stopped + network_mode: host # needed to reach Shelly + local MQTT on Pi + environment: + SHELLY_HOST: "192.168.178.151" + SHELLY_USER: "shelly@till.immers.ch" + SHELLY_PASS: "sh3llyTi33*" + MQTT_HOST: "localhost" + MQTT_PORT: "1884" + MQTT_PREFIX: "shelly-animator" + LOG_LEVEL: "INFO" + # If your MQTT broker requires auth, add: + # MQTT_USER: "..." + # MQTT_PASS: "..." diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..47c9a8d --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +paho-mqtt==2.1.0 +requests==2.32.3 +PyYAML==6.0.2