From 6c9e6545ca953ec53a97435ee3d15947a60e6038 Mon Sep 17 00:00:00 2001 From: Jochen Mader Date: Thu, 27 Nov 2025 16:10:50 +0100 Subject: [PATCH] Enable keep-alive for ADS and S7 --- .../plc4x/types/ads/ADSProtocolAdapter.java | 5 +++++ .../ads/config/ADSSpecificAdapterConfig.java | 16 +++++++++++++++- .../plc4x/types/siemens/S7ProtocolAdapter.java | 6 ++++-- .../siemens/config/S7SpecificAdapterConfig.java | 14 ++++++++++++++ .../ads/config/ADSProtocolAdapterConfigTest.java | 1 + .../config/S7ProtocolAdapterConfigTest.java | 1 + 6 files changed, 40 insertions(+), 3 deletions(-) diff --git a/modules/hivemq-edge-module-plc4x/src/main/java/com/hivemq/edge/adapters/plc4x/types/ads/ADSProtocolAdapter.java b/modules/hivemq-edge-module-plc4x/src/main/java/com/hivemq/edge/adapters/plc4x/types/ads/ADSProtocolAdapter.java index 2de9055b79..d744578ec4 100644 --- a/modules/hivemq-edge-module-plc4x/src/main/java/com/hivemq/edge/adapters/plc4x/types/ads/ADSProtocolAdapter.java +++ b/modules/hivemq-edge-module-plc4x/src/main/java/com/hivemq/edge/adapters/plc4x/types/ads/ADSProtocolAdapter.java @@ -35,6 +35,7 @@ public class ADSProtocolAdapter extends AbstractPlc4xAdapter= 7000) { + // Enable ping if explicitly configured OR if polling interval >= 7s (existing behavior) + boolean autoEnablePing = config.getPlc4xToMqttConfig() != null && + config.getPlc4xToMqttConfig().getPollingIntervalMillis() >= 7000; + if (config.isKeepAlive() || autoEnablePing) { map.put(PING, "true"); map.put(PING_TIME, "4"); } diff --git a/modules/hivemq-edge-module-plc4x/src/main/java/com/hivemq/edge/adapters/plc4x/types/siemens/config/S7SpecificAdapterConfig.java b/modules/hivemq-edge-module-plc4x/src/main/java/com/hivemq/edge/adapters/plc4x/types/siemens/config/S7SpecificAdapterConfig.java index a65442fd4d..ce241e2109 100644 --- a/modules/hivemq-edge-module-plc4x/src/main/java/com/hivemq/edge/adapters/plc4x/types/siemens/config/S7SpecificAdapterConfig.java +++ b/modules/hivemq-edge-module-plc4x/src/main/java/com/hivemq/edge/adapters/plc4x/types/siemens/config/S7SpecificAdapterConfig.java @@ -84,6 +84,12 @@ public enum ControllerType { defaultValue = "0") private final int remoteTsap; + @JsonProperty("keepAlive") + @ModuleConfigField(title = "Keep-Alive", + description = "Enable keep-alive ping to prevent TCP connection timeouts during long polling intervals. Recommended when polling interval exceeds 7 seconds.", + defaultValue = "false") + private final boolean keepAlive; + @JsonProperty(value = "s7ToMqtt", required = true) @ModuleConfigField(title = "S7 To MQTT Config", description = "The configuration for a data stream from S7 to MQTT", @@ -100,6 +106,7 @@ public S7SpecificAdapterConfig( @JsonProperty(value = "remoteSlot") final @Nullable Integer remoteSlot, @JsonProperty(value = "remoteSlot2") final @Nullable Integer remoteSlot2, @JsonProperty(value = "remoteTsap") final @Nullable Integer remoteTsap, + @JsonProperty(value = "keepAlive") final @Nullable Boolean keepAlive, @JsonProperty(value = "s7ToMqtt") final @Nullable S7ToMqttConfig s7ToMqttConfig) { super(port, host); this.port = port; @@ -109,6 +116,7 @@ public S7SpecificAdapterConfig( this.remoteSlot = Objects.requireNonNullElse(remoteSlot, 0); this.remoteSlot2 = Objects.requireNonNullElse(remoteSlot2, 0); this.remoteTsap = Objects.requireNonNullElse(remoteTsap, 0); + this.keepAlive = Objects.requireNonNullElse(keepAlive, false); if (s7ToMqttConfig == null) { this.s7ToMqttConfig = new S7ToMqttConfig(null, null, null); } else { @@ -142,6 +150,10 @@ public int getRemoteTsap() { return remoteTsap; } + public boolean isKeepAlive() { + return keepAlive; + } + public @NotNull ControllerType getControllerType() { return controllerType; } @@ -161,6 +173,7 @@ public boolean equals(final Object o) { getRemoteSlot() == that.getRemoteSlot() && getRemoteSlot2() == that.getRemoteSlot2() && getRemoteTsap() == that.getRemoteTsap() && + isKeepAlive() == that.isKeepAlive() && getControllerType() == that.getControllerType() && Objects.equals(s7ToMqttConfig, that.s7ToMqttConfig); } @@ -174,6 +187,7 @@ public int hashCode() { getRemoteSlot(), getRemoteSlot2(), getRemoteTsap(), + keepAlive, s7ToMqttConfig); } } diff --git a/modules/hivemq-edge-module-plc4x/src/test/java/com/hivemq/edge/adapters/plc4x/types/ads/config/ADSProtocolAdapterConfigTest.java b/modules/hivemq-edge-module-plc4x/src/test/java/com/hivemq/edge/adapters/plc4x/types/ads/config/ADSProtocolAdapterConfigTest.java index 5c2c651dcc..5a92a047bc 100644 --- a/modules/hivemq-edge-module-plc4x/src/test/java/com/hivemq/edge/adapters/plc4x/types/ads/config/ADSProtocolAdapterConfigTest.java +++ b/modules/hivemq-edge-module-plc4x/src/test/java/com/hivemq/edge/adapters/plc4x/types/ads/config/ADSProtocolAdapterConfigTest.java @@ -157,6 +157,7 @@ public void unconvertConfigObject_full_valid() { 16, "1.2.3.4.5.6", "1.2.3.4.5.7", + false, new ADSToMqttConfig( 12, 13, diff --git a/modules/hivemq-edge-module-plc4x/src/test/java/com/hivemq/edge/adapters/plc4x/types/siemens/config/S7ProtocolAdapterConfigTest.java b/modules/hivemq-edge-module-plc4x/src/test/java/com/hivemq/edge/adapters/plc4x/types/siemens/config/S7ProtocolAdapterConfigTest.java index e596ddae92..e03a4fd563 100644 --- a/modules/hivemq-edge-module-plc4x/src/test/java/com/hivemq/edge/adapters/plc4x/types/siemens/config/S7ProtocolAdapterConfigTest.java +++ b/modules/hivemq-edge-module-plc4x/src/test/java/com/hivemq/edge/adapters/plc4x/types/siemens/config/S7ProtocolAdapterConfigTest.java @@ -146,6 +146,7 @@ public void unconvertConfigObject_full_valid() { 3, 4, 5, + false, new S7ToMqttConfig( 12, 13,