From 09012cee8e45c3c622261e4a7321eb4d503e1fcd Mon Sep 17 00:00:00 2001 From: jimtng <2554958+jimtng@users.noreply.github.com> Date: Sun, 1 Sep 2024 20:43:19 +1000 Subject: [PATCH] [serial] Support chaining transformations without an intersection symbol (#17313) Signed-off-by: Jimmy Tanagra --- bundles/org.openhab.binding.serial/README.md | 19 ++-- .../serial/internal/SerialHandlerFactory.java | 18 +--- .../internal/channel/ChannelConfig.java | 6 +- .../internal/channel/DeviceChannel.java | 14 +-- .../channel/DeviceChannelFactory.java | 14 ++- .../internal/channel/DimmerChannel.java | 5 +- .../internal/channel/NumberChannel.java | 5 +- .../channel/RollershutterChannel.java | 6 +- .../internal/channel/StringChannel.java | 5 +- .../internal/channel/SwitchChannel.java | 5 +- .../internal/handler/SerialDeviceHandler.java | 10 +-- .../CascadedValueTransformationImpl.java | 54 ----------- .../transform/NoOpValueTransformation.java | 42 --------- .../transform/SingleValueTransformation.java | 90 ------------------- .../transform/ValueTransformation.java | 35 -------- .../ValueTransformationProvider.java | 34 ------- .../resources/OH-INF/i18n/serial.properties | 20 ++--- .../resources/OH-INF/thing/thing-types.xml | 70 ++++++++++----- 18 files changed, 104 insertions(+), 348 deletions(-) delete mode 100644 bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/transform/CascadedValueTransformationImpl.java delete mode 100644 bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/transform/NoOpValueTransformation.java delete mode 100644 bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/transform/SingleValueTransformation.java delete mode 100644 bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/transform/ValueTransformation.java delete mode 100644 bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/transform/ValueTransformationProvider.java diff --git a/bundles/org.openhab.binding.serial/README.md b/bundles/org.openhab.binding.serial/README.md index 80268098848..d0d578647dd 100644 --- a/bundles/org.openhab.binding.serial/README.md +++ b/bundles/org.openhab.binding.serial/README.md @@ -83,8 +83,8 @@ The configuration for the `serialBridge` channels consists of the following para | Parameter | Description | Supported Channels | | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- | -| `stateTransformation` | One or more transformation (concatenated with `∩`) used to convert device data to channel state, e.g. `REGEX:.*?STATE=(.*?);.*` | string, number, dimmer, switch, rollershutter | -| `commandTransformation` | One or more transformation (concatenated with `∩`) used to convert command to device data, e.g. `JS:device.js` | string, number, dimmer, switch, rollershutter | +| `stateTransformation` | One or more transformation (concatenated with `∩`) used to convert device data to channel state, e.g. `REGEX(.*?STATE=(.*?);.*)` | string, number, dimmer, switch, rollershutter | +| `commandTransformation` | One or more transformation (concatenated with `∩`) used to convert command to device data, e.g. `JS(device.js)` | string, number, dimmer, switch, rollershutter | | `commandFormat` | Format string applied to the command before transform, e.g. `ID=671;COMMAND=%s` | string, number, dimmer, rollershutter | | `onValue` | Send this value when receiving an ON command | switch, dimmer | | `offValue` | Send this value when receiving an OFF command | switch, dimmer | @@ -94,6 +94,11 @@ The configuration for the `serialBridge` channels consists of the following para | `downValue` | Send this value when receiving a DOWN command | rollershutter | | `stopValue` | Send this value when receiving a STOP command | rollershutter | +Transformations can be chained in the UI by listing each transformation on a separate line, or by separating them with the mathematical intersection character "∩". +Transformations are defined using this syntax: `TYPE(FUNCTION)`, e.g.: `JSONPATH($.path)`. +The syntax: `TYPE:FUNCTION` is still supported, e.g.: `JSONPATH:$.path`. +Please note that the values will be discarded if one transformation fails (e.g. REGEX did not match). + ## Full Example The following example is for a device connected to a serial port which provides data for many different sensors and we are interested in the temperature from a particular sensor. @@ -106,13 +111,13 @@ demo.things: Bridge serial:serialBridge:sensors [serialPort="/dev/ttyUSB01", baudRate=57600] { Thing serialDevice temperatureSensor [patternMatch="20;05;Cresta;ID=2801;.*"] { Channels: - Type number : temperature [stateTransformation="REGEX:.*?TEMP=(.*?);.*"] - Type number : humidity [stateTransformation="REGEX:.*?HUM=(.*?);.*"] + Type number : temperature [stateTransformation="REGEX(.*?TEMP=(.*?);.*)"] + Type number : humidity [stateTransformation="REGEX(.*?HUM=(.*?);.*)"] } Thing serialDevice rollershutter [patternMatch=".*"] { Channels: - Type rollershutter : serialRollo [stateTransformation="REGEX:Position:([0-9.]*)", upValue="Rollo_UP\n", downValue="Rollo_DOWN\n", stopValue="Rollo_STOP\n"] - Type switch : roloAt100 [stateTransformation="REGEX:s/Position:100/ON/"] + Type rollershutter : serialRollo [stateTransformation="REGEX(Position:([0-9.]*))", upValue="Rollo_UP\n", downValue="Rollo_DOWN\n", stopValue="Rollo_STOP\n"] + Type switch : roloAt100 [stateTransformation="REGEX(s/Position:100/ON/)"] } Thing serialDevice relay [patternMatch=".*"] { Channels: @@ -120,7 +125,7 @@ Bridge serial:serialBridge:sensors [serialPort="/dev/ttyUSB01", baudRate=57600] } Thing serialDevice myDevice [patternMatch="ID=2341;.*"] { Channels: - Type string : control [commandTransformation="JS:addCheckSum.js", commandFormat="ID=2341;COMMAND=%s;"] + Type string : control [commandTransformation="JS(addCheckSum.js)", commandFormat="ID=2341;COMMAND=%s;"] } } diff --git a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/SerialHandlerFactory.java b/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/SerialHandlerFactory.java index 776428c0b01..b6203c9e86c 100644 --- a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/SerialHandlerFactory.java +++ b/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/SerialHandlerFactory.java @@ -21,10 +21,6 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.serial.internal.handler.SerialBridgeHandler; import org.openhab.binding.serial.internal.handler.SerialDeviceHandler; -import org.openhab.binding.serial.internal.transform.CascadedValueTransformationImpl; -import org.openhab.binding.serial.internal.transform.NoOpValueTransformation; -import org.openhab.binding.serial.internal.transform.ValueTransformation; -import org.openhab.binding.serial.internal.transform.ValueTransformationProvider; import org.openhab.core.io.transport.serial.SerialPortManager; import org.openhab.core.thing.Bridge; import org.openhab.core.thing.Thing; @@ -32,7 +28,6 @@ import org.openhab.core.thing.ThingTypeUID; import org.openhab.core.thing.binding.BaseThingHandlerFactory; import org.openhab.core.thing.binding.ThingHandler; import org.openhab.core.thing.binding.ThingHandlerFactory; -import org.openhab.core.transform.TransformationHelper; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; @@ -45,7 +40,7 @@ import org.osgi.service.component.annotations.Reference; */ @NonNullByDefault @Component(configurationPid = "binding.serial", service = ThingHandlerFactory.class) -public class SerialHandlerFactory extends BaseThingHandlerFactory implements ValueTransformationProvider { +public class SerialHandlerFactory extends BaseThingHandlerFactory { private static final Set SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_BRIDGE, THING_TYPE_DEVICE); @@ -68,18 +63,9 @@ public class SerialHandlerFactory extends BaseThingHandlerFactory implements Val if (THING_TYPE_BRIDGE.equals(thingTypeUID)) { return new SerialBridgeHandler((Bridge) thing, serialPortManager); } else if (THING_TYPE_DEVICE.equals(thingTypeUID)) { - return new SerialDeviceHandler(thing, this); + return new SerialDeviceHandler(thing); } return null; } - - @Override - public ValueTransformation getValueTransformation(@Nullable final String pattern) { - if (pattern == null) { - return NoOpValueTransformation.getInstance(); - } - return new CascadedValueTransformationImpl(pattern, - name -> TransformationHelper.getTransformationService(bundleContext, name)); - } } diff --git a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/ChannelConfig.java b/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/ChannelConfig.java index fd9e7651405..df7778c9c4e 100644 --- a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/ChannelConfig.java +++ b/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/ChannelConfig.java @@ -12,6 +12,8 @@ */ package org.openhab.binding.serial.internal.channel; +import java.util.List; + import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -25,12 +27,12 @@ public class ChannelConfig { /** * Transform for received data */ - public @Nullable String stateTransformation; + public @Nullable List stateTransformation; /** * Transform for command */ - public @Nullable String commandTransformation; + public @Nullable List commandTransformation; /** * Format string for command diff --git a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/DeviceChannel.java b/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/DeviceChannel.java index 7d488d75409..d0b32c3fcd0 100644 --- a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/DeviceChannel.java +++ b/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/DeviceChannel.java @@ -16,8 +16,7 @@ import java.util.IllegalFormatException; import java.util.Optional; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.serial.internal.transform.ValueTransformation; -import org.openhab.binding.serial.internal.transform.ValueTransformationProvider; +import org.openhab.core.thing.binding.generic.ChannelTransformation; import org.openhab.core.types.Command; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,13 +33,14 @@ public abstract class DeviceChannel { protected final ChannelConfig config; - private final ValueTransformation stateTransform; - private final ValueTransformation commandTransform; + private final ChannelTransformation stateTransform; + private final ChannelTransformation commandTransform; - protected DeviceChannel(final ValueTransformationProvider valueTransformationProvider, final ChannelConfig config) { + protected DeviceChannel(final ChannelConfig config) { this.config = config; - stateTransform = valueTransformationProvider.getValueTransformation(config.stateTransformation); - commandTransform = valueTransformationProvider.getValueTransformation(config.commandTransformation); + + stateTransform = new ChannelTransformation(config.stateTransformation); + commandTransform = new ChannelTransformation(config.commandTransformation); } /** diff --git a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/DeviceChannelFactory.java b/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/DeviceChannelFactory.java index e90b8cef988..ca0b7ce12c6 100644 --- a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/DeviceChannelFactory.java +++ b/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/DeviceChannelFactory.java @@ -20,7 +20,6 @@ import static org.openhab.binding.serial.internal.SerialBindingConstants.DEVICE_ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.openhab.binding.serial.internal.transform.ValueTransformationProvider; /** * A factory to create {@link DeviceChannel} objects @@ -38,26 +37,25 @@ public class DeviceChannelFactory { * @param channelTypeID the channel type id * @return the DeviceChannel or null if the channel type is not supported. */ - public static @Nullable DeviceChannel createDeviceChannel( - final ValueTransformationProvider valueTransformationProvider, final ChannelConfig channelConfig, + public static @Nullable DeviceChannel createDeviceChannel(final ChannelConfig channelConfig, final String channelTypeID) { DeviceChannel deviceChannel; switch (channelTypeID) { case DEVICE_STRING_CHANNEL: - deviceChannel = new StringChannel(valueTransformationProvider, channelConfig); + deviceChannel = new StringChannel(channelConfig); break; case DEVICE_NUMBER_CHANNEL: - deviceChannel = new NumberChannel(valueTransformationProvider, channelConfig); + deviceChannel = new NumberChannel(channelConfig); break; case DEVICE_DIMMER_CHANNEL: - deviceChannel = new DimmerChannel(valueTransformationProvider, channelConfig); + deviceChannel = new DimmerChannel(channelConfig); break; case DEVICE_SWITCH_CHANNEL: - deviceChannel = new SwitchChannel(valueTransformationProvider, channelConfig); + deviceChannel = new SwitchChannel(channelConfig); break; case DEVICE_ROLLERSHUTTER_CHANNEL: - deviceChannel = new RollershutterChannel(valueTransformationProvider, channelConfig); + deviceChannel = new RollershutterChannel(channelConfig); break; default: deviceChannel = null; diff --git a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/DimmerChannel.java b/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/DimmerChannel.java index 26be40f341d..69f902eb96d 100644 --- a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/DimmerChannel.java +++ b/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/DimmerChannel.java @@ -15,7 +15,6 @@ package org.openhab.binding.serial.internal.channel; import java.util.Optional; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.serial.internal.transform.ValueTransformationProvider; import org.openhab.core.library.types.IncreaseDecreaseType; import org.openhab.core.library.types.OnOffType; import org.openhab.core.types.Command; @@ -28,8 +27,8 @@ import org.openhab.core.types.Command; @NonNullByDefault public class DimmerChannel extends SwitchChannel { - public DimmerChannel(final ValueTransformationProvider valueTransformationProvider, final ChannelConfig config) { - super(valueTransformationProvider, config); + public DimmerChannel(final ChannelConfig config) { + super(config); } @Override diff --git a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/NumberChannel.java b/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/NumberChannel.java index 58fcf2c7fc3..7b4d9e6d3c4 100644 --- a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/NumberChannel.java +++ b/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/NumberChannel.java @@ -13,7 +13,6 @@ package org.openhab.binding.serial.internal.channel; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.serial.internal.transform.ValueTransformationProvider; /** * The {@link NumberChannel} channel applies a format followed by a transform. @@ -23,7 +22,7 @@ import org.openhab.binding.serial.internal.transform.ValueTransformationProvider @NonNullByDefault public class NumberChannel extends DeviceChannel { - public NumberChannel(final ValueTransformationProvider valueTransformationProvider, final ChannelConfig config) { - super(valueTransformationProvider, config); + public NumberChannel(final ChannelConfig config) { + super(config); } } diff --git a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/RollershutterChannel.java b/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/RollershutterChannel.java index d9340e231d2..41dd93d94bd 100644 --- a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/RollershutterChannel.java +++ b/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/RollershutterChannel.java @@ -15,7 +15,6 @@ package org.openhab.binding.serial.internal.channel; import java.util.Optional; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.serial.internal.transform.ValueTransformationProvider; import org.openhab.core.library.types.StopMoveType; import org.openhab.core.library.types.UpDownType; import org.openhab.core.types.Command; @@ -28,9 +27,8 @@ import org.openhab.core.types.Command; @NonNullByDefault public class RollershutterChannel extends DeviceChannel { - public RollershutterChannel(final ValueTransformationProvider valueTransformationProvider, - final ChannelConfig config) { - super(valueTransformationProvider, config); + public RollershutterChannel(final ChannelConfig config) { + super(config); } @Override diff --git a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/StringChannel.java b/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/StringChannel.java index 35ddb0a1a04..0cf2e6de1ac 100644 --- a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/StringChannel.java +++ b/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/StringChannel.java @@ -13,7 +13,6 @@ package org.openhab.binding.serial.internal.channel; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.serial.internal.transform.ValueTransformationProvider; /** * The {@link StringChannel} channel applies a format followed by a transform. @@ -23,7 +22,7 @@ import org.openhab.binding.serial.internal.transform.ValueTransformationProvider @NonNullByDefault public class StringChannel extends DeviceChannel { - public StringChannel(final ValueTransformationProvider valueTransformationProvider, final ChannelConfig config) { - super(valueTransformationProvider, config); + public StringChannel(final ChannelConfig config) { + super(config); } } diff --git a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/SwitchChannel.java b/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/SwitchChannel.java index 1edc64e7ac0..4466ff2a9f7 100644 --- a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/SwitchChannel.java +++ b/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/SwitchChannel.java @@ -15,7 +15,6 @@ package org.openhab.binding.serial.internal.channel; import java.util.Optional; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.serial.internal.transform.ValueTransformationProvider; import org.openhab.core.library.types.OnOffType; import org.openhab.core.types.Command; @@ -27,8 +26,8 @@ import org.openhab.core.types.Command; @NonNullByDefault public class SwitchChannel extends DeviceChannel { - public SwitchChannel(final ValueTransformationProvider valueTransformationProvider, final ChannelConfig config) { - super(valueTransformationProvider, config); + public SwitchChannel(final ChannelConfig config) { + super(config); } @Override diff --git a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/handler/SerialDeviceHandler.java b/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/handler/SerialDeviceHandler.java index d352802e6eb..11c556e932d 100644 --- a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/handler/SerialDeviceHandler.java +++ b/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/handler/SerialDeviceHandler.java @@ -22,7 +22,6 @@ import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.serial.internal.channel.ChannelConfig; import org.openhab.binding.serial.internal.channel.DeviceChannel; import org.openhab.binding.serial.internal.channel.DeviceChannelFactory; -import org.openhab.binding.serial.internal.transform.ValueTransformationProvider; import org.openhab.core.library.types.StringType; import org.openhab.core.thing.Bridge; import org.openhab.core.thing.Channel; @@ -45,17 +44,14 @@ import org.openhab.core.types.RefreshType; @NonNullByDefault public class SerialDeviceHandler extends BaseThingHandler { - private final ValueTransformationProvider valueTransformationProvider; - private @Nullable Pattern devicePattern; private @Nullable String lastValue; private final Map channels = new HashMap<>(); - public SerialDeviceHandler(final Thing thing, final ValueTransformationProvider valueTransformationProvider) { + public SerialDeviceHandler(final Thing thing) { super(thing); - this.valueTransformationProvider = valueTransformationProvider; } @Override @@ -100,8 +96,8 @@ public class SerialDeviceHandler extends BaseThingHandler { if (type != null) { final ChannelConfig channelConfig = c.getConfiguration().as(ChannelConfig.class); try { - final DeviceChannel deviceChannel = DeviceChannelFactory - .createDeviceChannel(valueTransformationProvider, channelConfig, type.getId()); + final DeviceChannel deviceChannel = DeviceChannelFactory.createDeviceChannel(channelConfig, + type.getId()); if (deviceChannel != null) { channels.put(c.getUID(), deviceChannel); } diff --git a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/transform/CascadedValueTransformationImpl.java b/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/transform/CascadedValueTransformationImpl.java deleted file mode 100644 index a51515f6bce..00000000000 --- a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/transform/CascadedValueTransformationImpl.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright (c) 2010-2024 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.serial.internal.transform; - -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.openhab.core.transform.TransformationService; - -/** - * The {@link CascadedValueTransformationImpl} implements {@link ValueTransformation for a cascaded set of - * transformations} - * - * @author Jan N. Klug - Initial contribution - * @author Mike Major - Copied from HTTP binding to provide consistent user experience - */ -@NonNullByDefault -public class CascadedValueTransformationImpl implements ValueTransformation { - private final List transformations; - - public CascadedValueTransformationImpl(final String transformationString, - final Function transformationServiceSupplier) { - transformations = Arrays.stream(transformationString.split("∩")).filter(s -> !s.isEmpty()) - .map(transformation -> new SingleValueTransformation(transformation, transformationServiceSupplier)) - .collect(Collectors.toList()); - } - - @Override - public Optional apply(final String value) { - Optional valueOptional = Optional.of(value); - - // process all transformations - for (final ValueTransformation transformation : transformations) { - valueOptional = valueOptional.flatMap(transformation::apply); - } - - return valueOptional; - } -} diff --git a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/transform/NoOpValueTransformation.java b/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/transform/NoOpValueTransformation.java deleted file mode 100644 index 9f445b2ae6d..00000000000 --- a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/transform/NoOpValueTransformation.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Copyright (c) 2010-2024 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.serial.internal.transform; - -import java.util.Optional; - -import org.eclipse.jdt.annotation.NonNullByDefault; - -/** - * The {@link NoOpValueTransformation} implements a no-op (identity) transformation - * - * @author Jan N. Klug - Initial contribution - * @author Mike Major - Copied from HTTP binding to provide consistent user experience - */ -@NonNullByDefault -public class NoOpValueTransformation implements ValueTransformation { - private static final NoOpValueTransformation NO_OP_VALUE_TRANSFORMATION = new NoOpValueTransformation(); - - @Override - public Optional apply(final String value) { - return Optional.of(value); - } - - /** - * get the static value transformation for identity - * - * @return - */ - public static ValueTransformation getInstance() { - return NO_OP_VALUE_TRANSFORMATION; - } -} diff --git a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/transform/SingleValueTransformation.java b/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/transform/SingleValueTransformation.java deleted file mode 100644 index cc3d0cfb9cf..00000000000 --- a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/transform/SingleValueTransformation.java +++ /dev/null @@ -1,90 +0,0 @@ -/** - * Copyright (c) 2010-2024 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.serial.internal.transform; - -import java.lang.ref.WeakReference; -import java.util.Optional; -import java.util.function.Function; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.openhab.core.transform.TransformationException; -import org.openhab.core.transform.TransformationService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * A transformation for a value used in {@link org.openhab.binding.serial.internal.channel.DeviceChannel}. - * - * @author David Graeff - Initial contribution - * @author Jan N. Klug - adapted from MQTT binding to HTTP binding - * @author Mike Major - Copied from HTTP binding to provide consistent user experience - */ -@NonNullByDefault -public class SingleValueTransformation implements ValueTransformation { - private final Logger logger = LoggerFactory.getLogger(SingleValueTransformation.class); - private final Function transformationServiceSupplier; - private WeakReference<@Nullable TransformationService> transformationService = new WeakReference<>(null); - private final String pattern; - private final String serviceName; - - /** - * Creates a new channel state transformer. - * - * @param pattern A transformation pattern, starting with the transformation service - * name, followed by a colon and the transformation itself. - * @param transformationServiceSupplier - */ - public SingleValueTransformation(final String pattern, - final Function transformationServiceSupplier) { - this.transformationServiceSupplier = transformationServiceSupplier; - final int index = pattern.indexOf(':'); - if (index == -1) { - throw new IllegalArgumentException( - "The transformation pattern must consist of the type and the pattern separated by a colon"); - } - this.serviceName = pattern.substring(0, index).toUpperCase(); - this.pattern = pattern.substring(index + 1); - } - - @Override - public Optional apply(final String value) { - TransformationService transformationService = this.transformationService.get(); - if (transformationService == null) { - transformationService = transformationServiceSupplier.apply(serviceName); - if (transformationService == null) { - logger.warn("Transformation service {} for pattern {} not found!", serviceName, pattern); - return Optional.empty(); - } - this.transformationService = new WeakReference<>(transformationService); - } - - try { - final String result = transformationService.transform(pattern, value); - if (result == null) { - logger.debug("Transformation {} returned empty result when applied to {}.", this, value); - return Optional.empty(); - } - return Optional.of(result); - } catch (final TransformationException e) { - logger.warn("Executing transformation {} failed: {}", this, e.getMessage()); - } - - return Optional.empty(); - } - - @Override - public String toString() { - return "ChannelStateTransformation{pattern='" + pattern + "', serviceName='" + serviceName + "'}"; - } -} diff --git a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/transform/ValueTransformation.java b/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/transform/ValueTransformation.java deleted file mode 100644 index b30ab1ddc63..00000000000 --- a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/transform/ValueTransformation.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright (c) 2010-2024 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.serial.internal.transform; - -import java.util.Optional; - -import org.eclipse.jdt.annotation.NonNullByDefault; - -/** - * The {@link ValueTransformation} applies a set of transformations to a value - * - * @author Jan N. Klug - Initial contribution - * @author Mike Major - Copied from HTTP binding to provide consistent user experience - */ -@NonNullByDefault -public interface ValueTransformation { - - /** - * applies the value transformation to a value - * - * @param value The value - * @return Optional of string representing the transformed value (empty if transformation not present or failed) - */ - Optional apply(String value); -} diff --git a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/transform/ValueTransformationProvider.java b/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/transform/ValueTransformationProvider.java deleted file mode 100644 index 5e8529a2e43..00000000000 --- a/bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/transform/ValueTransformationProvider.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (c) 2010-2024 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.serial.internal.transform; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; - -/** - * The {@link ValueTransformationProvider} allows to retrieve a transformation service by name - * - * @author Jan N. Klug - Initial contribution - * @author Mike Major - Copied from HTTP binding to provide consistent user experience - */ -@NonNullByDefault -public interface ValueTransformationProvider { - - /** - * - * @param pattern A transformation pattern, starting with the transformation service - * * name, followed by a colon and the transformation itself. - * @return - */ - ValueTransformation getValueTransformation(@Nullable String pattern); -} diff --git a/bundles/org.openhab.binding.serial/src/main/resources/OH-INF/i18n/serial.properties b/bundles/org.openhab.binding.serial/src/main/resources/OH-INF/i18n/serial.properties index 32e799535a7..1cb5b869040 100644 --- a/bundles/org.openhab.binding.serial/src/main/resources/OH-INF/i18n/serial.properties +++ b/bundles/org.openhab.binding.serial/src/main/resources/OH-INF/i18n/serial.properties @@ -68,7 +68,7 @@ channel-type.serial.switch.description = Channel to receive commands from a Swit channel-type.config.serial.dimmer.commandFormat.label = Percent Format channel-type.config.serial.dimmer.commandFormat.description = Format string applied to the percent command, e.g. ID=671;VAL=%d channel-type.config.serial.dimmer.commandTransformation.label = Command Transformation -channel-type.config.serial.dimmer.commandTransformation.description = Transform used to convert command to device data, e.g. JS:device.js +channel-type.config.serial.dimmer.commandTransformation.description = Transformation used to convert command to device data, e.g. JS(device.js). Multiple transformations can be chained by listing each transformation on a separate line, or by concatenating them with "∩". channel-type.config.serial.dimmer.decreaseValue.label = Decrease Value channel-type.config.serial.dimmer.decreaseValue.description = Send this value when receiving a DECREASE command channel-type.config.serial.dimmer.increaseValue.label = Increase Value @@ -78,21 +78,21 @@ channel-type.config.serial.dimmer.offValue.description = Send this value when re channel-type.config.serial.dimmer.onValue.label = On Value channel-type.config.serial.dimmer.onValue.description = Send this value when receiving an ON command channel-type.config.serial.dimmer.stateTransformation.label = State Transformation -channel-type.config.serial.dimmer.stateTransformation.description = Transform used to convert device data to channel state, e.g. REGEX:.*?STATE=(.*?);.* +channel-type.config.serial.dimmer.stateTransformation.description = Transformation used to convert device data to channel state, e.g. REGEX(.*?STATE=(.*?);.*). Multiple transformations can be chained by listing each transformation on a separate line, or by concatenating them with "∩". channel-type.config.serial.number.commandFormat.label = Number Format channel-type.config.serial.number.commandFormat.description = Format string applied to the command, e.g. ID=671;VAL=%f channel-type.config.serial.number.commandTransformation.label = Command Transformation -channel-type.config.serial.number.commandTransformation.description = Transform used to convert command to device data, e.g. JS:device.js +channel-type.config.serial.number.commandTransformation.description = Transformation used to convert command to device data, e.g. JS(device.js). Multiple transformations can be chained by listing each transformation on a separate line, or by concatenating them with "∩". channel-type.config.serial.number.stateTransformation.label = State Transformation -channel-type.config.serial.number.stateTransformation.description = Transform used to convert device data to channel state, e.g. REGEX:.*?STATE=(.*?);.* +channel-type.config.serial.number.stateTransformation.description = Transformation used to convert device data to channel state, e.g. REGEX(.*?STATE=(.*?);.*). Multiple transformations can be chained by listing each transformation on a separate line, or by concatenating them with "∩". channel-type.config.serial.rollershutter.commandFormat.label = Percent Format channel-type.config.serial.rollershutter.commandFormat.description = Format string applied to the percent command, e.g. ID=671;VAL=%d channel-type.config.serial.rollershutter.commandTransformation.label = Command Transformation -channel-type.config.serial.rollershutter.commandTransformation.description = Transform used to convert command to device data, e.g. JS:device.js +channel-type.config.serial.rollershutter.commandTransformation.description = Transformation used to convert command to device data, e.g. JS(device.js). Multiple transformations can be chained by listing each transformation on a separate line, or by concatenating them with "∩". channel-type.config.serial.rollershutter.downValue.label = Down Value channel-type.config.serial.rollershutter.downValue.description = Send this value when receiving a DOWN command channel-type.config.serial.rollershutter.stateTransformation.label = State Transformation -channel-type.config.serial.rollershutter.stateTransformation.description = Transform used to convert device data to channel state, e.g. REGEX:.*?STATE=(.*?);.* +channel-type.config.serial.rollershutter.stateTransformation.description = Transformation used to convert device data to channel state, e.g. REGEX(.*?STATE=(.*?);.*). Multiple transformations can be chained by listing each transformation on a separate line, or by concatenating them with "∩". channel-type.config.serial.rollershutter.stopValue.label = Stop Value channel-type.config.serial.rollershutter.stopValue.description = Send this value when receiving a STOP command channel-type.config.serial.rollershutter.upValue.label = Up Value @@ -100,14 +100,14 @@ channel-type.config.serial.rollershutter.upValue.description = Send this value w channel-type.config.serial.string.commandFormat.label = String Format channel-type.config.serial.string.commandFormat.description = Format string applied to the command, e.g. ID=671;COMMAND=%s channel-type.config.serial.string.commandTransformation.label = Command Transformation -channel-type.config.serial.string.commandTransformation.description = Transform used to convert command to device data, e.g. JS:device.js +channel-type.config.serial.string.commandTransformation.description = Transformation used to convert command to device data, e.g. JS(device.js). Multiple transformations can be chained by listing each transformation on a separate line, or by concatenating them with "∩". channel-type.config.serial.string.stateTransformation.label = State Transformation -channel-type.config.serial.string.stateTransformation.description = Transform used to convert device data to channel state, e.g. REGEX:.*?STATE=(.*?);.* +channel-type.config.serial.string.stateTransformation.description = Transformation used to convert device data to channel state, e.g. REGEX(.*?STATE=(.*?);.*). Multiple transformations can be chained by listing each transformation on a separate line, or by concatenating them with "∩". channel-type.config.serial.switch.commandTransformation.label = Command Transformation -channel-type.config.serial.switch.commandTransformation.description = Transform used to convert command to device data, e.g. JS:device.js +channel-type.config.serial.switch.commandTransformation.description = Transformation used to convert command to device data, e.g. JS(device.js). Multiple transformations can be chained by listing each transformation on a separate line, or by concatenating them with "∩". channel-type.config.serial.switch.offValue.label = Off Value channel-type.config.serial.switch.offValue.description = Send this value when receiving an OFF command channel-type.config.serial.switch.onValue.label = On Value channel-type.config.serial.switch.onValue.description = Send this value when receiving an ON command channel-type.config.serial.switch.stateTransformation.label = State Transformation -channel-type.config.serial.switch.stateTransformation.description = Transform used to convert device data to channel state, e.g. REGEX:.*?STATE=(.*?);.* +channel-type.config.serial.switch.stateTransformation.description = Transformation used to convert device data to channel state, e.g. REGEX(.*?STATE=(.*?);.*). Multiple transformations can be chained by listing each transformation on a separate line, or by concatenating them with "∩". diff --git a/bundles/org.openhab.binding.serial/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.serial/src/main/resources/OH-INF/thing/thing-types.xml index 632d46fc4eb..9c2e4e57fda 100644 --- a/bundles/org.openhab.binding.serial/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.serial/src/main/resources/OH-INF/thing/thing-types.xml @@ -117,17 +117,23 @@ Channel to receive commands as a string - + - Transform used to convert device data to channel state, e.g. REGEX:.*?STATE=(.*?);.* + REGEX(.*?STATE=(.*?);.*). + Multiple transformations can be chained by listing each transformation on a separate line, + or by concatenating them with "∩".]]> Format string applied to the command, e.g. ID=671;COMMAND=%s - + - Transform used to convert command to device data, e.g. JS:device.js + JS(device.js). + Multiple transformations can be chained by listing each transformation on a separate line, + or by concatenating them with "∩".]]> @@ -137,17 +143,23 @@ Channel to receive commands as a number - + - Transform used to convert device data to channel state, e.g. REGEX:.*?STATE=(.*?);.* + REGEX(.*?STATE=(.*?);.*). + Multiple transformations can be chained by listing each transformation on a separate line, + or by concatenating them with "∩".]]> Format string applied to the command, e.g. ID=671;VAL=%f - + - Transform used to convert command to device data, e.g. JS:device.js + JS(device.js). + Multiple transformations can be chained by listing each transformation on a separate line, + or by concatenating them with "∩".]]> @@ -157,9 +169,12 @@ Channel to receive commands from a Dimmer - + - Transform used to convert device data to channel state, e.g. REGEX:.*?STATE=(.*?);.* + REGEX(.*?STATE=(.*?);.*). + Multiple transformations can be chained by listing each transformation on a separate line, + or by concatenating them with "∩".]]> @@ -181,9 +196,12 @@ Format string applied to the percent command, e.g. ID=671;VAL=%d - + - Transform used to convert command to device data, e.g. JS:device.js + JS(device.js). + Multiple transformations can be chained by listing each transformation on a separate line, + or by concatenating them with "∩".]]> @@ -193,9 +211,12 @@ Channel to receive commands from a Switch - + - Transform used to convert device data to channel state, e.g. REGEX:.*?STATE=(.*?);.* + REGEX(.*?STATE=(.*?);.*). + Multiple transformations can be chained by listing each transformation on a separate line, + or by concatenating them with "∩".]]> @@ -205,9 +226,12 @@ Send this value when receiving an OFF command - + - Transform used to convert command to device data, e.g. JS:device.js + JS(device.js). + Multiple transformations can be chained by listing each transformation on a separate line, + or by concatenating them with "∩".]]> @@ -217,9 +241,12 @@ Channel to receive commands from a Rollershutter - + - Transform used to convert device data to channel state, e.g. REGEX:.*?STATE=(.*?);.* + REGEX(.*?STATE=(.*?);.*). + Multiple transformations can be chained by listing each transformation on a separate line, + or by concatenating them with "∩".]]> @@ -237,9 +264,12 @@ Format string applied to the percent command, e.g. ID=671;VAL=%d - + - Transform used to convert command to device data, e.g. JS:device.js + JS(device.js). + Multiple transformations can be chained by listing each transformation on a separate line, + or by concatenating them with "∩".]]>