wire

package
v0.7.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 30, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package wire provides S7 PDU encoding and parsing (headers, read/write, setup, SZL, blocks) plus S7 TSAP helpers. Live transport uses go-cotp TSDUs; this package does not own TPKT or COTP framing.

Parsing philosophy: the wire layer is strict on framing and declared lengths—buffers are validated, lengths are checked, and overruns or mismatches return errors. Semantic interpretation (e.g. best-effort field extraction, device-dependent layouts) is left to the client and model layers.

Index

Constants

View Source
const (
	ErrClassNoError  = 0x00
	ErrClassApp      = 0x81
	ErrClassObject   = 0x82
	ErrClassResource = 0x83
	ErrClassService  = 0x84
	ErrClassSupplies = 0x85
	ErrClassAccess   = 0x87
)

S7 Error classes

View Source
const (
	RetCodeSuccess       = 0xFF // Success
	RetCodeHWFault       = 0x01 // Hardware fault
	RetCodeAccessFault   = 0x03 // Illegal object access
	RetCodeAddressFault  = 0x05 // Invalid address
	RetCodeDataTypeFault = 0x06 // Data type not supported
	RetCodeDataSizeFault = 0x07 // Data size mismatch
	RetCodeBusy          = 0x09 // Object is busy
	RetCodeNotAvailable  = 0x0A // Object not available
)

Return codes for Read/Write operations

View Source
const (
	BlockTypeOB  = 0x38
	BlockTypeDB  = 0x41
	BlockTypeSDB = 0x42
	BlockTypeFC  = 0x43
	BlockTypeSFC = 0x44
	BlockTypeFB  = 0x45
	BlockTypeSFB = 0x46
)

Block type codes for S7

View Source
const (
	AreaDataRecord    = 0x01 // Data record (optional; not all targets)
	AreaSysInfo       = 0x03
	AreaSysFlags      = 0x05
	AreaS7200AN       = 0x06 // Analog in 200
	AreaS7200AO       = 0x07 // Analog out 200 (S7-200 style)
	AreaInputs        = 0x81 // I
	AreaOutputs       = 0x82 // Q
	AreaMerkers       = 0x83 // M
	AreaDB            = 0x84 // DB
	AreaDI            = 0x85 // DI (instance DB)
	AreaLocal         = 0x86
	AreaV             = 0x87
	AreaCounter       = 0x1C // C (counter)
	AreaTimer         = 0x1D // T (timer)
	AreaIECCounter200 = 30   // IEC counters (S7-200 family)
	AreaIECTimer200   = 31   // IEC timers (S7-200 family)
	AreaPeripheral    = 0x80 // P
)

S7 Area codes (classic subset). C and T are timer/counter, not generic byte/bit addresses.

View Source
const (
	SyntaxIDS7Any        = 0x10 // Supported
	SyntaxIDDBRead       = 0xB0 // Recognized, rejected
	SyntaxID1200Symbolic = 0xB2
	SyntaxIDNCK          = 0x82 // 0x82/0x83/0x84
	SyntaxIDDriveES      = 0xA2
)

Syntax IDs for variable specification. Only S7Any is supported for encoding.

View Source
const (
	TransportSizeBit   = 0x01
	TransportSizeByte  = 0x02
	TransportSizeChar  = 0x03
	TransportSizeWord  = 0x04
	TransportSizeInt   = 0x05
	TransportSizeDWord = 0x06
	TransportSizeDInt  = 0x07
	TransportSizeReal  = 0x08
)

Transport size codes for request (address specification in S7Any). Do not use in response payload length normalization; use ResponseTransportSize there.

View Source
const (
	SZLModuleID       = 0x0011 // Module identification
	SZLComponentID    = 0x001C // Component identification
	SZLCPUState       = 0x0424 // CPU state
	SZLProtectionInfo = 0x0232 // Protection level
	SZLDiagBuffer     = 0x00A0 // Diagnostic buffer
	SZLBlockList      = 0x0111 // Block list
	SZLBlockInfo      = 0x0113 // Block info
)

SZL ID constants

View Source
const (
	UserdataReq      = 0x11
	UserdataRes      = 0x12
	UserdataSubParam = 0x44 // With parameters
	UserdataSZL      = 0x01 // SZL read
)

Userdata function codes

View Source
const (
	FuncSetupComm     = 0xF0 // Setup communication
	FuncReadVar       = 0x04 // Read variable
	FuncWriteVar      = 0x05 // Write variable
	FuncDownloadStart = 0x1A
	FuncDownload      = 0x1B
	FuncDownloadEnd   = 0x1C
	FuncUploadStart   = 0x1D
	FuncUpload        = 0x1E
	FuncUploadEnd     = 0x1F
	FuncPIService     = 0x28 // Program invocation
	FuncPLCStop       = 0x29
	FuncPLCControl    = 0x28
)

S7 function codes

View Source
const DataTransportSizeBit = 0x03

DataTransportSizeBit is the BIT transport size in Read/Write Var data sections (0x03). Distinct from request S7ANY TransportSizeBit (0x01).

View Source
const ReadVarRequestOverhead = S7HeaderSize + 2 + 12

ReadVarRequestOverhead is the minimum PDU bytes for one read-var item: S7 header (10) + param (2) + S7Any (12).

View Source
const S7HeaderSize = 10
View Source
const WriteVarRequestOverhead = S7HeaderSize + 2 + 12 + 4

WriteVarRequestOverhead is the minimum PDU bytes for one write-var item: S7 header (10) + param (2) + S7Any (12) + data header (4).

Variables

View Source
var (
	ErrShortS7Header        = errors.New("data too short for S7 header")
	ErrInvalidS7ProtocolID  = errors.New("invalid S7 protocol ID")
	ErrShortS7AckHeader     = errors.New("data too short for S7 ack header")
	ErrS7PayloadLength      = errors.New("S7 payload shorter than parameter/data lengths")
	ErrTruncatedItemHeader  = errors.New("read response item header truncated")
	ErrTruncatedItemPayload = errors.New("read response item payload truncated or overrun")
	ErrInvalidParamLength   = errors.New("invalid parameter section length")
	ErrInvalidDataLength    = errors.New("invalid data section length")
)

Functions

func AreaString

func AreaString(area byte) string

AreaString returns a short display name for the area code (e.g. "I", "DB", "M"). Unknown codes return hex.

func BuildTSAP

func BuildTSAP(connType, rack, slot int) (uint16, error)

BuildTSAP creates a TSAP from connection type, rack, and slot (S7 convention). Connection type: 1=PG, 2=OP, 3=S7Basic. Rack must be 0..7, slot 0..31; returns error if out of range.

func DecodeAsBit

func DecodeAsBit(item ReadVarItem) (bool, error)

DecodeAsBit interprets a successful one-bit Read Var item as a bool. Requires return code success, data transport BIT (0x03), and a one-byte payload. Any nonzero low bit is treated as true (Snap7-compatible).

func DecodeAsByte

func DecodeAsByte(item ReadVarItem) (byte, error)

DecodeAsByte returns the first byte. For BIT/BYTE transport size.

func DecodeAsDInt

func DecodeAsDInt(item ReadVarItem) (int32, error)

DecodeAsDInt returns the first 4 bytes as big-endian int32.

func DecodeAsDWord

func DecodeAsDWord(item ReadVarItem) (uint32, error)

DecodeAsDWord returns the first 4 bytes as big-endian uint32.

func DecodeAsInt

func DecodeAsInt(item ReadVarItem) (int16, error)

DecodeAsInt returns the first 2 bytes as big-endian int16.

func DecodeAsReal

func DecodeAsReal(item ReadVarItem) (float32, error)

DecodeAsReal returns the first 4 bytes as big-endian float32.

func DecodeAsWord

func DecodeAsWord(item ReadVarItem) (uint16, error)

DecodeAsWord returns the first 2 bytes as big-endian uint16.

func EncodeBlockListRequest

func EncodeBlockListRequest(pduRef uint16, blockType byte) []byte

EncodeBlockListRequest creates a block list request (via SZL)

func EncodeEndUploadRequest

func EncodeEndUploadRequest(pduRef uint16, sessionID string) []byte

EncodeEndUploadRequest ends an upload session.

func EncodeRackSlotTSAP

func EncodeRackSlotTSAP(rack, slot byte) byte

EncodeRackSlotTSAP returns the low byte of a classic S7 TSAP for rack/slot. Protocol: bits 0..4 = slot, bits 5..7 = rack. Rack must be 0..7, slot 0..31. This is the single canonical TSAP rack/slot encoder; do not duplicate bit-packing elsewhere.

func EncodeReadVarBitRequest

func EncodeReadVarBitRequest(pduRef uint16, addr S7AnyBitAddress) []byte

EncodeReadVarBitRequest creates a Read Var request for one bit.

func EncodeReadVarRequest

func EncodeReadVarRequest(pduRef uint16, addrs []S7AnyAddress) []byte

EncodeReadVarRequest creates a read variable request

func EncodeS7Any

func EncodeS7Any(addr S7AnyAddress) []byte

EncodeS7Any encodes an S7Any address specification (syntax SyntaxIDS7Any only). Call ValidateArea(addr.Area) before encoding if area comes from untrusted input. Byte-oriented: Start is a byte offset; Size is a byte count; transport size is BYTE.

func EncodeS7AnyBit

func EncodeS7AnyBit(addr S7AnyBitAddress) []byte

EncodeS7AnyBit encodes a one-bit S7ANY address (transport BIT, element count 1). Start is ByteOffset*8+BitOffset (already in bits; not multiplied again).

func EncodeS7Header

func EncodeS7Header(rosctr ROSCTR, pduRef uint16, paramLen, dataLen int) []byte

EncodeS7Header creates an S7 protocol header

func EncodeSZLRequest

func EncodeSZLRequest(pduRef, szlID, szlIndex uint16) []byte

EncodeSZLRequest creates a SZL read request

func EncodeSetupCommRequest

func EncodeSetupCommRequest(pduRef uint16, maxAmqCalling, maxAmqCalled, pduSize int) []byte

EncodeSetupCommRequest creates a Setup Communication request with the given PDU reference.

func EncodeStartUploadRequest

func EncodeStartUploadRequest(pduRef uint16, blockType byte, blockNum int) []byte

EncodeStartUploadRequest creates a start upload request

func EncodeUploadRequest

func EncodeUploadRequest(pduRef uint16, sessionID string) []byte

EncodeUploadRequest requests next upload segment for a started upload session.

func EncodeWriteVarBitRequest

func EncodeWriteVarBitRequest(pduRef uint16, addr S7AnyBitAddress, value bool) []byte

EncodeWriteVarBitRequest creates a Write Var request for one bit using native BIT data transport. Data section: reserved 0x00, transport BIT (0x03), length 1 bit, payload 0x00/0x01.

func EncodeWriteVarRequest

func EncodeWriteVarRequest(pduRef uint16, addr S7AnyAddress, value []byte) []byte

EncodeWriteVarRequest creates a write variable request

func ErrClassString

func ErrClassString(class byte) string

ErrClassString returns a short display name for the S7 header error class only (e.g. "Access error").

func FunctionCodeString

func FunctionCodeString(code byte) string

FunctionCodeString returns a display name for the S7 parameter function code (e.g. "Read Var", "Upload").

func HeaderErrorString

func HeaderErrorString(class, code byte) string

HeaderErrorString returns a human-readable string for S7 header error class/code. Preserves raw values in S7Error; this is for display only.

func ItemReturnCodeString

func ItemReturnCodeString(code byte) string

ItemReturnCodeString returns a human-readable string for Read/Write item return code.

func NormalizeResponseDataLength

func NormalizeResponseDataLength(transportSize ResponseTransportSize, rawLength uint16) (payloadBytes int, err error)

NormalizeResponseDataLength converts the raw length field of a Read Var response item to payload byte count. Use ResponseTransportSize only; do not pass request transport size.

func ParamErrorCodeString

func ParamErrorCodeString(code uint16) string

ParamErrorCodeString returns a human-readable string for the 16-bit S7 parameter error code. Codes are from the S7 parameter section of responses (block, upload, diagnostics, etc.). Unknown codes return a formatted hex string.

func ParamErrorFromParam

func ParamErrorFromParam(param []byte) (code uint16, ok bool)

ParamErrorFromParam reads the 16-bit parameter error code at the standard offset (bytes 2-3, big-endian). Many S7 Ack-Data parameter sections carry this code when the response indicates an error. Returns (code, true) if param has at least 4 bytes; otherwise (0, false).

func ParseStartUploadResponse

func ParseStartUploadResponse(param []byte) (string, error)

ParseStartUploadResponse extracts upload session ID from upload start response parameters.

func ParseWriteVarResponse

func ParseWriteVarResponse(param, data []byte) error

ParseWriteVarResponse parses a write variable response

func ReturnCodeError

func ReturnCodeError(code byte) error

ReturnCodeError returns an error for an item return code. Preserves raw Code in S7Error (Class zero).

func SZLIDString

func SZLIDString(id uint16) string

SZLIDString returns a human-readable name for the SZL ID when known (S7 SZL catalog). Use in logging and diagnostics. Unknown IDs return a formatted hex string.

func SyntaxIDString

func SyntaxIDString(syntax byte) string

SyntaxIDString returns a display name for the variable specification syntax ID. Unknown IDs return hex.

func ValidateArea

func ValidateArea(area byte) error

ValidateArea returns nil for supported classic areas, S7Error for unsupported.

func ValidateRackSlot

func ValidateRackSlot(rack, slot int) error

ValidateRackSlot returns an error if rack or slot are outside classic S7 range (rack 0..7, slot 0..31).

func ValidateRequestSyntax

func ValidateRequestSyntax(syntax byte) error

ValidateRequestSyntax returns nil for SyntaxIDS7Any, UnsupportedSyntaxError for known-unsupported syntaxes.

Types

type BlockInfoData

type BlockInfoData struct {
	LoadMemory int
	LocalData  int
	MC7Size    int
}

BlockInfoData holds block info fields parsed from SZL 0x0113 response data. Layout is heuristic and may vary by PLC; only LoadMemory, LocalData, MC7Size are parsed confidently.

func ParseBlockInfoResponse

func ParseBlockInfoResponse(szlData []byte) (BlockInfoData, error)

ParseBlockInfoResponse parses block info from SZL 0x0113 response data (resp.Data). Permissive/partial: requires at least 6 bytes; only the first three 16-bit fields are interpreted. SZL block info layout can vary by device; treat as heuristic for interoperability.

type BlockListEntry

type BlockListEntry struct {
	BlockType   byte
	BlockNumber uint16
	Language    byte
	Flags       byte
}

BlockListEntry represents an entry in the block list response

func ParseBlockListResponse

func ParseBlockListResponse(szlData []byte) ([]BlockListEntry, error)

ParseBlockListResponse parses a block list response. Strict: szlData length must be a multiple of 4 (no trailing garbage). Each entry is 4 bytes: block number, type, language/flags.

type FrameSummary

type FrameSummary struct {
	TPDULength  int
	COTPType    byte
	ROSCTR      byte
	Function    byte
	ParamLength int
	DataLength  int
	ErrorClass  byte
	ErrorCode   byte
}

FrameSummary captures key protocol fields from one COTP TPDU that may carry an S7 PDU.

func InspectTPDU

func InspectTPDU(tpdu []byte) (*FrameSummary, error)

InspectTPDU decodes a COTP TPDU payload (no TPKT header) and extracts high-level S7 metadata when present. This is a diagnostic helper for offline captures; the live client path uses cotp.Conn TSDUs. For full TPKT captures, peel the TPKT header with go-tpkt first, then pass the TPDU payload here.

type ROSCTR

type ROSCTR byte

ROSCTR is the S7 message type (Remote Operating Service Control).

const (
	ROSCTRJob      ROSCTR = 0x01 // Job request
	ROSCTRAck      ROSCTR = 0x02 // Acknowledgement without data
	ROSCTRAckData  ROSCTR = 0x03 // Acknowledgement with data
	ROSCTRUserdata ROSCTR = 0x07 // Userdata (for SZL, etc.)
)

S7 ROSCTR constants. ACK and ACK_DATA are distinct: ACK has no payload, ACK_DATA carries param+data.

func (ROSCTR) IsAck

func (r ROSCTR) IsAck() bool

IsAck returns true for ROSCTRAck (ack without data).

func (ROSCTR) IsAckData

func (r ROSCTR) IsAckData() bool

IsAckData returns true for ROSCTRAckData (ack with param/data payload).

func (ROSCTR) IsJob

func (r ROSCTR) IsJob() bool

IsJob returns true for ROSCTRJob.

func (ROSCTR) IsUserdata

func (r ROSCTR) IsUserdata() bool

IsUserdata returns true for ROSCTRUserdata.

type ReadVarItem

type ReadVarItem struct {
	ReturnCode       byte   // Item return code
	RawTransportSize byte   // Transport size from wire
	RawLength        uint16 // Length from wire (bits or bytes per transport size)
	Data             []byte // Normalized payload bytes (only when ReturnCode == RetCodeSuccess)
}

ReadVarItem represents a single read result. Raw fields are preserved; Data is normalized payload (success only).

func ParseReadVarResponse

func ParseReadVarResponse(param, data []byte) ([]ReadVarItem, error)

ParseReadVarResponse parses a read variable response. Strict: requires exactly itemCount items; fails on truncated item headers, length overrun, unknown transport size, or count mismatch.

type ResponseTransportSize

type ResponseTransportSize byte

ResponseTransportSize is the data transport size in a Read Var response item. Distinct type to prevent using request transport size in response length normalization.

const (
	RespTransportSizeBit       ResponseTransportSize = 0x01
	RespTransportSizeByte      ResponseTransportSize = 0x02
	RespTransportSizeChar      ResponseTransportSize = 0x03
	RespTransportSizeWord      ResponseTransportSize = 0x04
	RespTransportSizeInt       ResponseTransportSize = 0x05
	RespTransportSizeDWord     ResponseTransportSize = 0x06
	RespTransportSizeDInt      ResponseTransportSize = 0x07
	RespTransportSizeReal      ResponseTransportSize = 0x08
	RespTransportSizeDATE      ResponseTransportSize = 0x09 // 2 bytes
	RespTransportSizeTOD       ResponseTransportSize = 0x0A // 4 bytes (time of day)
	RespTransportSizeTIME      ResponseTransportSize = 0x0B // 4 bytes
	RespTransportSizeS5TIME    ResponseTransportSize = 0x0C // 2 bytes
	RespTransportSizeDT        ResponseTransportSize = 0x0F // 8 bytes (date and time)
	RespTransportSizeCount     ResponseTransportSize = 0x1C // COUNTER (2 bytes)
	RespTransportSizeTimer     ResponseTransportSize = 0x1D // TIMER (2 bytes)
	RespTransportSizeIECCount  ResponseTransportSize = 30   // IEC counter (S7-200)
	RespTransportSizeIECTimer  ResponseTransportSize = 31   // IEC timer (S7-200)
	RespTransportSizeHSCounter ResponseTransportSize = 32   // High-speed counter
)

func (ResponseTransportSize) String

func (r ResponseTransportSize) String() string

String returns the transport size name for logging/diagnostics (e.g. "BYTE", "DATE", "COUNTER").

type S7AnyAddress

type S7AnyAddress struct {
	Area     byte
	DBNumber int
	Start    int // Byte offset
	Size     int // Number of bytes
}

S7AnyAddress is a specification of an S7 variable address

type S7AnyBitAddress

type S7AnyBitAddress struct {
	Area       byte
	DBNumber   int
	ByteOffset int
	BitOffset  int
}

S7AnyBitAddress is a single-bit S7ANY address. BitOffset must be 0..7 (caller validated).

type S7Error

type S7Error struct {
	Class   byte
	Code    byte
	Message string
}

S7Error represents an S7 protocol error

func NewS7Error

func NewS7Error(class, code byte) *S7Error

NewS7Error creates a new S7 error preserving raw Class and Code, with a string mapping when known. Header-level errors use Class and Code; item-level return codes use Code only (Class zero).

func NewS7ErrorWithParam

func NewS7ErrorWithParam(class, code byte, param []byte) *S7Error

NewS7ErrorWithParam is like NewS7Error but when param contains a 16-bit parameter error code at the standard offset (bytes 2-3), uses ParamErrorCodeString for the message when that code is non-zero. This yields clearer errors (e.g. "block not found", "invalid request length") for block/upload/diagnostic responses.

func (*S7Error) Error

func (e *S7Error) Error() string

type S7Header

type S7Header struct {
	ProtocolID   byte   // Always 0x32
	ROSCTR       ROSCTR // Message type (Job, Ack, AckData, Userdata)
	RedundancyID uint16
	PDURef       uint16 // PDU reference for request/response correlation
	ParamLength  uint16 // Declared parameter section length
	DataLength   uint16 // Declared data section length
	ErrorClass   byte   // Error class (for Ack/AckData)
	ErrorCode    byte   // Error code (for Ack/AckData)
}

S7Header represents an S7 protocol header. All fields are raw wire values.

func ParseS7Header

func ParseS7Header(data []byte) (*S7Header, []byte, error)

ParseS7Header parses an S7 header from data

type SZLResponse

type SZLResponse struct {
	SZLID      uint16
	SZLIndex   uint16
	DataLength uint16
	Data       []byte
}

SZLResponse holds a parsed SZL response

func ParseSZLResponse

func ParseSZLResponse(data []byte) (*SZLResponse, error)

ParseSZLResponse parses a SZL read response from the S7 data payload. Strict: validates return code, data length, and minimum 8-byte header.

type SetupCommResponse

type SetupCommResponse struct {
	MaxAmqCalling int
	MaxAmqCalled  int
	PDUSize       int
}

SetupCommResponse holds the response from Setup Communication

func ParseSetupCommResponse

func ParseSetupCommResponse(data []byte) (*SetupCommResponse, error)

ParseSetupCommResponse parses a Setup Communication response

type UnsupportedSyntaxError

type UnsupportedSyntaxError struct {
	RawSyntaxID byte
}

UnsupportedSyntaxError indicates a request syntax ID that is recognized but not supported.

func (*UnsupportedSyntaxError) Error

func (e *UnsupportedSyntaxError) Error() string

type UploadChunk

type UploadChunk struct {
	Done bool
	Data []byte
}

UploadChunk is one chunk returned by upload continuation responses.

func ParseUploadResponse

func ParseUploadResponse(param, data []byte) (*UploadChunk, error)

ParseUploadResponse parses upload continuation response and chunk payload. Strict: declared length must not overrun the data buffer; overrun returns an error.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL