Skip to content

Commit

Permalink
[serial] Support chaining transformations without an intersection sym…
Browse files Browse the repository at this point in the history
…bol (#17313)

Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
  • Loading branch information
jimtng authored Sep 1, 2024
1 parent 6f55f3d commit 09012ce
Show file tree
Hide file tree
Showing 18 changed files with 104 additions and 348 deletions.
19 changes: 12 additions & 7 deletions bundles/org.openhab.binding.serial/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand All @@ -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.
Expand All @@ -106,21 +111,21 @@ 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:
Type switch : serialRelay [onValue="Q1_ON\n", offValue="Q1_OFF\n"]
}
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;"]
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,13 @@
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;
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;
Expand All @@ -45,7 +40,7 @@
*/
@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);

Expand All @@ -68,18 +63,9 @@ public boolean supportsThingType(final ThingTypeUID thingTypeUID) {
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));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
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;
Expand All @@ -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);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

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
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
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;
Expand All @@ -28,8 +27,8 @@
@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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -23,7 +22,7 @@
@NonNullByDefault
public class NumberChannel extends DeviceChannel {

public NumberChannel(final ValueTransformationProvider valueTransformationProvider, final ChannelConfig config) {
super(valueTransformationProvider, config);
public NumberChannel(final ChannelConfig config) {
super(config);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
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;
Expand All @@ -28,9 +27,8 @@
@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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -23,7 +22,7 @@
@NonNullByDefault
public class StringChannel extends DeviceChannel {

public StringChannel(final ValueTransformationProvider valueTransformationProvider, final ChannelConfig config) {
super(valueTransformationProvider, config);
public StringChannel(final ChannelConfig config) {
super(config);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
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;

Expand All @@ -27,8 +26,8 @@
@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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
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;
Expand All @@ -45,17 +44,14 @@
@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
Expand Down Expand Up @@ -100,8 +96,8 @@ public void initialize() {
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);
}
Expand Down

This file was deleted.

Loading

0 comments on commit 09012ce

Please sign in to comment.