codec

package
v1.0.1 Latest Latest
Warning

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

Go to latest
Published: Mar 16, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Index

Constants

View Source
const (
	HoldingRegister = protocol.HoldingRegister
	InputRegister   = protocol.InputRegister
)
View Source
const (
	BigEndian    = adu.BigEndian
	LittleEndian = adu.LittleEndian
)

Variables

View Source
var (
	ErrCodecRegisterCount = errors.New("modbus: codec register count mismatch")
	ErrCodecLayout        = errors.New("modbus: invalid codec layout")
	ErrCodecValue         = errors.New("modbus: invalid codec value")
	ErrCodecByteCount     = errors.New("modbus: codec byte count mismatch")
	ErrUnknownCodec       = errors.New("modbus: unknown codec")
	ErrEncodingError      = errors.New("modbus: encoding error")
)
View Source
var (
	Layout16_21 = MustNewRegisterLayout(1, 2, 1)
	Layout16_12 = MustNewRegisterLayout(1, 1, 2)
)
View Source
var (
	Layout32_4321 = MustNewRegisterLayout(2, 4, 3, 2, 1)
	Layout32_3412 = MustNewRegisterLayout(2, 3, 4, 1, 2)
	Layout32_2143 = MustNewRegisterLayout(2, 2, 1, 4, 3)
	Layout32_1234 = MustNewRegisterLayout(2, 1, 2, 3, 4)
)
View Source
var (
	Layout48_654321 = MustNewRegisterLayout(3, 6, 5, 4, 3, 2, 1)
	Layout48_563412 = MustNewRegisterLayout(3, 5, 6, 3, 4, 1, 2)
	Layout48_214365 = MustNewRegisterLayout(3, 2, 1, 4, 3, 6, 5)
	Layout48_123456 = MustNewRegisterLayout(3, 1, 2, 3, 4, 5, 6)
)
View Source
var (
	Layout64_87654321 = MustNewRegisterLayout(4, 8, 7, 6, 5, 4, 3, 2, 1)
	Layout64_78563412 = MustNewRegisterLayout(4, 7, 8, 5, 6, 3, 4, 1, 2)
	Layout64_21436587 = MustNewRegisterLayout(4, 2, 1, 4, 3, 6, 5, 8, 7)
	Layout64_12345678 = MustNewRegisterLayout(4, 1, 2, 3, 4, 5, 6, 7, 8)
)
View Source
var ErrInvalidLayout = errors.New("modbus: invalid register layout")

ErrInvalidLayout is returned when layout parameters are invalid (wrong length, duplicate or out-of-range positions).

Functions

func DecodeRegisters

func DecodeRegisters[T any](regs []uint16, codec Decoder[T]) (T, error)

DecodeRegisters decodes raw registers using the given codec. It validates register count against the codec's RegisterSpec before calling the codec.

func DecodeRegistersAny

func DecodeRegistersAny(regs []uint16, codec RuntimeDecoder) (any, error)

DecodeRegistersAny decodes raw registers using the given runtime decoder. It validates register count against the codec's RegisterSpec before calling the codec.

func DecodeWithDescriptor

func DecodeWithDescriptor(regs []uint16, desc CodecDescriptor) (any, error)

DecodeWithDescriptor builds a runtime codec from the descriptor and decodes the registers. Offline only (no client needed). Returns an error if the descriptor is unknown or if decode fails.

func EncodeRegisters

func EncodeRegisters[T any](value T, codec Encoder[T]) ([]uint16, error)

EncodeRegisters encodes a value to raw registers using the given codec, then validates the result against the codec's RegisterSpec.

func EncodeRegistersAny

func EncodeRegistersAny(value any, codec RuntimeEncoder) ([]uint16, error)

EncodeRegistersAny encodes a value to raw registers using the given runtime encoder. Wrong dynamic type returns *CodecValueError (never panics).

func EncodeWithDescriptor

func EncodeWithDescriptor(value any, desc CodecDescriptor) ([]uint16, error)

EncodeWithDescriptor builds a runtime codec from the descriptor and encodes the value to registers. Offline only (no client needed). Returns an error if the descriptor is unknown, if the value type does not match the codec, or if encode fails.

func PermuteBytesDecode

func PermuteBytesDecode(raw []byte, layout RegisterLayout) ([]byte, error)

PermuteBytesDecode converts raw register bytes (wire order) into canonical big-endian byte order using the layout permutation. Positions are 1-based: position 1 = LSB, position byteCount = MSB. len(raw) must equal layout.RegisterCount()*2.

func PermuteBytesEncode

func PermuteBytesEncode(canonical []byte, layout RegisterLayout) ([]byte, error)

PermuteBytesEncode converts canonical big-endian bytes into raw register bytes (wire order) using the layout permutation. len(canonical) must equal layout.RegisterCount()*2.

func ReadFromClient

func ReadFromClient[T any](
	r RegisterReader,
	ctx context.Context,
	unitID uint8,
	addr uint16,
	regType RegType,
	dec Decoder[T],
) (T, error)

ReadFromClient reads registers at the given address and decodes them using the supplied typed codec. The number of registers read is dec.RegisterSpec().Count. Register data is read in wire order (big-endian per register); the codec applies any layout or interpretation.

func ReadRuntimeFromClient

func ReadRuntimeFromClient(
	r RegisterReader,
	ctx context.Context,
	unitID uint8,
	addr uint16,
	regType RegType,
	dec RuntimeDecoder,
) (any, error)

ReadRuntimeFromClient reads registers and decodes them using a runtime decoder.

func ReadUint32FromClient

func ReadUint32FromClient(r RegisterReader, ctx context.Context, unitID uint8, addr uint16, regType RegType, layout RegisterLayout) (uint32, error)

ReadUint32FromClient reads two registers at addr and decodes them as uint32 using the given layout. Convenience wrapper around NewUint32Codec + ReadFromClient.

func ValidateByteSpec

func ValidateByteSpec(spec ByteSpec, b []byte, codecID string) error

ValidateByteSpec returns an error if the number of bytes in b does not match spec.Count. codecID is used in the error for diagnostics (e.g. codec.ID()); if empty, "codec" is used. Used for offline tooling and test helpers when working with byte-oriented views of codec data; transport remains register-native.

func ValidateRegisterSpec

func ValidateRegisterSpec(spec RegisterSpec, regs []uint16, codecID string) error

ValidateRegisterSpec returns an error if the number of registers in regs does not match spec.Count. codecID is used in the error for diagnostics (e.g. codec.ID()); if empty, "codec" is used. Use this before calling DecodeRegisters or after EncodeRegisters to enforce the codec contract.

func WriteRuntimeToClient

func WriteRuntimeToClient(
	w RegisterWriter,
	ctx context.Context,
	unitID uint8,
	addr uint16,
	value any,
	enc RuntimeEncoder,
) error

WriteRuntimeToClient encodes a value with the runtime encoder and writes the resulting registers. Wrong value type returns *CodecValueError.

func WriteToClient

func WriteToClient[T any](
	w RegisterWriter,
	ctx context.Context,
	unitID uint8,
	addr uint16,
	value T,
	enc Encoder[T],
) error

WriteToClient encodes value with the codec and writes the resulting registers at the given address. Register data is written in wire order (big-endian per register).

func WriteUint32ToClient

func WriteUint32ToClient(w RegisterWriter, ctx context.Context, unitID uint8, addr uint16, v uint32, layout RegisterLayout) error

WriteUint32ToClient encodes v as two registers using the given layout and writes them at addr. Convenience wrapper around NewUint32Codec + WriteToClient.

Types

type ByteSpec

type ByteSpec struct {
	Count uint16
}

ByteSpec declares the fixed byte count for a codec. Used for discovery and validation; transport remains register-native.

type Codec

type Codec[T any] interface {
	Decoder[T]
	Encoder[T]
}

Codec is a combined decoder and encoder for type T. Transport uses Codec for ReadWithCodec / WriteWithCodec; internally Decoder and Encoder allow read-only or write-only use later if needed.

func MustNewFloat32Codec

func MustNewFloat32Codec(layout RegisterLayout) Codec[float32]

func MustNewFloat64Codec

func MustNewFloat64Codec(layout RegisterLayout) Codec[float64]

func MustNewInt16Codec

func MustNewInt16Codec(layout RegisterLayout) Codec[int16]

func MustNewInt32Codec

func MustNewInt32Codec(layout RegisterLayout) Codec[int32]

func MustNewInt32M10kCodec

func MustNewInt32M10kCodec(order DecimalLimbOrder) Codec[int32]

MustNewInt32M10kCodec is like NewInt32M10kCodec but panics on error.

func MustNewInt48Codec

func MustNewInt48Codec(layout RegisterLayout) Codec[int64]

func MustNewInt48M10kCodec

func MustNewInt48M10kCodec(order DecimalLimbOrder) Codec[int64]

MustNewInt48M10kCodec is like NewInt48M10kCodec but panics on error.

func MustNewInt64Codec

func MustNewInt64Codec(layout RegisterLayout) Codec[int64]

func MustNewInt64M10kCodec

func MustNewInt64M10kCodec(order DecimalLimbOrder) Codec[int64]

MustNewInt64M10kCodec is like NewInt64M10kCodec but panics on error.

func MustNewUint16Codec

func MustNewUint16Codec(layout RegisterLayout) Codec[uint16]

MustNewUint16Codec is like NewUint16Codec but panics on error.

func MustNewUint32Codec

func MustNewUint32Codec(layout RegisterLayout) Codec[uint32]

func MustNewUint32M10kCodec

func MustNewUint32M10kCodec(order DecimalLimbOrder) Codec[uint32]

MustNewUint32M10kCodec is like NewUint32M10kCodec but panics on error.

func MustNewUint48Codec

func MustNewUint48Codec(layout RegisterLayout) Codec[uint64]

func MustNewUint48M10kCodec

func MustNewUint48M10kCodec(order DecimalLimbOrder) Codec[uint64]

MustNewUint48M10kCodec is like NewUint48M10kCodec but panics on error.

func MustNewUint64Codec

func MustNewUint64Codec(layout RegisterLayout) Codec[uint64]

func MustNewUint64M10kCodec

func MustNewUint64M10kCodec(order DecimalLimbOrder) Codec[uint64]

MustNewUint64M10kCodec is like NewUint64M10kCodec but panics on error.

func NewAsciiCodec

func NewAsciiCodec(registerCount uint16) (Codec[string], error)

NewAsciiCodec returns a codec for ASCII text: high byte first per register, decode trims trailing spaces, encode right-pads with space. registerCount must be >= 1.

func NewAsciiFixedCodec

func NewAsciiFixedCodec(registerCount uint16) (Codec[string], error)

NewAsciiFixedCodec returns a codec for fixed-width ASCII: no trim on decode, encode right-pads with NUL. registerCount must be >= 1.

func NewAsciiReverseCodec

func NewAsciiReverseCodec(registerCount uint16) (Codec[string], error)

NewAsciiReverseCodec returns a codec for ASCII with low byte first per register; decode trims trailing spaces. registerCount must be >= 1.

func NewBCDCodec

func NewBCDCodec(registerCount uint16) (Codec[string], error)

NewBCDCodec returns a codec for one-byte-per-digit BCD (0-9). Encode pads with leading zeros; non-digit input is rejected. registerCount must be >= 1.

func NewBytesCodec

func NewBytesCodec(byteCount uint16) (Codec[[]byte], error)

NewBytesCodec returns a codec for raw bytes in wire order. byteCount must be even (transport is register-based). Rejects 0 and odd byteCount.

func NewDateTime2S2000Codec

func NewDateTime2S2000Codec() Codec[time.Time]

NewDateTime2S2000Codec returns a codec for 2-register seconds-since-2000 (uint32). Uses layout 4321.

func NewDateTime3S2000Codec

func NewDateTime3S2000Codec() Codec[time.Time]

NewDateTime3S2000Codec returns a codec for 3-register seconds-since-2000 (48-bit). Uses layout 654321.

func NewDateTimeIEC870Codec

func NewDateTimeIEC870Codec() Codec[time.Time]

NewDateTimeIEC870Codec returns a codec for 4-register IEC 60870-5 CP56Time2a: timezone-unspecified wire value interpreted by library in UTC.

func NewDateTimeIEC870LocalCodec

func NewDateTimeIEC870LocalCodec() Codec[time.Time]

NewDateTimeIEC870LocalCodec returns a codec for 4-register IEC 60870-5 CP56Time2a interpreted as local time.

func NewDateTimeIEC870UTCCodec

func NewDateTimeIEC870UTCCodec() Codec[time.Time]

NewDateTimeIEC870UTCCodec returns a codec for 4-register IEC 60870-5 CP56Time2a interpreted as UTC.

func NewDateTimeYMDhmsCodec

func NewDateTimeYMDhmsCodec() Codec[time.Time]

NewDateTimeYMDhmsCodec returns a codec for 6-register YMDhms: naive Y/M/D/h/m/s tuple; library interprets it in UTC by default.

func NewDateTimeYMDhmsLocalCodec

func NewDateTimeYMDhmsLocalCodec() Codec[time.Time]

NewDateTimeYMDhmsLocalCodec returns a codec for 6-register YMDhms interpreted as local time.

func NewDateTimeYMDhmsUTCCodec

func NewDateTimeYMDhmsUTCCodec() Codec[time.Time]

NewDateTimeYMDhmsUTCCodec returns a codec for 6-register YMDhms interpreted as UTC.

func NewEUI48Codec

func NewEUI48Codec() Codec[net.HardwareAddr]

NewEUI48Codec returns a codec for EUI-48/MAC (6 bytes, 3 registers) in raw wire order.

func NewEUI64Codec

func NewEUI64Codec() Codec[net.HardwareAddr]

NewEUI64Codec returns a codec for EUI-64 (8 bytes, 4 registers) in raw wire order.

func NewFloat32Codec

func NewFloat32Codec(layout RegisterLayout) (Codec[float32], error)

NewFloat32Codec returns a codec for two registers. Layout must have RegisterCount() == 2.

func NewFloat64Codec

func NewFloat64Codec(layout RegisterLayout) (Codec[float64], error)

NewFloat64Codec returns a codec for four registers. Layout must have RegisterCount() == 4.

func NewIPAddrCodec

func NewIPAddrCodec() Codec[net.IP]

NewIPAddrCodec returns a codec for IPv4 (4 bytes, 2 registers) in raw wire order.

func NewIPv6AddrCodec

func NewIPv6AddrCodec() Codec[net.IP]

NewIPv6AddrCodec returns a codec for IPv6 (16 bytes, 8 registers) in raw wire order.

func NewInt16Codec

func NewInt16Codec(layout RegisterLayout) (Codec[int16], error)

NewInt16Codec returns a codec for one register. Layout must have RegisterCount() == 1.

func NewInt16SignMagnitudeCodec

func NewInt16SignMagnitudeCodec() Codec[int16]

NewInt16SignMagnitudeCodec returns a codec for one register as sign-magnitude: bit 15 = sign (1 = negative), bits 0–14 = magnitude. Not two's complement.

func NewInt32Codec

func NewInt32Codec(layout RegisterLayout) (Codec[int32], error)

NewInt32Codec returns a codec for two registers. Layout must have RegisterCount() == 2.

func NewInt32M10kCodec

func NewInt32M10kCodec(order DecimalLimbOrder) (Codec[int32], error)

NewInt32M10kCodec returns a signed 32-bit decimal-limb (M10k) codec. Only the most-significant limb is signed (-9999..9999); other limbs are 0..9999.

func NewInt48Codec

func NewInt48Codec(layout RegisterLayout) (Codec[int64], error)

NewInt48Codec returns a codec for three registers (48-bit as int64). Layout must have RegisterCount() == 3.

func NewInt48M10kCodec

func NewInt48M10kCodec(order DecimalLimbOrder) (Codec[int64], error)

NewInt48M10kCodec returns a signed 48-bit decimal-limb (M10k) codec; Go type int64. Only the MS limb is signed.

func NewInt64Codec

func NewInt64Codec(layout RegisterLayout) (Codec[int64], error)

NewInt64Codec returns a codec for four registers. Layout must have RegisterCount() == 4.

func NewInt64M10kCodec

func NewInt64M10kCodec(order DecimalLimbOrder) (Codec[int64], error)

NewInt64M10kCodec returns a signed 64-bit decimal-limb (M10k) codec. Only the MS limb is signed.

func NewPackedBCDCodec

func NewPackedBCDCodec(registerCount uint16) (Codec[string], error)

NewPackedBCDCodec returns a codec for packed BCD (two digits per byte). Encode pads with leading zeros; non-digit input is rejected. registerCount must be >= 1.

func NewPackedBCDReverseCodec

func NewPackedBCDReverseCodec(registerCount uint16) (Codec[string], error)

NewPackedBCDReverseCodec returns a codec for packed BCD with low byte first per register (byte-swap within each word on wire). registerCount must be >= 1.

func NewSignedPackedBCDCodec

func NewSignedPackedBCDCodec(registerCount uint16) (Codec[string], error)

NewSignedPackedBCDCodec returns a codec for signed packed BCD: trailing nibble 0xC/0xD/0xF = negative, 0x0-0x9 = positive. Decode returns e.g. "-1234" or "1234"; encode accepts optional leading "-". registerCount must be >= 1.

func NewUTF16BECodec

func NewUTF16BECodec(registerCount uint16) (Codec[string], error)

NewUTF16BECodec returns a codec for fixed-width UTF-16 big-endian (one code unit per register, high byte first). registerCount must be >= 1.

func NewUTF16LECodec

func NewUTF16LECodec(registerCount uint16) (Codec[string], error)

NewUTF16LECodec returns a codec for fixed-width UTF-16 little-endian (one code unit per register, low byte first on wire). registerCount must be >= 1.

func NewUint8SliceCodec

func NewUint8SliceCodec(byteCount uint16) (Codec[[]uint8], error)

NewUint8SliceCodec returns a codec for []uint8 in wire order. byteCount must be even. Rejects 0 and odd byteCount.

func NewUint16Codec

func NewUint16Codec(layout RegisterLayout) (Codec[uint16], error)

NewUint16Codec returns a codec for one register. Layout must have RegisterCount() == 1.

func NewUint32Codec

func NewUint32Codec(layout RegisterLayout) (Codec[uint32], error)

NewUint32Codec returns a codec for two registers. Layout must have RegisterCount() == 2.

func NewUint32M10kCodec

func NewUint32M10kCodec(order DecimalLimbOrder) (Codec[uint32], error)

NewUint32M10kCodec returns a 32-bit decimal-limb (M10k) codec. Order controls whether the first register is the least- or most-significant limb.

func NewUint48Codec

func NewUint48Codec(layout RegisterLayout) (Codec[uint64], error)

NewUint48Codec returns a codec for three registers (48-bit as uint64). Layout must have RegisterCount() == 3.

func NewUint48M10kCodec

func NewUint48M10kCodec(order DecimalLimbOrder) (Codec[uint64], error)

NewUint48M10kCodec returns a 48-bit decimal-limb (M10k) codec; Go type uint64.

func NewUint64Codec

func NewUint64Codec(layout RegisterLayout) (Codec[uint64], error)

NewUint64Codec returns a codec for four registers. Layout must have RegisterCount() == 4.

func NewUint64M10kCodec

func NewUint64M10kCodec(order DecimalLimbOrder) (Codec[uint64], error)

NewUint64M10kCodec returns a 64-bit decimal-limb (M10k) codec.

type CodecByteCountError

type CodecByteCountError struct {
	Codec    string
	Expected ByteSpec
	Actual   uint16
}

CodecByteCountError is returned when the number of bytes does not match the codec contract. Used by ValidateByteSpec for offline/byte-oriented tooling.

func (*CodecByteCountError) Error

func (e *CodecByteCountError) Error() string

func (*CodecByteCountError) Unwrap

func (e *CodecByteCountError) Unwrap() error

type CodecCandidate

type CodecCandidate struct {
	CodecID    string
	LayoutName string
}

CodecCandidate is a lightweight concrete selectable option for discovery/CLI. CodecID must equal the CodecDescriptor.ID of the option it refers to (same namespace). LayoutName is empty for layout-less codecs. Candidates mirror the registered descriptors rather than expanding from a separate family list.

func CodecCandidatesForByteCount

func CodecCandidatesForByteCount(count uint16) []CodecCandidate

CodecCandidatesForByteCount returns one candidate per descriptor whose ByteSpec.Count equals count.

func CodecCandidatesForRegisterCount

func CodecCandidatesForRegisterCount(count uint16) []CodecCandidate

CodecCandidatesForRegisterCount returns one candidate per descriptor whose RegisterSpec.Count equals count. CodecID is the descriptor's ID; LayoutName is the layout name when the descriptor has exactly one layout, otherwise empty.

type CodecDescriptor

type CodecDescriptor struct {
	ID           string
	Name         string
	Family       CodecFamily
	ValueKind    CodecValueKind
	RegisterSpec RegisterSpec
	ByteSpec     ByteSpec
	Layouts      []RegisterLayoutDescriptor // nil for layout-less codecs
}

CodecDescriptor is metadata for a codec option. Descriptors are derived from the registration table (see codec_registration.go), not hand-authored. Layouts is nil for layout-less codecs (ASCII, BCD, IP, EUI48, etc.).

In the current implementation each concrete option (e.g. a specific layout or width) is registered as its own descriptor; CodecCandidate then provides a lightweight view (CodecID + LayoutName) for discovery/CLI without duplicating full descriptor data.

func AvailableCodecDescriptors

func AvailableCodecDescriptors() []CodecDescriptor

AvailableCodecDescriptors returns a copy of all registered codec descriptors sorted by ID for deterministic discovery output. Layouts are deep-copied so returned descriptors are immutable to the caller.

func CodecDescriptorByID

func CodecDescriptorByID(id string) (CodecDescriptor, bool)

CodecDescriptorByID returns the descriptor with the given ID, if registered. The returned descriptor is a deep copy.

func CodecDescriptorsForByteCount

func CodecDescriptorsForByteCount(count uint16) []CodecDescriptor

CodecDescriptorsForByteCount returns descriptors whose ByteSpec.Count equals count. Returned descriptors are deep-copied.

func CodecDescriptorsForRegisterCount

func CodecDescriptorsForRegisterCount(count uint16) []CodecDescriptor

CodecDescriptorsForRegisterCount returns descriptors whose RegisterSpec.Count equals count. Returned descriptors are deep-copied.

func FindCodecDescriptors

func FindCodecDescriptors(q CodecQuery) []CodecDescriptor

FindCodecDescriptors returns descriptors matching the query. Zero values in CodecQuery mean "no filter" for that field. Returned descriptors are deep-copied.

type CodecFamily

type CodecFamily uint8

CodecFamily classifies a codec for discovery and CLI grouping.

const (
	CodecFamilyUnknown CodecFamily = iota
	CodecFamilyInteger
	CodecFamilyFloat
	CodecFamilyText
	CodecFamilyBCD
	CodecFamilyBytes
	CodecFamilyNetwork
	CodecFamilyHardwareAddress
	CodecFamilyDecimalLimb
	CodecFamilyTime
	CodecFamilyVendorSpecific
)

func (CodecFamily) String

func (f CodecFamily) String() string

type CodecLayoutError

type CodecLayoutError struct {
	Codec  string
	Layout RegisterLayout
	Reason string
}

CodecLayoutError is returned when a layout is invalid for the codec.

func (*CodecLayoutError) Error

func (e *CodecLayoutError) Error() string

func (*CodecLayoutError) Unwrap

func (e *CodecLayoutError) Unwrap() error

type CodecQuery

type CodecQuery struct {
	RegisterCount uint16
	ByteCount     uint16
	Family        CodecFamily
	ValueKind     CodecValueKind
}

CodecQuery filters descriptors by register count, byte count, family, and value kind. Zero values mean "no filter" for that field.

type CodecRegisterCountError

type CodecRegisterCountError struct {
	Codec    string
	Expected RegisterSpec
	Actual   uint16
}

CodecRegisterCountError is returned when the number of registers does not match the codec contract.

func (*CodecRegisterCountError) Error

func (e *CodecRegisterCountError) Error() string

func (*CodecRegisterCountError) Unwrap

func (e *CodecRegisterCountError) Unwrap() error

type CodecValueError

type CodecValueError struct {
	Codec  string
	Reason string
}

CodecValueError is returned when a value is invalid for encode or decode.

func (*CodecValueError) Error

func (e *CodecValueError) Error() string

func (*CodecValueError) Unwrap

func (e *CodecValueError) Unwrap() error

type CodecValueKind

type CodecValueKind uint8

CodecValueKind is the type of value a codec produces or consumes.

const (
	CodecValueUnknown CodecValueKind = iota
	CodecValueUint16
	CodecValueInt16
	CodecValueUint32
	CodecValueInt32
	CodecValueUint48
	CodecValueInt48
	CodecValueUint64
	CodecValueInt64
	CodecValueFloat32
	CodecValueFloat64
	CodecValueString
	CodecValueByteSlice
	CodecValueUint8Slice
	CodecValueIP
	CodecValueHardwareAddr
	CodecValueTime
)

func (CodecValueKind) String

func (k CodecValueKind) String() string

type DecimalLimbOrder

type DecimalLimbOrder uint8

DecimalLimbOrder controls how base-10000 limbs are ordered across registers. Used by M10k (modulo-10000) codecs; distinct from byte-order RegisterLayout.

const (
	// DecimalLimbLowToHigh: first register is least-significant limb.
	// Schneider equivalents: 2143, 21-65, 21-87.
	DecimalLimbLowToHigh DecimalLimbOrder = iota + 1
	// DecimalLimbHighToLow: first register is most-significant limb.
	// Schneider equivalents: 4321, 65-21, 87-21.
	DecimalLimbHighToLow
)

func (DecimalLimbOrder) String

func (o DecimalLimbOrder) String() string

type Decoder

type Decoder[T any] interface {
	ID() string
	Name() string
	RegisterSpec() RegisterSpec
	ByteSpec() ByteSpec
	DecodeRegisters(regs []uint16) (T, error)
}

Decoder decodes raw registers into a typed value.

type Encoder

type Encoder[T any] interface {
	ID() string
	Name() string
	RegisterSpec() RegisterSpec
	ByteSpec() ByteSpec
	EncodeRegisters(value T) ([]uint16, error)
}

Encoder encodes a typed value into raw registers.

type Endianness

type Endianness = adu.Endianness

type RegType

type RegType = protocol.RegType

RegType selects holding vs input registers for read operations. This is an alias for protocol.RegType, identical to modbus.RegType.

type RegisterLayout

type RegisterLayout struct {
	// contains filtered or unexported fields
}

RegisterLayout describes how the bytes of a multi-register value are permuted across Modbus registers. Positions are 1-based: 1 is the least-significant byte, and the highest position (e.g. 8 for 64-bit) is the most-significant byte. Layout is immutable; use NewRegisterLayout or MustNewRegisterLayout to construct.

func MustNewRegisterLayout

func MustNewRegisterLayout(registerCount uint16, positions ...uint8) RegisterLayout

MustNewRegisterLayout is like NewRegisterLayout but panics on error. Use for known-good layouts (e.g. package-level vars).

func NewRegisterLayout

func NewRegisterLayout(registerCount uint16, positions ...uint8) (RegisterLayout, error)

NewRegisterLayout builds a RegisterLayout from a register count and byte positions. Positions are 1-based (1 = least-significant byte). Each position 1..(registerCount*2) must appear exactly once. registerCount must be 1..4.

func (RegisterLayout) BytePositions

func (l RegisterLayout) BytePositions() []uint8

BytePositions returns a copy of the byte position permutation. Callers must not mutate the result. Length equals RegisterCount()*2.

func (RegisterLayout) RegisterCount

func (l RegisterLayout) RegisterCount() uint16

RegisterCount returns the number of 16-bit Modbus registers (1..4).

func (RegisterLayout) String

func (l RegisterLayout) String() string

String returns the layout as a compact digit string for IDs and discovery, e.g. "21", "4321", "87654321", "21436587".

type RegisterLayoutDescriptor

type RegisterLayoutDescriptor struct {
	Name   string
	Common bool
	Layout RegisterLayout
}

RegisterLayoutDescriptor describes a layout variant for discovery (e.g. "4321", "2143").

type RegisterReader

type RegisterReader interface {
	ReadRegisters(ctx context.Context, unitID uint8, addr uint16, quantity uint16, regType RegType) ([]uint16, error)
}

RegisterReader can read Modbus registers. *modbus.Client satisfies this.

type RegisterSpec

type RegisterSpec struct {
	Count uint16
}

RegisterSpec declares the fixed register count for a codec. v1 uses only fixed width; variable-width forms are a future extension.

type RegisterWriter

type RegisterWriter interface {
	WriteRegisters(ctx context.Context, unitID uint8, addr uint16, values []uint16) error
}

RegisterWriter can write Modbus registers. *modbus.Client satisfies this.

type RuntimeCodec

type RuntimeCodec interface {
	RuntimeDecoder
	RuntimeEncoder
}

RuntimeCodec is a combined runtime decoder and encoder.

func AsRuntimeCodec

func AsRuntimeCodec[T any](c Codec[T], kind CodecValueKind) RuntimeCodec

AsRuntimeCodec wraps a typed Codec[T] as a RuntimeCodec. Wrong type passed to EncodeRegistersAny returns *CodecValueError and never panics.

func FindRuntimeCodecs

func FindRuntimeCodecs(q CodecQuery) ([]RuntimeCodec, error)

FindRuntimeCodecs returns runtime codecs for all descriptors matching the query. Zero values in CodecQuery mean "no filter" for that field.

func MustRuntimeCodecByID

func MustRuntimeCodecByID(id string) RuntimeCodec

MustRuntimeCodecByID is like RuntimeCodecByID but panics if the ID is unknown or if construction fails. Use for known-good IDs (e.g. from config or tests).

func RuntimeCodecByID

func RuntimeCodecByID(id string) (RuntimeCodec, bool, error)

RuntimeCodecByID looks up a registered codec by ID and returns a RuntimeCodec. Returns (nil, false, nil) when the ID is not registered. Returns (nil, false, err) when the codec is registered but construction fails.

func RuntimeCodecFromDescriptor

func RuntimeCodecFromDescriptor(desc CodecDescriptor) (RuntimeCodec, error)

RuntimeCodecFromDescriptor builds a RuntimeCodec from a concrete codec descriptor. The descriptor must represent a fully concrete codec (e.g. "uint32/layout:4321", "ascii/registers:4", "ip_addr"). Unknown or abstract descriptors return an error. Descriptor metadata is used only to identify the codec; the actual layout/count comes from the descriptor's Layouts, RegisterSpec, or ByteSpec.

func RuntimeCodecsForByteCount

func RuntimeCodecsForByteCount(count uint16) ([]RuntimeCodec, error)

RuntimeCodecsForByteCount returns runtime codecs for all registered descriptors whose ByteSpec.Count equals count.

func RuntimeCodecsForRegisterCount

func RuntimeCodecsForRegisterCount(count uint16) ([]RuntimeCodec, error)

RuntimeCodecsForRegisterCount returns runtime codecs for all registered descriptors whose RegisterSpec.Count equals count. Returned codecs are directly usable for DecodeRegistersAny, EncodeRegistersAny, and runtime plan execution. Returns an error if any descriptor fails to instantiate.

type RuntimeDecoder

type RuntimeDecoder interface {
	ID() string
	Name() string
	RegisterSpec() RegisterSpec
	ByteSpec() ByteSpec
	ValueKind() CodecValueKind
	DecodeRegistersAny(regs []uint16) (any, error)
}

RuntimeDecoder decodes raw registers into an any value. Used for discovery, CLI selection, and batch decode plans where the concrete type is not known at compile time.

func AsRuntimeDecoder

func AsRuntimeDecoder[T any](d Decoder[T], kind CodecValueKind) RuntimeDecoder

AsRuntimeDecoder wraps a typed Decoder[T] as a RuntimeDecoder. The kind is stored for discovery/CLI.

type RuntimeEncoder

type RuntimeEncoder interface {
	ID() string
	Name() string
	RegisterSpec() RegisterSpec
	ByteSpec() ByteSpec
	ValueKind() CodecValueKind
	EncodeRegistersAny(value any) ([]uint16, error)
}

RuntimeEncoder encodes an any value into raw registers. Callers must pass a value whose type matches the codec; otherwise EncodeRegistersAny returns a *CodecValueError (never panics). For interface types (e.g. net.IP), a typed nil (var ip net.IP = nil) may pass the type assertion while an untyped nil may not; CLI/runtime callers should be aware when passing nil.

func AsRuntimeEncoder

func AsRuntimeEncoder[T any](e Encoder[T], kind CodecValueKind) RuntimeEncoder

AsRuntimeEncoder wraps a typed Encoder[T] as a RuntimeEncoder. Wrong type passed to EncodeRegistersAny returns *CodecValueError and never panics.

type WordOrder

type WordOrder uint

WordOrder controls the order of 16-bit words within multi-register values.

const (
	HighWordFirst WordOrder = 1
	LowWordFirst  WordOrder = 2
)

Jump to

Keyboard shortcuts

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