added migrated 2.x add-ons
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
34
bundles/org.openhab.binding.cbus/.classpath
Normal file
34
bundles/org.openhab.binding.cbus/.classpath
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="lib" path="lib/cgateinterface-1.1.0-JH-dev.jar"/>
|
||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="test" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
23
bundles/org.openhab.binding.cbus/.project
Normal file
23
bundles/org.openhab.binding.cbus/.project
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.openhab.binding.cbus</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
19
bundles/org.openhab.binding.cbus/NOTICE
Normal file
19
bundles/org.openhab.binding.cbus/NOTICE
Normal file
@@ -0,0 +1,19 @@
|
||||
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/openhab2-addons
|
||||
|
||||
== Third-party Content
|
||||
|
||||
* License: Apache 2.0 License
|
||||
* Project: https://github.com/jpharvey/cgateinterface
|
||||
* Source: https://github.com/jpharvey/cgateinterface
|
||||
112
bundles/org.openhab.binding.cbus/README.md
Normal file
112
bundles/org.openhab.binding.cbus/README.md
Normal file
@@ -0,0 +1,112 @@
|
||||
# C-Bus Binding
|
||||
|
||||
This is the binding for the [Clipsal C-Bus System](http://www2.clipsal.com/cis/technical/product_groups/cbus).
|
||||
This binding allows you to view and control groups on C-Bus networks from openHAB.
|
||||
|
||||
## Configuration
|
||||
|
||||
This binding connects to C-Gate software which can be downloaded from the [Clipsal Downloads Site](https://updates.clipsal.com/ClipsalSoftwareDownload/mainsite/cis/technical/index.html). There is information about setting up the C-Gate software in the [CBus Forums](https://www.cbusforums.com/forums/c-bus-toolkit-and-c-gate-software.4). Make sure that the config/access.txt file allows a connection from computer running openHAB.
|
||||
|
||||
Whilst all versions of C-Gate should work 2.11.2 contained a fix for handling Indicator Kill messages for trigger groups. Without that they will remain on the last value set and wont match what is shown on CBus devices.
|
||||
|
||||
First the CGate Connection bridge needs to be configured with the ip address of the computer running the C-Gate software.
|
||||
After this a Bridge is creaed for each network configured on the CBus Network. The CBus Project Name and the network Id for that network
|
||||
|
||||
|
||||
## Supported Things
|
||||
|
||||
This binding support 6 different things types
|
||||
|
||||
| Thing | Type | Description |
|
||||
|----------------|---------|-----------------------------------|
|
||||
| cgate | Bridge | This connects to a C-Bus CGate instance to |
|
||||
| network | Bridge | This connects to a C-Bus Network via a CGate bridge |
|
||||
| light | Thing | This is for C-Bus lighting groups |
|
||||
| temperature | Thing | This is for C-Bus temperature groups |
|
||||
| trigger | Thing | This is for C-Bus trigger groups |
|
||||
| dali | Thing | This is for C-Bus DALI dimming groups |
|
||||
|
||||
The scan within Paper UI will find all the groups on the CBus network and allow Things to be creaed for them.
|
||||
##Channels
|
||||
|
||||
At startup the binding will scan the network for the values of all the groups and set those on the appropriate channels. It is not possible to fetch the value of a Trigger Group so those values will only be updated when a trigger is set on the CBus network.
|
||||
|
||||
### Lights
|
||||
|
||||
Light things have 2 channels which show the current state of the group on the cbus network and can also set the state of the group:-
|
||||
|
||||
* **state** - On/Off state of the light
|
||||
* **level** - The level of the channel between 0 and 100
|
||||
|
||||
### Temperature
|
||||
|
||||
Temperature things have 1 channel which shows the current value. This is read-only and will not set the value on the CBus Network.
|
||||
|
||||
* **temp** - Temperature value
|
||||
|
||||
### Trigger
|
||||
|
||||
Trigger things have 1 channel which shows the current trigger value on the cbus network and can be used to set a trigger value on the CBus Network.
|
||||
|
||||
* **value** - CBus Trigger value
|
||||
|
||||
### Dali
|
||||
|
||||
Dali things have 1 channel which shows the current value on the cbus network and can be used to set a value on the CBus Network.
|
||||
|
||||
* **level** - Value from the DALI node
|
||||
|
||||
## Example
|
||||
|
||||
### cbus.things
|
||||
|
||||
```
|
||||
|
||||
/* Need a cgate bridge to connect to cgate and then 1 network bridge for each network on that system */
|
||||
Bridge cbus:cgate:cgatenetwork "file - cgate" [ ipAddress="127.0.0.1"] {
|
||||
Bridge network cbusnetwork "file - network" [ id=254, project="OURHOME" ] {
|
||||
/* Things can be configured within each network bridge */
|
||||
Thing light light27 "light 27" [group=27]
|
||||
}
|
||||
}
|
||||
|
||||
/* Things can be configured seperatly and associated with the network bridge */
|
||||
Thing cbus:light:cgatenetwork:cbusnetwork:light31 "light 31" (cbus:network:cgatenetwork:cbusnetwork) [ group=31 ]
|
||||
Thing cbus:trigger:cgatenetwork:cbusnetwork:trigger1 "trigger 1" (cbus:network:cgatenetwork:cbusnetwork) [ group=1 ]
|
||||
Thing cbus:temperature:cgatenetwork:cbusnetwork:temp2 "temp 2" (cbus:network:cgatenetwork:cbusnetwork) [ group=2 ]
|
||||
Thing cbus:dali:cgatenetwork:cbusnetwork:dali3 "dali 3 value" (cbus:network:cgatenetwork:cbusnetwork) [ group=3 ]
|
||||
```
|
||||
|
||||
### cbus.items
|
||||
|
||||
```
|
||||
Dimmer light31Dimmer { channel="cbus:light:cgatenetwork:cbusnetwork:light31:level"}
|
||||
Switch light31Switch { channel="cbus:light:cgatenetwork:cbusnetwork:light31:state"}
|
||||
Number trigger1Value { channel="cbus:trigger:cgatenetwork:cbusnetwork:trigger1:value"}
|
||||
Number temp2 { channel="cbus:temperature:cgatenetwork:cbusnetwork:temp2:temp"}
|
||||
Dimmer dali3 { channel="cbus:dali:cgatenetwork:cbusnetwork:dali3:level"}
|
||||
```
|
||||
|
||||
### cbusdemo.sitemap
|
||||
|
||||
```
|
||||
sitemap cbusdemo label="CBus Binding Demo"
|
||||
{
|
||||
Frame label="light" {
|
||||
Slider item=light31Dimmer label="dimmer"
|
||||
Switch item=light31Switch label="switch"
|
||||
}
|
||||
Frame label="trigger" {
|
||||
Switch item=trigger1Value label="trigger Value" mappings=[0="light 1", 1="light 2", 2="both lights", 3="off"]
|
||||
}
|
||||
Frame label="temperature" {
|
||||
Default item=temp2 label="Temperature" icon="temperature"
|
||||
}
|
||||
Frame label="dali" {
|
||||
Default item=dali3 label="Dali Level"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
18
bundles/org.openhab.binding.cbus/pom.xml
Normal file
18
bundles/org.openhab.binding.cbus/pom.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_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.cbus</artifactId>
|
||||
|
||||
<name>openHAB Add-ons :: Bundles :: CBUs Binding</name>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.cbus-${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-cbus" description="CBus Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.cbus/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
||||
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* 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.cbus;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link CBusBinding} class defines common constants, which are
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Scott Linton - Initial contribution
|
||||
*/
|
||||
|
||||
@NonNullByDefault
|
||||
public class CBusBindingConstants {
|
||||
|
||||
public static final String BINDING_ID = "cbus";
|
||||
|
||||
// List of main things
|
||||
public static final String BRIDGE_CGATE = "cgate";
|
||||
public static final String BRIDGE_NETWORK = "network";
|
||||
public static final String THING_GROUP = "group";
|
||||
public static final String THING_LIGHT = "light";
|
||||
public static final String THING_TEMPERATURE = "temperature";
|
||||
public static final String THING_TRIGGER = "trigger";
|
||||
public static final String THING_DALI = "dali";
|
||||
|
||||
// List of all Thing Type UIDs
|
||||
public static final ThingTypeUID BRIDGE_TYPE_CGATE = new ThingTypeUID(BINDING_ID, BRIDGE_CGATE);
|
||||
public static final ThingTypeUID BRIDGE_TYPE_NETWORK = new ThingTypeUID(BINDING_ID, BRIDGE_NETWORK);
|
||||
public static final ThingTypeUID THING_TYPE_GROUP = new ThingTypeUID(BINDING_ID, THING_GROUP);
|
||||
public static final ThingTypeUID THING_TYPE_LIGHT = new ThingTypeUID(BINDING_ID, THING_LIGHT);
|
||||
public static final ThingTypeUID THING_TYPE_TEMPERATURE = new ThingTypeUID(BINDING_ID, THING_TEMPERATURE);
|
||||
public static final ThingTypeUID THING_TYPE_TRIGGER = new ThingTypeUID(BINDING_ID, THING_TRIGGER);
|
||||
public static final ThingTypeUID THING_TYPE_DALI = new ThingTypeUID(BINDING_ID, THING_DALI);
|
||||
|
||||
// List of all Channel ids
|
||||
public static final String CHANNEL_LEVEL = "level";
|
||||
public static final String CHANNEL_STATE = "state";
|
||||
public static final String CHANNEL_TEMP = "temp";
|
||||
public static final String CHANNEL_VALUE = "value";
|
||||
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = new HashSet<ThingTypeUID>(
|
||||
Arrays.asList(BRIDGE_TYPE_CGATE, BRIDGE_TYPE_NETWORK, THING_TYPE_GROUP, THING_TYPE_LIGHT,
|
||||
THING_TYPE_TEMPERATURE, THING_TYPE_TRIGGER, THING_TYPE_DALI));
|
||||
public static final Set<ThingTypeUID> NETWORK_DISCOVERY_THING_TYPES_UIDS = new HashSet<ThingTypeUID>(
|
||||
Arrays.asList(BRIDGE_TYPE_NETWORK));
|
||||
|
||||
public static final String CONFIG_NETWORK_ID = "id";
|
||||
public static final String CONFIG_NETWORK_PROJECT = "project";
|
||||
public static final String CONFIG_NETWORK_SYNC = "syncInterval";
|
||||
public static final String PROPERTY_NETWORK_NAME = "name";
|
||||
|
||||
public static final String CONFIG_CGATE_IP_ADDRESS = "ipAddress";
|
||||
|
||||
public static final String CONFIG_GROUP_ID = "group";
|
||||
|
||||
public static final String PROPERTY_NETWORK_ID = "CBUS Network Id";
|
||||
public static final String PROPERTY_APPLICATION_ID = "CBUS Application Id";
|
||||
public static final String PROPERTY_GROUP_NAME = "CBUS Group Name";
|
||||
|
||||
public static final int CBUS_APPLICATION_LIGHTING = 56;
|
||||
public static final int CBUS_APPLICATION_TEMPERATURE = 25;
|
||||
public static final int CBUS_APPLICATION_TRIGGER = 202;
|
||||
public static final int CBUS_APPLICATION_DALI = 95;
|
||||
}
|
||||
@@ -0,0 +1,379 @@
|
||||
/**
|
||||
* 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.cbus.handler;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.cbus.CBusBindingConstants;
|
||||
import org.openhab.binding.cbus.internal.CBusCGateConfiguration;
|
||||
import org.openhab.binding.cbus.internal.CBusThreadPool;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
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.binding.BaseBridgeHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.daveoxley.cbus.CGateConnectException;
|
||||
import com.daveoxley.cbus.CGateException;
|
||||
import com.daveoxley.cbus.CGateInterface;
|
||||
import com.daveoxley.cbus.CGateSession;
|
||||
import com.daveoxley.cbus.events.EventCallback;
|
||||
import com.daveoxley.cbus.status.StatusChangeCallback;
|
||||
|
||||
/**
|
||||
* The {@link CBusCGateHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Scott Linton - Initial contribution
|
||||
*/
|
||||
|
||||
@NonNullByDefault
|
||||
public class CBusCGateHandler extends BaseBridgeHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CBusCGateHandler.class);
|
||||
private @Nullable InetAddress ipAddress;
|
||||
public @Nullable CGateSession cGateSession;
|
||||
private @Nullable ScheduledFuture<?> keepAliveFuture;
|
||||
|
||||
public CBusCGateHandler(Bridge br) {
|
||||
super(br);
|
||||
}
|
||||
|
||||
// This is abstract in base class so have to implement it.
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
updateStatus(ThingStatus.OFFLINE);
|
||||
logger.debug("Initializing CGate Bridge handler. {} {}", getThing().getThingTypeUID(), getThing().getUID());
|
||||
CBusCGateConfiguration configuration = getConfigAs(CBusCGateConfiguration.class);
|
||||
logger.debug("Using configuration {}", configuration);
|
||||
try {
|
||||
this.ipAddress = InetAddress.getByName(configuration.ipAddress);
|
||||
} catch (UnknownHostException e1) {
|
||||
updateStatus(ThingStatus.UNINITIALIZED, ThingStatusDetail.HANDLER_INITIALIZING_ERROR,
|
||||
"IP Address not resolvable");
|
||||
return;
|
||||
}
|
||||
|
||||
InetAddress address = this.ipAddress;
|
||||
if (address != null) {
|
||||
logger.debug("CGate IP {}.", address.getHostAddress());
|
||||
}
|
||||
|
||||
keepAliveFuture = scheduler.scheduleWithFixedDelay(this::keepAlive, 0, 100, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
private void keepAlive() {
|
||||
CGateSession session = cGateSession;
|
||||
if (session == null || !session.isConnected()) {
|
||||
if (!getThing().getStatus().equals(ThingStatus.ONLINE)) {
|
||||
connect();
|
||||
} else {
|
||||
updateStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void connect() {
|
||||
CGateSession cGateSession = this.cGateSession;
|
||||
if (cGateSession == null) {
|
||||
cGateSession = CGateInterface.connect(this.ipAddress, 20023, 20024, 20025, new CBusThreadPool());
|
||||
cGateSession.registerEventCallback(new EventMonitor());
|
||||
cGateSession.registerStatusChangeCallback(new StatusChangeMonitor());
|
||||
this.cGateSession = cGateSession;
|
||||
}
|
||||
if (cGateSession.isConnected()) {
|
||||
logger.debug("CGate session reports online");
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} else {
|
||||
try {
|
||||
cGateSession.connect();
|
||||
updateStatus();
|
||||
} catch (CGateConnectException e) {
|
||||
updateStatus();
|
||||
logger.debug("Failed to connect to CGate:", e);
|
||||
try {
|
||||
cGateSession.close();
|
||||
} catch (CGateException ignore) {
|
||||
// We dont really care if an exception is thrown when clossing the connection after a failure
|
||||
// connecting.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStatus() {
|
||||
ThingStatus lastStatus = getThing().getStatus();
|
||||
CGateSession cGateSession = this.cGateSession;
|
||||
if (cGateSession == null) {
|
||||
return;
|
||||
}
|
||||
if (cGateSession.isConnected()) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} else {
|
||||
if (lastStatus != ThingStatus.OFFLINE) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
|
||||
}
|
||||
}
|
||||
if (!getThing().getStatus().equals(lastStatus)) {
|
||||
boolean isOnline = getThing().getStatus().equals(ThingStatus.ONLINE);
|
||||
updateChildThings(isOnline);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateChildThings(boolean isOnline) {
|
||||
scheduler.execute(() -> {
|
||||
// now also re-initialize all network handlers
|
||||
for (Thing thing : getThing().getThings()) {
|
||||
ThingHandler handler = thing.getHandler();
|
||||
if (handler instanceof CBusNetworkHandler) {
|
||||
((CBusNetworkHandler) handler).cgateStateChanged(isOnline);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateGroup(@Nullable String address, @Nullable String value) {
|
||||
if (address == null || value == null) {
|
||||
return;
|
||||
}
|
||||
logger.debug("updateGroup address {}", address);
|
||||
// Address should be of the form //Project/network/application/group
|
||||
if (!address.startsWith("//")) {
|
||||
logger.debug("Address does not start with // so ignoring this update");
|
||||
return;
|
||||
}
|
||||
String[] addressParts = address.substring(2).split("/");
|
||||
if (addressParts.length != 4) {
|
||||
logger.debug("Address is badly formed so ignoring this update length of parts is {} not 4",
|
||||
addressParts.length);
|
||||
return;
|
||||
}
|
||||
updateGroup(Integer.parseInt(addressParts[1]), Integer.parseInt(addressParts[2]),
|
||||
Integer.parseInt(addressParts[3]), value);
|
||||
}
|
||||
|
||||
private void updateGroup(int network, int application, int group, String value) {
|
||||
for (Thing networkThing : getThing().getThings()) {
|
||||
// Is this networkThing from the network we are looking for...
|
||||
if (networkThing.getThingTypeUID().equals(CBusBindingConstants.BRIDGE_TYPE_NETWORK)) {
|
||||
CBusNetworkHandler netThingHandler = (CBusNetworkHandler) networkThing.getHandler();
|
||||
if (netThingHandler == null || netThingHandler.getNetworkId() != network) {
|
||||
continue;
|
||||
}
|
||||
// Loop through all the things on this network and see if they match the application / group
|
||||
for (Thing thing : netThingHandler.getThing().getThings()) {
|
||||
ThingHandler thingThingHandler = thing.getHandler();
|
||||
if (thingThingHandler == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (thingThingHandler instanceof CBusGroupHandler) {
|
||||
((CBusGroupHandler) thingThingHandler).updateGroup(application, group, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public @Nullable CGateSession getCGateSession() {
|
||||
return cGateSession;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
ScheduledFuture<?> keepAliveFuture = this.keepAliveFuture;
|
||||
if (keepAliveFuture != null) {
|
||||
keepAliveFuture.cancel(true);
|
||||
}
|
||||
CGateSession cGateSession = this.cGateSession;
|
||||
if (cGateSession != null && cGateSession.isConnected()) {
|
||||
try {
|
||||
cGateSession.close();
|
||||
} catch (CGateException e) {
|
||||
logger.warn("Cannot close CGate session", e);
|
||||
}
|
||||
} else {
|
||||
logger.debug("no session or it is disconnected");
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@NonNullByDefault
|
||||
private class EventMonitor extends EventCallback {
|
||||
|
||||
@Override
|
||||
public boolean acceptEvent(int eventCode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processEvent(@Nullable CGateSession cgate_session, int eventCode,
|
||||
@Nullable GregorianCalendar event_time, @Nullable String event) {
|
||||
if (event == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (eventCode == 701) {
|
||||
// By Marking this as Nullable it fools the static analyser into understanding that poll can return Null
|
||||
LinkedList<@Nullable String> tokenizer = new LinkedList<>(Arrays.asList(event.trim().split("\\s+")));
|
||||
@Nullable
|
||||
String address = tokenizer.poll();
|
||||
tokenizer.poll();
|
||||
@Nullable
|
||||
String value = tokenizer.poll();
|
||||
if (value != null && value.startsWith("level=")) {
|
||||
String level = value.replace("level=", "");
|
||||
updateGroup(address, level);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NonNullByDefault
|
||||
private class StatusChangeMonitor extends StatusChangeCallback {
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processStatusChange(@Nullable CGateSession cGateSession, @Nullable String status) {
|
||||
if (cGateSession == null || status == null) {
|
||||
return;
|
||||
}
|
||||
if (status.startsWith("# ")) {
|
||||
status = status.substring(2);
|
||||
// Shouldnt need to check for null but this silences a warning
|
||||
if (status == null || status.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
logger.debug("ProcessStatusChange {}", status);
|
||||
String[] contents = status.split("#");
|
||||
if (cGateSession.getSessionID() != null
|
||||
&& contents[1].contains("sessionId=" + cGateSession.getSessionID())) {
|
||||
// We created this event - don't worry about processing it again...
|
||||
return;
|
||||
}
|
||||
// By Marking this as Nullable it fools the static analyser into understanding that poll can return Null
|
||||
LinkedList<@Nullable String> tokenizer = new LinkedList<>(Arrays.asList(contents[0].split("\\s+")));
|
||||
@Nullable
|
||||
String firstToken = tokenizer.poll();
|
||||
if (firstToken == null) {
|
||||
logger.debug("ProcessStateChange: Cant tokenize status {}", status);
|
||||
return;
|
||||
}
|
||||
switch (firstToken) {
|
||||
case "lighting": {
|
||||
@Nullable
|
||||
String state = tokenizer.poll();
|
||||
@Nullable
|
||||
String address = tokenizer.poll();
|
||||
if ("ramp".equals(state)) {
|
||||
state = tokenizer.poll();
|
||||
}
|
||||
updateGroup(address, state);
|
||||
break;
|
||||
}
|
||||
case "temperature": {
|
||||
// For temperature we ignore the state
|
||||
tokenizer.poll();
|
||||
@Nullable
|
||||
String address = tokenizer.poll();
|
||||
@Nullable
|
||||
String temp = tokenizer.poll();
|
||||
updateGroup(address, temp);
|
||||
break;
|
||||
}
|
||||
case "trigger": {
|
||||
@Nullable
|
||||
String command = tokenizer.poll();
|
||||
@Nullable
|
||||
String address = tokenizer.poll();
|
||||
if ("event".equals(command)) {
|
||||
@Nullable
|
||||
String level = tokenizer.poll();
|
||||
updateGroup(address, level);
|
||||
} else if ("indicatorkill".equals(command)) {
|
||||
updateGroup(address, "-1");
|
||||
} else {
|
||||
logger.warn("Unhandled trigger command {} - status {}", command, status);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "clock": {
|
||||
@Nullable
|
||||
String address = "";
|
||||
@Nullable
|
||||
String value = "";
|
||||
@Nullable
|
||||
String type = tokenizer.poll();
|
||||
if ("date".equals(type)) {
|
||||
address = tokenizer.poll() + "/1";
|
||||
value = tokenizer.poll();
|
||||
} else if ("time".equals(type)) {
|
||||
address = tokenizer.poll() + "/0";
|
||||
value = tokenizer.poll();
|
||||
} else if (!"request_refresh".equals(type)) {
|
||||
// We dont handle request_refresh as we are not a clock master
|
||||
logger.debug("Received unknown clock event: {}", status);
|
||||
}
|
||||
if (value != null && !value.isEmpty()) {
|
||||
updateGroup(address, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LinkedList<String> commentTokenizer = new LinkedList<>(Arrays.asList(contents[1].split("\\s+")));
|
||||
if ("lighting".equals(commentTokenizer.peek())) {
|
||||
commentTokenizer.poll();
|
||||
@Nullable
|
||||
String commentToken = commentTokenizer.peek();
|
||||
|
||||
if ("SyncUpdate".equals(commentToken)) {
|
||||
commentTokenizer.poll();
|
||||
@Nullable
|
||||
String address = commentTokenizer.poll();
|
||||
|
||||
@Nullable
|
||||
String level = commentTokenizer.poll();
|
||||
level = level.replace("level=", "");
|
||||
updateGroup(address, level);
|
||||
}
|
||||
} else {
|
||||
logger.debug("Received unparsed event: '{}'", status);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* 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.cbus.handler;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.cbus.CBusBindingConstants;
|
||||
import org.openhab.core.library.types.IncreaseDecreaseType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
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.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.daveoxley.cbus.CGateException;
|
||||
import com.daveoxley.cbus.Group;
|
||||
|
||||
/**
|
||||
* The {@link CBusDaliHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Scott Linton - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class CBusDaliHandler extends CBusGroupHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CBusDaliHandler.class);
|
||||
|
||||
public CBusDaliHandler(Thing thing) {
|
||||
super(thing, CBusBindingConstants.CBUS_APPLICATION_DALI);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
Group group = this.group;
|
||||
if (group == null) {
|
||||
return;
|
||||
}
|
||||
if (command instanceof RefreshType) {
|
||||
try {
|
||||
int level = group.getLevel();
|
||||
logger.debug("handle RefreshType Command for Chanell {} Group {} level {}", channelUID, groupId, level);
|
||||
if (channelUID.getId().equals(CBusBindingConstants.CHANNEL_LEVEL)) {
|
||||
updateState(channelUID, new PercentType((int) (level * 100 / 255.0)));
|
||||
}
|
||||
} catch (CGateException e) {
|
||||
logger.debug("Failed to getLevel for group {}", groupId, e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Communication Error");
|
||||
}
|
||||
} else {
|
||||
if (channelUID.getId().equals(CBusBindingConstants.CHANNEL_LEVEL)) {
|
||||
logger.debug("Channel Level command for {}: {}", channelUID, command);
|
||||
try {
|
||||
if (command instanceof OnOffType) {
|
||||
if (command == OnOffType.ON) {
|
||||
group.on();
|
||||
} else if (command == OnOffType.OFF) {
|
||||
group.off();
|
||||
}
|
||||
} else if (command instanceof PercentType) {
|
||||
PercentType value = (PercentType) command;
|
||||
group.ramp((int) Math.round(value.doubleValue() / 100 * 255), 0);
|
||||
} else if (command instanceof IncreaseDecreaseType) {
|
||||
int level = group.getLevel();
|
||||
if (command == IncreaseDecreaseType.DECREASE) {
|
||||
level = Math.max(level - 1, 0);
|
||||
} else if (command == IncreaseDecreaseType.INCREASE) {
|
||||
level = Math.min(level + 1, 255);
|
||||
}
|
||||
group.ramp(level, 0);
|
||||
logger.debug("Change group level to {}", level);
|
||||
}
|
||||
} catch (CGateException e) {
|
||||
logger.debug("Cannot send command {} to {}", command, group, e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Communication Error");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateGroup(int updateApplicationId, int updateGroupId, String value) {
|
||||
if (updateGroupId == groupId && updateApplicationId == applicationId) {
|
||||
Thing thing = getThing();
|
||||
Channel channel = thing.getChannel(CBusBindingConstants.CHANNEL_LEVEL);
|
||||
if (channel != null) {
|
||||
ChannelUID channelUID = channel.getUID();
|
||||
|
||||
if ("on".equalsIgnoreCase(value) || "255".equalsIgnoreCase(value)) {
|
||||
updateState(channelUID, OnOffType.ON);
|
||||
updateState(channelUID, new PercentType(100));
|
||||
} else if ("off".equalsIgnoreCase(value) || "0".equalsIgnoreCase(value)) {
|
||||
updateState(channelUID, OnOffType.OFF);
|
||||
updateState(channelUID, new PercentType(0));
|
||||
} else {
|
||||
try {
|
||||
int v = Integer.parseInt(value);
|
||||
PercentType perc = new PercentType(Math.round(v * 100 / 255));
|
||||
updateState(channelUID, perc);
|
||||
} catch (NumberFormatException e) {
|
||||
logger.warn(
|
||||
"Invalid value presented to channel {}. Received {}, expected On/Off or decimal value",
|
||||
channelUID, value);
|
||||
}
|
||||
}
|
||||
logger.debug("Updating CBus Lighting Group {} with value {}", thing.getUID(), value);
|
||||
} else {
|
||||
logger.debug("Failed to Updat CBus Lighting Group {} with value {}: No Channel", thing.getUID(), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
/**
|
||||
* 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.cbus.handler;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.cbus.CBusBindingConstants;
|
||||
import org.openhab.binding.cbus.internal.CBusGroupConfiguration;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
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.binding.BaseThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.daveoxley.cbus.Application;
|
||||
import com.daveoxley.cbus.CGateException;
|
||||
import com.daveoxley.cbus.Group;
|
||||
import com.daveoxley.cbus.Network;
|
||||
|
||||
/**
|
||||
* The {@link CBusGroupHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Scott Linton - Initial contribution
|
||||
*/
|
||||
|
||||
@NonNullByDefault
|
||||
public abstract class CBusGroupHandler extends BaseThingHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CBusGroupHandler.class);
|
||||
protected @Nullable CBusNetworkHandler cBusNetworkHandler;
|
||||
protected @Nullable Group group;
|
||||
protected int applicationId = -1;
|
||||
protected int groupId = -1;
|
||||
|
||||
public CBusGroupHandler(Thing thing, int applicationId) {
|
||||
super(thing);
|
||||
this.applicationId = applicationId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract void handleCommand(ChannelUID channelUID, Command command);
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
/*
|
||||
* Cast to Nullable in map to avoid compiler warnings
|
||||
*/
|
||||
CBusGroupConfiguration configuration = getConfigAs(CBusGroupConfiguration.class);
|
||||
logger.debug("Using configuration {}", configuration);
|
||||
groupId = configuration.group;
|
||||
|
||||
CBusNetworkHandler cBusNetworkHandler = getCBusNetworkHandler();
|
||||
this.cBusNetworkHandler = cBusNetworkHandler;
|
||||
if (cBusNetworkHandler == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"No CBusNetworkHandler Bridge available");
|
||||
return;
|
||||
}
|
||||
updateStatus();
|
||||
|
||||
Map<String, String> updatedProperties = editProperties();
|
||||
updatedProperties.put(CBusBindingConstants.PROPERTY_APPLICATION_ID, Integer.toString(applicationId));
|
||||
updatedProperties.put(CBusBindingConstants.PROPERTY_NETWORK_ID,
|
||||
Integer.toString(cBusNetworkHandler.getNetworkId()));
|
||||
updateProperties(updatedProperties);
|
||||
}
|
||||
|
||||
public void updateStatus() {
|
||||
try {
|
||||
logger.debug("updateStatus UID: {} applicaton: {} group: {}", getThing().getUID(), applicationId, groupId);
|
||||
CBusNetworkHandler networkHandler = cBusNetworkHandler;
|
||||
if (networkHandler == null || !networkHandler.getThing().getStatus().equals(ThingStatus.ONLINE)) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
} else {
|
||||
Group group = this.group;
|
||||
if (group == null) {
|
||||
group = getGroup();
|
||||
this.group = group;
|
||||
}
|
||||
if (group == null) {
|
||||
logger.debug("Set state to configuration error -no group");
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"No Group object available");
|
||||
} else if (group.getNetwork().isOnline()) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
|
||||
try {
|
||||
Map<String, String> updatedProperties = editProperties();
|
||||
updatedProperties.put(CBusBindingConstants.PROPERTY_GROUP_NAME, group.getName());
|
||||
updateProperties(updatedProperties);
|
||||
} catch (CGateException ignore) {
|
||||
// Cant get name so properties wont be updated
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"Network is not reporting online");
|
||||
}
|
||||
}
|
||||
} catch (CGateException e) {
|
||||
logger.debug("Problem checking network state for network {}", e.getMessage());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void updateGroup(int application, int group, String value);
|
||||
|
||||
private @Nullable Group getGroup() {
|
||||
try {
|
||||
CBusNetworkHandler networkHandler = cBusNetworkHandler;
|
||||
if (networkHandler == null) {
|
||||
return null;
|
||||
}
|
||||
Network network = networkHandler.getNetwork();
|
||||
if (network != null) {
|
||||
Application application = network.getApplication(applicationId);
|
||||
if (application == null) {
|
||||
logger.debug("getGroup() Cant get application for id {}", applicationId);
|
||||
return null;
|
||||
}
|
||||
logger.debug("GetGroup for {}/id {}", applicationId, groupId);
|
||||
return application.getGroup(groupId);
|
||||
}
|
||||
} catch (CGateException e) {
|
||||
logger.debug("GetGroup for id {}/{} failed {}", applicationId, groupId, e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private @Nullable CBusNetworkHandler getCBusNetworkHandler() {
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge == null) {
|
||||
logger.debug("Required bridge not defined for device .");
|
||||
return null;
|
||||
}
|
||||
ThingHandler handler = bridge.getHandler();
|
||||
if (handler instanceof CBusNetworkHandler) {
|
||||
return (CBusNetworkHandler) handler;
|
||||
}
|
||||
logger.debug("No available bridge handler found for bridge: {}", bridge.getUID());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* 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.cbus.handler;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.cbus.CBusBindingConstants;
|
||||
import org.openhab.core.library.types.IncreaseDecreaseType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
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.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.daveoxley.cbus.CGateException;
|
||||
import com.daveoxley.cbus.Group;
|
||||
|
||||
/**
|
||||
* The {@link CBusLightHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Scott Linton - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class CBusLightHandler extends CBusGroupHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CBusLightHandler.class);
|
||||
|
||||
public CBusLightHandler(Thing thing) {
|
||||
super(thing, CBusBindingConstants.CBUS_APPLICATION_LIGHTING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
Group group = this.group;
|
||||
if (group == null) {
|
||||
return;
|
||||
}
|
||||
if (command instanceof RefreshType) {
|
||||
try {
|
||||
int level = group.getLevel();
|
||||
logger.debug("handle RefreshType Command for Chanell {} Group {} level {}", channelUID, groupId, level);
|
||||
if (channelUID.getId().equals(CBusBindingConstants.CHANNEL_STATE)) {
|
||||
updateState(channelUID, (level > 0) ? OnOffType.ON : OnOffType.OFF);
|
||||
} else if (channelUID.getId().equals(CBusBindingConstants.CHANNEL_LEVEL)) {
|
||||
updateState(channelUID, new PercentType((int) (level * 100 / 255.0)));
|
||||
}
|
||||
} catch (CGateException e) {
|
||||
logger.debug("Failed to getLevel for group {}", groupId, e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Communication Error");
|
||||
}
|
||||
} else {
|
||||
if (channelUID.getId().equals(CBusBindingConstants.CHANNEL_STATE)) {
|
||||
logger.debug("Channel State command for {}: {}", channelUID, command);
|
||||
if (command instanceof OnOffType) {
|
||||
try {
|
||||
if (command == OnOffType.ON) {
|
||||
group.on();
|
||||
} else if (command == OnOffType.OFF) {
|
||||
group.off();
|
||||
}
|
||||
} catch (CGateException e) {
|
||||
logger.debug("Failed to send command {} to {}", command, group, e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Communication Error");
|
||||
}
|
||||
}
|
||||
} else if (channelUID.getId().equals(CBusBindingConstants.CHANNEL_LEVEL)) {
|
||||
logger.debug("Channel Level command for {}: {}", channelUID, command);
|
||||
try {
|
||||
if (command instanceof OnOffType) {
|
||||
if (command == OnOffType.ON) {
|
||||
group.on();
|
||||
} else if (command == OnOffType.OFF) {
|
||||
group.off();
|
||||
}
|
||||
} else if (command instanceof PercentType) {
|
||||
PercentType value = (PercentType) command;
|
||||
group.ramp((int) Math.round(value.doubleValue() / 100 * 255), 0);
|
||||
} else if (command instanceof IncreaseDecreaseType) {
|
||||
int level = group.getLevel();
|
||||
if (command == IncreaseDecreaseType.DECREASE) {
|
||||
level = Math.max(level - 1, 0);
|
||||
} else if (command == IncreaseDecreaseType.INCREASE) {
|
||||
level = Math.min(level + 1, 255);
|
||||
}
|
||||
group.ramp(level, 0);
|
||||
logger.debug("Change group level to {}", level);
|
||||
}
|
||||
} catch (CGateException e) {
|
||||
logger.debug("Failed to send command {} to {}", command, group, e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Communication Error");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateGroup(int updateApplicationId, int updateGroupId, String value) {
|
||||
if (updateGroupId == groupId && updateApplicationId == applicationId) {
|
||||
Thing thing = getThing();
|
||||
Channel channel = thing.getChannel(CBusBindingConstants.CHANNEL_STATE);
|
||||
Channel channelLevel = thing.getChannel(CBusBindingConstants.CHANNEL_LEVEL);
|
||||
if (channel != null && channelLevel != null) {
|
||||
ChannelUID channelUID = channel.getUID();
|
||||
ChannelUID channelLevelUID = channelLevel.getUID();
|
||||
logger.debug("channel UID {} level UID {}", channelUID, channelLevelUID);
|
||||
if ("on".equalsIgnoreCase(value) || "255".equalsIgnoreCase(value)) {
|
||||
updateState(channelUID, OnOffType.ON);
|
||||
updateState(channelLevelUID, new PercentType(100));
|
||||
} else if ("off".equalsIgnoreCase(value) || "0".equalsIgnoreCase(value)) {
|
||||
updateState(channelUID, OnOffType.OFF);
|
||||
updateState(channelLevelUID, new PercentType(0));
|
||||
} else {
|
||||
try {
|
||||
int v = Integer.parseInt(value);
|
||||
updateState(channelUID, v > 0 ? OnOffType.ON : OnOffType.OFF);
|
||||
updateState(channelLevelUID, new PercentType((int) (v * 100 / 255.0)));
|
||||
} catch (NumberFormatException e) {
|
||||
logger.warn("Invalid value presented to channel {}. Received {}, expected On/Off", channelUID,
|
||||
value);
|
||||
}
|
||||
}
|
||||
logger.debug("Updating CBus Lighting Group {} with value {}", thing.getUID(), value);
|
||||
} else {
|
||||
logger.debug("Failed to Update CBus Lighting Group {} with value {}: No Channel", thing.getUID(),
|
||||
value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,289 @@
|
||||
/**
|
||||
* 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.cbus.handler;
|
||||
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.cbus.internal.CBusNetworkConfiguration;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
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.binding.BaseBridgeHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.daveoxley.cbus.CGateException;
|
||||
import com.daveoxley.cbus.CGateSession;
|
||||
import com.daveoxley.cbus.Network;
|
||||
import com.daveoxley.cbus.Project;
|
||||
|
||||
/**
|
||||
* The {@link CBusNetworkHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Scott Linton - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class CBusNetworkHandler extends BaseBridgeHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CBusNetworkHandler.class);
|
||||
private @Nullable CBusNetworkConfiguration configuration;
|
||||
private @Nullable Network network;
|
||||
private @Nullable Project projectObject;
|
||||
private @Nullable ScheduledFuture<?> initNetwork;
|
||||
private @Nullable ScheduledFuture<?> networkSync;
|
||||
|
||||
public CBusNetworkHandler(Bridge thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
// This is abstract in base class so have to implement it.
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("initialize ");
|
||||
configuration = getConfigAs(CBusNetworkConfiguration.class);
|
||||
logger.debug("Using configuration {}", configuration);
|
||||
CBusCGateHandler bridgeHandler = getCBusCGateHandler();
|
||||
if (bridgeHandler == null || !bridgeHandler.getThing().getStatus().equals(ThingStatus.ONLINE)) {
|
||||
logger.debug("bridge not online");
|
||||
updateStatus(ThingStatus.OFFLINE);
|
||||
return;
|
||||
}
|
||||
logger.debug("Bridge online so init properly");
|
||||
scheduler.execute(this::cgateOnline);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
ScheduledFuture<?> networkSync = this.networkSync;
|
||||
if (networkSync != null) {
|
||||
networkSync.cancel(false);
|
||||
}
|
||||
ScheduledFuture<?> initNetwork = this.initNetwork;
|
||||
if (initNetwork != null) {
|
||||
initNetwork.cancel(false);
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
public void cgateStateChanged(boolean isOnline) {
|
||||
logger.debug("CgateStateChanged {}", isOnline);
|
||||
if (!isOnline) {
|
||||
network = null;
|
||||
projectObject = null;
|
||||
updateStatus();
|
||||
} else {
|
||||
cgateOnline();
|
||||
}
|
||||
}
|
||||
|
||||
private void cgateOnline() {
|
||||
CBusNetworkConfiguration configuration = this.configuration;
|
||||
if (configuration == null) {
|
||||
logger.debug("cgateOnline - NetworkHandler not initialised");
|
||||
return;
|
||||
}
|
||||
ThingStatus lastStatus = getThing().getStatus();
|
||||
logger.debug("cgateOnline {}", lastStatus);
|
||||
|
||||
Integer networkID = configuration.id;
|
||||
String project = configuration.project;
|
||||
logger.debug("cgateOnline netid {} project {}", networkID, project);
|
||||
Project projectObject = getProjectObject();
|
||||
Network network = getNetwork();
|
||||
logger.debug("network {}", network);
|
||||
CBusCGateHandler cbusCGateHandler = getCBusCGateHandler();
|
||||
if (cbusCGateHandler == null) {
|
||||
logger.debug("NoCGateHandler");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (projectObject == null) {
|
||||
CGateSession session = cbusCGateHandler.getCGateSession();
|
||||
if (session != null) {
|
||||
try {
|
||||
projectObject = (Project) session.getCGateObject("//" + project);
|
||||
this.projectObject = projectObject;
|
||||
} catch (CGateException ignore) {
|
||||
// We dont need to do anything other than stop this propagating
|
||||
}
|
||||
}
|
||||
if (projectObject == null) {
|
||||
logger.debug("Cant get projectobject");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (network == null) {
|
||||
CGateSession session = cbusCGateHandler.getCGateSession();
|
||||
if (session != null) {
|
||||
try {
|
||||
network = (Network) session.getCGateObject("//" + project + "/" + networkID);
|
||||
this.network = network;
|
||||
} catch (CGateException ignore) {
|
||||
// We dont need to do anything other than stop this propagating
|
||||
}
|
||||
}
|
||||
if (network == null) {
|
||||
logger.debug("cgateOnline: Cant get network");
|
||||
return;
|
||||
}
|
||||
}
|
||||
String state = network.getState();
|
||||
logger.debug("Network state is {}", state);
|
||||
if ("new".equals(state)) {
|
||||
projectObject.start();
|
||||
logger.debug("Need to wait for it to be synced");
|
||||
} else if ("sync".equals(state)) {
|
||||
logger.debug("Network is syncing so wait for it to be ok");
|
||||
}
|
||||
if (!"ok".equals(state)) {
|
||||
ScheduledFuture<?> initNetwork = this.initNetwork;
|
||||
if (initNetwork == null || initNetwork.isCancelled()) {
|
||||
this.initNetwork = scheduler.scheduleWithFixedDelay(this::checkNetworkOnline, 30, 30,
|
||||
TimeUnit.SECONDS);
|
||||
logger.debug("Schedule a check every minute");
|
||||
} else {
|
||||
logger.debug("initNetwork alreadys started");
|
||||
}
|
||||
updateStatus();
|
||||
return;
|
||||
}
|
||||
} catch (CGateException e) {
|
||||
logger.warn("Cannot load C-Bus network {}", networkID, e);
|
||||
updateStatus(ThingStatus.UNINITIALIZED, ThingStatusDetail.COMMUNICATION_ERROR);
|
||||
}
|
||||
updateStatus();
|
||||
}
|
||||
|
||||
private void checkNetworkOnline() {
|
||||
Network network = getNetwork();
|
||||
try {
|
||||
if (network != null && network.isOnline()) {
|
||||
logger.debug("Network is online");
|
||||
ScheduledFuture<?> initNetwork = this.initNetwork;
|
||||
if (initNetwork != null) {
|
||||
initNetwork.cancel(false);
|
||||
this.initNetwork = null;
|
||||
}
|
||||
} else {
|
||||
ThingStatus lastStatus = getThing().getStatus();
|
||||
logger.debug("Network still not online {}", lastStatus);
|
||||
}
|
||||
} catch (CGateException e) {
|
||||
logger.warn("Cannot check if network is online {} ", network.getNetworkID());
|
||||
}
|
||||
updateStatus();
|
||||
}
|
||||
|
||||
private void updateStatus() {
|
||||
CBusNetworkConfiguration configuration = this.configuration;
|
||||
if (configuration == null) {
|
||||
logger.debug("updateStatus - NetworkHandler not initialised");
|
||||
return;
|
||||
}
|
||||
ThingStatus lastStatus = getThing().getStatus();
|
||||
Network network = getNetwork();
|
||||
CBusCGateHandler cbusCGateHandler = getCBusCGateHandler();
|
||||
try {
|
||||
if (cbusCGateHandler == null || !cbusCGateHandler.getThing().getStatus().equals(ThingStatus.ONLINE)) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, "CGate connection offline");
|
||||
} else if (network == null) {
|
||||
logger.debug("No network - set configuration error");
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "No Network object available");
|
||||
} else if (network.isOnline()) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"Network is not reporting online");
|
||||
}
|
||||
} catch (CGateException e) {
|
||||
logger.warn("Problem checking network state for network {}", network.getNetworkID(), e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
|
||||
}
|
||||
if (!getThing().getStatus().equals(lastStatus)) {
|
||||
ScheduledFuture<?> networkSync = this.networkSync;
|
||||
if (lastStatus == ThingStatus.OFFLINE) {
|
||||
if (networkSync == null || networkSync.isCancelled()) {
|
||||
this.networkSync = scheduler.scheduleWithFixedDelay(this::doNetworkSync, 10,
|
||||
configuration.syncInterval, TimeUnit.SECONDS);
|
||||
}
|
||||
} else {
|
||||
if (networkSync != null) {
|
||||
networkSync.cancel(false);
|
||||
}
|
||||
}
|
||||
for (Thing thing : getThing().getThings()) {
|
||||
ThingHandler handler = thing.getHandler();
|
||||
if (handler instanceof CBusGroupHandler) {
|
||||
((CBusGroupHandler) handler).updateStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void doNetworkSync() {
|
||||
Network network = getNetwork();
|
||||
try {
|
||||
if (getThing().getStatus().equals(ThingStatus.ONLINE) && network != null) {
|
||||
logger.info("Starting network sync on network {}", network.getNetworkID());
|
||||
network.startSync();
|
||||
}
|
||||
} catch (CGateException e) {
|
||||
logger.warn("Cannot start network sync on network {} - {}", network.getNetworkID(), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private @Nullable CBusCGateHandler getCBusCGateHandler() {
|
||||
logger.debug("getCBusCGateHandler");
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge == null) {
|
||||
logger.debug("Required bridge not defined for device.");
|
||||
return null;
|
||||
}
|
||||
ThingHandler handler = bridge.getHandler();
|
||||
if (handler instanceof CBusCGateHandler) {
|
||||
return (CBusCGateHandler) handler;
|
||||
} else {
|
||||
logger.debug("No available bridge handler found for bridge: {}.", bridge.getUID());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public @Nullable Network getNetwork() {
|
||||
return network;
|
||||
}
|
||||
|
||||
public int getNetworkId() {
|
||||
CBusNetworkConfiguration configuration = this.configuration;
|
||||
if (configuration == null) {
|
||||
logger.debug("getNetworkId - NetworkHandler not initialised");
|
||||
return -1;
|
||||
}
|
||||
return configuration.id;
|
||||
}
|
||||
|
||||
private @Nullable Project getProjectObject() {
|
||||
return projectObject;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* 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.cbus.handler;
|
||||
|
||||
import static org.openhab.core.library.unit.SIUnits.CELSIUS;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.cbus.CBusBindingConstants;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
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.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.daveoxley.cbus.CGateException;
|
||||
import com.daveoxley.cbus.Group;
|
||||
|
||||
/**
|
||||
* The {@link CBusTemperatureHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Scott Linton - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class CBusTemperatureHandler extends CBusGroupHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CBusTemperatureHandler.class);
|
||||
|
||||
public CBusTemperatureHandler(Thing thing) {
|
||||
super(thing, CBusBindingConstants.CBUS_APPLICATION_TEMPERATURE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
// Read only thing - no commands to handle
|
||||
if (command instanceof RefreshType) {
|
||||
try {
|
||||
Group group = this.group;
|
||||
if (group != null) {
|
||||
int level = group.getLevel();
|
||||
logger.debug("handle RefreshType Command for Chanell {} Group {} level {}", channelUID, groupId,
|
||||
level);
|
||||
if (channelUID.getId().equals(CBusBindingConstants.CHANNEL_TEMP)) {
|
||||
updateState(channelUID, new QuantityType<>(level, CELSIUS));
|
||||
}
|
||||
}
|
||||
} catch (CGateException e) {
|
||||
logger.debug("Failed to getLevel for group {}", groupId, e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Communication Error");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateGroup(int updateApplicationId, int updateGroupId, String value) {
|
||||
if (updateGroupId == groupId && updateApplicationId == applicationId) {
|
||||
Thing thing = getThing();
|
||||
Channel channel = thing.getChannel(CBusBindingConstants.CHANNEL_TEMP);
|
||||
|
||||
if (channel != null) {
|
||||
ChannelUID channelUID = channel.getUID();
|
||||
updateState(channelUID, new QuantityType<>(Double.parseDouble(value), CELSIUS));
|
||||
logger.trace("Updating CBus Temperature Group {} with value {}", thing.getUID(), value);
|
||||
} else {
|
||||
logger.trace("Failed to Update CBus Temperature Group {} with value {}: No Channel", thing.getUID(),
|
||||
value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* 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.cbus.handler;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.cbus.CBusBindingConstants;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
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.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.daveoxley.cbus.CGateException;
|
||||
import com.daveoxley.cbus.Group;
|
||||
|
||||
/**
|
||||
* The {@link CBusTriggerHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Scott Linton - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class CBusTriggerHandler extends CBusGroupHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CBusTriggerHandler.class);
|
||||
|
||||
public CBusTriggerHandler(Thing thing) {
|
||||
super(thing, CBusBindingConstants.CBUS_APPLICATION_TRIGGER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
Group group = this.group;
|
||||
if (group == null) {
|
||||
return;
|
||||
}
|
||||
if (command instanceof RefreshType) {
|
||||
/*
|
||||
* Cgate cant provide the current value for a trigger group
|
||||
*/
|
||||
logger.debug("Refresh for Trigger group not implemented");
|
||||
} else {
|
||||
if (channelUID.getId().equals(CBusBindingConstants.CHANNEL_VALUE)) {
|
||||
logger.debug("Channel Value command for {}: {}", channelUID, command);
|
||||
try {
|
||||
if (command instanceof DecimalType) {
|
||||
group.TriggerEvent(((DecimalType) command).intValue());
|
||||
}
|
||||
} catch (CGateException e) {
|
||||
logger.debug("Failed to send trigger command {} to {}", command, group, e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Communication Error");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateGroup(int updateApplicationId, int updateGroupId, String value) {
|
||||
if (updateGroupId == groupId && updateApplicationId == applicationId) {
|
||||
Thing thing = getThing();
|
||||
Channel channel = thing.getChannel(CBusBindingConstants.CHANNEL_VALUE);
|
||||
if (channel != null) {
|
||||
ChannelUID channelUID = channel.getUID();
|
||||
DecimalType val = new DecimalType(value);
|
||||
updateState(channelUID, val);
|
||||
logger.trace("Updating CBus Trigger Group {} with value {}", thing.getUID(), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 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.cbus.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Configuration class for {@link CBusCGateConfiguration}.
|
||||
*
|
||||
* @author John Harvey - Initial contribution
|
||||
*/
|
||||
|
||||
@NonNullByDefault
|
||||
public class CBusCGateConfiguration {
|
||||
|
||||
public String ipAddress = "";
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[ipAddress=%s]", ipAddress);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 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.cbus.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Configuration class for {@link CBusGroupConfiguration}.
|
||||
*
|
||||
* @author John Harvey - Initial contribution
|
||||
*/
|
||||
|
||||
@NonNullByDefault
|
||||
public class CBusGroupConfiguration {
|
||||
|
||||
public int group;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[group=%d]", group);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* 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.cbus.internal;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.cbus.CBusBindingConstants;
|
||||
import org.openhab.binding.cbus.handler.CBusCGateHandler;
|
||||
import org.openhab.binding.cbus.handler.CBusDaliHandler;
|
||||
import org.openhab.binding.cbus.handler.CBusLightHandler;
|
||||
import org.openhab.binding.cbus.handler.CBusNetworkHandler;
|
||||
import org.openhab.binding.cbus.handler.CBusTemperatureHandler;
|
||||
import org.openhab.binding.cbus.handler.CBusTriggerHandler;
|
||||
import org.openhab.binding.cbus.internal.discovery.CBusGroupDiscovery;
|
||||
import org.openhab.binding.cbus.internal.discovery.CBusNetworkDiscovery;
|
||||
import org.openhab.core.config.discovery.DiscoveryService;
|
||||
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.osgi.framework.ServiceRegistration;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
|
||||
/**
|
||||
* The {@link CBusHandlerFactory} is responsible for creating things and thing
|
||||
* handlers.
|
||||
*
|
||||
* @author Scott Linton - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.cbus")
|
||||
public class CBusHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
private @Nullable ServiceRegistration<?> cbusCGateHandlerServiceReg = null;
|
||||
private @Nullable ServiceRegistration<?> cbusNetworkHandlerServiceReg = null;
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return CBusBindingConstants.SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
if (CBusBindingConstants.BRIDGE_TYPE_CGATE.equals(thingTypeUID)) {
|
||||
CBusCGateHandler handler = new CBusCGateHandler((Bridge) thing);
|
||||
registerDeviceDiscoveryService(handler);
|
||||
return handler;
|
||||
}
|
||||
if (CBusBindingConstants.BRIDGE_TYPE_NETWORK.equals(thingTypeUID)) {
|
||||
CBusNetworkHandler handler = new CBusNetworkHandler((Bridge) thing);
|
||||
registerDeviceDiscoveryService(handler);
|
||||
return handler;
|
||||
}
|
||||
if (CBusBindingConstants.THING_TYPE_LIGHT.equals(thingTypeUID)) {
|
||||
return new CBusLightHandler(thing);
|
||||
}
|
||||
if (CBusBindingConstants.THING_TYPE_TEMPERATURE.equals(thingTypeUID)) {
|
||||
return new CBusTemperatureHandler(thing);
|
||||
}
|
||||
if (CBusBindingConstants.THING_TYPE_TRIGGER.equals(thingTypeUID)) {
|
||||
return new CBusTriggerHandler(thing);
|
||||
}
|
||||
if (CBusBindingConstants.THING_TYPE_DALI.equals(thingTypeUID)) {
|
||||
return new CBusDaliHandler(thing);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeHandler(ThingHandler thingHandler) {
|
||||
if (thingHandler instanceof CBusCGateHandler) {
|
||||
ServiceRegistration<?> serviceReg = this.cbusCGateHandlerServiceReg;
|
||||
if (serviceReg != null) {
|
||||
serviceReg.unregister();
|
||||
}
|
||||
} else if (thingHandler instanceof CBusNetworkHandler) {
|
||||
ServiceRegistration<?> serviceReg = this.cbusNetworkHandlerServiceReg;
|
||||
if (serviceReg != null) {
|
||||
serviceReg.unregister();
|
||||
}
|
||||
}
|
||||
super.removeHandler(thingHandler);
|
||||
}
|
||||
|
||||
private void registerDeviceDiscoveryService(CBusCGateHandler cbusCgateHandler) {
|
||||
CBusNetworkDiscovery discoveryService = new CBusNetworkDiscovery(cbusCgateHandler);
|
||||
cbusCGateHandlerServiceReg = super.bundleContext.registerService(DiscoveryService.class.getName(),
|
||||
discoveryService, new Hashtable<String, Object>());
|
||||
}
|
||||
|
||||
private void registerDeviceDiscoveryService(CBusNetworkHandler cbusNetworkHandler) {
|
||||
CBusGroupDiscovery discoveryService = new CBusGroupDiscovery(cbusNetworkHandler);
|
||||
cbusNetworkHandlerServiceReg = bundleContext.registerService(DiscoveryService.class.getName(), discoveryService,
|
||||
new Hashtable<String, Object>());
|
||||
}
|
||||
}
|
||||
@@ -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.cbus.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Configuration class for {@link CBusNetworkConfiguration}.
|
||||
*
|
||||
* @author John Harvey - Initial contribution
|
||||
*/
|
||||
|
||||
@NonNullByDefault
|
||||
public class CBusNetworkConfiguration {
|
||||
|
||||
public int id;
|
||||
public String project = "";
|
||||
public int syncInterval;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[id=%d, project=%s, syncInterval=%d]", id, project, syncInterval);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* 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.cbus.internal;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.common.ThreadPoolManager;
|
||||
|
||||
import com.daveoxley.cbus.CGateThreadPool;
|
||||
import com.daveoxley.cbus.CGateThreadPoolExecutor;
|
||||
|
||||
/**
|
||||
* The {@link CBusThreadPool} is responsible for executing jobs from a threadpool
|
||||
*
|
||||
* @author John Harvey - Initial contribution
|
||||
*/
|
||||
|
||||
@NonNullByDefault
|
||||
public class CBusThreadPool extends CGateThreadPool {
|
||||
|
||||
private final Map<String, @Nullable CGateThreadPoolExecutor> executorMap = new HashMap<>();
|
||||
|
||||
@Override
|
||||
protected synchronized CGateThreadPoolExecutor CreateExecutor(@Nullable String name) {
|
||||
if (name == null || name.isEmpty()) {
|
||||
name = "_default";
|
||||
}
|
||||
@Nullable
|
||||
CGateThreadPoolExecutor executor = executorMap.get(name);
|
||||
if (executor != null) {
|
||||
return executor;
|
||||
}
|
||||
CGateThreadPoolExecutor newExecutor = new CBusThreadPoolExecutor(name);
|
||||
executorMap.put(name, newExecutor);
|
||||
return newExecutor;
|
||||
}
|
||||
|
||||
@NonNullByDefault
|
||||
public class CBusThreadPoolExecutor extends CGateThreadPoolExecutor {
|
||||
private final ThreadPoolExecutor threadPool;
|
||||
|
||||
public CBusThreadPoolExecutor(@Nullable String poolName) {
|
||||
threadPool = (ThreadPoolExecutor) ThreadPoolManager.getPool("binding.cbus-" + poolName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(@Nullable Runnable runnable) {
|
||||
if (runnable != null) {
|
||||
threadPool.execute(runnable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* 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.cbus.internal.discovery;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.cbus.CBusBindingConstants;
|
||||
import org.openhab.binding.cbus.handler.CBusNetworkHandler;
|
||||
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||
import org.openhab.core.config.discovery.DiscoveryResult;
|
||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.daveoxley.cbus.Application;
|
||||
import com.daveoxley.cbus.CGateException;
|
||||
import com.daveoxley.cbus.Group;
|
||||
import com.daveoxley.cbus.Network;
|
||||
|
||||
/**
|
||||
* The {@link CBusGroupDiscovery} class is used to discover CBus
|
||||
* groups that are in the CBus Network
|
||||
*
|
||||
* @author Scott Linton - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class CBusGroupDiscovery extends AbstractDiscoveryService {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CBusGroupDiscovery.class);
|
||||
|
||||
private final CBusNetworkHandler cbusNetworkHandler;
|
||||
|
||||
public CBusGroupDiscovery(CBusNetworkHandler cbusNetworkHandler) {
|
||||
super(CBusBindingConstants.SUPPORTED_THING_TYPES_UIDS, 30, false);
|
||||
this.cbusNetworkHandler = cbusNetworkHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void startScan() {
|
||||
if (cbusNetworkHandler.getThing().getStatus().equals(ThingStatus.ONLINE)) {
|
||||
ThingUID bridgeUid = cbusNetworkHandler.getThing().getBridgeUID();
|
||||
if (bridgeUid == null) {
|
||||
scanFinished();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Map<Integer, ThingTypeUID> applications = new HashMap<Integer, ThingTypeUID>();
|
||||
applications.put(CBusBindingConstants.CBUS_APPLICATION_LIGHTING, CBusBindingConstants.THING_TYPE_LIGHT);
|
||||
applications.put(CBusBindingConstants.CBUS_APPLICATION_DALI, CBusBindingConstants.THING_TYPE_DALI);
|
||||
applications.put(CBusBindingConstants.CBUS_APPLICATION_TEMPERATURE,
|
||||
CBusBindingConstants.THING_TYPE_TEMPERATURE);
|
||||
applications.put(CBusBindingConstants.CBUS_APPLICATION_TRIGGER,
|
||||
CBusBindingConstants.THING_TYPE_TRIGGER);
|
||||
|
||||
Network network = cbusNetworkHandler.getNetwork();
|
||||
if (network == null) {
|
||||
scanFinished();
|
||||
return;
|
||||
}
|
||||
for (Map.Entry<Integer, ThingTypeUID> applicationItem : applications.entrySet()) {
|
||||
Application application = network.getApplication(applicationItem.getKey());
|
||||
if (application == null) {
|
||||
continue;
|
||||
}
|
||||
ArrayList<Group> groups = application.getGroups(false);
|
||||
for (Group group : groups) {
|
||||
logger.debug("Found group: {} {} {}", application.getName(), group.getGroupID(),
|
||||
group.getName());
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
properties.put(CBusBindingConstants.PROPERTY_APPLICATION_ID,
|
||||
Integer.toString(applicationItem.getKey()));
|
||||
properties.put(CBusBindingConstants.CONFIG_GROUP_ID, Integer.toString(group.getGroupID()));
|
||||
properties.put(CBusBindingConstants.PROPERTY_GROUP_NAME, group.getName());
|
||||
properties.put(CBusBindingConstants.PROPERTY_NETWORK_ID,
|
||||
Integer.toString(network.getNetworkID()));
|
||||
|
||||
ThingUID uid = new ThingUID(applicationItem.getValue(), Integer.toString(group.getGroupID()),
|
||||
bridgeUid.getId(), cbusNetworkHandler.getThing().getUID().getId());
|
||||
DiscoveryResult result = DiscoveryResultBuilder.create(uid).withProperties(properties)
|
||||
.withLabel("CBUS " + group.getName() + "(" + group.getGroupID() + ")")
|
||||
.withBridge(cbusNetworkHandler.getThing().getUID()).build();
|
||||
thingDiscovered(result);
|
||||
}
|
||||
}
|
||||
} catch (CGateException e) {
|
||||
logger.debug("Failed to discover groups", e);
|
||||
}
|
||||
}
|
||||
scanFinished();
|
||||
}
|
||||
|
||||
private synchronized void scanFinished() {
|
||||
stopScan();// this notifies the scan listener that the scan is finished
|
||||
abortScan();// this clears the scheduled call to stopScan
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* 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.cbus.internal.discovery;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.cbus.CBusBindingConstants;
|
||||
import org.openhab.binding.cbus.handler.CBusCGateHandler;
|
||||
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||
import org.openhab.core.config.discovery.DiscoveryResult;
|
||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.daveoxley.cbus.CGateException;
|
||||
import com.daveoxley.cbus.Network;
|
||||
|
||||
/**
|
||||
* The {@link CBusNetworkDiscovery} class is used to discover CBus
|
||||
* networks that are in the CBus Project
|
||||
*
|
||||
* @author Scott Linton - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class CBusNetworkDiscovery extends AbstractDiscoveryService {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CBusNetworkDiscovery.class);
|
||||
|
||||
private final CBusCGateHandler cBusCGateHandler;
|
||||
|
||||
public CBusNetworkDiscovery(CBusCGateHandler cBusCGateHandler) {
|
||||
super(CBusBindingConstants.NETWORK_DISCOVERY_THING_TYPES_UIDS, 60, false);
|
||||
this.cBusCGateHandler = cBusCGateHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startScan() {
|
||||
if (cBusCGateHandler.getThing().getStatus().equals(ThingStatus.ONLINE)) {
|
||||
try {
|
||||
ArrayList<Network> networks = Network.listAll(cBusCGateHandler.getCGateSession(), false);
|
||||
for (Network network : networks) {
|
||||
logger.debug("Found Network: {} {}", network.getNetworkID(), network.getName());
|
||||
Map<String, Object> properties = new HashMap<>(3);
|
||||
properties.put(CBusBindingConstants.CONFIG_NETWORK_ID, network.getNetworkID());
|
||||
properties.put(CBusBindingConstants.PROPERTY_NETWORK_NAME, network.getName());
|
||||
properties.put(CBusBindingConstants.CONFIG_NETWORK_PROJECT, network.getProjectName());
|
||||
ThingUID uid = new ThingUID(CBusBindingConstants.BRIDGE_TYPE_NETWORK,
|
||||
network.getProjectName().toLowerCase().replace(" ", "_") + network.getNetworkID(),
|
||||
cBusCGateHandler.getThing().getUID().getId());
|
||||
DiscoveryResult result = DiscoveryResultBuilder.create(uid).withProperties(properties)
|
||||
.withLabel(
|
||||
network.getProjectName() + "/" + network.getNetworkID() + " - " + network.getName())
|
||||
.withBridge(cBusCGateHandler.getThing().getUID()).build();
|
||||
thingDiscovered(result);
|
||||
}
|
||||
} catch (CGateException e) {
|
||||
logger.warn("Failed to discover networks", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void stopScan() {
|
||||
super.stopScan();
|
||||
removeOlderResults(getTimestampOfLastScan());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<binding:binding id="cbus" 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>C-Bus Binding</name>
|
||||
<description>Clipsal C-Bus Binding</description>
|
||||
<author>Scott Linton</author>
|
||||
|
||||
</binding:binding>
|
||||
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="cbus"
|
||||
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">
|
||||
|
||||
<bridge-type id="cgate">
|
||||
<label>CGate Connection</label>
|
||||
<description>CGate Connection to connect to physical C-Bus Networks</description>
|
||||
|
||||
<config-description>
|
||||
<parameter name="ipAddress" type="text" required="true">
|
||||
<context>network-address</context>
|
||||
<label>CGate Server IP</label>
|
||||
<description>The IP address of the CGate Server.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</bridge-type>
|
||||
|
||||
<bridge-type id="network">
|
||||
<label>C-Bus Network</label>
|
||||
<description>C-Bus Network bridge</description>
|
||||
|
||||
<config-description>
|
||||
<parameter name="id" type="integer" required="true">
|
||||
<label>C-Bus Network ID</label>
|
||||
<description>Network number of C-Bus Network.</description>
|
||||
</parameter>
|
||||
|
||||
<parameter name="project" type="text" required="true">
|
||||
<label>C-Bus Project Name</label>
|
||||
<description>Project name that contains the network.</description>
|
||||
</parameter>
|
||||
|
||||
<parameter name="syncInterval" type="integer" required="false" min="120" unit="s">
|
||||
<label>Network Sync Interval</label>
|
||||
<description>The interval in seconds between fetching current group states from the network.</description>
|
||||
<default>600</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</bridge-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,142 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="cbus"
|
||||
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-type id="light">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="network"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>Lighting Group</label>
|
||||
<description>Lighting Group</description>
|
||||
|
||||
<channels>
|
||||
<channel id="state" typeId="light-channel"/>
|
||||
<channel id="level" typeId="level-channel"/>
|
||||
</channels>
|
||||
<properties>
|
||||
<property name="CBUS Network Id"/>
|
||||
<property name="CBUS Application Id"/>
|
||||
<property name="CBUS Group Name"/>
|
||||
</properties>
|
||||
<config-description>
|
||||
<parameter name="group" type="integer" required="true">
|
||||
<label>CBus Group ID</label>
|
||||
<description>Group number of this Thing on the C-Bus Network.</description>
|
||||
<default>-1</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="temperature">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="network"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>Temperature Group</label>
|
||||
<description>Temperature Group</description>
|
||||
|
||||
<channels>
|
||||
<channel id="temp" typeId="temp-channel"/>
|
||||
</channels>
|
||||
<properties>
|
||||
<property name="CBUS Network Id"/>
|
||||
<property name="CBUS Application Id"/>
|
||||
<property name="CBUS Group Name"/>
|
||||
</properties>
|
||||
<config-description>
|
||||
<parameter name="group" type="integer" required="true">
|
||||
<label>CBus Group ID</label>
|
||||
<description>Group number of this Thing on the C-Bus Network.</description>
|
||||
<default>-1</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="trigger">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="network"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>Trigger Group</label>
|
||||
<description>Trigger Group</description>
|
||||
|
||||
<channels>
|
||||
<channel id="value" typeId="trigger-channel"/>
|
||||
</channels>
|
||||
<properties>
|
||||
<property name="CBUS Network Id"/>
|
||||
<property name="CBUS Application Id"/>
|
||||
<property name="CBUS Group Name"/>
|
||||
</properties>
|
||||
<config-description>
|
||||
<parameter name="group" type="integer" required="true">
|
||||
<label>CBus Group ID</label>
|
||||
<description>Group number of this Thing on the C-Bus Network.</description>
|
||||
<default>-1</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="dali">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="network"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>DALI Group</label>
|
||||
<description>DALI Group</description>
|
||||
|
||||
<channels>
|
||||
<channel id="level" typeId="dali-channel"/>
|
||||
</channels>
|
||||
<properties>
|
||||
<property name="CBUS Network Id"/>
|
||||
<property name="CBUS Application Id"/>
|
||||
<property name="CBUS Group Name"/>
|
||||
</properties>
|
||||
<config-description>
|
||||
<parameter name="group" type="integer" required="true">
|
||||
<label>CBus Group ID</label>
|
||||
<description>Group number of this Thing on the C-Bus Network.</description>
|
||||
<default>-1</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<!-- Lighting Group Channel Type -->
|
||||
<channel-type id="light-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Light Channel</label>
|
||||
<description>Group channel for CBus on/off lighting groups</description>
|
||||
<category>Light</category>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="level-channel">
|
||||
<item-type>Dimmer</item-type>
|
||||
<label>Level Channel</label>
|
||||
<description>Group channel for CBus variable value lighting groups</description>
|
||||
<category>DimmableLight</category>
|
||||
</channel-type>
|
||||
|
||||
<!-- Temperature Group Channel Type -->
|
||||
<channel-type id="temp-channel">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Temperature</label>
|
||||
<description>Group channel for CBus temperature groups</description>
|
||||
<category>Temperature</category>
|
||||
<state pattern="%.1f %unit%" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<!-- Trigger Group Channel Type -->
|
||||
<channel-type id="trigger-channel">
|
||||
<item-type>Number</item-type>
|
||||
<label>Trigger Channel</label>
|
||||
<description>Group channel for CBus trigger groups</description>
|
||||
</channel-type>
|
||||
|
||||
<!-- DALI Group Channel Type -->
|
||||
<channel-type id="dali-channel">
|
||||
<item-type>Dimmer</item-type>
|
||||
<label>DALI Channel</label>
|
||||
<description>Group channel for CBus DALI groups</description>
|
||||
</channel-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
Reference in New Issue
Block a user