Skip to content

Commit fd3ebdb

Browse files
authored
Fix exposed modbus client not setting slave id by making the connection wrapper compatible with the wrapped connection (#328)
1 parent 71e72c7 commit fd3ebdb

File tree

3 files changed

+64
-38
lines changed

3 files changed

+64
-38
lines changed

meter/modbus.go

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,7 @@ func NewModbusFromConfig(other map[string]interface{}) (api.Meter, error) {
6060
}
6161

6262
if err == nil {
63-
conn.Slave()
64-
err = device.Initialize(conn.ModbusClient())
63+
err = device.Initialize(conn)
6564

6665
// silence Kostal implementation errors
6766
if errors.Is(err, meters.ErrPartiallyOpened) {
@@ -103,21 +102,19 @@ func NewModbusFromConfig(other map[string]interface{}) (api.Meter, error) {
103102

104103
// floatGetter executes configured modbus read operation and implements func() (float64, error)
105104
func (m *Modbus) floatGetter(op modbus.Operation) (float64, error) {
106-
m.conn.Slave()
107-
108105
var res meters.MeasurementResult
109106
var err error
110107

111108
if dev, ok := m.device.(*rs485.RS485); ok {
112-
res, err = dev.QueryOp(m.conn.ModbusClient(), op.MBMD)
109+
res, err = dev.QueryOp(m.conn, op.MBMD)
113110
}
114111

115112
if dev, ok := m.device.(*sunspec.SunSpec); ok {
116113
if op.MBMD.IEC61850 != 0 {
117-
res, err = dev.QueryOp(m.conn.ModbusClient(), op.MBMD.IEC61850)
114+
res, err = dev.QueryOp(m.conn, op.MBMD.IEC61850)
118115
} else {
119116
res, err = dev.QueryPoint(
120-
m.conn.ModbusClient(),
117+
m.conn,
121118
op.SunSpec.Model,
122119
op.SunSpec.Block,
123120
op.SunSpec.Point,

provider/modbus.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,7 @@ func NewModbusFromConfig(other map[string]interface{}) (*Modbus, error) {
8888

8989
// prepare device
9090
if err == nil {
91-
conn.Slave()
92-
err = device.Initialize(conn.ModbusClient())
91+
err = device.Initialize(conn)
9392

9493
// silence KOSTAL implementation errors
9594
if errors.Is(err, meters.ErrPartiallyOpened) {
@@ -130,7 +129,6 @@ func (m *Modbus) FloatGetter() (float64, error) {
130129
}
131130

132131
if err != nil {
133-
m.conn.Close() // close connection in case of modbus error
134132
return 0, fmt.Errorf("read failed: %v", err)
135133
}
136134

@@ -140,10 +138,11 @@ func (m *Modbus) FloatGetter() (float64, error) {
140138
// if funccode is not configured, try find the reading on sunspec
141139
if dev, ok := m.device.(*sunspec.SunSpec); ok {
142140
if m.op.MBMD.IEC61850 != 0 {
143-
res, err = dev.QueryOp(m.conn.ModbusClient(), m.op.MBMD.IEC61850)
141+
// client := m.conn.ModbusClient()
142+
res, err = dev.QueryOp(m.conn, m.op.MBMD.IEC61850)
144143
} else {
145144
res, err = dev.QueryPoint(
146-
m.conn.ModbusClient(),
145+
m.conn,
147146
m.op.SunSpec.Model,
148147
m.op.SunSpec.Block,
149148
m.op.SunSpec.Point,

util/modbus/modbus.go

Lines changed: 56 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,58 +20,88 @@ type Settings struct {
2020
RTU *bool // indicates RTU over TCP if true
2121
}
2222

23-
// Connection decorates a meters.Connection with slave id and error handling
23+
// Connection decorates a meters.Connection with transparent slave id and error handling
2424
type Connection struct {
2525
slaveID uint8
26-
meters.Connection
26+
conn meters.Connection
2727
}
2828

2929
func (mb *Connection) handle(res []byte, err error) ([]byte, error) {
3030
if err != nil {
31-
mb.Connection.Close()
31+
mb.conn.Close()
3232
}
3333
return res, err
3434
}
3535

36-
// Slave sets slave id
37-
func (mb *Connection) Slave() {
38-
mb.Connection.Slave(mb.slaveID)
36+
// Logger sets logger implementation
37+
func (mb *Connection) Logger(logger meters.Logger) {
38+
mb.conn.Logger(logger)
3939
}
4040

41-
// ReadCoils decorates the mbmd meters.Connection with slave setting and error handling
41+
// ReadCoils wraps the underlying implementation
4242
func (mb *Connection) ReadCoils(address, quantity uint16) ([]byte, error) {
43-
mb.Connection.Slave(mb.slaveID)
44-
return mb.handle(mb.Connection.ModbusClient().ReadCoils(address, quantity))
43+
mb.conn.Slave(mb.slaveID)
44+
return mb.handle(mb.conn.ModbusClient().ReadCoils(address, quantity))
4545
}
4646

47-
// WriteSingleCoil decorates the mbmd meters.Connection with slave setting and error handling
47+
// WriteSingleCoil wraps the underlying implementation
4848
func (mb *Connection) WriteSingleCoil(address, quantity uint16) ([]byte, error) {
49-
mb.Connection.Slave(mb.slaveID)
50-
return mb.handle(mb.Connection.ModbusClient().WriteSingleCoil(address, quantity))
49+
mb.conn.Slave(mb.slaveID)
50+
return mb.handle(mb.conn.ModbusClient().WriteSingleCoil(address, quantity))
5151
}
5252

53-
// ReadInputRegisters decorates the mbmd meters.Connection with slave setting and error handling
53+
// ReadInputRegisters wraps the underlying implementation
5454
func (mb *Connection) ReadInputRegisters(address, quantity uint16) ([]byte, error) {
55-
mb.Connection.Slave(mb.slaveID)
56-
return mb.handle(mb.Connection.ModbusClient().ReadInputRegisters(address, quantity))
55+
mb.conn.Slave(mb.slaveID)
56+
return mb.handle(mb.conn.ModbusClient().ReadInputRegisters(address, quantity))
5757
}
5858

59-
// ReadHoldingRegisters decorates the mbmd meters.Connection with slave setting and error handling
59+
// ReadHoldingRegisters wraps the underlying implementation
6060
func (mb *Connection) ReadHoldingRegisters(address, quantity uint16) ([]byte, error) {
61-
mb.Connection.Slave(mb.slaveID)
62-
return mb.handle(mb.Connection.ModbusClient().ReadHoldingRegisters(address, quantity))
61+
mb.conn.Slave(mb.slaveID)
62+
return mb.handle(mb.conn.ModbusClient().ReadHoldingRegisters(address, quantity))
6363
}
6464

65-
// WriteSingleRegister decorates the mbmd meters.Connection with slave setting and error handling
65+
// WriteSingleRegister wraps the underlying implementation
6666
func (mb *Connection) WriteSingleRegister(address, value uint16) ([]byte, error) {
67-
mb.Connection.Slave(mb.slaveID)
68-
return mb.handle(mb.Connection.ModbusClient().WriteSingleRegister(address, value))
67+
mb.conn.Slave(mb.slaveID)
68+
return mb.handle(mb.conn.ModbusClient().WriteSingleRegister(address, value))
6969
}
7070

71-
// WriteMultipleRegisters decorates the mbmd meters.Connection with slave setting and error handling
71+
// WriteMultipleRegisters wraps the underlying implementation
7272
func (mb *Connection) WriteMultipleRegisters(address, quantity uint16, value []byte) ([]byte, error) {
73-
mb.Connection.Slave(mb.slaveID)
74-
return mb.handle(mb.Connection.ModbusClient().WriteMultipleRegisters(address, quantity, value))
73+
mb.conn.Slave(mb.slaveID)
74+
return mb.handle(mb.conn.ModbusClient().WriteMultipleRegisters(address, quantity, value))
75+
}
76+
77+
// ReadDiscreteInputs wraps the underlying implementation
78+
func (mb *Connection) ReadDiscreteInputs(address, quantity uint16) (results []byte, err error) {
79+
mb.conn.Slave(mb.slaveID)
80+
return mb.handle(mb.conn.ModbusClient().ReadDiscreteInputs(address, quantity))
81+
}
82+
83+
// WriteMultipleCoils wraps the underlying implementation
84+
func (mb *Connection) WriteMultipleCoils(address, quantity uint16, value []byte) (results []byte, err error) {
85+
mb.conn.Slave(mb.slaveID)
86+
return mb.handle(mb.conn.ModbusClient().WriteMultipleCoils(address, quantity, value))
87+
}
88+
89+
// ReadWriteMultipleRegisters wraps the underlying implementation
90+
func (mb *Connection) ReadWriteMultipleRegisters(readAddress, readQuantity, writeAddress, writeQuantity uint16, value []byte) (results []byte, err error) {
91+
mb.conn.Slave(mb.slaveID)
92+
return mb.handle(mb.conn.ModbusClient().ReadWriteMultipleRegisters(readAddress, readQuantity, writeAddress, writeQuantity, value))
93+
}
94+
95+
// MaskWriteRegister wraps the underlying implementation
96+
func (mb *Connection) MaskWriteRegister(address, andMask, orMask uint16) (results []byte, err error) {
97+
mb.conn.Slave(mb.slaveID)
98+
return mb.handle(mb.conn.ModbusClient().MaskWriteRegister(address, andMask, orMask))
99+
}
100+
101+
// ReadFIFOQueue wraps the underlying implementation
102+
func (mb *Connection) ReadFIFOQueue(address uint16) (results []byte, err error) {
103+
mb.conn.Slave(mb.slaveID)
104+
return mb.handle(mb.conn.ModbusClient().ReadFIFOQueue(address))
75105
}
76106

77107
var connections map[string]meters.Connection
@@ -117,8 +147,8 @@ func NewConnection(uri, device, comset string, baudrate int, rtu bool, slaveID u
117147
}
118148

119149
slaveConn := &Connection{
120-
slaveID: slaveID,
121-
Connection: conn,
150+
slaveID: slaveID,
151+
conn: conn,
122152
}
123153

124154
return slaveConn, nil

0 commit comments

Comments
 (0)