Documentation
¶
Index ¶
- Constants
- func IsErrDoubleCmdTerm(err error) bool
- func IsErrSingleCmdTerm(err error) bool
- func SetLogger(lg *logrus.Logger)
- type APCI
- type APDU
- type ASDU
- type AutoReconnectRule
- type COA
- type COT
- type Client
- func (c *Client) Close()
- func (c *Client) Connect() error
- func (c *Client) IsConnected() bool
- func (c *Client) SendCounterInterrogation()
- func (c *Client) SendDoubleCommand(address IOA, close bool) error
- func (c *Client) SendGeneralInterrogation()
- func (c *Client) SendIFrame(asdu *ASDU)
- func (c *Client) SendSingleCommand(address IOA, close bool) error
- func (c *Client) SendTestFrame()
- type ClientHandler
- type ClientOption
- func (o *ClientOption) SetAutoReconnectRule(rule *AutoReconnectRule) *ClientOption
- func (o *ClientOption) SetConnectTimeout(timeout time.Duration) *ClientOption
- func (o *ClientOption) SetOnConnectHandler(handler OnConnectHandler) *ClientOption
- func (o *ClientOption) SetOnDisconnectHandler(handler OnDisconnectHandler) *ClientOption
- func (o *ClientOption) SetTLS(tc *tls.Config) *ClientOption
- type Conn
- type Frame
- type FrameType
- type IFrame
- type IOA
- type InformationElement
- type InformationElementFormat
- type InformationElementType
- type InformationObject
- type NOO
- type ORG
- type OnConnectHandler
- type OnDisconnectHandler
- type PN
- type QualityDescriptor
- type SFrame
- type SQ
- type Server
- type T
- type TypeID
- type UFrame
- type UFrameFunction
Constants ¶
const ( ApduHeaderLen = 4 // non-include startByte and apduLen AsduHeaderLen = 6 )
const ( DefaultConnectTimeout = 30 * time.Second DefaultReconnectRetries = 0 DefaultReconnectInterval = 1 * time.Minute )
const (
IOALength = 3
)
Variables ¶
This section is empty.
Functions ¶
func IsErrDoubleCmdTerm ¶
func IsErrSingleCmdTerm ¶
Types ¶
type APCI ¶
APCI (Application Protocol Control Information).
Each APCI starts with a start byte with value 0x68 followed by the 8-bit length of APDU and four 8-bit control fields (CF). Generally, the length of APCI is 6 bytes.
| <- 8 bits -> | ----- | Start Byte (Ox68) | | | Length of APDU | | | Control Field 1 | APCI | Control Field 2 | | | Control Field 3 | | | Control Field 4 | | | <- 8 bits -> | -----
type APDU ¶
APDU (Application Protocol Data Unit).
APDU contains an APCI or an APCI with ASDU.
| <- 8 bits -> | ----- ----- | Start Byte (Ox68) | | | | Length of APDU | | | | Control Field 1 | APCI APDU | Control Field 2 | | | | Control Field 3 | | | | Control Field 4 | | | | <- 8 bits -> | ----- ----- <- APDU with fixed length -> | <- 8 bits -> | ----- ----- | Start Byte (Ox68) | | | | Length of APDU | | | | Control Field 1 | APCI APDU | Control Field 2 | | | | Control Field 3 | | | | Control Field 4 | | | | ASDU | ASDU | | <- 8 bits -> | ----- ----- <- APDU with variable length ->
type ASDU ¶
type ASDU struct { Signals []*InformationElement // contains filtered or unexported fields }
ASDU (Application Service Data Unit).
The ASDU contains two main sections: - the data unit identifier (with the fixed length of six bytes):
- defining the specific type of data;
- providing addressing to identify the specific data;
- including information as cause of transmission.
- the data itself, made up of one or more information objects:
- each ASDU can transmit maximum 127 objects;
- the type identification is applied to the entire ASDU, so the information objects contained in the ASDU are of the same type.
The format of ASDU:
| <- 8 bits -> | | Type Identification | -------------------- | SQ | Number of objects | | | T | P/N | Cause of transmission (COT) | | | Original address (ORG) | Data Uint Identifier | ASDU address fields | | | ASDU address fields | -------------------- | Information object address (IOA) | -------------------- | Information object address (IOA) | | | Information object address (IOA) | Information Object 1 | Information Elements | | | Time Tag | -------------------- | Information Object 2 | | Information Object N |
type AutoReconnectRule ¶
type AutoReconnectRule struct {
// contains filtered or unexported fields
}
type COA ¶
type COA = uint16
COA (Common Address of ASDU, 2 bytes) is normally interpreted as a station address. - COA is either 1 or 2 bytes in length, fixed on pre-system basis. The value range of 2 bytes (the standard):
- 0 is not used;
- 1-65534 means a station address;
- 65535 means global address, and it is broadcast in control direction have to be answered in monitor direction by the address that is the specific defined common address (station address).
- Global Address is used when the same application function must be initiated simultaneously. It's restricted to the following ASDUs:
- TypeID = CIcNa1: replay with particular system data snapshot at common time
- TypeID = CCiNa1: freeze totals at common time
- TypeID = CCsNa1: synchronize clocks to common time
- TypeID = CRpNc1: simultaneous reset
type COT ¶
type COT uint8
COT (Cause of Transmission, 6 bits) is used to control message routing. - value range:
0 is not defined!
1-47 is used for standard IEC 101 definitions
48-63 is for special use (private range)
COT field is used to control the routing of messages both on the communication network, and within a station, directing by ASDU to the correct program or task for processing. ASDUs in control direction are confirmed application services and may be mirrored in monitor direction with different causes of transmission.
COT is a 6-bit code which is used in interpreting the information at the destination station. Each defined ASDU type has a defined subset of the codes which are meaningful with it.
const ( CotPerCyc COT = 1 // periodic, cyclic CotBack COT = 2 // background scan CotSpont COT = 3 // spontaneous CotInit COT = 4 // initialized CotReq COT = 5 // request or requested CotAct COT = 6 // activation CotActCon COT = 7 // activation confirmation CotDeact COT = 8 // deactivation CotDeactCon COT = 9 // deactivation confirmation CotActTerm COT = 10 // activation termination CotRetRem COT = 11 // return information caused by a remote command CotRetLoc COT = 12 // return information caused by a local command CotFile COT = 13 // file transfer CotInrogen COT = 20 // interrogated by general interrogation CotInro1 COT = 21 // interrogated by general interrogation group1 CotInro2 COT = 22 // interrogated by general interrogation group2 CotInro3 COT = 23 // interrogated by general interrogation group3 CotInro4 COT = 24 // interrogated by general interrogation group4 CotInro5 COT = 25 // interrogated by general interrogation group5 CotInro6 COT = 26 // interrogated by general interrogation group6 CotInro7 COT = 27 // interrogated by general interrogation group7 CotInro8 COT = 28 // interrogated by general interrogation group8 CotInro9 COT = 29 // interrogated by general interrogation group9 CotInro10 COT = 30 // interrogated by general interrogation group10 CotInro11 COT = 31 // interrogated by general interrogation group11 CotInro12 COT = 32 // interrogated by general interrogation group12 CotInro13 COT = 33 // interrogated by general interrogation group13 CotInro14 COT = 34 // interrogated by general interrogation group14 CotInro15 COT = 35 // interrogated by general interrogation group15 CotInro16 COT = 36 // interrogated by general interrogation group16 CotReqcogen COT = 37 // interrogated by counter interrogation CotReqco1 COT = 38 // interrogated by counter interrogation group 1 CotReqco2 COT = 39 // interrogated by counter interrogation group 2 CotReqco3 COT = 40 // interrogated by counter interrogation group 3 CotReqco4 COT = 41 // interrogated by counter interrogation group 4 CotUnknownType COT = 44 // type identification unknown CotUnknownCause COT = 45 // cause of transmission unknown CotUnknownAsduAddress COT = 46 // ASDU address unknown CotUnknownObjectAddress COT = 47 // information object address unknown )
type Client ¶
type Client struct { *ClientOption // contains filtered or unexported fields }
Client in IEC 104 is also called as master or controlling station.
func NewClient ¶
func NewClient(option *ClientOption) *Client
func (*Client) IsConnected ¶
func (*Client) SendCounterInterrogation ¶
func (c *Client) SendCounterInterrogation()
func (*Client) SendDoubleCommand ¶
func (*Client) SendGeneralInterrogation ¶
func (c *Client) SendGeneralInterrogation()
func (*Client) SendIFrame ¶
func (*Client) SendSingleCommand ¶
func (*Client) SendTestFrame ¶
func (c *Client) SendTestFrame()
type ClientHandler ¶
type ClientHandler interface { GeneralInterrogationHandler(apdu *APDU) error CounterInterrogationHandler(apdu *APDU) error ClockSynchronizationHandler(apdu *APDU) error TestCommandHandler(apdu *APDU) error ReadCommandHandler(apdu *APDU) error ResetProcessCommandHandler(apdu *APDU) error DelayAcquisitionCommandHandler(apdu *APDU) error APDUHandler(apdu *APDU) error }
type ClientOption ¶
type ClientOption struct {
// contains filtered or unexported fields
}
func NewClientOption ¶
func NewClientOption(server string, handler ClientHandler) (*ClientOption, error)
func (*ClientOption) SetAutoReconnectRule ¶
func (o *ClientOption) SetAutoReconnectRule(rule *AutoReconnectRule) *ClientOption
func (*ClientOption) SetConnectTimeout ¶
func (o *ClientOption) SetConnectTimeout(timeout time.Duration) *ClientOption
func (*ClientOption) SetOnConnectHandler ¶
func (o *ClientOption) SetOnConnectHandler(handler OnConnectHandler) *ClientOption
func (*ClientOption) SetOnDisconnectHandler ¶
func (o *ClientOption) SetOnDisconnectHandler(handler OnDisconnectHandler) *ClientOption
func (*ClientOption) SetTLS ¶
func (o *ClientOption) SetTLS(tc *tls.Config) *ClientOption
type FrameType ¶
type FrameType = byte // transmission frame format
FrameType is the transmission frame format.
The frame format is determined by the two last bits of the first control field (CF1).
type IFrame ¶
IFrame (Information Transfer Format), last bit of CF1 is (0)B.
Control fields of I-format frame:
| <- 8 bits -> | | Send sequence no. N(S) [LSB] | 0 | | Send sequence no. N(S) [MSB] | | Receive sequence no. N(R) [LSB] | 0 | | Receive sequence no. N(R) [MSB] |
- It is used to preform numbered information transfer between the controlling and controlled station.
- I-format APDUs always contain an ASDU, so it has variable length.
- Control fields of I-format indicate message direction. It contains two 15-bit sequence numbers that are sequentially increased by one for each APDU and each direction.
- The sender increases the send sequence number N(S) and the receiver increases the receive sequence number N(S). The receiving station acknowledges each APDU or a number of APDUs when it returns the receive sequence number up to the number whose APDUs are properly received.
- The sending station holds the APDU or APDUs in a buffer until it receives back its own send sequence number as a receive sequence number which is valid acknowledge for all numbers less or equal to the received number.
- In case of a longer data transmission in one direction only, an S format has to be sent in the other direction to acknowledge the APDUs before buffer overflow or time out.
- The method should be used in both directions. After the establishment of a TCP connection, the send and receive sequence numbers are set to zero.
- The right interpretation of sequence numbers depends on the position of LSB (the Least Significant Bit) and MSB (the Most Significant Bit).
- N(S) = CF1 >> 1 + CF2 << 7
- N(R) = CF3 >> 1 + CF4 << 7 For example, CRs 0x06 Ox00 0x02 0x00 will be interpreted as N(S) = 3 and N(R) = 1, e.g., the third APDU send by the source and waiting for the first APDU from the destination.
type InformationElement ¶
type InformationElement struct { TypeID TypeID `json:"type_id"` Address IOA `json:"address"` Value float64 `json:"value"` Raw []byte `json:"raw"` Quality QualityDescriptor `json:"quality"` // if the value's quality is not zero, it means the value is not valid! Ts time.Time `json:"ts"` Format InformationElementFormat // contains filtered or unexported fields }
InformationElement is a building block used to transmit information. Format and length of each information differs and is given by the standard. The standard also describes how encoded values are interpreted.
func (*InformationElement) IsValid ¶
func (ie *InformationElement) IsValid() bool
type InformationElementFormat ¶
type InformationElementFormat []InformationElementType
type InformationElementType ¶
type InformationElementType int
const ( // SIQ indicates single-point information with quality descriptor. [单点遥信] // Length: 1 byte // TypeID: MSpNa1, 2 ,30 // Format: // | <- 8 bits -> | // ------------------------------------------------ // | IV | NT | SB | BL | 0 | 0 | 0 | SPI | // https://github.com/boundary/wireshark/blob/master/epan/dissectors/packet-iec104.c#L1587 // SIQ contains a set quality bits. SIQ InformationElementType = iota // DIQ indicates double-point information with quality descriptor. // Length: 1 byte // TypeID: MDpNa1 // Format: // | <- 8 bits -> | // ------------------------------------------------ // | IV | NT | SB | BL | 0 | 0 | DPI | // https://github.com/boundary/wireshark/blob/master/epan/dissectors/packet-iec104.c#L1607 // DIQ contains a set quality bits. DIQ // BSI indicates binary state information. // Length: 4 bytes // TypeID: 7,8,33,51 BSI // SCD indicates status and change detection. // Length: 4 bytes // TypeID: 20 SCD // QDS indicates quality descriptor. // Length: 1 byte // TypeID: 5,6,7,8,9,10,11,12,13,14,20,32,33,34,36 // Format: // | <- 8 bits -> | // ------------------------------------------------ // | IV | NT | SB | BL | 0 | 0 | 0 | OV | // https://github.com/wireshark/wireshark/blob/master/epan/dissectors/packet-iec104.c#L2461 // QDS contains a set quality bits. QDS // VTI indicates value with transient state indication. // Length: 1 byte // TypeID: 5,6,32 // Format: // | <- 8 bits -> | // ------------------------------------------------ // | T | Value I7 | // VTI contains a 7-bit value in the range [-64, 63]. VTI // NVA indicates normalized value. // Length: 2 bytes // TypeID: 9,10, MMeNd1, 34,48,110 // Range: [-1, +1-2^-15] // https://github.com/wireshark/wireshark/blob/master/epan/dissectors/packet-iec104.c#L1367 NVA // SVA indicates scaled value. // Length: 2 bytes // TypeID: 11,12,49,111 // Range: [-2^15, +2^15-1] // https://github.com/wireshark/wireshark/blob/master/epan/dissectors/packet-iec104.c#L1398 SVA // IEEE754STD indicates short floating point number. // Length: 4 bytes // TypeID: 13,14,36,50,112 // Format: // | <- 8 bits -> | // ------------------------------------------------ // | Value I16 | // SVA contains a 16-bit value in the range [-32768, 32767] which represents a fixed decimal point number. However, // the position of the decimal point is not transmitted by the value, but it is set in the system database. // For example, a value of 39.5 amps may be transmitted as 395 where the resolution is fixed at 0.1 amp. IEEE754STD // BCR indicates binary counter reading. // Length: 5 bytes // TypeID: MItNa1 BCR // SEP indicates single event of protection equipment. // Length: 1 byte // TypeID: 17,38 SEP // SPE indicates start events of protection equipment. // Length: 1 byte // TypeID: 18,39 SPE // OCI indicates output circuit information of protection equipment. // Length: 1 byte // TypeID: 19,40 OCI // QDP indicates quality descriptor for events of protection equipment. // Length: 1 byte // TypeID: 18,19,39,40 QDP // SCO indicates single command. // Length: 1 byte // Format: // | <- 8 bits -> | // ------------------------------------------------ // | SE | QU | 0 | ON | // // Value Range: // - Select Open : 0x80; // - Select Close : 0x81; // - Execute Open : 0x00; // - Execute Close : 0x01; // - Cancel Open : 0x00; // - Cancel Close : 0x01; // // TypeID: CScNa1 SCO // DCO indicates double command. // Length: 1 byte // Format: // | <- 8 bits -> | // ------------------------------------------------ // | SE | QU | ON | // // Value Range: // - Select Open : 0x81; // - Select Close : 0x82; // - Execute Open : 0x01; // - Execute Close : 0x02; // - Cancel Open : 0x01; // - Cancel Close : 0x02; // // TypeID: CDcNa1 DCO // RCO indicates regulating step command. // Length: 1 byte // Format: // | <- 8 bits -> | // ------------------------------------------------ // | SE | QU | UP | // // Value Range: // - Select Open : 0x81; // - Select Close : 0x82; // - Execute Open : 0x01; // - Execute Close : 0x02; // - Cancel Open : 0x01; // - Cancel Close : 0x02; // // TypeID: CRcNa1 RCO // CP56Time2a indicates 7-byte binary time. // Length: 7 bytes // TypeID: MSpTb1, MDpTb1 CP56Time2a // CP24Time2a indicates 3-byte binary time. // Length: 3 bytes // TypeID: CP24Time2a // CP16Time2a indicates 2-byte binary time/ // Length: 2 bytes // TypeID: CP16Time2a // QOI indicates qualifier of general interrogation. // Length: 1 byte // TypeID: CIcNa1 QOI // QCC indicates qualifier of counter interrogation command. // Length: 1 byte // TypeID: CCiNa1 QCC // QPM indicates qualifier of parameter of measured values. // Length: 1 byte // TypeID: 110,112 QPM // QPA indicates qualifier of parameter activation. // Length: 1 byte // TypeID: 111,113 QPA // QRP indicates qualifier of reset process command. // Length: 1 byte // TypeID: 105 QRP // QOC indicates qualifier of command. // Length: 1 byte // TypeID: 45,46,47,48,49,50 QOC // QOS indicates qualifier of set-point command. // Length: 1 byte // TypeID: 48,49,50 QOS // FRQ indicates file ready qualifier. // Length: 1 byte // TypeID: 120 FRQ // SRQ indicates section ready qualifier. // Length: 1 byte // TypeID: 121 SRQ // SCQ indicates select and call qualifier. // Length: 1 byte // TypeID: 122 SCQ // LSQ indicates last section or segment qualifier. // Length: 1 byte // TypeID: 123 LSQ // AFQ indicates acknowledge file or section qualifier. // Length: 1 byte // TypeID: 124 AFQ // NOF indicates name of file. // Length: 2 bytes // TypeID: 120,121,122,123,124,125,126 NOF // NOS indicates name of section. // Length: 2 bytes // TypeID: 121,122,123,124,125 NOS // LOF indicates length of file or section. // Length: 3 bytes // TypeID: 120,121 LOF // LOS indicates length of segment. // Length: 1 byte // TypeID: 125 LOS // CHS indicates checksum. // Length: 1 byte // TypeID: 123 CHS // SOF indicates status of file. // Length: 1 byte // TypeID: 126 SOF // COI indicates cause of initialization. // Length: 1 byte // TypeID: 70 COI // FBP indicates fixed test bit pattern. // Length: 2 bytes // TypeID: 104 FBP )
type InformationObject ¶
type InformationObject struct {
// contains filtered or unexported fields
}
InformationObject . Each information object is addressed by Information Object Address (IOA) which identifies the particular data within a defined station. Its length is 3 bytes for IEC 104. The address is used as destination address in control direction and as source address in monitor direction.
- The third byte of IOA is only used in case of structuring the information object address in order to define unambiguous addresses with a specific system.
- If the information object address is not relevant (not used) in some ASDUs, it is set to zero.
All information objects transmitted by one ASDU must have the same ASDU type. If there are more objects of different types to be transmitted, they are inserted in several ASDUs.
For each defined ASDU type, the IEC 104 standard defines the format of the information object, i.e., what information elements form such object and how they are structured.
The following example shows information object Single-point information without time (ASDU type=1). The object format has two forms: one for SQ=0 and one for SQ=1. Valid COT for this object are: 2 (background scan), 3 (spontaneous), 5 (requested), 11, 12 (feedback), 20 +G (interrogated by station interrogation)
| Information Object Type 1 (MSpNa1) | | <- 8 bits -> | | Information Object Address (IOA) | SQ=0 | IV | NT | SB | BL | 0 | 0 | 0 | SPI | --------------------------------------------------------- | <- 8 bits -> | | Information Object Address (IOA) | SQ=1 | IV | NT | SB | BL | 0 | 0 | 0 | SPI | | v | IV | NT | SB | BL | 0 | 0 | 0 | SPI |
Some information objects contain several information elements. For example, the following example shows information object of type 10 (measured value, normalized with time tag). This object is defined only for SQ=0 and contains three information elements: normalized value NVA (2 bytes), quality descriptor (1 byte), and binary timestamp (3 bytes). For this type of object, valid causes of transmission are 3 (spontaneous), 5 (requested).
| Information Object Type 10 (M_ME_TA_1) | | <- 8 bits -> | | Information Object Address (IOA) | SQ=0 | NVA | normalized value | NVA | | IV | NT | SB | BL | 0 | 0 | 0 | SPI | quality descriptor | CP24Time2a | binary timestamp | CP24Time2a | | CP24Time2a |
The number of information objects and information elements within the ASDU is the Number of objects given in the second byte of ASDU header.
func (*InformationObject) Data ¶
func (i *InformationObject) Data() []byte
type ORG ¶
type ORG uint8
ORG (Originator Address, 1 byte) provides a method for a controlling station to explicitly identify itself.
- The originator address is optional when there is only one controlling station in a system. If it is not used, all bits are set to zero.
- It is required when where is more than one controlling station, or some stations are dual-mode. In this case, the address can be used to direct command confirmations back to the particular controlling station rather than to the whole system.
- If there is more than one single source in a system defined, the ASDUs in monitor direction have to be directed to all relevant sources of the system. In this case the specific affected source has to select its specific ASDUs.
TODO What's the differences between ORG and TCP endpoint (IP + PORT)? Can we identify the source by TCP endpoint?
type OnConnectHandler ¶
type OnConnectHandler func(c *Client)
type OnDisconnectHandler ¶
type OnDisconnectHandler func(c *Client)
type PN ¶
type PN bool
PN (Positive/Negative, 1 bit) indicates the positive or negative confirmation of an activation requested by a primary application function. The bit is used when the control command is mirrored in the monitor direction, and it provides indication of whether the command was executed or not. - PN=0 (false): positive confirm. - PN=1 (true): negative confirm.
type QualityDescriptor ¶
type QualityDescriptor byte
const ( // IV = VALID (0) / INVALID (1). // - A value is valid if it was correctly acquired. After the acquisition function recognizes abnormal conditions // of the information source (missing or non-operating updating devices) the value is then marked invalid. The // value of the information object is not defined under this condition. // - The mark is invalid is used to indicate to the destination that the value may be incorrect due to a fault or // other abnormal condition, and cannot be used. IV QualityDescriptor = 1 << 7 // NT = TOPICAL (0) / NOT TOPICAL (1). // - A value is topical if the most recent update was successful. It is not topical if it was not updated // successfully during a specified time interval or if it is unavailable. NT QualityDescriptor = 1 << 6 // SB = NOT SUBSTITUTED (0) / SUBSTITUTED (1). // - The value of the information object is provided by the input of an operator (dispatcher) or by an automatic // source. // - It means that the value is derived from the normal measurement. SB QualityDescriptor = 1 << 5 // BL = NOT BLOCKED (0) / BLOCKED (1). // - The value of information object is blocked for transmission; the value remains in the state that was acquired // before it was blocked. Blocking prevents updating of the value of the point. // - Blocking and unblocking may be initiated for example by a local lock or a local automatic cause. BL QualityDescriptor = 1 << 4 // OV = NO OVERFLOW (0) / OVERFLOW (1) // - The value of the information object is beyond a predefined range of value (mainly applicable to analog values). // - It is used primarily with analog or counter values. OV QualityDescriptor = 1 << 0 // SPI (Single Point Information). // - 0 means status OFF; // - 1 means status ON. SPI QualityDescriptor = 1 // DPI (Double Point Information). // - 0 means intermediate state; // - 1 means determined state OFF; // - 2 means determined state ON. // - 3 means intermediate state; DPI QualityDescriptor = 3 )
type SFrame ¶
SFrame (Numbered Supervisory functions), last two bit of CF1 is (01)B.
Control fields of S-format frame:
| <- 8 bits -> | | | 0 | 1 | | | | Receive sequence no. N(R) [LSB] | 0 | | Receive sequence no. N(R) [MSB] |
- It is used to perform numbered supervisory functions.
- S-format APDUs always consist of one APCI only, so it has fixed length.
- In any cases where the data transfer is only in a single direction, S-format APDUs have to be sent in other direction before timeout, buffer overflow or when it has crossed maximum number of allowed I-format APDUs without acknowledgement.
type SQ ¶
type SQ bool
SQ (Structure Qualifier, 1 bit) specifies how information objects or elements are addressed.
- SQ=0 (false): each ASDU contains one or more than one equal information objects: | <- 8 bits -> | | Type Identification [1B] | -------------------- | 0 | Number of objects [7b] | | | T | P/N | Cause of transmission [6b] | Data Unit Identifier | Original address (ORG) [1B] | | | ASDU address fields [2B] | -------------------- | Information object address (IOA) [3B] | -------------------- | Information Elements | Information Object 1 | Time Tag (if used) | -------------------- | Information object address (IOA) [3B] | -------------------- | Information Elements | Information Object 2 | Time Tag (if used) | -------------------- | Information object address (IOA) [3B] | -------------------- | Information Elements | Information Object N | Time Tag (if used) | -------------------- | <- SQ = 0 -> |
- the number of objects is binary coded (NumberOfObjects), and defines the number of the information objects;
- each information object has its own information object address (IOA);
- each single element or a combination of elements of object is addressed by the IOA.
- [personal guess] SQ=0 is used to transmit a set of discontinuous values.
- SQ=1 (true): each ASDU contains just one information object. | <- 8 bits -> | | Type Identification [1B] | -------------------- | 1 | Number of objects [7b] | | | T | P/N | Cause of transmission [6b] | Data Unit Identifier | Original address (ORG) [1B] | | | ASDU address fields [2B] | -------------------- | Information object address (IOA) [3B] | -------------------- | Information Element 1 | | | Information Element 2 | | | Information Element 3 | Information Object | Information Element N | | | Time Tag (if used) | -------------------- | <- SQ = 1 -> |
- the number of elements is binary coded (NumberOfObjects), and defines the number of the information elements;
- there is just one information object address, which is the address of the first information element, the following information elements are identified by numbers continuous by +1 from this offset;
- all information elements are of the same format, such as a measured value.
- [personal guess] SQ=1 is used to transmit a sequence of continuous values to save bandwidth.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server in IEC 104 is also called as slave or controlled station.
type T ¶
type T bool // Test
T (Test, 1 bit) defines ASDUs which generated during test conditions. That is to say, it is not intended to control the process or change the system state. - T=0 (false): no test, used in the product environment. - T=1 (true): test, used in the development environment.
type TypeID ¶
type TypeID uint8
TypeID (Type Identification, 1 byte): - value range:
- 0 is not used;
- 1-127 is used for standard IEC 101 definitions, there are presently 58 specific types defined: | Type ID | Group | | 1-40 | Process information in monitor direction | | 45-51 | Process information in control direction | | 70 | System information in monitor direction | | 100-106 | System information in control direction | | 110-113 | Parameter in control direction | | 120-126 | File transfer |
- 128-135 is reserved for message routing;
- 136-255 for special use.
const ( // MSpNa1 indicates single point information. // InformationElementType: SIQ // COT: CotPerCyc, CotSpont, CotInrogen // [遥信 - 单点 - 不带时标] MSpNa1 TypeID = 0x1 // 1 // MSpTa1 indicates single point information with time tag CP24Time2a. // InformationElementType: SIQ + CP24Time2a // COT: CotSpont // [遥信 - 单点 - 三字节时标] MSpTa1 TypeID = 0x2 // 2 // MDpNa1 indicates double point information. // InformationElementType: DIQ // COT: CotSpont // [遥信 - 双点 - 不带时标] MDpNa1 TypeID = 0x3 // 3 // MDpTa1 indicates double point information with time tag CP24Time2a. // InformationElementType: DIQ + CP24Time2a // COT: CotSpont // [遥信 - 双点 - 三字节时标] MDpTa1 TypeID = 0x4 // 4 // MMeNa1 indicates measured value, normalized value. // InformationElementType: NVA + QDS // COT: 2, 3, 5, 11, 12, 20, 20+G MMeNa1 TypeID = 0x9 // 9 // MMeTa1 indicates measured value, normalized value with time tag CP24Time2a. // InformationElementType: NVA + QDS + CP24Time2a // COT: 3, 5 MMeTa1 TypeID = 0xa // 10 // MMeNb1 indicates measured value, scaled value. // InformationElementType: SVA + QDS // COT: 2, 3, 5, 11, 12, 20, 20+G MMeNb1 TypeID = 0xb // 11 // MMeTb1 indicates measured value, scaled value with time tag CP24Time2a. // InformationElementType: SVA + QDS + CP24Time2a // COT: 3, 5 MMeTb1 TypeID = 0xc // 12 // MMeNc1 indicates measured value, short floating point value. // InformationElementType: IEEE754STD + QDS // COT: 2, 3, 5, 11, 12, 20, 20+G MMeNc1 TypeID = 0xd // 13 // MMeTc1 indicates measured value, short floating point value with time tag CP24Time2a. // InformationElementType: IEEE754STD + QDS + CP24Time2a // COT: 2, 3, 5, 11, 12, 20, 20+G MMeTc1 TypeID = 0xe // 14 // MItNa1 indicates integrated totals. // InformationElementType: BCR // COT: 2, CotReqcogen, 37+G MItNa1 TypeID = 0xf // 15 // MItTa1 indicates integrated totals with time tag CP24Time2a. // InformationElementType: BCR + CP24Time2a // COT: 3, CotReqcogen, 37+G MItTa1 TypeID = 0x10 // 16 // MMeNd1 indicates measured value, normalized value without quality descriptor. // InformationElementType: NVA // COT: 1,2,3,5,11,12,20,20+G // [遥测 - 归一化值 - 不带时标 - 不带品质描述] MMeNd1 TypeID = 0x15 // 21 // MSpTb1 indicates single point information with time tag CP56Time2a. // InformationElementType: SIQ + CP56Time2a // COT: 3,5,11,12 MSpTb1 TypeID = 0x1e // 30 // MDpTb1 indicates double point information with time tag CP56Time2a. // InformationElementType: DIQ + CP56Time2a // COT: 3,5,11,12 MDpTb1 TypeID = 0x1f // 31 // MMeTd1 indicates measured value, normalized value with time tag CP56Time2a. // InformationElementType: NVA + QDS + CP56Time2a // COT: CotSpont, 5 MMeTd1 TypeID = 0x22 // 34 // MMeTe1 indicates measured value, scaled value with time tag CP56Time2a. // InformationElementType: SVA + QDS + CP56Time2a // COT: CotSpont, 5 MMeTe1 TypeID = 0x23 // 35 // MMeTf1 indicates measured value, short floating point value with time tag CP56Time2a. // InformationElementType: IEEE754STD + QDS + CP56Time2a // COT: 2, CotSpont, 5, 11, 12, 20, 20+G MMeTf1 TypeID = 0x24 // 36 // MItTb1 indicates integrated totals with time tag CP56Time2a. // InformationElementType: BCR + CP56Time2a // COT: CotSpont, CotReqcogen, 37+G MItTb1 TypeID = 0x25 // 37 // CScNa1 indicates single command. // InformationElementType: SCO // COT: 6, 7, 8, 9, 10, 44, 45, 46, 47 CScNa1 TypeID = 0x2d // 45 // CDcNa1 indicates double command. // InformationElementType: DCO // COT: 6, 7, 8, 9, 10, 44, 45, 46, 47 CDcNa1 TypeID = 0x2e // 46 // CRcNa1 indicates regulating step command. // InformationElementType: RCO // COT: 6, 7, 8, 9, 10, 44, 45, 46, 47 CRcNa1 TypeID = 0x2f // 47 // CSeNa1 indicates set-point command, normalized value. // InformationElementType: NVA + QOS // COT: 6, 7, 8, 9, 10, 44, 45, 46, 47 CSeNa1 TypeID = 0x30 // 48 // CSeNb1 indicates set-point command, scaled value. // InformationElementType: SVA + QOS // COT: 6, 7, 8, 9, 10, 44, 45, 46, 47 CSeNb1 TypeID = 0x31 // 49 // CSeNc1 indicates set-point command, short floating point value. // InformationElementType: IEEE754STD + QOS // COT: 6, 7, 8, 9, 10, 44, 45, 46, 47 CSeNc1 TypeID = 0x32 // 50 // CScTa1 indicates single command with time tag CP56Time2a. // InformationElementType: SCO + CP56Time2a CScTa1 TypeID = 0x3a // 58 // CDcTa1 indicates double command with time tag CP56Time2a. // InformationElementType: DCO + CP56Time2a CDcTa1 TypeID = 0x3b // 59 // CSeTa1 indicates set-point command, normalized value with time tag CP56Time2a. // InformationElementType: NVA + QOS + CP56Time2a CSeTa1 TypeID = 0x3d // 61 // CSeTb1 indicates set-point command, scaled value with time tag CP56Time2a. // InformationElementType: SVA + QOS + CP56Time2a CSeTb1 TypeID = 0x3e // 62 // CSeTc1 indicates set-point command, short floating point value with time tag CP56Time2a. // InformationElementType: IEEE754STD + QOS + CP56Time2a CSeTc1 TypeID = 0x3f // 63 // CIcNa1 indicates general interrogation command. [召唤全数据] // InformationElementType: QOI // COT: 6,7,8,9,10,44,45,46,47 CIcNa1 TypeID = 0x64 // 100 // CCiNa1 indicates counter interrogation command. [召唤全电度] // InformationElementType: QCC // COT: 6,7,8,9,10,44,45,46,47 CCiNa1 TypeID = 0x65 // 101 // CRdNa1 indicates read command. // InformationElementType: null // COT: 5 CRdNa1 TypeID = 0x66 // 102 // CCsNa1 indicates clock synchronization command. [时钟同步] // InformationElementType: CP56Time2a // COT: 3,6,7,44,45,46,47 CCsNa1 TypeID = 0x67 // 103 // CTsNb1 indicates test command. // InformationElementType: FBP // COT: 6, 7, 44, 45, 46, 47 CTsNb1 TypeID = 0x68 // 104 // CRpNc1 indicates reset process command. // InformationElementType: QRP // COT: 6, 7, 44, 45, 46, 47 CRpNc1 TypeID = 0x69 // 105 // CCdNa1 indicates delay acquisition command. // InformationElementType: CP16Time2a // COT: CotAct, CotActCon, 44, 45, 46, 47 CCdNa1 TypeID = 0x6a // 106 // CTsTa1 indicates command with time tag CP56Time2a. // InformationElementType: CTsTa1 TypeID = 0x6b // 107 )
type UFrame ¶
UFrame (Unnumbered control functions), last two bit of CF1 is (11)B.
Control fields of U-format frame:
| <- 8 bits -> | | TESTFR | STOPDT | STARTDT | 1 | 1 | | | | | 0 | | | | | 0 |
- It is used to perform unnumbered control functions. To be specific, it is used for activation and confirmation mechanism of STARTDT, STOPDT and TESTFR. Only one of functions TESTFR/STOPDT/STARTDT can be activated at the same time.
- U-format APDUs always contain one APCI only, so it has fixed length.
- STARTDT, and STOPDT are used by the controlling station to control the data transfer from a controlled station.
- When the connection is established, user data transfer is not automatically enabled, e.g., default state is STOPDT. In this state, the controlled station does not send any data via this connection, except unnumbered control functions and confirmations. The controlling station must activate the user data transfer by sending a STARTDT act (activate). The controlled station responds with a STARTDT con (confirm). If the STARTDT is not confirmed, the connection is closed by the controlling station. TODO 给 STARTDT ACTIVATE 设置确认超时!!!
- Only the controlling station sends the STARTDT. The expected mode of operation is that the STARTDT is sent only once after the initial establishment of the connection. The connection then operates with both controlled and controlling station permitted to send any messages at any time until the controlling station decides to close the connection with a STOPDT command.
- The controlling and/or controlled station must regularly check the status of all established connections to detect any communication problems as soon as possible. This is done by sending TESTFR frames.
- Open connections may be periodically tested in both directions by sending test APDUs (TESTFR=act) which are confirmed by the receiving station sending TESTFR=con.
- Both stations may initiate the test procedure after a specific period of time in which no data transfer occur (timeout). TODO 主站向子站发送 TESTFR=act 等待子站响应 TESTFR=con。
type UFrameFunction ¶
type UFrameFunction []byte
var ( UFrameFunctionStartDTA UFrameFunction = []byte{0x07, 0x00, 0x00, 0x00} // Start Data Transfer Activation CF1: 0 0 0 0 0 1 | 1 1 UFrameFunctionStartDTC UFrameFunction = []byte{0x0B, 0x00, 0x00, 0x00} // Start Data Transfer Confirmation CF1: 0 0 0 0 1 0 | 1 1 UFrameFunctionStopDTA UFrameFunction = []byte{0x13, 0x00, 0x00, 0x00} // Stop Data Transfer Activation CF1: 0 0 0 1 0 0 | 1 1 UFrameFunctionStopDTC UFrameFunction = []byte{0x23, 0x00, 0x00, 0x00} // Stop Data Transfer Confirmation CF1: 0 0 1 0 0 0 | 1 1 UFrameFunctionTestFA UFrameFunction = []byte{0x43, 0x00, 0x00, 0x00} // Test Frame Activation CF1: 0 1 0 0 0 0 | 1 1 UFrameFunctionTestFC UFrameFunction = []byte{0x83, 0x00, 0x00, 0x00} // Test Frame Confirmation CF1: 1 0 0 0 0 0 | 1 1 )