gpxd: Remove support (#273)

This commit is contained in:
Jason Wen
2024-02-01 21:03:17 -05:00
committed by GitHub
parent 72dba20a60
commit 8f0b4c49cc
5 changed files with 0 additions and 329 deletions
-2
View File
@@ -255,8 +255,6 @@ std::unordered_map<std::string, uint32_t> keys = {
{"GapAdjustCruiseMode", PERSISTENT},
{"GapAdjustCruiseTr", PERSISTENT},
{"GmapKey", PERSISTENT},
{"GpxDeleteAfterUpload", PERSISTENT},
{"GpxDeleteIfUploaded", PERSISTENT},
{"HandsOnWheelMonitoring", PERSISTENT},
{"HideVEgoUi", PERSISTENT},
{"HkgSmoothStop", PERSISTENT},
-149
View File
@@ -1,149 +0,0 @@
#!/usr/bin/env python3
# The MIT License
#
# Copyright (c) 2019-, Rick Lan, dragonpilot community, and a number of other of contributors.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
import os
import time
from common.params import Params
from common.realtime import Ratekeeper
from selfdrive.athena.registration import register
from system.version import get_version
# for uploader
from system.loggerd.xattr_cache import getxattr, setxattr
import glob
import requests
import json
RATE = 1
# customisable values
GPX_LOG_PATH = '/data/media/0/gpx_logs/'
LOG_HERTZ = 1/10 # 0.1 Hz = 10 sec, higher for higher accuracy, 10hz seems fine
# uploader
UPLOAD_ATTR_NAME = 'user.upload'
UPLOAD_ATTR_VALUE = b'1'
LOG_PATH = '/data/media/0/gpx_logs/'
# osm api
VERSION_URL = 'https://api.openstreetmap.org/api/versions'
UPLOAD_URL = 'https://sunnypilot.com/osm/gpx_uploader.php'
_DEBUG = False
def _debug(msg):
if not _DEBUG:
return
print(msg, flush=True)
def _get_is_uploaded(filename):
_debug("%s is uploaded: %s" % (filename, getxattr(filename, UPLOAD_ATTR_NAME) is not None))
return getxattr(filename, UPLOAD_ATTR_NAME) is not None
def _set_is_uploaded(filename):
_debug("%s set to uploaded" % filename)
setxattr(filename, UPLOAD_ATTR_NAME, UPLOAD_ATTR_VALUE)
def _get_files_to_be_uploaded():
files = sorted(filter(os.path.isfile, glob.glob(LOG_PATH + '*')))
files_to_be_uploaded = []
for file in files:
if not _get_is_uploaded(file):
files_to_be_uploaded.append(file)
return files_to_be_uploaded
class GpxUploader():
def __init__(self):
self.param_s = Params()
self.rk = Ratekeeper(RATE, print_delay_threshold=None)
self._delete_after_upload = self.param_s.get_bool('GpxDeleteAfterUpload')
self._car_model = "Unknown Model"
# read model from LiveParameters
params = self.param_s.get("LiveParameters")
if params is not None:
params = json.loads(params)
self._car_model = params.get('carFingerprint', self._car_model)
self._sp_version = get_version()
_debug("GpxUploader init - _delete_after_upload = %s" % self._delete_after_upload)
_debug("GpxUploader init - _car_model = %s" % self._car_model)
self.api_headers = {"User-Agent": f"sunnypilot-{self._sp_version}-{register()}"}
def update(self):
while True:
files = _get_files_to_be_uploaded()
if len(files) == 0 or not self._is_online():
_debug("run - not online or no files")
elif not self.param_s.get_bool("DisableOnroadUploads") or self.param_s.get_bool("IsOffroad"):
for file in files:
if self._do_upload(file):
if self._delete_after_upload:
_debug("run - _delete_after_upload")
os.remove(file)
else:
_debug("run - set_is_uploaded")
_set_is_uploaded(file)
# sleep for 300 secs if offroad
# otherwise sleep 60 secs
time.sleep(300 if self.param_s.get_bool("IsOffroad") else 60)
self.rk.keep_time()
def _is_online(self):
try:
r = requests.get(VERSION_URL, headers=self.api_headers)
_debug("is_online? status_code = %s" % r.status_code)
return r.status_code >= 200
except Exception as e:
print(f'Online check error: {e}')
return False
def _do_upload(self, filename):
fn = os.path.basename(filename)
data = {
'description': "Routes from sunnypilot %s (%s)." % (self._sp_version, self._car_model),
'visibility': 'identifiable'
}
files = {
"file": (fn, open(filename, 'rb'))
}
try:
r = requests.post(UPLOAD_URL, files=files, data=data, headers=self.api_headers)
_debug("do_upload - %s - %s" % (filename, r.status_code))
return r.status_code == 200
except Exception as e:
print(f'Upload error: {e}')
return False
def main():
gpx_uploader = GpxUploader()
gpx_uploader.update()
if __name__ == "__main__":
main()
-174
View File
@@ -1,174 +0,0 @@
#!/usr/bin/env python3
# The MIT License
#
# Copyright (c) 2019-, Rick Lan, dragonpilot community, and a number of other of contributors.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
import cereal.messaging as messaging
import os
import datetime
import signal
import threading
from common.realtime import Ratekeeper
from cereal import log
from system.swaglog import cloudlog
# customisable values
GPX_LOG_PATH = '/data/media/0/gpx_logs/'
LOG_HERTZ = 10 # 10 hz = 0.1 sec, higher for higher accuracy, 10hz seems fine
LOG_LENGTH = 10 # mins, higher means it keeps more data in the memory, will take more time to write into a file too.
LOST_SIGNAL_COUNT_LENGTH = 10 # secs, output log file if we lost signal for this long
# do not change
LOST_SIGNAL_COUNT_MAX = LOST_SIGNAL_COUNT_LENGTH * LOG_HERTZ # secs,
LOGS_PER_FILE = LOG_LENGTH * 60 * LOG_HERTZ # e.g. 10 * 60 * 10 = 6000 points per file
_DEBUG = False
_CLOUDLOG_DEBUG = True
def _debug(msg, log_to_cloud=True):
if _CLOUDLOG_DEBUG and log_to_cloud:
cloudlog.debug(msg)
if _DEBUG:
print(msg)
class WaitTimeHelper:
ready_event = threading.Event()
shutdown = False
def __init__(self):
signal.signal(signal.SIGTERM, self.graceful_shutdown)
signal.signal(signal.SIGINT, self.graceful_shutdown)
signal.signal(signal.SIGHUP, self.graceful_shutdown)
def graceful_shutdown(self, signum, frame):
self.shutdown = True
self.ready_event.set()
class GpxD:
def __init__(self, sm):
self.sm = sm
self.rk = Ratekeeper(LOG_HERTZ, print_delay_threshold=None)
self.log_count = 0
self.logs = list()
self.lost_signal_count = 0
self.wait_helper = WaitTimeHelper()
self.started_time = datetime.datetime.utcnow().isoformat()
self.v_ego_prev = 0.
self.pause = True
def log(self):
location = self.sm['liveLocationKalman']
gps = self.sm['gpsLocationExternal']
v_ego = self.sm['carState'].vEgo
if abs(v_ego) > 0.:
self.pause = False
location_valid = (location.status == log.LiveLocationKalman.Status.valid) and location.positionGeodetic.valid
_debug("gpxd: location_valid - %s" % location_valid)
if not location_valid or self.pause:
if self.log_count > 0:
self.lost_signal_count += 1
else:
lat = location.positionGeodetic.value[0]
lon = location.positionGeodetic.value[1]
alt = gps.altitude
_debug("gpxd: logged - %s %s %s %s" % (datetime.datetime.utcfromtimestamp(location.unixTimestampMillis*0.001).isoformat(), str(lat), str(lon), str(alt)))
self.logs.append([datetime.datetime.utcfromtimestamp(location.unixTimestampMillis*0.001).isoformat(), str(lat), str(lon), str(alt)])
self.log_count += 1
self.lost_signal_count = 0
if not self.pause and abs(v_ego) < 0.01:
_debug("gpxd: paused")
self.pause = True
self.v_ego_prev = v_ego
def write_log(self, force = False):
if self.log_count == 0:
return
if force or (self.log_count >= LOGS_PER_FILE or self.lost_signal_count >= LOST_SIGNAL_COUNT_MAX):
_debug("gpxd: save to log")
self._write_gpx()
self.lost_signal_count = 0
self.log_count = 0
self.logs.clear()
self.started_time = datetime.datetime.utcnow().isoformat()
def _write_gpx(self):
if len(self.logs) > 1:
if not os.path.exists(GPX_LOG_PATH):
os.makedirs(GPX_LOG_PATH)
filename = self.started_time.replace(':','-')
str = ''
str += "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\n"
str += "<gpx version=\"1.1\" creator=\"sunnypilot https://github.com/sunnypilot/openpilot\" xmlns=\"http://www.topografix.com/GPX/1/1\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\">\n"
str += "<trk>\n"
str += " <name>" + self.started_time + "</name>"
str += " <trkseg>\n"
for trkpt in self.logs:
str += self._trkpt_template(trkpt[1], trkpt[2], trkpt[3], trkpt[0])
str += " </trkseg>\n"
str += "</trk>\n"
str += "</gpx>\n"
try:
f = open('%s%sZ.gpx' % (GPX_LOG_PATH, filename), 'w')
f.write(str)
f.close()
except:
pass
def _trkpt_template(self, lat, lon, ele, time):
str = ""
str += " <trkpt lat=\"" + lat + "\" lon=\"" + lon + "\">\n"
str += " <ele>" + ele + "</ele>\n"
str += " <time>" + time + "</time>\n"
str += " </trkpt>\n"
return str
def gpxd_thread(self):
while True:
self.sm.update(0)
self.log()
self.write_log()
if self.wait_helper.shutdown:
self.write_log(True)
break
self.rk.keep_time()
def main(sm=None):
if sm is None:
sm = messaging.SubMaster(['liveLocationKalman', 'gpsLocationExternal', 'carState'])
gpx = GpxD(sm)
gpx.gpxd_thread()
if __name__ == "__main__":
main()
-2
View File
@@ -75,8 +75,6 @@ def manager_init() -> None:
("GapAdjustCruiseMin", "0"),
("GapAdjustCruiseMode", "0"),
("GapAdjustCruiseTr", "3"),
("GpxDeleteAfterUpload", "1"),
("GpxDeleteIfUploaded", "1"),
("HandsOnWheelMonitoring", "0"),
("HideVEgoUi", "0"),
("LastSpeedLimitSignTap", "0"),
-2
View File
@@ -82,8 +82,6 @@ procs = [
PythonProcess("uploader", "system.loggerd.uploader", always_run),
PythonProcess("statsd", "selfdrive.statsd", always_run),
PythonProcess("gpxd", "selfdrive.gpxd.gpxd", only_onroad),
PythonProcess("gpxd_uploader", "selfdrive.gpxd.gpx_uploader", always_run),
PythonProcess("fleet_manager", "system.fleetmanager.fleet_manager", only_offroad),
# debug procs