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)