diff --git a/backend/services/telemetry_collector.py b/backend/services/telemetry_collector.py index 735a33c..10e6a97 100644 --- a/backend/services/telemetry_collector.py +++ b/backend/services/telemetry_collector.py @@ -499,12 +499,19 @@ async def poll_loxone_sensors(site_id: int, db: asyncpg.Connection) -> None: ) -#: presence poll pacing (sekundy) a geofence poloměr (m) -EV_PRESENCE_POLL_S = 300 +#: presence poll pacing (sekundy) a geofence poloměr (m). +#: Fleet API je placené (vehicle_data $0.002/req, wake $0.02 — wake NIKDY): +#: list 10 min; vehicle_data jen při přechodu asleep→online a pak max 1×/15 min; +#: při otevřené ev_session se nepolluje vůbec (auto je u wallboxu = doma, +#: a při AC nabíjení nespí — bez gatu by data cally tekly celou noc). +EV_PRESENCE_POLL_S = 600 +EV_PRESENCE_DATA_MIN_S = 900 EV_PRESENCE_HOME_RADIUS_M = 150 #: anti-spam "píchni auto": min. rozestup notifikací per vozidlo (s) EV_PLUG_NUDGE_COOLDOWN_S = 2 * 3600 _EV_PRESENCE_LAST_POLL: dict[int, float] = {} +_EV_PRESENCE_LAST_DATA: dict[int, float] = {} +_EV_PRESENCE_LAST_STATE: dict[int, str] = {} _EV_PLUG_NUDGE_LAST: dict[int, float] = {} @@ -542,6 +549,19 @@ async def poll_tesla_presence(site_id: int, db: asyncpg.Connection) -> None: if veh is None or veh["latitude"] is None: return + # auto na wallboxu (otevřená session) = doma; žádné API cally (šetří $) + plugged = await db.fetchval( + """ + select exists( + select 1 from ems.ev_session es + where es.vehicle_id = $1 and es.session_end is null + ) + """, + int(veh["id"]), + ) + if plugged: + return + from services.tesla_client import get_charge_state, get_vehicle_api_state, haversine_m try: @@ -552,11 +572,20 @@ async def poll_tesla_presence(site_id: int, db: asyncpg.Connection) -> None: if api_state is None: return + prev_state = _EV_PRESENCE_LAST_STATE.get(int(veh["id"])) + _EV_PRESENCE_LAST_STATE[int(veh["id"])] = api_state + woke_up = api_state == "online" and prev_state != "online" + data_due = ( + loop_now - _EV_PRESENCE_LAST_DATA.get(int(veh["id"]), 0.0) + >= EV_PRESENCE_DATA_MIN_S + ) + at_home = None distance_m = None charging_state = None shift_state = None - if api_state == "online": + if api_state == "online" and (woke_up or data_due): + _EV_PRESENCE_LAST_DATA[int(veh["id"])] = loop_now try: st = await get_charge_state(db, veh["vin"]) except Exception as e: