diff --git a/bundles/binding/org.openhab.binding.velux/.classpath b/bundles/binding/org.openhab.binding.velux/.classpath
index 60df34e974b..1d436f028fb 100644
--- a/bundles/binding/org.openhab.binding.velux/.classpath
+++ b/bundles/binding/org.openhab.binding.velux/.classpath
@@ -3,6 +3,6 @@
-
+
diff --git a/bundles/binding/org.openhab.binding.velux/ESH-INF/binding/binding.xml b/bundles/binding/org.openhab.binding.velux/ESH-INF/binding/binding.xml
index ec56407fdfa..785a797c0bc 100644
--- a/bundles/binding/org.openhab.binding.velux/ESH-INF/binding/binding.xml
+++ b/bundles/binding/org.openhab.binding.velux/ESH-INF/binding/binding.xml
@@ -1,4 +1,18 @@
+
@@ -9,24 +23,33 @@
like controlling window openers, shutters and others. For example a KLF200 can act as interface between the HomeAutomation
and the VELUX INTEGRA products with wireless connectivity based on the io-homecontrol standard.
-
org.openhab.velux
-
+
+
+ The connection protocol to contact the Velux Bridge with (either slip or json).
+ slip
+ false
+ true
+
+
- The hostname or IP address of the Velux Bridge.
+ The IP address of the Velux Bridge.
+ trueTCP port of the Velux gateway
- 80
+ 51200
+ false
+
truePassword for authentication against the Velux Bridge.
- false
+ truevelux123
@@ -34,21 +57,28 @@
Initial Connection timeout in milliseconds.false
- 2000
+ 1000trueNumber of retries with timing along the Binary Exponential Backoff (BEB) Algorithm.false
- 10
+ 5
+ true
+
+
+
+ Refresh interval in milliseconds.
+ false
+ 15000true
-
-
- Data refresh interval for any bridge parameters in milliseconds.
- 3600000
+
+
+ Fetch the complete actuator information in a bulk.false
+ "true"true
diff --git a/bundles/binding/org.openhab.binding.velux/ESH-INF/i18n/velux_de.properties b/bundles/binding/org.openhab.binding.velux/ESH-INF/i18n/velux_de.properties
new file mode 100644
index 00000000000..61a4575b893
--- /dev/null
+++ b/bundles/binding/org.openhab.binding.velux/ESH-INF/i18n/velux_de.properties
@@ -0,0 +1,7 @@
+
+# binding
+binding.velux.name = Velux Binding (1.x)
+binding.velux.description = Ein openHAB1 Binding für das Velux KLF200 Kopplungselement. Das Velux Binding kommuniziert über ein Velux Kopplungselement mit den unterschiedlichen Velux-Geräten zur Steuerung von Fenstern, Rolläden und anderen Geräten. Beispielsweise kann ein KLF 200 als Schnittstelle zwischen Hausleitsystemen und VELUX INTEGRA Produkten mit Funkanbindung basierend auf dem io-homecontrol-Standard eingesetzt werden.
+
+# end-of-ESH-INF/i18n/velux_de.properties
+
diff --git a/bundles/binding/org.openhab.binding.velux/META-INF/MANIFEST.MF b/bundles/binding/org.openhab.binding.velux/META-INF/MANIFEST.MF
index 87707e09928..cd5ac276e25 100644
--- a/bundles/binding/org.openhab.binding.velux/META-INF/MANIFEST.MF
+++ b/bundles/binding/org.openhab.binding.velux/META-INF/MANIFEST.MF
@@ -37,4 +37,4 @@ Bundle-DocURL: http://www.openhab.org
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Service-Component: OSGI-INF/binding.xml, OSGI-INF/genericbindingprovider.xml
Bundle-ClassPath: .,
- lib/gson-2.2.4.jar
+ lib
diff --git a/bundles/binding/org.openhab.binding.velux/README.md b/bundles/binding/org.openhab.binding.velux/README.md
index 2fa62d4f3c7..ec99dcf4157 100644
--- a/bundles/binding/org.openhab.binding.velux/README.md
+++ b/bundles/binding/org.openhab.binding.velux/README.md
@@ -1,7 +1,7 @@
# Velux Binding
-This binding integrates the Velux devices with help of a gateway, the Velux Bridge KLF200.
+This binding integrates the Velux devices with help of a gateway, the Velux Bridge KLF200, which is able to control 200 actuators.
The Velux Binding interacts via the Velux Bridge with any [io-homecontrol](http://www.io-homecontrol.com/)-based
devices like window openers, shutters and others.
@@ -38,10 +38,11 @@ The binding can be configured by parameters in the global configuration file `op
|----------------|------------------------|:--------:|-----------------------------------------------------------|
| bridgeIPAddress| | Yes | Hostname or address for accessing the Velux Bridge. |
| bridgeProtocol | slip | No | Underlying communication protocol (http/https/slip). |
-| bridgeTCPPort | 80 | No | TCP port (80 or 51200)for accessing the Velux Bridge. |
+| bridgeTCPPort | 51200 | No | TCP port (80 or 51200) for accessing the Velux Bridge. |
| bridgePassword | velux123 | No | Password for authentication against the Velux Bridge.(**) |
-| timeoutMsecs | 2000 | No | Initial Connection timeout in milliseconds |
-| retries | 6 | No | Number of retries during I/O |
+| timeoutMsecs | 1000 | No | Initial Connection timeout in milliseconds |
+| retries | 5 | No | Number of retries during I/O |
+| refreshMsecs | 15000 | No | Refresh interval in milliseconds. |
(**) Note: This password is the API password that is printed on the back of the unit. Normally it differs from the password of the web frontend.
@@ -94,6 +95,8 @@ Optionally the subtype is enhanced with parameters like the appropriate name of
| action | Switch | Activates a set of predefined product settings | scene | required |
| silentMode | Switch | Modification of the silent mode of the defined product settings | scene | required |
| status | String | Current Bridge State (\*\*\*) | bridge | N/A |
+| reload | Switch | Reload information from bridge into binding | bridge | N/A |
+| timestamp | Number | Timestamp of last successful device interaction | bridge | N/A |
| doDetection | Switch | Start of the product detection mode | bridge | N/A |
| firmware | String | Software version of the Bridge | bridge | N/A |
| ipAddress | String | IP address of the Bridge | bridge | N/A |
@@ -106,10 +109,15 @@ Optionally the subtype is enhanced with parameters like the appropriate name of
| scenes | String | List of all defined scenes | bridge | N/A |
| check | String | Checks of current item configuratio | bridge | N/A |
| shutter | Rollershutter | Virtual rollershutter as combination of different scenes | bridge | required |
-| serial | Rollershutter | IO-Homecontrol'ed device | actuator | required |
-| serial | Switch | IO-Homecontrol'ed device | actuator | required |
+| serial | Rollershutter | IO-Homecontrol'ed device (\*\*\*\*) (\*\*\*\*\*) | actuator | required |
-Note (\*\*\*): The existence of this item triggers the continuous realtime status updates of any Velux item like shutters even if they are manually controlled by other controllers.
+Notes:
+(\*\*\*) The existence of this item triggers the continuous realtime status updates of any Velux item like shutters even if they are manually controlled by other controllers.
+
+(\*\*\*\*) To enable a complete invertion of all parameter values (i.e. for Velux windows), add a trailing star to the eight-byte serial number. For an example,
+see below at item `Velux DG Window Bathroom`.
+
+(\*\*\*\*\*) Somfy devices does not provides a valid serial number to the Velux KLF200 gateway: The bridge reports a registration of the serial number 00:00:00:00:00:00:00:00. Therefore the binding implements a fallback to allow an item specification with a actuator name instead of actuator serial number whenever such an invalid serial number occurs. For an example, see below at item `Velux OG Somfy Shutter`.
### Subtype Parameters
@@ -164,9 +172,18 @@ Switch V_DG_CLOSED "Velux DG closed" (gV) { velux="thing=scene;cha
// Velux Bridge parameters
-String V_FIRMWARE "Firmware [%s]" { velux="thing=bridge;channel=firmware" }
+Switch V_RELOAD "Reload info from bridge" { velux="thing=bridge;channel=reload" }
String V_STATUS "Status [%s]" { velux="thing=bridge;channel=status" }
-String V_CHECK "Velux Config Check [%s]" { velux="thing=bridge;channel=check" }
+String V_TIMESTAMP "Timestamp [%.1f]" { velux="thing=bridge;channel=timestamp" }
+String V_CHECK "Velux Config Check [%s]" { velux="thing=bridge;channel=check" }
+String V_FIRMWARE "Firmware [%s]" { velux="thing=bridge;channel=firmware" }
+String V_CONF_LAN_IP "KLF LAN IP [%s]" { velux="thing=bridge;channel=ipAddress" }
+String V_CONF_LAN_SUBNET "KLF LAN Subnet [%s]" { velux="thing=bridge;channel=subnetMask" }
+String V_CONF_LAN_GW "KLF LAN Gateway [%s]" { velux="thing=bridge;channel=defaultGW" }
+Switch V_CONF_LAN_DHCP "KLF LAN DHCP [%s]" { velux="thing=bridge;channel=DHCP" }
+String V_CONF_WLAN_SSID "KLF WLAN SSID [%s]" { velux="thing=bridge;channel=WLANSSID" }
+String V_CONF_WLAN_PW "KLF WLAN Password [%s]"{ velux="thing=bridge;channel=WLANPassword" }
+
// Velux Shutters
@@ -192,9 +209,17 @@ sitemap velux label="Velux Environment"
Switch item=V_DG_M_W
}
Frame label="Velux Bridge" {
- Text item=V_CHECK
+ Switch item=V_RELOAD
Text item=V_STATUS
+ Text item=V_TIMESTAMP
+ Text item=V_CHECK
Text item=V_FIRMWARE
+ Text item=V_CONF_LAN_IP
+ Text item=V_CONF_LAN_SUBNET
+ Text item=V_CONF_LAN_GW
+ Switch item=V_CONF_LAN_DHCP
+ Text item=V_CONF_WLAN_SSID
+ Text item=V_CONF_WLAN_PW
}
}
```
@@ -228,16 +253,27 @@ rule "PushButton of group gV"
```
// Velux Bridge parameters
-String V_FIRMWARE "Firmware [%s]" { velux="thing=bridge;channel=firmware" }
-String V_STATUS "Status [%s]" { velux="thing=bridge;channel=status" }
-String V_CHECK "Velux Config Check [%s]" { velux="thing=bridge;channel=check" }
+Switch V_RELOAD "Reload info from bridge" { velux="thing=bridge;channel=reload" }
+String V_STATUS "Status [%s]" { velux="thing=bridge;channel=status" }
+String V_TIMESTAMP "Timestamp [%.1f]" { velux="thing=bridge;channel=timestamp" }
+String V_CHECK "Velux Config Check [%s]" { velux="thing=bridge;channel=check" }
+String V_FIRMWARE "Firmware [%s]" { velux="thing=bridge;channel=firmware" }
+String V_CONF_LAN_IP "KLF LAN IP [%s]" { velux="thing=bridge;channel=ipAddress" }
+String V_CONF_LAN_SUBNET "KLF LAN Subnet [%s]" { velux="thing=bridge;channel=subnetMask" }
+String V_CONF_LAN_GW "KLF LAN Gateway [%s]" { velux="thing=bridge;channel=defaultGW" }
+Switch V_CONF_LAN_DHCP "KLF LAN DHCP [%s]" { velux="thing=bridge;channel=DHCP" }
+String V_CONF_WLAN_SSID "KLF WLAN SSID [%s]" { velux="thing=bridge;channel=WLANSSID" }
+String V_CONF_WLAN_PW "KLF WLAN Password [%s]" { velux="thing=bridge;channel=WLANPassword" }
+
// Velux Shutters
-Rollershutter V_DG_M_W "Velux DG Window Bathroom [%d]" { velux="thing=actuator;channel=serial#01:52:21:3E:26:0C:1B:01"}
+Rollershutter V_DG_M_W "Velux DG Window Bathroom [%d]" { velux="thing=actuator;channel=serial#01:52:21:3E:26:0C:1B:01*"}
Rollershutter V_DG_M_S "Velux DG Shutter Bathroom [%d]"{ velux="thing=actuator;channel=serial#01:52:00:21:00:07:00:02"}
Rollershutter V_DG_W_S "Velux DG Shutter West [%d]" { velux="thing=actuator;channel=serial#01:53:09:40:21:0C:2A:03" }
Rollershutter V_DG_E_S "Velux DG Shutter East [%d]" { velux="thing=actuator;channel=serial#11:56:32:14:5A:21:1C:04" }
+Rollershutter V_OG_W_S "Velux OG Somfy Shutter [%d]" { velux="thing=actuator;channel=serial#Bathroom" }
+
```
### Sitemap
@@ -252,18 +288,106 @@ sitemap velux label="Velux Environment"
Switch item=V_DG_M_W
}
Frame label="Velux Bridge" {
- Text item=V_CHECK
+ Switch item=V_RELOAD
Text item=V_STATUS
+ Text item=V_TIMESTAMP
+ Text item=V_CHECK
Text item=V_FIRMWARE
+ Text item=V_CONF_LAN_IP
+ Text item=V_CONF_LAN_SUBNET
+ Text item=V_CONF_LAN_GW
+ Switch item=V_CONF_LAN_DHCP
+ Text item=V_CONF_WLAN_SSID
+ Text item=V_CONF_WLAN_PW
}
}
```
-### Debugging
+## More automation samples
+
+At this point some interesting automation rules are included to demonstrate the power of this gateway to the io-homecontrol world.
+
+
+### 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
+ */
+
+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)
+ 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
+ */
+```
+
+## 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.
+With Karaf you can use the following command sequence:
+```
+log:set TRACE org.openhab.binding.velux
+log:tail
+```
+
+This, of course, is possible on command line with the commands:
+
+```
+% openhab-cli console log:set TRACE org.openhab.binding.velux
+% openhab-cli console log:tail org.openhab.binding.velux
+```
+
+On the other hand, if you prefer a textual configuration, you can append the logging definition with:
+
+```
+
+
+
+```
+
During startup of normal operations, there should be only some few messages within the logfile, like:
+
```
[INFO ] [.velux.internal.VeluxActivator] - velux binding has been started.
[INFO ] [.b.velux.internal.VeluxBinding] - Active items are: [V_DG_M_W, ..., V_DG_M_S].
@@ -304,9 +428,23 @@ Notes:
- 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.
+
+
## 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/binding/org.openhab.binding.velux/build.properties b/bundles/binding/org.openhab.binding.velux/build.properties
index 6db5343bc25..27f84634db8 100644
--- a/bundles/binding/org.openhab.binding.velux/build.properties
+++ b/bundles/binding/org.openhab.binding.velux/build.properties
@@ -2,6 +2,7 @@ source.. = src/main/java/
bin.includes = META-INF/,\
.,\
OSGI-INF/,\
+ lib/,\
NOTICE,\
ESH-INF/
output.. = target/classes/
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/VeluxBindingConstants.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/VeluxBindingConstants.java
index bd3ad0449c1..5f38c59c3df 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/VeluxBindingConstants.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/VeluxBindingConstants.java
@@ -39,6 +39,8 @@ public class VeluxBindingConstants {
// List of all bridge channel ids
public static final String CHANNEL_BRIDGE_STATUS = "status";
+ public static final String CHANNEL_BRIDGE_RELOAD = "reload";
+ public static final String CHANNEL_BRIDGE_TIMESTAMP = "timestamp";
public static final String CHANNEL_BRIDGE_DO_DETECTION = "doDetection";
public static final String CHANNEL_BRIDGE_FIRMWARE = "firmware";
public static final String CHANNEL_BRIDGE_IPADDRESS = "ipAddress";
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/VeluxBridge.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/VeluxBridge.java
index d112d52a4c0..d465ae1e701 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/VeluxBridge.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/VeluxBridge.java
@@ -84,6 +84,18 @@ public VeluxBridge(VeluxBridgeInstance bridgeInstance) {
this.bridgeInstance = bridgeInstance;
}
+ // Destructor methods
+
+ /**
+ * Destructor.
+ *
+ * Deinitializes the binding-wide instance.
+ *
+ */
+ public void shutdown() {
+ logger.trace("shutdown() called.");
+ }
+
// Class access methods
/**
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/VeluxBridgeGetFirmware.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/VeluxBridgeGetFirmware.java
index 5b0cc0a534c..fe82bb8b913 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/VeluxBridgeGetFirmware.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/VeluxBridgeGetFirmware.java
@@ -90,7 +90,7 @@ public Channel retrieve(VeluxBridge bridge) {
GetFirmware bcp = bridge.bridgeAPI().getFirmware();
if (bridge.bridgeCommunicate(bcp) && bcp.isCommunicationSuccessful()) {
- this.channel.firmwareVersion = new StringType(bcp.getFirmware().toString());
+ this.channel.firmwareVersion = new StringType(bcp.getFirmware().getfirmwareVersion());
this.channel.isRetrieved = true;
logger.trace("retrieve() found successfully firmware {}.", this.channel.firmwareVersion);
return channel;
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/common/BridgeAPI.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/common/BridgeAPI.java
index b9f8e188ada..c6c5202f96c 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/common/BridgeAPI.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/common/BridgeAPI.java
@@ -28,6 +28,8 @@
public interface BridgeAPI {
public boolean bridgeDirectCommunicate(BridgeCommunicationProtocol communication, boolean useAuthentication);
+ public long bridgeLastSuccessfullCommunication();
+
public CheckLostNodes checkLostNodes();
public DetectProducts detectProducts();
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JCcheckLostNodes.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JCcheckLostNodes.java
index db5d416d6f2..b281f59c8e0 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JCcheckLostNodes.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JCcheckLostNodes.java
@@ -37,7 +37,7 @@ public class JCcheckLostNodes extends CheckLostNodes implements JsonBridgeCommun
private static final String URL = "/api/v1/device";
private static final String DESCRIPTION = "check lost nodes";
- private Request request;
+ private Request request = new Request();
private Response response;
/*
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JCdetectProducts.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JCdetectProducts.java
index 10a14f2d7cd..a01b5570c1b 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JCdetectProducts.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JCdetectProducts.java
@@ -37,7 +37,7 @@ public class JCdetectProducts extends DetectProducts implements JsonBridgeCommun
private static final String URL = "/api/v1/products";
private static final String DESCRIPTION = "discover products";
- private Request request;
+ private Request request = new Request();
private Response response;
/*
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JCgetDeviceStatus.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JCgetDeviceStatus.java
index 2b4017fe754..2804520fd4d 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JCgetDeviceStatus.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JCgetDeviceStatus.java
@@ -40,7 +40,7 @@ public class JCgetDeviceStatus extends GetDeviceStatus implements JsonBridgeComm
private static final String URL = "/api/v1/device";
private static final String DESCRIPTION = "get device status";
- private Request request;
+ private Request request = new Request();
private Response response;
/*
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JCgetFirmware.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JCgetFirmware.java
index 2945ecea8e7..26831aee508 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JCgetFirmware.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JCgetFirmware.java
@@ -37,7 +37,7 @@ public class JCgetFirmware extends GetFirmware implements JsonBridgeCommunicatio
private static final String URL = "/api/v1/settings";
private static final String DESCRIPTION = "get firmware version";
- private Request request;
+ private Request request = new Request();
private Response response;
/*
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JCgetProducts.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JCgetProducts.java
index 54b044fbd95..db35e770c5d 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JCgetProducts.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JCgetProducts.java
@@ -40,7 +40,7 @@ public class JCgetProducts extends GetProducts implements JsonBridgeCommunicatio
private static final String URL = "/api/v1/products";
private static final String DESCRIPTION = "get Products";
- private Request request;
+ private Request request = new Request();
private Response response;
/**
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JCgetScenes.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JCgetScenes.java
index 181ad32ff23..e46e05829cf 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JCgetScenes.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JCgetScenes.java
@@ -40,7 +40,7 @@ public class JCgetScenes extends GetScenes implements JsonBridgeCommunicationPro
private static final String URL = "/api/v1/scenes";
private static final String DESCRIPTION = "get Scenes";
- private Request request;
+ private Request request = new Request();
private Response response;
/**
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JClogout.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JClogout.java
index 0381a883e19..322dcd83859 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JClogout.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JClogout.java
@@ -37,7 +37,7 @@ public class JClogout extends Logout implements JsonBridgeCommunicationProtocol
private static final String URL = "/api/v1/auth";
private static final String DESCRIPTION = "deauthenticate / logout";
- private Request request;
+ private Request request = new Request();
private Response response;
/*
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JsonBridgeAPI.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JsonBridgeAPI.java
index 7846130f86c..9304f6b2b8e 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JsonBridgeAPI.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JsonBridgeAPI.java
@@ -87,6 +87,11 @@ public boolean bridgeDirectCommunicate(BridgeCommunicationProtocol communication
return this.bridgeDirectCommunicate((JsonBridgeCommunicationProtocol) communication, useAuthentication);
}
+ @Override
+ public long bridgeLastSuccessfullCommunication() {
+ return this.lastSuccessfullCommunicationMillis;
+ }
+
@Override
public CheckLostNodes checkLostNodes() {
return CHECKLOSTNODES;
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JsonVeluxBridge.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JsonVeluxBridge.java
index d6e8b6c5bc1..6cb8ea16b5f 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JsonVeluxBridge.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/json/JsonVeluxBridge.java
@@ -65,6 +65,12 @@ public class JsonVeluxBridge extends VeluxBridge {
*/
public Set supportedProtocols;
+ /**
+ * Timestamp of last successfull communication in milliseconds.
+ *
+ */
+ protected long lastSuccessfullCommunicationMillis = 0;
+
/**
* Handler passing the interface methods to other classes.
* Can be accessed via method {@link org.openhab.binding.velux.bridge.common.json.bridgeAPI bridgeAPI}.
@@ -104,12 +110,12 @@ public BridgeAPI bridgeAPI() {
/**
* Base level communication with the Velux bridge.
*
- * @param url as String describing the Service Access Point location i.e. http://localhost/api .
- * @param authentication as String providing the Authentication token to be passed with the request header.
- * @param Request as Object representing the structure of the message request body to be converted into
- * JSON.
+ * @param url as String describing the Service Access Point location i.e. http://localhost/api .
+ * @param authentication as String providing the Authentication token to be passed with the request header.
+ * @param Request as Object representing the structure of the message request body to be converted into
+ * JSON.
* @param classOfResponse as Class representing the expected structure of the message response body to be converted
- * from JSON.
+ * from JSON.
* @return response of type Object containing all resulting informations, i.e. device status, errors a.s.o.
* Will
* return
@@ -154,6 +160,7 @@ private Object io(String url, String authentication, Object Request, Class class
logger.trace("io() cleaned response {}.", jsonResponse);
try {
Object response = gson.fromJson(jsonResponse, classOfResponse);
+ lastSuccessfullCommunicationMillis = System.currentTimeMillis();
return response;
} catch (JsonSyntaxException jse) {
logger.info("io(): Exception occurred on deserialization: {}, aborting.", jse.getMessage());
@@ -180,12 +187,12 @@ private Object io(String url, String authentication, Object Request, Class class
/**
* Initializes an authenticated communication with the {@link JsonVeluxBridge Velux bridge}.
*
- * @param url as String describing the Service Access Point location i.e. http://localhost/api .
- * @param authentication as String providing the Authentication token to be passed with the request header.
- * @param Request as Object representing the structure of the message request body to be converted into
- * JSON.
+ * @param url as String describing the Service Access Point location i.e. http://localhost/api .
+ * @param authentication as String providing the Authentication token to be passed with the request header.
+ * @param Request as Object representing the structure of the message request body to be converted into
+ * JSON.
* @param classOfResponse as Class representing the expected structure of the message response body to be converted
- * from JSON.
+ * from JSON.
* @return response of type T containing all resulting informations, i.e. device status, errors a.s.o. Will
* return
* null in case of communication or decoding error.
@@ -201,12 +208,12 @@ private Object ioAuthenticated(String url, String authentication, Object Request
/**
* Initializes an unauthenticated communication with the {@link JsonVeluxBridge Velux bridge}.
*
- * @param url as String describing the Service Access Point location i.e. http://localhost/api .
- * @param Request as Object representing the structure of the message request body to be converted into
- * JSON.
+ * @param url as String describing the Service Access Point location i.e. http://localhost/api .
+ * @param Request as Object representing the structure of the message request body to be converted into
+ * JSON.
* @param classOfResponse as Class representing the expected structure of the message response body to be converted
- * from JSON.
- * @param generic response based on classOfResponse.
+ * from JSON.
+ * @param generic response based on classOfResponse.
* @return response of type Object containing all resulting informations, i.e. device status, errors a.s.o.
* Will
* return
@@ -225,10 +232,10 @@ private Object ioUnauthenticated(String url, Object Request, Class classOfRespon
* based on the Basic I/O interface {@link VeluxBridge} and parameters
* passed as arguments (see below) and provided by {@link VeluxBridgeConfiguration}.
*
- * @param communication Structure of interface type {@link JsonBridgeCommunicationProtocol} describing the
- * intended
- * communication,
- * that is request and response interactions as well as appropriate URL definition.
+ * @param communication Structure of interface type {@link JsonBridgeCommunicationProtocol} describing the
+ * intended
+ * communication,
+ * that is request and response interactions as well as appropriate URL definition.
* @param useAuthentication boolean flag to decide whether to use authenticated communication.
* @return response of type boolean will indicate the success of the communication.
*/
@@ -243,6 +250,11 @@ public synchronized boolean bridgeDirectCommunicate(JsonBridgeCommunicationProto
.concat(communication.getURL());
logger.trace("bridgeCommunicate(): using SAP {}.", sapURL);
Object getRequest = communication.getObjectOfRequest();
+ if (getRequest == null) {
+ logger.warn("bridgeCommunicate(): Internal error: Empty object structure ({}), should never occur.",
+ communication.name());
+ return false;
+ }
Class> classOfResponse = communication.getClassOfResponse();
Object response;
@@ -252,9 +264,9 @@ public synchronized boolean bridgeDirectCommunicate(JsonBridgeCommunicationProto
} else {
response = ioUnauthenticated(sapURL, getRequest, classOfResponse);
}
+ communication.setResponse(response);
logger.trace("bridgeCommunicate(): communication result is {}, returning details.",
communication.isCommunicationSuccessful());
- communication.setResponse(response);
return true;
} catch (IOException ioe) {
logger.warn("bridgeCommunicate(): Exception occurred on accessing {}: {}.", sapURL, ioe.getMessage());
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SCgetProduct.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SCgetProduct.java
index cc3b9f95840..4456cd383e2 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SCgetProduct.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SCgetProduct.java
@@ -192,7 +192,7 @@ public void setResponse(short responseCommand, byte[] thisResponseData) {
break;
}
- logger.trace("setResponse(): nodeId={} (requested {}).", ntfNodeID);
+ logger.trace("setResponse(): nodeId={}.", ntfNodeID);
logger.trace("setResponse(): nodeName={}.", nodeName);
logger.trace("setResponse(): productNodeTypeSubType={}.", productNodeTypeSubType);
logger.trace("setResponse(): productNodeTypeSubTypeSYMBOLIC={}.",
@@ -201,10 +201,20 @@ public void setResponse(short responseCommand, byte[] thisResponseData) {
logger.trace("setResponse(): productCurrentPosition={}.", productCurrentPosition);
logger.trace("setResponse(): productNodeVariation={}.", productNodeVariation);
+ String commonSerialNumber = new Packet(productSerialNumber).toString(":");
+ if ((productSerialNumber[0] == 0) && (productSerialNumber[1] == 0) && (productSerialNumber[2] == 0)
+ && (productSerialNumber[3] == 0) && (productSerialNumber[4] == 0)
+ && (productSerialNumber[5] == 0) && (productSerialNumber[6] == 0)
+ && (productSerialNumber[7] == 0)) {
+ commonSerialNumber = new String(nodeName);
+ logger.debug("setResponse(): device provided invalid serial number, using name '{}' instead.",
+ commonSerialNumber);
+ }
+
product = new VeluxProduct(new VeluxProductName(nodeName), VeluxProductType.get(productNodeTypeSubType),
new ProductBridgeIndex(ntfNodeID), nodeOrder, nodePlacement, productVelocity,
- productNodeVariation, productPowerMode, new Packet(productSerialNumber).toString(":"),
- productState, productCurrentPosition, productTarget, productRemainingTime, productTimeStamp);
+ productNodeVariation, productPowerMode, commonSerialNumber, productState,
+ productCurrentPosition, productTarget, productRemainingTime, productTimeStamp);
success = true;
break;
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SCgetProducts.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SCgetProducts.java
index 0332e6f0a66..1bdd158544f 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SCgetProducts.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SCgetProducts.java
@@ -103,6 +103,7 @@ public void setResponse(short responseCommand, byte[] thisResponseData) {
Packet responseData = new Packet(thisResponseData);
switch (Command.get(responseCommand)) {
case GW_GET_ALL_NODES_INFORMATION_CFM:
+ logger.trace("setResponse(): got GW_GET_ALL_NODES_INFORMATION_CFM.");
if (!KLF200Response.isLengthValid(logger, responseCommand, thisResponseData, 2)) {
finished = true;
break;
@@ -132,6 +133,7 @@ public void setResponse(short responseCommand, byte[] thisResponseData) {
}
break;
case GW_GET_ALL_NODES_INFORMATION_NTF:
+ logger.trace("setResponse(): got GW_GET_ALL_NODES_INFORMATION_NTF.");
// ToDo: discuss with Velux the real length of response.
if (!KLF200Response.isLengthValid(logger, responseCommand, thisResponseData, 124)) {
finished = true;
@@ -145,44 +147,70 @@ public void setResponse(short responseCommand, byte[] thisResponseData) {
}
// Extracting information items
int ntfNodeID = responseData.getOneByteValue(0);
+ logger.trace("setResponse(): ntfNodeID={}.", ntfNodeID);
int ntfOrder = responseData.getTwoByteValue(1);
+ logger.trace("setResponse(): ntfOrder={}.", ntfOrder);
int ntfPlacement = responseData.getOneByteValue(3);
+ logger.trace("setResponse(): ntfPlacement={}.", ntfPlacement);
String ntfName = responseData.getString(4, 64);
+ logger.trace("setResponse(): ntfName={}.", ntfName);
int ntfVelocity = responseData.getOneByteValue(68);
+ logger.trace("setResponse(): ntfVelocity={}.", ntfVelocity);
int ntfNodeTypeSubType = responseData.getTwoByteValue(69);
+ logger.trace("setResponse(): ntfNodeTypeSubType={}.", ntfNodeTypeSubType);
@SuppressWarnings("unused")
int ntfProductGroup = responseData.getOneByteValue(71);
+ logger.trace("setResponse(): ntfProductGroup={}.", ntfProductGroup);
int ntfProductType = responseData.getOneByteValue(72);
+ logger.trace("setResponse(): ntfProductType={}.", ntfProductType);
int ntfNodeVariation = responseData.getOneByteValue(73);
+ logger.trace("setResponse(): ntfNodeVariation={}.", ntfNodeVariation);
int ntfPowerMode = responseData.getOneByteValue(74);
+ logger.trace("setResponse(): ntfPowerMode={}.", ntfPowerMode);
@SuppressWarnings("unused")
int ntfBuildNumber = responseData.getOneByteValue(75);
byte[] ntfSerialNumber = responseData.getByteArray(76, 8);
+ logger.trace("setResponse(): ntfSerialNumber={}.", ntfSerialNumber);
int ntfState = responseData.getOneByteValue(84);
+ logger.trace("setResponse(): ntfState={}.", ntfState);
int ntfCurrentPosition = responseData.getTwoByteValue(85);
+ logger.trace("setResponse(): ntfCurrentPosition={}.", ntfCurrentPosition);
int ntfTarget = responseData.getTwoByteValue(87);
+ logger.trace("setResponse(): ntfTarget={}.", ntfTarget);
@SuppressWarnings("unused")
int ntfFP1CurrentPosition = responseData.getTwoByteValue(89);
+ logger.trace("setResponse(): ntfFP1CurrentPosition={}.", ntfFP1CurrentPosition);
@SuppressWarnings("unused")
int ntfFP2CurrentPosition = responseData.getTwoByteValue(91);
+ logger.trace("setResponse(): ntfFP2CurrentPosition={}.", ntfFP2CurrentPosition);
@SuppressWarnings("unused")
int ntfFP3CurrentPosition = responseData.getTwoByteValue(93);
+ logger.trace("setResponse(): ntfFP3CurrentPosition={}.", ntfFP3CurrentPosition);
@SuppressWarnings("unused")
int ntfFP4CurrentPosition = responseData.getTwoByteValue(95);
+ logger.trace("setResponse(): ntfFP4CurrentPosition={}.", ntfFP4CurrentPosition);
int ntfRemainingTime = responseData.getTwoByteValue(97);
+ logger.trace("setResponse(): ntfRemainingTime={}.", ntfRemainingTime);
int ntfTimeStamp = responseData.getFourByteValue(99);
+ logger.trace("setResponse(): ntfTimeStamp={}.", ntfTimeStamp);
@SuppressWarnings("unused")
int ntfNbrOfAlias = responseData.getOneByteValue(103);
+ logger.trace("setResponse(): ntfNbrOfAlias={}.", ntfNbrOfAlias);
@SuppressWarnings("unused")
int ntfAliasOne = responseData.getFourByteValue(104);
+ logger.trace("setResponse(): ntfAliasOne={}.", ntfAliasOne);
@SuppressWarnings("unused")
int ntfAliasTwo = responseData.getFourByteValue(108);
+ logger.trace("setResponse(): ntfAliasTwo={}.", ntfAliasTwo);
@SuppressWarnings("unused")
int ntfAliasThree = responseData.getFourByteValue(112);
+ logger.trace("setResponse(): ntfAliasThree={}.", ntfAliasThree);
@SuppressWarnings("unused")
int ntfAliasFour = responseData.getFourByteValue(116);
+ logger.trace("setResponse(): ntfAliasFour={}.", ntfAliasFour);
@SuppressWarnings("unused")
int ntfAliasFive = responseData.getFourByteValue(120);
+ logger.trace("setResponse(): ntfAliasFive={}.", ntfAliasFive);
logger.trace("setResponse(): nodeId={}.", ntfNodeID);
logger.trace("setResponse(): nodeName={}.", ntfName);
@@ -192,16 +220,25 @@ public void setResponse(short responseCommand, byte[] thisResponseData) {
logger.trace("setResponse(): productCurrentPosition={}.", ntfCurrentPosition);
logger.trace("setResponse(): productNodeVariation={}.", ntfNodeVariation);
+ String commonSerialNumber = new Packet(ntfSerialNumber).toString(":");
+ if ((ntfSerialNumber[0] == 0) && (ntfSerialNumber[1] == 0) && (ntfSerialNumber[2] == 0)
+ && (ntfSerialNumber[3] == 0) && (ntfSerialNumber[4] == 0) && (ntfSerialNumber[5] == 0)
+ && (ntfSerialNumber[6] == 0) && (ntfSerialNumber[7] == 0)) {
+ commonSerialNumber = new String(ntfName);
+ logger.debug("setResponse(): device provided invalid serial number, using name '{}' instead.",
+ commonSerialNumber);
+ }
+
VeluxProduct product = new VeluxProduct(new VeluxProductName(ntfName),
VeluxProductType.get(ntfNodeTypeSubType), new ProductBridgeIndex(ntfNodeID), ntfOrder,
- ntfPlacement, ntfVelocity, ntfNodeVariation, ntfPowerMode,
- new Packet(ntfSerialNumber).toString(":"), ntfState, ntfCurrentPosition, ntfTarget,
- ntfRemainingTime, ntfTimeStamp);
+ ntfPlacement, ntfVelocity, ntfNodeVariation, ntfPowerMode, commonSerialNumber, ntfState,
+ ntfCurrentPosition, ntfTarget, ntfRemainingTime, ntfTimeStamp);
productArray[nextProductArrayItem++] = product;
success = true;
break;
case GW_GET_ALL_NODES_INFORMATION_FINISHED_NTF:
- logger.trace("setResponse(): finished-packet received.");
+ logger.trace("setResponse(): got GW_GET_ALL_NODES_INFORMATION_FINISHED_NTF.");
+ logger.debug("setResponse(): finished-packet received.");
success = true;
finished = true;
break;
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SCgetScenes.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SCgetScenes.java
index e88b50eef2f..7fe795efc02 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SCgetScenes.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SCgetScenes.java
@@ -102,6 +102,7 @@ public void setResponse(short responseCommand, byte[] thisResponseData) {
if (ntfTotalNumberOfObjects == 0) {
logger.trace("setResponse(): no scenes defined.");
success = true;
+ finished = true;
} else {
logger.trace("setResponse(): {} scenes defined.", ntfTotalNumberOfObjects);
}
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SCgetWLANConfig.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SCgetWLANConfig.java
index 0bddbb71d41..e93e799b802 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SCgetWLANConfig.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SCgetWLANConfig.java
@@ -116,7 +116,7 @@ public boolean isCommunicationSuccessful() {
public VeluxGwWLAN getWLANConfig() {
logger.trace("getWLANConfig() called.");
// ToDo: Velux will provide an API for retrieving the SSID.
- return new VeluxGwWLAN("SSID", "Password");
+ return new VeluxGwWLAN("***yet-unsupported-by-firmware**", "***yet-unsupported-by-firmware**");
}
}
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SCrunScene.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SCrunScene.java
index c73d2c13b0c..3bf4cf32587 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SCrunScene.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SCrunScene.java
@@ -165,15 +165,65 @@ public void setResponse(short responseCommand, byte[] thisResponseData) {
break;
case GW_COMMAND_RUN_STATUS_NTF:
- logger.warn("setResponse(): received GW_COMMAND_RUN_STATUS_NTF, continuing.");
+ logger.trace("setResponse(): received GW_COMMAND_RUN_STATUS_NTF, continuing.");
+ if (!KLF200Response.isLengthValid(logger, responseCommand, thisResponseData, 13)) {
+ logger.trace("setResponse(): GW_COMMAND_RUN_STATUS_NTF received with invalid length.");
+ finished = true;
+ break;
+ }
+ // Extracting information items
+ int ntfSessionID = responseData.getTwoByteValue(0);
+ int ntfStatusID = responseData.getOneByteValue(2);
+ int ntfIndex = responseData.getOneByteValue(3);
+ int ntfNodeParameter = responseData.getOneByteValue(4);
+ int ntfParameterValue = responseData.getTwoByteValue(5);
+ int ntfRunStatus = responseData.getOneByteValue(7);
+ int ntfStatusReply = responseData.getOneByteValue(8);
+ int ntfInformationCode = responseData.getFourByteValue(9);
+
+ logger.trace("setResponse(): SessionID={}.", ntfSessionID);
+ logger.trace("setResponse(): StatusID={}.", ntfStatusID);
+ logger.trace("setResponse(): Index={}.", ntfIndex);
+ logger.trace("setResponse(): NodeParameter={}.", ntfNodeParameter);
+ logger.trace("setResponse(): ParameterValue={}.", ntfParameterValue);
+ logger.trace("setResponse(): RunStatus={}.", ntfRunStatus);
+ logger.trace("setResponse(): StatusReply={}.", ntfStatusReply);
+ logger.trace("setResponse(): InformationCode={}.", ntfInformationCode);
+
break;
case GW_COMMAND_REMAINING_TIME_NTF:
- logger.warn("setResponse(): received GW_COMMAND_REMAINING_TIME_NTF, continuing.");
+ logger.trace("setResponse(): received GW_COMMAND_REMAINING_TIME_NTF, continuing.");
+ if (!KLF200Response.isLengthValid(logger, responseCommand, thisResponseData, 6)) {
+ logger.trace("setResponse(): GW_COMMAND_REMAINING_TIME_NTF received with invalid length.");
+ finished = true;
+ break;
+ }
+ // Extracting information items
+ ntfSessionID = responseData.getTwoByteValue(0);
+ ntfIndex = responseData.getOneByteValue(2);
+ ntfNodeParameter = responseData.getOneByteValue(3);
+ int ntfSeconds = responseData.getTwoByteValue(4);
+
+ logger.trace("setResponse(): SessionID={}.", ntfSessionID);
+ logger.trace("setResponse(): Index={}.", ntfIndex);
+ logger.trace("setResponse(): NodeParameter={}.", ntfNodeParameter);
+ logger.trace("setResponse(): Seconds={}.", ntfSeconds);
+
break;
case GW_SESSION_FINISHED_NTF:
- logger.warn("setResponse(): received GW_SESSION_FINISHED_NTF.");
+ logger.trace("setResponse(): received GW_SESSION_FINISHED_NTF.");
+ if (!KLF200Response.isLengthValid(logger, responseCommand, thisResponseData, 2)) {
+ logger.trace("setResponse(): GW_SESSION_FINISHED_NTF received with invalid length.");
+ finished = true;
+ break;
+ }
+ // Extracting information items
+ ntfSessionID = responseData.getTwoByteValue(0);
+
+ logger.trace("setResponse(): SessionID={}.", ntfSessionID);
+
success = true;
finished = true;
break;
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SlipBridgeAPI.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SlipBridgeAPI.java
index 9943987bdca..734372d08d2 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SlipBridgeAPI.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SlipBridgeAPI.java
@@ -111,6 +111,11 @@ public boolean bridgeDirectCommunicate(BridgeCommunicationProtocol communication
return this.bridgeDirectCommunicate((SlipBridgeCommunicationProtocol) communication, useAuthentication);
}
+ @Override
+ public long bridgeLastSuccessfullCommunication() {
+ return this.lastSuccessfullCommunicationMillis;
+ }
+
@Override
public CheckLostNodes checkLostNodes() {
return CHECKLOSTNODES;
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SlipVeluxBridge.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SlipVeluxBridge.java
index 83663f90e6a..78967447a04 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SlipVeluxBridge.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/SlipVeluxBridge.java
@@ -64,6 +64,12 @@ public class SlipVeluxBridge extends VeluxBridge {
*/
public Set supportedProtocols = new TreeSet();
+ /**
+ * Timestamp of last successfull communication in milliseconds.
+ *
+ */
+ protected long lastSuccessfullCommunicationMillis = 0;
+
private SSLconnection connectivity = null;
private final byte[] emptyPacket = new byte[0];
@@ -88,6 +94,27 @@ public SlipVeluxBridge(VeluxBridgeInstance bridgeInstance) {
supportedProtocols.add("slip");
}
+ /**
+ * Destructor.
+ *
+ * Deinitializes the binding-wide instance.
+ *
+ */
+ @Override
+ public void shutdown() {
+ logger.trace("shutdown() called.");
+ if (connectivity != null) {
+ logger.trace("shutdown(): shutting down connection.");
+ try {
+ connectivity.close();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ logger.warn("shutdown(): raised an error during connection close: {}.", e.getMessage());
+ }
+ connectivity = null;
+ }
+ }
+
/**
* Provides information about the base-level communication method and
* any kind of available gateway interactions.
@@ -151,6 +178,7 @@ private byte[] io(String host, int port, byte[] request) throws ConnectException
connectivity.send(request);
} catch (Exception e) {
logger.warn("io(): raised an error during sending: {}.", e.getMessage());
+ break;
}
// Give the bridge some time to breathe
@@ -172,6 +200,7 @@ private byte[] io(String host, int port, byte[] request) throws ConnectException
} else {
logger.debug("io(): received packet with {} bytes.", packet.length);
}
+ lastSuccessfullCommunicationMillis = System.currentTimeMillis();
logger.trace("io() finished.");
return packet;
} catch (IOException ioe) {
@@ -188,7 +217,9 @@ private byte[] io(String host, int port, byte[] request) throws ConnectException
}
}
} while (retryCount++ < bridgeInstance.veluxBridgeConfiguration().retries);
- logger.info("io(): socket I/O failed {} times.", bridgeInstance.veluxBridgeConfiguration().retries);
+ if (retryCount >= bridgeInstance.veluxBridgeConfiguration().retries) {
+ logger.info("io(): socket I/O failed {} times.", bridgeInstance.veluxBridgeConfiguration().retries);
+ }
logger.trace("io(): shutting down connection.");
connectivity.close();
connectivity = null;
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/util/Packet.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/util/Packet.java
index 30422ca497b..20bf800a23d 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/util/Packet.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/bridge/slip/util/Packet.java
@@ -61,7 +61,7 @@ public class Packet {
/**
* Constructor: Create a {@link org.openhab.binding.velux.bridge.slip.util.Packet Packet} out of a sequence of
* bytes.
- *
+ *
* @param thisData Packet as Array of bytes.
*/
public Packet(byte[] thisData) {
@@ -96,7 +96,7 @@ public byte[] toByteArray() {
/**
* Returns a part of the {@link org.openhab.binding.velux.bridge.slip.util.Packet Packet} as sequence of bytes
* starting at position (n) up to the position (n+length-1).
- *
+ *
* @param position Position (n) within the packet.
* @param length Length of the intended slice as int.
* @return packet of type Array-of-byte.
@@ -160,7 +160,7 @@ public void setOneByteValue(int position, int value) {
*
* Note: Big-endian LSB-0 encoding.
*
- *
+ *
* @param position Position (n) within the packet.
* @return value of type int.
*/
@@ -173,7 +173,7 @@ public int getTwoByteValue(int position) {
*
* Note: Big-endian LSB-0 encoding.
*
- *
+ *
* @param position Position (n) within the packet.
* @param value of type int.
*/
@@ -187,7 +187,7 @@ public void setTwoByteValue(int position, int value) {
*
* Note: Big-endian LSB-0 encoding.
*
- *
+ *
* @param position Position (n) within the packet.
* @return value of type int.
*/
@@ -201,7 +201,7 @@ public int getFourByteValue(int position) {
*
* Note: Big-endian LSB-0 encoding.
*
- *
+ *
* @param position Position (n) within the packet.
* @param value of type int.
*/
@@ -217,7 +217,7 @@ public void setFourByteValue(int position, int value) {
*
* Note: Any trailing null char will be eliminated.
*
- *
+ *
* @param position Position (n) within the packet.
* @param length Length of the intended slice as int.
* @return value of type String.
@@ -232,7 +232,7 @@ public String getString(int position, int length) {
*
* Note: The trailing null char will not be stored.
*
- *
+ *
* @param position Position (n) within the packet.
* @param text of type String.
*/
@@ -247,7 +247,7 @@ public void setString(int position, String text) {
/**
* Returns the hex char string representing the byte.
- *
+ *
* @param oneByte of type byte to be converted.
* @return hexByteString of type String.
*/
@@ -261,13 +261,13 @@ public static int byteArrayToInt(byte[] data) {
/**
* Returns the dotted string representing an IP address.
- *
+ *
* @param ipAddress of type int to be converted.
* @return ipAddressString of type String.
*/
public static String intToIPAddressString(int ipAddress) {
- return String.format("%d.%d.%d.%d", (byte) ((ipAddress >>> 24) & 0xFF), (byte) ((ipAddress >>> 16) & 0xFF),
- (byte) ((ipAddress >>> 8) & 0xFF), (byte) (ipAddress & 0xFF));
+ return String.format("%d.%d.%d.%d", ((ipAddress >>> 24) & 0xFF), ((ipAddress >>> 16) & 0xFF),
+ ((ipAddress >>> 8) & 0xFF), (ipAddress & 0xFF));
}
}
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/handler/VeluxBridgeHandlerOH1.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/handler/VeluxBridgeHandlerOH1.java
index 339e52f03b5..e301c173188 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/handler/VeluxBridgeHandlerOH1.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/handler/VeluxBridgeHandlerOH1.java
@@ -214,6 +214,13 @@ public VeluxBridgeHandlerOH1(VeluxBridgeConfiguration veluxBridgeConfiguration)
@Override
public void finalize() {
logger.trace("finalize({}) called.", this);
+ if (myJsonBridge != null) {
+ myJsonBridge.shutdown();
+ }
+ if (mySlipBridge != null) {
+ mySlipBridge.shutdown();
+ }
+ logger.trace("finalize() done.");
}
/***
@@ -267,10 +274,21 @@ private void bridgeParamsUpdated() {
}
veluxBridgeConfiguration.hasChanged = false;
- logger.info("{} Bridge is online, now.", VeluxBindingConstants.BINDING_ID);
+ logger.info("{} Bridge is online with {} scenes and {} actuators, now.", VeluxBindingConstants.BINDING_ID,
+ bridgeParameters.scenes.getChannel().existingScenes.getNoMembers(),
+ bridgeParameters.actuators.getChannel().existingProducts.getNoMembers());
logger.trace("bridgeParamsUpdated() successfully finished.");
}
+ private boolean _actuatorIsInverted(String actuatorSerial) {
+ return actuatorSerial.charAt(actuatorSerial.length() - 1) == '*';
+ }
+
+ private String _actuatorCleanupSerial(String actuatorSerial) {
+ return _actuatorIsInverted(actuatorSerial) ? actuatorSerial.substring(0, actuatorSerial.length() - 1)
+ : actuatorSerial;
+ }
+
/**
* General two-way communication method.
*
@@ -324,6 +342,12 @@ public void handleCommandOnChannel(String itemName, Command command, VeluxBindin
}
break;
+ case BRIDGE_TIMESTAMP:
+ DecimalType timestampValue = new DecimalType(
+ thisBridge.bridgeAPI().bridgeLastSuccessfullCommunication());
+ newState = timestampValue;
+ break;
+
case BRIDGE_FIRMWARE:
bridgeParameters.firmware = new VeluxBridgeGetFirmware().retrieve(thisBridge);
if (bridgeParameters.firmware != null && bridgeParameters.firmware.isRetrieved) {
@@ -335,7 +359,7 @@ public void handleCommandOnChannel(String itemName, Command command, VeluxBindin
case BRIDGE_SUBNETMASK:
case BRIDGE_DEFAULTGW:
case BRIDGE_DHCP:
- bridgeParameters.lanConfig = new VeluxBridgeLANConfig().retrieve(myJsonBridge);
+ bridgeParameters.lanConfig = new VeluxBridgeLANConfig().retrieve(thisBridge);
if (bridgeParameters.lanConfig != null && bridgeParameters.lanConfig.isRetrieved) {
switch (config.getBindingItemType()) {
case BRIDGE_IPADDRESS:
@@ -427,6 +451,9 @@ public void handleCommandOnChannel(String itemName, Command command, VeluxBindin
}
actuatorSerial = config.getBindingConfig();
logger.trace("handleCommandOnChannel(): actuatorSerial={}", actuatorSerial);
+ boolean isInverted = _actuatorIsInverted(actuatorSerial);
+ actuatorSerial = _actuatorCleanupSerial(actuatorSerial);
+ logger.trace("handleCommandOnChannel(): actuatorSerial={}", actuatorSerial);
if (!bridgeParameters.actuators.getChannel().existingProducts
.isRegistered(actuatorSerial)) {
@@ -449,10 +476,14 @@ public void handleCommandOnChannel(String itemName, Command command, VeluxBindin
if (bcp.isCommunicationSuccessful()) {
try {
PercentType positionAsPercent = new VeluxProductPosition(
- thisProduct.getCurrentPosition()).getPositionAsPercentType();
- logger.trace("handleCommandOnChannel(): found actuator at level {}.",
- positionAsPercent);
- newState = positionAsPercent;
+ thisProduct.getCurrentPosition()).getPositionAsPercentType(isInverted);
+ if (positionAsPercent != null) {
+ logger.trace("handleCommandOnChannel(): found actuator at level {}.",
+ positionAsPercent);
+ newState = positionAsPercent;
+ } else {
+ logger.trace("handleCommandOnChannel(): level of actuator is unknown.");
+ }
} catch (Exception e) {
logger.warn("handleCommandOnChannel(): getProducts() exception: {}.",
e.getMessage());
@@ -484,6 +515,15 @@ public void handleCommandOnChannel(String itemName, Command command, VeluxBindin
String sceneName;
switch (config.getBindingItemType()) {
+ case BRIDGE_RELOAD:
+ if (command.equals(OnOffType.ON)) {
+ logger.trace("handleCommandOnChannel(): about to reload informations from veluxBridge.");
+ bridgeParamsUpdated();
+ } else {
+ logger.trace("handleCommandOnChannel(): ignoring OFF command.");
+ }
+ break;
+
case SCENE_ACTION:
assert bridgeParameters.scenes
.getChannel().existingScenes != null : "VeluxBridgeHandlerOH1.existingScenes not initialized.";
@@ -506,28 +546,34 @@ public void handleCommandOnChannel(String itemName, Command command, VeluxBindin
break;
case BRIDGE_SHUTTER:
- if (true) {
- logger.trace("handleCommandOnChannel(): working on virtual rollershutter.");
- VeluxRSBindingConfig thisRSBindingConfig = (VeluxRSBindingConfig) config;
- Integer rollershutterLevel = thisRSBindingConfig.getLevel();
- logger.trace("handleCommandOnChannel(): current level is {}.", rollershutterLevel);
- if ((UpDownType) command == UpDownType.UP) {
- rollershutterLevel = thisRSBindingConfig.getNextDescendingLevel();
- } else if ((UpDownType) command == UpDownType.DOWN) {
- rollershutterLevel = thisRSBindingConfig.getNextAscendingLevel();
- } else {
- logger.info("handleCommandOnChannel(): ignoring command {}.", command);
- break;
- }
- logger.trace("handleCommandOnChannel(): next level is {}.", rollershutterLevel);
- sceneName = thisRSBindingConfig.getSceneName();
- assert eventPublisher != null : "eventPublisher not initialized.";
- eventPublisher.postUpdate(itemName, new PercentType(rollershutterLevel));
- VeluxScene thisScene = bridgeParameters.scenes.getChannel().existingScenes
- .get(new SceneName(sceneName));
- logger.trace("handleCommandOnChannel(): execution scene {}.", thisScene);
- new VeluxBridgeRunScene().execute(thisBridge, thisScene.getBridgeSceneIndex().toInt());
+ logger.trace("handleCommandOnChannel(): working on virtual rollershutter.");
+ VeluxRSBindingConfig thisRSBindingConfig = (VeluxRSBindingConfig) config;
+ Integer rollershutterLevel = thisRSBindingConfig.getLevel();
+ logger.trace("handleCommandOnChannel(): current level is {}.", rollershutterLevel);
+ if ((UpDownType) command == UpDownType.UP) {
+ rollershutterLevel = thisRSBindingConfig.getNextDescendingLevel();
+ } else if ((UpDownType) command == UpDownType.DOWN) {
+ rollershutterLevel = thisRSBindingConfig.getNextAscendingLevel();
+ } else {
+ logger.info("handleCommandOnChannel(): ignoring command {}.", command);
+ break;
}
+ logger.trace("handleCommandOnChannel(): next level is {}.", rollershutterLevel);
+ sceneName = thisRSBindingConfig.getSceneName();
+ logger.trace("handleCommandOnChannel(): scene name is {}.", sceneName);
+ assert eventPublisher != null : "eventPublisher not initialized.";
+ eventPublisher.postUpdate(itemName, new PercentType(rollershutterLevel));
+ VeluxScene thisScene2 = bridgeParameters.scenes.getChannel().existingScenes
+ .get(new SceneName(sceneName));
+ if (thisScene2 == null) {
+ logger.warn(
+ "handleCommandOnChannel(): aborting command as scene with name {} is not registered; please check your KLF scene definitions.",
+ sceneName);
+ break;
+ }
+ logger.trace("handleCommandOnChannel(): executing scene {} with index {}.", thisScene2,
+ thisScene2.getBridgeSceneIndex().toInt());
+ new VeluxBridgeRunScene().execute(thisBridge, thisScene2.getBridgeSceneIndex().toInt());
break;
case SCENE_SILENTMODE:
@@ -566,6 +612,9 @@ public void handleCommandOnChannel(String itemName, Command command, VeluxBindin
}
actuatorSerial = config.getBindingConfig();
logger.trace("handleCommandOnChannel(): actuatorSerial={}", actuatorSerial);
+ boolean isInverted = _actuatorIsInverted(actuatorSerial);
+ actuatorSerial = _actuatorCleanupSerial(actuatorSerial);
+ logger.trace("handleCommandOnChannel(): actuatorSerial={}", actuatorSerial);
if (!bridgeParameters.actuators.getChannel().existingProducts.isRegistered(actuatorSerial)) {
logger.info("handleCommandOnChannel(): cannot work on unknown actuator: {}.",
@@ -580,16 +629,21 @@ public void handleCommandOnChannel(String itemName, Command command, VeluxBindin
VeluxProductPosition targetLevel;
if ((command instanceof UpDownType) && ((UpDownType) command == UpDownType.UP)) {
logger.trace("handleCommandOnChannel(): found UP command.");
- targetLevel = new VeluxProductPosition(new PercentType(0));
+ targetLevel = isInverted ? new VeluxProductPosition(PercentType.HUNDRED)
+ : new VeluxProductPosition(PercentType.ZERO);
} else if ((command instanceof UpDownType) && ((UpDownType) command == UpDownType.DOWN)) {
logger.trace("handleCommandOnChannel(): found DOWN command.");
- targetLevel = new VeluxProductPosition(new PercentType(100));
+ targetLevel = isInverted ? new VeluxProductPosition(PercentType.ZERO)
+ : new VeluxProductPosition(PercentType.HUNDRED);
} else if ((command instanceof StopMoveType) && ((StopMoveType) command == StopMoveType.STOP)) {
logger.trace("handleCommandOnChannel(): found STOP command.");
targetLevel = new VeluxProductPosition();
} else if (command instanceof PercentType) {
logger.trace("handleCommandOnChannel(): found command of type PercentType.");
PercentType ptCommand = (PercentType) command;
+ if (isInverted) {
+ ptCommand = new PercentType(PercentType.HUNDRED.intValue() - ptCommand.intValue());
+ }
logger.trace("handleCommandOnChannel(): found command to set level to {}.", ptCommand);
targetLevel = new VeluxProductPosition(ptCommand);
} else {
@@ -599,6 +653,8 @@ public void handleCommandOnChannel(String itemName, Command command, VeluxBindin
logger.debug("handleCommandOnChannel(): sending command with target level {}.", targetLevel);
new VeluxBridgeSendCommand().sendCommand(thisBridge,
thisProduct.getBridgeProductIndex().toInt(), targetLevel);
+ logger.trace(
+ "handleCommandOnChannel(): The new shutter level will be send through the home monitoring events.");
if (bridgeParameters.actuators.autoRefresh(thisBridge)) {
logger.trace("handleCommandOnChannel(): position of actuators are updated.");
}
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBinding.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBinding.java
index 881d5351838..66d2e695c76 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBinding.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBinding.java
@@ -12,9 +12,8 @@
*/
package org.openhab.binding.velux.internal;
-import static org.apache.commons.lang.StringUtils.isNotBlank;
-
import java.util.Dictionary;
+import java.util.Enumeration;
import org.openhab.binding.velux.VeluxBindingConstants;
import org.openhab.binding.velux.VeluxBindingProvider;
@@ -92,7 +91,8 @@ public class VeluxBinding extends AbstractActiveBinding im
/**
* Velux bridge handler will provide the related interfacing information and methods.
*/
- private int refreshCounter = 0;
+ private static final int REFRESH_FIRST_TIME = 0;
+ private int refreshCounter = REFRESH_FIRST_TIME;
private boolean isModulo(int a, int b) {
return ((a % b) == 0) ? true : false;
@@ -173,14 +173,15 @@ public void execute() {
logger.debug("There is no existing Velux binding configuration => refresh cycle aborted.");
return;
}
- this.refreshCounter++;
for (VeluxBindingProvider provider : providers) {
logger.trace("execute(): working with VeluxBindingProvider {}.", provider);
for (String itemName : provider.getInBindingItemNames()) {
VeluxBindingConfig itemConfig = this.bindingProvider.getConfigForItemName(itemName);
VeluxItemType itemType = itemConfig.getBindingItemType();
- if (itemType.isToBeRefreshed()) {
- if (isModulo(this.refreshCounter, itemType.getRefreshDivider())) {
+ if (((this.refreshCounter == REFRESH_FIRST_TIME) && (itemType.isReadable()))
+ || (itemType.isToBeRefreshed())) {
+ if ((this.refreshCounter == REFRESH_FIRST_TIME)
+ || (isModulo(this.refreshCounter, itemType.getRefreshDivider()))) {
logger.trace("execute(): refreshing item {}.", itemName);
this.bridgeHandler.handleCommandOnChannel(itemName, null, itemConfig, provider,
this.eventPublisher);
@@ -192,6 +193,7 @@ public void execute() {
}
}
}
+ this.refreshCounter++;
logger.debug("execute() done.");
}
}
@@ -240,68 +242,114 @@ public void internalReceiveUpdate(String itemName, State newState) {
@Override
public void updated(final Dictionary config) throws ConfigurationException {
+ if (config == null) {
+ logger.info("updated() called with empty dictionary.");
+ return;
+ }
logger.debug("updated() called with {} dictionary entries.", config.size());
- if (config != null) {
- final String protocol = (String) config.get(VeluxBridgeConfiguration.BRIDGE_PROTOCOL);
- if (isNotBlank(protocol)) {
- this.config.bridgeProtocol = protocol;
- this.config.hasChanged = true;
- logger.debug("updated(): adapted BRIDGE_PROTOCOL to {}.", this.config.bridgeProtocol);
- }
- final String ipAddressString = (String) config.get(VeluxBridgeConfiguration.BRIDGE_IPADDRESS);
- if (isNotBlank(ipAddressString)) {
- this.config.bridgeIPAddress = ipAddressString;
- this.config.hasChanged = true;
- logger.debug("updated(): adapted BRIDGE_IPADDRESS to {}.", this.config.bridgeIPAddress);
- }
- final String tcpPortString = (String) config.get(VeluxBridgeConfiguration.BRIDGE_TCPPORT);
- if (isNotBlank(tcpPortString)) {
- try {
- this.config.bridgeTCPPort = Integer.parseInt(tcpPortString);
- } catch (NumberFormatException e) {
- throw new ConfigurationException(VeluxBridgeConfiguration.BRIDGE_TCPPORT, e.getMessage());
- }
- this.config.hasChanged = true;
- logger.debug("updated(): adapted BRIDGE_TCPPORT to {}.", this.config.bridgeTCPPort);
- }
- final String passwordString = (String) config.get(VeluxBridgeConfiguration.BRIDGE_PASSWORD);
- if (isNotBlank(passwordString)) {
- this.config.bridgePassword = passwordString;
- this.config.hasChanged = true;
- logger.debug("updated(): adapted BRIDGE_PASSWORD to {}.", this.config.bridgePassword);
- }
- final String timeoutMsecsString = (String) config.get(VeluxBridgeConfiguration.BRIDGE_TIMEOUT_MSECS);
- if (isNotBlank(timeoutMsecsString)) {
- try {
- this.config.timeoutMsecs = Integer.parseInt(timeoutMsecsString);
- } catch (NumberFormatException e) {
- throw new ConfigurationException(VeluxBridgeConfiguration.BRIDGE_TIMEOUT_MSECS, e.getMessage());
- }
- this.config.hasChanged = true;
- logger.debug("updated(): adapted BRIDGE_TIMEOUT_MSECS to {}.", this.config.timeoutMsecs);
- }
- final String retryNoString = (String) config.get(VeluxBridgeConfiguration.BRIDGE_RETRIES);
- if (isNotBlank(retryNoString)) {
- try {
- this.config.retries = Integer.parseInt(retryNoString);
- } catch (NumberFormatException e) {
- throw new ConfigurationException(VeluxBridgeConfiguration.BRIDGE_RETRIES, e.getMessage());
- }
- this.config.hasChanged = true;
- logger.debug("updated(): adapted BRIDGE_RETRIES to {}.", this.config.retries);
- }
- final String bulkRetrievalString = (String) config
- .get(VeluxBridgeConfiguration.BRIDGE_IS_BULK_RETRIEVAL_ENABLED);
- if (isNotBlank(bulkRetrievalString)) {
- try {
- this.config.isBulkRetrievalEnabled = Boolean.parseBoolean(bulkRetrievalString);
- } catch (NumberFormatException e) {
- throw new ConfigurationException(VeluxBridgeConfiguration.BRIDGE_IS_BULK_RETRIEVAL_ENABLED,
- e.getMessage());
- }
- this.config.hasChanged = true;
- logger.debug("updated(): adapted BRIDGE_IS_BULK_RETRIEVAL_ENABLED to {}.",
- this.config.isBulkRetrievalEnabled);
+ Enumeration configKeys = config.keys();
+ while (configKeys.hasMoreElements()) {
+ String key = configKeys.nextElement();
+ System.out.println(key + ": " + config.get(key));
+ switch (key) {
+ case VeluxBridgeConfiguration.BRIDGE_PROTOCOL:
+ final String protocol = (String) config.get(VeluxBridgeConfiguration.BRIDGE_PROTOCOL);
+ if (protocol.length() > 0) {
+ this.config.bridgeProtocol = protocol;
+ this.config.hasChanged = true;
+ logger.debug("updated(): adapted BRIDGE_PROTOCOL to {}.", this.config.bridgeProtocol);
+ }
+ break;
+ case VeluxBridgeConfiguration.BRIDGE_IPADDRESS:
+ final String ipAddressString = (String) config.get(VeluxBridgeConfiguration.BRIDGE_IPADDRESS);
+ if (ipAddressString.length() > 0) {
+ this.config.bridgeIPAddress = ipAddressString;
+ this.config.hasChanged = true;
+ logger.debug("updated(): adapted BRIDGE_IPADDRESS to {}.", this.config.bridgeIPAddress);
+ }
+ break;
+ case VeluxBridgeConfiguration.BRIDGE_TCPPORT:
+ final String tcpPortString = (String) config.get(VeluxBridgeConfiguration.BRIDGE_TCPPORT);
+ if (tcpPortString.length() > 0) {
+ try {
+ this.config.bridgeTCPPort = Integer.parseInt(tcpPortString);
+ } catch (NumberFormatException e) {
+ throw new ConfigurationException(VeluxBridgeConfiguration.BRIDGE_TCPPORT, e.getMessage());
+ }
+ this.config.hasChanged = true;
+ logger.debug("updated(): adapted BRIDGE_TCPPORT to {}.", this.config.bridgeTCPPort);
+ }
+ break;
+ case VeluxBridgeConfiguration.BRIDGE_PASSWORD:
+ final String passwordString = (String) config.get(VeluxBridgeConfiguration.BRIDGE_PASSWORD);
+ if (passwordString.length() > 0) {
+ this.config.bridgePassword = passwordString;
+ this.config.hasChanged = true;
+ logger.debug("updated(): adapted BRIDGE_PASSWORD to {}.", this.config.bridgePassword);
+ }
+ break;
+ case VeluxBridgeConfiguration.BRIDGE_TIMEOUT_MSECS:
+ final String timeoutMsecsString = (String) config
+ .get(VeluxBridgeConfiguration.BRIDGE_TIMEOUT_MSECS);
+ if (timeoutMsecsString.length() > 0) {
+ try {
+ this.config.timeoutMsecs = Integer.parseInt(timeoutMsecsString);
+ } catch (NumberFormatException e) {
+ throw new ConfigurationException(VeluxBridgeConfiguration.BRIDGE_TIMEOUT_MSECS,
+ e.getMessage());
+ }
+ this.config.hasChanged = true;
+ logger.debug("updated(): adapted BRIDGE_TIMEOUT_MSECS to {}.", this.config.timeoutMsecs);
+ }
+ break;
+ case VeluxBridgeConfiguration.BRIDGE_RETRIES:
+ final String retryNoString = (String) config.get(VeluxBridgeConfiguration.BRIDGE_RETRIES);
+ if (retryNoString.length() > 0) {
+ try {
+ this.config.retries = Integer.parseInt(retryNoString);
+ } catch (NumberFormatException e) {
+ throw new ConfigurationException(VeluxBridgeConfiguration.BRIDGE_RETRIES, e.getMessage());
+ }
+ this.config.hasChanged = true;
+ logger.debug("updated(): adapted BRIDGE_RETRIES to {}.", this.config.retries);
+ }
+ break;
+ case VeluxBridgeConfiguration.BRIDGE_REFRESH_MSECS:
+ final String refreshMsecsString = (String) config
+ .get(VeluxBridgeConfiguration.BRIDGE_REFRESH_MSECS);
+ if (refreshMsecsString.length() > 0) {
+ try {
+ this.config.refreshMSecs = Integer.parseInt(refreshMsecsString);
+ } catch (NumberFormatException e) {
+ throw new ConfigurationException(VeluxBridgeConfiguration.BRIDGE_REFRESH_MSECS,
+ e.getMessage());
+ }
+ this.config.hasChanged = true;
+ logger.debug("updated(): adapted BRIDGE_REFRESH_MSECS to {}.", this.config.refreshMSecs);
+ }
+ break;
+ case VeluxBridgeConfiguration.BRIDGE_IS_BULK_RETRIEVAL_ENABLED:
+ try {
+ final String bulkRetrievalString = (String) config
+ .get(VeluxBridgeConfiguration.BRIDGE_IS_BULK_RETRIEVAL_ENABLED);
+ if (bulkRetrievalString.length() > 0) {
+ try {
+ this.config.isBulkRetrievalEnabled = Boolean.parseBoolean(bulkRetrievalString);
+ } catch (NumberFormatException e) {
+ throw new ConfigurationException(
+ VeluxBridgeConfiguration.BRIDGE_IS_BULK_RETRIEVAL_ENABLED, e.getMessage());
+ }
+ this.config.hasChanged = true;
+ logger.debug("updated(): adapted BRIDGE_IS_BULK_RETRIEVAL_ENABLED to {}.",
+ this.config.isBulkRetrievalEnabled);
+ }
+ } catch (ClassCastException ex) {
+ logger.warn("updated(): bad configuration setting for {}: {}.",
+ VeluxBridgeConfiguration.BRIDGE_IS_BULK_RETRIEVAL_ENABLED, ex.toString());
+ }
+ break;
+ default:
+ logger.warn("updated(): unknown configuration entry {}:={}.", key, config.get(key));
}
}
@@ -331,6 +379,10 @@ public void updated(final Dictionary config) throws ConfigurationExce
@Override
public void deactivate() {
logger.trace("deactivate() called.");
+ if (this.bridgeHandler != null) {
+ this.bridgeHandler.finalize();
+ }
+ logger.trace("deactivate() done.");
}
@Override
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxGenericBindingProvider.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxGenericBindingProvider.java
index 74d440eb34b..1d7f891b96e 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxGenericBindingProvider.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxGenericBindingProvider.java
@@ -240,6 +240,12 @@ public void processBindingConfiguration(final String context, final Item item, f
case VeluxBindingConstants.CHANNEL_BRIDGE_STATUS:
config = new VeluxBindingConfig(VeluxItemType.BRIDGE_STATUS, bindingConfig);
break;
+ case VeluxBindingConstants.CHANNEL_BRIDGE_RELOAD:
+ config = new VeluxBindingConfig(VeluxItemType.BRIDGE_RELOAD, bindingConfig);
+ break;
+ case VeluxBindingConstants.CHANNEL_BRIDGE_TIMESTAMP:
+ config = new VeluxBindingConfig(VeluxItemType.BRIDGE_TIMESTAMP, bindingConfig);
+ break;
case VeluxBindingConstants.CHANNEL_BRIDGE_DO_DETECTION:
config = new VeluxBindingConfig(VeluxItemType.BRIDGE_DO_DETECTION, bindingConfig);
break;
@@ -261,6 +267,9 @@ public void processBindingConfiguration(final String context, final Item item, f
case VeluxBindingConstants.CHANNEL_BRIDGE_WLANSSID:
config = new VeluxBindingConfig(VeluxItemType.BRIDGE_WLANSSID, bindingConfig);
break;
+ case VeluxBindingConstants.CHANNEL_BRIDGE_WLANPASSWORD:
+ config = new VeluxBindingConfig(VeluxItemType.BRIDGE_WLANPASSWORD, bindingConfig);
+ break;
case VeluxBindingConstants.CHANNEL_BRIDGE_PRODUCTS:
config = new VeluxBindingConfig(VeluxItemType.BRIDGE_PRODUCTS, bindingConfig);
break;
@@ -329,7 +338,7 @@ public VeluxBindingConfig getConfigForItemName(String itemName) {
} else if (super.bindingConfigs.containsKey(itemName)) {
config = (VeluxBindingConfig) super.bindingConfigs.get(itemName);
}
- logger.trace("getConfigForItemName() returns {}.", config.getBindingConfig());
+ logger.trace("getConfigForItemName() returns {}.", (config != null) ? config.getBindingConfig() : "**null**");
return config;
}
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxItemType.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxItemType.java
index 0700fa2d28b..d4c3f23e560 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxItemType.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxItemType.java
@@ -19,6 +19,7 @@
import org.openhab.binding.velux.VeluxBindingConstants;
import org.openhab.core.items.Item;
+import org.openhab.core.library.items.NumberItem;
import org.openhab.core.library.items.RollershutterItem;
import org.openhab.core.library.items.StringItem;
import org.openhab.core.library.items.SwitchItem;
@@ -73,12 +74,16 @@
*
*/
public enum VeluxItemType {
+ BRIDGE_RELOAD(VeluxBindingConstants.THING_VELUX_BRIDGE, VeluxBindingConstants.CHANNEL_BRIDGE_RELOAD,
+ SwitchItem.class, false, false, true, false),
SCENE_ACTION(VeluxBindingConstants.THING_VELUX_SCENE, VeluxBindingConstants.CHANNEL_SCENE_ACTION, SwitchItem.class,
false, false, true, false),
SCENE_SILENTMODE(VeluxBindingConstants.THING_VELUX_SCENE, VeluxBindingConstants.CHANNEL_SCENE_SILENTMODE,
SwitchItem.class, false, true, false, false),
BRIDGE_STATUS(VeluxBindingConstants.THING_VELUX_BRIDGE, VeluxBindingConstants.CHANNEL_BRIDGE_STATUS,
StringItem.class, true, true, true, true, 1),
+ BRIDGE_TIMESTAMP(VeluxBindingConstants.THING_VELUX_BRIDGE, VeluxBindingConstants.CHANNEL_BRIDGE_TIMESTAMP,
+ NumberItem.class, true, true, true, true, 1),
BRIDGE_DO_DETECTION(VeluxBindingConstants.THING_VELUX_BRIDGE, VeluxBindingConstants.CHANNEL_BRIDGE_DO_DETECTION,
SwitchItem.class, false, false, true, false),
BRIDGE_FIRMWARE(VeluxBindingConstants.THING_VELUX_BRIDGE, VeluxBindingConstants.CHANNEL_BRIDGE_FIRMWARE,
@@ -94,7 +99,7 @@ public enum VeluxItemType {
BRIDGE_WLANSSID(VeluxBindingConstants.THING_VELUX_BRIDGE, VeluxBindingConstants.CHANNEL_BRIDGE_WLANSSID,
StringItem.class, true, false, false, false),
BRIDGE_WLANPASSWORD(VeluxBindingConstants.THING_VELUX_BRIDGE, VeluxBindingConstants.CHANNEL_BRIDGE_WLANPASSWORD,
- SwitchItem.class, true, false, false, false),
+ StringItem.class, true, false, false, false),
BRIDGE_PRODUCTS(VeluxBindingConstants.THING_VELUX_BRIDGE, VeluxBindingConstants.CHANNEL_BRIDGE_PRODUCTS,
StringItem.class, true, false, false, true, 15),
BRIDGE_SCENES(VeluxBindingConstants.THING_VELUX_BRIDGE, VeluxBindingConstants.CHANNEL_BRIDGE_SCENES,
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/things/VeluxGwLAN.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/things/VeluxGwLAN.java
index d54b14a95f4..655d21cd30e 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/things/VeluxGwLAN.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/things/VeluxGwLAN.java
@@ -47,24 +47,28 @@ public VeluxGwLAN(String ipAddress, String subnetMask, String defaultGW, boolean
// Class access methods
public String getIpAddress() {
+ logger.trace("getIpAddress() returns {}.", this.ipAddress);
return this.ipAddress;
}
public String getSubnetMask() {
+ logger.trace("getSubnetMask() returns {}.", this.subnetMask);
return this.subnetMask;
}
public String getDefaultGW() {
+ logger.trace("getDefaultGW() returns {}.", this.defaultGW);
return this.defaultGW;
}
public boolean getDHCP() {
+ logger.trace("getDHCP() returns {}.", this.enabledDHCP ? "enabled" : "disabled");
return this.enabledDHCP;
}
@Override
public String toString() {
- return String.format("ip %d, nm %d, gw %d, DHCP %s", this.ipAddress, this.subnetMask, this.defaultGW,
+ return String.format("ip %s, nm %s, gw %s, DHCP %s", this.ipAddress, this.subnetMask, this.defaultGW,
this.enabledDHCP ? "enabled" : "disabled");
}
diff --git a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/things/VeluxProductPosition.java b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/things/VeluxProductPosition.java
index ac5c5cc8b55..49133e76c57 100644
--- a/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/things/VeluxProductPosition.java
+++ b/bundles/binding/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/things/VeluxProductPosition.java
@@ -95,6 +95,10 @@ public PercentType getPositionAsPercentType() {
return position;
}
+ public PercentType getPositionAsPercentType(boolean toBeInverted) {
+ return toBeInverted ? new PercentType(PercentType.HUNDRED.intValue() - position.intValue()) : position;
+ }
+
public int getPositionAsVeluxType() {
if (this.position != null) {
float result = (ONE * position.intValue() - VPP_OPENHAB_MIN) / (VPP_OPENHAB_MAX - VPP_OPENHAB_MIN);
diff --git a/features/openhab-addons-external/src/main/resources/conf/velux.cfg b/features/openhab-addons-external/src/main/resources/conf/velux.cfg
index d49612fc60d..8687df5a6c2 100644
--- a/features/openhab-addons-external/src/main/resources/conf/velux.cfg
+++ b/features/openhab-addons-external/src/main/resources/conf/velux.cfg
@@ -3,17 +3,20 @@
# The hostname or IP address of the Velux Bridge
#bridgeIPAddress=192.168.0.1
-# TCP port of the Velux gateway (optional, defaults to 80)
-#bridgeTCPPort=80
+# Underlying communication protocol (http/https/slip) (optional, defaults to slip)
+#bridgeProtocol=slip
+
+# TCP port of the Velux gateway (optional, defaults to 51200)
+#bridgeTCPPort=51200
# Password for authentication against the Velux Bridge (optional, defaults to velux123)
#bridgePassword=velux123
-# Initial Connection timeout in milliseconds (optional, defaults to 2000)
-#timeoutMsecs=2000
+# Initial Connection timeout in milliseconds (optional, defaults to 1000)
+#timeoutMsecs=1000
-# Number of retries with timing along the Binary Exponential Backoff (BEB) Algorithm (optional, defaults to 10)
-#retries=10
+# Number of retries with timing along the Binary Exponential Backoff (BEB) Algorithm (optional, defaults to 5)
+#retries=5
-# Data refresh interval for any bridge parameters in milliseconds (optional, defaults to 3600000)
-#refreshSecs=3600000
+# Data refresh interval for any bridge parameters in milliseconds (optional, defaults to 15000)
+#refreshSecs=15000
diff --git a/features/openhab-addons/src/main/feature/feature.xml b/features/openhab-addons/src/main/feature/feature.xml
index 1b39cc12ae8..0092c9ed1de 100644
--- a/features/openhab-addons/src/main/feature/feature.xml
+++ b/features/openhab-addons/src/main/feature/feature.xml
@@ -575,6 +575,13 @@
mvn:${project.groupId}/openhab-addons-external/${project.version}/cfg/upb
+
+ openhab-runtime-base
+ openhab-runtime-compat1x
+ mvn:org.openhab.binding/org.openhab.binding.velux/${project.version}
+ mvn:${project.groupId}/openhab-addons-external/${project.version}/cfg/velux
+
+
openhab-runtime-baseopenhab-runtime-compat1x