- services/tesla_client.py: access token s cache + ROTACE refresh tokenu do ems.tesla_token (env jen seed — Tesla refresh token je jednorázový), vehicles → vehicle_data?endpoints=charge_state, 408 (spící auto) = tiché přeskočení, výběr vozidla dle VIN / jediného na účtu (VIN se auto-naučí) - hook _patch_session_from_tesla v _on_ev_arrival: PŘED replanem doplní soc_at_connect_pct (+ target z charge_limit_soc) do otevřené session přes fn_ev_session_apply_patch (rozšířena o soc_at_connect_pct) — energii si odvodí fn_planning_site_context (SQL-first); selhání neblokuje replan - V086: asset_vehicle.vin, api_type='tesla' pro tesla-my (Model Y, home-01), singleton ems.tesla_token; R__095: fn_tesla_token_get/upsert, fn_tesla_arrival_context, fn_vehicle_set_vin - config: TESLA_CLIENT_ID/SECRET/REFRESH_TOKEN (prázdné = vypnuto) - testy parserů; plná sada beze změny Aktivace: env do /opt/ems-deploy/.env + recreate backendu (docs/tesla-fleet-api.md §Stav). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
62 lines
1.9 KiB
PL/PgSQL
62 lines
1.9 KiB
PL/PgSQL
create or replace function ems.fn_ev_session_apply_patch(
|
||
p_site_id int,
|
||
p_session_id int,
|
||
p_patch jsonb
|
||
)
|
||
returns jsonb
|
||
language plpgsql
|
||
as $fn$
|
||
declare
|
||
v_id int;
|
||
begin
|
||
if not (p_patch ? 'target_soc_pct')
|
||
and not (p_patch ? 'target_deadline')
|
||
and not (p_patch ? 'soc_at_connect_pct') then
|
||
return jsonb_build_object('success', false, 'error', 'no_fields');
|
||
end if;
|
||
|
||
update ems.ev_session es
|
||
set
|
||
target_soc_pct = case
|
||
when p_patch ? 'target_soc_pct' then
|
||
case
|
||
when p_patch->'target_soc_pct' is null
|
||
or jsonb_typeof(p_patch->'target_soc_pct') = 'null' then null
|
||
else (p_patch->>'target_soc_pct')::double precision
|
||
end
|
||
else es.target_soc_pct
|
||
end,
|
||
-- skutečné SoC při připojení (Tesla Fleet API po příjezdu)
|
||
soc_at_connect_pct = case
|
||
when p_patch ? 'soc_at_connect_pct' then
|
||
case
|
||
when p_patch->'soc_at_connect_pct' is null
|
||
or jsonb_typeof(p_patch->'soc_at_connect_pct') = 'null' then null
|
||
else (p_patch->>'soc_at_connect_pct')::double precision
|
||
end
|
||
else es.soc_at_connect_pct
|
||
end,
|
||
target_deadline = case
|
||
when p_patch ? 'target_deadline' then
|
||
case
|
||
when p_patch->'target_deadline' is null
|
||
or jsonb_typeof(p_patch->'target_deadline') = 'null' then null
|
||
else (p_patch->>'target_deadline')::timestamptz
|
||
end
|
||
else es.target_deadline
|
||
end
|
||
where es.id = p_session_id
|
||
and es.site_id = p_site_id
|
||
returning es.id into v_id;
|
||
|
||
if v_id is null then
|
||
return jsonb_build_object('success', false, 'session_id', null);
|
||
end if;
|
||
|
||
return jsonb_build_object('success', true, 'session_id', v_id);
|
||
end;
|
||
$fn$;
|
||
|
||
comment on function ems.fn_ev_session_apply_patch(int, int, jsonb) is
|
||
'PATCH EV session – jen klíče přítomné v JSON (ISO string pro deadline; soc_at_connect_pct z Tesla API).';
|