Modbus DIA Client

From Digi Developer

(Redirected from Modbus Dia Client)
Jump to: navigation, search


Modbus DIA Client Driver

This driver polls remote Modbus servers/slaves for data (words or bits), which are then converted to standard DIA channels. So it imports Modbus data into DIA channels.

You can get more info and hints on these Wiki pages:

Uses Digi IA/Modbus Engine

The normal Digi "IA Modbus Engine" is required, and the DIA will appear to it as a remote client using Modbus/TCP form in UDP (the UDP is important), so you need to enable at least the Modbus/TCP master on UDP port 502. TCP/IP could have been supported, but it consumes considerable more resources than UDP/IP without adding value.

You need to set up IA table destinations pointing at your slaves, so these can be any combination of Modbus/TCP, Modbus/ASCII or Modbus/RTU via TCP/IP, UDP/IP, serial or Zigbee mesh.

This design has the following advantages:

  • supports a wide variety of Modbus devices:
    • Modbus/TCP slaves/servers via TCP/IP or UDP/IP, via Ethernet or cellular
    • Modbus/RTU slaves/servers via TCP/IP, UDP/IP, direct serial port or XBee 232/485 Adapters
    • Modbus/ASCII slaves/servers via TCP/IP, UDP/IP, direct serial port or XBee 232/485 Adapters
  • allows transparent pass-through for remote Modbus Clients. For example, a remote Modbus/TCP client can read or write a thousand various registers in a complex Modbus device, yet the DIA configuration need only import three registers of interest
  • the Digi IA/Modbus engine is a very mature product
  • is supported by at least these Digi products:
    • Digi ConnectPort X4, X4H, X8
    • Digi ConnectPort TS8, TS16
    • Digi Connect WAN IA, WAN VAN
    • Digi ConnectPort WAN

This design has the following disadvantages:

  • The Modbus DIA Driver cannot be used on Digi products unable to run the IA/Modbus engine concurrently with Python.
  • Specifically, it cannot be used on:
    • Digi ConnectPort X2
    • Digi ConnectPort X3

Example YML Configuration

Below is an example YML configuration which reads two blocks of data from remote server(s)

  - name: mbus
    driver: devices.modbus.mbus_udp_device:MBusUDPDevice
        poll_rate_sec: 30
        udp_peer: ('',502)
        trace: 'debug'
        round: 3
            - poll: in01
              pollinfo: { 'uid':1, 'fnc':3, 'ofs':0, 'cnt':20 }
                - parse: { 'nam':'panel', 'ofs':3, 'frm':']H', 'unt':'vdc', 'typ':'float', 'expr':'(%d/1000.0)*3.25' }
                - parse: { 'nam':'battery', 'ofs':4, 'frm':']H', 'unt':'vdc', 'typ':'float', 'expr':'(%d/1000.0)*3.25' }
                - parse: { 'nam':'load','ofs':5,'frm':']H','unt':'vdc', 'typ':'float', 'expr':'(%d/1000.0)*3.25' }
            - poll: in02
              pollinfo: { 'uid':1, 'fnc':1, 'ofs':0, 'cnt':48 }
                - parse: { 'nam':'DIN', 'ofs':8, 'frm':'?', 'unt':'valid', }
                - parse: { 'nam':'AIN', 'ofs':9, 'frm':'?', 'unt':'valid', }
                - parse: { 'nam':'DOT', 'ofs':10, 'frm':'?', 'unt':'valid', }

Base Device Settings

A single thread is spawned for each MBusUDPDevice device created. The thread sleeps and wakes on a cycle defined by the YML poll_rate_sec setting. When it wakes, it runs through a list of POLLS, running them in strict half-duplex sequential order. Modbus is not a high-speed protocol, so users must be reasonable in their selection of poll rates.

Specific settings for the base device:

  poll_rate_sec: 30
  udp_peer: ('',502)
  trace: 'debug'
  round: 3
  • defines the poll rate. Note that the device attempts to prevent system drift by compensating for delays in response.
  • type integer, stated in seconds, minimum is once per 5 seconds
  • optional, default = once per 15 seconds
  • defines the remote host address as IP (or DNS name) plus UDp port number to send requests to
  • type string
  • optional, default = ('',502) (localhost and the well-known Modbus/TCP port number, assumes links to Digi IA/Modbus Engine)
  • note that at present, the client does NOT time-out. It relies upon the server to always respond - which is true when the Digi IA/Modbus Engine is used.
  • defines how chatty the driver should be on the trace output
  • type string or integer
  • optional, default = 0x0032 (fancy steady-state, start/stop events and field errors)
  • see the documentation for more options.
  • defines a global 'round()' for floating point value
  • type integer
  • optional, default = 999, magic number for ignore
  • example: a temperature with a +/- 1 deg accuracy should not be returned as '23.34876549'. Setting round: 2 will cause all floating points to rounded to 2 places, so '23.34876549' is ASCII encoded as '23.35'
  • defines a collection (list) of Modbus block read/writes and now the data should be imported to DIA
  • required
  • example: see next section

Poll List Settings

Each MBusUDPDevice device can run a collection of Modbus polls. Although each MBusUDPDevice sends request to a single server, that server can interpret the Modbus Unit Id (or slave address) to obtain responses from multiple remote servers.

Specific settings for the poll objects:

  - poll: in01
    pollinfo: { 'uid':10, 'fnc':3, 'ofs':0, 'cnt':20 }
  • define the name for this poll object. This name is used to tag the output channels of this poll. Use only letters, numbers and underscore.
  • type string
  • required, user is responsible to insure uniqueness
  • example: in01 or motor or plc_b
  • define the Modbus parameters for this poll object. Only functions 1, 2, 3 and 4 are supported at present.
  • type Python dictionary
  • required, user is responsible to insure uniqueness
  • example: { 'uid':10, 'fnc':3, 'ofs':0, 'cnt':20 } means poll 20 holding regs starting at 4x00001 on slave unit-id 10. You should create the required destination in the Digi IA/Modbus table
  • defines the Modbus Unit Id or slave address to use in the request
  • defines the Modbus function code to use - limited to function 1, 2, 3 and 4
  • defines the offset (zero-based). So reading Modbus register 4x00001 is offset 0, which reading coil 0x00007 is offset 6.
  • defines the number of registers (words) or coils (bits) to read
  • defines a collection (list) of DIA channels to create from this Modbus poll object
  • required
  • example: see next section

Channel List Settings

Each Modbus poll block of data can be imported into multiple DIA channels.

Specific settings for the channel objects:

  - parse: { 'nam':'panel', 'ofs':3, 'frm':']H', 'unt':'vdc', 'typ':'float', 'expr':'(%d/1000.0)*3.25' }
  - parse: { 'nam':'totalEnergy', 'ofs':0, 'frm':'[L', 'unt':'Wh' }
  - parse: { 'nam':'load', 'ofs':5, 'frm':'[f', 'unt':'vdc', }
  - parse: { 'nam':'overload', 'ofs':8, 'frm':'?', 'unt':'valid', }
  • define the import/creation of a single DIA channelect. This name is used to tag the output channels of this poll. Use only letters, numbers and underscore.
  • type string
  • required, user is responsible to insure uniqueness
  • example: { 'nam':'totalEnergy', 'ofs':0, 'frm':'[L', 'unt':'Wh' } reads the first two registers of the poll block, treats them as a Modbus 32-int with LOW word first. It creates a DIA channel named mbus.in02_acTotalEnergy which will include a sample such as <Sample: "17294" "Wh" at "2009-10-28 15:36:30">
  • Defines the DIA channel name. So if the poll is named 'inv01' and channel named 'totalEnergy', then the final channel will be named 'inv01_totalEnergy'.
  • type string
  • required
  • Example: four poll blocks named ['inv01','inv02','south_wing','ghouse'] could create four channels named inv01_totalEnergy, inv02_totalEnergy, south_wing_totalEnergy, and ghouse_totalEnergy.
  • defines the word or bit offset in the poll block. It is zero-based.
  • type integer
  • required
  • defines how the Modbus data bytes are parsed to obtain the DIA sample.
  • type string
  • required
  • values are similar to the python struct format
    • '?' for 1-bit coils - these can be parsed from register or coil response, but be aware the 'ofs' value is from the start of the poll block so reading the 3rd bit in the 4th register requires 'ofs' of 66 (67th bit, zero-based)
    • 'h' for 16-bit signed int import to DIA ('H' is unsigned)
    • '[i' for 32-bit signed int import to DIA ('[I' is unsigned), with the '[I' meaning LOW word is in first Modbus register, which ']I' or '>I' would be BIG word in first Modbus register
    • '[f' for 32-bit float import to DIA with '[' or ']' being used as in the 32-bit int
  • defines the Unit of Measure string
  • type string
  • optional, default is (an empty string)
  • over-rides the type implied by the format string
  • type string, values in ['float','int','long','bool']
  • optional, default is to use parse['frm'] to estimate channel type
  • an 'eval' expression to do simple value conversion of the data
  • type string, in print format such as '(%d/1000.0)*3.25'
  • optional, default is no conversion
  • example: { 'nam':'panel', 'ofs':3, 'frm':'H', 'unt':'vdc', 'typ':'float', 'expr':'(%d/1000.0)*3.25' } treats the Modbus register as a 16-bit signed integer, yet applies the formula '(value/1000.0)*3.25' to create a floating point channel sample
  • example: { 'nam':'cold', 'ofs':3, 'frm':'H', 'unt':'is_cold', 'typ':'bool', 'expr':'bool(%d<230)' } treats the Modbus register as a 16-bit unsigned integer, yet creates a boolean channel sample

Handling Sample Errors

If the Modbus server/slave did NOT respond, then the DIA sample will be an 'AnnotatedSample', which just means you'll find a new field named 'errors', which is a set[] containing the reason code which are:

  • 'not_init' means the sample has never been updated even once.
  • 'stale' means the last 3 or more polls have timed out.
  • 'bad_calc' means some import/conversion failure occurred.
Personal tools
Wiki Editing