Skip to main content

Examples and Best Practices for the CODESYS Trace Scripting API

CODESYS Scripting from CODESYS Trace

The following examples are intended as a supplement to the automatically generated API documentation from CODESYS Scripting to CODESYS Trace.

Creating a Trace

You can use the CODESYS Trace Scripting API to create a new Trace.

myApplication = projects.primary.find("Device", "PLC Logic", "Application")[0]
traceObject = trace.create(myApplication, "MyTraceName")

A task named Task must already exist here. If it does not exist, then this assignment throws a ValueError.

traceObject.task_name = "Task" 

In the script, you can specify in which task the newly created trace should be executed.

myApplication = projects.primary.find("Device", "PLC Logic", "Application")[0]
traceObjectWithTaskSet = trace.create(myApplication, "NameOfMySecondTrace", "MainTask")
assert traceObjectWithTaskSet.task_name == "MainTask"

Finding and Verifying an Existing Trace

To find an existing trace, you can use the project.find method.

For all other objects of the IScriptObject type, .is_trace_object equals FALSE.

foundObjects = projects.primary.find("Device", "PLC Logic", "Application", "MyTraceObject")
expectedTraceObject = foundObjects[0]
assert expectedTraceObject.is_trace_object, "Could not find trace object with the expected name"

Adding and Modifying Trace Variables

The add_variable() method is a simple method to add a new ScriptTraceVariable and set its properties during creation.

myTrace = projects.primary.find("Device", "PLC Logic", "Application", "MyTraceObject")[0]

addedVariable = myTrace.add_trace_variable(variableName="PLC_PRG.a1",
        graphColor= 0xff000000,
        graphType=GraphType.LINES,
        activateMaxWarning=True,
        maxWarningArea=9.0,
        maxColor= 0xffff0000)
addedVariable.enabled = False

for i in range(2,11):
        newVariable = myTrace.variable_list.add()
        newVariable.variable_name = "PLC_PRG.a"+str(i)
        newVariable.graph_type = GraphType.LINES_CROSSES

assert len(myTrace.variable_list) == 10

Modifying the ScriptTrace Variable List

Removing a specific ScriptTrace variable

In the following code snippet, a variable with the specified name is first found and then removed from the ScriptTraceVariableList.

def remove_variable_by_name(traceObject, variableName):
        index_to_remove = -1
        for variable in traceObject.variable_list:
                if variable.variable_name == variableName:
                        index_to_remove = traceObject.variable_list.index_of(variable)
                        break
        if index_to_remove != -1:
        traceObject.variable_list.remove(index_to_remove)    

Modifying the Recording Settings

Setting the resolution (ms/µs) of the trace recording

The following code snippet is based on the "Creating a Trace" snippet.

traceObject.resolution = Resolution.MicroSeconds

Use Resolution.MilliSeconds if you want recording based on milliseconds.

Setting the recording condition

The following code snippet is based on the "Creating a Trace" snippet.

traceObject.record_condition = "PLC_PRG.bDoRecord"

Setting a comment

The following code snippet is based on the "Creating a Trace" snippet.

traceObject.comment = "This trace records the ..."

Setting the AutoStart option

The following code snippet is based on the "Creating a Trace" snippet.

traceObject.auto_start = True

Setting the option to record only in every n-th cycle

The following code snippet is based on the "Creating a Trace" snippet.

traceObject.every_n_cycles = 10

Diagrams and Their Variables

Creating one ScriptTrace diagram with all ScriptTrace variables

The following script is an example for creating a simple diagram where all variables are used.

First, a ScriptTrace object and some ScriptTrace variables are created.

traceObject = projects.primary.find("Device","PLC Logic","Application","Trace")[0]
assert traceObject.is_trace_object
for i in range(5):
        traceObject.add_trace_variable(variableName="PLC_PRG.a"+str(i))

Next, a ScriptTrace diagram is created and then all ScriptTrace variables are added.

traceDiagram = traceObject.diagrams.add()
for traceVar in traceObject.variable_list:
    traceDiagram.add_diagram_variable(traceVar)

Creating one ScriptTrace diagram per ScriptTrace variable

The following Python method takes one ScriptTrace object and adds a diagram per ScriptTrace variable.

def one_diagram_per_variable(traceObject):
    assert traceObject.is_trace_object
    for traceVar in traceObject.variable_list:
        diagram = traceObject.diagrams.add(traceVar)
        diagram.name = traceVar.variable_name

Copying the Settings of a ScriptTrace Diagram

The following script shows how to modify and copy the settings of a ScriptTrace diagram.

traceObject = projects.primary.find("Device","PLC Logic","Application","Trace")[0]
assert traceObject.is_trace_object

# apply settings for the first diagram
traceObject.diagrams[0].y_axis.mode = AxisScaleMode.FixedLength
traceObject.diagrams[0].y_axis.range = 10.0
traceObject.diagrams[0].y_axis.color = 0xffee0000
traceObject.diagrams[0].y_axis.draw_grid = True
traceObject.diagrams[0].y_axis.grid_color = 0xffee0000
traceObject.diagrams[0].tickmark_fixed_spacing = True
traceObject.diagrams[0].tickmark_fixed_distance = 5.0
traceObject.diagrams[0].tickmark_fixed_subdivisions = 4

# copy the settings from the first diagrams to all other diagrams
for i in range(1,len(traceObject.diagrams))
    traceObject.diagrams[i].y_axis.copy_from(traceObject.diagrams[0])

Online Handling of Trace

Downloading and starting Trace

The following code snippet finds the Trace trace of the Application application, downloads it, and starts it.

proj = projects.open(r"<Path to the project file>")
app = proj.find("Device", "PLC Logic", "Application")[0]
with online.create_online_application(app) as onlineapp:
    traceObject = proj.find("Device", "PLC Logic", "Application", "Trace")[0]
    onlineapp.login(OnlineChangeOption.Never, True)
    onlineapp.start()
    editor = traceObject.open_editor()
    editor.download()
    editor.start()

Saving the trace to a file

The following code snippet is based on the "Downloading and starting Trace" snippet.

A trace must be stopped before it can be saved. This can be done either by reaching the trigger condition or by an explicit call of stop().

It is assumed that a trace is already running.

editor.stop()
editor.save(r"<File path to csv file>")

Querying various information about the trace recording

The following code snippet is based on the "Downloading and starting Trace" snippet.

It is assumed that a trace is already running.

print("Packet State: {}".format(editor.get_packet_state()))
print("Trace started at {} (absolute timestamp)".format(editor.get_trace_start_timetamp()))

Trigger Handling

Configuring a Boolean trigger

traceObject = proj.find("Device", "PLC Logic", "Application", "Trace")[0]
traceObject.trigger_variable = "PLC_PRG.bVar"
traceObject.trigger_edge = TriggerEdge.Positive
traceObject.post_trigger_samples = 20

The trigger level is required only for numeric trigger variables. However, it is good coding style to explicitly set the trigger to None.

traceObject.trigger_level = None

Configuring a numeric trigger

traceObject = proj.find("Device", "PLC Logic", "Application", "Trace")[0]
traceObject.trigger_variable = "PLC_PRG.iTemperature"
traceObject.trigger_edge = TriggerEdge.Positive
traceObject.post_trigger_samples = 20

If the trigger variable is of type REAL or LREAL, then the trigger level can also be specified as a floating-point number (for example, 80.5).

traceObject.trigger_level = 80

Waiting for the trigger and saving recorded data

The following code snippet is based on the "Downloading and starting Trace" snippet and "Configuring a * trigger".

triggerstate = editor.get_trigger_state()
while triggerstate != TriggerState.TriggerReached:
        system.delay(200)
        triggerstate = editor.get_trigger_state()

editor.save(r"<File path to csv file>")

Querying timestamp information after reaching the trigger

The following code snippet is based on the "Downloading and starting Trace" snippet and "Configuring a * trigger".

print("Trigger reached at {} (absolute timestamp)".format(editor.get_trigger_timetamp()))
print("Trigger reached at {}".format(editor.get_trigger_startdate()))
print("Trace was running {}ms until trigger has been reached".format(editor.get_trigger_timetamp() - editor.get_trace_start_timetamp()))

Resuming trace recording after reaching the trigger

The following code snippet is based on the "Downloading and starting Trace" snippet and "Configuring a * trigger".

editor.reset_trigger()

Device Trace

Creating a DeviceTrace

myDevice = projects.primary.find("Device")[0]
devicetrace = trace.create(myDevice, "DeviceTrace")

Querying the current trace recordings on the device

The following code snippet is based on the "Creating a DeviceTrace" snippet.

traceObject = projects.primary.find("Device", "DeviceTrace")[0]

For application traces, the result of get_online_traces contains only traces of the application.

# traceObject = projects.primary.find("Device", "PLC Logic", "Application", "Trace")[0]
editor = traceObject.open_editor()
for tracepacket in editor.get_online_traces():
    print(tracepacket)

Uploading an existing trace as DeviceTrace

The following code snippet is based on the "Creating a DeviceTrace" snippet.

traceObject = projects.primary.find("Device", "DeviceTrace")[0]
editor = traceObject.open_editor()
editor.upload_to_device_trace("CpuCoreLoad")