From 7ac27a173f9a0abbfe701d3ccf7e717bce1326c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Dywicki?= Date: Thu, 11 Jan 2024 12:17:31 +0100 Subject: [PATCH] Update of amsads binding to permit mixed poll/subscribe operation. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some devices, such as old BX9000, do not support symbol discovery nor subscriptions. They can can work only in polling mode. Any call to symbols causes connection termination. Additionally brought back support for writing commands to ads devices. Minor adjustment - permit 0x preffix for address configuration in hex format. Signed-off-by: Ɓukasz Dywicki --- .../amsads/descriptors/channel-types.adoc | 118 +++++++++--- .../descriptors/config-descriptions.adoc | 123 ++++++++++--- .../docs/amsads/descriptors/thing-types.adoc | 5 - .../channel/DirectHexFieldConfiguration.java | 4 +- .../handler/AbstractAmsAdsThingHandler.java | 173 ++++++++---------- .../handler/AmsAdsNetworkBridgeHandler.java | 4 - .../handler/AmsAdsSerialBridgeHandler.java | 4 - .../handler/channel/AdsChannelHandler.java | 18 +- .../channel/AdsChannelHandlerBase.java | 20 +- .../channel/BinaryAdsChannelHandler.java | 36 +++- .../channel/DateTimeAdsChannelHandler.java | 21 ++- .../channel/NumericAdsChannelHandler.java | 60 +++++- .../channel/TextAdsChannelHandler.java | 26 ++- .../handler/polling/FetchContainer.java | 32 ++++ .../handler/polling/PollFetchContainer.java | 129 +++++++++++++ .../polling/SubscribeFetchContainer.java | 91 +++++++++ .../OH-INF/config/contact-channel-config.xml | 55 ++++-- .../OH-INF/config/datetime-channel-config.xml | 28 ++- .../OH-INF/config/number-channel-config.xml | 37 +++- .../OH-INF/config/switch-channel-config.xml | 37 +++- .../OH-INF/config/text-channel-config.xml | 35 +++- .../resources/OH-INF/thing/thing-types.xml | 8 +- 22 files changed, 817 insertions(+), 247 deletions(-) create mode 100644 bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/polling/FetchContainer.java create mode 100644 bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/polling/PollFetchContainer.java create mode 100644 bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/polling/SubscribeFetchContainer.java diff --git a/bundles/org.connectorio.addons.binding.amsads/docs/amsads/descriptors/channel-types.adoc b/bundles/org.connectorio.addons.binding.amsads/docs/amsads/descriptors/channel-types.adoc index fa3225d2..402c66d0 100644 --- a/bundles/org.connectorio.addons.binding.amsads/docs/amsads/descriptors/channel-types.adoc +++ b/bundles/org.connectorio.addons.binding.amsads/docs/amsads/descriptors/channel-types.adoc @@ -122,6 +122,11 @@ Below table contain configuration parameters which can be assigned to channels o | Inverse conversion logic | Inverse logical representation of FALSE/TRUE values. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== @@ -137,12 +142,12 @@ Below table contain configuration parameters which can be assigned to channels o | indexGroup | INTEGER | Index Group (decimal) -| Index group in decimal format (excluding 0x prefix). For example F00F. +| Index group in decimal format (with or without 0x prefix). For example F00F, 0xF00F. | indexOffset | INTEGER | Index Offset (decimal) -| Offset in given decimal in hex format (excluding 0x prefix). For example 01. +| Offset in given decimal in hex format (with or without 0x prefix). For example 01, 0x01. | type | TEXT @@ -154,6 +159,11 @@ Below table contain configuration parameters which can be assigned to channels o | Inverse conversion logic | Inverse logical representation of FALSE/TRUE values. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== @@ -169,12 +179,12 @@ Below table contain configuration parameters which can be assigned to channels o | indexGroup | TEXT | Index Group (hex) -| Index group in hex format (excluding 0x prefix). For example F00F. +| Index group in hex format (with or without 0x prefix). For example F00F, 0xF00F. | indexOffset -| INTEGER +| TEXT | Index Offset (hex) -| Offset in given group in hex format (excluding 0x prefix). For example 01. +| Offset in given group in hex format (with or without 0x prefix). For example 01, 0x01. | type | TEXT @@ -186,6 +196,11 @@ Below table contain configuration parameters which can be assigned to channels o | Inverse conversion logic | Inverse logical representation of FALSE/TRUE values. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== @@ -213,6 +228,11 @@ Below table contain configuration parameters which can be assigned to channels o | Inverse conversion logic | Inverse logical representation of FALSE/TRUE values. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== @@ -228,12 +248,12 @@ Below table contain configuration parameters which can be assigned to channels o | indexGroup | INTEGER | Index Group (decimal) -| Index group in decimal format (excluding 0x prefix). For example F00F. +| Index group in decimal format (with or without 0x prefix). For example F00F, 0xF00F. | indexOffset | INTEGER | Index Offset (decimal) -| Offset in given decimal in hex format (excluding 0x prefix). For example 01. +| Offset in given decimal in hex format (with or without 0x prefix). For example 01. | type | TEXT @@ -245,6 +265,11 @@ Below table contain configuration parameters which can be assigned to channels o | Inverse conversion logic | Inverse logical representation of FALSE/TRUE values. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== @@ -260,12 +285,12 @@ Below table contain configuration parameters which can be assigned to channels o | indexGroup | TEXT | Index Group (hex) -| Index group in hex format (excluding 0x prefix). For example F00F. +| Index group in hex format (with or without 0x prefix). For example F00F, 0xF00F. | indexOffset -| INTEGER +| TEXT | Index Offset (hex) -| Offset in given group in hex format (excluding 0x prefix). For example 01. +| Offset in given group in hex format (with or without 0x prefix). For example 01, 0x01. | type | TEXT @@ -277,6 +302,11 @@ Below table contain configuration parameters which can be assigned to channels o | Inverse conversion logic | Inverse logical representation of FALSE/TRUE values. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== @@ -299,6 +329,11 @@ Below table contain configuration parameters which can be assigned to channels o | Value encoding | Encoding of the field. Value in brackets indicate length of type in bytes. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== @@ -314,18 +349,23 @@ Below table contain configuration parameters which can be assigned to channels o | indexGroup | INTEGER | Index Group (decimal) -| Index group in decimal format (excluding 0x prefix). For example F00F. +| Index group in decimal format (with or without 0x prefix). For example F00F, 0xF00F. | indexOffset | INTEGER | Index Offset (decimal) -| Offset in given decimal in hex format (excluding 0x prefix). For example 01. +| Offset in given decimal in hex format (with or without 0x prefix). For example 01, 0x01. | type | TEXT | Value encoding | Encoding of the field. Value in brackets indicate length of type in bytes. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== @@ -341,18 +381,23 @@ Below table contain configuration parameters which can be assigned to channels o | indexGroup | TEXT | Index Group (hex) -| Index group in hex format (excluding 0x prefix). For example F00F. +| Index group in hex format (with or without 0x prefix). For example F00F, 0xF00F. | indexOffset -| INTEGER +| TEXT | Index Offset (hex) -| Offset in given group in hex format (excluding 0x prefix). For example 01. +| Offset in given group in hex format (with or without 0x prefix). For example 01, 0x01. | type | TEXT | Value encoding | Encoding of the field. Value in brackets indicate length of type in bytes. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== @@ -390,18 +435,23 @@ Below table contain configuration parameters which can be assigned to channels o | indexGroup | INTEGER | Index Group (decimal) -| Index group in decimal format (excluding 0x prefix). For example F00F. +| Index group in decimal format (with or without 0x prefix). For example F00F, 0xF00F. | indexOffset | INTEGER | Index Offset (decimal) -| Offset in given decimal in hex format (excluding 0x prefix). For example 01. +| Offset in given decimal in hex format (with or without 0x prefix). For example 01, 0x01. | type | TEXT | Value encoding | Encoding of the field. Value in brackets indicate length of type in bytes. Value FALSE or its numeric representation 0 is interpreted as OPEN. Any other value is assumed to represent CLOSED. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== @@ -417,18 +467,23 @@ Below table contain configuration parameters which can be assigned to channels o | indexGroup | TEXT | Index Group (hex) -| Index group in hex format (excluding 0x prefix). For example F00F. +| Index group in hex format (with or without 0x prefix). For example F00F, 0xF00F. | indexOffset -| INTEGER +| TEXT | Index Offset (hex) -| Offset in given group in hex format (excluding 0x prefix). For example 01. +| Offset in given group in hex format (with or without 0x prefix). For example 01, 0x01. | type | TEXT | Value encoding | Encoding of the field. Value in brackets indicate length of type in bytes. Value FALSE or its numeric representation 0 is interpreted as OPEN. Any other value is assumed to represent CLOSED. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== @@ -451,6 +506,11 @@ Below table contain configuration parameters which can be assigned to channels o | Value encoding | Encoding of the field. Value in brackets indicate length of type in bytes. Value FALSE or its numeric representation 0 is interpreted as OPEN. Any other value is assumed to represent CLOSED. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== @@ -466,18 +526,23 @@ Below table contain configuration parameters which can be assigned to channels o | indexGroup | INTEGER | Index Group (decimal) -| Index group in decimal format (excluding 0x prefix). For example F00F. +| Index group in decimal format (with or without 0x prefix). For example F00F, 0xF00F. | indexOffset | INTEGER | Index Offset (decimal) -| Offset in given decimal in hex format (excluding 0x prefix). For example 01. +| Offset in given decimal in hex format (with or without 0x prefix). For example 01, 0x01. | type | TEXT | Value encoding | Encoding of the field. Value in brackets indicate length of type in bytes. Value FALSE or its numeric representation 0 is interpreted as OPEN. Any other value is assumed to represent CLOSED. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== @@ -493,18 +558,23 @@ Below table contain configuration parameters which can be assigned to channels o | indexGroup | TEXT | Index Group (hex) -| Index group in hex format (excluding 0x prefix). For example F00F. +| Index group in hex format (with or without 0x prefix). For example F00F, 0xF00F. | indexOffset | INTEGER | Index Offset (hex) -| Offset in given group in hex format (excluding 0x prefix). For example 01. +| Offset in given group in hex format (). For example 01. | type | TEXT | Value encoding | Encoding of the field. Value in brackets indicate length of type in bytes. Value FALSE or its numeric representation 0 is interpreted as OPEN. Any other value is assumed to represent CLOSED. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== diff --git a/bundles/org.connectorio.addons.binding.amsads/docs/amsads/descriptors/config-descriptions.adoc b/bundles/org.connectorio.addons.binding.amsads/docs/amsads/descriptors/config-descriptions.adoc index 82deeee8..4b2cdac1 100644 --- a/bundles/org.connectorio.addons.binding.amsads/docs/amsads/descriptors/config-descriptions.adoc +++ b/bundles/org.connectorio.addons.binding.amsads/docs/amsads/descriptors/config-descriptions.adoc @@ -18,6 +18,11 @@ | Value encoding | Encoding of the field. Value in brackets indicate length of type in bytes. Value FALSE or its numeric representation 0 is interpreted as OPEN. Any other value is assumed to represent CLOSED. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== [[thing-type:co7io-amsads:serial]] @@ -57,18 +62,23 @@ | indexGroup | INTEGER | Index Group (decimal) -| Index group in decimal format (excluding 0x prefix). For example F00F. +| Index group in decimal format (with or without 0x prefix). For example F00F, 0xF00F. | indexOffset | INTEGER | Index Offset (decimal) -| Offset in given decimal in hex format (excluding 0x prefix). For example 01. +| Offset in given decimal in hex format (with or without 0x prefix). For example 01, 0x01. | type | TEXT | Value encoding | Encoding of the field. Value in brackets indicate length of type in bytes. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== [[thing-type:co7io-amsads:ams]] @@ -108,18 +118,23 @@ | indexGroup | TEXT | Index Group (hex) -| Index group in hex format (excluding 0x prefix). For example F00F. +| Index group in hex format (with or without 0x prefix). For example F00F, 0xF00F. | indexOffset -| INTEGER +| TEXT | Index Offset (hex) -| Offset in given group in hex format (excluding 0x prefix). For example 01. +| Offset in given group in hex format (with or without 0x prefix). For example 01, 0x01. | type | TEXT | Value encoding | Encoding of the field. Value in brackets indicate length of type in bytes. Value FALSE or its numeric representation 0 is interpreted as OPEN. Any other value is assumed to represent CLOSED. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== [[thing-type:co7io-amsads:switch-direct-dec-tag]] @@ -131,12 +146,12 @@ | indexGroup | INTEGER | Index Group (decimal) -| Index group in decimal format (excluding 0x prefix). For example F00F. +| Index group in decimal format (with or without 0x prefix). For example F00F, 0xF00F. | indexOffset | INTEGER | Index Offset (decimal) -| Offset in given decimal in hex format (excluding 0x prefix). For example 01. +| Offset in given decimal in hex format (with or without 0x prefix). For example 01, 0x01. | type | TEXT @@ -148,6 +163,11 @@ | Inverse conversion logic | Inverse logical representation of FALSE/TRUE values. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== [[thing-type:co7io-amsads:datetime-direct-dec-tag]] @@ -159,18 +179,23 @@ | indexGroup | INTEGER | Index Group (decimal) -| Index group in decimal format (excluding 0x prefix). For example F00F. +| Index group in decimal format (with or without 0x prefix). For example F00F, 0xF00F. | indexOffset | INTEGER | Index Offset (decimal) -| Offset in given decimal in hex format (excluding 0x prefix). For example 01. +| Offset in given decimal in hex format (with or without 0x prefix). For example 01, 0x01. | type | TEXT | Value encoding | Encoding of the field. Value in brackets indicate length of type in bytes. Value FALSE or its numeric representation 0 is interpreted as OPEN. Any other value is assumed to represent CLOSED. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== [[thing-type:co7io-amsads:number-symbol-tag]] @@ -189,6 +214,11 @@ | Value encoding | Encoding of the field. Value in brackets indicate length of type in bytes. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== [[thing-type:co7io-amsads:contact-direct-hex-tag]] @@ -200,12 +230,12 @@ | indexGroup | TEXT | Index Group (hex) -| Index group in hex format (excluding 0x prefix). For example F00F. +| Index group in hex format (with or without 0x prefix). For example F00F, 0xF00F. | indexOffset -| INTEGER +| TEXT | Index Offset (hex) -| Offset in given group in hex format (excluding 0x prefix). For example 01. +| Offset in given group in hex format (with or without 0x prefix). For example 01, 0x01. | type | TEXT @@ -217,6 +247,11 @@ | Inverse conversion logic | Inverse logical representation of FALSE/TRUE values. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== [[thing-type:co7io-amsads:switch-symbol-tag]] @@ -240,6 +275,11 @@ | Inverse conversion logic | Inverse logical representation of FALSE/TRUE values. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== [[thing-type:co7io-amsads:text-direct-hex-tag]] @@ -251,18 +291,23 @@ | indexGroup | TEXT | Index Group (hex) -| Index group in hex format (excluding 0x prefix). For example F00F. +| Index group in hex format (with or without 0x prefix). For example F00F, 0xF00F. | indexOffset | INTEGER | Index Offset (hex) -| Offset in given group in hex format (excluding 0x prefix). For example 01. +| Offset in given group in hex format (). For example 01. | type | TEXT | Value encoding | Encoding of the field. Value in brackets indicate length of type in bytes. Value FALSE or its numeric representation 0 is interpreted as OPEN. Any other value is assumed to represent CLOSED. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== [[thing-type:co7io-amsads:number-direct-hex-tag]] @@ -274,18 +319,23 @@ | indexGroup | TEXT | Index Group (hex) -| Index group in hex format (excluding 0x prefix). For example F00F. +| Index group in hex format (with or without 0x prefix). For example F00F, 0xF00F. | indexOffset -| INTEGER +| TEXT | Index Offset (hex) -| Offset in given group in hex format (excluding 0x prefix). For example 01. +| Offset in given group in hex format (with or without 0x prefix). For example 01, 0x01. | type | TEXT | Value encoding | Encoding of the field. Value in brackets indicate length of type in bytes. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== [[thing-type:co7io-amsads:switch-direct-hex-tag]] @@ -297,12 +347,12 @@ | indexGroup | TEXT | Index Group (hex) -| Index group in hex format (excluding 0x prefix). For example F00F. +| Index group in hex format (with or without 0x prefix). For example F00F, 0xF00F. | indexOffset -| INTEGER +| TEXT | Index Offset (hex) -| Offset in given group in hex format (excluding 0x prefix). For example 01. +| Offset in given group in hex format (with or without 0x prefix). For example 01, 0x01. | type | TEXT @@ -314,6 +364,11 @@ | Inverse conversion logic | Inverse logical representation of FALSE/TRUE values. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== [[thing-type:co7io-amsads:contact-direct-dec-tag]] @@ -325,12 +380,12 @@ | indexGroup | INTEGER | Index Group (decimal) -| Index group in decimal format (excluding 0x prefix). For example F00F. +| Index group in decimal format (with or without 0x prefix). For example F00F, 0xF00F. | indexOffset | INTEGER | Index Offset (decimal) -| Offset in given decimal in hex format (excluding 0x prefix). For example 01. +| Offset in given decimal in hex format (with or without 0x prefix). For example 01. | type | TEXT @@ -342,6 +397,11 @@ | Inverse conversion logic | Inverse logical representation of FALSE/TRUE values. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== [[thing-type:co7io-amsads:datetime-symbol-tag]] @@ -371,18 +431,23 @@ | indexGroup | INTEGER | Index Group (decimal) -| Index group in decimal format (excluding 0x prefix). For example F00F. +| Index group in decimal format (with or without 0x prefix). For example F00F, 0xF00F. | indexOffset | INTEGER | Index Offset (decimal) -| Offset in given decimal in hex format (excluding 0x prefix). For example 01. +| Offset in given decimal in hex format (with or without 0x prefix). For example 01, 0x01. | type | TEXT | Value encoding | Encoding of the field. Value in brackets indicate length of type in bytes. Value FALSE or its numeric representation 0 is interpreted as OPEN. Any other value is assumed to represent CLOSED. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== [[thing-type:co7io-amsads:network]] @@ -421,11 +486,6 @@ | Target AMS Network port | This is virtual port which is internally dispatched by PLC controller to running tasks or system services. -| refreshInterval -| INTEGER -| Refresh interval -| Time between next poll cycles. - | discoverChannels | BOOLEAN | Discover channels @@ -454,6 +514,11 @@ | Inverse conversion logic | Inverse logical representation of FALSE/TRUE values. +| refreshInterval +| INTEGER +| Refresh interval +| Default refresh interval specified for entire connection and devices associated with it. Setting refresh interval forces this channel to be polled rather than subscribed. It might help with older devices which do not support subscriptions. + |=== diff --git a/bundles/org.connectorio.addons.binding.amsads/docs/amsads/descriptors/thing-types.adoc b/bundles/org.connectorio.addons.binding.amsads/docs/amsads/descriptors/thing-types.adoc index a5b6dabd..752fcd7a 100644 --- a/bundles/org.connectorio.addons.binding.amsads/docs/amsads/descriptors/thing-types.adoc +++ b/bundles/org.connectorio.addons.binding.amsads/docs/amsads/descriptors/thing-types.adoc @@ -66,11 +66,6 @@ Supported bridges: | Target AMS Network port | This is virtual port which is internally dispatched by PLC controller to running tasks or system services. -| refreshInterval -| INTEGER -| Refresh interval -| Time between next poll cycles. - | discoverChannels | BOOLEAN | Discover channels diff --git a/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/config/channel/DirectHexFieldConfiguration.java b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/config/channel/DirectHexFieldConfiguration.java index 6200bebd..9d5bf99f 100644 --- a/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/config/channel/DirectHexFieldConfiguration.java +++ b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/config/channel/DirectHexFieldConfiguration.java @@ -22,10 +22,10 @@ public class DirectHexFieldConfiguration extends TypedChannelConfiguration imple public String indexOffset; public long getIndexGroup() { - return Long.parseLong(indexGroup, 16); + return indexGroup.startsWith("0x") ? Long.parseLong(indexGroup.substring(2), 16) : Long.parseLong(indexGroup, 16); } public long getIndexOffset() { - return Long.parseLong(indexGroup, 16); + return indexOffset.startsWith("0x") ? Long.parseLong(indexOffset.substring(2), 16) : Long.parseLong(indexOffset, 16); } } diff --git a/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/AbstractAmsAdsThingHandler.java b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/AbstractAmsAdsThingHandler.java index 2638aea3..93f713cd 100644 --- a/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/AbstractAmsAdsThingHandler.java +++ b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/AbstractAmsAdsThingHandler.java @@ -17,45 +17,38 @@ */ package org.connectorio.addons.binding.amsads.internal.handler; -import java.math.BigDecimal; +import java.util.AbstractMap.SimpleEntry; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Optional; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutionException; -import java.util.function.Consumer; +import org.apache.plc4x.java.ads.tag.AdsTag; import org.apache.plc4x.java.api.PlcConnection; -import org.apache.plc4x.java.api.exceptions.PlcException; -import org.apache.plc4x.java.api.messages.PlcSubscriptionEvent; -import org.apache.plc4x.java.api.messages.PlcSubscriptionRequest.Builder; -import org.apache.plc4x.java.api.messages.PlcSubscriptionResponse; -import org.apache.plc4x.java.api.messages.PlcUnsubscriptionRequest; import org.apache.plc4x.java.api.messages.PlcWriteRequest; -import org.apache.plc4x.java.api.model.PlcSubscriptionHandle; +import org.apache.plc4x.java.api.types.PlcResponseCode; import org.apache.plc4x.java.api.value.PlcValue; -import org.apache.plc4x.java.spi.values.PlcBOOL; -import org.connectorio.addons.binding.amsads.internal.config.AmsConfiguration; import org.connectorio.addons.binding.amsads.internal.config.AdsConfiguration; +import org.connectorio.addons.binding.amsads.internal.config.AmsConfiguration; import org.connectorio.addons.binding.amsads.internal.handler.channel.AdsChannelHandler; import org.connectorio.addons.binding.amsads.internal.handler.channel.ChannelHandlerFactory; +import org.connectorio.addons.binding.amsads.internal.handler.polling.FetchContainer; +import org.connectorio.addons.binding.amsads.internal.handler.polling.PollFetchContainer; +import org.connectorio.addons.binding.amsads.internal.handler.polling.SubscribeFetchContainer; import org.connectorio.addons.binding.amsads.internal.symbol.SymbolEntry; import org.connectorio.addons.binding.amsads.internal.symbol.SymbolReader; import org.connectorio.addons.binding.amsads.internal.symbol.SymbolReaderFactory; import org.connectorio.addons.binding.handler.GenericThingHandlerBase; -import org.openhab.core.library.types.DecimalType; -import org.openhab.core.library.types.OnOffType; import org.openhab.core.thing.Channel; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingStatus; import org.openhab.core.thing.ThingStatusDetail; import org.openhab.core.types.Command; -import org.openhab.core.types.State; -import org.openhab.core.types.UnDefType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -70,10 +63,11 @@ public abstract class AbstractAmsAdsThingHandler handlerMap = new ConcurrentHashMap<>(); + private final Map> handlerMap = new ConcurrentHashMap<>(); private final CompletableFuture initializer = new CompletableFuture<>();; - private PlcUnsubscriptionRequest unsubscriptionRequest; + private FetchContainer subscriber; + private FetchContainer poller; public AbstractAmsAdsThingHandler(Thing thing, SymbolReaderFactory symbolReaderFactory, ChannelHandlerFactory channelHandlerFactory) { super(thing); @@ -83,16 +77,35 @@ public AbstractAmsAdsThingHandler(Thing thing, SymbolReaderFactory symbolReaderF @Override public void handleCommand(ChannelUID channelUID, Command command) { - AdsChannelHandler channelHandler = handlerMap.get(channelUID.getAsString()); - if (channelHandler == null) { + String channelId = channelUID.getAsString(); + Entry handlerEntry = handlerMap.get(channelId); + if (handlerEntry == null) { logger.warn("Could not handle command '{}', unsupported channel {}", command, channelUID); return; } + PlcValue value = handlerEntry.getValue().update(command); + if (value == null) { + logger.warn("Skip write channel {} write attempt with command {}, can not determine write value", channelId, command); + return; + } + getPlcConnection().thenCompose(connection -> { + logger.trace("Attempting to send channel {} command {}", channelId, command); PlcWriteRequest.Builder builder = connection.writeRequestBuilder(); - //channelHandler.update(builder, channelUID.getAsString(), command); - return builder.build().execute(); + builder.addTag(channelId, handlerEntry.getKey(), value); + return builder.build().execute().whenComplete((r, e) -> { + if (e != null) { + logger.warn("Failure while writing channel {} command {} to device.", channelId, command, e); + return; + } + PlcResponseCode responseCode = r.getResponseCode(channelId); + if (responseCode != PlcResponseCode.OK) { + logger.warn("Error '{}' reported for channel {} write attempt with command {}", responseCode, channelId, command); + return; + } + logger.debug("Successful write for channel {} with command {}", channelId, command); + }); }); } @@ -126,14 +139,17 @@ public void initialize() { } Set symbolEntries = Collections.emptySet(); - try { - SymbolReader reader = symbolReaderFactory.create(connection); - symbolEntries = reader.read().join(); - } catch (Exception e) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.HANDLER_INITIALIZING_ERROR, "Could not retrieve data type and symbol information from ADS device " + e.getMessage()); - } + // populate raw symbol table, adjust bug in PLC4X itself + SymbolReader reader = symbolReaderFactory.create(connection); if (getThingConfig().get().discoverChannels) { + try { + symbolEntries = reader.read().join(); + } catch (Exception e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.HANDLER_INITIALIZING_ERROR, "Could not retrieve data type and symbol information from ADS device " + e.getMessage()); + return; + } + try { updateChannels(symbolEntries); } catch (Exception e) { @@ -144,48 +160,40 @@ public void initialize() { } List channels = getThing().getChannels(); - Builder subscriptionBuilder = connection.subscriptionRequestBuilder(); + poller = new PollFetchContainer(scheduler, connection); + subscriber = new SubscribeFetchContainer(connection); for (Channel channel : channels) { AdsChannelHandler handler = channelHandlerFactory.map(thing, getCallback(), channel); if (handler != null) { String channelId = channel.getUID().getAsString(); - handlerMap.put(channelId, handler); - handler.subscribe(subscriptionBuilder, channelId); + AdsTag tag = handler.createTag(); + if (tag == null) { + logger.warn("Ignoring channel {}, unsupported tag address", channelId); + continue; + } + if (handler.getRefreshInterval() != null) { + poller.add(handler.getRefreshInterval(), channelId, tag, handler::onChange); + } else { + subscriber.add(null, channelId, tag, handler::onChange); + } + // register handler so we can dispatch commands + handlerMap.put(channelId, new SimpleEntry<>(tag, handler)); } } - try { - PlcSubscriptionResponse rsp = subscriptionBuilder.build().execute().whenComplete((r, e) -> { - if (e != null) { - logger.error("Failed to setup subscription within PLC", e); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.HANDLER_INITIALIZING_ERROR, "Failure while subscribing for data subscribe " + e.getMessage()); - return; - } - - PlcUnsubscriptionRequest.Builder urb = connection.unsubscriptionRequestBuilder(); - for (String channelId : r.getTagNames()) { - AdsChannelHandler handler = handlerMap.get(channelId); - if (handler == null) { - logger.warn("Received update for unknown channel {} in thing {}", channelId, thing.getUID()); - continue; - } - PlcSubscriptionHandle subscriptionHandle = r.getSubscriptionHandle(channelId); - subscriptionHandle.register(new Consumer() { - @Override - public void accept(PlcSubscriptionEvent plcSubscriptionEvent) { - Object value = plcSubscriptionEvent.getObject(channelId); - if (value != null) { - logger.debug("Channel {} received update {}", channelId, value); - handler.onChange(value); - } - } - }); - urb.addHandles(subscriptionHandle); - } - unsubscriptionRequest = urb.build(); + if (channels.isEmpty()) { + updateStatus(ThingStatus.ONLINE); + return; + } - updateStatus(ThingStatus.ONLINE); - }).get(); + try { + if (subscriber.start()) { + logger.info("Started ADS subscription for thing {}", thing.getUID()); + } + if (poller.start()) { + logger.info("Started ADS polling for thing {}", thing.getUID()); + } + updateStatus(ThingStatus.ONLINE); } catch (Exception e) { logger.error("Failed to initialize thing", e); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.HANDLER_INITIALIZING_ERROR, "Failed to initialize thing " + e.getMessage()); @@ -195,10 +203,19 @@ public void accept(PlcSubscriptionEvent plcSubscriptionEvent) { @Override public void dispose() { - if (unsubscriptionRequest != null) { + if (poller != null) { + scheduler.execute(() -> { + try { + poller.stop(); + } catch (Exception e) { + logger.warn("Failed to gracefully shutdown polling", e); + } + }); + } + if (subscriber != null) { scheduler.execute(() -> { try { - unsubscriptionRequest.execute().get(); + subscriber.stop(); } catch (Exception e) { logger.warn("Failed to gracefully shutdown subscription", e); } @@ -216,36 +233,6 @@ public void dispose() { super.dispose(); } - private State convert(Object value) { - if (value == null) { - return UnDefType.NULL; - } - if (value instanceof Boolean) { - return (Boolean) value ? OnOffType.ON : OnOffType.OFF; - } - if (value instanceof BigDecimal) { - return new DecimalType((BigDecimal) value); - } - if (value instanceof Long) { - return new DecimalType((Long) value); - } - if (value instanceof Integer) { - return new DecimalType((Integer) value); - } - if (value instanceof Short) { - return new DecimalType((Short) value); - } - if (value instanceof Float) { - return new DecimalType((Float) value); - } - if (value instanceof Double) { - return new DecimalType((Double) value); - } - - // missing mapping - return UnDefType.UNDEF; - } - private void updateChannels(Set symbolEntries) { List channels = new ArrayList<>(); diff --git a/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/AmsAdsNetworkBridgeHandler.java b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/AmsAdsNetworkBridgeHandler.java index ee628436..08b0b728 100644 --- a/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/AmsAdsNetworkBridgeHandler.java +++ b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/AmsAdsNetworkBridgeHandler.java @@ -91,10 +91,6 @@ public void dispose() { } } - @Override - public void handleCommand(ChannelUID channelUID, Command command) { - } - @Override protected Runnable createInitializer(AmsConfiguration amsAds, CompletableFuture initializer) { return new Runnable() { diff --git a/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/AmsAdsSerialBridgeHandler.java b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/AmsAdsSerialBridgeHandler.java index f64de995..e9860144 100644 --- a/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/AmsAdsSerialBridgeHandler.java +++ b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/AmsAdsSerialBridgeHandler.java @@ -49,10 +49,6 @@ public AmsAdsSerialBridgeHandler(Thing thing, SymbolReaderFactory symbolReaderFa this.driverManager = driverManager; } - @Override - public void handleCommand(ChannelUID channelUID, Command command) { - } - @Override protected Runnable createInitializer(AmsConfiguration amsAds, CompletableFuture initializer) { return new Runnable() { diff --git a/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/channel/AdsChannelHandler.java b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/channel/AdsChannelHandler.java index 2225957a..f1c74ead 100644 --- a/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/channel/AdsChannelHandler.java +++ b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/channel/AdsChannelHandler.java @@ -17,10 +17,14 @@ */ package org.connectorio.addons.binding.amsads.internal.handler.channel; -import org.apache.plc4x.java.api.messages.PlcSubscriptionRequest.Builder; +import org.apache.plc4x.java.ads.tag.AdsTag; +import org.apache.plc4x.java.api.messages.PlcWriteRequest; +import org.apache.plc4x.java.api.messages.PlcWriteRequest.Builder; +import org.apache.plc4x.java.api.value.PlcValue; import org.connectorio.addons.binding.amsads.AmsAdsBindingConstants; import org.openhab.core.thing.Channel; import org.openhab.core.thing.type.ChannelTypeUID; +import org.openhab.core.types.Command; /** * Handler which is responsible for controlling and discovering channel information. @@ -49,7 +53,17 @@ public interface AdsChannelHandler { Channel createChannel(); - void subscribe(Builder subscriptionBuilder, String channelId); + AdsTag createTag(); + + /** + * Returns refresh interval time expressed in milliseconds if channel should be polled rather + * than subscribed using ads notifications. + * + * @return + */ + Long getRefreshInterval(); void onChange(Object value); + + PlcValue update(Command command); } diff --git a/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/channel/AdsChannelHandlerBase.java b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/channel/AdsChannelHandlerBase.java index 1c491bf0..e5d66293 100644 --- a/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/channel/AdsChannelHandlerBase.java +++ b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/channel/AdsChannelHandlerBase.java @@ -18,11 +18,14 @@ package org.connectorio.addons.binding.amsads.internal.handler.channel; import java.util.Collections; +import java.util.Optional; import org.apache.plc4x.java.ads.readwrite.AdsDataType; import org.apache.plc4x.java.ads.tag.AdsTag; import org.apache.plc4x.java.ads.tag.DirectAdsTag; import org.apache.plc4x.java.ads.tag.SymbolicAdsTag; -import org.apache.plc4x.java.api.messages.PlcSubscriptionRequest.Builder; +import org.apache.plc4x.java.api.messages.PlcReadRequest; +import org.apache.plc4x.java.api.messages.PlcSubscriptionRequest; +import org.apache.plc4x.java.api.messages.PlcWriteRequest.Builder; import org.apache.plc4x.java.api.types.PlcValueType; import org.connectorio.addons.binding.amsads.internal.config.channel.DirectFieldConfiguration; import org.connectorio.addons.binding.amsads.internal.config.channel.SymbolicFieldConfiguration; @@ -30,6 +33,7 @@ import org.openhab.core.thing.Channel; import org.openhab.core.thing.Thing; import org.openhab.core.thing.binding.ThingHandlerCallback; +import org.openhab.core.types.Command; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,19 +43,21 @@ public abstract class AdsChannelHandlerBase implements AdsChannelHandler { protected final Thing thing; protected final ThingHandlerCallback callback; protected final Channel channel; + protected final Long refreshInterval; // conditional protected AdsChannelHandlerBase(Thing thing, ThingHandlerCallback callback, Channel channel) { this.thing = thing; this.callback = callback; this.channel = channel; + this.refreshInterval = Optional.ofNullable(channel.getConfiguration()) + .map(cfg -> cfg.get("refreshInterval")) + .map(val -> val instanceof Long ? (Long) val : Long.parseLong("" + val)) + .orElse(null); } - protected void subscribe(Builder subscriptionBuilder, AdsTag tag, String channelId) { - if (tag == null) { - logger.warn("Could not determine valid subscription kind for channel {} with config {}", channel.getUID(), channel.getConfiguration().getProperties()); - return; - } - subscriptionBuilder.addChangeOfStateTag(channelId, tag); + @Override + public Long getRefreshInterval() { + return refreshInterval; } protected AdsTag createTag(TypedChannelConfiguration typeCfg, DirectFieldConfiguration address) { diff --git a/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/channel/BinaryAdsChannelHandler.java b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/channel/BinaryAdsChannelHandler.java index 15b2a74c..efdf37e8 100644 --- a/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/channel/BinaryAdsChannelHandler.java +++ b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/channel/BinaryAdsChannelHandler.java @@ -18,9 +18,13 @@ package org.connectorio.addons.binding.amsads.internal.handler.channel; import java.util.Map; -import org.apache.plc4x.java.api.messages.PlcSubscriptionRequest.Builder; +import org.apache.plc4x.java.ads.tag.AdsTag; +import org.apache.plc4x.java.api.messages.PlcWriteRequest.Builder; +import org.apache.plc4x.java.api.value.PlcValue; +import org.apache.plc4x.java.spi.values.PlcBOOL; import org.connectorio.addons.binding.amsads.internal.config.channel.binary.BinaryDirectDecimalFieldConfiguration; import org.connectorio.addons.binding.amsads.internal.config.channel.binary.BinaryDirectHexFieldConfiguration; +import org.connectorio.addons.binding.amsads.internal.config.channel.binary.BinaryFieldConfiguration; import org.connectorio.addons.binding.amsads.internal.config.channel.binary.BinarySymbolicFieldConfiguration; import org.connectorio.addons.binding.amsads.internal.symbol.SymbolEntry; import org.openhab.core.config.core.Configuration; @@ -32,6 +36,7 @@ import org.openhab.core.thing.Thing; import org.openhab.core.thing.binding.ThingHandlerCallback; import org.openhab.core.thing.binding.builder.ChannelBuilder; +import org.openhab.core.types.Command; public class BinaryAdsChannelHandler extends AdsChannelHandlerBase implements AdsChannelHandler { @@ -68,26 +73,41 @@ public Channel createChannel() { } @Override - public void subscribe(Builder subscriptionBuilder, String channelId) { + public PlcValue update(Command command) { + BinaryFieldConfiguration config = channel.getConfiguration().as(BinaryFieldConfiguration.class); + if (command instanceof OnOffType) { + boolean on = OnOffType.ON == command; + return new PlcBOOL(config.isInverse() ? !on : on); + } + if (command instanceof OpenClosedType) { + boolean open = OpenClosedType.OPEN == command; + return new PlcBOOL(config.isInverse() ? !open : open); + } + return null; + } + + @Override + public AdsTag createTag() { if (CONTACT_DIRECT_DEC.equals(channel.getChannelTypeUID())) { BinaryDirectDecimalFieldConfiguration configuration = channel.getConfiguration().as(BinaryDirectDecimalFieldConfiguration.class); - subscribe(subscriptionBuilder, createTag(configuration, configuration), channelId); + return createTag(configuration, configuration); } else if (CONTACT_DIRECT_HEX.equals(channel.getChannelTypeUID())) { BinaryDirectHexFieldConfiguration configuration = channel.getConfiguration().as(BinaryDirectHexFieldConfiguration.class); - subscribe(subscriptionBuilder, createTag(configuration, configuration), channelId); + return createTag(configuration, configuration); } else if (CONTACT_SYMBOL.equals(channel.getChannelTypeUID())) { BinarySymbolicFieldConfiguration configuration = channel.getConfiguration().as(BinarySymbolicFieldConfiguration.class); - subscribe(subscriptionBuilder, createTag(configuration, configuration), channelId); + return createTag(configuration, configuration); } else if (SWITCH_DIRECT_HEX.equals(channel.getChannelTypeUID())) { BinaryDirectDecimalFieldConfiguration configuration = channel.getConfiguration().as(BinaryDirectDecimalFieldConfiguration.class); - subscribe(subscriptionBuilder, createTag(configuration, configuration), channelId); + return createTag(configuration, configuration); } else if (SWITCH_DIRECT_DEC.equals(channel.getChannelTypeUID())) { BinaryDirectHexFieldConfiguration configuration = channel.getConfiguration().as(BinaryDirectHexFieldConfiguration.class); - subscribe(subscriptionBuilder, createTag(configuration, configuration), channelId); + return createTag(configuration, configuration); } else if (SWITCH_SYMBOL.equals(channel.getChannelTypeUID())) { BinarySymbolicFieldConfiguration configuration = channel.getConfiguration().as(BinarySymbolicFieldConfiguration.class); - subscribe(subscriptionBuilder, createTag(configuration, configuration), channelId); + return createTag(configuration, configuration); } + return null; } @Override diff --git a/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/channel/DateTimeAdsChannelHandler.java b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/channel/DateTimeAdsChannelHandler.java index cda9ceee..2ee18d56 100644 --- a/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/channel/DateTimeAdsChannelHandler.java +++ b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/channel/DateTimeAdsChannelHandler.java @@ -17,24 +17,22 @@ */ package org.connectorio.addons.binding.amsads.internal.handler.channel; -import java.time.Duration; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.ZoneId; import java.util.Map; +import org.apache.plc4x.java.ads.tag.AdsTag; import org.apache.plc4x.java.api.messages.PlcSubscriptionRequest.Builder; +import org.apache.plc4x.java.api.value.PlcValue; import org.connectorio.addons.binding.amsads.internal.config.channel.DirectDecimalFieldConfiguration; import org.connectorio.addons.binding.amsads.internal.config.channel.DirectHexFieldConfiguration; import org.connectorio.addons.binding.amsads.internal.config.channel.SymbolFieldConfiguration; import org.connectorio.addons.binding.amsads.internal.symbol.SymbolEntry; import org.openhab.core.config.core.Configuration; import org.openhab.core.library.CoreItemFactory; -import org.openhab.core.library.types.DateTimeType; import org.openhab.core.thing.Channel; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; import org.openhab.core.thing.binding.ThingHandlerCallback; import org.openhab.core.thing.binding.builder.ChannelBuilder; +import org.openhab.core.types.Command; public class DateTimeAdsChannelHandler extends AdsChannelHandlerBase implements AdsChannelHandler { @@ -73,17 +71,18 @@ public Channel createChannel() { } @Override - public void subscribe(Builder subscriptionBuilder, String channelId) { + public AdsTag createTag() { if (DATETIME_DIRECT_HEX.equals(channel.getChannelTypeUID())) { DirectDecimalFieldConfiguration configuration = channel.getConfiguration().as(DirectDecimalFieldConfiguration.class); - subscribe(subscriptionBuilder, createTag(configuration, configuration), channelId); + return createTag(configuration, configuration); } else if (DATETIME_DIRECT_HEX.equals(channel.getChannelTypeUID())) { DirectHexFieldConfiguration configuration = channel.getConfiguration().as(DirectHexFieldConfiguration.class); - subscribe(subscriptionBuilder, createTag(configuration, configuration), channelId); + return createTag(configuration, configuration); } else if (DATETIME_SYMBOL.equals(channel.getChannelTypeUID())) { SymbolFieldConfiguration configuration = channel.getConfiguration().as(SymbolFieldConfiguration.class); - subscribe(subscriptionBuilder, createTag(configuration, configuration), channelId); + return createTag(configuration, configuration); } + return null; } @Override @@ -97,4 +96,8 @@ public void onChange(Object value) { // } } + @Override + public PlcValue update(Command command) { + return null; + } } diff --git a/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/channel/NumericAdsChannelHandler.java b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/channel/NumericAdsChannelHandler.java index 720a1b72..3a082d21 100644 --- a/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/channel/NumericAdsChannelHandler.java +++ b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/channel/NumericAdsChannelHandler.java @@ -19,7 +19,10 @@ import java.math.BigDecimal; import java.util.Map; -import org.apache.plc4x.java.api.messages.PlcSubscriptionRequest.Builder; +import org.apache.plc4x.java.ads.tag.AdsTag; +import org.apache.plc4x.java.api.value.PlcValue; +import org.apache.plc4x.java.spi.values.*; +import org.connectorio.addons.binding.amsads.internal.config.channel.TypedChannelConfiguration; import org.connectorio.addons.binding.amsads.internal.config.channel.binary.BinaryDirectDecimalFieldConfiguration; import org.connectorio.addons.binding.amsads.internal.config.channel.binary.BinaryDirectHexFieldConfiguration; import org.connectorio.addons.binding.amsads.internal.config.channel.binary.BinarySymbolicFieldConfiguration; @@ -32,6 +35,8 @@ import org.openhab.core.thing.Thing; import org.openhab.core.thing.binding.ThingHandlerCallback; import org.openhab.core.thing.binding.builder.ChannelBuilder; +import org.openhab.core.types.Command; +import org.openhab.core.types.State; public class NumericAdsChannelHandler extends AdsChannelHandlerBase implements AdsChannelHandler { @@ -68,17 +73,18 @@ public Channel createChannel() { } @Override - public void subscribe(Builder subscriptionBuilder, String channelId) { + public AdsTag createTag() { if (NUMBER_DIRECT_DEC.equals(channel.getChannelTypeUID())) { BinaryDirectDecimalFieldConfiguration configuration = channel.getConfiguration().as(BinaryDirectDecimalFieldConfiguration.class); - subscribe(subscriptionBuilder, createTag(configuration, configuration), channelId); + return createTag(configuration, configuration); } else if (NUMBER_DIRECT_HEX.equals(channel.getChannelTypeUID())) { BinaryDirectHexFieldConfiguration configuration = channel.getConfiguration().as(BinaryDirectHexFieldConfiguration.class); - subscribe(subscriptionBuilder, createTag(configuration, configuration), channelId); + return createTag(configuration, configuration); } else if (NUMBER_SYMBOL.equals(channel.getChannelTypeUID())) { BinarySymbolicFieldConfiguration configuration = channel.getConfiguration().as(BinarySymbolicFieldConfiguration.class); - subscribe(subscriptionBuilder, createTag(configuration, configuration), channelId); + return createTag(configuration, configuration); } + return null; } @Override @@ -100,4 +106,48 @@ public void onChange(Object value) { } } + @Override + public PlcValue update(Command command) { + if (!(command instanceof State)) { + return null; + } + + DecimalType value = ((State) command).as(DecimalType.class); + TypedChannelConfiguration config = channel.getConfiguration().as(TypedChannelConfiguration.class); + switch (config.type) { + case BIT: + case BOOL: + return new PlcBOOL(value.intValue()); + case BYTE: + return new PlcBYTE(value.shortValue()); + case WORD: + return new PlcWORD(value.intValue()); + case DWORD: + case SINT: + case INT8: + case USINT: + case UINT8: + case INT: + case INT16: + case UINT: + case UINT16: + return new PlcUINT(value.intValue()); + case DINT: + case INT32: + case UDINT: + case UINT32: + case LINT: + return new PlcDINT(value.longValue()); + case INT64: + case ULINT: + case UINT64: + return new PlcULINT(value.toBigDecimal()); + case REAL: + case FLOAT: + case LREAL: + case DOUBLE: + return new PlcREAL(value.doubleValue()); + } + return null; + } } diff --git a/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/channel/TextAdsChannelHandler.java b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/channel/TextAdsChannelHandler.java index 2b369746..0f0214e5 100644 --- a/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/channel/TextAdsChannelHandler.java +++ b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/channel/TextAdsChannelHandler.java @@ -22,6 +22,7 @@ import org.apache.plc4x.java.ads.tag.AdsTag; import org.apache.plc4x.java.ads.tag.DirectAdsStringTag; import org.apache.plc4x.java.api.messages.PlcSubscriptionRequest.Builder; +import org.apache.plc4x.java.api.value.PlcValue; import org.connectorio.addons.binding.amsads.internal.config.channel.DirectDecimalFieldConfiguration; import org.connectorio.addons.binding.amsads.internal.config.channel.DirectFieldConfiguration; import org.connectorio.addons.binding.amsads.internal.config.channel.DirectHexFieldConfiguration; @@ -37,6 +38,7 @@ import org.openhab.core.thing.Thing; import org.openhab.core.thing.binding.ThingHandlerCallback; import org.openhab.core.thing.binding.builder.ChannelBuilder; +import org.openhab.core.types.Command; public class TextAdsChannelHandler extends AdsChannelHandlerBase implements AdsChannelHandler { @@ -73,19 +75,18 @@ public Channel createChannel() { } @Override - public void subscribe(Builder subscriptionBuilder, String channelId) { - /* + public AdsTag createTag() { if (TEXT_DIRECT_HEX.equals(channel.getChannelTypeUID())) { DirectDecimalFieldConfiguration configuration = channel.getConfiguration().as(DirectDecimalFieldConfiguration.class); - subscribe(subscriptionBuilder, createTag(configuration, configuration), channelId); + return createTag(configuration, configuration); } else if (TEXT_DIRECT_HEX.equals(channel.getChannelTypeUID())) { DirectHexFieldConfiguration configuration = channel.getConfiguration().as(DirectHexFieldConfiguration.class); - subscribe(subscriptionBuilder, createTag(configuration, configuration), channelId); + return createTag(configuration, configuration); } else if (TEXT_SYMBOL.equals(channel.getChannelTypeUID())) { SymbolFieldConfiguration configuration = channel.getConfiguration().as(SymbolFieldConfiguration.class); - subscribe(subscriptionBuilder, createTag(configuration, configuration), channelId); + return createTag(configuration, configuration); } - */ + return null; } @Override @@ -98,15 +99,6 @@ protected AdsTag createTag(TypedChannelConfiguration typeCfg, SymbolicFieldConfi return null; } - @Override - protected void subscribe(Builder subscriptionBuilder, AdsTag tag, String channelId) { - if (tag == null) { - logger.warn("Unsupported text channel {} / {}", channelId, tag); - return; - } - subscriptionBuilder.addCyclicTag(channelId, tag, Duration.ofMillis(5000L)); - } - @Override public void onChange(Object value) { if (value instanceof String) { @@ -114,4 +106,8 @@ public void onChange(Object value) { } } + @Override + public PlcValue update(Command command) { + return null; + } } diff --git a/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/polling/FetchContainer.java b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/polling/FetchContainer.java new file mode 100644 index 00000000..5d28d337 --- /dev/null +++ b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/polling/FetchContainer.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2024-2024 ConnectorIO Sp. z o.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.connectorio.addons.binding.amsads.internal.handler.polling; + +import java.util.function.Consumer; +import org.apache.plc4x.java.ads.tag.AdsTag; + +public interface FetchContainer { + + void add(Long interval, String channelId, AdsTag tag, Consumer onChange); + + // indicate if thing was actually started + boolean start(); + + void stop(); + +} diff --git a/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/polling/PollFetchContainer.java b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/polling/PollFetchContainer.java new file mode 100644 index 00000000..56647a02 --- /dev/null +++ b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/polling/PollFetchContainer.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2024-2024 ConnectorIO Sp. z o.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.connectorio.addons.binding.amsads.internal.handler.polling; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import org.apache.plc4x.java.ads.tag.AdsTag; +import org.apache.plc4x.java.api.PlcConnection; +import org.apache.plc4x.java.api.messages.PlcReadRequest; +import org.apache.plc4x.java.api.messages.PlcReadRequest.Builder; +import org.apache.plc4x.java.api.types.PlcResponseCode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PollFetchContainer implements FetchContainer { + + private final ScheduledExecutorService executor; + private final PlcConnection connection; + Map> operations = new ConcurrentHashMap<>(); + Map> futures = new ConcurrentHashMap<>(); + + public PollFetchContainer(ScheduledExecutorService executor, PlcConnection connection) { + this.executor = executor; + this.connection = connection; + } + + @Override + public void add(Long interval, String channelId, AdsTag tag, Consumer onChange) { + if (!operations.containsKey(interval)) { + operations.put(interval, new HashMap<>()); + } + operations.get(interval).put(channelId, new Operation(tag, onChange)); + } + + @Override + public boolean start() { + if (operations.isEmpty()) { + return false; + } + + for (Entry> operation : operations.entrySet()) { + Builder requestBuilder = connection.readRequestBuilder(); + Map polledValues = operation.getValue(); + for (Entry polledValue : polledValues.entrySet()) { + requestBuilder.addTag(polledValue.getKey(), polledValue.getValue().tag); + } + + ScheduledFuture future = executor.scheduleAtFixedRate(new PollingRunnable(requestBuilder.build(), polledValues), + operation.getKey(), operation.getKey(), TimeUnit.MILLISECONDS); + futures.put(operation.getKey(), future); + } + + return true; + } + + @Override + public void stop() { + futures.forEach((key, future) -> future.cancel(true)); + } + + static class Operation { + + private final AdsTag tag; + private final Consumer onChange; + + public Operation(AdsTag tag, Consumer onChange) { + this.tag = tag; + this.onChange = onChange; + } + + public void onChange(Object object) { + onChange.accept(object); + } + } + + static class PollingRunnable implements Runnable { + + private final Logger logger = LoggerFactory.getLogger(PollingRunnable.class); + + private final PlcReadRequest request; + private final Map polledValues; + + PollingRunnable(PlcReadRequest request, Map polledValues) { + this.request = request; + this.polledValues = polledValues; + } + + @Override + public void run() { + logger.debug("Fetching data for channels {}", polledValues.keySet()); + request.execute().whenComplete((result, error) -> { + if (error != null) { + logger.warn("Failed to poll data through cyclic read request", error); + return; + } + + for (String tag : result.getTagNames()) { + PlcResponseCode responseCode = result.getResponseCode(tag); + if (polledValues.containsKey(tag) && responseCode == PlcResponseCode.OK) { + polledValues.get(tag).onChange(result.getObject(tag)); + } else { + logger.warn("Unexpected response code {} for channel {}", responseCode, tag); + } + } + }); + } + } +} diff --git a/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/polling/SubscribeFetchContainer.java b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/polling/SubscribeFetchContainer.java new file mode 100644 index 00000000..f9eda5c2 --- /dev/null +++ b/bundles/org.connectorio.addons.binding.amsads/src/main/java/org/connectorio/addons/binding/amsads/internal/handler/polling/SubscribeFetchContainer.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2024-2024 ConnectorIO Sp. z o.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.connectorio.addons.binding.amsads.internal.handler.polling; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Consumer; +import org.apache.plc4x.java.ads.tag.AdsTag; +import org.apache.plc4x.java.api.PlcConnection; +import org.apache.plc4x.java.api.messages.PlcSubscriptionEvent; +import org.apache.plc4x.java.api.messages.PlcSubscriptionRequest; +import org.apache.plc4x.java.api.messages.PlcUnsubscriptionRequest; +import org.apache.plc4x.java.api.model.PlcSubscriptionHandle; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SubscribeFetchContainer implements FetchContainer { + + private final Logger logger = LoggerFactory.getLogger(SubscribeFetchContainer.class); + + private final Map> handlers = new ConcurrentHashMap<>(); + private final PlcSubscriptionRequest.Builder subscribeBuilder; + private final PlcUnsubscriptionRequest.Builder unsubscribeBuilder; + + + public SubscribeFetchContainer(PlcConnection connection) { + subscribeBuilder = connection.subscriptionRequestBuilder(); + unsubscribeBuilder = connection.unsubscriptionRequestBuilder(); + } + + @Override + public void add(Long interval, String channelId, AdsTag tag, Consumer onChange) { + subscribeBuilder.addChangeOfStateTag(channelId, tag); + handlers.put(channelId, onChange); + } + + @Override + public boolean start() { + if (handlers.isEmpty()) { + return false; + } + + subscribeBuilder.build().execute().whenComplete((response, error) -> { + if (error != null) { + return; + } + + for (String channelId : response.getTagNames()) { + PlcSubscriptionHandle subscriptionHandle = response.getSubscriptionHandle(channelId); + subscriptionHandle.register(new Consumer() { + @Override + public void accept(PlcSubscriptionEvent plcSubscriptionEvent) { + Object value = plcSubscriptionEvent.getObject(channelId); + if (value != null) { + logger.debug("Channel {} received update {}", channelId, value); + Consumer consumer = handlers.get(channelId); + if (consumer != null) { + consumer.accept(value); + } else { + logger.warn("Unknown channel/tag association: {}", channelId); + } + } + } + }); + unsubscribeBuilder.addHandles(subscriptionHandle); + } + }); + return true; + } + + @Override + public void stop() { + unsubscribeBuilder.build().execute().join(); + } + +} diff --git a/bundles/org.connectorio.addons.binding.amsads/src/main/resources/OH-INF/config/contact-channel-config.xml b/bundles/org.connectorio.addons.binding.amsads/src/main/resources/OH-INF/config/contact-channel-config.xml index e9e0e9f6..c7fdc8e7 100644 --- a/bundles/org.connectorio.addons.binding.amsads/src/main/resources/OH-INF/config/contact-channel-config.xml +++ b/bundles/org.connectorio.addons.binding.amsads/src/main/resources/OH-INF/config/contact-channel-config.xml @@ -37,10 +37,10 @@ - - + + - + @@ -48,16 +48,25 @@ Inverse logical representation of FALSE/TRUE values. false + + + + + Default refresh interval specified for entire connection and devices associated with it. + Setting refresh interval forces this channel to be polled rather than subscribed. + It might help with older devices which do not support subscriptions. + + - Index group in decimal format (excluding 0x prefix). For example F00F. + Index group in decimal format (with or without 0x prefix). For example F00F, 0xF00F. - Offset in given decimal in hex format (excluding 0x prefix). For example 01. + Offset in given decimal in hex format (with or without 0x prefix). For example 01. @@ -68,10 +77,10 @@ - - + + - + @@ -79,16 +88,25 @@ Inverse logical representation of FALSE/TRUE values. false + + + + + Default refresh interval specified for entire connection and devices associated with it. + Setting refresh interval forces this channel to be polled rather than subscribed. + It might help with older devices which do not support subscriptions. + + - Index group in hex format (excluding 0x prefix). For example F00F. + Index group in hex format (with or without 0x prefix). For example F00F, 0xF00F. - + - Offset in given group in hex format (excluding 0x prefix). For example 01. + Offset in given group in hex format (with or without 0x prefix). For example 01, 0x01. @@ -99,10 +117,10 @@ - - + + - + @@ -110,6 +128,15 @@ Inverse logical representation of FALSE/TRUE values. false + + + + + Default refresh interval specified for entire connection and devices associated with it. + Setting refresh interval forces this channel to be polled rather than subscribed. + It might help with older devices which do not support subscriptions. + + diff --git a/bundles/org.connectorio.addons.binding.amsads/src/main/resources/OH-INF/config/datetime-channel-config.xml b/bundles/org.connectorio.addons.binding.amsads/src/main/resources/OH-INF/config/datetime-channel-config.xml index 292c532f..8ca0ab9a 100644 --- a/bundles/org.connectorio.addons.binding.amsads/src/main/resources/OH-INF/config/datetime-channel-config.xml +++ b/bundles/org.connectorio.addons.binding.amsads/src/main/resources/OH-INF/config/datetime-channel-config.xml @@ -50,11 +50,11 @@ - Index group in decimal format (excluding 0x prefix). For example F00F. + Index group in decimal format (with or without 0x prefix). For example F00F, 0xF00F. - Offset in given decimal in hex format (excluding 0x prefix). For example 01. + Offset in given decimal in hex format (with or without 0x prefix). For example 01, 0x01. @@ -73,16 +73,25 @@ + + + + + Default refresh interval specified for entire connection and devices associated with it. + Setting refresh interval forces this channel to be polled rather than subscribed. + It might help with older devices which do not support subscriptions. + + - Index group in hex format (excluding 0x prefix). For example F00F. + Index group in hex format (with or without 0x prefix). For example F00F, 0xF00F. - + - Offset in given group in hex format (excluding 0x prefix). For example 01. + Offset in given group in hex format (with or without 0x prefix). For example 01, 0x01. @@ -101,6 +110,15 @@ + + + + + Default refresh interval specified for entire connection and devices associated with it. + Setting refresh interval forces this channel to be polled rather than subscribed. + It might help with older devices which do not support subscriptions. + + diff --git a/bundles/org.connectorio.addons.binding.amsads/src/main/resources/OH-INF/config/number-channel-config.xml b/bundles/org.connectorio.addons.binding.amsads/src/main/resources/OH-INF/config/number-channel-config.xml index 6d57c841..2b0c6560 100644 --- a/bundles/org.connectorio.addons.binding.amsads/src/main/resources/OH-INF/config/number-channel-config.xml +++ b/bundles/org.connectorio.addons.binding.amsads/src/main/resources/OH-INF/config/number-channel-config.xml @@ -63,16 +63,25 @@ + + + + + Default refresh interval specified for entire connection and devices associated with it. + Setting refresh interval forces this channel to be polled rather than subscribed. + It might help with older devices which do not support subscriptions. + + - Index group in decimal format (excluding 0x prefix). For example F00F. + Index group in decimal format (with or without 0x prefix). For example F00F, 0xF00F. - Offset in given decimal in hex format (excluding 0x prefix). For example 01. + Offset in given decimal in hex format (with or without 0x prefix). For example 01, 0x01. @@ -109,17 +118,26 @@ + + + + + Default refresh interval specified for entire connection and devices associated with it. + Setting refresh interval forces this channel to be polled rather than subscribed. + It might help with older devices which do not support subscriptions. + + - Index group in hex format (excluding 0x prefix). For example F00F. + Index group in hex format (with or without 0x prefix). For example F00F, 0xF00F. - + - Offset in given group in hex format (excluding 0x prefix). For example 01. + Offset in given group in hex format (with or without 0x prefix). For example 01, 0x01. @@ -156,6 +174,15 @@ + + + + + Default refresh interval specified for entire connection and devices associated with it. + Setting refresh interval forces this channel to be polled rather than subscribed. + It might help with older devices which do not support subscriptions. + + diff --git a/bundles/org.connectorio.addons.binding.amsads/src/main/resources/OH-INF/config/switch-channel-config.xml b/bundles/org.connectorio.addons.binding.amsads/src/main/resources/OH-INF/config/switch-channel-config.xml index 1349c58d..1afb24a4 100644 --- a/bundles/org.connectorio.addons.binding.amsads/src/main/resources/OH-INF/config/switch-channel-config.xml +++ b/bundles/org.connectorio.addons.binding.amsads/src/main/resources/OH-INF/config/switch-channel-config.xml @@ -48,16 +48,25 @@ Inverse logical representation of FALSE/TRUE values. false + + + + + Default refresh interval specified for entire connection and devices associated with it. + Setting refresh interval forces this channel to be polled rather than subscribed. + It might help with older devices which do not support subscriptions. + + - Index group in decimal format (excluding 0x prefix). For example F00F. + Index group in decimal format (with or without 0x prefix). For example F00F, 0xF00F. - Offset in given decimal in hex format (excluding 0x prefix). For example 01. + Offset in given decimal in hex format (with or without 0x prefix). For example 01, 0x01. @@ -79,16 +88,25 @@ Inverse logical representation of FALSE/TRUE values. false + + + + + Default refresh interval specified for entire connection and devices associated with it. + Setting refresh interval forces this channel to be polled rather than subscribed. + It might help with older devices which do not support subscriptions. + + - Index group in hex format (excluding 0x prefix). For example F00F. + Index group in hex format (with or without 0x prefix). For example F00F, 0xF00F. - + - Offset in given group in hex format (excluding 0x prefix). For example 01. + Offset in given group in hex format (with or without 0x prefix). For example 01, 0x01. @@ -110,6 +128,15 @@ Inverse logical representation of FALSE/TRUE values. false + + + + + Default refresh interval specified for entire connection and devices associated with it. + Setting refresh interval forces this channel to be polled rather than subscribed. + It might help with older devices which do not support subscriptions. + + diff --git a/bundles/org.connectorio.addons.binding.amsads/src/main/resources/OH-INF/config/text-channel-config.xml b/bundles/org.connectorio.addons.binding.amsads/src/main/resources/OH-INF/config/text-channel-config.xml index 90ae4f64..ac8e56bf 100644 --- a/bundles/org.connectorio.addons.binding.amsads/src/main/resources/OH-INF/config/text-channel-config.xml +++ b/bundles/org.connectorio.addons.binding.amsads/src/main/resources/OH-INF/config/text-channel-config.xml @@ -42,16 +42,25 @@ + + + + + Default refresh interval specified for entire connection and devices associated with it. + Setting refresh interval forces this channel to be polled rather than subscribed. + It might help with older devices which do not support subscriptions. + + - Index group in decimal format (excluding 0x prefix). For example F00F. + Index group in decimal format (with or without 0x prefix). For example F00F, 0xF00F. - Offset in given decimal in hex format (excluding 0x prefix). For example 01. + Offset in given decimal in hex format (with or without 0x prefix). For example 01, 0x01. @@ -67,16 +76,25 @@ + + + + + Default refresh interval specified for entire connection and devices associated with it. + Setting refresh interval forces this channel to be polled rather than subscribed. + It might help with older devices which do not support subscriptions. + + - Index group in hex format (excluding 0x prefix). For example F00F. + Index group in hex format (with or without 0x prefix). For example F00F, 0xF00F. - Offset in given group in hex format (excluding 0x prefix). For example 01. + Offset in given group in hex format (). For example 01. @@ -92,6 +110,15 @@ + + + + + Default refresh interval specified for entire connection and devices associated with it. + Setting refresh interval forces this channel to be polled rather than subscribed. + It might help with older devices which do not support subscriptions. + + diff --git a/bundles/org.connectorio.addons.binding.amsads/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.connectorio.addons.binding.amsads/src/main/resources/OH-INF/thing/thing-types.xml index 8b2618f7..1306b762 100644 --- a/bundles/org.connectorio.addons.binding.amsads/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.connectorio.addons.binding.amsads/src/main/resources/OH-INF/thing/thing-types.xml @@ -97,13 +97,7 @@ This is virtual port which is internally dispatched by PLC controller to running tasks or system services. - - - Time between next poll cycles. - 1000 - - - + Because AMS/ADS enabled PLCs might retain symbol table which can be scanned.