Timezoned (#19960)
* untested code * add to manager * whitespace * only save on fix * cleanup * fix typo * add to ignored processes * import tici * fix param name * cleanup * only run offroad * use itertools * wait for thermald * simpler * fall back to api call * add param to override timezone Co-authored-by: Comma Device <device@comma.ai>albatross
parent
3dc45554d7
commit
4c04e220a1
1
Pipfile
1
Pipfile
|
@ -119,6 +119,7 @@ PyJWT = "*"
|
|||
pyserial = "*"
|
||||
onnx = "*"
|
||||
onnxruntime = "*"
|
||||
timezonefinder = "*"
|
||||
|
||||
[requires]
|
||||
python_version = "3.8"
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -44,8 +44,9 @@ keys = {
|
|||
b"IsUpdateAvailable": [TxType.CLEAR_ON_MANAGER_START],
|
||||
b"IsUploadRawEnabled": [TxType.PERSISTENT],
|
||||
b"LastAthenaPingTime": [TxType.PERSISTENT],
|
||||
b"LastUpdateTime": [TxType.PERSISTENT],
|
||||
b"LastGPSPosition": [TxType.PERSISTENT],
|
||||
b"LastUpdateException": [TxType.PERSISTENT],
|
||||
b"LastUpdateTime": [TxType.PERSISTENT],
|
||||
b"LiveParameters": [TxType.PERSISTENT],
|
||||
b"OpenpilotEnabledToggle": [TxType.PERSISTENT],
|
||||
b"LaneChangeEnabled": [TxType.PERSISTENT],
|
||||
|
@ -58,6 +59,7 @@ keys = {
|
|||
b"ShouldDoUpdate": [TxType.CLEAR_ON_MANAGER_START],
|
||||
b"SubscriberInfo": [TxType.PERSISTENT],
|
||||
b"TermsVersion": [TxType.PERSISTENT],
|
||||
b"Timezone": [TxType.PERSISTENT],
|
||||
b"TrainingVersion": [TxType.PERSISTENT],
|
||||
b"UpdateAvailable": [TxType.CLEAR_ON_MANAGER_START],
|
||||
b"UpdateFailedCount": [TxType.CLEAR_ON_MANAGER_START],
|
||||
|
|
|
@ -30,7 +30,7 @@ STEER_ANGLE_SATURATION_THRESHOLD = 2.5 # Degrees
|
|||
|
||||
SIMULATION = "SIMULATION" in os.environ
|
||||
NOSENSOR = "NOSENSOR" in os.environ
|
||||
IGNORE_PROCESSES = set(["rtshield", "uploader", "deleter", "loggerd", "logmessaged", "tombstoned", "logcatd", "proclogd", "clocksd", "gpsd", "updated"])
|
||||
IGNORE_PROCESSES = set(["rtshield", "uploader", "deleter", "loggerd", "logmessaged", "tombstoned", "logcatd", "proclogd", "clocksd", "gpsd", "updated", "timezoned"])
|
||||
|
||||
ThermalStatus = log.ThermalData.ThermalStatus
|
||||
State = log.ControlsState.OpenpilotState
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
#!/usr/bin/env python3
|
||||
import json
|
||||
import numpy as np
|
||||
import sympy as sp
|
||||
import cereal.messaging as messaging
|
||||
from cereal import log
|
||||
from common.params import Params
|
||||
import common.transformations.coordinates as coord
|
||||
from common.transformations.orientation import ecef_euler_from_ned, \
|
||||
euler_from_quat, \
|
||||
|
@ -295,6 +297,7 @@ def locationd_thread(sm, pm, disabled_logs=None):
|
|||
if pm is None:
|
||||
pm = messaging.PubMaster(['liveLocationKalman'])
|
||||
|
||||
params = Params()
|
||||
localizer = Localizer(disabled_logs=disabled_logs)
|
||||
|
||||
while True:
|
||||
|
@ -327,6 +330,14 @@ def locationd_thread(sm, pm, disabled_logs=None):
|
|||
msg.liveLocationKalman.gpsOK = gps_age < 1.0
|
||||
pm.send('liveLocationKalman', msg)
|
||||
|
||||
if sm.frame % 1200 == 0 and msg.liveLocationKalman.gpsOK: # once a minute
|
||||
location = {
|
||||
'latitude': msg.liveLocationKalman.positionGeodetic.value[0],
|
||||
'longitude': msg.liveLocationKalman.positionGeodetic.value[1],
|
||||
'altitude': msg.liveLocationKalman.positionGeodetic.value[2],
|
||||
}
|
||||
params.put("LastGPSPosition", json.dumps(location))
|
||||
|
||||
|
||||
def main(sm=None, pm=None):
|
||||
locationd_thread(sm, pm)
|
||||
|
|
|
@ -19,7 +19,7 @@ from common.basedir import BASEDIR
|
|||
from common.spinner import Spinner
|
||||
from common.text_window import TextWindow
|
||||
import selfdrive.crash as crash
|
||||
from selfdrive.hardware import HARDWARE, EON, PC
|
||||
from selfdrive.hardware import HARDWARE, EON, PC, TICI
|
||||
from selfdrive.hardware.eon.apk import update_apks, pm_apply_packages, start_offroad
|
||||
from selfdrive.swaglog import cloudlog, add_logentries_handler
|
||||
from selfdrive.version import version, dirty
|
||||
|
@ -218,6 +218,10 @@ if EON:
|
|||
'sensord',
|
||||
]
|
||||
|
||||
if TICI:
|
||||
managed_processes["timezoned"] = "selfdrive.timezoned"
|
||||
persistent_processes += ['timezoned']
|
||||
|
||||
car_started_processes = [
|
||||
'controlsd',
|
||||
'plannerd',
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
#!/usr/bin/env python3
|
||||
import time
|
||||
import json
|
||||
import subprocess
|
||||
|
||||
import requests
|
||||
from timezonefinder import TimezoneFinder
|
||||
|
||||
from common.params import Params
|
||||
from selfdrive.swaglog import cloudlog
|
||||
|
||||
|
||||
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:
|
||||
subprocess.check_call(f'sudo timedatectl set-timezone {timezone}', shell=True)
|
||||
except subprocess.CalledProcessError:
|
||||
cloudlog.exception(f"Error setting timezone to {timezone}")
|
||||
|
||||
|
||||
def main():
|
||||
params = Params()
|
||||
tf = TimezoneFinder()
|
||||
|
||||
# Get allowed timezones
|
||||
valid_timezones = subprocess.check_output('timedatectl list-timezones', shell=True, encoding='utf8').strip().split('\n')
|
||||
|
||||
while True:
|
||||
time.sleep(60)
|
||||
|
||||
is_onroad = params.get("IsOffroad") != b"1"
|
||||
if is_onroad:
|
||||
continue
|
||||
|
||||
# Set based on param
|
||||
timezone = params.get("Timezone", encoding='utf8')
|
||||
if timezone is not None:
|
||||
cloudlog.info("Setting timezone based on param")
|
||||
set_timezone(valid_timezones, timezone)
|
||||
continue
|
||||
|
||||
location = params.get("LastGPSPosition", encoding='utf8')
|
||||
|
||||
# Find timezone based on IP geolocation if no gps location is available
|
||||
if location is None:
|
||||
cloudlog.info("Setting timezone based on IP lookup")
|
||||
try:
|
||||
r = requests.get("https://ipapi.co/timezone", timeout=10)
|
||||
if r.status_code == 200:
|
||||
set_timezone(valid_timezones, r.text)
|
||||
else:
|
||||
cloudlog.error(f"Unexpected status code from api {r.status_code}")
|
||||
except requests.exceptions.RequestException:
|
||||
cloudlog.exception("Error getting timezone based on IP")
|
||||
continue
|
||||
|
||||
# Find timezone by reverse geocoding the last known gps location
|
||||
else:
|
||||
cloudlog.info("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…
Reference in New Issue