Skip to content

Commit 916e8bb

Browse files
committed
fix: Fixed an issue with the Modbus driver, causing errors when reading invalid addresses.
1 parent 793f370 commit 916e8bb

File tree

2 files changed

+37
-5
lines changed

2 files changed

+37
-5
lines changed

plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/optimizer/ModbusOptimizer.java

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,13 @@ protected PlcReadResponse processReadResponses(PlcReadRequest readRequest, Map<P
169169
if (!responses.containsKey(tagType)) {
170170
responses.put(tagType, new ArrayList<>());
171171
}
172-
responses.get(tagType).add(new Response(modbusTag.getAddress(), optimizedReadResponse.getPlcValue(tagName).getRaw()));
172+
PlcResponseCode responseCode = optimizedReadResponse.getResponseCode(tagName);
173+
int startingAddress = modbusTag.getAddress();
174+
int endingAddressRegister = modbusTag.getAddress() + modbusTag.getNumberOfElements();
175+
int endingAddressCoil = modbusTag.getAddress() + modbusTag.getNumberOfElements();
176+
byte[] responseData = (responseCode == PlcResponseCode.OK) ? optimizedReadResponse.getPlcValue(tagName).getRaw() : null;
177+
responses.get(tagType).add(new Response(responseCode, startingAddress,
178+
endingAddressRegister, endingAddressCoil, responseData));
173179
}
174180

175181
// Now go through the original requests and try to answer them by using the raw data we now have.
@@ -185,6 +191,16 @@ protected PlcReadResponse processReadResponses(PlcReadRequest readRequest, Map<P
185191
for (Response response : responses.get(tagType)) {
186192
if(modbusTag instanceof ModbusTagCoil) {
187193
if(response.matchesCoil(modbusTag)) {
194+
// If this response was invalid, return all associated addresses as equally invalid.
195+
// TODO: Possibly it would be worth doing a single item request for each of these
196+
// tags in order to find out which ones are actually invalid as if one item in the
197+
// current request exceeds the address range, all items in this chunk will fail, even
198+
// if only one element was invalid.
199+
if(response.getResponseCode() != PlcResponseCode.OK) {
200+
values.put(tagName, new ResponseItem<>(response.getResponseCode(), null));
201+
break;
202+
}
203+
188204
// Coils are read completely different from registers.
189205
ModbusTagCoil coilTag = (ModbusTagCoil) modbusTag;
190206

@@ -200,6 +216,16 @@ protected PlcReadResponse processReadResponses(PlcReadRequest readRequest, Map<P
200216
}
201217
// Read a normal register.
202218
else if (response.matchesRegister(modbusTag)) {
219+
// If this response was invalid, return all associated addresses as equally invalid.
220+
// TODO: Possibly it would be worth doing a single item request for each of these
221+
// tags in order to find out which ones are actually invalid as if one item in the
222+
// current request exceeds the address range, all items in this chunk will fail, even
223+
// if only one element was invalid.
224+
if(response.getResponseCode() != PlcResponseCode.OK) {
225+
values.put(tagName, new ResponseItem<>(response.getResponseCode(), null));
226+
break;
227+
}
228+
203229
byte[] responseData = response.getResponseDataForTag(modbusTag);
204230
ReadBuffer readBuffer = getReadBuffer(responseData, modbusContext.getByteOrder());
205231
try {
@@ -340,18 +366,20 @@ protected List<PlcReadRequest> processRegisterRequests(TreeSet<ModbusTag> tags,
340366
}
341367

342368
protected static class Response {
369+
private final PlcResponseCode responseCode;
343370
private final int startingAddress;
344371
private final int endingAddressCoil;
345372
private final int endingAddressRegister;
346373
private final byte[] responseData;
347374

348-
public Response(int startingAddress, byte[] responseData) {
375+
public Response(PlcResponseCode responseCode, int startingAddress, int endingAddressRegister, int endingAddressCoil, byte[] responseData) {
376+
this.responseCode = responseCode;
349377
this.startingAddress = startingAddress;
350378
this.responseData = responseData;
351-
this.endingAddressCoil = startingAddress + responseData.length * 8;
379+
this.endingAddressCoil = endingAddressRegister;
352380
// In general a "Celil(responseData.length / 2)" would have been more correct,
353381
// but the data returned from the device should already be an even number.
354-
this.endingAddressRegister = startingAddress + (responseData.length / 2);
382+
this.endingAddressRegister = endingAddressCoil;
355383
}
356384

357385
public boolean matchesCoil(ModbusTag modbusTag) {
@@ -366,6 +394,10 @@ public boolean matchesRegister(ModbusTag modbusTag) {
366394
return ((tagStartingAddress >= this.startingAddress) && (tagEndingAddress <= this.endingAddressRegister));
367395
}
368396

397+
public PlcResponseCode getResponseCode() {
398+
return responseCode;
399+
}
400+
369401
public byte[] getResponseData() {
370402
return responseData;
371403
}

plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualModbusTCPDriverTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public class ManualModbusTCPDriverTest extends ManualTest {
6565
*/
6666

6767
public ManualModbusTCPDriverTest(String connectionString) {
68-
super(connectionString/*, true, false, false, 100*/);
68+
super(connectionString, true, true, true, true, 100);
6969
}
7070

7171
public static void main(String[] args) throws Exception {

0 commit comments

Comments
 (0)