,.... |
+| currentLevel | 0 | No | Inverts any device values. |
-### Rain Sensor
+## Supported Channels for Thing Types
-Unfortunately Velux has decided to closely integrate the rain sensor into the window device. The rain sensor is therefore not displayed in the device list. On the other hand, the 'limitMinimum' channel of a roof window now provides information about rainy weather: if it is set internally by the Velux control unit to a value other than zero, it rains.
+### Channels for "bridge" Things
-### Virtual shutter
+The supported Channels and their associated channel types are shown below.
-As the bridge with firmware version one does not support a real rollershutter interaction, this binding provides a virtual rollershutter consisting of different scenes which set a specific shutter level. Therefore the item definition contains multiple pairs of rollershutter levels each followed by a scene name, which leads to this setting.
+| Channel | Data Type | Description |
+|-------------|-----------|---------------------------------------------------------------------------------|
+| status | String | Description of current Bridge State. |
+| reload | Switch | Command to force reload of the bridge information. |
+| downtime | Number | Time interval (sec) between last successful and most recent device interaction. |
+| doDetection | Switch | Command to activate bridge detection mode. |
+### Channels for "window", "rollershutter" Things
-### Items
+The supported Channels and their associated channel types are shown below.
-[Sample items file for textual configuration](doc/conf/items/velux.items)
+| Channel | Data Type | Description |
+|--------------|---------------|-------------------------------------------------|
+| position | Rollershutter | Actual position of the window or device. |
+| limitMinimum | Rollershutter | Minimum limit position of the window or device. |
+| limitMaximum | Rollershutter | Maximum limit position of the window or device. |
-### Sitemap
+### Channels for "actuator" Things
-[Sample sitemaps file for textual configuration](doc/conf/sitemaps/velux.sitemap)
+The supported Channels and their associated channel types are shown below.
-### Rules
+| Channel | Data Type | Description |
+|--------------|---------------|-------------------------------------------------|
+| position | Rollershutter | Actual position of the window or device. |
+| state | Switch | Device control (ON, OFF). |
+| limitMinimum | Rollershutter | Minimum limit position of the window or device. |
+| limitMaximum | Rollershutter | Maximum limit position of the window or device. |
-[Sample rules file for textual configuration](doc/conf/rules/velux.rules)
+### Channels for "scene" Things
+
+The supported Channels and their associated channel types are shown below.
+
+| Channel | Data Type | Description |
+|------------|-----------|----------------------------------------------------------------|
+| action | Switch | Activates the scene (moves devices to their preset positions). |
+| silentMode | Switch | Enables silent mode. |
+
+### Channels for "vshutter" Things
+
+The supported Channel and its associated channel type is shown below.
+
+| Channel | Data Type | Description |
+|--------------|---------------|-----------------------------------------|
+| position | Rollershutter | Position of the virtual roller shutter. |
+
+### Channels for "information" Thing
+
+The supported Channel and its associated channel type is shown below.
+
+| Channel | Data Type | Description |
+|-------------|-----------|--------------------------------|
+| information | String | Information about the binding. |
+
+## Rain Sensor
+
+Unfortunately Velux has decided to closely integrate the rain sensor into the window device.
+The rain sensor is therefore not displayed in the device list.
+On the other hand, the 'limitMinimum' channel of a roof window provides information about rainy weather:
+If it is set internally by the Velux control unit to a value other than zero, it rains. (Joke!!)
+
+## Properties of the "bridge" Thing
+
+The bridge Thing provides the following properties.
+
+| Property | Description |
+|-------------------|-----------------------------------------------------------------|
+| check | Result of the check of current item configuration |
+| connectionAttempt | Date-Time of last connection attampt |
+| connectionSuccess | Date-Time of last successful connection attampt |
+| defaultGW | IP address of the Default Gateway of the Bridge |
+| DHCP | Flag whether automatic IP configuration is enabled |
+| firmware | Software version of the Bridge |
+| ipAddress | IP address of the Bridge |
+| products | List of all recognized products |
+| scenes | List of all defined scenes |
+| subnetMask | IP subnetmask of the Bridge |
+| vendor | Vendow name |
+| WLANSSID | Name of the wireless network (not suported any more) |
+| WLANPassword | WLAN Authentication Password (not suported any more) |
+
+## Full Example
### Things
-[Sample things file for textual configuration](doc/conf/things/velux.things)
+```
+Bridge velux:klf200:g24 "Velux KLF200 Hub" @ "Under Stairs" [ipAddress="192.168.1.xxx", password="secret"] {
+ Thing window w56-36-13-5A-11-2A-05-70 "Bathroom Roof Window" @ "Bathroom" [serial="56:36:13:5A:11:2A:05:70", inverted=true]
+}
+```
-## More automation samples
+[=> download sample things file for textual configuration](./doc/conf/things/velux.things)
-At this point some interesting automation rules are included to demonstrate the power of this gateway to the io-homecontrol world.
+### Items
+```
+Rollershutter Bathroom_Roof_Window_Position "Bathroom Roof Window Position [%.0f %%]" {channel="velux:window:g24:w56-36-13-5A-11-2A-05-70:position"}
+```
-### Closing windows after a period of time
+[=> download sample items file for textual configuration](./doc/conf/items/velux.items)
+### Sitemap
+
+```
+Frame label="Velux Windows" {
+ Slider item=Bathroom_Roof_Window_Position
+}
+```
+
+[=> download sample sitemaps file for textual configuration](./doc/conf/sitemaps/velux.sitemap)
+
+### Rules
+
+**Rule for closing windows after a period of time**:
Especially in the colder months, it is advisable to close the window after adequate ventilation. Therefore, automatic closing after one minute is good to save on heating costs.
However, to allow the case of intentional prolonged opening, an automatic closure is made only with the window fully open.
-```
-/*
- * Start of imports
- */
-
-import org.openhab.core.library.types.*
-
-/*
- * Start of rules
- */
-
+```java
rule "V_WINDOW_changed"
when
Item V_WINDOW changed
then
logInfo("rules.V_WINDOW", "V_WINDOW_changes() called.")
- //
// Get the sensor value
- //
val Number windowState = V_WINDOW.state as DecimalType
logWarn("rules.V_WINDOW", "Window state is "+windowState+".")
if (windowState < 80) {
if (windowState == 0) {
logWarn("rules.V_WINDOW", "V-WINDOW changed to fully open.")
-
var int interval = 1
-
- createTimer(now.plusMinutes(interval)) [|
- logWarn("rules.V_WINDOW:event", "event-V_WINDOW(): setting V-WINDOW to 100.")
- sendCommand(V_WINDOW,100)
- V_WINDOW.postUpdate(100)
+ createTimer(now.plusMinutes(interval)) [ |
+ logWarn("rules.V_WINDOW:event", "event-V_WINDOW(): setting V-WINDOW to 100.")
+ sendCommand(V_WINDOW,100)
+ V_WINDOW.postUpdate(100)
logWarn("rules.V_WINDOW:event", "event-V_WINDOW done.")
]
} else {
logWarn("rules.V_WINDOW", "V-WINDOW changed to partially open.")
}
}
- //
// Check type of item
- //
logDebug("rules.V_WINDOW", "V_WINDOW_changes finished.")
end
-
-/*
- * end-of-rules/V_WINDOW.rules
- */
```
+[=> download sample rules file for textual configuration](./doc/conf/rules/velux.rules)
+
## Debugging
For those who are interested in more detailed insight of the processing of this binding, a deeper look can be achieved by increased loglevel.
@@ -352,46 +350,46 @@ However if you have set the configuration parameter isProtocolTraceEnabled to tr
[INFO ] [internal.bridge.slip.SlipVeluxBridge] - Received answer GW_GET_NODE_INFORMATION_CFM.
[INFO ] [internal.bridge.slip.SlipVeluxBridge] - Received answer GW_GET_NODE_INFORMATION_NTF.
[INFO ] [internal.bridge.slip.SlipVeluxBridge] - Sending command GW_GET_LIMITATION_STATUS_REQ.
-...
```
-
## Supported/Tested Firmware Revisions
-The Velux Bridge in API version one (firmware version 0.1.1.*) allows activating a set of predefined actions, so called scenes. Therefore beside the bridge, only one main thing exists, the scene element. The next-generation firmware version two is not backward compatible, and does not provide a public web frontend, but version two does provide full access to any IO-Home compatible devices not limited to Velux and includes many different features.
+The Velux Bridge in API version one (firmware version 0.1.1.*) allows activating a set of predefined actions, so called scenes.
+Therefore beside the bridge, only one main thing exists, the scene element.
+
+The next-generation firmware version two is not backward compatible, and does not provide a public web frontend, but version two does provide full access to any IO-Home compatible devices not limited to Velux and includes many different features.
| Firmware revision | Release date | Description |
|:-----------------:|:------------:|-------------------------------------------------------------------------|
| 0.1.1.0.41.0 | 2016-06-01 | Default factory shipping revision. |
| 0.1.1.0.42.0 | 2017-07-01 | Public Web Frontend w/ JSON-API. |
| 0.1.1.0.44.0 | 2017-12-14 | Public Web Frontend w/ JSON-API. |
-| 2.0.0.71 | 2018-09-27 | Public SLIP-API w/ private-only WLAN-based Web Frontend w/ JSON-API. |
+| 0.2.0.0.71.0 | 2018-09-27 | Public SLIP-API w/ private-only WLAN-based Web Frontend w/ JSON-API. |
Notes:
- Velux bridges cannot be returned to version one of the firmware after being upgraded to version two.
- Firmware updates are currently provided at [Velux download area](https://updates2.velux.com/).
-
## Is it possible to run the both communication methods in parallel?
For environments with the firmware version 0.1.* on the gateway, the interaction with the bridge is limited to the HTTP/JSON based communication, of course. On the other hand, after upgrading the gateway firmware to version 2, it is possible to run the binding either using HTTP/JSON if there is a permanent connectivity towards the WLAN interface of the KLF200 or using SLIP towards the LAN interface of the gateway. For example the Raspberry PI can directly be connected via WLAN to the Velux gateway and providing the other services via the LAN interface (but not vice versa).
-
## Known Limitations
The communication based on HTTP/JSON is limited to one connection: If the binding is operational, you won't get access to the Web Frontend in parallel.
The SLIP communication is limited to two connections in parallel, i.e. two different openHAB bindings - or - one openHAB binding and another platform connection.
-Both interfacing methods, HTTP/JSON and SLIP, can be run in parallel. Therefore, on the one hand you can use the Web Frontend for manual control and on the other hand a binding can do all automatic jobs.
-
+Both interfacing methods, HTTP/JSON and SLIP, can be run in parallel.
+Therefore, on the one hand you can use the Web Frontend for manual control and on the other hand a binding can do all automatic jobs.
## Unknown Velux devices
-All known Velux devices can be handled by this binding. However, there might be some new ones which will be reported within the logfiles. Therefore, error messages like the one below should be reported to the maintainers so that the new Velux device type can be incorporated."
+All known Velux devices can be handled by this binding.
+However, there might be some new ones which will be reported within the logfiles.
+Therefore, error messages like the one below should be reported to the maintainers so that the new Velux device type can be incorporated.
```
[ERROR] [g.velux.things.VeluxProductReference] - PLEASE REPORT THIS TO MAINTAINER: VeluxProductReference(3) has found an unregistered ProductTypeId.
```
-
diff --git a/bundles/org.openhab.binding.velux/doc/veluxlogo.jpg b/bundles/org.openhab.binding.velux/doc/veluxlogo.jpg
new file mode 100644
index 000000000..5a81b081e
Binary files /dev/null and b/bundles/org.openhab.binding.velux/doc/veluxlogo.jpg differ
diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBindingConstants.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBindingConstants.java
index 4aa8eda02..c647c8a8d 100644
--- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBindingConstants.java
+++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBindingConstants.java
@@ -145,4 +145,7 @@ public class VeluxBindingConstants {
// Critical issues to be reported will use the following message
public static final String LOGGING_CONTACT = "Please report to maintainer: ";
+
+ public static final String UNKNOWN_THING_TYPE_ID = "FAILED";
+ public static final String UNKNOWN_IP_ADDRESS = "xxx.xxx.xxx.xxx";
}
diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JClogin.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JClogin.java
index 862f32188..3e8880dc0 100644
--- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JClogin.java
+++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JClogin.java
@@ -39,8 +39,8 @@ class JClogin extends Login implements JsonBridgeCommunicationProtocol {
private static final String URL = "/api/v1/auth";
private static final String DESCRIPTION = "authenticate / login";
- private static Request request = new Request();
- private static Response response = new Response();
+ private Request request = new Request();
+ private Response response = new Response();
/*
* Message Objects
diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JsonBridgeAPI.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JsonBridgeAPI.java
index f8e377759..99ace70ce 100644
--- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JsonBridgeAPI.java
+++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JsonBridgeAPI.java
@@ -83,19 +83,19 @@ import org.slf4j.LoggerFactory;
class JsonBridgeAPI implements BridgeAPI {
private final Logger logger = LoggerFactory.getLogger(JsonBridgeAPI.class);
- private static final GetDeviceStatus GETDEVICESTATUS = new JCgetDeviceStatus();
- private static final GetFirmware GETFIRMWARE = new JCgetFirmware();
- private static final GetLANConfig GETLANCONFIG = new JCgetLANConfig();
- private static final GetProducts GETPRODUCTS = new JCgetProducts();
- private static final GetScenes GETSCENES = new JCgetScenes();
- private static final GetWLANConfig GETWLANCONFIG = new JCgetWLANConfig();
- private static final Login LOGIN = new JClogin();
- private static final Logout LOGOUT = new JClogout();
- private static final RunProductDiscovery RUNPRODUCTDISCOVERY = new JCrunProductDiscovery();
- private static final RunProductIdentification RUNPRODUCTIDENTIFICATION = new JCrunProductIdentification();
- private static final RunProductSearch RUNPRODUCTSEARCH = new JCrunProductSearch();
- private static final RunScene RUNSCENE = new JCrunScene();
- private static final SetSceneVelocity SETSCENEVELOCITY = new JCsetSceneVelocity();
+ private final GetDeviceStatus jsonGetDeviceStatus = new JCgetDeviceStatus();
+ private final GetFirmware jsonGetFirmware = new JCgetFirmware();
+ private final GetLANConfig jsonGetLanConfig = new JCgetLANConfig();
+ private final GetProducts jsonGetProducts = new JCgetProducts();
+ private final GetScenes jsonGetScenes = new JCgetScenes();
+ private final GetWLANConfig jsonGetWLanConfig = new JCgetWLANConfig();
+ private final Login jsonLogin = new JClogin();
+ private final Logout jsonLogout = new JClogout();
+ private final RunProductDiscovery jsonRunProductDiscovery = new JCrunProductDiscovery();
+ private final RunProductIdentification jsonRunProductIdentification = new JCrunProductIdentification();
+ private final RunProductSearch jsonRunProductSearch = new JCrunProductSearch();
+ private final RunScene jsonRunScene = new JCrunScene();
+ private final SetSceneVelocity jsonSetSceneVelocity = new JCsetSceneVelocity();
/**
* Constructor.
@@ -113,12 +113,12 @@ class JsonBridgeAPI implements BridgeAPI {
@Override
public GetDeviceStatus getDeviceStatus() {
- return GETDEVICESTATUS;
+ return jsonGetDeviceStatus;
}
@Override
public GetFirmware getFirmware() {
- return GETFIRMWARE;
+ return jsonGetFirmware;
}
@Override
@@ -128,7 +128,7 @@ class JsonBridgeAPI implements BridgeAPI {
@Override
public GetLANConfig getLANConfig() {
- return GETLANCONFIG;
+ return jsonGetLanConfig;
}
@Override
@@ -148,27 +148,27 @@ class JsonBridgeAPI implements BridgeAPI {
@Override
public GetProducts getProducts() {
- return GETPRODUCTS;
+ return jsonGetProducts;
}
@Override
public GetScenes getScenes() {
- return GETSCENES;
+ return jsonGetScenes;
}
@Override
public GetWLANConfig getWLANConfig() {
- return GETWLANCONFIG;
+ return jsonGetWLanConfig;
}
@Override
public Login login() {
- return LOGIN;
+ return jsonLogin;
}
@Override
public Logout logout() {
- return LOGOUT;
+ return jsonLogout;
}
@Override
@@ -178,22 +178,22 @@ class JsonBridgeAPI implements BridgeAPI {
@Override
public RunProductDiscovery runProductDiscovery() {
- return RUNPRODUCTDISCOVERY;
+ return jsonRunProductDiscovery;
}
@Override
public RunProductIdentification runProductIdentification() {
- return RUNPRODUCTIDENTIFICATION;
+ return jsonRunProductIdentification;
}
@Override
public RunProductSearch runProductSearch() {
- return RUNPRODUCTSEARCH;
+ return jsonRunProductSearch;
}
@Override
public RunScene runScene() {
- return RUNSCENE;
+ return jsonRunScene;
}
@Override
@@ -203,6 +203,6 @@ class JsonBridgeAPI implements BridgeAPI {
@Override
public SetSceneVelocity setSceneVelocity() {
- return SETSCENEVELOCITY;
+ return jsonSetSceneVelocity;
}
}
diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SlipBridgeAPI.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SlipBridgeAPI.java
index 5d9084d39..357ee8cc8 100644
--- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SlipBridgeAPI.java
+++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SlipBridgeAPI.java
@@ -83,25 +83,25 @@ import org.slf4j.LoggerFactory;
class SlipBridgeAPI implements BridgeAPI {
private final Logger logger = LoggerFactory.getLogger(SlipBridgeAPI.class);
- private static final GetDeviceStatus GETDEVICESTATUS = new SCgetDeviceStatus();
- private static final GetFirmware GETFIRMWARE = new SCgetFirmware();
- private static final GetHouseStatus GETHOUSESTATUS = new SCgetHouseStatus();
- private static final GetLANConfig GETLANCONFIG = new SCgetLANConfig();
- private static final GetProduct GETPRODUCT = new SCgetProduct();
- private static final GetProductLimitation GETPRODUCTLIMITATION = new SCgetLimitation();
- private static final GetProducts GETPRODUCTS = new SCgetProducts();
- private static final GetScenes GETSCENES = new SCgetScenes();
- private static final GetWLANConfig GETWLANCONFIG = new SCgetWLANConfig();
- private static final Login LOGIN = new SClogin();
- private static final Logout LOGOUT = new SClogout();
- private static final RunProductCommand RUNPRODUCTCOMMAND = new SCrunProductCommand();
- private static final RunProductDiscovery RUNPRODUCTDISCOVERY = new SCrunProductDiscovery();
- private static final RunProductIdentification RUNPRODUCTIDENTIFICATION = new SCrunProductIdentification();
- private static final RunProductSearch RUNPRODUCTSEARCH = new SCrunProductSearch();
- private static final RunScene RUNSCENE = new SCrunScene();
- private static final SetHouseStatusMonitor SETHOUSESTATUSMONITOR = new SCsetHouseStatusMonitor();
- private static final SetProductLimitation SETPRODUCTLIMITATION = new SCsetLimitation();
- private static final SetSceneVelocity SETSCENEVELOCITY = new SCsetSceneVelocity();
+ private final GetDeviceStatus slipGetDeviceStatus = new SCgetDeviceStatus();
+ private final GetFirmware slipGetFirmware = new SCgetFirmware();
+ private final GetHouseStatus slipGetHouseStatus = new SCgetHouseStatus();
+ private final GetLANConfig slipGetLanConfig = new SCgetLANConfig();
+ private final GetProduct slipGetProduct = new SCgetProduct();
+ private final GetProductLimitation slipGetProductLimitation = new SCgetLimitation();
+ private final GetProducts slipGetProducts = new SCgetProducts();
+ private final GetScenes slipGetScenes = new SCgetScenes();
+ private final GetWLANConfig slipGetWLanConfig = new SCgetWLANConfig();
+ private final Login slipLogin = new SClogin();
+ private final Logout slipLogout = new SClogout();
+ private final RunProductCommand slipRunProductCommand = new SCrunProductCommand();
+ private final RunProductDiscovery slipRunProductDiscovery = new SCrunProductDiscovery();
+ private final RunProductIdentification slipRunProductIdentification = new SCrunProductIdentification();
+ private final RunProductSearch slipRunProductSearch = new SCrunProductSearch();
+ private final RunScene slipRunScene = new SCrunScene();
+ private final SetHouseStatusMonitor slipSetHouseMonitor = new SCsetHouseStatusMonitor();
+ private final SetProductLimitation slipSetProductLimitation = new SCsetLimitation();
+ private final SetSceneVelocity slipSetSceneVelocity = new SCsetSceneVelocity();
/**
* Constructor.
@@ -118,96 +118,96 @@ class SlipBridgeAPI implements BridgeAPI {
@Override
public GetDeviceStatus getDeviceStatus() {
- return GETDEVICESTATUS;
+ return slipGetDeviceStatus;
}
@Override
public GetFirmware getFirmware() {
- return GETFIRMWARE;
+ return slipGetFirmware;
}
@Override
public @Nullable GetHouseStatus getHouseStatus() {
- return GETHOUSESTATUS;
+ return slipGetHouseStatus;
}
@Override
public GetLANConfig getLANConfig() {
- return GETLANCONFIG;
+ return slipGetLanConfig;
}
@Override
public @Nullable GetProduct getProduct() {
- return GETPRODUCT;
+ return slipGetProduct;
}
@Override
public @Nullable GetProductLimitation getProductLimitation() {
- return GETPRODUCTLIMITATION;
+ return slipGetProductLimitation;
}
@Override
public @Nullable SetProductLimitation setProductLimitation() {
- return SETPRODUCTLIMITATION;
+ return slipSetProductLimitation;
}
@Override
public GetProducts getProducts() {
- return GETPRODUCTS;
+ return slipGetProducts;
}
@Override
public GetScenes getScenes() {
- return GETSCENES;
+ return slipGetScenes;
}
@Override
public GetWLANConfig getWLANConfig() {
- return GETWLANCONFIG;
+ return slipGetWLanConfig;
}
@Override
public Login login() {
- return LOGIN;
+ return slipLogin;
}
@Override
public Logout logout() {
- return LOGOUT;
+ return slipLogout;
}
@Override
public @Nullable RunProductCommand runProductCommand() {
- return RUNPRODUCTCOMMAND;
+ return slipRunProductCommand;
}
@Override
public RunProductDiscovery runProductDiscovery() {
- return RUNPRODUCTDISCOVERY;
+ return slipRunProductDiscovery;
}
@Override
public RunProductIdentification runProductIdentification() {
- return RUNPRODUCTIDENTIFICATION;
+ return slipRunProductIdentification;
}
@Override
public RunProductSearch runProductSearch() {
- return RUNPRODUCTSEARCH;
+ return slipRunProductSearch;
}
@Override
public RunScene runScene() {
- return RUNSCENE;
+ return slipRunScene;
}
@Override
public @Nullable SetHouseStatusMonitor setHouseStatusMonitor() {
- return SETHOUSESTATUSMONITOR;
+ return slipSetHouseMonitor;
}
@Override
public SetSceneVelocity setSceneVelocity() {
- return SETSCENEVELOCITY;
+ return slipSetSceneVelocity;
}
}
diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SlipVeluxBridge.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SlipVeluxBridge.java
index d7f737248..16f4c1f35 100644
--- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SlipVeluxBridge.java
+++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SlipVeluxBridge.java
@@ -193,7 +193,8 @@ public class SlipVeluxBridge extends VeluxBridge {
*/
private synchronized boolean bridgeDirectCommunicate(SlipBridgeCommunicationProtocol communication,
boolean useAuthentication) {
- logger.trace("bridgeDirectCommunicate({},{}authenticated) called.", communication.name(),
+ String host = this.bridgeInstance.veluxBridgeConfiguration().ipAddress;
+ logger.trace("bridgeDirectCommunicate({},{}authenticated) on {} called.", host, communication.name(),
useAuthentication ? "" : "un");
assert this.bridgeInstance.veluxBridgeConfiguration().protocol.contentEquals("slip");
@@ -213,15 +214,15 @@ public class SlipVeluxBridge extends VeluxBridge {
Threads.findDeadlocked();
}
- logger.debug("bridgeDirectCommunicate({},{}authenticated) initiated by {}.", commandString,
+ logger.debug("bridgeDirectCommunicate({},{}authenticated) on {} initiated by {}.", host, commandString,
useAuthentication ? "" : "un", Thread.currentThread());
boolean success = false;
communication: do {
if (communicationStartInMSecs + COMMUNICATION_TIMEOUT_MSECS < System.currentTimeMillis()) {
logger.warn(
- "{} bridgeDirectCommunicate({}): communication handshake failed (unexpected sequence of requests/responses).",
- VeluxBindingConstants.BINDING_VALUES_SEPARATOR, communication.name());
+ "{} bridgeDirectCommunicate({}) on {}: communication handshake failed (unexpected sequence of requests/responses).",
+ VeluxBindingConstants.BINDING_VALUES_SEPARATOR, communication.name(), host);
break;
}
@@ -234,67 +235,71 @@ public class SlipVeluxBridge extends VeluxBridge {
}
// Normal processing
- logger.trace("bridgeDirectCommunicate(): working on request {} with {} bytes of data.", commandString,
- data.length);
+ logger.trace("bridgeDirectCommunicate() on {}: working on request {} with {} bytes of data.", host,
+ commandString, data.length);
byte[] sendBytes = emptyPacket;
if (Command.get(command) == Command.GW_OPENHAB_RECEIVEONLY) {
logger.trace(
- "bridgeDirectCommunicate(): special command: determine whether there is any message waiting.");
+ "bridgeDirectCommunicate() on {}: special command: determine whether there is any message waiting.",
+ host);
logger.trace("bridgeDirectCommunicate(): check for a waiting message.");
if (!connection.isMessageAvailable()) {
- logger.trace("bridgeDirectCommunicate(): no message waiting, aborting.");
+ logger.trace("bridgeDirectCommunicate() on {}: no message waiting, aborting.", host);
break communication;
}
- logger.trace("bridgeDirectCommunicate(): there is a message waiting.");
+ logger.trace("bridgeDirectCommunicate() on {}: there is a message waiting.", host);
} else {
SlipEncoding t = new SlipEncoding(command, data);
if (!t.isValid()) {
- logger.warn("bridgeDirectCommunicate(): SlipEncoding() failed, aborting.");
+ logger.warn("bridgeDirectCommunicate() on {}: SlipEncoding() failed, aborting.", host);
break;
}
- logger.trace("bridgeDirectCommunicate(): transportEncoding={}.", t.toString());
+ logger.trace("bridgeDirectCommunicate() on {}: transportEncoding={}.", host, t.toString());
sendBytes = new SlipRFC1055().encode(t.toMessage());
}
do {
if (communicationStartInMSecs + COMMUNICATION_TIMEOUT_MSECS < System.currentTimeMillis()) {
- logger.warn("bridgeDirectCommunicate(): receive takes too long. Please report to maintainer.");
+ logger.warn("bridgeDirectCommunicate() on {}: receive takes too long. Please report to maintainer.",
+ host);
break communication;
}
byte[] receivedPacket;
try {
if (sendBytes.length > 0) {
- logger.trace("bridgeDirectCommunicate(): sending {} bytes.", sendBytes.length);
+ logger.trace("bridgeDirectCommunicate() on {}: sending {} bytes.", host, sendBytes.length);
if (isProtocolTraceEnabled) {
logger.info("Sending command {}.", commandString);
}
} else {
- logger.trace("bridgeDirectCommunicate(): initiating receive-only.");
+ logger.trace("bridgeDirectCommunicate() on {}: initiating receive-only.", host);
}
// (Optionally) Send and receive packet.
receivedPacket = connection.io(this.bridgeInstance, sendBytes);
// Once being sent, it should never be sent again
sendBytes = emptyPacket;
} catch (Exception e) {
- logger.warn("bridgeDirectCommunicate(): connection.io returns {}", e.getMessage());
+ logger.warn("bridgeDirectCommunicate() on {}: connection.io returns {}", host, e.getMessage());
break communication;
}
- logger.trace("bridgeDirectCommunicate(): received packet {}.", new Packet(receivedPacket).toString());
+ logger.trace("bridgeDirectCommunicate() on {}: received packet {}.", host,
+ new Packet(receivedPacket).toString());
byte[] response;
try {
response = new SlipRFC1055().decode(receivedPacket);
} catch (ParseException e) {
- logger.warn("bridgeDirectCommunicate(): method SlipRFC1055() raised a decoding error: {}.",
- e.getMessage());
+ logger.warn("bridgeDirectCommunicate() on {}: method SlipRFC1055() raised a decoding error: {}.",
+ host, e.getMessage());
break communication;
}
SlipEncoding tr = new SlipEncoding(response);
if (!tr.isValid()) {
- logger.warn("bridgeDirectCommunicate(): method SlipEncoding() raised a decoding error.");
+ logger.warn("bridgeDirectCommunicate() on {}: method SlipEncoding() raised a decoding error.",
+ host);
break communication;
}
short responseCommand = tr.getCommand();
byte[] responseData = tr.getData();
- logger.debug("bridgeDirectCommunicate(): working on response {} with {} bytes of data.",
+ logger.debug("bridgeDirectCommunicate() on {}: working on response {} with {} bytes of data.", host,
Command.get(responseCommand).toString(), responseData.length);
if (isProtocolTraceEnabled) {
logger.info("Received answer {}.", Command.get(responseCommand).toString());
@@ -302,63 +307,66 @@ public class SlipVeluxBridge extends VeluxBridge {
// Handle some common (unexpected) answers
switch (Command.get(responseCommand)) {
case GW_NODE_INFORMATION_CHANGED_NTF:
- logger.trace("bridgeDirectCommunicate(): received GW_NODE_INFORMATION_CHANGED_NTF.");
- logger.trace("bridgeDirectCommunicate(): continue with receiving.");
+ logger.trace("bridgeDirectCommunicate() on {}: received GW_NODE_INFORMATION_CHANGED_NTF.",
+ host);
+ logger.trace("bridgeDirectCommunicate() on {}: continue with receiving.", host);
continue;
case GW_NODE_STATE_POSITION_CHANGED_NTF:
logger.trace(
- "bridgeDirectCommunicate(): received GW_NODE_STATE_POSITION_CHANGED_NTF, special processing of this packet.");
+ "bridgeDirectCommunicate() on {}: received GW_NODE_STATE_POSITION_CHANGED_NTF, special processing of this packet.",
+ host);
SCgetHouseStatus receiver = new SCgetHouseStatus();
receiver.setResponse(responseCommand, responseData, isSequentialEnforced);
if (receiver.isCommunicationSuccessful()) {
- logger.trace("bridgeDirectCommunicate(): existingProducts().update() called.");
+ logger.trace("bridgeDirectCommunicate() on {}: existingProducts().update() called.", host);
bridgeInstance.existingProducts().update(new ProductBridgeIndex(receiver.getNtfNodeID()),
receiver.getNtfState(), receiver.getNtfCurrentPosition(), receiver.getNtfTarget());
}
- logger.trace("bridgeDirectCommunicate(): continue with receiving.");
+ logger.trace("bridgeDirectCommunicate() on {}: continue with receiving.", host);
continue;
case GW_ERROR_NTF:
switch (responseData[0]) {
case 0:
logger.warn(
- "bridgeDirectCommunicate(): received GW_ERROR_NTF on {} (Not further defined error), aborting.",
- commandString);
+ "bridgeDirectCommunicate() on {}: received GW_ERROR_NTF on {} (Not further defined error), aborting.",
+ host, commandString);
break communication;
case 1:
logger.warn(
- "bridgeDirectCommunicate(): received GW_ERROR_NTF (Unknown Command or command is not accepted at this state) on {}, aborting.",
- commandString);
+ "bridgeDirectCommunicate() on {}: received GW_ERROR_NTF (Unknown Command or command is not accepted at this state) on {}, aborting.",
+ host, commandString);
break communication;
case 2:
logger.warn(
- "bridgeDirectCommunicate(): received GW_ERROR_NTF (ERROR on Frame Structure) on {}, aborting.",
- commandString);
+ "bridgeDirectCommunicate() on {}: received GW_ERROR_NTF (ERROR on Frame Structure) on {}, aborting.",
+ host, commandString);
break communication;
case 7:
logger.trace(
- "bridgeDirectCommunicate(): received GW_ERROR_NTF (Busy. Try again later) on {}, retrying.",
- commandString);
+ "bridgeDirectCommunicate() on {}: received GW_ERROR_NTF (Busy. Try again later) on {}, retrying.",
+ host, commandString);
sendBytes = emptyPacket;
continue;
case 8:
logger.warn(
- "bridgeDirectCommunicate(): received GW_ERROR_NTF (Bad system table index) on {}, aborting.",
- commandString);
+ "bridgeDirectCommunicate() on {}: received GW_ERROR_NTF (Bad system table index) on {}, aborting.",
+ host, commandString);
break communication;
case 12:
logger.warn(
- "bridgeDirectCommunicate(): received GW_ERROR_NTF (Not authenticated) on {}, aborting.",
- commandString);
+ "bridgeDirectCommunicate() on {}: received GW_ERROR_NTF (Not authenticated) on {}, aborting.",
+ host, commandString);
resetAuthentication();
break communication;
default:
- logger.warn("bridgeDirectCommunicate(): received GW_ERROR_NTF ({}) on {}, aborting.",
- responseData[0], commandString);
+ logger.warn(
+ "bridgeDirectCommunicate() on {}: received GW_ERROR_NTF ({}) on {}, aborting.",
+ host, responseData[0], commandString);
break communication;
}
case GW_ACTIVATION_LOG_UPDATED_NTF:
- logger.info("bridgeDirectCommunicate(): received GW_ACTIVATION_LOG_UPDATED_NTF.");
- logger.trace("bridgeDirectCommunicate(): continue with receiving.");
+ logger.info("bridgeDirectCommunicate() on {}: received GW_ACTIVATION_LOG_UPDATED_NTF.", host);
+ logger.trace("bridgeDirectCommunicate() on {}: continue with receiving.", host);
continue;
case GW_COMMAND_RUN_STATUS_NTF:
@@ -366,19 +374,21 @@ public class SlipVeluxBridge extends VeluxBridge {
case GW_SESSION_FINISHED_NTF:
if (!isSequentialEnforced) {
logger.trace(
- "bridgeDirectCommunicate(): response ignored due to activated parallelism, continue with receiving.");
+ "bridgeDirectCommunicate() on {}: response ignored due to activated parallelism, continue with receiving.",
+ host);
continue;
}
default:
}
- logger.trace("bridgeDirectCommunicate(): passes back command {} and data {}.",
+ logger.trace("bridgeDirectCommunicate() on {}: passes back command {} and data {}.", host,
new CommandNumber(responseCommand).toString(), new Packet(responseData).toString());
communication.setResponse(responseCommand, responseData, isSequentialEnforced);
} while (!communication.isCommunicationFinished());
success = communication.isCommunicationSuccessful();
} while (false); // communication
- logger.debug("bridgeDirectCommunicate({}) returns {}.", commandString, success ? "success" : "failure");
+ logger.debug("bridgeDirectCommunicate({}) on {}: returns {}.", commandString, host,
+ success ? "success" : "failure");
return success;
}
}
diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/io/Connection.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/io/Connection.java
index a42d7a12c..d6e32c297 100644
--- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/io/Connection.java
+++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/io/Connection.java
@@ -16,6 +16,7 @@ import java.io.IOException;
import java.net.ConnectException;
import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.binding.velux.internal.VeluxBindingConstants;
import org.openhab.binding.velux.internal.bridge.VeluxBridgeInstance;
import org.openhab.binding.velux.internal.bridge.slip.utils.Packet;
import org.slf4j.Logger;
@@ -59,6 +60,8 @@ public class Connection {
*/
private SSLconnection connectivity = SSLconnection.UNKNOWN;
+ private String host = VeluxBindingConstants.UNKNOWN_IP_ADDRESS;
+
/*
* **************************
* ***** Public Methods *****
@@ -75,7 +78,7 @@ public class Connection {
*/
public synchronized byte[] io(VeluxBridgeInstance bridgeInstance, byte[] request)
throws ConnectException, IOException {
- logger.trace("io() called.");
+ logger.trace("io() on {}: called.", host);
lastCommunicationInMSecs = System.currentTimeMillis();
@@ -88,18 +91,18 @@ public class Connection {
if (!connectivity.isReady()) {
try {
// From configuration
- String host = bridgeInstance.veluxBridgeConfiguration().ipAddress;
+ host = bridgeInstance.veluxBridgeConfiguration().ipAddress;
int port = bridgeInstance.veluxBridgeConfiguration().tcpPort;
int timeoutMsecs = bridgeInstance.veluxBridgeConfiguration().timeoutMsecs;
- logger.trace("io(): connecting to {}:{}.", host, port);
+ logger.trace("io() on {}: connecting to port {}", host, port);
connectivity = new SSLconnection(host, port);
connectivity.setTimeout(timeoutMsecs);
} catch (ConnectException ce) {
throw new ConnectException(String
.format("raised a non-recoverable error during connection setup: %s", ce.getMessage()));
} catch (IOException e) {
- logger.warn("io(): raised an error during connection setup: {}.", e.getMessage());
+ logger.warn("io() on {}: raised an error during connection setup: {}.", host, e.getMessage());
lastIOE = new IOException(String.format("error during connection setup: %s.", e.getMessage()));
continue;
}
@@ -107,65 +110,68 @@ public class Connection {
if (request.length > 0) {
try {
if (logger.isTraceEnabled()) {
- logger.trace("io(): sending packet with {} bytes: {}", request.length, new Packet(request));
+ logger.trace("io() on {}: sending packet with {} bytes: {}", host, request.length,
+ new Packet(request));
} else {
- logger.debug("io(): sending packet of size {}.", request.length);
+ logger.debug("io() on {}: sending packet of size {}.", host, request.length);
}
if (connectivity.isReady()) {
connectivity.send(request);
}
} catch (IOException e) {
- logger.info("io(): raised an error during sending: {}.", e.getMessage());
+ logger.info("io() on {}: raised an error during sending: {}.", host, e.getMessage());
break;
}
// Give the bridge some time to breathe
if (bridgeInstance.veluxBridgeConfiguration().timeoutMsecs > 0) {
- logger.trace("io(): wait time {} msecs.",
+ logger.trace("io() on {}: wait time {} msecs.", host,
bridgeInstance.veluxBridgeConfiguration().timeoutMsecs);
try {
Thread.sleep(bridgeInstance.veluxBridgeConfiguration().timeoutMsecs);
} catch (InterruptedException ie) {
- logger.trace("io() wait interrupted.");
+ logger.trace("io() on {}: wait interrupted.", host);
}
}
}
byte[] packet = new byte[0];
- logger.trace("io(): receiving bytes.");
+ logger.trace("io() on {}: receiving bytes.", host);
if (connectivity.isReady()) {
packet = connectivity.receive();
}
if (logger.isTraceEnabled()) {
- logger.trace("io(): received packet with {} bytes: {}", packet.length, new Packet(packet));
+ logger.trace("io() on {}: received packet with {} bytes: {}", host, packet.length,
+ new Packet(packet));
} else {
- logger.debug("io(): received packet with {} bytes.", packet.length);
+ logger.debug("io() on {}: received packet with {} bytes.", host, packet.length);
}
lastSuccessfulCommunicationInMSecs = System.currentTimeMillis();
lastCommunicationInMSecs = lastSuccessfulCommunicationInMSecs;
- logger.trace("io() finished.");
+ logger.trace("io() on {}: finished.", host);
return packet;
} catch (IOException ioe) {
- logger.info("io(): Exception occurred during I/O: {}.", ioe.getMessage());
+ logger.info("io() on {}: Exception occurred during I/O: {}.", host, ioe.getMessage());
lastIOE = ioe;
// Error Retries with Exponential Backoff
long waitTime = ((long) Math.pow(2, retryCount)
* bridgeInstance.veluxBridgeConfiguration().timeoutMsecs);
- logger.trace("io(): wait time {} msecs.", waitTime);
+ logger.trace("io() on {}: wait time {} msecs.", host, waitTime);
try {
Thread.sleep(waitTime);
} catch (InterruptedException ie) {
- logger.trace("io(): wait interrupted.");
+ logger.trace("io() on {}: wait interrupted.", host);
}
}
} while (retryCount++ < bridgeInstance.veluxBridgeConfiguration().retries);
if (retryCount >= bridgeInstance.veluxBridgeConfiguration().retries) {
- logger.info("io(): socket I/O failed {} times.", bridgeInstance.veluxBridgeConfiguration().retries);
+ logger.info("io() on {}: socket I/O failed {} times.", host,
+ bridgeInstance.veluxBridgeConfiguration().retries);
}
- logger.trace("io(): shutting down connection.");
+ logger.trace("io() on {}: shutting down connection.", host);
if (connectivity.isReady()) {
connectivity.close();
}
- logger.trace("io() finishes with failure by throwing exception.");
+ logger.trace("io() on {}: finishes with failure by throwing exception.", host);
throw lastIOE;
}
@@ -175,7 +181,7 @@ public class Connection {
* @return state as boolean.
*/
public boolean isAlive() {
- logger.trace("isAlive(): called.");
+ logger.trace("isAlive() on {}: called.", host);
return connectivity.isReady();
}
@@ -185,17 +191,17 @@ public class Connection {
* @return state as boolean.
*/
public synchronized boolean isMessageAvailable() {
- logger.trace("isMessageAvailable(): called.");
+ logger.trace("isMessageAvailable() on {}: called.", host);
try {
if ((connectivity.isReady()) && (connectivity.available())) {
- logger.trace("isMessageAvailable(): there is a message waiting.");
+ logger.trace("isMessageAvailable() on {}: there is a message waiting.", host);
return true;
}
} catch (IOException e) {
- logger.trace("isMessageAvailable(): lost connection due to {}.", e.getMessage());
+ logger.trace("isMessageAvailable() on {}: lost connection due to {}.", host, e.getMessage());
resetConnection();
}
- logger.trace("isMessageAvailable(): no message waiting.");
+ logger.trace("isMessageAvailable() on {}: no message waiting.", host);
return false;
}
@@ -223,18 +229,12 @@ public class Connection {
* Resets an open connectivity by closing the socket and resetting the authentication information.
*/
public synchronized void resetConnection() {
- logger.trace("resetConnection() called.");
- if (connectivity.isReady()) {
- logger.trace("resetConnection(): shutting down connection.");
- try {
- if (connectivity.isReady()) {
- connectivity.close();
- }
- } catch (IOException e) {
- logger.info("resetConnection(): raised an error during connection close: {}.", e.getMessage());
- }
- logger.trace("resetConnection(): clearing authentication token.");
+ logger.trace("resetConnection() on {}: called.", host);
+ try {
+ connectivity.close();
+ } catch (IOException e) {
+ logger.info("resetConnection() on {}: raised an error during connection close: {}.", host, e.getMessage());
}
- logger.trace("resetConnection() done.");
+ logger.trace("resetConnection() on {}: done.", host);
}
}
diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/io/SSLconnection.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/io/SSLconnection.java
index d53ea0594..b93bfad8f 100644
--- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/io/SSLconnection.java
+++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/io/SSLconnection.java
@@ -155,23 +155,43 @@ class SSLconnection {
/**
* Method to pass a message towards the bridge.
+ * This method gets called when we are initiating a new SLIP transaction.
+ *
+ * Note that DataOutputStream and DataInputStream are buffered I/O's. The SLIP protocol requires that prior requests
+ * should have been fully sent over the socket, and their responses should have been fully read from the buffer
+ * before the next request is initiated. i.e. Both read and write buffers should already be empty. Nevertheless,
+ * just in case, we do the following..
+ *
+ * 1) Flush from the read buffer any orphan response data that may have been left over from prior transactions, and
+ * 2) Flush the write buffer directly to the socket to ensure that any exceptions are raised immediately, and the
+ * KLF starts work immediately
*
* @param packet as Array of bytes to be transmitted towards the bridge via the established connection.
- * @throws java.io.IOException in case of a communication I/O failure.
+ * @throws java.io.IOException in case of a communication I/O failure, and sets 'ready' = false
*/
@SuppressWarnings("null")
synchronized void send(byte[] packet) throws IOException {
logger.trace("send() called, writing {} bytes.", packet.length);
- if (!ready || (dOut == null)) {
- throw new IOException();
- }
- dOut.write(packet, 0, packet.length);
- if (logger.isTraceEnabled()) {
- StringBuilder sb = new StringBuilder();
- for (byte b : packet) {
- sb.append(String.format("%02X ", b));
+ try {
+ if (!ready || (dOut == null) || (dIn == null)) {
+ throw new IOException();
}
- logger.trace("send() finished after having send {} bytes: {}", packet.length, sb.toString());
+ // flush the read buffer if (exceptionally) there is orphan response data in it
+ flushReadBufffer();
+ // copy packet data to the write buffer
+ dOut.write(packet, 0, packet.length);
+ // force the write buffer data to be written to the socket
+ dOut.flush();
+ if (logger.isTraceEnabled()) {
+ StringBuilder sb = new StringBuilder();
+ for (byte b : packet) {
+ sb.append(String.format("%02X ", b));
+ }
+ logger.trace("send() finished after having send {} bytes: {}", packet.length, sb.toString());
+ }
+ } catch (IOException e) {
+ ready = false;
+ throw e;
}
}
@@ -196,26 +216,31 @@ class SSLconnection {
* Method to get a message from the bridge.
*
* @return packet as Array of bytes as received from the bridge via the established connection.
- * @throws java.io.IOException in case of a communication I/O failure.
+ * @throws java.io.IOException in case of a communication I/O failure, and sets 'ready' = false
*/
synchronized byte[] receive() throws IOException {
logger.trace("receive() called.");
- if (!ready || (dIn == null)) {
- throw new IOException();
- }
- byte[] message = new byte[CONNECTION_BUFFER_SIZE];
- @SuppressWarnings("null")
- int messageLength = dIn.read(message, 0, message.length, ioTimeoutMSecs);
- byte[] packet = new byte[messageLength];
- System.arraycopy(message, 0, packet, 0, messageLength);
- if (logger.isTraceEnabled()) {
- StringBuilder sb = new StringBuilder();
- for (byte b : packet) {
- sb.append(String.format("%02X ", b));
+ try {
+ if (!ready || (dIn == null)) {
+ throw new IOException();
}
- logger.trace("receive() finished after having read {} bytes: {}", messageLength, sb.toString());
+ byte[] message = new byte[CONNECTION_BUFFER_SIZE];
+ @SuppressWarnings("null")
+ int messageLength = dIn.read(message, 0, message.length, ioTimeoutMSecs);
+ byte[] packet = new byte[messageLength];
+ System.arraycopy(message, 0, packet, 0, messageLength);
+ if (logger.isTraceEnabled()) {
+ StringBuilder sb = new StringBuilder();
+ for (byte b : packet) {
+ sb.append(String.format("%02X ", b));
+ }
+ logger.trace("receive() finished after having read {} bytes: {}", messageLength, sb.toString());
+ }
+ return packet;
+ } catch (IOException e) {
+ ready = false;
+ throw e;
}
- return packet;
}
/**
@@ -231,16 +256,19 @@ class SSLconnection {
DataInputStreamWithTimeout dInX = dIn;
if (dInX != null) {
dInX.close();
+ dIn = null;
}
// Just for avoidance of Potential null pointer access
DataOutputStream dOutX = dOut;
if (dOutX != null) {
dOutX.close();
+ dOut = null;
}
// Just for avoidance of Potential null pointer access
SSLSocket socketX = socket;
if (socketX != null) {
socketX.close();
+ socket = null;
}
logger.trace("close() finished.");
}
@@ -254,4 +282,32 @@ class SSLconnection {
logger.debug("setTimeout() set timeout to {} milliseconds.", timeoutMSecs);
ioTimeoutMSecs = timeoutMSecs;
}
+
+ /**
+ * Method to flush the input buffer.
+ *
+ * @throws java.io.IOException in case of a communication I/O failure.
+ */
+ private void flushReadBufffer() throws IOException {
+ logger.trace("flushReadBuffer() called.");
+ DataInputStreamWithTimeout dInX = dIn;
+ if (!ready || (dInX == null)) {
+ throw new IOException();
+ }
+ int byteCount = dInX.available();
+ if (byteCount > 0) {
+ byte[] byteArray = new byte[byteCount];
+ dInX.readFully(byteArray);
+ if (logger.isTraceEnabled()) {
+ StringBuilder stringBuilder = new StringBuilder();
+ for (byte currByte : byteArray) {
+ stringBuilder.append(String.format("%02X ", currByte));
+ }
+ logger.trace("flushReadBuffer(): discarded {} unexpected bytes in the input buffer: {}", byteCount,
+ stringBuilder.toString());
+ } else {
+ logger.warn("flushReadBuffer(): discarded {} unexpected bytes in the input buffer", byteCount);
+ }
+ }
+ }
}
diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/utils/KLF200Response.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/utils/KLF200Response.java
index d29aa9717..520ce67c7 100644
--- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/utils/KLF200Response.java
+++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/utils/KLF200Response.java
@@ -64,9 +64,9 @@ public class KLF200Response {
*/
public static void errorLogging(Logger logger, short responseCommand) {
logger.trace("setResponse(): cannot handle response {} ({}).", Command.get(responseCommand).toString(),
- responseCommand);
+ new CommandNumber(responseCommand).toString());
logger.warn("Gateway response {} ({}) cannot be handled at this point of interaction.",
- Command.get(responseCommand).toString(), responseCommand);
+ Command.get(responseCommand).toString(), new CommandNumber(responseCommand).toString());
}
/**
@@ -122,10 +122,10 @@ public class KLF200Response {
* @return check4matchingAnyID of type boolean which signals the equality.
*/
private static boolean check4matchingAnyID(Logger logger, String idName, int requestID, int responseID) {
- logger.trace("check4matchingAnyID() called for request{} {} and response{} {}.", idName, requestID, idName,
+ logger.trace("check4matchingAnyID() called for request {} {} and response {} {}.", idName, requestID, idName,
responseID);
if (requestID != responseID) {
- logger.warn("Gateway response with {} {} unexpected as query asked for {} {}.", idName, requestID, idName,
+ logger.warn("Gateway query for {} {} received unexpected response of {} {}.", idName, requestID, idName,
responseID);
return false;
}
diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/utils/SlipEncoding.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/utils/SlipEncoding.java
index 704778022..3c4e74064 100644
--- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/utils/SlipEncoding.java
+++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/utils/SlipEncoding.java
@@ -47,8 +47,8 @@ public class SlipEncoding {
private final Logger logger = LoggerFactory.getLogger(SlipEncoding.class);
private static final byte PROTOCOL_ID = 0;
- private static boolean encodingValid = false;
- private static byte[] message = new byte[0];
+ private boolean encodingValid = false;
+ private byte[] message = new byte[0];
/**
* Builds a message based on command and parameters.
diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/discovery/VeluxDiscoveryService.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/discovery/VeluxDiscoveryService.java
index affd62785..6bf3f1471 100644
--- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/discovery/VeluxDiscoveryService.java
+++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/discovery/VeluxDiscoveryService.java
@@ -14,8 +14,10 @@ package org.openhab.binding.velux.internal.discovery;
import static org.openhab.binding.velux.internal.VeluxBindingConstants.*;
+import java.util.HashSet;
+import java.util.Set;
+
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.velux.internal.VeluxBindingConstants;
import org.openhab.binding.velux.internal.VeluxBindingProperties;
import org.openhab.binding.velux.internal.handler.VeluxBridgeHandler;
@@ -60,7 +62,7 @@ public class VeluxDiscoveryService extends AbstractDiscoveryService implements R
private @NonNullByDefault({}) LocaleProvider localeProvider;
private @NonNullByDefault({}) TranslationProvider i18nProvider;
private Localization localization = Localization.UNKNOWN;
- private static @Nullable VeluxBridgeHandler bridgeHandler = null;
+ private final Set bridgeHandlers = new HashSet<>();
// Private
@@ -102,21 +104,11 @@ public class VeluxDiscoveryService extends AbstractDiscoveryService implements R
* Initializes the {@link VeluxDiscoveryService} with a reference to the well-prepared environment with a
* {@link VeluxBridgeHandler}.
*
- * @param bridge Initialized Velux bridge handler.
* @param localizationHandler Initialized localization handler.
*/
- public VeluxDiscoveryService(VeluxBridgeHandler bridge, Localization localizationHandler) {
+ public VeluxDiscoveryService(Localization localizationHandler) {
super(VeluxBindingConstants.SUPPORTED_THINGS_ITEMS, DISCOVER_TIMEOUT_SECONDS);
- logger.trace("VeluxDiscoveryService(bridge={},locale={},i18n={}) just initialized.", bridge, localeProvider,
- i18nProvider);
-
- if (bridgeHandler == null) {
- logger.trace("VeluxDiscoveryService(): registering bridge {} for lateron use for Discovery.", bridge);
- } else if (!bridge.equals(bridgeHandler)) {
- logger.trace("VeluxDiscoveryService(): replacing already registered bridge {} by {}.", bridgeHandler,
- bridge);
- }
- bridgeHandler = bridge;
+ logger.trace("VeluxDiscoveryService(locale={},i18n={}) just initialized.", localeProvider, i18nProvider);
localization = localizationHandler;
}
@@ -126,16 +118,14 @@ public class VeluxDiscoveryService extends AbstractDiscoveryService implements R
* Initializes the {@link VeluxDiscoveryService} with a reference to the well-prepared environment with a
* {@link VeluxBridgeHandler}.
*
- * @param bridge Initialized Velux bridge handler.
* @param locationProvider Provider for a location.
* @param localeProvider Provider for a locale.
* @param i18nProvider Provider for the internationalization.
*/
- public VeluxDiscoveryService(VeluxBridgeHandler bridge, LocationProvider locationProvider,
- LocaleProvider localeProvider, TranslationProvider i18nProvider) {
- this(bridge, new Localization(localeProvider, i18nProvider));
- logger.trace("VeluxDiscoveryService(bridge={},locale={},i18n={}) finished.", bridge, localeProvider,
- i18nProvider);
+ public VeluxDiscoveryService(LocationProvider locationProvider, LocaleProvider localeProvider,
+ TranslationProvider i18nProvider) {
+ this(new Localization(localeProvider, i18nProvider));
+ logger.trace("VeluxDiscoveryService(locale={},i18n={}) finished.", localeProvider, i18nProvider);
}
@Override
@@ -157,8 +147,8 @@ public class VeluxDiscoveryService extends AbstractDiscoveryService implements R
logger.debug("startScan(): registering new thing {}.", discoveryResult);
thingDiscovered(discoveryResult);
- if (bridgeHandler == null) {
- logger.debug("startScan(): VeluxDiscoveryService cannot proceed due to missing Velux bridge.");
+ if (bridgeHandlers.isEmpty()) {
+ logger.debug("startScan(): VeluxDiscoveryService cannot proceed due to missing Velux bridge(s).");
} else {
logger.debug("startScan(): Starting Velux discovery scan for scenes and actuators.");
discoverScenes();
@@ -185,29 +175,25 @@ public class VeluxDiscoveryService extends AbstractDiscoveryService implements R
*/
private void discoverScenes() {
logger.trace("discoverScenes() called.");
- // Just for avoidance of Potential null pointer access
- VeluxBridgeHandler bridgeHandlerX = bridgeHandler;
- if (bridgeHandlerX == null) {
- logger.debug("discoverScenes(): VeluxDiscoveryService.bridgeHandler not initialized, aborting discovery.");
- return;
- }
- ThingUID bridgeUID = bridgeHandlerX.getThing().getUID();
- logger.debug("discoverScenes(): discovering all scenes.");
- for (VeluxScene scene : bridgeHandlerX.existingScenes().values()) {
- String sceneName = scene.getName().toString();
- logger.trace("discoverScenes(): found scene {}.", sceneName);
+ for (VeluxBridgeHandler bridgeHandlerX : bridgeHandlers) {
+ ThingUID bridgeUID = bridgeHandlerX.getThing().getUID();
+ logger.debug("discoverScenes(): discovering all scenes on bridge {}.", bridgeUID);
+ for (VeluxScene scene : bridgeHandlerX.existingScenes().values()) {
+ String sceneName = scene.getName().toString();
+ logger.trace("discoverScenes(): found scene {}.", sceneName);
- String label = sceneName.replaceAll("\\P{Alnum}", "_");
- logger.trace("discoverScenes(): using label {}.", label);
+ String label = sceneName.replaceAll("\\P{Alnum}", "_");
+ logger.trace("discoverScenes(): using label {}.", label);
- ThingTypeUID thingTypeUID = THING_TYPE_VELUX_SCENE;
- ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, label);
- DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withThingType(thingTypeUID)
- .withProperty(VeluxBindingProperties.PROPERTY_SCENE_NAME, sceneName)
- .withRepresentationProperty(VeluxBindingProperties.PROPERTY_SCENE_NAME).withBridge(bridgeUID)
- .withLabel(label).build();
- logger.debug("discoverScenes(): registering new thing {}.", discoveryResult);
- thingDiscovered(discoveryResult);
+ ThingTypeUID thingTypeUID = THING_TYPE_VELUX_SCENE;
+ ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, label);
+ DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withThingType(thingTypeUID)
+ .withProperty(VeluxBindingProperties.PROPERTY_SCENE_NAME, sceneName)
+ .withRepresentationProperty(VeluxBindingProperties.PROPERTY_SCENE_NAME).withBridge(bridgeUID)
+ .withLabel(label).build();
+ logger.debug("discoverScenes(): registering new thing {}.", discoveryResult);
+ thingDiscovered(discoveryResult);
+ }
}
logger.trace("discoverScenes() finished.");
}
@@ -217,56 +203,87 @@ public class VeluxDiscoveryService extends AbstractDiscoveryService implements R
*/
private void discoverProducts() {
logger.trace("discoverProducts() called.");
- // Just for avoidance of Potential null pointer access
- VeluxBridgeHandler bridgeHandlerX = bridgeHandler;
- if (bridgeHandlerX == null) {
- logger.debug("discoverScenes() VeluxDiscoveryService.bridgeHandlerR not initialized, aborting discovery.");
- return;
- }
- ThingUID bridgeUID = bridgeHandlerX.getThing().getUID();
- logger.debug("discoverProducts(): discovering all actuators.");
- for (VeluxProduct product : bridgeHandlerX.existingProducts().values()) {
- String serialNumber = product.getSerialNumber();
- String actuatorName = product.getProductName().toString();
- logger.trace("discoverProducts() found actuator {} (name {}).", serialNumber, actuatorName);
- String identifier;
- if (serialNumber.equals(VeluxProductSerialNo.UNKNOWN)) {
- identifier = actuatorName;
- } else {
- identifier = serialNumber;
+ for (VeluxBridgeHandler bridgeHandlerX : bridgeHandlers) {
+ ThingUID bridgeUID = bridgeHandlerX.getThing().getUID();
+ logger.debug("discoverProducts(): discovering all actuators on bridge {}.", bridgeUID);
+ for (VeluxProduct product : bridgeHandlerX.existingProducts().values()) {
+ String serialNumber = product.getSerialNumber();
+ String actuatorName = product.getProductName().toString();
+ logger.trace("discoverProducts() found actuator {} (name {}).", serialNumber, actuatorName);
+ String identifier;
+ if (serialNumber.equals(VeluxProductSerialNo.UNKNOWN)) {
+ identifier = actuatorName;
+ } else {
+ identifier = serialNumber;
+ }
+ String label = actuatorName.replaceAll("\\P{Alnum}", "_");
+ logger.trace("discoverProducts(): using label {}.", label);
+ ThingTypeUID thingTypeUID;
+ boolean isInverted = false;
+ logger.trace("discoverProducts() dealing with {} (type {}).", product, product.getProductType());
+ switch (product.getProductType()) {
+ case SLIDER_WINDOW:
+ logger.trace("discoverProducts(): creating window.");
+ thingTypeUID = THING_TYPE_VELUX_WINDOW;
+ isInverted = true;
+ break;
+
+ case SLIDER_SHUTTER:
+ logger.trace("discoverProducts(): creating rollershutter.");
+ thingTypeUID = THING_TYPE_VELUX_ROLLERSHUTTER;
+ break;
+
+ default:
+ logger.trace("discoverProducts(): creating actuator.");
+ thingTypeUID = THING_TYPE_VELUX_ACTUATOR;
+ }
+ ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, label);
+
+ DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withThingType(thingTypeUID)
+ .withProperty(VeluxBindingProperties.CONFIG_ACTUATOR_SERIALNUMBER, identifier)
+ .withProperty(VeluxBindingProperties.PROPERTY_ACTUATOR_NAME, actuatorName)
+ .withProperty(VeluxBindingProperties.PROPERTY_ACTUATOR_INVERTED, isInverted)
+ .withRepresentationProperty(VeluxBindingProperties.CONFIG_ACTUATOR_SERIALNUMBER)
+ .withBridge(bridgeUID).withLabel(actuatorName).build();
+ logger.debug("discoverProducts(): registering new thing {}.", discoveryResult);
+ thingDiscovered(discoveryResult);
}
- String label = actuatorName.replaceAll("\\P{Alnum}", "_");
- logger.trace("discoverProducts(): using label {}.", label);
- ThingTypeUID thingTypeUID;
- boolean isInverted = false;
- logger.trace("discoverProducts() dealing with {} (type {}).", product, product.getProductType());
- switch (product.getProductType()) {
- case SLIDER_WINDOW:
- logger.trace("discoverProducts(): creating window.");
- thingTypeUID = THING_TYPE_VELUX_WINDOW;
- isInverted = true;
- break;
-
- case SLIDER_SHUTTER:
- logger.trace("discoverProducts(): creating rollershutter.");
- thingTypeUID = THING_TYPE_VELUX_ROLLERSHUTTER;
- break;
-
- default:
- logger.trace("discoverProducts(): creating actuator.");
- thingTypeUID = THING_TYPE_VELUX_ACTUATOR;
- }
- ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, label);
-
- DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withThingType(thingTypeUID)
- .withProperty(VeluxBindingProperties.CONFIG_ACTUATOR_SERIALNUMBER, identifier)
- .withProperty(VeluxBindingProperties.PROPERTY_ACTUATOR_NAME, actuatorName)
- .withProperty(VeluxBindingProperties.PROPERTY_ACTUATOR_INVERTED, isInverted)
- .withRepresentationProperty(VeluxBindingProperties.CONFIG_ACTUATOR_SERIALNUMBER)
- .withBridge(bridgeUID).withLabel(actuatorName).build();
- logger.debug("discoverProducts(): registering new thing {}.", discoveryResult);
- thingDiscovered(discoveryResult);
}
logger.trace("discoverProducts() finished.");
}
+
+ /**
+ * Add a {@link VeluxBridgeHandler} to the {@link VeluxDiscoveryService}
+ *
+ * @param bridge Velux bridge handler.
+ * @return true if the bridge was added, or false if it was already present
+ */
+ public boolean addBridge(VeluxBridgeHandler bridge) {
+ if (!bridgeHandlers.contains(bridge)) {
+ logger.trace("VeluxDiscoveryService(): registering bridge {} for discovery.", bridge);
+ bridgeHandlers.add(bridge);
+ return true;
+ }
+ logger.trace("VeluxDiscoveryService(): bridge {} already registered for discovery.", bridge);
+ return false;
+ }
+
+ /**
+ * Remove a {@link VeluxBridgeHandler} from the {@link VeluxDiscoveryService}
+ *
+ * @param bridge Velux bridge handler.
+ * @return true if the bridge was removed, or false if it was not present
+ */
+ public boolean removeBridge(VeluxBridgeHandler bridge) {
+ return bridgeHandlers.remove(bridge);
+ }
+
+ /**
+ * Check if the {@link VeluxDiscoveryService} list of {@link VeluxBridgeHandler} is empty
+ *
+ * @return true if empty
+ */
+ public boolean isEmpty() {
+ return bridgeHandlers.isEmpty();
+ }
}
diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/factory/VeluxHandlerFactory.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/factory/VeluxHandlerFactory.java
index aff42c6cc..52710a791 100644
--- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/factory/VeluxHandlerFactory.java
+++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/factory/VeluxHandlerFactory.java
@@ -12,10 +12,8 @@
*/
package org.openhab.binding.velux.internal.factory;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
-import java.util.Map;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -32,7 +30,6 @@ import org.openhab.core.i18n.TranslationProvider;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingTypeUID;
-import org.openhab.core.thing.ThingUID;
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.ThingHandlerFactory;
@@ -56,7 +53,8 @@ public class VeluxHandlerFactory extends BaseThingHandlerFactory {
// Class internal
- private final Map> discoveryServiceRegistrations = new HashMap<>();
+ private @Nullable ServiceRegistration> discoveryServiceRegistration = null;
+ private @Nullable VeluxDiscoveryService discoveryService = null;
private Set veluxBindingHandlers = new HashSet<>();
private Set veluxBridgeHandlers = new HashSet<>();
@@ -69,20 +67,25 @@ public class VeluxHandlerFactory extends BaseThingHandlerFactory {
// Private
private void registerDeviceDiscoveryService(VeluxBridgeHandler bridgeHandler) {
- VeluxDiscoveryService discoveryService = new VeluxDiscoveryService(bridgeHandler, localization);
- ServiceRegistration> discoveryServiceReg = bundleContext.registerService(DiscoveryService.class.getName(),
- discoveryService, new Hashtable<>());
- discoveryServiceRegistrations.put(bridgeHandler.getThing().getUID(), discoveryServiceReg);
+ logger.trace("registerDeviceDiscoveryService({}) called.", bridgeHandler);
+ boolean createNew = (discoveryService == null);
+ if (createNew) {
+ discoveryService = new VeluxDiscoveryService(localization);
+ }
+ discoveryService.addBridge(bridgeHandler);
+ if (createNew) {
+ discoveryServiceRegistration = bundleContext.registerService(DiscoveryService.class.getName(),
+ discoveryService, new Hashtable<>());
+ }
}
- // Even if the compiler tells, that the value of cannot be null, it is possible!
- // Therefore a @SuppressWarnings("null") is needed to suppress the warning
- @SuppressWarnings("null")
- private synchronized void unregisterDeviceDiscoveryService(ThingUID thingUID) {
- logger.trace("unregisterDeviceDiscoveryService({}) called.", thingUID);
- ServiceRegistration> remove = discoveryServiceRegistrations.remove(thingUID);
- if (remove != null) {
- remove.unregister();
+ private synchronized void unregisterDeviceDiscoveryService(VeluxBridgeHandler bridgeHandler) {
+ logger.trace("unregisterDeviceDiscoveryService({}) called.", bridgeHandler);
+ if (discoveryService != null) {
+ discoveryService.removeBridge(bridgeHandler);
+ if (discoveryService.isEmpty()) {
+ discoveryServiceRegistration.unregister();
+ }
}
}
@@ -191,7 +194,7 @@ public class VeluxHandlerFactory extends BaseThingHandlerFactory {
if (thingHandler instanceof VeluxBridgeHandler) {
logger.trace("removeHandler() removing bridge '{}'.", thingHandler.toString());
veluxBridgeHandlers.remove(thingHandler);
- unregisterDeviceDiscoveryService(thingHandler.getThing().getUID());
+ unregisterDeviceDiscoveryService((VeluxBridgeHandler) thingHandler);
} else
// Handle removal of Things behind the Bridge
if (thingHandler instanceof VeluxHandler) {
diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeWLANconfig.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeWLANconfig.java
index 80925dd09..3857f88a6 100644
--- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeWLANconfig.java
+++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeWLANconfig.java
@@ -19,6 +19,7 @@ import org.openhab.binding.velux.internal.VeluxItemType;
import org.openhab.binding.velux.internal.bridge.VeluxBridgeWLANConfig;
import org.openhab.binding.velux.internal.handler.utils.StateUtils;
import org.openhab.binding.velux.internal.handler.utils.ThingProperty;
+import org.openhab.core.library.types.StringType;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.types.State;
import org.slf4j.Logger;
@@ -69,16 +70,15 @@ final class ChannelBridgeWLANconfig extends ChannelHandlerTemplate {
if (thisBridgeHandler.bridgeParameters.wlanConfig.isRetrieved) {
VeluxItemType itemType = VeluxItemType.getByThingAndChannel(thisBridgeHandler.thingTypeUIDOf(channelUID),
channelUID.getId());
+ String msg = thisBridgeHandler.localization.getText("config.velux.bridge.unAvailable");
switch (itemType) {
case BRIDGE_WLANSSID:
- newState = StateUtils.createState(thisBridgeHandler.bridgeParameters.lanConfig.openHABipAddress);
- ThingProperty.setValue(thisBridgeHandler, VeluxBindingConstants.PROPERTY_BRIDGE_WLANSSID,
- thisBridgeHandler.bridgeParameters.wlanConfig.openHABwlanSSID.toString());
+ newState = StateUtils.createState(new StringType(msg));
+ ThingProperty.setValue(thisBridgeHandler, VeluxBindingConstants.PROPERTY_BRIDGE_WLANSSID, msg);
break;
case BRIDGE_WLANPASSWORD:
- newState = StateUtils.createState(thisBridgeHandler.bridgeParameters.lanConfig.openHABsubnetMask);
- ThingProperty.setValue(thisBridgeHandler, VeluxBindingConstants.PROPERTY_BRIDGE_WLANPASSWORD,
- thisBridgeHandler.bridgeParameters.wlanConfig.openHABwlanPassword.toString());
+ newState = StateUtils.createState(new StringType(msg));
+ ThingProperty.setValue(thisBridgeHandler, VeluxBindingConstants.PROPERTY_BRIDGE_WLANPASSWORD, msg);
break;
default:
}
diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBindingHandler.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBindingHandler.java
index 29f99de38..ab22f02b4 100644
--- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBindingHandler.java
+++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBindingHandler.java
@@ -13,6 +13,7 @@
package org.openhab.binding.velux.internal.handler;
import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.binding.velux.internal.VeluxBindingConstants;
import org.openhab.binding.velux.internal.VeluxBindingProperties;
import org.openhab.binding.velux.internal.VeluxItemType;
import org.openhab.binding.velux.internal.handler.utils.ExtendedBaseThingHandler;
@@ -20,6 +21,7 @@ import org.openhab.binding.velux.internal.handler.utils.StateUtils;
import org.openhab.binding.velux.internal.handler.utils.ThingProperty;
import org.openhab.binding.velux.internal.utils.Localization;
import org.openhab.binding.velux.internal.utils.ManifestInformation;
+import org.openhab.core.common.AbstractUID;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
@@ -82,9 +84,13 @@ public class VeluxBindingHandler extends ExtendedBaseThingHandler {
* @param channelUID for type {@link ChannelUID}.
* @return thingTypeUID of type {@link ThingTypeUID}.
*/
- @SuppressWarnings("deprecation")
private ThingTypeUID thingTypeUIDOf(ChannelUID channelUID) {
- return channelUID.getThingUID().getThingTypeUID();
+ String[] segments = channelUID.getAsString().split(AbstractUID.SEPARATOR);
+ if (segments.length > 1) {
+ return new ThingTypeUID(segments[0], segments[1]);
+ }
+ logger.warn("thingTypeUIDOf({}) failed.", channelUID);
+ return new ThingTypeUID(VeluxBindingConstants.BINDING_ID, VeluxBindingConstants.UNKNOWN_THING_TYPE_ID);
}
/**
diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java
index 8df63c2e2..c39a3415f 100644
--- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java
+++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java
@@ -49,6 +49,7 @@ import org.openhab.binding.velux.internal.things.VeluxProduct;
import org.openhab.binding.velux.internal.things.VeluxProduct.ProductBridgeIndex;
import org.openhab.binding.velux.internal.things.VeluxProductPosition;
import org.openhab.binding.velux.internal.utils.Localization;
+import org.openhab.core.common.AbstractUID;
import org.openhab.core.common.ThreadPoolManager;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
@@ -187,9 +188,13 @@ public class VeluxBridgeHandler extends ExtendedBaseBridgeHandler implements Vel
* @param channelUID for type {@link ChannelUID}.
* @return thingTypeUID of type {@link ThingTypeUID}.
*/
- @SuppressWarnings("deprecation")
ThingTypeUID thingTypeUIDOf(ChannelUID channelUID) {
- return channelUID.getThingUID().getThingTypeUID();
+ String[] segments = channelUID.getAsString().split(AbstractUID.SEPARATOR);
+ if (segments.length > 1) {
+ return new ThingTypeUID(segments[0], segments[1]);
+ }
+ logger.warn("thingTypeUIDOf({}) failed.", channelUID);
+ return new ThingTypeUID(VeluxBindingConstants.BINDING_ID, VeluxBindingConstants.UNKNOWN_THING_TYPE_ID);
}
// Objects and Methods for interface VeluxBridgeInstance
diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxKLFAPI.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxKLFAPI.java
index 255beae72..6b064c8fd 100644
--- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxKLFAPI.java
+++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxKLFAPI.java
@@ -129,7 +129,7 @@ public class VeluxKLFAPI {
UNDEFTYPE((short) -1, "Unknown command."),
// Special item: Shutdown of the connection
GW_OPENHAB_CLOSE((short) -2, "openHAB connection shutdown command."),
- // Special item: Shutdown of the connection
+ // Special item: Empty Command (used to send nothing and process an incoming message only)
GW_OPENHAB_RECEIVEONLY((short) -3, "openHAB receive command."),
// Velux specific commands
GW_ERROR_NTF((short) 0x0000, "Provides information on what triggered the error."),
diff --git a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/i18n/velux.properties b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/i18n/velux.properties
index d6ec46c33..667abb72b 100644
--- a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/i18n/velux.properties
+++ b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/i18n/velux.properties
@@ -68,6 +68,7 @@ config.velux.bridge.isSequentialEnforced.label = Enforce Sequential Mode
config.velux.bridge.isSequentialEnforced.description = Enforce Sequential Actuator Control. Determine the mode of operation for long-time actions like running commands or activation of scenes. However the parallelism disables the in-depth protocol handshake processing which does not affect or limit any functionalities.
config.velux.bridge.isProtocolTraceEnabled.label = Enable Protocol Trace
config.velux.bridge.isProtocolTraceEnabled.description = Provide KLF200 protocol details.
+config.velux.bridge.unAvailable = Unavailable
#
config.velux.thing.scene.sceneName.label = Scene Name
config.velux.thing.scene.sceneName.description = Name of the scene to be handled.
diff --git a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/i18n/velux_de.properties b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/i18n/velux_de.properties
index 7afb26955..5af09f7a7 100644
--- a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/i18n/velux_de.properties
+++ b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/i18n/velux_de.properties
@@ -69,6 +69,7 @@ config.velux.bridge.isSequentialEnforced.label = Sequentielles Modus
config.velux.bridge.isSequentialEnforced.description = Erzwingt den sequentiellen Modus von Operationen, insbesondere von länger andauernden Aktionen, wie der Aktivierung von Szenen.
config.velux.bridge.isProtocolTraceEnabled.label = Protokolleinblick
config.velux.bridge.isProtocolTraceEnabled.description = Aktiviert KLF200 Protokolldetails.
+config.velux.bridge.unAvailable = Nicht verfügbar
#
config.velux.thing.scene.sceneName.label = Scenenname
config.velux.thing.scene.sceneName.description = Name der Szene, wie sie auf dem Kopplungselements definiert wurde.
diff --git a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/i18n/velux_dk.properties b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/i18n/velux_dk.properties
index c67e8e698..51c444136 100644
--- a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/i18n/velux_dk.properties
+++ b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/i18n/velux_dk.properties
@@ -65,6 +65,7 @@ config.velux.bridge.isSequentialEnforced.label = Håndhæv sekventiel tilstand
config.velux.bridge.isSequentialEnforced.description = Håndhæv sekventiel aktuatorstyring. Bestem driftsmåden for handlinger i lang tid som at køre kommandoer eller aktivering af scener. Paralleliteten deaktiverer imidlertid den dybdegående protokolhåndtryksbehandling, som ikke påvirker eller begrænser nogen funktionaliteter.
config.velux.bridge.isProtocolTraceEnabled.label = Protocol Insight
config.velux.bridge.isProtocolTraceEnabled.description = Aktiverer KLF200-protokoldetaljer.
+config.velux.bridge.unAvailable = Utilgængelig
#
config.velux.thing.scene.sceneName.label = Scenavn
config.velux.thing.scene.sceneName.description = Navn på den scene, der skal håndteres.
diff --git a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/i18n/velux_nl.properties b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/i18n/velux_nl.properties
index 6e26a089a..70e719899 100644
--- a/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/i18n/velux_nl.properties
+++ b/bundles/org.openhab.binding.velux/src/main/resources/OH-INF/i18n/velux_nl.properties
@@ -65,6 +65,7 @@ config.velux.bridge.isSequentialEnforced.label = Opeenvolgende modus afdwingen
config.velux.bridge.isSequentialEnforced.description = Handhaving van sequentiële actuatorcontrole. Bepaal de werkingsmodus voor langdurige acties zoals het uitvoeren van opdrachten of het activeren van scènes. Het parallellisme schakelt echter de diepgaande protocolhandshake-verwerking uit die geen enkele functionaliteit beïnvloedt of beperkt.
config.velux.bridge.isProtocolTraceEnabled.label = Protocol Insight
config.velux.bridge.isProtocolTraceEnabled.description = Schakelt KLF200-protocoldetails in.
+config.velux.bridge.unAvailable = Niet beschikbaar
#
config.velux.thing.scene.sceneName.label = Scènenaam
config.velux.thing.scene.sceneName.description = Naam van de te behandelen scène.
diff --git a/bundles/pom.xml b/bundles/pom.xml
index 8527b7f5e..440974cc5 100644
--- a/bundles/pom.xml
+++ b/bundles/pom.xml
@@ -280,6 +280,7 @@
org.openhab.binding.valloxmv
org.openhab.binding.vektiva
org.openhab.binding.velbus
+ org.openhab.binding.velux
org.openhab.binding.venstarthermostat
org.openhab.binding.verisure
org.openhab.binding.vigicrues
diff --git a/features/openhab-addons/pom.xml b/features/openhab-addons/pom.xml
index d0bb948b7..bc6d0afd4 100644
--- a/features/openhab-addons/pom.xml
+++ b/features/openhab-addons/pom.xml
@@ -52,7 +52,6 @@
-