Skip to content

Commit e063926

Browse files
authored
Merge pull request #873 from tainnok/pr_multiple_changes_including_container_pdu_secoc
multiple changes: mainly improve SecOC support and Container-PDU support
2 parents e17b7a0 + d7b1b88 commit e063926

File tree

3 files changed

+556
-184
lines changed

3 files changed

+556
-184
lines changed

src/canmatrix/canmatrix.py

Lines changed: 85 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -468,8 +468,8 @@ def phys2raw(self, value=None):
468468
# if not (0 <= value <= 10):
469469
if not (self.min <= value <= self.max):
470470
logger.warning(
471-
"Value {} is not valid for {}. Min={} and Max={}".format(
472-
value, self, self.min, self.max)
471+
"Signal {}: Value {} is not valid for {}. Min={} and Max={}".format(
472+
self.name, value, self, self.min, self.max)
473473
)
474474
raw_value = (self.float_factory(value) - self.float_factory(self.offset)) / self.float_factory(self.factor)
475475

@@ -612,6 +612,10 @@ def unpack_bitstring(length, is_float, is_signed, bits):
612612
value, = struct.unpack(float_type, bytearray(int(''.join(b), 2) for b in grouper(bits, 8)))
613613
else:
614614
value = int(bits, 2)
615+
# try:
616+
# value = int(bits, 2)
617+
# except Exception as e:
618+
# xx = 1
615619

616620
if is_signed and bits[0] == '1':
617621
value -= (1 << len(bits))
@@ -823,18 +827,28 @@ class Endpoint(object):
823827
@attr.s(eq=False)
824828
class AutosarE2EProperties(object):
825829
profile = attr.ib(default=None) # type: str
830+
data_id_mode = attr.ib(default=None) # type: str
826831
data_ids = attr.ib(default=None) # type: List[int]
827832
data_length = attr.ib(default=None) # type: int
828833

829834

830835
@attr.s(eq=False)
831836
class AutosarSecOCProperties(object):
832-
auth_algorithm = attr.ib(default="") # type: str
833-
payload_length = attr.ib(default=0) # type: int
834-
auth_tx_length = attr.ib(default=0) # type: int
835-
data_id = attr.ib(default=0) # type: int
836-
freshness_length = attr.ib(default=0) # type: int
837-
freshness_tx_length = attr.ib(default=0) # type: int
837+
secured_i_pdu_name = attr.ib(default="unknown") # type: str
838+
authentic_i_pdu_name = attr.ib(default="unknown") # type: str
839+
auth_algorithm = attr.ib(default=None) # type: str|None
840+
authentic_pdu_length = attr.ib(default=0) # type: int
841+
secured_i_pdu_length = attr.ib(default=0) # type: int
842+
auth_tx_length = attr.ib(default=None) # type: int|None
843+
data_id = attr.ib(default=None) # type: int|None
844+
freshness_value_id = attr.ib(default=None) # type: int|None
845+
freshness_length = attr.ib(default=None) # type: int|None
846+
freshness_tx_length = attr.ib(default=None) # type: int|None
847+
use_as_cryptographic_i_pdu = attr.ib(default=False) # type: bool
848+
message_link_length = attr.ib(default=None) # type: int|None
849+
message_link_position = attr.ib(default=None) # type: int|None
850+
key_id = attr.ib(default=None) # type: int|None
851+
838852

839853
@attr.s(eq=False)
840854
class Pdu(object):
@@ -845,6 +859,8 @@ class Pdu(object):
845859
Whereas a PDU is the same than a frame on CAN bus, at flexray a frame may consist of
846860
multiple PDUs (a bit like multiple signal layout for multiplexed can frames).
847861
This class is only used for flexray busses.
862+
Note: since container-pdus are supported for arxml, this class is also used for arxml (but only
863+
for sub-pdus of container-pdus).
848864
"""
849865

850866
name = attr.ib(default="") # type: str
@@ -856,6 +872,9 @@ class Pdu(object):
856872
signals = attr.ib(factory=list) # type: typing.MutableSequence[Signal]
857873
signalGroups = attr.ib(factory=list) # type: typing.MutableSequence[SignalGroup]
858874
cycle_time = attr.ib(default=0) # type: int
875+
secOC_properties = attr.ib(default=None) # type: Optional[AutosarSecOCProperties]
876+
# offset is used for arxml, sub-pdu inside a static-container-pdu
877+
offset_bytes = attr.ib(default=0) # type: int
859878

860879
def add_signal(self, signal):
861880
# type: (Signal) -> Signal
@@ -1503,56 +1522,86 @@ def unpack(self, data: bytes,
15031522
f"Received message 0x{msg_id:04X} with wrong data size: {rx_length} instead of {self.size}")
15041523

15051524
if self.is_pdu_container:
1525+
# note: PDU-Container without header is possible for ARXML-Container-PDUs with NO-HEADER
1526+
# that mean this are not dynamic Container-PDUs rather than static ones. (each sub-pdu has
1527+
# a fixed offset in the container)
1528+
header_signals = []
15061529
header_id_signal = self.signal_by_name("Header_ID")
15071530
header_dlc_signal = self.signal_by_name("Header_DLC")
1508-
if header_id_signal is None or header_dlc_signal is None:
1509-
raise DecodingContainerPdu(
1510-
'Received message 0x{:08X} without Header_ID or '
1511-
'Header_DLC signal'.format(self.arbitration_id.id)
1512-
)
1531+
1532+
if header_id_signal is not None:
1533+
header_signals.append(header_id_signal)
1534+
_header_id_signal_size = header_id_signal.size
1535+
else:
1536+
_header_id_signal_size = 0
1537+
if header_dlc_signal is not None:
1538+
header_signals.append(header_dlc_signal)
1539+
_header_dlc_signal_size = header_dlc_signal.size
1540+
else:
1541+
_header_dlc_signal_size = 0
15131542
# TODO: may be we need to check that ID/DLC signals are contiguous
1514-
header_size = header_id_signal.size + header_dlc_signal.size
1543+
if len(header_signals) > 0 and len(header_signals) != 2:
1544+
raise DecodingConatainerPdu(
1545+
'Received message 0x{:08X} with incorrect Header-Defintiion. '
1546+
'Header_ID signal or Header_DLC is missing'.format(self.arbitration_id.id)
1547+
)
1548+
header_size = _header_id_signal_size + _header_dlc_signal_size
15151549
little, big = self.bytes_to_bitstrings(data)
15161550
size = self.size * 8
15171551
return_dict = dict({"pdus": []})
15181552
# decode signal which are not in PDUs
1519-
signals = [s for s in self.signals if s not in [header_id_signal, header_dlc_signal]]
1553+
signals = [s for s in self.signals if s not in header_signals]
15201554
if signals:
15211555
unpacked = self.bitstring_to_signal_list(signals, big, little, size)
15221556
for s, v in zip(signals, unpacked):
15231557
return_dict[s.name] = DecodedSignal(v, s)
15241558
# decode PDUs
1525-
offset = header_id_signal.start_bit
1526-
header_signals = [header_id_signal, header_dlc_signal]
1527-
while (offset + header_size) < size:
1528-
unpacked = self.bitstring_to_signal_list(
1529-
header_signals,
1530-
big[offset:offset + header_size],
1531-
little[size - offset - header_size:size - offset],
1532-
header_size
1533-
)
1534-
offset += header_size
1535-
pdu_id = unpacked[0]
1536-
pdu_dlc = unpacked[1]
1537-
for s, v in zip(header_signals, unpacked):
1538-
if s.name not in return_dict:
1539-
return_dict[s.name] = []
1540-
return_dict[s.name].append(DecodedSignal(v, s))
1541-
pdu = self.pdu_by_id(pdu_id)
1559+
offset = header_id_signal.start_bit if header_id_signal is not None else 0
1560+
no_header_next_pdu_idx = 0
1561+
# decode as long as there is data left to decode (if there is a header), or as long as there are sub-pdus
1562+
# left to decode (in case of static-container without pdu-headers)
1563+
while (offset + header_size) < size and no_header_next_pdu_idx < len(self.pdus):
1564+
if len(header_signals) > 0:
1565+
unpacked = self.bitstring_to_signal_list(
1566+
header_signals,
1567+
big[offset:offset + header_size],
1568+
little[size - offset - header_size:size - offset],
1569+
header_size
1570+
)
1571+
offset += header_size
1572+
pdu_id = unpacked[0]
1573+
pdu_dlc = unpacked[1]
1574+
for s, v in zip(header_signals, unpacked):
1575+
if s.name not in return_dict:
1576+
return_dict[s.name] = []
1577+
return_dict[s.name].append(DecodedSignal(v, s))
1578+
pdu = self.pdu_by_id(pdu_id)
1579+
else:
1580+
# if there is no pdu-header, then we have a static container-pdu
1581+
# we have to loop all sub-pdus and set the offset to the offset of the PDU
1582+
# note: order of processing sub-PDUs is not important, even if the sub-PDUs are not ordered
1583+
# by the pdu-offset (we just set the offset correct to the actual processed sub-PDU)
1584+
pdu = self.pdus[no_header_next_pdu_idx]
1585+
no_header_next_pdu_idx += 1
1586+
pdu_dlc = pdu.size
1587+
offset = pdu.offset_bytes * 8
1588+
decode_size_bits = pdu_dlc * 8
15421589
if pdu is None:
15431590
return_dict['pdus'].append(None)
15441591
else:
15451592
unpacked = self.bitstring_to_signal_list(
15461593
pdu.signals,
1547-
big[offset:offset + pdu_dlc * 8],
1548-
little[size - offset - pdu_dlc * 8:size - offset],
1549-
pdu_dlc * 8
1594+
big[offset:offset + decode_size_bits],
1595+
little[size - offset - decode_size_bits:size - offset],
1596+
decode_size_bits
15501597
)
15511598
pdu_dict = dict()
15521599
for s, v in zip(pdu.signals, unpacked):
15531600
pdu_dict[s.name] = DecodedSignal(v, s)
15541601
return_dict["pdus"].append({pdu.name: pdu_dict})
1555-
offset += (pdu_dlc * 8)
1602+
if len(header_signals) > 0:
1603+
# if there is a pdu-header, we have to set the offset to the start of the next pdu
1604+
offset += decode_size_bits
15561605
return return_dict
15571606
else:
15581607
little, big = self.bytes_to_bitstrings(data)

src/canmatrix/cli/convert.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ def get_formats():
9696
@click.option('--arxmlFlexray/--no-arxmlFlexray', 'decode_flexray', default = False, help="EXPERIMENTAL: import basic flexray data from ARXML")
9797
@click.option('--arxmlEthernet/--no-arxmlEthernet', 'decode_ethernet', default = False, help="EXPERIMENTAL: import basic ethernet data from ARXML")
9898
@click.option('--preferred-languages', 'preferred_languages', default = "EN,DE", help="the preferred languages will be given priority when there are comments or descriptions available in multiple languages\ndefault EN,DE")
99+
@click.option('--arxmlUpdate-bit-init_1/--no-arxmlUpdate-bit-init_1', 'update_bit_init_1', default=False, help="Init generated Update-Bits with init-value 1 (True: init_value=1, False: init_value=0")
99100

100101

101102
# dbc switches

0 commit comments

Comments
 (0)