Skip to content

Commit c1983b1

Browse files
committed
rtu: Fix incorrectly calculating response length for ReadWriteMultipleRegisters
1 parent 8c91ed0 commit c1983b1

File tree

7 files changed

+53
-83
lines changed

7 files changed

+53
-83
lines changed

asciiclient.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ func (mb *asciiSerialTransporter) Send(aduRequest []byte) (aduResponse []byte, e
168168
defer mb.Close()
169169
}
170170
if mb.Logger != nil {
171-
mb.Logger.Printf("modbus: sending %s\n", aduRequest)
171+
mb.Logger.Printf("modbus: sending %q\n", aduRequest)
172172
}
173173
if _, err = mb.port.Write(aduRequest); err != nil {
174174
return
@@ -193,7 +193,7 @@ func (mb *asciiSerialTransporter) Send(aduRequest []byte) (aduResponse []byte, e
193193
}
194194
aduResponse = data[:length]
195195
if mb.Logger != nil {
196-
mb.Logger.Printf("modbus: received %s\n", aduResponse)
196+
mb.Logger.Printf("modbus: received %q\n", aduResponse)
197197
}
198198
return
199199
}

client.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ func (mb *client) MaskWriteRegister(address, andMask, orMask uint16) (results []
368368
// Write registers value : N* bytes
369369
// Response:
370370
// Function code : 1 byte (0x17)
371-
// Byte count : 2 bytes
371+
// Byte count : 1 byte
372372
// Read registers value : Nx2 bytes
373373
func (mb *client) ReadWriteMultipleRegisters(readAddress, readQuantity, writeAddress, writeQuantity uint16, value []byte) (results []byte, err error) {
374374
if readQuantity < 1 || readQuantity > 125 {

rtuclient.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,17 +168,15 @@ func calculateResponseLength(adu []byte) int {
168168
length++
169169
}
170170
case FuncCodeReadInputRegisters,
171-
FuncCodeReadHoldingRegisters:
171+
FuncCodeReadHoldingRegisters,
172+
FuncCodeReadWriteMultipleRegisters:
172173
count := int(binary.BigEndian.Uint16(adu[4:]))
173174
length += 1 + count*2
174175
case FuncCodeWriteSingleCoil,
175176
FuncCodeWriteMultipleCoils,
176177
FuncCodeWriteSingleRegister,
177178
FuncCodeWriteMultipleRegisters:
178179
length += 4
179-
case FuncCodeReadWriteMultipleRegisters:
180-
count := int(binary.BigEndian.Uint16(adu[4:]))
181-
length += 2 + count*2
182180
case FuncCodeMaskWriteRegister:
183181
length += 6
184182
case FuncCodeReadFIFOQueue:

test/asciiclient_test.go

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,24 @@ import (
1313
)
1414

1515
const (
16-
testASCIIDevice = "/dev/pts/6"
16+
asciiDevice = "/dev/pts/6"
1717
)
1818

19-
func TestASCIIClientReadCoils(t *testing.T) {
20-
client := modbus.ASCIIClient(testASCIIDevice)
21-
ClientTestReadCoils(t, client)
19+
func TestASCIIClient(t *testing.T) {
20+
// Diagslave does not support broadcast id.
21+
handler := modbus.NewASCIIClientHandler(asciiDevice)
22+
handler.SlaveId = 17
23+
ClientTestAll(t, modbus.NewClient(handler))
2224
}
2325

2426
func TestASCIIClientAdvancedUsage(t *testing.T) {
25-
handler := modbus.NewASCIIClientHandler(testASCIIDevice)
27+
handler := modbus.NewASCIIClientHandler(asciiDevice)
2628
handler.BaudRate = 19200
2729
handler.DataBits = 8
2830
handler.Parity = "E"
2931
handler.StopBits = 1
30-
handler.SlaveId = 17
31-
handler.Logger = log.New(os.Stdout, "test: ", log.LstdFlags)
32+
handler.SlaveId = 12
33+
handler.Logger = log.New(os.Stdout, "ascii: ", log.LstdFlags)
3234
err := handler.Connect()
3335
if err != nil {
3436
t.Fatal(err)
@@ -40,4 +42,8 @@ func TestASCIIClientAdvancedUsage(t *testing.T) {
4042
if err != nil || results == nil {
4143
t.Fatal(err, results)
4244
}
45+
results, err = client.ReadWriteMultipleRegisters(0, 2, 2, 2, []byte{1, 2, 3, 4})
46+
if err != nil || results == nil {
47+
t.Fatal(err, results)
48+
}
4349
}

test/client.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ func ClientTestReadCoils(t *testing.T, client modbus.Client) {
2121
AssertEquals(t, 3, len(results))
2222
}
2323

24-
func ClientTestDiscreteInputs(t *testing.T, client modbus.Client) {
24+
func ClientTestReadDiscreteInputs(t *testing.T, client modbus.Client) {
2525
// Read discrete inputs 197-218
2626
address := uint16(0x00C4)
2727
quantity := uint16(0x0016)
@@ -137,3 +137,17 @@ func ClientTestReadFIFOQueue(t *testing.T, client modbus.Client) {
137137
AssertEquals(t, 0, len(results))
138138
}
139139
}
140+
141+
func ClientTestAll(t *testing.T, client modbus.Client) {
142+
ClientTestReadCoils(t, client)
143+
ClientTestReadDiscreteInputs(t, client)
144+
ClientTestReadHoldingRegisters(t, client)
145+
ClientTestReadInputRegisters(t, client)
146+
ClientTestWriteSingleCoil(t, client)
147+
ClientTestWriteSingleRegister(t, client)
148+
ClientTestWriteMultipleCoils(t, client)
149+
ClientTestWriteMultipleRegisters(t, client)
150+
ClientTestMaskWriteRegisters(t, client)
151+
ClientTestReadWriteMultipleRegisters(t, client)
152+
ClientTestReadFIFOQueue(t, client)
153+
}

test/rtuclient_test.go

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,24 @@ import (
1313
)
1414

1515
const (
16-
testRTUDevice = "/dev/pts/6"
16+
rtuDevice = "/dev/pts/6"
1717
)
1818

19-
func TestRTUClientReadCoils(t *testing.T) {
20-
client := modbus.RTUClient(testRTUDevice)
21-
ClientTestReadCoils(t, client)
19+
func TestRTUClient(t *testing.T) {
20+
// Diagslave does not support broadcast id.
21+
handler := modbus.NewRTUClientHandler(rtuDevice)
22+
handler.SlaveId = 17
23+
ClientTestAll(t, modbus.NewClient(handler))
2224
}
2325

2426
func TestRTUClientAdvancedUsage(t *testing.T) {
25-
handler := modbus.NewRTUClientHandler(testRTUDevice)
27+
handler := modbus.NewRTUClientHandler(rtuDevice)
2628
handler.BaudRate = 19200
2729
handler.DataBits = 8
2830
handler.Parity = "E"
2931
handler.StopBits = 1
30-
handler.SlaveId = 17
31-
handler.Logger = log.New(os.Stdout, "test: ", log.LstdFlags)
32+
handler.SlaveId = 11
33+
handler.Logger = log.New(os.Stdout, "rtu: ", log.LstdFlags)
3234
err := handler.Connect()
3335
if err != nil {
3436
t.Fatal(err)
@@ -40,4 +42,8 @@ func TestRTUClientAdvancedUsage(t *testing.T) {
4042
if err != nil || results == nil {
4143
t.Fatal(err, results)
4244
}
45+
results, err = client.ReadWriteMultipleRegisters(0, 2, 2, 2, []byte{1, 2, 3, 4})
46+
if err != nil || results == nil {
47+
t.Fatal(err, results)
48+
}
4349
}

test/tcpclient_test.go

Lines changed: 7 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -14,73 +14,19 @@ import (
1414
)
1515

1616
const (
17-
testTCPServer = "localhost:5020"
17+
tcpDevice = "localhost:5020"
1818
)
1919

20-
func TestTCPClientReadCoils(t *testing.T) {
21-
client := modbus.TCPClient(testTCPServer)
22-
ClientTestReadCoils(t, client)
23-
}
24-
25-
func TestTCPClientReadDiscreteInputs(t *testing.T) {
26-
client := modbus.TCPClient(testTCPServer)
27-
// Read discrete inputs 197-218
28-
ClientTestDiscreteInputs(t, client)
29-
}
30-
31-
func TestTCPClientReadHoldingRegisters(t *testing.T) {
32-
client := modbus.TCPClient(testTCPServer)
33-
ClientTestReadHoldingRegisters(t, client)
34-
}
35-
36-
func TestTCPClientReadInputRegisters(t *testing.T) {
37-
client := modbus.TCPClient(testTCPServer)
38-
ClientTestReadInputRegisters(t, client)
39-
}
40-
41-
func TestTCPClientWriteSingleCoil(t *testing.T) {
42-
client := modbus.TCPClient(testTCPServer)
43-
ClientTestWriteSingleCoil(t, client)
44-
}
45-
46-
func TestTCPClientWriteSingleRegister(t *testing.T) {
47-
client := modbus.TCPClient(testTCPServer)
48-
ClientTestWriteSingleRegister(t, client)
49-
}
50-
51-
func TestTCPClientWriteMultipleCoils(t *testing.T) {
52-
client := modbus.TCPClient(testTCPServer)
53-
ClientTestWriteMultipleCoils(t, client)
54-
}
55-
56-
func TestTCPClientWriteMultipleRegisters(t *testing.T) {
57-
client := modbus.TCPClient(testTCPServer)
58-
ClientTestWriteMultipleRegisters(t, client)
59-
}
60-
61-
func TestTCPClientMaskWriteRegisters(t *testing.T) {
62-
client := modbus.TCPClient(testTCPServer)
63-
ClientTestMaskWriteRegisters(t, client)
64-
}
65-
66-
func TestTCPClientReadWriteMultipleRegisters(t *testing.T) {
67-
client := modbus.TCPClient(testTCPServer)
68-
ClientTestReadWriteMultipleRegisters(t, client)
69-
}
70-
71-
func TestTCPClientReadFIFOQueue(t *testing.T) {
72-
handler := modbus.NewTCPClientHandler(testTCPServer)
73-
handler.Logger = log.New(os.Stdout, "test: ", log.LstdFlags)
74-
75-
client := modbus.NewClient(handler)
76-
ClientTestReadFIFOQueue(t, client)
20+
func TestTCPClient(t *testing.T) {
21+
client := modbus.TCPClient(tcpDevice)
22+
ClientTestAll(t, client)
7723
}
7824

7925
func TestTCPClientAdvancedUsage(t *testing.T) {
80-
handler := modbus.NewTCPClientHandler(testTCPServer)
26+
handler := modbus.NewTCPClientHandler(tcpDevice)
8127
handler.Timeout = 5 * time.Second
82-
handler.SlaveId = 0x01
83-
handler.Logger = log.New(os.Stdout, "test: ", log.LstdFlags)
28+
handler.SlaveId = 1
29+
handler.Logger = log.New(os.Stdout, "tcp: ", log.LstdFlags)
8430
handler.Connect()
8531
defer handler.Close()
8632

0 commit comments

Comments
 (0)