mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[serial] Initial contribution (#8851)
Signed-off-by: Mike Major <mike_j_major@hotmail.com>
This commit is contained in:
parent
fa21dff364
commit
55bf82c477
@ -215,6 +215,7 @@
|
|||||||
/bundles/org.openhab.binding.seneye/ @nikotanghe
|
/bundles/org.openhab.binding.seneye/ @nikotanghe
|
||||||
/bundles/org.openhab.binding.sensebox/ @hakan42
|
/bundles/org.openhab.binding.sensebox/ @hakan42
|
||||||
/bundles/org.openhab.binding.sensibo/ @seime
|
/bundles/org.openhab.binding.sensibo/ @seime
|
||||||
|
/bundles/org.openhab.binding.serial/ @MikeJMajor
|
||||||
/bundles/org.openhab.binding.serialbutton/ @kaikreuzer
|
/bundles/org.openhab.binding.serialbutton/ @kaikreuzer
|
||||||
/bundles/org.openhab.binding.shelly/ @markus7017
|
/bundles/org.openhab.binding.shelly/ @markus7017
|
||||||
/bundles/org.openhab.binding.siemensrds/ @andrewfg
|
/bundles/org.openhab.binding.siemensrds/ @andrewfg
|
||||||
|
@ -1066,6 +1066,11 @@
|
|||||||
<artifactId>org.openhab.binding.sensibo</artifactId>
|
<artifactId>org.openhab.binding.sensibo</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openhab.addons.bundles</groupId>
|
||||||
|
<artifactId>org.openhab.binding.serial</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.openhab.addons.bundles</groupId>
|
<groupId>org.openhab.addons.bundles</groupId>
|
||||||
<artifactId>org.openhab.binding.serialbutton</artifactId>
|
<artifactId>org.openhab.binding.serialbutton</artifactId>
|
||||||
|
13
bundles/org.openhab.binding.serial/NOTICE
Normal file
13
bundles/org.openhab.binding.serial/NOTICE
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
This content is produced and maintained by the openHAB project.
|
||||||
|
|
||||||
|
* Project home: https://www.openhab.org
|
||||||
|
|
||||||
|
== Declared Project Licenses
|
||||||
|
|
||||||
|
This program and the accompanying materials are made available under the terms
|
||||||
|
of the Eclipse Public License 2.0 which is available at
|
||||||
|
https://www.eclipse.org/legal/epl-2.0/.
|
||||||
|
|
||||||
|
== Source Code
|
||||||
|
|
||||||
|
https://github.com/openhab/openhab-addons
|
140
bundles/org.openhab.binding.serial/README.md
Normal file
140
bundles/org.openhab.binding.serial/README.md
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
# Serial Binding
|
||||||
|
|
||||||
|
The Serial binding allows openHAB to communicate over serial ports attached to the openHAB server.
|
||||||
|
|
||||||
|
The binding allows data to be sent and received from a serial port.
|
||||||
|
The binding does not support any particular serial protocols and simply reads what is available and sends what is provided.
|
||||||
|
|
||||||
|
The binding can be used to communicate with simple serial devices for which a dedicated openHAB binding does not exist.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The Serial binding represents a serial port as a bridge thing and data matching defined patterns as things connected to the bridge.
|
||||||
|
|
||||||
|
### Serial Bridge
|
||||||
|
|
||||||
|
A Serial Bridge thing (`serialBridge`) represents a single serial port.
|
||||||
|
|
||||||
|
The bridge supports a String channel which is set to the currently received data from the serial port.
|
||||||
|
Sending a command to this channel sends the command as a string to the serial port.
|
||||||
|
|
||||||
|
The bridge also supports a String channel which encodes the received data as the string representation of a RawType to handle data that is
|
||||||
|
not supported by the REST interface.
|
||||||
|
A command sent to this channel will only be sent to the serial port if it is encoded as the string representation of a RawType.
|
||||||
|
|
||||||
|
A trigger channel is also provided which triggers when data is received.
|
||||||
|
|
||||||
|
### Serial Device
|
||||||
|
|
||||||
|
A Serial Device thing (`serialDevice`) can be used to represent data matching a defined pattern as a device.
|
||||||
|
The serial port may be providing data for many different devices/sensors, such as a temperature sensor or a doorbell.
|
||||||
|
Usually such devices can be identified by performing a pattern match on the received data.
|
||||||
|
For example, a Serial Device could be configured to represent a temperature sensor.
|
||||||
|
|
||||||
|
The thing will only update its channels if the received data matches the defined pattern.
|
||||||
|
|
||||||
|
The thing supports generic String and Number channels which can apply a transform on the received data to set the channel state.
|
||||||
|
Commands sent to the channels can be formatted and transformed before being sent to the device.
|
||||||
|
|
||||||
|
The thing also supports Switch and Rollershutter channels which provide simple mappings for the ON, OFF, UP, DOWN and STOP commands.
|
||||||
|
|
||||||
|
When using a Serial Device the expectation is that the received data for each device is terminated by a line break.
|
||||||
|
|
||||||
|
## Thing Configuration
|
||||||
|
|
||||||
|
The configuration for the `serialBridge` consists of the following parameters:
|
||||||
|
|
||||||
|
| Parameter | Description |
|
||||||
|
|---------------------|--------------------------------------------------------------------------------------------------------|
|
||||||
|
| serialPort | The serial port to use (e.g. Linux: /dev/ttyUSB0, Windows: COM1) (mandatory) |
|
||||||
|
| baudRate | Set the baud rate. Valid values: 4800, 9600, 19200, 38400, 57600, 115200 (default 9600) |
|
||||||
|
| dataBits | Set the data bits. Valid values: 5, 6, 7, 8 (default 8) |
|
||||||
|
| parity | Set the parity. Valid values: N(one), O(dd), E(even), M(ark), S(pace) (default N) |
|
||||||
|
| stopBits | Set the stop bits. Valid values: 1, 1.5, 2 (default 1) |
|
||||||
|
| charset | The charset to use for converting between bytes and string (e.g. UTF-8,ISO-8859-1) |
|
||||||
|
|
||||||
|
The configuration for the `serialDevice` consists of the following parameters:
|
||||||
|
|
||||||
|
| Parameter | Description |
|
||||||
|
|---------------------|--------------------------------------------------------------------------------------------------------|
|
||||||
|
| patternMatch | Regular expression used to identify device from received data (must match the whole line) (mandatory) |
|
||||||
|
|
||||||
|
## Channels
|
||||||
|
|
||||||
|
The channels supported by the `serialBridge` are:
|
||||||
|
|
||||||
|
| Channel | Type | Description |
|
||||||
|
|----------|------------------|----------------------------------------------------------------------------------------------------------|
|
||||||
|
| `string` | String | Channel for sending/receiving data as a string to/from the serial port. The channel will update its state to a StringType that is the data received from the serial port. A command sent to this channel will be sent out as data through the serial port. |
|
||||||
|
| `binary` | String | Channel for sending/receiving data in Base64 format to/from the serial port. The channel will update its state to a StringType which is the string representation of a RawType that contains the data received from the serial port. A command sent to this channel must be encoded as the string representation of a RawType, e.g. `"data:application/octet-stream;base64 MjA7MDU7Q3Jlc3RhO0lEPTI4MDE7VEVNUD0yNTtIVU09NTU7QkFUPU9LOwo="` |
|
||||||
|
| `data` | system.rawbutton | Trigger which emits `PRESSED` events (no `RELEASED` events) whenever data is available on the serial port |
|
||||||
|
|
||||||
|
|
||||||
|
The channels supported by the `serialDevice` are:
|
||||||
|
|
||||||
|
| Channel Type | Type | Description |
|
||||||
|
|---------------|------------------|----------------------------------------------------------------------------------------------------------|
|
||||||
|
| `string` | String | Channel for receiving string based commands. The channel can be configured to apply a transform on the received data to convert to the channel state. Commands received by the channel can be formatted and transformed before sending to the device. |
|
||||||
|
| `number` | Number | Channel for receiving number based commands. The channel can be configured to apply a transform on the received data to convert to the channel state. Commands received by the channel can be formatted and transformed before sending to the device. |
|
||||||
|
| `dimmer` | Dimmer | Channel for receiving commands from a Dimmer. The channel can be configured to apply a transform on the received data to convert to the channel state. The channel can be configured to apply a simple mapping for the ON, OFF, INCREASE and DECREASE commands. |
|
||||||
|
| `switch` | Switch | Channel for receiving commands from a Switch. The channel can be configured to apply a transform on the received data to convert to the channel state. The channel can be configured to apply a simple mapping for the ON and OFF commands. |
|
||||||
|
| `rollershutter` | Rollershutter | Channel for receiving commands from a Rollershutter. The channel can be configured to apply a transform on the received data to convert to the channel state. The channel can be configured to apply a simple mapping for the UP, DOWN and STOP commands. |
|
||||||
|
|
||||||
|
The configuration for the `serialBridge` channels consists of the following parameters:
|
||||||
|
|
||||||
|
| 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 |
|
||||||
|
| `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 |
|
||||||
|
| `increaseValue` | Send this value when receiving an INCREASE command | dimmer |
|
||||||
|
| `decreaseValue` | Send this value when receiving a DECREASE command | dimmer |
|
||||||
|
| `upValue` | Send this value when receiving an UP command | rollershutter |
|
||||||
|
| `downValue` | Send this value when receiving a DOWN command | rollershutter |
|
||||||
|
| `stopValue` | Send this value when receiving a STOP command | rollershutter |
|
||||||
|
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|
The data for the sensor of interest is `20;05;Cresta;ID=2801;TEMP=25;HUM=55;BAT=OK;`
|
||||||
|
|
||||||
|
demo.things:
|
||||||
|
|
||||||
|
```
|
||||||
|
Bridge serial:serialBridge:sensors [serialPort="/dev/ttyUSB01", baudRate=57600] {
|
||||||
|
Thing serialDevice temperatureSensor [patternMatch="20;05;Cresta;ID=2801;.*"] {
|
||||||
|
Channels:
|
||||||
|
Type number : temperature [transform="REGEX:.*?TEMP=(.*?);.*"]
|
||||||
|
Type number : humidity [transform="REGEX:.*?HUM=(.*?);.*"]
|
||||||
|
}
|
||||||
|
Thing serialDevice rollershutter [patternMatch=".*"] {
|
||||||
|
Channels:
|
||||||
|
Type rollershutter : serialRollo [transform="REGEX:Position:([0-9.]*)", up="Rollo_UP\n", down="Rollo_DOWN\n", stop="Rollo_STOP\n"]
|
||||||
|
Type switch : roloAt100 [transform="REGEX:s/Position:100/ON/"]
|
||||||
|
}
|
||||||
|
Thing serialDevice relay [patternMatch=".*"] {
|
||||||
|
Channels:
|
||||||
|
Type switch : serialRelay [on="Q1_ON\n", off="Q1_OFF\n"]
|
||||||
|
}
|
||||||
|
Thing serialDevice myDevice [patternMatch="ID=2341;.*"] {
|
||||||
|
Channels:
|
||||||
|
Type string : control [commandTransform="JS:addCheckSum.js", commandFormat="ID=2341;COMMAND=%s;"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
demo.items:
|
||||||
|
|
||||||
|
```
|
||||||
|
Number:Temperature myTemp "My Temperature" {channel="serial:serialDevice:sensors:temperatureSensor:temperature"}
|
||||||
|
Number myHum "My Humidity" {channel="serial:serialDevice:sensors:temperatureSensor:humidity"}
|
||||||
|
Switch serialRelay "Relay Q1" (Entrance) {channel="serial:serialDevice:sensors:relay:serialRelay"}
|
||||||
|
Rollershutter serialRollo "Entrance Rollo" (Entrance) {channel="serial:serialDevice:sensors:rollershutter:serialRollo"}
|
||||||
|
Rollershutter roloAt100 "Rolo at 100" (Entrance) {channel="serial:serialDevice:sensors:rollershutter:roloAt100"}
|
||||||
|
String deviceControl {channel="serial:serialDevice:sensors:myDevice:control"}
|
||||||
|
```
|
17
bundles/org.openhab.binding.serial/pom.xml
Normal file
17
bundles/org.openhab.binding.serial/pom.xml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.openhab.addons.bundles</groupId>
|
||||||
|
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
|
||||||
|
<version>3.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>org.openhab.binding.serial</artifactId>
|
||||||
|
|
||||||
|
<name>openHAB Add-ons :: Bundles :: Serial Binding</name>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Copyright (c) 2010-2020 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
|
||||||
|
|
||||||
|
-->
|
||||||
|
<features name="org.openhab.binding.serial-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||||
|
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
|
||||||
|
|
||||||
|
<feature name="openhab-binding-serial" description="Serial Binding" version="${project.version}">
|
||||||
|
<feature>openhab-runtime-base</feature>
|
||||||
|
<feature>openhab-transport-serial</feature>
|
||||||
|
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.serial/${project.version}</bundle>
|
||||||
|
</feature>
|
||||||
|
</features>
|
@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2020 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;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.thing.ThingTypeUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SerialBindingConstants} class defines common constants, which are
|
||||||
|
* used across the whole binding.
|
||||||
|
*
|
||||||
|
* @author Mike Major - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SerialBindingConstants {
|
||||||
|
|
||||||
|
private static final String BINDING_ID = "serial";
|
||||||
|
|
||||||
|
// List of all Thing Type UIDs
|
||||||
|
public static final ThingTypeUID THING_TYPE_BRIDGE = new ThingTypeUID(BINDING_ID, "serialBridge");
|
||||||
|
public static final ThingTypeUID THING_TYPE_DEVICE = new ThingTypeUID(BINDING_ID, "serialDevice");
|
||||||
|
|
||||||
|
// List of all Channel ids
|
||||||
|
public static final String TRIGGER_CHANNEL = "data";
|
||||||
|
public static final String STRING_CHANNEL = "string";
|
||||||
|
public static final String BINARY_CHANNEL = "binary";
|
||||||
|
public static final String DEVICE_STRING_CHANNEL = "string";
|
||||||
|
public static final String DEVICE_NUMBER_CHANNEL = "number";
|
||||||
|
public static final String DEVICE_DIMMER_CHANNEL = "dimmer";
|
||||||
|
public static final String DEVICE_SWITCH_CHANNEL = "switch";
|
||||||
|
public static final String DEVICE_ROLLERSHUTTER_CHANNEL = "rollershutter";
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2020 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;
|
||||||
|
|
||||||
|
import static org.openhab.binding.serial.internal.SerialBindingConstants.THING_TYPE_BRIDGE;
|
||||||
|
import static org.openhab.binding.serial.internal.SerialBindingConstants.THING_TYPE_DEVICE;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SerialHandlerFactory} is responsible for creating things and thing
|
||||||
|
* handlers.
|
||||||
|
*
|
||||||
|
* @author Mike Major - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
@Component(configurationPid = "binding.serial", service = ThingHandlerFactory.class)
|
||||||
|
public class SerialHandlerFactory extends BaseThingHandlerFactory implements ValueTransformationProvider {
|
||||||
|
|
||||||
|
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_BRIDGE, THING_TYPE_DEVICE);
|
||||||
|
|
||||||
|
private final SerialPortManager serialPortManager;
|
||||||
|
|
||||||
|
@Activate
|
||||||
|
public SerialHandlerFactory(@Reference final SerialPortManager serialPortManager) {
|
||||||
|
this.serialPortManager = serialPortManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsThingType(final ThingTypeUID thingTypeUID) {
|
||||||
|
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @Nullable ThingHandler createHandler(final Thing thing) {
|
||||||
|
final ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||||
|
|
||||||
|
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 null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueTransformation getValueTransformation(@Nullable final String pattern) {
|
||||||
|
if (pattern == null) {
|
||||||
|
return NoOpValueTransformation.getInstance();
|
||||||
|
}
|
||||||
|
return new CascadedValueTransformationImpl(pattern,
|
||||||
|
name -> TransformationHelper.getTransformationService(bundleContext, name));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2020 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.channel;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class describing the channel user configuration
|
||||||
|
*
|
||||||
|
* @author Mike Major - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class ChannelConfig {
|
||||||
|
/**
|
||||||
|
* Transform for received data
|
||||||
|
*/
|
||||||
|
public @Nullable String stateTransformation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform for command
|
||||||
|
*/
|
||||||
|
public @Nullable String commandTransformation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format string for command
|
||||||
|
*/
|
||||||
|
public @Nullable String commandFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On value
|
||||||
|
*/
|
||||||
|
public @Nullable String onValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Off value
|
||||||
|
*/
|
||||||
|
public @Nullable String offValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Up value
|
||||||
|
*/
|
||||||
|
public @Nullable String upValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Down value
|
||||||
|
*/
|
||||||
|
public @Nullable String downValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop value
|
||||||
|
*/
|
||||||
|
public @Nullable String stopValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increase value
|
||||||
|
*/
|
||||||
|
public @Nullable String increaseValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrease value
|
||||||
|
*/
|
||||||
|
public @Nullable String decreaseValue;
|
||||||
|
}
|
@ -0,0 +1,105 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2020 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.channel;
|
||||||
|
|
||||||
|
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.types.Command;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link DeviceChannel} is the abstract class for handling a channel. Provides
|
||||||
|
* the ability to transform the device data into the channel state.
|
||||||
|
*
|
||||||
|
* @author Mike Major - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public abstract class DeviceChannel {
|
||||||
|
protected final Logger logger = LoggerFactory.getLogger(DeviceChannel.class);
|
||||||
|
|
||||||
|
protected final ChannelConfig config;
|
||||||
|
|
||||||
|
private final ValueTransformation stateTransform;
|
||||||
|
private final ValueTransformation commandTransform;
|
||||||
|
|
||||||
|
protected DeviceChannel(final ValueTransformationProvider valueTransformationProvider, final ChannelConfig config) {
|
||||||
|
this.config = config;
|
||||||
|
stateTransform = valueTransformationProvider.getValueTransformation(config.stateTransformation);
|
||||||
|
commandTransform = valueTransformationProvider.getValueTransformation(config.commandTransformation);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map the supplied command into the data to send to the device by
|
||||||
|
* applying a format followed by a transform.
|
||||||
|
*
|
||||||
|
* @param command the command to map
|
||||||
|
* @return the mapped data if the mapping produced a result.
|
||||||
|
*/
|
||||||
|
public Optional<String> mapCommand(final Command command) {
|
||||||
|
final Optional<String> result = transformCommand(formatCommand(command));
|
||||||
|
|
||||||
|
logger.debug("Mapped command is '{}'", result.orElse(null));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform the data using the configured transform
|
||||||
|
*
|
||||||
|
* @param data the data to transform
|
||||||
|
* @return the transformed data if the transform produced a result.
|
||||||
|
*/
|
||||||
|
public Optional<String> transformData(final String data) {
|
||||||
|
return stateTransform.apply(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform the data using the configured command transform
|
||||||
|
*
|
||||||
|
* @param data the command to transform
|
||||||
|
* @return the transformed data if the transform produced a result.
|
||||||
|
*/
|
||||||
|
protected Optional<String> transformCommand(final String data) {
|
||||||
|
return commandTransform.apply(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format the commnd using the configured format
|
||||||
|
*
|
||||||
|
* @param data the command to transform
|
||||||
|
* @return the formatted data. The orginal data is returned if there is no format string
|
||||||
|
* or if there is an error performing the format.
|
||||||
|
*/
|
||||||
|
protected String formatCommand(final Command command) {
|
||||||
|
String data;
|
||||||
|
|
||||||
|
final String commandFormat = config.commandFormat;
|
||||||
|
if (commandFormat != null) {
|
||||||
|
try {
|
||||||
|
data = command.format(commandFormat);
|
||||||
|
} catch (final IllegalFormatException e) {
|
||||||
|
logger.warn("Couldn't format commmand because format string '{}' is invalid", commandFormat);
|
||||||
|
data = command.toFullString();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data = command.toFullString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2020 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.channel;
|
||||||
|
|
||||||
|
import static org.openhab.binding.serial.internal.SerialBindingConstants.DEVICE_DIMMER_CHANNEL;
|
||||||
|
import static org.openhab.binding.serial.internal.SerialBindingConstants.DEVICE_NUMBER_CHANNEL;
|
||||||
|
import static org.openhab.binding.serial.internal.SerialBindingConstants.DEVICE_ROLLERSHUTTER_CHANNEL;
|
||||||
|
import static org.openhab.binding.serial.internal.SerialBindingConstants.DEVICE_STRING_CHANNEL;
|
||||||
|
import static org.openhab.binding.serial.internal.SerialBindingConstants.DEVICE_SWITCH_CHANNEL;
|
||||||
|
|
||||||
|
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
|
||||||
|
*
|
||||||
|
* @author Mike Major - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class DeviceChannelFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a {@link DeviceChannel} for the channel type
|
||||||
|
*
|
||||||
|
* @param bundleContext the bundle context
|
||||||
|
* @param channelConfig the channel configuration
|
||||||
|
* @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,
|
||||||
|
final String channelTypeID) {
|
||||||
|
DeviceChannel deviceChannel;
|
||||||
|
|
||||||
|
switch (channelTypeID) {
|
||||||
|
case DEVICE_STRING_CHANNEL:
|
||||||
|
deviceChannel = new StringChannel(valueTransformationProvider, channelConfig);
|
||||||
|
break;
|
||||||
|
case DEVICE_NUMBER_CHANNEL:
|
||||||
|
deviceChannel = new NumberChannel(valueTransformationProvider, channelConfig);
|
||||||
|
break;
|
||||||
|
case DEVICE_DIMMER_CHANNEL:
|
||||||
|
deviceChannel = new DimmerChannel(valueTransformationProvider, channelConfig);
|
||||||
|
break;
|
||||||
|
case DEVICE_SWITCH_CHANNEL:
|
||||||
|
deviceChannel = new SwitchChannel(valueTransformationProvider, channelConfig);
|
||||||
|
break;
|
||||||
|
case DEVICE_ROLLERSHUTTER_CHANNEL:
|
||||||
|
deviceChannel = new RollershutterChannel(valueTransformationProvider, channelConfig);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
deviceChannel = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return deviceChannel;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2020 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.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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link DimmerChannel} channel applies a format followed by a transform.
|
||||||
|
*
|
||||||
|
* @author Mike Major - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class DimmerChannel extends SwitchChannel {
|
||||||
|
|
||||||
|
public DimmerChannel(final ValueTransformationProvider valueTransformationProvider, final ChannelConfig config) {
|
||||||
|
super(valueTransformationProvider, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<String> mapCommand(final Command command) {
|
||||||
|
Optional<String> result;
|
||||||
|
|
||||||
|
if (command instanceof OnOffType) {
|
||||||
|
result = super.mapCommand(command);
|
||||||
|
} else {
|
||||||
|
String data;
|
||||||
|
|
||||||
|
final String increaseValue = config.increaseValue;
|
||||||
|
final String decreaseValue = config.decreaseValue;
|
||||||
|
|
||||||
|
if (command instanceof IncreaseDecreaseType) {
|
||||||
|
if (increaseValue != null && IncreaseDecreaseType.INCREASE.equals(command)) {
|
||||||
|
data = increaseValue;
|
||||||
|
} else if (decreaseValue != null && IncreaseDecreaseType.DECREASE.equals(command)) {
|
||||||
|
data = decreaseValue;
|
||||||
|
} else {
|
||||||
|
data = command.toFullString();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data = formatCommand(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = transformCommand(data);
|
||||||
|
|
||||||
|
logger.debug("Mapped command is '{}'", result.orElse(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2020 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.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.
|
||||||
|
*
|
||||||
|
* @author Mike Major - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class NumberChannel extends DeviceChannel {
|
||||||
|
|
||||||
|
public NumberChannel(final ValueTransformationProvider valueTransformationProvider, final ChannelConfig config) {
|
||||||
|
super(valueTransformationProvider, config);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2020 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.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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link RollershutterChannel} channel provides mappings for the UP, DOWN and STOP commands
|
||||||
|
*
|
||||||
|
* @author Mike Major - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class RollershutterChannel extends DeviceChannel {
|
||||||
|
|
||||||
|
public RollershutterChannel(final ValueTransformationProvider valueTransformationProvider,
|
||||||
|
final ChannelConfig config) {
|
||||||
|
super(valueTransformationProvider, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<String> mapCommand(final Command command) {
|
||||||
|
String data;
|
||||||
|
|
||||||
|
final String upValue = config.upValue;
|
||||||
|
final String downValue = config.downValue;
|
||||||
|
final String stopValue = config.stopValue;
|
||||||
|
|
||||||
|
if (command instanceof UpDownType) {
|
||||||
|
if (upValue != null && UpDownType.UP.equals(command)) {
|
||||||
|
data = upValue;
|
||||||
|
} else if (downValue != null && UpDownType.DOWN.equals(command)) {
|
||||||
|
data = downValue;
|
||||||
|
} else {
|
||||||
|
data = command.toFullString();
|
||||||
|
}
|
||||||
|
} else if (command instanceof StopMoveType) {
|
||||||
|
if (stopValue != null && StopMoveType.STOP.equals(command)) {
|
||||||
|
data = stopValue;
|
||||||
|
} else {
|
||||||
|
data = command.toFullString();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data = formatCommand(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Optional<String> result = transformCommand(data);
|
||||||
|
|
||||||
|
logger.debug("Mapped command is '{}'", result.orElse(null));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2020 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.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.
|
||||||
|
*
|
||||||
|
* @author Mike Major - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class StringChannel extends DeviceChannel {
|
||||||
|
|
||||||
|
public StringChannel(final ValueTransformationProvider valueTransformationProvider, final ChannelConfig config) {
|
||||||
|
super(valueTransformationProvider, config);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2020 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.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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SwitchChannel} channel provides mappings for the ON and OFF commands
|
||||||
|
*
|
||||||
|
* @author Mike Major - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SwitchChannel extends DeviceChannel {
|
||||||
|
|
||||||
|
public SwitchChannel(final ValueTransformationProvider valueTransformationProvider, final ChannelConfig config) {
|
||||||
|
super(valueTransformationProvider, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<String> mapCommand(final Command command) {
|
||||||
|
String data;
|
||||||
|
|
||||||
|
final String onValue = config.onValue;
|
||||||
|
final String offValue = config.offValue;
|
||||||
|
|
||||||
|
if (onValue != null && OnOffType.ON.equals(command)) {
|
||||||
|
data = onValue;
|
||||||
|
} else if (offValue != null && OnOffType.OFF.equals(command)) {
|
||||||
|
data = offValue;
|
||||||
|
} else {
|
||||||
|
data = command.toFullString();
|
||||||
|
}
|
||||||
|
|
||||||
|
final Optional<String> result = transformCommand(data);
|
||||||
|
|
||||||
|
logger.debug("Mapped command is '{}'", result.orElse(null));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2020 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.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class describing the serial bridge user configuration
|
||||||
|
*
|
||||||
|
* @author Mike Major - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SerialBridgeConfiguration {
|
||||||
|
/**
|
||||||
|
* Serial port name
|
||||||
|
*/
|
||||||
|
public @Nullable String serialPort;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serial port baud rate
|
||||||
|
*/
|
||||||
|
public int baudRate = 9600;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serial port data bits
|
||||||
|
*/
|
||||||
|
public int dataBits = 8;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serial port parity
|
||||||
|
*/
|
||||||
|
public String parity = "N";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serial port stop bits
|
||||||
|
*/
|
||||||
|
public String stopBits = "1";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Charset
|
||||||
|
*/
|
||||||
|
public @Nullable String charset;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "SerialBridgeConfiguration [serialPort=" + serialPort + ", Baudrate=" + baudRate + ", Databits="
|
||||||
|
+ dataBits + ", Parity=" + parity + ", Stopbits=" + stopBits + ", charset=" + charset + "]";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,343 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2020 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.handler;
|
||||||
|
|
||||||
|
import static org.openhab.binding.serial.internal.SerialBindingConstants.BINARY_CHANNEL;
|
||||||
|
import static org.openhab.binding.serial.internal.SerialBindingConstants.STRING_CHANNEL;
|
||||||
|
import static org.openhab.binding.serial.internal.SerialBindingConstants.TRIGGER_CHANNEL;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.charset.IllegalCharsetNameException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.TooManyListenersException;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.serial.internal.util.Parity;
|
||||||
|
import org.openhab.binding.serial.internal.util.StopBits;
|
||||||
|
import org.openhab.core.io.transport.serial.PortInUseException;
|
||||||
|
import org.openhab.core.io.transport.serial.SerialPort;
|
||||||
|
import org.openhab.core.io.transport.serial.SerialPortEvent;
|
||||||
|
import org.openhab.core.io.transport.serial.SerialPortEventListener;
|
||||||
|
import org.openhab.core.io.transport.serial.SerialPortIdentifier;
|
||||||
|
import org.openhab.core.io.transport.serial.SerialPortManager;
|
||||||
|
import org.openhab.core.io.transport.serial.UnsupportedCommOperationException;
|
||||||
|
import org.openhab.core.library.types.RawType;
|
||||||
|
import org.openhab.core.library.types.StringType;
|
||||||
|
import org.openhab.core.thing.Bridge;
|
||||||
|
import org.openhab.core.thing.ChannelUID;
|
||||||
|
import org.openhab.core.thing.CommonTriggerEvents;
|
||||||
|
import org.openhab.core.thing.ThingStatus;
|
||||||
|
import org.openhab.core.thing.ThingStatusDetail;
|
||||||
|
import org.openhab.core.thing.binding.BaseBridgeHandler;
|
||||||
|
import org.openhab.core.types.Command;
|
||||||
|
import org.openhab.core.types.RefreshType;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SerialBridgeHandler} is responsible for handling commands, which
|
||||||
|
* are sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Mike Major - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SerialBridgeHandler extends BaseBridgeHandler implements SerialPortEventListener {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(SerialBridgeHandler.class);
|
||||||
|
|
||||||
|
private SerialBridgeConfiguration config = new SerialBridgeConfiguration();
|
||||||
|
|
||||||
|
private final SerialPortManager serialPortManager;
|
||||||
|
private @Nullable SerialPort serialPort;
|
||||||
|
|
||||||
|
private @Nullable InputStream inputStream;
|
||||||
|
private @Nullable OutputStream outputStream;
|
||||||
|
|
||||||
|
private Charset charset = StandardCharsets.UTF_8;
|
||||||
|
|
||||||
|
private @Nullable String lastValue;
|
||||||
|
|
||||||
|
private final AtomicBoolean readerActive = new AtomicBoolean(false);
|
||||||
|
private @Nullable ScheduledFuture<?> reader;
|
||||||
|
|
||||||
|
public SerialBridgeHandler(final Bridge bridge, final SerialPortManager serialPortManager) {
|
||||||
|
super(bridge);
|
||||||
|
this.serialPortManager = serialPortManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleCommand(final ChannelUID channelUID, final Command command) {
|
||||||
|
if (command instanceof RefreshType) {
|
||||||
|
final String lastValue = this.lastValue;
|
||||||
|
|
||||||
|
if (lastValue != null) {
|
||||||
|
refresh(channelUID.getId(), lastValue);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (channelUID.getId()) {
|
||||||
|
case STRING_CHANNEL:
|
||||||
|
writeString(command.toFullString(), false);
|
||||||
|
break;
|
||||||
|
case BINARY_CHANNEL:
|
||||||
|
writeString(command.toFullString(), true);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
config = getConfigAs(SerialBridgeConfiguration.class);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (config.charset != null) {
|
||||||
|
charset = Charset.forName(config.charset);
|
||||||
|
}
|
||||||
|
logger.debug("Serial port '{}' charset '{}' set", config.serialPort, charset);
|
||||||
|
} catch (final IllegalCharsetNameException e) {
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, "Invalid charset");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String port = config.serialPort;
|
||||||
|
if (port == null) {
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, "Port must be set");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse ports and if the port is found, initialize the reader
|
||||||
|
final SerialPortIdentifier portId = serialPortManager.getIdentifier(port);
|
||||||
|
if (portId == null) {
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, "Port is not known");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize serial port
|
||||||
|
try {
|
||||||
|
final SerialPort serialPort = portId.open(getThing().getUID().toString(), 2000);
|
||||||
|
this.serialPort = serialPort;
|
||||||
|
|
||||||
|
serialPort.setSerialPortParams(config.baudRate, config.dataBits,
|
||||||
|
StopBits.fromConfig(config.stopBits).getSerialPortValue(),
|
||||||
|
Parity.fromConfig(config.parity).getSerialPortValue());
|
||||||
|
|
||||||
|
serialPort.addEventListener(this);
|
||||||
|
|
||||||
|
// activate the DATA_AVAILABLE notifier
|
||||||
|
serialPort.notifyOnDataAvailable(true);
|
||||||
|
inputStream = serialPort.getInputStream();
|
||||||
|
outputStream = serialPort.getOutputStream();
|
||||||
|
|
||||||
|
updateStatus(ThingStatus.ONLINE);
|
||||||
|
} catch (final IOException ex) {
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, "I/O error");
|
||||||
|
} catch (final PortInUseException e) {
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, "Port is in use");
|
||||||
|
} catch (final TooManyListenersException e) {
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
|
||||||
|
"Cannot attach listener to port");
|
||||||
|
} catch (final UnsupportedCommOperationException e) {
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
|
||||||
|
"Unsupported port parameters: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
final SerialPort serialPort = this.serialPort;
|
||||||
|
if (serialPort != null) {
|
||||||
|
serialPort.removeEventListener();
|
||||||
|
serialPort.close();
|
||||||
|
this.serialPort = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final InputStream inputStream = this.inputStream;
|
||||||
|
if (inputStream != null) {
|
||||||
|
try {
|
||||||
|
inputStream.close();
|
||||||
|
} catch (final IOException e) {
|
||||||
|
logger.debug("Error while closing the input stream: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
this.inputStream = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final OutputStream outputStream = this.outputStream;
|
||||||
|
if (outputStream != null) {
|
||||||
|
try {
|
||||||
|
outputStream.close();
|
||||||
|
} catch (final IOException e) {
|
||||||
|
logger.debug("Error while closing the output stream: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
this.outputStream = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
readerActive.set(false);
|
||||||
|
final ScheduledFuture<?> reader = this.reader;
|
||||||
|
if (reader != null) {
|
||||||
|
reader.cancel(false);
|
||||||
|
this.reader = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastValue = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void serialEvent(final SerialPortEvent event) {
|
||||||
|
switch (event.getEventType()) {
|
||||||
|
case SerialPortEvent.DATA_AVAILABLE:
|
||||||
|
if (readerActive.compareAndSet(false, true)) {
|
||||||
|
reader = scheduler.schedule(() -> receiveAndProcess(new StringBuilder(), true), 0,
|
||||||
|
TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a string to the serial port.
|
||||||
|
*
|
||||||
|
* @param string the string to send
|
||||||
|
*/
|
||||||
|
public void writeString(final String string) {
|
||||||
|
writeString(string, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refreshes the channel with the last received data
|
||||||
|
*
|
||||||
|
* @param channelId the channel to refresh
|
||||||
|
* @param channelId the data to use
|
||||||
|
*/
|
||||||
|
private void refresh(final String channelId, final String data) {
|
||||||
|
if (!isLinked(channelId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (channelId) {
|
||||||
|
case STRING_CHANNEL:
|
||||||
|
updateState(channelId, new StringType(data));
|
||||||
|
break;
|
||||||
|
case BINARY_CHANNEL:
|
||||||
|
final StringBuilder sb = new StringBuilder("data:");
|
||||||
|
sb.append(RawType.DEFAULT_MIME_TYPE).append(";base64,")
|
||||||
|
.append(Base64.getEncoder().encodeToString(data.getBytes(charset)));
|
||||||
|
updateState(channelId, new StringType(sb.toString()));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read from the serial port and process the data
|
||||||
|
*
|
||||||
|
* @param sb the string builder to receive the data
|
||||||
|
* @param firstAttempt indicates if this is the first read attempt without waiting
|
||||||
|
*/
|
||||||
|
private void receiveAndProcess(final StringBuilder sb, final boolean firstAttempt) {
|
||||||
|
final InputStream inputStream = this.inputStream;
|
||||||
|
|
||||||
|
if (inputStream == null) {
|
||||||
|
readerActive.set(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (firstAttempt || inputStream.available() > 0) {
|
||||||
|
final byte[] readBuffer = new byte[20];
|
||||||
|
|
||||||
|
// read data from serial device
|
||||||
|
while (inputStream.available() > 0) {
|
||||||
|
final int bytes = inputStream.read(readBuffer);
|
||||||
|
sb.append(new String(readBuffer, 0, bytes, charset));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add wait states around reading the stream, so that interrupted transmissions
|
||||||
|
// are merged
|
||||||
|
if (readerActive.get()) {
|
||||||
|
reader = scheduler.schedule(() -> receiveAndProcess(sb, false), 100, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
final String result = sb.toString();
|
||||||
|
|
||||||
|
triggerChannel(TRIGGER_CHANNEL, CommonTriggerEvents.PRESSED);
|
||||||
|
refresh(STRING_CHANNEL, result);
|
||||||
|
refresh(BINARY_CHANNEL, result);
|
||||||
|
|
||||||
|
result.lines().forEach(l -> getThing().getThings().forEach(t -> {
|
||||||
|
final SerialDeviceHandler device = (SerialDeviceHandler) t.getHandler();
|
||||||
|
if (device != null) {
|
||||||
|
device.handleData(l);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
lastValue = result;
|
||||||
|
|
||||||
|
if (readerActive.compareAndSet(true, false)) {
|
||||||
|
// Check we haven't received more data while processing
|
||||||
|
if (inputStream.available() > 0 && readerActive.compareAndSet(false, true)) {
|
||||||
|
reader = scheduler.schedule(() -> receiveAndProcess(new StringBuilder(), true), 0,
|
||||||
|
TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (final IOException e) {
|
||||||
|
logger.debug("Error reading from serial port: {}", e.getMessage(), e);
|
||||||
|
readerActive.set(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a string to the serial port.
|
||||||
|
*
|
||||||
|
* @param string the string to send
|
||||||
|
* @param isRawType the string should be handled as a RawType
|
||||||
|
*/
|
||||||
|
private void writeString(final String string, final boolean isRawType) {
|
||||||
|
final OutputStream outputStream = this.outputStream;
|
||||||
|
|
||||||
|
if (outputStream == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug("Writing '{}' to serial port {}", string, config.serialPort);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// write string to serial port
|
||||||
|
if (isRawType) {
|
||||||
|
final RawType rt = RawType.valueOf(string);
|
||||||
|
outputStream.write(rt.getBytes());
|
||||||
|
} else {
|
||||||
|
outputStream.write(string.getBytes(charset));
|
||||||
|
}
|
||||||
|
|
||||||
|
outputStream.flush();
|
||||||
|
} catch (final IOException | IllegalArgumentException e) {
|
||||||
|
logger.warn("Error writing '{}' to serial port {}: {}", string, config.serialPort, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2020 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.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class describing the serial device user configuration
|
||||||
|
*
|
||||||
|
* @author Mike Major - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SerialDeviceConfiguration {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Pattern match
|
||||||
|
*/
|
||||||
|
public String patternMatch = "";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "SerialDeviceConfiguration [patternMatch=" + patternMatch + "]";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,168 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2020 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.handler;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.regex.PatternSyntaxException;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
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;
|
||||||
|
import org.openhab.core.thing.ChannelUID;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.openhab.core.thing.ThingStatus;
|
||||||
|
import org.openhab.core.thing.ThingStatusDetail;
|
||||||
|
import org.openhab.core.thing.ThingStatusInfo;
|
||||||
|
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||||
|
import org.openhab.core.thing.type.ChannelTypeUID;
|
||||||
|
import org.openhab.core.types.Command;
|
||||||
|
import org.openhab.core.types.RefreshType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SerialDeviceHandler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Mike Major - Initial contribution
|
||||||
|
*/
|
||||||
|
@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) {
|
||||||
|
super(thing);
|
||||||
|
this.valueTransformationProvider = valueTransformationProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleCommand(final ChannelUID channelUID, final Command command) {
|
||||||
|
if (command instanceof RefreshType) {
|
||||||
|
final String lastValue = this.lastValue;
|
||||||
|
|
||||||
|
if (lastValue != null) {
|
||||||
|
final DeviceChannel channel = channels.get(channelUID);
|
||||||
|
if (channel != null) {
|
||||||
|
refresh(channelUID, channel, lastValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
final DeviceChannel channel = channels.get(channelUID);
|
||||||
|
if (channel != null) {
|
||||||
|
final Bridge bridge = getBridge();
|
||||||
|
if (bridge != null) {
|
||||||
|
final SerialBridgeHandler handler = (SerialBridgeHandler) bridge.getHandler();
|
||||||
|
if (handler != null) {
|
||||||
|
channel.mapCommand(command).ifPresent(value -> handler.writeString(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
final SerialDeviceConfiguration config = getConfigAs(SerialDeviceConfiguration.class);
|
||||||
|
|
||||||
|
try {
|
||||||
|
devicePattern = Pattern.compile(config.patternMatch);
|
||||||
|
} catch (final PatternSyntaxException e) {
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||||
|
"Invalid device pattern: " + e.getMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final Channel c : getThing().getChannels()) {
|
||||||
|
final ChannelTypeUID type = c.getChannelTypeUID();
|
||||||
|
if (type != null) {
|
||||||
|
final ChannelConfig channelConfig = c.getConfiguration().as(ChannelConfig.class);
|
||||||
|
try {
|
||||||
|
final DeviceChannel deviceChannel = DeviceChannelFactory
|
||||||
|
.createDeviceChannel(valueTransformationProvider, channelConfig, type.getId());
|
||||||
|
if (deviceChannel != null) {
|
||||||
|
channels.put(c.getUID(), deviceChannel);
|
||||||
|
}
|
||||||
|
} catch (final IllegalArgumentException e) {
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||||
|
"Configuration error for channel " + c.getUID().getId() + ": " + e.getMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getBridgeStatus().getStatus() == ThingStatus.ONLINE) {
|
||||||
|
updateStatus(ThingStatus.ONLINE);
|
||||||
|
} else {
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
channels.clear();
|
||||||
|
lastValue = null;
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a line of data received from the bridge
|
||||||
|
*
|
||||||
|
* @param data the line of data
|
||||||
|
*/
|
||||||
|
public void handleData(final String data) {
|
||||||
|
final Pattern devicePattern = this.devicePattern;
|
||||||
|
|
||||||
|
if (devicePattern != null && devicePattern.matcher(data).matches()) {
|
||||||
|
channels.forEach((channelUID, channel) -> refresh(channelUID, channel, data));
|
||||||
|
this.lastValue = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the bridge status.
|
||||||
|
*/
|
||||||
|
private ThingStatusInfo getBridgeStatus() {
|
||||||
|
final Bridge b = getBridge();
|
||||||
|
if (b != null) {
|
||||||
|
return b.getStatusInfo();
|
||||||
|
} else {
|
||||||
|
return new ThingStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refreshes the channel with the last received data
|
||||||
|
*
|
||||||
|
* @param channelId the channel to refresh
|
||||||
|
*/
|
||||||
|
private void refresh(final ChannelUID channelUID, final DeviceChannel channel, final String data) {
|
||||||
|
if (!isLinked(channelUID)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
channel.transformData(data).ifPresent(value -> updateState(channelUID, new StringType(value)));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2020 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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2020 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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2020 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 {@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 + "'}";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2020 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);
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2020 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);
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2020 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.util;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.io.transport.serial.SerialPort;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum to convert config parity value to serial port value
|
||||||
|
*
|
||||||
|
* @author Mike Major - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public enum Parity {
|
||||||
|
NONE("N", SerialPort.PARITY_NONE),
|
||||||
|
ODD("O", SerialPort.PARITY_ODD),
|
||||||
|
EVEN("E", SerialPort.PARITY_EVEN),
|
||||||
|
MARK("M", SerialPort.PARITY_MARK),
|
||||||
|
SPACE("S", SerialPort.PARITY_SPACE);
|
||||||
|
|
||||||
|
final String configValue;
|
||||||
|
final int serialPortValue;
|
||||||
|
|
||||||
|
private Parity(final String configValue, final int serialPortValue) {
|
||||||
|
this.configValue = configValue;
|
||||||
|
this.serialPortValue = serialPortValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the serial port value
|
||||||
|
*
|
||||||
|
* @return the serial port value
|
||||||
|
*/
|
||||||
|
public int getSerialPortValue() {
|
||||||
|
return serialPortValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the enum value from the config value
|
||||||
|
*
|
||||||
|
* @param configValue the config value
|
||||||
|
* @return the enum value
|
||||||
|
*/
|
||||||
|
public static Parity fromConfig(final String configValue) {
|
||||||
|
return Arrays.asList(values()).stream().filter(p -> p.configValue.equals(configValue)).findFirst().orElse(NONE);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2020 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.util;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.io.transport.serial.SerialPort;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum to convert config stopBits value to serial port value
|
||||||
|
*
|
||||||
|
* @author Mike Major - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public enum StopBits {
|
||||||
|
STOPBITS_1("1", SerialPort.STOPBITS_1),
|
||||||
|
STOPBITS_1_5("1.5", SerialPort.STOPBITS_1_5),
|
||||||
|
STOPBITS_2("2", SerialPort.STOPBITS_2);
|
||||||
|
|
||||||
|
final String configValue;
|
||||||
|
final int serialPortValue;
|
||||||
|
|
||||||
|
private StopBits(final String configValue, final int serialPortValue) {
|
||||||
|
this.configValue = configValue;
|
||||||
|
this.serialPortValue = serialPortValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the serial port value
|
||||||
|
*
|
||||||
|
* @return the serial port value
|
||||||
|
*/
|
||||||
|
public int getSerialPortValue() {
|
||||||
|
return serialPortValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the enum value from the config value
|
||||||
|
*
|
||||||
|
* @param configValue the config value
|
||||||
|
* @return the enum value
|
||||||
|
*/
|
||||||
|
public static StopBits fromConfig(final String configValue) {
|
||||||
|
return Arrays.asList(values()).stream().filter(p -> p.configValue.equals(configValue)).findFirst()
|
||||||
|
.orElse(STOPBITS_1);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<binding:binding id="serial" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
|
||||||
|
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
|
||||||
|
|
||||||
|
<name>Serial Binding</name>
|
||||||
|
<description>This binding supports sending/receiving data to/from a serial port</description>
|
||||||
|
<author>Mike Major</author>
|
||||||
|
|
||||||
|
</binding:binding>
|
@ -0,0 +1,245 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<thing:thing-descriptions bindingId="serial"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||||
|
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||||
|
|
||||||
|
<!-- Thing Types -->
|
||||||
|
<bridge-type id="serialBridge">
|
||||||
|
<label>Serial Bridge</label>
|
||||||
|
<description>Serial port which can send and receive data</description>
|
||||||
|
|
||||||
|
<channels>
|
||||||
|
<channel id="string" typeId="stringData"/>
|
||||||
|
<channel id="binary" typeId="binaryData"/>
|
||||||
|
<channel id="data" typeId="system.rawbutton"/>
|
||||||
|
</channels>
|
||||||
|
|
||||||
|
<config-description>
|
||||||
|
<parameter name="serialPort" type="text" required="true">
|
||||||
|
<context>serial-port</context>
|
||||||
|
<label>Serial Port</label>
|
||||||
|
<description>The serial port to use (e.g. Linux: /dev/ttyUSB0, Windows: COM1)</description>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="baudRate" type="integer">
|
||||||
|
<advanced>true</advanced>
|
||||||
|
<label>Baud Rate</label>
|
||||||
|
<description>Set the baud rate</description>
|
||||||
|
<default>9600</default>
|
||||||
|
<options>
|
||||||
|
<option value="4800">4800</option>
|
||||||
|
<option value="9600">9600</option>
|
||||||
|
<option value="19200">19200</option>
|
||||||
|
<option value="38400">38400</option>
|
||||||
|
<option value="57600">57600</option>
|
||||||
|
<option value="115200">115200</option>
|
||||||
|
</options>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="dataBits" type="integer">
|
||||||
|
<advanced>true</advanced>
|
||||||
|
<label>Data Bits</label>
|
||||||
|
<description>Set the data bits</description>
|
||||||
|
<default>8</default>
|
||||||
|
<options>
|
||||||
|
<option value="5">5</option>
|
||||||
|
<option value="6">6</option>
|
||||||
|
<option value="7">7</option>
|
||||||
|
<option value="8">8</option>
|
||||||
|
</options>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="parity" type="text">
|
||||||
|
<advanced>true</advanced>
|
||||||
|
<label>Parity</label>
|
||||||
|
<description>Set the parity</description>
|
||||||
|
<default>N</default>
|
||||||
|
<options>
|
||||||
|
<option value="N">N(one)</option>
|
||||||
|
<option value="O">O(dd)</option>
|
||||||
|
<option value="E">E(even)</option>
|
||||||
|
<option value="M">M(ark)</option>
|
||||||
|
<option value="S">S(pace)</option>
|
||||||
|
</options>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="stopBits" type="text">
|
||||||
|
<advanced>true</advanced>
|
||||||
|
<label>Stop Bits</label>
|
||||||
|
<description>Set the stop bits</description>
|
||||||
|
<default>1</default>
|
||||||
|
<options>
|
||||||
|
<option value="1">1</option>
|
||||||
|
<option value="1.5">1.5</option>
|
||||||
|
<option value="2">2</option>
|
||||||
|
</options>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="charset" type="text">
|
||||||
|
<advanced>true</advanced>
|
||||||
|
<label>Charset</label>
|
||||||
|
<description>The charset to use for converting between bytes and string (e.g. UTF-8, ISO-8859-1)</description>
|
||||||
|
</parameter>
|
||||||
|
</config-description>
|
||||||
|
</bridge-type>
|
||||||
|
|
||||||
|
<thing-type id="serialDevice" extensible="string, number, dimmer, switch, rollershutter">
|
||||||
|
<supported-bridge-type-refs>
|
||||||
|
<bridge-type-ref id="serialBridge"/>
|
||||||
|
</supported-bridge-type-refs>
|
||||||
|
|
||||||
|
<label>Serial Device</label>
|
||||||
|
<description>Represents a device</description>
|
||||||
|
|
||||||
|
<config-description>
|
||||||
|
<parameter name="patternMatch" type="text">
|
||||||
|
<label>Patern Match</label>
|
||||||
|
<context>pattern-match</context>
|
||||||
|
<required>true</required>
|
||||||
|
<description>Regular expression used to identify device from received data (must match the whole line)</description>
|
||||||
|
</parameter>
|
||||||
|
</config-description>
|
||||||
|
</thing-type>
|
||||||
|
|
||||||
|
<!-- Channel Types -->
|
||||||
|
<channel-type id="stringData">
|
||||||
|
<item-type>String</item-type>
|
||||||
|
<label>String Data</label>
|
||||||
|
<description>Channel for sending/receiving data as a string to/from the serial port</description>
|
||||||
|
</channel-type>
|
||||||
|
|
||||||
|
<channel-type id="binaryData">
|
||||||
|
<item-type>String</item-type>
|
||||||
|
<label>Binary Data</label>
|
||||||
|
<description>Channel for sending/receiving data encoded as Base64 to/from the serial port</description>
|
||||||
|
</channel-type>
|
||||||
|
|
||||||
|
<channel-type id="string">
|
||||||
|
<item-type>String</item-type>
|
||||||
|
<label>String</label>
|
||||||
|
<description>Channel to receive commands as a string</description>
|
||||||
|
<config-description>
|
||||||
|
<parameter name="stateTransformation" type="text">
|
||||||
|
<label>State Transformation</label>
|
||||||
|
<description>Transform used to convert device data to channel state, e.g. REGEX:.*?STATE=(.*?);.*</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">
|
||||||
|
<label>Command Transformation</label>
|
||||||
|
<description>Transform used to convert command to device data, e.g. JS:device.js</description>
|
||||||
|
</parameter>
|
||||||
|
</config-description>
|
||||||
|
</channel-type>
|
||||||
|
|
||||||
|
<channel-type id="number">
|
||||||
|
<item-type>Number</item-type>
|
||||||
|
<label>Number</label>
|
||||||
|
<description>Channel to receive commands as a number</description>
|
||||||
|
<config-description>
|
||||||
|
<parameter name="stateTransformation" type="text">
|
||||||
|
<label>State Transformation</label>
|
||||||
|
<description>Transform used to convert device data to channel state, e.g. REGEX:.*?STATE=(.*?);.*</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">
|
||||||
|
<label>Command Transformation</label>
|
||||||
|
<description>Transform used to convert command to device data, e.g. JS:device.js</description>
|
||||||
|
</parameter>
|
||||||
|
</config-description>
|
||||||
|
</channel-type>
|
||||||
|
|
||||||
|
<channel-type id="dimmer">
|
||||||
|
<item-type>Dimmer</item-type>
|
||||||
|
<label>Dimmer</label>
|
||||||
|
<description>Channel to receive commands from a Dimmer</description>
|
||||||
|
<config-description>
|
||||||
|
<parameter name="stateTransformation" type="text">
|
||||||
|
<label>State Transformation</label>
|
||||||
|
<description>Transform used to convert device data to channel state, e.g. REGEX:.*?STATE=(.*?);.*</description>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="onValue" type="text">
|
||||||
|
<label>On Value</label>
|
||||||
|
<description>Send this value when receiving an ON command</description>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="offValue" type="text">
|
||||||
|
<label>Off Value</label>
|
||||||
|
<description>Send this value when receiving an OFF command</description>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="increaseValue" type="text">
|
||||||
|
<label>Increase Value</label>
|
||||||
|
<description>Send this value when receiving an INCREASE command</description>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="decreaseValue" type="text">
|
||||||
|
<label>Decrease Value</label>
|
||||||
|
<description>Send this value when receiving a DECREASE command</description>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="commandFormat" type="text">
|
||||||
|
<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">
|
||||||
|
<label>Command Transformation</label>
|
||||||
|
<description>Transform used to convert command to device data, e.g. JS:device.js</description>
|
||||||
|
</parameter>
|
||||||
|
</config-description>
|
||||||
|
</channel-type>
|
||||||
|
|
||||||
|
<channel-type id="switch">
|
||||||
|
<item-type>Switch</item-type>
|
||||||
|
<label>Switch</label>
|
||||||
|
<description>Channel to receive commands from a Switch</description>
|
||||||
|
<config-description>
|
||||||
|
<parameter name="stateTransformation" type="text">
|
||||||
|
<label>State Transformation</label>
|
||||||
|
<description>Transform used to convert device data to channel state, e.g. REGEX:.*?STATE=(.*?);.*</description>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="onValue" type="text">
|
||||||
|
<label>On Value</label>
|
||||||
|
<description>Send this value when receiving an ON command</description>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="offValue" type="text">
|
||||||
|
<label>Off Value</label>
|
||||||
|
<description>Send this value when receiving an OFF command</description>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="commandTransformation" type="text">
|
||||||
|
<label>Command Transformation</label>
|
||||||
|
<description>Transform used to convert command to device data, e.g. JS:device.js</description>
|
||||||
|
</parameter>
|
||||||
|
</config-description>
|
||||||
|
</channel-type>
|
||||||
|
|
||||||
|
<channel-type id="rollershutter">
|
||||||
|
<item-type>Rollershutter</item-type>
|
||||||
|
<label>Rollershutter</label>
|
||||||
|
<description>Channel to receive commands from a Rollershutter</description>
|
||||||
|
<config-description>
|
||||||
|
<parameter name="stateTransformation" type="text">
|
||||||
|
<label>State Transformation</label>
|
||||||
|
<description>Transform used to convert device data to channel state, e.g. REGEX:.*?STATE=(.*?);.*</description>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="upValue" type="text">
|
||||||
|
<label>Up Value</label>
|
||||||
|
<description>Send this value when receiving an UP command</description>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="downValue" type="text">
|
||||||
|
<label>Down Value</label>
|
||||||
|
<description>Send this value when receiving a DOWN command</description>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="stopValue" type="text">
|
||||||
|
<label>Stop Value</label>
|
||||||
|
<description>Send this value when receiving a STOP command</description>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="commandFormat" type="text">
|
||||||
|
<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">
|
||||||
|
<label>Command Transformation</label>
|
||||||
|
<description>Transform used to convert command to device data, e.g. JS:device.js</description>
|
||||||
|
</parameter>
|
||||||
|
</config-description>
|
||||||
|
</channel-type>
|
||||||
|
|
||||||
|
</thing:thing-descriptions>
|
@ -247,6 +247,7 @@
|
|||||||
<module>org.openhab.binding.seneye</module>
|
<module>org.openhab.binding.seneye</module>
|
||||||
<module>org.openhab.binding.sensebox</module>
|
<module>org.openhab.binding.sensebox</module>
|
||||||
<module>org.openhab.binding.sensibo</module>
|
<module>org.openhab.binding.sensibo</module>
|
||||||
|
<module>org.openhab.binding.serial</module>
|
||||||
<module>org.openhab.binding.serialbutton</module>
|
<module>org.openhab.binding.serialbutton</module>
|
||||||
<module>org.openhab.binding.shelly</module>
|
<module>org.openhab.binding.shelly</module>
|
||||||
<module>org.openhab.binding.silvercrestwifisocket</module>
|
<module>org.openhab.binding.silvercrestwifisocket</module>
|
||||||
|
Loading…
Reference in New Issue
Block a user