4545logger = logging .getLogger (__name__ )
4646
4747fx = "http://www.asam.net/xml/fbx"
48+ te = "http://www.technica-engineering.com/xml/fbx"
4849ho = "http://www.asam.net/xml"
4950can = "http://www.asam.net/xml/fbx/can"
5051xsi = "http://www.w3.org/2001/XMLSchema-instance"
5152ns_ho = "{%s}" % ho
5253ns_fx = "{%s}" % fx
54+ ns_te = "{%s}" % te
5355ns_can = "{%s}" % can
5456ns_xsi = "{%s}" % xsi
5557
@@ -74,6 +76,13 @@ def create_sub_element_fx(parent, element_name, element_text=None):
7476 new .text = element_text
7577 return new
7678
79+ def create_sub_element_te (parent , element_name , element_text = None ):
80+ # type: (_Element, str, typing.Optional[str]) -> _Element
81+ new = lxml .etree .SubElement (parent , ns_te + element_name )
82+ if element_text is not None :
83+ new .text = element_text
84+ return new
85+
7786
7887def create_sub_element_ho (parent , element_name , element_text = None ):
7988 # type: (_Element, str, typing.Optional[str]) -> _Element
@@ -133,6 +142,103 @@ def get_multiplexing_parts_infos(signals, frame_name, start_pos=-1, end_pos=-1,
133142
134143 return start_pos , end_pos , seg_big_endian
135144
145+ def create_frame_element (parent , frame , prefix = "" ):
146+ """Helper function to create a frame element with PDU instances."""
147+ frame_element = create_sub_element_fx (parent , "FRAME" )
148+ frame_element .set ("ID" , f"{ prefix } FRAME_{ frame .name } " )
149+
150+ create_short_name_desc (frame_element , frame .name , frame .comment )
151+ create_sub_element_fx (frame_element , "BYTE-LENGTH" , str (frame .size ))
152+ create_sub_element_fx (frame_element , "PDU-TYPE" , "APPLICATION" )
153+
154+ # PDU instances
155+ pdu_instances = create_sub_element_fx (frame_element , "PDU-INSTANCES" )
156+ pdu_instance = create_sub_element_fx (pdu_instances , "PDU-INSTANCE" )
157+ pdu_instance .set ("ID" , f"PDUINSTANCE_{ frame .name } " ) # Note: No prefix for ID
158+
159+ pdu_ref = create_sub_element_fx (pdu_instance , "PDU-REF" )
160+ pdu_ref .set ("ID-REF" , f"{ prefix } PDU_{ frame .name } " )
161+
162+ create_sub_element_fx (pdu_instance , "BIT-POSITION" , "0" )
163+ create_sub_element_fx (pdu_instance , "IS-HIGH-LOW-BYTE-ORDER" , "false" )
164+
165+ return frame_element
166+
167+ def create_frame_triggering (parent , frame , prefix = "" ):
168+ """Helper function to create a frame triggering element."""
169+ frame_triggering = create_sub_element_fx (parent , "FRAME-TRIGGERING" )
170+ frame_triggering .set ("ID" , f"{ prefix } FT_{ frame .name } " )
171+
172+ # Identifier
173+ identifier = create_sub_element_fx (frame_triggering , "IDENTIFIER" )
174+ create_sub_element_fx (identifier , "IDENTIFIER-VALUE" , str (frame .arbitration_id .id ))
175+
176+ # Frame reference
177+ frame_ref = create_sub_element_fx (frame_triggering , "FRAME-REF" )
178+ frame_ref .set ("ID-REF" , f"{ prefix } FRAME_{ frame .name } " )
179+
180+ # CAN-FD behavior (if applicable)
181+ if frame .is_fd :
182+ create_sub_element_fx (frame_triggering , "CAN-FRAME-TX-BEHAVIOR" , "CAN-FD" )
183+ create_sub_element_fx (frame_triggering , "CAN-FRAME-RX-BEHAVIOR" , "CAN-FD" )
184+
185+ return frame_triggering
186+
187+ def create_pdu_triggering (parent , pdu , prefix = "" ):
188+ """Helper function to create a PDU triggering element with timings."""
189+ pdu_triggering = create_sub_element_fx (parent , "PDU-TRIGGERING" )
190+ pdu_triggering .set ("ID" , f"{ prefix } PDU_{ pdu .name } " )
191+
192+ # Timings
193+ pdu_timings = create_sub_element_fx (pdu_triggering , "TIMINGS" )
194+ if pdu .cycle_time > 0 :
195+ cyclic_timing = create_sub_element_fx (pdu_timings , "CYCLIC-TIMING" )
196+ repeating_time_range = create_sub_element_fx (cyclic_timing , "REPEATING-TIME-RANGE" )
197+ time_value = f"PT{ pdu .cycle_time / 1000.0 } S"
198+ create_sub_element_fx (repeating_time_range , "VALUE" , time_value )
199+
200+ # PDU reference
201+ pdu_ref = create_sub_element_fx (pdu_triggering , "PDU-REF" )
202+ pdu_ref .set ("ID-REF" , f"{ prefix } PDU_{ pdu .name } " )
203+
204+ return pdu_triggering
205+
206+
207+ def create_output_port (parent , frame , prefix = "" ):
208+ """Helper function to create output port with frame and PDU references."""
209+ output_port = create_sub_element_fx (parent , "OUTPUT-PORT" )
210+
211+ # Frame triggering reference
212+ frame_triggering_ref = create_sub_element_fx (output_port , "FRAME-TRIGGERING-REF" )
213+ frame_triggering_ref .set ("ID-REF" , f"{ prefix } FT_{ frame .name } " )
214+
215+ # PDU references
216+ included_pdus = create_sub_element_fx (output_port , "INCLUDED-PDUS" )
217+ included_pdu = create_sub_element_fx (included_pdus , "INCLUDED-PDU" )
218+ included_pdu .set ('ID' , f'{ prefix .lower ()} output_included_pdu_{ frame .name } ' )
219+
220+ pdu_triggering_ref = create_sub_element_fx (included_pdu , "PDU-TRIGGERING-REF" )
221+ pdu_triggering_ref .set ("ID-REF" , f"{ prefix } PDU_{ frame .name } " )
222+
223+ return output_port
224+
225+ def create_secoc_configuration (frame , auth_info_tx_length_def , freshness_value_tx_length_def , data_id_def , freshness_value_length_def , spdu ):
226+ auth_info_tx_length = int (frame .attribute ("SCP_AuthInfoTxLength" )) if frame .attribute ("SCP_AuthInfoTxLength" ) is not None else int (auth_info_tx_length_def )
227+ freshness_value_tx_length = int (frame .attribute ("SCP_FreshnessValueTxLength" )) if frame .attribute ("SCP_FreshnessValueTxLength" ) is not None else int (freshness_value_tx_length_def )
228+ secoc_pdu_length = frame .size + (auth_info_tx_length // 8 ) + (freshness_value_tx_length // 8 )
229+ create_sub_element_fx (spdu , "BYTE-LENGTH" , str (secoc_pdu_length ))
230+ create_sub_element_fx (spdu , "PDU-TYPE" , "OTHER" )
231+ manufac_extansion = create_sub_element_te (spdu , "MANUFACTURER-EXTENSION" )
232+ sec_props = create_sub_element_te (manufac_extansion , "SECURITY-PROPERTIES" )
233+ data_id = frame .attribute ("SCP_DataId" ) if frame .attribute ("SCP_DataId" ) else data_id_def
234+ create_sub_element_te (sec_props , "DATA-ID" , data_id )
235+ create_sub_element_te (sec_props , "AUTH-INFO-TX-LENGTH" , str (auth_info_tx_length ))
236+ freshness_value_length = frame .attribute ("SCP_FreshnessValueLength" ) if frame .attribute ("SCP_FreshnessValueLength" ) else freshness_value_length_def
237+ create_sub_element_te (sec_props , "FRESHNESS-VALUE-LENGTH" , str (freshness_value_length ))
238+ create_sub_element_te (sec_props , "FRESHNESS-VALUE-TX-LENGTH" , str (freshness_value_tx_length ))
239+ payload_pdu = create_sub_element_te (sec_props , "PAYLOAD-REF" )
240+ payload_pdu .set ("ID-REF" , "PDU_" + frame .name )
241+
136242def get_base_data_type (signal ):
137243 # type: (Signal) -> str
138244 if signal .is_float :
@@ -423,7 +529,7 @@ def load(f, **_options):
423529
424530def dump (db , f , ** options ):
425531 # type: (canmatrix.CanMatrix, typing.IO, **typing.Any) -> None
426- ns_map = {"fx" : fx , "ho" : ho , "can" : can , "xsi" : xsi }
532+ ns_map = {"fx" : fx , "ho" : ho , "te" : te , " can" : can , "xsi" : xsi }
427533 can_channel = 'CANCHANNEL01'
428534 db_name = db .attribute ("DBName" )
429535 if db_name :
@@ -512,30 +618,22 @@ def dump(db, f, **options):
512618 # for pdu triggerings
513619 pdu_triggerings = create_sub_element_fx (channel , "PDU-TRIGGERINGS" )
514620 for pdu in db .frames :
515- pdu_triggering = create_sub_element_fx (
516- pdu_triggerings , "PDU-TRIGGERING" )
517- pdu_triggering .set ("ID" , "PDU_" + pdu .name )
518- pdu_timings = create_sub_element_fx (pdu_triggering , "TIMINGS" )
519- if pdu .cycle_time > 0 :
520- cyclic_timing = create_sub_element_fx (pdu_timings , "CYCLIC-TIMING" )
521- repeating_time_range = create_sub_element_fx (cyclic_timing , "REPEATING-TIME-RANGE" )
522- create_sub_element_fx (repeating_time_range , "VALUE" , "PT" + str (pdu .cycle_time / 1000.0 ) + "S" )
523-
524- pdu_ref = create_sub_element_fx (pdu_triggering , "PDU-REF" )
525- pdu_ref .set ("ID-REF" , "PDU_" + pdu .name )
621+ # Create regular PDU triggering
622+ create_pdu_triggering (pdu_triggerings , pdu )
623+
624+ # Create secured PDU triggering if applicable
625+ if pdu .attribute ("SC_Message" ) and pdu .attribute ("SC_Message" ).lower () == "yes" :
626+ create_pdu_triggering (pdu_triggerings , pdu , prefix = "S" )
627+
526628
527629 frame_triggerings = create_sub_element_fx (channel , "FRAME-TRIGGERINGS" )
528630 for frame in db .frames :
529- frame_triggering = create_sub_element_fx (
530- frame_triggerings , "FRAME-TRIGGERING" )
531- frame_triggering .set ("ID" , "FT_" + frame .name )
532- identifier = create_sub_element_fx (frame_triggering , "IDENTIFIER" )
533- create_sub_element_fx (identifier , "IDENTIFIER-VALUE" , str (frame .arbitration_id .id ))
534- frame_ref = create_sub_element_fx (frame_triggering , "FRAME-REF" )
535- frame_ref .set ("ID-REF" , "FRAME_" + frame .name )
536- if (frame .is_fd ):
537- create_sub_element_fx (frame_triggering , "CAN-FRAME-TX-BEHAVIOR" ,"CAN-FD" )
538- create_sub_element_fx (frame_triggering , "CAN-FRAME-RX-BEHAVIOR" ,"CAN-FD" )
631+ # Create regular frame triggering
632+ create_frame_triggering (frame_triggerings , frame )
633+
634+ # Create secured frame triggering if applicable
635+ if frame .attribute ("SC_Message" ) and frame .attribute ("SC_Message" ).lower () == "yes" :
636+ create_frame_triggering (frame_triggerings , frame , prefix = "S" )
539637
540638 #
541639 # ECUS
@@ -577,22 +675,22 @@ def dump(db, f, **options):
577675 outputs = create_sub_element_fx (connector , "OUTPUTS" )
578676 for frame in db .frames :
579677 if bu .name in frame .transmitters :
580- input_port = create_sub_element_fx (outputs , "OUTPUT-PORT" )
581- frame_triggering_ref = create_sub_element_fx (input_port , "FRAME-TRIGGERING-REF" )
582- frame_triggering_ref .set ("ID-REF" , "FT_" + frame .name )
583- # Reference to PDUs
584- included_pdus = create_sub_element_fx (input_port , "INCLUDED-PDUS" )
585- included_pdu = create_sub_element_fx (included_pdus , "INCLUDED-PDU" )
586- included_pdu .set ('ID' , 'output_included_pdu_' + frame .name )
587- pdu_triggering_ref = create_sub_element_fx (included_pdu , "PDU-TRIGGERING-REF" )
588- pdu_triggering_ref .set ("ID-REF" , "PDU_" + frame .name )
678+ # Create regular output port
679+ create_output_port (outputs , frame )
680+ # Create secured output port if applicable
681+ if frame .attribute ("SC_Message" ) and frame .attribute ("SC_Message" ).lower () == "yes" :
682+ create_output_port (outputs , frame , prefix = "S" )
589683
590684 # ignore CONTROLLERS/CONTROLLER
591685
592686 #
593687 # PDUS
594688 #
595689 pdus = create_sub_element_fx (elements , "PDUS" )
690+ auth_info_tx_length_def = db .frame_defines ["SCP_AuthInfoTxLength" ].defaultValue
691+ freshness_value_tx_length_def = db .frame_defines ["SCP_FreshnessValueTxLength" ].defaultValue
692+ data_id_def = db .frame_defines ["SCP_DataId" ].defaultValue
693+ freshness_value_length_def = db .frame_defines ["SCP_FreshnessValueLength" ].defaultValue
596694 for frame in db .frames :
597695 pdu = create_sub_element_fx (pdus , "PDU" )
598696 pdu .set ("ID" , "PDU_" + frame .name )
@@ -723,23 +821,22 @@ def dump(db, f, **options):
723821 signal_id = create_signal_id (frame , signal )
724822 signal_instance = create_signal_instance (signal_instances , signal , signal_id )
725823 create_signal_ref (signal_instance , signal_id )
824+ if frame .attribute ("SC_Message" ) and frame .attribute ("SC_Message" ).lower () == "yes" :
825+ spdu = create_sub_element_fx (pdus , "PDU" )
826+ spdu .set ("ID" , "SPDU_" + frame .name )
827+ create_short_name_desc (spdu , "SPDU_" + frame .name , frame .comment )
828+ create_secoc_configuration (frame , auth_info_tx_length_def , freshness_value_tx_length_def , data_id_def , freshness_value_length_def , spdu )
726829
727830 # FRAMES
728831 #
729832 frames = create_sub_element_fx (elements , "FRAMES" )
730833 for frame in db .frames :
731- frame_element = create_sub_element_fx (frames , "FRAME" )
732- frame_element .set ("ID" , "FRAME_" + frame .name )
733- create_short_name_desc (frame_element , frame .name , frame .comment )
734- create_sub_element_fx (frame_element , "BYTE-LENGTH" , str (frame .size )) # DLC
735- create_sub_element_fx (frame_element , "PDU-TYPE" , "APPLICATION" )
736- pdu_instances = create_sub_element_fx (frame_element , "PDU-INSTANCES" )
737- pdu_instance = create_sub_element_fx (pdu_instances , "PDU-INSTANCE" )
738- pdu_instance .set ("ID" , "PDUINSTANCE_" + frame .name )
739- pdu_ref = create_sub_element_fx (pdu_instance , "PDU-REF" )
740- pdu_ref .set ("ID-REF" , "PDU_" + frame .name )
741- create_sub_element_fx (pdu_instance , "BIT-POSITION" , "0" )
742- create_sub_element_fx (pdu_instance , "IS-HIGH-LOW-BYTE-ORDER" , "false" )
834+ # Create regular frame
835+ create_frame_element (frames , frame )
836+
837+ # Create secured frame if applicable
838+ if frame .attribute ("SC_Message" ) and frame .attribute ("SC_Message" ).lower () == "yes" :
839+ create_frame_element (frames , frame , prefix = "S" )
743840
744841 #
745842 # FUNCTIONS
0 commit comments