• Skip to main content
  • Skip to header right navigation
  • Skip to site footer
CDP Studio logo

CDP Studio

The no-code and full-code software development tool for distributed control systems and HMI

  • Why CDP
    • Software developers
    • Automation engineers
    • Managers
  • Product
    • Design UI
    • Develop
    • Analyze and test
    • Deploy
    • Framework and toolbox
    • Compatibility
  • Services
  • Use cases
  • Pricing
  • Try CDP

CDP Studio Documentation

  • Tools
  • Configurator

Configurator

The CDP configurator command-line tool allows to automate configuration and testing of CDP applications. The Configurator has two alternate ways for providing command sequences. The first option is through a YAML file and the second option is through a command-line interface.

Motivation And Use Cases

Though CDP Studio is a powerful tool to visually construct and setup any automation or control system with several features to ease reusing existing configuration structures and validating behaviors, it not well suited for programmatic use when generating project structures, testing or integrating to CI pipeline is involved.

Configurator tool is intended to be used for programmatic generation of projects, testing, validation and other CI pipline integrations or custom built tools. It can add new nodes, remove nodes, move nodes, set and get or test values using mathematical expressions and also verify events generated by nodes.

  • Set up automated tests for your system and run them in your CI tool
  • Set up automated tests for your library and run them in your CI tool
  • Set up a new system using a script instead of manually adding resources in CDP Studio Configure mode
  • Create graphical tools that guide users in configuration and adding whole subsystems to projects
  • Set up as part of External tools in CDP Studio to automate tedious tasks

Locating Configurator Tool In Toolkits

The Configurator tool is provided as part of each installed CDP Studio toolkit See Toolkits location in your system for more information.

The host Configurator tool resides in above mentioned toolkits folder.

/<toolkit name>/CDP-X.x/bin

Configurator Tool Options

Supported configurator tool options are listed in the table below.

OptionDescription
-mPath(s) separated by : to models folder for configuration (may be metamodels when parsing a library) NB! If folder is named "Recipes" it is treated as recipes folder
-aPath to application folder with Application.xml to load application configuration
-cip:port of running StudioAPI server used in place of -a for connecting to running system
-uOptional username for connectiong to StudioAPI server
-pOptional password for connecting to StudioAPI server
-gGenerate Nodes XML configuration snipplet based on the passed in list: "<add_to_model>,<add_model>,<node_name>"
-yPath to YAML file to be parsed for configure, test, verify tag(s) (optional)
-tWith this option the test, verify tags are used from YAML file instead of configure tag (test tag when -c is provided and verify tag when -a is provided)
-lPath to library folder with Models, option inplace of -a
-rPath to library folder with Recipes
-dcDump entire configuration tree to CSV file
-dmDump entire model tree to CSV file
-uriBase uri for relative uri(s) in YAML file. Relative uri(s) start with '.' symbol
-tchTouch provided model files to cause any tools monitoring them to reload and reparse
-cliUse command line interface of configurator (use instead of -y and -t options)

For better understanding, next are some examples of invoking the configurator tool with arguments.

To configure app in path -a <path> with YAML file from -y <file> via its configure section:

configurator -m <path> -a <path> -y <file>

To verify configuration of application in path -a <path> with YAML file from -y <file> via its verify section:

configurator -m <path> -a <path> -y <file> -t

To parse library in path -l <path> with models in paths -m <path> (model path list should include metamodels located in toolkits/<toolkit name>/CDP-X.x/templates/metamodels as first path):

configurator -m <path> -l <path>

To test app running at -c <ip:port> with yaml file from -y <file> via its test section:

configurator -m <path> -c <ip:port> -y <file> -t [-u <user>] [-p <pass>]

To generate XML sniplet of model instantiation in a parent model with given node name:

configurator -m <path> -g "<add_to_model>,<add_model>,<node_name>"

Configurator Tool YAML Syntax

The YAML syntax supports three different functions defined under the three toplevel tags: configure, test, verify.

  • configure allows directly configuring an application configuration files
  • test allows testing/asserting a running system
  • verify allows asserting directly on application configuration files to verify some expected state

Configure Tag

The supported tag structure in configure tag is the following:

  • configure as toplevel tag contains a list of dictionaries with possible keys uri: full node path, add: list of child dictionaries. (the uri key supports also relative paths starting with '.' symbol if a base uri was passed in with -uri argument)
  • remove : list of dictionaries with name tags to remove
  • move : list of dictionaries with old name tag and new uri or offset tags to "move to" or "move by relative to current location"
  • values : dictionary of values for uri
  • children : list of recursive dictionaries with required name and add, move, remove, values, children. Tags add and children can recurse multiple levels

Example:

configure:
- uri: App
  add:
    - name: MyComponent
      model: MyComponentModel
      values:
        Debug: 5
        SomeTrueBool: 1
      children:
        - name: Priority
          values:
            Value: high
      add:
        - name: MyTest
          model: MyComponentModel
      remove:
        - name: ComponentoNonGrata
      move:
        - name: MyOldSignalName
          uri: App.MyComponent.MyNewSignalName
        - name: MyOldSignalName2
          offset: -1
- uri: App.MyOtherComponent
  values:
    Debug: 1

Test Tag

This is intended to allow running simple tests on CDP Applications. The test top-level tag allows to define named sequential test cases with setup, test, and assert sections that are applied to the running CDP Application through StudioAPI server.

Failure to find defined uri's or failure to assert conditions will all be considered as test failures in a given test case. The test will also produce a TestResults.xml in JUnit format for CI tools to parse.

The supported tag structure in test tag is the following:

  • test as toplevel tag contains a list of dictionaries with possible keys case: test case name, setup: test setup assignments, test: test assignments, assert: assert statements with only case as the required tag.
  • setup : list of dictionaries with uri as the required key and values and children are optional
  • test : list of dictionaries with uri as the required key and values, children, delay_ms and wait_ms are optional
  • assert : list of dictionaries with uri as the required key and values, evaluate, children, event, delay_ms and wait_ms are optional. event can have optional dictionaries like code, status and values to match a event

The steps are always executed in the same order regardless of definition order: setup, test and assert. The only behavioural difference is with assert which does not assign its values but asserts them by comparing its value to the one provided by the StudioAPI server.

In addition to comparing values with constants, the 'evaluate' expression can be used to test any number of values of the uri using a mathematical expression. The 'evaluate' tester supports the same set of mathematical operators and functions as are described in the Evaluate operator documentation. The 'evaluate' accepts both single expression string or a list of expression strings. All expressions must return true as a result of the evaluation (or non-zero) for the test to be processed without error.

Also, assert can have a additional keyword event that can be used assert a event was generated by the node that match the parameters under the keyword.

The asserts are considered handled as soon as the value gets the asserted value with a default timeout of 5000 milliseconds. It is possible to set shorter timeout values with wait_ms key. This will only apply to values on the same level and is not be waited fully when the asserts are fulfilled before timeout. It is also possible to set a delay into the test sequence by adding delay_ms key. This will only apply to values on the same level and is always fully applied.

There are optional additional top-level tags application_name and test_name when using the test top-level object.

Example:

test_name: ConfiguratorTesting
application_name: &app_name ConfiguratorTest

test:
- case: WhenSignalIsSet_RoutedSignalsGetValue
  setup:
    - uri: ConfiguratorTest
      values:
        OutS: 5
        InS: 5
  test:
    - uri: ConfiguratorTest
      delay_ms: 500
      values:
        OutS: 10
  assert:
    - uri: ConfiguratorTest
      wait_ms: 50
      values:
        InS: 10
      evaluate:
        - 'rint(InS * 1000) / 1000 == 5'
        - 'OutS > InS'
      children:
        - name: OutS
          values:
            Value: 10
        - name: Moooos
          values:
            Value: 5

Example for event testing:

test_name: AlarmTesting
application_name: &app_name AlarmTest

test:
  - case: WhenAlarmIsSet_AlarmEventIsTriggered
    setup:
      - uri: '%{AppName}.TestAlarm'
        values:
          CM_ALARMSET: 1
    assert:
      - uri: '%{AppName}.TestAlarm'
        event:
          code: { AlarmSet: 1, AlarmClr: 0, AlarmAck: 0, Reprise: 0 }
          status: { NotifySet: 0, WarningSet: 1, ErrorSet: 0, WarningUnacked: 1 }
          values:
            Level: WARNING
            Text: 'Test Alarm'

Verify Tag

This is intended to be used to verify post-run configuration state by verifying that uri's that must exist are present and stored values in the configuration are as expected.

The top-level verify object contains a list of dictionaries with the same syntax as the top-level test object. That said only the assert steps are reasonable in post-run verification.

Configurator Tool CLI Syntax

The command-line interface is started with -cli option instead of using -y and -t options. This makes it possible to issue configuration commands manually or use the CLI interface from a script to manipulate or check the configuration. This allows building CI related test scripts but also generator tools to generate control systems from given parameters, options, etc.

The -cli option also accepts -uri option when provided for initial location after startup. The prompt of the CLI consists of the current location uri followed by a '#' character.

CommandAliasUsageDescription
uri <uri>cduri MyApp.MyCompSet new location. Command also accepts relative uris starting with at least one '.' charecter denoting current location (except at System level)
add <model> <name>add CDPSignal<double> MySignalAdd new node to current location based on provided model and name
get <name>get MySignalGet the value of named node in current location. The value is returned as standard output before next prompt
set <name> <value>set MySignal 6.0Set the value of named node in current location
remove <name>rmremove MySignalRemove the named node from current location
move <name> <uri>mvmove MySignal MyApp.MyMovedSignalMove or rename the named node to path given by uri
list [basemodel]lslist CDPAlarmList all the child nodes that are at the current level at the current location. If [basemodel] is specified, only results where [basemodel] is found in the model or base model name will be outputted. For example, list CDPAlarm will list all CDPAlarm based objects, but also objects containing CDPAlarm in the model or basemodel name, such as MyLib.MyCDPAlarm and SomeLib.CDPAlarmExtended.
find [-b basemodel] [-n name]findfind -b CDPAlarm -n FaultFind all the child nodes and children, starting at the current location, that partially matches the basemodel filter and/or the shortname filter. The usage above will find all CDPAlarm based objects in the current (sub)tree that has the name "Fault".

The basemodel matching as shown above will find all objects containing CDPAlarm in model or basemodel, such as MyLib.MyCDPAlarm and SomeLib.CDPAlarmExtended.

quitexitquitQuit the configurator tool running the command line interface
helpli helpPrint CLI help

Example CLI session after starting the configurator tool:

$ configurator -m ./Models -a . -cli
Configurator started...
Looking for models from ./Models
Parsed application from .

# uri ConfiguratorCLI
ConfiguratorCLI# get fs
10
ConfiguratorCLI# add CDPSignal<double> MySignal
OK
ConfiguratorCLI# set MySignal 10
ConfiguratorCLI# get MySignal
10
ConfiguratorCLI# exit
Configurator closed...

Python Example CLI Usage

It is quite simple to use the command-line interface in a scripting environment. This example shows how to use Python 'pexpect' module to write a script that uses the CLI. This example assumes that you are familiar with python. The 'pexpect' module is used because it simplifies these kinds of command-line interface scripts.

import sys
import os
import pexpect

def command(cli_in, execute):
    cli_in.sendline(execute)
    cli_in.expect("# ")

def get_value(cli_data):
    return cli_data.split("\r\n")[1]

With these helper functions you can access all the configurator commands. The cli.before can be also used to detect command errors as then it would contain an error message starting with "Error:". Checking this would allow the script to also report errors. The 'pexpect' based example works on Linux, but on Windows, 'wexpect' can be used in a similar fashion.

Example using the above functionality and 'pexpect' on Linux:

cli = pexpect.spawn("./configurator -m ./Models -a . -cli")
cli.delaybeforesend = None  # disable the pexpect 50 ms default delay before send
cli.expect("# ")

command(cli, "uri ConfiguratorCLI")
command(cli, "set fs 20")
command(cli, "get fs")
fs = get_value(cli.before)
command(cli, "add CDPComponent TestC")
command(cli, "uri .TestC")
command(cli, "add CDPSignal<double> S1")

Configurator Python API

The cdpconfigurator.py class is an Operating System independent (Windows&Linux) API to simplify accessing the configurator executable from a Python version 3.x script.

With this python class, you can easily add and remove objects in an Application, set or get values, list contents, find objects, etc. When you combine this approach together with CDP Studio Recipes, it becomes a very powerful tool that enables you to, for instance, generate complete systems from sources such as an Excel file or a database.

Note: For supported CDP versions, the cdpconfigurator.py is located in the CDP Studio installation folder under toolkits/<toolkit>/CDP<version>/bin.

Requirements: In addition to 'os' and 'sys.platform':

  • Linux: pexpect
  • Windows: wexpect

Below are some python Configurator API usage examples:

Initialize the Configurator Object and Set Location to the First Object (Application)

import sys
import os

toolkit_path = "/home/user/CDPStudio/toolkits/linux_x86_64_13/CDP-4.10"
sys.path.append(os.path.join(toolkit_path, "bin"))
from cdpconfigurator import CDPConfigurator

app_path = "/home/user/CDPStudioWorkspace/systems/CabinSystem/CabinApp/Application"
commandline_options = "-a " + app_path
model_paths = (CDPConfigurator.get_default_models_and_recipes_path(toolkit_path)
              + ":../libraries/CustomModelsLib/Templates/Models"
              + ":../libraries/AnotherModelLib/Templates/Models")

app = CDPConfigurator(toolkit_path, commandline_options, model_paths)
app_tree = app.ls()
app_component = app_tree[0][0]

app.cd(app_component)
print("Location: " + app_component + " of type "+app_tree[0][1])

List All Alarms in the Application, along with Their 'Description' Attributes

items = app.find("Alarm")
for item in items:
    try:
      app.cd(item[0])
    except Exception as e:
      print("Could not cd() into '" + item[0] + "', error : " + str(e))
    try:
      desc = app.get_value("Description")
    except Exception as e:
      print("Could not find " + item[0] + ".Description")
    print("Alarm: " + item[0], " Description=" + desc)

Add a Component of a given Model Name, and Change Location to the Newly Added Object:

try:
  app.add("CustomComp", "CustomModelsLib.CustomComponent")
  app.cd(".CustomComp")
except Exception as e:
  raise SystemExit("Failed adding and going into CustomComp: " + str(e))

Add a Signal to the Current Location and Set Its 'Description' Property

try:
  app.add("IsRunning", "CDPSignal<int>")
  app.cd(".IsRunning")
  app.set_value("Description","The motor is running.")
except Exception as e:
  raise SystemExit("Error adding IsRunning/Description: " + str(e))

Move One Level up the Tree:

try:
  app.cd("..")
except Exception:
  print("Failed walking up one level in the tree.")

Move/Rename a Signal

app.move("Running", ".IsRunning")

Verify That an Object Named 'ControlPosition' Is Found at the Current Location

items = app.ls()
for item in items:
    if item[0] == "ControlPosition":
        print("Found ControlPosition that has model " + item[1])

Set 'ControlPosition' Value to '4' and Verify It Was Set

try:
  app.cd(".ControlPosition")
  app.set_value("Value", "4")
except Exception as e:
    result = str(e)
    raise SystemExit("Setting ControlPosition.Value to 4 failed: " + result)

try:
  value = app.get_value("Value")
except Exception:
  print("Failed to get Value!")

print("Value is " + value)
if (int(value, 10) != 4):
    raise SystemExit("Could not get correct ControlPosition Value!")

Remove 'ControlPosition' Object At Current Location

app.remove("ControlPosition")

Duplicate the Component 'Motor' and Change It into a Recipe Named 'ACInductionMotor'

app.transform_component_to_recipe(
    app_path, "Motor",
    os.path.join(app_path, "Recipes"), "ACInductionMotor")

See the cdpconfigurator.py class API for further description and help.

The content of this document is confidential information not to be published without the consent of CDP Technologies AS.

CDP Technologies AS, www.cdpstudio.com

Get started with CDP Studio today

Let us help you take your great ideas and turn them into the products your customer will love.

Try CDP Studio for free
Why CDP Studio?

CDP Technologies AS
Hundsværgata 8,
P.O. Box 144
6001 Ålesund, Norway

Tel: +47 990 80 900
E-mail: info@cdptech.com

Company

About CDP

Contact us

Services

Partners

Blog

Developers

Get started

User manuals

Support

Document download

Release notes

Follow CDP

  • LinkedIn
  • YouTube
  • GitHub

    © Copyright 2022 CDP Technologies. Privacy and cookie policy.

    Return to top