mirror of
https://github.com/dragonpilot/dragonpilot.git
synced 2026-02-27 09:33:56 +08:00
dragonpilot 2022-10-07T10:01:36 for EON/C2
version: dragonpilot v0.8.17 beta for EON/C2 date: 2022-10-07T10:01:36 dp-dev(priv2) master commit: 3aecc0939a714f5f572b3cbe85669ed389161870
This commit is contained in:
committed by
Comma Device
parent
fe6459224b
commit
4c3c884245
@@ -117,6 +117,16 @@ def ensure_can_packet_version(fn):
|
||||
return fn(self, *args, **kwargs)
|
||||
return wrapper
|
||||
|
||||
def ensure_can_health_packet_version(fn):
|
||||
@wraps(fn)
|
||||
def wrapper(self, *args, **kwargs):
|
||||
if self.can_health_version < self.CAN_HEALTH_PACKET_VERSION:
|
||||
raise RuntimeError("Panda firmware has outdated CAN health packet definition. Reflash panda firmware.")
|
||||
elif self.can_health_version > self.CAN_HEALTH_PACKET_VERSION:
|
||||
raise RuntimeError("Panda python library has outdated CAN health packet definition. Update panda python library.")
|
||||
return fn(self, *args, **kwargs)
|
||||
return wrapper
|
||||
|
||||
class ALTERNATIVE_EXPERIENCE:
|
||||
DEFAULT = 0
|
||||
DISABLE_DISENGAGE_ON_GAS = 1
|
||||
@@ -172,17 +182,20 @@ class Panda:
|
||||
HW_TYPE_UNO = b'\x05'
|
||||
HW_TYPE_DOS = b'\x06'
|
||||
HW_TYPE_RED_PANDA = b'\x07'
|
||||
HW_TYPE_RED_PANDA_V2 = b'\x08'
|
||||
|
||||
CAN_PACKET_VERSION = 2
|
||||
HEALTH_PACKET_VERSION = 8
|
||||
HEALTH_STRUCT = struct.Struct("<IIIIIIIIBBBBBBBHBBBHIfB")
|
||||
HEALTH_PACKET_VERSION = 11
|
||||
CAN_HEALTH_PACKET_VERSION = 2
|
||||
HEALTH_STRUCT = struct.Struct("<IIIIIIIIIBBBBBBHBBBHfBBB")
|
||||
CAN_HEALTH_STRUCT = struct.Struct("<BIBBBBBBBBIIIIIIHHBB")
|
||||
|
||||
F2_DEVICES = (HW_TYPE_PEDAL, )
|
||||
F4_DEVICES = (HW_TYPE_WHITE_PANDA, HW_TYPE_GREY_PANDA, HW_TYPE_BLACK_PANDA, HW_TYPE_UNO, HW_TYPE_DOS)
|
||||
H7_DEVICES = (HW_TYPE_RED_PANDA, )
|
||||
H7_DEVICES = (HW_TYPE_RED_PANDA, HW_TYPE_RED_PANDA_V2)
|
||||
|
||||
INTERNAL_DEVICES = (HW_TYPE_UNO, HW_TYPE_DOS)
|
||||
HAS_OBD = (HW_TYPE_BLACK_PANDA, HW_TYPE_UNO, HW_TYPE_DOS, HW_TYPE_RED_PANDA)
|
||||
HAS_OBD = (HW_TYPE_BLACK_PANDA, HW_TYPE_UNO, HW_TYPE_DOS, HW_TYPE_RED_PANDA, HW_TYPE_RED_PANDA_V2)
|
||||
|
||||
CLOCK_SOURCE_MODE_DISABLED = 0
|
||||
CLOCK_SOURCE_MODE_FREE_RUNNING = 1
|
||||
@@ -272,7 +285,7 @@ class Panda:
|
||||
|
||||
assert self._handle is not None
|
||||
self._mcu_type = self.get_mcu_type()
|
||||
self.health_version, self.can_version = self.get_packets_versions()
|
||||
self.health_version, self.can_version, self.can_health_version = self.get_packets_versions()
|
||||
print("connected")
|
||||
|
||||
# disable openpilot's heartbeat checks
|
||||
@@ -438,26 +451,64 @@ class Panda:
|
||||
"uptime": a[0],
|
||||
"voltage": a[1],
|
||||
"current": a[2],
|
||||
"can_rx_errs": a[3],
|
||||
"can_send_errs": a[4],
|
||||
"can_fwd_errs": a[5],
|
||||
"gmlan_send_errs": a[6],
|
||||
"faults": a[7],
|
||||
"ignition_line": a[8],
|
||||
"ignition_can": a[9],
|
||||
"controls_allowed": a[10],
|
||||
"gas_interceptor_detected": a[11],
|
||||
"car_harness_status": a[12],
|
||||
"usb_power_mode": a[13],
|
||||
"safety_tx_blocked": a[3],
|
||||
"safety_rx_invalid": a[4],
|
||||
"tx_buffer_overflow": a[5],
|
||||
"rx_buffer_overflow": a[6],
|
||||
"gmlan_send_errs": a[7],
|
||||
"faults": a[8],
|
||||
"ignition_line": a[9],
|
||||
"ignition_can": a[10],
|
||||
"controls_allowed": a[11],
|
||||
"gas_interceptor_detected": a[12],
|
||||
"car_harness_status": a[13],
|
||||
"safety_mode": a[14],
|
||||
"safety_param": a[15],
|
||||
"fault_status": a[16],
|
||||
"power_save_enabled": a[17],
|
||||
"heartbeat_lost": a[18],
|
||||
"alternative_experience": a[19],
|
||||
"blocked_msg_cnt": a[20],
|
||||
"interrupt_load": a[21],
|
||||
"fan_power": a[22],
|
||||
"interrupt_load": a[20],
|
||||
"fan_power": a[21],
|
||||
"safety_rx_checks_invalid": a[22],
|
||||
"usb_power_mode": a[23],
|
||||
}
|
||||
|
||||
@ensure_can_health_packet_version
|
||||
def can_health(self, can_number):
|
||||
LEC_ERROR_CODE = {
|
||||
0: "No error",
|
||||
1: "Stuff error",
|
||||
2: "Form error",
|
||||
3: "AckError",
|
||||
4: "Bit1Error",
|
||||
5: "Bit0Error",
|
||||
6: "CRCError",
|
||||
7: "NoChange",
|
||||
}
|
||||
dat = self._handle.controlRead(Panda.REQUEST_IN, 0xc2, int(can_number), 0, self.CAN_HEALTH_STRUCT.size)
|
||||
a = self.CAN_HEALTH_STRUCT.unpack(dat)
|
||||
return {
|
||||
"bus_off": a[0],
|
||||
"bus_off_cnt": a[1],
|
||||
"error_warning": a[2],
|
||||
"error_passive": a[3],
|
||||
"last_error": LEC_ERROR_CODE[a[4]],
|
||||
"last_stored_error": LEC_ERROR_CODE[a[5]],
|
||||
"last_data_error": LEC_ERROR_CODE[a[6]],
|
||||
"last_data_stored_error": LEC_ERROR_CODE[a[7]],
|
||||
"receive_error_cnt": a[8],
|
||||
"transmit_error_cnt": a[9],
|
||||
"total_error_cnt": a[10],
|
||||
"total_tx_lost_cnt": a[11],
|
||||
"total_rx_lost_cnt": a[12],
|
||||
"total_tx_cnt": a[13],
|
||||
"total_rx_cnt": a[14],
|
||||
"total_fwd_cnt": a[15],
|
||||
"can_speed": a[16],
|
||||
"can_data_speed": a[17],
|
||||
"canfd_enabled": a[18],
|
||||
"brs_enabled": a[19],
|
||||
}
|
||||
|
||||
# ******************* control *******************
|
||||
@@ -494,12 +545,12 @@ class Panda:
|
||||
|
||||
# Returns tuple with health packet version and CAN packet/USB packet version
|
||||
def get_packets_versions(self):
|
||||
dat = self._handle.controlRead(Panda.REQUEST_IN, 0xdd, 0, 0, 2)
|
||||
if dat:
|
||||
a = struct.unpack("BB", dat)
|
||||
return (a[0], a[1])
|
||||
dat = self._handle.controlRead(Panda.REQUEST_IN, 0xdd, 0, 0, 3)
|
||||
if dat and len(dat) == 3:
|
||||
a = struct.unpack("BBB", dat)
|
||||
return (a[0], a[1], a[2])
|
||||
else:
|
||||
return (0, 0)
|
||||
return (0, 0, 0)
|
||||
|
||||
def get_mcu_type(self):
|
||||
hw_type = self.get_type()
|
||||
|
||||
@@ -382,7 +382,7 @@ class IsoTpMessage():
|
||||
self.debug = debug
|
||||
self.max_len = max_len
|
||||
|
||||
def send(self, dat: bytes) -> None:
|
||||
def send(self, dat: bytes, setup_only: bool = False) -> None:
|
||||
# throw away any stale data
|
||||
self._can_client.recv(drain=True)
|
||||
|
||||
@@ -396,39 +396,42 @@ class IsoTpMessage():
|
||||
self.rx_idx = 0
|
||||
self.rx_done = False
|
||||
|
||||
if self.debug:
|
||||
if self.debug and not setup_only:
|
||||
print(f"ISO-TP: REQUEST - {hex(self._can_client.tx_addr)} 0x{bytes.hex(self.tx_dat)}")
|
||||
self._tx_first_frame()
|
||||
self._tx_first_frame(setup_only=setup_only)
|
||||
|
||||
def _tx_first_frame(self) -> None:
|
||||
def _tx_first_frame(self, setup_only: bool = False) -> None:
|
||||
if self.tx_len < self.max_len:
|
||||
# single frame (send all bytes)
|
||||
if self.debug:
|
||||
if self.debug and not setup_only:
|
||||
print(f"ISO-TP: TX - single frame - {hex(self._can_client.tx_addr)}")
|
||||
msg = (bytes([self.tx_len]) + self.tx_dat).ljust(self.max_len, b"\x00")
|
||||
self.tx_done = True
|
||||
else:
|
||||
# first frame (send first 6 bytes)
|
||||
if self.debug:
|
||||
if self.debug and not setup_only:
|
||||
print(f"ISO-TP: TX - first frame - {hex(self._can_client.tx_addr)}")
|
||||
msg = (struct.pack("!H", 0x1000 | self.tx_len) + self.tx_dat[:self.max_len - 2]).ljust(self.max_len - 2, b"\x00")
|
||||
self._can_client.send([msg])
|
||||
if not setup_only:
|
||||
self._can_client.send([msg])
|
||||
|
||||
def recv(self, timeout=None) -> Optional[bytes]:
|
||||
def recv(self, timeout=None) -> Tuple[Optional[bytes], bool]:
|
||||
if timeout is None:
|
||||
timeout = self.timeout
|
||||
|
||||
start_time = time.monotonic()
|
||||
updated = False
|
||||
try:
|
||||
while True:
|
||||
for msg in self._can_client.recv():
|
||||
self._isotp_rx_next(msg)
|
||||
start_time = time.monotonic()
|
||||
updated = True
|
||||
if self.tx_done and self.rx_done:
|
||||
return self.rx_dat
|
||||
return self.rx_dat, updated
|
||||
# no timeout indicates non-blocking
|
||||
if timeout == 0:
|
||||
return None
|
||||
return None, updated
|
||||
if time.monotonic() - start_time > timeout:
|
||||
raise MessageTimeoutError("timeout waiting for response")
|
||||
finally:
|
||||
@@ -456,8 +459,8 @@ class IsoTpMessage():
|
||||
print(f"ISO-TP: RX - first frame - {hex(self._can_client.rx_addr)} idx={self.rx_idx} done={self.rx_done}")
|
||||
if self.debug:
|
||||
print(f"ISO-TP: TX - flow control continue - {hex(self._can_client.tx_addr)}")
|
||||
# send flow control message (send all bytes)
|
||||
msg = b"\x30\x00\x00".ljust(self.max_len, b"\x00")
|
||||
# send flow control message (send all bytes) with a separation time of 10 ms
|
||||
msg = b"\x30\x00\x0a".ljust(self.max_len, b"\x00")
|
||||
self._can_client.send([msg])
|
||||
return
|
||||
|
||||
@@ -553,7 +556,7 @@ class UdsClient():
|
||||
response_pending = False
|
||||
while True:
|
||||
timeout = self.response_pending_timeout if response_pending else self.timeout
|
||||
resp = isotp_msg.recv(timeout)
|
||||
resp, _ = isotp_msg.recv(timeout)
|
||||
|
||||
if resp is None:
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user