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

CDP Studio

Software development tool for distributed control systems

  • 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

  • Examples and Tutorials
  • User Defined Structure Example A

Expose Custom Data in Automation System User Defined Structure Example B

User Defined Structure Example A

Example A

Select UserComponentA under UserDefinedStructureLib

In Resource tree, CDPModel should have appeared. Right-click AggregateModel and select Add option in the context menu

Scroll down to Element-section and find the Element just added (AggregatedModel)

In the AcceptsModel column, enter the model-name which shall be accepted ('UserDefinedStructureLib.UserNodeA')

Change the Element name from AggregatedModel to UserNodeA

Note: Build your library: Right-click UserDefinedStructureLib and select Build.

Select UserComponentA under UserDefinedStructureLib

In Resource tree, UserNodeA should have appeared under UserDefinedStructureLib. Right-click UserNodeA and select Add, and then Add a second UserNodeA so that you have two UserNodeA.

Give names to the added nodes (UserNodeA1 and UserNodeA2)

Note: Build the library before you continue: Right-click UserDefinedStructureLib and select Build.

Now create a system UserDefinedStructureSystem containing an application called App. If this is new to you, please see the following getting started guide: How to Create a System.

Select App under UserDefinedStructureSystem

In Resource tree, right-click UserComponentA under UserDefinedStructureLib and select Add

Select UserComponentA under App in UserDefinedStructureSystem

In the UserNodeA section, you can see that 2 nodes of type UserNodeA are already added

In Resource tree, right-click UserNodeA under UserDefinedStructureLib and select Add

Give the name UserNodeA3 to the newly added node. There should now be 2 "grey" nodes, which comes from the model (not possible to delete), and the newly added node (UserNodeA3).

If you now try to Run & Connect the application without any modifications in the C++-code, no UserNodeA will show up:

Right click on UserDefinedStructureSystem and select Run & Connect

Select UserComponentA under App in UserDefinedStructureSystem

Changes to UserComponentA

The UserComponentA behavior is described by two C++ files UserComponentA.h under Headers, UserComponentA.cpp under Sources in the Code mode Project tree.

The UserComponentA configuration options for CDP Studio are described by the model file UserDefinedStructureLib.UserComponentA.xml under Other files Templates/Models.

The UserComponentA is referred to in the library meta file UserDefinedStructureLib.xml under Other files exposing the file as a user resource that can be added during configuration and in UserDefinedStructureLibBuilder.cpp builder class that is used to create instances during runtime startup.

UserComponentA in the Model File

The syntax of model files is detailed in help page: CDP Model syntax. The configuration done in start of Example A (adding 'AggregateModel' and configuring AcceptsModel), enables UserNodeA to be dragged into UserComponentA during configuration:

<Element Name="UserNodeA" Property="0" AcceptsModel="UserDefinedStructureLib.UserNodeA"></Element>

The "Name" attribute in the Element defines the name used/generated in the configuration files - It can be named anything, except names already used in this model or its base model(s).

The Property="0" attribute makes the element a section definition and not a property element definition.

The AcceptsModel attribute lists one or more ; separated models that are aggregated by the user model. The model syntax provides also an alternative attribute called AcceptsBase that makes the section accept all models that inherit a given base model.

Note: The set of models the section accepts can't intersect with other sections in given model or its base models. This means that the same model can't be used in two different sections in the same view-level.

In addition, 2 UserNodeA prototypes were added to UserComponentA model-file:

<UserNodeA Model="UserDefinedStructureLib.UserNodeA" Name="UserNodeA1"></UserNodeA>
<UserNodeA Model="UserDefinedStructureLib.UserNodeA" Name="UserNodeA2"></UserNodeA>

UserComponentA in C++ Files

To enable UserComponentA to show the nodes of type UserNodeA during Online view (when connected to the running application), we need to add some code. It is has three main items: the container used to keep track of the UserNodeA instances, custom XML configuration handling and exposing the container to serialization in StudioAPI (so they will show up with values in Studio).

Firstly, UserComponentA.h needs a container to hold the pointer to created instances of UserNodeA, but the UserNodeA class should be forward declared before the class definition starts.

Before class declaration:

class UserNodeA;

In class declaration:

protected:
    std::vector<UserNodeA*> m_userNodesA;

Secondly, UserComponentA.h/.cpp needs to override HandleXMLElement() to handle defined UserNodeA tags defined in the XML. The section in component xml-file for UserComponentA which we need to parse, looks like this:

UserComponentA.xml:

<UserNodeA Description="Simple node example." Model="UserDefinedStructureLib.UserNodeA" Name="UserNodeA1" UserAttribute="StringA1"></UserNodeA>
<UserNodeA Description="Simple node example." Model="UserDefinedStructureLib.UserNodeA" Name="UserNodeA2" UserAttribute="StringA2"></UserNodeA>
<UserNodeA Description="Simple node example." Model="UserDefinedStructureLib.UserNodeA" Name="UserNodeA3" UserAttribute="StringA3"></UserNodeA>

UserComponentA.h:

    bool HandleXMLElement(XMLElementEx *pEx) override;

UserComponentA.cpp:

bool UserComponentA::HandleXMLElement(XMLElementEx *pEx)
{
    const XMLString& currentElement = pEx->GetName();

    if (currentElement == "UserNodeA")
    {
        m_userNodesA.push_back(new UserNodeA(pEx, this));
        return true; // done with handling the structure
    }

    return CDPComponent::HandleXMLElement(pEx);
}

Thirdly, UserComponentA.h/.cpp needs to override FillNodeChildren() to expose UserNodeA instances as its children in StudioAPI during runtime.

UserComponentA.h:

    void FillNodeChildren(CDP::StudioAPI::NodeStream &serializer) const override;

UserComponentA.cpp:

void UserComponentA::FillNodeChildren(CDP::StudioAPI::NodeStream &serializer) const
{
    serializer.StdContainerStreamer(m_userNodesA);
    CDPComponent::FillNodeChildren(serializer);
}

To finish up, the class destructor should delete the nodes instantiated, and the UserNodeA header must be included in the UserComponentA.cpp file.

Changes to UserNodeA

The UserNodeA has similar definition files as UserComponentA: header, source and model. The only difference is that UserNodeA is not added to the Builder class. For the default UserNodeA in UserComponentA to work, the generated UserNodeA definition need no further changes.

Note: After the changes done in the C++ files (UserComponentA.h/.cpp), remember to build the library.

Configuring UserNodeA's Property Values and Show Values in Runtime

By default, a CDPNode created by the wizard has one property to contain a user-value (in addition to the standard attributes/properties called "Model" and "Description"). In the model-file, this property is called "UserAttribute" of type "string" with value "Simple attribute". To modify the value for the 3 UserNodeA in UserComponentA:

Select UserComponentA under App in UserDefinedStructureSystem

Find the "UserAttribute" column in "UserNodeA" section and change the value to "StringA1" for UserNodeA1.

Modify the UserAttribute value to "StringA2" and "StringA3" for the other nodes as well.

If you now try to run the application, nodes of type UserNodeA will show up in default section UserNodeA:

Right click on UserDefinedStructureSystem and select Run & Connect

Select UserComponentA under App in UserDefinedStructureSystem

A section called UserNodeA shows the 3 nodes with correct values.

Example A-2

If you want to inhibit the possibility to add nodes of type UserNodeA, remove the following line from the library meta file UserDefinedStructureLib.xml, found under Other files in the Code mode Project tree:

<Model Name="UserDefinedStructureLib.UserNodeA"/>

Then UserNodeA will not appear as a resource in the Resource tree any more. Since there is no available resource for the table, CDP Studio will not allow adding any resources.

Files

  • UserComponentA.cpp
  • UserComponentA.h
  • UserNodeA.cpp
  • UserNodeA.h

Expose Custom Data in Automation System User Defined Structure Example B

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

    © Copyright 2021 CDP Technologies. Privacy and cookie policy.

    Return to top