mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-09-20 14:33:55 +08:00
Car Date/Time fallback when gps/wifi not available
This commit is contained in:
+80
-4
@@ -17,6 +17,67 @@ try:
|
||||
except Exception:
|
||||
TimezoneFinder = None
|
||||
|
||||
try:
|
||||
from zoneinfo import ZoneInfo
|
||||
except Exception:
|
||||
ZoneInfo = None
|
||||
|
||||
# StarPilot variables
|
||||
# Hyundai/Kia cluster wall clock, local time. Fallback when GPS has no fix.
|
||||
CAR_CLOCK_ADDR = 0x4F0
|
||||
CAR_CLOCK_BUS = 1
|
||||
|
||||
|
||||
def parse_car_clock(dat: bytes):
|
||||
# cluster sends all 0xFF until initialized
|
||||
if len(dat) < 7:
|
||||
return None
|
||||
if all(b == 0xFF for b in dat) or all(b == 0 for b in dat):
|
||||
return None
|
||||
|
||||
hour, minute, second = dat[1], dat[2], dat[3]
|
||||
month = (dat[4] >> 2) & 0x0F
|
||||
year = 2000 + dat[5]
|
||||
day = dat[6]
|
||||
|
||||
try:
|
||||
return datetime.datetime(year, month, day, hour, minute, second)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
|
||||
def read_car_clock(can_sock, timezone):
|
||||
latest = None
|
||||
for msg in messaging.drain_sock(can_sock):
|
||||
for frame in msg.can:
|
||||
if frame.address == CAR_CLOCK_ADDR and frame.src == CAR_CLOCK_BUS:
|
||||
parsed = parse_car_clock(bytes(frame.dat))
|
||||
if parsed is not None:
|
||||
latest = parsed
|
||||
|
||||
if latest is None:
|
||||
return None
|
||||
|
||||
utc = car_clock_to_utc(latest, timezone)
|
||||
if utc is None or not (min_date() <= utc <= MAX_DATE):
|
||||
return None
|
||||
return utc
|
||||
|
||||
|
||||
def car_clock_to_utc(local_dt, timezone):
|
||||
# timezone comes from the last GPS fix, so this needs one to have happened once
|
||||
if ZoneInfo is None or not timezone:
|
||||
return None
|
||||
if isinstance(timezone, bytes):
|
||||
timezone = timezone.decode("utf-8", errors="replace")
|
||||
try:
|
||||
tz = ZoneInfo(timezone)
|
||||
except Exception:
|
||||
cloudlog.exception("timed.bad_timezone")
|
||||
return None
|
||||
# fold=0: on the duplicated hour of a DST fall back, assume the first pass
|
||||
return local_dt.replace(tzinfo=tz, fold=0).astimezone(datetime.UTC).replace(tzinfo=None)
|
||||
|
||||
|
||||
def set_time(new_time):
|
||||
diff = datetime.datetime.now(datetime.UTC).replace(tzinfo=None) - new_time
|
||||
@@ -64,10 +125,13 @@ def main() -> NoReturn:
|
||||
|
||||
pm = messaging.PubMaster(['clocks'])
|
||||
sm = messaging.SubMaster([gps_location_service])
|
||||
# StarPilot variables
|
||||
can_sock = messaging.sub_sock('can', timeout=100)
|
||||
|
||||
# StarPilot variables
|
||||
tf = TimezoneFinder() if TimezoneFinder is not None else None
|
||||
timezonefinder_logged = False
|
||||
car_clock_tz_logged = False
|
||||
|
||||
last_timezone = params.get("Timezone")
|
||||
if last_timezone is not None:
|
||||
@@ -83,11 +147,23 @@ def main() -> NoReturn:
|
||||
|
||||
gps = sm[gps_location_service]
|
||||
gps_time = datetime.datetime.fromtimestamp(gps.unixTimestampMillis / 1000., datetime.UTC).replace(tzinfo=None)
|
||||
if not sm.updated[gps_location_service] or (time.monotonic() - sm.logMonoTime[gps_location_service] / 1e9) > 2.0:
|
||||
gps_usable = (sm.updated[gps_location_service] and
|
||||
(time.monotonic() - sm.logMonoTime[gps_location_service] / 1e9) <= 2.0 and
|
||||
gps.hasFix and min_date() <= gps_time <= MAX_DATE)
|
||||
|
||||
# StarPilot variables
|
||||
# only corrects an invalid clock, so GPS and NTP always win
|
||||
if not gps_usable and not system_time_valid():
|
||||
if not last_timezone and not car_clock_tz_logged:
|
||||
cloudlog.warning("timed: no saved timezone, cannot use car clock fallback")
|
||||
car_clock_tz_logged = True
|
||||
car_time = read_car_clock(can_sock, last_timezone)
|
||||
if car_time is not None:
|
||||
cloudlog.warning(f"timed: setting time from car clock: {car_time}")
|
||||
set_time(car_time)
|
||||
continue
|
||||
if not gps.hasFix:
|
||||
continue
|
||||
if gps_time < min_date() or gps_time > MAX_DATE:
|
||||
|
||||
if not gps_usable:
|
||||
continue
|
||||
|
||||
set_time(gps_time)
|
||||
|
||||
Reference in New Issue
Block a user