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 of the modbus device

port (integer, required)

Port of the Modbus device

unitId (integer)

Default: 1

Endpoint Properties

fc (integer, enum, required)

Function Code

This element must be one of the following enum values:

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 15

  • 16

address (integer, required)

length (integer, required)

Length

dataType (string, enum)

Converts the modbus value to this type

This element must be one of the following enum values:

  • raw

  • base64

  • boolean

  • doubleBE

  • floatBE

  • int16BE

  • int32BE

  • uint16BE

  • uint32BE

  • doubleLE

  • floatLE

  • int16LE

  • int32LE

  • uint16LE

  • uint32LE

interval (integer) eg: 2000

Poll interval (best effort) in ms

Default: 1000

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.

DataType/FC

1

2

3

4

raw

bool

x

x

ascii

x

x

base64

x

x

int16BE

x

x

int16LE

x

x

int32BE

x

x

int32LE

x

x

uint16BE

x

x

uint16LE

x

x

uint32BE

x

x

uint32LE

x

x

floatBE

x

x

floatLE

x

x

doubleBE

x

x

doubleLE

x

x

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.

Example Configuration

The following example demonstrates how to configure a simple Modbus connection and endpoint that reads holding registers (fc 3) from the device.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
# ----------------------------------------------------------------------------#
# Commissioning File
# ----------------------------------------------------------------------------#
# Copyright: Cybus GmbH (2020)
# Contact: support@cybus.io
# ----------------------------------------------------------------------------#
# Source Interface Definition - Modbus TCP
# ----------------------------------------------------------------------------#

description: |
  Sample comissioning file for Modbus TCP protocol connectivity and data mapping

metadata:

  name: ModBus TCP Protocol Connectivity
  icon: https://www.cybus.io/wp-content/uploads/2019/03/Cybus-logo-Claim-lang.svg
  provider: cybus
  homepage: https://www.cybus.io
  version: 0.0.1

parameters:
  IP_Address:
    type: string
    default: 192.168.10.30

  Port_Number:
    type: number
    default: 502

resources:

  modbusConnection:
    type: Cybus::Connection
    properties:
      protocol: Modbus
      targetState: connected
      connection:
        host: !ref IP_Address
        port: !ref Port_Number

  readCoil:
    type: Cybus::Endpoint
    properties:
      protocol: Modbus
      connection: !ref modbusConnection
      subscribe:
        fc: 1
        length: 2
        interval: 1000
        address: 3
        dataType: boolean

  writeCoil:
    type: Cybus::Endpoint
    properties:
      protocol: Modbus
      connection: !ref modbusConnection
      write:
        fc: 5
        length: 2
        address: 3
        dataType: boolean

  readRegister:
    type: Cybus::Endpoint
    properties:
      protocol: Modbus
      connection: !ref modbusConnection
      subscribe:
        fc: 3
        length: 2
        interval: 1000
        address: 1
        dataType: int16BE

  writeRegister:
    type: Cybus::Endpoint
    properties:
      protocol: Modbus
      connection: !ref modbusConnection
      write:
        fc: 6
        length: 2
        address: 1
        dataType: int16BE

  mapping:
    type: Cybus::Mapping
    properties:
      mappings:
        - subscribe:
            endpoint: !ref readCoil
          publish:
            topic: !sub '${Cybus::MqttRoot}/read/coil'
        - subscribe:
            topic: !sub '${Cybus::MqttRoot}/write/coil'
          publish:
            endpoint: !ref writeCoil
        - subscribe:
            endpoint: !ref readRegister
          publish:
            topic: !sub '${Cybus::MqttRoot}/read/register'
        - subscribe:
            topic: !sub '${Cybus::MqttRoot}/write/register'
          publish:
            endpoint: !ref writeRegister

Output Format

If data is read from Modbus the output will be provided as JSON object if its dataType is not ‘raw’

{
  "timestamp": "<unix timestamp in ms>",
  "value": "<value>"
}