Add Home Assistant shopping API
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
# Home Assistant
|
||||
|
||||
Nouri stellt für Home Assistant eine kleine token-geschützte JSON-API bereit. Sie ist für Sprachbefehle wie diese gedacht:
|
||||
|
||||
- `Füge Erbsen auf die Einkaufsliste hinzu`
|
||||
- `Füge Erbsen mit Hinweis TK auf die Einkaufsliste hinzu`
|
||||
- `Füge Blumenerde als Einkaufsartikel hinzu`
|
||||
- `Füge Skyr als Lebensmittel hinzu`
|
||||
|
||||
## Nouri konfigurieren
|
||||
|
||||
Setze in der Nouri-Umgebung:
|
||||
|
||||
```bash
|
||||
NOURI_HA_TOKEN=<langes-zufälliges-token>
|
||||
NOURI_HA_USER_ID=<optionale-nouri-user-id>
|
||||
```
|
||||
|
||||
`NOURI_HA_USER_ID` ist optional. Ohne diesen Wert nutzt Nouri zuerst den ersten aktiven Admin und danach den ersten aktiven Nutzer.
|
||||
|
||||
Lokal zum Testen:
|
||||
|
||||
```bash
|
||||
export NOURI_HA_TOKEN='ein-langes-zufälliges-token'
|
||||
flask --app wsgi run --debug
|
||||
```
|
||||
|
||||
Auf Cloudron:
|
||||
|
||||
```bash
|
||||
cloudron env set --app <nouri-app> NOURI_HA_TOKEN='ein-langes-zufälliges-token'
|
||||
cloudron restart --app <nouri-app>
|
||||
```
|
||||
|
||||
## Home Assistant vorbereiten
|
||||
|
||||
Lege in Home Assistant in `secrets.yaml` diese Werte an:
|
||||
|
||||
```yaml
|
||||
nouri_ha_token: ein-langes-zufälliges-token
|
||||
nouri_url: https://deine-nouri-domain.example.org
|
||||
```
|
||||
|
||||
Wenn Home Assistant lokal auf Nouri zugreift, nimm die aus Home Assistant erreichbare Adresse, zum Beispiel:
|
||||
|
||||
```yaml
|
||||
nouri_url: http://192.168.178.50:5000
|
||||
```
|
||||
|
||||
`127.0.0.1` funktioniert nur, wenn Home Assistant und Nouri im selben Prozess- oder Container-Kontext laufen.
|
||||
|
||||
## Eintrag hinzufügen
|
||||
|
||||
```http
|
||||
POST /api/home-assistant/shopping
|
||||
Authorization: Bearer <NOURI_HA_TOKEN>
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Erbsen",
|
||||
"note": "TK"
|
||||
}
|
||||
```
|
||||
|
||||
Wenn Nouri den Eintrag kennt, wird er direkt auf die Einkaufsliste gesetzt. `note` landet im bestehenden Feld `Einkaufshinweis`.
|
||||
|
||||
Wenn Nouri den Eintrag nicht kennt, kommt eine Rückfrage-Antwort:
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"status": "needs_confirmation",
|
||||
"name": "Erbsen",
|
||||
"note": "TK",
|
||||
"options": ["food", "shopping"],
|
||||
"message": "Erbsen kenne ich noch nicht. Soll ich es als Lebensmittel oder Einkaufsartikel anlegen?"
|
||||
}
|
||||
```
|
||||
|
||||
## Rückfrage bestätigen
|
||||
|
||||
```http
|
||||
POST /api/home-assistant/shopping/confirm
|
||||
Authorization: Bearer <NOURI_HA_TOKEN>
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Erbsen",
|
||||
"note": "TK",
|
||||
"create_as": "food"
|
||||
}
|
||||
```
|
||||
|
||||
Mögliche Werte für `create_as`:
|
||||
|
||||
- `food` für Lebensmittel
|
||||
- `shopping` für reine Einkaufsartikel
|
||||
|
||||
Alternativ kann der erste Endpoint mit `confirm_create: true` verwendet werden:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Blumenerde",
|
||||
"create_as": "shopping",
|
||||
"confirm_create": true
|
||||
}
|
||||
```
|
||||
|
||||
## REST Commands
|
||||
|
||||
Trage in `configuration.yaml` ein:
|
||||
|
||||
```yaml
|
||||
rest_command:
|
||||
nouri_shopping:
|
||||
url: "{{ url }}/api/home-assistant/shopping"
|
||||
method: post
|
||||
headers:
|
||||
X-Nouri-Token: !secret nouri_ha_token
|
||||
Content-Type: "application/json"
|
||||
payload: >
|
||||
{
|
||||
"name": "{{ name }}",
|
||||
"note": "{{ note | default('') }}",
|
||||
"create_as": "{{ create_as | default('') }}",
|
||||
"confirm_create": {{ confirm_create | default(false) | tojson }}
|
||||
}
|
||||
|
||||
nouri_shopping_confirm:
|
||||
url: "{{ url }}/api/home-assistant/shopping/confirm"
|
||||
method: post
|
||||
headers:
|
||||
X-Nouri-Token: !secret nouri_ha_token
|
||||
Content-Type: "application/json"
|
||||
payload: >
|
||||
{
|
||||
"name": "{{ name }}",
|
||||
"note": "{{ note | default('') }}",
|
||||
"create_as": "{{ create_as }}"
|
||||
}
|
||||
```
|
||||
|
||||
Danach Home Assistant neu starten oder die YAML-Konfiguration neu laden.
|
||||
|
||||
## Manuell testen
|
||||
|
||||
In Home Assistant:
|
||||
|
||||
1. Öffne `Entwicklerwerkzeuge`.
|
||||
2. Öffne `Aktionen`.
|
||||
3. Wähle `rest_command.nouri_shopping`.
|
||||
4. Nutze zum Testen:
|
||||
|
||||
```yaml
|
||||
url: !secret nouri_url
|
||||
name: Erbsen
|
||||
note: TK
|
||||
```
|
||||
|
||||
Wenn `Erbsen` in Nouri existiert, wird es auf die Einkaufsliste gesetzt. Wenn nicht, antwortet Nouri mit `needs_confirmation`.
|
||||
|
||||
## Assist-Sprachsätze
|
||||
|
||||
Minimal in `configuration.yaml`:
|
||||
|
||||
```yaml
|
||||
conversation:
|
||||
intents:
|
||||
NouriShopping:
|
||||
- "füge {name} auf die einkaufsliste hinzu"
|
||||
- "füge {name} mit hinweis {note} auf die einkaufsliste hinzu"
|
||||
- "füge {name} als lebensmittel hinzu"
|
||||
- "füge {name} als einkaufsartikel hinzu"
|
||||
```
|
||||
|
||||
Dazu ein Intent Script:
|
||||
|
||||
```yaml
|
||||
intent_script:
|
||||
NouriShopping:
|
||||
action:
|
||||
- action: rest_command.nouri_shopping
|
||||
data:
|
||||
url: !secret nouri_url
|
||||
name: "{{ name }}"
|
||||
note: "{{ note | default('') }}"
|
||||
create_as: >
|
||||
{% if 'lebensmittel' in text | default('') | lower %}food{% elif 'einkaufsartikel' in text | default('') | lower %}shopping{% else %}{% endif %}
|
||||
confirm_create: false
|
||||
response_variable: nouri_response
|
||||
- stop: "Nouri Antwort"
|
||||
response_variable: nouri_response
|
||||
speech:
|
||||
text: >
|
||||
{{ action_response.content.message }}
|
||||
```
|
||||
|
||||
## Rückfrage-Logik
|
||||
|
||||
Der erste Schritt ist damit fertig: bekannte Lebensmittel oder Einkaufsartikel landen direkt auf der Nouri-Einkaufsliste.
|
||||
|
||||
Wenn Nouri mit `needs_confirmation` antwortet, muss Home Assistant im nächsten Schritt nachfragen:
|
||||
|
||||
> Soll ich das als Lebensmittel oder als Einkaufsartikel anlegen?
|
||||
|
||||
Danach ruft Home Assistant `/api/home-assistant/shopping/confirm` mit `create_as: food` oder `create_as: shopping` auf. Diese zweite Stufe kann je nach Setup über Assist, eine Automation, eine mobile Benachrichtigung oder später über Alexa umgesetzt werden.
|
||||
Reference in New Issue
Block a user