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/27 19:48:20 UTC
[plc4x] branch develop updated: chore(plc4j/ads): Finished implementing single and multi-item requests containing purely simple data types (no lists and no structs)
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
The following commit(s) were added to refs/heads/develop by this push:
new 4fb452aee chore(plc4j/ads): Finished implementing single and multi-item requests containing purely simple data types (no lists and no structs)
4fb452aee is described below
commit 4fb452aeec7b963614d056b7240f3d65522edbde
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Tue Sep 27 21:45:31 2022 +0200
chore(plc4j/ads): Finished implementing single and multi-item requests containing purely simple data types (no lists and no structs)
---
.../templates/java/data-io-template.java.ftlh | 2 +
.../plc4x/java/ads/field/DirectAdsField.java | 2 +-
.../plc4x/java/ads/protocol/AdsProtocolLogic.java | 169 ++++++++++++++-------
.../plc4x/protocol/ads/ManualAdsDriverTest.java | 57 ++++---
.../java/s7/readwrite/ManualS7DriverTest.java | 50 +++---
.../java/spi/generation/WriteBufferByteBased.java | 21 ++-
.../org/apache/plc4x/java/spi/values/PlcDATE.java | 13 ++
.../plc4x/java/spi/values/PlcDATE_AND_TIME.java | 13 +-
.../org/apache/plc4x/java/spi/values/PlcLTIME.java | 30 ++++
.../apache/plc4x/java/spi/values/PlcSTRING.java | 2 +-
.../org/apache/plc4x/java/spi/values/PlcTIME.java | 21 +++
.../plc4x/java/spi/values/PlcTIME_OF_DAY.java | 12 ++
.../apache/plc4x/java/spi/values/PlcValues.java | 5 +-
.../spi/values/{PlcSTRING.java => PlcWSTRING.java} | 16 +-
.../org/apache/plc4x/test/manual/ManualTest.java | 71 +++++++--
15 files changed, 357 insertions(+), 127 deletions(-)
diff --git a/code-generation/language-java/src/main/resources/templates/java/data-io-template.java.ftlh b/code-generation/language-java/src/main/resources/templates/java/data-io-template.java.ftlh
index efeaa6625..4c795c326 100644
--- a/code-generation/language-java/src/main/resources/templates/java/data-io-template.java.ftlh
+++ b/code-generation/language-java/src/main/resources/templates/java/data-io-template.java.ftlh
@@ -422,6 +422,8 @@ public class ${type.name} {
${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.getStruct().get("${simpleField.name}").get${helper.getLanguageTypeNameForField(simpleField)?cap_first}();
<#else>
<#if simpleField.name == "value">
+ ${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.get${helper.getLanguageTypeNameForField(simpleField)?cap_first}();
+ <#elseif simpleField.name == "secondsSinceEpoch">
${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.get${helper.getLanguageTypeNameForField(simpleField)?cap_first}();
<#else>
<#-- Just for now -->
diff --git a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/field/DirectAdsField.java b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/field/DirectAdsField.java
index cb6f79793..7a689aeb2 100644
--- a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/field/DirectAdsField.java
+++ b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/field/DirectAdsField.java
@@ -105,7 +105,7 @@ public class DirectAdsField implements AdsField {
return indexOffset;
}
- public String getAdsDataTypeName() {
+ public String getPlcDataType() {
return adsDataTypeName;
}
diff --git a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java
index 1f4fa085f..077787239 100644
--- a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java
+++ b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java
@@ -616,7 +616,7 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
protected CompletableFuture<PlcReadResponse> singleRead(PlcReadRequest readRequest, DirectAdsField directAdsField) {
CompletableFuture<PlcReadResponse> future = new CompletableFuture<>();
- String dataTypeName = directAdsField.getAdsDataTypeName();
+ String dataTypeName = directAdsField.getPlcDataType();
AdsDataTypeTableEntry adsDataTypeTableEntry = dataTypeTable.get(dataTypeName);
long size = adsDataTypeTableEntry.getSize();
@@ -655,7 +655,7 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
// Calculate the expected size of the response data.
long expectedResponseDataSize = resolvedFields.values().stream().mapToLong(
field -> {
- String dataTypeName = field.getAdsDataTypeName();
+ String dataTypeName = field.getPlcDataType();
AdsDataTypeTableEntry adsDataTypeTableEntry = dataTypeTable.get(dataTypeName);
long size = adsDataTypeTableEntry.getSize();
// Status code + payload size
@@ -669,7 +669,7 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
expectedResponseDataSize, readRequest.getFieldNames().stream().map(fieldName -> {
AdsField field = (AdsField) readRequest.getField(fieldName);
DirectAdsField directAdsField = resolvedFields.get(field);
- String dataTypeName = directAdsField.getAdsDataTypeName();
+ String dataTypeName = directAdsField.getPlcDataType();
AdsDataTypeTableEntry adsDataTypeTableEntry = dataTypeTable.get(dataTypeName);
long size = adsDataTypeTableEntry.getSize();
return new AdsMultiRequestItemRead(
@@ -762,7 +762,7 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
private ResponseItem<PlcValue> parseResponseItem(DirectAdsField field, ReadBuffer readBuffer) {
try {
- String dataTypeName = field.getAdsDataTypeName();
+ String dataTypeName = field.getPlcDataType();
AdsDataTypeTableEntry adsDataTypeTableEntry = dataTypeTable.get(dataTypeName);
PlcValueType plcValueType = getPlcValueTypeForAdsDataType(adsDataTypeTableEntry);
@@ -780,14 +780,14 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
try {
return parsePlcValue(plcValueType, adsDataTypeTableEntry, stringLength, readBuffer);
} catch (ParseException e) {
- LOGGER.warn("Error parsing field item of type: '{}' (at position {}})", field.getAdsDataTypeName(), i, e);
+ LOGGER.warn("Error parsing field item of type: '{}' (at position {}})", field.getPlcDataType(), i, e);
}
return null;
}).toArray(PlcValue[]::new);
return new ResponseItem<>(PlcResponseCode.OK, IEC61131ValueHandler.of(resultItems));
}
} catch (Exception e) {
- LOGGER.warn(String.format("Error parsing field item of type: '%s'", field.getAdsDataTypeName()), e);
+ LOGGER.warn(String.format("Error parsing field item of type: '%s'", field.getPlcDataType()), e);
return new ResponseItem<>(PlcResponseCode.INTERNAL_ERROR, null);
}
}
@@ -909,26 +909,14 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
protected CompletableFuture<PlcWriteResponse> singleWrite(PlcWriteRequest writeRequest, DirectAdsField directAdsField) {
CompletableFuture<PlcWriteResponse> future = new CompletableFuture<>();
-/* final String fieldName = writeRequest.getFieldNames().iterator().next();
- final AdsField plcField = (AdsField) writeRequest.getField(fieldName);
+ final String fieldName = writeRequest.getFieldNames().iterator().next();
final PlcValue plcValue = writeRequest.getPlcValue(fieldName);
- final int stringLength;
- if (directAdsField.getAdsDataType() == AdsDataType.STRING) {
- stringLength = plcValue.getString().length() + 1;
- } else {
- if (directAdsField.getAdsDataType() == AdsDataType.WSTRING) {
- stringLength = (plcValue.getString().length() + 1) * 2;
- } else {
- stringLength = 0;
- }
- }
+
try {
- WriteBufferByteBased writeBuffer = new WriteBufferByteBased(DataItem.getLengthInBytes(plcValue,
- plcField.getAdsDataType().getPlcValueType(), stringLength));
- DataItem.staticSerialize(writeBuffer, plcValue, plcField.getAdsDataType().getPlcValueType(), stringLength, ByteOrder.LITTLE_ENDIAN);
+ byte[] serializedValue = serializePlcValue(plcValue, directAdsField.getPlcDataType());
AmsPacket amsPacket = new AdsWriteRequest(configuration.getTargetAmsNetId(), configuration.getTargetAmsPort(),
configuration.getSourceAmsNetId(), configuration.getSourceAmsPort(),
- 0, getInvokeId(), directAdsField.getIndexGroup(), directAdsField.getIndexOffset(), writeBuffer.getData());
+ 0, getInvokeId(), directAdsField.getIndexGroup(), directAdsField.getIndexOffset(), serializedValue);
AmsTCPPacket amsTCPPacket = new AmsTCPPacket(amsPacket);
// Start a new request-transaction (Is ended in the response-handler)
@@ -953,53 +941,56 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
}));
} catch (Exception e) {
future.completeExceptionally(new PlcException("Error"));
- }*/
+ }
return future;
}
protected CompletableFuture<PlcWriteResponse> multiWrite(PlcWriteRequest writeRequest, Map<AdsField, DirectAdsField> resolvedFields) {
CompletableFuture<PlcWriteResponse> future = new CompletableFuture<>();
- // Calculate the size of all fields together.
- // Calculate the expected size of the response data.
-/* int expectedRequestDataSize = directAdsFields.stream().mapToInt(
- field -> field.getAdsDataType().getNumBytes() * field.getNumberOfElements()).sum();
- byte[] writeBuffer = new byte[expectedRequestDataSize];
- int pos = 0;
+ int numFields = writeRequest.getFields().size();
+ // Serialize all fields.
+ List<byte[]> serializedFields = new ArrayList<>(numFields);
+ Map<DirectAdsField, AdsDataTypeTableEntry> directAdsFields = new LinkedHashMap<>(numFields);
for (String fieldName : writeRequest.getFieldNames()) {
final AdsField field = (AdsField) writeRequest.getField(fieldName);
+ final DirectAdsField directAdsField = resolvedFields.get(field);
final PlcValue plcValue = writeRequest.getPlcValue(fieldName);
- final int stringLength;
- if (field.getAdsDataType() == AdsDataType.STRING) {
- stringLength = plcValue.getString().length() + 1;
- } else {
- if (field.getAdsDataType() == AdsDataType.WSTRING) {
- stringLength = (plcValue.getString().length() + 1) * 2;
- } else {
- stringLength = 0;
- }
- }
+ final AdsDataTypeTableEntry dataType = dataTypeTable.get(directAdsField.getPlcDataType());
try {
- WriteBufferByteBased itemWriteBuffer = new WriteBufferByteBased(DataItem.getLengthInBytes(plcValue,
- field.getAdsDataType().getPlcValueType(), stringLength));
- DataItem.staticSerialize(itemWriteBuffer, plcValue,
- field.getAdsDataType().getPlcValueType(), stringLength, ByteOrder.LITTLE_ENDIAN);
- int numBytes = itemWriteBuffer.getPos();
- System.arraycopy(itemWriteBuffer.getData(), 0, writeBuffer, pos, numBytes);
- pos += numBytes;
+ byte[] serializedValue = serializePlcValue(plcValue, directAdsField.getPlcDataType());
+ serializedFields.add(serializedValue);
+ directAdsFields.put(directAdsField, dataType);
} catch (Exception e) {
- throw new PlcRuntimeException("Error serializing data", e);
+ future.completeExceptionally(new PlcException("Error serializing data", e));
+ return future;
+ }
+ }
+
+ // Calculate the size of all serialized fields together.
+ int serializedSize = serializedFields.stream().mapToInt(
+ serializedField -> serializedField.length).sum();
+
+ // Copy all serialized fields into one buffer.
+ WriteBufferByteBased writeBuffer = new WriteBufferByteBased(serializedSize);
+ for (byte[] serializedField : serializedFields) {
+ try {
+ writeBuffer.writeByteArray("", serializedField);
+ } catch (SerializationException e) {
+ future.completeExceptionally(new PlcException("Error serializing data", e));
+ return future;
}
}
// With multi-requests, the index-group is fixed and the index offset indicates the number of elements.
AmsPacket amsPacket = new AdsReadWriteRequest(configuration.getTargetAmsNetId(), configuration.getTargetAmsPort(),
configuration.getSourceAmsNetId(), configuration.getSourceAmsPort(),
- 0, getInvokeId(), ReservedIndexGroups.ADSIGRP_MULTIPLE_WRITE.getValue(), directAdsFields.size(), (long) directAdsFields.size() * 4,
- directAdsFields.stream().map(directAdsField -> new AdsMultiRequestItemWrite(
- directAdsField.getIndexGroup(), directAdsField.getIndexOffset(),
- ((long) directAdsField.getAdsDataType().getNumBytes() * directAdsField.getNumberOfElements())))
- .collect(Collectors.toList()), writeBuffer);
+ 0, getInvokeId(), ReservedIndexGroups.ADSIGRP_MULTIPLE_WRITE.getValue(), serializedSize,
+ (long) numFields * 4,
+ directAdsFields.entrySet().stream().map(entry -> new AdsMultiRequestItemWrite(
+ entry.getKey().getIndexGroup(), entry.getKey().getIndexOffset(),
+ entry.getValue().getEntryLength()))
+ .collect(Collectors.toList()), writeBuffer.getBytes());
AmsTCPPacket amsTCPPacket = new AmsTCPPacket(amsPacket);
// Start a new request-transaction (Is ended in the response-handler)
@@ -1021,10 +1012,78 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
}
// Finish the request-transaction.
transaction.endRequest();
- }));*/
+ }));
return future;
}
+ protected byte[] serializePlcValue(PlcValue plcValue, String datatypeName) throws SerializationException {
+ // First check, if we have type information available.
+ if (!dataTypeTable.containsKey(datatypeName)) {
+ throw new SerializationException("Could not find data type: " + datatypeName);
+ }
+
+ // Get the data type, allocate enough memory and serialize the value based on the
+ // structure defined by the data type.
+ AdsDataTypeTableEntry dataType = dataTypeTable.get(datatypeName);
+ WriteBufferByteBased writeBuffer = new WriteBufferByteBased((int) dataType.getSize());
+ List<AdsDataTypeArrayInfo> arrayInfo = dataType.getArrayInfo();
+ serializeInternal(plcValue, dataType, arrayInfo, writeBuffer);
+ return writeBuffer.getBytes();
+ }
+
+ protected void serializeInternal(PlcValue contextValue,
+ AdsDataTypeTableEntry dataType,
+ List<AdsDataTypeArrayInfo> arrayInfo,
+ WriteBufferByteBased writeBuffer) throws SerializationException {
+
+ // An array type: Recursively iterate over the elements
+ if (arrayInfo.size() > 0) {
+ if (!contextValue.isList()) {
+ throw new SerializationException("Expected a PlcList, but got a " + contextValue.getPlcValueType().name());
+ }
+ AdsDataTypeArrayInfo curArrayLevel = arrayInfo.get(0);
+ List<? extends PlcValue> list = contextValue.getList();
+ if(curArrayLevel.getNumElements() != list.size()) {
+ throw new SerializationException(String.format(
+ "Expected a PlcList of size %d, but got one of size %d", curArrayLevel.getNumElements(), list.size()));
+ }
+ for (PlcValue plcValue : list) {
+ serializeInternal(plcValue, dataType, arrayInfo.subList(1, arrayInfo.size()), writeBuffer);
+ }
+ }
+
+ // A complex type
+ else if (dataType.getChildren().size() > 0) {
+ if (!contextValue.isStruct()) {
+ throw new SerializationException("Expected a PlcStruct, but got a " + contextValue.getPlcValueType().name());
+ }
+ PlcStruct plcStruct = (PlcStruct) contextValue;
+ for (AdsDataTypeTableChildEntry child : dataType.getChildren()) {
+ AdsDataTypeTableEntry childDataType = dataTypeTable.get(child.getDataTypeName());
+ if (!plcStruct.hasKey(child.getPropertyName())) {
+ throw new SerializationException("PlcStruct is missing a child with the name " + child.getPropertyName());
+ }
+ PlcValue childValue = plcStruct.getValue(child.getPropertyName());
+ serializeInternal(childValue, childDataType, childDataType.getArrayInfo(), writeBuffer);
+ }
+ }
+
+ // A simple type
+ else {
+ PlcValueType plcValueType = getPlcValueTypeForAdsDataType(dataType);
+ if (plcValueType == null) {
+ throw new SerializationException("Unsupported simple type: " + dataType.getDataTypeName());
+ }
+ int stringLength = 0;
+ if ((plcValueType == PlcValueType.STRING) || (plcValueType == PlcValueType.WSTRING)) {
+ String stringTypeName = dataType.getDataTypeName();
+ stringLength = Integer.parseInt(
+ stringTypeName.substring(stringTypeName.indexOf("(") + 1, stringTypeName.indexOf(")")));
+ }
+ DataItem.staticSerialize(writeBuffer, contextValue, plcValueType, stringLength);
+ }
+ }
+
protected PlcWriteResponse convertToPlc4xWriteResponse(PlcWriteRequest writeRequest, AmsPacket adsData) {
Map<String, PlcResponseCode> responseCodes = new HashMap<>();
if (adsData instanceof AdsWriteResponse) {
@@ -1105,7 +1164,7 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
List<AmsTCPPacket> amsTCPPackets = subscribeRequest.getFields().stream()
.map(field -> (DefaultPlcSubscriptionField) field)
.map(field -> {
- AdsDataTypeTableEntry adsDataTypeTableEntry = dataTypeTable.get(resolvedFields.get((AdsField) field.getPlcField()).getAdsDataTypeName());
+ AdsDataTypeTableEntry adsDataTypeTableEntry = dataTypeTable.get(resolvedFields.get((AdsField) field.getPlcField()).getPlcDataType());
DirectAdsField directAdsField = getDirectAdsFieldForSymbolicName(field.getPlcField());
return new AmsTCPPacket(new AdsAddDeviceNotificationRequest(configuration.getTargetAmsNetId(), configuration.getTargetAmsPort(),
configuration.getSourceAmsNetId(), configuration.getSourceAmsPort(),
@@ -1154,7 +1213,7 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
.handle(response -> {
if (response.getResult() == ReturnCode.OK) {
DefaultPlcSubscriptionField subscriptionField = (DefaultPlcSubscriptionField) subscriptionRequest.getField(fieldName);
- AdsDataTypeTableEntry adsDataTypeTableEntry = dataTypeTable.get((resolvedFields.get((AdsField) subscriptionField.getPlcField())).getAdsDataTypeName());
+ AdsDataTypeTableEntry adsDataTypeTableEntry = dataTypeTable.get((resolvedFields.get((AdsField) subscriptionField.getPlcField())).getPlcDataType());
// Collect notification handle from individual response.
responses.put(fieldName, new ResponseItem<>(
diff --git a/plc4j/drivers/ads/src/test/java/org/apache/plc4x/protocol/ads/ManualAdsDriverTest.java b/plc4j/drivers/ads/src/test/java/org/apache/plc4x/protocol/ads/ManualAdsDriverTest.java
index d89a68d95..3beb89099 100644
--- a/plc4j/drivers/ads/src/test/java/org/apache/plc4x/protocol/ads/ManualAdsDriverTest.java
+++ b/plc4j/drivers/ads/src/test/java/org/apache/plc4x/protocol/ads/ManualAdsDriverTest.java
@@ -18,9 +18,13 @@
*/
package org.apache.plc4x.protocol.ads;
+import org.apache.plc4x.java.spi.values.*;
import org.apache.plc4x.test.manual.ManualTest;
-import java.util.Arrays;
+import java.time.Duration;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
public class ManualAdsDriverTest extends ManualTest {
@@ -64,7 +68,7 @@ public class ManualAdsDriverTest extends ManualTest {
*/
public ManualAdsDriverTest(String connectionString) {
- super(connectionString);
+ super(connectionString, true);
}
public static void main(String[] args) throws Exception {
@@ -76,29 +80,32 @@ public class ManualAdsDriverTest extends ManualTest {
int targetAmsPort = 851;
String connectionString = String.format("ads:tcp://%s?sourceAmsNetId=%s&sourceAmsPort=%d&targetAmsNetId=%s&targetAmsPort=%d", spsIp, sourceAmsNetId, sourceAmsPort, targetAmsNetId, targetAmsPort);
ManualAdsDriverTest test = new ManualAdsDriverTest(connectionString);
- test.addTestCase("MAIN.hurz_BOOL", true);
- test.addTestCase("MAIN.hurz_BYTE", Arrays.asList(false, false, true, false, true, false, true, false));
- test.addTestCase("MAIN.hurz_WORD", Arrays.asList(true, false, true, false, false, true, false, true, true, false, true, true, true, false, false, false));
- test.addTestCase("MAIN.hurz_DWORD", Arrays.asList(true, true, true, true, true, true, false, false, true, true, false, true, true, true, true, false, true, false, false, false, true, false, false, false, true, false, true, true, true, false, false, false));
- test.addTestCase("MAIN.hurz_SINT", -42);
- test.addTestCase("MAIN.hurz_USINT", 42);
- test.addTestCase("MAIN.hurz_INT", -2424);
- test.addTestCase("MAIN.hurz_UINT", 42424);
- test.addTestCase("MAIN.hurz_DINT", -242442424);
- test.addTestCase("MAIN.hurz_UDINT", 4242442424L);
- test.addTestCase("MAIN.hurz_LINT", -4242442424242424242L);
- test.addTestCase("MAIN.hurz_ULINT", 4242442424242424242L);
- test.addTestCase("MAIN.hurz_REAL", 3.14159265359F);
- test.addTestCase("MAIN.hurz_LREAL", 2.71828182846D);
- test.addTestCase("MAIN.hurz_STRING", "hurz");
- test.addTestCase("MAIN.hurz_WSTRING", "wolf");
- test.addTestCase("MAIN.hurz_TIME", "PT1.234S");
- test.addTestCase("MAIN.hurz_LTIME", "PT24015H23M12.034002044S");
- test.addTestCase("MAIN.hurz_DATE", "1978-03-28");
- test.addTestCase("MAIN.hurz_TIME_OF_DAY", "15:36:30.123");
- test.addTestCase("MAIN.hurz_TOD", "16:17:18.123");
- test.addTestCase("MAIN.hurz_DATE_AND_TIME", "1996-05-06T15:36:30");
- test.addTestCase("MAIN.hurz_DT", "1972-03-29T00:00");
+ test.addTestCase("MAIN.hurz_BOOL", new PlcBOOL(true));
+ test.addTestCase("MAIN.hurz_BYTE", new PlcBitString(new boolean[]{false, false, true, false, true, false, true, false}));
+ test.addTestCase("MAIN.hurz_WORD", new PlcBitString(new boolean[]{true, false, true, false, false, true, false, true, true, false, true, true, true, false, false, false}));
+ test.addTestCase("MAIN.hurz_DWORD", new PlcBitString(new boolean[]{true, true, true, true, true, true, false, false, true, true, false, true, true, true, true, false, true, false, false, false, true, false, false, false, true, false, true, true, true, false, false, false}));
+ // These are the values, if we decide to go with numeric values instead of bit-strings.
+ //test.addTestCase("MAIN.hurz_BYTE", new PlcBYTE(42));
+ //test.addTestCase("MAIN.hurz_WORD", new PlcWORD(42424));
+ //test.addTestCase("MAIN.hurz_DWORD", new PlcDWORD(4242442424L));
+ test.addTestCase("MAIN.hurz_SINT", new PlcSINT(-42));
+ test.addTestCase("MAIN.hurz_USINT", new PlcUSINT(42));
+ test.addTestCase("MAIN.hurz_INT", new PlcINT(-2424));
+ test.addTestCase("MAIN.hurz_UINT", new PlcUINT(42424));
+ test.addTestCase("MAIN.hurz_DINT", new PlcDINT(-242442424));
+ test.addTestCase("MAIN.hurz_UDINT", new PlcUDINT(4242442424L));
+ test.addTestCase("MAIN.hurz_LINT", new PlcLINT(-4242442424242424242L));
+ test.addTestCase("MAIN.hurz_ULINT", new PlcULINT(4242442424242424242L));
+ test.addTestCase("MAIN.hurz_REAL", new PlcREAL(3.14159265359F));
+ test.addTestCase("MAIN.hurz_LREAL", new PlcLREAL(2.71828182846D));
+ test.addTestCase("MAIN.hurz_STRING", new PlcSTRING("hurz"));
+ test.addTestCase("MAIN.hurz_WSTRING", new PlcWSTRING("wolf"));
+ test.addTestCase("MAIN.hurz_TIME", new PlcTIME(Duration.parse("PT1.234S")));
+ test.addTestCase("MAIN.hurz_LTIME", new PlcLTIME(Duration.parse("PT24015H23M12.034002044S")));
+ test.addTestCase("MAIN.hurz_DATE", new PlcDATE(LocalDate.parse("1978-03-28")));
+ test.addTestCase("MAIN.hurz_TIME_OF_DAY", new PlcTIME_OF_DAY(LocalTime.parse("15:36:30.123")));
+ test.addTestCase("MAIN.hurz_DATE_AND_TIME", new PlcDATE_AND_TIME(LocalDateTime.parse("1996-05-06T15:36:30")));
+ //test.addTestCase("MAIN.hurz_DT", new PlcDT("1972-03-29T00:00"));
test.run();
}
diff --git a/plc4j/drivers/s7/src/test/java/org/apache/plc4x/java/s7/readwrite/ManualS7DriverTest.java b/plc4j/drivers/s7/src/test/java/org/apache/plc4x/java/s7/readwrite/ManualS7DriverTest.java
index 8a82896c4..4f1488a5b 100644
--- a/plc4j/drivers/s7/src/test/java/org/apache/plc4x/java/s7/readwrite/ManualS7DriverTest.java
+++ b/plc4j/drivers/s7/src/test/java/org/apache/plc4x/java/s7/readwrite/ManualS7DriverTest.java
@@ -18,8 +18,11 @@
*/
package org.apache.plc4x.java.s7.readwrite;
+import org.apache.plc4x.java.spi.values.*;
import org.apache.plc4x.test.manual.ManualTest;
+import java.time.LocalDate;
+import java.time.LocalTime;
import java.util.Arrays;
public class ManualS7DriverTest extends ManualTest {
@@ -69,41 +72,42 @@ public class ManualS7DriverTest extends ManualTest {
public static void main(String[] args) throws Exception {
ManualS7DriverTest test = new ManualS7DriverTest("s7://192.168.23.30");
- test.addTestCase("%DB4:0.0:BOOL", true);
- test.addTestCase("%DB4:1:BYTE", Arrays.asList(false, false, true, false, true, false, true, false));
- test.addTestCase("%DB4:2:WORD", Arrays.asList(true, false, true, false, false, true, false, true, true, false, true, true, true, false, false, false));
- test.addTestCase("%DB4:4:DWORD", Arrays.asList(true, true, true, true, true, true, false, false, true, true, false, true, true, true, true, false, true, false, false, false, true, false, false, false, true, false, true, true, true, false, false, false));
- test.addTestCase("%DB4:16:SINT", -42);
- test.addTestCase("%DB4:17:USINT", 42);
- test.addTestCase("%DB4:18:INT", -2424);
- test.addTestCase("%DB4:20:UINT", 42424);
- test.addTestCase("%DB4:22:DINT", -242442424);
- test.addTestCase("%DB4:26:UDINT", 4242442424L);
+ test.addTestCase("%DB4:0.0:BOOL", new PlcBOOL(true));
+ test.addTestCase("%DB4:1:BYTE", new PlcBitString(new boolean[]{false, false, true, false, true, false, true, false}));
+ test.addTestCase("%DB4:2:WORD", new PlcBitString(new boolean[]{true, false, true, false, false, true, false, true, true, false, true, true, true, false, false, false}));
+ test.addTestCase("%DB4:4:DWORD", new PlcBitString(new boolean[]{true, true, true, true, true, true, false, false, true, true, false, true, true, true, true, false, true, false, false, false, true, false, false, false, true, false, true, true, true, false, false, false}));
+ test.addTestCase("%DB4:16:SINT", new PlcSINT(-42));
+ test.addTestCase("%DB4:17:USINT", new PlcUSINT(42));
+ test.addTestCase("%DB4:18:INT", new PlcINT(-2424));
+ test.addTestCase("%DB4:20:UINT", new PlcUINT(42424));
+ test.addTestCase("%DB4:22:DINT", new PlcDINT(-242442424));
+ test.addTestCase("%DB4:26:UDINT", new PlcUDINT(4242442424L));
// Not supported in S7 1200
- //test.addTestCase("%DB4:30:LINT", -4242442424242424242L);
+ //test.addTestCase("%DB4:30:LINT", new PlcLINT(-4242442424242424242L));
// Not supported in S7 1200
- //test.addTestCase("%DB4:38:ULINT", 4242442424242424242L);
- test.addTestCase("%DB4:46:REAL", 3.141593F);
+ //test.addTestCase("%DB4:38:ULINT", new PlcULINT(4242442424242424242L));
+ test.addTestCase("%DB4:46:REAL", new PlcREAL(3.141593F));
// Not supported in S7 1200
- //test.addTestCase("%DB4:50:LREAL", 2.71828182846D);
+ //test.addTestCase("%DB4:50:LREAL", new PlcLREAL(2.71828182846D));
test.addTestCase("%DB4:58:TIME", "PT1.234S");
+ test.addTestCase("%DB4:136:CHAR", new PlcCHAR("H"));
+ test.addTestCase("%DB4:138:WCHAR", new PlcWCHAR("w"));
+ test.addTestCase("%DB4:140:STRING(10)", new PlcSTRING("hurz"));
+ test.addTestCase("%DB4:396:WSTRING(10)", new PlcWSTRING("wolf"));
+ //test.addTestCase("%DB4:70:TIME", new PlcTIME(Duration.parse("PT1.234S"));
// Not supported in S7 1200
- //test.addTestCase("%DB4:62:LTIME", "PT24015H23M12.034002044S");
- test.addTestCase("%DB4:70:DATE", "1998-03-28");
- test.addTestCase("%DB4:72:TIME_OF_DAY", "15:36:30.123");
- test.addTestCase("%DB4:76:TOD", "16:17:18.123");
+ //test.addTestCase("%DB4:62:LTIME", new PlcLTIME(Duration.parse("PT24015H23M12.034002044S"));
+ test.addTestCase("%DB4:70:DATE", new PlcDATE(LocalDate.parse("1998-03-28")));
+ test.addTestCase("%DB4:72:TIME_OF_DAY", new PlcTIME_OF_DAY(LocalTime.parse("15:36:30.123")));
+ test.addTestCase("%DB4:76:TOD", new PlcTIME_OF_DAY(LocalTime.parse("16:17:18.123")));
// Not supported in S7 1200
- //test.addTestCase("%DB4:96:DATE_AND_TIME", "1996-05-06T15:36:30");
+ //test.addTestCase("%DB4:96:DATE_AND_TIME", new PlcDATE_AND_TIME(LocalDateTime.parse("1996-05-06T15:36:30")));
// Not supported in S7 1200
//test.addTestCase("%DB4:104:DT", "1992-03-29T00:00");
// Not supported in S7 1200
//test.addTestCase("%DB4:112:LDATE_AND_TIME", "1978-03-28T15:36:30");
// Not supported in S7 1200
//test.addTestCase("%DB4:124:LDT", "1978-03-28T15:36:30");
- test.addTestCase("%DB4:136:CHAR", "H");
- test.addTestCase("%DB4:138:WCHAR", "w");
- test.addTestCase("%DB4:140:STRING(10)", "hurz");
- test.addTestCase("%DB4:396:WSTRING(10)", "wolf");
test.run();
}
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferByteBased.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferByteBased.java
index 41ae7f830..e7a019f96 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferByteBased.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferByteBased.java
@@ -20,6 +20,7 @@ package org.apache.plc4x.java.spi.generation;
import com.github.jinahya.bit.io.BufferByteOutput;
import org.apache.commons.lang3.ArrayUtils;
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
import org.apache.plc4x.java.spi.generation.io.MyDefaultBitOutput;
import java.io.IOException;
@@ -27,6 +28,7 @@ import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
import static org.apache.commons.lang3.ArrayUtils.subarray;
@@ -303,9 +305,24 @@ public class WriteBufferByteBased implements WriteBuffer {
@Override
public void writeString(String logicalName, int bitLength, String encoding, String value, WithWriterArgs... writerArgs) throws SerializationException {
- final byte[] bytes = value.getBytes(Charset.forName(encoding.replaceAll("[^a-zA-Z0-9]", "")));
- int fixedByteLength = (int) Math.ceil((float) bitLength / 8.0);
+ byte[] bytes;
+ encoding = encoding.replaceAll("[^a-zA-Z0-9]", "");
+ switch (encoding.toUpperCase()) {
+ case "UTF8": {
+ bytes = value.getBytes(StandardCharsets.UTF_8);
+ break;
+ }
+ case "UTF16":
+ case "UTF16LE":
+ case "UTF16BE": {
+ bytes = value.getBytes(StandardCharsets.UTF_16);
+ break;
+ }
+ default:
+ throw new SerializationException("Unsupported encoding: " + encoding);
+ }
+ int fixedByteLength = (int) Math.ceil((float) bitLength / 8.0);
if (bitLength == 0) {
fixedByteLength = bytes.length;
}
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcDATE.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcDATE.java
index 25d2fef8a..41913929f 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcDATE.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcDATE.java
@@ -32,6 +32,8 @@ import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
+import java.time.temporal.ChronoUnit;
+import java.time.temporal.TemporalField;
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "className")
public class PlcDATE extends PlcSimpleValue<LocalDate> {
@@ -70,6 +72,17 @@ public class PlcDATE extends PlcSimpleValue<LocalDate> {
return PlcValueType.DATE;
}
+ @Override
+ public boolean isLong() {
+ return true;
+ }
+
+ @Override
+ public long getLong() {
+ Instant instant = value.atStartOfDay(ZoneId.systemDefault()).toInstant();
+ return (instant.toEpochMilli() / 1000);
+ }
+
@Override
@JsonIgnore
public boolean isString() {
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcDATE_AND_TIME.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcDATE_AND_TIME.java
index 0227160f4..1d5121bd7 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcDATE_AND_TIME.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcDATE_AND_TIME.java
@@ -38,7 +38,7 @@ public class PlcDATE_AND_TIME extends PlcSimpleValue<LocalDateTime> {
return new PlcDATE_AND_TIME((LocalDateTime) value);
} else if (value instanceof Long) {
return new PlcDATE_AND_TIME(LocalDateTime.ofInstant(
- Instant.ofEpochSecond((long) value), ZoneId.of("UTC")));
+ Instant.ofEpochSecond((long) value), ZoneId.systemDefault()));
}
throw new PlcRuntimeException("Invalid value type");
}
@@ -59,6 +59,17 @@ public class PlcDATE_AND_TIME extends PlcSimpleValue<LocalDateTime> {
return PlcValueType.DATE_AND_TIME;
}
+ @Override
+ public boolean isLong() {
+ return true;
+ }
+
+ @Override
+ public long getLong() {
+ Instant instant = value.atZone(ZoneId.systemDefault()).toInstant();
+ return instant.getEpochSecond();
+ }
+
@Override
@JsonIgnore
public boolean isString() {
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcLTIME.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcLTIME.java
index 80645d465..6b742a23e 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcLTIME.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcLTIME.java
@@ -68,6 +68,21 @@ public class PlcLTIME extends PlcSimpleValue<Duration> {
return PlcValueType.LTIME;
}
+ @Override
+ public boolean isInteger() {
+ return true;
+ }
+
+ @Override
+ public boolean isLong() {
+ return true;
+ }
+
+ @Override
+ public boolean isBigInteger() {
+ return true;
+ }
+
@Override
@JsonIgnore
public boolean isString() {
@@ -79,6 +94,21 @@ public class PlcLTIME extends PlcSimpleValue<Duration> {
return true;
}
+ @Override
+ public int getInteger() {
+ return (int) (value.get(ChronoUnit.NANOS) / 1000000);
+ }
+
+ @Override
+ public long getLong() {
+ return value.get(ChronoUnit.NANOS);
+ }
+
+ @Override
+ public BigInteger getBigInteger() {
+ return BigInteger.valueOf(value.get(ChronoUnit.NANOS));
+ }
+
@Override
public Duration getDuration() {
return value;
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcSTRING.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcSTRING.java
index 1d8f43af8..d01fe4431 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcSTRING.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcSTRING.java
@@ -232,7 +232,7 @@ public class PlcSTRING extends PlcSimpleValue<String> {
@Override
public void serialize(WriteBuffer writeBuffer) throws SerializationException {
- String valueString = value.toString();
+ String valueString = value;
writeBuffer.writeString(getClass().getSimpleName(), valueString.getBytes(StandardCharsets.UTF_8).length*8,StandardCharsets.UTF_8.name(),valueString);
}
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcTIME.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcTIME.java
index 72e7bd623..948186233 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcTIME.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcTIME.java
@@ -30,6 +30,7 @@ import org.apache.plc4x.java.spi.generation.WriteBuffer;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
+import java.time.temporal.TemporalUnit;
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "className")
public class PlcTIME extends PlcSimpleValue<Duration> {
@@ -63,6 +64,16 @@ public class PlcTIME extends PlcSimpleValue<Duration> {
return PlcValueType.TIME;
}
+ @Override
+ public boolean isInteger() {
+ return true;
+ }
+
+ @Override
+ public boolean isLong() {
+ return true;
+ }
+
@Override
@JsonIgnore
public boolean isString() {
@@ -74,6 +85,16 @@ public class PlcTIME extends PlcSimpleValue<Duration> {
return true;
}
+ @Override
+ public int getInteger() {
+ return (int) (value.get(ChronoUnit.NANOS) / 1000000);
+ }
+
+ @Override
+ public long getLong() {
+ return value.get(ChronoUnit.NANOS) / 1000000;
+ }
+
@Override
public Duration getDuration() {
return value;
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcTIME_OF_DAY.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcTIME_OF_DAY.java
index 90bc0c1a9..56360458a 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcTIME_OF_DAY.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcTIME_OF_DAY.java
@@ -28,7 +28,9 @@ import org.apache.plc4x.java.spi.generation.SerializationException;
import org.apache.plc4x.java.spi.generation.WriteBuffer;
import java.nio.charset.StandardCharsets;
+import java.time.Instant;
import java.time.LocalTime;
+import java.time.ZoneId;
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "className")
public class PlcTIME_OF_DAY extends PlcSimpleValue<LocalTime> {
@@ -57,6 +59,16 @@ public class PlcTIME_OF_DAY extends PlcSimpleValue<LocalTime> {
return PlcValueType.TIME_OF_DAY;
}
+ @Override
+ public boolean isLong() {
+ return true;
+ }
+
+ @Override
+ public long getLong() {
+ return ((long) value.toSecondOfDay()) * 1000;
+ }
+
@Override
@JsonIgnore
public boolean isString() {
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcValues.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcValues.java
index 06d1cf67e..ff98f9f28 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcValues.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcValues.java
@@ -69,11 +69,14 @@ public class PlcValues {
Object[] objectArray = (Object[]) o;
o = Arrays.asList(objectArray);
}
+ if (simpleName.equals("Boolean")) {
+ simpleName = "Bool";
+ }
// If it's one of the LocalDate, LocalTime or LocalDateTime, cut off the "Local".
if (simpleName.startsWith("Local")) {
simpleName = simpleName.substring(5);
}
- Constructor<?> constructor = Class.forName(PlcValues.class.getPackage().getName() + ".Plc" + simpleName).getDeclaredConstructor(clazz);
+ Constructor<?> constructor = Class.forName(PlcValues.class.getPackage().getName() + ".Plc" + simpleName.toUpperCase()).getDeclaredConstructor(clazz);
return ((PlcValue) constructor.newInstance(o));
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | ClassNotFoundException e) {
LOGGER.warn("Cannot wrap", e);
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcSTRING.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcWSTRING.java
similarity index 92%
copy from plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcSTRING.java
copy to plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcWSTRING.java
index 1d8f43af8..2cf0b0714 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcSTRING.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcWSTRING.java
@@ -31,23 +31,23 @@ import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "className")
-public class PlcSTRING extends PlcSimpleValue<String> {
+public class PlcWSTRING extends PlcSimpleValue<String> {
- public static PlcSTRING of(Object value) {
+ public static PlcWSTRING of(Object value) {
if (value instanceof String) {
- return new PlcSTRING((String) value);
+ return new PlcWSTRING((String) value);
}
- return new PlcSTRING(String.valueOf(value));
+ return new PlcWSTRING(String.valueOf(value));
}
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
- public PlcSTRING(@JsonProperty("value") String value) {
+ public PlcWSTRING(@JsonProperty("value") String value) {
super(value, true);
}
@Override
public PlcValueType getPlcValueType() {
- return PlcValueType.STRING;
+ return PlcValueType.WSTRING;
}
@Override
@@ -232,8 +232,8 @@ public class PlcSTRING extends PlcSimpleValue<String> {
@Override
public void serialize(WriteBuffer writeBuffer) throws SerializationException {
- String valueString = value.toString();
- writeBuffer.writeString(getClass().getSimpleName(), valueString.getBytes(StandardCharsets.UTF_8).length*8,StandardCharsets.UTF_8.name(),valueString);
+ String valueString = value;
+ writeBuffer.writeString(getClass().getSimpleName(), valueString.getBytes(StandardCharsets.UTF_16).length*8,StandardCharsets.UTF_16.name(),valueString);
}
}
diff --git a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/manual/ManualTest.java b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/manual/ManualTest.java
index 92e4733c3..018329b36 100644
--- a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/manual/ManualTest.java
+++ b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/manual/ManualTest.java
@@ -22,8 +22,13 @@ import org.apache.plc4x.java.PlcDriverManager;
import org.apache.plc4x.java.api.PlcConnection;
import org.apache.plc4x.java.api.messages.PlcReadRequest;
import org.apache.plc4x.java.api.messages.PlcReadResponse;
+import org.apache.plc4x.java.api.messages.PlcWriteRequest;
+import org.apache.plc4x.java.api.messages.PlcWriteResponse;
import org.apache.plc4x.java.api.types.PlcResponseCode;
+import org.apache.plc4x.java.api.value.PlcValue;
+import org.apache.plc4x.java.spi.values.PlcBitString;
import org.apache.plc4x.java.spi.values.PlcList;
+import org.apache.plc4x.java.spi.values.PlcValues;
import org.junit.jupiter.api.Assertions;
import java.util.ArrayList;
@@ -33,10 +38,16 @@ import java.util.List;
public abstract class ManualTest {
private final String connectionString;
+ private final boolean testWrite;
private final List<TestCase> testCases;
public ManualTest(String connectionString) {
+ this(connectionString, false);
+ }
+
+ public ManualTest(String connectionString, boolean testWrite) {
this.connectionString = connectionString;
+ this.testWrite = testWrite;
testCases = new ArrayList<>();
}
@@ -63,17 +74,50 @@ public abstract class ManualTest {
Assertions.assertNotNull(readResponse.getPlcValue(fieldName), fieldName);
if(readResponse.getPlcValue(fieldName) instanceof PlcList) {
PlcList plcList = (PlcList) readResponse.getPlcValue(fieldName);
- if(testCase.expectedReadValue instanceof List) {
- List<Object> expectedValues = (List<Object>) testCase.expectedReadValue;
- for (int j = 0; j < expectedValues.size(); j++) {
- Assertions.assertEquals(expectedValues.get(j), plcList.getIndex(j).getObject(), fieldName + "[" + j + "]");
- }
+ List expectedValues;
+ if (testCase.expectedReadValue instanceof PlcList) {
+ PlcList expectedPlcList = (PlcList) testCase.expectedReadValue;
+ expectedValues = expectedPlcList.getList();
+ } else if(testCase.expectedReadValue instanceof List) {
+ expectedValues = (List) testCase.expectedReadValue;
} else {
Assertions.fail("Got a list of values, but only expected one.");
+ return;
+ }
+ for (int j = 0; j < expectedValues.size(); j++) {
+ if (expectedValues.get(j) instanceof PlcValue) {
+ Assertions.assertEquals(((PlcValue) expectedValues.get(j)).getObject(), plcList.getIndex(j).getObject(), fieldName + "[" + j + "]");
+ } else {
+ Assertions.assertEquals(expectedValues.get(j), plcList.getIndex(j).getObject(), fieldName + "[" + j + "]");
+ }
}
} else {
- Assertions.assertEquals(
- testCase.expectedReadValue.toString(), readResponse.getPlcValue(fieldName).getObject().toString(), fieldName);
+ if (testCase.expectedReadValue instanceof PlcValue) {
+ Assertions.assertEquals(
+ ((PlcValue) testCase.expectedReadValue).getObject(), readResponse.getPlcValue(fieldName).getObject(), fieldName);
+ } else {
+ Assertions.assertEquals(
+ testCase.expectedReadValue.toString(), readResponse.getPlcValue(fieldName).getObject().toString(), fieldName);
+ }
+ }
+
+ // Try writing the same value back to the PLC.
+ if(testWrite) {
+ PlcValue plcValue;
+ if(testCase.expectedReadValue instanceof PlcValue) {
+ plcValue = ((PlcValue) testCase.expectedReadValue);
+ } else {
+ plcValue = PlcValues.of(testCase.expectedReadValue);
+ }
+
+ // Prepare the write request
+ PlcWriteRequest writeRequest = plcConnection.writeRequestBuilder().addItem(fieldName, testCase.address, plcValue).build();
+
+ // Execute the write request
+ PlcWriteResponse writeResponse = writeRequest.execute().get();
+
+ // Check the result
+ Assertions.assertEquals(PlcResponseCode.OK, writeResponse.getResponseCode(fieldName));
}
}
System.out.println("Success");
@@ -110,16 +154,23 @@ public abstract class ManualTest {
Assertions.assertEquals(PlcResponseCode.OK, readResponse.getResponseCode(fieldName),
"Field: " + fieldName);
Assertions.assertNotNull(readResponse.getPlcValue(fieldName), "Field: " + fieldName);
- if (readResponse.getPlcValue(fieldName) instanceof PlcList) {
+ if (readResponse.getPlcValue(fieldName) instanceof PlcBitString) {
+ PlcBitString plcBitString = (PlcBitString) readResponse.getPlcValue(fieldName);
+ List<PlcValue> expectedValues = ((PlcBitString) testCase.expectedReadValue).getList();
+ for (int j = 0; j < expectedValues.size(); j++) {
+ Assertions.assertEquals(expectedValues.get(j).toString(), plcBitString.getIndex(j).toString(),
+ "Field: " + fieldName);
+ }
+ } else if (readResponse.getPlcValue(fieldName) instanceof PlcList) {
PlcList plcList = (PlcList) readResponse.getPlcValue(fieldName);
List<Object> expectedValues = (List<Object>) testCase.expectedReadValue;
for (int j = 0; j < expectedValues.size(); j++) {
- Assertions.assertEquals(expectedValues.get(j), plcList.getIndex(j).getObject(),
+ Assertions.assertEquals(expectedValues.get(j), plcList.getIndex(j),
"Field: " + fieldName);
}
} else {
Assertions.assertEquals(
- testCase.expectedReadValue.toString(), readResponse.getPlcValue(fieldName).getObject().toString(),
+ testCase.expectedReadValue.toString(), readResponse.getPlcValue(fieldName).toString(),
"Field: " + fieldName);
}
}