You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2018/09/06 14:06:32 UTC
[incubator-plc4x] branch feature/api-redesign-chris-c updated: some
(little) progress on ADS api refactoring
This is an automated email from the ASF dual-hosted git repository.
sruehl pushed a commit to branch feature/api-redesign-chris-c
in repository https://gitbox.apache.org/repos/asf/incubator-plc4x.git
The following commit(s) were added to refs/heads/feature/api-redesign-chris-c by this push:
new 88a3df1 some (little) progress on ADS api refactoring
88a3df1 is described below
commit 88a3df1ab15d4d5e14162dce9f1e685a0aaef17d
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Thu Sep 6 16:06:28 2018 +0200
some (little) progress on ADS api refactoring
---
.../java/api/connection/PlcProprietarySender.java | 2 +-
.../java/api/messages/PlcProprietaryResponse.java | 2 +-
.../java/api/messages/PlcSubscriptionRequest.java | 12 +-
.../ads/connection/AdsAbstractPlcConnection.java | 29 ++---
.../java/ads/connection/AdsTcpPlcConnection.java | 39 +++---
.../apache/plc4x/java/ads/model/AdsDataType.java | 61 ++++++---
.../org/apache/plc4x/java/ads/model/AdsField.java | 7 +-
.../plc4x/java/ads/model/SymbolicAdsField.java | 29 ++++-
.../plc4x/java/ads/protocol/Plc4x2AdsProtocol.java | 92 ++++++++------
.../ads/protocol/util/LittleEndianDecoder.java | 139 ++++++++++++++++++++-
.../ads/protocol/util/LittleEndianEncoder.java | 59 +++++----
.../messages/DefaultPlcProprietaryRequest.java | 4 +-
.../messages/DefaultPlcProprietaryResponse.java | 11 +-
.../messages/DefaultPlcSubscriptionRequest.java | 26 +++-
.../java/base/messages/DefaultPlcWriteRequest.java | 7 +-
...est.java => InternalPlcProprietaryRequest.java} | 5 +-
...st.java => InternalPlcProprietaryResponse.java} | 7 +-
.../base/messages/InternalPlcWriteRequest.java | 6 +
.../plc4x/java/base/messages/items/FieldItem.java | 2 +-
19 files changed, 387 insertions(+), 152 deletions(-)
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/connection/PlcProprietarySender.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/connection/PlcProprietarySender.java
index efcdc3f..f735449 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/connection/PlcProprietarySender.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/connection/PlcProprietarySender.java
@@ -25,5 +25,5 @@ import java.util.concurrent.CompletableFuture;
public interface PlcProprietarySender {
- <PROP_REQUEST, PROP_RESPONSE> CompletableFuture<PlcProprietaryResponse<PROP_REQUEST, PROP_RESPONSE>> send(PlcProprietaryRequest<PROP_REQUEST> proprietaryRequest);
+ <PROP_REQUEST, PROP_RESPONSE> CompletableFuture<? extends PlcProprietaryResponse<? extends PlcProprietaryRequest<PROP_REQUEST>, PROP_RESPONSE>> send(PlcProprietaryRequest<PROP_REQUEST> proprietaryRequest);
}
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcProprietaryResponse.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcProprietaryResponse.java
index 23ff22f..2e3bf58 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcProprietaryResponse.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcProprietaryResponse.java
@@ -18,6 +18,6 @@
*/
package org.apache.plc4x.java.api.messages;
-public interface PlcProprietaryResponse<REQUEST, RESPONSE> extends PlcResponse<PlcProprietaryRequest<REQUEST>> {
+public interface PlcProprietaryResponse<REQUEST extends PlcProprietaryRequest, RESPONSE> extends PlcResponse<REQUEST> {
RESPONSE getResponse();
}
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcSubscriptionRequest.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcSubscriptionRequest.java
index fc95e00..f88137f 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcSubscriptionRequest.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcSubscriptionRequest.java
@@ -22,14 +22,14 @@ import java.time.Duration;
public interface PlcSubscriptionRequest extends PlcFieldRequest {
- PlcMessageBuilder<PlcSubscriptionRequest> builder();
+ PlcSubscriptionRequest.Builder builder();
interface Builder extends PlcMessageBuilder<PlcSubscriptionRequest> {
/**
* Adds a new field to the to be constructed request which should be polled cyclically.
*
- * @param name alias of the field.
- * @param fieldQuery field query string for accessing the field.
+ * @param name alias of the field.
+ * @param fieldQuery field query string for accessing the field.
* @param pollingInterval interval, in which the field should be polled.
* @return
*/
@@ -39,7 +39,7 @@ public interface PlcSubscriptionRequest extends PlcFieldRequest {
* Adds a new field to the to be constructed request which should be updated as soon as
* a value changes in the PLC.
*
- * @param name alias of the field.
+ * @param name alias of the field.
* @param fieldQuery field query string for accessing the field.
* @return
*/
@@ -48,10 +48,10 @@ public interface PlcSubscriptionRequest extends PlcFieldRequest {
/**
* Adds a new subscription to the to be constructed request which should be updated
* as soon as an event occurs.
- *
+ * <p>
* REMARK: We will have to see if this signature is correct as soon as we start using this type of subscription.
*
- * @param name alias of the field.
+ * @param name alias of the field.
* @param fieldQuery field query string for accessing the field.
* @return
*/
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/AdsAbstractPlcConnection.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/AdsAbstractPlcConnection.java
index 79eb938..f9e0917 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/AdsAbstractPlcConnection.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/AdsAbstractPlcConnection.java
@@ -39,10 +39,7 @@ import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
import org.apache.plc4x.java.api.messages.*;
import org.apache.plc4x.java.base.connection.AbstractPlcConnection;
import org.apache.plc4x.java.base.connection.ChannelFactory;
-import org.apache.plc4x.java.base.messages.DefaultPlcProprietaryRequest;
-import org.apache.plc4x.java.base.messages.DefaultPlcReadRequest;
-import org.apache.plc4x.java.base.messages.DefaultPlcWriteRequest;
-import org.apache.plc4x.java.base.messages.PlcRequestContainer;
+import org.apache.plc4x.java.base.messages.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -95,10 +92,10 @@ public abstract class AdsAbstractPlcConnection extends AbstractPlcConnection imp
}
@Override
- public CompletableFuture<PlcReadResponse> read(PlcReadRequest readRequest) {
+ public CompletableFuture<InternalPlcReadResponse> read(PlcReadRequest readRequest) {
mapFields(readRequest);
- CompletableFuture<PlcReadResponse> readFuture = new CompletableFuture<>();
- ChannelFuture channelFuture = channel.writeAndFlush(new PlcRequestContainer<>(readRequest, readFuture));
+ CompletableFuture<InternalPlcReadResponse> readFuture = new CompletableFuture<>();
+ ChannelFuture channelFuture = channel.writeAndFlush(new PlcRequestContainer<>((InternalPlcReadRequest) readRequest, readFuture));
channelFuture.addListener(future -> {
if (!future.isSuccess()) {
readFuture.completeExceptionally(future.cause());
@@ -113,10 +110,10 @@ public abstract class AdsAbstractPlcConnection extends AbstractPlcConnection imp
}
@Override
- public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) {
+ public CompletableFuture<InternalPlcWriteResponse> write(PlcWriteRequest writeRequest) {
mapFields(writeRequest);
- CompletableFuture<PlcWriteResponse> writeFuture = new CompletableFuture<>();
- ChannelFuture channelFuture = channel.writeAndFlush(new PlcRequestContainer<>(writeRequest, writeFuture));
+ CompletableFuture<InternalPlcWriteResponse> writeFuture = new CompletableFuture<>();
+ ChannelFuture channelFuture = channel.writeAndFlush(new PlcRequestContainer<>((InternalPlcWriteRequest) writeRequest, writeFuture));
channelFuture.addListener(future -> {
if (!future.isSuccess()) {
writeFuture.completeExceptionally(future.cause());
@@ -131,9 +128,9 @@ public abstract class AdsAbstractPlcConnection extends AbstractPlcConnection imp
}
@Override
- public <REQUEST, RESPONSE> CompletableFuture<PlcProprietaryResponse<REQUEST, RESPONSE>> send(PlcProprietaryRequest<REQUEST> proprietaryRequest) {
- CompletableFuture<PlcProprietaryResponse<REQUEST, RESPONSE>> sendFuture = new CompletableFuture<>();
- ChannelFuture channelFuture = channel.writeAndFlush(new PlcRequestContainer<>(proprietaryRequest, sendFuture));
+ public <PROP_REQUEST, PROP_RESPONSE> CompletableFuture<? extends PlcProprietaryResponse<? extends PlcProprietaryRequest<PROP_REQUEST>, PROP_RESPONSE>> send(PlcProprietaryRequest<PROP_REQUEST> proprietaryRequest) {
+ CompletableFuture<InternalPlcProprietaryResponse<PROP_REQUEST, PROP_RESPONSE>> sendFuture = new CompletableFuture<>();
+ ChannelFuture channelFuture = channel.writeAndFlush(new PlcRequestContainer<>((InternalPlcProprietaryRequest<PROP_REQUEST>) proprietaryRequest, sendFuture));
channelFuture.addListener(future -> {
if (!future.isSuccess()) {
sendFuture.completeExceptionally(future.cause());
@@ -168,9 +165,9 @@ public abstract class AdsAbstractPlcConnection extends AbstractPlcConnection imp
);
// TODO: This is blocking, should be changed to be async.
- CompletableFuture<PlcProprietaryResponse<AdsReadWriteRequest, AdsReadWriteResponse>> getHandelFuture = new CompletableFuture<>();
+ CompletableFuture<InternalPlcProprietaryResponse<InternalPlcProprietaryRequest<AdsWriteRequest>, AdsReadWriteResponse>> getHandelFuture = new CompletableFuture<>();
channel.writeAndFlush(new PlcRequestContainer<>(new DefaultPlcProprietaryRequest<>(adsReadWriteRequest), getHandelFuture));
- PlcProprietaryResponse<AdsReadWriteRequest, AdsReadWriteResponse> getHandleResponse = getFromFuture(getHandelFuture, SYMBOL_RESOLVE_TIMEOUT);
+ InternalPlcProprietaryResponse<InternalPlcProprietaryRequest<AdsWriteRequest>, AdsReadWriteResponse> getHandleResponse = getFromFuture(getHandelFuture, SYMBOL_RESOLVE_TIMEOUT);
AdsReadWriteResponse response = getHandleResponse.getResponse();
if (response.getResult().toAdsReturnCode() != AdsReturnCode.ADS_CODE_0) {
@@ -178,7 +175,7 @@ public abstract class AdsAbstractPlcConnection extends AbstractPlcConnection imp
}
IndexOffset symbolHandle = IndexOffset.of(response.getData().getBytes());
- return AdsField.of(IndexGroup.ReservedGroups.ADSIGRP_SYM_VALBYHND.getAsLong(), symbolHandle.getAsLong());
+ return AdsField.of(IndexGroup.ReservedGroups.ADSIGRP_SYM_VALBYHND.getAsLong(), symbolHandle.getAsLong(), symbolicAdsFieldInternal.getAdsDataType(), symbolicAdsFieldInternal.getNumberOfElements());
});
}
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/AdsTcpPlcConnection.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/AdsTcpPlcConnection.java
index efe2f5f..687f7b0 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/AdsTcpPlcConnection.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/AdsTcpPlcConnection.java
@@ -27,6 +27,7 @@ import org.apache.plc4x.java.ads.api.commands.types.*;
import org.apache.plc4x.java.ads.api.generic.types.AmsNetId;
import org.apache.plc4x.java.ads.api.generic.types.AmsPort;
import org.apache.plc4x.java.ads.api.generic.types.Invoke;
+import org.apache.plc4x.java.ads.model.AdsDataType;
import org.apache.plc4x.java.ads.model.AdsField;
import org.apache.plc4x.java.ads.model.AdsSubscriptionHandle;
import org.apache.plc4x.java.ads.model.SymbolicAdsField;
@@ -39,14 +40,10 @@ import org.apache.plc4x.java.api.exceptions.PlcNotImplementedException;
import org.apache.plc4x.java.api.exceptions.PlcProtocolException;
import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
import org.apache.plc4x.java.api.messages.*;
-import org.apache.plc4x.java.api.messages.items.SubscriptionEventItem;
-import org.apache.plc4x.java.api.messages.items.SubscriptionRequestItem;
-import org.apache.plc4x.java.api.messages.items.SubscriptionResponseItem;
-import org.apache.plc4x.java.api.messages.items.UnsubscriptionRequestItem;
import org.apache.plc4x.java.api.model.PlcField;
import org.apache.plc4x.java.api.types.PlcResponseCode;
import org.apache.plc4x.java.base.connection.TcpSocketChannelFactory;
-import org.apache.plc4x.java.base.messages.PlcRequestContainer;
+import org.apache.plc4x.java.base.messages.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -61,6 +58,9 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
+import static org.apache.plc4x.java.api.types.PlcSubscriptionType.CHANGE_OF_STATE;
+import static org.apache.plc4x.java.api.types.PlcSubscriptionType.CYCLIC;
+
public class AdsTcpPlcConnection extends AdsAbstractPlcConnection implements PlcSubscriber {
private static final Logger LOGGER = LoggerFactory.getLogger(AdsTcpPlcConnection.class);
@@ -142,18 +142,12 @@ public class AdsTcpPlcConnection extends AdsAbstractPlcConnection implements Plc
throw new PlcNotImplementedException("Multirequest on subscribe not implemented yet");
}
- PlcField plcField = subscriptionRequest.getFields().get(0);
- SubscriptionRequestItem<?> subscriptionRequestItem = subscriptionRequest.getRequestItem().orElseThrow(NullPointerException::new);
-
- Objects.requireNonNull(subscriptionRequestItem.getConsumer());
- Objects.requireNonNull(subscriptionRequestItem.getField());
- Objects.requireNonNull(subscriptionRequestItem.getDatatype());
-
- PlcField field = subscriptionRequestItem.getField();
- Class<?> datatype = subscriptionRequestItem.getDatatype();
+ PlcField field = subscriptionRequest.getFields().get(0);
IndexGroup indexGroup;
IndexOffset indexOffset;
+ AdsDataType adsDataType;
+ int numberOfElements;
// If this is a symbolic field, it has to be resolved first.
// TODO: This is blocking, should be changed to be async.
if (field instanceof SymbolicAdsField) {
@@ -164,6 +158,8 @@ public class AdsTcpPlcConnection extends AdsAbstractPlcConnection implements Plc
}
indexGroup = IndexGroup.of(adsField.getIndexGroup());
indexOffset = IndexOffset.of(adsField.getIndexOffset());
+ adsDataType = adsField.getAdsDataType();
+ numberOfElements = adsField.getNumberOfElements();
}
// If it's no symbolic field, we can continue immediately
// without having to do any resolving.
@@ -171,6 +167,8 @@ public class AdsTcpPlcConnection extends AdsAbstractPlcConnection implements Plc
AdsField adsField = (AdsField) field;
indexGroup = IndexGroup.of(adsField.getIndexGroup());
indexOffset = IndexOffset.of(adsField.getIndexOffset());
+ adsDataType = adsField.getAdsDataType();
+ numberOfElements = adsField.getNumberOfElements();
} else {
throw new IllegalArgumentException("Unsupported field type " + field.getClass());
}
@@ -196,8 +194,7 @@ public class AdsTcpPlcConnection extends AdsAbstractPlcConnection implements Plc
Invoke.NONE,
indexGroup,
indexOffset,
- // TODO: length determination doesn't work here really as this is only known within the plc or by the developer
- Length.of(LittleEndianDecoder.getLengthFor(datatype, 1)),
+ Length.of(adsDataType.getTagetByteSize() * numberOfElements),
transmissionMode,
MaxDelay.of(0),
CycleTime.of(4000000)
@@ -205,9 +202,9 @@ public class AdsTcpPlcConnection extends AdsAbstractPlcConnection implements Plc
// Send the request to the plc and wait for a response
// TODO: This is blocking, should be changed to be async.
- CompletableFuture<PlcProprietaryResponse<AdsAddDeviceNotificationResponse>> addDeviceFuture = new CompletableFuture<>();
- channel.writeAndFlush(new PlcRequestContainer<>(new PlcProprietaryRequest<>(adsAddDeviceNotificationRequest), addDeviceFuture));
- PlcProprietaryResponse<AdsAddDeviceNotificationResponse> addDeviceResponse = getFromFuture(addDeviceFuture, ADD_DEVICE_TIMEOUT);
+ CompletableFuture<InternalPlcProprietaryResponse<InternalPlcProprietaryRequest<AdsAddDeviceNotificationRequest>, AdsAddDeviceNotificationResponse>> addDeviceFuture = new CompletableFuture<>();
+ channel.writeAndFlush(new PlcRequestContainer<>(new DefaultPlcProprietaryRequest<>(adsAddDeviceNotificationRequest), addDeviceFuture));
+ InternalPlcProprietaryResponse<InternalPlcProprietaryRequest<AdsAddDeviceNotificationRequest>, AdsAddDeviceNotificationResponse> addDeviceResponse = getFromFuture(addDeviceFuture, ADD_DEVICE_TIMEOUT);
AdsAddDeviceNotificationResponse response = addDeviceResponse.getResponse();
// Abort if we got anything but a successful response.
@@ -215,7 +212,7 @@ public class AdsTcpPlcConnection extends AdsAbstractPlcConnection implements Plc
throw new PlcRuntimeException("Error code received " + response.getResult());
}
AdsSubscriptionHandle adsSubscriptionHandle = new AdsSubscriptionHandle(response.getNotificationHandle());
- future.complete(new PlcSubscriptionResponse(subscriptionRequest, Collections.singletonList(
+ future.complete(new DefaultPlcSubscriptionResponse(subscriptionRequest, Collections.singletonList(
new SubscriptionResponseItem<>(subscriptionRequestItem, adsSubscriptionHandle, PlcResponseCode.OK))));
Consumer<AdsDeviceNotificationRequest> adsDeviceNotificationRequestConsumer =
@@ -228,7 +225,7 @@ public class AdsTcpPlcConnection extends AdsAbstractPlcConnection implements Plc
Data data = adsNotificationSample.getData();
try {
@SuppressWarnings("unchecked")
- List<?> decodeData = LittleEndianDecoder.decodeData(datatype, data.getBytes());
+ List<?> decodeData = LittleEndianDecoder.decodeData(adsDataType, data.getBytes());
SubscriptionEventItem subscriptionEventItem =
new SubscriptionEventItem(subscriptionRequestItem, timeStamp, decodeData);
subscriptionRequestItem.getConsumer().accept(subscriptionEventItem);
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/AdsDataType.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/AdsDataType.java
index 31b9b34..f46c856 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/AdsDataType.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/AdsDataType.java
@@ -19,19 +19,50 @@
package org.apache.plc4x.java.ads.model;
public enum AdsDataType {
- BIT,
- BIT8,
- BITARR8,
- BITARR16,
- BITARR32,
- INT8,
- INT16,
- INT32,
- INT64,
- UINT8,
- UINT16,
- UINT32,
- UINT64,
- FLOAT,
- DOUBLE
+ // https://infosys.beckhoff.com/english.php?content=../content/1033/tcsystemmanager/basics/TcSysMgr_DatatypeComparison.htm&id=
+ BIT(1),
+ BIT8(1),
+ BITARR8(1),
+ BITARR16(2),
+ BITARR32(4),
+ INT8(1),
+ INT16(2),
+ INT32(4),
+ INT64(8),
+ UINT8(1),
+ UINT16(2),
+ UINT32(4),
+ UINT64(8),
+ FLOAT(4),
+ DOUBLE(8),
+ // https://infosys.beckhoff.com/english.php?content=../content/1033/tcplccontrol/html/tcplcctrl_plc_data_types_overview.htm&id
+ BOOL(0),
+ BYTE(0),
+ WORD(0),
+ DWORD(0),
+ SINT(0),
+ USINT(0),
+ INT(0),
+ UINT(0),
+ DINT(0),
+ UDINT(0),
+ LINT(0),
+ ULINT(0),
+ REAL(0),
+ LREAL(0),
+ STRING(0),
+ TIME(0),
+ TIME_OF_DAY(0),
+ DATE(0),
+ DATE_AND_TIME(0);
+
+ private final int tagetByteSize;
+
+ AdsDataType(int tagetByteSize) {
+ this.tagetByteSize = tagetByteSize;
+ }
+
+ public int getTagetByteSize() {
+ return tagetByteSize;
+ }
}
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/AdsField.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/AdsField.java
index b4e8d38..e5a1822 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/AdsField.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/AdsField.java
@@ -47,7 +47,7 @@ public class AdsField implements PlcField {
this.indexGroup = indexGroup;
ByteValue.checkUnsignedBounds(indexOffset, 4);
this.indexOffset = indexOffset;
- this.adsDataType = adsDataType;
+ this.adsDataType = Objects.requireNonNull(adsDataType);
this.numberOfElements = numberOfElements != null ? numberOfElements : 1;
if (this.numberOfElements <= 0) {
throw new IllegalArgumentException("numberOfElements must be greater then zero. Was " + this.numberOfElements);
@@ -87,11 +87,8 @@ public class AdsField implements PlcField {
String adsDataTypeString = matcher.group("adsDataType");
AdsDataType adsDataType = AdsDataType.valueOf(adsDataTypeString);
- Integer numberOfElements = null;
String numberOfElementsString = matcher.group("numberOfElements");
- if (numberOfElementsString != null) {
- numberOfElements = Integer.valueOf(numberOfElementsString);
- }
+ Integer numberOfElements = numberOfElementsString != null ? Integer.valueOf(numberOfElementsString) : null;
return new AdsField(indexGroup, indexOffset, adsDataType, numberOfElements);
}
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/SymbolicAdsField.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/SymbolicAdsField.java
index 2437b44..b8fc06e 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/SymbolicAdsField.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/SymbolicAdsField.java
@@ -30,12 +30,21 @@ import java.util.regex.Pattern;
*/
public class SymbolicAdsField implements PlcField {
- private static final Pattern SYMBOLIC_ADDRESS_PATTERN = Pattern.compile("^(?<symbolicAddress>.+)");
+ private static final Pattern SYMBOLIC_ADDRESS_PATTERN = Pattern.compile("^(?<symbolicAddress>.+):(?<adsDataType>.+)(\\[(?<numberOfElements>\\d)])?");
private final String symbolicAddress;
- private SymbolicAdsField(String symbolicAddress) {
+ private final AdsDataType adsDataType;
+
+ private final int numberOfElements;
+
+ private SymbolicAdsField(String symbolicAddress, AdsDataType adsDataType, Integer numberOfElements) {
this.symbolicAddress = Objects.requireNonNull(symbolicAddress);
+ this.adsDataType = Objects.requireNonNull(adsDataType);
+ this.numberOfElements = numberOfElements != null ? numberOfElements : 1;
+ if (this.numberOfElements <= 0) {
+ throw new IllegalArgumentException("numberOfElements must be greater then zero. Was " + this.numberOfElements);
+ }
}
public static SymbolicAdsField of(String address) throws PlcInvalidFieldException {
@@ -45,7 +54,13 @@ public class SymbolicAdsField implements PlcField {
}
String symbolicAddress = matcher.group("symbolicAddress");
- return new SymbolicAdsField(symbolicAddress);
+ String adsDataTypeString = matcher.group("adsDataType");
+ AdsDataType adsDataType = AdsDataType.valueOf(adsDataTypeString);
+
+ String numberOfElementsString = matcher.group("numberOfElements");
+ Integer numberOfElements = numberOfElementsString != null ? Integer.valueOf(numberOfElementsString) : null;
+
+ return new SymbolicAdsField(symbolicAddress, adsDataType, numberOfElements);
}
public static boolean matches(String address) {
@@ -56,6 +71,14 @@ public class SymbolicAdsField implements PlcField {
return symbolicAddress;
}
+ public AdsDataType getAdsDataType() {
+ return adsDataType;
+ }
+
+ public int getNumberOfElements() {
+ return numberOfElements;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) {
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/Plc4x2AdsProtocol.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/Plc4x2AdsProtocol.java
index 4f165c1..5a85640 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/Plc4x2AdsProtocol.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/Plc4x2AdsProtocol.java
@@ -20,38 +20,43 @@ package org.apache.plc4x.java.ads.protocol;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
+import org.apache.commons.lang3.tuple.Pair;
import org.apache.plc4x.java.ads.api.commands.*;
import org.apache.plc4x.java.ads.api.commands.types.*;
import org.apache.plc4x.java.ads.api.generic.AmsPacket;
import org.apache.plc4x.java.ads.api.generic.types.AmsNetId;
import org.apache.plc4x.java.ads.api.generic.types.AmsPort;
import org.apache.plc4x.java.ads.api.generic.types.Invoke;
+import org.apache.plc4x.java.ads.model.AdsDataType;
import org.apache.plc4x.java.ads.model.AdsField;
import org.apache.plc4x.java.ads.model.SymbolicAdsField;
import org.apache.plc4x.java.ads.protocol.exception.AdsException;
-import org.apache.plc4x.java.ads.protocol.util.LittleEndianDecoder;
import org.apache.plc4x.java.api.exceptions.PlcException;
import org.apache.plc4x.java.api.exceptions.PlcIoException;
import org.apache.plc4x.java.api.exceptions.PlcProtocolException;
-import org.apache.plc4x.java.api.messages.*;
+import org.apache.plc4x.java.api.messages.PlcProprietaryRequest;
+import org.apache.plc4x.java.api.messages.PlcReadRequest;
+import org.apache.plc4x.java.api.messages.PlcRequest;
+import org.apache.plc4x.java.api.messages.PlcWriteRequest;
import org.apache.plc4x.java.api.model.PlcField;
import org.apache.plc4x.java.api.types.PlcResponseCode;
-import org.apache.plc4x.java.base.messages.InternalPlcRequest;
-import org.apache.plc4x.java.base.messages.InternalPlcResponse;
-import org.apache.plc4x.java.base.messages.PlcRequestContainer;
+import org.apache.plc4x.java.base.messages.*;
+import org.apache.plc4x.java.base.messages.items.FieldItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
-import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
+import java.util.stream.Collectors;
import static org.apache.plc4x.java.ads.protocol.util.LittleEndianDecoder.decodeData;
+import static org.apache.plc4x.java.ads.protocol.util.LittleEndianEncoder.encodeData;
public class Plc4x2AdsProtocol extends MessageToMessageCodec<AmsPacket, PlcRequestContainer<InternalPlcRequest, InternalPlcResponse>> {
@@ -128,7 +133,7 @@ public class Plc4x2AdsProtocol extends MessageToMessageCodec<AmsPacket, PlcReque
}
private void encodeWriteRequest(PlcRequestContainer<InternalPlcRequest, InternalPlcResponse> msg, List<Object> out) throws PlcException {
- PlcWriteRequest writeRequest = (PlcWriteRequest) msg.getRequest();
+ InternalPlcWriteRequest writeRequest = (InternalPlcWriteRequest) msg.getRequest();
if (writeRequest.getFields().size() != 1) {
throw new PlcProtocolException("Only one item supported");
}
@@ -145,7 +150,11 @@ public class Plc4x2AdsProtocol extends MessageToMessageCodec<AmsPacket, PlcReque
Invoke invokeId = Invoke.of(correlationBuilder.incrementAndGet());
IndexGroup indexGroup = IndexGroup.of(adsField.getIndexGroup());
IndexOffset indexOffset = IndexOffset.of(adsField.getIndexOffset());
- byte[] bytes = encodeData(adsField.getAdsDataType(), writeRequestItem.getValues().toArray());
+
+ FieldItem fieldItem = writeRequest.getFieldItems().get(0);
+ Object[] values = fieldItem.getValues();
+
+ byte[] bytes = encodeData(adsField.getAdsDataType(), values);
Data data = Data.of(bytes);
AmsPacket amsPacket = AdsWriteRequest.of(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId, indexGroup, indexOffset, data);
LOGGER.debug("encoded write request {}", amsPacket);
@@ -175,19 +184,17 @@ public class Plc4x2AdsProtocol extends MessageToMessageCodec<AmsPacket, PlcReque
Invoke invokeId = Invoke.of(correlationBuilder.incrementAndGet());
IndexGroup indexGroup = IndexGroup.of(adsField.getIndexGroup());
IndexOffset indexOffset = IndexOffset.of(adsField.getIndexOffset());
- // TODO: length determination doesn't work here really as this is only known within the plc or by the developer
- Length length = Length.of(calculateLength(readRequestItem.getDatatype(), readRequestItem.getSize()));
+ AdsDataType adsDataType = adsField.getAdsDataType();
+ int numberOfElements = adsField.getNumberOfElements();
+ int readLength = adsDataType.getTagetByteSize() * numberOfElements;
+ Length length = Length.of(readLength);
AmsPacket amsPacket = AdsReadRequest.of(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId, indexGroup, indexOffset, length);
LOGGER.debug("encoded read request {}", amsPacket);
out.add(amsPacket);
requests.put(invokeId.getAsLong(), msg);
}
- private long calculateLength(Class<?> dataType, int size) {
- return LittleEndianDecoder.getLengthFor(dataType, 16) * size;
- }
-
- private void encodeProprietaryRequest(PlcRequestContainer<PlcRequest, PlcResponse> msg, List<Object> out) throws PlcProtocolException {
+ private void encodeProprietaryRequest(PlcRequestContainer<InternalPlcRequest, InternalPlcResponse> msg, List<Object> out) throws PlcProtocolException {
PlcProprietaryRequest plcProprietaryRequest = (PlcProprietaryRequest) msg.getRequest();
if (!(plcProprietaryRequest.getProprietaryRequest() instanceof AmsPacket)) {
throw new PlcProtocolException("Unsupported proprietary type for this driver " + plcProprietaryRequest.getProprietaryRequest().getClass());
@@ -206,13 +213,13 @@ public class Plc4x2AdsProtocol extends MessageToMessageCodec<AmsPacket, PlcReque
handleAdsDeviceNotificationRequest((AdsDeviceNotificationRequest) amsPacket);
return;
}
- PlcRequestContainer<PlcRequest, PlcResponse> plcRequestContainer = requests.remove(amsPacket.getAmsHeader().getInvokeId().getAsLong());
+ PlcRequestContainer<InternalPlcRequest, InternalPlcResponse> plcRequestContainer = requests.remove(amsPacket.getAmsHeader().getInvokeId().getAsLong());
if (plcRequestContainer == null) {
LOGGER.info("Unmapped packet received {}", amsPacket);
return;
}
PlcRequest request = plcRequestContainer.getRequest();
- PlcResponse response = null;
+ final InternalPlcResponse response;
// Handle the response to a read request.
if (request instanceof PlcReadRequest) {
@@ -229,6 +236,8 @@ public class Plc4x2AdsProtocol extends MessageToMessageCodec<AmsPacket, PlcReque
}
} else if (request instanceof PlcProprietaryRequest) {
response = decodeProprietaryResponse(amsPacket, plcRequestContainer);
+ } else {
+ response = null;
}
LOGGER.debug("Plc4x response {}", response);
@@ -258,37 +267,46 @@ public class Plc4x2AdsProtocol extends MessageToMessageCodec<AmsPacket, PlcReque
@SuppressWarnings("unchecked")
- private PlcResponse decodeWriteResponse(AdsWriteResponse responseMessage, PlcRequestContainer<PlcRequest, PlcResponse> requestContainer) {
- PlcWriteRequest plcWriteRequest = (PlcWriteRequest) requestContainer.getRequest();
- PlcWriteRequestItem requestItem = plcWriteRequest.getRequestItems().get(0);
-
+ private InternalPlcResponse decodeWriteResponse(AdsWriteResponse responseMessage, PlcRequestContainer<InternalPlcRequest, InternalPlcResponse> requestContainer) {
+ InternalPlcWriteRequest plcWriteRequest = (InternalPlcWriteRequest) requestContainer.getRequest();
PlcResponseCode responseCode = decodeResponseCode(responseMessage.getResult());
- if (plcWriteRequest instanceof TypeSafePlcWriteRequest) {
- return new TypeSafePlcWriteResponse((TypeSafePlcWriteRequest) plcWriteRequest, Collections.singletonList(new PlcWriteResponseItem<>(requestItem, responseCode)));
- } else {
- return new PlcWriteResponse(plcWriteRequest, Collections.singletonList(new PlcWriteResponseItem<>(requestItem, responseCode)));
- }
+ // TODO: does every item has the same ads response or is this whole aggregation broken?
+ Map<String, PlcResponseCode> responseItems = plcWriteRequest.getFieldNames()
+ .stream()
+ .collect(Collectors.toMap(
+ fieldName -> fieldName,
+ __ -> responseCode
+ ));
+ return new DefaultPlcWriteResponse(plcWriteRequest, responseItems);
}
@SuppressWarnings("unchecked")
- private PlcResponse decodeReadResponse(AdsReadResponse responseMessage, PlcRequestContainer<PlcRequest, PlcResponse> requestContainer) throws PlcProtocolException {
- PlcReadRequest plcReadRequest = (PlcReadRequest) requestContainer.getRequest();
- PlcReadRequestItem requestItem = plcReadRequest.getRequestItems().get(0);
+ private InternalPlcResponse decodeReadResponse(AdsReadResponse responseMessage, PlcRequestContainer<InternalPlcRequest, InternalPlcResponse> requestContainer) throws PlcProtocolException {
+ InternalPlcReadRequest plcReadRequest = (InternalPlcReadRequest) requestContainer.getRequest();
+
+ // TODO: only single requests supported for now
+ AdsField field = (AdsField) plcReadRequest.getFields().get(0);
+
PlcResponseCode responseCode = decodeResponseCode(responseMessage.getResult());
byte[] bytes = responseMessage.getData().getBytes();
- List decoded = decodeData(requestItem.getDatatype(), bytes);
+ FieldItem<?> fieldItem = decodeData(field.getAdsDataType(), bytes);
- if (plcReadRequest instanceof TypeSafePlcReadRequest) {
- return new TypeSafePlcReadResponse((TypeSafePlcReadRequest) plcReadRequest, Collections.singletonList(new PlcReadResponseItem<>(requestItem, responseCode, decoded)));
- } else {
- return new PlcReadResponse(plcReadRequest, Collections.singletonList(new PlcReadResponseItem<>(requestItem, responseCode, decoded)));
- }
+ // TODO: does every item has the same ads response or is this whole aggregation broken?
+ Map<String, Pair<PlcResponseCode, FieldItem>> responseItems = plcReadRequest.getFieldNames()
+ .stream()
+ .collect(Collectors.toMap(
+ fieldName -> fieldName,
+ __ -> Pair.of(responseCode, fieldItem)
+ ));
+
+ return new DefaultPlcReadResponse(plcReadRequest, responseItems);
}
- private PlcResponse decodeProprietaryResponse(AmsPacket amsPacket, PlcRequestContainer<PlcRequest, PlcResponse> plcRequestContainer) {
- return new PlcProprietaryResponse<>((PlcProprietaryRequest) plcRequestContainer.getRequest(), amsPacket);
+ @SuppressWarnings("unchecked")
+ private InternalPlcResponse decodeProprietaryResponse(AmsPacket amsPacket, PlcRequestContainer<InternalPlcRequest, InternalPlcResponse> plcRequestContainer) {
+ return new DefaultPlcProprietaryResponse<>((InternalPlcProprietaryRequest) plcRequestContainer.getRequest(), amsPacket);
}
private PlcResponseCode decodeResponseCode(Result result) {
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianDecoder.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianDecoder.java
index a0fb491..38e3d03 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianDecoder.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianDecoder.java
@@ -18,10 +18,16 @@
*/
package org.apache.plc4x.java.ads.protocol.util;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.NotImplementedException;
import org.apache.plc4x.java.ads.api.commands.types.TimeStamp;
+import org.apache.plc4x.java.ads.model.AdsDataType;
import org.apache.plc4x.java.api.exceptions.PlcProtocolException;
-import org.apache.plc4x.java.api.exceptions.PlcUnsupportedDataTypeException;
+import org.apache.plc4x.java.base.messages.items.BooleanFieldItem;
+import org.apache.plc4x.java.base.messages.items.FieldItem;
+import org.apache.plc4x.java.base.messages.items.IntegerFieldItem;
import java.math.BigInteger;
import java.util.*;
@@ -56,7 +62,135 @@ public class LittleEndianDecoder {
}
@SuppressWarnings("unchecked")
- public static <T> List<T> decodeData(Class<T> dataType, byte[] adsData) throws PlcProtocolException {
+ public static FieldItem<?> decodeData(AdsDataType adsDataType, byte[] adsData) {
+ ByteBuf wrappedBuffer = Unpooled.wrappedBuffer(adsData);
+ switch (adsDataType) {
+ case BIT: {
+ LinkedList<Boolean> values = new LinkedList<>();
+ while (wrappedBuffer.isReadable()) {
+ short aByte = wrappedBuffer.readUnsignedByte();
+ values.offer(aByte != 0);
+ }
+ return new BooleanFieldItem(values.toArray(new Boolean[0]));
+ }
+ case BIT8: {
+ LinkedList<Boolean> values = new LinkedList<>();
+ while (wrappedBuffer.isReadable()) {
+ short aByte = wrappedBuffer.readUnsignedByte();
+ values.offer(aByte != 0);
+ }
+ return new BooleanFieldItem(values.toArray(new Boolean[0]));
+ }
+ case BITARR8: {
+ LinkedList<Long> values = new LinkedList<>();
+ while (wrappedBuffer.isReadable()) {
+ short aByte = wrappedBuffer.readUnsignedByte();
+ values.offer((long) aByte);
+ }
+ return new IntegerFieldItem(values.toArray(new Long[0]));
+ }
+ case BITARR16: {
+ LinkedList<Long> values = new LinkedList<>();
+ while (wrappedBuffer.isReadable()) {
+ long aLong = wrappedBuffer.readUnsignedIntLE();
+ values.offer(aLong);
+ }
+ return new IntegerFieldItem(values.toArray(new Long[0]));
+ }
+ case BITARR32: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case INT8: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case INT16: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case INT32: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case INT64: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case UINT8: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case UINT16: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case UINT32: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case UINT64: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case FLOAT: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case DOUBLE: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case BOOL: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case BYTE: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case WORD: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case DWORD: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case SINT: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case USINT: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case INT: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case UINT: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case DINT: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case UDINT: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case LINT: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case ULINT: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case REAL: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case LREAL: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case STRING: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case TIME: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case TIME_OF_DAY: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case DATE: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ case DATE_AND_TIME: {
+ throw new NotImplementedException("not implemented yet " + adsDataType);
+ }
+ default:
+ throw new IllegalArgumentException("Unsupported adsDataType " + adsDataType);
+ }
+ /*
if (dataType == byte[].class) {
return (List<T>) Collections.singletonList(adsData);
}
@@ -122,6 +256,7 @@ public class LittleEndianDecoder {
}
}
return (List<T>) result;
+ */
}
private static int decodeString(byte[] adsData, int i, int length, List<Object> result) throws PlcProtocolException {
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianEncoder.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianEncoder.java
index a66fa0b..c09298b 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianEncoder.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianEncoder.java
@@ -20,6 +20,7 @@ package org.apache.plc4x.java.ads.protocol.util;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.plc4x.java.ads.api.commands.types.TimeStamp;
+import org.apache.plc4x.java.ads.model.AdsDataType;
import org.apache.plc4x.java.api.exceptions.PlcProtocolException;
import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
import org.apache.plc4x.java.api.exceptions.PlcUnsupportedDataTypeException;
@@ -41,33 +42,34 @@ public class LittleEndianEncoder {
}
// TODO: add bound checking
- public static byte[] encodeData(Class<?> valueType, Object... values) throws PlcProtocolException {
+ public static byte[] encodeData(AdsDataType adsDataType, Object... values) throws PlcProtocolException {
if (values.length == 0) {
return new byte[]{};
}
+ Class<?> valueType = values[0].getClass();
Stream<byte[]> result;
if (valueType == Boolean.class) {
- result = encodeBoolean(Arrays.stream(values).map(Boolean.class::cast));
+ result = encodeBoolean(adsDataType, Arrays.stream(values).map(Boolean.class::cast));
} else if (valueType == Byte.class) {
- result = encodeByte(Arrays.stream(values).map(Byte.class::cast));
+ result = encodeByte(adsDataType, Arrays.stream(values).map(Byte.class::cast));
} else if (valueType == Short.class) {
- result = encodeShort(Arrays.stream(values).map(Short.class::cast));
+ result = encodeShort(adsDataType, Arrays.stream(values).map(Short.class::cast));
} else if (valueType == Integer.class) {
- result = encodeInteger(Arrays.stream(values).map(Integer.class::cast));
+ result = encodeInteger(adsDataType, Arrays.stream(values).map(Integer.class::cast));
} else if (valueType == BigInteger.class) {
- result = encodeBigInteger(Arrays.stream(values).map(BigInteger.class::cast));
+ result = encodeBigInteger(adsDataType, Arrays.stream(values).map(BigInteger.class::cast));
} else if (valueType == Calendar.class || Calendar.class.isAssignableFrom(valueType)) {
- result = encodeCalendar(Arrays.stream(values).map(Calendar.class::cast));
+ result = encodeCalendar(adsDataType, Arrays.stream(values).map(Calendar.class::cast));
} else if (valueType == Float.class) {
- result = encodeFloat(Arrays.stream(values).map(Float.class::cast));
+ result = encodeFloat(adsDataType, Arrays.stream(values).map(Float.class::cast));
} else if (valueType == Double.class) {
- result = encodeDouble(Arrays.stream(values).map(Double.class::cast));
+ result = encodeDouble(adsDataType, Arrays.stream(values).map(Double.class::cast));
} else if (valueType == String.class) {
- result = encodeString(Arrays.stream(values).map(String.class::cast));
+ result = encodeString(adsDataType, Arrays.stream(values).map(String.class::cast));
} else if (valueType == byte[].class) {
- result = encodeByteArray(Arrays.stream(values).map(byte[].class::cast));
+ result = encodeByteArray(adsDataType, Arrays.stream(values).map(byte[].class::cast));
} else if (valueType == Byte[].class) {
- result = encodeBigByteArray(Arrays.stream(values).map(Byte[].class::cast));
+ result = encodeBigByteArray(adsDataType, Arrays.stream(values).map(Byte[].class::cast));
} else {
throw new PlcUnsupportedDataTypeException(valueType);
}
@@ -90,7 +92,8 @@ public class LittleEndianEncoder {
}
}
- private static Stream<byte[]> encodeString(Stream<String> stringStream) {
+ private static Stream<byte[]> encodeString(AdsDataType adsDataType, Stream<String> stringStream) {
+ // TODO: add boundchecks and add optional extension
// TODO: what do we do with utf-8 values with 2 bytes? what is the charset here?
return stringStream
.map(s -> s.getBytes(Charset.defaultCharset()))
@@ -98,15 +101,18 @@ public class LittleEndianEncoder {
.map(bytes -> ArrayUtils.add(bytes, (byte) 0x0));
}
- private static Stream<byte[]> encodeByteArray(Stream<byte[]> byteArrayStream) {
+ private static Stream<byte[]> encodeByteArray(AdsDataType adsDataType, Stream<byte[]> byteArrayStream) {
+ // TODO: add boundchecks and add optional extension
return byteArrayStream;
}
- private static Stream<byte[]> encodeBigByteArray(Stream<Byte[]> byteArrayStream) {
+ private static Stream<byte[]> encodeBigByteArray(AdsDataType adsDataType, Stream<Byte[]> byteArrayStream) {
+ // TODO: add boundchecks and add optional extension
return byteArrayStream.map(ArrayUtils::toPrimitive);
}
- private static Stream<byte[]> encodeFloat(Stream<Float> floatStream) {
+ private static Stream<byte[]> encodeFloat(AdsDataType adsDataType, Stream<Float> floatStream) {
+ // TODO: add boundchecks and add optional extension
return floatStream
// TODO: check how ads expects this data
.map(Float::floatToIntBits)
@@ -118,7 +124,8 @@ public class LittleEndianEncoder {
});
}
- private static Stream<byte[]> encodeDouble(Stream<Double> doubleStream) {
+ private static Stream<byte[]> encodeDouble(AdsDataType adsDataType, Stream<Double> doubleStream) {
+ // TODO: add boundchecks and add optional extension
return doubleStream
// TODO: check how ads expects this data
.map(Double::doubleToLongBits)
@@ -134,7 +141,8 @@ public class LittleEndianEncoder {
});
}
- private static Stream<byte[]> encodeInteger(Stream<Integer> integerStream) {
+ private static Stream<byte[]> encodeInteger(AdsDataType adsDataType, Stream<Integer> integerStream) {
+ // TODO: add boundchecks and add optional extension
return integerStream
.map(intValue -> new byte[]{
(byte) (intValue & 0x000000ff),
@@ -144,7 +152,8 @@ public class LittleEndianEncoder {
});
}
- private static Stream<byte[]> encodeBigInteger(Stream<BigInteger> bigIntegerStream) {
+ private static Stream<byte[]> encodeBigInteger(AdsDataType adsDataType, Stream<BigInteger> bigIntegerStream) {
+ // TODO: add boundchecks and add optional extension
return bigIntegerStream
.map(bigIntValue -> {
byte[] bytes = bigIntValue.toByteArray();
@@ -159,7 +168,8 @@ public class LittleEndianEncoder {
});
}
- private static Stream<byte[]> encodeCalendar(Stream<Calendar> calendarStream) {
+ private static Stream<byte[]> encodeCalendar(AdsDataType adsDataType, Stream<Calendar> calendarStream) {
+ // TODO: add boundchecks and add optional extension
return calendarStream
.map(Calendar.class::cast)
.map(Calendar::getTime)
@@ -181,7 +191,8 @@ public class LittleEndianEncoder {
}
- private static Stream<byte[]> encodeShort(Stream<Short> shortStream) {
+ private static Stream<byte[]> encodeShort(AdsDataType adsDataType, Stream<Short> shortStream) {
+ // TODO: add boundchecks and add optional extension
return shortStream
.map(shortValue -> new byte[]{
(byte) (shortValue & 0x00ff),
@@ -189,12 +200,14 @@ public class LittleEndianEncoder {
});
}
- private static Stream<byte[]> encodeByte(Stream<Byte> byteStream) {
+ private static Stream<byte[]> encodeByte(AdsDataType adsDataType, Stream<Byte> byteStream) {
+ // TODO: add boundchecks and add optional extension
return byteStream
.map(aByte -> new byte[]{aByte});
}
- private static Stream<byte[]> encodeBoolean(Stream<Boolean> booleanStream) {
+ private static Stream<byte[]> encodeBoolean(AdsDataType adsDataType, Stream<Boolean> booleanStream) {
+ // TODO: add boundchecks and add optional extension
return booleanStream
.map(booleanValue -> new byte[]{booleanValue ? (byte) 0x01 : (byte) 0x00});
}
diff --git a/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/DefaultPlcProprietaryRequest.java b/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/DefaultPlcProprietaryRequest.java
index eb9715c..fa716f0 100644
--- a/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/DefaultPlcProprietaryRequest.java
+++ b/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/DefaultPlcProprietaryRequest.java
@@ -18,9 +18,7 @@
*/
package org.apache.plc4x.java.base.messages;
-import org.apache.plc4x.java.api.messages.PlcProprietaryRequest;
-
-public class DefaultPlcProprietaryRequest<REQUEST> implements PlcProprietaryRequest<REQUEST> {
+public class DefaultPlcProprietaryRequest<REQUEST> implements InternalPlcProprietaryRequest<REQUEST> {
private REQUEST proprietaryRequest;
diff --git a/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/DefaultPlcProprietaryResponse.java b/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/DefaultPlcProprietaryResponse.java
index a459866..679fde1 100644
--- a/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/DefaultPlcProprietaryResponse.java
+++ b/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/DefaultPlcProprietaryResponse.java
@@ -18,16 +18,13 @@
*/
package org.apache.plc4x.java.base.messages;
-import org.apache.plc4x.java.api.messages.PlcProprietaryRequest;
-import org.apache.plc4x.java.api.messages.PlcProprietaryResponse;
+public class DefaultPlcProprietaryResponse<REQUEST, RESPONSE> implements InternalPlcProprietaryResponse<REQUEST, RESPONSE> {
-public class DefaultPlcProprietaryResponse<REQUEST, RESPONSE> implements PlcProprietaryResponse<REQUEST, RESPONSE> {
-
- private final PlcProprietaryRequest<REQUEST> plcProprietaryRequest;
+ private final InternalPlcProprietaryRequest<REQUEST> plcProprietaryRequest;
private final RESPONSE proprietaryResponse;
- public DefaultPlcProprietaryResponse(PlcProprietaryRequest<REQUEST> plcProprietaryRequest, RESPONSE proprietaryResponse) {
+ public DefaultPlcProprietaryResponse(InternalPlcProprietaryRequest<REQUEST> plcProprietaryRequest, RESPONSE proprietaryResponse) {
this.plcProprietaryRequest = plcProprietaryRequest;
this.proprietaryResponse = proprietaryResponse;
}
@@ -38,7 +35,7 @@ public class DefaultPlcProprietaryResponse<REQUEST, RESPONSE> implements PlcProp
}
@Override
- public PlcProprietaryRequest<REQUEST> getRequest() {
+ public InternalPlcProprietaryRequest getRequest() {
return plcProprietaryRequest;
}
}
diff --git a/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/DefaultPlcSubscriptionRequest.java b/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/DefaultPlcSubscriptionRequest.java
index b6b3a3d..2a50cc4 100644
--- a/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/DefaultPlcSubscriptionRequest.java
+++ b/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/DefaultPlcSubscriptionRequest.java
@@ -18,10 +18,10 @@ under the License.
*/
package org.apache.plc4x.java.base.messages;
-import org.apache.plc4x.java.api.messages.PlcMessageBuilder;
import org.apache.plc4x.java.api.messages.PlcSubscriptionRequest;
import org.apache.plc4x.java.api.model.PlcField;
+import java.time.Duration;
import java.util.LinkedHashSet;
import java.util.LinkedList;
@@ -48,8 +48,28 @@ public class DefaultPlcSubscriptionRequest implements InternalPlcSubscriptionReq
}
@Override
- public PlcMessageBuilder<PlcSubscriptionRequest> builder() {
- return null;
+ public Builder builder() {
+ return new Builder() {
+ @Override
+ public Builder addCyclicField(String name, String fieldQuery, Duration pollingInterval) {
+ return null;
+ }
+
+ @Override
+ public Builder addChangeOfStateField(String name, String fieldQuery) {
+ return null;
+ }
+
+ @Override
+ public Builder addEventField(String name, String fieldQuery) {
+ return null;
+ }
+
+ @Override
+ public PlcSubscriptionRequest build() {
+ return null;
+ }
+ };
}
}
diff --git a/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/DefaultPlcWriteRequest.java b/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/DefaultPlcWriteRequest.java
index 888c5a6..218d61e 100644
--- a/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/DefaultPlcWriteRequest.java
+++ b/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/DefaultPlcWriteRequest.java
@@ -59,7 +59,7 @@ public class DefaultPlcWriteRequest implements InternalPlcWriteRequest {
@Override
public LinkedList<PlcField> getFields() {
- return new LinkedList<>(fields.values().stream().map(Pair::getKey).collect(Collectors.toList()));
+ return fields.values().stream().map(Pair::getKey).collect(Collectors.toCollection(LinkedList::new));
}
public FieldItem getFieldItem(String name) {
@@ -67,6 +67,11 @@ public class DefaultPlcWriteRequest implements InternalPlcWriteRequest {
}
@Override
+ public LinkedList<FieldItem> getFieldItems() {
+ return fields.values().stream().map(Pair::getValue).collect(Collectors.toCollection(LinkedList::new));
+ }
+
+ @Override
public int getNumberOfValues(String name) {
return fields.get(name).getValue().getNumValues();
}
diff --git a/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/InternalPlcWriteRequest.java b/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/InternalPlcProprietaryRequest.java
similarity index 82%
copy from plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/InternalPlcWriteRequest.java
copy to plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/InternalPlcProprietaryRequest.java
index 2a6b03d..3e2ed9f 100644
--- a/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/InternalPlcWriteRequest.java
+++ b/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/InternalPlcProprietaryRequest.java
@@ -18,8 +18,7 @@
*/
package org.apache.plc4x.java.base.messages;
-import org.apache.plc4x.java.api.messages.PlcWriteRequest;
-
-public interface InternalPlcWriteRequest extends PlcWriteRequest, InternalPlcRequest {
+import org.apache.plc4x.java.api.messages.PlcProprietaryRequest;
+public interface InternalPlcProprietaryRequest<REQUEST> extends PlcProprietaryRequest<REQUEST>, InternalPlcRequest {
}
diff --git a/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/InternalPlcWriteRequest.java b/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/InternalPlcProprietaryResponse.java
similarity index 74%
copy from plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/InternalPlcWriteRequest.java
copy to plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/InternalPlcProprietaryResponse.java
index 2a6b03d..eb5aa3b 100644
--- a/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/InternalPlcWriteRequest.java
+++ b/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/InternalPlcProprietaryResponse.java
@@ -18,8 +18,7 @@
*/
package org.apache.plc4x.java.base.messages;
-import org.apache.plc4x.java.api.messages.PlcWriteRequest;
+import org.apache.plc4x.java.api.messages.PlcProprietaryResponse;
-public interface InternalPlcWriteRequest extends PlcWriteRequest, InternalPlcRequest {
-
-}
+public interface InternalPlcProprietaryResponse<REQUEST, RESPONSE> extends PlcProprietaryResponse<InternalPlcProprietaryRequest<REQUEST>, RESPONSE>, InternalPlcResponse<InternalPlcProprietaryRequest<REQUEST>> {
+}
\ No newline at end of file
diff --git a/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/InternalPlcWriteRequest.java b/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/InternalPlcWriteRequest.java
index 2a6b03d..a4bad51 100644
--- a/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/InternalPlcWriteRequest.java
+++ b/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/InternalPlcWriteRequest.java
@@ -19,7 +19,13 @@
package org.apache.plc4x.java.base.messages;
import org.apache.plc4x.java.api.messages.PlcWriteRequest;
+import org.apache.plc4x.java.base.messages.items.FieldItem;
+
+import java.util.LinkedList;
public interface InternalPlcWriteRequest extends PlcWriteRequest, InternalPlcRequest {
+ FieldItem getFieldItem(String name);
+
+ LinkedList<FieldItem> getFieldItems();
}
diff --git a/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/items/FieldItem.java b/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/items/FieldItem.java
index 38a1694..1ce4134 100644
--- a/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/items/FieldItem.java
+++ b/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/items/FieldItem.java
@@ -111,7 +111,7 @@ public abstract class FieldItem<T> {
return null;
}
- protected T[] getValues() {
+ public T[] getValues() {
return values;
}