]> git.basschouten.com Git - openhab-addons.git/commitdiff
[serial] Support chaining transformations without an intersection symbol (#17313)
authorjimtng <2554958+jimtng@users.noreply.github.com>
Sun, 1 Sep 2024 10:43:19 +0000 (20:43 +1000)
committerGitHub <noreply@github.com>
Sun, 1 Sep 2024 10:43:19 +0000 (12:43 +0200)
Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
18 files changed:
bundles/org.openhab.binding.serial/README.md
bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/SerialHandlerFactory.java
bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/ChannelConfig.java
bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/DeviceChannel.java
bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/DeviceChannelFactory.java
bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/DimmerChannel.java
bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/NumberChannel.java
bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/RollershutterChannel.java
bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/StringChannel.java
bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/channel/SwitchChannel.java
bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/handler/SerialDeviceHandler.java
bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/transform/CascadedValueTransformationImpl.java [deleted file]
bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/transform/NoOpValueTransformation.java [deleted file]
bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/transform/SingleValueTransformation.java [deleted file]
bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/transform/ValueTransformation.java [deleted file]
bundles/org.openhab.binding.serial/src/main/java/org/openhab/binding/serial/internal/transform/ValueTransformationProvider.java [deleted file]
bundles/org.openhab.binding.serial/src/main/resources/OH-INF/i18n/serial.properties
bundles/org.openhab.binding.serial/src/main/resources/OH-INF/thing/thing-types.xml

index 80268098848c6f158b616139b110f6e80ef758d7..d0d578647dd63ce7bef3619d4920aec7e4c345fe 100644 (file)
@@ -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;"]
     }
 }
 
index 776428c0b01ae5d7012b3b082a8bcda965abb54d..b6203c9e86cb53f492e789ce65de6d5cc6294b3b 100644 (file)
@@ -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<ThingTypeUID> 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));
-    }
 }
index fd9e76514053663e5d5f3400804b43247fa85a2e..df7778c9c4e325e3105794b56d921d42ccfa2ffc 100644 (file)
@@ -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<String> stateTransformation;
 
     /**
      * Transform for command
      */
-    public @Nullable String commandTransformation;
+    public @Nullable List<String> commandTransformation;
 
     /**
      * Format string for command
index 7d488d75409cc53ad77885001145080648b0f7aa..d0b32c3fcd0f6ac679cea5a977dcbdce66c88430 100644 (file)
@@ -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);
     }
 
     /**
index e90b8cef98897fc4392b981ab17ac2f68e9bd422..ca0b7ce12c6a96b1876e1e473c43379c4015e977 100644 (file)
@@ -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;
index 26be40f341d3b016b47e32ffa5efc232a1fecfee..69f902eb96d9abc4e48727ec9c4e9b99b8892815 100644 (file)
@@ -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
index 58fcf2c7fc30d6a00d04ed55ab221d23a2b430f8..7b4d9e6d3c4acbee63c746a9b48fa18f4eabd80d 100644 (file)
@@ -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);
     }
 }
index d9340e231d20c10d7281abda7436ae82ef6d5310..41dd93d94bdfaba6b86369b1c49d4c0330a960ba 100644 (file)
@@ -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
index 35ddb0a1a049b99296fc7b3f9e043b3867fd7cb2..0cf2e6de1acefb4817cd4e5568961f148ac33a36 100644 (file)
@@ -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);
     }
 }
index 1edc64e7ac0115c5b1ed13fcd91ca348b33c7106..4466ff2a9f7da9f8c832ba837e50e4cd2eaf8832 100644 (file)
@@ -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
index d352802e6eb55cc1d9649f5fbcd9d146c8650fcb..11c556e932d3ab154d3892ecc373e46747d5fb31 100644 (file)
@@ -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<ChannelUID, DeviceChannel> 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 (file)
index a51515f..0000000
+++ /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<ValueTransformation> transformations;
-
-    public CascadedValueTransformationImpl(final String transformationString,
-            final Function<String, @Nullable TransformationService> transformationServiceSupplier) {
-        transformations = Arrays.stream(transformationString.split("∩")).filter(s -> !s.isEmpty())
-                .map(transformation -> new SingleValueTransformation(transformation, transformationServiceSupplier))
-                .collect(Collectors.toList());
-    }
-
-    @Override
-    public Optional<String> apply(final String value) {
-        Optional<String> 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 (file)
index 9f445b2..0000000
+++ /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<String> 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 (file)
index cc3d0cf..0000000
+++ /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<String, @Nullable TransformationService> 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<String, @Nullable TransformationService> 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<String> 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 (file)
index b30ab1d..0000000
+++ /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<String> 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 (file)
index 5e8529a..0000000
+++ /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);
-}
index 32e799535a7493005d498374ca8d9d24cd294d06..1cb5b86904029a3ffde46193f312c12bc32c5020 100644 (file)
@@ -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. <code>JS(device.js)</code>. 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. <code>REGEX(.*?STATE=(.*?);.*)</code>. 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. <code>JS(device.js)</code>. 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. <code>REGEX(.*?STATE=(.*?);.*)</code>. 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. <code>JS(device.js)</code>. 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. <code>REGEX(.*?STATE=(.*?);.*)</code>. 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. <code>JS(device.js)</code>. 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. <code>REGEX(.*?STATE=(.*?);.*)</code>. 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. <code>JS(device.js)</code>. 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. <code>REGEX(.*?STATE=(.*?);.*)</code>. Multiple transformations can be chained by listing each transformation on a separate line, or by concatenating them with "∩".
index 632d46fc4ebe59595a26eb66f565805577339f00..9c2e4e57fdaf032452343d2e5357da3ae5166b1a 100644 (file)
                <label>String</label>
                <description>Channel to receive commands as a string</description>
                <config-description>
-                       <parameter name="stateTransformation" type="text">
+                       <parameter name="stateTransformation" type="text" multiple="true">
                                <label>State Transformation</label>
-                               <description>Transform used to convert device data to channel state, e.g. REGEX:.*?STATE=(.*?);.*</description>
+                               <description><![CDATA[Transformation used to convert device data to channel state, e.g.
+                                       <code>REGEX(.*?STATE=(.*?);.*)</code>.
+                                       Multiple transformations can be chained by listing each transformation on a separate line,
+                                       or by concatenating them with "∩".]]></description>
                        </parameter>
                        <parameter name="commandFormat" type="text">
                                <label>String Format</label>
                                <description>Format string applied to the command, e.g. ID=671;COMMAND=%s</description>
                        </parameter>
-                       <parameter name="commandTransformation" type="text">
+                       <parameter name="commandTransformation" type="text" multiple="true">
                                <label>Command Transformation</label>
-                               <description>Transform used to convert command to device data, e.g. JS:device.js</description>
+                               <description><![CDATA[Transformation used to convert command to device data, e.g.
+                                       <code>JS(device.js)</code>.
+                                       Multiple transformations can be chained by listing each transformation on a separate line,
+                                       or by concatenating them with "∩".]]></description>
                        </parameter>
                </config-description>
        </channel-type>
                <label>Number</label>
                <description>Channel to receive commands as a number</description>
                <config-description>
-                       <parameter name="stateTransformation" type="text">
+                       <parameter name="stateTransformation" type="text" multiple="true">
                                <label>State Transformation</label>
-                               <description>Transform used to convert device data to channel state, e.g. REGEX:.*?STATE=(.*?);.*</description>
+                               <description><![CDATA[Transformation used to convert device data to channel state, e.g.
+                                       <code>REGEX(.*?STATE=(.*?);.*)</code>.
+                                       Multiple transformations can be chained by listing each transformation on a separate line,
+                                       or by concatenating them with "∩".]]></description>
                        </parameter>
                        <parameter name="commandFormat" type="text">
                                <label>Number Format</label>
                                <description>Format string applied to the command, e.g. ID=671;VAL=%f</description>
                        </parameter>
-                       <parameter name="commandTransformation" type="text">
+                       <parameter name="commandTransformation" type="text" multiple="true">
                                <label>Command Transformation</label>
-                               <description>Transform used to convert command to device data, e.g. JS:device.js</description>
+                               <description><![CDATA[Transformation used to convert command to device data, e.g.
+                                       <code>JS(device.js)</code>.
+                                       Multiple transformations can be chained by listing each transformation on a separate line,
+                                       or by concatenating them with "∩".]]></description>
                        </parameter>
                </config-description>
        </channel-type>
                <label>Dimmer</label>
                <description>Channel to receive commands from a Dimmer</description>
                <config-description>
-                       <parameter name="stateTransformation" type="text">
+                       <parameter name="stateTransformation" type="text" multiple="true">
                                <label>State Transformation</label>
-                               <description>Transform used to convert device data to channel state, e.g. REGEX:.*?STATE=(.*?);.*</description>
+                               <description><![CDATA[Transformation used to convert device data to channel state, e.g.
+                                       <code>REGEX(.*?STATE=(.*?);.*)</code>.
+                                       Multiple transformations can be chained by listing each transformation on a separate line,
+                                       or by concatenating them with "∩".]]></description>
                        </parameter>
                        <parameter name="onValue" type="text">
                                <label>On Value</label>
                                <label>Percent Format</label>
                                <description>Format string applied to the percent command, e.g. ID=671;VAL=%d</description>
                        </parameter>
-                       <parameter name="commandTransformation" type="text">
+                       <parameter name="commandTransformation" type="text" multiple="true">
                                <label>Command Transformation</label>
-                               <description>Transform used to convert command to device data, e.g. JS:device.js</description>
+                               <description><![CDATA[Transformation used to convert command to device data, e.g.
+                                       <code>JS(device.js)</code>.
+                                       Multiple transformations can be chained by listing each transformation on a separate line,
+                                       or by concatenating them with "∩".]]></description>
                        </parameter>
                </config-description>
        </channel-type>
                <label>Switch</label>
                <description>Channel to receive commands from a Switch</description>
                <config-description>
-                       <parameter name="stateTransformation" type="text">
+                       <parameter name="stateTransformation" type="text" multiple="true">
                                <label>State Transformation</label>
-                               <description>Transform used to convert device data to channel state, e.g. REGEX:.*?STATE=(.*?);.*</description>
+                               <description><![CDATA[Transformation used to convert device data to channel state, e.g.
+                                       <code>REGEX(.*?STATE=(.*?);.*)</code>.
+                                       Multiple transformations can be chained by listing each transformation on a separate line,
+                                       or by concatenating them with "∩".]]></description>
                        </parameter>
                        <parameter name="onValue" type="text">
                                <label>On Value</label>
                                <label>Off Value</label>
                                <description>Send this value when receiving an OFF command</description>
                        </parameter>
-                       <parameter name="commandTransformation" type="text">
+                       <parameter name="commandTransformation" type="text" multiple="true">
                                <label>Command Transformation</label>
-                               <description>Transform used to convert command to device data, e.g. JS:device.js</description>
+                               <description><![CDATA[Transformation used to convert command to device data, e.g.
+                                       <code>JS(device.js)</code>.
+                                       Multiple transformations can be chained by listing each transformation on a separate line,
+                                       or by concatenating them with "∩".]]></description>
                        </parameter>
                </config-description>
        </channel-type>
                <label>Rollershutter</label>
                <description>Channel to receive commands from a Rollershutter</description>
                <config-description>
-                       <parameter name="stateTransformation" type="text">
+                       <parameter name="stateTransformation" type="text" multiple="true">
                                <label>State Transformation</label>
-                               <description>Transform used to convert device data to channel state, e.g. REGEX:.*?STATE=(.*?);.*</description>
+                               <description><![CDATA[Transformation used to convert device data to channel state, e.g.
+                                       <code>REGEX(.*?STATE=(.*?);.*)</code>.
+                                       Multiple transformations can be chained by listing each transformation on a separate line,
+                                       or by concatenating them with "∩".]]></description>
                        </parameter>
                        <parameter name="upValue" type="text">
                                <label>Up Value</label>
                                <label>Percent Format</label>
                                <description>Format string applied to the percent command, e.g. ID=671;VAL=%d</description>
                        </parameter>
-                       <parameter name="commandTransformation" type="text">
+                       <parameter name="commandTransformation" type="text" multiple="true">
                                <label>Command Transformation</label>
-                               <description>Transform used to convert command to device data, e.g. JS:device.js</description>
+                               <description><![CDATA[Transformation used to convert command to device data, e.g.
+                                       <code>JS(device.js)</code>.
+                                       Multiple transformations can be chained by listing each transformation on a separate line,
+                                       or by concatenating them with "∩".]]></description>
                        </parameter>
                </config-description>
        </channel-type>