modbusclient

package module
v0.0.0-...-4473963 Latest Latest
Warning

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

Go to latest
Published: Jun 26, 2020 License: MIT Imports: 10 Imported by: 0

README

go-modbus

About

This Go package provides Modbus access for client (master) applications to communicate with server (slave) devices, over both TCP/IP and Serial Line/RTU/ASCII frame protocols.

Note that in modbus terminology, client refers to the master application or device, and the server is the slave waiting to respond to instructions, as shown in this transaction diagram:

Modbus Transaction

This code was originally forked from lubia/modbus and repositioned as a pure client (master) library for use by controller applications.

Installation and Usage

Install the package in your environment with these commands (the RTU code now depends on goserial):

go get github.com/tarm/goserial
go get github.com/dpapathanasiou/go-modbus

Next, build and run the examples:

Enabling the USB Serial Port adapter (RS-232) for RTU/ASCII Access

Slave devices which have USB ports for RTU access will not work immediately upon hot-plugging into a master computer.

For master devices running linux, the USB serial port adapter must be explicitly activated using the usbserial linux kernel module, as follows:

  1. Immediately after plugging in the serial port USB, use dmesg to find the vendor and product ID numbers:
$ sudo dmesg | tail

There should be a line which looks like this:

[  556.572417] usb 3-1: New USB device found, idVendor=04d8, idProduct=000c
  1. Use the usbserial linux kernel module to enable it, using the same vendor and product ID numbers from the dmesg output:
$ sudo modprobe usbserial vendor=0x04d8 product=0x000c
  1. Confirm that the serial port is attached to a specific tty device file:
$ sudo dmesg | tail

There should now be a line like this:

[ 2134.866724] usb 3-1: generic converter now attached to ttyUSB0

which means that the serial port is now programmatically accessible via /dev/ttyUSB0

References

Acknowledgements

Documentation

Index

Constants

View Source
const (
	MODBUS_PORT         = 502
	RTU_FRAME_MAXSIZE   = 512
	ASCII_FRAME_MAXSIZE = 512
	TCP_FRAME_MAXSIZE   = 260

	FUNCTION_READ_COILS                    = 0x01
	FUNCTION_READ_DISCRETE_INPUTS          = 0x02
	FUNCTION_READ_HOLDING_REGISTERS        = 0x03
	FUNCTION_READ_INPUT_REGISTERS          = 0x04
	FUNCTION_WRITE_SINGLE_COIL             = 0x05
	FUNCTION_WRITE_SINGLE_REGISTER         = 0x06
	FUNCTION_WRITE_MULTIPLE_REGISTERS      = 0x10
	FUNCTION_MODBUS_ENCAPSULATED_INTERFACE = 0x2B

	EXCEPTION_UNSPECIFIED = 0x00 // catch-all for unspecified modbus errors

	EXCEPTION_ILLEGAL_FUNCTION                        = 0x01
	EXCEPTION_DATA_ADDRESS                            = 0x02
	EXCEPTION_DATA_VALUE                              = 0x03
	EXCEPTION_SLAVE_DEVICE_FAILURE                    = 0x04
	EXCEPTION_ACKNOWLEDGE                             = 0x05
	EXCEPTION_SLAVE_DEVICE_BUSY                       = 0x06
	EXCEPTION_MEMORY_PARITY_ERROR                     = 0x08
	EXCEPTION_GATEWAY_PATH_UNAVAILABLE                = 0x0A
	EXCEPTION_GATEWAY_TARGET_DEVICE_FAILED_TO_RESPOND = 0x0B
	EXCEPTION_BAD_CHECKSUM                            = 0xff // this is not official
)

Variables

View Source
var MODBUS_EXCEPTIONS = map[uint16]error{
	EXCEPTION_UNSPECIFIED:                             errors.New("Modbus Error"),
	EXCEPTION_ILLEGAL_FUNCTION:                        errors.New("Modbus Error: Illegal Function (0x01)"),
	EXCEPTION_DATA_ADDRESS:                            errors.New("Modbus Error: Data Address (0x02)"),
	EXCEPTION_DATA_VALUE:                              errors.New("Modbus Error: Data Value (0x03)"),
	EXCEPTION_SLAVE_DEVICE_FAILURE:                    errors.New("Modbus Error: Slave Device Failure (0x04)"),
	EXCEPTION_ACKNOWLEDGE:                             errors.New("Modbus Error: Acknowledge (0x05)"),
	EXCEPTION_SLAVE_DEVICE_BUSY:                       errors.New("Modbus Error: Slave Device Busy (0x06)"),
	EXCEPTION_MEMORY_PARITY_ERROR:                     errors.New("Modbus Error: Memory Parity Error (0x08)"),
	EXCEPTION_GATEWAY_PATH_UNAVAILABLE:                errors.New("Modbus Error: Gateway Path Unavailable (0x0A)"),
	EXCEPTION_GATEWAY_TARGET_DEVICE_FAILED_TO_RESPOND: errors.New("Modbus Error: Gateway Target Device Failed to Respond (0x0B)"),
	EXCEPTION_BAD_CHECKSUM:                            errors.New("Modbus Error: Bad Checksum"),
}

Functions

func ASCIIRead

func ASCIIRead(serialDeviceConnection io.ReadWriteCloser, slaveAddress, functionCode byte, startRegister, numRegisters uint16, timeOut int, debug bool) ([]byte, error)

ASCIIRead performs the given modbus Read function over ASCII to the given serialDevice, using the given frame data

func ASCIIWrite

func ASCIIWrite(serialDeviceConnection io.ReadWriteCloser, slaveAddress, functionCode byte, startRegister, numRegisters uint16, data []byte, timeOut int, debug bool) ([]byte, error)

ASCIIWrite performs the given modbus Write function over ASCII to the given serialDevice, using the given frame data

func ConnectASCII

func ConnectASCII(serialDevice string, baudRate int) (io.ReadWriteCloser, error)

ConnectASCII attempts to access the Serial Device for subsequent ASCII writes and response reads from the modbus slave device

func ConnectRTU

func ConnectRTU(serialDevice string, baudRate int) (io.ReadWriteCloser, error)

ConnectRTU attempts to access the Serial Device for subsequent RTU writes and response reads from the modbus slave device

func ConnectTCP

func ConnectTCP(server string, port int) (net.Conn, error)

ConnectTCP attempts to make a tcp connection to the given server/port and returns the connection object (or nil, if fail) and an error (which will be nil on success)

func DecodeHiLo

func DecodeHiLo(data []byte) (int16, error)

DecodeHiLo attempts to convert a byte array of High/Low Byte values into a 16-bit integer, and returns the result, also with an error, which will be non-nil if the decoding failed.

func DisconnectASCII

func DisconnectASCII(ctx io.ReadWriteCloser)

DisconnectASCII closes the underlying Serial Device connection

func DisconnectRTU

func DisconnectRTU(ctx io.ReadWriteCloser)

DisconnectRTU closes the underlying Serial Device connection

func DisconnectTCP

func DisconnectTCP(conn net.Conn)

func Lrc

func Lrc(data []byte) uint8

func RTURead

func RTURead(serialDeviceConnection io.ReadWriteCloser, slaveAddress, functionCode byte, startRegister, numRegisters uint16, timeOut int, debug bool) ([]byte, error)

RTURead performs the given modbus Read function over RTU to the given serialDevice, using the given frame data

func RTUWrite

func RTUWrite(serialDeviceConnection io.ReadWriteCloser, slaveAddress, functionCode byte, startRegister, numRegisters uint16, data []byte, timeOut int, debug bool) ([]byte, error)

RTUWrite performs the given modbus Write function over RTU to the given serialDevice, using the given frame data

func TCPRead

func TCPRead(conn net.Conn, timeOut, transactionID int, functionCode byte, serialBridge bool, slaveAddress byte, data []byte, debug bool) ([]byte, error)

TCPRead performs the given modbus Read function over TCP to the given host/port combination, using the given frame data

func TCPWrite

func TCPWrite(conn net.Conn, timeOut, transactionID int, functionCode byte, serialBridge bool, slaveAddress byte, data []byte, debug bool) ([]byte, error)

TCPWrite performs the given modbus Write function over TCP to the given host/port combination, using the given frame data

func ValidFunction

func ValidFunction(fnCode byte) bool

ValidFunction returns a boolean, depending on whether or not the given code corresponds to a valid modbus function code, read, write, or interface

func ValidReadFunction

func ValidReadFunction(fnCode byte) bool

ValidReadFunction returns a boolean, depending on whether or not the given code corresponds to a valid modbus read function code

func ValidWriteFunction

func ValidWriteFunction(fnCode byte) bool

ValidWriteFunction returns a boolean, depending on whether or not the given code corresponds to a valid modbus write function code

Types

type ASCIIFrame

type ASCIIFrame struct {
	TimeoutInMilliseconds int
	SlaveAddress          byte
	FunctionCode          byte
	StartRegister         uint16
	NumberOfRegisters     uint16
	Data                  []byte
}

func (*ASCIIFrame) GenerateASCIIFrame

func (frame *ASCIIFrame) GenerateASCIIFrame() []byte

GenerateASCIIFrame is a method corresponding to a ASCIIFrame object which returns a byte array representing the associated serial line/ASCII application data unit (ADU)

type RTUFrame

type RTUFrame struct {
	TimeoutInMilliseconds int
	SlaveAddress          byte
	FunctionCode          byte
	StartRegister         uint16
	NumberOfRegisters     uint16
	Data                  []byte
}

func (*RTUFrame) GenerateRTUFrame

func (frame *RTUFrame) GenerateRTUFrame() []byte

GenerateRTUFrame is a method corresponding to a RTUFrame object which returns a byte array representing the associated serial line/RTU application data unit (ADU)

type TCPFrame

type TCPFrame struct {
	TimeoutInMilliseconds  int
	DebugTrace             bool
	TransactionID          int
	FunctionCode           byte
	EthernetToSerialBridge bool
	SlaveAddress           byte
	Data                   []byte
}

func (*TCPFrame) GenerateTCPFrame

func (frame *TCPFrame) GenerateTCPFrame() []byte

GenerateTCPFrame is a method corresponding to a TCPFrame object which returns a byte array representing the associated TCP/IP application data unit (ADU)

func (*TCPFrame) TransmitAndReceive

func (frame *TCPFrame) TransmitAndReceive(conn net.Conn) ([]byte, error)

TransmitAndReceive is a method corresponding to a TCPFrame object which generates the corresponding ADU, transmits it to the modbus server (slave device) specified by the TCP address+port, and returns a byte array of the slave device's reply, and error (if any)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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