Acquaintance with libuniset - library for creating ACS

This article will focus on an open library for building distributed control systems - libuniset, written in C ++ for Linux. A general overview of the basic concepts, elements and concepts used in the library will be given.

The main goal of the libuniset library is to provide ready-made “cubes” for building distributed automated control systems (ACS). In any ACS, one can distinguish such main areas as:
  • input Output;
  • network sharing;
  • management processes (algorithms);
  • data storage;
  • work with the database.

In libuniset an attempt was made to create ready-to-use, consistent and interacting components for all these directions, 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 that implement state management and control, as well as operator stations (usually at least two reserving each other) displaying information and, in addition, realizing the logging of all events occurring in system (i.e. populating the database). In general, the number of system nodes is unlimited.

A small historical background

The libuniset library developed (and is developing now) as it should - gradually. In the course of work on various projects of control systems, some common properties, mechanisms or components were distinguished from all systems, and these common parts were entered into the library for further reuse. At the moment, the current version is version 1.6, which is a fairly mature library with a well-established API, which allows you to easily (and quickly) create and deploy control systems.

At the moment, the library and all its auxiliary utilities are being assembled under the ALT Linux distribution ,
and in addition, using the Korinf system , the library is being built under:

What is libuniset


The figure attempts to graphically represent what libuniset is.

It is based on CORBA technology , on it is built all the interaction of the "components" of the system with each other. It should be noted that the library API "masks" the interaction based on CORBAand, 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: from writing the necessary functionality by inheriting from the library classes to using ready-made components without any modification, but only customizing them for your tasks.

Basic concepts

The main information unit in the library is the sensor . In fact, a sensor is a variable storing a state. Almost any information (about events, about the state of a particular process, object, message to the operator, etc.) is transmitted through the state of the “sensor” . There are four types of sensors in the library :
  • DI - Digital Input (DigitalInput)
  • DO - Digital Output (DigitalOutput)
  • AI - analog input (AnalogInput)
  • AO - analog output (AnalogOutput)

Initially, these types are used directly by I / O processes. “Outputs” (DO, AO) are the commands “from the control system”, “Inputs” (DI, AI) are the information from the object “to the control system”. In addition, the sensors do not have to be “live” inputs or outputs - using 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 in advance and, if necessary, send a message to set it to “1”. The convenience and versatility of digital sensors allows you to use 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 an object is meant an entity capable of receiving messages. Objects are created, initialized and launched into operation by a special activator .
Additionally, you can still introduce the concept of process . By a process is meant a system process (a running program) that performs certain control functions and exchanges for this with other processesmessaging or remotely calling functions of other objects. Most often, the concepts of process and object coincide. In some cases, a process may contain several interacting objects. All processes in the system are multi-threaded, because for interaction with other objects (processes), threads for CORBA are created without fail , and each object has its own message processing thread (unless you specifically disable it).

Node Process Interaction

During the development of the project, the following scheme of interaction of processes on the node was formed empirically: 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”, which refers to the mechanisms of interaction in UNIX systems. In this case, the SharedMemory process simply acts as a shared repository, and so got the name. In addition, SharedMemory sends out notifications to other processes about the state change of a sensor.
All processes can be conditionally divided into two types: “active” and “passive”.
Passive processes- These are processes that “sleep” most of the time, waiting for messages about a change in one or another sensor. Basically, these processes include management processes.
Active processes are processes that constantly perform some kind of work. These processes include:
  • exchange processes over the network (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 work (exclude remote procedure calls through CORBA), all active processes are launched in the same address space as SharedMemory (each process in a separate thread), and work with SM directly, through pointers. This historical process is called SharedMemory2 for historical reasons.
Separately, we can distinguish a group of "auxiliary" processes. In this figure, DBServer refers to these, usually launched at operator stations where the database is maintained. Its task is to receive notifications from SM when any sensor changes and save these events to the database. By default, support for MySQL and SQLite is implemented in libuniset, but if necessary, you can implement interaction with any DBMS by developing the appropriate DBServer.

Distributed interaction (network)

The figure shows a typical network diagram based on libuniset.

To ensure "network transparency", each node runs its own copy of SharedMemory (SM). At the same time, “transparency” is ensured by the exchange processes between nodes using the appropriate protocol (in the figure these are CAN and UNET). The nodes are constantly exchanging sensors among themselves, ensuring the "uniformity" of information stored in the SM. Each exchange process receives information from other nodes about the sensors they have, and in turn sends other nodes information about the sensors located on its node.
The I / O process (IOControl) also functions through SM. Everything that is read from input channels is stored in SM, and the status of “outputs” is read from SM and output to output channels.
From the figure you can see that the interaction can be built on virtually any interface (Ethernet, CAN, RS, MIL-STD, etc.). To do this, just write an exchange process that implements the appropriate interface and interacts with SM. However, the rest of the system will not require modification.

A brief description of the ready-made components included in libuniset

Ready-made components are already completed programs (processes) that “know how” to interact with SharedMemory and make it easy to “deploy” distributed systems. The following ready-made components are available in the libuniset library:
  • SharedMemory - storage of "variables";
  • IOControl - work with input / output cards;
  • ModbusMaster - implementation of Modbus TCP / RTU master mode;
  • ModbusSlave - implementation of Modbus TCP / RTU slave mode;
  • UNetExchange - UDP communication;
  • LogicProcessor - a component that allows you to describe algorithms based on logical circuits (written in an xml file);
  • DBServer_MySQL - a server for interacting with the MySQL database;
  • DBServer_SQLite - a server for working with SQLite.

Utilities included with libuniset

As we worked on projects and developed the library's capabilities, various auxiliary utilities began to be included in it, allowing us to set up projects created using it. Here is a list of basic utilities with a brief description:
A group of utilities for working with sensors:

  • uniset-admin - a multifunctional console utility that allows you to write / read the status of sensors, but also has 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 a sensor (or group of sensors).

Utilities for working with network protocols:

  • uniset-mbtcpserver-echo - simulator Modbus TCP Slave device;
  • uniset-mbtcptest - Console utility that allows interrogating (checking) devices using Modbus TCP protocol (Master mode);
  • uniset-mbrtuslave-echo - simulator Modbu RTU Slave device;
  • uniset-mbrtutest - Console utility that allows you to interrogate (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 input-output cards;
  • uniset-iocalibr - calibration of analog sensors;
  • uniset-codegen - generator of the skeleton of the control process.

Additional projects

The libuniset library's programming interface (API) has stabilized for a long time, and gradually, in addition to it, various auxiliary programs have appeared. Since the purpose of this article is to get to know libuniset specifically, we restrict ourselves only 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 communication, etc.
  • uniset-testsuite - a set of utilities (a separate project) for creating special test scripts that allow automatic (regression and not only) tests of a system built on the basis of libuniset.
  • uniwidgets - a library for building graphical interfaces based on gtkmm, interacting using libuniset.


The libuniset library allows you to quickly create "complex" systems. In some ways, it is ideologically similar to SCADA systems, but it should be borne in mind that this is only a superficial similarity: in this case, the user is given complete control over the system, the ability to program any algorithms (in C ++). Although it should be noted that a system built on libuniset can be easily integrated into any existing system (based on SCADA) - simply 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 critical projects, where it has proved itself to be a reliable system (24x7x365).

Related Links

Update : Continuing the theme new version

Also popular now: