Modbus/TCP¶
Overview¶
Modbus/TCP is a communication protocol which is a variant of the Modbus family. It is based on a master/slave architecture and intended for use in industrial automation especially with PLCs or IO modules. Modbus/TCP is defined in IEC 61158.
Modbus uses big-endian representation for addresses and data items.
Protocol structure:
transaction identifier |
protocol identifier |
length field |
unit identifier |
function code |
data |
---|---|---|---|---|---|
2 byte |
2 byte (always 0x0000) |
2 byte (n+2) |
1 byte |
1 byte |
n byte |
Connection Properties¶
host
(string, required)¶
Hostname or IP address of the modbus device
Example: "126.4.10.52"
port
(integer, required)¶
Port of the Modbus device
Example: 15200
unitId
(integer)¶
Default: 1
socketTimeout
(integer)¶
Default: 30000
Additional restrictions:
Minimum:
2000
connectionStrategy
(object)¶
If a connection attempt fails, retries will be performed with increasing delay (waiting time) in between. The following parameters control how these delays behave.
Properties of the connectionStrategy
object:
initialDelay
(integer)¶
Delay (waiting time) of the first connection retry (in milliseconds). For subsequent retries, the delay will be increased according to the parameter incrementFactor which has a default value of 2.
Default: 1000
Additional restrictions:
Minimum:
1000
maxDelay
(integer)¶
Maximum delay (waiting time) to wait until the next retry (in milliseconds). The delay (waiting time) for any subsequent connection retry will not be larger than this value. Must be strictly greater than initialDelay.
Default: 30000
incrementFactor
(integer)¶
The factor used to increment initialDelay up to maxDelay. For example if initialDelay is set to 1000 and maxDelay to 5000 the values for the delay would be 1000, 2000, 4000, 5000.
Default: 2
Additional restrictions:
Minimum:
2
Endpoint Properties¶
unitId
(integer)¶
By setting this optional parameter, the unitId defined in the Connection resource will be overwritten.
Examples: 1
, 2
Additional restrictions:
Maximum:
255
fc
(integer, enum, required)¶
The Function Code (fc) defines the operation of the request. This can be any of the common Modbus codes, but the exact implementation depends on the concrete device manufacturer.
This element must be one of the following enum values:
1
2
3
4
5
6
15
16
Example: 2
address
(integer, required)¶
Example: 0
length
(integer, required)¶
The length describes how many registers should be read starting at the specified address. The registers of a modbus device have a length of 16 bits.
Example: 4
dataType
(string, enum)¶
If given, convert the Modbus value to this specified type. Types are available in byte ordering Big Endian (BE), or Little Endian (LE), or with additional word swap (BEWS, LEWS).
This element must be one of the following enum values:
raw
base64
boolean
doubleBE
doubleLE
floatBE
floatBEWS
floatLE
floatLEWS
int16BE
int16LE
int32BE
int32LE
uint16BE
uint16LE
uint32BE
uint32LE
Example: "floatLE"
interval
(integer)¶
Poll interval (best effort) in milliseconds
Default: 1000
Example: 2000
cronExpression
(string)¶
The Cron expression used to poll the endpoint. (For examples, see: https://github.com/node-cron/node-cron)
Examples: "1,2,4,5 * * * *"
, "1-5 * * * *"
, "*/2 * * * *"
,
"* * * January,September Sunday"
Supported function codes¶
For reading or writing data over Modbus/TCP the protocol provides a set of functions. Which action should be performed on the other end of the connection is defined by the function code (fc).
Supported function codes are:
Function code |
Action |
Operation |
---|---|---|
1 |
Read coils |
subscribe |
2 |
Read discrete inputs |
|
3 |
Read holding registers |
|
4 |
Read input registers |
|
5 |
Write single coil |
write |
6 |
Write single holding register |
|
15 |
Write multiple coils |
|
16 |
Write multiple holding registers |
Supported Data-types¶
In Modbus/TCP there are no predefined data-types. The Connectware supports sending the raw payload over MQTT as binary. If the data-type is known and supported by the respective fc, the payload is converted to JSON format.
The desired data type on read or on write is specified with the property
dataType
. The possible values are as follows:
DataType/FC |
1 |
2 |
3 |
4 |
Size |
raw |
✓ |
✓ |
✓ |
✓ |
variable |
bool |
✓ |
✓ |
x |
x |
1 bit |
ascii |
x |
x |
✓ |
✓ |
variable |
base64 |
x |
x |
✓ |
✓ |
variable |
int16BE |
x |
x |
✓ |
✓ |
16 bit |
int16LE |
x |
x |
✓ |
✓ |
16 bit |
int32BE |
x |
x |
✓ |
✓ |
32 bit |
int32LE |
x |
x |
✓ |
✓ |
32 bit |
uint16BE |
x |
x |
✓ |
✓ |
16 bit |
uint16LE |
x |
x |
✓ |
✓ |
16 bit |
uint32BE |
x |
x |
✓ |
✓ |
32 bit |
uint32LE |
x |
x |
✓ |
✓ |
32 bit |
floatBE |
x |
x |
✓ |
✓ |
32 bit |
floatLE |
x |
x |
✓ |
✓ |
32 bit |
doubleBE |
x |
x |
✓ |
✓ |
64 bit |
doubleLE |
x |
x |
✓ |
✓ |
64 bit |
bigUInt64BE |
x |
x |
✓ |
✓ |
64 bit |
bigUInt64LE |
x |
x |
✓ |
✓ |
64 bit |
If the payload is smaller than the required bits for the conversion (payload.length < dataType.length), an error is displayed in the logs and no message is sent over MQTT. If the payload has more bits (payload.length > dataType.length) than needed for the conversion, the “extra” bits are ignored and a message is sent over MQTT.
As a comparison to other documentation, this is a list of other common names for the supported types:
Common type name |
Size |
Minimum value |
Maximum value |
---|---|---|---|
char |
8 bit |
0 |
255 |
byte |
8 bit |
-128 |
127 |
short (int16) |
16 bit |
-2^15 |
2^15-1 |
int (int32) |
32 bit |
-2^31 |
2^31-1 |
uint (uint32) |
32 bit |
0 |
2^32-1 |
long64 |
64 bit |
-2^63 |
2^63-1 |
float |
32 bit |
IEEE 754 |
IEEE 754 |
double |
64 bit |
IEEE 754 |
IEEE 754 |
Input Format¶
This Modbus implementation supports writing using the standard function calls 5, 6, 15 and 16. In most cases you can directly send a number in the message payload when you are trying to write to a coil or a single register (function call 5 or 6, respectively).
When trying to write several coils at once (function call 15) your data
message’s value
must consist of an array of boolean values, for example:
[true, true, false, true]
.
Alternatively, if your goal is to write several registers at once, the data type
of the endpoint needs to be considered. The property dataType
(see
Endpoint properties) specifies how to properly serialize
the data into an array of bytes suitable to write into the Modbus registers.
For the available integer and float data types (see
Supported Data-types above) you can directly send the value in
the message payload. A BigInt
must be sent as a string value. You can also
send ascii, base64, and utf8 encoded strings that will be parsed using Node.js
Buffer class.
Raw data in the form of an array of bytes is also supported.
Input Format on Write¶
For writing data to modbus a message needs to be published to the /set topic of the Endpoint with the following properties:
{
"fc": "<function call value>",
"dataType": "<one of the modbus data types>",
"data": "<the data to be written>"
}
Output Format on Write¶
Results are published to the /res topic of the Endpoint. The format depends on the modbus function being called and it is returned as a JSON object.
Output Format¶
If data is read from Modbus and dataType
is set to any of the potential
values
Output Format on Read¶
When data is read from the endpoint, results are published to the /res topic of the Endpoint. The output message is an object with two properties:
{
"timestamp": "<unix timestamp in ms>",
"value": "<value>"
}
The value of the value
property will be the JSON representation of the
configured dataType
, i.e. a number, or a string, or for ‘raw’ the JSON
representation of a Javascript buffer object.
Alternatively, the property dataType
can be left undefined, in which case
the output is a Javascript buffer object directly. This is probably useful for
further processing using suitable mappings.
Example Configuration¶
The following example demonstrates how to configure a simple Modbus connection and endpoint that reads holding registers (fc 3) from the device.
Download: modbus-example.yml
1# ----------------------------------------------------------------------------#
2# Commissioning File
3# ----------------------------------------------------------------------------#
4# Copyright: Cybus GmbH (2020)
5# Contact: support@cybus.io
6# ----------------------------------------------------------------------------#
7# Source Interface Definition - Modbus TCP
8# ----------------------------------------------------------------------------#
9
10description: |
11 Sample commissioning file for Modbus TCP protocol connectivity and data mapping
12
13metadata:
14
15 name: ModBus TCP Protocol Connectivity
16 icon: https://www.cybus.io/wp-content/uploads/2019/03/Cybus-logo-Claim-lang.svg
17 provider: cybus
18 homepage: https://www.cybus.io
19 version: 0.0.1
20
21parameters:
22 IP_Address:
23 type: string
24 default: 192.168.10.30
25
26 Port_Number:
27 type: number
28 default: 502
29
30 initialReconnectDelay:
31 type: integer
32 default: 1000
33
34 maxReconnectDelay:
35 type: integer
36 default: 30000
37
38 factorReconnectDelay:
39 type: integer
40 default: 2
41
42resources:
43
44 modbusConnection:
45 type: Cybus::Connection
46 properties:
47 protocol: Modbus
48 targetState: connected
49 connection:
50 host: !ref IP_Address
51 port: !ref Port_Number
52 connectionStrategy:
53 initialDelay: !ref initialReconnectDelay
54 maxDelay: !ref maxReconnectDelay
55 incrementFactor: !ref factorReconnectDelay
56
57 readCoil:
58 type: Cybus::Endpoint
59 properties:
60 protocol: Modbus
61 connection: !ref modbusConnection
62 subscribe:
63 fc: 1
64 length: 2
65 interval: 1000
66 address: 3
67 dataType: boolean
68
69 writeCoil:
70 type: Cybus::Endpoint
71 properties:
72 protocol: Modbus
73 connection: !ref modbusConnection
74 write:
75 fc: 5
76 length: 2
77 address: 3
78 dataType: boolean
79
80 readRegister:
81 type: Cybus::Endpoint
82 properties:
83 protocol: Modbus
84 connection: !ref modbusConnection
85 subscribe:
86 fc: 3
87 length: 2
88 interval: 1000
89 address: 1
90 dataType: int16BE
91
92 writeRegister:
93 type: Cybus::Endpoint
94 properties:
95 protocol: Modbus
96 connection: !ref modbusConnection
97 write:
98 fc: 6
99 length: 2
100 address: 1
101 dataType: int16BE
102
103 mapping:
104 type: Cybus::Mapping
105 properties:
106 mappings:
107 - subscribe:
108 endpoint: !ref readCoil
109 publish:
110 topic: !sub '${Cybus::MqttRoot}/read/coil'
111 - subscribe:
112 topic: !sub '${Cybus::MqttRoot}/write/coil'
113 publish:
114 endpoint: !ref writeCoil
115 - subscribe:
116 endpoint: !ref readRegister
117 publish:
118 topic: !sub '${Cybus::MqttRoot}/read/register'
119 - subscribe:
120 topic: !sub '${Cybus::MqttRoot}/write/register'
121 publish:
122 endpoint: !ref writeRegister