timed: always pull time and timezone from GPS (#31112)

* timed

* rm timezoned

* just gps

* ok

* little more

* fix

* datetime

* sleep a little

---------

Co-authored-by: Comma Device <device@comma.ai>
pull/31118/head
Adeeb Shihadeh 1 year ago committed by GitHub
parent 389b8ca30d
commit 827aa2e4fa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      release/files_common
  2. 2
      release/files_tici
  3. 2
      selfdrive/manager/process_config.py
  4. 2
      selfdrive/test/test_onroad.py
  5. 94
      system/timed.py
  6. 70
      system/timezoned.py

@ -153,6 +153,7 @@ selfdrive/controls/lib/lateral_mpc_lib/*
selfdrive/controls/lib/longitudinal_mpc_lib/* selfdrive/controls/lib/longitudinal_mpc_lib/*
system/__init__.py system/__init__.py
system/*.py
system/hardware/__init__.py system/hardware/__init__.py
system/hardware/base.h system/hardware/base.h

@ -4,8 +4,6 @@ third_party/snpe/aarch64-ubuntu-gcc7.5/*
third_party/mapbox-gl-native-qt/include/* third_party/mapbox-gl-native-qt/include/*
third_party/acados/larch64/** third_party/acados/larch64/**
system/timezoned.py
system/camerad/cameras/camera_qcom2.cc system/camerad/cameras/camera_qcom2.cc
system/camerad/cameras/camera_qcom2.h system/camerad/cameras/camera_qcom2.h
system/camerad/cameras/camera_util.cc system/camerad/cameras/camera_util.cc

@ -49,7 +49,7 @@ procs = [
NativeProcess("proclogd", "system/proclogd", ["./proclogd"], only_onroad), NativeProcess("proclogd", "system/proclogd", ["./proclogd"], only_onroad),
PythonProcess("logmessaged", "system.logmessaged", always_run), PythonProcess("logmessaged", "system.logmessaged", always_run),
PythonProcess("micd", "system.micd", iscar), PythonProcess("micd", "system.micd", iscar),
PythonProcess("timezoned", "system.timezoned", always_run, enabled=not PC), PythonProcess("timed", "system.timed", always_run, enabled=not PC),
PythonProcess("dmonitoringmodeld", "selfdrive.modeld.dmonitoringmodeld", driverview, enabled=(not PC or WEBCAM)), PythonProcess("dmonitoringmodeld", "selfdrive.modeld.dmonitoringmodeld", driverview, enabled=(not PC or WEBCAM)),
NativeProcess("encoderd", "system/loggerd", ["./encoderd"], only_onroad), NativeProcess("encoderd", "system/loggerd", ["./encoderd"], only_onroad),

@ -53,7 +53,7 @@ PROCS = {
"selfdrive.tombstoned": 0, "selfdrive.tombstoned": 0,
"./logcatd": 0, "./logcatd": 0,
"system.micd": 6.0, "system.micd": 6.0,
"system.timezoned": 0, "system.timed": 0,
"selfdrive.boardd.pandad": 0, "selfdrive.boardd.pandad": 0,
"selfdrive.statsd": 0.4, "selfdrive.statsd": 0.4,
"selfdrive.navd.navd": 0.4, "selfdrive.navd.navd": 0.4,

@ -0,0 +1,94 @@
#!/usr/bin/env python3
import datetime
import os
import subprocess
import time
from typing import NoReturn
from timezonefinder import TimezoneFinder
import cereal.messaging as messaging
from openpilot.common.params import Params
from openpilot.common.swaglog import cloudlog
from openpilot.system.hardware import AGNOS
def set_timezone(timezone):
valid_timezones = subprocess.check_output('timedatectl list-timezones', shell=True, encoding='utf8').strip().split('\n')
if timezone not in valid_timezones:
cloudlog.error(f"Timezone not supported {timezone}")
return
cloudlog.debug(f"Setting timezone to {timezone}")
try:
if AGNOS:
tzpath = os.path.join("/usr/share/zoneinfo/", timezone)
subprocess.check_call(f'sudo su -c "ln -snf {tzpath} /data/etc/tmptime && \
mv /data/etc/tmptime /data/etc/localtime"', shell=True)
subprocess.check_call(f'sudo su -c "echo \"{timezone}\" > /data/etc/timezone"', shell=True)
else:
subprocess.check_call(f'sudo timedatectl set-timezone {timezone}', shell=True)
except subprocess.CalledProcessError:
cloudlog.exception(f"Error setting timezone to {timezone}")
def set_time(new_time):
diff = datetime.datetime.now() - new_time
if diff < datetime.timedelta(seconds=10):
cloudlog.debug(f"Time diff too small: {diff}")
return
cloudlog.debug(f"Setting time to {new_time}")
try:
subprocess.run(f"TZ=UTC date -s '{new_time}'", shell=True, check=True)
except subprocess.CalledProcessError:
cloudlog.exception("timed.failed_setting_time")
def main() -> NoReturn:
"""
timed has two responsibilities:
- getting the current time
- getting the current timezone
GPS directly gives time, and timezone is looked up from GPS position.
AGNOS will also use NTP to update the time.
"""
params = Params()
tf = TimezoneFinder()
# Restore timezone from param
tz = params.get("Timezone", encoding='utf8')
tf = TimezoneFinder()
if tz is not None:
cloudlog.debug("Restoring timezone from param")
set_timezone(tz)
sm = messaging.SubMaster(['liveLocationKalman'])
while True:
sm.update(1000)
llk = sm['liveLocationKalman']
if not llk.gpsOK or (time.monotonic() - sm.logMonoTime['liveLocationKalman']/1e9) > 0.2:
continue
# set time
# TODO: account for unixTimesatmpMillis being a (usually short) time in the past
gps_time = datetime.datetime.fromtimestamp(llk.unixTimestampMillis / 1000.)
set_time(gps_time)
# set timezone
pos = llk.positionGeodetic.value
if len(pos) == 3:
gps_timezone = tf.timezone_at(lat=pos[0], lng=pos[1])
if gps_timezone is None:
cloudlog.critical(f"No timezone found based on {pos=}")
else:
set_timezone(gps_timezone)
params.put_nonblocking("Timezone", gps_timezone)
time.sleep(10)
if __name__ == "__main__":
main()

@ -1,70 +0,0 @@
#!/usr/bin/env python3
import json
import os
import time
import subprocess
from typing import NoReturn
from timezonefinder import TimezoneFinder
from openpilot.common.params import Params
from openpilot.system.hardware import AGNOS
from openpilot.common.swaglog import cloudlog
from openpilot.system.version import get_version
REQUEST_HEADERS = {'User-Agent': "openpilot-" + get_version()}
def set_timezone(valid_timezones, timezone):
if timezone not in valid_timezones:
cloudlog.error(f"Timezone not supported {timezone}")
return
cloudlog.info(f"Setting timezone to {timezone}")
try:
if AGNOS:
tzpath = os.path.join("/usr/share/zoneinfo/", timezone)
subprocess.check_call(f'sudo su -c "ln -snf {tzpath} /data/etc/tmptime && \
mv /data/etc/tmptime /data/etc/localtime"', shell=True)
subprocess.check_call(f'sudo su -c "echo \"{timezone}\" > /data/etc/timezone"', shell=True)
else:
subprocess.check_call(f'sudo timedatectl set-timezone {timezone}', shell=True)
except subprocess.CalledProcessError:
cloudlog.exception(f"Error setting timezone to {timezone}")
def main() -> NoReturn:
params = Params()
tf = TimezoneFinder()
# Get allowed timezones
valid_timezones = subprocess.check_output('timedatectl list-timezones', shell=True, encoding='utf8').strip().split('\n')
timezone = params.get("Timezone", encoding='utf8')
if timezone is not None:
cloudlog.debug("Setting timezone based on param")
set_timezone(valid_timezones, timezone)
while True:
time.sleep(60)
location = params.get("LastGPSPosition", encoding='utf8')
# Find timezone by reverse geocoding the last known gps location
if location is not None:
cloudlog.debug("Setting timezone based on GPS location")
try:
location = json.loads(location)
except Exception:
cloudlog.exception("Error parsing location")
continue
timezone = tf.timezone_at(lng=location['longitude'], lat=location['latitude'])
if timezone is None:
cloudlog.error(f"No timezone found based on location, {location}")
continue
set_timezone(valid_timezones, timezone)
if __name__ == "__main__":
main()
Loading…
Cancel
Save