System Definition Examples
Basic Examples
Creating a basic system definition file
A system definition can be created with a target operating system of Windows or Linux_x64.
1 is_local = ip_address == "localhost" or ip_address == "127.0.0.1"
2 target_type = "Windows" if is_local else "Linux_x64"
3 system_definition = SystemDefinition(
4 filename,
5 "This is an example System Definition file created using the System Definition API",
6 "System Definition API",
7 "1.0.0.0",
8 "Controller",
9 target_type,
10 filepath,
11 )
12
13 target = system_definition.root.get_targets().get_target_list()[0]
14 if not is_local:
15 target.ip_address = ip_address
Be sure to save the system definition when you have made all necessary modifications.
1 filepath = system_definition.document_type.document_file_path
2 saved, error = system_definition.save_system_definition_file()
3 if saved:
4 print(f'System Definition saved to "{filepath}"')
5 else:
6 raise FileNotFoundError(f'Unable to save System Definition to "{filepath}": {error}')
Adding User Channels, Calculated Channels, and Aliases
User channels can be added to a target.
1 target.get_user_channels().add_new_user_channel("MyUserChannel", "", "", 1.0)
2 user_channel = target.get_user_channels().get_user_channel_list()[1]
3
Calculated channels can likewise be added to a target.
1 lpf_calculated_channel = LowpassFilter("MyLowpassFilterChannel", "", user_channel, 50, 1)
2 target.get_calculated_channels().add_calculated_channel(lpf_calculated_channel)
3
Aliases get added to the system definition root instead of the target.
1 alias = Alias("MyUserChannelAlias", "", user_channel)
2 alias_folder = AliasFolder("MyAliasFolder", "")
3 system_definition.root.get_aliases().add_alias_folder(alias_folder)
4 system_definition.root.get_aliases().get_alias_folder_list()[0].add_alias(alias)
5
Adding Alarms and Procedures
Procedures are added to a target.
1 procedure = Procedure("MyProcedure", "")
2 procedure.add_new_dwell("Dwell Step", "Dwell for 3 seconds.", 3)
3 procedure.add_new_set_variable(
4 "Counting Step", "", user_channel, SetVariableStepFunction.ADD, user_channel, 1
5 )
6 target.get_procedures().add_procedure(procedure)
7
Alarms are also added to a target.
1 target.get_alarms().add_new_alarm(
2 "MyAlarm",
3 "",
4 user_channel,
5 2,
6 1,
7 procedure,
8 AlarmMode.NORMAL,
9 AlarmState.ENABLED,
10 AlarmPriority.LOW,
11 0,
12 "",
13 )
14
Adding Models
Models are added to a target.
1 target = system_definition.root.get_targets().get_target_list()[0]
2 simulation_models = target.get_simulation_models()
3
4 random_model = Model("RandomFMU", "", get_asset("RandomFMU.fmu"), 0, 1, 0, True, True, True)
5 simulation_models.get_models().add_model(random_model)
6
More Detailed Examples
DAQ
There are many options available when adding DAQ devices.
1 daq_device = DAQDevice(
2 "Dev1",
3 "This is a DAQ Device created using the System Definition Offline API.",
4 DAQDeviceInputConfiguration.DEFAULT,
5 )
6 target = system_definition.root.get_targets().get_target_list()[0]
7 chassis = target.get_hardware().get_chassis_list()[0]
8 chassis.get_daq().add_device(daq_device)
9
10 # Analog Input Channels
11 analog_inputs = daq_device.create_analog_inputs()
12 analog_inputs.add_analog_input(
13 DAQAnalogInput("AI0", 1, DAQMeasurementType.ANALOG_INPUT_TEMPERATURE_THERMOCOUPLE)
14 )
15 analog_inputs.add_analog_input(
16 DAQAnalogInput("AI1", 0, DAQMeasurementType.ANALOG_INPUT_VOLTAGE)
17 )
18
19 # Analog Output Channels
20 analog_outputs = daq_device.create_analog_outputs()
21 analog_outputs.add_analog_output(
22 DAQAnalogOutput("AO0", 0, DAQMeasurementType.ANALOG_OUTPUT_VOLTAGE)
23 )
24
25 # Digital Input Channels
26 digital_inputs = daq_device.create_digital_inputs()
27 daq_input_port = DAQDIOPort(0, False)
28 digital_inputs.add_dio_port(daq_input_port)
29 daq_input_port.add_digital_input(DAQDigitalInput("DI0", False, 0, 0))
30 daq_input_port.add_digital_input(DAQDigitalInput("DI1", False, 1, 0))
31
32 # Digital Output Channels
33 digital_outputs = daq_device.create_digital_outputs()
34 daq_output_port = DAQDIOPort(1, False)
35 digital_outputs.add_dio_port(daq_output_port)
36 daq_output_port.add_digital_output(DAQDigitalOutput("DO4", False, 4, 1))
37
38 # Counter Channels
39 counters = daq_device.create_counters()
40 counters.add_counter(
41 DAQFrequencyMeasurement("FreqIn", "", 0, 0.0, 1.0, 0.0, DAQCounterEdge.FALLING)
42 )
43 counters.add_counter_output(DAQPulseGeneration("PWMOut", "", 1))
44
45 # Internal Channels
46 internal_channels = daq_device.create_internal_channels()
47 internal_channels.add_internal_channel(DAQInternalChannel("Channel 0", 0.0))
48
49 # Waveform Tasks
50 daq_device_waveform = DAQDevice("Dev2", "", DAQDeviceInputConfiguration.DEFAULT)
51 chassis.get_daq().add_device(daq_device_waveform)
52 daq_tasks = chassis.get_daq().get_tasks()
53 waveform_task = DAQTaskAI("Task1", 1000, AcquisitionMode.CONTINUOUS)
54 waveform_task.get_triggers().start_trigger = DAQTriggerDigitalEdge(
55 "PFI0", DirectionType.FALLING
56 )
57 daq_tasks.add_task(waveform_task)
58 analog_waveform_input = DAQWaveformAnalogInput(
59 "AI2", 0, DAQMeasurementType.ANALOG_INPUT_CURRENT
60 )
61 waveform_analog_inputs = daq_device_waveform.create_analog_inputs()
62 waveform_analog_inputs.sample_mode = SampleMode.WAVEFORM
63 waveform_analog_inputs.add_waveform_analog_input(analog_waveform_input)
64 waveform_analog_inputs.waveform_analog_input_task = waveform_task
65
66 # Polynomial Scale
67 coefficients = [1.0]
68 reverse_coefficients = []
69 scale = PolynomialScale("MyScale", coefficients, reverse_coefficients, "")
70 system_definition.root.get_scales().add_scale(scale)
71 daq_device.get_analog_input_section().get_analog_input_list()[0].scale = scale
CAN
An NI-XNET CAN interface can be added.
1 target = system_definition.root.get_targets().get_target_list()[0]
2 chassis = target.get_hardware().get_chassis_list()[0]
3 chassis.get_xnet().enable_xnet() # enable XNET if we haven't already
4
5 target.get_user_channels().add_new_user_channel("MyXnetUserChannel", "", "", 1.0)
6 user_channel = target.get_user_channels().get_user_channel_list()[0]
7
8 # CAN Database
9 can = chassis.get_xnet().get_can()
10 can_database = Database("NIXNET_example")
11 target.get_xnet_databases().add_database(can_database)
12
13 # CAN Cluster
14 can_cluster = "CAN_Cluster"
15 can_port = CANPort("CAN 1", 1, can_database, can_cluster, 125000)
16 can_port.termination = XNETTermination.ON
17 can.add_can_port(can_port)
18
19 # Frame Variables
20 cyclic_frame = "CANCyclicFrame1"
21 cyclic_frame_signals = ["CANCyclicSignal1", "CANCyclicSignal2"]
22 event_frame = "CANEventFrame1"
23 event_frame_signals = ["CANEventSignal1", "CANEventSignal2"]
24
25 # CAN Incoming Frames
26 incoming_cyclic_frame = SignalBasedFrame(
27 cyclic_frame, 64, can_database, can_cluster, 8, 0.1, False, cyclic_frame_signals
28 )
29 can_port.get_incoming().get_single_point().add_signal_based_frame(incoming_cyclic_frame)
30 for signal in cyclic_frame_signals:
31 incoming_cyclic_frame.create_signal_based_signal(signal, "", "volts", 0.0)
32
33 incoming_event_frame = SignalBasedFrame(
34 event_frame, 66, can_database, can_cluster, 8, 0.1, False, event_frame_signals
35 )
36 can_port.get_incoming().get_single_point().add_signal_based_frame(incoming_event_frame)
37 for signal in event_frame_signals:
38 incoming_event_frame.create_signal_based_signal(signal, "", "volts", 0.0)
39
40 incoming_cyclic_frame.create_frame_information()
41
42 incoming_data_logging = DataLoggingFile(
43 "log", "file", os.path.dirname(system_definition.document_type.document_file_path)
44 )
45 incoming_data_logging.data_logging_file_type = FileType.TDMS
46 can_port.get_incoming().get_raw_frame_data_logging().add_data_logging_file(
47 incoming_data_logging
48 )
49 can_port.get_incoming().get_raw_frame_data_logging().get_data_logging_file_list()[
50 0
51 ].trigger_channel = user_channel
52
53 # CAN Outgoing Frames
54 outgoing_cyclic_frame = SignalBasedFrame(
55 cyclic_frame, 64, can_database, can_cluster, 8, 0.1, False, cyclic_frame_signals
56 )
57 can_port.get_outgoing().get_cyclic().add_signal_based_frame(outgoing_cyclic_frame)
58 for signal in cyclic_frame_signals:
59 outgoing_cyclic_frame.create_signal_based_signal(signal, "", "volts", 0.0)
60
61 outgoing_event_frame = SignalBasedFrame(
62 event_frame, 64, can_database, can_cluster, 8, 0.1, False, event_frame_signals
63 )
64 can_port.get_outgoing().get_event_triggered().add_signal_based_frame(outgoing_event_frame)
65 for signal in event_frame_signals:
66 outgoing_event_frame.create_signal_based_signal(signal, "", "volts", 0.0)
67
68 outgoing_cyclic_frame.create_frame_faulting(True, True)
69 outgoing_cyclic_frame.get_frame_faulting().get_skip_cyclic_frames().trigger_channel = (
70 user_channel
71 )
72 outgoing_cyclic_frame.get_frame_faulting().get_transmit_time().set_trigger_channel(user_channel)
73
74 outgoing_data_replay = DataFileReplay("replay", get_asset("fake.tdms"))
75 can_port.get_outgoing().get_data_replay().add_data_file_replay(outgoing_data_replay)
76 can_port.get_outgoing().get_data_replay().get_data_file_replay_list()[
77 0
78 ].trigger_channel = user_channel
LIN
An NI-XNET LIN interface can be added.
1 target = system_definition.root.get_targets().get_target_list()[0]
2 chassis = target.get_hardware().get_chassis_list()[0]
3 chassis.get_xnet().enable_xnet() # enable XNET if we haven't already
4
5 # LIN Database
6 lin = chassis.get_xnet().get_lin()
7 lin_database = Database("NIXNET_exampleLDF")
8 target.get_xnet_databases().add_database(lin_database)
9
10 # LIN Cluster
11 lin_cluster = "Cluster"
12 lin_port = LINPort("LIN 1", 1, lin_database, lin_cluster, 125000, "SlowSchedule")
13 lin.add_lin_port(lin_port)
14
15 # LIN Incoming Frame
16 incoming_signals = ["SlaveSignal3_U8", "SlaveSignal4_U8"]
17 incoming_frame = SignalBasedFrame(
18 "Slave1Frame2", 5, lin_database, lin_cluster, 8, 0.1, False, incoming_signals
19 )
20 lin_port.get_incoming().get_single_point().add_signal_based_frame(incoming_frame)
21 for signal in incoming_signals:
22 incoming_frame.create_signal_based_signal(signal, "", "volts", 0.0)
23
24 # LIN Outgoing Frame
25 outgoing_signals = ["MasterSignal3_U8", "MasterSignal4_U8"]
26 outgoing_frame = SignalBasedFrame(
27 "MasterFrame2", 3, lin_database, lin_cluster, 8, 0.1, False, outgoing_signals
28 )
29 lin_port.get_outgoing().get_unconditional().add_signal_based_frame(outgoing_frame)
30 for signal in outgoing_signals:
31 outgoing_frame.create_signal_based_signal(signal, "", "volts", 0.0)