Documentation
¶
Overview ¶
Package dnp3 implements the DNP3 protocol (IEEE Std 1815-2012) for both master and outstation roles.
The stack is layered the way the standard is. Each layer below this package exposes a core that takes bytes and returns bytes — it performs no I/O, starts no goroutines, and reads no clock. Sessions and channels supply those concerns from the outside, which is what makes every parser fuzzable and every state machine testable against a virtual clock.
internal/link framing, CRC-16/DNP, primary and secondary state machines internal/transport FIR/FIN/SEQ segmentation and reassembly internal/app application headers, function codes, IIN, qualifiers objects group/variation codecs master, outstation session state machines built on the layers above channel TCP, TLS, UDP, serial and in-process pipe transports
This root package holds the value types the whole stack shares: measurements, quality flags, timestamps, commands and their status codes.
Index ¶
- Constants
- Variables
- func AnalogFitsIn16(v float64) bool
- func AnalogFitsIn32(v float64) bool
- func AttributeName(variation uint8) (string, bool)
- func DNP3ToTime(ms uint64) time.Time
- func TimeToDNP3(t time.Time) uint64
- type Analog
- type AnalogOutput
- type AnalogOutputFloat32
- type AnalogOutputFloat64
- type AnalogOutputInt16
- type AnalogOutputInt32
- type AnalogOutputStatus
- type Attribute
- type AttributeType
- type Binary
- type BinaryOutputStatus
- type Class
- type CommandStatus
- type ControlCode
- type ControlRelayOutputBlock
- type Counter
- type DoubleBit
- type DoubleBitBinary
- type FileInfo
- type FileMode
- type FilePermissions
- type FileStatus
- type FileType
- type Flags
- type FrozenCounter
- type Indexed
- type OctetString
- type PointType
- type RestartMode
- type Timestamp
- type TimestampQuality
Constants ¶
const ( // AttrSetStandard is attribute set 0, the one the standard defines. A // device may keep private attributes in other sets. AttrSetStandard uint8 = 0 // AttrAll is the variation a master reads to ask for every attribute a // device has, rather than naming them one at a time. It appears only in // requests. AttrAll uint8 = 254 // AttrList asks which attributes the device implements. AttrList uint8 = 255 )
Attribute set and variation numbers with a meaning fixed by the standard.
const MaxDNP3Time = int64(1)<<48 - 1
MaxDNP3Time is the largest instant a 48-bit DNP3 timestamp can express: 2^48 - 1 milliseconds after the UNIX epoch, which falls in the year 10889.
const MaxOctetStringLen = 255
MaxOctetStringLen is the largest octet string the encoding allows.
const Version = "0.1.0-dev"
Version is the library version, following semantic versioning.
Variables ¶
var ( // ErrMalformed means a received octet sequence did not conform to the // protocol and could not be recovered. ErrMalformed = errors.New("dnp3: malformed data") // ErrTimeout means a peer did not respond within the configured window. ErrTimeout = errors.New("dnp3: timeout") // ErrClosed means the session or channel has been shut down. ErrClosed = errors.New("dnp3: closed") // ErrNotSupported means the peer rejected a function code or object it // does not implement. ErrNotSupported = errors.New("dnp3: not supported by peer") // ErrBadConfig means a configuration value is outside the range the // protocol allows. ErrBadConfig = errors.New("dnp3: invalid configuration") // ErrTaskFailed means a master task exhausted its retries. ErrTaskFailed = errors.New("dnp3: task failed") // ErrFileTransfer means an outstation rejected a file operation. The // wrapped message carries the status code it reported. ErrFileTransfer = errors.New("dnp3: file transfer failed") // ErrNoConnection means the channel has no established connection. ErrNoConnection = errors.New("dnp3: no connection") )
Errors returned across the stack. Layer packages define their own detailed errors and wrap them in these, so callers can classify a failure without importing internal packages.
Functions ¶
func AnalogFitsIn16 ¶
AnalogFitsIn16 reports whether v can be encoded as a 16-bit analog without loss, which the outstation needs when a master requests a narrow variation.
func AnalogFitsIn32 ¶
AnalogFitsIn32 reports whether v can be encoded as a 32-bit analog without loss.
func AttributeName ¶ added in v0.4.0
AttributeName returns the standard set's name for a variation, and whether there is one. It is exported so a tool can label an attribute it has only the number of.
func DNP3ToTime ¶
DNP3ToTime converts a 48-bit DNP3 timestamp to a time.Time in UTC. Bits above the low 48 are ignored, matching what a conforming encoder can emit.
func TimeToDNP3 ¶
TimeToDNP3 converts t to DNP3's wire representation: milliseconds since the UNIX epoch, clamped to the 48 bits the encoding provides. Times before the epoch clamp to zero.
Types ¶
type Analog ¶
Analog is an analog input. The stack carries every analog variation — 16-bit, 32-bit, single and double precision — as a float64 and narrows only at the encoding boundary.
type AnalogOutput ¶
type AnalogOutput interface {
AnalogOutputInt16 | AnalogOutputInt32 | AnalogOutputFloat32 | AnalogOutputFloat64
}
AnalogOutput is any of the four analog output command variations.
type AnalogOutputFloat32 ¶
type AnalogOutputFloat32 struct {
Value float32
Status CommandStatus
}
AnalogOutputFloat32 is a group 41 variation 3 control.
type AnalogOutputFloat64 ¶
type AnalogOutputFloat64 struct {
Value float64
Status CommandStatus
}
AnalogOutputFloat64 is a group 41 variation 4 control.
type AnalogOutputInt16 ¶
type AnalogOutputInt16 struct {
Value int16
Status CommandStatus
}
AnalogOutputInt16 is a group 41 variation 2 control.
type AnalogOutputInt32 ¶
type AnalogOutputInt32 struct {
Value int32
Status CommandStatus
}
AnalogOutputInt32 is a group 41 variation 1 control.
type AnalogOutputStatus ¶
AnalogOutputStatus reports the present value of an analog control point.
type Attribute ¶ added in v0.4.0
type Attribute struct {
// Set is the attribute set, and Variation identifies the attribute within
// it. Together they are the attribute's name on the wire.
Set uint8
Variation uint8
Type AttributeType
Text string
Number int64
Real float64
Octets []byte
Time time.Time
}
Attribute is one thing a device says about itself.
Exactly one of the value fields carries the value, chosen by Type. They are separate fields rather than an interface because the overwhelmingly common thing to do with an attribute is print it, and the second most common is to read one number out of it.
type AttributeType ¶ added in v0.4.0
type AttributeType uint8
AttributeType is the encoding of an attribute's value, from the standard's attribute data type codes.
const ( AttrVisibleString AttributeType = 1 AttrUnsignedInt AttributeType = 2 AttrSignedInt AttributeType = 3 AttrFloat AttributeType = 4 AttrOctetString AttributeType = 5 AttrBitString AttributeType = 6 AttrTime AttributeType = 7 )
Attribute data types.
func (AttributeType) String ¶ added in v0.4.0
func (t AttributeType) String() string
type BinaryOutputStatus ¶
BinaryOutputStatus reports the present state of a control point.
type Class ¶
type Class uint8
Class is a bit mask over the DNP3 event classes plus class 0, the static data set. Masks are how polls are expressed: an integrity poll is Class0 | Class1 | Class2 | Class3.
const ( Class0 Class = 1 << iota // static data Class1 // event class 1, conventionally the most urgent Class2 Class3 // ClassNone assigns a point to no event class, suppressing its events. ClassNone Class = 0 // Class123 is every event class, excluding static data. Class123 = Class1 | Class2 | Class3 // ClassAll is an integrity poll: static data plus every event class. ClassAll = Class0 | Class123 )
Class mask bits.
type CommandStatus ¶
type CommandStatus uint8
CommandStatus is the outcome an outstation reports for a control operation.
const ( CommandSuccess CommandStatus = 0 CommandTimeout CommandStatus = 1 CommandNoSelect CommandStatus = 2 CommandFormatError CommandStatus = 3 CommandNotSupported CommandStatus = 4 CommandAlreadyActive CommandStatus = 5 CommandHardwareError CommandStatus = 6 CommandLocal CommandStatus = 7 CommandTooManyOps CommandStatus = 8 CommandNotAuthorized CommandStatus = 9 CommandAutomationInhibit CommandStatus = 10 CommandProcessingLimited CommandStatus = 11 CommandOutOfRange CommandStatus = 12 CommandDownstreamLocal CommandStatus = 13 CommandAlreadyComplete CommandStatus = 14 CommandBlocked CommandStatus = 15 CommandCanceled CommandStatus = 16 CommandBlockedOtherMstr CommandStatus = 17 CommandDownstreamFail CommandStatus = 18 CommandNonParticipating CommandStatus = 126 CommandUndefined CommandStatus = 127 )
Command status codes defined by the standard.
func (CommandStatus) OK ¶
func (s CommandStatus) OK() bool
OK reports whether the command succeeded.
func (CommandStatus) String ¶
func (s CommandStatus) String() string
type ControlCode ¶
type ControlCode uint8
ControlCode is the operation field of a Control Relay Output Block. It packs an operation type in the low four bits with three modifier flags above.
const ( ControlNUL ControlCode = 0x00 ControlPulseOn ControlCode = 0x01 ControlPulseOff ControlCode = 0x02 ControlLatchOn ControlCode = 0x03 ControlLatchOff ControlCode = 0x04 )
Control operation types, occupying the low nibble of a ControlCode.
const ( // ControlClose sets the close coil field. ControlClose ControlCode = 0x80 // ControlTrip sets the trip coil field. ControlTrip ControlCode = 0x40 )
Trip/close modifiers, which pair with an operation type to drive the two coils of a breaker.
func (ControlCode) Clear ¶
func (c ControlCode) Clear() bool
Clear reports whether the clear bit is set, which cancels a queued or running operation on the point.
func (ControlCode) IsClose ¶
func (c ControlCode) IsClose() bool
IsClose reports whether the close coil is selected.
func (ControlCode) IsTrip ¶
func (c ControlCode) IsTrip() bool
IsTrip reports whether the trip coil is selected.
func (ControlCode) OpType ¶
func (c ControlCode) OpType() ControlCode
OpType returns the operation type nibble.
func (ControlCode) String ¶
func (c ControlCode) String() string
type ControlRelayOutputBlock ¶
type ControlRelayOutputBlock struct {
Code ControlCode
// Count is how many times to execute the operation. Zero is legal and
// means "do nothing", which some masters use to probe a point.
Count uint8
// OnTime and OffTime are milliseconds, used by the pulse operations.
OnTime uint32
OffTime uint32
// Status is meaningful only on a response echo.
Status CommandStatus
}
ControlRelayOutputBlock is a group 12 variation 1 control: the command used to operate breakers, reclosers and other discrete outputs.
func (ControlRelayOutputBlock) String ¶
func (c ControlRelayOutputBlock) String() string
type DoubleBit ¶
type DoubleBit uint8
DoubleBit is the state of a double-bit binary input, which reports a two-contact device — typically a breaker with separate open and closed auxiliary contacts — and can therefore distinguish a device in transit or miswired from one that is definitely open or definitely closed.
const ( // DoubleBitIntermediate: both contacts read open. The device is moving. DoubleBitIntermediate DoubleBit = 0 // DoubleBitDeterminedOff: the device is open. DoubleBitDeterminedOff DoubleBit = 1 // DoubleBitDeterminedOn: the device is closed. DoubleBitDeterminedOn DoubleBit = 2 // DoubleBitIndeterminate: both contacts read closed, which is impossible. DoubleBitIndeterminate DoubleBit = 3 )
Double-bit states. The numeric values are the on-the-wire encoding.
type DoubleBitBinary ¶
DoubleBitBinary is a two-bit status input.
type FileInfo ¶ added in v0.3.0
type FileInfo struct {
// Name is the path the outstation knows the file by. In a directory
// listing it is the entry's own name, not the full path.
Name string
Type FileType
Size uint32
// Created is the file's creation time. It is the zero time when the
// outstation does not keep one, which many embedded devices do not.
Created time.Time
Permissions FilePermissions
}
FileInfo describes one file or directory on an outstation.
type FileMode ¶ added in v0.3.0
type FileMode uint16
FileMode is what a file is opened for.
const ( // FileModeNull opens nothing. It is what a command that names a file // without transferring it — a delete — carries. FileModeNull FileMode = 0 // FileModeRead opens an existing file for reading. FileModeRead FileMode = 1 // FileModeWrite creates or truncates a file for writing. FileModeWrite FileMode = 2 // FileModeAppend opens a file for writing at its end. FileModeAppend FileMode = 3 )
File open modes.
type FilePermissions ¶ added in v0.3.0
type FilePermissions uint16
FilePermissions are the access bits of a file, laid out as POSIX lays them out: three groups of read, write and execute.
const ( PermWorldExecute FilePermissions = 0x0001 PermWorldWrite FilePermissions = 0x0002 PermWorldRead FilePermissions = 0x0004 PermGroupExecute FilePermissions = 0x0008 PermGroupWrite FilePermissions = 0x0010 PermGroupRead FilePermissions = 0x0020 PermOwnerExecute FilePermissions = 0x0040 PermOwnerWrite FilePermissions = 0x0080 PermOwnerRead FilePermissions = 0x0100 )
Permission bits, from IEEE 1815 table 4-7.
func (FilePermissions) String ¶ added in v0.3.0
func (p FilePermissions) String() string
String renders the bits the way ls does, so a directory listing from a device reads like one from a filesystem.
type FileStatus ¶ added in v0.3.0
type FileStatus uint8
FileStatus is the outcome an outstation reports for a file operation.
The set is the standard's, including the gap between 9 and 16: the codes are fixed by IEEE 1815 table 4-8 and are not renumbered here, because a capture has to be readable against the specification.
const ( FileSuccess FileStatus = 0 FilePermissionDenied FileStatus = 1 // FileInvalidMode means the requested mode is not one the outstation // allows for that file — writing a read-only configuration, say. FileInvalidMode FileStatus = 2 FileNotFound FileStatus = 3 // FileLocked means another master has the file open. FileLocked FileStatus = 4 FileTooManyOpen FileStatus = 5 // FileInvalidHandle means the handle is unknown, which is what a master // sees after the outstation has timed the transfer out. FileInvalidHandle FileStatus = 6 FileWriteBlockSize FileStatus = 7 FileCommLost FileStatus = 8 FileCannotAbort FileStatus = 9 FileNotOpen FileStatus = 16 // FileHandleExpired means the outstation closed the file itself after the // master went quiet for longer than its inactivity timeout. FileHandleExpired FileStatus = 17 FileBufferOverrun FileStatus = 18 // FileFatal means the transfer failed for a reason the outstation cannot // describe more precisely; the file is not usable. FileFatal FileStatus = 19 // FileBlockSequence means a block arrived out of order, which invalidates // everything written so far. FileBlockSequence FileStatus = 20 FileUndefined FileStatus = 255 )
File operation status codes.
func (FileStatus) Err ¶ added in v0.3.0
func (s FileStatus) Err() error
Err returns nil for FileSuccess and an error wrapping ErrFileTransfer otherwise, so a caller can test the outcome with errors.Is and still print what the outstation actually said.
func (FileStatus) String ¶ added in v0.3.0
func (s FileStatus) String() string
type FileType ¶ added in v0.3.0
type FileType uint16
FileType says whether a directory entry is a file or another directory.
type Flags ¶
type Flags uint8
Flags is the quality octet that accompanies most measurements.
The low five bits mean the same thing for every measurement type. The upper three are type-specific: what is CHATTER_FILTER on a binary input is OVER_RANGE on an analog input and ROLLOVER on a counter. Because the interpretation depends on the point type, Flags stores the raw octet and leaves naming to the per-type accessors below.
const ( // Online means the point is being read from the field. A cleared Online // bit is the single most important quality signal in DNP3: the value // present alongside it is not trustworthy. Online Flags = 0x01 // Restart means the value has not been updated since the device restarted. Restart Flags = 0x02 // CommLost means communication with the source of the point has failed. CommLost Flags = 0x04 // RemoteForced means the value was forced by a downstream device. RemoteForced Flags = 0x08 // LocalForced means the value was forced by the outstation itself. LocalForced Flags = 0x10 )
Flag bits common to every measurement type.
const ( // ChatterFilter applies to binary and double-bit binary inputs: the point // is toggling faster than the outstation's filter allows. ChatterFilter Flags = 0x20 // Rollover applies to counters. Deprecated by the standard in favour of // letting the counter wrap, but still emitted by older devices. Rollover Flags = 0x20 // Discontinuity applies to counters: the value cannot be compared against // the previous reading. Discontinuity Flags = 0x40 // OverRange applies to analog inputs and outputs: the value exceeds the // range the point can represent. OverRange Flags = 0x20 // ReferenceErr applies to analog inputs and outputs: the reference used to // digitise the value is not accurate. ReferenceErr Flags = 0x40 // StateBit carries the value itself for binary points inside a flags // octet, as in group 1 variation 2. StateBit Flags = 0x80 )
Type-specific bits. Each is valid only for the measurement types named.
func (Flags) IsGood ¶
IsGood reports whether the value carrying these flags may be trusted: online, not restarting, not comm-lost, and not forced from either end.
func (Flags) String ¶
String renders the common bits by name. Type-specific bits are shown by position because their meaning depends on the point type; use Flags.StringFor when the type is known.
type FrozenCounter ¶
FrozenCounter is a counter value captured at a freeze command.
type Indexed ¶
Indexed pairs a measurement with the point index it was reported at.
Index is 32 bits because that is what the protocol can carry: an object header may address points with a four-octet range or prefix. It was once 16, and a master narrowing what an outstation reported to fit it delivered point 70000 as point 4464 — a real measurement attributed to a different point, with nothing to say so.
type OctetString ¶
type OctetString []byte
OctetString is a variable-length opaque value, group 110 and 111. The standard caps it at 255 octets.
type PointType ¶
type PointType uint8
PointType identifies a measurement type, which fixes the meaning of the upper three quality bits.
type RestartMode ¶
type RestartMode uint8
RestartMode selects between the two restart function codes.
const ( // ColdRestart reinitialises the outstation completely, as though power // had been cycled. ColdRestart RestartMode = iota // WarmRestart reinitialises only the communications process. WarmRestart )
Restart modes.
func (RestartMode) String ¶
func (m RestartMode) String() string
type Timestamp ¶
type Timestamp struct {
Time time.Time
Quality TimestampQuality
}
Timestamp pairs a time with how much that time can be trusted.
The two are kept together deliberately. A DNP3 measurement can carry a perfectly well-formed timestamp from an outstation whose clock has never been set, and a consumer that ignores the quality will happily file that event under 1970 or under whatever the drifted clock says.
func NoTime ¶
func NoTime() Timestamp
NoTime returns the timestamp used by measurements that carry no time.
func Unsynchronized ¶
Unsynchronized returns a timestamp for t whose source clock was not synced.
type TimestampQuality ¶
type TimestampQuality uint8
TimestampQuality describes how much a timestamp can be relied on.
const ( // TimestampInvalid means the measurement carried no time at all. The // Timestamp's Time field is the zero value. TimestampInvalid TimestampQuality = iota // TimestampUnsynchronized means the outstation reported a time while its // own clock was not synchronised to the master. TimestampUnsynchronized // TimestampSynchronized means the outstation's clock was synchronised when // the measurement was taken. TimestampSynchronized )
Timestamp qualities, in increasing order of trust.
func (TimestampQuality) String ¶
func (q TimestampQuality) String() string
Directories
¶
| Path | Synopsis |
|---|---|
|
Package channel provides the physical layer beneath a DNP3 session: the thing that produces a byte stream and reproduces it after a failure.
|
Package channel provides the physical layer beneath a DNP3 session: the thing that produces a byte stream and reproduces it after a failure. |
|
cmd
|
|
|
dnp3-decode
command
Command dnp3-decode renders DNP3 octets as a decoded protocol tree.
|
Command dnp3-decode renders DNP3 octets as a decoded protocol tree. |
|
dnp3-explorer
command
Command dnp3-explorer is a terminal browser for a DNP3 outstation.
|
Command dnp3-explorer is a terminal browser for a DNP3 outstation. |
|
dnp3-master
command
Command dnp3-master is a SCADA client: it polls outstations, records what they report, and issues controls.
|
Command dnp3-master is a SCADA client: it polls outstations, records what they report, and issues controls. |
|
dnp3-outstation
command
Command dnp3-outstation is a simulated DNP3 outstation: a substation RTU with plant behind it.
|
Command dnp3-outstation is a simulated DNP3 outstation: a substation RTU with plant behind it. |
|
Package decoder turns DNP3 octets into a structured trace.
|
Package decoder turns DNP3 octets into a structured trace. |
|
internal
|
|
|
app
Package app implements the DNP3 application layer framing: the fragment header, function codes, internal indications, and the object headers with their qualifier, range and prefix encodings.
|
Package app implements the DNP3 application layer framing: the fragment header, function codes, internal indications, and the object headers with their qualifier, range and prefix encodings. |
|
gen
command
Command gen reads objects/spec/dnp3_objects.yaml and emits the object codecs, the descriptor registry, and the size table the framing layer needs.
|
Command gen reads objects/spec/dnp3_objects.yaml and emits the object codecs, the descriptor registry, and the size table the framing layer needs. |
|
link
Package link implements the DNP3 data link layer: frame encoding and decoding, the CRC, and the primary and secondary station state machines.
|
Package link implements the DNP3 data link layer: frame encoding and decoding, the CRC, and the primary and secondary station state machines. |
|
stack
Package stack couples the link and transport layers to a byte stream.
|
Package stack couples the link and transport layers to a byte stream. |
|
transport
Package transport implements the DNP3 transport function: the single-octet layer that cuts application fragments into link-sized segments and puts them back together.
|
Package transport implements the DNP3 transport function: the single-octet layer that cuts application fragments into link-sized segments and puts them back together. |
|
Package master implements the DNP3 master role: the station that polls outstations, receives their events, and issues commands.
|
Package master implements the DNP3 master role: the station that polls outstations, receives their events, and issues commands. |
|
Package multidrop shares one channel between several DNP3 sessions.
|
Package multidrop shares one channel between several DNP3 sessions. |
|
Package objects implements the DNP3 object group and variation codecs.
|
Package objects implements the DNP3 object group and variation codecs. |
|
Package outstation implements the DNP3 outstation role: the device that holds measurements, answers a master's polls, and executes its commands.
|
Package outstation implements the DNP3 outstation role: the device that holds measurements, answers a master's polls, and executes its commands. |