XML config file

Most of the configuration is provided via a XML document. It is designed, to be very flexible in usage as well as easy to create.

Working Example

This example consists of one TCP endpoint, one Modbus device with one register.

<Modbus version="1.0">
    <TCPEndpoint name = "MyEndpoint" host = "192.168.1.100" port = "502" polling_rate = "1Hz">
        <Device name = "MyDevice1" device_type = "MyDeviceType" unit_id = "1"/>
    </TCPEndpoint>
    <ModbusDevice name="MyDeviceType">
        <HoldingRegister address="40000" description="This is a Test Value" name="Value 1" type="float"/>
    </ModbusDevice>
</Modbus>

The first part in this Example is the TCPEndpoint.

<TCPEndpoint name = "MyEndpoint" host = "192.168.1.100" port = "502" poll-ing_rate = "1Hz">
    <Device name = "MyDevice1" device_type = "MyDeviceType" unit_id = "1"/>
</TCPEndpoint>

The TCPEndpoint Node in the XML describes an endpoint with the name “MyEndpoint”. The host can be an ip-address or a hostname, the ip-port is 502 by default. In this case, the polling rate is set to 1Hz, which means, that the register values are read once per second. An Endpoint consists of one or more devices, which are separated by their UNIT_ID. The Endpoint is the dedicated device itself, which is holding the Modbus registers. Typically, the Endpoint is equal to the device. But in some cases, an Endpoint consists of 2 or more devices (e.g. a gateway). The important value here is the device_type. It holds the name of the device, which is defined in the bottom part of the XML (ModbusDevice). This allows the user, to re-use the description of one device in multiple Endpoints.

<ModbusDevice name="MyDeviceType">
    <HoldingRegister address="40000" description="This is a test value" name="Value 1" type="float"/>
</ModbusDevice>

Continuous register numbering is necessary for fast one-block retrieval. If an address is omitted in the register numbering, OXYGEN divides it into individual blocks, and is then not inter-preted as a single block. By filling in the unneeded registers, the query is interpreted by OXYGEN as one block. This can also be done by filling the unneeded registers with dummy values. In the follow-ing example, Oxygen would store 3 individual blocks.

<ModbusDevice name="MyDeviceType">
    <HoldingRegister address="0" description=" Value" name="Value 1" type="float"/>
    <HoldingRegister address="1" description=" Value" name="Value 1" type="float"/>
    <HoldingRegister address="2" description=" Value" name="Value 1" type="float"/>

    <HoldingRegister address="5" description=" Value" name="Value 1" type="float"/>
    <HoldingRegister address="6" description=" Value" name="Value 1" type="float"/>
    <HoldingRegister address="7" description=" Value" name="Value 1" type="float"/>
    <HoldingRegister address="8" description=" Value" name="Value 1" type="float"/>

    <HoldingRegister address="13" description=" Value" name="Value 1" type="float"/>
    <HoldingRegister address="14" description=" Value" name="Value 1" type="float"/>
    <HoldingRegister address="15" description=" Value" name="Value 1" type="float"/>
</ModbusDevice>

To prevent this and to query a single block it is necessary to fill the missing addresses.

<ModbusDevice name="MyDeviceType">
    <HoldingRegister address="0" description=" Value" name="Value 1" type="float"/>
    <HoldingRegister address="1" description=" Value" name="Value 1" type="float"/>
    <HoldingRegister address="2" description=" Value" name="Value 1" type="float"/>
    <HoldingRegister address="3" description=" dummy" name="dummy_3" type="float"/>
    <HoldingRegister address="4" description=" dummy" name=”dummy_4" type="float"/>
    <HoldingRegister address="5" description=" Value" name="Value 1" type="float"/>
    <HoldingRegister address="6" description=" Value" name="Value 1" type="float"/>
    <HoldingRegister address="7" description=" Value" name="Value 1" type="float"/>
    <HoldingRegister address="8" description=" Value" name="Value 1" type="float"/>
    <HoldingRegister address="9" description=" dummy" name="dummy_9" type="float"/>
    <HoldingRegister address="10" description=" dummy" name="dummy_10" type="float"/>
    <HoldingRegister address="11" description=" dummy" name="dummy_11" type="float"/>
    <HoldingRegister address="12" description=" dummy" name="dummy_12" type="float"/>
    <HoldingRegister address="13" description=" Value" name="Value 1" type="float"/>
    <HoldingRegister address="14" description=" Value" name="Value 1" type="float"/>
    <HoldingRegister address="15" description=" Value" name="Value 1" type="float"/>
</ModbusDevice>

TCP Endpoint

Table 2 TCPENDPOINT

Property

Value Options

Mandatory

Example

Description

name

string

yes

“My Endpoint”

Friendly name of the Endpoint

host

string

yes

“192.168.1.100”

Hostname of the Endpoint, IP address or hostname allowed

port

number

yes

“502”

IP-Port of the Endpoint, default is 502

polling_rate

rate [0.1Hz - 100Hz]

no

“1Hz”

Polling / reading rate of the endpoint

response_timeout

time

no

“0.25s”

Timeout for waiting on response of the endpoint

Device

Table 3 DEVICE

Property

Value Options

Mandatory

Example

Description

name

string

yes

“My Device”

Friendly name of the Device

device_type

string

yes

“MyDevice-Type”

Name of the used device, must be available as ModbusDevice

unit_id

number [0-255]

yes

“1”

Unit_Id of the device, typically “1”

MODBUS Device

Table 4 MODBUSDEVICE

Property

Value Options

Mandatory

Example

Description

name

string

yes

“MyDeviceType”

Friendly name of the Modbus Device

byte_order

see byte order

no

“big_endian”

Byte / Word Order

Register

  • Coil use function code 0x01 for reading.

  • DiscreteInput use function code 0x02 for reading.

  • HoldingRegister use function code 0x03 for reading.

  • InputRegister use function code 0x04 for reading.

Table 5 Register

Property

Value Options

Mandatory

Example

Description

address

number [0-65535]

yes

“40000”

Register Start address, starting with 0

name

string

yes

“Value 1”

Channel name of the Modbus Register in OXYGEN

type

data_type

yes

“int16”

Data type of the register value

scale_mode

“const_linear” or “sunssf”

no

“const_linear”

Scaling Mode

scale

number

no

“0.1”

Scaling factor, only valid if scale_mode == “const_linear”

offset

number

no

“100”

Scaling offset, only valid if scale_mode == “const_linear”

scale_reg

register

no

“1234”

Scaling register, only valid if scale_mode == “sunssf”

min

number

no

“-100”

Minimum display value range [RESERVED]

max

number

no

“100”

Maximum display value range [RESERVED]

unit

string

no

“V”

Value Unit

nan

value

no

“0xffff”

Value to be treated as NaN

byte_order

see byte order

no

“big_endian”

Byte / Word Order

description

string

no

“Description”

Channel description of the Modbus Register in OXYGEN

Datatypes

Table 6 Datatypes

Name

Word Count

Description

Value Range

“uint16”

1

Unsigned Integer 16 Bit

0 to 32767

“int16”

1

Signed Integer 16 Bit

-16384 to 16383

“uint32””

2

Unsigned Integer 32 Bit

0 to 2^32-1

“int32”

2

Signed Integer 32 Bit

-2^31 to 2^31-1

“float”

2

IEE 754 Floating Point Single

+-3.402823e+38

“double”

4

IEE 754 Floating Point Double

+-1e+308

Byte Order

Table 7 Byte Order

Name

Synonym

Description

“abcd”

“big_endian”

Decode Data in Big Endian matter (High-Byte before Low-Byte)

“dcba”

“little_endian”

Decode Data in Little Endian matter (Low-Byte before High-Byte)

“cdab”

“-”

Decode Data in Mixed-Byte Order

“badc”

“-”

Decode Data in Mixed-Byte Order