modbus

package module
v0.0.9 Latest Latest
Warning

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

Go to latest
Published: Dec 27, 2022 License: Apache-2.0 Imports: 10 Imported by: 1

README

Modbus

License Go Report Card Go Reference

This package provides functions and definitions for communicating with modbus compliant devices. The implementation tries to follow the specification as closely as possible. However certain parts of the terminology have been changed to feel more familiar to go programmers.
The focus lies on offering an easy to use client and server.

NOTICE:

The package is currently in alpha state. Significant changes to the signatures are likely in the future.

Supported features

The following points are available for the server and client implementation.

  • context support
  • TCP networking
  • modbus TCP payload framing
  • asynchronous communication in TCP-framing mode
  • function code 0x01: Read Coils
  • function code 0x02: Read Discrete Inputs
  • function code 0x03: Read Holding Registers
  • function code 0x04: Read Input Registers
  • function code 0x05: Write Single Coil
  • function code 0x06: Write Single Register
  • function code 0x0F: Write Multiple Coils
  • function code 0x10: Write Multiple Registers
  • function code 0x17: Read/Write Multiple Registers

These functionalities are yet to be implemented:

  • serial networking
  • UDP networking
  • modbus RTU payload framing
  • modbus ASCII payload framing
  • function code 0x07: Read Exception Status
  • function code 0x08: Diagnostics
  • function code 0x0B: Get Comm Event Counter
  • function code 0x0C: Get Comm Event Log
  • function code 0x11: Report Slave ID
  • function code 0x14: Read File Record
  • function code 0x15: Write File Record
  • function code 0x16: Mask Write Registers
  • function code 0x18: Read FIFO Queue
  • function code 0x2B: Encapsulated Interface Transport

Installation

Use the following command in a go mod initialized project.

go get github.com/GoAethereal/modbus

Documentation

Overview

Package modbus offers functions and definitions for communicating with modbus compliant devices.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrMismatchedTransactionId indicates that a received modbus server response did not match
	// the expected request. This error can only occurs in TCP-framing mode, where it´s allowed
	// to send multiple parallel request, without waiting for each response.
	// The individual requests are identified by their transaction id.
	// A mismatch therefore means that the response was not intended for the message in question.
	// As a result it should be waited for the next response instead.
	//	NOTICE:
	// This error is handled inside the modbus package and will never be escalated outside the
	// package scope.
	ErrMismatchedTransactionId = errors.New("modbus: mismatch of transaction id")
	// ErrMismatchedProtocolId signals a mismatch of the protocol identifier field.
	// A normal response is expected to this value copied from the request.
	ErrMismatchedProtocolId = errors.New("modbus: mismatch of protocol id")
	// ErrMismatchedUnitId signals a mismatch of the unit identifier field.
	// A normal response is expected to this value copied from the request.
	ErrMismatchedUnitId = errors.New("modbus: mismatch of unit id")
	// ErrDataSizeExceeded indicates that the given data length exceeds the limits of a modbus
	// package payload.
	ErrDataSizeExceeded = errors.New("modbus: data size exceeds limit")
	// ErrInvalidParameter signals a malformed input.
	ErrInvalidParameter = errors.New("modbus: given parameter violates restriction")
)

Functions

This section is empty.

Types

type Client

type Client struct {
	Config
	// contains filtered or unexported fields
}

Client is the go implementation of a modbus master. Generally the intended use is as follows:

c := modbus.Client{Config: modbus.Config{
	Mode:     "tcp",
	Kind:     "tcp",
	Endpoint: "localhost:502",
}}
defer c.Disconnect()

//use the client`s read/write methods like c.ReadCoils, etc

func (*Client) Disconnect

func (c *Client) Disconnect()

Disconnect shuts down the connection. All running requests will be canceled as a result.

func (*Client) ReadCoils

func (c *Client) ReadCoils(ctx cancel.Context, uid byte, address, quantity uint16) (status []bool, err error)

ReadCoils requests 1 to 2000 (quantity) contiguous coil states, starting from address. On success returns a bool slice with size of quantity where false=OFF and true=ON.

func (*Client) ReadDiscreteInputs

func (c *Client) ReadDiscreteInputs(ctx cancel.Context, uid byte, address, quantity uint16) (status []bool, err error)

ReadDiscreteInputs requests 1 to 2000 (quantity) contiguous discrete inputs, starting from address. On success returns a bool slice with size of quantity where false=OFF and true=ON.

func (*Client) ReadHoldingRegisters

func (c *Client) ReadHoldingRegisters(ctx cancel.Context, uid byte, address, quantity uint16) (values []byte, err error)

ReadHoldingRegisters reads from 1 to 125 (quantity) contiguous holding registers starting at address. On success returns a byte slice with the response data which is 2*quantity in length.

func (*Client) ReadInputRegisters

func (c *Client) ReadInputRegisters(ctx cancel.Context, uid byte, address, quantity uint16) (values []byte, err error)

ReadInputRegisters reads from 1 to 125 (quantity) contiguous input registers starting at address. On success returns a byte slice with the response data which is 2*quantity in length.

func (*Client) ReadWriteMultipleRegisters

func (c *Client) ReadWriteMultipleRegisters(ctx cancel.Context, uid byte, rAddress, rQuantity, wAddress uint16, values []byte) (res []byte, err error)

ReadWriteMultipleRegisters reads a contiguous block of holding registers (rQuantity) from rAddress. Also the values are written at wAddress.

func (*Client) Ready added in v0.0.6

func (c *Client) Ready() bool

func (*Client) Request

func (c *Client) Request(ctx cancel.Context, uid, code byte, req []byte) (res []byte, err error)

Request encodes the request into a valid application data unit and sends it to the clients endpoint. Only function codes below 0x80 are accepted. The method will return a nil response and an error if something went wrong.

func (*Client) WriteMultipleCoils

func (c *Client) WriteMultipleCoils(ctx cancel.Context, uid byte, address uint16, status ...bool) (err error)

WriteMultipleCoils sets the state of all coils starting at address to the value of status, where false=OFF and true=ON. Status needs to be of length 1 to 1968.

func (*Client) WriteMultipleRegisters

func (c *Client) WriteMultipleRegisters(ctx cancel.Context, uid byte, address uint16, values []byte) (err error)

WriteMultipleRegisters writes the values to the holding registers at address. Values must be a multiple of 2 and in the range of 2 to 246

func (*Client) WriteSingleCoil

func (c *Client) WriteSingleCoil(ctx cancel.Context, uid byte, address uint16, status bool) (err error)

WriteSingleCoil sets the output of the coil at address to ON=true or OFF=false.

func (*Client) WriteSingleRegister

func (c *Client) WriteSingleRegister(ctx cancel.Context, uid byte, address, value uint16) (err error)

WriteSingleRegister writes value to a single holding register at address.

type Config added in v0.0.2

type Config struct {
	// Mode defines the communication framing
	// valid modes are:
	//	- tcp
	//	- rtu	(ToDo)
	//	- ascii	(ToDo)
	Mode string
	// Kind specifies the underlying network layer
	// valid kinds are:
	//	- tcp
	//	- udp 		(ToDo)
	//	- serial	(ToDo)
	Kind string
	// Endpoint used for connecting to (client) or listening on (server)
	Endpoint string
}

Config are used to configure a modbus client or server

func (*Config) Verify added in v0.0.2

func (cfg *Config) Verify() error

Verify validates the modbus.Options, thereby checking for invalid parameter. If the options are valid no error (nil) is returned.

type Exception

type Exception byte

Exception represents a modbus exception as defined by the specification. It´s a superset of the error interface.

const (
	// IllegalFunction - Exception code 0x01
	//
	// The function code received in the query is not an allowable action for the server (or slave). This
	// may be because the function code is only applicable to newer devices, and was not
	// implemented in the unit selected. It could also indicate that the server (or slave) is in the wrong
	// state to process a request of this type, for example because it is not configured and is being
	// asked to return register values.
	IllegalFunction Exception = 0x01
	// IllegalDataAddress - Exception code 0x02
	//
	// The data address received in the query is not an allowable address for the server (or slave). More
	// specifically, the combination of reference number and transfer length is invalid. For a controller with
	// 100 registers, the PDU addresses the first register as 0, and the last one as 99. If a request
	// is submitted with a starting register address of 96 and a quantity of registers of 4, then this request
	// will successfully operate (address-wise at least) on registers 96, 97, 98, 99. If a request is
	// submitted with a starting register address of 96 and a quantity of registers of 5, then this request
	// will fail with Exception Code 0x02 “Illegal Data Address” since it attempts to operate on registers
	// 96, 97, 98, 99 and 100, and there is no register with address 100.
	IllegalDataAddress Exception = 0x02
	// IllegalDataValue - Exception code 0x03
	//
	// A value contained in the query data field is not an allowable value for server (or slave). This
	// indicates a fault in the structure of the remainder of a complex request, such as that the implied
	// length is incorrect. It specifically does NOT mean that a data item submitted for storage in a register
	// has a value outside the expectation of the application program, since the MODBUS protocol
	// is unaware of the significance of any particular value of any particular register.
	IllegalDataValue Exception = 0x03
	// SlaveDeviceFailure - Exception code 0x04
	//
	// An unrecoverable error occurred while the server (or slave) was attempting to perform the
	// requested action.
	SlaveDeviceFailure Exception = 0x04
	// Acknowledge - Exception code 0x05
	//
	// Specialized use in conjunction with programming commands. The server (or slave) has accepted the request
	// and is processing it, but a long duration of time will be required to do so. This response is
	// returned to prevent a timeout error from occurring in the client (or master). The client (or master)
	// can next issue a Poll Program Complete message to determine if processing is completed.
	Acknowledge Exception = 0x05
	// SlaveDeviceBusy - Exception code 0x06
	//
	// Specialized use in conjunction with programming commands. The server (or slave) is engaged in processing a
	// long–duration program command. The client (or master) should retransmit the message later when
	// the server (or slave) is free
	SlaveDeviceBusy Exception = 0x06
	// MemoryParityError - Exception code 0x08
	//
	// Specialized use in conjunction with function codes 20 and 21 and reference type 6, to indicate that
	// the extended file area failed to pass a consistency check. The server (or slave) attempted to read record
	// file, but detected a parity error in the memory. The client (or master) can retry the request, but
	// service may be required on the server (or slave) device.
	MemoryParityError Exception = 0x08
	// GatewayPathUnavailable - Exception code 0x0A
	//
	// Specialized use in conjunction with gateways, indicates that the gateway was unable to allocate
	// an internal communication path from the input port to the output port for processing the request.
	// Usually means that the gateway is misconfigured or overloaded.
	GatewayPathUnavailable Exception = 0x0A
	// GatewayTargetDeviceFailedToRespond - Exception code 0x0B
	//
	// Specialized use in conjunction with gateways, indicates that no response was obtained from the
	// target device. Usually means that the device is not present on the network.
	GatewayTargetDeviceFailedToRespond Exception = 0x0B
)

func (Exception) Error added in v0.0.2

func (ex Exception) Error() string

Error returns a human readable string representing the underlying exception.

type Handler

type Handler interface {
	Handle(ctx cancel.Context, uid, code byte, req []byte) (res []byte, ex Exception)
}

Handler is firstly and foremost used by the modbus.Server. The Handle method describes how incoming messages are managed.

type Mux

type Mux struct {
	Fallback                   func(ctx cancel.Context, uid, code byte, req []byte) (res []byte, ex Exception)
	ReadCoils                  func(ctx cancel.Context, uid byte, address, quantity uint16) (res []bool, ex Exception)
	ReadDiscreteInputs         func(ctx cancel.Context, uid byte, address, quantity uint16) (res []bool, ex Exception)
	ReadHoldingRegisters       func(ctx cancel.Context, uid byte, address, quantity uint16) (res []byte, ex Exception)
	ReadInputRegisters         func(ctx cancel.Context, uid byte, address, quantity uint16) (res []byte, ex Exception)
	WriteSingleCoil            func(ctx cancel.Context, uid byte, address uint16, status bool) (ex Exception)
	WriteSingleRegister        func(ctx cancel.Context, uid byte, address, value uint16) (ex Exception)
	WriteMultipleCoils         func(ctx cancel.Context, uid byte, address uint16, status []bool) (ex Exception)
	WriteMultipleRegisters     func(ctx cancel.Context, uid byte, address uint16, values []byte) (ex Exception)
	ReadWriteMultipleRegisters func(ctx cancel.Context, uid byte, rAddress, rQuantity, wAddress uint16, values []byte) (res []byte, ex Exception)
}

Mux implements the modbus.Handler interface and is intended to be used as a server side request multiplexer. When called by the server it will redirect the inbound message to the given function. If the callback is not set the Mux will return the modbus.ExIllegalFunction exception to the server. In case of an unknown function code the Fallback function, if set, will be executed. All given functions must be safe for use by multiple go routines.

func (*Mux) Handle

func (h *Mux) Handle(ctx cancel.Context, uid byte, code byte, req []byte) (res []byte, ex Exception)

Handle dispatches incoming requests depending on their function code to the correlating callbacks as defined inside the Mux.

type Server

type Server struct {
	Config
	// contains filtered or unexported fields
}

Server is the go implementation of a modbus slave. Once serving it will listen for incoming requests and forward them to the modbus.Handler h. Generally the intended use is as follows:

ctx := cancel.New()
cfg := modbus.Config{
	Mode:     "tcp",
	Kind:     "tcp",
	Endpoint: "localhost:502",
}
s := cfg.Server()
h := &modbus.Mux{/*define individual handlers*/}

log.Fatal(s.Serve(ctx,h))

func (*Server) Serve

func (s *Server) Serve(ctx cancel.Context, h Handler) error

Serve starts the modbus server and listens for incoming requests. The Handler h is called for each inbound message. h must be safe for use by multiple go routines.

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

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