From 10594498c5db2cb5715c770053eb3f701c09da66 Mon Sep 17 00:00:00 2001 From: Javier Peletier Date: Wed, 16 Dec 2020 00:08:23 +0100 Subject: [PATCH] modbus module --- modbus/mock.go | 44 ++++++++++++++++++++++++++++++ modbus/modbus.go | 70 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 modbus/mock.go create mode 100644 modbus/modbus.go diff --git a/modbus/mock.go b/modbus/mock.go new file mode 100644 index 0000000..5d516b6 --- /dev/null +++ b/modbus/mock.go @@ -0,0 +1,44 @@ +package modbus + +import ( + "encoding/binary" + "errors" +) + +type Mock struct { + State map[byte][]uint16 +} + +func NewMock() Modbus { + return &Mock{ + State: map[byte][]uint16{ + 49: {3, 68, 41, 41, 3, 68, 41, 41, 3, 68, 41, 45, 3, 68, 41, 45, 3, 68, 41, 42, 3, 52, 41, 40, 3, 52, 41, 44, 3, 68, 41, 41, 3, 68, 41, 40, 3, 68, 41, 41, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0}, + 50: {3, 68, 41, 41, 3, 68, 41, 41, 3, 68, 41, 45, 3, 68, 41, 45, 3, 68, 41, 42, 3, 52, 41, 40, 3, 52, 41, 44, 3, 68, 41, 41, 3, 68, 41, 40, 3, 68, 41, 41, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0}, + }, + } +} + +func (ms *Mock) ReadRegister(slaveID byte, address uint16, quantity uint16) (results []byte, err error) { + state, ok := ms.State[slaveID] + if !ok { + return nil, errors.New("Unknown slave") + } + for a := address; a < address+quantity; a++ { + b := make([]byte, 2) + binary.BigEndian.PutUint16(b, state[a]) + results = append(results, b...) + } + return results, nil +} +func (ms *Mock) WriteRegister(slaveID byte, address uint16, value uint16) (results []byte, err error) { + state, ok := ms.State[slaveID] + if !ok { + return nil, errors.New("Unknown slave") + } + state[address] = value + results = make([]byte, 2) + binary.BigEndian.PutUint16(results, value) + return results, nil +} + +func (ms *Mock) Close() error { return nil } diff --git a/modbus/modbus.go b/modbus/modbus.go new file mode 100644 index 0000000..c773b91 --- /dev/null +++ b/modbus/modbus.go @@ -0,0 +1,70 @@ +package modbus + +import ( + "sync" + "time" + + gmodbus "github.com/goburrow/modbus" +) + +type Modbus interface { + ReadRegister(slaveID byte, address uint16, quantity uint16) (results []byte, err error) + WriteRegister(slaveID byte, address uint16, value uint16) (results []byte, err error) + Close() error +} + +type Config struct { + Port string + BaudRate int + DataBits int + Parity string + StopBits int + Timeout time.Duration +} + +type modbus struct { + handler *gmodbus.RTUClientHandler + client gmodbus.Client + lock sync.RWMutex +} + +func New(config *Config) (Modbus, error) { + handler := gmodbus.NewRTUClientHandler(config.Port) + handler.BaudRate = config.BaudRate + handler.DataBits = config.DataBits + handler.Parity = config.Parity + handler.StopBits = config.StopBits + handler.Timeout = config.Timeout + + err := handler.Connect() + if err != nil { + return nil, err + } + + return &modbus{ + handler: handler, + client: gmodbus.NewClient(handler), + }, nil +} + +func (mb *modbus) Close() error { + return mb.handler.Close() +} + +func (mb *modbus) ReadRegister(slaveID byte, address uint16, quantity uint16) (results []byte, err error) { + mb.lock.Lock() + defer mb.lock.Unlock() + mb.handler.SlaveId = slaveID + results, err = mb.client.ReadHoldingRegisters(address-1, quantity) + return results, err + +} + +func (mb *modbus) WriteRegister(slaveID byte, address uint16, value uint16) (results []byte, err error) { + mb.lock.Lock() + defer mb.lock.Unlock() + mb.handler.SlaveId = slaveID + results, err = mb.client.WriteSingleRegister(address-1, value) + return results, err + +}