Documentation
¶
Index ¶
- Constants
- Variables
- func LoadCertPool(filePath string) (cp *x509.CertPool, err error)
- type ClientConfiguration
- type ClientMetrics
- type CoilsRequest
- type DetectionMode
- type DeviceIdentification
- type DeviceIdentificationObject
- type DiagnosticResponse
- type DiagnosticSubFunction
- type DiscreteInputsRequest
- type Endianness
- type ExceptionError
- type ExponentialBackoffConfig
- type FileRecord
- type FileRecordRequest
- type HoldingRegistersRequest
- type InputRegistersRequest
- type Logger
- type ModbusClient
- func (mc *ModbusClient) Close() (err error)
- func (mc *ModbusClient) DetectUnitID(ctx context.Context) ([]uint8, error)
- func (mc *ModbusClient) Diagnostics(ctx context.Context, unitId uint8, subFunction DiagnosticSubFunction, ...) (dr *DiagnosticResponse, err error)
- func (mc *ModbusClient) FingerprintDevice(ctx context.Context, unitId uint8) (*ModbusFingerprint, error)
- func (mc *ModbusClient) IsModbusDevice(ctx context.Context, unitId uint8) (bool, error)
- func (mc *ModbusClient) Open() (err error)
- func (mc *ModbusClient) ReadAllDeviceIdentification(ctx context.Context, unitId uint8) (*DeviceIdentification, error)
- func (mc *ModbusClient) ReadAscii(ctx context.Context, unitId uint8, addr uint16, quantity uint16, ...) (value string, err error)
- func (mc *ModbusClient) ReadAsciiReverse(ctx context.Context, unitId uint8, addr uint16, quantity uint16, ...) (value string, err error)
- func (mc *ModbusClient) ReadBCD(ctx context.Context, unitId uint8, addr uint16, quantity uint16, ...) (value string, err error)
- func (mc *ModbusClient) ReadBytes(ctx context.Context, unitId uint8, addr uint16, quantity uint16, ...) (values []byte, err error)
- func (mc *ModbusClient) ReadCoil(ctx context.Context, unitId uint8, addr uint16) (value bool, err error)
- func (mc *ModbusClient) ReadCoils(ctx context.Context, unitId uint8, addr uint16, quantity uint16) (values []bool, err error)
- func (mc *ModbusClient) ReadDeviceIdentification(ctx context.Context, unitId uint8, readDeviceIdCode uint8, objectId uint8) (di *DeviceIdentification, err error)
- func (mc *ModbusClient) ReadDiscreteInput(ctx context.Context, unitId uint8, addr uint16) (value bool, err error)
- func (mc *ModbusClient) ReadDiscreteInputs(ctx context.Context, unitId uint8, addr uint16, quantity uint16) (values []bool, err error)
- func (mc *ModbusClient) ReadFIFOQueue(ctx context.Context, unitId uint8, addr uint16) (values []uint16, err error)
- func (mc *ModbusClient) ReadFileRecords(ctx context.Context, unitId uint8, requests []FileRecordRequest) (records [][]uint16, err error)
- func (mc *ModbusClient) ReadFloat32(ctx context.Context, unitId uint8, addr uint16, regType RegType) (value float32, err error)
- func (mc *ModbusClient) ReadFloat32s(ctx context.Context, unitId uint8, addr uint16, quantity uint16, ...) (values []float32, err error)
- func (mc *ModbusClient) ReadFloat64(ctx context.Context, unitId uint8, addr uint16, regType RegType) (value float64, err error)
- func (mc *ModbusClient) ReadFloat64s(ctx context.Context, unitId uint8, addr uint16, quantity uint16, ...) (values []float64, err error)
- func (mc *ModbusClient) ReadInt16(ctx context.Context, unitId uint8, addr uint16, regType RegType) (value int16, err error)
- func (mc *ModbusClient) ReadInt16s(ctx context.Context, unitId uint8, addr uint16, quantity uint16, ...) (values []int16, err error)
- func (mc *ModbusClient) ReadInt32(ctx context.Context, unitId uint8, addr uint16, regType RegType) (value int32, err error)
- func (mc *ModbusClient) ReadInt32s(ctx context.Context, unitId uint8, addr uint16, quantity uint16, ...) (values []int32, err error)
- func (mc *ModbusClient) ReadInt48(ctx context.Context, unitId uint8, addr uint16, regType RegType) (value int64, err error)
- func (mc *ModbusClient) ReadInt48s(ctx context.Context, unitId uint8, addr uint16, quantity uint16, ...) (values []int64, err error)
- func (mc *ModbusClient) ReadInt64(ctx context.Context, unitId uint8, addr uint16, regType RegType) (value int64, err error)
- func (mc *ModbusClient) ReadInt64s(ctx context.Context, unitId uint8, addr uint16, quantity uint16, ...) (values []int64, err error)
- func (mc *ModbusClient) ReadPackedBCD(ctx context.Context, unitId uint8, addr uint16, quantity uint16, ...) (value string, err error)
- func (mc *ModbusClient) ReadRawBytes(ctx context.Context, unitId uint8, addr uint16, quantity uint16, ...) (values []byte, err error)
- func (mc *ModbusClient) ReadRegister(ctx context.Context, unitId uint8, addr uint16, regType RegType) (value uint16, err error)
- func (mc *ModbusClient) ReadRegisters(ctx context.Context, unitId uint8, addr uint16, quantity uint16, ...) (values []uint16, err error)
- func (mc *ModbusClient) ReadUint16(ctx context.Context, unitId uint8, addr uint16, regType RegType) (value uint16, err error)
- func (mc *ModbusClient) ReadUint16s(ctx context.Context, unitId uint8, addr uint16, quantity uint16, ...) (values []uint16, err error)
- func (mc *ModbusClient) ReadUint32(ctx context.Context, unitId uint8, addr uint16, regType RegType) (value uint32, err error)
- func (mc *ModbusClient) ReadUint32s(ctx context.Context, unitId uint8, addr uint16, quantity uint16, ...) (values []uint32, err error)
- func (mc *ModbusClient) ReadUint48(ctx context.Context, unitId uint8, addr uint16, regType RegType) (value uint64, err error)
- func (mc *ModbusClient) ReadUint48s(ctx context.Context, unitId uint8, addr uint16, quantity uint16, ...) (values []uint64, err error)
- func (mc *ModbusClient) ReadUint64(ctx context.Context, unitId uint8, addr uint16, regType RegType) (value uint64, err error)
- func (mc *ModbusClient) ReadUint64s(ctx context.Context, unitId uint8, addr uint16, quantity uint16, ...) (values []uint64, err error)
- func (mc *ModbusClient) ReadWriteMultipleRegisters(ctx context.Context, unitId uint8, readAddr, readQty, writeAddr uint16, ...) (values []uint16, err error)
- func (mc *ModbusClient) ReportServerId(ctx context.Context, unitId uint8) (rs *ReportServerIdResponse, err error)
- func (mc *ModbusClient) SetEncoding(endianness Endianness, wordOrder WordOrder) (err error)
- func (mc *ModbusClient) WriteBytes(ctx context.Context, unitId uint8, addr uint16, values []byte) (err error)
- func (mc *ModbusClient) WriteCoil(ctx context.Context, unitId uint8, addr uint16, value bool) (err error)
- func (mc *ModbusClient) WriteCoilValue(ctx context.Context, unitId uint8, addr uint16, payload uint16) (err error)
- func (mc *ModbusClient) WriteCoils(ctx context.Context, unitId uint8, addr uint16, values []bool) (err error)
- func (mc *ModbusClient) WriteFileRecords(ctx context.Context, unitId uint8, records []FileRecord) (err error)
- func (mc *ModbusClient) WriteFloat32(ctx context.Context, unitId uint8, addr uint16, value float32) (err error)
- func (mc *ModbusClient) WriteFloat32s(ctx context.Context, unitId uint8, addr uint16, values []float32) (err error)
- func (mc *ModbusClient) WriteFloat64(ctx context.Context, unitId uint8, addr uint16, value float64) (err error)
- func (mc *ModbusClient) WriteFloat64s(ctx context.Context, unitId uint8, addr uint16, values []float64) (err error)
- func (mc *ModbusClient) WriteRawBytes(ctx context.Context, unitId uint8, addr uint16, values []byte) (err error)
- func (mc *ModbusClient) WriteRegister(ctx context.Context, unitId uint8, addr uint16, value uint16) (err error)
- func (mc *ModbusClient) WriteRegisters(ctx context.Context, unitId uint8, addr uint16, values []uint16) (err error)
- func (mc *ModbusClient) WriteUint32(ctx context.Context, unitId uint8, addr uint16, value uint32) (err error)
- func (mc *ModbusClient) WriteUint32s(ctx context.Context, unitId uint8, addr uint16, values []uint32) (err error)
- func (mc *ModbusClient) WriteUint64(ctx context.Context, unitId uint8, addr uint16, value uint64) (err error)
- func (mc *ModbusClient) WriteUint64s(ctx context.Context, unitId uint8, addr uint16, values []uint64) (err error)
- type ModbusFingerprint
- type ModbusServer
- type Parity
- type RegType
- type ReportServerIdResponse
- type RequestHandler
- type RetryPolicy
- type ServerConfiguration
- type ServerMetrics
- type WordOrder
Constants ¶
const ( ParityNone Parity = 0 ParityEven Parity = 1 ParityOdd Parity = 2 HoldingRegister RegType = 0 InputRegister RegType = 1 // endianness of 16-bit registers. BigEndian Endianness = 1 LittleEndian Endianness = 2 // word order of 32-bit registers. HighWordFirst WordOrder = 1 LowWordFirst WordOrder = 2 )
const ( ReadDeviceIdBasic = 0x01 // Basic: VendorName, ProductCode, MajorMinorRevision (mandatory) ReadDeviceIdRegular = 0x02 // Regular: Basic + VendorUrl, ProductName, ModelName, UserApplicationName ReadDeviceIdExtended = 0x03 // Extended: Regular + private/vendor objects (0x80–0xFF) ReadDeviceIdIndividual = 0x04 // Individual: request a single object by objectId )
Read Device ID codes for FC43 (Read Device Identification). Use with ReadDeviceIdentification; ReadAllDeviceIdentification uses Extended internally.
Variables ¶
var ( ErrConfigurationError = errors.New("modbus: configuration error") ErrRequestTimedOut = errors.New("modbus: request timed out") ErrIllegalFunction = errors.New("modbus: illegal function") ErrIllegalDataAddress = errors.New("modbus: illegal data address") ErrIllegalDataValue = errors.New("modbus: illegal data value") ErrServerDeviceFailure = errors.New("modbus: server device failure") ErrAcknowledge = errors.New("modbus: acknowledge") ErrServerDeviceBusy = errors.New("modbus: server device busy") ErrMemoryParityError = errors.New("modbus: memory parity error") ErrGWTargetFailedToRespond = errors.New("modbus: gateway target failed to respond") ErrBadCRC = errors.New("modbus: bad crc") ErrShortFrame = errors.New("modbus: short frame") ErrProtocolError = errors.New("modbus: protocol error") ErrBadUnitId = errors.New("modbus: bad unit id") ErrBadTransactionId = errors.New("modbus: bad transaction id") ErrUnknownProtocolId = errors.New("modbus: unknown protocol identifier") ErrUnexpectedParameters = errors.New("modbus: unexpected parameters") )
Sentinel error variables. Use errors.Is to test for a specific condition; use errors.As with *ExceptionError to inspect Modbus exception details.
Functions ¶
Types ¶
type ClientConfiguration ¶
type ClientConfiguration struct {
// URL sets the client mode and target location in the form
// <mode>://<serial device or host:port> e.g. tcp://plc:502
URL string
// Speed sets the serial link speed (in bps, rtu only)
Speed uint
// DataBits sets the number of bits per serial character (rtu only)
DataBits uint
// Parity sets the serial link parity mode (rtu only)
Parity Parity
// StopBits sets the number of serial stop bits (rtu only)
StopBits uint
// Timeout sets the request timeout value
Timeout time.Duration
// TLSClientCert sets the client-side TLS key pair (tcp+tls only)
TLSClientCert *tls.Certificate
// TLSRootCAs sets the list of CA certificates used to authenticate
// the server (tcp+tls only). Leaf (i.e. server) certificates can also
// be used in case of self-signed certs, or if cert pinning is required.
TLSRootCAs *x509.CertPool
// Logger provides a custom sink for log messages.
// If nil, the slog default logger (slog.Default()) is used.
// Use NewStdLogger, NewSlogLogger, or NopLogger to build a value.
Logger Logger
// RetryPolicy controls whether and how failed requests are retried.
// A nil RetryPolicy (the default) is equivalent to NoRetry() — errors are
// returned to the caller immediately without any retry attempt.
// Use ExponentialBackoff or NewExponentialBackoff to configure automatic retries.
// On retry the client closes and re-dials the transport before each attempt;
// when a connection pool is configured only the failed connection is replaced.
RetryPolicy RetryPolicy
// Metrics receives callbacks for every request outcome.
// A nil Metrics (the default) disables metric collection.
Metrics ClientMetrics
// MinConns is the number of connections pre-warmed during Open().
// Applies only to TCP-based transports (tcp, rtuovertcp, rtuoverudp, udp).
// Zero disables pre-warming.
MinConns int
// MaxConns is the maximum number of concurrent connections maintained by the
// internal connection pool. When > 1, multiple goroutines sharing a single
// ModbusClient can execute requests concurrently, each on its own connection.
// Applies only to TCP-based transports. Zero and 1 both mean a single connection
// (no pool). Values greater than 1 allocate a pool of up to MaxConns connections.
MaxConns int
// DetectionMode controls which probes IsModbusDevice and DetectUnitID execute.
// DetectAggressive (default, zero value) uses the full set: FC08, FC43, FC03, FC04, FC01, FC02.
// DetectStrict uses FC08, FC43, FC03. DetectBasic uses FC03 only.
DetectionMode DetectionMode
}
Modbus client configuration object.
type ClientMetrics ¶
type ClientMetrics interface {
// OnRequest is called immediately before the first attempt to send a request.
// unitId and functionCode identify the target device and operation.
OnRequest(unitId uint8, functionCode uint8)
// OnResponse is called after a successful round-trip.
// duration covers the total elapsed time including any retry delays.
OnResponse(unitId uint8, functionCode uint8, duration time.Duration)
// OnError is called when a request ultimately fails with a non-timeout error
// (after all retry attempts are exhausted).
// duration covers the total elapsed time including any retry delays.
OnError(unitId uint8, functionCode uint8, duration time.Duration, err error)
// OnTimeout is called when a request ultimately fails because it exceeded
// its deadline (errors.Is(err, ErrRequestTimedOut) or context deadline exceeded).
// duration covers the total elapsed time including any retry delays.
OnTimeout(unitId uint8, functionCode uint8, duration time.Duration)
}
ClientMetrics is an optional callback interface for observing client-side request outcomes. All methods are called synchronously in the goroutine executing the request; implementations must be non-blocking (e.g. increment an atomic counter, send on a buffered channel). A nil ClientMetrics is valid and disables collection.
type CoilsRequest ¶
type CoilsRequest struct {
ClientAddr string // the source (client) IP address
ClientRole string // the client role as encoded in the client certificate (tcp+tls only)
UnitId uint8 // the requested unit id (slave id)
Addr uint16 // the base coil address requested
Quantity uint16 // the number of consecutive coils covered by this request
// (first address: Addr, last address: Addr + Quantity - 1)
IsWrite bool // true if the request is a write, false if a read
Args []bool // a slice of bool values of the coils to be set, ordered
}
Request object passed to the coil handler.
type DetectionMode ¶ added in v1.0.3
type DetectionMode int
DetectionMode controls the probe sequence used by IsModbusDevice. The zero value (DetectAggressive) uses the full probe set for maximum coverage.
const ( // DetectAggressive uses the full probe sequence: FC08, FC43, FC03, FC04, FC01, FC02. // This is the default (zero value) and provides the highest detection confidence. DetectAggressive DetectionMode = iota // DetectStrict uses a reduced probe set: FC08, FC43, FC03. // Good balance between speed and coverage. DetectStrict // DetectBasic uses only FC03 (Read Holding Registers, addr 0, qty 1). // Fastest but may miss devices that don't implement FC03. DetectBasic )
type DeviceIdentification ¶
type DeviceIdentification struct {
ReadDeviceIdCode uint8
ConformityLevel uint8
MoreFollows uint8
NextObjectId uint8
Objects []DeviceIdentificationObject
}
DeviceIdentification groups all decoded data from an FC43/MEI response.
type DeviceIdentificationObject ¶
DeviceIdentificationObject represents one object from an FC43/MEI response.
type DiagnosticResponse ¶ added in v1.0.3
type DiagnosticResponse struct {
SubFunction DiagnosticSubFunction
Data []byte
}
DiagnosticResponse is the response from Diagnostics (FC 0x08). SubFunction is echoed from the request; Data is the sub-function-specific data (e.g. loopback data, diagnostic register value).
type DiagnosticSubFunction ¶ added in v1.0.3
type DiagnosticSubFunction uint16
DiagnosticSubFunction is the two-byte sub-function code for Diagnostics (FC 0x08). Use the constants below for well-known sub-functions; raw uint16 values are valid.
const ( DiagReturnQueryData DiagnosticSubFunction = 0x0000 // Loopback request data DiagRestartCommunications DiagnosticSubFunction = 0x0001 DiagReturnDiagnosticRegister DiagnosticSubFunction = 0x0002 DiagChangeASCIIInputDelimiter DiagnosticSubFunction = 0x0003 DiagForceListenOnlyMode DiagnosticSubFunction = 0x0004 DiagClearCountersAndDiagnosticReg DiagnosticSubFunction = 0x000A DiagReturnBusMessageCount DiagnosticSubFunction = 0x000B DiagReturnBusCommunicationErrorCount DiagnosticSubFunction = 0x000C DiagReturnBusExceptionErrorCount DiagnosticSubFunction = 0x000D DiagReturnServerMessageCount DiagnosticSubFunction = 0x000E DiagReturnServerNoResponseCount DiagnosticSubFunction = 0x000F DiagReturnServerNAKCount DiagnosticSubFunction = 0x0010 DiagReturnServerBusyCount DiagnosticSubFunction = 0x0011 DiagReturnBusCharacterOverrunCount DiagnosticSubFunction = 0x0012 DiagClearOverrunCounterAndFlag DiagnosticSubFunction = 0x0014 )
func (DiagnosticSubFunction) String ¶ added in v1.0.3
func (s DiagnosticSubFunction) String() string
String returns a short name for the sub-function for logging and debugging.
type DiscreteInputsRequest ¶
type DiscreteInputsRequest struct {
ClientAddr string // the source (client) IP address
ClientRole string // the client role as encoded in the client certificate (tcp+tls only)
UnitId uint8 // the requested unit id (slave id)
Addr uint16 // the base discrete input address requested
Quantity uint16 // the number of consecutive discrete inputs covered by this request
}
Request object passed to the discrete input handler.
type Endianness ¶
type Endianness uint
type ExceptionError ¶
type ExceptionError struct {
FunctionCode byte // originating Modbus function code (high bit clear)
ExceptionCode byte // raw Modbus exception code (0x01–0x0b)
Sentinel error // one of the Err* sentinel variables below
}
ExceptionError is returned by client methods when the remote device responds with a Modbus exception. It gives callers structured access to the raw function and exception codes while remaining compatible with errors.Is / errors.As:
var excErr *modbus.ExceptionError
if errors.As(err, &excErr) {
fmt.Printf("fc=0x%02x exception=0x%02x\n", excErr.FunctionCode, excErr.ExceptionCode)
}
if errors.Is(err, modbus.ErrIllegalDataAddress) { ... }
func (*ExceptionError) Error ¶
func (e *ExceptionError) Error() string
func (*ExceptionError) Is ¶
func (e *ExceptionError) Is(target error) bool
func (*ExceptionError) Unwrap ¶
func (e *ExceptionError) Unwrap() error
type ExponentialBackoffConfig ¶
type ExponentialBackoffConfig struct {
// BaseDelay is the wait after the first failure; doubles each subsequent attempt.
// Defaults to 100 ms when zero.
BaseDelay time.Duration
// MaxDelay caps the computed delay. Defaults to 30 s when zero.
MaxDelay time.Duration
// MaxAttempts is the maximum number of retries (not counting the original attempt).
// Zero means unlimited retries — use with care; always pass a context with a deadline.
MaxAttempts int
// RetryOnTimeout controls whether ErrRequestTimedOut triggers a retry.
// Default false: timed-out requests are NOT retried (the deadline has already elapsed).
RetryOnTimeout bool
}
ExponentialBackoffConfig is the full configuration set for exponential back-off.
type FileRecord ¶
type FileRecord struct {
FileNumber uint16 // file number (1–0xFFFF)
RecordNumber uint16 // starting record number within the file (0–0x270F)
Data []uint16 // register values to write (len gives record length)
}
FileRecord describes one sub-request for WriteFileRecords (FC21). Each record writes a contiguous slice of registers to a single file. The record length is implied by len(Data).
type FileRecordRequest ¶
type FileRecordRequest struct {
FileNumber uint16 // file number (1–0xFFFF)
RecordNumber uint16 // starting record number within the file (0–0x270F)
RecordLength uint16 // number of 16-bit registers to read (≥ 1)
}
FileRecordRequest describes one sub-request for ReadFileRecords (FC20). Each sub-request reads a contiguous slice of registers from a single file.
type HoldingRegistersRequest ¶
type HoldingRegistersRequest struct {
ClientAddr string // the source (client) IP address
ClientRole string // the client role as encoded in the client certificate (tcp+tls only)
UnitId uint8 // the requested unit id (slave id)
Addr uint16 // the base register address requested
Quantity uint16 // the number of consecutive registers covered by this request
IsWrite bool // true if the request is a write, false if a read
Args []uint16 // a slice of register values to be set, ordered from
}
Request object passed to the holding register handler.
type InputRegistersRequest ¶
type InputRegistersRequest struct {
ClientAddr string // the source (client) IP address
ClientRole string // the client role as encoded in the client certificate (tcp+tls only)
UnitId uint8 // the requested unit id (slave id)
Addr uint16 // the base register address requested
Quantity uint16 // the number of consecutive registers covered by this request
}
Request object passed to the input register handler.
type Logger ¶
type Logger interface {
Debugf(format string, args ...any)
Infof(format string, args ...any)
Warnf(format string, args ...any)
Errorf(format string, args ...any)
}
Logger is the logging interface accepted by ClientConfiguration and ServerConfiguration. Implement this interface to integrate any structured or levelled logging library (e.g. zap, zerolog, slog, logrus).
func NewSlogLogger ¶
NewSlogLogger wraps a slog.Handler so it satisfies the Logger interface. Use slog.NewJSONHandler, slog.NewTextHandler, or any third-party handler.
func NewStdLogger ¶
NewStdLogger wraps a stdlib *log.Logger so it satisfies the Logger interface. If l is nil, output is written to os.Stdout with no flags.
type ModbusClient ¶
type ModbusClient struct {
// contains filtered or unexported fields
}
Modbus client object.
func NewClient ¶
func NewClient(conf *ClientConfiguration) (mc *ModbusClient, err error)
NewClient creates, configures and returns a modbus client object.
func (*ModbusClient) Close ¶
func (mc *ModbusClient) Close() (err error)
Closes the underlying transport (or connection pool).
func (*ModbusClient) DetectUnitID ¶ added in v1.0.3
func (mc *ModbusClient) DetectUnitID(ctx context.Context) ([]uint8, error)
DetectUnitID scans the full unit-ID range (0–255) and returns every unit ID that responds with a valid Modbus frame. The scan order is optimised for speed: common IDs first (1, 255, 0), then ascending 2–254.
Returns (ids, nil) on success where ids may be empty, or (nil, err) on context cancellation or transport error.
func (*ModbusClient) Diagnostics ¶ added in v1.0.3
func (mc *ModbusClient) Diagnostics(ctx context.Context, unitId uint8, subFunction DiagnosticSubFunction, data []byte) (dr *DiagnosticResponse, err error)
Diagnostics sends a Diagnostics request (FC 0x08). subFunction selects the diagnostic (use DiagnosticSubFunction constants). data is optional request data (sub-function-specific; use nil or empty for none). The response echoes the sub-function and returns sub-function-specific data.
func (*ModbusClient) FingerprintDevice ¶ added in v1.0.3
func (mc *ModbusClient) FingerprintDevice(ctx context.Context, unitId uint8) (*ModbusFingerprint, error)
FingerprintDevice runs all detection probes against the given unit ID and records which function codes the device actively supports. A function is marked as supported when the device responds with a normal (non-exception) response or an exception other than Illegal Function (0x01). Use after Open().
func (*ModbusClient) IsModbusDevice ¶ added in v1.0.2
IsModbusDevice probes the target with a minimal, read-only request sequence to determine whether the given unit ID responds with Modbus-compliant structure (valid MBAP where applicable, structurally valid normal or exception response). Use after Open(); does not mutate server state.
The probe sequence depends on ClientConfiguration.DetectionMode:
DetectAggressive (default) : FC08 → FC43 → FC03 → FC04 → FC01 → FC02 DetectStrict : FC08 → FC43 → FC03 DetectBasic : FC03
Returns true on first structurally validated response (normal or exception), false if no probe succeeds. Caller decides which unit IDs to try.
func (*ModbusClient) Open ¶
func (mc *ModbusClient) Open() (err error)
Opens the underlying transport (network socket or serial line). If MaxConns > 1 and the transport is TCP-based, a connection pool pre-warmed with MinConns connections is created; subsequent requests draw from the pool and may execute concurrently. For serial transports, a single transport is used.
func (*ModbusClient) ReadAllDeviceIdentification ¶ added in v1.0.1
func (mc *ModbusClient) ReadAllDeviceIdentification(ctx context.Context, unitId uint8) (*DeviceIdentification, error)
ReadAllDeviceIdentification reads all device identification the unit supports: basic, regular, and extended (FC43 / MEI 0x0E). It requests the Extended category (ReadDeviceIdExtended); the device responds with all objects it implements, up to its conformity level. Use this when you want a single, complete snapshot of device identification without calling ReadDeviceIdentification multiple times.
func (*ModbusClient) ReadAscii ¶
func (mc *ModbusClient) ReadAscii(ctx context.Context, unitId uint8, addr uint16, quantity uint16, regType RegType) (value string, err error)
Reads quantity registers (function code 03 or 04) as an ASCII string. The high byte of each register is the first character, the low byte the second. Trailing spaces are stripped from the returned string.
func (*ModbusClient) ReadAsciiReverse ¶
func (mc *ModbusClient) ReadAsciiReverse(ctx context.Context, unitId uint8, addr uint16, quantity uint16, regType RegType) (value string, err error)
Reads quantity registers (function code 03 or 04) as an ASCII string with byte-swapped register words. The low byte of each register is the first character, the high byte the second. Trailing spaces are stripped.
func (*ModbusClient) ReadBCD ¶
func (mc *ModbusClient) ReadBCD(ctx context.Context, unitId uint8, addr uint16, quantity uint16, regType RegType) (value string, err error)
Reads quantity registers (function code 03 or 04) as a Binary Coded Decimal (BCD) string. Each byte encodes one decimal digit (0–9). Returns a string of decimal digits, most-significant digit first.
func (*ModbusClient) ReadBytes ¶
func (mc *ModbusClient) ReadBytes(ctx context.Context, unitId uint8, addr uint16, quantity uint16, regType RegType) (values []byte, err error)
Reads one or multiple 16-bit registers (function code 03 or 04) as bytes. A per-register byteswap is performed if endianness is set to LittleEndian.
func (*ModbusClient) ReadCoil ¶
func (mc *ModbusClient) ReadCoil(ctx context.Context, unitId uint8, addr uint16) (value bool, err error)
Reads a single coil (function code 01).
func (*ModbusClient) ReadCoils ¶
func (mc *ModbusClient) ReadCoils(ctx context.Context, unitId uint8, addr uint16, quantity uint16) (values []bool, err error)
Reads multiple coils (function code 01).
func (*ModbusClient) ReadDeviceIdentification ¶
func (mc *ModbusClient) ReadDeviceIdentification(ctx context.Context, unitId uint8, readDeviceIdCode uint8, objectId uint8) (di *DeviceIdentification, err error)
ReadDeviceIdentification reads device identification objects using FC43 / MEI type 0x0E. It automatically pages through MoreFollows and returns all objects for the requested category.
readDeviceIdCode selects the category (use constants from this package):
- ReadDeviceIdBasic (0x01): VendorName, ProductCode, MajorMinorRevision (mandatory)
- ReadDeviceIdRegular (0x02): Basic + VendorUrl, ProductName, ModelName, UserApplicationName
- ReadDeviceIdExtended (0x03): Regular + private/vendor objects (0x80–0xFF)
- ReadDeviceIdIndividual (0x04): single object by objectId (objectId must be set)
For objectId use 0x00 to start from the first object (stream access); for Individual, pass the desired object ID. The device responds at its conformity level if a higher category is requested (e.g. requesting Extended on a basic-only device returns Basic).
func (*ModbusClient) ReadDiscreteInput ¶
func (mc *ModbusClient) ReadDiscreteInput(ctx context.Context, unitId uint8, addr uint16) (value bool, err error)
Reads a single discrete input (function code 02).
func (*ModbusClient) ReadDiscreteInputs ¶
func (mc *ModbusClient) ReadDiscreteInputs(ctx context.Context, unitId uint8, addr uint16, quantity uint16) (values []bool, err error)
Reads multiple discrete inputs (function code 02).
func (*ModbusClient) ReadFIFOQueue ¶
func (mc *ModbusClient) ReadFIFOQueue(ctx context.Context, unitId uint8, addr uint16) (values []uint16, err error)
Reads the contents of a FIFO queue of holding registers (function code 24). addr is the FIFO Pointer Address (the count register); registers are returned as big-endian uint16 values exactly as they arrive from the device. The FIFO queue may contain at most 31 registers; an exception response is returned by the server if the count exceeds 31.
func (*ModbusClient) ReadFileRecords ¶
func (mc *ModbusClient) ReadFileRecords(ctx context.Context, unitId uint8, requests []FileRecordRequest) (records [][]uint16, err error)
Reads one or more groups of file records (function code 20). Each FileRecordRequest selects a contiguous run of registers from one file. The returned slice has one []uint16 entry per request, in the same order. Register data is returned as big-endian uint16 values as received from the device.
Spec limits:
FileNumber must be 1–0xFFFF RecordNumber must be 0–0x270F (decimal 0–9999) Total request byte count must not exceed 0xF5 (at most 35 sub-requests)
func (*ModbusClient) ReadFloat32 ¶
func (mc *ModbusClient) ReadFloat32(ctx context.Context, unitId uint8, addr uint16, regType RegType) (value float32, err error)
Reads a single 32-bit float register.
func (*ModbusClient) ReadFloat32s ¶
func (mc *ModbusClient) ReadFloat32s(ctx context.Context, unitId uint8, addr uint16, quantity uint16, regType RegType) (values []float32, err error)
Reads multiple 32-bit float registers.
func (*ModbusClient) ReadFloat64 ¶
func (mc *ModbusClient) ReadFloat64(ctx context.Context, unitId uint8, addr uint16, regType RegType) (value float64, err error)
Reads a single 64-bit float register.
func (*ModbusClient) ReadFloat64s ¶
func (mc *ModbusClient) ReadFloat64s(ctx context.Context, unitId uint8, addr uint16, quantity uint16, regType RegType) (values []float64, err error)
Reads multiple 64-bit float registers.
func (*ModbusClient) ReadInt16 ¶
func (mc *ModbusClient) ReadInt16(ctx context.Context, unitId uint8, addr uint16, regType RegType) (value int16, err error)
Reads a single 16-bit signed register (function code 03 or 04). The raw 16-bit value is reinterpreted as int16.
func (*ModbusClient) ReadInt16s ¶
func (mc *ModbusClient) ReadInt16s(ctx context.Context, unitId uint8, addr uint16, quantity uint16, regType RegType) (values []int16, err error)
Reads multiple 16-bit signed registers (function code 03 or 04). The raw 16-bit value of each register is reinterpreted as int16.
func (*ModbusClient) ReadInt32 ¶
func (mc *ModbusClient) ReadInt32(ctx context.Context, unitId uint8, addr uint16, regType RegType) (value int32, err error)
Reads a single 32-bit signed register (function code 03 or 04). The value occupies 2 consecutive 16-bit registers.
func (*ModbusClient) ReadInt32s ¶
func (mc *ModbusClient) ReadInt32s(ctx context.Context, unitId uint8, addr uint16, quantity uint16, regType RegType) (values []int32, err error)
Reads multiple 32-bit signed registers (function code 03 or 04). Each value occupies 2 consecutive 16-bit registers. Byte and word order are controlled by SetEncoding.
func (*ModbusClient) ReadInt48 ¶
func (mc *ModbusClient) ReadInt48(ctx context.Context, unitId uint8, addr uint16, regType RegType) (value int64, err error)
Reads a single 48-bit signed value (function code 03 or 04), returned as int64. The value occupies 3 consecutive 16-bit registers.
func (*ModbusClient) ReadInt48s ¶
func (mc *ModbusClient) ReadInt48s(ctx context.Context, unitId uint8, addr uint16, quantity uint16, regType RegType) (values []int64, err error)
Reads multiple 48-bit signed values (function code 03 or 04), returned as int64. Each value occupies 3 consecutive 16-bit registers. The 48-bit value is sign-extended to 64 bits. Byte and word order are controlled by SetEncoding.
func (*ModbusClient) ReadInt64 ¶
func (mc *ModbusClient) ReadInt64(ctx context.Context, unitId uint8, addr uint16, regType RegType) (value int64, err error)
Reads a single 64-bit signed register (function code 03 or 04). The value occupies 4 consecutive 16-bit registers.
func (*ModbusClient) ReadInt64s ¶
func (mc *ModbusClient) ReadInt64s(ctx context.Context, unitId uint8, addr uint16, quantity uint16, regType RegType) (values []int64, err error)
Reads multiple 64-bit signed registers (function code 03 or 04). Each value occupies 4 consecutive 16-bit registers. Byte and word order are controlled by SetEncoding.
func (*ModbusClient) ReadPackedBCD ¶
func (mc *ModbusClient) ReadPackedBCD(ctx context.Context, unitId uint8, addr uint16, quantity uint16, regType RegType) (value string, err error)
Reads quantity registers (function code 03 or 04) as a Packed BCD string. Each nibble encodes one decimal digit (0–9): the high nibble is the more- significant digit. Returns a string of decimal digits, most-significant digit first.
func (*ModbusClient) ReadRawBytes ¶
func (mc *ModbusClient) ReadRawBytes(ctx context.Context, unitId uint8, addr uint16, quantity uint16, regType RegType) (values []byte, err error)
Reads one or multiple 16-bit registers (function code 03 or 04) as bytes. No byte or word reordering is performed: bytes are returned exactly as they come off the wire, allowing the caller to handle encoding/endianness/word order manually.
func (*ModbusClient) ReadRegister ¶
func (mc *ModbusClient) ReadRegister(ctx context.Context, unitId uint8, addr uint16, regType RegType) (value uint16, err error)
Reads a single 16-bit register (function code 03 or 04).
func (*ModbusClient) ReadRegisters ¶
func (mc *ModbusClient) ReadRegisters(ctx context.Context, unitId uint8, addr uint16, quantity uint16, regType RegType) (values []uint16, err error)
Reads multiple 16-bit registers (function code 03 or 04).
func (*ModbusClient) ReadUint16 ¶
func (mc *ModbusClient) ReadUint16(ctx context.Context, unitId uint8, addr uint16, regType RegType) (value uint16, err error)
Reads a single 16-bit unsigned register (function code 03 or 04). Equivalent to ReadRegister; provided for naming consistency.
func (*ModbusClient) ReadUint16s ¶
func (mc *ModbusClient) ReadUint16s(ctx context.Context, unitId uint8, addr uint16, quantity uint16, regType RegType) (values []uint16, err error)
Reads multiple 16-bit unsigned registers (function code 03 or 04). Equivalent to ReadRegisters; provided for naming consistency.
func (*ModbusClient) ReadUint32 ¶
func (mc *ModbusClient) ReadUint32(ctx context.Context, unitId uint8, addr uint16, regType RegType) (value uint32, err error)
Reads a single 32-bit register.
func (*ModbusClient) ReadUint32s ¶
func (mc *ModbusClient) ReadUint32s(ctx context.Context, unitId uint8, addr uint16, quantity uint16, regType RegType) (values []uint32, err error)
Reads multiple 32-bit registers.
func (*ModbusClient) ReadUint48 ¶
func (mc *ModbusClient) ReadUint48(ctx context.Context, unitId uint8, addr uint16, regType RegType) (value uint64, err error)
Reads a single 48-bit unsigned value (function code 03 or 04), returned as uint64. The value occupies 3 consecutive 16-bit registers.
func (*ModbusClient) ReadUint48s ¶
func (mc *ModbusClient) ReadUint48s(ctx context.Context, unitId uint8, addr uint16, quantity uint16, regType RegType) (values []uint64, err error)
Reads multiple 48-bit unsigned values (function code 03 or 04), returned as uint64. Each value occupies 3 consecutive 16-bit registers. Byte and word order are controlled by SetEncoding.
func (*ModbusClient) ReadUint64 ¶
func (mc *ModbusClient) ReadUint64(ctx context.Context, unitId uint8, addr uint16, regType RegType) (value uint64, err error)
Reads a single 64-bit register.
func (*ModbusClient) ReadUint64s ¶
func (mc *ModbusClient) ReadUint64s(ctx context.Context, unitId uint8, addr uint16, quantity uint16, regType RegType) (values []uint64, err error)
Reads multiple 64-bit registers.
func (*ModbusClient) ReadWriteMultipleRegisters ¶
func (mc *ModbusClient) ReadWriteMultipleRegisters(ctx context.Context, unitId uint8, readAddr, readQty, writeAddr uint16, writeValues []uint16) (values []uint16, err error)
Performs a combined read/write in a single Modbus transaction (function code 23). The write is executed on the server before the read. writeValues are encoded using the client's current endianness setting. The returned slice contains the registers read, also decoded with the current endianness setting.
Limits (per spec):
readQty: 1–125 (0x7D) writeQty: 1–121 (0x79), implied by len(writeValues)
func (*ModbusClient) ReportServerId ¶ added in v1.0.3
func (mc *ModbusClient) ReportServerId(ctx context.Context, unitId uint8) (rs *ReportServerIdResponse, err error)
ReportServerId requests the Report Server ID (FC 0x11). The response contains device-specific server ID, run indicator status, and optional additional data.
func (*ModbusClient) SetEncoding ¶
func (mc *ModbusClient) SetEncoding(endianness Endianness, wordOrder WordOrder) (err error)
Sets the encoding (endianness and word ordering) of subsequent requests.
func (*ModbusClient) WriteBytes ¶
func (mc *ModbusClient) WriteBytes(ctx context.Context, unitId uint8, addr uint16, values []byte) (err error)
Writes the given slice of bytes to 16-bit registers starting at addr. A per-register byteswap is performed if endianness is set to LittleEndian. Odd byte quantities are padded with a null byte to fall on 16-bit register boundaries.
func (*ModbusClient) WriteCoil ¶
func (mc *ModbusClient) WriteCoil(ctx context.Context, unitId uint8, addr uint16, value bool) (err error)
Writes a single coil (function code 05).
func (*ModbusClient) WriteCoilValue ¶
func (mc *ModbusClient) WriteCoilValue(ctx context.Context, unitId uint8, addr uint16, payload uint16) (err error)
Sends a write coil request (function code 05) with a specific payload value instead of the standard 0xff00 (true) or 0x0000 (false). This is a violation of the modbus spec and should almost never be necessary, but a handful of vendors seem to be hiding various DO/coil control modes behind it (e.g. toggle, interlock, delayed open/close, etc.).
func (*ModbusClient) WriteCoils ¶
func (mc *ModbusClient) WriteCoils(ctx context.Context, unitId uint8, addr uint16, values []bool) (err error)
Writes multiple coils (function code 15).
func (*ModbusClient) WriteFileRecords ¶
func (mc *ModbusClient) WriteFileRecords(ctx context.Context, unitId uint8, records []FileRecord) (err error)
Writes one or more groups of file records (function code 21). Each FileRecord specifies the target file, starting record number, and the register values to write. The normal response is an echo of the request. Register data is encoded as big-endian uint16 values on the wire.
Spec limits:
FileNumber must be 1–0xFFFF RecordNumber must be 0–0x270F (decimal 0–9999) Total request data length must be in the range 0x09–0xFB
func (*ModbusClient) WriteFloat32 ¶
func (mc *ModbusClient) WriteFloat32(ctx context.Context, unitId uint8, addr uint16, value float32) (err error)
Writes a single 32-bit float register.
func (*ModbusClient) WriteFloat32s ¶
func (mc *ModbusClient) WriteFloat32s(ctx context.Context, unitId uint8, addr uint16, values []float32) (err error)
Writes multiple 32-bit float registers.
func (*ModbusClient) WriteFloat64 ¶
func (mc *ModbusClient) WriteFloat64(ctx context.Context, unitId uint8, addr uint16, value float64) (err error)
Writes a single 64-bit float register.
func (*ModbusClient) WriteFloat64s ¶
func (mc *ModbusClient) WriteFloat64s(ctx context.Context, unitId uint8, addr uint16, values []float64) (err error)
Writes multiple 64-bit float registers.
func (*ModbusClient) WriteRawBytes ¶
func (mc *ModbusClient) WriteRawBytes(ctx context.Context, unitId uint8, addr uint16, values []byte) (err error)
Writes the given slice of bytes to 16-bit registers starting at addr. No byte or word reordering is performed: bytes are pushed to the wire as-is, allowing the caller to handle encoding/endianness/word order manually. Odd byte quantities are padded with a null byte to fall on 16-bit register boundaries.
func (*ModbusClient) WriteRegister ¶
func (mc *ModbusClient) WriteRegister(ctx context.Context, unitId uint8, addr uint16, value uint16) (err error)
Writes a single 16-bit register (function code 06).
func (*ModbusClient) WriteRegisters ¶
func (mc *ModbusClient) WriteRegisters(ctx context.Context, unitId uint8, addr uint16, values []uint16) (err error)
Writes multiple 16-bit registers (function code 16).
func (*ModbusClient) WriteUint32 ¶
func (mc *ModbusClient) WriteUint32(ctx context.Context, unitId uint8, addr uint16, value uint32) (err error)
Writes a single 32-bit register.
func (*ModbusClient) WriteUint32s ¶
func (mc *ModbusClient) WriteUint32s(ctx context.Context, unitId uint8, addr uint16, values []uint32) (err error)
Writes multiple 32-bit registers.
func (*ModbusClient) WriteUint64 ¶
func (mc *ModbusClient) WriteUint64(ctx context.Context, unitId uint8, addr uint16, value uint64) (err error)
Writes a single 64-bit register.
func (*ModbusClient) WriteUint64s ¶
func (mc *ModbusClient) WriteUint64s(ctx context.Context, unitId uint8, addr uint16, values []uint64) (err error)
Writes multiple 64-bit registers.
type ModbusFingerprint ¶ added in v1.0.3
type ModbusFingerprint struct {
UnitId uint8
SupportsFC01 bool // Read Coils
SupportsFC02 bool // Read Discrete Inputs
SupportsFC03 bool // Read Holding Registers
SupportsFC04 bool // Read Input Registers
SupportsFC08 bool // Diagnostics
SupportsFC11 bool // Report Server ID
SupportsFC18 bool // Read FIFO Queue
SupportsFC20 bool // Read File Record
SupportsFC43 bool // Read Device Identification
}
ModbusFingerprint records which function codes a unit actively supports. A function is marked as supported when the device responds with a non-exception normal response, or with an exception other than Illegal Function (0x01). Use FingerprintDevice to populate.
type ModbusServer ¶
type ModbusServer struct {
// contains filtered or unexported fields
}
Modbus server object.
func NewServer ¶
func NewServer(conf *ServerConfiguration, reqHandler RequestHandler) ( ms *ModbusServer, err error)
Returns a new modbus server. reqHandler should be a user-provided handler object satisfying the RequestHandler interface.
func (*ModbusServer) Start ¶
func (ms *ModbusServer) Start() (err error)
Starts accepting client connections.
func (*ModbusServer) Stop ¶
func (ms *ModbusServer) Stop() (err error)
Stops accepting new client connections and closes any active session. Blocks until all in-flight client goroutines have exited.
type ReportServerIdResponse ¶ added in v1.0.3
ReportServerIdResponse is the response from Report Server ID (FC 0x11). ByteCount is the number of following bytes; Data contains device-specific server ID, run indicator status (0x00 = OFF, 0xFF = ON), and optional additional data.
type RequestHandler ¶
type RequestHandler interface {
// HandleCoils handles the read coils (0x01), write single coil (0x05)
// and write multiple coils (0x0f) function codes.
// A CoilsRequest object is passed to the handler (see above).
//
// Expected return values:
// - res: a slice of bools containing the coil values to be sent to back
// to the client (only sent for reads; the return value is
// ignored for write requests),
// - err: either nil if no error occurred, a modbus error (see
// mapErrorToExceptionCode() in modbus.go for a complete list),
// or any other error.
// If nil, a positive modbus response is sent back to the client
// along with the returned data.
// If non-nil, a negative modbus response is sent back, with the
// exception code set depending on the error
// (again, see mapErrorToExceptionCode()).
HandleCoils(ctx context.Context, req *CoilsRequest) (res []bool, err error)
// HandleDiscreteInputs handles the read discrete inputs (0x02) function code.
// A DiscreteInputsRequest oibject is passed to the handler (see above).
//
// Expected return values:
// - res: a slice of bools containing the discrete input values to be
// sent back to the client,
// - err: either nil if no error occurred, a modbus error (see
// mapErrorToExceptionCode() in modbus.go for a complete list),
// or any other error.
HandleDiscreteInputs(ctx context.Context, req *DiscreteInputsRequest) (res []bool, err error)
// HandleHoldingRegisters handles the read holding registers (0x03),
// write single register (0x06) and write multiple registers (0x10).
// A HoldingRegistersRequest object is passed to the handler (see above).
//
// Expected return values:
// - res: a slice of uint16 containing the register values to be sent
// to back to the client (only sent for reads; the return value is
// ignored for write requests),
// - err: either nil if no error occurred, a modbus error (see
// mapErrorToExceptionCode() in modbus.go for a complete list),
// or any other error.
HandleHoldingRegisters(ctx context.Context, req *HoldingRegistersRequest) (res []uint16, err error)
// HandleInputRegisters handles the read input registers (0x04) function code.
// An InputRegistersRequest object is passed to the handler (see above).
//
// Expected return values:
// - res: a slice of uint16 containing the register values to be sent
// back to the client,
// - err: either nil if no error occurred, a modbus error (see
// mapErrorToExceptionCode() in modbus.go for a complete list),
// or any other error.
HandleInputRegisters(ctx context.Context, req *InputRegistersRequest) (res []uint16, err error)
}
The RequestHandler interface should be implemented by the handler object passed to NewServer (see reqHandler in NewServer()). After decoding and validating an incoming request, the server will invoke the appropriate handler function, depending on the function code of the request.
type RetryPolicy ¶
type RetryPolicy interface {
// ShouldRetry returns (true, waitDuration) to schedule another attempt after
// waitDuration, or (false, 0) to stop and propagate the error to the caller.
ShouldRetry(attempt int, err error) (bool, time.Duration)
}
RetryPolicy controls whether and how a failed request is retried. Each call to ShouldRetry receives the zero-based attempt index (0 = first failure) and the error that caused it, and returns whether to retry and how long to wait.
The wait duration is honoured by the client but capped by the remaining context deadline. A nil RetryPolicy is equivalent to NoRetry().
func ExponentialBackoff ¶
func ExponentialBackoff(base, maxDelay time.Duration, maxAttempts int) RetryPolicy
ExponentialBackoff returns an exponential back-off RetryPolicy with common defaults. delay grows as base × 2^attempt, capped at maxDelay; retries stop after maxAttempts. Passing maxAttempts = 0 means unlimited retries.
func NewExponentialBackoff ¶
func NewExponentialBackoff(cfg ExponentialBackoffConfig) RetryPolicy
NewExponentialBackoff constructs an exponential back-off RetryPolicy from a full ExponentialBackoffConfig, allowing control over RetryOnTimeout and unlimited attempts.
func NoRetry ¶
func NoRetry() RetryPolicy
NoRetry returns a RetryPolicy that never retries; requests fail on the first error. This is the default behaviour when ClientConfiguration.RetryPolicy is nil.
type ServerConfiguration ¶
type ServerConfiguration struct {
// URL defines where to listen at e.g. tcp://[::]:502
URL string
// Timeout sets the idle session timeout (client connections will
// be closed if idle for this long)
Timeout time.Duration
// MaxClients sets the maximum number of concurrent client connections
MaxClients uint
// TLSServerCert sets the server-side TLS key pair (tcp+tls only)
TLSServerCert *tls.Certificate
// TLSClientCAs sets the list of CA certificates used to authenticate
// client connections (tcp+tls only). Leaf (i.e. client) certificates can
// also be used in case of self-signed certs, or if cert pinning is required.
TLSClientCAs *x509.CertPool
// TLSHandshakeTimeout sets the maximum time allowed to complete the TLS
// handshake for incoming connections. Defaults to 30 seconds when zero.
TLSHandshakeTimeout time.Duration
// Logger provides a custom sink for log messages.
// If nil, the slog default logger (slog.Default()) is used.
// Use NewStdLogger, NewSlogLogger, or NopLogger to build a value.
Logger Logger
// Metrics receives callbacks for every request handled by the server.
// A nil Metrics (the default) disables metric collection.
Metrics ServerMetrics
}
Server configuration object.
type ServerMetrics ¶
type ServerMetrics interface {
// OnRequest is called immediately before the handler is invoked.
// unitId and functionCode identify the incoming request.
OnRequest(unitId uint8, functionCode uint8)
// OnResponse is called after the handler returns without error.
// duration is the handler execution time.
OnResponse(unitId uint8, functionCode uint8, duration time.Duration)
// OnError is called when the handler returns an error.
// duration is the handler execution time.
OnError(unitId uint8, functionCode uint8, duration time.Duration, err error)
}
ServerMetrics is an optional callback interface for observing server-side request outcomes. All methods are called synchronously; implementations must be non-blocking. A nil ServerMetrics is valid and disables collection.