def manager_thread(): # now loop thermal_sock = messaging.sub_sock('thermal') cloudlog.info("manager start") cloudlog.info({"environ": os.environ}) # save boot log subprocess.call(["./loggerd", "--bootlog"], cwd=os.path.join(BASEDIR, "selfdrive/loggerd")) params = Params() # start daemon processes for p in daemon_processes: start_daemon_process(p) # start persistent processes for p in persistent_processes: start_managed_process(p) # start frame pm_apply_packages('enable') start_frame() if os.getenv("NOBOARD") is None: start_managed_process("pandad") logger_dead = False while 1: msg = messaging.recv_sock(thermal_sock, wait=True) # uploader is gated based on the phone temperature if msg.thermal.thermalStatus >= ThermalStatus.yellow: kill_managed_process("uploader") else: start_managed_process("uploader") if msg.thermal.freeSpace < 0.05: logger_dead = True if msg.thermal.started: for p in car_started_processes: if p == "loggerd" and logger_dead: kill_managed_process(p) else: start_managed_process(p) else: logger_dead = False for p in reversed(car_started_processes): kill_managed_process(p) # check the status of all processes, did any of them die? running_list = ["%s%s\u001b[0m" % ("\u001b[32m" if running[p].is_alive() else "\u001b[31m", p) for p in running] cloudlog.debug(' '.join(running_list)) # Exit main loop when uninstall is needed if params.get("DoUninstall", encoding='utf8') == "1": break
def manager_thread(): cloudlog.info("manager start") cloudlog.info({"environ": os.environ}) # save boot log subprocess.call("./bootlog", cwd=os.path.join(BASEDIR, "selfdrive/loggerd")) params = Params() ignore = [] if os.getenv("NOBOARD") is not None: ignore.append("pandad") if os.getenv("BLOCK") is not None: ignore += os.getenv("BLOCK").split(",") ensure_running(managed_processes.values(), started=False, not_run=ignore) started_prev = False sm = messaging.SubMaster(['deviceState']) pm = messaging.PubMaster(['managerState']) while True: sm.update() not_run = ignore[:] if sm['deviceState'].freeSpacePercent < 5: not_run.append("loggerd") started = sm['deviceState'].started driverview = params.get_bool("IsDriverViewEnabled") ensure_running(managed_processes.values(), started, driverview, not_run) # trigger an update after going offroad if started_prev and not started and 'updated' in managed_processes: os.sync() managed_processes['updated'].signal(signal.SIGHUP) started_prev = started running_list = [ "%s%s\u001b[0m" % ("\u001b[32m" if p.proc.is_alive() else "\u001b[31m", p.name) for p in managed_processes.values() if p.proc ] cloudlog.debug(' '.join(running_list)) # send managerState msg = messaging.new_message('managerState') msg.managerState.processes = [ p.get_process_state_msg() for p in managed_processes.values() ] pm.send('managerState', msg) # TODO: let UI handle this # Exit main loop when uninstall is needed if params.get_bool("DoUninstall"): break
def upload(self, key, fn): try: sz = os.path.getsize(fn) except OSError: cloudlog.exception("upload: getsize failed") return False cloudlog.event("upload", key=key, fn=fn, sz=sz) cloudlog.debug("checking %r with size %r", key, sz) if sz == 0: try: # tag files of 0 size as uploaded setxattr(fn, UPLOAD_ATTR_NAME, UPLOAD_ATTR_VALUE) except OSError: cloudlog.event("uploader_setxattr_failed", exc=self.last_exc, key=key, fn=fn, sz=sz) success = True else: start_time = time.monotonic() cloudlog.debug("uploading %r", fn) stat = self.normal_upload(key, fn) if stat is not None and stat.status_code in (200, 201, 403, 412): cloudlog.event("upload_success" if stat.status_code != 412 else "upload_ignored", key=key, fn=fn, sz=sz, debug=True) try: # tag file as uploaded setxattr(fn, UPLOAD_ATTR_NAME, UPLOAD_ATTR_VALUE) except OSError: cloudlog.event("uploader_setxattr_failed", exc=self.last_exc, key=key, fn=fn, sz=sz) self.last_filename = fn self.last_time = time.monotonic() - start_time self.last_speed = (sz / 1e6) / self.last_time success = True else: cloudlog.event("upload_failed", stat=stat, exc=self.last_exc, key=key, fn=fn, sz=sz, debug=True) success = False return success
def manager_thread(): cloudlog.info("manager start") cloudlog.info({"environ": os.environ}) params = Params() ignore = [] if params.get("DongleId", encoding='utf8') == UNREGISTERED_DONGLE_ID: ignore += ["manage_athenad", "uploader"] if os.getenv("NOBOARD") is not None: ignore.append("pandad") if os.getenv("BLOCK") is not None: ignore += os.getenv("BLOCK").split(",") ensure_running(managed_processes.values(), started=False, not_run=ignore) started_prev = False sm = messaging.SubMaster(['deviceState']) pm = messaging.PubMaster(['managerState']) while True: sm.update() not_run = ignore[:] if sm['deviceState'].freeSpacePercent < 5: not_run.append("loggerd") started = sm['deviceState'].started driverview = params.get_bool("IsDriverViewEnabled") ensure_running(managed_processes.values(), started, driverview, not_run) # trigger an update after going offroad if started_prev and not started and 'updated' in managed_processes: os.sync() managed_processes['updated'].signal(signal.SIGHUP) started_prev = started running = ' '.join(["%s%s\u001b[0m" % ("\u001b[32m" if p.proc.is_alive() else "\u001b[31m", p.name) for p in managed_processes.values() if p.proc]) print(running) cloudlog.debug(running) # send managerState msg = messaging.new_message('managerState') msg.managerState.processes = [p.get_process_state_msg() for p in managed_processes.values()] pm.send('managerState', msg) # Exit main loop when uninstall/shutdown/reboot is needed shutdown = False for param in ("DoUninstall", "DoShutdown", "DoReboot"): if params.get_bool(param): cloudlog.warning(f"Shutting down manager - {param} set") shutdown = True if shutdown: break
def manager_thread(): # now loop context = zmq.Context() thermal_sock = messaging.sub_sock(context, service_list['thermal'].port) cloudlog.info("manager start") cloudlog.info({"environ": os.environ}) # save boot log subprocess.call(["./loggerd", "--bootlog"], cwd=os.path.join(BASEDIR, "selfdrive/loggerd")) for p in persistent_processes: start_managed_process(p) # start frame pm_apply_packages('enable') system("am start -n ai.comma.plus.frame/.MainActivity") if os.getenv("NOBOARD") is None: start_managed_process("pandad") params = Params() logger_dead = False while 1: # get health of board, log this in "thermal" msg = messaging.recv_sock(thermal_sock, wait=True) # uploader is gated based on the phone temperature if msg.thermal.thermalStatus >= ThermalStatus.yellow: kill_managed_process("uploader") else: start_managed_process("uploader") if msg.thermal.freeSpace < 0.05: logger_dead = True if msg.thermal.started: for p in car_started_processes: if p == "loggerd" and logger_dead: kill_managed_process(p) else: start_managed_process(p) else: logger_dead = False for p in car_started_processes: kill_managed_process(p) # check the status of all processes, did any of them die? for p in running: cloudlog.debug(" running %s %s" % (p, running[p])) # is this still needed? if params.get("DoUninstall") == "1": break
def __init__(self, CP, CarController, CarState): super().__init__(CP, CarController, CarState) cloudlog.debug("Using Mock Car Interface") self.sensor = messaging.sub_sock('sensorEvents') self.gps = messaging.sub_sock('gpsLocationExternal') self.speed = 0. self.prev_speed = 0. self.yaw_rate = 0. self.yaw_rate_meas = 0.
def uploader_fn(exit_event): params = Params() dongle_id = params.get("DongleId", encoding='utf8') if dongle_id is None: cloudlog.info("uploader missing dongle_id") raise Exception("uploader can't start without dongle id") if TICI and not Path("/data/media").is_mount(): cloudlog.warning("NVME not mounted") sm = messaging.SubMaster(['deviceState']) pm = messaging.PubMaster(['uploaderState']) uploader = Uploader(dongle_id, ROOT) backoff = 0.1 while not exit_event.is_set(): sm.update(0) offroad = params.get_bool("IsOffroad") network_type = sm[ 'deviceState'].networkType if not force_wifi else NetworkType.wifi if network_type == NetworkType.none: if allow_sleep: time.sleep(60 if offroad else 5) continue good_internet = network_type in [ NetworkType.wifi, NetworkType.ethernet ] allow_raw_upload = params.get_bool("UploadRaw") d = uploader.next_file_to_upload( with_raw=allow_raw_upload and good_internet and offroad) if d is None: # Nothing to upload if allow_sleep: time.sleep(60 if offroad else 5) continue key, fn = d cloudlog.debug("upload %r over %s", d, network_type) success = uploader.upload(key, fn) if success: backoff = 0.1 elif allow_sleep: cloudlog.info("upload backoff %r", backoff) time.sleep(backoff + random.uniform(0, backoff)) backoff = min(backoff * 2, 120) pm.send("uploaderState", uploader.get_msg()) cloudlog.info("upload done, success=%r", success)
def __init__(self, CP, CarController, CarState): self.CP = CP self.CC = CarController cloudlog.debug("Using Mock Car Interface") # TODO: subscribe to phone sensor self.sensor = messaging.sub_sock('sensorEvents') self.gps = messaging.sub_sock('gpsLocation') self.speed = 0. self.prev_speed = 0. self.yaw_rate = 0. self.yaw_rate_meas = 0.
def __init__(self, CP, sendcan=None): self.CP = CP cloudlog.debug("Using Mock Car Interface") context = zmq.Context() # TODO: subscribe to phone sensor self.sensor = messaging.sub_sock(context, service_list['sensorEvents'].port) self.gps = messaging.sub_sock(context, service_list['gpsLocation'].port) self.speed = 0. self.prev_speed = 0. self.yaw_rate = 0. self.yaw_rate_meas = 0.
def manager_thread() -> None: Process(name="road_speed_limiter", target=launcher, args=("selfdrive.road_speed_limiter", "road_speed_limiter")).start() cloudlog.bind(daemon="manager") cloudlog.info("manager start") cloudlog.info({"environ": os.environ}) params = Params() ignore: List[str] = [] if params.get("DongleId", encoding='utf8') in (None, UNREGISTERED_DONGLE_ID): ignore += ["manage_athenad", "uploader"] if os.getenv("NOBOARD") is not None: ignore.append("pandad") ignore += [x for x in os.getenv("BLOCK", "").split(",") if len(x) > 0] ensure_running(managed_processes.values(), started=False, not_run=ignore) sm = messaging.SubMaster(['deviceState', 'carParams'], poll=['deviceState']) pm = messaging.PubMaster(['managerState']) while True: sm.update() started = sm['deviceState'].started driverview = params.get_bool("IsDriverViewEnabled") ensure_running(managed_processes.values(), started=started, driverview=driverview, notcar=sm['carParams'].notCar, not_run=ignore) running = ' '.join("%s%s\u001b[0m" % ("\u001b[32m" if p.proc.is_alive() else "\u001b[31m", p.name) for p in managed_processes.values() if p.proc) print(running) cloudlog.debug(running) # send managerState msg = messaging.new_message('managerState') msg.managerState.processes = [p.get_process_state_msg() for p in managed_processes.values()] pm.send('managerState', msg) # Exit main loop when uninstall/shutdown/reboot is needed shutdown = False for param in ("DoUninstall", "DoShutdown", "DoReboot"): if params.get_bool(param): shutdown = True params.put("LastManagerExitReason", param) cloudlog.warning(f"Shutting down manager - {param} set") if shutdown: break
def __init__(self, CP, CarController): self.CP = CP self.CC = CarController cloudlog.debug("Using Mock Car Interface") # TODO: subscribe to phone sensor self.sensor = messaging.sub_sock(service_list['sensorEvents'].port) self.gps = messaging.sub_sock(service_list['gpsLocation'].port) self.speed = 0. self.prev_speed = 0. self.yaw_rate = 0. self.yaw_rate_meas = 0. self.rk = Ratekeeper(100, print_delay_threshold=2. / 1000)
def ws_proxy_recv(ws, local_sock, ssock, end_event, global_end_event): while not (end_event.is_set() or global_end_event.is_set()): try: data = ws.recv() local_sock.sendall(data) except WebSocketTimeoutException: pass except Exception: cloudlog.exception("athenad.ws_proxy_recv.exception") break cloudlog.debug("athena.ws_proxy_recv closing sockets") ssock.close() local_sock.close() cloudlog.debug("athena.ws_proxy_recv done closing sockets") end_event.set()
def jsonrpc_handler(end_event): dispatcher["startLocalProxy"] = partial(startLocalProxy, end_event) while not end_event.is_set(): try: data = recv_queue.get(timeout=1) if "method" in data: cloudlog.debug(f"athena.jsonrpc_handler.call_method {data}") response = JSONRPCResponseManager.handle(data, dispatcher) send_queue.put_nowait(response.json) elif "id" in data and ("result" in data or "error" in data): log_recv_queue.put_nowait(data) else: raise Exception("not a valid request or response") except queue.Empty: pass except Exception as e: cloudlog.exception("athena jsonrpc handler failed") send_queue.put_nowait(json.dumps({"error": str(e)}))
def uploader_fn(exit_event): cloudlog.info("uploader_fn") params = Params() dongle_id = params.get("DongleId").decode('utf8') if dongle_id is None: cloudlog.info("uploader missing dongle_id") raise Exception("uploader can't start without dongle id") if TICI and not Path("/data/media").is_mount(): cloudlog.debug("NVME not mounted") sm = messaging.SubMaster(['deviceState']) uploader = Uploader(dongle_id, ROOT) backoff = 0.1 while not exit_event.is_set(): sm.update(0) on_wifi = force_wifi or sm[ 'deviceState'].networkType == NetworkType.wifi offroad = params.get("IsOffroad") == b'1' allow_raw_upload = params.get("IsUploadRawEnabled") != b"0" d = uploader.next_file_to_upload( with_raw=allow_raw_upload and on_wifi and offroad) if d is None: # Nothing to upload if allow_sleep: time.sleep(60 if offroad else 5) continue key, fn = d cloudlog.event("uploader_netcheck", is_on_wifi=on_wifi) cloudlog.info("to upload %r", d) success = uploader.upload(key, fn) if success: backoff = 0.1 elif allow_sleep: cloudlog.info("backoff %r", backoff) time.sleep(backoff + random.uniform(0, backoff)) backoff = min(backoff * 2, 120) cloudlog.info("upload done, success=%r", success)
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 do_upload(self, key, fn): try: url_resp = self.api.get("v1.4/" + self.dongle_id + "/upload_url/", timeout=10, path=key, access_token=self.api.get_token()) if url_resp.status_code == 412: self.last_resp = url_resp return url_resp_json = json.loads(url_resp.text) url = url_resp_json['url'] headers = url_resp_json['headers'] cloudlog.debug("upload_url v1.4 %s %s", url, str(headers)) if fake_upload: cloudlog.debug( f"*** WARNING, THIS IS A FAKE UPLOAD TO {url} ***") class FakeResponse(): def __init__(self): self.status_code = 200 self.last_resp = FakeResponse() else: with open(fn, "rb") as f: if key.endswith('.bz2') and not fn.endswith('.bz2'): data = bz2.compress(f.read()) data = io.BytesIO(data) else: data = f self.last_resp = requests.put(url, data=data, headers=headers, timeout=10) except Exception as e: self.last_exc = (e, traceback.format_exc()) raise
def ws_proxy_send(ws, local_sock, signal_sock, end_event): while not end_event.is_set(): try: r, _, _ = select.select((local_sock, signal_sock), (), ()) if r: if r[0].fileno() == signal_sock.fileno(): # got end signal from ws_proxy_recv end_event.set() break data = local_sock.recv(4096) if not data: # local_sock is dead end_event.set() break ws.send(data, ABNF.OPCODE_BINARY) except Exception: cloudlog.exception("athenad.ws_proxy_send.exception") end_event.set() cloudlog.debug("athena.ws_proxy_send closing sockets") signal_sock.close() cloudlog.debug("athena.ws_proxy_send done closing sockets")
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)
def __init__(self, CP, CarController, CarState): self.CP = CP self.CC = CarController cloudlog.debug("Using Mock Car Interface") # TODO: subscribe to phone sensor self.sensor = messaging.sub_sock('sensorEvents') self.gps = messaging.sub_sock('gpsLocation') self.speed = 0. self.prev_speed = 0. self.yaw_rate = 0. self.yaw_rate_meas = 0. # dp # mock override constructor so we need to define here as well. self.dragon_toyota_stock_dsu = False self.dragon_enable_steering_on_signal = False self.dragon_allow_gas = False self.ts_last_check = 0. self.dragon_lat_ctrl = True self.dp_last_modified = None self.dp_gear_check = True
def manager_thread(): cloudlog.info("manager start") cloudlog.info({"environ": os.environ}) # save boot log subprocess.call("./bootlog", cwd=os.path.join(BASEDIR, "selfdrive/loggerd")) # start daemon processes for p in daemon_processes: start_daemon_process(p) # start persistent processes for p in persistent_processes: start_managed_process(p) # start offroad if EON: pm_apply_packages('enable') start_offroad() if os.getenv("NOBOARD") is not None: del managed_processes["pandad"] if os.getenv("BLOCK") is not None: for k in os.getenv("BLOCK").split(","): del managed_processes[k] started_prev = False logger_dead = False params = Params() device_state_sock = messaging.sub_sock('deviceState') pm = messaging.PubMaster(['managerState']) while 1: msg = messaging.recv_sock(device_state_sock, wait=True) if msg.deviceState.freeSpacePercent < 5: logger_dead = True if msg.deviceState.started: for p in car_started_processes: if p == "loggerd" and logger_dead: kill_managed_process(p) else: start_managed_process(p) else: logger_dead = False driver_view = params.get("IsDriverViewEnabled") == b"1" # TODO: refactor how manager manages processes for p in reversed(car_started_processes): if p not in driver_view_processes or not driver_view: kill_managed_process(p) for p in driver_view_processes: if driver_view: start_managed_process(p) else: kill_managed_process(p) # trigger an update after going offroad if started_prev: os.sync() send_managed_process_signal("updated", signal.SIGHUP) started_prev = msg.deviceState.started # check the status of all processes, did any of them die? running_list = ["%s%s\u001b[0m" % ("\u001b[32m" if running[p].is_alive() else "\u001b[31m", p) for p in running] cloudlog.debug(' '.join(running_list)) # send managerState states = [] for p in managed_processes: state = log.ManagerState.ProcessState.new_message() state.name = p if p in running: state.running = running[p].is_alive() state.pid = running[p].pid state.exitCode = running[p].exitcode or 0 states.append(state) msg = messaging.new_message('managerState') msg.managerState.processes = states pm.send('managerState', msg) # Exit main loop when uninstall is needed if params.get("DoUninstall", encoding='utf8') == "1": break
def manager_thread(): # now loop thermal_sock = messaging.sub_sock('thermal') if os.getenv("GET_CPU_USAGE"): proc_sock = messaging.sub_sock('procLog', conflate=True) cloudlog.info("manager start") cloudlog.info({"environ": os.environ}) # save boot log subprocess.call(["./loggerd", "--bootlog"], cwd=os.path.join(BASEDIR, "selfdrive/loggerd")) params = Params() # start daemon processes for p in daemon_processes: start_daemon_process(p) # start persistent processes for p in persistent_processes: start_managed_process(p) # start offroad if ANDROID: pm_apply_packages('enable') start_offroad() if os.getenv("NOBOARD") is None: start_managed_process("pandad") if os.getenv("BLOCK") is not None: for k in os.getenv("BLOCK").split(","): del managed_processes[k] logger_dead = False start_t = time.time() first_proc = None while 1: msg = messaging.recv_sock(thermal_sock, wait=True) # heavyweight batch processes are gated on favorable thermal conditions if msg.thermal.thermalStatus >= ThermalStatus.yellow: for p in green_temp_processes: if p in persistent_processes: kill_managed_process(p) else: for p in green_temp_processes: if p in persistent_processes: start_managed_process(p) if msg.thermal.freeSpace < 0.05: logger_dead = True if msg.thermal.started and "driverview" not in running: for p in car_started_processes: if p == "loggerd" and logger_dead: kill_managed_process(p) else: start_managed_process(p) else: logger_dead = False for p in reversed(car_started_processes): kill_managed_process(p) # this is ugly if "driverview" not in running and params.get( "IsDriverViewEnabled") == b"1": start_managed_process("driverview") elif "driverview" in running and params.get( "IsDriverViewEnabled") == b"0": kill_managed_process("driverview") # check the status of all processes, did any of them die? running_list = [ "%s%s\u001b[0m" % ("\u001b[32m" if running[p].is_alive() else "\u001b[31m", p) for p in running ] cloudlog.debug(' '.join(running_list)) # Exit main loop when uninstall is needed if params.get("DoUninstall", encoding='utf8') == "1": break if os.getenv("GET_CPU_USAGE"): dt = time.time() - start_t # Get first sample if dt > 30 and first_proc is None: first_proc = messaging.recv_sock(proc_sock) # Get last sample and exit if dt > 90: last_proc = messaging.recv_sock(proc_sock, wait=True) cleanup_all_processes(None, None) sys.exit(print_cpu_usage(first_proc, last_proc))
def manager_thread(): cloudlog.info("manager start") cloudlog.info({"environ": os.environ}) params = Params() dp_reg = params.get_bool('dp_reg') dp_logger = params.get_bool('dp_logger') dp_athenad = params.get_bool('dp_athenad') dp_uploader = params.get_bool('dp_uploader') dp_atl = params.get_bool('dp_atl') dp_jetson = params.get_bool('dp_jetson') dp_otisserv = params.get_bool('dp_otisserv') dp_mapd = params.get_bool('dp_mapd') if not dp_reg: dp_athenad = False dp_uploader = False # save boot log if dp_logger: subprocess.call("./bootlog", cwd=os.path.join(BASEDIR, "selfdrive/loggerd")) ignore = [] if dp_jetson: ignore += ['dmonitoringmodeld', 'dmonitoringd'] if not params.get_bool('dp_dashcamd'): ignore += ['dashcamd'] if not params.get_bool('dp_updated'): ignore += ['updated'] if not dp_logger: ignore += [ 'logcatd', 'loggerd', 'proclogd', 'logmessaged', 'tombstoned' ] if not dp_athenad: ignore += ['manage_athenad'] if not dp_athenad and not dp_uploader: ignore += ['deleter'] if not dp_mapd: ignore += ['mapd'] if not dp_otisserv: ignore += ['otisserv'] if not dp_mapd and not dp_otisserv and not params.get_bool('dp_gpxd'): ignore += ['gpxd'] if params.get("DongleId", encoding='utf8') == UNREGISTERED_DONGLE_ID: ignore += ["manage_athenad", "uploader"] if os.getenv("NOBOARD") is not None: ignore.append("pandad") if os.getenv("BLOCK") is not None: ignore += os.getenv("BLOCK").split(",") ensure_running(managed_processes.values(), started=False, not_run=ignore) started_prev = False sm = messaging.SubMaster(['deviceState']) pm = messaging.PubMaster(['managerState']) while True: sm.update() not_run = ignore[:] if sm['deviceState'].freeSpacePercent < 5: not_run.append("loggerd") started = sm['deviceState'].started driverview = params.get_bool("IsDriverViewEnabled") ensure_running(managed_processes.values(), started, driverview, not_run) # trigger an update after going offroad if started_prev and not started and 'updated' in managed_processes: os.sync() managed_processes['updated'].signal(signal.SIGHUP) started_prev = started running_list = [ "%s%s\u001b[0m" % ("\u001b[32m" if p.proc.is_alive() else "\u001b[31m", p.name) for p in managed_processes.values() if p.proc ] cloudlog.debug(' '.join(running_list)) # send managerState msg = messaging.new_message('managerState') msg.managerState.processes = [ p.get_process_state_msg() for p in managed_processes.values() ] pm.send('managerState', msg) # TODO: let UI handle this # Exit main loop when uninstall is needed if params.get_bool("DoUninstall"): break
def manager_thread(spinner=None): shutdownd = Process(name="shutdownd", target=launcher, args=("selfdrive.shutdownd", )) shutdownd.start() if EON: pm_grant("com.neokii.openpilot", "android.permission.ACCESS_FINE_LOCATION") appops_set("com.neokii.optool", "SU", "allow") system("am startservice com.neokii.optool/.MainService") system("am startservice com.neokii.openpilot/.MainService") cloudlog.info("manager start") cloudlog.info({"environ": os.environ}) # save boot log #subprocess.call("./bootlog", cwd=os.path.join(BASEDIR, "selfdrive/loggerd")) ignore = [] if os.getenv("NOBOARD") is not None: ignore.append("pandad") if os.getenv("BLOCK") is not None: ignore += os.getenv("BLOCK").split(",") # start offroad if EON and "QT" not in os.environ: pm_apply_packages('enable') start_offroad() ensure_running(managed_processes.values(), started=False, not_run=ignore) if spinner: # close spinner when ui has started spinner.close() started_prev = False params = Params() sm = messaging.SubMaster(['deviceState']) pm = messaging.PubMaster(['managerState']) while True: sm.update() not_run = ignore[:] if sm['deviceState'].freeSpacePercent < 5: not_run.append("loggerd") started = sm['deviceState'].started driverview = params.get("IsDriverViewEnabled") == b"1" ensure_running(managed_processes.values(), started, driverview, not_run) # trigger an update after going offroad if started_prev and not started and 'updated' in managed_processes: os.sync() managed_processes['updated'].signal(signal.SIGHUP) started_prev = started running_list = [ "%s%s\u001b[0m" % ("\u001b[32m" if p.proc.is_alive() else "\u001b[31m", p.name) for p in managed_processes.values() if p.proc ] cloudlog.debug(' '.join(running_list)) # send managerState msg = messaging.new_message('managerState') msg.managerState.processes = [ p.get_process_state_msg() for p in managed_processes.values() ] pm.send('managerState', msg) # Exit main loop when uninstall is needed if params.get("DoUninstall", encoding='utf8') == "1": break
def manager_thread(): if EON: Process(name="shutdownd", target=launcher, args=("selfdrive.shutdownd", )).start() system("am startservice com.neokii.optool/.MainService") Process(name="road_speed_limiter", target=launcher, args=("selfdrive.road_speed_limiter", )).start() cloudlog.info("manager start") cloudlog.info({"environ": os.environ}) # save boot log #subprocess.call("./bootlog", cwd=os.path.join(BASEDIR, "selfdrive/loggerd")) params = Params() ignore = [] if params.get("DongleId", encoding='utf8') == UNREGISTERED_DONGLE_ID: ignore += ["manage_athenad", "uploader"] if os.getenv("NOBOARD") is not None: ignore.append("pandad") if os.getenv("BLOCK") is not None: ignore += os.getenv("BLOCK").split(",") ensure_running(managed_processes.values(), started=False, not_run=ignore) started_prev = False sm = messaging.SubMaster(['deviceState']) pm = messaging.PubMaster(['managerState']) while True: sm.update() not_run = ignore[:] if sm['deviceState'].freeSpacePercent < 5: not_run.append("loggerd") started = sm['deviceState'].started driverview = params.get_bool("IsDriverViewEnabled") ensure_running(managed_processes.values(), started, driverview, not_run) # trigger an update after going offroad if started_prev and not started and 'updated' in managed_processes: os.sync() managed_processes['updated'].signal(signal.SIGHUP) started_prev = started running_list = [ "%s%s\u001b[0m" % ("\u001b[32m" if p.proc.is_alive() else "\u001b[31m", p.name) for p in managed_processes.values() if p.proc ] cloudlog.debug(' '.join(running_list)) # send managerState msg = messaging.new_message('managerState') msg.managerState.processes = [ p.get_process_state_msg() for p in managed_processes.values() ] pm.send('managerState', msg) # TODO: let UI handle this # Exit main loop when uninstall is needed if params.get_bool("DoUninstall"): break
def log_handler(end_event): if PC: return log_files = [] last_scan = 0 while not end_event.is_set(): try: curr_scan = sec_since_boot() if curr_scan - last_scan > 10: log_files = get_logs_to_send_sorted() last_scan = curr_scan # send one log curr_log = None if len(log_files) > 0: log_entry = log_files.pop() cloudlog.debug( f"athena.log_handler.forward_request {log_entry}") try: curr_time = int(time.time()) log_path = os.path.join(SWAGLOG_DIR, log_entry) setxattr(log_path, LOG_ATTR_NAME, int.to_bytes(curr_time, 4, sys.byteorder)) with open(log_path, "r") as f: jsonrpc = { "method": "forwardLogs", "params": { "logs": f.read() }, "jsonrpc": "2.0", "id": log_entry } log_send_queue.put_nowait(json.dumps(jsonrpc)) curr_log = log_entry except OSError: pass # file could be deleted by log rotation # wait for response up to ~100 seconds # always read queue at least once to process any old responses that arrive for _ in range(100): if end_event.is_set(): break try: log_resp = json.loads(log_recv_queue.get(timeout=1)) log_entry = log_resp.get("id") log_success = "result" in log_resp and log_resp[ "result"].get("success") cloudlog.debug( f"athena.log_handler.forward_response {log_entry} {log_success}" ) if log_entry and log_success: log_path = os.path.join(SWAGLOG_DIR, log_entry) try: setxattr(log_path, LOG_ATTR_NAME, LOG_ATTR_VALUE_MAX_UNIX_TIME) except OSError: pass # file could be deleted by log rotation if curr_log == log_entry: break except queue.Empty: if curr_log is None: break except Exception: cloudlog.exception("athena.log_handler.exception")
def uploader_fn(exit_event): params = Params() dongle_id = params.get("DongleId", encoding='utf8') transition_to_offroad_last = 0. disable_onroad_upload_offroad_transition_timeout = 900. # wait until offroad for 15 minutes before starting uploads offroad_last = params.get_bool("IsOffroad") if dongle_id is None: cloudlog.info("uploader missing dongle_id") raise Exception("uploader can't start without dongle id") if TICI and not Path("/data/media").is_mount(): cloudlog.warning("NVME not mounted") sm = messaging.SubMaster(['deviceState']) pm = messaging.PubMaster(['uploaderState']) uploader = Uploader(dongle_id, ROOT) backoff = 0.1 while not exit_event.is_set(): sm.update(0) offroad = params.get_bool("IsOffroad") t = sec_since_boot() if offroad and not offroad_last and t > 300.: transition_to_offroad_last = sec_since_boot() offroad_last = offroad network_type = sm[ 'deviceState'].networkType if not force_wifi else NetworkType.wifi if network_type == NetworkType.none: if allow_sleep: time.sleep(60 if offroad else 5) continue on_wifi = network_type == NetworkType.wifi allow_raw_upload = params.get_bool("UploadRaw") if Params().get_bool("DisableOnroadUploads"): if not offroad or ( transition_to_offroad_last > 0. and t - transition_to_offroad_last < disable_onroad_upload_offroad_transition_timeout): if not offroad: cloudlog.info("not uploading: onroad uploads disabled") else: wait_minutes = int( disable_onroad_upload_offroad_transition_timeout / 60) time_left = disable_onroad_upload_offroad_transition_timeout - ( t - transition_to_offroad_last) if (time_left / 60. > 2.): time_left_str = f"{int(time_left / 60)} minute(s)" else: time_left_str = f"{int(time_left)} seconds(s)" cloudlog.info( f"not uploading: waiting until offroad for {wait_minutes} minutes; {time_left_str} left" ) if allow_sleep: time.sleep(60) continue d = uploader.next_file_to_upload( with_raw=allow_raw_upload and on_wifi and offroad) if d is None: # Nothing to upload if allow_sleep: time.sleep(60 if offroad else 5) continue key, fn = d cloudlog.debug("upload %r over %s", d, network_type) success = uploader.upload(key, fn) if success: backoff = 0.1 elif allow_sleep: cloudlog.info("upload backoff %r", backoff) time.sleep(backoff + random.uniform(0, backoff)) backoff = min(backoff * 2, 120) pm.send("uploaderState", uploader.get_msg()) cloudlog.info("upload done, success=%r", success)
def manager_thread(): global baseui_running # now loop context = zmq.Context() thermal_sock = messaging.pub_sock(context, service_list['thermal'].port) health_sock = messaging.sub_sock(context, service_list['health'].port) location_sock = messaging.sub_sock(context, service_list['gpsLocation'].port) cloudlog.info("manager start") cloudlog.info({"environ": os.environ}) for p in persistent_processes: start_managed_process(p) manage_baseui(True) # do this before panda flashing setup_eon_fan() if os.getenv("NOBOARD") is None: start_managed_process("pandad") passive = bool(os.getenv("PASSIVE")) passive_starter = LocationStarter() started_ts = None logger_dead = False count = 0 fan_speed = 0 ignition_seen = False health_sock.RCVTIMEO = 1500 while 1: # get health of board, log this in "thermal" td = messaging.recv_sock(health_sock, wait=True) location = messaging.recv_sock(location_sock) location = location.gpsLocation if location else None print td # replace thermald msg = read_thermal() # loggerd is gated based on free space statvfs = os.statvfs(ROOT) avail = (statvfs.f_bavail * 1.0)/statvfs.f_blocks # thermal message now also includes free space msg.thermal.freeSpace = avail with open("/sys/class/power_supply/battery/capacity") as f: msg.thermal.batteryPercent = int(f.read()) with open("/sys/class/power_supply/battery/status") as f: msg.thermal.batteryStatus = f.read().strip() # TODO: add car battery voltage check max_temp = max(msg.thermal.cpu0, msg.thermal.cpu1, msg.thermal.cpu2, msg.thermal.cpu3) / 10.0 fan_speed = handle_fan(max_temp, fan_speed) msg.thermal.fanSpeed = fan_speed thermal_sock.send(msg.to_bytes()) print msg # uploader is gated based on the phone temperature if max_temp > 85.0: cloudlog.warning("over temp: %r", max_temp) kill_managed_process("uploader") elif max_temp < 70.0: start_managed_process("uploader") if avail < 0.05: logger_dead = True # start constellation of processes when the car starts ignition = td is not None and td.health.started ignition_seen = ignition_seen or ignition params = Params() should_start = ignition and (params.get("HasAcceptedTerms") == "1") # start on gps in passive mode if passive and not ignition_seen: should_start = should_start or passive_starter.update(started_ts, location) # with 2% left, we killall, otherwise the phone is bricked should_start = should_start and avail > 0.02 if should_start: if not started_ts: params.car_start() started_ts = sec_since_boot() for p in car_started_processes: if p == "loggerd" and logger_dead: kill_managed_process(p) else: start_managed_process(p) manage_baseui(False) else: manage_baseui(True) started_ts = None logger_dead = False for p in car_started_processes: kill_managed_process(p) # shutdown if the battery gets lower than 10%, we aren't running, and we are discharging if msg.thermal.batteryPercent < 5 and msg.thermal.batteryStatus == "Discharging": os.system('LD_LIBRARY_PATH="" svc power shutdown') # check the status of baseui baseui_running = 'com.baseui' in subprocess.check_output(["ps"]) # check the status of all processes, did any of them die? for p in running: cloudlog.debug(" running %s %s" % (p, running[p])) # report to server once per minute if (count%60) == 0: cloudlog.event("STATUS_PACKET", running=running.keys(), count=count, health=(td.to_dict() if td else None), thermal=msg.to_dict()) count += 1
def manager_thread(): # now loop thermal_sock = messaging.sub_sock('thermal') cloudlog.info("manager start") cloudlog.info({"environ": os.environ}) params = Params() EnableLogger = int(params.get('OpkrEnableLogger')) #EnableLogger = (params.get("RecordFront") != b"0") if not EnableLogger: car_started_processes.remove('loggerd') persistent_processes.remove('logmessaged') persistent_processes.remove('uploader') persistent_processes.remove('logcatd') persistent_processes.remove('updated') persistent_processes.remove('deleter') persistent_processes.remove('tombstoned') else: # save boot log subprocess.call(["./loggerd", "--bootlog"], cwd=os.path.join(BASEDIR, "selfdrive/loggerd")) # start daemon processes for p in daemon_processes: start_daemon_process(p) # start persistent processes for p in persistent_processes: start_managed_process(p) # start offroad if ANDROID: pm_apply_packages('enable') start_offroad() if os.getenv("NOBOARD") is None: start_managed_process("pandad") if os.getenv("BLOCK") is not None: for k in os.getenv("BLOCK").split(","): del managed_processes[k] logger_dead = False while 1: msg = messaging.recv_sock(thermal_sock, wait=True) # heavyweight batch processes are gated on favorable thermal conditions if msg.thermal.thermalStatus >= ThermalStatus.yellow: for p in green_temp_processes: if p in persistent_processes: kill_managed_process(p) else: for p in green_temp_processes: if p in persistent_processes: start_managed_process(p) if msg.thermal.freeSpace < 0.05: logger_dead = True if msg.thermal.started and "driverview" not in running: for p in car_started_processes: if p == "loggerd" and logger_dead: kill_managed_process(p) else: start_managed_process(p) else: logger_dead = False for p in reversed(car_started_processes): kill_managed_process(p) # this is ugly if "driverview" not in running and params.get( "IsDriverViewEnabled") == b"1": start_managed_process("driverview") elif "driverview" in running and params.get( "IsDriverViewEnabled") == b"0": kill_managed_process("driverview") # check the status of all processes, did any of them die? running_list = [ "%s%s\u001b[0m" % ("\u001b[32m" if running[p].is_alive() else "\u001b[31m", p) for p in running ] cloudlog.debug(' '.join(running_list)) # Exit main loop when uninstall is needed if params.get("DoUninstall", encoding='utf8') == "1": break
def manager_thread(): # now loop context = zmq.Context() thermal_sock = messaging.pub_sock(context, service_list['thermal'].port) health_sock = messaging.sub_sock(context, service_list['health'].port) location_sock = messaging.sub_sock(context, service_list['gpsLocation'].port) cloudlog.info("manager start") cloudlog.info({"environ": os.environ}) for p in persistent_processes: start_managed_process(p) # start frame system("am start -n ai.comma.plus.frame/.MainActivity") # do this before panda flashing setup_eon_fan() if os.getenv("NOBOARD") is None: start_managed_process("pandad") params = Params() passive = params.get("Passive") == "1" passive_starter = LocationStarter() started_ts = None logger_dead = False count = 0 fan_speed = 0 ignition_seen = False battery_was_high = False health_sock.RCVTIMEO = 1500 while 1: # get health of board, log this in "thermal" td = messaging.recv_sock(health_sock, wait=True) location = messaging.recv_sock(location_sock) location = location.gpsLocation if location else None print td # replace thermald msg = read_thermal() # loggerd is gated based on free space statvfs = os.statvfs(ROOT) avail = (statvfs.f_bavail * 1.0) / statvfs.f_blocks # thermal message now also includes free space msg.thermal.freeSpace = avail with open("/sys/class/power_supply/battery/capacity") as f: msg.thermal.batteryPercent = int(f.read()) with open("/sys/class/power_supply/battery/status") as f: msg.thermal.batteryStatus = f.read().strip() with open("/sys/class/power_supply/usb/online") as f: msg.thermal.usbOnline = bool(int(f.read())) # TODO: add car battery voltage check max_temp = max(msg.thermal.cpu0, msg.thermal.cpu1, msg.thermal.cpu2, msg.thermal.cpu3) / 10.0 bat_temp = msg.thermal.bat / 1000. fan_speed = handle_fan(max_temp, bat_temp, fan_speed) msg.thermal.fanSpeed = fan_speed msg.thermal.started = started_ts is not None msg.thermal.startedTs = int(1e9 * (started_ts or 0)) thermal_sock.send(msg.to_bytes()) print msg # uploader is gated based on the phone temperature if max_temp > 85.0: cloudlog.warning("over temp: %r", max_temp) kill_managed_process("uploader") elif max_temp < 70.0: start_managed_process("uploader") if avail < 0.05: logger_dead = True # start constellation of processes when the car starts ignition = td is not None and td.health.started ignition_seen = ignition_seen or ignition do_uninstall = params.get("DoUninstall") == "1" accepted_terms = params.get("HasAcceptedTerms") == "1" should_start = ignition # start on gps in passive mode if passive and not ignition_seen: should_start = should_start or passive_starter.update( started_ts, location) # with 2% left, we killall, otherwise the phone is bricked should_start = should_start and avail > 0.02 # require usb power should_start = should_start and msg.thermal.usbOnline should_start = should_start and accepted_terms and (not do_uninstall) # if any CPU gets above 107 or the battery gets above 53, kill all processes # controls will warn with CPU above 95 or battery above 50 if max_temp > 107.0 or msg.thermal.bat >= 53000: should_start = False if should_start: if not started_ts: params.car_start() started_ts = sec_since_boot() for p in car_started_processes: if p == "loggerd" and logger_dead: kill_managed_process(p) else: start_managed_process(p) else: started_ts = None logger_dead = False for p in car_started_processes: kill_managed_process(p) # shutdown if the battery gets lower than 5%, we aren't running, and we are discharging if msg.thermal.batteryPercent < 5 and msg.thermal.batteryStatus == "Discharging" and battery_was_high: os.system('LD_LIBRARY_PATH="" svc power shutdown') if msg.thermal.batteryPercent > 10: battery_was_high = True # check the status of all processes, did any of them die? for p in running: cloudlog.debug(" running %s %s" % (p, running[p])) # report to server once per minute if (count % 60) == 0: cloudlog.event("STATUS_PACKET", running=running.keys(), count=count, health=(td.to_dict() if td else None), thermal=msg.to_dict()) if do_uninstall: break count += 1
def manager_thread(): # now loop thermal_sock = messaging.sub_sock('thermal') cloudlog.info("manager start") cloudlog.info({"environ": os.environ}) # save boot log subprocess.call(["./loggerd", "--bootlog"], cwd=os.path.join(BASEDIR, "selfdrive/loggerd")) params = Params() # start daemon processes for p in daemon_processes: start_daemon_process(p) # start persistent processes for p in persistent_processes: start_managed_process(p) # start offroad if ANDROID: pm_apply_packages('enable') start_offroad() if os.getenv("NOBOARD") is None: start_managed_process("pandad") if os.getenv("BLOCK") is not None: for k in os.getenv("BLOCK").split(","): del managed_processes[k] started_prev = False logger_dead = False while 1: msg = messaging.recv_sock(thermal_sock, wait=True) if msg.thermal.freeSpace < 0.05: logger_dead = True if msg.thermal.started: for p in car_started_processes: if p == "loggerd" and logger_dead: kill_managed_process(p) else: start_managed_process(p) else: logger_dead = False driver_view = params.get("IsDriverViewEnabled") == b"1" # TODO: refactor how manager manages processes for p in reversed(car_started_processes): if p not in driver_view_processes or not driver_view: kill_managed_process(p) for p in driver_view_processes: if driver_view: start_managed_process(p) else: kill_managed_process(p) # trigger an update after going offroad if started_prev: send_managed_process_signal("updated", signal.SIGHUP) started_prev = msg.thermal.started # check the status of all processes, did any of them die? running_list = [ "%s%s\u001b[0m" % ("\u001b[32m" if running[p].is_alive() else "\u001b[31m", p) for p in running ] cloudlog.debug(' '.join(running_list)) # Exit main loop when uninstall is needed if params.get("DoUninstall", encoding='utf8') == "1": break