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

References

  1. https://www.rtaautomation.com/technologies/modbus-tcpip/