From debc2a0bc830ca4d1d72b9e0cd2d02cf562c4f63 Mon Sep 17 00:00:00 2001 From: Till Immer Date: Tue, 22 Sep 2026 13:52:48 +0000 Subject: [PATCH] Dateien nach "/" hochladen --- .env.example | 28 +++++++++++++++++++++ Dockerfile | 14 +++++++++++ README.md | 62 ++++++++++++++++++++++++++++++++++++++++++++++ docker-compose.yml | 33 ++++++++++++++++++++++++ requirements.txt | 4 +++ 5 files changed, 141 insertions(+) create mode 100644 .env.example create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 docker-compose.yml create mode 100644 requirements.txt diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..ede120a --- /dev/null +++ b/.env.example @@ -0,0 +1,28 @@ +# Generate token: openssl rand -hex 32 +API_TOKEN=CHANGE_ME_LONG_RANDOM_TOKEN + +HOST=0.0.0.0 +PORT=8090 + +# MQTT – same host/port as your openHAB Mosquitto +MQTT_HOST=192.168.178.60 +MQTT_PORT=1884 +MQTT_USERNAME= +MQTT_PASSWORD= +MQTT_TLS=false +MQTT_PREFIX=openhab/ai_bridge + +DB_PATH=/data/bridge.db +MAX_HISTORY_MESSAGES=16 +SESSION_TTL_SECONDS=7200 +MAX_SESSIONS=20 +LOG_LEVEL=INFO + +# Pi speaker (ALSA) +ALSA_PLAYBACK_DEVICE=default +AUDIO_GID=29 + +# Free Edge TTS (German) +TTS_VOICE=de-DE-ConradNeural +TTS_RATE=+0% +TTS_VOLUME=+0% diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..9357d5b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +FROM python:3.12-slim-bookworm +ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1 PIP_NO_CACHE_DIR=1 +RUN apt-get update && apt-get install -y --no-install-recommends \ + alsa-utils libasound2 ffmpeg libatomic1 \ + && rm -rf /var/lib/apt/lists/* +RUN useradd --create-home --uid 10001 --shell /usr/sbin/nologin bridge +WORKDIR /app +COPY requirements.txt . +RUN pip install -r requirements.txt +COPY app ./app +RUN mkdir -p /data /data/audio && chown -R bridge:bridge /app /data +USER bridge +EXPOSE 8090 +CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8090"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..ffabc20 --- /dev/null +++ b/README.md @@ -0,0 +1,62 @@ +# openHAB AI Bridge – Simple (Text + Claude + Edge TTS) + +Kostenlose KI-Anbindung über **Ask Claude** (iOS Shortcut), ohne API-Key. + +## Ablauf + +``` +openHAB Textfeld + → Bridge (Session + Kontext in SQLite) + → MQTT notify + → openHAB Cloud Push ans iPhone + → Shortcut: Ask Claude + → Antwort zurück an Bridge + → Edge TTS → Lautsprecher am Pi +``` + +Rückfragen nutzen denselben Session-Kontext (Standard: 2 Stunden). + +## Schnellstart (Raspberry Pi) + +```bash +cd ~/openhab-ai-bridge-simple +cp .env.example .env +openssl rand -hex 32 # → in .env als API_TOKEN eintragen +getent group audio | cut -d: -f3 # → AUDIO_GID setzen + +docker compose build +docker compose up -d +curl http://127.0.0.1:8090/health +``` + +## openHAB + +1. Thing + Items aus `openhab/` übernehmen (Broker-UID anpassen). +2. JS-Regel aus `openhab/ai_bridge.rules.js` (Token + IP eintragen). +3. Regel „AI Bridge Notify → Push“ sendet die Cloud-Notification. + +## iOS Shortcut + +1. Trigger: openHAB-Notification mit Text `KI_DIALOG` +2. GET `http://PI:8090/api/v1/active` (Header: `Authorization: Bearer TOKEN`) +3. GET `/api/v1/sessions/{session_id}/context` +4. Prompt aus Messages bauen → **Ask Claude** +5. POST `/api/v1/sessions/{session_id}/answer` `{"content":"..."}` +6. POST `/api/v1/audio/speak` `{"text":"..."}` (Pi spricht) + +## API (alle außer /health brauchen Bearer-Token) + +| Methode | Pfad | Zweck | +|---------|------|--------| +| POST | /api/v1/dialog | Frage aus openHAB | +| GET | /api/v1/active | Aktive Session | +| GET | /api/v1/sessions/{id}/context | Gesprächsverlauf | +| POST | /api/v1/sessions/{id}/answer | Claude-Antwort speichern | +| POST | /api/v1/audio/speak | Edge TTS abspielen | +| POST | /api/v1/sessions/{id}/end | Session beenden | + +## Sicherheit + +- Nur LAN, Port 8090 nicht nach außen freigeben +- Langer zufälliger API_TOKEN +- Docker: non-root, read-only root, dropped capabilities diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..391808b --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,33 @@ +services: + openhab-ai-bridge: + build: . + container_name: openhab-ai-bridge + restart: unless-stopped + env_file: .env + ports: + - "8090:8090" + volumes: + - ./data:/data + devices: + - /dev/snd:/dev/snd + group_add: + - "${AUDIO_GID:-29}" + read_only: true + tmpfs: + - /tmp:size=32m,noexec,nosuid,nodev + security_opt: + - no-new-privileges:true + cap_drop: + - ALL + healthcheck: + test: + [ + "CMD", + "python", + "-c", + "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8090/health',timeout=2).read()", + ] + interval: 30s + timeout: 5s + retries: 3 + start_period: 10s diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..74b71f2 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +fastapi==0.116.1 +uvicorn[standard]==0.35.0 +paho-mqtt==2.1.0 +edge-tts==7.2.7