Tesla presence watcher: geofence, ev_presence_obs, 'píchni auto' pobídka
All checks were successful
CI and deploy / migration-check (push) Successful in 47s
CI and deploy / deploy (push) Has been skipped

- 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>
This commit is contained in:
Dusan Vojacek
2026-06-12 14:14:48 +02:00
parent ea4ca0e3de
commit 2122fa2035
5 changed files with 223 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
"""EV presence — čisté helpery (haversine, přechody)."""
from __future__ import annotations
import unittest
from services.telemetry_collector import ev_presence_transition
from services.tesla_client import haversine_m
class HaversineTests(unittest.TestCase):
def test_zero_distance(self) -> None:
self.assertAlmostEqual(haversine_m(49.2445, 17.4070, 49.2445, 17.4070), 0.0, places=2)
def test_known_distance(self) -> None:
# ~111 km na 1° zeměpisné šířky
d = haversine_m(49.0, 17.0, 50.0, 17.0)
self.assertAlmostEqual(d, 111_195, delta=300)
def test_geofence_scale(self) -> None:
# ~100 m posun (0.0009° lat)
d = haversine_m(49.24457, 17.407054, 49.24547, 17.407054)
self.assertTrue(80 < d < 120, d)
class TransitionTests(unittest.TestCase):
def test_arrived(self) -> None:
self.assertEqual(ev_presence_transition(False, True), "arrived")
def test_left(self) -> None:
self.assertEqual(ev_presence_transition(True, False), "left")
def test_none_cases(self) -> None:
self.assertIsNone(ev_presence_transition(None, True))
self.assertIsNone(ev_presence_transition(True, None))
self.assertIsNone(ev_presence_transition(True, True))
self.assertIsNone(ev_presence_transition(False, False))
if __name__ == "__main__":
unittest.main()