modbusclient

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

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

Go to latest
Published: Aug 18, 2014 License: MIT Imports: 9 Imported by: 9

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 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 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


3. 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 <tt>/dev/ttyUSB0</tt>

## References
- [Modbus Technical Specifications](http://www.modbus.org/specs.php)
- [Modbus Interface Tutorial](http://www.lammertbies.nl/comm/info/modbus.html)
- [Modbus TCP/IP Overview](http://www.rtaautomation.com/modbustcp/)
- [Modbus RTU Protocol Overview](http://www.rtaautomation.com/modbusrtu/)

## Acknowledgements
- [Lubia Yang](http://www.lubia.me) for the [original modbus code](https://github.com/lubia/modbus) in Go
- [l.lefebvre](http://source.perl.free.fr/) for his excellent [modbus client](https://github.com/sourceperl/MBclient) and [server (slave device simulator)](https://github.com/sourceperl/mbserverd) code repositories
- [Tarmigan Casebolt](https://github.com/tarm/) for his [goserial](https://github.com/tarm/goserial) library, which resolved connection issues in RTU mode
- [modbusdriver.com](http://www.modbusdriver.com/) for their free [Diagslave Modbus Slave Simulator](http://www.modbusdriver.com/diagslave.html) tool
- [Mohammad Hafiz (mypapit)](https://plus.google.com/113437861006502895279?rel=author) for his well-written [How to enable USB-Serial Port adapter (RS-232) in Ubuntu Linux](http://blog.mypapit.net/2008/05/how-to-use-usb-serial-port-converter-in-ubuntu.html) blog post

Documentation

Index

Constants

View Source
const (
	MODBUS_PORT       = 502
	RTU_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 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 DisconnectRTU

func DisconnectRTU(ctx io.ReadWriteCloser)

DisconnectRTU closes the underlying Serial Device connection

func DisconnectTCP

func DisconnectTCP(conn net.Conn)

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 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