DNP3 Slave Driver
The ESF DNP3 Slave Driver implements a DNP3 slave integrated with ESF Driver and Wires/Asset models.
Features
- The driver manages a local cache whose entries represent DNP3 data points.
- Support for a subset of DNP3 object types.
- Support for spontaneous messages.
- Supports assigning group/variation to be used for static/event data for each point.
- Support for assigning deadbands to data points in configuration.
- Supports changing analog/binary output status points using commands.
- TCP and SSL support
- UDP support (starting from 2.1.0)
Driver cache
The drive cache can be represented as a key -> value map.
The keys are are (data point index, resource type)
pairs, where resource type represents the data point type (binary input, analog input etc)
The values are are information object representations.
The most straightforward way for populating the cache is to define Assets whose channels represent the entries.
More precisely, entries are created by calling the Driver.prepareRead()
and/or Driver.registerChannelListener()
Java APIs. If the entries are defined through the Web UI by creating Assets, ESF will take care of calling the APIs above.
- Current cache entry values can be retrieved using READ operations/channels.
- Cache entry values can be updated using READ_WRITE operations/channels.
- Cache update events can be notified to applications by registering channel listeners. In terms of Assets, this corresponds to enabling the listen channel parameter.
Driver cache size
The driver allows to define at most 65536 data points per resource type.
The number of data points for each type can be configured using the following global configuration parameters:
- Binary input count
- Double bit binary input count
- Analog input count
- Counter count
- Binary output status count
- Analog output status count
Input cache entries
The entries that represent input data can be retrieved and/or updated locally using all the interfaces that leverage ESF Driver APIs, for example by performing a read or write on an Asset channel.
After the value of an input entry is updated by a framework component, its value will be visible to DNP3 masters.
Updating an input entry value can optionally also trigger sending an unsolicited message to the client.
Output status cache entries
Binary/Analog output status entry values can be retrieved and/or updated locally in the same way as input entries.
Output status entries can also be modified by the DNP3 master through commands. When a command is received, the new value will be written in the cache and retained indefinitely until another command for the same entry is received.
The driver can emit events to framework components just after a command is received. Events can be received on a Wire Graph by ticking the listen flag in Wire Asset configuration or by using the Driver.registerChannelListener()
Java APIs.
Commands only cause modifications of the output status data point values. Any side effects of the command need to be managed by external components in an appropriate way for the specific application.
Uninitialized entries
All cache entries are created in an uninitialized state until a value is written to them either by an ESF component or by the DNP3 master.
The behavior of an uninitialized entry is the following:
-
If the value is read by a framework component, an error will be generated reporting that the entry value has not been set yet.
-
If the data point is sent to a DNP3 master, it will report a default value and the offline, restart flags.
Entry lifecycle
As previously said, entries are created by calling the Driver.prepareRead()
and/or Driver.registerChannelListener()
Java APIs, which is done automatically by the framework if the user creates Asset channels using the web UI.
Every entry is reference counted, calls to Driver.prepareRead()
or Driver.registerChannelListener()
related to the same (index, resource type)
entry key will increase the reference count and calls to PreparedRead.close()
and Driver.unregisterChannelListener()
will decrease it.
When the reference count reaches 0, the entry will be deleted.
In term of Assets, all channels referring to the same (index, resource type)
will refer to the same entry and increase the reference count. If and when all channels referring to the same (index, resource type)
are deleted the entry will be removed.
Asset channel configuration contains other parameters besides (index, resource type)
, (for example static/event group variation). If multiple channels referencing the same entry are defined, it is important that the other parameters are set to same value. If this requirement is not respected, the driver will use one of the provided values for each parameter, which one is undefined.
Cache persistence
Cache entries reside in device RAM only and are not persisted in any way. An ESF restart or gateway reboot will cause all entries to return to the uninitialized state.
UDP Support
Knows issues/limitations
Version 2.1.0 is affected by OpenDNP3 issue https://github.com/dnp3/opendnp3/issues/405.
This can cause connection problems and log flooding if the drivers receives UDP communication related ICMP errors.
Until the issue is fixed upstream, a possible workaround is to filter ICMP error messages using firewall.
This can be done adding the following iptables rules on the gateway, for example by adding them in /etc/sysconfig/iptables
:
-A INPUT -p icmp -m icmp --icmp-type port-unreachable -j DROP
-A INPUT -p icmp -m icmp --icmp-type host-unreachable -j DROP
While this should prevent the issue, these rules will cause parsing failures in ESF 6.2.0 and earlier Firewall Service. This will cause the Firewall Web UI to stop working. This will be fixed in ESF 7.0.0.
In order to restore Firewall Web UI operation, the rules above can be removed from /etc/sysconfig/iptables
and restart the gateway, this will also remove the workaround.
If possible, similar rules should be instead added to the peer so that it does not send back ICMP errors to the gateway.
Using UDP on Docker will not work if the UDP port is exposed using the -p
docker run
argument due to port/address translation.
#### Configuration parameter changes
The following global configuration parameters have been changed/added in 2.1.0:
-
The Transport type parameter has been added with the following options
- TCP (the default)
- UDP
Select UDP to enable UDP communication.
-
The Master address parameter must be set to the master hostname/IP address. This parameter is mandatory for UDP communication, it is otherwise ignored.
-
The Master port parameter must be set to the UDP port used by the master. The driver will send packets to this UDP ports and expects this to be used as source port by the master. This parameter is mandatory for UDP communication, it is otherwise ignored.
Channel configuration parameters
Currently the channel configuration is composed of the following parameters:
-
Resource Type: The resource type addressed by the channel, usually a data point type.
-
Index: The index of the data point. The value of this parameter must be less than the cache size for the corresponding data point type set in global driver configuration.
-
Event class: Can be used to assign a per channel event class. If set to
DEFAULT
, the default event class for the channel data point type from global configuration will be used. -
Static Variation: Can be used to assign the static variation to be used for the channel. If set to
DEFAULT
, the default static variation for the channel data point type from global configuration will be used.
The static variation must be compatible with the data point type. -
Event Variation: Can be used to assign the event variation to be used for the channel. If set to
DEFAULT
, the default event variation for the channel data point type from global configuration will be used.
The event variation must be compatible with the data point type. -
Deadband: Can be used to assign a numeric deadband to the channel. If not set, deadbanding for the channel will be disabled.
Supported types
The driver currently supports the following data point types:
-
Binary input:
Supported static variations:
Group Variation 1 1 1 2 Supported event variations:
Group Variation 2 1 2 2 2 3 -
Double bit binary input
Supported static variations:
Group Variation 3 2 Supported event variations:
Group Variation 4 1 4 2 4 3 -
Analog input
Supported static variations:
Group Variation 30 1 30 2 30 3 30 4 30 5 30 6 Supported event variations:
Group Variation 32 1 32 2 32 3 32 4 32 5 32 6 32 7 32 8 -
Counter
Supported static variations:
Group Variation 20 1 20 2 20 5 20 6 Supported event variations:
Group Variation 22 1 22 2 22 5 22 6 -
Binary output status
Supported static variations:
Group Variation 10 2 Supported event variations:
Group Variation 11 1 11 2 -
Analog output status
Supported static variations:
Group Variation 40 1 40 2 40 3 40 4 Supported event variations:
Group Variation 42 1 42 2 42 3 42 4 42 5 42 6 42 7 42 8
Mapping DNP3 types and Driver/Wires types
The Driver, Wires and Asset models support the following types, that refer to the corresponding Java types.
- BOOLEAN
- BYTE_ARRAY
- DOUBLE
- INTEGER
- LONG
- FLOAT
- STRING
These types are used in interactions between the Driver and the other ESF components, like the Wire Graph.
-
The numeric types allow to encode the "main" value of the information objects.
-
The STRING type allows to produce a Json representation of the information objects, containing all of its fields (e.g. value, timestamp, quality bits, etc).
The current version of the driver only supports this type for reads from the cache and events sent to the framework, currently it is not possible to use it for updating a cache entry.This driver uses the same JSON format as DNP3 master driver, please refer to master driver documentation for more details.
-
The BYTE_ARRAY type is not currently supported by the Driver.
The applicable types for each information object type are described below:
Binary inputs
-
BOOLEAN: Encodes the data point value
-
STRING: JSON representation
Double bit binary input
-
INTEGER, LONG, DOUBLE, FLOAT: Encode the current data point value in the following way (available for reads and writes):
Numeric value State 0 INTERMEDIATE
1 DETERMINED_OFF
2 DETERMINED_ON
other INDETERMINATE
-
STRING: JSON representation (available for reads)
Analog input
-
INTEGER, LONG, DOUBLE, FLOAT: Encode the data point value (available for reads and writes).
-
STRING: JSON representation (available for reads).
Counter
-
INTEGER, LONG, DOUBLE, FLOAT: Encode the data point value (available for reads and writes).
-
STRING: JSON representation (available for reads).
Binary output status
-
BOOLEAN: Encodes the data point value (available for reads and writes).
-
STRING: JSON representation (available for reads).
Analog output status
-
INTEGER, LONG, DOUBLE, FLOAT: Encode the data point value (available for reads and writes).
-
STRING: JSON representation (available for reads).
Command handling
The driver allows to update the Binary output status and Analog output points by the DNP3 master through commands.
The reception of a command causes the generation of an event reporting the received value. Events can be received by framework components using the ChannelListener
APIs and can be emitted by WireAsset components if the listen
flag is selected in channel configuration.
The updated value is also stored in the corresponding cache entry and can be retrieved by framework components using reads.
Binary output status
Binary output status value can be set using CROB commands, all command fields except the control code are currently ignored. The control code that sets the data point in the on and off state is defined by the following global configuration parameters:
- Binary output status on control code
- Binary output status off control code
Analog output status
Analog output status values can be set using the following commands:
- 32 bit analog output block command (Group 41 Variation 1).
- 16 bit analog output block command (Group 41 Variation 2).
- 32 bit floating point output block command (Group 41 Variation 3).
- 64 bit floating point output block command (Group 41 Variation 4).
Clock synchronization
The driver supports the clock synchronization command that can be used to adjust the timestamps contained in time-tagged information objects.
Timestamps in time-tagged information objects are obtained from server clock.
Server clock behavior is the following:
- It is initialized from system time when the driver starts.
- It is based on a monotonic clock provided by the
java.lang.System.nanoTime()
Java function.- A clock synchronization command does not affect device system time but only server time.
- If no clock sync is received for a time interval equal to Expected clock sync interval seconds global configuration parameter value, the driver will se the need time IIN flag.
Note about floating point values
The driver currently does not support denormal floating point values, it is recommended to avoid using such values if possible. Denormal floating point values received from the framework will be clamped to 0 by the driver.
Updated about 1 year ago