nopenpilot/selfdrive/timezoned.py

90 lines
2.8 KiB
Python
Executable File

#!/usr/bin/env python3
import json
import os
import time
import subprocess
from typing import NoReturn
import requests
from timezonefinder import TimezoneFinder
from common.params import Params
from selfdrive.hardware import TICI
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.debug(f"Setting timezone to {timezone}")
try:
if TICI:
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')
while True:
time.sleep(60)
is_onroad = not params.get_bool("IsOffroad")
if is_onroad:
continue
# Set based on param
timezone = params.get("Timezone", encoding='utf8')
if timezone is not None:
cloudlog.debug("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.debug("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}")
time.sleep(3600) # Don't make too many API requests
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.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()