@@ -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 ) 
824828class  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 ) 
831836class  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 ) 
840854class  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} { rx_length } { 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 )
0 commit comments