mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 07:02:02 +01:00
[serial] Support chaining transformations without an intersection symbol (#17313)
Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
This commit is contained in:
parent
6f55f3d2ad
commit
09012cee8e
@ -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;"]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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 + "'}";
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -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 "∩".
|
||||
|
@ -117,17 +117,23 @@
|
||||
<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>
|
||||
@ -137,17 +143,23 @@
|
||||
<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>
|
||||
@ -157,9 +169,12 @@
|
||||
<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>
|
||||
@ -181,9 +196,12 @@
|
||||
<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>
|
||||
@ -193,9 +211,12 @@
|
||||
<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>
|
||||
@ -205,9 +226,12 @@
|
||||
<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>
|
||||
@ -217,9 +241,12 @@
|
||||
<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>
|
||||
@ -237,9 +264,12 @@
|
||||
<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>
|
||||
|
Loading…
Reference in New Issue
Block a user