You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2022/09/18 17:29:44 UTC
[plc4x] 01/02: fix(plc4j/modbus): PLC4X-354 - ArrayIndexOutOfBoundsException when reading a single bit via Modbus
This is an automated email from the ASF dual-hosted git repository.
cdutz pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit c63919bf75cb93792c2e8040a1f3e66c677c46d9
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Sun Sep 18 19:28:53 2022 +0200
fix(plc4j/modbus): PLC4X-354 - ArrayIndexOutOfBoundsException when reading a single bit via Modbus
- Fixed the way the responses for Multi-Item requests are parsed.
---
.../modbus/base/protocol/ModbusProtocolLogic.java | 48 ++++++++++++----------
1 file changed, 26 insertions(+), 22 deletions(-)
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/protocol/ModbusProtocolLogic.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/protocol/ModbusProtocolLogic.java
index dab093e9c..bd3fbed22 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/protocol/ModbusProtocolLogic.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/protocol/ModbusProtocolLogic.java
@@ -19,11 +19,9 @@
package org.apache.plc4x.java.modbus.base.protocol;
import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
-import org.apache.plc4x.java.api.messages.*;
import org.apache.plc4x.java.api.value.*;
import org.apache.plc4x.java.api.model.PlcField;
import org.apache.plc4x.java.api.types.PlcResponseCode;
-import org.apache.plc4x.java.modbus.tcp.config.ModbusTcpConfiguration;
import org.apache.plc4x.java.modbus.base.field.ModbusField;
import org.apache.plc4x.java.modbus.base.field.ModbusFieldCoil;
import org.apache.plc4x.java.modbus.base.field.ModbusFieldDiscreteInput;
@@ -33,25 +31,17 @@ import org.apache.plc4x.java.modbus.base.field.ModbusExtendedRegister;
import org.apache.plc4x.java.modbus.readwrite.*;
import org.apache.plc4x.java.spi.ConversationContext;
import org.apache.plc4x.java.spi.Plc4xProtocolBase;
-import org.apache.plc4x.java.spi.configuration.HasConfiguration;
import org.apache.plc4x.java.spi.generation.*;
-import org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest;
-import org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse;
-import org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest;
-import org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse;
-import org.apache.plc4x.java.spi.messages.utils.ResponseItem;
import org.apache.plc4x.java.spi.transaction.RequestTransactionManager;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.plc4x.java.spi.values.PlcBOOL;
import org.apache.plc4x.java.spi.values.PlcList;
import java.time.Duration;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections;
import java.util.List;
-import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
public abstract class ModbusProtocolLogic<T extends ModbusADU> extends Plc4xProtocolBase<T> {
@@ -221,7 +211,7 @@ public abstract class ModbusProtocolLogic<T extends ModbusADU> extends Plc4xProt
}
ModbusPDUReadDiscreteInputsRequest req = (ModbusPDUReadDiscreteInputsRequest) request;
ModbusPDUReadDiscreteInputsResponse resp = (ModbusPDUReadDiscreteInputsResponse) response;
- return readBooleanList(req.getQuantity(), resp.getValue());
+ return readCoilBooleanList(req.getQuantity(), resp.getValue());
} else if (request instanceof ModbusPDUReadCoilsRequest) {
if (!(response instanceof ModbusPDUReadCoilsResponse)) {
throw new PlcRuntimeException("Unexpected response type. " +
@@ -229,7 +219,7 @@ public abstract class ModbusProtocolLogic<T extends ModbusADU> extends Plc4xProt
}
ModbusPDUReadCoilsRequest req = (ModbusPDUReadCoilsRequest) request;
ModbusPDUReadCoilsResponse resp = (ModbusPDUReadCoilsResponse) response;
- return readBooleanList(req.getQuantity(), resp.getValue());
+ return readCoilBooleanList(req.getQuantity(), resp.getValue());
} else if (request instanceof ModbusPDUReadInputRegistersRequest) {
if (!(response instanceof ModbusPDUReadInputRegistersResponse)) {
throw new PlcRuntimeException("Unexpected response type. " +
@@ -322,20 +312,34 @@ public abstract class ModbusProtocolLogic<T extends ModbusADU> extends Plc4xProt
return Arrays.copyOf(reverse.toByteArray(), 1)[0];
}
- protected PlcValue readBooleanList(int count, byte[] data) throws ParseException {
+ protected PlcValue readCoilBooleanList(int count, byte[] data) throws ParseException {
ReadBuffer io = new ReadBufferByteBased(data);
if (count == 1) {
- return DataItem.staticParse(io, ModbusDataType.BOOL, 1);
+ // Skip the first 7 bits.
+ io.readInt(7);
+ return new PlcBOOL(io.readBit());
}
- // Make sure we read in all the bytes. Unfortunately when requesting 9 bytes
- // they are ordered like this: 8 7 6 5 4 3 2 1 | 0 0 0 0 0 0 0 9
- // Luckily it turns out that this is exactly how BitSet parses byte[]
- BitSet bits = BitSet.valueOf(data);
- List<PlcValue> result = new ArrayList<>(count);
- for (int i = 0; i < count; i++) {
- result.add(new PlcBOOL(bits.get(i)));
+
+ int numFullBytes = count / 8;
+ int numBitsIncompleteByte = count - (numFullBytes * 8);
+ PlcValue[] values = new PlcValue[count];
+ for (int i = 0; i < numFullBytes; i++) {
+ values[(i*8)+7] = new PlcBOOL(io.readBit());
+ values[(i*8)+6] = new PlcBOOL(io.readBit());
+ values[(i*8)+5] = new PlcBOOL(io.readBit());
+ values[(i*8)+4] = new PlcBOOL(io.readBit());
+ values[(i*8)+3] = new PlcBOOL(io.readBit());
+ values[(i*8)+2] = new PlcBOOL(io.readBit());
+ values[(i*8)+1] = new PlcBOOL(io.readBit());
+ values[(i*8)] = new PlcBOOL(io.readBit());
+ }
+ if(numBitsIncompleteByte > 0) {
+ io.readInt(8 - numBitsIncompleteByte);
+ for (int i = 1; i <= numBitsIncompleteByte; i++) {
+ values[(numFullBytes*8)+(numBitsIncompleteByte - i)] = new PlcBOOL(io.readBit());
+ }
}
- return new PlcList(result);
+ return new PlcList(Arrays.asList(values));
}
}