mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-06 20:43:46 +08:00
71 lines
2.4 KiB
Python
71 lines
2.4 KiB
Python
"""Generic lifetime holder for a car-owned prepublication startup transaction."""
|
|
import threading
|
|
|
|
|
|
class VehicleStartupOwner:
|
|
def __init__(self, owner=None):
|
|
# Explicit-CI callers may supply an already prepared car-owned decision.
|
|
self.owner = owner
|
|
self.send_lock = threading.Lock()
|
|
|
|
def prepare(self, cp, interface, callbacks, *, requested, admission, defer_until_controls=False):
|
|
factory = getattr(interface, 'startup_owner', None)
|
|
if factory is None:
|
|
return cp
|
|
recv, send = callbacks
|
|
def locked_send(frames):
|
|
with self.send_lock:
|
|
send(frames)
|
|
owner = factory(cp, (recv, locked_send), requested=requested)
|
|
if owner is None:
|
|
return cp
|
|
# Register before any ECU request so a partially constructed Card can close.
|
|
self.owner = owner
|
|
prepare = getattr(owner, 'prepare_when_controls_ready', owner.prepare) if defer_until_controls else owner.prepare
|
|
return prepare(admission=admission)
|
|
|
|
def configure(self, ci):
|
|
required = getattr(type(ci), 'startup_required', None)
|
|
if required is not None and required(ci.CP):
|
|
matches = getattr(self.owner, 'prepared_for', None)
|
|
if matches is None or not matches(ci.CP):
|
|
raise RuntimeError('Car interface requires a matching prepared startup owner')
|
|
if self.owner is not None:
|
|
self.owner.configure(ci)
|
|
|
|
def finalize_aol_configuration(self, ci):
|
|
finalize = getattr(self.owner, 'finalize_aol_configuration', None)
|
|
if finalize is not None:
|
|
finalize(ci)
|
|
|
|
def seal_publication(self):
|
|
if self.owner is not None:
|
|
self.owner.seal_publication()
|
|
|
|
def check(self):
|
|
if self.owner is not None:
|
|
self.owner.check()
|
|
|
|
def after_state(self, **context):
|
|
if self.owner is not None:
|
|
self.owner.after_state(**context)
|
|
|
|
def consume_cruise_resume(self):
|
|
return self.owner.consume_cruise_resume() if self.owner is not None else None
|
|
|
|
def before_control(self, *, configured, ci, now_ns, control_current):
|
|
return self.owner is None or self.owner.before_control(
|
|
configured=configured, sources_current=self.owner.sources_current(ci, now_ns), control_current=control_current)
|
|
|
|
def maintain(self, *, configured):
|
|
if self.owner is not None:
|
|
self.owner.maintain(configured=configured)
|
|
|
|
def sent(self, frames, *, valid):
|
|
if self.owner is not None:
|
|
self.owner.sent(frames, valid=valid)
|
|
|
|
def close(self):
|
|
if self.owner is not None:
|
|
self.owner.close()
|