Tesla Fleet API: příprava domény ems.vojacek.eu (cert + public key + callback)
All checks were successful
CI and deploy / migration-check (push) Successful in 33s
CI and deploy / deploy (push) Successful in 1m30s

Doména slouží jen jako veřejná vizitka pro Tesla: Caddy blok vystavuje POUZE
.well-known public key a statickou OAuth callback stránku (zobrazí ?code=,
nic neodesílá), vše ostatní 404 — EMS zůstává na VPN. Certifikát Let's Encrypt
řeší hostovský Caddy automaticky.

deploy/tesla/setup_tesla_domain.sh (spustit NA SERVERU): EC keypair prime256v1
(privátní do /opt/ems-deploy/secrets 0600), public do .well-known, callback,
vypíše Caddy blok. docs/tesla-fleet-api.md: developer portál, partner
registrace, OAuth flow, plán EMS integrace (tesla_client + hook v _on_ev_arrival).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dusan Vojacek
2026-06-11 22:58:28 +02:00
parent 0ed6f18e1a
commit 620cea8b9b
3 changed files with 191 additions and 0 deletions

88
docs/tesla-fleet-api.md Normal file
View File

@@ -0,0 +1,88 @@
# Tesla Fleet API — napojení EMS (čtení SoC vozidla)
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/tesla/callback` (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/tesla/callback`
- **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/tesla/callback&
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/tesla/callback
# → 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
- [x] skript + callback + dokumentace v repu
- [ ] uživatel: spustit setup na serveru + Caddy blok + reload
- [ ] uživatel: developer portál (CLIENT_ID/SECRET) + partner registrace + OAuth
- [ ] EMS: tesla_client.py + hook (čeká na credentials)