mbserver

package module
v0.0.0-...-1d29cbb Latest Latest
Warning

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

Go to latest
Published: Mar 10, 2023 License: MIT Imports: 9 Imported by: 7

README

Go modbus server

This repo is a simplified version of github.com/simonvetter/modbus

The main changes are:

  • simplified the modbus server
  • removed TLS handling (this should be done in the calling application)
  • added an Option interface to creating the server
  • added a DummyHandler
  • removed modbus client (use github.com/grid-x/modbus)

Description

This package is a go implementation of the modbus protocol. It aims to provide a simple-to-use, high-level API to interact with modbus devices using native Go types.

Please note that UDP transports are not part of the Modbus specification. Some devices expect MBAP (modbus TCP) framing in UDP packets while others use RTU frames instead. The client support both so if unsure, try with both udp:// and rtuoverudp:// schemes.

The server supports:

  • modbus TCP (a.k.a. MBAP)

License

MIT.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Logger

func Logger(logger LeveledLogger) func(*ModbusServer) error

Logger is the modbus server logger option

func MapExceptionCodeToError

func MapExceptionCodeToError(exceptionCode uint8) (err error)

MapExceptionCodeToError turns a modbus exception code into a higher level Error object.

func MaxClients

func MaxClients(max uint) func(*ModbusServer) error

MaxClients is the modbus server maximum concurrent clients option

func Timeout

func Timeout(timeout time.Duration) func(*ModbusServer) error

Timeout is the modbus server timeout option

Types

type CoilsRequest

type CoilsRequest struct {
	WriteFuncCode uint8  // the function code of the write request
	ClientAddr    string // the source (client) IP address
	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 DiscreteInputsRequest

type DiscreteInputsRequest struct {
	ClientAddr string // the source (client) IP address
	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 DummyHandler

type DummyHandler struct{}

func (*DummyHandler) HandleCoils

func (h *DummyHandler) HandleCoils(req *CoilsRequest) ([]bool, error)

func (*DummyHandler) HandleDiscreteInputs

func (h *DummyHandler) HandleDiscreteInputs(req *DiscreteInputsRequest) ([]bool, error)

func (*DummyHandler) HandleHoldingRegisters

func (h *DummyHandler) HandleHoldingRegisters(req *HoldingRegistersRequest) ([]uint16, error)

func (*DummyHandler) HandleInputRegisters

func (h *DummyHandler) HandleInputRegisters(req *InputRegistersRequest) ([]uint16, error)

type Error

type Error string
const (

	// errors
	ErrConfigurationError      Error = "configuration error"
	ErrRequestTimedOut         Error = "request timed out"
	ErrIllegalFunction         Error = "illegal function"
	ErrIllegalDataAddress      Error = "illegal data address"
	ErrIllegalDataValue        Error = "illegal data value"
	ErrServerDeviceFailure     Error = "server device failure"
	ErrAcknowledge             Error = "request acknowledged"
	ErrServerDeviceBusy        Error = "server device busy"
	ErrMemoryParityError       Error = "memory parity error"
	ErrGWPathUnavailable       Error = "gateway path unavailable"
	ErrGWTargetFailedToRespond Error = "gateway target device failed to respond"
	ErrBadCRC                  Error = "bad crc"
	ErrShortFrame              Error = "short frame"
	ErrProtocolError           Error = "protocol error"
	ErrBadUnitId               Error = "bad unit id"
	ErrBadTransactionId        Error = "bad transaction id"
	ErrUnknownProtocolId       Error = "unknown protocol identifier"
	ErrUnexpectedParameters    Error = "unexpected parameters"
)

func (Error) Error

func (me Error) Error() (s string)

Error implements the error interface.

type HoldingRegistersRequest

type HoldingRegistersRequest struct {
	WriteFuncCode uint8    // the function code of the write request
	ClientAddr    string   // the source (client) IP address
	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
	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 LeveledLogger

type LeveledLogger interface {
	Info(msg string)
	Infof(format string, msg ...interface{})
	Warning(msg string)
	Warningf(format string, msg ...interface{})
	Error(msg string)
	Errorf(format string, msg ...interface{})
	Fatal(msg string)
	Fatalf(format string, msg ...interface{})
}

type ModbusServer

type ModbusServer struct {
	// 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
	// contains filtered or unexported fields
}

Modbus server object.

func New

func New(reqHandler RequestHandler, opts ...Option) (*ModbusServer, 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(l net.Listener) error

Starts accepting client connections.

func (*ModbusServer) Stop

func (ms *ModbusServer) Stop() (err error)

Stops accepting new client connections and closes any active session.

type Option

type Option func(*ModbusServer) error

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),
	// - 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(*CoilsRequest) ([]bool, 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(*DiscreteInputsRequest) ([]bool, 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),
	// - err:	either nil if no error occurred, a modbus error (see
	//		mapErrorToExceptionCode() in modbus.go for a complete list),
	//		or any other error.
	HandleHoldingRegisters(*HoldingRegistersRequest) ([]uint16, 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(*InputRegistersRequest) ([]uint16, 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 WordOrder

type WordOrder uint
const (
	// word order of 32-bit registers
	HIGH_WORD_FIRST WordOrder = 1
	LOW_WORD_FIRST  WordOrder = 2
)

Jump to

Keyboard shortcuts

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