peamodbus

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

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

Go to latest
Published: Nov 7, 2023 License: MIT Imports: 7 Imported by: 0

README

go.dev reference Go Report Card Go codecov

peamodbus

Fault tolerant, TCP modbus implementation in Go that just works. Apt for embedded systems.

This is a WIP.

Protocol sequence diagram:

Mermaid Sequence diagram

sequenceDiagram
    participant Client
    participant Server
    
    critical No requests pending
        note left of Client: peamodbus.Tx.Request*()
        Client ->>+ Server: Request data read or write
        note right of Server: peamodbus.Rx.ReceiveRequest()
        option Handle request on server side
        Server --> Server: Identify func. code and validate request.
        note right of Server: peamodbus.Receive*Response()
        Server --> Server: Access modbus data, read or write.
        note right of Server: peamodbus.Receive*Response()
        option Write response
        note right of Server: peamodbus.Request.PutResponse()
        Server ->>- Client: Write response (nominal or exception)
        note left of Client: peamodbus.Receive*Response()
    end

Examples

See up to date examples in examples directory. These are just copy pasted from there and may occasionally be out of date.

Modbus Server via TCP
Click to see TCP example
package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/soypat/peamodbus"
	"github.com/soypat/peamodbus/modbustcp"
)

// This program creates a modbus server that adds 1 to
// all holding registers on every client request.

func main() {
	dataBank := peamodbus.ConcurrencySafeDataModel(&peamodbus.BlockedModel{})
	sv, err := modbustcp.NewServer(modbustcp.ServerConfig{
		Address:        "localhost:8080",
		ConnectTimeout: 5 * time.Second,
		DataModel:      dataBank,
	})
	if err != nil {
		log.Fatal(err)
	}
	ctx := context.Background()
	for {
		if !sv.IsConnected() {
			fmt.Println("attempting connection")
			err = sv.Accept(ctx)
			if err != nil {
				log.Println("error connecting", err)
			}
			time.Sleep(time.Second)
			continue
		}
		err = sv.HandleNext()
		if err != nil {
			log.Println("error in HandleNext", err)
			time.Sleep(time.Second)
		} else {
			for addr := 0; addr < 125; addr++ {
				value, exc := dataBank.GetHoldingRegister(addr)
				if exc != 0 {
					panic(exc.Error())
				}
				dataBank.SetHoldingRegister(addr, value+1)
			}
		}
		if err := sv.Err(); err != nil {
			log.Println("server error:", err)
		}
	}
}
Modbus Client RTU via USB

Reads from 2 registers in an instrument connected on a port using the go.bug.st/serial library.

Click to see RTU example
package main

import (
	"io"
	"os"
	"time"

	"github.com/soypat/peamodbus/modbusrtu"
	"go.bug.st/serial"
	"golang.org/x/exp/slog"
)

func main() {
	const (
		deviceAddress         = 86
		sensorRegisterAddress = 0
	)

	port, err := serial.Open("/dev/ttyUSB0", &serial.Mode{
		BaudRate: 9600,
		DataBits: 8,
		Parity:   serial.NoParity,
		StopBits: serial.OneStopBit,
	})
	if err != nil {
		panic(err)
	}
	defer port.Close()

	logfp, _ := os.Create("log.txt")
	defer logfp.Close()

	logger := slog.New(slog.NewTextHandler(io.MultiWriter(os.Stdout, logfp), &slog.HandlerOptions{
		Level: slog.LevelDebug,
	}))

	c := modbusrtu.NewClient(modbusrtu.ClientConfig{
		Logger: logger,
	})

	c.SetTransport(port)
	for {
		var tempHumidity [2]uint16
		err = c.ReadHoldingRegisters(deviceAddress, sensorRegisterAddress, tempHumidity[:])
		if err != nil {
			panic(err)
		}
		logger.Info("read", "humidity", float32(tempHumidity[0])/10, "temperature", float32(tempHumidity[1])/10)
		time.Sleep(time.Second)
	}
}

Documentation

Overview

package peamodbus implements the modbus protocol for TCP networks.

Glossary

  • MBAP: Modbus Application Protocol. Used to differentiate between Modbus RTU which is lower level in character.
  • ADU: Application Data Unit. Encapsulates the PDU packet of data and some additional fields that are introduced by nature of the underlying network used.
  • PDU: Protocol Data Unit. Refers to packet of data with function code and data associated with said function. This is data relevant to the Modbus system.
  • MBAP Header: This refers to the segment of data that precedes the PDU in a Modbus request or response over TCP/IP.

MBAP Header

2 bytes | Transaction Identifier
2 bytes | Protocol Identifier. Is 0 for Modbus protocol
2 bytes | Length. Number of following bytes in PDU
1 byte  | Unit identifier: Identifies a remote slave connected on a serial line or other buses

Modbus Data Model

Data table type   | Structure  | Access     | Comments
Discrete Inputs   | Single bit | Read-only  | Data provided by an IO system
Coils             | Single bit | Read/Write | Alterable by application program
Input Registers   | 16bit word | Read-only  | Data provided by an IO system
Holding Registers | 16bit word | Read/Write | Alterable by application program

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrMissingPacketData = errors.New("missing packet data")
	ErrBadFunctionCode   = errors.New("bad function code")
)

Functions

func ReceiveDataResponse

func ReceiveDataResponse(pdu []byte) (data []byte, err error)

ReceiveDataResponse decodes a response packet for any of the following packets:

FCReadCoils, FCReadDiscreteInputs, FCReadHoldingRegisters, FCReadInputRegisters

func ReceiveSingleWriteResponse

func ReceiveSingleWriteResponse(pdu []byte) (addr, value uint16, err error)

ReceiveSingleWriteResponse

Types

type BlockedModel

type BlockedModel struct {
	// contains filtered or unexported fields
}

BlockedModel is a memory constrained DataModel implementation. Each data type (coil, registers) occupies its own block/segment of memory. A non-nil BlockedModel is ready for use after being declared.

func (*BlockedModel) GetCoil

func (sm *BlockedModel) GetCoil(i int) (bool, Exception)

GetCoil returns 1 if the coil at position i is set and 0 if it is not. Expects coil index in range 0..1999.

func (*BlockedModel) GetDiscreteInput

func (sm *BlockedModel) GetDiscreteInput(i int) (bool, Exception)

GetDiscreteInput returns 1 if the discrete input at position i is set and 0 if it is not. Expects discrete input index in range 0..1999.

func (*BlockedModel) GetHoldingRegister

func (dm *BlockedModel) GetHoldingRegister(i int) (uint16, Exception)

func (*BlockedModel) GetInputRegister

func (dm *BlockedModel) GetInputRegister(i int) (uint16, Exception)

func (*BlockedModel) SetCoil

func (sm *BlockedModel) SetCoil(i int, value bool) Exception

SetCoil sets the coil at position i to 1 if value is true and to 0 if value is false. Expects coil index in range 0..1999.

func (*BlockedModel) SetDiscreteInput

func (sm *BlockedModel) SetDiscreteInput(i int, value bool) Exception

SetDiscreteInput sets the discrete input at position i to 1 if value is true and 0 if it is false. Expects discrete input index in range 0..1999.

func (*BlockedModel) SetHoldingRegister

func (dm *BlockedModel) SetHoldingRegister(i int, v uint16) Exception

func (*BlockedModel) SetInputRegister

func (dm *BlockedModel) SetInputRegister(i int, v uint16) Exception

type DataInterpreter

type DataInterpreter struct {
	// contains filtered or unexported fields
}

DataInterpreter provides primitive data type reading and writing from and to modbus [DataModel]s.

func NewDataInterpreter

func NewDataInterpreter(cfg DataInterpreterConfig) (*DataInterpreter, error)

func (*DataInterpreter) Float32Holding

func (interpret *DataInterpreter) Float32Holding(dm DataModel, startIdx int) (float32, Exception)

Float32Holding interprets consecutive 32bit holding register data at startIdx as a floating point number.

func (*DataInterpreter) Float32Input

func (interpret *DataInterpreter) Float32Input(dm DataModel, startIdx int) (float32, Exception)

Float32Input interprets consecutive 32bit input register data at startIdx as a floating point number.

func (*DataInterpreter) Float64Holding

func (interpret *DataInterpreter) Float64Holding(dm DataModel, startIdx int) (float64, Exception)

Float64Holding interprets consecutive 64bit holding register data at startIdx as a floating point number.

func (*DataInterpreter) Float64Input

func (interpret *DataInterpreter) Float64Input(dm DataModel, startIdx int) (float64, Exception)

Float64Input interprets consecutive 64bit input register data at startIdx as a floating point number.

func (*DataInterpreter) Int16Holding

func (interpret *DataInterpreter) Int16Holding(dm DataModel, i int) (int16, Exception)

Int16Holding interprets the holding register at i as a signed 16 bit integer.

func (*DataInterpreter) Int16Input

func (interpret *DataInterpreter) Int16Input(dm DataModel, i int) (int16, Exception)

Int16Input interprets the input register at i as a signed 16 bit integer.

func (*DataInterpreter) Int32Holding

func (interpret *DataInterpreter) Int32Holding(dm DataModel, startIdx int) (int32, Exception)

Int32Holding interprets consecutive 32bit holding register data at startIdx as a signed integer.

func (*DataInterpreter) Int32Input

func (interpret *DataInterpreter) Int32Input(dm DataModel, startIdx int) (int32, Exception)

Int32Input interprets consecutive 32bit input register data at startIdx as a signed integer.

func (*DataInterpreter) Int64Holding

func (interpret *DataInterpreter) Int64Holding(dm DataModel, startIdx int) (int64, Exception)

Int64Holding interprets consecutive 64bit holding register data at startIdx as a signed integer.

func (*DataInterpreter) Int64Input

func (interpret *DataInterpreter) Int64Input(dm DataModel, startIdx int) (int64, Exception)

Int64Input interprets consecutive 64bit input register data at startIdx as a signed integer.

func (*DataInterpreter) PutFloat32Holding

func (interpret *DataInterpreter) PutFloat32Holding(dm DataModel, startIdx int, v float32) Exception

PutFloat32Holding stores a 32bit floating point number into 2 holding registers at startIdx.

func (*DataInterpreter) PutFloat32Input

func (interpret *DataInterpreter) PutFloat32Input(dm DataModel, startIdx int, v float32) Exception

PutFloat32Input stores a 32bit floating point number into 2 input registers at startIdx.

func (*DataInterpreter) PutFloat64Holding

func (interpret *DataInterpreter) PutFloat64Holding(dm DataModel, startIdx int, v float64) Exception

PutFloat64Holding stores a 64bit floating point number into 4 holding registers at startIdx.

func (*DataInterpreter) PutFloat64Input

func (interpret *DataInterpreter) PutFloat64Input(dm DataModel, startIdx int, v float64) Exception

PutFloat64Input stores a 64bit floating point number into 4 input registers at startIdx.

func (*DataInterpreter) PutUint32Holding

func (interpret *DataInterpreter) PutUint32Holding(dm DataModel, startIdx int, v uint32) Exception

PutUint32Holding stores a 32bit unsigned integer into 2 holding registers at startIdx.

func (*DataInterpreter) PutUint32Input

func (interpret *DataInterpreter) PutUint32Input(dm DataModel, startIdx int, v uint32) Exception

PutUint32Input stores a 32bit unsigned integer into 2 input registers at startIdx.

func (*DataInterpreter) PutUint64Holding

func (interpret *DataInterpreter) PutUint64Holding(dm DataModel, startIdx int, v uint64) Exception

PutUint64Holding stores a 64bit unsigned integer into 4 holding registers at startIdx.

func (*DataInterpreter) PutUint64Input

func (interpret *DataInterpreter) PutUint64Input(dm DataModel, startIdx int, v uint64) Exception

PutUint64Input stores a 64bit unsigned integer into 4 input registers at startIdx.

func (*DataInterpreter) ReadBytesHolding

func (interpret *DataInterpreter) ReadBytesHolding(dm DataModel, dst []byte, startIdx int) (int, Exception)

ReadBytesHolding reads data from the holding registers of the data model into dst starting at startIdx.

func (*DataInterpreter) ReadBytesInput

func (interpret *DataInterpreter) ReadBytesInput(dm DataModel, dst []byte, startIdx int) (int, Exception)

ReadBytesInput reads data from the input registers of the data model into dst starting at startIdx.

func (*DataInterpreter) ReadUint16Holding

func (interpret *DataInterpreter) ReadUint16Holding(dm DataModel, dst []uint16, startIdx int) (int, Exception)

ReadUint16Holding reads data from the holding registers of the data model into dst starting at startIdx.

func (*DataInterpreter) ReadUint16Input

func (interpret *DataInterpreter) ReadUint16Input(dm DataModel, dst []uint16, startIdx int) (int, Exception)

ReadUint16Input reads data from the input registers of the data model into dst starting at startIdx.

func (*DataInterpreter) Uint32Holding

func (interpret *DataInterpreter) Uint32Holding(dm DataModel, startIdx int) (v uint32, _ Exception)

Uint32Holding interprets consecutive 32bit holding register data at startIdx as a unsigned integer.

func (*DataInterpreter) Uint32Input

func (interpret *DataInterpreter) Uint32Input(dm DataModel, startIdx int) (v uint32, _ Exception)

Uint32Input interprets consecutive 32bit input register data at startIdx as a unsigned integer.

func (*DataInterpreter) Uint64Holding

func (interpret *DataInterpreter) Uint64Holding(dm DataModel, startIdx int) (v uint64, _ Exception)

Uint64Holding interprets consecutive 64bit holding register data at startIdx as a unsigned integer.

func (*DataInterpreter) Uint64Input

func (interpret *DataInterpreter) Uint64Input(dm DataModel, startIdx int) (v uint64, _ Exception)

Uint64Input interprets consecutive 64bit input register data at startIdx as a unsigned integer.

func (*DataInterpreter) WriteBytesHolding

func (interpret *DataInterpreter) WriteBytesHolding(dm DataModel, data []byte, startIdx int) (int, Exception)

WriteBytesHolding writes the data byte slice into the holding registers of the data model starting at startIdx.

func (*DataInterpreter) WriteBytesInput

func (interpret *DataInterpreter) WriteBytesInput(dm DataModel, data []byte, startIdx int) (int, Exception)

WriteBytesInput writes the data byte slice into the input registers of the data model starting at startIdx.

func (*DataInterpreter) WriteUint16Holding

func (interpret *DataInterpreter) WriteUint16Holding(dm DataModel, data []uint16, startIdx int) (int, Exception)

WriteUint16Holding writes the 16bit data slice into the holding registers of the data model starting at startIdx.

func (*DataInterpreter) WriteUint16Input

func (interpret *DataInterpreter) WriteUint16Input(dm DataModel, data []uint16, startIdx int) (int, Exception)

WriteUint16Input writes the 16bit data slice into the input registers of the data model starting at startIdx.

type DataInterpreterConfig

type DataInterpreterConfig struct {
	// BadFloat is the value to return when a float conversion fails.
	// Ideally the exception should be checked and the value ignored.
	BadFloat float64
	// MostSignificantWordFirst can be set to interpret contiguous modbus 16bit register data
	// as having the first 16bit register be the most significant word (MSW).
	// If not set the first 16bit register is the least significant word (LSW).
	MostSignificantWordFirst bool
}

type DataModel

type DataModel interface {
	// GetCoil checks if coil at position i is set.
	GetCoil(i int) (bool, Exception)
	// SetCoil sets the coil at position i to b.
	SetCoil(i int, b bool) Exception

	// GetDiscreteInput checks if discrete input at position i is set.
	GetDiscreteInput(i int) (bool, Exception)
	// SetDiscreteInput sets the discrete input at position i to b.
	SetDiscreteInput(i int, b bool) Exception

	// GetInputRegister returns the 16-bit value of the input register at position i.
	GetInputRegister(i int) (uint16, Exception)
	// SetInputRegister sets the 16-bit value of the input register at position i.
	SetInputRegister(i int, value uint16) Exception

	// GetHoldingRegister returns the 16-bit value of the holding register at position i.
	GetHoldingRegister(i int) (uint16, Exception)
	// SetHoldingRegister sets the 16-bit value of the holding register at position i.
	SetHoldingRegister(i int, value uint16) Exception
}

DataModel is the core abstraction of the register data in the modbus protocol. The definition of this interface allows for abstract representations of the Modbus data allowing for low memory representations of registers that are ideal for microcontrollers. An explicit representation of Modbus memory (BlockedModel) occupies a kilobyte, This could be reduced to just 2 bytes for a controller that just operates a 16bit sensor.

func ConcurrencySafeDataModel

func ConcurrencySafeDataModel(dm DataModel) DataModel

ConcurrencySafeDataModel returns a DataModel that is safe for concurrent use from a existing datamodel.

type Exception

type Exception uint8

Exception represents a modbus Exception Code. Appears as section 6.7 in the modbus specification. A Value of 0 is equivalent to no exception.

const (
	// ExceptionNone indicates no exception has ocurred.
	ExceptionNone Exception = iota
	// The function code received in the query is not an allowable action for the slave.
	// If a Poll Program Complete command was issued, this code indicates that no
	// program function preceded it.
	ExceptionIllegalFunction
	//  The data address received in the query is not an allowable address for the slave.
	ExceptionIllegalDataAddr
	// A value contained in the query data field is not an allowable value for the slave.
	ExceptionIllegalDataValue
	// An unrecoverable error occurred while the slave was attempting to perform the requested action.
	ExceptionDeviceFailure
	// The 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 master. The master can next issue a Poll Program
	// Complete message to determine if processing is completed.
	ExceptionAcknowledge
	// The slave is engaged in processing a long–duration program command.
	// The master should retransmit the message later when the slave is free.
	ExceptionDeviceBusy
	// The slave cannot perform the program function received in the query.
	// This code is returned for an unsuccessful programming request using function
	// code 13 or 14 decimal. The master should request diagnostic or error information from the slave
	ExceptionNegativeAcknowledge
	// The slave detected a parity error in the memory. The master can retry the request,
	// but service may be required on the slave device.
	ExceptionMemoryParityError
)

func (Exception) Error

func (e Exception) Error() (s string)

func (Exception) PutResponse

func (e Exception) PutResponse(dst []byte, fc FunctionCode)

PutResponse writes the 2 byte error+exception codes to the destination slice. If there is not enough space in dst, PutResponse panics.

type FunctionCode

type FunctionCode uint8
const (
	// FCReadCoils a.k.a ReadDiscreteOutputs.
	// Request:
	//  0    1        2           3         4         5
	//  | FC | StartAddr (uint16) | Quantity (uint16) |
	// Response:
	//  0    1             2            2+n+X   where X=n%8 == 0 ? 0 : 1
	//  | FC | ByteCount=n | Coil status |
	FCReadCoils                  FunctionCode = 0x01
	FCReadDiscreteInputs         FunctionCode = 0x02
	FCReadHoldingRegisters       FunctionCode = 0x03
	FCReadInputRegisters         FunctionCode = 0x04
	FCWriteSingleCoil            FunctionCode = 0x05
	FCWriteSingleRegister        FunctionCode = 0x06 // Holding register.
	FCWriteMultipleRegisters     FunctionCode = 0x10 // Holding registers.
	FCReadFileRecord             FunctionCode = 0x14
	FCWriteFileRecord            FunctionCode = 0x15
	FCMaskWriteRegister          FunctionCode = 0x16
	FCReadWriteMultipleRegisters FunctionCode = 0x17
	FCReadFIFOQueue              FunctionCode = 0x18
	FCWriteMultipleCoils         FunctionCode = 0x0F
)

Data access function codes.

const (
	FCReadExceptionStatus      FunctionCode = 0x07
	FCDiagnostic               FunctionCode = 0x08
	FCGetComEventCounter       FunctionCode = 0x0B
	FCGetComEventLog           FunctionCode = 0x0C
	FCReportServerID           FunctionCode = 0x11
	FCReadDeviceIdentification FunctionCode = 0x2B
)

Diagnostic function codes.

func InferRequestPacketLength

func InferRequestPacketLength(b []byte) (fc FunctionCode, n uint16, err error)

InferRequestPacketLength returns the expected length of a client (master) request PDU in bytes by looking at the function code as the first byte of the packet and the contained data in the packet.

If there is not enough data in the packet to infer the length of the packet then InferResponsePacketLength returns ErrMissingPacketData and the number of bytes needed to be able to infer the packet length while guaranteeing no over-reads.

May return a peamodbus exception code if the function code is not implemented.

func InferResponsePacketLength

func InferResponsePacketLength(b []byte) (fc FunctionCode, n uint16, err error)

InferResponsePacketLength returns the expected length of a server (instrument) response PDU in bytes by looking at the function code as the first byte of the response packet and the contained data in the packet.

If there is not enough data in the packet to infer the length of the packet then InferResponsePacketLength returns ErrMissingPacketData and the number of bytes needed to be able to infer the packet length.

func (FunctionCode) IsRead

func (fc FunctionCode) IsRead() bool

IsRead returns true if fc is an exclusively read operation. Returns false if fc is a read/write operation.

func (FunctionCode) IsWrite

func (fc FunctionCode) IsWrite() bool

IsWrite returns true if fc is an exclusively write operation. Returns false if fc is a read/write operation.

func (FunctionCode) String

func (fc FunctionCode) String() (s string)

String returns a human readable string representation of the function code.

type Request

type Request struct {
	FC FunctionCode
	// contains filtered or unexported fields
}

Request is a client (master) request meant for a server (instrument).

func DecodeRequest

func DecodeRequest(pdu []byte) (req Request, dataoffset int, err error)

DecodeRequest parses a request packet and returns the request and the offset into the packet where the data starts, if there is any.

func (*Request) PutResponse

func (req *Request) PutResponse(model DataModel, dst, data []byte) (packetLenWritten int, err error)

PutResponse writes the response to the receiver Request into dst.

Returns a Exception returned by DataModel or if function code is not implemented.

func (Request) String

func (req Request) String() string

type Tx

type Tx struct{}

Tx provides the low level functions that marshal modbus packets onto byte slices.

If implementing a modbus server it is very likely one will not interact with Tx directly but rather use the higher level PutResponse method of Request.

func (*Tx) RequestReadCoils

func (tx *Tx) RequestReadCoils(dst []byte, startAddr, quantityOfCoils uint16) (int, error)

RequestReadCoils writes packet to dst used to read from 1 to 2000 contiguous status of coils in a remote device. startAddr must be in 0x0000..0xFFFF. quantityOfCoils must be in 1..2000.

func (*Tx) RequestReadDiscreteInputs

func (tx *Tx) RequestReadDiscreteInputs(dst []byte, startAddr, quantityOfInputs uint16) (int, error)

func (*Tx) RequestReadHoldingRegisters

func (tx *Tx) RequestReadHoldingRegisters(dst []byte, startAddr, numberOfRegisters uint16) (int, error)

RequestReadDiscreteInputs writes packet to dst used to read from 1 to 125 contiguous holding registers.

func (*Tx) RequestReadInputRegisters

func (tx *Tx) RequestReadInputRegisters(dst []byte, startAddr, numberOfRegisters uint16) (int, error)

RequestReadInputRegisters writes packet to dst used to read from 1 to 125 contiguous input registers in a remote device.

func (*Tx) RequestWriteMultipleCoils

func (tx *Tx) RequestWriteMultipleCoils(dst []byte, startAddr, quantityOfOutputs uint16, data []byte) (int, error)

RequestWriteMultipleCoils writes packet to dst used to force contiguous coils to either ON or OFF in a remote device. The data argument contains packed coil values.

func (*Tx) RequestWriteMultipleRegisters

func (tx *Tx) RequestWriteMultipleRegisters(dst []byte, startAddr uint16, registers []uint16) (int, error)

RequestWriteMultipleRegisters writes packet to dst used to write contiguous block of holding registers (1 to 123 registers) in a remote device.

func (*Tx) RequestWriteSingleCoil

func (tx *Tx) RequestWriteSingleCoil(dst []byte, addr uint16, value bool) (int, error)

RequestWriteSingleCoil writes packet to dst used to write a single coil to either ON or OFF in a remote device.

func (*Tx) RequestWriteSingleRegister

func (tx *Tx) RequestWriteSingleRegister(dst []byte, addr, value uint16) (int, error)

RequestWriteSingleRegister writes packet to dst used to write a single holding register in a remote device.

func (*Tx) ResponseReadCoils

func (tx *Tx) ResponseReadCoils(dst, registerData []byte) (int, error)

func (*Tx) ResponseReadDiscreteInputs

func (tx *Tx) ResponseReadDiscreteInputs(dst, registerData []byte) (int, error)

func (*Tx) ResponseReadHoldingRegisters

func (tx *Tx) ResponseReadHoldingRegisters(dst, registerData []byte) (int, error)

func (*Tx) ResponseReadInputRegisters

func (tx *Tx) ResponseReadInputRegisters(dst, registerData []byte) (int, error)

func (*Tx) ResponseWriteMultipleCoils

func (tx *Tx) ResponseWriteMultipleCoils(dst []byte, address, quantityOfOutputs uint16) (int, error)

func (*Tx) ResponseWriteMultipleRegisters

func (tx *Tx) ResponseWriteMultipleRegisters(dst []byte, address, quantityOfOutputs uint16) (int, error)

func (*Tx) ResponseWriteSingleCoil

func (tx *Tx) ResponseWriteSingleCoil(dst []byte, address uint16, writtenValue bool) (int, error)

func (*Tx) ResponseWriteSingleRegister

func (tx *Tx) ResponseWriteSingleRegister(dst []byte, address, writtenValue uint16) (int, error)

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

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