# What is Monokot Server?

Monokot Server is a cross-platform OPC UA server designed for distributed industrial automation systems (Industry 4.0) and Internet of Things. The server is compatible with Windows, Linux and macOS operating systems and x64/ARM/ARM64 hardware platforms. Built-in script module based on JavaScript allows you to flexibly convert input data from field devices to output OPC UA variables.

Supported drivers for interaction with external devices and services:

* Modbus TCP, RTU over TCP, RTU, ASCII (as master or slave).
* S7 protocol for Siemens devices via Ethernet.
* SNMP v1 and SNMP v2c.
* InfluxDB Connector (representation of time series fields as OPC UA items).
* IEC 60870-5-104 (TCP/IP client).
* OPC UA Client (access to external OPC UA servers).

The server provides the ability to publish and store industrial data as time series using the following drivers:

* InfluxDB.
* PostgreSQL.
* Oracle Database.
* MS SQL Server.
* MySQL.
* REST Client.

Supported OPC UA communication services:

* Data Access.
* History Access.
* Methods.

The server supports remote administration, which makes it possible to deploy it on operating systems without a graphical shell.


# Quickstart

In this 5–10 minute guide, you will set up communication with a Modbus TCP device and create several tags available for the OPC UA client. If you do not have Monokot Server, go to[ ](https://www.monokot.io/download/)[<mark style="color:blue;">this</mark>](/basics/installation) section to download and install it.

### Connection to Monokot Server <a href="#h.26ahlvn04b2v" id="h.26ahlvn04b2v"></a>

1. Open Monokot Server Administrator
2. Create a new connection or just click the *Connect* button to connect to the local server
3. Please wait until the main application window opens

### Configuring Modbus TCP Device <a href="#h.g6g8jfvgg34d" id="h.g6g8jfvgg34d"></a>

1. In the *Server Explorer* pane, double-click on *Devices* to open the device manager

![](/files/umFWVQyYUvAMgTdojtGa)

2. In the device manager, click on the *New Device* button
3. In the drop-down menu, select *Modbus TCP*
4. On the settings pane, enter the IP address of the target device and slave ID (if required)

### Creating Tags <a href="#h.ux81zl8bzqaa" id="h.ux81zl8bzqaa"></a>

1. In the *Server Explorer* pane, double-click on *Tags* to open the tags manager

![](/files/aZaWjStfb3opBL9GqQUg)

2. In the tags manager, click on the *New Group* button
3. Double-click on the new group, name it as **MyModbusTags** and press the Enter key
4. Click on the *New Tag* button
5. To associate the tag with a device, double-click on the *Device* cell
6. Click on the *...* button in the device cell
7. In the device selector dialog window, select the **Device1** and click the *OK* button
8. Double-click on the *Address* cell
9. To specify Modbus register, in the address editor, type **300000\@WORD** and press the Enter key or use graphical address editor by clicking on the *Pen* button. Thus, the tag will be addressed to the first register of the Internal Registers area in the Word format
10. Click on the *New Tag* button and associate the created **Tag2** with **Device1**
11. Set address **400001.3** to **Tag2**. Thus, the tag will be addressed to the fourth bit of the second register from the Holding Registers area
12. To make your changes take effect, click on the *Sync* button (on the top panel) or press the F5 key

After the changes are synchronized with the server, the **Tag1** and **Tag2** will be associated with the specified registers and will become available to the OPC UA client.

### Testing by Third-party OPC UA client <a href="#h.gvnzwlpaxsg" id="h.gvnzwlpaxsg"></a>

In the OPC UA client, connect to the Monokot Server using the following endpoint parameters:

* Endpoint URL - **opc.tcp\://localhost:43043/MonokotOPC**
* Security Policy - **None**
* Authentication Mode - **Anonymous**

Now you can see the created tags and device in the object browser of your OPC UA client.

![](/files/dbJne3BQnLgABBv7KuXv)


# Supported OS and Hardware

Before starting to use Monokot Server and Monokot Server Administrator please carefully review the list of supported operating systems and hardware:

### Windows

| **Operating System**                     | **Architectures** | **Note**                 |
| ---------------------------------------- | ----------------- | ------------------------ |
| Windows 7 SP1\*                          | x64               | not supported officially |
| Windows 8.1                              | x64               |                          |
| <p>Windows 10 (1607 and later)<br></p>   | x64               |                          |
| <p>Windows Server 2012 and later<br></p> | x64               |                          |

\* Windows 7 SP1 with [<mark style="color:blue;">Extended Security Updates</mark>](https://docs.microsoft.com/troubleshoot/windows-client/windows-7-eos-faq/windows-7-extended-security-updates-faq) installed.

### Linux

| **Operating System**                                       | **Architectures**          | **Note** |
| ---------------------------------------------------------- | -------------------------- | -------- |
| Red Hat Enterprise Linux 7 and later\*                     | x64                        |          |
| <p>CentOS 7 and later\*<br></p>                            | x64                        |          |
| <p>Fedora 33 and later\*<br></p>                           | x64                        |          |
| <p>Debian 9 and later\*<br></p>                            | <p>x64, ARM, ARM64<br></p> |          |
| Ubuntu 18.10 and later\*                                   | x64, ARM, ARM64            |          |
| Linux Mint 18 and later\*                                  | x64                        |          |
| openSUSE 15 and later\*                                    | <p>x64<br></p>             |          |
| <p>SUSE Enterprise Linux (SLES) 12 SP2 and later\*<br></p> | <p>x64<br></p>             |          |
| <p>Alpine Linux 3.12 and later\*<br></p>                   | <p>x64, ARM64<br></p>      |          |

\* In the latest versions of Linux, there is an incompatibility of libssl. The solution to the issue is described in the [<mark style="color:blue;">Installation section</mark>](/basics/installation#linux-and-macos).

{% hint style="warning" %}
Because the server depends on armv7 instructions all models of generation Raspberry Pi 1 are not supported. Please use generation Raspberry Pi 2 or above
{% endhint %}

### macOS

| **Operating System**                         | **Architectures** | **Note** |
| -------------------------------------------- | ----------------- | -------- |
| <p>macOS High Sierra 10.13 and later<br></p> | x64               |          |

The server is compatible with ARM/ARM64 hardware platforms if they support Armv7 instructions


# Installation

To install the server and the server configurator, download the archive corresponding to your operating system and hardware platform architecture and unpack it:

* Windows-x64 ([<mark style="color:blue;">https://monokot.io/download/mos-windows-x64-latest</mark>](https://monokot.io/download/mos-2.0.6068.25731-full-win-x64.zip))
* Linux-x64 ([<mark style="color:blue;">https://monokot.io/download/mos-linux-x64-latest</mark>](https://monokot.io/download/mos-2.0.6068.25731-full-linux-x64.tar.gz))
* Linux-arm ([<mark style="color:blue;">https://monokot.io/download/mos-linux-arm-latest</mark>](https://monokot.io/download/mos-2.0.6068.25731-full-linux-arm.tar.gz))
* Linux-arm64 ([<mark style="color:blue;">https://monokot.io/download/mos-linux-arm64-latest</mark>](https://monokot.io/download/mos-2.0.6068.25731-full-linux-arm64.tar.gz))
* macOS-x64 ([<mark style="color:blue;">https://monokot.io/download/mos-osx-x64-latest</mark>](https://monokot.io/download/mos-2.0.6068.25731-full-osx-x64.zip))

### Windows

Prerequisites for Windows 7 SP1, ESU:

* KB3063858 ([<mark style="color:blue;">https://www.microsoft.com/en-us/download/details.aspx?id=47442</mark>](https://www.microsoft.com/en-us/download/details.aspx?id=47442))
* Microsoft Visual C++ 2015–2019 ([<mark style="color:blue;">https://aka.ms/vs/16/release/vc\_redist.x64.exe</mark>](https://aka.ms/vs/16/release/vc_redist.x64.exe))

Prerequisites for Windows 8.1, Windows Server 2012:

* Microsoft Visual C++ 2015–2019 ([<mark style="color:blue;">https://aka.ms/vs/16/release/vc\_redist.x64.exe</mark>](https://aka.ms/vs/16/release/vc_redist.x64.exe))

To install the server and the server configurator, please **run install.bat as an administrator** and follow the instructions. If you are using a firewall, then you need to create rules for ports 9881 and 43043. By default, port 9881 is used for server configuration, and port 43043 is used for OPC UA connections.

{% hint style="info" %}
Make sure that copying files has not been blocked by antivirus
{% endhint %}

### Linux and macOS

To install the software, open a terminal and run the following commands:

```bash
cd path_to_unzipped_files_mos-x.x.x.x-full-platform-arch
sudo bash ./install.sh
```

{% hint style="info" %}
**rsync** is required for successful installation
{% endhint %}

Enter the administrator password and press Enter then follow the steps suggested by the installation script. To start the server, you need systemd and launchd for Linux and macOS, respectively. Executable files: Monokot Server - server/mosconsole, Monokot Server Administrator - admin/mosadmin (macOS -> admin/Monokot Server Administrator.app/Contents/MacOS/mosadmin). &#x20;

### About Libssl

On fresh Linux distros (such as Ubuntu 22.04.2), the software does not start due to the incompatibility of the libssl library. The solution below is tested on Ubuntu 22.04.2.

If you have already tried to install the software, then first you need to remove it from the computer, to do this, run the following command:

```bash
# Default installation folder /opt/Monokot
sudo rm -rf /opt/Monokot
```

Next, download and install the missing version of libssl, to do this, run the following commands:

```bash
# arm
# wget http://ports.ubuntu.com/pool/main/o/openssl1.0/libssl1.0.0_1.0.2n-1ubuntu5.13_armhf.deb
# sudo dpkg -i libssl1.0.0_1.0.2n-1ubuntu5.13_armhf.deb

# arm64
# wget http://ports.ubuntu.com/pool/main/o/openssl1.0/libssl1.0.0_1.0.2n-1ubuntu5.13_arm64.deb
# sudo dpkg -i libssl1.0.0_1.0.2n-1ubuntu5.13_arm64.deb

# x64
wget http://security.ubuntu.com/ubuntu/pool/main/o/openssl1.0/libssl1.0.0_1.0.2n-1ubuntu5.13_amd64.deb
sudo dpkg -i libssl1.0.0_1.0.2n-1ubuntu5.13_amd64.deb
```

and run the installation script again.

### About Libicu

To successfully launch Monokot Server Administrator, libicu must be installed (the issue is observed on Ubuntu 23.10). It can be installed using the following commands:

```bash
# arm
# wget http://ports.ubuntu.com/pool/main/i/icu/libicu70_70.1-2_armhf.deb
# sudo dpkg -i libicu70_70.1-2_armhf.deb

# arm64
# wget http://ports.ubuntu.com/pool/main/i/icu/libicu70_70.1-2_arm64.deb
# sudo dpkg -i libicu70_70.1-2_arm64.deb

# x64
wget http://en.archive.ubuntu.com/ubuntu/pool/main/i/icu/libicu70_70.1-2_amd64.deb
sudo dpkg -i libicu70_70.1-2_amd64.deb
```

### Firewall

If you are using a firewall, then you need to allow incoming connections.

#### Linux:

Open a terminal and run the following commands:

```bash
sudo iptables -I INPUT -p tcp --dport 9881 -j ACCEPT # 9881 is for configuration
sudo iptables -I INPUT -p tcp --dport 43043 -j ACCEPT # 43043 is for OPC UA clients
```

#### macOS:

Apple menu -> System Preferences -> Security & Privacy -> Firewall,\
click on the + button and select the mosconsole executable file (default directory - /Library/Application Support/Monokot/Monokot Server)


# Licensing

Server communication features such as Modbus Connectivity or InfluxDB Connectivity are licensed server components. Licensing is performed using software or hardware keys. Software license keys are perpetual and assigned to a specific device. Without a purchased license, server can operate in two modes:

* with limited functionality
* with full functionality for 3 hours

When connectivity switches to demo mode, the following warning will appear in the server event log:  **Demo timer for 'XXX Connectivity' started. Demo time expires in 180 minutes**. Upon expiration of the demo period, the warning **Demo period for 'XXX Connectivity' has expired** will appear in the event log and all tags using this connectivity will go into the **BadLicenseExpired** status.

To reset the demo period timer, you have to restart the service/process/daemon or reinitialize the server. To reinitialize the server in Monokot Server Administrator, connect to the server and click the *Reinitialize Server* button on the *General* tab.

Components licensing and limitations (summary table)

| **Component**                           | **Licensing Method**                         | **Limitations**                                                                                                                                                                                                                                               |
| --------------------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Modbus Connectivity                     | By number of tags used                       | <p>Up to 16 tags / Up to 1 device<br></p>                                                                                                                                                                                                                     |
| Siemens Connectivity                    | By number of tags used                       | Up to 16 tags / Up to 1 device                                                                                                                                                                                                                                |
| InfluxDB Connectivity                   | By total number of tags and time series used | <p>Up to 16 tags (time series) / Up to 1 device (store); Immediately switches to demo mode when attempting a historical read (using OPC UA)<br></p>                                                                                                           |
| MongoDB Connectivity                    | By number of time series used                | <p>Up to 16 time series / Up to 1 store<br></p>                                                                                                                                                                                                               |
| REST Connectivity                       | By number of time series used                | <p>Up to 16 time series / Up to 1 store<br></p>                                                                                                                                                                                                               |
| PostgreSQL Connectivity                 | By number of time series used                | <p>Up to 16 time series / Up to 1 store; Immediately switches to demo mode when attempting a historical read (using OPC UA)<br></p>                                                                                                                           |
| <p>Oracle Database Connectivity<br></p> | By number of time series used                | Up to 16 time series / Up to 1 store; Immediately switches to demo mode when attempting a historical read (using OPC UA)                                                                                                                                      |
| <p>MS SQL Connectivity<br></p>          | By number of time series used                | Up to 16 time series / Up to 1 store; Immediately switches to demo mode when attempting a historical read (using OPC UA)                                                                                                                                      |
| <p>MySQL Connectivity<br></p>           | By number of time series used                | Up to 16 time series / Up to 1 store; Immediately switches to demo mode when attempting a historical read (using OPC UA)                                                                                                                                      |
| SNMP Connectivity                       | By number of tags used                       | Up to 16 tags / Up to 1 device                                                                                                                                                                                                                                |
| <p>IEC 60870-5-104 Connectivity<br></p> | By number of tags used                       | Up to 16 tags / Up to 1 device                                                                                                                                                                                                                                |
| OPC UA Connectivity                     | By number of tags used                       | Up to 16 tags / Up to 1 device                                                                                                                                                                                                                                |
| Expressions (Scripts) Plugin            | Only special features require licensing      | <p>The feature immediately switches to demo mode if extra functions are called (from MosUtils.setXXXProperty, MosOdbc, MosDirectories, MosFiles, MosProcess objects); Immediately switches to demo mode when trying to call the method (using OPC UA)<br></p> |

A license must be purchased for **each physical device** that hosts the server. It is linked to the device using the **Device ID**, which is generated using a special procedure. Licenses cannot be transferred from one device to another; if after activating the license the device malfunctions (or its components), please contact [<mark style="color:blue;">support@monokot.io</mark>](mailto:support@monokot.io).

### Installing a Hardware License

The hardware license key is a driverless device, so you just need to connect the USB-dongle to your computer and restart (or reinitialize) the server. If you need an extra feature after purchasing a hardware key, the key can be upgraded remotely. Thus, there is no need to purchase an additional hardware key. To upgrade your hardware key please contact [<mark style="color:blue;">support@monokot.io</mark>](mailto:support@monokot.io).

{% hint style="warning" %}
Please note that the current server version does not support hardware keys for ARM64
{% endhint %}

### Installing a Software License via the Monokot Server Administrator <a href="#h.yz9ns14x5bz7" id="h.yz9ns14x5bz7"></a>

First, you need to obtain the Device ID for the server on which you want to install the license. To do this, connect to server and on the *Server Explorer* pane click on *General*. Go to the *Licenses* tab, click on *Save Device ID As...* button and specify the path and the file name; that way you will save the Device ID of the target server to your computer.

![](/files/ancZZQQ7EKJppQWALUN1)

In the menu of the main window, select *Tools* → *Activation Wizard*, and the license activation wizard will open. Follow all of the steps listed by the activation wizard. Upon completion of the activation process, you will receive an email (within 10–15 minutes) with the license file. Save it to your computer.

On the *Licenses* tab, click on the *Upload License(s)...* button. A window for uploading the licenses to the server will open. Click on the *Browse…* button, select one or more license files, click on the *Upload* button and wait until the files are uploaded. **To complete the licensing process, restart the server service/process/daemon**.


# OPC UA

To interact with external systems (such as SCADA), the server implements the data access features via OPC UA. OPC UA – is a modern technology for communication in the fields of industrial automation, Internet of Things (IoT), etc. Technology provides opportunities for encryption of transmitted data and authentication/authorization of users. Available features and OPC UA settings are described below.


# UA TCP Endpoint

This section describes the settings associated with the connection point (endpoint). Endpoint determines the connection address and the required security modes that OPC UA clients must use.

{% hint style="info" %}
Monokot OPC Server provides communication for OPC UA clients only using the UA TCP protocol (binary data transfer protocol). Default UA TCP endpoint is opc.tcp\://localhost:43043/MonokotOPC or opc.tcp\://localhost:43043
{% endhint %}

* Port – specifies the port to connect to the UA TCP endpoint (by default 43043)
* Channel Lifetime – specifies the number of milliseconds, after which the server frees up resources for the channel

{% hint style="info" %}
If you use firewall you must add the incoming connections rule for OPC UA clients
{% endhint %}

The TCP UA endpoint allows you to encrypt and verify authenticity of transmitted data and provides the following security policies:

* None – allows for transfer of data without encryption
* Basic128Rsa15, Basic256, Basic256Sha256 – allows you to transfer encrypted data in different modes

After changing and synchronizing the settings described above the OPC UA server will be automatically restarted.

A custom security certificate can be specified for UA TCP Endpoint. To do this, you need to import the certificate from a PFX file. To import a custom security certificate, open the *OPC UA* manager in Monokot Server Administrator and switch to the *UA TCP Endpoint* tab.

![](/files/9pYYDkgm3TofEsfZmMj1)

Click the *Import* button and choose the PFX file. Enter password for the certificate (if no password is used, leave the field empty) and click *OK*. For the changes to take effect on the server, click *Sync* or press the F5 key. The UA TCP Endpoint tab also offers the following possibilities:

* To reissue the security certificate
* To reset the custom security certificate to the server’s default certificate
* To export the certificate (public key) to a CRT file


# UA Settings

This section describes the general communication settings of the OPC UA server.

**Allow Anonymous Login:** allows OPC UA client not to provide username and password when opening a connection.

**Enable UA TCP Endpoint:** allows connection to the OPC UA Server using the UA TCP protocol (binary protocol).

{% hint style="info" %}
Please note that by default anonymous connection to the OPC UA server is allowed
{% endhint %}

**Max Notification Queue Size:** specifies the maximum number of notifications stored in the queue for each monitored data change item.

**Max Notifications per Publish:** indicates the maximum number of messages sent in one publication response.

**Max Message Queue Size:** specifies the maximum number of sent messages that are saved in the queue for each subscription.

**Min Session Timeout:** indicates the minimum number of milliseconds during which the session remains open.

**Max Session Timeout:** specifies the maximum number of milliseconds during which the session remains open.

**Max Session Count:** indicates the maximum number of simultaneous sessions.

**Max Browse Continuation Points:** specifies the maximum number of continuation points used in Browse/BrowseNext operations.

**Min Subscription Lifetime:** sets the minimum subscription lifetime, which can be specified by OPC UA client when creating a subscription.

**Max Subscription Lifetime:** sets the maximum subscription lifetime, which can be specified by OPC UA client when creating a subscription.

**Min Publishing Interval:** sets the minimum subscription publishing interval, which can be specified by OPC UA client when creating a subscription.

**Max Publishing Interval:** sets the maximum subscription publishing interval, which can be specified by OPC UA client when creating a subscription.

**Min Sampling Interval:** sets the minimum sampling rate, which can be specified by OPC UA client when creating a monitoring item.

After changing and synchronizing the settings described above the OPC UA server will be automatically restarted.


# Client Certificates

Security certificates are used to verify the authenticity of an OPC UA client (on the server side), authenticity of an OPC UA client (on the client side) and to encrypt. In order to establish secure connection between the OPC UA client and the OPC UA server, they must add the security certificates given to them to the repository as "trusted". There is a special repository intended for working with client security certificates in Monokot Server. It allows you to import, reject or confirm client security certificates.

When an OPC UA client trying establish secure connection to the OPC UA server, a client security certificate will automatically be placed in the repository as “rejected” if it was not added before as “trusted”.

The default UA TCP endpoint security certificate is a self-signed certificate that was created when the server was first started. Click here to learn more about the default server security certificate.

### How to: Adding a security certificate to the security certificates repository as "trusted" using Monokot Server Administrator <a href="#h.m8tuj2ghfc9l" id="h.m8tuj2ghfc9l"></a>

To add an OPC UA security certificate to the repository as "trusted" in *Server Explorer* pane, double-click on *OPC UA* and go to the *Client Certificates* tab.

![](/files/60yoTaRGkhwkd21SHxMn)

### If you have the client security certificate of OPC UA client on your computer: <a href="#h.gvt4okbhmmfa" id="h.gvt4okbhmmfa"></a>

Click on the *Import* button and select one or more certificates. The certificates will appear on the client as “trusted”. Click on the *Sync* button to transfer the added security certificates to the server. Now the OPC UA client can connect to the OPC UA server via a secure connection.

### If you do not have the OPC UA client security certificate on your computer: <a href="#h.rezj1af7jmx2" id="h.rezj1af7jmx2"></a>

Connect the OPC UA client to the OPC UA server via a secure connection. Connection is not established and the client will return the error **BadCertificateUntrusted** or **BadSecurityChecksFailed**. The OPC UA client security certificate will automatically be added to server repository as "rejected". Click on the *Sync* button, the “rejected” certificate will appear in the table of certificates.

![](/files/ZrheuRVa4kEUSY1eEfHe)

Select the certificate and click on "Trust" button and then click on the *Sync* button to trust the security certificate on the server. Now the OPC UA client can connect to the OPC UA server via a secure connection.

The parameter **Client Certificate Validation Mode** specifies client security certificate validation mode and has the following values:

* Accept Any (no validation)
* Verify by Operating System (the most rigorous way of certificate validation; builds a trusted certificate chain using the operating system certificate store with validation of domain name, certificate expiration date, etc.)
* Trusted Certificates List (successfully validated if the certificate is in the certificate list and is trusted)
* Trusted CA’s List (successfully validated if it is possible to build a trust chain to any of the trusted certificates on the list).

Note that if you select the Accept Any or Verify by Operating System mode, the client security certificate will not be added to the certificate list when the client tries to establish a secure connection. If the Trusted Certificates List or Trusted CA's List mode is selected, automatic addition of a client certificate is regulated by the **Automatically add a client certificate as "untrusted"** parameter.

![](/files/XeOykrJxx029UnnF1JPx)


# Aliases

Aliases are designed to map existing bindings on OPC UA items (for example, defined in HMI/SCADA) to OPC UA items that are defined in the server. This can be useful when upgrading an existing automation system to prevent changing bindings on OPC UA items in an existing HMI/SCADA application. Aliases can also be used to better structure server objects, such as combining tags and expressions into a single virtual structure. Aliases can only be defined for string identifiers.

To start configuring aliases, open Monokot Server Administrator, double-click the *OPC UA* in the *Server Explorer* pane, and then click the *Aliases* tab.

![](/files/GDskuh9sv5InvAn5V8kf)

{% hint style="info" %}
In Monokot Server Administrator, you can import / export aliases from / to a CSV file
{% endhint %}

The following parameters are available for the alias:

**ID**: Specifies the unique numeric identifier of the alias.

**Namespace Index**: Specifies the index for the source namespace to be replaced with the server namespace (ns=2). A value of -1 indicates that any source index should be replaced with ns=2.

**Node ID/Pattern**: Specifies the OPC UA identifier or template that the source OPC UA identifier should match. The value is case sensitive.

**Replacement**: Specifies the OPC UA identifier or template to match the resulting (modeled) OPC UA identifier.

**Type**: Specifies the type of alias. There are two types of aliases provided:

* Simple
* Based on a regular expression (Regex)

A simple alias matches the source OPC UA ID of the item and replaces it with the target OPC UA ID. For example, consider the following alias:

| **Namespace Index** | **Node ID/Pattern**             | **Replacement**     | **Type** |
| ------------------- | ------------------------------- | ------------------- | -------- |
| -1                  | ModbusTcpChannel.RTU001.Current | Tags.RTU001.Current | Simple   |

Now the client's OPC UA attempt to add an OPC UA item with the ID *ns=3;s=ModbusTcpChannel.RU 001.Current*, will be successful if there is a tag with the address *Tags.RTU001.Current* in the server. The problem with simple aliases is that they are mapped one-by-one and for a large project (for several thousand tags) this can negatively affect server performance, both in design-time mode and in run-time mode.

Regular expression-based aliases are a more flexible and productive type of alias. It allows you to set mapping based on a template. For example, consider the following alias:

| **Namespace Index** | **Node ID/Pattern** | **Replacement** | **Type** |
| ------------------- | ------------------- | --------------- | -------- |
| -1                  | ^ModbusRtuChannel   | Tags            | Regex    |

This alias will transform all the source OPC UA items IDs starting with ModbusRtuChannel, where the ModbusRtuChannel string will be replaced with Tags, for example:

```
ns=3;s=ModbusRtuChannel.RTU004.Current → ns=2;s=Tags.RTU004.Current
ns=1;s=ModbusRtuChannel.SWT-10.Link → ns=2;s=Tags.SWT-10.Link
ns=2;s=ModbusRtuChannel.Pump.Plc.CpuAvg → ns=2;s=Tags.Pump.Plc.CpuAvg
```

Consider an example of another regular expression-based alias:

| **Namespace Index** | **Node ID/Pattern**           | **Replacement** | **Type** |
| ------------------- | ----------------------------- | --------------- | -------- |
| -1                  | ^ModbusRtuChannel\\..\*\\.RTU | Tags.Area1.RTU  | Regex    |

This alias will transform the IDs of the source OPC UA items as follows:

```
ns=3;s=ModbusRtuChannel.Group1.SubGroup1.RTU004.Current → ns=2;s=Tags.Area1.RTU004.Current
ns=3;s=ModbusRtuChannel.MyGroup.RTU100.Power → ns=2;s=Tags.Area1.RTU100.Power
```

A detailed description of the language for substitutions in regular expressions is provided [<mark style="color:blue;">here</mark>](https://docs.microsoft.com/en-us/dotnet/standard/base-types/substitutions-in-regular-expressions). To test the template, you can use the online service located [<mark style="color:blue;">here</mark>](http://regexstorm.net/tester). Substitutions in regular expressions are a flexible tool for automatic conversion of source identifiers; they allow you to make all sorts of substitutions and permutations. The pattern of the source string can be very complex, both for human understanding and computationally. To limit the maximum execution time of a regular expression, the Alias Max Execution Time parameter is provided (by default, 1 second).

By default, aliases are used only if the requested OPC UA item cannot be found, this behavior is the most productive, but it can be changed by setting Alias Usage Mode.

![](/files/LIEr80pudrINwDjqWbLv)


# Access to Object Settings

Most server objects such as tags, devices, time series, etc. are represented as items of the OPC UA hierarchy.

The server offers the possibility to read and write most of the control and diagnostic properties of objects defined on the server. For example, through the OPC UA client you can change the host for a Modbus TCP device, set the update rate for a tag, etc. By default, access to the properties of the server objects is set to read-only mode. For tags, tag groups, time series and time series groups, properties are also not available for browsing through the OPC UA client.

{% hint style="info" %}
Browsing properties of tags, tag groups, time series, and time series groups is not available by default in order to prevent creation of a large number of variables when importing OPC UA hierarchies into third-party systems such as SCADA
{% endhint %}

Access rights for specific categories of objects are configured in the security manager. After the credentials provided by the OPC UA client are associated with the role, the client will have access to the specified set of rights. By default, if the OPC UA client connects in  anonymous mode, the server cannot authorize the client with the necessary set of rights, and therefore it provides access to all categories of objects.

To enable properties writing for server objects, open the OPC UA manager in Monokot Server Administrator, go to the *Object Access* tab and select *Read/Write* in the *Access Mode to Object Properties* drop-down menu.

![](/files/vAHyU8kh42AbnxR2DrWM)

Click *Sync* for the changes to take effect on the server. Other options available on the *Object Access* tab include:

* Allow access to object properties when connecting to the server in anonymous mode (enabled by default)
* Browse tag properties for OPC UA client
* Browse tag group properties for OPC UA client
* Browse time series properties for OPC UA client
* Browse time series group properties for OPC UA client
* Browse expression properties for OPC UA client
* Browse expression group properties for OPC UA client


# Troubleshooting

**Issue:** Unable to connect the OPC UA client to the OPC UA server via a secure connection. All the necessary security certificates were added to repository as "trusted", but the client returns the **BadInvalidTimestamp** error.

**Solution:** Synchronize time between the client and server computers.


# Security Certififcate

The server security certificate is used to establish communication between the server and the HTTPS client (such as Monokot Server Administrator), and is also the default certificate of the OPC UA application. During the first start-up, the server creates a self-signed security certificate and saves it in the following directories:

* **Windows:** *%ProgramData%\Monokot\Mos\Certificates\Own\ (C:\ProgramData\Monokot\Mos\Certificates\Own)*
* **Linux:** */usr/share/Monokot/Mos/Certificates/Own/*
* **macOS:** */usr/local/Monokot/Mos/Certificates/Own/*

{% hint style="info" %}
Please note that these directories are hidden file system directories
{% endhint %}

The certificate is saved in PFX and DER formats (files monokotserver.pfx and monokotserver.der); the PFX file is then used as a server certificate each time the server starts. If the server cannot find or read the monokotserver.pfx file during boot, it will reissue the certificate, and a warning will be written to the server event log.

To install a custom server security certificate, replace the monokotserver.pfx file with the required certificate in PFX format.

{% hint style="info" %}
Please note that the PFX file must not be password protected. An empty string should be used as password
{% endhint %}

After replacing the file, you need to restart the service/process/daemon for the changes to take effect.


# Users & Roles

The server provides a system of access rights and privileges to ensure security. Its main function is verification of authenticity (authentication) and giving the client access to certain rights (authorization). The authentication mechanism provided by the client authenticates the username and password provided by the client compared to the user existing in the system, which is authorized according to the specified role.&#x20;

User represents the server user with the specified login, password and role set. User lists are used for authentication of OPC UA clients and clients that administer the server. By default, the server has a blank password for the admin. You cannot rename, delete or modify the admin user, but you can change its password.

{% hint style="info" %}
To reset the administrator password to the default (blank), you must run the utility **resadmpwd** from the server root folder and restart server service/process/daemon
{% endhint %}

{% hint style="info" %}
User name is case-sensitive
{% endhint %}

Role represents the set of rights available to the user. Roles restrict the rights associated with server administration and data access. The following are the categories of rights and their description.

| **Category**                         | **Permissions**                                                                                                                                                                                                   |
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| General                              | <ul><li>Connect, data synchronization and read server information (licenses, time, etc)</li><li>Download configuration</li><li>Reinitialize server</li><li>Upload configuration</li><li>Upload licenses</li></ul> |
| Security                             | <ul><li>Create role</li><li>Create user</li><li>Delete role</li><li>Delete user</li><li>Update role</li><li>Update user</li></ul>                                                                                 |
| Devices                              | <ul><li>Create device</li><li>Delete device</li><li>Update device</li><li>Run command</li></ul>                                                                                                                   |
| Tags                                 | <ul><li>Create tag</li><li>Delete tag</li><li>Group action</li><li>Update tag</li></ul>                                                                                                                           |
| Time Series                          | <ul><li>Create time series</li><li>Delete time series</li><li>Group action</li><li>Update time series</li></ul>                                                                                                   |
| Data Access (via OPC UA and Web API) | <ul><li>Read Value</li><li>Write Value</li><li>Browsing</li><li>Write Diagnostics</li></ul>                                                                                                                       |
| OPC UA                               | <ul><li>Delete security certificate</li><li>Import security certificate</li><li>Trust/Reject security certificate</li><li>Update Settings</li></ul>                                                               |
| Stores                               | <ul><li>Create store</li><li>Delete store</li><li>Update store</li></ul>                                                                                                                                          |
| Scripts                              | <ul><li>Create module</li><li>Create expression</li><li>Delete module</li><li>Delete expression</li><li>Update module</li><li>Update expression</li><li>Execute expression</li></ul>                              |


# Administrator GUI

Monokot Server Administrator is a GUI application for managing and configuring the Monokot Server. It is intended primarily for configuring objects and server settings. The application does not perform the function of an OPC UA client, but provides a feature to write and read tags data for diagnostics and debugging. In this mode, the application communicates with the server via HTTPS.

After starting the application, a window for connecting to the server will appear. In this window, you can create, edit, delete or select the connection to the server.&#x20;

![](/files/7z9Y6NKXK1Sz56AWOTUK)

To connect to the server, select the desired connection and click on the *Connect* button. After successfully connecting to the server, the main application window will appear. The main application window is divided into three areas:

* Server explorer (on the left side of the main window)
* Main toolbar (at the top of the main window)
* Manager tabs (in the center of the main window)

![](/files/2qwsReTKIRdDmM0VhTUv)

In the *Server Explorer* pane, various managers will be available to configure server objects and its settings.

![](/files/EHBM62pMm8vMvkf2bga3)

The main toolbar contains the following buttons:

* *Settings*. It allows you to specify server connection parameters (such as timeout, username, etc)
* *Undo and Redo*. They allow you to cancel/repeat the action taken by the user. Please note that after synchronization with the server, the undo and redo actions are unavailable.
* *Sync*. It allows you to synchronize application state with the server.
* *Upload Config*. It allows you to upload the server configuration from file to the server.
* *Download Config*. It allows you to download the server configuration to the specified file.

![](/files/YR68hM12hohtXbMVq8Vu)


# Event Log

The event log records errors, warnings and informational messages that occur during server operation, and is a diagnostic and troubleshooting tool. The event log is stored in the root folder of the server in the logs subfolder. Event log can be viewed via the Monokot Server Administrator or Web API.

To open a event log in the Monokot Server Administrator, on the *Server Explorer* pane double-click on *General* and go to *Event Log* tab.

![](/files/xyOFWgs0d7R4y5oYDnoQ)

You can sort the event log by message type, date and time, message source by clicking on the corresponding column in the table. To save the event log to a file click the *Save...* button and specify the path and file name. To view the current version of the event log, click on the *Refresh* or *Sync* button. Use *Errors*, *Warnings* or *Messages* checkboxes to filter messages by type.


# Users in Monokot Server Administrator

To open a user manager in the Monokot Server Administrator, on the *Server Explorer* pane double-click on *Users*.&#x20;

![](/files/BpYBvzMyUvumyirl51oF)

The manager allows you to create, copy, delete users and assign passwords to them. To perform the listed actions, use the manager toolbar, the context menu and Ctrl + C, Ctrl + V, Insert, Delete keys. Please note that when copying a user it retains the password of the original user.


# Roles in Monokot Server Administrator

To open a role manager in the Monokot Server Administrator, on the *Server Explorer* pane double-click on *Roles*.&#x20;

![](/files/10PIKEvduJUZGDPaBiHQ)

The manager allows you to create, copy, delete roles and set their privileges. To perform the listed actions, use the manager toolbar, the context menu and Ctrl + C, Ctrl + V, Insert, Delete keys.


# Startup Parameters

Server startup parameters are set in the **server.ini** file in the root folder of the server. For the new values of parameters to take effect, you must restart the server service/process/daemon. The following is a description of the available parameters:

* **ServerUid:** specifies the global identifier of the server, which is generated after the first startup. Intended for internal use.
* **Port:** specifies the number of the port, on which the server is running.
* **DetailLog:** indicates that a detailed event log of the server must be generated ("True" or "False"). You can only read the detailed log in the logs folder.
* **SafeMode**: specifies whether the server should be run in safe mode. Takes True or False as values. When the server is launched in safe mode, the OPC UA modules, scripts, devices and stores do not perform the execution time actions.
* **MinWorkerThreads**: specifies the minimum number of worker threads in the thread pool. Affects server performance. Accepts values from -1 to 2147483646.
* **EnableRemoteConnection:** enable remote server management ("Yes" or "No").

{% hint style="warning" %}
Remote server management is enabled by default
{% endhint %}

* **EnableCompression:** enable compression of HTTP responses ("Yes" or "No").
* **ReissueServerCert:** indicates that the server security certificate must be re-issued ("True" or "False"). After the server is restarted, parameter sets to "False".
* **ServerCulture:** specifies the culture from which the server is running. The parameter affects how the server logs events and parse the time, date and floating-point numbers during conversion from string format.
* **BacklogPath**: specifies the directory where store backlog files are saved. You can learn more about backlog [<mark style="color:blue;">here</mark>](/time-series-and-stores/stores/backlog).


# Devices

**Device** is a driver used for interacting with an external data source (a PLC, sensor, database, etc.) in read and write modes.&#x20;

**Subdevice** represents a child element of the device and works with the **same communication channel** as the parent device. Each subdevice has a specific priority with which it will access the communication channel. Highest priority value means that the subdevice will gain access first. The parent device always has the highest priority.&#x20;

The concept of a device and subdevice allows for working with Modbus TCP/Modbus RTU interface converter (in bridge mode) if there is more than one node in the RTU network.

The current version of the server includes a set of drivers for:

* Modbus TCP, Modbus RTU over TCP and Modbus RTU/ASCII (cyclic driver).
* S7 protocol for Siemens S7-300/S7-400/S7-1200/S7-1500/Sinamics over Ethernet (cyclic driver).
* Simple Network Management Protocol v1 and v2c (cyclic driver).
* InfluxDB connector (represents time series fields as OPC UA items, cyclic driver).
* IEC 60870-5-104 TCP/IP Master (event-oriented driver).
* OPC UA Client (access to external OPC UA servers).

Cyclic driver perform reading and writing are performed cyclically at certain time intervals. The time interval depends on the update rate of tags associated with the driver and its settings.&#x20;

As well as executing cyclic polling protocols, all drivers are also ‘block’ polling drivers. The ‘block’ polling is used to achieve maximum data reading performance. For example:

* The Modbus driver reads data by organizing them into 120-byte blocks, which is much more efficient than reading one register at a time
* The SNMP driver reads blocks consisting of 25 OIDs, which is much more efficient than reading one OID at a time

The maximum size of the block can be changed in the device settings. By default, maximum allowed values are used.

After generating the blocks, the device groups them by update rate and device-specific characteristics. For example, the Siemens driver polls several addresses with the same update rate of 500 ms, of which two (address A and address C) belong to DB1, and the third (address B) belongs to DB20. With this configuration, the driver will create two blocks:

* 1st block (addresses A and C with 500ms update rate)
* 2nd block (address B with 500ms update rate)

In case the tag with address C has an update rate of 100 ms, the driver will create three block groups:

* 1st block (address A with 500ms update rate)
* 2nd block (address B with 500ms update rate)
* 3rd block (address C with 100ms update rate)

**All operations on generating blocks and block groups are performed by the driver automatically** without any user intervention.

To improve polling performance, several devices can be created to connect to the same data source. In this case, the source is polled asynchronously. This method is only suitable if the target data source is able to handle multiple connections at the same time.

Unlike the cyclic driver, the event-oriented driver does not send periodic requests to the device, but only initiates data transfer; most of the time it listens to the information channel analyzing the received traffic. During the traffic analysis, the driver queues the values for each tag associated with the driver. Note that in the case of event-oriented driver, the tag’s *Update Rate* determines what frequency the tag value queue will be processed with.


# Diagnostics

Diagnostic variables are available for device operation diagnostics. They are represented as OPC UA items and described below.

Only diagnostic variables that are common for all types of devices are described here

![](/files/O2xzxTP5hNR27kFnQWGB)

* **GoodResponses** (cyclic driver only): contains the total number of successful responses from the data source.
* **LastGoodResponseUtcTime** (cyclic driver only): contains the time of the last successful response from the data source in the UTC format.
* **BadResponses** (cyclic driver only): contains the total number of unsuccessful or unreceived (during loss of connection) responses from the data source.
* **LastBadResponseUtcTime** (cyclic driver only): contains the time of the last unsuccessful or unreceived response from the data source in the UTC format.
* **CommunicationEstablished:** contains that communication channel between the device and the data source has been established (True or False).
* **CommunicationLost:** inverted value of \_CommunicationEstablished.
* **DemoIsExpired:** contains that demonstration period for the device is expired.
* **MaxPollingDuration** (cyclic driver only): contains the longest reading time for a group of blocks in the device.
* **MaxScanDuration** (event-oriented driver only): specifies the maximum time (in milliseconds) it takes to parse data when listening to the channel.

The values of the diagnostic variables can be overwritten by the user. This requires that the user has the rights to write diagnostic parameters. Read more about this [<mark style="color:blue;">here</mark>](/basics/users-and-roles).


# Devices in the Monokot Server Administrator

To open the device manager in Monokot Server Administrator, on the *Server Explorer* pane click on the *Devices*.&#x20;

![](/files/HlRatDI85LglMorJx5QQ)

The manager allows you to create, copy, move and delete devices, as well as organize them into groups (only a single-level hierarchy is supported). To perform the listed actions, use the manager toolbar, the context menu and Ctrl + C, Ctrl + X, Ctrl + V, Insert, Delete keys.


# Tags

**Tag** represents the area of device data identified by the specific address. Address identifies the data type and the dimension (scalar or array). Tags are organized in a hierarchy, which forms the objects structure of the OPC UA items, where the folder is a group of tags, and a variable is a tag.


# Parameters

Description of tag parameters is shown below.&#x20;

* **Name:** is used for naming the data represented by the tag.
* **Device:** identifies the device the tag is associated with.
* **Address:** identifies the data area, as well as defines data type and dimension, and can affect the access rights. Address format depends on the specified device.
* **Update Rate:** determines how frequently a tag is updated (in milliseconds). The 0 value indicates that the tag must not be updated (but it will be available for writing).
* **Access:** defines the access rights provided to the client (Read/Write or Read Only). Access rights can also depend on the specified address, for example: Internal Modbus registers always have read-only access rights. How to specify the read and write access rights of a tag for a specific user is described below.
* **Converter:** specifies conversion applied to tag value. The following conversions are available: division by a specified number, linear scaling, logical “NOT” (available only for the boolean data type).
* **Comment:** contains any custom text.
* **Change Trigger**: specifies change notification mode.

Most of the parameters described above are available as OPC UA items. More information about editing server object properties via OPC UA is described [<mark style="color:blue;">here</mark>](/basics/opc-ua/access-to-object-settings).


# Change Trigger

### Change Trigger

Change trigger specifies what changes the tag should notify all "interested" consumers about (OPC UA variable, time series, etc.). The following values are available:

* **StatusValue** ensures the best performance, because in this mode the notifications are only sent after a change of status (for example, when the connection is lost) or value.
* **StatusValueTimestamp** is the most resource-intensive notification mode. In this mode, the tag will signal its change with the frequency specified in the *Update Rate*, regardless of whether the status or value of the tag has changed or not.

Change trigger affects the amount of data saved in the store if the tag is associated to a time series, as well as the filtering mode for OPC UA subscription.


# Tags in Monokot Server Administrator

To open the tags manager in Monokot Server Administrator, on the *Server Explorer* pane click on the *Tags* item.

![](/files/VweEq5VFqvKPQaqbhqN7)

The manager allows you to create, copy, move and delete tags, organize them into groups, perform group action and provides a diagnostic feature (*Go Online*). To perform the listed actions, use the manager toolbar, the context menu and Ctrl + C, Ctrl + X, Ctrl + V, Insert, Delete keys.


# Go Online

For diagnostics (read) and debugging (write) tags Monokot Server Administrator provides the *Go Online* mode. In the *Go Online* mode, the following additional tag information is available:

* **Actual:** contains the converted value of the tag.
* **Raw:** contains the raw value of the tag (before conversion). If no value converter is set for the tag, the Actual and Raw fields are the same.
* **Status:** contains the current tag status, e.g. *Good*, *BadNoCommunication*, *BadLicenseExpired.*
* **Update Time:**  contains the time (UTC) of the last tag update.
* **Access**: contain access mode to tag.

To read and write the tag values, the following requirements must be met:

* The user (specified in the credentials for connection) must have the required access rights.
* The tag must exist on the server and have the required access rights.
* The tag must be associated with a device and have an address.


# Group Action

Tags manager supports bulk change of tag parameters by using *Group Action* function. It allows you to set parameters for tag group and for all tag located in subgroups (optionally). Parameters available for bulk change are: Device, Update Rate, Access, Converter, Change Trigger, etc.


# Import & Export

The tag manager allows to import/export the structure of groups and tags from/to a CSV file. The CSV file is formatted as follows:&#x20;

* Each field is enclosed in double quotes. If the field contains double quotes, then additional double quotes are put around them. For example, the field **"Mud" temperature, °C** should look like this: **"""Mud"" temperature, °C"**
* Fields are separated by commas. For example: **"Group1","Tag4","","gas-plc","400005\[10]@INT"**
* Each new set of fields begins with a new line
* The first line defines the names of the fields (parameters) and should contain all the parameters used

Description of fields used when exporting and importing tags:

![](/files/RJ09OtxNyclVCsTR39C7)

* **Tag Group:** contains the path to the group where the tag is located. Group names are separated by dots.
* **Tag:** contains the tag name.
* **Device Group:** contains the name of the group where the device associated with the tag is located.
* **Device:** contains the path to the device or child device. Device names are separated by dots.
* **Address:** contains string representation of the data address (in device-specific format).
* **Update Rate:** contains the tag update rate.
* **Converter:** contains string representation of the value converter (in converter-specific format).
* **Comment:** contains any custom text.
* **Change Trigger**: contains change notification mode.


# Modbus Connectivity

The communication drivers for Modbus TCP and RTU/ASCII protocols are implemented as **Modbus TCP** and **Modbus Serial** devices. They provide high-performance polling, support a variety of data encoding formats, and they can operate in a shared channel mode.

### Key Features <a href="#h.cmoldbsq38ug" id="h.cmoldbsq38ug"></a>

* Communication with Modbus TCP, RTU over TCP, RTU/ASCII as master or slave.
* Data types: Boolean, Byte, Byte Array, Word, Word Array, Int, Int Array, DWord, DWord Array, DInt (32-bit signed integer), DInt Array, Float, Float Array, Double, Double Array, QWord, QWord Array, Long, Long Array, String.
* Data areas: Internal Registers, Holding Registers, Input Coils, Output Coils.
* Byte, word and dword order swapping.
* Reverse bit ordering.
* Polling optimization.


# Parameters

### Common Parameters <a href="#h.vbfuxayjb3k9" id="h.vbfuxayjb3k9"></a>

Listed below are the common parameters for all types of Modbus devices.

### General <a href="#h.83nfaosp08q2" id="h.83nfaosp08q2"></a>

* **Slave ID:** indicates the slave device ID in the Modbus network.
* **Inter-Request Delay:** sets the delay for sending a request (in milliseconds) after receiving the response.
* **Writes per Cycle:** indicates the number of write requests sent after read request completion.

### Blocks <a href="#h.1upumfybrijz" id="h.1upumfybrijz"></a>

* **Output Coils Block Size** and **Input Coils Block Size:** determines the maximum number of bits that can be read in one request from Output and Input Coils. The value of this parameter must be in the range from 1 to 2000.
* **Internal Registers Block Size** and **Holding Registers Block Size:** determines the maximum number of registers that can be read for one request from the Internal and Holding Registers. The value of this parameter must be in the range from 4 to 120.

### Data - Functions <a href="#h.euel1kb7z1nx" id="h.euel1kb7z1nx"></a>

* **Use function 06 for single register writes:** indicates which function should be used when writing one register (06 or 16).
* **Use function 05 for single coil writes:** indicates which function should be used when writing one bit (05 or 15).

### Data - Encoding <a href="#h.yv0yc7zg537m" id="h.yv0yc7zg537m"></a>

* **Use Big-Endian Byte Order:** sets the byte order (Big-Endian or Little-Endian) when organizing the word.
* **First word low in 32-bit values:** sets the word order (from low to high or high to low) when organizing 32-bit values.
* **First DWord low in 64-bit values:** sets the order of double words (from low to high or high to low) when organizing 64-bit values.
* **Reverse Bit Ordering:** indicates the order of bits used when working with register bits (0 bit is MSB or 15 bit is MSB).
* **Swap Every Two Bytes in a String:** indicates that every two bytes in a string must be swapped.

### Modbus TCP Parameters <a href="#h.594trkuq0axi" id="h.594trkuq0axi"></a>

Listed below are the parameters specific to the Modbus TCP.

* **Host:** sets the IP address or hostname of the device.
* **Port:** specifies the port number of the device. The standard port number for Modbus protocol is 502.
* **Transport:** indicates which transport mode must be used (TCP, RTU over TCP or UDP).
* **Retries:** sets the number of attempts after which request is considered failed.
* **Request Timeout:** sets the time to wait for the request to be executed (in milliseconds) after which the request execution error occurs. An error occurs after the time specified in Request Timeout parameter multiplied by Retries.
* **Connection Timeout:** sets the connection timeout (in milliseconds) after which connection error occurs.
* **Close TCP Socket:** specifies whether to close the TCP connection if a timeout occurred while sending a request to the server.
* **Transaction Threshold**: specifies the maximum allowed difference between the sent and received transaction ID, after exceeding which the reconnection to the server is performed.
* **Operation Mode:** specifies the master or slave operation mode.
* **Max Connection Idle Interval:** specifies the maximum silence interval (in milliseconds) for each incoming connection before it is closed.

### Modbus Serial Parameters <a href="#h.u7p8k1ecoa7k" id="h.u7p8k1ecoa7k"></a>

The following are the settings specific to Modbus Serial.

* **COM ID:** indicates the symbol name of the serial port. For example: COM1, COM10, /dev/ttyS0, /dev/ttyUSB0.
* **Mode:** sets the mode of serial protocol (RTU or ASCII).
* **Baud Rate:** specifies data transfer rate.
* **Parity:** defines the method of detecting errors in transmission.
* **Data Bits:** indicates the number of used data bits.
* **Stop Bits:** indicates the number of stop bits used.
* **Retries:** sets the number of attempts after which request is considered failed.
* **Request Timeout:** sets the time to wait for the request to be executed (in milliseconds) after which the request execution error occurs. An error occurs after the time specified in Request Timeout parameter multiplied by Retries.
* **Operation Mode:** specifies the master or slave operation mode.

Most of the parameters described above are available as OPC UA items. More information about editing server object properties via OPC UA is described [<mark style="color:blue;">here</mark>](/basics/opc-ua/access-to-object-settings).


# Addressing

For addressing a single value, use the following address format:

```
START_ADDRESS@DATA_TYPE, where START_ADDRESS indicates the area and the starting address of the element,
and DATA_TYPE – the data type
```

To address one of the bits of the word, you must use the following format:&#x20;

```
START_ADDRESS.BIT_INDEX, where START_ADDRESS indicates the area and the starting address
of the element, 
and BIT_INDEX – the bit number in the 16-bit word (from 0 to 15)
```

An array of values can be set using the following address format:&#x20;

```
START_ADDRESS[LENGTH]@DATA_TYPE, where START_ADDRESS specifies the area and the starting address
of the element, 
LENGTH – number of elements in the array, 
and DATA_TYPE – the data type
```

{% hint style="info" %}
Note that zero-based addressing is used for all types of data areas. This means that the addresses entered by the user are not shifted by 1 when constructing a Modbus frame
{% endhint %}

The table below maps data areas to supported address ranges, data types and access modes.&#x20;

| **Data Area**      | **Address Range** | **Data Type**                                                                                | **OPC UA Access Mode**                                 |
| ------------------ | ----------------- | -------------------------------------------------------------------------------------------- | ------------------------------------------------------ |
| Output Coils       | 0 - 65535         | Boolean                                                                                      | Read/Write                                             |
| Input Coils        | 100000 - 165535   | Boolean                                                                                      | <p>Read Only,</p><p>Read/Write (in slave mode)<br></p> |
| Internal Registers | 300000 - 365535   | <p>Boolean, Byte, Word,</p><p>Int, DWord, DInt,</p><p>Float, Double, QWord, Long, String</p> | <p>Read Only,</p><p>Read/Write (in slave mode)</p>     |
| Holding Registers  | 400000 - 465535   | <p>Boolean, Byte, Word,</p><p>Int, DWord, DInt,</p><p>Float, Double, QWord, Long, String</p> | Read/Write                                             |

{% hint style="info" %}
For byte data type you must specify the byte order in the word (MSB or LSB) after the @ character, for example: 400000\@MSB&#x20;
{% endhint %}

The following are examples of available addresses:

* 400020\@INT
* 300001.14
* 300999\@FLOAT
* 400005\[10]INT
* 100035\[12]
* 000021


# Diagnostics

In addition to the diagnostic variables described in the Devices [<mark style="color:blue;">section</mark>](/tags-and-devices/devices/diagnostics), the Modbus device in slave mode also has the following diagnostic variables:

**Current Connections (Modbus TCP only):** contains the current number of connections to the server.

**Incoming Read Requests:** contains the number of incoming read requests for the current slave identifier.

**Incoming Write Requests:** contains the number of incoming write requests for the current slave identifier.

**Last Incoming Read Utc Time:** contains the UTC time of the last incoming read request for the current slave identifier.

**Last Incoming Write Utc Time:** contains the UTC time of the last incoming write request for the current slave identifier.


# Siemens Connectivity

The communication driver for the S7 protocol is implemented as a Siemens Ethernet device. It offers high-performance device polling and supports various data formats. **Please note that the driver is for TCP/IP networks only.**

### Key Features <a href="#h.r9s5u9nuj6n6" id="h.r9s5u9nuj6n6"></a>

* Communication with CPUs S7-300/S7-400/S7-1200/S7-1500.
* Communication with CPs 343/443.
* Communication with Sinamics.
* Data types: BOOL, BYTE, BYTE ARRAY, WORD, WORD ARRAY, INT, INT ARRAY, DWORD, DWORD ARRAY, DINT, DINT ARRAY, REAL, REAL ARRAY, CHAR ARRAY, DATETIME, DATETIME ARRAY.
* Data areas: DB (Data Blocks), M (Merkers), I (Inputs), Q (Outputs).
* Polling optimization.

{% hint style="info" %}
To get an access to a DBs in PLCs S7-1200 and S7-1500 you will need additional settings on the PLC-side. The required actions are described later in this [<mark style="color:blue;">section</mark>](/tags-and-devices/siemens-connectivity/access-to-dbs-area-in-s7-1200-s7-1500)
{% endhint %}


# Parameters

Listed below are the parameters of Siemens Ethernet device.

* **Host:** contains the IP address or hostname of the device.
* **Rack:** contains the number of the destination CPU in rack.
* **Slot:** contains the number of the destination slot.
* **Port:** contains the device port number. The standard port number for S7 protocol is 102.
* **Connection Type**: Is a type of protocol supported by the device.
* **Max. PDU Size:** specifies the maximum number of bytes which will be read/written per one request to PLC (maximum block size).
* **Inter-Request Delay:** contains the delay for sending a request (in milliseconds) after receiving the response.
* **Request Timeout:** contains the time to wait for the request to be executed (in milliseconds) after which the request execution error occurs.
* **Connection Timeout:** contains the connection timeout (in milliseconds) after which connection error occurs.

Most of the parameters described above are available as OPC UA items. More information about editing server object properties via OPC UA is described [<mark style="color:blue;">here</mark>](/basics/opc-ua/access-to-object-settings).


# Addressing

For addressing a single value, use the following address format:&#x20;

```
AREA,DATA_TYPE START_BYTE, where AREA indicates the data area,
DATA_TYPE indicates the data type,
and START_BYTE indicates the starting byte of data
```

To address one of the bits of the data byte, you must use the following address format:&#x20;

```
AREA,X START_BYTE.BIT_INDEX, where AREA indicates the data area,
START_BYTE indicates the starting byte of data,
and BIT_INDEX indicates the bit number in a byte (from 0 to 7)
```

For addressing an array of values, use the following address format:&#x20;

```
AREA,DATA_TYPE START_BYTE[LENGTH], where AREA indicates the data area,
DATA_TYPE indicates the data type,
START_BYTE indicates the starting byte of data,
and LENGTH indicates the number of elements in the array
```

The table below maps data areas to supported address ranges, data types and access modes.

| **Data Area** | **Address Range** | **Data Type**                                                                                                                                          | **Access Mode** |
| ------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------- |
| DB, M, Q, I   | 0 - 65535         | BOOL, BYTE, BYTE ARRAY, WORD, WORD ARRAY, INT, INT ARRAY, DWORD, DWORD ARRAY, DINT, DINT ARRAY, REAL, REAL ARRAY, CHAR ARRAY, DATETIME, DATETIME ARRAY | Read/Write      |

The following are examples of available addresses:&#x20;

* DB1,INT0
* DB7,DBX99.5
* M0,X0.1
* DB10,REAL2\[50]
* DB111,DT0
* I,X10.3
* Q,WORD4
* DB12,CHAR0\[6]


# Access to DBs area in S7-1200/S7-1500

To access a DB in S7-1200/S7-1500 some additional setting PLC-side are needed:

* Only global DBs can be accessed
* The optimized block access must be turned off
* The access level must be “full” and the “connection mechanism” must allow GET/PUT

The setup of access to DBs in TIA Portal V15 is described below.

Right click on the DB and select *Properties...* item.

![](/files/glqD8frBgigp2JGxNwDf)

Go to *Attributes* and uncheck *Optimize block access*.

![](/files/P1nluyLnrqor2wky6vdr)

Right click on the CPU and select menu item *Properties…*

![](/files/lFOBMAz16MTofPKXEOZJ)

Select *Protection & Security* and select *Full access (no protection)* as shown below.

![](/files/NVePyiEfIwqQqMqgHqAY)

Go to *Connection mechanisms* and check *Permit access with PUT/GET communication from remote partner*.

![](/files/UK052F8XmJhqd7WmM8ZJ)

For changes to take effect, download hardware and program to the PLC.


# IEC 60870-5-104 Connectivity

To interact with peripheral stations of the IEC 60870-5-104 standard, the server provides an IEC 60870-5-104 device. The device functions as a master node in an Ethernet network and implements most of the application commands of the 60870-5-5 standard.

### Key Features <a href="#h.1jrxdqk9ft" id="h.1jrxdqk9ft"></a>

* Representation of value, quality descriptor, cause of transmission, timestamp as OPC UA elements.
* Periodic, manual, event-driven call of applied commands (general interrogation, counter interrogation, time synchronization, etc).
* Controlled station time zone setting.
* SSL support.
* Proper writing of buffered data to external database.
* Shared TCP/IP channel concept for primary device and subdevice.


# Parameters

Listed below are common parameters for primary device and subdevice.

### General <a href="#h.v0x6m2bzuwsv" id="h.v0x6m2bzuwsv"></a>

* **Common Address:** specifies common address of the controlled station.
* **Device Time Zone:** specifies time zone of the controlled station. This parameter is used to convert the timestamp during time synchronization and processing control and monitoring ASDUs. The default setting is \[Local Time Zone], which corresponds to the local time zone of the system the server is deployed on.
* **Enable Reads:** specifies that the driver should send a command to read C\_RC\_NA\_1 data for all associated monitor tags with the frequency specified in the *Update Rate* parameter of each tag.

### Services <a href="#h.r5fyatnqzslj" id="h.r5fyatnqzslj"></a>

* **General Interrogation (Initialization Settings):** specifies whether the driver should send a general interrogation command (C\_IC\_NA\_1) after connecting or reconnecting. The default value is *Connect/Reconnect.*
* **General Interrogation Mode (Periodic Settings):** specifies whether the driver should periodically send a general interrogation command (C\_IC\_NA\_1). The default value is *Disabled.*
* **General Interrogation Interval (Periodic Settings):** defines the time interval (in seconds) for periodic sending of the general interrogation command (C\_IC\_NA\_1). The default value is *3600.*

{% hint style="info" %}
Please note that general interrogation command is generated with the qualifier of QOI = 20 (station interrogation)
{% endhint %}

* **Counter Interrogation (Initialization Settings):** specifies whether the driver should send a counter interrogation command (C\_CI\_NA\_1) after connecting or reconnecting. The default value is *Disabled.*
* **Counter Interrogation Mode (Periodic Settings):** specifies whether the driver should periodically send a counter interrogation command (C\_CI\_NA\_1). The default value is *Disabled.*
* **Counter Interrogation Interval (Periodic Settings):** defines the time interval (in seconds) for periodic sending of the counter interrogation command (C\_CI\_NA\_1). The default value is *3600.*

{% hint style="info" %}
Please note that counter interrogation command is generated with the qualifier of QCC = 5 (request general counter group)
{% endhint %}

* **Time Sync (Initialization Settings):** specifies whether the driver should send a time synchronization command (C\_CS\_NA\_1) after connecting or reconnecting. The default value is *Connect/Reconnect.*
* **Time Sync Mode (Periodic Settings):** specifies whether the driver should periodically send a time synchronization command (C\_CS\_NA\_1). The default value is *Periodically.*
* **Time Sync Interval (Periodic Settings):** defines the time interval (in seconds) for sending the periodic time synchronization command (C\_CS\_NA\_1). The default value is *3600.*
* **Test Mode (Periodic Settings):** specifies whether the driver should periodically send a testing command (C\_TS\_NA\_1). The default value is *Disabled.*
* **Test Interval (Periodic Settings):** defines the time interval (in seconds) for sending the periodic testing command (C\_TS\_NA\_1). The default value is *15.*

Listed below are the common parameters of primary device that are used to organize the data transmission channel.

### Advanced <a href="#h.y013kqh7x99t" id="h.y013kqh7x99t"></a>

* **Originator Address:** specifies the client’s originator address. Takes a value from 0 to 254.
* **Max ASDU Size:** specifies the maximum size of the generated ASDU (in bytes).
* **Size of IOA:** specifies the size of the the information object address (1, 2 or 3 octets). Note that all tags associated with the device whose information object address does not fit in the specified number of octets will be ignored by the driver.
* **Size of COT:** specifies the cause of transmission field size (1 or 2 octets).
* **Size of CA:** specifies the size of the common address field (1 or 2 octets). Note that the parameter cannot be changed if the *Common Address* of the device or any of the subdevices does not fit in the specified number of octets.
* **Max Buffer Size:** specifies the maximum number of ASDUs that the scan buffer can contain.

### SSL <a href="#h.vlixmhi3jfb7" id="h.vlixmhi3jfb7"></a>

* **Use SSL:** specifies whether the driver should establish a secure connection with the controlled station.
* **Client Certificate:** specifies a client-side security certificate. Note that the certificate must contain both public and private encryption keys.
* **SSL Verification**:  contains verification mode of controlled station SSL certificate:
  * Accept any.
  * Verify chain of trust by using a store of certificates of the operating system
  * Verify chain of trust by using custom certificate of certification authority
* **Custom CA File:** contains custom certificate of certification authority


# Addressing

### Monitor ASDUs <a href="#h.2ay3hasa6gha" id="h.2ay3hasa6gha"></a>

To determine the address representing the information object in the monitor direction, use the following template:

```
ASDU_TYPE.IOA.Option[,Read=1], where ASDU_TYPE specifies the type of the represented ASDU (see below), 
IOA specifies the address of the information object, 
Option specifies the attribute represented by the address (see below), 
and the Read=1 (optional) descriptor indicates that the value must be 
requested periodically by sending the command C_RC_NA_1
```

The Read=1 specifier affects the request procedure if the *Enable Reads* parameter of the device is set to *True*.

The table below lists the possible values for *ASDU\_TYPE*.

| **ASDU\_TYPE** | **ASDU**                                              | **Description**                                                                      |
| -------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------ |
| M\_SP          | M\_SP\_NA\_1, M\_SP\_TA\_1, M\_SP\_TB\_1              | Single-point information.                                                            |
| M\_DP          | M\_DP\_NA\_1, M\_DP\_TA\_1, M\_DP\_TB\_1              | Double-point information.                                                            |
| M\_ST          | M\_ST\_NA\_1, M\_ST\_TA\_1, M\_ST\_TB\_1              | Step position information.                                                           |
| M\_BO          | <p>M\_BO\_NA\_1, M\_BO\_TA\_1,</p><p>M\_BO\_TB\_1</p> | Bit string of 32 bit.                                                                |
| M\_ME\_NV      | <p>M\_ME\_NA\_1, M\_ME\_TA\_1,</p><p>M\_ME\_TD\_1</p> | Measured value normalized. This represents a value between -1 and 0.999969482421875. |
| M\_ME\_SV      | <p>M\_ME\_NB\_1, M\_ME\_TB\_1,</p><p>M\_ME\_TE\_1</p> | Measured value scaled. Possible values are -32768 to 32767.                          |
| M\_ME\_FV      | M\_ME\_NC\_1, M\_ME\_TC\_1, M\_ME\_TF\_1              | Measured value short floating point number.                                          |
| M\_IT          | M\_IT\_NA\_1, M\_IT\_TA\_1, M\_IT\_TB\_1              | Integrated totals. Read=1 specifier is not supported for this ASDU type.             |

The table below lists the possible values for *Option*.

| **Option** | **Supported ASDU\_TYPE** | **Description**                                                                                                                                                                                                            |
| ---------- | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Value      | All types                | Represents the value of the information object. If the IV (invalid) bit is set in the quality descriptor of the information object, the tag will go to the *Bad* state.                                                    |
| COT        | All types                | Represents the ASDU cause of transmission field.                                                                                                                                                                           |
| Quality    | All types                | Represents the quality descriptor of the information object as a number.                                                                                                                                                   |
| Timestamp  | All types                | Represents the timestamp CP56Time2a (without any conversion) of the information object. If the information object does not contain a timestamp, the tag will take the value 0001-01-01 00:00:00 and go to the *Bad* state. |
| Transient  | Only for M\_ST           | Specifies whether M\_ST is in transient state.                                                                                                                                                                             |
| SQ         | Only for M\_IT           | Represents the M\_IT sequence number.                                                                                                                                                                                      |

Note that if the information object contains the timestamp CP56Time2a, it will be used as the timestamp of the tag (taking into account the time zone of the station), otherwise the time ASDU arrival to the server will be used.

It should also be noted that for buffered ASDUs (containing several states of the same information object), the “last” state of the information object will be used as the resulting tag state, but the entire sequence of states will be written to the store (for example, InfluxDB), if such feature is used.

Examples of allowed addresses in the monitor direction:

* &#x20;M\_SP.1.COT
* &#x20;M\_SP.62.Quality,Read=1
* &#x20;M\_SP.40.Timestamp,Read=1
* &#x20;M\_SP.1.Value
* &#x20;M\_ME\_SV.1.Value,Read=1
* &#x20;M\_BO.1.Value,Read=1
* &#x20;M\_IT.9.Value
* &#x20;M\_ME\_FV.1.Value

### Control ASDUs <a href="#h.4qy6c7m5iw3q" id="h.4qy6c7m5iw3q"></a>

To determine the address representing the information object in the control direction, use the following template:

```
ASDU_TYPE.IOA.Option[.SubOption][.Timestamp], where ASDU_TYPE specifies 
the type 
of the control command (see below), 
IOA defines the address of the information object, 
Option specifies the purpose of the command (see below), 
SubOption (optional) specifies the duration of the command, 
Timestamp (optional) indicates that a timestamp must be sent along 
with the command (the time zone set for the station affects the timestamp generation)
```

The table below lists the possible values for *ASDU\_TYPE*.

| **ASDU\_TYPE** | **ASDU**                   | **Description**                                                                    |
| -------------- | -------------------------- | ---------------------------------------------------------------------------------- |
| C\_SC          | C\_SC\_NA\_1, C\_SC\_TA\_1 | Single command. Possible values are True or False                                  |
| C\_DC          | C\_DC\_NA\_1, C\_DC\_TA\_1 | Double command. Possible values are 1 or 2.                                        |
| C\_RC          | C\_RC\_NA\_1, C\_RC\_TA\_1 | Step command. Possible values are 1 or 2.                                          |
| C\_SE\_NV      | C\_SE\_NA\_1, C\_SE\_TA\_1 | Set point command (normalized value). Possible values are -1 to 0.999969482421875. |
| C\_SE\_SV      | C\_SE\_NB\_1, C\_SE\_TB\_1 | Set point command (scaled value). Possible values are -32768 to 32767.             |
| C\_SE\_FV      | C\_SE\_NC\_1, C\_SE\_TC\_1 | Set point command (short value).                                                   |
| C\_BO          | C\_BO\_NA\_1, C\_BO\_TA\_1 | Bit string of 32 bit.                                                              |

&#x20;The table below lists the possible values for *Option*.

| **Option** | **Supported ASDU\_TYPE** | **Description**                                                                                                                                                                                |
| ---------- | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Execute    | All types                | Indicates that the control command is executed in one step.                                                                                                                                    |
| Select     | All types except C\_BO   | The first step of the two-step value writing process known as “select before operation”. The command is executed with the help of sending the Execute command for the same information object. |
| Deselect   | All types except C\_BO   | Resets the selection command to the initial stage before execution, if a selection has been made for it.                                                                                       |

The table below lists the possible values for *SubOption.*

| **SubOption** | **Supported ASDU\_TYPE** | **Description**                                      |
| ------------- | ------------------------ | ---------------------------------------------------- |
| ShortPulse    | C\_SC, C\_DC, C\_RC      | The value of the command specifier will be set to 1. |
| LongPulse     | C\_SC, C\_DC, C\_RC      | The value of the command specifier will be set to 2. |
| Persistent    | C\_SC, C\_DC, C\_RC      | The value of the command specifier will be set to 3. |

&#x20;Examples of allowed addresses in the control direction:

* &#x20;C\_SC.1.Execute
* &#x20;C\_DC.15.Select.ShortPulse
* &#x20;C\_DC.1.Select.Timestamp
* &#x20;C\_SC.73.Select.ShortPulse.Timestamp
* &#x20;C\_SC.1.Select.Persistent
* &#x20;C\_SC.3219.Deselect.LongPulse
* &#x20;C\_SC.1.Deselect.Persistent


# Time Conversion

The conversion of time from one time zone to another occurs when sending control commands (with a timestamp), synchronizing time, and receiving information objects with the timestamp CP56Time2a.

The time formation process for control and time synchronization commands is as follows: the current local time is converted to UTC (based on the operating system’s time zone settings), then the UTC time is converted to the time in the time zone specified in the *Device Time Zone* parameter. For example, the operating system’s time zone is Europe / Moscow (UTC +03: 00), the client’s current time is 2019-12-15 19:31:00, and the time zone specified for the device is America / Costa\_Rica (UTC -06: 00). The total time that the command will contain will be generated as follows: 2019-12-15 19:31:00 (Local) → 2019-12-15 16:31:00 (UTC) → 2019-12-15 10:31:00 (Device Time Zone).

The conversion process of the timestamp CP56Time2a of the information object to the timestamp of the tag is as follows: the time of the information object is converted to UTC (based on the device’s time zone settings), then the received UTC time is converted to the time in the time zone of the operating system. For example, the device’s time zone is America / Costa\_Rica (UTC -06: 00), the device’s current time is 2019-12-14 19:15:00, and the time zone of the server is Europe / Moscow (UTC +03: 00). The total time of the tag will be formed as follows: 2019-12-14 19:15:00 (Device Time Zone) → 2019-12-15 01:15:00 (UTC) → 2019-12-15 04:15:00 (Local). If an invalid or ambiguous time occurs during the conversion of CP56Time2a time from one time zone to another, the ASDU will be assigned the timestamp of the tag. You can read more about invalid and ambiguous times [<mark style="color:blue;">here</mark>](https://codeofmatt.com/five-common-daylight-saving-time-antipatterns-of-net-developers/#-4-field-validation).

To ensure cross-platform compatibility, time zone identifiers from the [<mark style="color:blue;">IANA</mark>](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) database are used. Therefore, **if time zone identifier is not found when uploading the configuration, for example, from the test server to the production server, then the local time zone will be used to convert the time**, and an error message will appear in the server’s event log. In order to avoid problems associated with the time conversion from one time zone to another, it is recommended to generate timestamps in the UTC time zone at the controlled station.


# Diagnostics and Commands

In addition to the diagnostic variables described in "Devices" [<mark style="color:blue;">section</mark>](/tags-and-devices/devices/diagnostics), the IEC 60870-5-104 device also has the following diagnostic variables:

* **RecvCounter**: received messages counter.
* **SentCounter**: sent messages counter.

Variables with the *Run* prefix allow you to manually start the execution of application commands of the IEC 60870-5-5 standard. To do this, you need to write any value to the corresponding variable. The following variables are defined in the device:

* **RunGeneralInterrogation:** initializes general interrogation of the station. The command is executed with the qualifier specified by the user, for example QOI = 20 (station interrogation).
* **RunCounterInterrogation:** initializes counter interrogation. The command is executed with the qualifier of QCC = 5 (general group of counters).
* **RunFreezeCounters:** initializes the counter freeze command. The command is executed with the qualifier of QCC = 69 (freeze for general group of counters).
* **RunFreezeResetCounters:** initializes the counter freeze and reset command. The command is executed with the qualifier of QCC = 133 (freeze and reset for general group of counters).
* **RunResetCounters:** initializes the counter reset command. The command is executed with the qualifier of QCC = 197 (reset for the general group of counters).
* **RunTestProcedure**: initializes the testing command (TEST-FR).
* **RunTimeSync**: initializes the time synchronization command.

For application commands to be initialized by the OPC UA client, the following conditions must be met:

* the user must have the *Run Command* rights from the *Devices* category. You can read more about this [<mark style="color:blue;">here</mark>](/basics/users-and-roles).


# OPC UA Connectivity

To enable communication with external OPC UA sources, the server offers the OPC UA Client device. The driver is designed to work with Standard Server profile and all the profiles included in it.

### Key Features <a href="#h.2755as4jbck" id="h.2755as4jbck"></a>

* Data reading in notification and polling modes.
* Data encryption.
* Data loss prevention in the event of a connection failure to the server.
* Import of OPC UA variables into CSV file.
* Basic data types support.


# Parameters

### General <a href="#h.x6qpxlxfalie" id="h.x6qpxlxfalie"></a>

**Endpoint URL:** contains the identifier of the server connection endpoint, for example: opc.tcp\://localhost:43043/MonokotOPC.

{% hint style="info" %}
Note that only binary transport profile (UA TCP) is supported, so the Endpoint URL must start with opc.tcp\://
{% endhint %}

**Security Policy:** specifies the endpoint security policy (None, Basic128Rsa15, Basic256, Basic256Sha256).

**Security Mode:** specifies the endpoint security mode (None, Sign, SignAndEncrypt).

**Connection Timeout:** indicates timeout (in milliseconds) to discover the endpoints of OPC UA server.

**Session Timeout:** indicates for how many seconds a session should exist if the connection between client and server is lost. After session timeout, the server closes the session and frees all resources it occupied.

**Channel Renewal Timeout:** specifies the interval (in seconds) before the encryption keys are renewed.

**Watchdog Interval:** specifies the interval (in milliseconds) for checking the connection to the server.

**Reconnect Interval:** indicates delay (in milliseconds) before each new attempt to reconnect to the server, in case the connection was lost.

**Request Timeout:** specifies a timeout (in milliseconds) for sending/receiving data over the network.

### Subscription <a href="#h.dq5il2jztr8a" id="h.dq5il2jztr8a"></a>

**Publishing Interval:** indicates new data publishing rate (in milliseconds).

**Max. Notifications per Publish:** specifies the maximum number of notifications that each data publication can contain. By default, the parameter is 0, which means the maximum possible number of publications determined by the server.

**Keep Alive Count:** specifies for how many publishing intervals the silence mode must be maintained before the server starts testing the connection to the client.

**Lifetime Count:** specifies for how many publishing intervals the silence mode must be maintained before the server terminates the subscription and frees all resources it occupies.

**Subscription Priority:** indicates priority for subscription. Higher number means that notifications for this subscription will be sent with higher priority.

**Re-applying Changes:** indicates delay (in seconds) before each new attempt to add monitored subscription items. This option is only used if, at the time the subscription is created, the server is unable to provide all the monitored items required by the client because they have not yet been created on the server.

**Update Mode:** indicates which data receiving mode is used:

* Exception (Notification).
* Poll.

**Used Timestamp:** indicates what timestamp should be used when forming the time of OPC UA client-associated tags update.

**Sample Interval:** specifies the rate (in milliseconds) at which the server should read values for the monitored items.

**Queue Size:** specifies the maximum queue size of values to be sent to the client that were read for the monitored item.

**Discard Oldest:** indicates which values (newest or oldest) should be discarded from the queue if the queue has reached its maximum size.

**Deadband Type:** indicates which type of deadband to use for the monitored items:

* None
* Absolute
* Percent (for this type, the monitored item must provide EU Range engineering units)

**Data Change Trigger:** indicates which parameters (Status, StatusValue, StatusValueTimestamp) of the monitored item lead to notification of the client when changed.

**Items per Request:** specifies how many items can be read in a single request. This parameter is only used in polling mode.

### Security <a href="#h.56nh6dnko2a" id="h.56nh6dnko2a"></a>

**Use Credentials:** indicates whether username and password must be used when connecting to the OPC UA server.

**Username:** contains username to be used in credentials.

**Password:** contains password to be used in credentials.

**Certificate:** contains security certificate for organizing a secure transmission channel. You can read about the default security certificate [<mark style="color:blue;">here</mark>](/basics/security-certififcate).

### Server Certificates <a href="#h.38qwjx2kx4ya" id="h.38qwjx2kx4ya"></a>

**Certificate Validation Mode:** Specifies server security certificate validation mode:

* Accept Any (no validation).
* Verify by Operating System (the most rigorous way of certificate validation; builds a trusted certificate chain using the operating system certificate store with validation of domain name, certificate expiration date, etc).
* Trusted Certificates List (successfully validated if the certificate is in the certificate list and is trusted).
* Trusted CA’s List (successfully validated if it is possible to build a trust chain to any of the trusted certificates on the list).

Most of the parameters described above are available as OPC UA items. More information about editing server object properties via OPC UA is described [<mark style="color:blue;">here</mark>](/basics/opc-ua/access-to-object-settings).


# Addressing

Addressing of monitored items is done using the following template:

```
ns=NAMESPACE_INDEX;ADDRESS_TYPE=ADDRESS@DATA_TYPE, where NAMESPACE_INDEX specifies the namespace index, 
ADDRESS_TYPE specifies the type of address used (number, string, GUID, byte string), 
ADDRESS specifies the identifier of the item being monitored, and DATA_TYPE specifies the target data type.
```

The following are examples of available addresses:

* &#x20;ns=2;i=15\@FLOAT
* &#x20;ns=2;s=Device1.Group2.Tag3\@INT
* &#x20;g={066779c4-1598-4eb0-b7a8-553798052ea2}@DOUBLE
* &#x20;ns=1;b=SGVsbG8gd29ybGQ=@DOUBLE


# Diagnostics

In addition to diagnostic variables described [<mark style="color:blue;">here</mark>](/tags-and-devices/devices/diagnostics), OPC UA Client provides the *LastKeepAliveUtcTime* property. It contains the time of the last successful check of connection with the server in UTC.


# How to: Importing OPC UA items

Monokot Server Administrator provides a tool for importing OPC UA items into CSV file.

To open the utility, in Monokot Server Administrator select *Tools* → *CSV Generator* → *Import OPC UA Items*.

![](/files/273jcJZKbkYoSY65ddTH)

Specify settings for connecting to the OPC UA server and click *Connect*.

In the *Browser* panel, select the folder you want to import and click *Add Branch*.

![](/files/s0iXcrnYThNbYKVpaUvF)

The selected items will appear in the *Import Items* panel and will be ready for saving to a CSV file. Click *Save as CSV...*, save the file to disk and close the utility.

Open the device manager, create an OPC UA Client device with the name **opcua-cli** and necessary connection parameters.

![](/files/s4pnZd4xcAPtE1DIPYxF)

Open the tag manager, select the group to which you want to import, click *Import CSV...* and select the previously saved file.

![](/files/1wusoL7buXlhjhbfV90m)

In the window that appears, check *Select from the manager* and click the selection button.

![](/files/QCUuZoFxaRBy80UZqWbx)

In the device selection window, choose the previously created device named **opcua-cli** and click *Import*.&#x20;

For the changes to take effect, they need to be synchronized with the server by pressing the *Sync* button or the F5 key. Now the structure of folders and variables of the external OPC UA server is recreated and ready for use.


# How to: Pulling Security Certificate

To pull the security certificate of an external OPC UA server and place it to the certificate list using Monokot Server Administrator, open the Device Manager, select the OPC UA Client device used for communication with the external OPC UA server and click *Pull The Certificate*.

![](/files/HoqK2ExlLQfOg178qg0H)

In the following dialog box, click *Yes*, and the certificate will appear in the certificate list on the *Server Certificates* tab. To make the added certificate trusted, select it from the certificate list and click the Trust button.

For the changes to take effect, they need to be synchronized with the server by pressing the *Sync* button or the F5 key.


# InfluxDB Connectivity (Connector)

To present fields of InfluxDB database as OPC UA items the server provides InfluxDB Connector. The device periodically sends requests to the database and maps the received query result to the associated tags (variables).

{% hint style="info" %}
Variables hereinafter are referred to tags specified in the server, and tags are referred to tags used in InfluxDB to store time series metadata
{% endhint %}

### Key Features <a href="#h.auy1ifvf0z1p" id="h.auy1ifvf0z1p"></a>

* Data fetch by using of Influx Query Language.
* Data writing by using of Influx Line Protocol.
* Data types: Boolean, Byte, Word, Int, DWord, DInt (32-bit signed integer), Float, Double, QWord, Long, String, DateTime.
* Block data reading.
* OPC UA Historical access (raw/aggregated data reading).


# Parameters

### General <a href="#h.iy2j3qpghg0m" id="h.iy2j3qpghg0m"></a>

* **Host:** contains target IP address or database server hostname.
* **Port:** contains database server port (8086 by default).
* **Database:** contains name of the database.
* **Retention Policy:** contains the retention policy.
* **Measurement:** contains name of measurement.

{% hint style="info" %}
Note that if database, retention policy or measurement do not exist in the database server, reading and writing will not be performed
{% endhint %}

* **Items per Request:** contains maximum number of items (values) that can be read per one request.
* **Query Template:** contains query text for data fetch. The information about how the query result is associated with the variables can be found further. Query text can contain the following keywords for replacement:
  * *{DATABASE\_NAME}* - is replaced with the name of database specified in the device.
  * *{RETENTION\_POLICY\_NAME}* - is replaced with the name of retention policy specified in the device.
  * *{MEASUREMENT\_NAME}* - is replaced with the name of the measurement specified in the device.
  * *{WHERE\_CONDITION}* - is replaced with WHERE condition: *("tsid" = 'Group1.Series1' AND "tsc" = 'Room\_25') OR ("tsid" = 'Group2.Series3' AND "tsc" = 'Room\_228')*, generated for addresses in the block.
  * *{TAG\_KEYS}* - is replaced with a list of tag keys used in the block, e.g.: *"tsid", "tsc", "location"*
  * *{FIELD\_NAMES}* - is replaced with a list of fields used in the block, e.g.: *"value", "time", "flag"*
  * *{ITEMS\_COUNT}* - is replaced with a quantity of unique tags combinations used in the block.
* **Inter-request Delay:** contains timeout interval (in milliseconds) before the next query is sent. &#x20;
* **Request Timeout** - contains time interval (in milliseconds) within which the response from the database server must be received. If the response is not received during the specified interval an error occurs. &#x20;

### Security <a href="#h.mxh7apafhfs0" id="h.mxh7apafhfs0"></a>

* **Use Credentials:** specifies that it is necessary to use credentials (Base64 Auth in HTTP-header).
* **Username:** contains the username.
* **Password:** contains the password.
* **Use SSL:** specifies that it is necessary to verify database server SSL certificate.
* **SSL Verification:** contains verification mode of database server SSL certificate:
  * Accept any.
  * Verify chain of trust by using a store of certificates of the operating system.
  * Verify chain of trust by using custom certificate of certification authority.
* &#x20;**Custom CA File:** contains custom certificate of certification authority.

Most of the parameters described above are available as OPC UA items. More information about editing server object properties via OPC UA is described [<mark style="color:blue;">here</mark>](/basics/opc-ua/access-to-object-settings).


# Addressing

In order to map the variable with the field in database you need to define the following parameters in the variable address:

* The field that must be presented by the variable e.g.: *value*, *time*, *last*, *ts\_value*
* Tags (pairs key-value) to identify the time series, e.g.: *value\_type='temperature',location='CA'* or *tsid='Group1.TimeSeries1',su='MJqdilungXgCeSqAF5sGUq=='*
* Target data type

Address can be specified by using the following template:

```
TAG1_KEY='TAG1_VALUE',TAG2_KEY='TAG2_VALUE',...,TAGN_KEY='TAGN_VALUE'[FIELD_NAME]@DATA_TYPE, 
where TAG1_KEY, TAG2_KEY, TAGN_KEY - tag keys, 
TAG1_VALUE, TAG2_VALUE, TAGN_VALUE - tag values, 
FIELD_NAME - field name
and DATA_TYPE - data type
```

The following are examples of available addresses:

* tsid='TS\_Motor1\_Rpm',tsc='DPP1'\[v]@DOUBLE
* country='France',city='Paris',address='40-50 boulevard Lannes',location='room 123',value\_type='fire\_alarm'\[value]@BOOLEAN


# Query Result and Data Mapping

For better understanding of mapping principle of the query result with the variable values let’s consider the following measurement:

| **time**            | **location** | **signal** | **source**  | **tsid** | **val** | **value\_type** |
| ------------------- | ------------ | ---------- | ----------- | -------- | ------- | --------------- |
| 2019-09-22 18:20:41 | Area1        | -          | -           | Voltage  | 223.7   | analog          |
| 2019-09-22 18:21:40 | Area1        | -          | -           | Voltage  | 246.23  | analog          |
| 2019-09-22 18:23:55 | -            | true       | fire\_alarm | Signal   | -       | discrete        |
| 2019-09-22 18:23:59 | -            | false      | fire\_alarm | Signal   | -       | discrete        |
| 2019-09-22 18:24:02 | -            | true       | fire\_alarm | Signal   | -       | discrete        |
| 2019-09-22 18:24:12 | Area1        | -          | -           | Voltage  | 219.6   | analog          |

In the table shown above *location, source, tsid, value\_type* - are the tags, and *signal* and *val* - are the fields. It is necessary to read two values:

* The last value of *val* field for time series with tags *"tsid"='Voltage' AND "value\_type"='analog' AND "location"='Area1'*
* The last value of *signal* field for time series with tags *"tsid"='Signal' AND "value\_type"='discrete' AND "source"='fire\_alarm'*

For this it is necessary to add two variables with the following addresses:

* *tsid='Voltage',value\_type='analog',location='Area1'\[val]@DOUBLE*
* *tsid='Signal',value\_type='discrete',source='fire\_alarm'\[signal]@BOOLEAN*

In InfluxDB Connector we specify the following query template: *SELECT {FIELD\_NAMES} FROM {DATABASE\_NAME}.{RETENTION\_POLICY\_NAME}.{MEASUREMENT\_NAME} WHERE {WHERE\_CONDITION} GROUP BY {TAG\_KEYS} ORDER BY DESC LIMIT 1*.

For block consisting of two above mentioned addresses the following values for replacements will be generated:

**{FIELD\_NAMES}:** "signal","val"

**{WHERE\_CONDITION}:** ("tsid"='Signal' AND "value\_type"='discrete' AND "source"='fire\_alarm') OR ("tsid"='Voltage' AND "value\_type"='analog' AND "location"='Area1')

**{TAG\_KEYS}:** "tsid","value\_type","source","location"

and the result query to database will be as follows:&#x20;

{% code overflow="wrap" %}

```sql
SELECT "signal","val" FROM "timeseries"."autogen"."tssamples" WHERE  ("tsid"='Signal' AND "value_type"='discrete' AND "source"='fire_alarm') OR ("tsid"='Voltage' AND "value_type"='analog' AND "location"='Area1')  GROUP BY "tsid","value_type","source","location" ORDER BY DESC LIMIT 1
```

{% endcode %}

Query to database will return the following result:

| **time**            | **location** | **signal** | **source**  | **tsid** | **val** | **value\_type** |
| ------------------- | ------------ | ---------- | ----------- | -------- | ------- | --------------- |
| 2019-09-22 18:24:02 | -            | true       | fire\_alarm | Signal   | -       | discrete        |
| 2019-09-22 18:24:12 | Area1        | -          | -           | Voltage  | 219.6   | analog          |

Next, the driver will find the first entry for each definite address where the set of record tags matches the tags specified in the address, and will assign value of the field specified in the address. If the record can’t be found the variable will be assigned the *BadOutOfRange* status. Thus for the variable with the address tsid='Voltage',value\_type='analog',location='Area1'\[val]@DOUBLE the value *219.6* will be assigned, and for the variable with the address *tsid='Signal',value\_type='discrete',source='fire\_alarm'\[signal]@BOOLEAN* the *true* value will be assigned.

{% hint style="info" %}
Note that in Query Template any custom query can be specified, for example: *SELECT MAX("val") as "Maximum" FROM "mydb"."myrp"."mymeasurement" GROUP BY "value\_type" LIMIT 1*. The main requirement here is that the driver could map the result of the query with tags and fields specified in the address. In this case the variable address must be something like this: *value\_type='temperature'\[Maximum]@DOUBLE*
{% endhint %}


# Diagnostics

In addition to diagnostic variables described in "Devices" [<mark style="color:blue;">section</mark>](/tags-and-devices/devices/diagnostics), InfluxDB Connector has a diagnostic variable *MaxQuerySize* which contains maximum query size (in bytes) to the database.


# How to: Configure for InfluxDB 2.x

Since the driver is designed for InfluxDB 1.x, some additional steps need to be performed to work with InfluxDB 2.x.

On the InfluxDB 2.x side, you need to create authentication (Basic Auth) using the Influx CLI. To do this, run the following command and type the password for NEW\_USER\_NAME\_V1:

```powershell
influx v1 auth create --org-id YOUR_ORG_ID  --read-bucket YOUR_BUCKET_ID --write-bucket YOUR_BUCKET_ID --username NEW_USER_NAME_V1 --token YOUR_OPERATOR_TOKEN --host http://localhost:8086
```

For the InfluxDB connector, specify the following settings:

<figure><img src="/files/ty7x9ms6keMsGk2TNokG" alt="influxdb-con-1"><figcaption></figcaption></figure>

and then specify the credentials:

<figure><img src="/files/Ei2lGm4hxhTaQR88exo2" alt="influxdb-con-2"><figcaption></figcaption></figure>

In order for the changes to take effect on the server, click the Sync button.


# SNMP Connectivity

The communication driver for the SNMP protocol is implemented as an SNMP device. It provides high reading performance and supports various types of data.

### Key Features <a href="#h.33avvwqm4skg" id="h.33avvwqm4skg"></a>

* Communication with devices via SNMPv1 and SNMPv2 protocols.
* Data Types: BOOL, BYTE, DATETIME, DINT, DOUBLE, DWORD, FLOAT, INT, LONG, QWORD, STRING, WORD.
* Value conversion from OCTET STRING to an output data type (e.g. DOUBLE).
* Working in read and write modes.
* Block reading.

{% hint style="warning" %}
Please note that SNMP Trap is not supported in the current version of the server
{% endhint %}

### Block Reading Considerations <a href="#h.fqcp5zvvvgsf" id="h.fqcp5zvvvgsf"></a>

Before reading, the driver sorts the OID’s and organizes them into blocks. Typically, there are 25 OID’s per block (depending on the Items per Request parameter). With such mode of data reading, a negative effect may occur in the SNMPv1 protocol: if one of the OIDs is unavailable or does not exist, then the entire block will become inaccessible for reading, and the tags associated with it will go into the BadOutOfRange state. There is no such problem with the SNMPv2c protocol. In the case of SNMPv2c, only the OID that is unavailable or does not exist in the device will not be read, and the tag associated with it will go into the BadOutOfRange state.


# Parameters

Listed below are the parameters of SNMP device.

* **Host**: contains IP address or hostname of the device.
* **Port:** contains port of the device. Default port used for SNMP is 161.
* **Community:** contains community name for accessing the remote SNMP device.
* **Items per Request**: contains maximum number of items (OID’s) that can be read per one request.
* **Version:** contains the SNMP protocol version (V1 or V2).
* **Inter-request Delay**: contains timeout interval (in milliseconds) before the next request is sent.
* **Retries:** contains the number of attempts before the request is considered failed.
* **Request Timeout:** contains the time interval (in milliseconds) during which a response should be received from the device. If a response is not received within the time interval, an error occurs. Thus, the final time interval before an error occurs is the result of *Retries ✕ Request Timeout.*
* **Writes per Cycle:** contains the maximum number of items (OIDs) that can be written after reading one block of data.

Most of the parameters described above are available as OPC UA items. More information about editing server object properties via OPC UA is described [<mark style="color:blue;">here</mark>](/basics/opc-ua/access-to-object-settings).


# Addressing

To address a value, the following string address format is used:&#x20;

```
OID@DATA_TYPE, where OID indicates the Object Identifier of the value, 
and DATA_TYPE defines the output data type
```

Examples of valid addresses:

* *.1.3.6.1.2.1.1.1.0\@STRING*
* *.1.3.6.1.2.1.2.1.0\@INT*
* *.1.3.6.1.2.1.2.2.1.10.1\@DWORD*
* *.1.3.6.1.2.1.1.3.0\@DINT*

### String Conversion <a href="#h.gc41mqgzgll5" id="h.gc41mqgzgll5"></a>

If the OID specified in the address refers to OCTET STRING and the output data type is not string, the driver will try to convert OCTET STRING to the output data type. Please note that conversion from a string to, for example, a real number is performed in accordance with the culture (regional settings) specified in server.ini. This is also true for conversions from string to date and time.


# UDP Considerations

The SNMP driver implemented in the server works only via UDP protocol. This causes a number of considerations as compared to devices operating over the TCP protocol. For example, if the Modbus TCP driver does not receive a response from the slave node during the *Request Timeout*, this means that communication with the slave node is lost and all tags associated with the driver must go to the *BadNoCommunication* state. This happens because TCP provides reliable data transfer. UDP does not guarantee data delivery, therefore, if the response from the target device is not received during the Request Timeout, only the tags associated with this request will go to the *BadNoCommunication* state.

### Diagnostics <a href="#h.th4k692qxt9s" id="h.th4k692qxt9s"></a>

Use of UDP as transport protocol brings its own aspects to the use of diagnostic variables described in the “Devices” [<mark style="color:blue;">section</mark>](/tags-and-devices/devices/diagnostics). The *CommunicationEstablished* and *CommunicationLost* variables should not be used to diagnose driver operation, as they do not reflect the state of the communication channel between the driver and the target device.


# Stores

**Store** is a driver used for interacting with a database in write mode. The drivers are designed so as to allow working with both databases located in local area networks and databases located in cloud services.&#x20;

The current version of the server includes a set of drivers for:

* InfluxDB Line Protocol.
* PostgreSQL.
* Oracle Database.
* MS SQL Server.
* MySQL.
* REST Client.

Currently, all types of drivers supported by the server work as follows:

* **Step 1.** Accumulating data in the driver during a certain period of time.
* **Step 2.** Generating a packet for writing into the database. At this step, the data is “fitted” into a packet of a certain size. For example, simultaneous data writing is performed for no more than 50 time series, where each time series is represented by no more than 200 samples.
* **Step 3.** Preparing the database for writing, e.g. executing a query such as "CREATE DATABASE tsdata".
* **Step 4.** Writing the data into the store and going to step 1.

In case database preparation or data writing fails, the driver continues to accumulate data until the size of the data buffer exceeds a certain value. When the buffer overflows, older data is replaced by newer ones (cyclic queue).

**All operations related to data accumulation, packet writing, etc. are performed by the driver automatically** without any user intervention.

To improve the data writing performance, you can create several drivers to connect to the same database. In this case, writing is performed asynchronously.


# Backlog

Backlog is designed to prevent data disappearance in the event of long-term loss of communication with the target store. This is achieved by saving data to the local disk and writing it again after the connection is restored. The backlog mechanism is available for all store types and offers the following settings:

* **Mode**: specifies backlog mode (*None* – do not use backlog, *Cyclic* – write files to disk cyclically).
* **File Size:** specifies the maximum backlog file size (in KB) that can be saved for each time series.
* **Files Count**: specifies the maximum number of files that can be saved for each time series. When this value is reached, the files are cyclically overwritten.
* **Buffer Size**: specifies the number of samples at which the backlog file is flushed to disk.
* **Flush Interval**: specifies the interval (in seconds) after which the backlog file is flushed to disk.

By default, the backlog is saved in the following directories:

* **Windows**: %ProgramData%\Monokot\Mos\Backlog\ (C:\ProgramData\Monokot\Mos\Backlog)
* **Linux**: /usr/share/Monokot/Mos/Backlog/

{% hint style="info" %}
Please note that these directories are hidden file system directories
{% endhint %}

You can change the backlog directory in the server [<mark style="color:blue;">startup settings</mark>](/basics/startup-parameters).


# Diagnostics

Diagnostic variables are available for store operation diagnostics. They are represented as OPC UA items and described below.&#x20;

Only diagnostic variables that are common for all types of stores are described here:

![](/files/SCmbilg0ZH1ldnQfywwg)

* **GoodResponses:** contains the total number of successful responses from the database when preparing or writing data.
* **LastResponseUtcTime:** contains the time of the last successful response from the database in the UTC format.
* **BadResponses:** contains the total number of unsuccessful or unreceived (during loss of connection) responses from the database.
* **LastErrorUtcTime:** contains the time of the last unsuccessful or unreceived response from the database in the UTC format.
* **HasError:** indicates whether the last request sent to the database was successful or not.
* **DemoIsExpired:** contains that demonstration period for the store is expired.
* **MaxWriteDuration:** contains the longest time interval between sending a write request and receiving a response.
* **MaxPrepareDuration:** contains the longest time interval between sending a database preparation request and receiving a response.


# Stores in Monokot Server Administrator

To open stores manager in Monokot Server Administrator, double-click *Stores* on the *Server Explorer* pane.

![](/files/U2mxCtGD3epwn75EodWk)

The manager allows you to create, copy, delete stores and set their parameters. To perform the listed actions, use the manager toolbar, the context menu and Ctrl + C, Ctrl + V, Insert, Delete keys.


# Time Series

**Time Series** is a value which is written in a store, received from the specified data source (tag or expression) and identified by the address (ID). Time series are organized in groups and are presented as a hierarchical structure.

Interaction between time series and a store is performed on the model of publisher-subscriber, where publisher is a time series and subscriber is a store. It means that time series notifies the associated store about the fact that it has changed. In its turn the store accumulates the received values and writes them in the target database. Notification about changing of the time series occurs in the following cases:

* Data source (tag or expression) associated with the time series has changed.
* Data source (tag or expression) associated with the time series is not changing during a certain period of time. This mode is turned on optionally.

{% hint style="warning" %}
Please take note that time series supports only those data sources which values can be converted into double (64-bit floating point number, IEEE-754), e.g.: UInt64, Int32, Boolean, Byte, etc. Non scalar data types are not supported
{% endhint %}


# Parameters

Description of time series parameters is shown below.&#x20;

* **Name**: contains the symbolic name of the time series.
* **Data Source:** specifies the data source which values generate the time series. &#x20;
* **Store:** specifies the store in which the time series should be written. &#x20;
* **Address (ID):** contains the time series ID in a store. For example, for InfluxDB it is record metadata.
* **Converter:** specifies conversion applied to the data source value. The following conversions are available: division by specified number linear scaling.
* **Comment:** contains any custom text.
* **Deadband Mode:** contains deadband mode (None, Absolute, Percent).
* **Deadband:** contains value for the deadband.
* **Sampling Mode:** specifies the mode for presentation of continuous quantity (None, Discrete, Analog).
* **Sampling Delta Factor:** specifies the factor (the real number) used for the values representation in the Analog mode. &#x20;
* **Repeat Last Sample:** specifies that the current sample must be cycled if data source doesn’t change.
* **Repeat Last Sample Factor:** contains the factor (the real number) used for calculation of time interval in the cycling mode.

Most of the parameters described above are available as OPC UA items. More information about editing server object properties via OPC UA is described [<mark style="color:blue;">here</mark>](/basics/opc-ua/access-to-object-settings).


# Deadband

To filter values received from time series data source you can specify the deadband. It is determined by the positive real number. The following deadband modes are supported.

* **None:** filtering of samples is not performed.
* **Absolute:** filtering of new sample is performed if the absolute value of difference between the current and the new values is less than or equal to the specified value of the deadband, e.g.: *CurrentValue = 7; NewValue = 15; Deadband = 10; Delta = Abs(7 - 15) = 8; Delta (8) < Deadband (10)*. Thus the new value will be filtered.
* **Percent**: filtering of new sample is performed if the absolute value of difference between the current and the new values is less than or equal to the specified value of the deadband in percentage correlation, e.g.: *CurrentValue = 1000; NewValue = 1200; Deadband = 15; Delta = Abs(1000 - 1200) = 200; Percent = CurrentValue / 100 ✕ Deadband = 150; Delta (200) > Percent (150)*. Thus the value will not be filtered.


# Sampling

The following sampling modes are available to represent continuous quantity as a time series: None, Discrete, and Analog. In fact these modes define whether the insert of extra sample between the current and the new samples is required or not.

Find more information about the presentation modes below. Please note that in all the images presented below the points indicate the samples that were written in a store. Data source was changing as follows:

| **Time**                | **Value** |
| ----------------------- | --------- |
| 2019-09-17 21:41:23.538 | 0.00      |
| 2019-09-17 21:42:12.818 | 80.00     |
| 2019-09-17 21:42:36.163 | 20.00     |
| 2019-09-17 21:42:40.182 | 50.00     |
| 2019-09-17 21:42:56.916 | 0.00      |

**None Mode**. In this mode extra sample is not created, values are sent to a store as they are.&#x20;

![](/files/dittBnmlQ8rPz3oihGcn)

**Discrete Mode**. In this mode before each new sample new extra sample is created. Its value is equal to the current sample, but time differs 1 millisecond from the new one.<br>

![](/files/4oqyPVonkVeoF8JNTBGa)

**Analog Mode**. In this mode before each new sample extra sample is created depending on a condition: if the time interval between the current and the new samples is more than *SamplingDeltaFactor ✕ DataSource.UpdateRate,* the new sample will appear, otherwise - it will not. For example, data source with update rate 500 ms (*DataSource.UpdateRate*) is specified for the time series, *SamplingDeltaFactor = 10.* Current sample was received in 2019-09-17 21:42:12.818 (*CurrentTime)*, and new sample - in 2019-09-17 21:42:36.163 (*NewTime*), *Interval = SamplingDeltaFactor ✕ DataSource.UpdateRate = 500 ✕ 10 = 5000ms,* *Delta = DeltaMilliseconds(NewTime - CurrentTime) = 24655ms, Delta > Interval*. So the extra sample would appear in a store. The value of the extra sample would be equal to the current sample, and time would differ *1 ✕ DataSource.UpdateRate* from the new sample.<br>

![](/files/9ipGjEWksNW4W95inbBv)


# Last Sample Repeat

By default time series creates samples only if the associated data source is changed. Optionally you can add behavior where the new sample will be created if the data source is not changed within *RepeatLastSampleFactor* *✕ DataSource.UpdateRate* time interval (in milliseconds). The new sample time will differ *RepeatLastSampleFactor* *✕ DataSource.UpdateRate* from the current one, and the value will be equal to the current sample value. Thus the combined mode of writing data to the store is implemented:&#x20;

* Generation of time series sample in case data source changes. &#x20;
* Cycling of the current sample in case data source doesn’t change.


# Time Series in Monokot Server Administrator

To open time series manager in Monokot Server Administrator, on the *Server Explorer* pane double-click on *Time Series*.

![](/files/3EbtzgsSQdGrRISeqULo)

The manager allows you to create, copy, move and delete time series, organize them into groups and perform group action. To perform the listed actions, use the manager toolbar, the context menu and Ctrl + C, Ctrl + X, Ctrl + V, Insert, Delete keys.


# Group Action

Time series manager supports bulk change of time series parameters by using *Group Action* function. It allows you to set parameters for time series group and for all time series located in subgroups (optionally). Parameters available for bulk change are: Store, Converter, Deadband Mode, Deadband, Sampling Mode, Sampling Delta Factor, Repeat Last Sample, and Repeat Last Sample Factor.


# Import & Export

### CSV File <a href="#h.sfbslpwtvz02" id="h.sfbslpwtvz02"></a>

Time series manager allows you to import (export) structure of groups and time series from (to) CSV file. Format of the CSV file is as follows:

* Each field is enclosed in double quotes. If the field contains double quotes, then extra double quotes are inserted in front of them. For example, field **"Mud" temperature, °C** must be as follows **"""Mud"" temperature, °C"**
* Fields are separated by commas, e.g.: **"Group1","TS\_WaterLevel","Influx","Tag"**&#x20;
* Each new set of fields starts with a new line.
* The first line specifies the name of the fields (parameters) and must contain all the parameters used.

Description of fields used during export and import of the time series:

![](/files/a1AWeph9z5y1W4odaYF3)

* **Series Group:** contains path to the group which contains the time series. Names of the groups are separated by dots. &#x20;
* **Series:** contains the time series name.
* **Store:** contains the store name associated with the time series. &#x20;
* **Data Source Object Type:** contains the data source type (**Tag** or **Expression**).
* **Data Source Group:** contains path to the group which contains the data source. Names of the groups are separated by dots. &#x20;
* **Data Source:** contains the data source name. &#x20;
* **Address:** contains string representation of the address (ID) (in the format specified by the store).
* **Converter:** contains string representation of the value converter (in the format specified for each type of the converter).
* **Deadband:** contains value for the deadband.
* **Deadband Mode:** contains deadband mode.
* **Sampling Mode:** specifies the mode for presentation of continuous quantity (None, Discrete, Analog).
* **Sampling Delta Factor:** specifies the factor (the real number) used for the values representation in the Analog mode. &#x20;
* **Repeat Last Sample:** specifies that the current sample must be cycled if data source doesn’t change.
* **Repeat Last Sample Factor:** contains the factor (the real number) used for calculation of time interval in the cycling mode.
* **Comment:** contains any custom text.

### Import from Tags/Expressions <a href="#h.nv8mfww4i2rt" id="h.nv8mfww4i2rt"></a>

Time series manager allows you to import the structure of groups and time series from the tags/expressions available in the server. In this case the structure of groups and time series is created being equivalent to the structure of groups and tags/expressions where the data source for each time series will be a tag/expression which is the basis for this time series.


# InfluxDB Connectivity (Store)

Server provides InfluxDB store to write time series in InfluxDB database. The store in its turn writes data according to Influx Line Protocol by sending HTTP-POST requests to database.

### Key Features <a href="#h.kunpaoip10hy" id="h.kunpaoip10hy"></a>

* Flexible tuning of writing performance.
* Authentication support (Base64 Auth).
* Verification of SSL server certificate.
* Flexible tuning of time series metadata.
* OPC UA Historical access (raw/aggregated data reading).


# Parameters

### General <a href="#h.iy2j3qpghg0m" id="h.iy2j3qpghg0m"></a>

* **Host:** contains target IP address or database server hostname.&#x20;
* **Port:** contains database server port (8086 by default).&#x20;
* **Database:** contains name of the database.&#x20;
* **Retention Policy:** contains retention policy.&#x20;

{% hint style="info" %}
Note that if retention policy doesn’t exist in the database server, writing will not be performed
{% endhint %}

* **Measurement:** contains measurement name.
* **Request Timeout:** contains time interval (in milliseconds) within which the response from the database server must be received. If the response is not received during the specified interval an error occurs.
* **Wait after Write:** contains timeout interval (in milliseconds) before the start of next data writing to the store.
* **Wait after Error**: contains timeout interval (in milliseconds) in case an error occurs during data writing or store preparation.
* **Inter-request Interval:** contains timeout interval (in milliseconds) before sending the next request. It is used if data doesn’t fit in one request.

### Security <a href="#h.mxh7apafhfs0" id="h.mxh7apafhfs0"></a>

* **Use Credentials:** specifies that it is necessary to use credentials (Base64 Auth in HTTP-header).
* **Username:** contains username.
* **Password:** contains password.
* **Use SSL:** specifies that it is necessary to verify database server SSL certificate.
* **SSL Verification:** contains verification mode of database server SSL certificate:
  * Accept any.
  * Verify chain of trust by using a store of certificates of the operating system.
  * Verify chain of trust by using custom certificate of certification authority.
* **Custom CA File:**  contains custom certificate of certification authority.

### Performance <a href="#h.32r40uqgjetb" id="h.32r40uqgjetb"></a>

* **Series per Request:** contains maximum number of time series that can be written per one request.
* **Samples per Request:** contains maximum number of samples for each time series that can be written per one request.
* **Max. Buffer Size:** contains maximum size of sample buffer for each time series that is accumulated in the server memory.

### Advanced <a href="#h.33nk75zg8yc1" id="h.33nk75zg8yc1"></a>

* **Add Server UID to Tag:** specifies that for all store associated time series server UID will be added as *su* tag value (record metadata).
* **Add Store UID to Tag:** specifies that for all store associated time series store UID will be added as *stu* tag value (record metadata).
* **Add Time Series UID to Tag:** specifies that for all store associated time series time series UID will be added as *tsu* tag value (record metadata).
* **Add Time Series Path to Tag:** specifies that for all store associated time series string path to time series will be added as *tsp* tag value (record metadata).
* **Add Time Series Comment to Tag**: specifies that for all store associated time series comment to time series will be added as *tsc* tag value (record metadata).
* **Use Server UID in ‘Hash’ Addresses:** specifies that unique server identifier should be used to generate *Hash* addresses.

Most of the parameters described above are available as OPC UA items. More information about editing server object properties via OPC UA is described [<mark style="color:blue;">here</mark>](/basics/opc-ua/access-to-object-settings).


# Addressing

The following address types are specified for identification of time series in InfluxDB: *Path, custom address*, and *Hash*. The address specifies which value should be used for *tsid* tag as a time series identifier.

**"Path" address:** Identifies time series by using string path.

**Custom text:** Identifies time series by using custom text.

**"Hash" address:** Identifies time series by using hash-function. Hash is calculated as follows: *SHA1(ServerUID + TimeSeriesUID)*. Thus time series gets the following unique global identifier *LhdB7l4450F/xs1GjJzHGV+k2VU=*. Let’s consider the case of Hash address use. You have 100 one-type distributed Modbus devices to control electrical network parameters. You plan to use 100 instances of Monokot Server to get data from multimeters and to store it in InfluxDB.

By the way for such a large order you will be provided with a very good discount! 🙂

After you configure, debug and start one instance of the server using time series *Path* addressing everything will operate correctly. But if you upload config of the first server to the second and subsequent instances you will get undesirable effect: data from all servers will be randomly written to the same time series because all server instances have the same addressing.

![](/files/GfG9NSvGu3t9IhE3eqeH)

To solve this problem specify *Hash* address for all time series. In this case data will be written correctly: each time series specified in the server will be presented by its own time series in the database. Another way of solving this task can be the use of *Path* addressing together with *Add Server UID to Tag* flag. This method is more convenient for further queries, but *Hash* addressing also has its advantages. *Hash* address is always a fixed-size string (28 bytes). That is why:

* Maximum message body size in the writing request becomes predictable and can be calculated.

For example, let’s consider the following path to the time series: *DrillingRig.VariableFrequencyDriveHouse.MudCirculatingSystem.VerticalSludge Pump1.Voltage* (string size is 90 bytes). Thus when using *Path* addressing you need to send \~900 bytes to the database server to write just 10 values. Big size of the request increases information network load and reduces InfluxDB performance.

* Short values of tags have a positive effect on writing performance into database.
* Short values of tags have a positive effect on fetch performance from database.

Disadvantages of using *Hash* addressing:

* Hash is not human “friendly”. For example, the following hash *6ig0pCCEf4XcZZZqacVATbaNJTU=*  can unambiguously identify time series in the database, but at the same time it doesn’t carry any additional information about the time series. In other words it is impossible to understand which parameter (temperature, pressure, current, torque, etc.) is hidden behind this identifier. In order to map hash address with a certain time series there is a special tool in Monokot Server Administrator which is described below.
* After time series is deleted *Hash* address will be lost forever.


# Data Structure

Structure of fields and tags written for the time series can be as follows:

| **time**            | **v**   | **s** | **tsid**           |
| ------------------- | ------- | ----- | ------------------ |
| 2019-08-28 03:18:29 | 1234.12 | 0     | Group1.Temperature |

or

| **time**            | **v** | **s** | **tsid**           | **tsc** |
| ------------------- | ----- | ----- | ------------------ | ------- |
| 2019-08-28 03:18:29 | 88.7  | 0     | Group1.Temperature | Room 27 |

**v** and **s** are the required time series fields. **v** field is a real number and it contains sample value in the moment of time (time field). **s** field is a integer, it contains status of sample or data source in the moment of time (time field) and can take the following values:

| **Status**            | **Code (DEC)** | **Code (HEX)** |
| --------------------- | -------------- | -------------- |
| Good                  | 0              | 0x00           |
| Uncertain             | 1073741824     | 0x40000000     |
| UncertainInitialValue | 1083310080     | 0x40920000     |
| Bad                   | -2147483648    | 0x80000000     |
| BadNoCommunication    | -2144272384    | 0x80310000     |
| BadTypeMismatch       | -2139881472    | 0x80740000     |
| BadOutOfRange         | -2143551488    | 0x803C0000     |
| BadLicenseExpired     | -2129788928    | 0x810E0000     |
| BadNotFound           | -2143420416    | 0x803E0000     |
| BadUserAccessDenied   | -2145452032    | 0x801F0000     |
| BadObjectDeleted      | -2143354880    | 0x803F0000     |
| BadNodeIdUnknown      | -2144075776    | 0x80340000     |
| BadOutOfService       | -2138243072    | 0x808D0000     |

{% hint style="info" %}
Note that *BadLicenseExpired* status means that demo period of time series associated data source has expired. If demo period is expired for InfluxDB store data will no longer be written to the database
{% endhint %}

*tsid* is the required time series tag. *tsid* tag contains time series address (identifier), for example, string path *Group1.Temperature.* Please find more information about possible address types below. Optional are the following tags: *su*, *stu*, *tsu*, *tsp*, *tsc*.


# About Metadata

For better understanding of the parameters from the Advanced category let’s consider the time series shown in the picture below:

<figure><img src="/files/XaJL7ZE9uRbCB62yggu0" alt=""><figcaption></figcaption></figure>

Note that for all time series specified data source and store are the same, but types of addresses and comments are different.

**Case when default store parameters are used.** After data source value changes request *SELECT \* FROM "timeseries"."autogen"."tssamples" GROUP BY "tsid" ORDER BY DESC LIMIT 1* will return the following result:

| **time**            | **tsid**                     | **s** | **v** |
| ------------------- | ---------------------------- | ----- | ----- |
| 2019-09-25 23:12:41 | MySeries.Series1             | 0     | 25.00 |
| 2019-09-25 23:12:41 | MyCustomID                   | 0     | 25.00 |
| 2019-09-25 23:12:41 | 22ePXYjPQ0GM/3iyM+Dii12+3n4= | 0     | 25.00 |

**Case when Add Time Series Comment to Tag parameter is True.** After data source value changes the same request will return the following result:

| **time**            | **tsid**                     | **tsc**    | **s** | **v** |
| ------------------- | ---------------------------- | ---------- | ----- | ----- |
| 2019-09-25 23:57:16 | MySeries.Series1             | S1 Comment | 0     | 99.00 |
| 2019-09-25 23:57:16 | MyCustomID                   | S3 Comment | 0     | 99.00 |
| 2019-09-25 23:57:16 | 22ePXYjPQ0GM/3iyM+Dii12+3n4= | S2 Comment | 0     | 99.00 |

Thus *tsc* tag will be added to the record metadata for each time series and it will contain time series comment.

**Case when Add Time Series Path to Tag parameter is True*****.*** After data source value changes the same request will return the following result:

| **time**            | **tsid**                     | **tsp**          | **s** | **v**  |
| ------------------- | ---------------------------- | ---------------- | ----- | ------ |
| 2019-09-26 00:09:58 | MySeries.Series1             | MySeries.Series1 | 0     | 117.00 |
| 2019-09-26 00:09:58 | MyCustomID                   | MySeries.Series3 | 0     | 117.00 |
| 2019-09-26 00:09:58 | 22ePXYjPQ0GM/3iyM+Dii12+3n4= | MySeries.Series2 | 0     | 117.00 |

Thus *tsp* tag will be added to the record metadata for each time series and it will contain path to the series.

**Case when Add Server UID to Tag parameter is True.** After data source value changes the same request will return the following result:

| **time**            | **tsid**                     | **su**                   | **s** | **v** |
| ------------------- | ---------------------------- | ------------------------ | ----- | ----- |
| 2019-09-26 00:09:58 | MySeries.Series1             | CeSqAF5sGUqMJqdilungXg== | 0     | 33.00 |
| 2019-09-26 00:09:58 | MyCustomID                   | CeSqAF5sGUqMJqdilungXg== | 0     | 33.00 |
| 2019-09-26 00:09:58 | 22ePXYjPQ0GM/3iyM+Dii12+3n4= | CeSqAF5sGUqMJqdilungXg== | 0     | 33.00 |

Thus *su* tag will be added to the record metadata for each time series and it will contain unique server identifier in the format of Base64.

You can use different combinations of flags from the Advanced category in order to define several meta-tags.


# Diagnostics

In addition to diagnostic variables described in the "Stores" [<mark style="color:blue;">section</mark>](/time-series-and-stores/stores/diagnostics) InfluxDB store has diagnostic variable *MaxWriteBodySize* which contains maximum writing request size measured in bytes.


# How to: Configure for InfluxDB 2.x

Since the data logger is designed for InfluxDB 1.x, some additional steps need to be performed to work with InfluxDB 2.x.

On the InfluxDB 2.x side, you need to create authentication (Basic Auth) using the Influx CLI. To do this, run the following command and type the password for NEW\_USER\_NAME\_V1:

```powershell
influx v1 auth create --org-id YOUR_ORG_ID  --read-bucket YOUR_BUCKET_ID --write-bucket YOUR_BUCKET_ID --username NEW_USER_NAME_V1 --token YOUR_OPERATOR_TOKEN --host http://localhost:8086
```

For the InfluxDB data logger, specify the following settings:

<figure><img src="/files/G7ArvV2fD9mSwT6LLr8O" alt=""><figcaption></figcaption></figure>

then specify the credentials:

<figure><img src="/files/n37cwesosHrtAejE7kQo" alt=""><figcaption></figcaption></figure>

and then disable the DDL settings:

<figure><img src="/files/YFin6k5vV5JqyxBhBFBc" alt=""><figcaption></figcaption></figure>

In order for the changes to take effect on the server, click the Sync button.


# PostgreSQL Connectivity

Store allows you to save time series data in PostgreSQL database. It uses a native PostgreSQL driver to interact with the database and provides high reliability and performance.

### Key Features <a href="#h.q6tu5c18i0e8" id="h.q6tu5c18i0e8"></a>

* Flexible tuning of writing performance.
* Verification of SSL server certificate.
* Flexible tuning of time series metadata and database design.
* OPC UA Historical access (raw/aggregated data reading).

We strongly recommend using TimescaleDB extension as it has several advantages over traditional PostgreSQL:

* High performance at INSERTs and SELECTs
* Fast removal of old data
* Automatic data compression


# Parameters

### General <a href="#h.ngydid6um4rf" id="h.ngydid6um4rf"></a>

* **Host:** contains target IP address or database server hostname.
* **Port:** contains database server port (5432 by default).
* **Database:** contains name of the database.
* **Schema**: contains name of the schema.
* **Table Prefix**: contains prefix of the tables.
* **Connection Timeout:** contains the time interval (in milliseconds) within which the connection to the database should be established. If the connection is not established within the specified time, an error occurs.
* **Request Timeout:** contains time interval (in milliseconds) within which the response from the database server must be received. If the response is not received during the specified interval, an error occurs.
* **Max. Buffer Size:** contains maximum size of sample buffer for each time series that is accumulated in the server memory. &#x20;
* **Wait after Write:** contains timeout interval (in milliseconds) before the start of next data writing to the store.
* **Wait after Error**: contains timeout interval (in milliseconds) in case an error occurs during data writing or store preparation.
* **Inter-request Interval:** contains timeout interval (in milliseconds) before sending the next request. It is used if data doesn’t fit in one request.

### Security <a href="#h.vsannrjlkcdw" id="h.vsannrjlkcdw"></a>

* **Username:** contains username.
* **Password:** contains password.
* **Use SSL:** specifies that it is necessary to verify database server SSL certificate.
* **SSL Verification:** contains verification mode of database server SSL certificate:
  * Accept any.
  * Verify chain of trust by using a store of certificates of the operating system.
  * Verify chain of trust by using custom certificate of certification authority.
* **Custom CA File:**  contains custom certificate of certification authority.

### Performance <a href="#h.45fuuylh92h8" id="h.45fuuylh92h8"></a>

* **Series per Request:** contains maximum number of time series that can be written per one request.
* **Samples per Request:** contains maximum number of samples for each time series that can be written per one request.
* **Max. Buffer Size:** contains maximum size of sample buffer for each time series that is accumulated in the server memory.
* **Wait after Write:** contains timeout interval (in milliseconds) before the start of next data writing to the store.
* **Wait after Error**: contains timeout interval (in milliseconds) in case an error occurs during data writing or store preparation.
* **Inter-request Interval:** contains timeout interval (in milliseconds) before sending the next request. It is used if data doesn’t fit in one request.

### Advanced <a href="#h.tgirsy885ch8" id="h.tgirsy885ch8"></a>

* **Add Server UID to Tag:** specifies that for all store associated time series server UID will be added as *su* tag value (record metadata).
* **Add Store UID to Tag:** specifies that for all store associated time series store UID will be added as *stu* tag value (record metadata).
* **Add Time Series UID to Tag:** specifies that for all store associated time series time series UID will be added as *tsu* tag value (record metadata).
* **Add Time Series Path to Tag:** specifies that for all store associated time series string path to time series will be added as *tsp* tag value (record metadata).
* **Add Time Series Comment to Tag**: specifies that for all store associated time series comment to time series will be added as *tsc* tag value (record metadata).
* **Use Server UID in ‘Hash’ Addresses:** specifies that unique server identifier should be used to generate *Hash* addresses.
* **Database Auto-creation:** if the parameter is set, database will be created automatically.
* **Schema Auto-creation:** if the parameter is set, schema will be created automatically.
* **Table Auto-creation:** if the parameter is set, data and metadata tables will be created automatically.
* **Index Auto-creation:** if the parameter is set, indexes for tables will be created automatically.


# Addressing

The addressing of time series is done in the same way as for [<mark style="color:blue;">InfluxDB</mark>](/time-series-and-stores/influxdb-connectivity-store/addressing).


# Database Design

By default, the store creates a database and two tables: *tssamples\_metadata* and *tssamples\_data*. Metadata of the time series associated with the store is placed In *tssamples\_metadata*, while the time series values are written in *tssamples\_data*.&#x20;

Structure of the time series metadata table (*tssamples\_metadata*):

| <p>tag\_set \[PK]</p><p><strong>jsonb</strong></p> | <p>server\_uid</p><p><strong>text</strong></p> | <p>store\_uid</p><p><strong>text</strong></p> | <p>ts\_uid</p><p><strong>text</strong></p> | <p>ts\_path</p><p><strong>text</strong></p> | <p>ts\_comment</p><p><strong>text</strong></p> | <p>tag\_set\_id</p><p><strong>integer</strong></p> |
| -------------------------------------------------- | ---------------------------------------------- | --------------------------------------------- | ------------------------------------------ | ------------------------------------------- | ---------------------------------------------- | -------------------------------------------------- |

* **tag\_set**: The column is the primary key of the table and is of the JSONB type. The column is a set of attributes or *tags* (key-value pairs) identifying a time series. By default, the set contains only one tag, *tsid*, representing the address of the time series. However, by changing parameters from the *Advanced* category, you can add additional tags. For example, if you set the parameter *Add Time Series Comment to Tag*, a *tsc* tag will be added to the set containing a comment to the series.
* **server\_uid**: The column is of the TEXT type and contains a unique server identifier.
* **store\_uid**: The column is of the TEXT type and contains unique store identifier.
* **ts\_uid**: The column is of the TEXT type and contains unique time series identifier.
* **ts\_path**: The column is of the TEXT type and contains path to time series. The values of this column are indexed.
* **ts\_comment**: The column is of the TEXT type and contains comment for time series.
* **tag\_set\_id**: The column is of the INTEGER type, is auto-incremental and contains unique numeric identifier for time series.

Structure of the time series data table (*tssamples\_data*):

| <p>sample\_time</p><p><strong>timestamp without time zone</strong></p> | <p>tag\_id</p><p><strong>integer</strong></p> | <p>sample\_value</p><p><strong>double precision</strong></p> | <p>sample\_status</p><p><strong>integer</strong></p> |
| ---------------------------------------------------------------------- | --------------------------------------------- | ------------------------------------------------------------ | ---------------------------------------------------- |

* **sample\_time:** The column is of the TIMESTAMP WITHOUT TIME ZONE type and contains measurement time. The values of this column are indexed.
* **tag\_id**: The column is of the INTEGER type and contains the link to the *tag\_set\_id* column from the *tssamples\_metadata* table. The values of this column are indexed.
* **sample\_value**: The column is of the FLOAT8 type and contains the sample value.
* **sample\_status**: The column is of the INTEGER type and contains the sample status.

Below is an example of a database query that will return data for a 5-minute interval for time series with the paths *MySeries.Temperature* and *MySeries.Pressure*:

```sql
SELECT m.ts_path, d.sample_time, d.sample_value, d.sample_status
FROM public.tssamples_data d
JOIN public.tssamples_metadata m ON m.tag_set_id = d.tag_id
WHERE d.sample_time BETWEEN '2020-03-20T09:20:00' AND '2020-03-20T09:25:00'
AND (m.ts_path = 'MySeries.Temperature' OR m.ts_path = 'MySeries.Pressure')
ORDER BY m.tag_set_id, d.sample_time DESC
```

Note that the time of this query is in the UTC format.


# Data Compression

Storing time series in PostgreSQL can be very demanding in terms of disk space consumption. For example, 500 time series changing every 500 ms will consume \~6000 MB of disk space per day. TimescaleDB provides a mechanism for automatically compressing data with a very high compression rate, for example, for the above case the size of compressed data will be \~350 MB. **The store does not provide an automatic mechanism to set compression**, but you can set it by running the following SQL scripts:

```sql
// set compression for the hypertable
ALTER TABLE public.tssamples_data SET
(
    timescaledb.compress,
    timescaledb.compress_segmentby = 'tag_id'
)
```

and&#x20;

<pre class="language-sql"><code class="lang-sql"><strong>// set up automatic data compression call
</strong><strong>SELECT add_compress_chunks_policy('public.tssamples_data', INTERVAL '7 days');
</strong></code></pre>

You can read more about data compression in TimescaleDB [<mark style="color:blue;">here</mark>](https://docs.timescale.com/latest/using-timescaledb/compression).


# REST Connectivity

REST store provider is used for sending time series data via HTTP. The driver allows to dynamically generate HTTP messages using JavaScript.

### Key Features <a href="#h.rk8c6dekn2su" id="h.rk8c6dekn2su"></a>

* HTTPS encryption support.
* Flexible message header and body generation using JavaScript.
* HTTP authorization support.
* Built-in cryptographic functions.

By default, REST store provider is configured for inserting data into InfluxDB, but it can be easily re-configured to work with cloud-based IoT platforms or other services


# Parameters

### General <a href="#h.7ent2ri2xon7" id="h.7ent2ri2xon7"></a>

**URL:** contains the target service URL, such as <http://localhost:8086/write?db=monokotdb&precision=ms> or <https://192.168.0.75:8086/write?db=monokotdb&precision=ms>

**Method:** contains HTTP request method (POST or PUT).

**User Agent:** contains value for User-Agent header.

**HTTP Headers:** contains additional HTTP request headers in the following format: *Key1: Value1.*

**Secret String:** contains a secret string used by the driver, such as the authorization token. The secret string is only accessible by the server and cannot be read by other clients.

**Request Timeout:** contains time interval (in milliseconds) within which the response from the server must be received. If the response is not received during the specified interval an error occurs.

**Wait after Write:** contains timeout interval (in milliseconds) before the start of next data writing to the server.

**Wait after Error:** contains timeout interval (in milliseconds) in case an error occurs during data writing.

**Inter-request Interval:** contains timeout interval (in milliseconds) before sending the next request. It is used if data doesn’t fit in one request.

### Security <a href="#h.fybeaqp34tsi" id="h.fybeaqp34tsi"></a>

**Use Credentials:** specifies that it is necessary to use credentials (Base64 Auth in HTTP-header).

**Username:** contains username.

**Password:** contains password.

**Use SSL:** specifies that it is necessary to verify server SSL certificate.

**SSL Verification:** contains verification mode of the target server SSL certificate:

* Accept any.
* Verify chain of trust by using a store of certificates of the operating system.
* Verify chain of trust by using custom certificate of certification authority.

**Custom CA File:**  contains custom certificate of certification authority.

### Performance <a href="#h.macu933qduq" id="h.macu933qduq"></a>

**Series per Request:** contains maximum number of time series that can be written per one request.

**Samples per Request:** contains maximum number of samples for each time series that can be written per one request.

**Max. Buffer Size:** contains maximum size of sample buffer for each time series that is accumulated in RAM.

### Message <a href="#h.xbv5qp780p5c" id="h.xbv5qp780p5c"></a>

**Message Script:** contains a script for dynamic generation of HTTP message headers and body and is executed before sending each new request. You can read more about this [<mark style="color:blue;">here</mark>](/time-series-and-stores/rest-connectivity/message-script).


# Addressing

As each request for data insertion is generated using a message script, the addressing of time series is not performed. A special *(Not use)* address is used.


# Message Script

The message script allows to dynamically generate an HTTP request for sending time series to the target URL. The script uses JavaScript with the support for all built-in objects and functions of ECMAScript 5 specification (read more about it [<mark style="color:blue;">here</mark>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects)).  As a result, the script should return a *RestRequestMessage* object. The object is a prototype of the generated HTTP request and should contain all necessary message headers and body. Detailed description of the object can be found [<mark style="color:blue;">here</mark>](/time-series-and-stores/rest-connectivity/restrequestmessage).

In order to access the time series data ready to be sent, the *dataContext* object is used. It provides access to an array of time series data. The object provides access to the secret string, [<mark style="color:blue;">TimeSeries</mark>](/time-series-and-stores/rest-connectivity/timeseries) and [<mark style="color:blue;">ValueState</mark>](/scripts/api/valuestate) objects. A detailed description of *dataContext* can be found [<mark style="color:blue;">here</mark>](/time-series-and-stores/rest-connectivity/datacontext).

The following example shows a script used for inserting data into InfluxDB, which marks the data with an additional *ts\_type* tag during generation.

```javascript
var message = new RestRequestMessage();
var body = '';
var firstLine = true;
var ts_type = 'misc'; // Declare a variable for the ts_type tag

// Process the ready-to-publish time series
for (var i = 0; i < dataContext.series.length; i++)
{
	var ts = dataContext.series[i];

	// Determine the value of the ts_type tag
	// based on the path of the time series
	if (ts.path.includes('Power'))
		ts_type = 'power';
	else if (ts.path.includes('Alarms'))
		ts_type = 'alarm';
	else if (ts.path.includes('Fuel'))
		ts_type = 'fuel';

	// Process the samples of the i-th time series
	for (var j = 0; j < ts.samples.length; j++)
	{
		var sample = ts.samples[j];        
		
		if (!firstLine)
			body += '\n'; // If at least one line was added, insert a line break
           
		// Generate a string like this:
		// rest_measures,ts_path=Plant.Generator1.Power full.kWh value=280.87124,status=0,ts_type='power' 1591172295193
		body += 'rest_measures,ts_path=' + ts.path
            + ' value=' + sample.value.toFixed(5)
            + ',status=' + sample.status
            + ', ts_type=' + ts_type
            + ' ' + sample.time.getTime();

            firstLine = false;
	}
}

// Specifying the final string as the HTTP request body
message.body = body;
return message;
```

When publishing data to various cloud services, cryptographic and text functions may be useful. Access to them is provided by [<mark style="color:blue;">MosCrypto</mark>](/scripts/api/moscrypto) and [<mark style="color:blue;">MosText</mark>](/scripts/api/mostext) objects.


# RestRequestMessage

RestRequestMessage object represents an HTTP request returned by the REST Store message script.

### Constructor <a href="#h.oo8fqfidvw4z" id="h.oo8fqfidvw4z"></a>

```javascript
var message = new RestRequestMessage();
```

### Fields <a href="#h.2av81iyk042f" id="h.2av81iyk042f"></a>

| **Name** | **Description**                                                                                                       |
| -------- | --------------------------------------------------------------------------------------------------------------------- |
| body     | Contains the body of the HTTP request.                                                                                |
| headers  | Contains the HTTP request headers. Methods and properties are equivalent to the [Bundle](/scripts/api/bundle) object. |

### Examples <a href="#h.6y2dhlx9go9i" id="h.6y2dhlx9go9i"></a>

A custom HTTP header can be added using the following code:

```javascript
var request = new RestRequestMessage();

// Add header
request.headers.set('User-Agent', 'My Agent ' + new Date().getTime());
```

Note that HTTP message headers generated by the script have higher priority than the static HTTP headers specified in the REST Store.


# DataContext

The object is represented by the *dataContext* variable and provides access to time series and their samples ready for publication.

### Fields

| **Name**     | **Description**                                                                                   |
| ------------ | ------------------------------------------------------------------------------------------------- |
| token        | Intended to store arbitrary data available at each script execution.                              |
| series       | Contains an array of time series samples. Each time series is represented by a TimeSeries object. |
| secretString | Contains the secret string of the REST store provider.                                            |


# TimeSeries

The TimeSeries object is intended to obtain data on time series.

### Fields

| **Name** | **Description**                                                                                                         |
| -------- | ----------------------------------------------------------------------------------------------------------------------- |
| path     | Contains string path to time series.                                                                                    |
| comment  | Contains comment for time series.                                                                                       |
| samples  | Contains an array of time series samples. Each sample is represented by a [ValueState](/scripts/api/valuestate) object. |


# Overview

The server has a built-in engine for running JS scripts that supports the ECMAScript 5 specification. The script manager provides a flexible mechanism for converting data received, for example, from a Modbus device and presenting them as OPC UA variables or time series.

### Key Features <a href="#h.omjuh8c18pvw" id="h.omjuh8c18pvw"></a>

* Formula between tags.
* Mathematical functions and number conversion to and from bytes.
* Operators of conditional statements (if-else) and cycles (for, while).
* Working with numbers, strings, date and time, arrays and dictionaries (hashtables).
* Re-use of code (modules).
* OPC UA Methods.


# Expression

**Expression** represents a result of executing a JavaScript function specified in code. Expressions are organized in a hierarchy that forms the structure of OPC UA items, where the folder is a group of expressions, and the variable is an expression. The execution of the expression code is made manually (via the OPC UA variable), periodically or on tag changning, depending on the set of triggers. In the general case, expressions must have correct syntax, contain the keyword **return** and return the result that can be presented in the format of the returned data type, for example:

```javascript
return Math.sin(Math.PI / 2);
```

or

```javascript
if (context.data['tag_flag'].state.value == true)
	return FahrenheitToCelsius(context.data['tag_temperature'].state.value);
else return context.data['tag_temperature'].state.value;
```

For each expression, a global object **context** is defined, which can be used to access context-dependent properties and methods, i.e., during the execution of an expression, the **context** object is filled with the data of the expression currently being executed. For example, the following code is given for all expressions:&#x20;

```javascript
if (context.expression.id == 'MyExpression')
  return 111;
else if (context.expression.id == 'NotMineExpression')
  return 999;
else return 0;
```

In this case, *MyExpression* will return *111*, *NotMineExpression* will return *999*, and all others will return *0*. The above mentioned script can be declared in modules as a function, which will be an example of code reuse. Then, the expression will return a function as a result.

Module1 code:

```javascript
function getResult() {
if (context.expression.id == 'MyExpression')
  return 111;
else if (context.expression.id == 'NotMineExpression')
  return 999;
else return 0;
}
```

Expressions code:

```javascript
return getResult();
```

Transformation of expression script into binary code involves several steps:

* Syntax check of the expression code
* Linking the imported modules (whose code also passes syntax check)
* Building the expression (converting the resulting code into binary code)

Note that the procedure of binary code creation may lead to memory shortage. For example, there are several thousand expressions defined on the server and they all use the same 10 KB module. In this case, the module code will be linked to each expression, so the module code will be copied into RAM as many times as the number of expressions defined on the server. Let's assume that the module code was erroneously changed and the module size increased to 500 KB. In this case, an avalanche-like increase in RAM consumption will occur (\~ 50 times), which may cause the server to crash. To eliminate such problems, the server can be run in [<mark style="color:blue;">safe mode</mark>](/basics/startup-parameters).

All expressions are executed in an isolated context, i.e. variables and objects defined in the code are not shared, a special mechanism is provided for data transfer between expressions.


# Parameters

Description of expression parameters is shown below.&#x20;

* **Name:** contains symbolic name of the expression.
* **DataType:** specifies the type of data to be returned.
* **Code**: contains the JavaScript code of the expression.
* **Triggers:** indicates a set of triggers that lead to code execution.
* **Imports:** contains the set of imported modules.
* **Comment:** contains a custom comment.

Most of the parameters described above are available as OPC UA items. More information about editing server object properties via OPC UA is described[ ](https://docs.monokot.io/hc/en-us/articles/360034746391)[<mark style="color:blue;">here</mark>](/basics/opc-ua/access-to-object-settings).


# Import & Export

The script manager allows to import / export the structure of groups and expressions from / to a CSV file. The CSV file is formatted as follows:

* Each field is enclosed in double quotes. If the field contains double quotes, then additional double quotes are put around them. For example, the field **"Mud" temperature, °C** should look like this: **"""Mud"" temperature, °C"**
* Fields are separated by commas. For example: **"Group1","RandomExpr","pt=trig1:100;","","DOUBLE","return Math.random();","Random number every 100ms"**
* Each new set of fields begins with a new line
* The first line defines the names of the fields (parameters) and should contain all the parameters used

Description of fields used when exporting and importing expressions:

* **Expression Group:** contains the path to the group where the expression is located. Group names are separated by dots.
* **Expression:** contains the expression name.
* **Triggers:** contains a set of triggers defined in the expression, such as *dt=trig\_b:Examples.TagB.* The format of this field is described below.
* **Modules:** Contains a set of modules imported into the expression, e.g. *module1;module2;md5* (modules are separated by semicolons)..
* **DataType:** contains the type of data to be returned.
* **Code:** contains the expression code.
* **Comment:** contains any custom text.

Triggers are written using the following format: \[TRIGGER\_TYPE]=\[TRIGGER\_NAME]:\[PARAMETER], where

* **TRIGGER\_TYPE:** specifies the trigger type (periodic or data trigger) and takes the value of *pt* or *dt*, respectively.
* **TRIGGER\_NAME:** specifies the name (key) of the trigger.
* **PARAMETER:** depending on the trigger type, defines the following parameter:

1. Update rate set in milliseconds (for the periodic trigger).
2. Path to the tag (for the data trigger).

To define several triggers, you need to specify the required number of strings in \[TRIGGER\_TYPE]=\[TRIGGER\_NAME]:\[PARAMETER] format divided by semicolons.


# Go Online

For diagnostics and debugging expressions Monokot Server Administrator provides the *Go Online* mode. In the *Go Online* mode, the following additional expression information is available:

* **Actual:** contains the value of the expression
* **Status:** contains the current tag status, e.g. *Good*, *BadLicenseExpired*
* **Update Time:**  contains the time (UTC) of the last expression update

To read expression values, the following requirements must be met:

* The user (specified in the credentials for connection) must have the read access rights


# Programming Examples

This section provides some examples of working with expressions and using the built-in scripting language.


# How to: Calculate Arithmetic Mean

The guide demonstrates how to create an expression that calculates the arithmetic mean between two tags. Before starting, create a Modbus device and two numeric tags named *source\_tag1* and *source\_tag2* respectively.

Open Monokot Server Administrator and double-click *Scripts* on the *Server Explorer* pane. Click *New Expression* and set the name *Mean* for the expression that appears. Insert the following code into the expression code editor:

```javascript
// Getting the value of the first tag
var tag1 = context.data['tag1_trig'].state.value;

// Getting the value of the second tag
var tag2 = context.data['tag2_trig'].state.value;

return (tag1 + tag2) / 2;
```

Press *Ctrl + Enter* to apply the change in the code editor.

Go to the *Triggers* tab and click *Add Data...*. Select the tag created earlier (*source\_tag1*) as the data source for the trigger. Enter the name (key) *tag1\_trig* for the trigger. In the same way, create a data trigger for the second tag.

![](/files/qxE89KEwz7WPBTMQqrHp)

In order for the changes to take effect on the server, click the Sync button. Now, each time one of the tags is updated, the expression will be evaluated. You can see the result of the expression in the *Go Online* mode or read it as an OPC UA variable.

![](/files/rd47UJRw0ujQ95jUNVkE)


# How to: DoNothing

The manual demonstrates how to filter out part of values using an expression. Before starting, create a data source – a tag named *Sine*, which will generate a source signal, e.g. a sinusoid.&#x20;

Open Monokot Server Administrator and double-click *Scripts* on the *Server Explorer* pane. Click *New Expression* and set the name *HalfSine* for the expression that appears. Insert the following code into the expression code editor:

```javascript
var state = context.data['trig_sine'].state;

if (state.value < 0)
    return MosUtils.doNothing;

return state;
```

Press *Ctrl + Enter* to apply the change in the code editor.

Go to the *Triggers* tab and click *Add Data...*. Select the tag *Sine* as the data source for the trigger. Enter the name (key) *trig\_sine* for the trigger.

![](/files/Mwl62X9ew2kt0MV1htdU)

In order for the changes to take effect on the server, click the Sync button. Thus, the expression will filter out all negative values received from the tag. You can read more about the *ValueState* object [<mark style="color:blue;">here</mark>](/scripts/api/valuestate).

If you set up saving tag values and expressions as time series, you will see the following picture:

![](/files/5r0MASM9CbxtjOWMKM3w)


# How to: Writing to Tag

The guide demonstrates how to create an expression that writes the control signal if the threshold value is exceeded or decreased. Before starting, create a Modbus device and two tags named *monitoring\_tag* (WORD, 16-bit unsigned integer) and *control\_tag* (BOOLEAN).

Open Monokot Server Administrator and double-click *Scripts* on the *Server Explorer* pane. Click *New Expression* and set the name *Writer* for the expression that appears. Insert the following code into the expression code editor:&#x20;

```javascript
// Declaring a limit as a constant
const LIMIT = 100;

// Getting the tag value
var value = context.data['monitoring_tag_trig'].state.value;

if (value > LIMIT)
  return MosUtils.writeTagValueSync('control_tag', true);
else
  return MosUtils.writeTagValueSync('control_tag', false);
```

Press *Ctrl + Enter* to apply the change in the code editor.&#x20;

Go to the *Triggers* tab and click *Add Data...*. Select the tag *monitoring\_tag* created earlier as the data source for the trigger. Enter the name (key) *monitoring\_tag\_trig* for the trigger.

![](/files/n8O86FEFidCvvmXD2zls)

In order for the changes to take effect on the server, click the Sync button. Thus, the expression will be executed each time the *monitoring\_tag* is changed. If *monitoring\_tag* exceeds 100, *control\_tag* will be set to *True*, otherwise *False*.

You can read more about the *MosUtils* object [<mark style="color:blue;">here</mark>](/scripts/api/mosutils).


# How to: Inverting Bits

The guide demonstrates how to create an expression that will invert the bits of a given tag. Before starting, create a local Modbus device, a tag with the name *source\_tag* and data format WORD (16-bit unsigned integer).

Open *Monokot Server Administrator*, double-click *Scripts* on the *Server Explorer* pane and go to the *Modules* tab. Click the *New Module* button and name the module *BitsOp*. Insert the following code into the code editor:

```javascript
function bit_test(num, bit){
    return ((num>>bit) % 2 != 0)
}

function bit_set(num, bit){
    return num | 1<<bit;
}

function bit_clear(num, bit){
    return num & ~(1<<bit);
}

function bit_toggle(num, bit){
    return bit_test(num, bit) ? bit_clear(num, bit) : bit_set(num, bit);
}
```

Press *Ctrl + Enter* to apply the change in the code editor.

![](/files/yQ7AorchsnimCLfAA05d)

Thus, the following functions are defined in the *BitsOp* module:

* **bit\_test:** returns the state (true or false) of the bit number *bit* from the number *num*
* **bit\_set:** sets the bit number *bit* of the specified number *num* to true and returns the resulting number
* **bit\_clear:** resets the bit number *bit* of the specified number *num* to false and returns the resulting number
* **bit\_toggle:** inverts the bit number *bit* of the specified number *num* and returns the resulting number

Go to the *Expressions* tab and click the *New Expression* button. For the expression that appeared, set the name *Inverse* and specify the data type WORD (16-bit unsigned integer). Insert the following code into the expression code editor:

```javascript
const NUMBER_OF_BIT = 16;

var value = context.data['source_tag_trig'].state.value;

for (var i = 0; i < NUMBER_OF_BIT; i++)
  value = bit_toggle(value, i);

return value;
```

Press *Ctrl + Enter* to apply the change in the code editor.

While in the code editor you can check the syntax by pressing the F9 key

Go to the *Triggers* tab and click *Add Data*.... Select the previously created tag (*source\_tag*) as the data source for the trigger. Enter *source\_tag\_trig* as the name (key) of the trigger.

![](/files/f3XXb9JSbGEhFzgltR58)

&#x20;Go to the *Imports* tab and click the checkbox of the *BitsOp* module.

![](/files/OwFkgEh2h1Sz9jseorX8)

In order for the changes to take effect on the server, click the Sync button. If you switch to *Go Online* mode, you will see a picture similar to the following (in my case, the number *21845* is inverted).&#x20;

![](/files/86Mi5O6ZtKiWY428roPN)


# How to: Execute SQL

This guide demonstrates how to create an expression that executes an SQL query to a PostgreSQL database using the ODBC driver. The ODBC driver for PostgreSQL must be installed on the target machine before starting.&#x20;

{% hint style="warning" %}
Please note that calling the *executeScalar* function will immediately put the script module into demo mode if it is not licensed
{% endhint %}

Open Monokot Server Administrator and double-click *Scripts* on the *Server Explorer* pane. Click *New Expression*, set the name *PgDateTime* for the expression that appears and set the *STRING* type for the return data. Insert the following code into the expression code editor:

```javascript
var connectionString = 'DRIVER={PostgreSQL UNICODE};Server=localhost;Port=5432;UID=postgres;PWD=qwerty;';
return MosOdbc.executeScalar(connectionString, 'SELECT now();');
```

Note that in the server connection line you need to specify your server credentials (*Server, Port, UID, PWD*). Press *Ctrl + Enter* to apply the change in the code editor.

Go to the *Triggers* tab and click *Add Periodic*. In order for the changes to take effect on the server, click the Sync button. Thus, the expression will return the current date and time received from PostgreSQL every 500 ms.

You can find the full set of *MosOdbc* functions and their descriptions [<mark style="color:blue;">here</mark>](/scripts/api/mosodbc).




---

[Next Page](/llms-full.txt/1)

