Files
ems/docs/tesla-fleet-api.md
Dusan Vojacek 2122fa2035
All checks were successful
CI and deploy / migration-check (push) Successful in 47s
CI and deploy / deploy (push) Has been skipped
Tesla presence watcher: geofence, ev_presence_obs, 'píchni auto' pobídka
- V095 ems.ev_presence_obs (state/at_home/distance/charging/shift per ~5 min)
- tesla_client: get_vehicle_api_state (jen /vehicles — nebudí), haversine_m
- collector poll_tesla_presence: online → poloha → geofence 150 m vs GPS site;
  přechod pryč→doma + Disconnected → Discord pobídka s aktuálním přebytkem
  (cooldown 2 h); vše logováno pro budoucí dostupnostní statistiku
- 6 testů (haversine, přechody); docs: zákopy reauth procesu (6 bodů)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 14:14:48 +02:00

121 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Tesla Fleet API — napojení EMS (čtení SoC vozidla)
> **REDIRECT URI registrovaná v dev portálu: `https://ems.vojacek.eu/t-auth`**
> (musí se znak po znaku shodovat v authorize URL, v token výměně i v portálu).
> Stránka s kódem se servíruje na /t-auth (Caddy rewrite); kód jde vždy
> zkopírovat i z adresního řádku (`?code=...`).
Cíl: po příjezdu EV přečíst skutečné SoC → `ev_session.energy_needed_wh`
přesně místo defaultu. Doména `ems.vojacek.eu` slouží JEN jako veřejná
vizitka pro Tesla (cert + public key + jednorázový OAuth callback) — EMS
samotné zůstává na VPN.
## 1. Doména (jednorázově, na serveru)
```bash
bash /opt/ems-deploy/app/deploy/tesla/setup_tesla_domain.sh
# → přidat vypsaný blok do /etc/caddy/Caddyfile a `systemctl reload caddy`
```
Veřejné je pouze:
- `https://ems.vojacek.eu/.well-known/appspecific/com.tesla.3p.public-key.pem`
- `https://ems.vojacek.eu/t-auth` (statická stránka zobrazí `?code=`)
- vše ostatní → 404; certifikát řeší Caddy (Let's Encrypt) automaticky.
## 2. Tesla developer portál (developer.tesla.com)
Vytvořit aplikaci:
- **Allowed Origin:** `https://ems.vojacek.eu`
- **Allowed Redirect URI:** `https://ems.vojacek.eu/t-auth`
- **Scopes:** `openid offline_access vehicle_device_data` (čtení SoC stačí;
`vehicle_charging_cmds` až kdybychom chtěli vozidlu poroučet my — teď řídí
wallbox, ne auto)
→ získáš `CLIENT_ID` a `CLIENT_SECRET`.
## 3. Partner account registrace (jednorázově)
```bash
# partner token (client_credentials):
curl -s https://fleet-auth.prd.vn.cloud.tesla.com/oauth2/v3/token \
-d grant_type=client_credentials -d client_id=$CLIENT_ID \
-d client_secret=$CLIENT_SECRET \
-d scope='openid vehicle_device_data' \
-d audience=https://fleet-api.prd.eu.vn.cloud.tesla.com | jq -r .access_token
# registrace domény (ověří si public key na .well-known):
curl -s -X POST https://fleet-api.prd.eu.vn.cloud.tesla.com/api/1/partner_accounts \
-H "Authorization: Bearer $PARTNER_TOKEN" -H 'Content-Type: application/json' \
-d '{"domain":"ems.vojacek.eu"}'
```
## 4. Uživatelský OAuth (jednorázově, z prohlížeče)
```
https://fleet-auth.prd.vn.cloud.tesla.com/oauth2/v3/authorize?
response_type=code&client_id=$CLIENT_ID&
redirect_uri=https://ems.vojacek.eu/t-auth&
scope=openid%20offline_access%20vehicle_device_data&state=ems
```
Přihlásíš se Tesla účtem → redirect na callback stránku → zkopíruješ `code`
výměna za tokeny:
```bash
curl -s https://fleet-auth.prd.vn.cloud.tesla.com/oauth2/v3/token \
-d grant_type=authorization_code -d client_id=$CLIENT_ID \
-d client_secret=$CLIENT_SECRET -d code=$CODE \
-d redirect_uri=https://ems.vojacek.eu/t-auth
# → access_token (krátký) + refresh_token (ULOŽIT — viz krok 5)
```
## 5. EMS integrace (plán implementace)
- env: `TESLA_CLIENT_ID`, `TESLA_CLIENT_SECRET`, `TESLA_REFRESH_TOKEN`
(`/opt/ems-deploy/.env`); refresh token rotuje → po každém refreshi uložit
nový (tabulka `ems.tesla_token` nebo aktualizace .env jobem — rozhodnout).
- `services/tesla_client.py`: refresh → access token (cache ~8 h),
`GET /api/1/vehicles`, `GET /api/1/vehicles/{id}/vehicle_data`
`charge_state.battery_level`, `charge_state.charge_limit_soc`.
- Hook v `_on_ev_arrival` (telemetry_collector): po detekci příjezdu zavolat
API, `energy_needed_wh = max(0, (limit level)/100 × battery_capacity_kwh
× 1000 / účinnost nabíjení)``fn_ev_session_apply_patch`; replan už běží.
- Mapování vozidlo↔wallbox: `asset_vehicle.api_type='tesla'` + VIN sloupec
(doplnit migrací), heuristika „Tesla je na chargeru X" dle
`default_charger_id`.
- Pozn.: vehicle_data budí auto (vampire drain) — volat jen při příjezdu
a max 1× za session.
## Stav (2026-06-11 večer)
- [x] skript + callback + dokumentace v repu
- [x] uživatel: doména + Caddy + developer portál (CLIENT_ID/SECRET získány)
- [x] EMS implementace: `services/tesla_client.py` (refresh s rotací do
`ems.tesla_token`, vehicles → vehicle_data charge_state, 408=spící auto),
hook `_patch_session_from_tesla` v telemetry_collector (po příjezdu, před
replanem; selhání neblokuje plán), `fn_tesla_arrival_context`,
`fn_ev_session_apply_patch` + soc_at_connect_pct, VIN auto-learn,
V086 (vin, api_type='tesla' pro tesla-my, tabulka tesla_token)
- [ ] uživatel: partner registrace (§3) + OAuth (§4) → `TESLA_CLIENT_ID`,
`TESLA_CLIENT_SECRET`, `TESLA_REFRESH_TOKEN` do `/opt/ems-deploy/.env`
a `docker compose -f /opt/ems-deploy/docker-compose.yml --env-file
/opt/ems-deploy/.env up -d backend` (recreate kvůli env)
- [ ] ověření: po příjezdu Tesly log `Tesla SoC -> session …` +
`select soc_at_connect_pct, target_soc_pct from ems.ev_session order by id desc limit 1`
## Presence watcher (2026-06-12, dev)
Poll ~5 min: `GET /vehicles` (state, NEBUDÍ) → při `online` poloha
(`location_data`, vyžaduje scope `vehicle_location`) → geofence 150 m vs GPS
site → `ems.ev_presence_obs` (V095). Přechod pryč→doma + `Disconnected`
Discord pobídka „auto doma a nepíchnuté (+aktuální přebytek)“; cooldown 2 h.
Data = základ dostupnostní statistiky per DOW×hodina (follow-up: maska
ev_connected v plánovači + zreálnění oportunistické hodnoty).
### Zákopy z reauth (12. 6.) — ať se neopakují
1. redirect URI `/t-auth` (musí sedět všude), 2. refresh token ROTUJE →
provozní hodnota v `ems.tesla_token` (ne .env), 3. po revokaci souhlasu ~10 min
výpadek auth, 4. `client_not_found` = app smazána/nové ID → opravit .env +
recreate, 5. **public key hash je vázán na app** — po smazání app nutná rotace
klíče (`mv private.pem .old` + `setup_tesla_domain.sh`) před partner registrací,
6. prázdný seznam vozidel = chybí partner registrace (ne spánek).