forked from TillRepo/IrSender
5.7 KiB
5.7 KiB
Raspberry Pi IR Web API
Kleine Python Web API für Raspberry Pi zur Ausführung definierter IR-Kommandos mittels ir-ctl.
Features:
- REST API mit API-Key
- Kleine Weboberfläche ohne Login
- JSON-basierte Konfiguration
- Definierte Kommandos
- Keine Shell Injection (
shell=False) - Timeout pro Kommando
- Logging
- Geeignet für openHAB HTTP Binding
- Kein Docker notwendig
Architektur
+-------------------+
| openHAB / Browser |
+-------------------+
|
v
+-------------------+
| Python Web API |
| script-api.py |
+-------------------+
|
v
+-------------------+
| ir-ctl |
| Linux IR Subsystem|
+-------------------+
|
v
+-------------------+
| IR Sender GPIO |
+-------------------+
Voraussetzungen
Pakete installieren
sudo apt update
sudo apt install -y ir-ctl python3
Optional:
sudo apt install -y v4l-utils
Dateien
/home/timm/IRSender/
├── script-api.py
├── commands.json
├── apiout.log
├── blue.txt
├── brighter.txt
├── darker.txt
├── defaultColor.txt
├── fade.txt
├── green.txt
├── LichtAus.txt
├── LichtEin.txt
├── Nachtlicht.txt
├── off.txt
├── on.txt
├── purple.txt
├── red.txt
├── smooth.txt
├── white.txt
└── yellow.txt
Starten
cd /home/timm/IRSender
chmod +x script-api.py
nohup python3 -u script-api.py ./commands.json >> apiout.log 2>&1 &
Stoppen
pkill -f script-api.py
Logs anzeigen
tail -f /home/timm/IRSender/apiout.log
Health Check
curl http://<rpi-ip>:8080/health
Antwort:
{
"ok": true
}
Weboberfläche
http://<rpi-ip>:8080/
Die Weboberfläche benötigt keinen Login.
Nur Commands mit:
"web_enabled": true
werden angezeigt.
REST API
Kommando ausführen
Request
curl -s -X POST \
-H "X-API-Key: change-this-global-api-key" \
-H "Content-Type: application/json" \
http://<rpi-ip>:8080/run/lirc-tv-power \
-d '{"args":{}}'
Response
{
"ok": true,
"request_id": "f8d7f6a1",
"command_id": "lirc-tv-power",
"exit_code": 0,
"timed_out": false,
"duration_ms": 124,
"stdout": "",
"stderr": ""
}
Kommandos anzeigen
curl http://<rpi-ip>:8080/commands
commands.json
Beispiel
{
"host": "0.0.0.0",
"port": 8080,
"commands": {
"lirc-tv-power": {
"description": "Send TV power button",
"web_title": "TV Power",
"web_enabled": true,
"api_key": "change-this-global-api-key",
"timeout_seconds": 10,
"command": [
"ir-ctl",
"--send",
"/home/timm/IRSender/LichtEin.txt"
],
"args": {}
}
}
}
Neues Kommando hinzufügen
Beispiel
"my-command": {
"description": "Example command",
"web_title": "Example",
"web_enabled": true,
"api_key": "change-this-global-api-key",
"timeout_seconds": 10,
"command": [
"ir-ctl",
"--send",
"/home/timm/IRSender/example.txt"
],
"args": {}
}
openHAB Integration
HTTP Thing
Thing
UID: http:url:ir_sender
label: IR Sender
thingTypeUID: http:url
configuration:
baseURL: http://<rpi-ip>:8080
commandMethod: POST
contentType: application/json
headers:
- X-API-Key=change-this-global-api-key
Channel
channels:
- id: lirc_tv_power
channelTypeUID: http:switch
label: TV Power
configuration:
mode: WRITEONLY
commandExtension: /run/lirc-tv-power
onValue: {"args":{}}
offValue: {"args":{}}
Item
Switch IR_TV_Power "TV Power"
{ channel="http:url:ir_sender:lirc_tv_power" }
Systemd Service
Service Datei
[Unit]
Description=Raspberry Pi IR Web API
After=network-online.target
[Service]
Type=simple
User=timm
WorkingDirectory=/home/timm/IRSender
ExecStart=/usr/bin/python3 /home/timm/IRSender/script-api.py /home/timm/IRSender/commands.json
Restart=always
RestartSec=3
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=false
[Install]
WantedBy=multi-user.target
Installation
sudo nano /etc/systemd/system/rpi-ir-api.service
Service einfügen.
Dann:
sudo systemctl daemon-reload
sudo systemctl enable --now rpi-ir-api
Service Status
sudo systemctl status rpi-ir-api
Service Logs
journalctl -u rpi-ir-api -f
Sicherheit
Implementiert
- Keine Shell-Ausführung
- Keine freien Kommandos
- API-Key Prüfung
- JSON Validierung
- Timeout pro Kommando
- Regex Validierung
- HTML Escaping
- CSRF Token für Web UI
- Security Headers
Wichtig
Niemals erlauben:
"command": ["bash", "-c", "{user_input}"]
oder:
shell=True
Sonst wird aus der Lichtsteuerung sehr schnell eine Fernwartung mit Spezialeffekten.
Troubleshooting
403 invalid api key
API Key falsch oder Header fehlt.
Prüfen:
-H "X-API-Key: change-this-global-api-key"
400 invalid json
Body ist kein gültiges JSON.
Korrekt:
{"args":{}}
500 command failed
ir-ctl oder Datei prüfen:
ir-ctl --send /home/timm/IRSender/LichtEin.txt
Permission denied
GPIO / IR Rechte prüfen.
Test:
sudo ir-ctl --send /home/timm/IRSender/LichtEin.txt
Falls nur mit sudo funktioniert:
sudo usermod -aG video timm
Danach neu anmelden.
Backup
Wichtig sichern:
script-api.py
commands.json
*.txt
Lizenz
Internes Projekt.