This article focuses on an open library for building distributed control systems - libuniset, written in C ++ for Linux. An overview of the basic concepts, elements and concepts used in the library will be given.
The main purpose of the library libuniset is to provide ready-made "cubes" for building distributed automated control systems (ACS). In any automated control system, you can identify the following main areas:
- input Output;
- network exchange;
- management processes (algorithms);
- data storage;
- work with the database.
In libuniset, an attempt has been made to create ready-for-use, consistent and interoperable components for all of the specified areas, and at the same time create a fairly universal and easily extensible library.
A typical project using this library is a project
consisting of about 20-25 nodes implementing control and monitoring of state, as well as operator stations (usually at least two reserving each other) displaying information and, in addition, implementing journaling of all events occurring in the system (that is, filling the database). In general, the number of nodes in the system is unlimited.
')
A little historical background
The libuniset library developed (and is developing now) as it should be - gradually. In the course of work on various control system projects, some of the properties, mechanisms or components common to all systems were singled out, and these common parts were added to the library for further reuse. At the moment, the current version is version 1.6, which is already a fairly mature library with an established API, which allows you to easily (and quickly) create and deploy management systems.
At the moment, the library and all its supporting utilities are built
for the ALT Linux distribution ,
as well as additionally, using the
Korinf system, the library is built under:
What is libuniset

The figure attempts to graphically represent what libuniset is.
It is based on the
CORBA technology, and the entire interaction of the “components” of the system between them is built on it. It should be noted that the library API “masks” the interaction based on
CORBA and, if necessary, the interaction can be rewritten using other mechanisms without affecting the interfaces intended for use in projects. You can see that libuniset uses third-party libraries whenever possible (trying to avoid the invention of bicycles). Methods of using the library can be different: starting from writing the necessary functionality by inheriting from the library classes and ending with the use of ready-made components without any modification, but only setting them up for their tasks.
Basic concepts
The main information unit in the library is the
sensor . In essence, a
sensor is a kind of stateful variable. Virtually any information (about events, the status of a process, an object, a message to the operator, etc.) is transmitted through the state of the
“sensor” . The library has four types of
sensors :
- DI - discrete input (DigitalInput)
- DO - discrete output (DigitalOutput)
- AI - Analog Input (AnalogInput)
- AO - Analog Output (AnalogOutput)
Initially, these types are used directly by input / output processes. “Outputs” (DO, AO) are commands “from the control system”, “Inputs” (DI, AI) are information from the object “into the control system”. In addition, sensors do not have to be “live” inputs or outputs — with these four types, you can encode any information. For example, you can send messages to the operator by creating your own “sensor” for each message and, if necessary, send a message to put it at “1”. The convenience and versatility of numerical sensors allows the use of a large number of different protocols for transmitting data, designed to transmit only digital information. For example:
CAN ,
ModbusRTU ,
ModbusTCP , etc.
The second important concept is the
object . By
object is meant an entity capable of receiving messages. Objects are created, initialized and started to work with a special
activator .
Additionally, you can still introduce the concept of
process . By
process is meant a system process (running program) that performs certain control functions and exchanges messages with other
processes or remotely calls functions of other objects. Most often, the concepts process and object are the same. In some cases, a process may contain several interacting objects. All processes in the system are multi-threaded, since for interaction with other objects (processes) threads are necessarily created for
CORBA , and each object has its own message processing flow (unless it is specifically turned off).
Interaction of processes on the node
During the development of the project, the following scheme of interaction between the processes on the site was formed by experiment:

The central element of the system is SharedMemory (SM) - a process that stores the status of all sensors. All interaction between processes is carried out through it. At the same time, this name should not be confused with the concept of “shared memory”, related to the interaction mechanisms in UNIX-systems. In this case, the SharedMemory process simply performs the function of a shared repository and therefore has received this name. In addition, SharedMemory sends out notifications to other processes about changes in the state of a particular sensor.
All processes can be divided into two types: "active" and "passive."
Passive processes are processes that “sleep” most of the time, waiting for messages about a change in a particular sensor. Mostly such processes include management processes.
Active processes are processes that are constantly doing some work. These processes include:
- network exchange processes (in this case, CAN);
- processes of work with input / output cards (IOControl);
- exchange processes with some external devices (RS485 or ModbusTCP).
Since active processes work closely with SharedMemory, to optimize the work (excluding remote procedure calls through CORBA) all active processes run in the same address space with SharedMemory (each process in a separate thread), and work with SM directly, via pointers. This “merged” process is for historical reasons called SharedMemory2.
Separately, you can select a group of "auxiliary" processes. In this figure, DBServer, which is usually run on the operator stations where the database is maintained, refers to such. Its task is to receive notifications from the SM about changes in any sensor and save these events in the database. By default, libuniset supports MySQL and SQLite, but if necessary, you can implement interaction with any DBMS by developing the appropriate DBServer.
Distributed Interaction (Network)
The figure shows a typical libuniset-based network connectivity scheme.

To ensure network transparency, each node runs its own copy of SharedMemory (SM). “Transparency” at the same time ensures the exchange processes between nodes using the appropriate protocol (in the figure, these are CAN and UNET). Nodes are constantly exchanging sensors between themselves ensuring the "sameness" of information stored in SM. Each exchange process receives information about other sensors from other nodes, and in turn sends information about sensors located at its node to other nodes.
The input / output process (IOControl) also functions through SM. Everything that is read from the input channels is stored in the SM, and the state of the “outputs” is read from the SM and output to the output channels.
From the figure it can be seen that the interaction can be built on practically any interface (Ethernet, CAN, RS, MIL-STD, etc.). It is enough to write an exchange process that implements the appropriate interface and interacts with SM. In this case, the rest of the system does not require modification.
A brief description of the components included in the libuniset
The finished components are already finished programs (processes) that “know how” to interact with SharedMemory and make it easy to “deploy” distributed systems. The following components are available in the libuniset library:
- SharedMemory - storage of "variables";
- IOControl - working with I / O cards;
- ModbusMaster - implementation of Modbus TCP / RTU master mode;
- ModbusSlave - implementation of Modbus TCP / RTU slave mode;
- UNetExchange - UDP protocol interaction;
- LogicProcessor - a component that allows you to describe algorithms based on logic circuits (recorded in the xml-file);
- DBServer_MySQL - server for interacting with MySQL database;
- DBServer_SQLite - server for working with SQLite.
Libuniset utilities
As work on projects and the development of the library's capabilities, various auxiliary utilities began to be included in it, allowing for the adjustment of projects created with its use. Here is a list of basic utilities with a brief description:
The group of utilities for working with sensors:
- uniset-admin is a multifunctional console utility that allows you to write / read the status of sensors, as well as having various auxiliary functions;
- uniset-simitator - simulator of linear change of analog sensors;
- uniset-smviewer - view the status of all sensors;
- uniset-smonit - monitoring changes in the state of the sensor (or group of sensors).
Utilities for working with network protocols:
- uniset-mbtcpserver-echo - device Modbus TCP Slave simulator;
- uniset-mbtcptest - A console utility that allows you to poll (check) devices using the Modbus TCP protocol (Master mode);
- uniset-mbrtuslave-echo - Modbu RTU Slave simulator device;
- uniset-mbrtutest - A console utility that allows you to poll (check) devices using the Modbus RTU protocol (Master mode);
- uniset-unet-udp-tester - work with the UnetUDP protocol.
Various additional utilities:
- uniset-iotest - testing work with I / O cards;
- uniset-iocalibr - calibration of analog sensors;
- uniset-codegen is the skeleton generator of the control process.
Additional projects
The program interface (API) of the libuniset library has been stabilized for a long time, and gradually, in addition to it, various auxiliary programs appeared. Since the purpose of this article is a general acquaintance with libuniset, we restrict ourselves to listing such additions:
- uniset-configurator is a graphical utility that allows you to configure various system parameters (I / O cards, I / O channels, network interaction, etc.).
- uniset-testsuite is a set of utilities (a separate project) for creating special test scenarios that allow you to perform automatic (regression and not only) tests of the system based on libuniset.
- uniwidgets is a library for building graphical interfaces based on gtkmm, interacting with the use of libuniset.
Conclusion
The libuniset library allows you to quickly create "complex" systems. In some respects, it is ideologically similar to SCADA systems, but it should be borne in mind that this is only a superficial similarity: the user in this case is given complete control over the operation of the system, the ability to program any algorithms (in C ++). Although it should be noted that the system built on libuniset can be easily integrated into any existing system (based on SCADA) - just acting, for example, as a Modbus Slave node. Or vice versa, it can interact with any third-party SCADA-system, simply using the Modbus Master exchange process (ready-made component).
There is a positive experience of using it in responsible projects, where it proved to be a reliable system (24x7x365).
Related Links
Update : Continuing the theme
new version