Skip to content

Commit df7453e

Browse files
author
sbenhmouda
committed
Handle SecOc configuration in fibex
1 parent 95fa32c commit df7453e

1 file changed

Lines changed: 140 additions & 43 deletions

File tree

src/canmatrix/formats/fibex.py

Lines changed: 140 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,13 @@
4545
logger = logging.getLogger(__name__)
4646

4747
fx = "http://www.asam.net/xml/fbx"
48+
te = "http://www.technica-engineering.com/xml/fbx"
4849
ho = "http://www.asam.net/xml"
4950
can = "http://www.asam.net/xml/fbx/can"
5051
xsi = "http://www.w3.org/2001/XMLSchema-instance"
5152
ns_ho = "{%s}" % ho
5253
ns_fx = "{%s}" % fx
54+
ns_te = "{%s}" % te
5355
ns_can = "{%s}" % can
5456
ns_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

7887
def 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+
136242
def get_base_data_type(signal):
137243
# type: (Signal) -> str
138244
if signal.is_float:
@@ -423,7 +529,7 @@ def load(f, **_options):
423529

424530
def 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

Comments
 (0)