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¶
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¶
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¶
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.
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¶
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¶
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 |