Developer Guide
Overview
This documentation is organized into several major sections, each focusing on a specific aspect of using CDP Framework to develop automation and control systems. The purpose of the document is to provide a comprehensive guide to the platform's features, functionality, and best practices, helping developers build robust, scalable, and efficient control systems. The guide covers essential concepts, such as communication, scheduling, and data processing, and provides detailed instructions on structuring applications, creating modular designs, and using core resources effectively.
- Introduction to the CDP Framework
Provides a high-level overview of the platform’s purpose, structure, and key benefits.
- The Basic Building Blocks
Explains how code-based and XML-based models function, including recipes and the use of factory pattern in object creation. Also introduces the CDP class hierarchy.
- Core Concepts of CDP Framework
Covers fundamental ideas like communication: routing vs. push routing, real-time values, messages, and event handling for ex. Alarms.
- Scheduling and Data Processing in CDP
Details how processes are created and managed, including cyclic and event-based processing, and how data flows between them.
- Application Startup
Describes the initialization process, from XML configuration loading to activation and inter-application discovery.
- Networking Setup in CDP
Explains how network interfaces are managed within a CDP application and how IO servers integrate with these interfaces.
- Structuring CDP Applications
Discusses component-based architecture, hierarchical configuration, and how applications are formed by composing pre-built blocks.
- Modular Design
Provides practical guidance on creating maintainable, reusable modules, including component grouping and best-practice tips.
- Usage of CDP Core Resources
Provides practical guidance on using CDP Core resources, including CDPComponent for configurations and code models, OperatorContainer for organizing operators for logic and math. It covers CDPSignal for I/O, CDPPort for interface simplification, MessageArgument for message forwarding, and SendMessage/ReceiveMessage for transitioning between cyclic and event-based pipelines. Additionally, it discusses Sequencer's BasicFunctionBlock for no-code logic and ServiceBlock for event-driven code-based models.
- Industrial Protocols and Control I/O
Discusses CDP Framework approach to sending and receiving data from/to industrial protocols such as Modbus, OPC-UA and MQTT, and remote IO usage.
Each section contains additional subsections that explore these concepts in detail, helping you build, configure, and manage robust, real-time control systems with the CDP Framework.
Introduction to the CDP Framework
The CDP Framework is a comprehensive platform. It is designed to streamline the development of real-time advanced control systems and Human-Machine Interfaces (HMIs). It offers a suite of tools and libraries that facilitate the creation, deployment, and management of automation projects across various industries, enabling diverse use cases and simplifying complex workflows. By providing a unified environment, the CDP Framework enables developers to efficiently design modular and scalable systems while adapting to changing project requirements. This ensures smooth integration between components, fosters interoperability, and delivers dependable performance across different application scenarios.
At its core, the CDP Framework comprises several key parts, which together create a cohesive and flexible platform for industrial automation. These components interact seamlessly to empower developers with tools to tackle a wide range of challenges, from simple automation tasks to advanced real-time control systems. The framework's modular architecture further allows for continuous upgrades, ensuring its relevance in dynamic industrial environments:
- CDPCore Middleware that facilitates seamless communication and scheduling across multiple controllers (targets) on the local network.
- Libraries called Addons are a collection of pre-built or user-created resources represented by models that offer essential functionalities, reduce development time, and promote code reuse.
- The public API provided by StudioAPI interfaces with open-source clients, enabling external applications to interact with the CDP Framework applications, facilitating integration with third-party systems and extending the framework's capabilities.
Note: The core component responsible for the public StudioAPI in a CDP application is StudioAPIServer located at
<app_name>.CDP.StudioAPIServer
and contains info and API configuration options. Press Ctrl K and type in StudioAPIServer to find the component.For more information about using StudioAPI, see Usage of Public API for HMI development
- Built-in Security provided by CDP allows for fine-grained access level control based on users and groups.
- Tools provided by CDP such as the Configurator , discoverers, etc., automate the configuration and testing of CDP applications, streamlining workflows and enhancing efficiency.
These aspects of the framework work cohesively to provide a robust foundation for developing sophisticated control systems, catering to the diverse needs of automation projects.
The basic terminology used in this guide is explained in Glossary.
The Basic Building Blocks
In the CDP Framework, using CDP Studio, new functionality can be created either by using no-code (pure configuration) or code-based (Code + configuration). These options cater to diverse development needs, offering flexibility for developers with varying levels of expertise.
Code-Based Models
These involve writing C++ classes that define the behaviour and functionality of blocks. Developers implement the logic directly in code, providing greater control over the component's behaviour. This method is suitable for complex functionalities that require detailed programming. Code-based models also include an XML file containing information about the block, its types, and configuration behaviour via different elements and attributes in the XML that can be edited with CDP Studio. Code-based models are created in a library using the wizards CDP Studio provides in the library’s “Add New…” context menu.
Code-based models are typically created to provide new functionality or change the behaviour of some existing model by overloading its behaviour. For example, developers can override methods in a base model to customize its logic or introduce additional features specific to the application.
Configuration-Based Models
These models describe the structure and configuration of blocks in a declarative manner. They outline the component's properties, relationships, and configuration without delving into coding implementation details and are always based on other existing Models. This approach allows for a clear separation between configuration and coding, facilitating easier maintenance and updates. XML configuration-based models are typically created by copying configured blocks from the application to the library and converting them into Models. Instances in an application created from Models are tightly coupled to a given model and library as a dependency where the model resides. Instance members listed in models cannot be removed nor renamed in application configuration.
XML configuration-based models are typically created when new behaviours can be achieved by combining one or more existing models and connecting and configuring them to achieve the desired new behaviour. Sometimes, the goal can be just to change the look and feel of an existing model by applying different model hints.
For more information about model syntax, see Model hinting syntax help.
Configuration-Based Recipes
Recipes provide specific configurations and parameter values based on existing models. For instance, a recipe might predefine communication settings or sensor thresholds for a particular application, allowing developers to quickly implement standardized setups. They are used to customize existing models for particular applications or scenarios, allowing reusability and adaptable configuration hierarchies to be composed using existing models. The main difference is that Recipes don't allow overriding hints about its members. Members declared in Recipes can be later removed or renamed from instances in application configuration created from Recipes. XML configuration-based Recipes are created by copying configured blocks from the application to the library. Instances in applications created from Recipes are not linked to the Recipes after creation, but only to the models the Recipes refer to.
When added to an application, it behaves as if the user manually added each of the Models during configuration. Recipes save significant time and effort by enabling the reuse of predefined configurations and allowing customization of parameters for specific application scenarios. They streamline the process of creating complex applications by abstracting repetitive tasks and ensuring consistency across projects.
Factory Pattern Using Library Builder
The CDP Framework employs a factory design pattern to manage the construction of code-based instances. Each library has a CDPBuilder class. This class acts as a factory, responsible for constructing items listed in configuration based on their model names. When an instance is needed, the builder’s suitable Create[...]()
method is called by the framework depending on the model, which creates an instance of the first found code-based model in the requested model's base models.
CDP Class Hierarchy
The Class Hierarchy diagram represents the detailed programmers view of the CDP Framework main base clesses.
The diagram above illustrates the primary classes of the CDP Framework and shows how they relate to each other through inheritance, composition, and aggregation. The following highlights some key elements:
- CDPStarter and Application
These two form the top-level entry point of a typical CDP-based system. CDPStarter composes an Application to manage startup tasks and overall lifecycle.
- CDPEngine
CDPEngine extends core functionality for scheduling and managing processes. The engine aggregates one or more CDPProcess objects to handle the system’s operational flow.
- CDPComponent and CDPBuilder
CDPComponent is a generic class that represents a functional piece of the system typically with its own task. It can aggregate multiple CDPObject and CDPBaseObject based instances. CDPComponent can also be used as a container for other components and operators based logic in no-code designs. CDPBuilder is responsible for creating all objects and orchestrating how new system objects are instantiated.
- CDPBaseObject
The fundamental base class on which many others (e.g., CDPObject, CDPOperator) are based on. It defines shared behavior and interfaces.
- CDPObject, CDPPort, MessageArgument, and CDPOperator
CDPObject extends CDPBaseObject and acts as a more specialized foundation for ports, message handling. CDPPort extends CDPObject and is used for handling communication of real-time value structures. MessageArgument extends CDPObject and provides a message-oriented structure to pass data around the system as messages. CDPOperator extends CDPBaseObject defines operational logic; it is typically nested in an OperatorContainer or CDPComponent. OperatorContainer is a container for operators and sub-operator containers, providing a hierarchical organization of logic ran in nearest parent component task.
- Argument
Argument is class that represents a real-time input and output values in CDPOperator based objects.
- CDPProperty and CDPSetting
CDPProperty extends CDPNode and implements storage of configuration data and real-time data propagation for other objects. CDPSetting extends CDPNode and holds simple values for controlling behavior or showing status at runtime.
- CDPNode
Is the base class of all other CDP classes in your application’s logical hierarchy. CDPNode is used to expose application structure and data to StudioAPI.
Core Concepts of CDP Framework
Communication and Data Propagation in CDP
The primary communication methods in CDP are real-time values and messaging, each serve distinct purposes in facilitating data exchange between blocks. These methods operate through the Routing mechanism, which uses CDP's hierarchical naming system. In addition, CDP has support for alarm handling via a built-in event system, which enables blocks to detect, report, and respond to abnormal conditions with various severity levels. For example, when a monitored parameter exceeds a defined threshold, an alarm event is triggered and propagated to all event subscribers, ensuring prompt system-wide notification and handling.
Note: The core component responsible for collecting Routing info in the CDP application is RoutingTracker located at <app_name>.CDP.RoutingTracker
and contains listings of all valid and invalid routings. Press Ctrl K and type in RoutingTracker to find the component.
Pull Routing
Pull Routing is a communication method where a block requests data from another block. It is used for real-time values in CDP. Pull Routing is also known as regular routing.
In this diagram, the left-hand object (e.g., a Sine generator) produces a continuous real-time value—such as a sine wave—while the right-hand object (e.g., an Add operator) subscribes to that value.
This kind of "pull" or regular routing, requires that a property named Routing on the right-hand object input to reference the hierarchical name of the left-hand object's output or drag a connection from left to right in a block diagram.
This means that Add block pulls data from Sine block whenever an update occurs. This style is common for continuous or real-time values, where the consumer regularly reads or updates from the producer. In other words, the right-hand side knows about and depends on the left-hand side.
Push Routing
Push Routing is a communication method where a block sends data to another block. It is used for Messages in CDP and spechial PushPorts.
Note: The source bubble contains an arrow indicating the push routing type.
In this diagram, the left-hand object (e.g., a SendMessage block) sends or "pushes" a message to the right-hand object (e.g., a ReceiveMessage block), this routing type is indicated by the small triangle in the left-hand object connection bubble.
This push routing type, requires that a property named Routing or RoutingList on the left-hand object output is set to reference the hierarchical name of the right-hand object input or again drag a connection from left to right in a block diagram, but due to Push type the routing is set this time on the left-hand object. Here, the left-hand side knows about and depends on the right-hand side.
Main Difference: Dependency Direction
- Pull (Regular) Routing: The right-hand side (consumer) knows about the left-hand side (producer) and explicitly references it.
- Push Routing: The left-hand side (producer) knows about the right-hand side (consumer) and explicitly references it.
This distinction lets you decide which side holds the routing reference depending on whether you want the consumer to pull data from the producer or the producer to push data to the consumer.
Read more about routings in Routing usage documentation.
Real-Time Values
Real-time primitive values (bool, char, unsigned char, short, unsigned short, int, unsigned int, int64, uint64, float, double, string)
represent the dynamic data exchanged between components in a control system. Real-time values can implement one-to-one and one-to-many data propagation semantics. Real-time value subscribers refer to values by their hierarchical name in the application by using Routing. Typical value objects are CDPSignal, CDPSignalChannel, CDPParameter, Argument, etc., that reflect the current state, input, or output of a block. Each of the value object implementations uses CDPProperty as the value representation and CDPProperty implements value propagation and other behavioral semantics like optional storage for all value types.
Blocks can consume and propagate real-time value information each time they run, allowing for timely control actions. This is essential for maintaining synchronization and ensuring that all parts of the system operate based on the most current data available. This method of propagation is called Periodic propagation in the framework and is the default for most Real-Time values. It is optionally possible to set the values propagation type to Event-based propagation, then the value propagation occurs only when the source value changes, but is not guaranteed to happen by the next cycle of the subscriber.
CDP allows differing real-time value types to be connected with Routings. While this flexibility supports a wide range of applications, it comes with potential limitations. For instance, connecting numbers to strings or strings to numbers may lead to unexpected results, such as the number becoming 0 if the string is not convertible. Additionally, when connecting a real type to an integral type, or a larger integral type to a smaller one, value truncation can occur, causing loss of precision. These pitfalls should be carefully managed to ensure data integrity.
Managing numerous primitive values between blocks can be cumbersome. CDPPort simplifies this by grouping related values into structures. For instance, a Port in a control system might group motor-related values like speed, direction, and torque, enabling efficient Routing with fewer connections and improved maintainability.
Note: The core component responsible for propagating real-time values between CDP applications is MessengerIOServer located at <app_name>.CDP.MessengerIOServer
and contains statistics and global configuration options. Press Ctrl K and type in MessengerIOServer to find the component.
Ports with Real-Time Values
Ports facilitate connecting entire real-time value structures using a single Routing when value names match at both ends of the Port chain. A Port chain consists of two or more Ports linked sequentially, enabling a clear and organized flow of data. Only the first and last Ports need to handle or store values, while intermediate Ports remain empty and serve as pass-through proxy ports, seamlessly relaying connections. This design simplifies data flow and allows developers to create modular, hierarchical structures for efficient system design. For example, a hierarchical control application could use Ports to route motor control signals through different levels of its architecture, reducing complexity and improving maintainability.
For more information about Ports, see the Port documentation
Messages
Messages are structured data packets facilitating zero-copy communication between blocks, often used for more complex interactions. Messages can implement one-to-one, one-to-many, many-to-one, and many-to-many data propagation semantics. Message senders use a hierarchical name called Routing to indicate message target(s). They can encapsulate various types of structured information, including commands, status updates, or configuration changes. Messages allow for asynchronous communication. Blocks can send and receive information via Messages without waiting for their cycle time. This flexibility is crucial for asynchronous systems, where blocks may operate independently yet require coordination and data sharing.
Message Encoding
CDP Framework supports two separate encodings for messages: TEXT and BINARY. The TEXT-encoded messages have Command property with default value 0x20100 and contain a separate TextCommand property string (up to 31 characters) in addition to the payload, which is a semicolon-separated list of key=value pairs (e.g., Speed=11;Dir=180). BINARY-encoded messages (with all other Command property values) encode the data directly in the order they are listed in the sender, where strings are encoded beginning with 4 bytes of run-length encoding info before the string data by default. String Arguments have an optional Size property that, when set to a non-zero value, will use fixed-length encoding for the string. This option allows regular C++ structures with fixed sizes to send or receive data in code via messages.
Message receivers perform receive-side filtering based on message Command and TextCommand properties that must match between sender and receiver. It is possible to leave the TextCommand property empty to receive all 0x20100 commands. It is also possible to set the receiver Command property to 0x0 to accept all commands with all command codes.
For a detailed information about MessageArguments, see the MessageArgument documentation
Message Use in Sequencer
Messages are used by the Sequencer addon to create event-based computing blocks triggered by messages, where blocks execute when they receive messages that may contain data and, in turn, produce messages that may contain generated data as the result to pass on execution to other blocks. In Sequencer, the message input and output models are called EventIn and EventOut, and they include an additional Data property used to list the Argument members in the parent block that are to be decoded or encoded from/to the payload for that message.
Event Handling
Event handling is a communication method that focuses on responding to specific condition occurrences within the system. Events implement one-to-all or many-to-all data propagation semantics. Events don’t make use of hierarchical name-based Routings to propagate event data. Events can be triggered by changes in state, user actions, or external inputs. Typical event types in CDP are from CDPAlarm or AlarmOperator and are received by all subscribers of application events. Event subscriptions are per application and are set up automatically by CDP. By implementing an event handling mechanism for Alarms, CDP enables blocks to promptly report unexpected behaviour with levels of severity, enhancing the overall functionality and reliability of the control system.
In addition to alarm-created events, it is possible to create custom code to both create custom events via the IEventLogger
interface and to receive events by implementing the IEventSubscriber
interface. Implementing new event sources or sinks is considered a very advanced use case and should not usually be needed.
Note: There are multiple core components responsible for propagating events in and between CDP applications. The CDPEventNode located at <app_name>.CDP.CDPEventNode
contains statistics and global configuration options about application alarms. The CDPEventSubscriber located at <app_name>.CDP.CDPEventSubscriber
contains event subscriptions and global configuration options for event subscriptions. Press Ctrl K and type in CDPEventNode or CDPEventSubscriber to find the component.
For more information about the event system, see the CDPEventNode and CDPEventSubscriber documentation
Scheduling and Data Processing in CDP
Processes and Scheduling
In CDP, processes representing tasks or threads, which can be said to have their running context, are created automatically based on configuration. All CDPComponent
-based items like Application
, IOServers
, and user-created CDPComponents
define their required process setup via the following properties: SchedulingGroup
, Priority
, and fs
. A new thread is created for each value combination of SchedulingGroup
and Priority
used in the application. All components that share the values of the two properties share the same thread for doing work.
Each Process
in the CDP Framework has two main ways to schedule work:
- There is a cyclic scheduler that considers the cycle rates configured by
fs
property in the components registered in the givenProcess
. - There is a message queue that is processed whenever messages are added to the queue.
These built-in execution methods are the base for implementing two very different scheduling paradigms: cycle-based processing and event-based processing.
Note: The core component responsible for scheduling in CDP applications is CDPEngine located at <app_name>.CDP.CDPEngine
. It contains statistics and global configuration options about application scheduling and async workers used by CDPEngine. Press Ctrl K and type in CDPEngine to find the component.
Cyclic Processing
Cycle-based processing means that part of the object code is executed with a deterministic predefined interval or rate. The rate in Hz at which the cyclic code is executed in the given thread is set by the fs
property. When components share all three values SchedulingGroup
, Priority
, and fs
, those components and their non-component children are executed in the order they are listed in configuration, where parents are executed before children, but in the same cycle timeslot.
During this timeslot run, any real-time values that are produced can be propagated to the next block in the same timeslot without any delay. This makes it possible to build data processing pipelines from blocks that execute and process data in a single cycle. In the CDP Framework, the cycle timeslot locations in time are deterministic and defined by the cycle rate fs
and the number of cycles from the time epoch. This allows for synchronized code execution across multiple devices when PTP ClockSync
is used for the synchronization of the applications on different devices.
The cyclic processing is performed for CDPComponent
-based blocks in Process<state-name>()
functions and for CDPOperator
-based blocks in Process()
functions.
Note: Backloops occur when routing needs to go to a higher (previous) block in the execution order, causing a cycle delay for the data propagation.
Event-Based Processing
Event-based processing means that some object code is executed asynchronously and immediately based on some event. In the CDP Framework, those events are Messages
that can be sent point-to-point between any two objects in the applications within the same system.
All CDPObject
-based items (this includes CDPComponents
) can be woken up in between cycles by a Message
to process the received message. This base capability allows for event-driven application code to be created where there is no delay in executing the message-handling code in the object.
Data Exchange
In most systems where both cyclic and event-based processing methods are used, there often is a need to exchange data between the cyclic domain and the event-based domain in the design. The CDP Framework provides two specialized blocks to facilitate this communication:
- SendMessage block allows sending cyclically triggered messages from the cyclic domain.
- ReceiveMessage block allows messages to be received from the event-based domain of the application in the cyclic domain.
Application Startup
The startup sequence of a CDP application follows a structured process that ensures a systematic initialization, configuration, and activation of all components within the system. This sequence involves carefully orchestrated steps that establish the application framework, organize components hierarchically, and facilitate seamless communication across the system's architecture.
- Initialization: The process begins with the
Application.xml
file located in the Application folder. This file outlines the first level of the hierarchical structure of components, their nested children, and values. The process goes through all levels of structure based on the order of the components and their sub-components listed in the XML files. - Instance Creation and Configuration: The framework reads the XML configuration, invoking
Create()
andConfigure()
on all instances described in the XML files. This process sets up the components and their relationships and links instances created by library-provided factory classes to their names in the system. - Activation: Once all components are configured, the
Activate()
method is called on each instance. The framework then establishes processes based on the component structure, considering combinations of Priority and SchedulingGroup used across all components. - Discovery and Communication: All applications in the system perform UDP broadcast-based discovery to identify other CDP applications with the same Domain name. This mechanism enables the system to find and connect to data values in all applications, facilitating inter-application communication.
Networking Setup in CDP
Correct network setup is essential for ensuring seamless communication between applications and devices. This section provides detailed guidance on how interface selection works in CDP applications and in IO Servers.
Application's NetworkInterface Table
Each CDP application has a NetworkInterface table with one default interface item ETH0 that defines the address and network mask CDP will use by default for communication with other CDP applications. This can be changed in Messenger component (that exists in the internal CDP component under the Application) by selecting a non default NetworkInterface that the user has added to the application NetworkInterface table manually.
Note: The core component for base messaging between CDP applications is Messenger located at <app_name>.CDP.Messenger
. It contains statistics and global messaging configuration options. Press Ctrl K and type in Messenger to find the component.
For more information about the Messenger, see the Messenger configuration manual
In CDP Studio, network interface selection in Deploy Configuration plays a critical role in application network configuration. By selecting a network interface, CDP Studio scans for devices with an active SSH server on port 22, facilitating the target device discovery process.
The Deploy Configuration enables users to assign applications to specific target devices in the selected network. The target devices IP address is set in the Application NetworkInterface item ETH0 automatically during deploy. This ensures consistency and alignment between the deployment settings and the actual network interface used by the application.
IOServer Integration with Interfaces
IOServers in CDP Framework are designed to manage data transformation between CDP and external systems. They can reference the default or added interfaces in the Application NetworkInterface table by selecting the relevant interface name in NetworkInterface property. This association allows the IOServer to utilize the correct network interface for communication, ensuring it aligns with the application's deployment configuration. Proper setup of IOServers with these interfaces is crucial for maintaining efficient and reliable system operation.
Structuring CDP Applications
In the CDP Framework the applications don’t contain user code directly, as the focus is on composing functionality from pre-built components. Instead, applications are composed of components that the user selects by using some resource from the given library in application configuration and loosely coupling it to other components in the application via the Routing mechanism. For example, a sensor component can send its data to a processing component through a defined routing path, enabling flexibility and modularity without direct code dependencies. This approach is known as component-based architecture. Application behaviour is not defined by the application executable. Instead, it is determined by the components and their relations, which the user configures using CDP Studio IDE. The same application binary can run configurations of very different control applications.
The configuration of the application is stored in XML-based configuration files. These files are structured as hierarchical trees, where each node represents a component. For example, a configuration file might define a component with attributes like name, type, and connections to other components, enabling users to define complex setups in a clear and organized manner. CDP Studio automatically creates, edits and deletes these files as needed, based on user actions in the IDE.
Modular Design
To arrive at a modular design for a control system, identify key functionalities that can be encapsulated into distinct, self-contained modules. Each module should encapsulate specific functionality, promoting reusability and simplifying maintenance. For example, a module might encapsulate a temperature control system, handling data input from temperature sensors, processing it to maintain a setpoint, and outputting signals to an actuator.
Module breakdown also needs to take into account:
- Desired scheduling: is the logic cyclic or event-driven by nature?
- Desired interfacing: is the interface of the module cyclic or event-based?
CDPComponent is the main building block of your application. Each component encapsulates specific functionality and can interact with other components. Interaction typically occurs through defined interfaces, such as real-time values, ports or messages, which enable components to exchange information in a standardized and decoupled manner. It has its cyclic running frequency, scheduling priority and group. Components can contain sub-components and OperatorContainer(s) allowing for a nested, hierarchical organization that reflects the system's architecture.
This organization provides clear separation of responsibilities, simplifies debugging, and enables scalability by making it easier to add or modify specific functionality without impacting the entire system.
OperatorContainer can contain sub-operator containers, and CDPOperator based logic like Add, Mul operators etc., allowing for a nested, hierarchical organization of logic in OperatorContainer. Operator-based logic structures lack a separate cyclic frequency setting and are tied to the nearest parent component in priority and cyclic frequency. This design ensures that operators are tightly integrated within the parent CDPComponent's execution framework, reducing complexity in scheduling while maintaining consistent performance across the hierarchy.
Sequencer CompositeBlock can contain sub-blocks like BasicBlock, and ServiceBlock, allowing for nested hierarchical organization of event-driven computational logic. These blocks by default don’t run cyclically, but only when a message is received. The exception is BasicBlock when set to use Cyclic scheduling, it will also inherit the nearest parent CDPComponent priority and cyclic frequency.
Each of the main structural blocks described above accepts and supports the propagation of real-time values, structured real-time values via ports and messages to other parts of the component architecture, including connections across applications.
Modular component-based design offers numerous advantages for developers. The benefits of modular component-based design are:
- Reusability: Modules can be reused across different projects or within different parts of the same project.
- Maintainability: Isolated modules make it easier to identify and fix issues without affecting the entire system.
- Scalability: New features can be added as separate modules without disrupting existing functionalities.
Implementation Tips
- Encapsulation: Keep the internal workings of a module hidden, exposing only what is necessary through well-defined block interfaces, configuration options, or read-only status values. A well-defined block interface includes clear input and output parameters, proper documentation of expected data types, and consistent naming conventions. For instance, a block interface for a temperature sensor might specify input as calibration parameters and output as a real-time temperature value, ensuring clarity for integration.
- Make use of design sugar like TypeHint, InputOutputHint, TypeColorHint, ColorHint, DisplayHint etc. For example, TypeHint can ensure configuration fields only accept specific data types, while DisplayHint controls the visibility elements, enhancing user interaction. Design sugar refers to additional hints and attributes that improve the usability and visual presentation of components described in hinting syntax help.
- Differentiate between what constitutes the block interface for data input and output (InputOutputHint) and what types and values are allowed in configuration options (TypeHint).
- Leverage naming conventions to make your module or block more intuitive. For example, use action-oriented names such as
'ProcessSensorData'
for processing modules or'TemperatureSensor'
for sensor modules. Avoid ambiguous terms, and ensure the names clearly indicate the purpose or role of the module or block within the system. Use descriptive names for blocks and components that reflect their purpose or function. - Group related components logically to simplify navigation and management in large projects. For instance, you might group all sensor-related components under a
'Sensors'
component and all processing-related components under a'Processors'
component. Using hierarchical naming such as'Sensors.Temperature'
and'Processors.DataFilter'
can further enhance clarity and maintainability. Use hierarchical naming to categorize them effectively. - Test modular components individually before integrating them into the larger system to ensure functionality and reduce debugging complexity during later stages.
- Document your configuration settings, especially for complex modules. Focus on key aspects like required inputs, expected outputs, and valid ranges for parameters. For instance, a configuration for a temperature control module might specify the acceptable temperature range, calibration parameters, and default settings to guide users effectively. Fill in Description properties in the XML Models and in configuration or add supplemental QDoc documentation to clarify the purpose and usage of settings.
- Regularly review and refactor components to ensure they adhere to best practices and remain maintainable over time.
Usage of CDP Core Resources
This section explains the purpose and how to leverage core classes and constructs within the CDP Framework. From setting up CDPComponent objects in your configuration to integrating operator blocks and ports, these usage examples aim to illustrate use-case scenarios you can adapt to your projects.
- CDPComponent as a Logic Container or Base Class
- CDPSignal for Real-Time Component I/O
- Simplifying Interfaces with CDPPort
- MessageArgument in CDP
- Transitioning Between Cyclic and Event-Based Data Pipelines
- OperatorContainer for Organizing Operators
- Utilizing CDP Operators with Argument Real-Time I/O
- Implementing Custom Logic with Sequencer Blocks
CDPComponent as a Logic Container or Base Class
In the CDP Framework, CDPComponent is the foundational building block for applications. It acts as a container for logic, encapsulating functionality and managing subcomponents. It allows the creation of hierarchies that run as a single process with specific cycle frequency and priority set with fs
and Priority
properties. When developing code-based models, CDPComponent is typically used as the base class, providing essential interfaces for initialization, message handling, and state management. Developers can override methods such as Create(), Configure(), and Process() to define custom behaviour. Additionally, CDPComponent supports the integration of:
- CDPSignal for real-time values as inputs and outputs
- CDPPort for real-time structures of values as inputs and outputs
- MessageArgument (Message) for message-based inputs and outputs
- CDPParameter for stored configuration options of real number values
- CDPAlarm for emitting alarm events based on local values
- CDPComponent for nested component-based blocks either sharing the same process or creating a new process
- OperatorContainer for nested operator-based logic
- CDPOperator for local logic within the component
for facilitating seamless communication within the application.
CDPSignal for Real-Time Component I/O
CDPSignal is used to represent real-time values within a component, serving as inputs or outputs. These signals facilitate the propagation of dynamic data between components, ensuring timely updates and synchronization across the system. By adding CDPSignal instances, developers can manage real-time data flow, connecting signals to operator arguments, or other components signals as required.
Simplifying Interfaces with CDPPort
In CDP Framework the CDPPort serves as a powerful tool to streamline component interfaces by aggregating related data into a single object, akin to a structure in traditional programming languages. This design enhances clarity and efficiency in data management.
CDPPorts are interconnected through CDP's routing mechanism, enabling the establishment of a data bus that propagates information in directions defined by the port's connections. This setup simplifies the interface between components by consolidating multiple signals or parameters into a cohesive unit, reducing the complexity of managing numerous individual connections.
Depending on communication requirements, ports can be configured as unidirectional or bidirectional. Unidirectional ports facilitate data flow in a single direction, while bidirectional ports allow for two-way communication, providing flexibility in how components interact within the system.
Moreover, CDPPorts can be utilized to forward interfaces through a block hierarchy, promoting organized and scalable application structures. By defining a unified interface for components to communicate over, developers can create systems that are both modular and maintainable. This approach is particularly beneficial when managing complex systems, as it allows for the seamless integration and interaction of various components.
For instance, in a scenario where multiple devices need to be controlled simultaneously, such as turning on or off a group of lamps, a CDPPort can be defined to include control signals like TurnOn, TurnOff, and status indicators like IsOn. This port can then be used across different components, ensuring a consistent interface and simplifying the control logic.
MessageArgument in CDP
The MessageArgument class in CDP enables efficient inter-component communication by allowing components to send and receive messages. Developers can configure MessageArgument instances to define message structure and content, setting them as input or output by adjusting the Input property. The Command property specifies the message command code, defaulting to CM_TEXTCOMMAND (0x20100)
- all other values indicate a binary message. The TextCommand property refines message handling by determining which specific text messages are received or sent, while the RoutingList property enables sending or forwarding messages to specific targets, supporting a modular, event-driven architecture.
For no-code implementation, the ReceiveMessage block detects messages in cyclic logic with received data set to named outputs, while the SendMessage block facilitates message dispatching with named inputs as data. By using MessageArgument, CDP applications achieve structured, efficient messaging without extensive coding.
Transitioning Between Cyclic and Event-Based Data Pipelines
The SendMessage and ReceiveMessage operators can be used to bridge the gap between cyclic and event-based processing. SendMessage allows cyclic processes to emit messages that can trigger event-based handlers, while ReceiveMessage enables event-driven messages to be received within cyclic processes with local queuing to allow a single message per cycle to be processed. This flexibility ensures that different parts of the application can communicate effectively, regardless of their processing paradigms.
OperatorContainer for Organizing Operators
The OperatorContainer is designed to group multiple operators from Automation resources within a single container, allowing for organized and efficient processing of operations. By encapsulating operators in an OperatorContainer, developers can manage complex logic structures more effectively, ensuring that related operations are processed cohesively. This approach enhances modularity and readability within the application's configuration.
Additionally, OperatorContainer supports the integration of:
- Argument for real-time values as inputs and outputs
- CDPPort for real-time structures of values as inputs and outputs
- MessageArgument (Message) for message-based inputs and outputs
- Alarm operator and ExtendedAlarm operator for emitting alarm events based on local values
- OperatorContainer for nested operator-based logic
- CDPOperator for local logic implementation within the container
for facilitating seamless communication within the application.
Utilizing CDP Operators with Argument Real-Time I/O
CDP offers a comprehensive suite of pre-made operators that streamline the development of automation and control systems. These operators, such as Add and Mul, perform arithmetic operations on input arguments efficiently and can be customized through their properties or arguments. For instance, the Add operator can sum multiple input values, while the Mul operator multiplies them. Arguments define the inputs to these operators and can be connected to arguments, signals or parameters within the application. This flexibility allows for precise control and manipulation of data flows in your system.
In addition to arithmetic functions, CDP provides a variety of other operators to enhance your application's functionality. For example, the Scaling operator allows for the transformations of signal values from one range to another, which is particularly useful when interfacing with different hardware components. The Delay operator enables the buffering and delaying of signal outputs, facilitating the synchronization of processes within your system. Furthermore, the PIDRegulator operator calculates control values based on system position and desired position, essential for implementing control loops in automation tasks.
Implementing Custom Logic with Sequencer Blocks
For more complex control tasks that require sequential operations, CDP Sequencer addon is invaluable. The Sequencer BasicBlock (BFB) can encapsulate existing CDP operators for data processing and allows for the creation of state machines using the Execution Control Chart (ECC). This setup is ideal for tasks that consist of steps taken in sequence, such as controlling manufacturing lines. The Sequencer BasicBlock also allow cycle-based processing when its ProcessOn
property has also C flag set.
Moreover, CDP enables the creation of custom operators tailored to specific application needs. Using the built-in wizards, developers can implement specific functionality as needed, allowing for the extension of the existing operator set to meet unique requirements. In addition, Sequencer supports the development of new code-based Service Function Blocks (SFB) for custom user extensions that can be created using built-in wizard in code mode, allowing for the execution of custom C++ code in response to specific events.
By leveraging these pre-made and custom operators, along with the Sequencer addon, developers can efficiently design, implement, and manage complex automation and control systems within CDP.
Industrial Protocols and Control I/O
The CDP Framework offers robust support for integrating industrial protocols and managing control I/O, enabling seamless communication between your application and various industrial devices and systems. This guide provides an overview of how to effectively utilize protocols such as Modbus, OPC UA, and MQTT within the CDP environment, as well as guidance on handling remote I/O operations.
In the CDP Framework, the IOServer class serves as a specialized component designed to facilitate communication between CDP applications and external devices or systems through various protocols. Acting as an intermediary, an IOServer transforms CDP data into protocol-specific formats and vice versa, enabling seamless data exchange with hardware devices.
In IOServes, users define the data values they wish to monitor or control. This is done by adding typically CDPSignalChannel real-time values to modules or packets defined by the specific IOServer. The CDPSignalChannel real-time values can be connected to/from the CDP control system using the Routing mechanism as single values. It is also possible to add CDPPort to the IOServer and map the IO data to a Port-based interface to simplify connecting data.
When event-based communication is needed, some IOServers have built-in support like MQTT, but it is possible to add SendMessage and RecieveMessage to the IOServer for event-based transition. SendMessage can be configured to send messages when its input data changes.
When developing support for new industrial protocols or custom I/O operations, developers create subclasses of the IOServer base class using a built-in wizard. These subclasses implement the necessary methods to handle protocol-specific
- Modbus Integration
- OPC UA Integration
- MQTT Integration
- Remote I/O Management
- Implementation Steps and Connecting to CDP
Modbus Integration
Modbus is a widely adopted master-slave protocol that is used for communication with industrial devices like PLCs and I/O modules. The CDP Framework provides pre-configured models for Modbus communication, including ModbusMasterRTU, ModbusMasterTCP, and ModbusMasterUDP (there are also slave configurations available). These models can be easily added to your project, facilitating straightforward data exchange with Modbus-compatible devices.
OPC UA Integration
OPC UA (Open Platform Communications Unified Architecture) is a platform-independent, service-oriented architecture that ensures secure and reliable data exchange in industrial automation. The CDP Framework includes support for OPC UA, allowing your application to interact with a wide range of industrial equipment and systems. This integration enables standardized communication and enhances interoperability across diverse devices.
MQTT Integration
MQTT (Message Queuing Telemetry Transport) is a lightweight, publish-subscribe messaging protocol ideal for scenarios requiring efficient, real-time communication, especially in environments with limited bandwidth. The CDP Framework's support for MQTT enables your application to connect to various devices and systems, facilitating efficient data transmission and reception.
Remote I/O Management
Managing remote I/O is crucial for distributed control systems. The CDP Framework provides comprehensive support for remote I/O operations, allowing your application to monitor and control I/O points across various devices and networks. This capability ensures that your system can effectively manage inputs and outputs, regardless of their physical location, enhancing the scalability and flexibility of your control architecture.
CDP comes with built-in support and pre-defined configurations for I/O modules from a range of industrial I/O vendors, including Wago, Phoenix Contact, Weidmüller, Beckhoff, and B&R Automation. New modules and vendors are continuously added, and you can also create support for your own developed hardware or add your own pre-defined configurations.
For example, CDP Frameworks ModbusIO supports most of the 750-series analog and digital modules from Wago, using the standard (non-complex) process-data image. Similarly, it supports most of the Axioline analog and digital modules from Phoenix Contact for the AXL F BK ETH bus coupler.
Implementation Steps and Connecting to CDP
- Adding Protocol Support: Incorporate the desired protocol model (e.g., ModbusMasterTCP, OPCUAClient, MQTTClient) into your project using the CDP Studio IDE.
- Configuring Communication Parameters: Set up the necessary communication parameters such as IP addresses, ports, and device IDs to establish connections with your target devices.
- Connect real-time data to CDP: In CDP, IOServer real-time data can be connected using the standard Routing mechanism. This involves connecting data directly to or from CDP control values, utilizing Ports, or employing SendMessage and ReceiveMessage blocks.
Get started with CDP Studio today
Let us help you take your great ideas and turn them into the products your customer will love.