You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cg...@apache.org on 2024/03/15 02:45:40 UTC
(plc4x) branch fix/s7async updated: Fixed time base handling for cyclical subscriptions. Subscription routine for changes is added experimentally.
This is an automated email from the ASF dual-hosted git repository.
cgarcia pushed a commit to branch fix/s7async
in repository https://gitbox.apache.org/repos/asf/plc4x.git
The following commit(s) were added to refs/heads/fix/s7async by this push:
new f8ca0f6226 Fixed time base handling for cyclical subscriptions. Subscription routine for changes is added experimentally.
f8ca0f6226 is described below
commit f8ca0f622680c2c99875331a183b31ec179619a9
Author: Cesar Garcia <ce...@ceos.com.ve>
AuthorDate: Thu Mar 14 22:45:06 2024 -0400
Fixed time base handling for cyclical subscriptions. Subscription routine for changes is added experimentally.
---
.../apache/plc4x/java/s7/events/S7CyclicEvent.java | 131 ++++++++-------------
.../readwrite/protocol/S7ProtocolEventLogic.java | 10 ++
.../s7/readwrite/protocol/S7ProtocolLogic.java | 28 ++++-
.../readwrite/utils/S7PlcSubscriptionRequest.java | 100 +++++++++++++++-
.../org/apache/plc4x/java/spi/values/PlcBINT.java | 5 +
.../org/apache/plc4x/java/spi/values/PlcBOOL.java | 5 +
.../org/apache/plc4x/java/spi/values/PlcBREAL.java | 5 +
.../org/apache/plc4x/java/spi/values/PlcBYTE.java | 5 +
.../org/apache/plc4x/java/spi/values/PlcCHAR.java | 5 +
.../org/apache/plc4x/java/spi/values/PlcDINT.java | 5 +
.../org/apache/plc4x/java/spi/values/PlcDWORD.java | 5 +
.../org/apache/plc4x/java/spi/values/PlcINT.java | 5 +
.../org/apache/plc4x/java/spi/values/PlcLINT.java | 5 +
.../org/apache/plc4x/java/spi/values/PlcLREAL.java | 5 +
.../org/apache/plc4x/java/spi/values/PlcLWORD.java | 5 +
.../org/apache/plc4x/java/spi/values/PlcREAL.java | 5 +
.../plc4x/java/spi/values/PlcRawByteArray.java | 5 +
.../org/apache/plc4x/java/spi/values/PlcSINT.java | 5 +
.../org/apache/plc4x/java/spi/values/PlcUBINT.java | 5 +
.../org/apache/plc4x/java/spi/values/PlcUDINT.java | 5 +
.../org/apache/plc4x/java/spi/values/PlcUINT.java | 5 +
.../org/apache/plc4x/java/spi/values/PlcULINT.java | 5 +
.../org/apache/plc4x/java/spi/values/PlcUSINT.java | 5 +
.../org/apache/plc4x/java/spi/values/PlcWCHAR.java | 5 +
.../org/apache/plc4x/java/spi/values/PlcWORD.java | 5 +
25 files changed, 280 insertions(+), 94 deletions(-)
diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/events/S7CyclicEvent.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/events/S7CyclicEvent.java
index b1ad3ff3ec..42e96ce34a 100644
--- a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/events/S7CyclicEvent.java
+++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/events/S7CyclicEvent.java
@@ -106,34 +106,10 @@ public class S7CyclicEvent implements S7Event {
int i = n[0];
map.put(Fields.RETURNCODE_.name() + i, event.getItems().get(i).getReturnCode().getValue());
map.put(Fields.TRANSPORTSIZE_.name() + i, event.getItems().get(i).getTransportSize().getValue());
-// byte[] buffer = new byte[event.getItems().get(i).getData().size()];
-// j = 0;
-
-// event.getItems().get(i).getData().forEach(s -> {
-// buffer[j] = s.byteValue();
-// j++;
-// });
map.put(tagname, DataToPlcValue(tagname, request, event.getItems().get(i).getData()));
- n[0]++;
-
-
-
-
+ n[0]++;
});
-
-// for (int i=0; i<event.getItemsCount(); i++){
-// //map.put(Fields.RETURNCODE_.name()+i, event.getItems()[i].getReturnCode().getValue());
-// map.put(Fields.RETURNCODE_.name()+i, event.getItems().get(i).getReturnCode().getValue());
-// map.put(Fields.TRANSPORTSIZE_.name()+i, event.getItems().get(i).getTransportSize().getValue());
-// byte[] buffer = new byte[event.getItems().get(i).getData().size()];
-// j = 0;
-// event.getItems().get(i).getData().forEach(s->{
-// buffer[j] = s.byteValue();
-// j ++;
-// });
-// map.put(Fields.DATA_.name()+i, buffer);
-// }
}
public S7CyclicEvent(PlcSubscriptionRequest request, short jobid, S7PayloadUserDataItemCyclicServicesChangeDrivenPush event) {
@@ -145,30 +121,15 @@ public class S7CyclicEvent implements S7Event {
map.put(Fields.JOBID.name(), jobid);
map.put(Fields.ITEMSCOUNT.name(), event.getItemsCount());
int[] n = new int[1];
+
request.getTagNames().forEach(tagname -> {
int i = n[0];
map.put(Fields.RETURNCODE_.name() + i, event.getItems().get(i).getReturnCode().getValue());
map.put(Fields.TRANSPORTSIZE_.name() + i, event.getItems().get(i).getTransportSize().getValue());
- byte[] buffer = new byte[event.getItems().get(i).getData().size()];
- j = 0;
- event.getItems().get(i).getData().forEach(s -> {
- buffer[j] = s.byteValue();
- j++;
- });
- map.put(tagname, buffer);
- n[0]++;
+ map.put(tagname, DataToPlcValue(tagname, request, event.getItems().get(i).getData()));
+ n[0]++;
});
-// for (int i=0; i<event.getItemsCount(); i++){
-// map.put(Fields.RETURNCODE_.name()+i, event.getItems().get(i).getReturnCode().getValue());
-// map.put(Fields.TRANSPORTSIZE_.name()+i, event.getItems().get(i).getTransportSize().getValue());
-// byte[] buffer = new byte[event.getItems().get(i).getData().size()];
-// j = 0;
-// event.getItems().get(i).getData().forEach(s->{
-// buffer[j] = s.byteValue();
-// j ++;
-// });
-// map.put(Fields.DATA_.name()+i, buffer);
-// }
+
}
public S7CyclicEvent(PlcSubscriptionRequest request, short jobid, S7PayloadUserDataItemCyclicServicesSubscribeResponse event) {
@@ -180,30 +141,14 @@ public class S7CyclicEvent implements S7Event {
map.put(Fields.JOBID.name(), jobid);
map.put(Fields.ITEMSCOUNT.name(), event.getItemsCount());
int[] n = new int[1];
+
request.getTagNames().forEach(tagname -> {
int i = n[0];
map.put(Fields.RETURNCODE_.name() + i, event.getItems().get(i).getReturnCode().getValue());
map.put(Fields.TRANSPORTSIZE_.name() + i, event.getItems().get(i).getTransportSize().getValue());
- byte[] buffer = new byte[event.getItems().get(i).getData().size()];
- j = 0;
- event.getItems().get(i).getData().forEach(s -> {
- buffer[j] = s.byteValue();
- j++;
- });
- map.put(tagname, buffer);
- n[0]++;
- });
-// for (int i=0; i<event.getItemsCount(); i++){
-// map.put(Fields.RETURNCODE_.name()+i, event.getItems().get(i).getReturnCode().getValue());
-// map.put(Fields.TRANSPORTSIZE_.name()+i, event.getItems().get(i).getTransportSize().getValue());
-// byte[] buffer = new byte[event.getItems().get(i).getData().size()];
-// j = 0;
-// event.getItems().get(i).getData().forEach(s->{
-// buffer[j] = s.byteValue();
-// j ++;
-// });
-// map.put(Fields.DATA_.name()+i, buffer);
-// }
+ map.put(tagname, DataToPlcValue(tagname, request, event.getItems().get(i).getData()));
+ n[0]++;
+ });
}
public S7CyclicEvent(PlcSubscriptionRequest request, short jobid, S7PayloadUserDataItemCyclicServicesChangeDrivenSubscribeResponse event) {
@@ -215,30 +160,14 @@ public class S7CyclicEvent implements S7Event {
map.put(Fields.JOBID.name(), jobid);
map.put(Fields.ITEMSCOUNT.name(), event.getItemsCount());
int[] n = new int[1];
+
request.getTagNames().forEach(tagname -> {
int i = n[0];
map.put(Fields.RETURNCODE_.name() + i, event.getItems().get(i).getReturnCode().getValue());
map.put(Fields.TRANSPORTSIZE_.name() + i, event.getItems().get(i).getTransportSize().getValue());
- byte[] buffer = new byte[event.getItems().get(i).getData().size()];
- j = 0;
- event.getItems().get(i).getData().forEach(s -> {
- buffer[j] = s.byteValue();
- j++;
- });
- map.put(tagname, buffer);
- n[0]++;
- });
-// for (int i=0; i<event.getItemsCount(); i++){
-// map.put(Fields.RETURNCODE_.name()+i, event.getItems().get(i).getReturnCode().getValue());
-// map.put(Fields.TRANSPORTSIZE_.name()+i, event.getItems().get(i).getTransportSize().getValue());
-// byte[] buffer = new byte[event.getItems().get(i).getData().size()];
-// j = 0;
-// event.getItems().get(i).getData().forEach(s->{
-// buffer[j] = s.byteValue();
-// j ++;
-// });
-// map.put(Fields.DATA_.name()+i, buffer);
-// }
+ map.put(tagname, DataToPlcValue(tagname, request, event.getItems().get(i).getData()));
+ n[0]++;
+ });
}
@Override
@@ -263,7 +192,12 @@ public class S7CyclicEvent implements S7Event {
@Override
public PlcValue getPlcValue(String name) {
- throw new UnsupportedOperationException("Not supported yet.");
+ if (request.getTagNames().contains(name)) {
+ PlcValue plcvalue = (PlcValue) map.get(name);
+ plcvalue.getRaw();
+ return plcvalue;
+ }
+ return null;
}
@Override
@@ -813,7 +747,32 @@ public class S7CyclicEvent implements S7Event {
throw new UnsupportedOperationException("Not supported yet.");
}
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final S7CyclicEvent other = (S7CyclicEvent) obj;
+
+ for (String tag:request.getTagNames()) {
+ final PlcValue othervalue = other.getPlcValue(tag);
+ if (othervalue == null) return false;
+ final PlcValue localvalue = (PlcValue) getPlcValue(tag);
+ if (Arrays.equals(localvalue.getRaw(), othervalue.getRaw()) == false){
+ return false;
+ }
+ };
+
+ return true;
+ }
+
private static PlcValue DataToPlcValue(String tagname, PlcSubscriptionRequest request, List<Short> data){
int[] i = new int[1];
@@ -930,6 +889,8 @@ public class S7CyclicEvent implements S7Event {
return plcValue;
};
+
+
}
diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolEventLogic.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolEventLogic.java
index 0191660ceb..3288a2d77b 100644
--- a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolEventLogic.java
+++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolEventLogic.java
@@ -114,6 +114,8 @@ public class S7ProtocolEventLogic implements PlcSubscriber {
mapConsumers.remove(registration);
}
+
+ //TODO: Replace with disruptor
private class ObjectProcessor implements Runnable {
private final BlockingQueue<S7Event> eventQueue;
@@ -154,6 +156,7 @@ public class S7ProtocolEventLogic implements PlcSubscriber {
}
}
+ //TODO: Replace with disruptor
private class EventDispatcher implements Runnable {
private final BlockingQueue<S7Event> dispatchQueue;
private boolean shutdown = false;
@@ -173,6 +176,10 @@ public class S7ProtocolEventLogic implements PlcSubscriber {
while (!shutdown) {
try {
S7Event s7Event = dispatchQueue.poll(DEFAULT_DELAY, TimeUnit.MILLISECONDS);
+ if ((s7Event == null) && (cycDelayedObject != null)) {
+ s7Event = cycDelayedObject;
+ cycDelayedObject = null;
+ }
if (s7Event != null) {
if (s7Event instanceof S7ModeEvent) {
S7ModeEvent modeEvent = (S7ModeEvent) s7Event;
@@ -202,10 +209,13 @@ public class S7ProtocolEventLogic implements PlcSubscriber {
S7CyclicEvent cyclicEvent = (S7CyclicEvent) s7Event;
if (mapIndex.containsKey(EventType.CYC)) {
Map<PlcConsumerRegistration, Consumer<PlcSubscriptionEvent>> mapConsumers = mapIndex.get(EventType.CYC);
+
if (cycDelayedObject != null) {
mapConsumers.forEach((x, y) -> y.accept(cycDelayedObject));
cycDelayedObject = null;
}
+ if (mapConsumers.isEmpty()) cycDelayedObject = s7Event;
+
mapConsumers.forEach((x, y) -> {
S7PlcSubscriptionHandle sh = (S7PlcSubscriptionHandle) x.getSubscriptionHandles().get(0);
Short id = Short.parseShort(sh.getEventId());
diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java
index e758d2fb85..b161770abf 100644
--- a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java
+++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java
@@ -63,6 +63,7 @@ import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
+import org.apache.plc4x.java.api.types.PlcSubscriptionType;
import org.apache.plc4x.java.s7.events.S7AlarmEvent;
import org.apache.plc4x.java.s7.events.S7ModeEvent;
import org.apache.plc4x.java.s7.events.S7SysEvent;
@@ -114,7 +115,14 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> {
* the values sent PUSH from the PLC to the driver refer to this JobID.
*/
private final Map<Short, PlcSubscriptionRequest> cycRequests = new HashMap<>();
-
+
+ /*
+ * This data structure stores the last value associated with a cyclic
+ * subscription request. In each event received, the values of the internal
+ * PlcValue are compared and if any of them are different, the new value is
+ * transferred to the event stack and the value is updated in this HashMap.
+ */
+ private final Map<Short, S7CyclicEvent> cycChangeValueEvents = new HashMap<>();
private S7DriverContext s7DriverContext;
private RequestTransactionManager tm;
@@ -800,6 +808,10 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> {
S7CyclicEvent cycEvent = new S7CyclicEvent(plcSubscriptionRequest,
msgParameter.getSequenceNumber(),
(S7PayloadUserDataItemCyclicServicesSubscribeResponse) payloadItems.get(0));
+
+ if (plcSubscriptionRequest.getTags().get(0).getPlcSubscriptionType() == PlcSubscriptionType.CHANGE_OF_STATE) {
+ cycChangeValueEvents.put(msgParameter.getSequenceNumber(), cycEvent);
+ }
eventQueue.add(cycEvent);
@@ -1526,7 +1538,7 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> {
} else if ((myParameter.getCpuFunctionType() == 0x00) && (myParameter.getCpuSubfunction() == 0x13)) {
//TODO: Requires reverse engineering.
- } else if ((myParameter.getCpuFunctionGroup() == 0x02) && (myParameter.getCpuFunctionType() == 0x00) && (myParameter.getCpuSubfunction() == 0x01)) { //(05)
+ } else if (((myParameter.getCpuFunctionGroup() == 0x02) && (myParameter.getCpuFunctionType() == 0x00) && (myParameter.getCpuSubfunction() == 0x01))) { //(05)
S7ParameterUserDataItemCPUFunctions parameterItem =
(S7ParameterUserDataItemCPUFunctions)
@@ -1539,7 +1551,17 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> {
S7CyclicEvent cycEvent = new S7CyclicEvent(cycRequests.get(parameterItem.getSequenceNumber()),
parameterItem.getSequenceNumber(),
payloadItem);
- eventQueue.add(cycEvent);
+
+ if (cycChangeValueEvents.containsKey(parameterItem.getSequenceNumber())){
+ S7CyclicEvent lastCycEvent = cycChangeValueEvents.get(parameterItem.getSequenceNumber());
+ if (cycEvent.equals(lastCycEvent ) == false) {
+ cycChangeValueEvents.replace(parameterItem.getSequenceNumber(), cycEvent);
+ eventQueue.add(cycEvent);
+ }
+
+ } else {
+ eventQueue.add(cycEvent);
+ }
} else if ((myParameter.getCpuFunctionGroup() == 0x02) && (myParameter.getCpuFunctionType() == 0x00) && (myParameter.getCpuSubfunction() == 0x05)) { //(06)
diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/utils/S7PlcSubscriptionRequest.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/utils/S7PlcSubscriptionRequest.java
index 16d0f59096..a0c06cb6cf 100644
--- a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/utils/S7PlcSubscriptionRequest.java
+++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/utils/S7PlcSubscriptionRequest.java
@@ -41,6 +41,7 @@ import static org.apache.plc4x.java.s7.readwrite.TimeBase.B01SEC;
import org.apache.plc4x.java.s7.readwrite.tag.S7SubscriptionTag;
import org.apache.plc4x.java.s7.readwrite.tag.S7Tag;
import org.apache.plc4x.java.s7.readwrite.types.S7SubscriptionType;
+import org.apache.plc4x.java.spi.messages.DefaultPlcSubscriptionRequest;
import org.apache.plc4x.java.spi.messages.PlcSubscriber;
public class S7PlcSubscriptionRequest implements PlcSubscriptionRequest, Serializable {
@@ -123,6 +124,27 @@ public class S7PlcSubscriptionRequest implements PlcSubscriptionRequest, Seriali
this.preRegisteredConsumers = new LinkedHashMap<>();
}
+ /*
+ * This method receives a String that describes an S7Tag and the
+ * interval required for its sampling.
+ * The value of the "pollingInterval" parameter is adapted to the
+ * cyclical subscription requirements of an S7-300/S7-400,
+ * for which multiples of the time base given by TimeBase
+ * must be handled. To say:
+ *
+ * . B01SEC -> 100, 200, 300, 400, 500, 600, 700, 800, 900 msec
+ * . B1SEC -> 1, 2, 3, 4, 5, 6, 7, 8, 9 sec
+ * . B10SEC -> 10, 20, 30, 40, 50, 60, 70, 80, 90 sec
+ *
+ * As you can see there are no intermediate values, for example 513 msec,
+ * it will actually be 500 msec, or its nearest rounding.
+ *
+ * @param name Name of the subscription Tag.
+ * @param tagAddress String representing an S7Tag
+ * @param pollingInterval Required sampling rate based on the "TimeBase"
+ * @return PlcSubscriptionRequest.Builder S7SubscriptonTag type constructor
+ *
+ */
@Override
public PlcSubscriptionRequest.Builder addCyclicTagAddress(String name, String tagAddress, Duration pollingInterval) {
if (tags.containsKey(name)) {
@@ -136,6 +158,16 @@ public class S7PlcSubscriptionRequest implements PlcSubscriptionRequest, Seriali
return this;
}
+ /*
+ * This method receives an S7Tag built by the user, he is responsible
+ * for the construction of the object, so no additional verification
+ * is included.
+ *
+ * @param name Name of the subscription Tag.
+ * @param tag Tag of S7SubscriptionTag type.
+ * @param pollingInterval Required sampling rate based on the "TimeBase"
+ * @return PlcSubscriptionRequest.Builder S7SubscriptonTag type constructor
+ */
@Override
public PlcSubscriptionRequest.Builder addCyclicTag(String name, PlcTag tag, Duration pollingInterval) {
if (tags.containsKey(name)) {
@@ -148,16 +180,63 @@ public class S7PlcSubscriptionRequest implements PlcSubscriptionRequest, Seriali
return this;
}
+ /*
+ *
+ */
@Override
public PlcSubscriptionRequest.Builder addChangeOfStateTagAddress(String name, String tagAddress) {
- throw new PlcRuntimeException("Feature currently not supported.");
+ if (tags.containsKey(name)) {
+ throw new PlcRuntimeException("Duplicate tag definition '" + name + "'");
+ }
+ S7Tag[] s7tags = new S7Tag[]{S7Tag.of(tagAddress)};
+ S7SubscriptionTag tag = new S7SubscriptionTag(S7SubscriptionType.CYCLIC_SUBSCRIPTION, s7tags, TimeBase.B01SEC, (short) 1);
+ tags.put(name, new BuilderItem(() -> tag, PlcSubscriptionType.CHANGE_OF_STATE));
+ return this;
}
+ /*
+ *
+ */
@Override
public PlcSubscriptionRequest.Builder addChangeOfStateTag(String name, PlcTag tag) {
- throw new PlcRuntimeException("Feature currently not supported.");
+ if (tags.containsKey(name)) {
+ throw new PlcRuntimeException("Duplicate tag definition '" + name + "'");
+ }
+ if ((tag instanceof S7SubscriptionTag) == false){
+ throw new PlcRuntimeException("Tag is not of type S7SubcriptionTag");
+ }
+ tags.put(name, new BuilderItem(() -> tag, PlcSubscriptionType.CHANGE_OF_STATE));
+ return this;
}
+ /*
+ * This method is responsible for the subscription to Events associated
+ * with the PLC as well as the preliminary version of cyclical
+ * subscription of values.
+ *
+ * The type of function performed by the tag is given by the definition
+ * of the "tagAddress", for example:
+ *
+ * "ACK:16#12345678"
+ *
+ * Represents an acknowledgment of an alarm whose ID is 16#12345678.
+ * The following functions are defined:
+ *
+ * . MODE
+ * . SYS
+ * . USR
+ * . ALM
+ * . ACK
+ * . QUERY
+ * . CYC
+ * . CANCEL
+ *
+ * Go to the driver manual for a complete description.
+ *
+ * @param name Name of the subscription Tag.
+ * @param tag Tag of S7SubscriptionTag type.
+ * @return PlcSubscriptionRequest.Builder S7SubscriptonTag type constructor
+ */
@Override
public PlcSubscriptionRequest.Builder addEventTagAddress(String name, String tagAddress) {
if (tags.containsKey(name)) {
@@ -171,6 +250,15 @@ public class S7PlcSubscriptionRequest implements PlcSubscriptionRequest, Seriali
return this;
}
+ /*
+ * This method receives an S7Tag built by the user, he is responsible
+ * for the construction of the object, so no additional verification
+ * is included.
+ *
+ * @param name Name of the subscription Tag.
+ * @param tag Tag of S7SubscriptionTag type.
+ * @return PlcSubscriptionRequest.Builder S7SubscriptonTag type constructor
+ */
@Override
public PlcSubscriptionRequest.Builder addEventTag(String name, PlcTag tag) {
if (tags.containsKey(name)) {
@@ -228,15 +316,15 @@ public class S7PlcSubscriptionRequest implements PlcSubscriptionRequest, Seriali
throw new PlcRuntimeException("Subscription time cannot be zero.");
}
long millis = duration.toMillis();
- if (millis <= 25500) {
+ if (millis < 1000) {
return TimeBase.B01SEC;
- } if (millis <= 255000) {
+ } if (millis < 10000) {
return TimeBase.B1SEC;
- } if (millis <= 2550000) {
+ } if (millis < 100000) {
return TimeBase.B10SEC;
}
- throw new PlcRuntimeException("The maximum subscription time of 2550 sec.");
+ throw new PlcRuntimeException("The maximum subscription time is 90 sec.");
}
//TODO: Chek multiplier is 1-99 in BCD??
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcBINT.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcBINT.java
index cd8b739a96..e3295121f8 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcBINT.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcBINT.java
@@ -210,6 +210,11 @@ public class PlcBINT extends PlcIECValue<BigInteger> {
public String toString() {
return value.toString();
}
+
+ @Override
+ public byte[] getRaw() {
+ return getBytes();
+ }
public byte[] getBytes() {
byte[] tmp = value.toByteArray();
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcBOOL.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcBOOL.java
index b1f900a9ad..229c805de9 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcBOOL.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcBOOL.java
@@ -253,6 +253,11 @@ public class PlcBOOL extends PlcIECValue<Boolean> {
return toString();
}
+ @Override
+ public byte[] getRaw() {
+ return getBytes();
+ }
+
public byte[] getBytes() {
return ((value != null) && value) ? new byte[]{0x01} : new byte[]{0x00};
}
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcBREAL.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcBREAL.java
index 6b67ea4f3c..6f73a709e6 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcBREAL.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcBREAL.java
@@ -211,6 +211,11 @@ public class PlcBREAL extends PlcIECValue<BigDecimal> {
return value.toString();
}
+ @Override
+ public byte[] getRaw() {
+ return getBytes();
+ }
+
public byte[] getBytes() {
// TODO: Not sure if this is correct ...
byte[] tmp = value.unscaledValue().toByteArray();
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcBYTE.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcBYTE.java
index 76f67e75c1..72370dee5a 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcBYTE.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcBYTE.java
@@ -266,6 +266,11 @@ public class PlcBYTE extends PlcIECValue<Short> {
public String toString() {
return Short.toString(value);
}
+
+ @Override
+ public byte[] getRaw() {
+ return getBytes();
+ }
public byte[] getBytes() {
byte[] bytes = new byte[1];
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcCHAR.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcCHAR.java
index 7f24576d0d..19a4727e0f 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcCHAR.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcCHAR.java
@@ -300,6 +300,11 @@ public class PlcCHAR extends PlcIECValue<Short> {
return Character.toString((char) ((short) value));
}
+ @Override
+ public byte[] getRaw() {
+ return getBytes();
+ }
+
public byte[] getBytes() {
byte[] bytes = new byte[1];
bytes[0] = (byte) (value & 0xff);
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcDINT.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcDINT.java
index b0f2abd170..dc587043a9 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcDINT.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcDINT.java
@@ -240,6 +240,11 @@ public class PlcDINT extends PlcIECValue<Integer> {
return Integer.toString(value);
}
+ @Override
+ public byte[] getRaw() {
+ return getBytes();
+ }
+
public byte[] getBytes() {
return new byte[]{
(byte) ((value >> 24) & 0xff),
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcDWORD.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcDWORD.java
index 64ac2e0575..e33a6f9f25 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcDWORD.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcDWORD.java
@@ -267,6 +267,11 @@ public class PlcDWORD extends PlcIECValue<Long> {
return Long.toString(value);
}
+ @Override
+ public byte[] getRaw() {
+ return getBytes();
+ }
+
public byte[] getBytes() {
byte[] bytes = new byte[4];
bytes[0] = (byte) ((value >> 24) & 0xff);
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcINT.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcINT.java
index 874ad6fb2a..93caa2ce75 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcINT.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcINT.java
@@ -244,6 +244,11 @@ public class PlcINT extends PlcIECValue<Short> {
return Integer.toString(value);
}
+ @Override
+ public byte[] getRaw() {
+ return getBytes();
+ }
+
public byte[] getBytes() {
return new byte[]{
(byte) ((value >> 8) & 0xff),
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcLINT.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcLINT.java
index 3b6e4d5ebf..1e1ecfac0f 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcLINT.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcLINT.java
@@ -237,6 +237,11 @@ public class PlcLINT extends PlcIECValue<Long> {
return Long.toString(value);
}
+ @Override
+ public byte[] getRaw() {
+ return getBytes();
+ }
+
public byte[] getBytes() {
return new byte[]{
(byte) ((value >> 56) & 0xff),
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcLREAL.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcLREAL.java
index a407405f10..2d440d847b 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcLREAL.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcLREAL.java
@@ -227,6 +227,11 @@ public class PlcLREAL extends PlcIECValue<Double> {
return Double.toString(value);
}
+ @Override
+ public byte[] getRaw() {
+ return getBytes();
+ }
+
public byte[] getBytes() {
long longBits = Double.doubleToRawLongBits(value);
return new byte[]{
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcLWORD.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcLWORD.java
index acba299118..c0b055a6a0 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcLWORD.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcLWORD.java
@@ -277,6 +277,11 @@ public class PlcLWORD extends PlcIECValue<BigInteger> {
return value.toString();
}
+ @Override
+ public byte[] getRaw() {
+ return getBytes();
+ }
+
public byte[] getBytes() {
byte[] tmp = value.toByteArray();
byte[] bytes = new byte[8];
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcREAL.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcREAL.java
index bef0e744c5..f919cacecb 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcREAL.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcREAL.java
@@ -229,6 +229,11 @@ public class PlcREAL extends PlcIECValue<Float> {
public String toString() {
return Float.toString(value);
}
+
+ @Override
+ public byte[] getRaw() {
+ return getBytes();
+ }
public byte[] getBytes() {
int intBits = Float.floatToIntBits(value);
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcRawByteArray.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcRawByteArray.java
index cb1fc54cee..65605d8a47 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcRawByteArray.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcRawByteArray.java
@@ -46,6 +46,11 @@ public class PlcRawByteArray extends PlcIECValue<byte[]> {
public String toString() {
return Hex.encodeHexString(value);
}
+
+ @Override
+ public byte[] getRaw() {
+ return getBytes();
+ }
public byte[] getBytes() {
return value;
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcSINT.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcSINT.java
index 852da57090..162f430caa 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcSINT.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcSINT.java
@@ -246,6 +246,11 @@ public class PlcSINT extends PlcIECValue<Byte> {
return Byte.toString(value);
}
+ @Override
+ public byte[] getRaw() {
+ return getBytes();
+ }
+
public byte[] getBytes() {
byte[] bytes = new byte[1];
bytes[0] = (byte) (value & 0xff);
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcUBINT.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcUBINT.java
index 772314204c..e688f9075c 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcUBINT.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcUBINT.java
@@ -266,6 +266,11 @@ public class PlcUBINT extends PlcIECValue<BigInteger> {
return value.toString();
}
+ @Override
+ public byte[] getRaw() {
+ return getBytes();
+ }
+
public byte[] getBytes() {
byte[] tmp = value.toByteArray();
byte[] bytes = new byte[8];
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcUDINT.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcUDINT.java
index 861fd75a32..ede2fa8a03 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcUDINT.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcUDINT.java
@@ -259,6 +259,11 @@ public class PlcUDINT extends PlcIECValue<Long> {
return Long.toString(value);
}
+ @Override
+ public byte[] getRaw() {
+ return getBytes();
+ }
+
public byte[] getBytes() {
byte[] bytes = new byte[4];
bytes[0] = (byte) ((value >> 24) & 0xff);
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcUINT.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcUINT.java
index 8a82ea2359..ee7a66c4f5 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcUINT.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcUINT.java
@@ -253,6 +253,11 @@ public class PlcUINT extends PlcIECValue<Integer> {
return Integer.toString(value);
}
+ @Override
+ public byte[] getRaw() {
+ return getBytes();
+ }
+
public byte[] getBytes() {
return new byte[]{
(byte) ((value >> 8) & 0xff),
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcULINT.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcULINT.java
index 589f06114c..f9107815ae 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcULINT.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcULINT.java
@@ -267,6 +267,11 @@ public class PlcULINT extends PlcIECValue<BigInteger> {
return value.toString();
}
+ @Override
+ public byte[] getRaw() {
+ return getBytes();
+ }
+
public byte[] getBytes() {
byte[] tmp = value.toByteArray();
byte[] bytes = new byte[8];
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcUSINT.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcUSINT.java
index 23346642c7..d6f16e8b2b 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcUSINT.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcUSINT.java
@@ -255,6 +255,11 @@ public class PlcUSINT extends PlcIECValue<Short> {
public String toString() {
return Short.toString(value);
}
+
+ @Override
+ public byte[] getRaw() {
+ return getBytes();
+ }
public byte[] getBytes() {
byte[] bytes = new byte[1];
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcWCHAR.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcWCHAR.java
index d72ac5b042..5e787a3db5 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcWCHAR.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcWCHAR.java
@@ -274,6 +274,11 @@ public class PlcWCHAR extends PlcIECValue<Integer> {
public String toString() {
return Character.toString((char) ((int) value));
}
+
+ @Override
+ public byte[] getRaw() {
+ return getBytes();
+ }
public byte[] getBytes() {
return new byte[]{
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcWORD.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcWORD.java
index a227dc41e0..9003db7753 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcWORD.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcWORD.java
@@ -262,6 +262,11 @@ public class PlcWORD extends PlcIECValue<Integer> {
public String toString() {
return Integer.toString(value);
}
+
+ @Override
+ public byte[] getRaw() {
+ return getBytes();
+ }
public byte[] getBytes() {
return new byte[]{