Release 260111
This commit is contained in:
8
opendbc_repo/opendbc/can/tests/__init__.py
Normal file
8
opendbc_repo/opendbc/can/tests/__init__.py
Normal file
@@ -0,0 +1,8 @@
|
||||
import glob
|
||||
import os
|
||||
|
||||
from opendbc import DBC_PATH
|
||||
|
||||
ALL_DBCS = [os.path.basename(dbc).split('.')[0] for dbc in
|
||||
glob.glob(f"{DBC_PATH}/*.dbc")]
|
||||
TEST_DBC = os.path.abspath(os.path.join(os.path.dirname(__file__), "test.dbc"))
|
||||
45
opendbc_repo/opendbc/can/tests/benchmark.py
Normal file
45
opendbc_repo/opendbc/can/tests/benchmark.py
Normal file
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env python3
|
||||
import time
|
||||
from opendbc.can import CANPacker, CANParser
|
||||
|
||||
|
||||
def _benchmark(checks, n):
|
||||
parser = CANParser('toyota_new_mc_pt_generated', checks, 0)
|
||||
packer = CANPacker('toyota_new_mc_pt_generated')
|
||||
|
||||
t1 = time.process_time_ns()
|
||||
can_msgs = []
|
||||
for i in range(10000):
|
||||
values = {"ACC_CONTROL": {"ACC_TYPE": 1, "ALLOW_LONG_PRESS": 3}}
|
||||
msgs = [packer.make_can_msg(k, 0, v) for k, v in values.items()]
|
||||
can_msgs.append([int(0.01 * i * 1e9), msgs])
|
||||
t2 = time.process_time_ns()
|
||||
pack_dt = t2 - t1
|
||||
|
||||
ets = []
|
||||
for _ in range(25):
|
||||
if n > 1:
|
||||
strings = []
|
||||
for i in range(0, len(can_msgs), n):
|
||||
strings.append(can_msgs[i:i + n])
|
||||
t1 = time.process_time_ns()
|
||||
for m in strings:
|
||||
parser.update(m)
|
||||
t2 = time.process_time_ns()
|
||||
else:
|
||||
t1 = time.process_time_ns()
|
||||
for m in can_msgs:
|
||||
parser.update([m])
|
||||
t2 = time.process_time_ns()
|
||||
|
||||
ets.append(t2 - t1)
|
||||
|
||||
et = sum(ets) / len(ets)
|
||||
avg_nanos = et / len(can_msgs)
|
||||
print('[%d] %.1fms to pack, %.1fms to parse %s messages, avg: %dns' % (n, pack_dt/1e6, et/1e6, len(can_msgs), avg_nanos))
|
||||
|
||||
if __name__ == "__main__":
|
||||
# python -m cProfile -s cumulative benchmark.py
|
||||
_benchmark([('ACC_CONTROL', 10)], 1)
|
||||
_benchmark([('ACC_CONTROL', 10)], 5)
|
||||
_benchmark([('ACC_CONTROL', 10)], 10)
|
||||
27
opendbc_repo/opendbc/can/tests/test.dbc
Normal file
27
opendbc_repo/opendbc/can/tests/test.dbc
Normal file
@@ -0,0 +1,27 @@
|
||||
CM_ "This DBC is used for the CAN parser and packer tests.";
|
||||
|
||||
BO_ 228 STEERING_CONTROL: 5 EON
|
||||
SG_ STEER_TORQUE_REQUEST : 23|1@0+ (1,0) [0|1] "" EPS
|
||||
SG_ SET_ME_X00 : 22|7@0+ (1,0) [0|127] "" EPS
|
||||
SG_ SET_ME_X00_2 : 31|8@0+ (1,0) [0|0] "" EPS
|
||||
SG_ STEER_TORQUE : 7|16@0- (1,0) [-4096|4096] "" EPS
|
||||
SG_ STEER_DOWN_TO_ZERO : 38|1@0+ (1,0) [0|1] "" EPS
|
||||
SG_ COUNTER : 37|2@0+ (1,0) [0|3] "" EPS
|
||||
SG_ CHECKSUM : 35|4@0+ (1,0) [0|15] "" EPS
|
||||
|
||||
BO_ 316 Brake_Status: 8 XXX
|
||||
SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX
|
||||
SG_ Signal1 : 12|46@1+ (1,0) [0|1] "" XXX
|
||||
SG_ ES_Brake : 58|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ Signal2 : 59|3@1+ (1,0) [0|1] "" XXX
|
||||
SG_ Brake : 62|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ Signal3 : 63|1@1+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 245 CAN_FD_MESSAGE: 32 XXX
|
||||
SG_ COUNTER : 7|8@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SIGNED : 22|16@0- (1,0) [0|1] "" XXX
|
||||
SG_ 64_BIT_LE : 159|64@1+ (1,0) [0|1] "" XXX
|
||||
SG_ 64_BIT_BE : 80|64@0+ (1,0) [0|1] "" XXX
|
||||
|
||||
VAL_ 80 NON_EXISTENT_ADDR 0 "test";
|
||||
555
opendbc_repo/opendbc/can/tests/test_checksums.py
Normal file
555
opendbc_repo/opendbc/can/tests/test_checksums.py
Normal file
@@ -0,0 +1,555 @@
|
||||
import copy
|
||||
from opendbc.can import CANPacker, CANParser
|
||||
|
||||
|
||||
class TestCanChecksums:
|
||||
|
||||
def verify_checksum(self, subtests, dbc_file: str, msg_name: str, msg_addr: int, test_messages: list[bytes],
|
||||
checksum_field: str = 'CHECKSUM', counter_field = 'COUNTER'):
|
||||
"""
|
||||
Verify that opendbc calculates payload CRCs/checksums matching those received in known-good sample messages
|
||||
Depends on all non-zero bits in the sample message having a corresponding DBC signal, add UNKNOWN signals if needed
|
||||
"""
|
||||
parser = CANParser(dbc_file, [(msg_name, 0)], 0)
|
||||
packer = CANPacker(dbc_file)
|
||||
|
||||
for data in test_messages:
|
||||
expected_msg = (msg_addr, data, 0)
|
||||
parser.update([0, [expected_msg]])
|
||||
expected = copy.deepcopy(parser.vl[msg_name])
|
||||
|
||||
modified = copy.deepcopy(expected)
|
||||
modified.pop(checksum_field, None)
|
||||
modified_msg = packer.make_can_msg(msg_name, 0, modified)
|
||||
|
||||
parser.update([0, [modified_msg]])
|
||||
tested = parser.vl[msg_name]
|
||||
with subtests.test(counter=expected[counter_field]):
|
||||
assert tested[checksum_field] == expected[checksum_field]
|
||||
|
||||
def verify_fca_giorgio_crc(self, subtests, msg_name: str, msg_addr: int, test_messages: list[bytes]):
|
||||
"""Test modified SAE J1850 CRCs, with special final XOR cases for EPS messages"""
|
||||
assert len(test_messages) == 3
|
||||
self.verify_checksum(subtests, "fca_giorgio", msg_name, msg_addr, test_messages)
|
||||
|
||||
def test_fca_giorgio_eps_1(self, subtests):
|
||||
self.verify_fca_giorgio_crc(subtests, "EPS_1", 0xDE, [
|
||||
b'\x17\x51\x97\xcc\x00\xdf',
|
||||
b'\x17\x51\x97\xc9\x01\xa3',
|
||||
b'\x17\x51\x97\xcc\x02\xe5',
|
||||
])
|
||||
|
||||
def test_fca_giorgio_eps_2(self, subtests):
|
||||
self.verify_fca_giorgio_crc(subtests, "EPS_2", 0x106, [
|
||||
b'\x7c\x43\x57\x60\x00\x00\xa1',
|
||||
b'\x7c\x63\x58\xe0\x00\x01\xd5',
|
||||
b'\x7c\x63\x58\xe0\x00\x02\xf2',
|
||||
])
|
||||
|
||||
def test_fca_giorgio_eps_3(self, subtests):
|
||||
self.verify_fca_giorgio_crc(subtests, "EPS_3", 0x122, [
|
||||
b'\x7b\x30\x00\xf8',
|
||||
b'\x7b\x10\x01\x90',
|
||||
b'\x7b\xf0\x02\x6e',
|
||||
])
|
||||
|
||||
def test_fca_giorgio_abs_2(self, subtests):
|
||||
self.verify_fca_giorgio_crc(subtests, "ABS_2", 0xFE, [
|
||||
b'\x7e\x38\x00\x7d\x10\x31\x80\x32',
|
||||
b'\x7e\x38\x00\x7d\x10\x31\x81\x2f',
|
||||
b'\x7e\x38\x00\x7d\x20\x31\x82\x20',
|
||||
])
|
||||
|
||||
def test_honda_checksum(self):
|
||||
"""Test checksums for Honda standard and extended CAN ids"""
|
||||
# TODO: refactor to use self.verify_checksum()
|
||||
dbc_file = "honda_accord_2018_can_generated"
|
||||
msgs = [("LKAS_HUD", 0), ("LKAS_HUD_A", 0)]
|
||||
parser = CANParser(dbc_file, msgs, 0)
|
||||
packer = CANPacker(dbc_file)
|
||||
|
||||
values = {
|
||||
'SET_ME_X41': 0x41,
|
||||
'STEERING_REQUIRED': 1,
|
||||
'SOLID_LANES': 1,
|
||||
'BEEP': 0,
|
||||
}
|
||||
|
||||
# known correct checksums according to the above values
|
||||
checksum_std = [11, 10, 9, 8]
|
||||
checksum_ext = [4, 3, 2, 1]
|
||||
|
||||
for std, ext in zip(checksum_std, checksum_ext, strict=True):
|
||||
msgs = [
|
||||
packer.make_can_msg("LKAS_HUD", 0, values),
|
||||
packer.make_can_msg("LKAS_HUD_A", 0, values),
|
||||
]
|
||||
parser.update([0, msgs])
|
||||
|
||||
assert parser.vl['LKAS_HUD']['CHECKSUM'] == std
|
||||
assert parser.vl['LKAS_HUD_A']['CHECKSUM'] == ext
|
||||
|
||||
def verify_volkswagen_mqb_crc(self, subtests, msg_name: str, msg_addr: int, test_messages: list[bytes], counter_field: str = 'COUNTER'):
|
||||
"""Test AUTOSAR E2E Profile 2 CRCs"""
|
||||
assert len(test_messages) == 16 # All counter values must be tested
|
||||
self.verify_checksum(subtests, "vw_mqb", msg_name, msg_addr, test_messages, counter_field=counter_field)
|
||||
|
||||
def test_volkswagen_mqb_crc_lwi_01(self, subtests):
|
||||
self.verify_volkswagen_mqb_crc(subtests, "LWI_01", 0x86, [
|
||||
b'\x6b\x00\xbd\x00\x00\x00\x00\x00',
|
||||
b'\xee\x01\x0a\x00\x00\x00\x00\x00',
|
||||
b'\xd8\x02\xa9\x00\x00\x00\x00\x00',
|
||||
b'\x03\x03\xbe\xa2\x12\x00\x00\x00',
|
||||
b'\x7b\x04\x31\x20\x03\x00\x00\x00',
|
||||
b'\x8b\x05\xe2\x85\x09\x00\x00\x00',
|
||||
b'\x63\x06\x13\x21\x00\x00\x00\x00',
|
||||
b'\x66\x07\x05\x00\x00\x00\x00\x00',
|
||||
b'\x49\x08\x0d\x00\x00\x00\x00\x00',
|
||||
b'\x5f\x09\x7e\x60\x01\x00\x00\x00',
|
||||
b'\xaf\x0a\x72\x20\x00\x00\x00\x00',
|
||||
b'\x59\x0b\x1b\x00\x00\x00\x00\x00',
|
||||
b'\xa8\x0c\x06\x00\x00\x00\x00\x00',
|
||||
b'\xbc\x0d\x72\x20\x00\x00\x00\x00',
|
||||
b'\xf9\x0e\x0f\x00\x00\x00\x00\x00',
|
||||
b'\x60\x0f\x62\xc0\x00\x00\x00\x00',
|
||||
])
|
||||
|
||||
def test_volkswagen_mqb_crc_airbag_01(self, subtests):
|
||||
self.verify_volkswagen_mqb_crc(subtests, "Airbag_01", 0x40, [
|
||||
b'\xaf\x00\x00\x80\xc0\x00\x20\x3e',
|
||||
b'\x54\x01\x00\x80\xc0\x00\x20\x1a',
|
||||
b'\x54\x02\x00\x80\xc0\x00\x60\x00',
|
||||
b'\x31\x03\x00\x80\xc0\x00\x60\xf2',
|
||||
b'\xe0\x04\x00\x80\xc0\x00\x60\xcc',
|
||||
b'\xb3\x05\x00\x80\xc0\x00\x40\xde',
|
||||
b'\xa4\x06\x00\x80\xc0\x00\x40\x18',
|
||||
b'\x94\x07\x00\x80\xc0\x00\x20\x38',
|
||||
b'\x2d\x08\x00\x80\xc0\x00\x60\xae',
|
||||
b'\xc2\x09\x00\x80\xc0\x00\x00\x1c',
|
||||
b'\x1f\x0a\x00\x80\xc0\x00\x60\x2c',
|
||||
b'\x7f\x0b\x00\x80\xc0\x00\x00\x00',
|
||||
b'\x03\x0c\x00\x80\xc0\x00\x40\xd6',
|
||||
b'\x56\x0d\x00\x80\xc0\x00\x20\x50',
|
||||
b'\x4a\x0e\x00\x80\xc0\x00\x20\xf2',
|
||||
b'\xe5\x0f\x00\x80\xc0\x00\x40\xf6',
|
||||
])
|
||||
|
||||
def test_volkswagen_mqb_crc_lh_eps_03(self, subtests):
|
||||
self.verify_volkswagen_mqb_crc(subtests, "LH_EPS_03", 0x9F, [
|
||||
b'\x11\x30\x2e\x00\x05\x1c\x80\x30',
|
||||
b'\x5b\x31\x8e\x03\x05\x53\x00\x30',
|
||||
b'\xcb\x32\xd3\x06\x05\x73\x00\x30',
|
||||
b'\xf2\x33\x28\x00\x05\x26\x00\x30',
|
||||
b'\x0b\x34\x44\x00\x05\x5b\x80\x30',
|
||||
b'\xed\x35\x80\x00\x03\x34\x00\x30',
|
||||
b'\xf0\x36\x88\x00\x05\x3d\x80\x30',
|
||||
b'\x9e\x37\x44\x03\x05\x41\x00\x30',
|
||||
b'\x68\x38\x06\x01\x05\x18\x80\x30',
|
||||
b'\x87\x39\x51\x00\x05\x11\x80\x30',
|
||||
b'\x8c\x3a\x29\x00\x05\xac\x00\x30',
|
||||
b'\x08\x3b\xbd\x00\x05\x8e\x00\x30',
|
||||
b'\xd4\x3c\x19\x00\x05\x05\x80\x30',
|
||||
b'\x29\x3d\x54\x00\x05\x5b\x00\x30',
|
||||
b'\xa1\x3e\x49\x01\x03\x04\x80\x30',
|
||||
b'\xe2\x3f\x05\x00\x05\x0a\x00\x30',
|
||||
])
|
||||
|
||||
def test_volkswagen_mqb_crc_getriebe_11(self, subtests):
|
||||
self.verify_volkswagen_mqb_crc(subtests, "Getriebe_11", 0xAD, [
|
||||
b'\xf8\xe0\xbf\xff\x5f\x20\x20\x20',
|
||||
b'\xb0\xe1\xbf\xff\xc6\x98\x21\x80',
|
||||
b'\xd2\xe2\xbf\xff\x5f\x20\x20\x20',
|
||||
b'\x00\xe3\xbf\xff\xaa\x20\x20\x10',
|
||||
b'\xf1\xe4\xbf\xff\x5f\x20\x20\x20',
|
||||
b'\xc4\xe5\xbf\xff\x5f\x20\x20\x20',
|
||||
b'\xda\xe6\xbf\xff\x5f\x20\x20\x20',
|
||||
b'\x85\xe7\xbf\xff\x5f\x20\x20\x20',
|
||||
b'\x12\xe8\xbf\xff\x5f\x20\x20\x20',
|
||||
b'\x45\xe9\xbf\xff\xaa\x20\x20\x10',
|
||||
b'\x03\xea\xbf\xff\xcc\x20\x20\x10',
|
||||
b'\xfc\xeb\xbf\xff\x5f\x20\x21\x20',
|
||||
b'\xfe\xec\xbf\xff\xad\x20\x20\x10',
|
||||
b'\xbd\xed\xbf\xff\xaa\x20\x20\x10',
|
||||
b'\x67\xee\xbf\xff\xaa\x20\x20\x10',
|
||||
b'\x36\xef\xbf\xff\xaa\x20\x20\x10',
|
||||
], counter_field="COUNTER_DISABLED") # see opendbc#1235
|
||||
|
||||
def test_volkswagen_mqb_crc_esp_21(self, subtests):
|
||||
self.verify_volkswagen_mqb_crc(subtests, "ESP_21", 0xFD, [
|
||||
b'\x66\xd0\x1f\x80\x45\x05\x00\x00',
|
||||
b'\x87\xd1\x1f\x80\x52\x05\x00\x00',
|
||||
b'\xcd\xd2\x1f\x80\x50\x06\x00\x00',
|
||||
b'\xfd\xd3\x1f\x80\x35\x02\x00\x00',
|
||||
b'\xfa\xd4\x1f\x80\x22\x05\x00\x00',
|
||||
b'\xfd\xd5\x1f\x80\x84\x04\x00\x00',
|
||||
b'\x2e\xd6\x1f\x80\xf0\x03\x00\x00',
|
||||
b'\x9f\xd7\x1f\x80\x00\x00\x00\x00',
|
||||
b'\x1e\xd8\x1f\x80\xb3\x03\x00\x00',
|
||||
b'\x61\xd9\x1f\x80\x6d\x05\x00\x00',
|
||||
b'\x44\xda\x1f\x80\x47\x02\x00\x00',
|
||||
b'\x86\xdb\x1f\x80\x3a\x02\x00\x00',
|
||||
b'\x39\xdc\x1f\x80\xcb\x01\x00\x00',
|
||||
b'\x19\xdd\x1f\x80\x00\x00\x00\x00',
|
||||
b'\x8c\xde\x1f\x80\xba\x04\x00\x00',
|
||||
b'\xfb\xdf\x1f\x80\x46\x00\x00\x00',
|
||||
])
|
||||
|
||||
def test_volkswagen_mqb_crc_esp_02(self, subtests):
|
||||
self.verify_volkswagen_mqb_crc(subtests, "ESP_02", 0x101, [
|
||||
b'\xf2\x00\x7e\xff\xa1\x2a\x40\x00',
|
||||
b'\xd3\x01\x7d\x00\xa2\x0c\x02\x00',
|
||||
b'\x03\x02\x7a\x06\xa2\x49\x42\x00',
|
||||
b'\xfd\x03\x70\xfb\xa1\xde\x00\x00',
|
||||
b'\x8e\x04\x7b\xf7\xa1\xd2\x01\x00',
|
||||
b'\x0f\x05\x7d\xfd\xa1\x31\x40\x00',
|
||||
b'\xb6\x06\x7d\x01\xa2\x0a\x40\x00',
|
||||
b'\xe8\x07\x7e\xfd\xa1\x12\x40\x00',
|
||||
b'\x74\x08\x7a\x01\xa2\x40\x01\x00',
|
||||
b'\xe3\x09\x81\x00\xa2\xb5\x01\x00',
|
||||
b'\xab\x0a\x74\x09\xa2\x9f\x42\x00',
|
||||
b'\xf3\x0b\x80\x12\xa2\x94\x00\x00',
|
||||
b'\x88\x0c\x7f\x07\xa2\x46\x00\x00',
|
||||
b'\x6f\x0d\x7f\xff\xa1\x53\x40\x00',
|
||||
b'\x38\x0e\x73\xd6\xa1\x6a\x40\x00',
|
||||
b'\x49\x0f\x85\x12\xa2\xf6\x01\x00',
|
||||
])
|
||||
|
||||
def test_volkswagen_mqb_crc_esp_05(self, subtests):
|
||||
self.verify_volkswagen_mqb_crc(subtests, "ESP_05", 0x106, [
|
||||
b'\x90\x80\x64\x00\x00\x00\xe7\x10',
|
||||
b'\xf4\x81\x64\x00\x00\x00\xe7\x10',
|
||||
b'\x90\x82\x63\x00\x00\x00\xe8\x10',
|
||||
b'\xa0\x83\x63\x00\x00\x00\xe6\x10',
|
||||
b'\xe7\x84\x63\x00\x00\x00\xe8\x10',
|
||||
b'\x2e\x85\x78\x04\x00\x00\xea\x30',
|
||||
b'\x7b\x86\x63\x00\x00\x00\xe6\x10',
|
||||
b'\x71\x87\x79\x04\x00\x00\xd0\x30',
|
||||
b'\x50\x88\x79\x04\x00\x00\xea\x30',
|
||||
b'\x81\x89\x64\x00\x00\x00\xe1\x10',
|
||||
b'\x6a\x8a\x68\x00\x00\x04\xd0\x10',
|
||||
b'\x17\x8b\x6a\x04\x00\x00\xe6\x10',
|
||||
b'\xc7\x8c\x63\x00\x00\x00\xd1\x10',
|
||||
b'\x53\x8d\x64\x04\x00\x00\xe2\x10',
|
||||
b'\x24\x8e\x63\x00\x00\x00\xe7\x10',
|
||||
b'\x3f\x8f\x82\x04\x00\x00\xe6\x30',
|
||||
])
|
||||
|
||||
def test_volkswagen_mqb_crc_esp_10(self, subtests):
|
||||
self.verify_volkswagen_mqb_crc(subtests, "ESP_10", 0x116, [
|
||||
b'\x2d\x00\xd5\x98\x9f\x26\x25\x0f',
|
||||
b'\x24\x01\x60\x63\x2c\x5e\x3b\x0f',
|
||||
b'\x08\x02\xb2\x2f\xee\x9a\x29\x0f',
|
||||
b'\x7c\x03\x17\x07\x1d\xe5\x8c\x0f',
|
||||
b'\xaa\x04\xd6\xe3\xeb\x98\xe8\x0f',
|
||||
b'\x4e\x05\xbb\xd9\x65\x43\xca\x0f',
|
||||
b'\x59\x06\x78\xbd\x25\xc6\xf2\xff',
|
||||
b'\xaf\x07\x42\x85\x53\xbe\xbe\x0f',
|
||||
b'\x2a\x08\xa6\xcd\x95\x8c\x12\x0f',
|
||||
b'\xce\x09\x6e\x17\x6d\x1b\x2f\x0f',
|
||||
b'\x60\x0a\xd3\xe6\x3a\x8d\xf0\x0f',
|
||||
b'\xc5\x0b\xfc\x69\x57\x50\x21\x0f',
|
||||
b'\x70\x0c\xde\xf3\x9d\xe9\x6b\xff',
|
||||
b'\x62\x0d\xc4\x1a\xdb\x61\x7a\x0f',
|
||||
b'\x76\x0e\x79\x69\xe3\x32\x67\x0f',
|
||||
b'\x15\x0f\x51\x59\x56\x35\xb1\x0f',
|
||||
])
|
||||
|
||||
def test_volkswagen_mqb_crc_acc_10(self, subtests):
|
||||
self.verify_volkswagen_mqb_crc(subtests, "ACC_10", 0x117, [
|
||||
b'\x9b\x00\x00\x40\x68\x00\x00\xff',
|
||||
b'\xff\x01\x00\x40\x68\x00\x00\xff',
|
||||
b'\x53\x02\x00\x40\x68\x00\x00\xff',
|
||||
b'\x37\x03\x00\x40\x68\x00\x00\xff',
|
||||
b'\x24\x04\x00\x40\x68\x00\x00\xff',
|
||||
b'\x40\x05\x00\x40\x68\x00\x00\xff',
|
||||
b'\xec\x06\x00\x40\x68\x00\x00\xff',
|
||||
b'\x88\x07\x00\x40\x68\x00\x00\xff',
|
||||
b'\xca\x08\x00\x40\x68\x00\x00\xff',
|
||||
b'\xae\x09\x00\x40\x68\x00\x00\xff',
|
||||
b'\x02\x0a\x00\x40\x68\x00\x00\xff',
|
||||
b'\x66\x0b\x00\x40\x68\x00\x00\xff',
|
||||
b'\x75\x0c\x00\x40\x68\x00\x00\xff',
|
||||
b'\x11\x0d\x00\x40\x68\x00\x00\xff',
|
||||
b'\xbd\x0e\x00\x40\x68\x00\x00\xff',
|
||||
b'\xd9\x0f\x00\x40\x68\x00\x00\xff',
|
||||
])
|
||||
|
||||
def test_volkswagen_mqb_crc_tsk_06(self, subtests):
|
||||
self.verify_volkswagen_mqb_crc(subtests, "TSK_06", 0x120, [
|
||||
b'\xc1\x00\x00\x02\x00\x08\xff\x21',
|
||||
b'\x34\x01\x00\x02\x00\x08\xff\x21',
|
||||
b'\xcc\x02\x00\x02\x00\x08\xff\x21',
|
||||
b'\x1e\x03\x00\x02\x00\x08\xff\x21',
|
||||
b'\x48\x04\x00\x02\x00\x08\xff\x21',
|
||||
b'\x4a\x05\x00\x02\x00\x08\xff\x21',
|
||||
b'\xa5\x06\x00\x02\x00\x08\xff\x21',
|
||||
b'\xa7\x07\x00\x02\x00\x08\xff\x21',
|
||||
b'\xfe\x08\x00\x02\x00\x08\xff\x21',
|
||||
b'\xa8\x09\x00\x02\x00\x08\xff\x21',
|
||||
b'\x73\x0a\x00\x02\x00\x08\xff\x21',
|
||||
b'\xdf\x0b\x00\x02\x00\x08\xff\x21',
|
||||
b'\x05\x0c\x00\x02\x00\x08\xff\x21',
|
||||
b'\xb5\x0d\x00\x02\x00\x08\xff\x21',
|
||||
b'\xde\x0e\x00\x02\x00\x08\xff\x21',
|
||||
b'\x0b\x0f\x00\x02\x00\x08\xff\x21',
|
||||
])
|
||||
|
||||
def test_volkswagen_mqb_crc_motor_20(self, subtests):
|
||||
self.verify_volkswagen_mqb_crc(subtests, "Motor_20", 0x121, [
|
||||
b'\xb9\x00\x00\xc0\x39\x46\x7e\xfe',
|
||||
b'\x85\x31\x20\x00\x1a\x46\x7e\xfe',
|
||||
b'\xc7\x12\x00\x40\x1a\x46\x7e\xfe',
|
||||
b'\x53\x93\x00\x00\x19\x46\x7e\xfe',
|
||||
b'\xa4\x34\x00\x80\x1a\x46\x7e\xfe',
|
||||
b'\x0e\x55\x20\x60\x18\x46\x7e\xfe',
|
||||
b'\x3f\x06\x00\xc0\x37\x4c\x7e\xfe',
|
||||
b'\x0c\x07\x00\x40\x39\x46\x7e\xfe',
|
||||
b'\x2a\x08\x00\x00\x3a\x46\x7e\xfe',
|
||||
b'\x7f\x49\x20\x80\x1a\x46\x7e\xfe',
|
||||
b'\x2f\x0a\x00\xc0\x39\x46\x7e\xfe',
|
||||
b'\x70\xbb\x00\x00\x17\x46\x7e\xfe',
|
||||
b'\x06\x0c\x00\x00\x39\x46\x7e\xfe',
|
||||
b'\x4b\x9d\x20\xe0\x16\x4c\x7e\xfe',
|
||||
b'\x73\xfe\x00\x40\x16\x46\x7e\xfe',
|
||||
b'\xaf\x0f\x20\x80\x39\x4c\x7e\xfe',
|
||||
])
|
||||
|
||||
def test_volkswagen_mqb_crc_acc_06(self, subtests):
|
||||
self.verify_volkswagen_mqb_crc(subtests, "ACC_06", 0x122, [
|
||||
b'\x14\x80\x00\xfe\x07\x00\x00\x18',
|
||||
b'\x9f\x81\x00\xfe\x07\x00\x00\x18',
|
||||
b'\x0a\x82\x00\xfe\x07\x00\x00\x28',
|
||||
b'\x40\x83\x00\xfe\x07\x00\x00\x18',
|
||||
b'\x2d\x84\x00\xfe\x07\x00\x00\x28',
|
||||
b'\xdb\x85\x00\xfe\x07\x00\x00\x18',
|
||||
b'\x4d\x86\x00\xfe\x07\x00\x00\x28',
|
||||
b'\x35\x87\x00\xfe\x07\x00\x00\x18',
|
||||
b'\x23\x88\x00\xfe\x07\x00\x00\x28',
|
||||
b'\x4a\x89\x00\xfe\x07\x00\x00\x28',
|
||||
b'\xe1\x8a\x00\xfe\x07\x00\x00\x28',
|
||||
b'\x30\x8b\x00\xfe\x07\x00\x00\x28',
|
||||
b'\x60\x8c\x00\xfe\x07\x00\x00\x28',
|
||||
b'\x0d\x8d\x00\xfe\x07\x00\x00\x18',
|
||||
b'\x8c\x8e\x00\xfe\x07\x00\x00\x18',
|
||||
b'\x6f\x8f\x00\xfe\x07\x00\x00\x28',
|
||||
])
|
||||
|
||||
def test_volkswagen_mqb_crc_hca_01(self, subtests):
|
||||
self.verify_volkswagen_mqb_crc(subtests, "HCA_01", 0x126, [
|
||||
b'\x00\x30\x0d\xc0\x05\xfe\x07\x00',
|
||||
b'\x3e\x31\x54\xc0\x05\xfe\x07\x00',
|
||||
b'\xa7\x32\xbb\x40\x05\xfe\x07\x00',
|
||||
b'\x96\x33\x29\xc0\x05\xfe\x07\x00',
|
||||
b'\x5f\x34\x00\x00\x03\xfe\x07\x00',
|
||||
b'\x3b\x35\xae\x40\x05\xfe\x07\x00',
|
||||
b'\xc7\x36\x7a\x40\x05\xfe\x07\x00',
|
||||
b'\x6f\x37\x76\x40\x05\xfe\x07\x00',
|
||||
b'\xb1\x38\x00\x00\x03\xfe\x07\x00',
|
||||
b'\xd5\x39\x00\x00\x03\xfe\x07\x00',
|
||||
b'\xba\x3a\x69\xc0\x05\xfe\x07\x00',
|
||||
b'\x65\x3b\x10\x40\x05\xfe\x07\x00',
|
||||
b'\x49\x3c\x72\xc0\x05\xfe\x07\x00',
|
||||
b'\xc6\x3d\xdf\x40\x05\xfe\x07\x00',
|
||||
b'\x1d\x3e\x2c\xc1\x05\xfe\x07\x00',
|
||||
b'\x9b\x3f\x20\x40\x05\xfe\x07\x00',
|
||||
])
|
||||
|
||||
def test_volkswagen_mqb_crc_gra_acc_01(self, subtests):
|
||||
self.verify_volkswagen_mqb_crc(subtests, "GRA_ACC_01", 0x12B, [
|
||||
b'\x86\x40\x80\x2a\x00\x00\x00\x00',
|
||||
b'\xf4\x41\x80\x2a\x00\x00\x00\x00',
|
||||
b'\x50\x42\x80\x2a\x00\x00\x00\x00',
|
||||
b'\x08\x43\x80\x2a\x00\x00\x00\x00',
|
||||
b'\x88\x44\x80\x2a\x00\x00\x00\x00',
|
||||
b'\x2d\x45\x80\x2a\x00\x00\x00\x00',
|
||||
b'\x34\x46\x80\x2a\x00\x00\x00\x00',
|
||||
b'\x11\x47\x80\x2a\x00\x00\x00\x00',
|
||||
b'\xc4\x48\x80\x2a\x00\x00\x00\x00',
|
||||
b'\xcc\x49\x80\x2a\x00\x00\x00\x00',
|
||||
b'\xdc\x4a\x80\x2a\x00\x00\x00\x00',
|
||||
b'\x79\x4b\x80\x2a\x00\x00\x00\x00',
|
||||
b'\x3c\x4c\x80\x2a\x00\x00\x00\x00',
|
||||
b'\x68\x4d\x80\x2a\x00\x00\x00\x00',
|
||||
b'\x27\x4e\x80\x2a\x00\x00\x00\x00',
|
||||
b'\x0d\x4f\x80\x2a\x00\x00\x00\x00',
|
||||
])
|
||||
|
||||
def test_volkswagen_mqb_crc_acc_07(self, subtests):
|
||||
self.verify_volkswagen_mqb_crc(subtests, "ACC_07", 0x12E, [
|
||||
b'\xac\xe0\x7f\x00\xfe\x00\xc0\xff',
|
||||
b'\xa2\xe1\x7f\x00\xfe\x00\xc0\xff',
|
||||
b'\x6b\xe2\x7f\x00\xfe\x00\xc0\xff',
|
||||
b'\xf2\xe3\x7f\x00\xfe\x00\xc0\xff',
|
||||
b'\xd5\xe4\x7f\x00\xfe\x00\xc0\xff',
|
||||
b'\x35\xe5\x7f\x00\xfe\x00\xc0\xff',
|
||||
b'\x7f\xe6\x7f\x00\xfe\x00\xc0\xff',
|
||||
b'\x6c\xe7\x7f\x00\xfe\x00\xc0\xff',
|
||||
b'\x05\xe8\x7f\x00\xfe\x00\xc0\xff',
|
||||
b'\x79\xe9\x7f\x00\xfe\x00\xc0\xff',
|
||||
b'\x25\xea\x7f\x00\xfe\x00\xc0\xff',
|
||||
b'\xd1\xeb\x7f\x00\xfe\x00\xc0\xff',
|
||||
b'\x72\xec\x7f\x00\xfe\x00\xc0\xff',
|
||||
b'\x58\xed\x7f\x00\xfe\x00\xc0\xff',
|
||||
b'\x82\xee\x7f\x00\xfe\x00\xc0\xff',
|
||||
b'\x85\xef\x7f\x00\xfe\x00\xc0\xff',
|
||||
])
|
||||
|
||||
def test_volkswagen_mqb_crc_motor_ev_01(self, subtests):
|
||||
self.verify_volkswagen_mqb_crc(subtests, "Motor_EV_01", 0x187, [
|
||||
b'\x70\x80\x15\x00\x00\x00\x00\xF0',
|
||||
b'\x07\x81\x15\x00\x00\x00\x00\xF0',
|
||||
b'\x7A\x82\x15\x00\x00\x00\x00\xF0',
|
||||
b'\x26\x83\x15\x00\x00\x00\x00\xF0',
|
||||
b'\xBE\x84\x15\x00\x00\x00\x00\xF0',
|
||||
b'\x5A\x85\x15\x00\x00\x00\x00\xF0',
|
||||
b'\xFC\x86\x15\x00\x00\x00\x00\xF0',
|
||||
b'\x9E\x87\x15\x00\x00\x00\x00\xF0',
|
||||
b'\xAF\x88\x15\x00\x00\x00\x00\xF0',
|
||||
b'\x35\x89\x15\x00\x00\x00\x00\xF0',
|
||||
b'\xC5\x8A\x15\x00\x00\x00\x00\xF0',
|
||||
b'\x11\x8B\x15\x00\x00\x00\x00\xF0',
|
||||
b'\xD0\x8C\x15\x00\x00\x00\x00\xF0',
|
||||
b'\xE8\x8D\x15\x00\x00\x00\x00\xF0',
|
||||
b'\xF5\x8E\x15\x00\x00\x00\x00\xF0',
|
||||
b'\x00\x8F\x15\x00\x00\x00\x00\xF0',
|
||||
])
|
||||
|
||||
def test_volkswagen_mqb_crc_esp_33(self, subtests):
|
||||
self.verify_volkswagen_mqb_crc(subtests, "ESP_33", 0x1AB, [
|
||||
b'\x64\x00\x80\x02\x00\x00\x00\x00',
|
||||
b'\x19\x01\x00\x00\x00\x00\x00\x00',
|
||||
b'\xfc\x02\x00\x10\x01\x00\x00\x00',
|
||||
b'\x8b\x03\x80\x02\x00\x00\x00\x00',
|
||||
b'\xa4\x04\x00\x10\x01\x00\x00\x00',
|
||||
b'\x97\x05\x00\x02\x00\x00\x01\x00',
|
||||
b'\xd5\x06\x80\x02\x00\x00\x01\x00',
|
||||
b'\xa0\x07\x80\x02\x00\x00\x01\x00',
|
||||
b'\x89\x08\x00\x00\x00\x00\x00\x00',
|
||||
b'\xe3\x09\x00\x00\x00\x00\x00\x00',
|
||||
b'\x0e\x0a\x00\x00\x00\x00\x00\x00',
|
||||
b'\x90\x0b\x00\x00\x00\x00\x00\x00',
|
||||
b'\x32\x0c\x00\x10\x01\x00\x00\x00',
|
||||
b'\x30\x0d\x00\x00\x00\x00\x00\x00',
|
||||
b'\xc2\x0e\x00\x10\x01\x00\x00\x00',
|
||||
b'\x68\x0f\x80\x02\x00\x00\x00\x00',
|
||||
])
|
||||
|
||||
def test_volkswagen_mqb_crc_acc_02(self, subtests):
|
||||
self.verify_volkswagen_mqb_crc(subtests, "ACC_02", 0x30C, [
|
||||
b'\x82\xf0\x3f\x00\x40\x30\x00\x40',
|
||||
b'\xe6\xf1\x3f\x00\x40\x30\x00\x40',
|
||||
b'\x4a\xf2\x3f\x00\x40\x30\x00\x40',
|
||||
b'\x2e\xf3\x3f\x00\x40\x30\x00\x40',
|
||||
b'\x3d\xf4\x3f\x00\x40\x30\x00\x40',
|
||||
b'\x59\xf5\x3f\x00\x40\x30\x00\x40',
|
||||
b'\xf5\xf6\x3f\x00\x40\x30\x00\x40',
|
||||
b'\x91\xf7\x3f\x00\x40\x30\x00\x40',
|
||||
b'\xd3\xf8\x3f\x00\x40\x30\x00\x40',
|
||||
b'\xb7\xf9\x3f\x00\x40\x30\x00\x40',
|
||||
b'\x1b\xfa\x3f\x00\x40\x30\x00\x40',
|
||||
b'\x7f\xfb\x3f\x00\x40\x30\x00\x40',
|
||||
b'\x6c\xfc\x3f\x00\x40\x30\x00\x40',
|
||||
b'\x08\xfd\x3f\x00\x40\x30\x00\x40',
|
||||
b'\xa4\xfe\x3f\x00\x40\x30\x00\x40',
|
||||
b'\xc0\xff\x3f\x00\x40\x30\x00\x40',
|
||||
])
|
||||
|
||||
def test_volkswagen_mqb_crc_swa_01(self, subtests):
|
||||
self.verify_volkswagen_mqb_crc(subtests, "SWA_01", 0x30F, [
|
||||
b'\x10\x00\x10\x00\x00\x00\x00\x00',
|
||||
b'\x74\x01\x10\x00\x00\x00\x00\x00',
|
||||
b'\xD8\x02\x10\x00\x00\x00\x00\x00',
|
||||
b'\xBC\x03\x10\x00\x00\x00\x00\x00',
|
||||
b'\xAF\x04\x10\x00\x00\x00\x00\x00',
|
||||
b'\xCB\x05\x10\x00\x00\x00\x00\x00',
|
||||
b'\x67\x06\x10\x00\x00\x00\x00\x00',
|
||||
b'\x03\x07\x10\x00\x00\x00\x00\x00',
|
||||
b'\x41\x08\x10\x00\x00\x00\x00\x00',
|
||||
b'\x25\x09\x10\x00\x00\x00\x00\x00',
|
||||
b'\x89\x0A\x10\x00\x00\x00\x00\x00',
|
||||
b'\xED\x0B\x10\x00\x00\x00\x00\x00',
|
||||
b'\xFE\x0C\x10\x00\x00\x00\x00\x00',
|
||||
b'\x9A\x0D\x10\x00\x00\x00\x00\x00',
|
||||
b'\x36\x0E\x10\x00\x00\x00\x00\x00',
|
||||
b'\x52\x0F\x10\x00\x00\x00\x00\x00',
|
||||
])
|
||||
|
||||
def test_volkswagen_mqb_crc_acc_04(self, subtests):
|
||||
self.verify_volkswagen_mqb_crc(subtests, "ACC_04", 0x324, [
|
||||
b'\xba\x00\x00\x00\x00\x00\x00\x10',
|
||||
b'\xde\x01\x00\x00\x00\x00\x00\x10',
|
||||
b'\x72\x02\x00\x00\x00\x00\x00\x10',
|
||||
b'\x16\x03\x00\x00\x00\x00\x00\x10',
|
||||
b'\x05\x04\x00\x00\x00\x00\x00\x10',
|
||||
b'\x44\x05\x00\x00\x00\x00\x00\x00',
|
||||
b'\xe8\x06\x00\x00\x00\x00\x00\x00',
|
||||
b'\xa9\x07\x00\x00\x00\x00\x00\x10',
|
||||
b'\xeb\x08\x00\x00\x00\x00\x00\x10',
|
||||
b'\x8f\x09\x00\x00\x00\x00\x00\x10',
|
||||
b'\x06\x0a\x00\x00\x00\x00\x00\x00',
|
||||
b'\x47\x0b\x00\x00\x00\x00\x00\x10',
|
||||
b'\x71\x0c\x00\x00\x00\x00\x00\x00',
|
||||
b'\x15\x0d\x00\x00\x00\x00\x00\x00',
|
||||
b'\xb9\x0e\x00\x00\x00\x00\x00\x00',
|
||||
b'\xdd\x0f\x00\x00\x00\x00\x00\x00',
|
||||
])
|
||||
|
||||
def test_volkswagen_mqb_crc_klemmen_status_01(self, subtests):
|
||||
self.verify_volkswagen_mqb_crc(subtests, "Klemmen_Status_01", 0x3C0, [
|
||||
b'\x74\x00\x03\x00',
|
||||
b'\xc1\x01\x03\x00',
|
||||
b'\x31\x02\x03\x00',
|
||||
b'\x84\x03\x03\x00',
|
||||
b'\xfe\x04\x03\x00',
|
||||
b'\x4b\x05\x03\x00',
|
||||
b'\xbb\x06\x03\x00',
|
||||
b'\x0e\x07\x03\x00',
|
||||
b'\x4f\x08\x03\x00',
|
||||
b'\xfa\x09\x03\x00',
|
||||
b'\x0a\x0a\x03\x00',
|
||||
b'\xbf\x0b\x03\x00',
|
||||
b'\xc5\x0c\x03\x00',
|
||||
b'\x70\x0d\x03\x00',
|
||||
b'\x80\x0e\x03\x00',
|
||||
b'\x35\x0f\x03\x00',
|
||||
])
|
||||
|
||||
def test_volkswagen_mqb_crc_licht_anf_01(self, subtests):
|
||||
self.verify_volkswagen_mqb_crc(subtests, "Licht_Anf_01", 0x3D5, [
|
||||
b'\xc8\x00\x00\x04\x00\x00\x00\x00',
|
||||
b'\x9f\x01\x00\x04\x00\x00\x00\x00',
|
||||
b'\x5e\x02\x00\x04\x00\x00\x00\x00',
|
||||
b'\x52\x03\x00\x04\x00\x00\x00\x00',
|
||||
b'\xf2\x04\x00\x04\x00\x00\x00\x00',
|
||||
b'\x79\x05\x00\x04\x00\x00\x00\x00',
|
||||
b'\xe6\x06\x00\x04\x00\x00\x00\x00',
|
||||
b'\xfd\x07\x00\x04\x00\x00\x00\x00',
|
||||
b'\xf8\x08\x00\x04\x00\x00\x00\x00',
|
||||
b'\xc6\x09\x00\x04\x00\x00\x00\x00',
|
||||
b'\xf5\x0a\x00\x04\x00\x00\x00\x00',
|
||||
b'\x1a\x0b\x00\x04\x00\x00\x00\x00',
|
||||
b'\x65\x0c\x00\x04\x00\x00\x00\x00',
|
||||
b'\x41\x0d\x00\x04\x00\x00\x00\x00',
|
||||
b'\x7f\x0e\x00\x04\x00\x00\x00\x00',
|
||||
b'\x98\x0f\x00\x04\x00\x00\x00\x00',
|
||||
])
|
||||
|
||||
def test_volkswagen_mqb_crc_esp_20(self, subtests):
|
||||
self.verify_volkswagen_mqb_crc(subtests, "ESP_20", 0x65D, [
|
||||
b'\x98\x30\x2b\x10\x00\x00\x22\x81',
|
||||
b'\xc8\x31\x2b\x10\x00\x00\x22\x81',
|
||||
b'\x9d\x32\x2b\x10\x00\x00\x22\x81',
|
||||
b'\x1f\x33\x2b\x10\x00\x00\x22\x81',
|
||||
b'\x6e\x34\x2b\x10\x00\x00\x22\x81',
|
||||
b'\x61\x35\x2b\x10\x00\x00\x22\x81',
|
||||
b'\x6f\x36\x2b\x10\x00\x00\x22\x81',
|
||||
b'\xe5\x37\x2b\x10\x00\x00\x22\x81',
|
||||
b'\xf8\x38\x2b\x10\x00\x00\x22\x81',
|
||||
b'\xe1\x39\x2b\x10\x00\x00\x22\x81',
|
||||
b'\xaa\x3a\x2b\x10\x00\x00\x22\x81',
|
||||
b'\xe6\x3b\x2b\x10\x00\x00\x22\x81',
|
||||
b'\xef\x3c\x2b\x10\x00\x00\x22\x81',
|
||||
b'\xbb\x3d\x2b\x10\x00\x00\x22\x81',
|
||||
b'\x9b\x3e\x2b\x10\x00\x00\x22\x81',
|
||||
b'\x72\x3f\x2b\x10\x00\x00\x22\x81',
|
||||
])
|
||||
29
opendbc_repo/opendbc/can/tests/test_dbc_exceptions.py
Normal file
29
opendbc_repo/opendbc/can/tests/test_dbc_exceptions.py
Normal file
@@ -0,0 +1,29 @@
|
||||
import pytest
|
||||
|
||||
from opendbc.can import CANDefine, CANPacker, CANParser
|
||||
from opendbc.can.tests import TEST_DBC
|
||||
|
||||
|
||||
class TestCanParserPackerExceptions:
|
||||
def test_civic_exceptions(self):
|
||||
dbc_file = "honda_civic_touring_2016_can_generated"
|
||||
dbc_invalid = dbc_file + "abcdef"
|
||||
msgs = [("STEERING_CONTROL", 50)]
|
||||
with pytest.raises(FileNotFoundError):
|
||||
CANParser(dbc_invalid, msgs, 0)
|
||||
with pytest.raises(FileNotFoundError):
|
||||
CANPacker(dbc_invalid)
|
||||
with pytest.raises(FileNotFoundError):
|
||||
CANDefine(dbc_invalid)
|
||||
with pytest.raises(KeyError):
|
||||
CANDefine(TEST_DBC)
|
||||
|
||||
parser = CANParser(dbc_file, msgs, 0)
|
||||
with pytest.raises(IndexError):
|
||||
parser.update([b''])
|
||||
|
||||
# Everything is supposed to work below
|
||||
CANParser(dbc_file, msgs, 0)
|
||||
CANParser(dbc_file, [], 0)
|
||||
CANPacker(dbc_file)
|
||||
CANDefine(dbc_file)
|
||||
21
opendbc_repo/opendbc/can/tests/test_dbc_parser.py
Normal file
21
opendbc_repo/opendbc/can/tests/test_dbc_parser.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from opendbc.can import CANParser
|
||||
from opendbc.can.tests import ALL_DBCS
|
||||
|
||||
|
||||
class TestDBCParser:
|
||||
def test_enough_dbcs(self):
|
||||
# sanity check that we're running on the real DBCs
|
||||
assert len(ALL_DBCS) > 20
|
||||
|
||||
def test_parse_all_dbcs(self, subtests):
|
||||
"""
|
||||
Dynamic DBC parser checks:
|
||||
- Checksum and counter length, start bit, endianness
|
||||
- Duplicate message addresses and names
|
||||
- Signal out of bounds
|
||||
- All BO_, SG_, VAL_ lines for syntax errors
|
||||
"""
|
||||
|
||||
for dbc in ALL_DBCS:
|
||||
with subtests.test(dbc=dbc):
|
||||
CANParser(dbc, [], 0)
|
||||
26
opendbc_repo/opendbc/can/tests/test_define.py
Normal file
26
opendbc_repo/opendbc/can/tests/test_define.py
Normal file
@@ -0,0 +1,26 @@
|
||||
from opendbc.can import CANDefine
|
||||
from opendbc.can.tests import ALL_DBCS
|
||||
|
||||
|
||||
class TestCANDefine:
|
||||
def test_civic(self):
|
||||
|
||||
dbc_file = "honda_civic_touring_2016_can_generated"
|
||||
defs = CANDefine(dbc_file)
|
||||
|
||||
assert defs.dv[399] == defs.dv['STEER_STATUS']
|
||||
assert defs.dv[399] == {'STEER_STATUS':
|
||||
{7: 'PERMANENT_FAULT',
|
||||
6: 'TMP_FAULT',
|
||||
5: 'FAULT_1',
|
||||
4: 'NO_TORQUE_ALERT_2',
|
||||
3: 'LOW_SPEED_LOCKOUT',
|
||||
2: 'NO_TORQUE_ALERT_1',
|
||||
0: 'NORMAL'}
|
||||
}
|
||||
|
||||
def test_all_dbcs(self, subtests):
|
||||
# Asserts no exceptions on all DBCs
|
||||
for dbc in ALL_DBCS:
|
||||
with subtests.test(dbc=dbc):
|
||||
CANDefine(dbc)
|
||||
367
opendbc_repo/opendbc/can/tests/test_packer_parser.py
Normal file
367
opendbc_repo/opendbc/can/tests/test_packer_parser.py
Normal file
@@ -0,0 +1,367 @@
|
||||
import pytest
|
||||
import random
|
||||
|
||||
from opendbc.can import CANPacker, CANParser
|
||||
from opendbc.can.tests import TEST_DBC
|
||||
|
||||
MAX_BAD_COUNTER = 5
|
||||
|
||||
|
||||
class TestCanParserPacker:
|
||||
def test_packer(self):
|
||||
packer = CANPacker(TEST_DBC)
|
||||
|
||||
for b in range(6):
|
||||
for i in range(256):
|
||||
values = {"COUNTER": i}
|
||||
addr, dat, bus = packer.make_can_msg("CAN_FD_MESSAGE", b, values)
|
||||
assert addr == 245
|
||||
assert bus == b
|
||||
assert dat[0] == i
|
||||
|
||||
def test_packer_counter(self):
|
||||
msgs = [("CAN_FD_MESSAGE", 0), ]
|
||||
packer = CANPacker(TEST_DBC)
|
||||
parser = CANParser(TEST_DBC, msgs, 0)
|
||||
|
||||
# packer should increment the counter
|
||||
for i in range(1000):
|
||||
msg = packer.make_can_msg("CAN_FD_MESSAGE", 0, {})
|
||||
parser.update([0, [msg]])
|
||||
assert parser.vl["CAN_FD_MESSAGE"]["COUNTER"] == (i % 256)
|
||||
|
||||
# setting COUNTER should override
|
||||
for _ in range(100):
|
||||
cnt = random.randint(0, 255)
|
||||
msg = packer.make_can_msg("CAN_FD_MESSAGE", 0, {
|
||||
"COUNTER": cnt,
|
||||
"SIGNED": 0
|
||||
})
|
||||
parser.update([0, [msg]])
|
||||
assert parser.vl["CAN_FD_MESSAGE"]["COUNTER"] == cnt
|
||||
|
||||
# then, should resume counting from the override value
|
||||
cnt = parser.vl["CAN_FD_MESSAGE"]["COUNTER"]
|
||||
for i in range(100):
|
||||
msg = packer.make_can_msg("CAN_FD_MESSAGE", 0, {})
|
||||
parser.update([0, [msg]])
|
||||
assert parser.vl["CAN_FD_MESSAGE"]["COUNTER"] == ((cnt + i) % 256)
|
||||
|
||||
def test_parser_can_valid(self):
|
||||
msgs = [("CAN_FD_MESSAGE", 10), ]
|
||||
packer = CANPacker(TEST_DBC)
|
||||
parser = CANParser(TEST_DBC, msgs, 0)
|
||||
|
||||
# shouldn't be valid initially
|
||||
assert not parser.can_valid
|
||||
|
||||
# not valid until the message is seen
|
||||
for _ in range(100):
|
||||
parser.update([0, []])
|
||||
assert not parser.can_valid
|
||||
|
||||
# valid once seen
|
||||
for i in range(1, 100):
|
||||
t = int(0.01 * i * 1e9)
|
||||
msg = packer.make_can_msg("CAN_FD_MESSAGE", 0, {})
|
||||
parser.update([t, [msg]])
|
||||
assert parser.can_valid
|
||||
|
||||
def test_parser_updated_list(self):
|
||||
msgs = [("CAN_FD_MESSAGE", 10), ]
|
||||
parser = CANParser(TEST_DBC, msgs, 0)
|
||||
packer = CANPacker(TEST_DBC)
|
||||
|
||||
msg = packer.make_can_msg("CAN_FD_MESSAGE", 0, {})
|
||||
ret = parser.update([0, [msg]])
|
||||
assert ret == {245}
|
||||
|
||||
ret = parser.update([])
|
||||
assert len(ret) == 0
|
||||
|
||||
def test_parser_counter_can_valid(self):
|
||||
"""
|
||||
Tests number of allowed bad counters + ensures CAN stays invalid
|
||||
while receiving invalid messages + that we can recover
|
||||
"""
|
||||
msgs = [
|
||||
("STEERING_CONTROL", 0),
|
||||
]
|
||||
packer = CANPacker("honda_civic_touring_2016_can_generated")
|
||||
parser = CANParser("honda_civic_touring_2016_can_generated", msgs, 0)
|
||||
|
||||
msg = packer.make_can_msg("STEERING_CONTROL", 0, {"COUNTER": 0})
|
||||
|
||||
# bad static counter, invalid once it's seen MAX_BAD_COUNTER messages
|
||||
for idx in range(0x1000):
|
||||
parser.update([0, [msg]])
|
||||
assert ((idx + 1) < MAX_BAD_COUNTER) == parser.can_valid
|
||||
|
||||
# one to recover
|
||||
msg = packer.make_can_msg("STEERING_CONTROL", 0, {"COUNTER": 1})
|
||||
parser.update([0, [msg]])
|
||||
assert parser.can_valid
|
||||
|
||||
def test_parser_no_partial_update(self):
|
||||
"""
|
||||
Ensure that the CANParser doesn't partially update messages with invalid signals (COUNTER/CHECKSUM).
|
||||
Previously, the signal update loop would only break once it got to one of these invalid signals,
|
||||
after already updating most/all of the signals.
|
||||
"""
|
||||
msgs = [
|
||||
("STEERING_CONTROL", 0),
|
||||
]
|
||||
packer = CANPacker("honda_civic_touring_2016_can_generated")
|
||||
parser = CANParser("honda_civic_touring_2016_can_generated", msgs, 0)
|
||||
|
||||
def rx_steering_msg(values, bad_checksum=False):
|
||||
msg = packer.make_can_msg("STEERING_CONTROL", 0, values)
|
||||
if bad_checksum:
|
||||
# add 1 to checksum
|
||||
dat = bytearray(msg[1])
|
||||
dat[4] = (dat[4] & 0xF0) | ((dat[4] & 0x0F) + 1)
|
||||
msg = (msg[0], bytes(dat), msg[2])
|
||||
|
||||
parser.update([0, [msg]])
|
||||
|
||||
rx_steering_msg({"STEER_TORQUE": 100}, bad_checksum=False)
|
||||
assert parser.vl["STEERING_CONTROL"]["STEER_TORQUE"] == 100
|
||||
assert parser.vl_all["STEERING_CONTROL"]["STEER_TORQUE"] == [100]
|
||||
|
||||
for _ in range(5):
|
||||
rx_steering_msg({"STEER_TORQUE": 200}, bad_checksum=True)
|
||||
assert parser.vl["STEERING_CONTROL"]["STEER_TORQUE"] == 100
|
||||
assert parser.vl_all["STEERING_CONTROL"]["STEER_TORQUE"] == []
|
||||
|
||||
# Even if CANParser doesn't update instantaneous vl, make sure it didn't add invalid values to vl_all
|
||||
rx_steering_msg({"STEER_TORQUE": 300}, bad_checksum=False)
|
||||
assert parser.vl["STEERING_CONTROL"]["STEER_TORQUE"] == 300
|
||||
assert parser.vl_all["STEERING_CONTROL"]["STEER_TORQUE"] == [300]
|
||||
|
||||
def test_packer_parser(self):
|
||||
msgs = [
|
||||
("Brake_Status", 0),
|
||||
("CAN_FD_MESSAGE", 0),
|
||||
("STEERING_CONTROL", 0),
|
||||
]
|
||||
packer = CANPacker(TEST_DBC)
|
||||
parser = CANParser(TEST_DBC, msgs, 0)
|
||||
|
||||
for steer in range(-256, 255):
|
||||
for active in (1, 0):
|
||||
values = {
|
||||
"STEERING_CONTROL": {
|
||||
"STEER_TORQUE": steer,
|
||||
"STEER_TORQUE_REQUEST": active,
|
||||
},
|
||||
"Brake_Status": {
|
||||
"Signal1": 61042322657536.0,
|
||||
},
|
||||
"CAN_FD_MESSAGE": {
|
||||
"SIGNED": steer,
|
||||
"64_BIT_LE": random.randint(0, 100),
|
||||
"64_BIT_BE": random.randint(0, 100),
|
||||
},
|
||||
}
|
||||
|
||||
msgs = [packer.make_can_msg(k, 0, v) for k, v in values.items()]
|
||||
parser.update([0, msgs])
|
||||
|
||||
for k, v in values.items():
|
||||
for key, val in v.items():
|
||||
assert parser.vl[k][key] == pytest.approx(val)
|
||||
|
||||
# also check address
|
||||
for sig in ("STEER_TORQUE", "STEER_TORQUE_REQUEST", "COUNTER", "CHECKSUM"):
|
||||
assert parser.vl["STEERING_CONTROL"][sig] == parser.vl[228][sig]
|
||||
|
||||
def test_scale_offset(self):
|
||||
"""Test that both scale and offset are correctly preserved"""
|
||||
dbc_file = "honda_civic_touring_2016_can_generated"
|
||||
msgs = [("VSA_STATUS", 50)]
|
||||
parser = CANParser(dbc_file, msgs, 0)
|
||||
packer = CANPacker(dbc_file)
|
||||
|
||||
for brake in range(100):
|
||||
values = {"USER_BRAKE": brake}
|
||||
msgs = packer.make_can_msg("VSA_STATUS", 0, values)
|
||||
parser.update([0, [msgs]])
|
||||
|
||||
assert parser.vl["VSA_STATUS"]["USER_BRAKE"] == pytest.approx(brake)
|
||||
|
||||
def test_subaru(self):
|
||||
# Subaru is little endian
|
||||
|
||||
dbc_file = "subaru_global_2017_generated"
|
||||
|
||||
msgs = [("ES_LKAS", 50)]
|
||||
|
||||
parser = CANParser(dbc_file, msgs, 0)
|
||||
packer = CANPacker(dbc_file)
|
||||
|
||||
idx = 0
|
||||
for steer in range(-256, 255):
|
||||
for active in [1, 0]:
|
||||
values = {
|
||||
"LKAS_Output": steer,
|
||||
"LKAS_Request": active,
|
||||
"SET_1": 1
|
||||
}
|
||||
|
||||
msgs = packer.make_can_msg("ES_LKAS", 0, values)
|
||||
parser.update([0, [msgs]])
|
||||
|
||||
assert parser.vl["ES_LKAS"]["LKAS_Output"] == pytest.approx(steer)
|
||||
assert parser.vl["ES_LKAS"]["LKAS_Request"] == pytest.approx(active)
|
||||
assert parser.vl["ES_LKAS"]["SET_1"] == pytest.approx(1)
|
||||
assert parser.vl["ES_LKAS"]["COUNTER"] == pytest.approx(idx % 16)
|
||||
idx += 1
|
||||
|
||||
def test_bus_timeout(self):
|
||||
"""Test CAN bus timeout detection"""
|
||||
dbc_file = "honda_civic_touring_2016_can_generated"
|
||||
|
||||
freq = 100
|
||||
msgs = [("VSA_STATUS", freq), ("STEER_MOTOR_TORQUE", freq/2)]
|
||||
|
||||
parser = CANParser(dbc_file, msgs, 0)
|
||||
packer = CANPacker(dbc_file)
|
||||
|
||||
i = 0
|
||||
def send_msg(blank=False):
|
||||
nonlocal i
|
||||
i += 1
|
||||
t = i*((1 / freq) * 1e9)
|
||||
|
||||
if blank:
|
||||
msgs = []
|
||||
else:
|
||||
msgs = [packer.make_can_msg("VSA_STATUS", 0, {}), ]
|
||||
|
||||
parser.update([t, msgs])
|
||||
|
||||
# all good, no timeout
|
||||
for _ in range(1000):
|
||||
send_msg()
|
||||
assert not parser.bus_timeout, str(_)
|
||||
|
||||
# timeout after 10 blank msgs
|
||||
for n in range(200):
|
||||
send_msg(blank=True)
|
||||
assert (n >= 10) == parser.bus_timeout
|
||||
|
||||
# no timeout immediately after seen again
|
||||
send_msg()
|
||||
assert not parser.bus_timeout
|
||||
|
||||
def test_updated(self):
|
||||
"""Test updated value dict"""
|
||||
dbc_file = "honda_civic_touring_2016_can_generated"
|
||||
msgs = [("VSA_STATUS", 50)]
|
||||
parser = CANParser(dbc_file, msgs, 0)
|
||||
packer = CANPacker(dbc_file)
|
||||
|
||||
# Make sure nothing is updated
|
||||
assert len(parser.vl_all["VSA_STATUS"]["USER_BRAKE"]) == 0
|
||||
|
||||
idx = 0
|
||||
for _ in range(10):
|
||||
# Ensure CANParser holds the values of any duplicate messages over multiple frames
|
||||
user_brake_vals = [random.randrange(100) for _ in range(random.randrange(5, 10))]
|
||||
half_idx = len(user_brake_vals) // 2
|
||||
can_msgs = [[], []]
|
||||
for frame, brake_vals in enumerate((user_brake_vals[:half_idx], user_brake_vals[half_idx:])):
|
||||
for user_brake in brake_vals:
|
||||
values = {"USER_BRAKE": user_brake}
|
||||
can_msgs[frame].append(packer.make_can_msg("VSA_STATUS", 0, values))
|
||||
idx += 1
|
||||
|
||||
parser.update([[0, m] for m in can_msgs])
|
||||
vl_all = parser.vl_all["VSA_STATUS"]["USER_BRAKE"]
|
||||
|
||||
assert vl_all == user_brake_vals
|
||||
if len(user_brake_vals):
|
||||
assert vl_all[-1] == parser.vl["VSA_STATUS"]["USER_BRAKE"]
|
||||
|
||||
def test_timestamp_nanos(self):
|
||||
"""Test message timestamp dict"""
|
||||
dbc_file = "honda_civic_touring_2016_can_generated"
|
||||
|
||||
msgs = [
|
||||
("VSA_STATUS", 50),
|
||||
("POWERTRAIN_DATA", 100),
|
||||
]
|
||||
|
||||
parser = CANParser(dbc_file, msgs, 0)
|
||||
packer = CANPacker(dbc_file)
|
||||
|
||||
# Check the default timestamp is zero
|
||||
for msg in ("VSA_STATUS", "POWERTRAIN_DATA"):
|
||||
ts_nanos = parser.ts_nanos[msg].values()
|
||||
assert set(ts_nanos) == {0}
|
||||
|
||||
# Check:
|
||||
# - timestamp is only updated for correct messages
|
||||
# - timestamp is correct for multiple runs
|
||||
# - timestamp is from the latest message if updating multiple strings
|
||||
for _ in range(10):
|
||||
can_strings = []
|
||||
log_mono_time = 0
|
||||
for i in range(10):
|
||||
log_mono_time = int(0.01 * i * 1e+9)
|
||||
can_msg = packer.make_can_msg("VSA_STATUS", 0, {})
|
||||
can_strings.append((log_mono_time, [can_msg]))
|
||||
parser.update(can_strings)
|
||||
|
||||
ts_nanos = parser.ts_nanos["VSA_STATUS"].values()
|
||||
assert set(ts_nanos) == {log_mono_time}
|
||||
ts_nanos = parser.ts_nanos["POWERTRAIN_DATA"].values()
|
||||
assert set(ts_nanos) == {0}
|
||||
|
||||
def test_nonexistent_messages(self):
|
||||
# Ensure we don't allow messages not in the DBC
|
||||
existing_messages = ("STEERING_CONTROL", 228, "CAN_FD_MESSAGE", 245)
|
||||
|
||||
for msg in existing_messages:
|
||||
CANParser(TEST_DBC, [(msg, 0)], 0)
|
||||
with pytest.raises(RuntimeError):
|
||||
new_msg = msg + "1" if isinstance(msg, str) else msg + 1
|
||||
CANParser(TEST_DBC, [(new_msg, 0)], 0)
|
||||
|
||||
def test_track_all_signals(self):
|
||||
parser = CANParser("toyota_nodsu_pt_generated", [("ACC_CONTROL", 0)], 0)
|
||||
assert parser.vl["ACC_CONTROL"] == {
|
||||
"ACCEL_CMD": 0,
|
||||
"ALLOW_LONG_PRESS": 0,
|
||||
"ACC_MALFUNCTION": 0,
|
||||
"RADAR_DIRTY": 0,
|
||||
"DISTANCE": 0,
|
||||
"MINI_CAR": 0,
|
||||
"ACC_TYPE": 0,
|
||||
"CANCEL_REQ": 0,
|
||||
"ACC_CUT_IN": 0,
|
||||
"LEAD_VEHICLE_STOPPED": 0,
|
||||
"PERMIT_BRAKING": 0,
|
||||
"RELEASE_STANDSTILL": 0,
|
||||
"ITS_CONNECT_LEAD": 0,
|
||||
"ACCEL_CMD_ALT": 0,
|
||||
"CHECKSUM": 0,
|
||||
}
|
||||
|
||||
def test_disallow_duplicate_messages(self):
|
||||
CANParser("toyota_nodsu_pt_generated", [("ACC_CONTROL", 5)], 0)
|
||||
|
||||
with pytest.raises(RuntimeError):
|
||||
CANParser("toyota_nodsu_pt_generated", [("ACC_CONTROL", 5), ("ACC_CONTROL", 10)], 0)
|
||||
|
||||
with pytest.raises(RuntimeError):
|
||||
CANParser("toyota_nodsu_pt_generated", [("ACC_CONTROL", 10), ("ACC_CONTROL", 10)], 0)
|
||||
|
||||
def test_allow_undefined_msgs(self):
|
||||
# TODO: we should throw an exception for these, but we need good
|
||||
# discovery tests in openpilot first
|
||||
packer = CANPacker("toyota_nodsu_pt_generated")
|
||||
|
||||
assert packer.make_can_msg("ACC_CONTROL", 0, {"UNKNOWN_SIGNAL": 0}) == (835, b'\x00\x00\x00\x00\x00\x00\x00N', 0)
|
||||
assert packer.make_can_msg("UNKNOWN_MESSAGE", 0, {"UNKNOWN_SIGNAL": 0}) == (0, b'', 0)
|
||||
assert packer.make_can_msg(0, 0, {"UNKNOWN_SIGNAL": 0}) == (0, b'', 0)
|
||||
Reference in New Issue
Block a user