diff --git a/README.md b/README.md index c243136bf3cdb..e266a9875567e 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,174 @@ -## openHAB 2 Add-ons +# Zoneminder Binding -This repository contains add-ons that are implemenented using the new [Eclipse SmartHome APIs](https://www.eclipse.org/smarthome/documentation/development/bindings/how-to.html) of openHAB 2. +This binding offers integration to a ZoneMinder Server. It currently only offers to integrate to monitors (eg. cameras in ZoneMinder). It also only offers access to a limited set of values, as well as a even more limited option to update values in ZoneMinder. It requires at least ZoneMinder 1.29 with API enabled (option 'OPT_USE_API' in ZoneMinder must be enabled). The option 'OPT_TRIGGERS' must be anabled to allow openHAB to trip the ForceAlarm in ZoneMinder. -Note that all information about openHAB itself, the IDE setup and the contribution processes can be found in the [openhab-distro](https://github.com/openhab/openhab-distro) project, so please go there for any further details! +## Supported Things -## Add-ons in other repositories -Some add-ons (e.g. specific bindings such as [Z-Wave](https://github.com/openhab/org.openhab.binding.zwave)) are maintained in separate repositories in order to improve their management. In order to contribute to these bindings, you should follow the following steps -: +This binding supports the following thing types -1. Fork the repository on Github -2. Clone your repository to your local computer as described in the [Github tutorial](https://help.github.com/articles/cloning-a-repository/) -3. Open the openHAB Eclipse IDE -4. Select the *File | Import* menu option -5. Select *General | Existing Projects into Workspace* and click Next -6. Select the root directory where you made the local clone of the repository -7. Select the project and click *Next* -8. The project will now be imported and available in the Package Explorer -9. You may want to add the project to the *OH2 Add-ons* Working Set + + + + +
ThingThing TypeDiscoveryDescription
ZoneMinder ServerBridgeManualA ZoneMinder Server. Required version is minimum 1.29
ZoneMinder MonitorThingAutomaticMonitor as defined in ZoneMinder Server
+ +## Getting started / Discovery + +The binding consists of a Bridge (the ZoneMinder Server it self), and a number of Things, which relates to the induvidual monitors in ZoneMinder. ZoneMinder things can be configured either through the online configuration utility via discovery, or manually through the 'zoneminder.things' configuration file. The Bridge will not be autodiscovered, this behaviour is by design. That is because the ZoneMinder API can be configured to communicate on custom ports, you can even change the url from the default /zm/ to something userdefined. That makes it meaningless to scan for a ZoneMinder Server. The Bridge must therefore be added manually, this can be done from PaperUI. After adding the Bridge it will go ONLINE, and after a short while and the discovery process for monitors will start. When a new monitor is discovered it will appear in the Inbox. + + +### Bridge ### + +Channel | Type | Description +-------------- | --------- | ---------------------------------- +online | Switch | Parameter indicating if the server is online +CPU load | Text | Current CPU Load of server +Disk Usage | text | Current Disk Usage on server + +### Thing ### + + Channel | Type | Description +-------------- | --------- | ---------------------------------- +online | Switch | Parameter indicating if the monitor is online +enabled | Switch | Parameter indicating if the monitor is enabled +force-alarm | Switch | Parameter indicating if Force Alarm for the the monitor is active +alarm | Switch | true if monitor has an active alarm +recording | Text | true if monitor is recording +detailed-status| Text | Detailed status of monitor (Idle, Pre-alarm, Alarm, Alert, Recording) +event-cause | Text | Empty when there is no active event, else it contains the text with the cause of the event +function | Text | Text corresponding the value in ZoneMinder: None, Monitor, Modect, Record, Mocord, Nodect +capture-daemon | Switch | Run state of ZMC Daemon +analysis-daemon| Switch | Run state of ZMA Daemon +frame-daemon | Switch | Run state of ZMF Daemon + +##Manual configuration## + +###Things configuration### + +``` +Bridge zoneminder:server:ZoneMinderSample [ hostname="192.168.1.55", user="", password="", telnet_port=6802, refresh_interval_disk_usage=1 ] +{ + Thing monitor monitor_1 [ monitorId=1, monitorTriggerTimeout=120, monitorEventText="Trigger activated from OpenHAB" ] +} + +``` +###Items configuration### + +``` +/* ***************************************** + * SERVER + * *****************************************/ +Switch zmServer_Online "Zoneminder Online [%s]" {channel="zoneminder:server:ZoneMinderSample:online"} +Number zmServer_CpuLoad "ZoneMinder Server Load [%s]" {channel="zoneminder:server:ZoneMinderSample:cpu-load"} + +Number zmServer_DiskUsage "ZoneMinder Disk Usage [%s]" {channel="zoneminder:server:ZoneMinderSample:disk-usage"} + +/* ***************************************** + * MONITOR 1 + * *****************************************/ +Switch zmMonitor1_Online "Online [%s]" {channel="zoneminder:monitor:ZoneMinderSample:monitor-1:online"} +Switch zmMonitor1_Enabled "Enabled [%s]" {channel="zoneminder:monitor:ZoneMinderSample:monitor-1:enabled"} +Switch zmMonitor1_ForceAlarm "Force Alarm [%s]" {channel="zoneminder:monitor:ZoneMinderSample:monitor-1:force-alarm"} +Switch zmMonitor1_EventState "Alarm [%s]" {channel="zoneminder:monitor:ZoneMinderSample:monitor-1:alarm"} +Switch zmMonitor1_Recording "Recording [%s]" {channel="zoneminder:monitor:ZoneMinderSample:monitor-1:recording"} +String zmMonitor1_DetailedStatus "Detailed Status [%s]" {channel="zoneminder:monitor:ZoneMinderSample:monitor-1:detailed-status"} +String zmMonitor1_EventCause "Event Cause [%s]" {channel="zoneminder:monitor:ZoneMinderSample:monitor-1:event-cause"} +String zmMonitor1_Function "Function [%s]" {channel="zoneminder:monitor:ZoneMinderSample:monitor-1:function"} +Switch zmMonitor1_CaptureState "Capture Daemon [%s]" {channel="zoneminder:monitor:ZoneMinderSample:monitor-1:capture-daemon"} +Switch zmMonitor1_AnalysisState "Analysis Daemon [%s]" {channel="zoneminder:monitor:ZoneMinderSample:monitor-1:analysis-daemon"} +Switch zmMonitor1_FrameState "Frame Daemon [%s]" {channel="zoneminder:monitor:ZoneMinderSample:monitor-1:frame-daemon"} + + +// Helpers +Switch zmMonitor1_Mode "Monitor active [%s]" +``` + +###Sample Rule### + +``` +rule "Monitor1 Alarm State" +when + Item zmMonitor1_EventState changed +then + if (zmMonitor1_EventState.state == ON) { + logInfo("zoneminder.rules", "ZoneMinder Alarm started") + } + else if (zmMonitor1_EventState.state == OFF) { + logInfo("zoneminder.rules", "ZoneMinder Alarm stopped") + } +end + +rule "Monitor1 Recording State" +when + Item zmMonitor1_Recording changed +then + if (zmMonitor1_Recording.state == ON) { + logInfo("zoneminder.rules", "ZoneMinder recording started") + } + else if (zmMonitor1_Recording.state == OFF) { + logInfo("zoneminder.rules", "ZoneMinder recording stopped") + } +end + + +rule "Change Monitor1 Mode" +when + Item zmMonitor1_Mode changed +then + if (zmMonitor1_Mode.state==ON) { + sendCommand(zmMonitor1_Function, "Modect") + sendCommand(zmMonitor1_Enabled, ON) + } + else { + sendCommand(zmMonitor1_Function, "Monitor") + sendCommand(zmMonitor1_Enabled, OFF) + } +end +``` + + +###Sitemap configuration### + +``` +sitemap zoneminder label="Zoneminder" +{ + Frame { + Text item=zmServer_Online label="ZoneMinder Server [%s]" { + Frame { + Text item=zmServer_Online + Text item=zmServer_CpuLoad + Text item=zmServer_DiskUsage + } + } + + Text item=zmMonitor1_Function label="(Monitor-1) [%s]" { + Frame { + Switch item=zmMonitor1_Enabled + Switch item=zmMonitor1_ForceAlarm + Text item=zmMonitor1_Online + Selection item=zmMonitor1_Function mappings=["None"=None, "Modect"=Modect, "Monitor"=Monitor, "Record"=Record, "Mocord"=Mocord, "Nodect"=Nodect] + Text item=zmMonitor1_EventState + Text item=zmMonitor1_Recording + Text item=zmMonitor1_DetailedStatus + Text item=zmMonitor1_EventCause + Text item=zmMonitor1_CaptureState + Text item=zmMonitor1_AnalysisState + Text item=zmMonitor1_FrameState + } + } + Frame label="Monitor Helpers" { + Switch item=zmMonitor1_Mode + } + } +} +``` +##Troubleshooting## + + + + + + + + +
ProblemSolution
Cannot connect to ZoneMinder BridgeCheck if you can logon to ZoneMinder from your openHAB server (with http).
Check that it is possible to establish a Telnet connection from openHAB server to Zoneminder Server
ZoneMinder Bridge is not comming ONLINE. It says: 'OFFLINE - COMMUNICATION_ERROR Cannot access ZoneMinder Server. Check provided usercredentials'Check that the hostname is valid, if using a DNS name, make sure name is correct resolved. Also check that the given host can be accessed from a browser. Finally make sure to change the additional path from '/zm', if not using standard setup.
Cannot connect to ZoneMinder Bridge via HTTPS, using Letsencrypt certificateVerify your Java version, if Java is below build 101, letsencrypt certificate isn't known by Java. Either use HTTP or upgrade Java to newest build. Please be aware that https support is provided as an experimental feature.
I have tried all of the above, it still doesn't workTry to execute this from a commandline (on your openHAB server): curl -d "=XXXX&=YYYY&action=login&view=console" -c cookies.txt http:///zm/index.php. Change , and to the actual values. This will check if your server is accessible from the openHAB server.
diff --git a/addons/archetype-catalog.xml b/addons/binding/archetype-catalog.xml similarity index 100% rename from addons/archetype-catalog.xml rename to addons/binding/archetype-catalog.xml diff --git a/addons/binding/create_openhab_binding_skeleton.cmd b/addons/binding/create_openhab_binding_skeleton.cmd index e881130d243bc..a6f7cbc9058bd 100644 --- a/addons/binding/create_openhab_binding_skeleton.cmd +++ b/addons/binding/create_openhab_binding_skeleton.cmd @@ -1,16 +1,16 @@ -@echo off - - -SETLOCAL -SET ARGC=0 - -FOR %%x IN (%*) DO SET /A ARGC+=1 - -IF %ARGC% NEQ 2 ( - echo Usage: %0 BindingIdInCamelCase BindingIdInLowerCase - exit /B 1 -) - -mvn archetype:generate -N -DarchetypeGroupId=org.eclipse.smarthome.archetype -DarchetypeArtifactId=org.eclipse.smarthome.archetype.binding -DarchetypeVersion=0.9.0-SNAPSHOT -DgroupId=org.openhab.binding -DartifactId=org.openhab.binding.%2 -Dpackage=org.openhab.binding.%2 -DarchetypeCatalog='file://../archetype-catalog.xml' -Dversion=2.0.0-SNAPSHOT -DbindingId=%2 -DbindingIdCamelCase=%1 -DvendorName=openHAB -Dnamespace=org.openhab - +@echo off + + +SETLOCAL +SET ARGC=0 + +FOR %%x IN (%*) DO SET /A ARGC+=1 + +IF %ARGC% NEQ 2 ( + echo Usage: %0 BindingIdInCamelCase BindingIdInLowerCase + exit /B 1 +) + +mvn archetype:generate -N -DarchetypeGroupId=org.eclipse.smarthome.archetype -DarchetypeArtifactId=org.eclipse.smarthome.archetype.binding -DarchetypeVersion=0.9.0-SNAPSHOT -DgroupId=org.openhab.binding -DartifactId=org.openhab.binding.%2 -Dpackage=org.openhab.binding.%2 -DarchetypeCatalog='file://../archetype-catalog.xml' -Dversion=2.0.0-SNAPSHOT -DbindingId=%2 -DbindingIdCamelCase=%1 -DvendorName=openHAB -Dnamespace=org.openhab + ENDLOCAL \ No newline at end of file diff --git a/addons/binding/create_openhab_binding_skeleton.sh b/addons/binding/create_openhab_binding_skeleton.sh old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/FritzahaContentExchange.java b/addons/binding/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/FritzahaContentExchange.java index d7c4eec55a6b4..22d92a52f9c0b 100644 --- a/addons/binding/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/FritzahaContentExchange.java +++ b/addons/binding/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/FritzahaContentExchange.java @@ -1,73 +1,73 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.avmfritz.internal.hardware; - -import org.eclipse.jetty.client.api.Response; -import org.eclipse.jetty.client.api.Response.CompleteListener; -import org.eclipse.jetty.client.api.Response.ContentListener; -import org.eclipse.jetty.client.api.Response.FailureListener; -import org.eclipse.jetty.client.api.Response.SuccessListener; -import org.eclipse.jetty.client.api.Result; -import org.eclipse.jetty.client.util.BufferingResponseListener; -import org.openhab.binding.avmfritz.internal.hardware.callbacks.FritzAhaCallback; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Implementation of Jetty ContextExchange to handle callbacks - * - * @author Robert Bausdorf - * - */ -public class FritzahaContentExchange extends BufferingResponseListener - implements SuccessListener, FailureListener, ContentListener, CompleteListener { - /** - * logger - */ - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - - /** - * Callback to execute on complete response - */ - private FritzAhaCallback callback; - - /** - * Constructor - * - * @param callback Callback which execute method has to be called. - */ - public FritzahaContentExchange(FritzAhaCallback callback) { - this.callback = callback; - } - - /** - * Log request success - */ - @Override - public void onSuccess(Response response) { - logger.debug("HTTP response {}", response.getStatus()); - } - - /** - * Log request failure - */ - @Override - public void onFailure(Response response, Throwable failure) { - logger.debug(failure.getLocalizedMessage()); - } - - /** - * Call the callbacks execute method on request completion. - */ - @Override - public void onComplete(Result result) { - logger.debug("response complete: " + this.getContentAsString()); - this.callback.execute(result.getResponse().getStatus(), this.getContentAsString()); - } -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.avmfritz.internal.hardware; + +import org.eclipse.jetty.client.api.Response; +import org.eclipse.jetty.client.api.Response.CompleteListener; +import org.eclipse.jetty.client.api.Response.ContentListener; +import org.eclipse.jetty.client.api.Response.FailureListener; +import org.eclipse.jetty.client.api.Response.SuccessListener; +import org.eclipse.jetty.client.api.Result; +import org.eclipse.jetty.client.util.BufferingResponseListener; +import org.openhab.binding.avmfritz.internal.hardware.callbacks.FritzAhaCallback; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Implementation of Jetty ContextExchange to handle callbacks + * + * @author Robert Bausdorf + * + */ +public class FritzahaContentExchange extends BufferingResponseListener + implements SuccessListener, FailureListener, ContentListener, CompleteListener { + /** + * logger + */ + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + /** + * Callback to execute on complete response + */ + private FritzAhaCallback callback; + + /** + * Constructor + * + * @param callback Callback which execute method has to be called. + */ + public FritzahaContentExchange(FritzAhaCallback callback) { + this.callback = callback; + } + + /** + * Log request success + */ + @Override + public void onSuccess(Response response) { + logger.debug("HTTP response {}", response.getStatus()); + } + + /** + * Log request failure + */ + @Override + public void onFailure(Response response, Throwable failure) { + logger.debug(failure.getLocalizedMessage()); + } + + /** + * Call the callbacks execute method on request completion. + */ + @Override + public void onComplete(Result result) { + logger.debug("response complete: " + this.getContentAsString()); + this.callback.execute(result.getResponse().getStatus(), this.getContentAsString()); + } +} diff --git a/addons/binding/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaCallback.java b/addons/binding/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaCallback.java index 461ce44bdb635..9cb3a0b1d1b0e 100644 --- a/addons/binding/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaCallback.java +++ b/addons/binding/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaCallback.java @@ -1,34 +1,34 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.avmfritz.internal.hardware.callbacks; - -/** - * Interface for callbacks in asynchronous requests. - * - * @author Robert Bausdorf - * - */ -public interface FritzAhaCallback { - /** - * Runs callback code after response completion. - */ - void execute(int status, String response); - - /** - * Get the URI path - * @return URI path as String - */ - public String getPath(); - - /** - * Get the query String - * @return Query string as String - */ - public String getArgs(); -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.avmfritz.internal.hardware.callbacks; + +/** + * Interface for callbacks in asynchronous requests. + * + * @author Robert Bausdorf + * + */ +public interface FritzAhaCallback { + /** + * Runs callback code after response completion. + */ + void execute(int status, String response); + + /** + * Get the URI path + * @return URI path as String + */ + public String getPath(); + + /** + * Get the query String + * @return Query string as String + */ + public String getArgs(); +} diff --git a/addons/binding/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaReauthCallback.java b/addons/binding/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaReauthCallback.java index dd95b6df9deb8..f4718b074ac62 100644 --- a/addons/binding/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaReauthCallback.java +++ b/addons/binding/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaReauthCallback.java @@ -1,144 +1,144 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.avmfritz.internal.hardware.callbacks; - -import org.openhab.binding.avmfritz.internal.hardware.FritzahaWebInterface; - -/** - * Callback implementation for reauthorization and retry - * - * @author Robert Bausdorf, Christian Brauers - * - */ -public class FritzAhaReauthCallback implements FritzAhaCallback { - - public static final String WEBSERVICE_PATH = "webservices/homeautoswitch.lua"; - /** - * Path to HTTP interface - */ - private String path; - /** - * Arguments to use - */ - private String args; - /** - * Web interface to use - */ - private FritzahaWebInterface webIface; - - /** - * HTTP Method for callback retries - */ - public enum Method { - POST, GET - }; - - /** - * Method used - */ - private Method httpMethod; - /** - * Number of remaining retries - */ - private int retries; - /** - * Whether the request returned a valid response - */ - private boolean validRequest; - /** - * Callback to execute on next retry - */ - private FritzAhaCallback retryCallback; - - /** - * Returns whether the request returned a valid response - * - * @return Validity of response - */ - public boolean isValidRequest() { - return validRequest; - } - - /** - * Returns whether there will be another retry on an invalid response - * - * @return true if there will be no more retries, false otherwise - */ - public boolean isFinalAttempt() { - return retries <= 0; - } - - /** - * Sets different Callback to use on retry (initial value: same callback - * after decremented retry counter) - * - * @param newRetryCallback - * Callback to retry with - */ - public void setRetryCallback(FritzAhaCallback newRetryCallback) { - retryCallback = newRetryCallback; - } - - - public String getPath() { - return path; - } - - public String getArgs() { - return args; - } - - - public FritzahaWebInterface getWebIface() { - return webIface; - } - - /** - * {@inheritDoc} - */ - public void execute(int status, String response) { - if (status != 200 || "".equals(response) || ".".equals(response)) { - validRequest = false; - if (retries >= 1) { - webIface.authenticate(); - retries--; - if (httpMethod == Method.GET) { - webIface.asyncGet(path, args, retryCallback); - } else if (httpMethod == Method.POST) { - webIface.asyncPost(path, args, retryCallback); - } - } - } else - validRequest = true; - } - - /** - * Constructor for retriable authentication - * - * @param path - * Path to HTTP interface - * @param args - * Arguments to use - * @param webIface - * Web interface to use - * @param httpMethod - * Method used - * @param retries - * Number of retries - */ - public FritzAhaReauthCallback(String path, String args, FritzahaWebInterface webIface, Method httpMethod, - int retries) { - this.path = path; - this.args = args; - this.webIface = webIface; - this.httpMethod = httpMethod; - this.retries = retries; - retryCallback = this; - } -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.avmfritz.internal.hardware.callbacks; + +import org.openhab.binding.avmfritz.internal.hardware.FritzahaWebInterface; + +/** + * Callback implementation for reauthorization and retry + * + * @author Robert Bausdorf, Christian Brauers + * + */ +public class FritzAhaReauthCallback implements FritzAhaCallback { + + public static final String WEBSERVICE_PATH = "webservices/homeautoswitch.lua"; + /** + * Path to HTTP interface + */ + private String path; + /** + * Arguments to use + */ + private String args; + /** + * Web interface to use + */ + private FritzahaWebInterface webIface; + + /** + * HTTP Method for callback retries + */ + public enum Method { + POST, GET + }; + + /** + * Method used + */ + private Method httpMethod; + /** + * Number of remaining retries + */ + private int retries; + /** + * Whether the request returned a valid response + */ + private boolean validRequest; + /** + * Callback to execute on next retry + */ + private FritzAhaCallback retryCallback; + + /** + * Returns whether the request returned a valid response + * + * @return Validity of response + */ + public boolean isValidRequest() { + return validRequest; + } + + /** + * Returns whether there will be another retry on an invalid response + * + * @return true if there will be no more retries, false otherwise + */ + public boolean isFinalAttempt() { + return retries <= 0; + } + + /** + * Sets different Callback to use on retry (initial value: same callback + * after decremented retry counter) + * + * @param newRetryCallback + * Callback to retry with + */ + public void setRetryCallback(FritzAhaCallback newRetryCallback) { + retryCallback = newRetryCallback; + } + + + public String getPath() { + return path; + } + + public String getArgs() { + return args; + } + + + public FritzahaWebInterface getWebIface() { + return webIface; + } + + /** + * {@inheritDoc} + */ + public void execute(int status, String response) { + if (status != 200 || "".equals(response) || ".".equals(response)) { + validRequest = false; + if (retries >= 1) { + webIface.authenticate(); + retries--; + if (httpMethod == Method.GET) { + webIface.asyncGet(path, args, retryCallback); + } else if (httpMethod == Method.POST) { + webIface.asyncPost(path, args, retryCallback); + } + } + } else + validRequest = true; + } + + /** + * Constructor for retriable authentication + * + * @param path + * Path to HTTP interface + * @param args + * Arguments to use + * @param webIface + * Web interface to use + * @param httpMethod + * Method used + * @param retries + * Number of retries + */ + public FritzAhaReauthCallback(String path, String args, FritzahaWebInterface webIface, Method httpMethod, + int retries) { + this.path = path; + this.args = args; + this.webIface = webIface; + this.httpMethod = httpMethod; + this.retries = retries; + retryCallback = this; + } +} diff --git a/addons/binding/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaSetSwitchCallback.java b/addons/binding/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaSetSwitchCallback.java index f62fa6f29bd1f..be3c72b23a67d 100644 --- a/addons/binding/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaSetSwitchCallback.java +++ b/addons/binding/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaSetSwitchCallback.java @@ -1,50 +1,50 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.avmfritz.internal.hardware.callbacks; - -import org.openhab.binding.avmfritz.internal.hardware.FritzahaWebInterface; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Callback implementation for updating switch states Supports reauthorization - * - * @author Robert Bausdorf - * - */ -public class FritzAhaSetSwitchCallback extends FritzAhaReauthCallback { - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - /** - * Item to update - */ - private String itemName; - - /** - * Constructor - * @param webIface Interface to FRITZ!Box - * @param ain AIN of the device that should be switched - * @param switchOn true - switch on, false - switch off - */ - public FritzAhaSetSwitchCallback(FritzahaWebInterface webIface, String ain, boolean switchOn) { - super(WEBSERVICE_PATH, - "ain=" + ain + "&switchcmd=" + (switchOn ? "setswitchon" : "setswitchoff"), - webIface, Method.GET, 1); - this.itemName = ain; - } - - /** - * {@inheritDoc} - */ - public void execute(int status, String response) { - super.execute(status, response); - if (this.isValidRequest()) { - logger.debug("Received State response " + response + " for item " + itemName); - } - } -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.avmfritz.internal.hardware.callbacks; + +import org.openhab.binding.avmfritz.internal.hardware.FritzahaWebInterface; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Callback implementation for updating switch states Supports reauthorization + * + * @author Robert Bausdorf + * + */ +public class FritzAhaSetSwitchCallback extends FritzAhaReauthCallback { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + /** + * Item to update + */ + private String itemName; + + /** + * Constructor + * @param webIface Interface to FRITZ!Box + * @param ain AIN of the device that should be switched + * @param switchOn true - switch on, false - switch off + */ + public FritzAhaSetSwitchCallback(FritzahaWebInterface webIface, String ain, boolean switchOn) { + super(WEBSERVICE_PATH, + "ain=" + ain + "&switchcmd=" + (switchOn ? "setswitchon" : "setswitchoff"), + webIface, Method.GET, 1); + this.itemName = ain; + } + + /** + * {@inheritDoc} + */ + public void execute(int status, String response) { + super.execute(status, response); + if (this.isValidRequest()) { + logger.debug("Received State response " + response + " for item " + itemName); + } + } +} diff --git a/addons/binding/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaUpdateXmlCallback.java b/addons/binding/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaUpdateXmlCallback.java index bc085e3377e63..c851b9bcc0731 100644 --- a/addons/binding/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaUpdateXmlCallback.java +++ b/addons/binding/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaUpdateXmlCallback.java @@ -1,84 +1,84 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.avmfritz.internal.hardware.callbacks; - -import java.io.StringReader; - -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; - -import org.eclipse.smarthome.core.thing.ThingStatus; -import org.eclipse.smarthome.core.thing.ThingStatusDetail; -import org.openhab.binding.avmfritz.handler.IFritzHandler; -import org.openhab.binding.avmfritz.internal.ahamodel.DeviceModel; -import org.openhab.binding.avmfritz.internal.ahamodel.DevicelistModel; -import org.openhab.binding.avmfritz.internal.hardware.FritzahaWebInterface; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Callback implementation for updating multiple numbers decoded from a xml - * response. Supports reauthorization. - * - * @author Robert Bausdorf - * - */ -public class FritzAhaUpdateXmlCallback extends FritzAhaReauthCallback { - /** - * logger - */ - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - - /** - * Handler to update - */ - private IFritzHandler handler; - - /** - * Constructor - * @param webIface Webinterface to FRITZ!Box - * @param handler Bridge handler taht will update things. - */ - public FritzAhaUpdateXmlCallback(FritzahaWebInterface webIface, IFritzHandler handler) { - super(WEBSERVICE_PATH, "switchcmd=getdevicelistinfos", webIface, Method.GET, 1); - this.handler = handler; - } - - /** - * {@inheritDoc} - */ - public void execute(int status, String response) { - super.execute(status, response); - if (this.isValidRequest()) { - logger.trace("Received State response " + response); - try { - JAXBContext jaxbContext = JAXBContext - .newInstance(DevicelistModel.class); - Unmarshaller jaxbUM = jaxbContext.createUnmarshaller(); - - DevicelistModel model = (DevicelistModel) jaxbUM - .unmarshal(new StringReader(response)); - if( model != null ) { - for( DeviceModel device : model.getDevicelist() ) { - handler.addDeviceList(device); - } - handler.setStatusInfo(ThingStatus.ONLINE, - ThingStatusDetail.NONE, "FritzBox online"); - } else { - logger.warn("no model in response"); - } - } catch (JAXBException e) { - logger.error(e.getLocalizedMessage(), e); - } - } else { - logger.info("request is invalid: " + status); - } - } -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.avmfritz.internal.hardware.callbacks; + +import java.io.StringReader; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; + +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.openhab.binding.avmfritz.handler.IFritzHandler; +import org.openhab.binding.avmfritz.internal.ahamodel.DeviceModel; +import org.openhab.binding.avmfritz.internal.ahamodel.DevicelistModel; +import org.openhab.binding.avmfritz.internal.hardware.FritzahaWebInterface; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Callback implementation for updating multiple numbers decoded from a xml + * response. Supports reauthorization. + * + * @author Robert Bausdorf + * + */ +public class FritzAhaUpdateXmlCallback extends FritzAhaReauthCallback { + /** + * logger + */ + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + /** + * Handler to update + */ + private IFritzHandler handler; + + /** + * Constructor + * @param webIface Webinterface to FRITZ!Box + * @param handler Bridge handler taht will update things. + */ + public FritzAhaUpdateXmlCallback(FritzahaWebInterface webIface, IFritzHandler handler) { + super(WEBSERVICE_PATH, "switchcmd=getdevicelistinfos", webIface, Method.GET, 1); + this.handler = handler; + } + + /** + * {@inheritDoc} + */ + public void execute(int status, String response) { + super.execute(status, response); + if (this.isValidRequest()) { + logger.trace("Received State response " + response); + try { + JAXBContext jaxbContext = JAXBContext + .newInstance(DevicelistModel.class); + Unmarshaller jaxbUM = jaxbContext.createUnmarshaller(); + + DevicelistModel model = (DevicelistModel) jaxbUM + .unmarshal(new StringReader(response)); + if( model != null ) { + for( DeviceModel device : model.getDevicelist() ) { + handler.addDeviceList(device); + } + handler.setStatusInfo(ThingStatus.ONLINE, + ThingStatusDetail.NONE, "FritzBox online"); + } else { + logger.warn("no model in response"); + } + } catch (JAXBException e) { + logger.error(e.getLocalizedMessage(), e); + } + } else { + logger.info("request is invalid: " + status); + } + } +} diff --git a/addons/binding/org.openhab.binding.max.test/.classpath b/addons/binding/org.openhab.binding.max.test/.classpath index 0b00a0280ed45..bc938b62884fd 100644 --- a/addons/binding/org.openhab.binding.max.test/.classpath +++ b/addons/binding/org.openhab.binding.max.test/.classpath @@ -1,9 +1,9 @@ - - - - - - - - - + + + + + + + + + diff --git a/addons/binding/org.openhab.binding.max.test/.groovy/suggestions.xdsl b/addons/binding/org.openhab.binding.max.test/.groovy/suggestions.xdsl index 1ce9852b140c0..f5bf460b7522c 100644 --- a/addons/binding/org.openhab.binding.max.test/.groovy/suggestions.xdsl +++ b/addons/binding/org.openhab.binding.max.test/.groovy/suggestions.xdsl @@ -1,2 +1,2 @@ - - + + diff --git a/addons/binding/org.openhab.binding.max.test/.settings/org.eclipse.jdt.groovy.core.prefs b/addons/binding/org.openhab.binding.max.test/.settings/org.eclipse.jdt.groovy.core.prefs index a68b5bf397081..65c6dc88b43da 100644 --- a/addons/binding/org.openhab.binding.max.test/.settings/org.eclipse.jdt.groovy.core.prefs +++ b/addons/binding/org.openhab.binding.max.test/.settings/org.eclipse.jdt.groovy.core.prefs @@ -1,2 +1,2 @@ -eclipse.preferences.version=1 -groovy.compiler.level=-1 +eclipse.preferences.version=1 +groovy.compiler.level=-1 diff --git a/addons/binding/org.openhab.binding.max.test/.settings/org.eclipse.pde.core.prefs b/addons/binding/org.openhab.binding.max.test/.settings/org.eclipse.pde.core.prefs index e313d3c3b6b38..923c37fb8d55b 100644 --- a/addons/binding/org.openhab.binding.max.test/.settings/org.eclipse.pde.core.prefs +++ b/addons/binding/org.openhab.binding.max.test/.settings/org.eclipse.pde.core.prefs @@ -1,2 +1,2 @@ -eclipse.preferences.version=1 -resolve.requirebundle=false +eclipse.preferences.version=1 +resolve.requirebundle=false diff --git a/addons/binding/org.openhab.binding.max.test/META-INF/MANIFEST.MF b/addons/binding/org.openhab.binding.max.test/META-INF/MANIFEST.MF index d975b3d4243a0..0dedc8c13c0cd 100644 --- a/addons/binding/org.openhab.binding.max.test/META-INF/MANIFEST.MF +++ b/addons/binding/org.openhab.binding.max.test/META-INF/MANIFEST.MF @@ -1,26 +1,26 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Openhab Max! Binding Tests -Bundle-SymbolicName: org.openhab.binding.max.test;singleton:=true -Bundle-Version: 2.1.0.qualifier -Bundle-RequiredExecutionEnvironment: JavaSE-1.7 -Bundle-Vendor: Openhab -Fragment-Host: org.openhab.binding.max -Import-Package: groovy.json, - groovy.lang, - org.codehaus.groovy.reflection, - org.codehaus.groovy.runtime, - org.codehaus.groovy.runtime.callsite, - org.codehaus.groovy.runtime.typehandling, - org.eclipse.smarthome.core.events, - org.eclipse.smarthome.core.thing.util, - org.eclipse.smarthome.test, - org.eclipse.smarthome.test.storage, - org.hamcrest;core=split, - org.openhab.binding.max, - org.osgi.service.device, - org.slf4j -Require-Bundle: org.junit;bundle-version="4.11.0" -Export-Package: org.openhab.binding.max.internal.message;x-internal:=true, - org.openhab.binding.max.test;uses:="org.eclipse.smarthome.test" - +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Openhab Max! Binding Tests +Bundle-SymbolicName: org.openhab.binding.max.test;singleton:=true +Bundle-Version: 2.1.0.qualifier +Bundle-RequiredExecutionEnvironment: JavaSE-1.7 +Bundle-Vendor: Openhab +Fragment-Host: org.openhab.binding.max +Import-Package: groovy.json, + groovy.lang, + org.codehaus.groovy.reflection, + org.codehaus.groovy.runtime, + org.codehaus.groovy.runtime.callsite, + org.codehaus.groovy.runtime.typehandling, + org.eclipse.smarthome.core.events, + org.eclipse.smarthome.core.thing.util, + org.eclipse.smarthome.test, + org.eclipse.smarthome.test.storage, + org.hamcrest;core=split, + org.openhab.binding.max, + org.osgi.service.device, + org.slf4j +Require-Bundle: org.junit;bundle-version="4.11.0" +Export-Package: org.openhab.binding.max.internal.message;x-internal:=true, + org.openhab.binding.max.test;uses:="org.eclipse.smarthome.test" + diff --git a/addons/binding/org.openhab.binding.max.test/MaxBindingTests.launch b/addons/binding/org.openhab.binding.max.test/MaxBindingTests.launch index 542fab481d331..935c5473c823c 100644 --- a/addons/binding/org.openhab.binding.max.test/MaxBindingTests.launch +++ b/addons/binding/org.openhab.binding.max.test/MaxBindingTests.launch @@ -1,45 +1,45 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/addons/binding/org.openhab.binding.max.test/sample/sampleMessage.txt b/addons/binding/org.openhab.binding.max.test/sample/sampleMessage.txt index dfe346ac57615..0cb2df31149e8 100644 --- a/addons/binding/org.openhab.binding.max.test/sample/sampleMessage.txt +++ b/addons/binding/org.openhab.binding.max.test/sample/sampleMessage.txt @@ -1,12 +1,12 @@ -H:KEQ0565026,0b5951,0113,00000000,4eed6795,01,32,0f0113,0f34,03,0000 -M:00,01,VgIFAQhiYWRrYW1lcgsNowIMU3R1ZGVlcmthbWVyB7bnAwlXb29ua2FtZXIL6aIEDFN6b25qYSBLYW1lcgjDSQUGWm9sZGVyCMHWCAILDaNLRVEwNTQ0MjQyEUJhZGthbWVyIFJhZGlhdG9yAQEHtudLRVEwMTQ1MTcyFVJhZGlhdG9yIFN0dWRlZXJrYW1lcgIDDhXMTEVRMDAxNTM0MBlXYWxsIFRoZXJtb3N0YXQgV29vbmthbWVyAwEL6aJLRVE5MDE1NDMyG1BsdWcgQWRhcHRlciBNdXVydmVyd2FybWluZwMFBDNvSkVRMDM4MDg3OBdFY28gU3dpdGNoIFN0dWRlZXJrYW1lcgAEDnX2S0VRMTEwNDM4MBpXaW5kb3cgU2Vuc29yIFN0dWRlZXJrYW1lcgIBCMNJS0VRMDY0ODk0ORJUaGVybW9zdGFhdCBTem9uamEEAQjB1ktFUTA2NDkzMTIRU3R1ZGVlcmthbWVyIElybWEFAQ== -C:0b5951,7QtZUQATAf9LRVEwNTY1MDI2AQsABEAAAAAAAAAAQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAsABEAAAAAAAAAAQgAAAAAAAAAAAAAAAAAAAAAAAAAAAGh0dHA6Ly9tYXguZXEtMy5kZTo4MC9jdWJlADAvbG9va3VwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAENFVAAACgADAAAOEENFU1QAAwACAAAcIA== -C:0b0da3,0gsNowIBEABLRVEwNTQ0MjQyLCQ9CQcYAzAM/wBIYViRSP1ZFE0gTSBNIEUgRSBFIEUgRSBFIEhhWJFQ/VkVUSBRIFEgRSBFIEUgRSBFIEUgSFBYWkj+WRRNIE0gTSBFIEUgRSBFIEUgRSBIUFhaSP5ZFE0gTSBNIEUgRSBFIEUgRSBFIEhQWFpI/lkUTSBNIE0gRSBFIEUgRSBFIEUgSFBYWkj+WRRNIE0gTSBFIEUgRSBFIEUgRSBIUFhaSP5ZFE0gTSBNIEUgRSBFIEUgRSBFIA== -C:08c1d6,0gjB1gEFGP9LRVEwNjQ5MzEyKyE9CQcYAzAM/wBEeFUgVSBVIFUgVSBVIEUgRSBFIEUgRSBFIER4VRZFIEUgRSBFIEUgRSBFIEUgRSBFIEUgRFFEYkTkTQ9FIEUgRSBFIEUgRSBFIEUgRSBEUURiRORND0UgRSBFIEUgRSBFIEUgRSBFIERRRGJE5E0PRSBFIEUgRSBFIEUgRSBFIEUgRFFEYkTkTQ9FIEUgRSBFIEUgRSBFIEUgRSBEUURiRORRGEUgRSBFIEUgRSBFIEUgRSBFIA== -C:0e75f6,EQ519gQCEABLRVExMTA0Mzgw -C:04336f,EQQzbwUAEg9KRVEwMzgwODc4 -C:0be9a2,0gvpogEDEapLRVE5MDE1NDMyKyE9CQcYAzAM/wBEbFkgWSBZIFkgWSBZIEUgRSBFIEUgRSBFIERgWSBZIFkgWSBZIFkgRSBFIEUgRSBFIEUgRFFUYUTYWSBZIFkgWSBFIEUgRSBFIEUgRSBEUVRhRNhZIFkgWSBZIEUgRSBFIEUgRSBFIERRVGFE2FkgWSBZIFkgRSBFIEUgRSBFIEUgRFFUYUTYWSBZIFkgWSBFIEUgRSBFIEUgRSBEUVRhRNhZIFkgWSBZIEUgRSBFIEUgRSBFIA== -C:0e15cc,zg4VzAMDEP9MRVEwMDE1MzQwKyE9CURsWSBZIFkgWSBZIFkgRSBFIEUgRSBFIEUgRGBZIFkgWSBZIFkgWSBFIEUgRSBFIEUgRSBEUVRhRNhZIFkgWSBZIEUgRSBFIEUgRSBFIERRVGFE2FkgWSBZIFkgRSBFIEUgRSBFIEUgRFFUYUTYWSBZIFkgWSBFIEUgRSBFIEUgRSBEUVRhRNhZIFkgWSBZIEUgRSBFIEUgRSBFIERRVGFE2FkgWSBZIFkgRSBFIEUgRSBFIEUgBxgw -C:08c349,0gjDSQEEGP9LRVEwNjQ4OTQ5KiA9CQcYAzAM/wBEbFUKRSBFIEUgRSBFIEUgRSBFIEUgRSBFIERgVQlFIEUgRSBFIEUgRSBFIEUgRSBFIEUgRFFUYUS0VQNFIEUgRSBFIEUgRSBFIEUgRSBEUVRhRLRVA0UgRSBFIEUgRSBFIEUgRSBFIERRVGFEtFUDRSBFIEUgRSBFIEUgRSBFIEUgRFFUYUS0VQNFIEUgRSBFIEUgRSBFIEUgRSBEUVRhRLRVCkUgRSBFIEUgRSBFIEUgRSBFIA== -C:07b6e7,0ge25wECGP9LRVEwMTQ1MTcyKyE9CQcYAzAM/wBEflUaRSBFIEUgRSBFIEUgRSBFIEUgRSBFIER+VRpFIEUgRSBFIEUgRSBFIEUgRSBFIEUgRFRUcEjSVRJJIEkgSSBFIEUgRSBFIEUgRSBEVFRwSNJVEkkgSSBJIEUgRSBFIEUgRSBFIERUVG9U01URSSBJIEkgRSBFIEUgRSBFIEUgRFRUcEjSVRJJIEkgSSBFIEUgRSBFIEUgRSBEVFRwSNJVEkkgSSBJIEUgRSBFIEUgRSBFIA== -L:CwsNowkSGE0kALAACwjB1gkSGGAiAAAABg519gkSEAYEM28JAAALC+miCRIYACIAAAAMDhXMCRIYBCIAAACtCwjDSQkSGGQqAGMACwe25wkSGGQkAAAA +H:KEQ0565026,0b5951,0113,00000000,4eed6795,01,32,0f0113,0f34,03,0000 +M:00,01,VgIFAQhiYWRrYW1lcgsNowIMU3R1ZGVlcmthbWVyB7bnAwlXb29ua2FtZXIL6aIEDFN6b25qYSBLYW1lcgjDSQUGWm9sZGVyCMHWCAILDaNLRVEwNTQ0MjQyEUJhZGthbWVyIFJhZGlhdG9yAQEHtudLRVEwMTQ1MTcyFVJhZGlhdG9yIFN0dWRlZXJrYW1lcgIDDhXMTEVRMDAxNTM0MBlXYWxsIFRoZXJtb3N0YXQgV29vbmthbWVyAwEL6aJLRVE5MDE1NDMyG1BsdWcgQWRhcHRlciBNdXVydmVyd2FybWluZwMFBDNvSkVRMDM4MDg3OBdFY28gU3dpdGNoIFN0dWRlZXJrYW1lcgAEDnX2S0VRMTEwNDM4MBpXaW5kb3cgU2Vuc29yIFN0dWRlZXJrYW1lcgIBCMNJS0VRMDY0ODk0ORJUaGVybW9zdGFhdCBTem9uamEEAQjB1ktFUTA2NDkzMTIRU3R1ZGVlcmthbWVyIElybWEFAQ== +C:0b5951,7QtZUQATAf9LRVEwNTY1MDI2AQsABEAAAAAAAAAAQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAsABEAAAAAAAAAAQgAAAAAAAAAAAAAAAAAAAAAAAAAAAGh0dHA6Ly9tYXguZXEtMy5kZTo4MC9jdWJlADAvbG9va3VwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAENFVAAACgADAAAOEENFU1QAAwACAAAcIA== +C:0b0da3,0gsNowIBEABLRVEwNTQ0MjQyLCQ9CQcYAzAM/wBIYViRSP1ZFE0gTSBNIEUgRSBFIEUgRSBFIEhhWJFQ/VkVUSBRIFEgRSBFIEUgRSBFIEUgSFBYWkj+WRRNIE0gTSBFIEUgRSBFIEUgRSBIUFhaSP5ZFE0gTSBNIEUgRSBFIEUgRSBFIEhQWFpI/lkUTSBNIE0gRSBFIEUgRSBFIEUgSFBYWkj+WRRNIE0gTSBFIEUgRSBFIEUgRSBIUFhaSP5ZFE0gTSBNIEUgRSBFIEUgRSBFIA== +C:08c1d6,0gjB1gEFGP9LRVEwNjQ5MzEyKyE9CQcYAzAM/wBEeFUgVSBVIFUgVSBVIEUgRSBFIEUgRSBFIER4VRZFIEUgRSBFIEUgRSBFIEUgRSBFIEUgRFFEYkTkTQ9FIEUgRSBFIEUgRSBFIEUgRSBEUURiRORND0UgRSBFIEUgRSBFIEUgRSBFIERRRGJE5E0PRSBFIEUgRSBFIEUgRSBFIEUgRFFEYkTkTQ9FIEUgRSBFIEUgRSBFIEUgRSBEUURiRORRGEUgRSBFIEUgRSBFIEUgRSBFIA== +C:0e75f6,EQ519gQCEABLRVExMTA0Mzgw +C:04336f,EQQzbwUAEg9KRVEwMzgwODc4 +C:0be9a2,0gvpogEDEapLRVE5MDE1NDMyKyE9CQcYAzAM/wBEbFkgWSBZIFkgWSBZIEUgRSBFIEUgRSBFIERgWSBZIFkgWSBZIFkgRSBFIEUgRSBFIEUgRFFUYUTYWSBZIFkgWSBFIEUgRSBFIEUgRSBEUVRhRNhZIFkgWSBZIEUgRSBFIEUgRSBFIERRVGFE2FkgWSBZIFkgRSBFIEUgRSBFIEUgRFFUYUTYWSBZIFkgWSBFIEUgRSBFIEUgRSBEUVRhRNhZIFkgWSBZIEUgRSBFIEUgRSBFIA== +C:0e15cc,zg4VzAMDEP9MRVEwMDE1MzQwKyE9CURsWSBZIFkgWSBZIFkgRSBFIEUgRSBFIEUgRGBZIFkgWSBZIFkgWSBFIEUgRSBFIEUgRSBEUVRhRNhZIFkgWSBZIEUgRSBFIEUgRSBFIERRVGFE2FkgWSBZIFkgRSBFIEUgRSBFIEUgRFFUYUTYWSBZIFkgWSBFIEUgRSBFIEUgRSBEUVRhRNhZIFkgWSBZIEUgRSBFIEUgRSBFIERRVGFE2FkgWSBZIFkgRSBFIEUgRSBFIEUgBxgw +C:08c349,0gjDSQEEGP9LRVEwNjQ4OTQ5KiA9CQcYAzAM/wBEbFUKRSBFIEUgRSBFIEUgRSBFIEUgRSBFIERgVQlFIEUgRSBFIEUgRSBFIEUgRSBFIEUgRFFUYUS0VQNFIEUgRSBFIEUgRSBFIEUgRSBEUVRhRLRVA0UgRSBFIEUgRSBFIEUgRSBFIERRVGFEtFUDRSBFIEUgRSBFIEUgRSBFIEUgRFFUYUS0VQNFIEUgRSBFIEUgRSBFIEUgRSBEUVRhRLRVCkUgRSBFIEUgRSBFIEUgRSBFIA== +C:07b6e7,0ge25wECGP9LRVEwMTQ1MTcyKyE9CQcYAzAM/wBEflUaRSBFIEUgRSBFIEUgRSBFIEUgRSBFIER+VRpFIEUgRSBFIEUgRSBFIEUgRSBFIEUgRFRUcEjSVRJJIEkgSSBFIEUgRSBFIEUgRSBEVFRwSNJVEkkgSSBJIEUgRSBFIEUgRSBFIERUVG9U01URSSBJIEkgRSBFIEUgRSBFIEUgRFRUcEjSVRJJIEkgSSBFIEUgRSBFIEUgRSBEVFRwSNJVEkkgSSBJIEUgRSBFIEUgRSBFIA== +L:CwsNowkSGE0kALAACwjB1gkSGGAiAAAABg519gkSEAYEM28JAAALC+miCRIYACIAAAAMDhXMCRIYBCIAAACtCwjDSQkSGGQqAGMACwe25wkSGGQkAAAA diff --git a/addons/binding/org.openhab.binding.miele/OSGI-INF/MieleMDNSDiscoveryParticipant.xml b/addons/binding/org.openhab.binding.miele/OSGI-INF/MieleMDNSDiscoveryParticipant.xml index fc94056247ef0..8e4ed752e3e94 100644 --- a/addons/binding/org.openhab.binding.miele/OSGI-INF/MieleMDNSDiscoveryParticipant.xml +++ b/addons/binding/org.openhab.binding.miele/OSGI-INF/MieleMDNSDiscoveryParticipant.xml @@ -1,21 +1,21 @@ - - - - - - - + + + + + + + - + diff --git a/addons/binding/org.openhab.binding.netatmo/README.md b/addons/binding/org.openhab.binding.netatmo/README.md index 6d9b6ef7d1730..43bf5c00bf487 100644 --- a/addons/binding/org.openhab.binding.netatmo/README.md +++ b/addons/binding/org.openhab.binding.netatmo/README.md @@ -1,274 +1,274 @@ ---- -layout: documentation ---- - -{% include base.html %} - -# Netatmo Binding - -The Netatmo binding integrates the following Netatmo products : -- *Personal Weather Station*. Reports temperature, humidity, air pressure, carbon dioxide concentration in the air, as well as the ambient noise level. -- *Thermostat*. Reports ambient temperature, allow to check target temperature, consult and change furnace heating status. - -See http://www.netatmo.com/ for details on their product. - -## Binding Configuration - -The binding has no configuration options itself, all configuration is done at 'Things' level but before, you'll have to grant openHab to access Netatmo API. Here is the procedure : - -### 1. Application creation -Create an application at https://dev.netatmo.com/dev/createapp - -The variables you'll need to get to setup the binding are: -* `` Your client ID taken from your App at https://dev.netatmo.com/dev/listapps -* `` A token provided along with the ``. -* `` The username you use to connect to the Netatmo API (usually your mail address). -* `` The password attached to the above username. - -## 2.Bridge and Things Configuration - -Once you'll get needed informations from the Netatmo API, you'll be able to configure bridge and things. - -E.g. -``` -Bridge netatmo:netatmoapi:home [ clientId="", clientSecret="", username = "", password = "", readStation=true|false, readThermostat=true|false] { - Thing NAMain inside [ equipmentId="aa:aa:aa:aa:aa:aa", [refreshInterval=60000] ] - Thing NAModule1 outside [ equipmentId="yy:yy:yy:yy:yy:yy", parentId="aa:aa:aa:aa:aa:aa" ] - Thing NAPlug plugtherm [ equipmentId="bb:bb:bb:bb:bb:bb", [refreshInterval=60000] ] - Thing NATherm1 thermostat [ equipmentId="xx:xx:xx:xx:xx:xx", parentId="bb:bb:bb:bb:bb:bb" ] - ... -} -``` - -### Configure Things - -The IDs for the modules can be extracted from the developer documentation on the netatmo site. -First login with your user. Then some examples of the documentation contain the **real results** of your weather station. Get the IDs of your devices (indoor, outdoor, rain gauge) here: - -``` -https://dev.netatmo.com/doc/methods/devicelist -``` - -main_device is the ID of the "main device", the indoor sensor. This is equal to the MAC address of the Netatmo. - -The other modules you can recognize by "module_name" and then note the "_id" which you need later. - -**Another way to get the IDs is to calculate them:** - -You have to calculate the ID for the outside module as follows: (it cannot be read from the app) -if the first serial character is "h": start with "02", -if the first serial character is "i": start with "03", - -append ":00:00:", - -split the rest into three parts of two characters and append with a colon as delimeter. - -For example your serial number "h00bcdc" should end up as "02:00:00:00:bc:dc". - -## Discovery - -If you don't manually create things in the *.things file, the Netatmo Binding is able to discover automatically all depending modules and devices from Netatmo website. - -## Channels - -### Weather Station Main Indoor Device -Example item for the **indoor module**: -``` -Number Netatmo_Indoor_CO2 "CO2" { channel = "netatmo:NAMain:home:inside:Co2" } -``` - -**Supported types for the indoor module:** -* Temperature -* Humidity -* Co2 -* Pressure -* AbsolutePressure -* Noise -* WifiStatus -* Location -* TimeStamp -* HeatIndex -* Humidex -* Dewpoint -* DewpointDepression -* WifiStatus -* LastStatusStore - -### Weather Station Outdoor module -Example item for the **outdoor module** -``` -Number Netatmo_Outdoor_Temperature "Temperature" { channel = "netatmo:NAModule1:home:outside:Temperature" } -``` - -**Supported types for the outdoor module:** -* Temperature -* Humidity -* RfStatus -* BatteryVP -* TimeStamp -* Humidex -* HeatIndex -* Dewpoint -* DewpointDepression -* LastMessage -* LowBattery - -### Weather Station Additional Indoor module -Example item for the **indoor module** -``` -Number Netatmo_Indoor2_Temperature "Temperature" { channel = "netatmo:NAModule4:home:insidesupp:Temperature" } -``` - -**Supported types for the additional indoor module:** -* Co2 -* Temperature -* Humidity -* RfStatus -* BatteryVP -* TimeStamp -* Humidex -* HeatIndex -* Dewpoint -* DewpointDepression -* LastMessage -* LowBattery - -### Rain -Example item for the **rain gauge** -``` -Number Netatmo_Rain_Current "Rain [%.1f mm]" { channel = "netatmo:NAModule3:home:rain:Rain" } -``` - -**Supported types for the rain guage:** -* Rain -* RfStatus -* BatteryVP -* LastMessage -* LowBattery - -### Weather Station Wind module -Example item for the **wind module** : -``` -Number Netatmo_Wind_Strength "Wind Strength [%.0f KPH]" { channel = "netatmo:NAModule2:home:wind:WindStrength" } -``` - -**Supported types for the wind module:** -* WindStrength -* WindAngle -* GustStrength -* GustAngle -* LastMessage -* LowBattery -* RfStatus -* BatteryVP - -### Thermostat Relay Device - - -**Supported types for the thermostat relay device:** -* LastStatusStore -* WifiStatus -* Location - -### Thermostat Module - -**Supported types for the thermostat module:** -* Temperature -* SetpointTemperature -* SetpointMode -* BoilerOn -* BoilerOff -* TimeStamp - -# Common problems - -## Missing Certificate Authority - -This version of the binding has been modified to avoid the need to impoort StartCom certificate in the local JDK certificate store. - - -``` -javax.net.ssl.SSLHandshakeException: -sun.security.validator.ValidatorException: -PKIX path building failed: -sun.security.provider.certpath.SunCertPathBuilderException: -unable to find valid certification path to requested target -``` - -can be solved by installing the StartCom CA Certificate into the local JDK like this: - -* Download the certificate from https://www.startssl.com/certs/ca.pem or use wget https://www.startssl.com/certs/ca.pem - -* Then import it into the keystore (the password is "changeit") -``` -$JAVA_HOME/bin/keytool -import -keystore $JAVA_HOME/jre/lib/security/cacerts -alias StartCom-Root-CA -file ca.pem -``` -If $JAVA_HOME is not set then run the command: -update-alternatives --list java - -This should output something similar to: -/usr/lib/jvm/java-8-oracle/jre/bin/java - -Use everything before /jre/... to set the JAVA_HOME environment variable: -export JAVA_HOME=/usr/lib/jvm/java-8-oracle - -After you set the environment variable, try: - -ls -l $JAVA_HOME/jre/lib/security/cacerts - -If it's set correctly then you should see something similar to: --rw-r--r-- 1 root root 101992 Nov 4 10:54 /usr/lib/jvm/java-8-oracle/jre/lib/security/cacerts - -Now try and rerun the keytool command. If you didn't get errors, you should be good to go. - -source: http://jinahya.wordpress.com/2013/04/28/installing-the-startcom-ca-certifcate-into-the-local-jdk/ - -alternative approach if above solution does not work: - -``` -sudo keytool -delete -alias StartCom-Root-CA -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit -``` - -download the certificate from https://api.netatmo.net to $JAVA_HOME/jre/lib/security/ and save it as api.netatmo.net.crt (X.509 / PEM) - - -``` -sudo $JAVA_HOME/bin/keytool -import -keystore $JAVA_HOME/jre/lib/security/cacerts -alias StartCom-Root-CA -file api.netatmo.net.crt -``` -The password is "changeit". - -# Sample data - -If you want to evaluate this binding but have not got a Netatmo station yourself -yet, you can add the Netatmo office in Paris to your account: - -http://www.netatmo.com/en-US/addguest/index/TIQ3797dtfOmgpqUcct3/70:ee:50:00:02:20 - -# Icons -The following icons are used by original Netatmo web app: - -## Modules -http://my.netatmo.com/img/my/app/module_int.png -http://my.netatmo.com/img/my/app/module_ext.png -http://my.netatmo.com/img/my/app/module_rain.png - -## Battery status -http://my.netatmo.com/img/my/app/battery_verylow.png -http://my.netatmo.com/img/my/app/battery_low.png -http://my.netatmo.com/img/my/app/battery_medium.png -http://my.netatmo.com/img/my/app/battery_high.png -http://my.netatmo.com/img/my/app/battery_full.png - -## Signal status -http://my.netatmo.com/img/my/app/signal_verylow.png -http://my.netatmo.com/img/my/app/signal_low.png -http://my.netatmo.com/img/my/app/signal_medium.png -http://my.netatmo.com/img/my/app/signal_high.png -http://my.netatmo.com/img/my/app/signal_full.png - -## Wifi status -http://my.netatmo.com/img/my/app/wifi_low.png -http://my.netatmo.com/img/my/app/wifi_medium.png -http://my.netatmo.com/img/my/app/wifi_high.png -http://my.netatmo.com/img/my/app/wifi_full.png +--- +layout: documentation +--- + +{% include base.html %} + +# Netatmo Binding + +The Netatmo binding integrates the following Netatmo products : +- *Personal Weather Station*. Reports temperature, humidity, air pressure, carbon dioxide concentration in the air, as well as the ambient noise level. +- *Thermostat*. Reports ambient temperature, allow to check target temperature, consult and change furnace heating status. + +See http://www.netatmo.com/ for details on their product. + +## Binding Configuration + +The binding has no configuration options itself, all configuration is done at 'Things' level but before, you'll have to grant openHab to access Netatmo API. Here is the procedure : + +### 1. Application creation +Create an application at https://dev.netatmo.com/dev/createapp + +The variables you'll need to get to setup the binding are: +* `` Your client ID taken from your App at https://dev.netatmo.com/dev/listapps +* `` A token provided along with the ``. +* `` The username you use to connect to the Netatmo API (usually your mail address). +* `` The password attached to the above username. + +## 2.Bridge and Things Configuration + +Once you'll get needed informations from the Netatmo API, you'll be able to configure bridge and things. + +E.g. +``` +Bridge netatmo:netatmoapi:home [ clientId="", clientSecret="", username = "", password = "", readStation=true|false, readThermostat=true|false] { + Thing NAMain inside [ equipmentId="aa:aa:aa:aa:aa:aa", [refreshInterval=60000] ] + Thing NAModule1 outside [ equipmentId="yy:yy:yy:yy:yy:yy", parentId="aa:aa:aa:aa:aa:aa" ] + Thing NAPlug plugtherm [ equipmentId="bb:bb:bb:bb:bb:bb", [refreshInterval=60000] ] + Thing NATherm1 thermostat [ equipmentId="xx:xx:xx:xx:xx:xx", parentId="bb:bb:bb:bb:bb:bb" ] + ... +} +``` + +### Configure Things + +The IDs for the modules can be extracted from the developer documentation on the netatmo site. +First login with your user. Then some examples of the documentation contain the **real results** of your weather station. Get the IDs of your devices (indoor, outdoor, rain gauge) here: + +``` +https://dev.netatmo.com/doc/methods/devicelist +``` + +main_device is the ID of the "main device", the indoor sensor. This is equal to the MAC address of the Netatmo. + +The other modules you can recognize by "module_name" and then note the "_id" which you need later. + +**Another way to get the IDs is to calculate them:** + +You have to calculate the ID for the outside module as follows: (it cannot be read from the app) +if the first serial character is "h": start with "02", +if the first serial character is "i": start with "03", + +append ":00:00:", + +split the rest into three parts of two characters and append with a colon as delimeter. + +For example your serial number "h00bcdc" should end up as "02:00:00:00:bc:dc". + +## Discovery + +If you don't manually create things in the *.things file, the Netatmo Binding is able to discover automatically all depending modules and devices from Netatmo website. + +## Channels + +### Weather Station Main Indoor Device +Example item for the **indoor module**: +``` +Number Netatmo_Indoor_CO2 "CO2" { channel = "netatmo:NAMain:home:inside:Co2" } +``` + +**Supported types for the indoor module:** +* Temperature +* Humidity +* Co2 +* Pressure +* AbsolutePressure +* Noise +* WifiStatus +* Location +* TimeStamp +* HeatIndex +* Humidex +* Dewpoint +* DewpointDepression +* WifiStatus +* LastStatusStore + +### Weather Station Outdoor module +Example item for the **outdoor module** +``` +Number Netatmo_Outdoor_Temperature "Temperature" { channel = "netatmo:NAModule1:home:outside:Temperature" } +``` + +**Supported types for the outdoor module:** +* Temperature +* Humidity +* RfStatus +* BatteryVP +* TimeStamp +* Humidex +* HeatIndex +* Dewpoint +* DewpointDepression +* LastMessage +* LowBattery + +### Weather Station Additional Indoor module +Example item for the **indoor module** +``` +Number Netatmo_Indoor2_Temperature "Temperature" { channel = "netatmo:NAModule4:home:insidesupp:Temperature" } +``` + +**Supported types for the additional indoor module:** +* Co2 +* Temperature +* Humidity +* RfStatus +* BatteryVP +* TimeStamp +* Humidex +* HeatIndex +* Dewpoint +* DewpointDepression +* LastMessage +* LowBattery + +### Rain +Example item for the **rain gauge** +``` +Number Netatmo_Rain_Current "Rain [%.1f mm]" { channel = "netatmo:NAModule3:home:rain:Rain" } +``` + +**Supported types for the rain guage:** +* Rain +* RfStatus +* BatteryVP +* LastMessage +* LowBattery + +### Weather Station Wind module +Example item for the **wind module** : +``` +Number Netatmo_Wind_Strength "Wind Strength [%.0f KPH]" { channel = "netatmo:NAModule2:home:wind:WindStrength" } +``` + +**Supported types for the wind module:** +* WindStrength +* WindAngle +* GustStrength +* GustAngle +* LastMessage +* LowBattery +* RfStatus +* BatteryVP + +### Thermostat Relay Device + + +**Supported types for the thermostat relay device:** +* LastStatusStore +* WifiStatus +* Location + +### Thermostat Module + +**Supported types for the thermostat module:** +* Temperature +* SetpointTemperature +* SetpointMode +* BoilerOn +* BoilerOff +* TimeStamp + +# Common problems + +## Missing Certificate Authority + +This version of the binding has been modified to avoid the need to impoort StartCom certificate in the local JDK certificate store. + + +``` +javax.net.ssl.SSLHandshakeException: +sun.security.validator.ValidatorException: +PKIX path building failed: +sun.security.provider.certpath.SunCertPathBuilderException: +unable to find valid certification path to requested target +``` + +can be solved by installing the StartCom CA Certificate into the local JDK like this: + +* Download the certificate from https://www.startssl.com/certs/ca.pem or use wget https://www.startssl.com/certs/ca.pem + +* Then import it into the keystore (the password is "changeit") +``` +$JAVA_HOME/bin/keytool -import -keystore $JAVA_HOME/jre/lib/security/cacerts -alias StartCom-Root-CA -file ca.pem +``` +If $JAVA_HOME is not set then run the command: +update-alternatives --list java + +This should output something similar to: +/usr/lib/jvm/java-8-oracle/jre/bin/java + +Use everything before /jre/... to set the JAVA_HOME environment variable: +export JAVA_HOME=/usr/lib/jvm/java-8-oracle + +After you set the environment variable, try: + +ls -l $JAVA_HOME/jre/lib/security/cacerts + +If it's set correctly then you should see something similar to: +-rw-r--r-- 1 root root 101992 Nov 4 10:54 /usr/lib/jvm/java-8-oracle/jre/lib/security/cacerts + +Now try and rerun the keytool command. If you didn't get errors, you should be good to go. + +source: http://jinahya.wordpress.com/2013/04/28/installing-the-startcom-ca-certifcate-into-the-local-jdk/ + +alternative approach if above solution does not work: + +``` +sudo keytool -delete -alias StartCom-Root-CA -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit +``` + +download the certificate from https://api.netatmo.net to $JAVA_HOME/jre/lib/security/ and save it as api.netatmo.net.crt (X.509 / PEM) + + +``` +sudo $JAVA_HOME/bin/keytool -import -keystore $JAVA_HOME/jre/lib/security/cacerts -alias StartCom-Root-CA -file api.netatmo.net.crt +``` +The password is "changeit". + +# Sample data + +If you want to evaluate this binding but have not got a Netatmo station yourself +yet, you can add the Netatmo office in Paris to your account: + +http://www.netatmo.com/en-US/addguest/index/TIQ3797dtfOmgpqUcct3/70:ee:50:00:02:20 + +# Icons +The following icons are used by original Netatmo web app: + +## Modules +http://my.netatmo.com/img/my/app/module_int.png +http://my.netatmo.com/img/my/app/module_ext.png +http://my.netatmo.com/img/my/app/module_rain.png + +## Battery status +http://my.netatmo.com/img/my/app/battery_verylow.png +http://my.netatmo.com/img/my/app/battery_low.png +http://my.netatmo.com/img/my/app/battery_medium.png +http://my.netatmo.com/img/my/app/battery_high.png +http://my.netatmo.com/img/my/app/battery_full.png + +## Signal status +http://my.netatmo.com/img/my/app/signal_verylow.png +http://my.netatmo.com/img/my/app/signal_low.png +http://my.netatmo.com/img/my/app/signal_medium.png +http://my.netatmo.com/img/my/app/signal_high.png +http://my.netatmo.com/img/my/app/signal_full.png + +## Wifi status +http://my.netatmo.com/img/my/app/wifi_low.png +http://my.netatmo.com/img/my/app/wifi_medium.png +http://my.netatmo.com/img/my/app/wifi_high.png +http://my.netatmo.com/img/my/app/wifi_full.png \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.network/src/main/java/org/openhab/binding/network/discovery/NetworkDiscoveryService.java b/addons/binding/org.openhab.binding.network/src/main/java/org/openhab/binding/network/discovery/NetworkDiscoveryService.java index ffd66a3e49cfd..a26fd92ecb2d8 100644 --- a/addons/binding/org.openhab.binding.network/src/main/java/org/openhab/binding/network/discovery/NetworkDiscoveryService.java +++ b/addons/binding/org.openhab.binding.network/src/main/java/org/openhab/binding/network/discovery/NetworkDiscoveryService.java @@ -1,104 +1,104 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.network.discovery; - -import static org.openhab.binding.network.NetworkBindingConstants.*; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService; -import org.eclipse.smarthome.config.discovery.DiscoveryResult; -import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; -import org.eclipse.smarthome.core.thing.ThingUID; -import org.openhab.binding.network.service.DiscoveryCallback; -import org.openhab.binding.network.service.NetworkUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link NetworkDiscoveryService} is responsible for discovering devices on - * the current Network. It uses every Network Interface which is connected to a network. - * - * @author Marc Mettke - Initial contribution - */ -public class NetworkDiscoveryService extends AbstractDiscoveryService implements DiscoveryCallback { - private final Logger logger = LoggerFactory.getLogger(NetworkDiscoveryService.class); - private ExecutorService executorService = null; - final static int PING_TIMEOUT_IN_MS = 500; - private int scanningNetworkSize = 0; - - public NetworkDiscoveryService() { - super(SUPPORTED_THING_TYPES_UIDS, 900, false); - } - - /** - * Starts the DiscoveryThread for each IP on each interface on the network - * - */ - @Override - protected void startScan() { - if (executorService != null) { - stopScan(); - } - - logger.debug("Starting Discovery"); - LinkedHashSet networkIPs = NetworkUtils.getNetworkIPs(NetworkUtils.getInterfaceIPs()); - scanningNetworkSize = networkIPs.size(); - executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 10); - - for (Iterator it = networkIPs.iterator(); it.hasNext();) { - final String ip = it.next(); - executorService.execute(new PingRunnable(ip, this)); - } - stopScan(); - } - - @Override - protected synchronized void stopScan() { - super.stopScan(); - if (executorService == null) { - return; - } - - try { - executorService.awaitTermination(PING_TIMEOUT_IN_MS * scanningNetworkSize, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - } - executorService.shutdown(); - executorService = null; - - } - - /** - * Submit newly discovered devices. This method is called by the spawned threads in {@link startScan}. - * - * @param ip The device IP, received by the - */ - @Override - public void newDevice(String ip) { - logger.info("Found " + ip); - - // uid must not contains dots - ThingUID uid = new ThingUID(THING_TYPE_DEVICE, ip.replace('.', '_')); - - if (uid != null) { - Map properties = new HashMap<>(1); - properties.put(PARAMETER_HOSTNAME, ip); - DiscoveryResult result = DiscoveryResultBuilder.create(uid).withProperties(properties) - .withLabel("Network Device (" + ip + ")").build(); - thingDiscovered(result); - } - } -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.network.discovery; + +import static org.openhab.binding.network.NetworkBindingConstants.*; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService; +import org.eclipse.smarthome.config.discovery.DiscoveryResult; +import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.openhab.binding.network.service.DiscoveryCallback; +import org.openhab.binding.network.service.NetworkUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link NetworkDiscoveryService} is responsible for discovering devices on + * the current Network. It uses every Network Interface which is connected to a network. + * + * @author Marc Mettke - Initial contribution + */ +public class NetworkDiscoveryService extends AbstractDiscoveryService implements DiscoveryCallback { + private final Logger logger = LoggerFactory.getLogger(NetworkDiscoveryService.class); + private ExecutorService executorService = null; + final static int PING_TIMEOUT_IN_MS = 500; + private int scanningNetworkSize = 0; + + public NetworkDiscoveryService() { + super(SUPPORTED_THING_TYPES_UIDS, 900, false); + } + + /** + * Starts the DiscoveryThread for each IP on each interface on the network + * + */ + @Override + protected void startScan() { + if (executorService != null) { + stopScan(); + } + + logger.debug("Starting Discovery"); + LinkedHashSet networkIPs = NetworkUtils.getNetworkIPs(NetworkUtils.getInterfaceIPs()); + scanningNetworkSize = networkIPs.size(); + executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 10); + + for (Iterator it = networkIPs.iterator(); it.hasNext();) { + final String ip = it.next(); + executorService.execute(new PingRunnable(ip, this)); + } + stopScan(); + } + + @Override + protected synchronized void stopScan() { + super.stopScan(); + if (executorService == null) { + return; + } + + try { + executorService.awaitTermination(PING_TIMEOUT_IN_MS * scanningNetworkSize, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + } + executorService.shutdown(); + executorService = null; + + } + + /** + * Submit newly discovered devices. This method is called by the spawned threads in {@link startScan}. + * + * @param ip The device IP, received by the + */ + @Override + public void newDevice(String ip) { + logger.info("Found " + ip); + + // uid must not contains dots + ThingUID uid = new ThingUID(THING_TYPE_DEVICE, ip.replace('.', '_')); + + if (uid != null) { + Map properties = new HashMap<>(1); + properties.put(PARAMETER_HOSTNAME, ip); + DiscoveryResult result = DiscoveryResultBuilder.create(uid).withProperties(properties) + .withLabel("Network Device (" + ip + ")").build(); + thingDiscovered(result); + } + } +} diff --git a/addons/binding/org.openhab.binding.opensprinkler/.classpath b/addons/binding/org.openhab.binding.opensprinkler/.classpath index f4091170bca81..c383bda0dd310 100644 --- a/addons/binding/org.openhab.binding.opensprinkler/.classpath +++ b/addons/binding/org.openhab.binding.opensprinkler/.classpath @@ -1,8 +1,8 @@ - - - - - - - - + + + + + + + + diff --git a/addons/binding/org.openhab.binding.opensprinkler/.project b/addons/binding/org.openhab.binding.opensprinkler/.project index 7020a66fb3a26..359cb92cd22f8 100644 --- a/addons/binding/org.openhab.binding.opensprinkler/.project +++ b/addons/binding/org.openhab.binding.opensprinkler/.project @@ -1,33 +1,33 @@ - - - org.openhab.binding.opensprinkler - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - org.eclipse.pde.ds.core.builder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - + + + org.openhab.binding.opensprinkler + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.ds.core.builder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/addons/binding/org.openhab.binding.opensprinkler/ESH-INF/binding/binding.xml b/addons/binding/org.openhab.binding.opensprinkler/ESH-INF/binding/binding.xml index 66c6e5104477e..97ccb13a3797b 100644 --- a/addons/binding/org.openhab.binding.opensprinkler/ESH-INF/binding/binding.xml +++ b/addons/binding/org.openhab.binding.opensprinkler/ESH-INF/binding/binding.xml @@ -1,11 +1,11 @@ - - - - OpenSprinkler Binding - This is the binding for OpenSprinkler. - Chris Graham - - + + + + OpenSprinkler Binding + This is the binding for OpenSprinkler. + Chris Graham + + diff --git a/addons/binding/org.openhab.binding.opensprinkler/ESH-INF/thing/thing-types.xml b/addons/binding/org.openhab.binding.opensprinkler/ESH-INF/thing/thing-types.xml index bf9bcf67071b1..ef16600231d81 100644 --- a/addons/binding/org.openhab.binding.opensprinkler/ESH-INF/thing/thing-types.xml +++ b/addons/binding/org.openhab.binding.opensprinkler/ESH-INF/thing/thing-types.xml @@ -1,467 +1,467 @@ - - - - - - - This is the stand alone OpenSprinkler device that allows sprinkler control. - - - - - - Controls station 01 on the OpenSprinkler device. - - - - Controls station 02 on the OpenSprinkler device. - - - - Controls station 03 on the OpenSprinkler device. - - - - Controls station 04 on the OpenSprinkler device. - - - - Controls station 05 on the OpenSprinkler device. - - - - Controls station 06 on the OpenSprinkler device. - - - - Controls station 07 on the OpenSprinkler device. - - - - Controls station 08 on the OpenSprinkler device. - - - - Controls station 09 on the OpenSprinkler device. - - - - Controls station 10 on the OpenSprinkler device. - - - - Controls station 11 on the OpenSprinkler device. - - - - Controls station 12 on the OpenSprinkler device. - - - - Controls station 13 on the OpenSprinkler device. - - - - Controls station 14 on the OpenSprinkler device. - - - - Controls station 15 on the OpenSprinkler device. - - - - Controls station 16 on the OpenSprinkler device. - - - - Controls station 17 on the OpenSprinkler device. - - - - Controls station 18 on the OpenSprinkler device. - - - - Controls station 19 on the OpenSprinkler device. - - - - Controls station 20 on the OpenSprinkler device. - - - - Controls station 21 on the OpenSprinkler device. - - - - Controls station 22 on the OpenSprinkler device. - - - - Controls station 23 on the OpenSprinkler device. - - - - Controls station 24 on the OpenSprinkler device. - - - - Controls station 25 on the OpenSprinkler device. - - - - Controls station 26 on the OpenSprinkler device. - - - - Controls station 27 on the OpenSprinkler device. - - - - Controls station 28 on the OpenSprinkler device. - - - - Controls station 29 on the OpenSprinkler device. - - - - Controls station 30 on the OpenSprinkler device. - - - - Controls station 31 on the OpenSprinkler device. - - - - Controls station 32 on the OpenSprinkler device. - - - - Controls station 33 on the OpenSprinkler device. - - - - Controls station 34 on the OpenSprinkler device. - - - - Controls station 35 on the OpenSprinkler device. - - - - Controls station 36 on the OpenSprinkler device. - - - - Controls station 37 on the OpenSprinkler device. - - - - Controls station 38 on the OpenSprinkler device. - - - - Controls station 39 on the OpenSprinkler device. - - - - Controls station 40 on the OpenSprinkler device. - - - - Controls station 41 on the OpenSprinkler device. - - - - Controls station 42 on the OpenSprinkler device. - - - - Controls station 43 on the OpenSprinkler device. - - - - Controls station 44 on the OpenSprinkler device. - - - - Controls station 45 on the OpenSprinkler device. - - - - Controls station 46 on the OpenSprinkler device. - - - - Controls station 47 on the OpenSprinkler device. - - - - Controls station 48 on the OpenSprinkler device. - - - - - - - The host name or IP address of the OpenSprinkler Web API interface. - localhost - - - - Port of the OpenSprinkler Web API interface. - 80 - - - - The admin password used to access the Web API interface. - opendoor - - - - Specifies the refresh interval in seconds. - 60 - - - - - - - - This is the Raspberry Pi OpenSprinkler device that allows sprinkler control. - - - - - Controls station 01 on the OpenSprinkler device. - - - - Controls station 02 on the OpenSprinkler device. - - - - Controls station 03 on the OpenSprinkler device. - - - - Controls station 04 on the OpenSprinkler device. - - - - Controls station 05 on the OpenSprinkler device. - - - - Controls station 06 on the OpenSprinkler device. - - - - Controls station 07 on the OpenSprinkler device. - - - - Controls station 08 on the OpenSprinkler device. - - - - Controls station 09 on the OpenSprinkler device. - - - - Controls station 10 on the OpenSprinkler device. - - - - Controls station 11 on the OpenSprinkler device. - - - - Controls station 12 on the OpenSprinkler device. - - - - Controls station 13 on the OpenSprinkler device. - - - - Controls station 14 on the OpenSprinkler device. - - - - Controls station 15 on the OpenSprinkler device. - - - - Controls station 16 on the OpenSprinkler device. - - - - Controls station 17 on the OpenSprinkler device. - - - - Controls station 18 on the OpenSprinkler device. - - - - Controls station 19 on the OpenSprinkler device. - - - - Controls station 20 on the OpenSprinkler device. - - - - Controls station 21 on the OpenSprinkler device. - - - - Controls station 22 on the OpenSprinkler device. - - - - Controls station 23 on the OpenSprinkler device. - - - - Controls station 24 on the OpenSprinkler device. - - - - Controls station 25 on the OpenSprinkler device. - - - - Controls station 26 on the OpenSprinkler device. - - - - Controls station 27 on the OpenSprinkler device. - - - - Controls station 28 on the OpenSprinkler device. - - - - Controls station 29 on the OpenSprinkler device. - - - - Controls station 30 on the OpenSprinkler device. - - - - Controls station 31 on the OpenSprinkler device. - - - - Controls station 32 on the OpenSprinkler device. - - - - Controls station 33 on the OpenSprinkler device. - - - - Controls station 34 on the OpenSprinkler device. - - - - Controls station 35 on the OpenSprinkler device. - - - - Controls station 36 on the OpenSprinkler device. - - - - Controls station 37 on the OpenSprinkler device. - - - - Controls station 38 on the OpenSprinkler device. - - - - Controls station 39 on the OpenSprinkler device. - - - - Controls station 40 on the OpenSprinkler device. - - - - Controls station 41 on the OpenSprinkler device. - - - - Controls station 42 on the OpenSprinkler device. - - - - Controls station 43 on the OpenSprinkler device. - - - - Controls station 44 on the OpenSprinkler device. - - - - Controls station 45 on the OpenSprinkler device. - - - - Controls station 46 on the OpenSprinkler device. - - - - Controls station 47 on the OpenSprinkler device. - - - - Controls station 48 on the OpenSprinkler device. - - - - - - - The number of stations to control. - 8 - - - - Specifies the refresh interval in seconds. - 60 - - - - - - Switch - - Provides feedback on whether the OpenSprinkler device has detected rain or not. - Sensor - - - - - Switch - - Controls a station on the OpenSprinkler device. - Switch - - - - Switch - - Controls a station on the OpenSprinkler device. - Switch - - + + + + + + + This is the stand alone OpenSprinkler device that allows sprinkler control. + + + + + + Controls station 01 on the OpenSprinkler device. + + + + Controls station 02 on the OpenSprinkler device. + + + + Controls station 03 on the OpenSprinkler device. + + + + Controls station 04 on the OpenSprinkler device. + + + + Controls station 05 on the OpenSprinkler device. + + + + Controls station 06 on the OpenSprinkler device. + + + + Controls station 07 on the OpenSprinkler device. + + + + Controls station 08 on the OpenSprinkler device. + + + + Controls station 09 on the OpenSprinkler device. + + + + Controls station 10 on the OpenSprinkler device. + + + + Controls station 11 on the OpenSprinkler device. + + + + Controls station 12 on the OpenSprinkler device. + + + + Controls station 13 on the OpenSprinkler device. + + + + Controls station 14 on the OpenSprinkler device. + + + + Controls station 15 on the OpenSprinkler device. + + + + Controls station 16 on the OpenSprinkler device. + + + + Controls station 17 on the OpenSprinkler device. + + + + Controls station 18 on the OpenSprinkler device. + + + + Controls station 19 on the OpenSprinkler device. + + + + Controls station 20 on the OpenSprinkler device. + + + + Controls station 21 on the OpenSprinkler device. + + + + Controls station 22 on the OpenSprinkler device. + + + + Controls station 23 on the OpenSprinkler device. + + + + Controls station 24 on the OpenSprinkler device. + + + + Controls station 25 on the OpenSprinkler device. + + + + Controls station 26 on the OpenSprinkler device. + + + + Controls station 27 on the OpenSprinkler device. + + + + Controls station 28 on the OpenSprinkler device. + + + + Controls station 29 on the OpenSprinkler device. + + + + Controls station 30 on the OpenSprinkler device. + + + + Controls station 31 on the OpenSprinkler device. + + + + Controls station 32 on the OpenSprinkler device. + + + + Controls station 33 on the OpenSprinkler device. + + + + Controls station 34 on the OpenSprinkler device. + + + + Controls station 35 on the OpenSprinkler device. + + + + Controls station 36 on the OpenSprinkler device. + + + + Controls station 37 on the OpenSprinkler device. + + + + Controls station 38 on the OpenSprinkler device. + + + + Controls station 39 on the OpenSprinkler device. + + + + Controls station 40 on the OpenSprinkler device. + + + + Controls station 41 on the OpenSprinkler device. + + + + Controls station 42 on the OpenSprinkler device. + + + + Controls station 43 on the OpenSprinkler device. + + + + Controls station 44 on the OpenSprinkler device. + + + + Controls station 45 on the OpenSprinkler device. + + + + Controls station 46 on the OpenSprinkler device. + + + + Controls station 47 on the OpenSprinkler device. + + + + Controls station 48 on the OpenSprinkler device. + + + + + + + The host name or IP address of the OpenSprinkler Web API interface. + localhost + + + + Port of the OpenSprinkler Web API interface. + 80 + + + + The admin password used to access the Web API interface. + opendoor + + + + Specifies the refresh interval in seconds. + 60 + + + + + + + + This is the Raspberry Pi OpenSprinkler device that allows sprinkler control. + + + + + Controls station 01 on the OpenSprinkler device. + + + + Controls station 02 on the OpenSprinkler device. + + + + Controls station 03 on the OpenSprinkler device. + + + + Controls station 04 on the OpenSprinkler device. + + + + Controls station 05 on the OpenSprinkler device. + + + + Controls station 06 on the OpenSprinkler device. + + + + Controls station 07 on the OpenSprinkler device. + + + + Controls station 08 on the OpenSprinkler device. + + + + Controls station 09 on the OpenSprinkler device. + + + + Controls station 10 on the OpenSprinkler device. + + + + Controls station 11 on the OpenSprinkler device. + + + + Controls station 12 on the OpenSprinkler device. + + + + Controls station 13 on the OpenSprinkler device. + + + + Controls station 14 on the OpenSprinkler device. + + + + Controls station 15 on the OpenSprinkler device. + + + + Controls station 16 on the OpenSprinkler device. + + + + Controls station 17 on the OpenSprinkler device. + + + + Controls station 18 on the OpenSprinkler device. + + + + Controls station 19 on the OpenSprinkler device. + + + + Controls station 20 on the OpenSprinkler device. + + + + Controls station 21 on the OpenSprinkler device. + + + + Controls station 22 on the OpenSprinkler device. + + + + Controls station 23 on the OpenSprinkler device. + + + + Controls station 24 on the OpenSprinkler device. + + + + Controls station 25 on the OpenSprinkler device. + + + + Controls station 26 on the OpenSprinkler device. + + + + Controls station 27 on the OpenSprinkler device. + + + + Controls station 28 on the OpenSprinkler device. + + + + Controls station 29 on the OpenSprinkler device. + + + + Controls station 30 on the OpenSprinkler device. + + + + Controls station 31 on the OpenSprinkler device. + + + + Controls station 32 on the OpenSprinkler device. + + + + Controls station 33 on the OpenSprinkler device. + + + + Controls station 34 on the OpenSprinkler device. + + + + Controls station 35 on the OpenSprinkler device. + + + + Controls station 36 on the OpenSprinkler device. + + + + Controls station 37 on the OpenSprinkler device. + + + + Controls station 38 on the OpenSprinkler device. + + + + Controls station 39 on the OpenSprinkler device. + + + + Controls station 40 on the OpenSprinkler device. + + + + Controls station 41 on the OpenSprinkler device. + + + + Controls station 42 on the OpenSprinkler device. + + + + Controls station 43 on the OpenSprinkler device. + + + + Controls station 44 on the OpenSprinkler device. + + + + Controls station 45 on the OpenSprinkler device. + + + + Controls station 46 on the OpenSprinkler device. + + + + Controls station 47 on the OpenSprinkler device. + + + + Controls station 48 on the OpenSprinkler device. + + + + + + + The number of stations to control. + 8 + + + + Specifies the refresh interval in seconds. + 60 + + + + + + Switch + + Provides feedback on whether the OpenSprinkler device has detected rain or not. + Sensor + + + + + Switch + + Controls a station on the OpenSprinkler device. + Switch + + + + Switch + + Controls a station on the OpenSprinkler device. + Switch + + diff --git a/addons/binding/org.openhab.binding.opensprinkler/META-INF/MANIFEST.MF b/addons/binding/org.openhab.binding.opensprinkler/META-INF/MANIFEST.MF index 9ef66cb944018..4cb62cc7be49f 100644 --- a/addons/binding/org.openhab.binding.opensprinkler/META-INF/MANIFEST.MF +++ b/addons/binding/org.openhab.binding.opensprinkler/META-INF/MANIFEST.MF @@ -1,24 +1,24 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: OpenSprinkler Binding -Bundle-SymbolicName: org.openhab.binding.opensprinkler;singleton:=true -Bundle-Vendor: openHAB -Bundle-Version: 2.1.0.qualifier -Bundle-RequiredExecutionEnvironment: JavaSE-1.7 -Bundle-ClassPath: ., - lib/pi4j-core.jar -Import-Package: - com.google.gson, - org.apache.commons.net.util, - org.eclipse.smarthome.config.core, - org.eclipse.smarthome.config.discovery, - org.eclipse.smarthome.core.library.types, - org.eclipse.smarthome.core.thing, - org.eclipse.smarthome.core.thing.binding, - org.eclipse.smarthome.core.thing.binding.builder, - org.eclipse.smarthome.core.thing.type, - org.eclipse.smarthome.core.types, - org.slf4j -Service-Component: OSGI-INF/*.xml -Export-Package: org.openhab.binding.opensprinkler, - org.openhab.binding.opensprinkler.handler +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: OpenSprinkler Binding +Bundle-SymbolicName: org.openhab.binding.opensprinkler;singleton:=true +Bundle-Vendor: openHAB +Bundle-Version: 2.1.0.qualifier +Bundle-RequiredExecutionEnvironment: JavaSE-1.7 +Bundle-ClassPath: ., + lib/pi4j-core.jar +Import-Package: + com.google.gson, + org.apache.commons.net.util, + org.eclipse.smarthome.config.core, + org.eclipse.smarthome.config.discovery, + org.eclipse.smarthome.core.library.types, + org.eclipse.smarthome.core.thing, + org.eclipse.smarthome.core.thing.binding, + org.eclipse.smarthome.core.thing.binding.builder, + org.eclipse.smarthome.core.thing.type, + org.eclipse.smarthome.core.types, + org.slf4j +Service-Component: OSGI-INF/*.xml +Export-Package: org.openhab.binding.opensprinkler, + org.openhab.binding.opensprinkler.handler diff --git a/addons/binding/org.openhab.binding.opensprinkler/OSGI-INF/OpenSprinklerHandlerFactory.xml b/addons/binding/org.openhab.binding.opensprinkler/OSGI-INF/OpenSprinklerHandlerFactory.xml index 878ef8840705d..6b20a10eef75c 100644 --- a/addons/binding/org.openhab.binding.opensprinkler/OSGI-INF/OpenSprinklerHandlerFactory.xml +++ b/addons/binding/org.openhab.binding.opensprinkler/OSGI-INF/OpenSprinklerHandlerFactory.xml @@ -1,20 +1,20 @@ - - - - - - - - - - - + + + + + + + + + + + diff --git a/addons/binding/org.openhab.binding.opensprinkler/build.properties b/addons/binding/org.openhab.binding.opensprinkler/build.properties index 8c38637d80645..74698c0216904 100644 --- a/addons/binding/org.openhab.binding.opensprinkler/build.properties +++ b/addons/binding/org.openhab.binding.opensprinkler/build.properties @@ -1,7 +1,7 @@ -source.. = src/main/java/ -output.. = target/classes -bin.includes = META-INF/,\ - .,\ - OSGI-INF/,\ - ESH-INF/,\ - lib/pi4j-core.jar +source.. = src/main/java/ +output.. = target/classes +bin.includes = META-INF/,\ + .,\ + OSGI-INF/,\ + ESH-INF/,\ + lib/pi4j-core.jar diff --git a/addons/binding/org.openhab.binding.opensprinkler/pom.xml b/addons/binding/org.openhab.binding.opensprinkler/pom.xml index 769fa22baa6d1..5134021bf072d 100644 --- a/addons/binding/org.openhab.binding.opensprinkler/pom.xml +++ b/addons/binding/org.openhab.binding.opensprinkler/pom.xml @@ -1,19 +1,19 @@ - - - - 4.0.0 - - - org.openhab.binding - pom - 2.1.0-SNAPSHOT - - - org.openhab.binding - org.openhab.binding.opensprinkler - 2.1.0-SNAPSHOT - - OpenSprinkler Binding - eclipse-plugin - - + + + + 4.0.0 + + + org.openhab.binding + pom + 2.1.0-SNAPSHOT + + + org.openhab.binding + org.openhab.binding.opensprinkler + 2.1.0-SNAPSHOT + + OpenSprinkler Binding + eclipse-plugin + + diff --git a/addons/binding/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/OpenSprinklerBindingConstants.java b/addons/binding/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/OpenSprinklerBindingConstants.java index 62061fc8874d8..165b435918844 100644 --- a/addons/binding/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/OpenSprinklerBindingConstants.java +++ b/addons/binding/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/OpenSprinklerBindingConstants.java @@ -1,187 +1,187 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.opensprinkler; - -import org.eclipse.smarthome.core.thing.ThingTypeUID; - -/** - * The {@link OpenSprinklerBinding} class defines common constants, which are - * used across the whole binding. - * - * @author Chris Graham - Initial contribution - */ -public class OpenSprinklerBindingConstants { - public static final String BINDING_ID = "opensprinkler"; - - // List of all Thing ids - public final static String OPENSPRINKLER = "http"; - public final static String OPENSPRINKLERPI = "pi"; - - // List of all Thing Type UIDs - public final static ThingTypeUID OPENSPRINKLER_THING = new ThingTypeUID(BINDING_ID, OPENSPRINKLER); - public final static ThingTypeUID OPENSPRINKLERPI_THING = new ThingTypeUID(BINDING_ID, OPENSPRINKLERPI); - - public final static int DEFAULT_WAIT_BEFORE_INITIAL_REFRESH = 30; - public final static int DEFAULT_REFRESH_RATE = 60; - public final static short DISCOVERY_SUBNET_MASK = 24; - public final static int DISCOVERY_THREAD_POOL_SIZE = 15; - public final static int DISCOVERY_THREAD_POOL_SHUTDOWN_WAIT_TIME_SECONDS = 300; - public final static boolean DISCOVERY_DEFAULT_AUTO_DISCOVER = false; - public final static int DISCOVERY_DEFAULT_TIMEOUT_RATE = 500; - public final static int DISCOVERY_DEFAULT_IP_TIMEOUT_RATE = 750; - - // List of all Channel ids - public final static String SENSOR_RAIN = "rainsensor"; - - public final static String STATION_01 = "station01"; - public final static String STATION_02 = "station02"; - public final static String STATION_03 = "station03"; - public final static String STATION_04 = "station04"; - public final static String STATION_05 = "station05"; - public final static String STATION_06 = "station06"; - public final static String STATION_07 = "station07"; - public final static String STATION_08 = "station08"; - public final static String STATION_09 = "station09"; - public final static String STATION_10 = "station10"; - public final static String STATION_11 = "station11"; - public final static String STATION_12 = "station12"; - public final static String STATION_13 = "station13"; - public final static String STATION_14 = "station14"; - public final static String STATION_15 = "station15"; - public final static String STATION_16 = "station16"; - public final static String STATION_17 = "station17"; - public final static String STATION_18 = "station18"; - public final static String STATION_19 = "station19"; - public final static String STATION_20 = "station20"; - public final static String STATION_21 = "station21"; - public final static String STATION_22 = "station22"; - public final static String STATION_23 = "station23"; - public final static String STATION_24 = "station24"; - public final static String STATION_25 = "station25"; - public final static String STATION_26 = "station26"; - public final static String STATION_27 = "station27"; - public final static String STATION_28 = "station28"; - public final static String STATION_29 = "station29"; - public final static String STATION_30 = "station30"; - public final static String STATION_31 = "station31"; - public final static String STATION_32 = "station32"; - public final static String STATION_33 = "station33"; - public final static String STATION_34 = "station34"; - public final static String STATION_35 = "station35"; - public final static String STATION_36 = "station36"; - public final static String STATION_37 = "station37"; - public final static String STATION_38 = "station38"; - public final static String STATION_39 = "station39"; - public final static String STATION_40 = "station40"; - public final static String STATION_41 = "station41"; - public final static String STATION_42 = "station42"; - public final static String STATION_43 = "station43"; - public final static String STATION_44 = "station44"; - public final static String STATION_45 = "station45"; - public final static String STATION_46 = "station46"; - public final static String STATION_47 = "station47"; - public final static String STATION_48 = "station48"; - - /** - * Enumeration of station constants for mapping station channel names to ints and back. - * - * @author CrackerStealth - */ - public enum Station { - STATION01(0, STATION_01), - STATION02(1, STATION_02), - STATION03(2, STATION_03), - STATION04(3, STATION_04), - STATION05(4, STATION_05), - STATION06(5, STATION_06), - STATION07(6, STATION_07), - STATION08(7, STATION_08), - STATION09(8, STATION_09), - STATION10(9, STATION_10), - STATION11(10, STATION_11), - STATION12(11, STATION_12), - STATION13(12, STATION_13), - STATION14(13, STATION_14), - STATION15(14, STATION_15), - STATION16(15, STATION_16), - STATION17(16, STATION_17), - STATION18(17, STATION_18), - STATION19(18, STATION_19), - STATION20(19, STATION_20), - STATION21(20, STATION_21), - STATION22(21, STATION_22), - STATION23(22, STATION_23), - STATION24(23, STATION_24), - STATION25(24, STATION_25), - STATION26(25, STATION_26), - STATION27(26, STATION_27), - STATION28(27, STATION_28), - STATION29(28, STATION_29), - STATION30(29, STATION_30), - STATION31(30, STATION_31), - STATION32(31, STATION_32), - STATION33(32, STATION_33), - STATION34(33, STATION_34), - STATION35(34, STATION_35), - STATION36(35, STATION_36), - STATION37(36, STATION_37), - STATION38(37, STATION_38), - STATION39(38, STATION_39), - STATION40(39, STATION_40), - STATION41(40, STATION_41), - STATION42(41, STATION_42), - STATION43(42, STATION_43), - STATION44(43, STATION_44), - STATION45(44, STATION_45), - STATION46(45, STATION_46), - STATION47(46, STATION_47), - STATION48(47, STATION_48); - - private final int number; - private final String id; - - private Station(final int number, final String id) { - this.number = number; - this.id = id; - } - - @Override - public String toString() { - return String.valueOf(number); - } - - public int toNumber() { - return number; - } - - public static Station get(int valueSelectorNumber) throws IllegalArgumentException { - for (Station c : Station.values()) { - if (c.number == valueSelectorNumber) { - return c; - } - } - - throw new IllegalArgumentException("Not a valid value selector."); - } - - public static Station get(String valueSelectorText) throws IllegalArgumentException { - for (Station c : Station.values()) { - if (c.id.equals(valueSelectorText)) { - return c; - } - } - - throw new IllegalArgumentException("Not a valid value selector."); - } - - public String channelID() { - return this.id; - } - } -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.opensprinkler; + +import org.eclipse.smarthome.core.thing.ThingTypeUID; + +/** + * The {@link OpenSprinklerBinding} class defines common constants, which are + * used across the whole binding. + * + * @author Chris Graham - Initial contribution + */ +public class OpenSprinklerBindingConstants { + public static final String BINDING_ID = "opensprinkler"; + + // List of all Thing ids + public final static String OPENSPRINKLER = "http"; + public final static String OPENSPRINKLERPI = "pi"; + + // List of all Thing Type UIDs + public final static ThingTypeUID OPENSPRINKLER_THING = new ThingTypeUID(BINDING_ID, OPENSPRINKLER); + public final static ThingTypeUID OPENSPRINKLERPI_THING = new ThingTypeUID(BINDING_ID, OPENSPRINKLERPI); + + public final static int DEFAULT_WAIT_BEFORE_INITIAL_REFRESH = 30; + public final static int DEFAULT_REFRESH_RATE = 60; + public final static short DISCOVERY_SUBNET_MASK = 24; + public final static int DISCOVERY_THREAD_POOL_SIZE = 15; + public final static int DISCOVERY_THREAD_POOL_SHUTDOWN_WAIT_TIME_SECONDS = 300; + public final static boolean DISCOVERY_DEFAULT_AUTO_DISCOVER = false; + public final static int DISCOVERY_DEFAULT_TIMEOUT_RATE = 500; + public final static int DISCOVERY_DEFAULT_IP_TIMEOUT_RATE = 750; + + // List of all Channel ids + public final static String SENSOR_RAIN = "rainsensor"; + + public final static String STATION_01 = "station01"; + public final static String STATION_02 = "station02"; + public final static String STATION_03 = "station03"; + public final static String STATION_04 = "station04"; + public final static String STATION_05 = "station05"; + public final static String STATION_06 = "station06"; + public final static String STATION_07 = "station07"; + public final static String STATION_08 = "station08"; + public final static String STATION_09 = "station09"; + public final static String STATION_10 = "station10"; + public final static String STATION_11 = "station11"; + public final static String STATION_12 = "station12"; + public final static String STATION_13 = "station13"; + public final static String STATION_14 = "station14"; + public final static String STATION_15 = "station15"; + public final static String STATION_16 = "station16"; + public final static String STATION_17 = "station17"; + public final static String STATION_18 = "station18"; + public final static String STATION_19 = "station19"; + public final static String STATION_20 = "station20"; + public final static String STATION_21 = "station21"; + public final static String STATION_22 = "station22"; + public final static String STATION_23 = "station23"; + public final static String STATION_24 = "station24"; + public final static String STATION_25 = "station25"; + public final static String STATION_26 = "station26"; + public final static String STATION_27 = "station27"; + public final static String STATION_28 = "station28"; + public final static String STATION_29 = "station29"; + public final static String STATION_30 = "station30"; + public final static String STATION_31 = "station31"; + public final static String STATION_32 = "station32"; + public final static String STATION_33 = "station33"; + public final static String STATION_34 = "station34"; + public final static String STATION_35 = "station35"; + public final static String STATION_36 = "station36"; + public final static String STATION_37 = "station37"; + public final static String STATION_38 = "station38"; + public final static String STATION_39 = "station39"; + public final static String STATION_40 = "station40"; + public final static String STATION_41 = "station41"; + public final static String STATION_42 = "station42"; + public final static String STATION_43 = "station43"; + public final static String STATION_44 = "station44"; + public final static String STATION_45 = "station45"; + public final static String STATION_46 = "station46"; + public final static String STATION_47 = "station47"; + public final static String STATION_48 = "station48"; + + /** + * Enumeration of station constants for mapping station channel names to ints and back. + * + * @author CrackerStealth + */ + public enum Station { + STATION01(0, STATION_01), + STATION02(1, STATION_02), + STATION03(2, STATION_03), + STATION04(3, STATION_04), + STATION05(4, STATION_05), + STATION06(5, STATION_06), + STATION07(6, STATION_07), + STATION08(7, STATION_08), + STATION09(8, STATION_09), + STATION10(9, STATION_10), + STATION11(10, STATION_11), + STATION12(11, STATION_12), + STATION13(12, STATION_13), + STATION14(13, STATION_14), + STATION15(14, STATION_15), + STATION16(15, STATION_16), + STATION17(16, STATION_17), + STATION18(17, STATION_18), + STATION19(18, STATION_19), + STATION20(19, STATION_20), + STATION21(20, STATION_21), + STATION22(21, STATION_22), + STATION23(22, STATION_23), + STATION24(23, STATION_24), + STATION25(24, STATION_25), + STATION26(25, STATION_26), + STATION27(26, STATION_27), + STATION28(27, STATION_28), + STATION29(28, STATION_29), + STATION30(29, STATION_30), + STATION31(30, STATION_31), + STATION32(31, STATION_32), + STATION33(32, STATION_33), + STATION34(33, STATION_34), + STATION35(34, STATION_35), + STATION36(35, STATION_36), + STATION37(36, STATION_37), + STATION38(37, STATION_38), + STATION39(38, STATION_39), + STATION40(39, STATION_40), + STATION41(40, STATION_41), + STATION42(41, STATION_42), + STATION43(42, STATION_43), + STATION44(43, STATION_44), + STATION45(44, STATION_45), + STATION46(45, STATION_46), + STATION47(46, STATION_47), + STATION48(47, STATION_48); + + private final int number; + private final String id; + + private Station(final int number, final String id) { + this.number = number; + this.id = id; + } + + @Override + public String toString() { + return String.valueOf(number); + } + + public int toNumber() { + return number; + } + + public static Station get(int valueSelectorNumber) throws IllegalArgumentException { + for (Station c : Station.values()) { + if (c.number == valueSelectorNumber) { + return c; + } + } + + throw new IllegalArgumentException("Not a valid value selector."); + } + + public static Station get(String valueSelectorText) throws IllegalArgumentException { + for (Station c : Station.values()) { + if (c.id.equals(valueSelectorText)) { + return c; + } + } + + throw new IllegalArgumentException("Not a valid value selector."); + } + + public String channelID() { + return this.id; + } + } +} diff --git a/addons/binding/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/handler/OpenSprinklerHTTPHandler.java b/addons/binding/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/handler/OpenSprinklerHTTPHandler.java index fe282c73c5e3c..4d4cf498cb6b7 100644 --- a/addons/binding/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/handler/OpenSprinklerHTTPHandler.java +++ b/addons/binding/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/handler/OpenSprinklerHTTPHandler.java @@ -1,145 +1,145 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.opensprinkler.handler; - -import static org.openhab.binding.opensprinkler.OpenSprinklerBindingConstants.*; - -import java.util.concurrent.TimeUnit; - -import org.eclipse.smarthome.core.library.types.OnOffType; -import org.eclipse.smarthome.core.thing.ChannelUID; -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingStatus; -import org.eclipse.smarthome.core.thing.ThingStatusDetail; -import org.eclipse.smarthome.core.types.State; -import org.openhab.binding.opensprinkler.OpenSprinklerBindingConstants.Station; -import org.openhab.binding.opensprinkler.config.OpenSprinklerConfig; -import org.openhab.binding.opensprinkler.internal.api.OpenSprinklerApiFactory; - -/** - * The {@link OpenSprinklerHTTPHandler} is responsible for handling commands, which are - * sent to one of the channels. - * - * @author Chris Graham - Initial contribution - */ -public class OpenSprinklerHTTPHandler extends OpenSprinklerHandler { - private OpenSprinklerConfig openSprinklerConfig = null; - - public OpenSprinklerHTTPHandler(Thing thing) { - super(thing); - } - - @Override - public void initialize() { - openSprinklerConfig = getConfig().as(OpenSprinklerConfig.class); - - logger.debug("Initializing OpenSprinkler with config (Hostname: {}, Port: {}, Password: {}, Refresh: {}).", - openSprinklerConfig.hostname, openSprinklerConfig.port, openSprinklerConfig.password, - openSprinklerConfig.refresh); - - if (openSprinklerConfig == null) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, - "Could not parse the config for the OpenSprinkler."); - - return; - } - - try { - openSprinklerDevice = OpenSprinklerApiFactory.getHttpApi(openSprinklerConfig.hostname, - openSprinklerConfig.port, openSprinklerConfig.password); - } catch (Exception exp) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, - "Could not create a connection to the OpenSprinkler."); - logger.debug("Could not create API connection to the OpenSprinkler device. Exception received: {}", - exp.toString()); - - return; - } - - logger.debug("Successfully created API connection to the OpenSprinkler device."); - - try { - openSprinklerDevice.openConnection(); - } catch (Exception exp) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, - "Could not open the connection to the OpenSprinkler."); - logger.debug("Could not open API connection to the OpenSprinkler device. Exception received: {}", - exp.toString()); - } - - if (openSprinklerDevice.isConnected()) { - updateStatus(ThingStatus.ONLINE); - logger.debug("OpenSprinkler connected."); - } else { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, - "Could not initialize the connection to the OpenSprinkler."); - - return; - } - - onUpdate(); - } - - /** - * Creates a new polling job to sync state with the OpenSprinkler device. - */ - private synchronized void onUpdate() { - if (pollingJob == null || pollingJob.isCancelled()) { - int refresh; - - try { - refresh = getConfig().as(OpenSprinklerConfig.class).refresh; - } catch (Exception exp) { - refresh = this.refreshInterval; - } - - pollingJob = scheduler.scheduleWithFixedDelay(refreshService, DEFAULT_WAIT_BEFORE_INITIAL_REFRESH, refresh, - TimeUnit.SECONDS); - } - } - - /** - * Threaded scheduled job that periodically syncs the state of the OpenSprinkler device. - */ - private Runnable refreshService = new Runnable() { - @Override - public void run() { - if (openSprinklerDevice != null) { - if (openSprinklerDevice.isConnected()) { - logger.debug("Refreshing state with the OpenSprinkler device."); - - try { - if (openSprinklerDevice.isRainDetected()) { - updateState(new ChannelUID(getThing().getUID(), SENSOR_RAIN), OnOffType.ON); - } else { - updateState(new ChannelUID(getThing().getUID(), SENSOR_RAIN), OnOffType.OFF); - } - - for (int i = 0; i < openSprinklerDevice.getNumberOfStations(); i++) { - ChannelUID channel = new ChannelUID(getThing().getUID(), Station.get(i).channelID()); - State command = getStationState(i); - updateState(channel, command); - } - - updateStatus(ThingStatus.ONLINE); - } catch (Exception exp) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, - "Could not refresh current state from the OpenSprinkler."); - logger.debug( - "Could not refresh current state of the OpenSprinkler device. Exception received: {}", - exp.toString()); - } - } else { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, - "Could not sync status with the OpenSprinkler."); - } - } - } - }; -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.opensprinkler.handler; + +import static org.openhab.binding.opensprinkler.OpenSprinklerBindingConstants.*; + +import java.util.concurrent.TimeUnit; + +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.types.State; +import org.openhab.binding.opensprinkler.OpenSprinklerBindingConstants.Station; +import org.openhab.binding.opensprinkler.config.OpenSprinklerConfig; +import org.openhab.binding.opensprinkler.internal.api.OpenSprinklerApiFactory; + +/** + * The {@link OpenSprinklerHTTPHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Chris Graham - Initial contribution + */ +public class OpenSprinklerHTTPHandler extends OpenSprinklerHandler { + private OpenSprinklerConfig openSprinklerConfig = null; + + public OpenSprinklerHTTPHandler(Thing thing) { + super(thing); + } + + @Override + public void initialize() { + openSprinklerConfig = getConfig().as(OpenSprinklerConfig.class); + + logger.debug("Initializing OpenSprinkler with config (Hostname: {}, Port: {}, Password: {}, Refresh: {}).", + openSprinklerConfig.hostname, openSprinklerConfig.port, openSprinklerConfig.password, + openSprinklerConfig.refresh); + + if (openSprinklerConfig == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, + "Could not parse the config for the OpenSprinkler."); + + return; + } + + try { + openSprinklerDevice = OpenSprinklerApiFactory.getHttpApi(openSprinklerConfig.hostname, + openSprinklerConfig.port, openSprinklerConfig.password); + } catch (Exception exp) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, + "Could not create a connection to the OpenSprinkler."); + logger.debug("Could not create API connection to the OpenSprinkler device. Exception received: {}", + exp.toString()); + + return; + } + + logger.debug("Successfully created API connection to the OpenSprinkler device."); + + try { + openSprinklerDevice.openConnection(); + } catch (Exception exp) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, + "Could not open the connection to the OpenSprinkler."); + logger.debug("Could not open API connection to the OpenSprinkler device. Exception received: {}", + exp.toString()); + } + + if (openSprinklerDevice.isConnected()) { + updateStatus(ThingStatus.ONLINE); + logger.debug("OpenSprinkler connected."); + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, + "Could not initialize the connection to the OpenSprinkler."); + + return; + } + + onUpdate(); + } + + /** + * Creates a new polling job to sync state with the OpenSprinkler device. + */ + private synchronized void onUpdate() { + if (pollingJob == null || pollingJob.isCancelled()) { + int refresh; + + try { + refresh = getConfig().as(OpenSprinklerConfig.class).refresh; + } catch (Exception exp) { + refresh = this.refreshInterval; + } + + pollingJob = scheduler.scheduleWithFixedDelay(refreshService, DEFAULT_WAIT_BEFORE_INITIAL_REFRESH, refresh, + TimeUnit.SECONDS); + } + } + + /** + * Threaded scheduled job that periodically syncs the state of the OpenSprinkler device. + */ + private Runnable refreshService = new Runnable() { + @Override + public void run() { + if (openSprinklerDevice != null) { + if (openSprinklerDevice.isConnected()) { + logger.debug("Refreshing state with the OpenSprinkler device."); + + try { + if (openSprinklerDevice.isRainDetected()) { + updateState(new ChannelUID(getThing().getUID(), SENSOR_RAIN), OnOffType.ON); + } else { + updateState(new ChannelUID(getThing().getUID(), SENSOR_RAIN), OnOffType.OFF); + } + + for (int i = 0; i < openSprinklerDevice.getNumberOfStations(); i++) { + ChannelUID channel = new ChannelUID(getThing().getUID(), Station.get(i).channelID()); + State command = getStationState(i); + updateState(channel, command); + } + + updateStatus(ThingStatus.ONLINE); + } catch (Exception exp) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, + "Could not refresh current state from the OpenSprinkler."); + logger.debug( + "Could not refresh current state of the OpenSprinkler device. Exception received: {}", + exp.toString()); + } + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, + "Could not sync status with the OpenSprinkler."); + } + } + } + }; +} diff --git a/addons/binding/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/OpenSprinklerHandlerFactory.java b/addons/binding/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/OpenSprinklerHandlerFactory.java index a694d788b111f..e88b722d53e03 100644 --- a/addons/binding/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/OpenSprinklerHandlerFactory.java +++ b/addons/binding/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/OpenSprinklerHandlerFactory.java @@ -1,51 +1,51 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.opensprinkler.internal; - -import static org.openhab.binding.opensprinkler.OpenSprinklerBindingConstants.*; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingTypeUID; -import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; -import org.eclipse.smarthome.core.thing.binding.ThingHandler; -import org.openhab.binding.opensprinkler.handler.OpenSprinklerHTTPHandler; -import org.openhab.binding.opensprinkler.handler.OpenSprinklerPiHandler; - -/** - * The {@link OpenSprinklerHandlerFactory} is responsible for creating things and thing - * handlers. - * - * @author Chris Graham - Initial contribution - */ -public class OpenSprinklerHandlerFactory extends BaseThingHandlerFactory { - private final static Set SUPPORTED_THING_TYPES_UIDS = new HashSet( - Arrays.asList(OPENSPRINKLER_THING, OPENSPRINKLERPI_THING)); - - @Override - public boolean supportsThingType(ThingTypeUID thingTypeUID) { - return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); - } - - @Override - protected ThingHandler createHandler(Thing thing) { - ThingTypeUID thingTypeUID = thing.getThingTypeUID(); - - if (thingTypeUID.equals(OPENSPRINKLER_THING)) { - return new OpenSprinklerHTTPHandler(thing); - } else if (thingTypeUID.equals(OPENSPRINKLERPI_THING)) { - return new OpenSprinklerPiHandler(thing); - } - - return null; - } -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.opensprinkler.internal; + +import static org.openhab.binding.opensprinkler.OpenSprinklerBindingConstants.*; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.openhab.binding.opensprinkler.handler.OpenSprinklerHTTPHandler; +import org.openhab.binding.opensprinkler.handler.OpenSprinklerPiHandler; + +/** + * The {@link OpenSprinklerHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Chris Graham - Initial contribution + */ +public class OpenSprinklerHandlerFactory extends BaseThingHandlerFactory { + private final static Set SUPPORTED_THING_TYPES_UIDS = new HashSet( + Arrays.asList(OPENSPRINKLER_THING, OPENSPRINKLERPI_THING)); + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Override + protected ThingHandler createHandler(Thing thing) { + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (thingTypeUID.equals(OPENSPRINKLER_THING)) { + return new OpenSprinklerHTTPHandler(thing); + } else if (thingTypeUID.equals(OPENSPRINKLERPI_THING)) { + return new OpenSprinklerPiHandler(thing); + } + + return null; + } +} diff --git a/addons/binding/org.openhab.binding.pioneeravr/.classpath b/addons/binding/org.openhab.binding.pioneeravr/.classpath index 642bfb34f723f..a95e0906ca013 100644 --- a/addons/binding/org.openhab.binding.pioneeravr/.classpath +++ b/addons/binding/org.openhab.binding.pioneeravr/.classpath @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/addons/binding/org.openhab.binding.pioneeravr/.project b/addons/binding/org.openhab.binding.pioneeravr/.project index 3664a60fe003b..039829a40e6d9 100644 --- a/addons/binding/org.openhab.binding.pioneeravr/.project +++ b/addons/binding/org.openhab.binding.pioneeravr/.project @@ -1,33 +1,33 @@ - - - org.openhab.binding.pioneeravr - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - org.eclipse.pde.ds.core.builder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - + + + org.openhab.binding.pioneeravr + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.ds.core.builder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/addons/binding/org.openhab.binding.rfxcom/src/main/java/org/openhab/binding/rfxcom/internal/discovery/RFXComDeviceDiscoveryService.java b/addons/binding/org.openhab.binding.rfxcom/src/main/java/org/openhab/binding/rfxcom/internal/discovery/RFXComDeviceDiscoveryService.java index cdb2e4e24253e..0142b06b24995 100644 --- a/addons/binding/org.openhab.binding.rfxcom/src/main/java/org/openhab/binding/rfxcom/internal/discovery/RFXComDeviceDiscoveryService.java +++ b/addons/binding/org.openhab.binding.rfxcom/src/main/java/org/openhab/binding/rfxcom/internal/discovery/RFXComDeviceDiscoveryService.java @@ -1,84 +1,84 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.rfxcom.internal.discovery; - -import java.util.Set; - -import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService; -import org.eclipse.smarthome.config.discovery.DiscoveryResult; -import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; -import org.eclipse.smarthome.core.thing.ThingTypeUID; -import org.eclipse.smarthome.core.thing.ThingUID; -import org.openhab.binding.rfxcom.RFXComBindingConstants; -import org.openhab.binding.rfxcom.handler.RFXComBridgeHandler; -import org.openhab.binding.rfxcom.internal.DeviceMessageListener; -import org.openhab.binding.rfxcom.internal.messages.RFXComBaseMessage; -import org.openhab.binding.rfxcom.internal.messages.RFXComMessage; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link RFXComDeviceDiscoveryService} class is used to discover RFXCOM - * devices that send messages to RFXCOM bridge. - * - * @author Pauli Anttila - Initial contribution - */ -public class RFXComDeviceDiscoveryService extends AbstractDiscoveryService implements DeviceMessageListener { - - private final static Logger logger = LoggerFactory.getLogger(RFXComDeviceDiscoveryService.class); - - private RFXComBridgeHandler bridgeHandler; - - public RFXComDeviceDiscoveryService(RFXComBridgeHandler rfxcomBridgeHandler) { - super(null, 1, false); - this.bridgeHandler = rfxcomBridgeHandler; - } - - public void activate() { - bridgeHandler.registerDeviceStatusListener(this); - } - - @Override - public void deactivate() { - bridgeHandler.unregisterDeviceStatusListener(this); - } - - @Override - public Set getSupportedThingTypes() { - return RFXComBindingConstants.SUPPORTED_DEVICE_THING_TYPES_UIDS; - } - - @Override - protected void startScan() { - // this can be ignored here as we discover devices from received messages - } - - @Override - public void onDeviceMessageReceived(ThingUID bridge, RFXComMessage message) { - logger.trace("Received: bridge: {} message: {}", bridge, message); - - try { - RFXComBaseMessage msg = (RFXComBaseMessage) message; - String id = message.getDeviceId(); - ThingTypeUID uid = RFXComBindingConstants.packetTypeThingMap.get(msg.packetType); - ThingUID thingUID = new ThingUID(uid, bridge, id.replace(RFXComBaseMessage.ID_DELIMITER, "_")); - if (thingUID != null) { - logger.trace("Adding new RFXCOM {} with id '{}' to smarthome inbox", thingUID, id); - String subType = msg.convertSubType(String.valueOf(msg.subType)).toString(); - String label = msg.packetType + "-" + id; - DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withLabel(label) - .withProperty(RFXComBindingConstants.DEVICE_ID, id) - .withProperty(RFXComBindingConstants.SUB_TYPE, subType).withBridge(bridge).build(); - thingDiscovered(discoveryResult); - } - } catch (Exception e) { - logger.debug("Error occurred during device discovery", e); - } - } -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.rfxcom.internal.discovery; + +import java.util.Set; + +import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService; +import org.eclipse.smarthome.config.discovery.DiscoveryResult; +import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.openhab.binding.rfxcom.RFXComBindingConstants; +import org.openhab.binding.rfxcom.handler.RFXComBridgeHandler; +import org.openhab.binding.rfxcom.internal.DeviceMessageListener; +import org.openhab.binding.rfxcom.internal.messages.RFXComBaseMessage; +import org.openhab.binding.rfxcom.internal.messages.RFXComMessage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link RFXComDeviceDiscoveryService} class is used to discover RFXCOM + * devices that send messages to RFXCOM bridge. + * + * @author Pauli Anttila - Initial contribution + */ +public class RFXComDeviceDiscoveryService extends AbstractDiscoveryService implements DeviceMessageListener { + + private final static Logger logger = LoggerFactory.getLogger(RFXComDeviceDiscoveryService.class); + + private RFXComBridgeHandler bridgeHandler; + + public RFXComDeviceDiscoveryService(RFXComBridgeHandler rfxcomBridgeHandler) { + super(null, 1, false); + this.bridgeHandler = rfxcomBridgeHandler; + } + + public void activate() { + bridgeHandler.registerDeviceStatusListener(this); + } + + @Override + public void deactivate() { + bridgeHandler.unregisterDeviceStatusListener(this); + } + + @Override + public Set getSupportedThingTypes() { + return RFXComBindingConstants.SUPPORTED_DEVICE_THING_TYPES_UIDS; + } + + @Override + protected void startScan() { + // this can be ignored here as we discover devices from received messages + } + + @Override + public void onDeviceMessageReceived(ThingUID bridge, RFXComMessage message) { + logger.trace("Received: bridge: {} message: {}", bridge, message); + + try { + RFXComBaseMessage msg = (RFXComBaseMessage) message; + String id = message.getDeviceId(); + ThingTypeUID uid = RFXComBindingConstants.packetTypeThingMap.get(msg.packetType); + ThingUID thingUID = new ThingUID(uid, bridge, id.replace(RFXComBaseMessage.ID_DELIMITER, "_")); + if (thingUID != null) { + logger.trace("Adding new RFXCOM {} with id '{}' to smarthome inbox", thingUID, id); + String subType = msg.convertSubType(String.valueOf(msg.subType)).toString(); + String label = msg.packetType + "-" + id; + DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withLabel(label) + .withProperty(RFXComBindingConstants.DEVICE_ID, id) + .withProperty(RFXComBindingConstants.SUB_TYPE, subType).withBridge(bridge).build(); + thingDiscovered(discoveryResult); + } + } catch (Exception e) { + logger.debug("Error occurred during device discovery", e); + } + } +} diff --git a/addons/binding/org.openhab.binding.rfxcom/src/main/java/org/openhab/binding/rfxcom/internal/messages/RFXComRainMessage.java b/addons/binding/org.openhab.binding.rfxcom/src/main/java/org/openhab/binding/rfxcom/internal/messages/RFXComRainMessage.java index a581676aa94ec..bf5d89dc3dffb 100644 --- a/addons/binding/org.openhab.binding.rfxcom/src/main/java/org/openhab/binding/rfxcom/internal/messages/RFXComRainMessage.java +++ b/addons/binding/org.openhab.binding.rfxcom/src/main/java/org/openhab/binding/rfxcom/internal/messages/RFXComRainMessage.java @@ -1,231 +1,231 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.rfxcom.internal.messages; - -import org.eclipse.smarthome.core.library.items.NumberItem; -import org.eclipse.smarthome.core.library.types.DecimalType; -import org.eclipse.smarthome.core.types.State; -import org.eclipse.smarthome.core.types.Type; -import org.eclipse.smarthome.core.types.UnDefType; -import org.openhab.binding.rfxcom.RFXComValueSelector; -import org.openhab.binding.rfxcom.internal.exceptions.RFXComException; - -import java.util.Arrays; -import java.util.List; - -/** - * RFXCOM data class for temperature and humidity message. - * - * @author Marc SAUVEUR - Initial contribution - * @author Pauli Anttila - */ -public class RFXComRainMessage extends RFXComBaseMessage { - - public enum SubType { - RAIN1(1), - RAIN2(2), - RAIN3(3), - RAIN4(4), - RAIN5(5), - RAIN6(6), - - UNKNOWN(255); - - private final int subType; - - SubType(int subType) { - this.subType = subType; - } - - SubType(byte subType) { - this.subType = subType; - } - - public byte toByte() { - return (byte) subType; - } - - public static SubType fromByte(int input) { - for (SubType c : SubType.values()) { - if (c.subType == input) { - return c; - } - } - - return SubType.UNKNOWN; - } - } - - private final static List supportedInputValueSelectors = Arrays.asList( - RFXComValueSelector.SIGNAL_LEVEL, RFXComValueSelector.BATTERY_LEVEL, RFXComValueSelector.RAIN_RATE, - RFXComValueSelector.RAIN_TOTAL); - - private final static List supportedOutputValueSelectors = Arrays.asList(); - - public SubType subType = SubType.UNKNOWN; - public int sensorId = 0; - public double rainRate = 0; - public double rainTotal = 0; - public byte signalLevel = 0; - public byte batteryLevel = 0; - - public RFXComRainMessage() { - packetType = PacketType.RAIN; - } - - public RFXComRainMessage(byte[] data) { - encodeMessage(data); - } - - @Override - public String toString() { - String str = ""; - - str += super.toString(); - str += ", Sub type = " + subType; - str += ", Device Id = " + getDeviceId(); - str += ", Rain rate = " + rainRate; - str += ", Rain total = " + rainTotal; - str += ", Signal level = " + signalLevel; - str += ", Battery level = " + batteryLevel; - - return str; - } - - @Override - public void encodeMessage(byte[] data) { - super.encodeMessage(data); - - subType = SubType.fromByte(super.subType); - sensorId = (data[4] & 0xFF) << 8 | (data[5] & 0xFF); - - rainRate = (short) ((data[6] & 0xFF) << 8 | (data[7] & 0xFF)); - if (subType == SubType.RAIN2) { - rainRate *= 0.01; - } - - if (subType == SubType.RAIN6) { - rainTotal = (short) ((data[10] & 0xFF)) * 0.266; - } else { - rainTotal = (short) ((data[8] & 0xFF) << 8 | (data[9] & 0xFF) << 8 | (data[10] & 0xFF)) * 0.1; - } - - signalLevel = (byte) ((data[11] & 0xF0) >> 4); - batteryLevel = (byte) (data[11] & 0x0F); - } - - @Override - public byte[] decodeMessage() { - byte[] data = new byte[12]; - - data[0] = 0x0B; - data[1] = RFXComBaseMessage.PacketType.RAIN.toByte(); - data[2] = subType.toByte(); - data[3] = seqNbr; - data[4] = (byte) ((sensorId & 0xFF00) >> 8); - data[5] = (byte) (sensorId & 0x00FF); - - short rainR = (short) Math.abs(rainRate * 100); - data[6] = (byte) ((rainR >> 8) & 0xFF); - data[7] = (byte) (rainR & 0xFF); - - short rainT = (short) Math.abs(rainTotal * 10); - data[8] = (byte) ((rainT >> 16) & 0xFF); - data[9] = (byte) ((rainT >> 8) & 0xFF); - data[10] = (byte) (rainT & 0xFF); - - data[11] = (byte) (((signalLevel & 0x0F) << 4) | (batteryLevel & 0x0F)); - - return data; - } - - @Override - public String getDeviceId() { - return String.valueOf(sensorId); - } - - @Override - public State convertToState(RFXComValueSelector valueSelector) throws RFXComException { - - State state = UnDefType.UNDEF; - - if (valueSelector.getItemClass() == NumberItem.class) { - - if (valueSelector == RFXComValueSelector.SIGNAL_LEVEL) { - - state = new DecimalType(signalLevel); - - } else if (valueSelector == RFXComValueSelector.BATTERY_LEVEL) { - - state = new DecimalType(batteryLevel); - - } else if (valueSelector == RFXComValueSelector.RAIN_RATE) { - - state = new DecimalType(rainRate); - } else if (valueSelector == RFXComValueSelector.RAIN_TOTAL) { - - state = new DecimalType(rainTotal); - - } else { - throw new RFXComException("Can't convert " + valueSelector + " to NumberItem"); - } - - } else { - - throw new RFXComException("Can't convert " + valueSelector + " to " + valueSelector.getItemClass()); - - } - - return state; - } - - @Override - public void setSubType(Object subType) throws RFXComException { - throw new RFXComException("Not supported"); - } - - @Override - public void setDeviceId(String deviceId) throws RFXComException { - throw new RFXComException("Not supported"); - } - - @Override - public void convertFromState(RFXComValueSelector valueSelector, Type type) throws RFXComException { - - throw new RFXComException("Not supported"); - } - - @Override - public Object convertSubType(String subType) throws RFXComException { - - for (SubType s : SubType.values()) { - if (s.toString().equals(subType)) { - return s; - } - } - - // try to find sub type by number - try { - return SubType.values()[Integer.parseInt(subType)]; - } catch (Exception e) { - throw new RFXComException("Unknown sub type " + subType); - } - } - - @Override - public List getSupportedInputValueSelectors() throws RFXComException { - return supportedInputValueSelectors; - } - - @Override - public List getSupportedOutputValueSelectors() throws RFXComException { - return supportedOutputValueSelectors; - } - -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.rfxcom.internal.messages; + +import org.eclipse.smarthome.core.library.items.NumberItem; +import org.eclipse.smarthome.core.library.types.DecimalType; +import org.eclipse.smarthome.core.types.State; +import org.eclipse.smarthome.core.types.Type; +import org.eclipse.smarthome.core.types.UnDefType; +import org.openhab.binding.rfxcom.RFXComValueSelector; +import org.openhab.binding.rfxcom.internal.exceptions.RFXComException; + +import java.util.Arrays; +import java.util.List; + +/** + * RFXCOM data class for temperature and humidity message. + * + * @author Marc SAUVEUR - Initial contribution + * @author Pauli Anttila + */ +public class RFXComRainMessage extends RFXComBaseMessage { + + public enum SubType { + RAIN1(1), + RAIN2(2), + RAIN3(3), + RAIN4(4), + RAIN5(5), + RAIN6(6), + + UNKNOWN(255); + + private final int subType; + + SubType(int subType) { + this.subType = subType; + } + + SubType(byte subType) { + this.subType = subType; + } + + public byte toByte() { + return (byte) subType; + } + + public static SubType fromByte(int input) { + for (SubType c : SubType.values()) { + if (c.subType == input) { + return c; + } + } + + return SubType.UNKNOWN; + } + } + + private final static List supportedInputValueSelectors = Arrays.asList( + RFXComValueSelector.SIGNAL_LEVEL, RFXComValueSelector.BATTERY_LEVEL, RFXComValueSelector.RAIN_RATE, + RFXComValueSelector.RAIN_TOTAL); + + private final static List supportedOutputValueSelectors = Arrays.asList(); + + public SubType subType = SubType.UNKNOWN; + public int sensorId = 0; + public double rainRate = 0; + public double rainTotal = 0; + public byte signalLevel = 0; + public byte batteryLevel = 0; + + public RFXComRainMessage() { + packetType = PacketType.RAIN; + } + + public RFXComRainMessage(byte[] data) { + encodeMessage(data); + } + + @Override + public String toString() { + String str = ""; + + str += super.toString(); + str += ", Sub type = " + subType; + str += ", Device Id = " + getDeviceId(); + str += ", Rain rate = " + rainRate; + str += ", Rain total = " + rainTotal; + str += ", Signal level = " + signalLevel; + str += ", Battery level = " + batteryLevel; + + return str; + } + + @Override + public void encodeMessage(byte[] data) { + super.encodeMessage(data); + + subType = SubType.fromByte(super.subType); + sensorId = (data[4] & 0xFF) << 8 | (data[5] & 0xFF); + + rainRate = (short) ((data[6] & 0xFF) << 8 | (data[7] & 0xFF)); + if (subType == SubType.RAIN2) { + rainRate *= 0.01; + } + + if (subType == SubType.RAIN6) { + rainTotal = (short) ((data[10] & 0xFF)) * 0.266; + } else { + rainTotal = (short) ((data[8] & 0xFF) << 8 | (data[9] & 0xFF) << 8 | (data[10] & 0xFF)) * 0.1; + } + + signalLevel = (byte) ((data[11] & 0xF0) >> 4); + batteryLevel = (byte) (data[11] & 0x0F); + } + + @Override + public byte[] decodeMessage() { + byte[] data = new byte[12]; + + data[0] = 0x0B; + data[1] = RFXComBaseMessage.PacketType.RAIN.toByte(); + data[2] = subType.toByte(); + data[3] = seqNbr; + data[4] = (byte) ((sensorId & 0xFF00) >> 8); + data[5] = (byte) (sensorId & 0x00FF); + + short rainR = (short) Math.abs(rainRate * 100); + data[6] = (byte) ((rainR >> 8) & 0xFF); + data[7] = (byte) (rainR & 0xFF); + + short rainT = (short) Math.abs(rainTotal * 10); + data[8] = (byte) ((rainT >> 16) & 0xFF); + data[9] = (byte) ((rainT >> 8) & 0xFF); + data[10] = (byte) (rainT & 0xFF); + + data[11] = (byte) (((signalLevel & 0x0F) << 4) | (batteryLevel & 0x0F)); + + return data; + } + + @Override + public String getDeviceId() { + return String.valueOf(sensorId); + } + + @Override + public State convertToState(RFXComValueSelector valueSelector) throws RFXComException { + + State state = UnDefType.UNDEF; + + if (valueSelector.getItemClass() == NumberItem.class) { + + if (valueSelector == RFXComValueSelector.SIGNAL_LEVEL) { + + state = new DecimalType(signalLevel); + + } else if (valueSelector == RFXComValueSelector.BATTERY_LEVEL) { + + state = new DecimalType(batteryLevel); + + } else if (valueSelector == RFXComValueSelector.RAIN_RATE) { + + state = new DecimalType(rainRate); + } else if (valueSelector == RFXComValueSelector.RAIN_TOTAL) { + + state = new DecimalType(rainTotal); + + } else { + throw new RFXComException("Can't convert " + valueSelector + " to NumberItem"); + } + + } else { + + throw new RFXComException("Can't convert " + valueSelector + " to " + valueSelector.getItemClass()); + + } + + return state; + } + + @Override + public void setSubType(Object subType) throws RFXComException { + throw new RFXComException("Not supported"); + } + + @Override + public void setDeviceId(String deviceId) throws RFXComException { + throw new RFXComException("Not supported"); + } + + @Override + public void convertFromState(RFXComValueSelector valueSelector, Type type) throws RFXComException { + + throw new RFXComException("Not supported"); + } + + @Override + public Object convertSubType(String subType) throws RFXComException { + + for (SubType s : SubType.values()) { + if (s.toString().equals(subType)) { + return s; + } + } + + // try to find sub type by number + try { + return SubType.values()[Integer.parseInt(subType)]; + } catch (Exception e) { + throw new RFXComException("Unknown sub type " + subType); + } + } + + @Override + public List getSupportedInputValueSelectors() throws RFXComException { + return supportedInputValueSelectors; + } + + @Override + public List getSupportedOutputValueSelectors() throws RFXComException { + return supportedOutputValueSelectors; + } + +} diff --git a/addons/binding/org.openhab.binding.rfxcom/src/main/java/org/openhab/binding/rfxcom/internal/messages/RFXComSecurity1Message.java b/addons/binding/org.openhab.binding.rfxcom/src/main/java/org/openhab/binding/rfxcom/internal/messages/RFXComSecurity1Message.java index 80bf0964076dc..58f180f1dc0ad 100644 --- a/addons/binding/org.openhab.binding.rfxcom/src/main/java/org/openhab/binding/rfxcom/internal/messages/RFXComSecurity1Message.java +++ b/addons/binding/org.openhab.binding.rfxcom/src/main/java/org/openhab/binding/rfxcom/internal/messages/RFXComSecurity1Message.java @@ -1,424 +1,424 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.rfxcom.internal.messages; - -import org.eclipse.smarthome.core.library.items.*; -import org.eclipse.smarthome.core.library.types.*; -import org.eclipse.smarthome.core.types.State; -import org.eclipse.smarthome.core.types.Type; -import org.eclipse.smarthome.core.types.UnDefType; -import org.openhab.binding.rfxcom.RFXComValueSelector; -import org.openhab.binding.rfxcom.internal.exceptions.RFXComException; - -import java.util.Arrays; -import java.util.List; - -/** - * RFXCOM data class for Security1 message. - * (i.e. X10 Security, Visonic PowerCode, Meiantech, etc.) - * - * @author David Kalff - Initial contribution - * @author Pauli Anttila - */ -public class RFXComSecurity1Message extends RFXComBaseMessage { - - public enum SubType { - X10_SECURITY(0), - X10_SECURITY_MOTION(1), - X10_SECURITY_REMOTE(2), - KD101(3), - VISONIC_POWERCODE_SENSOR_PRIMARY_CONTACT(4), - VISONIC_POWERCODE_MOTION(5), - VISONIC_CODESECURE(6), - VISONIC_POWERCODE_SENSOR_AUX_CONTACT(7), - MEIANTECH(8), - SA30(9), - - UNKNOWN(255); - - private final int subType; - - SubType(int subType) { - this.subType = subType; - } - - SubType(byte subType) { - this.subType = subType; - } - - public byte toByte() { - return (byte) subType; - } - - public static SubType fromByte(int input) { - for (SubType c : SubType.values()) { - if (c.subType == input) { - return c; - } - } - - return SubType.UNKNOWN; - } - } - - public enum Status { - NORMAL(0), - NORMAL_DELAYED(1), - ALARM(2), - ALARM_DELAYED(3), - MOTION(4), - NO_MOTION(5), - PANIC(6), - END_PANIC(7), - IR(8), - ARM_AWAY(9), - ARM_AWAY_DELAYED(10), - ARM_HOME(11), - ARM_HOME_DELAYED(12), - DISARM(13), - LIGHT_1_OFF(16), - LIGHT_1_ON(17), - LIGHT_2_OFF(18), - LIGHT_2_ON(19), - DARK_DETECTED(20), - LIGHT_DETECTED(21), - BATLOW(22), - PAIR_KD101(23), - NORMAL_TAMPER(128), - NORMAL_DELAYED_TAMPER(129), - ALARM_TAMPER(130), - ALARM_DELAYED_TAMPER(131), - MOTION_TAMPER(132), - NO_MOTION_TAMPER(133), - - UNKNOWN(255); - - private final int status; - - Status(int status) { - this.status = status; - } - - Status(byte status) { - this.status = status; - } - - public byte toByte() { - return (byte) status; - } - - public static Status fromByte(int input) { - for (Status status : Status.values()) { - if (status.status == input) { - return status; - } - } - - return Status.UNKNOWN; - } - } - - /* Added item for ContactTypes */ - public enum Contact { - NORMAL(0), - NORMAL_DELAYED(1), - ALARM(2), - ALARM_DELAYED(3), - NORMAL_TAMPER(128), - NORMAL_DELAYED_TAMPER(129), - ALARM_TAMPER(130), - ALARM_DELAYED_TAMPER(131), - - UNKNOWN(255); - - private final int contact; - - Contact(int contact) { - this.contact = contact; - } - - Contact(byte contact) { - this.contact = contact; - } - - public byte toByte() { - return (byte) contact; - } - - public static Contact fromByte(int input) { - for (Contact status : Contact.values()) { - if (status.contact == input) { - return status; - } - } - - return Contact.UNKNOWN; - } - } - - /* Added item for MotionTypes */ - public enum Motion { - MOTION(4), - NO_MOTION(5), - MOTION_TAMPER(132), - NO_MOTION_TAMPER(133), - - UNKNOWN(255); - - private final int motion; - - Motion(int motion) { - this.motion = motion; - } - - Motion(byte motion) { - this.motion = motion; - } - - public byte toByte() { - return (byte) motion; - } - - public static Motion fromByte(int input) { - for (Motion motion : Motion.values()) { - if (motion.motion == input) { - return motion; - } - } - - return Motion.UNKNOWN; - } - } - - private final static List supportedInputValueSelectors = Arrays.asList( - RFXComValueSelector.SIGNAL_LEVEL, RFXComValueSelector.BATTERY_LEVEL, RFXComValueSelector.STATUS, - RFXComValueSelector.CONTACT, RFXComValueSelector.MOTION); - - private final static List supportedOutputValueSelectors = Arrays - .asList(RFXComValueSelector.STATUS, RFXComValueSelector.CONTACT); - - public SubType subType = SubType.UNKNOWN; - public int sensorId = 0; - public Status status = Status.UNKNOWN; - public byte batteryLevel = 0; - public byte signalLevel = 0; - public Contact contact = Contact.UNKNOWN; - public Motion motion = Motion.UNKNOWN; - - public RFXComSecurity1Message() { - packetType = PacketType.SECURITY1; - } - - public RFXComSecurity1Message(byte[] data) { - encodeMessage(data); - } - - @Override - public String toString() { - String str = ""; - - str += super.toString(); - str += ", Sub type = " + subType; - str += ", Device Id = " + getDeviceId(); - str += ", Status = " + status; - str += ", Battery level = " + batteryLevel; - str += ", Signal level = " + signalLevel; - - return str; - } - - @Override - public void encodeMessage(byte[] data) { - - super.encodeMessage(data); - - subType = SubType.fromByte(super.subType); - sensorId = (data[4] & 0xFF) << 16 | (data[5] & 0xFF) << 8 | (data[6] & 0xFF); - - status = Status.fromByte(data[7]); - batteryLevel = (byte) ((data[8] & 0xF0) >> 4); - signalLevel = (byte) (data[8] & 0x0F); - - contact = Contact.fromByte(data[7]); - motion = Motion.fromByte(data[7]); - } - - @Override - public byte[] decodeMessage() { - - byte[] data = new byte[9]; - - data[0] = 0x08; - data[1] = RFXComBaseMessage.PacketType.SECURITY1.toByte(); - data[2] = subType.toByte(); - data[3] = seqNbr; - data[4] = (byte) ((sensorId >> 16) & 0xFF); - data[5] = (byte) ((sensorId >> 8) & 0xFF); - data[6] = (byte) (sensorId & 0xFF); - data[7] = status.toByte(); - data[8] = (byte) (((batteryLevel & 0x0F) << 4) | (signalLevel & 0x0F)); - - return data; - } - - @Override - public String getDeviceId() { - return String.valueOf(sensorId); - } - - @Override - public State convertToState(RFXComValueSelector valueSelector) throws RFXComException { - - State state = UnDefType.UNDEF; - - if (valueSelector.getItemClass() == SwitchItem.class) { - - if (valueSelector == RFXComValueSelector.MOTION) { - - switch (status) { - case MOTION: - state = OnOffType.ON; - break; - case NO_MOTION: - state = OnOffType.OFF; - break; - default: - break; - } - - } else { - throw new RFXComException("Can't convert " + valueSelector + " to SwitchItem"); - } - - } else if (valueSelector.getItemClass() == ContactItem.class) { - - if (valueSelector == RFXComValueSelector.CONTACT) { - - switch (status) { - - case NORMAL: - state = OpenClosedType.CLOSED; - break; - case NORMAL_DELAYED: - state = OpenClosedType.CLOSED; - break; - case ALARM: - state = OpenClosedType.OPEN; - break; - case ALARM_DELAYED: - state = OpenClosedType.OPEN; - break; - default: - break; - - } - - } else { - throw new RFXComException("Can't convert " + valueSelector + " to ContactItem"); - } - - } else if (valueSelector.getItemClass() == StringItem.class) { - - if (valueSelector == RFXComValueSelector.STATUS) { - - state = new StringType(status.toString()); - - } else { - throw new RFXComException("Can't convert " + valueSelector + " to StringItem"); - } - - } else if (valueSelector.getItemClass() == NumberItem.class) { - - if (valueSelector == RFXComValueSelector.SIGNAL_LEVEL) { - - state = new DecimalType(signalLevel); - - } else if (valueSelector == RFXComValueSelector.BATTERY_LEVEL) { - - state = new DecimalType(batteryLevel); - - } else { - throw new RFXComException("Can't convert " + valueSelector + " to StringItem"); - } - - } else if (valueSelector.getItemClass() == DateTimeItem.class) { - - state = new DateTimeType(); - - } else { - - throw new RFXComException("Can't convert " + valueSelector + " to " + valueSelector.getItemClass()); - } - - return state; - - } - - @Override - public void setSubType(Object subType) throws RFXComException { - this.subType = ((SubType) subType); - } - - @Override - public void setDeviceId(String deviceId) throws RFXComException { - sensorId = Integer.parseInt(deviceId); - } - - @Override - public void convertFromState(RFXComValueSelector valueSelector, Type type) throws RFXComException { - - switch (valueSelector) { - case COMMAND: - if ((type instanceof OnOffType) && (subType == SubType.X10_SECURITY_REMOTE)) { - status = (type == OnOffType.ON ? Status.ARM_AWAY_DELAYED : Status.DISARM); - } else { - throw new RFXComException("Can't convert " + type + " to Command"); - } - break; - - case STATUS: - if (type instanceof StringType) { - status = Status.valueOf(type.toString()); - } else { - throw new RFXComException("Can't convert " + type + " to Status"); - } - break; - - default: - throw new RFXComException("Can't convert " + type + " to " + valueSelector); - } - } - - @Override - public Object convertSubType(String subType) throws RFXComException { - - for (SubType s : SubType.values()) { - if (s.toString().equals(subType)) { - return s; - } - } - - // try to find sub type by number - try { - return SubType.values()[Integer.parseInt(subType)]; - } catch (Exception e) { - throw new RFXComException("Unknown sub type " + subType); - } - } - - @Override - public List getSupportedInputValueSelectors() throws RFXComException { - return supportedInputValueSelectors; - } - - @Override - public List getSupportedOutputValueSelectors() throws RFXComException { - return supportedOutputValueSelectors; - } -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.rfxcom.internal.messages; + +import org.eclipse.smarthome.core.library.items.*; +import org.eclipse.smarthome.core.library.types.*; +import org.eclipse.smarthome.core.types.State; +import org.eclipse.smarthome.core.types.Type; +import org.eclipse.smarthome.core.types.UnDefType; +import org.openhab.binding.rfxcom.RFXComValueSelector; +import org.openhab.binding.rfxcom.internal.exceptions.RFXComException; + +import java.util.Arrays; +import java.util.List; + +/** + * RFXCOM data class for Security1 message. + * (i.e. X10 Security, Visonic PowerCode, Meiantech, etc.) + * + * @author David Kalff - Initial contribution + * @author Pauli Anttila + */ +public class RFXComSecurity1Message extends RFXComBaseMessage { + + public enum SubType { + X10_SECURITY(0), + X10_SECURITY_MOTION(1), + X10_SECURITY_REMOTE(2), + KD101(3), + VISONIC_POWERCODE_SENSOR_PRIMARY_CONTACT(4), + VISONIC_POWERCODE_MOTION(5), + VISONIC_CODESECURE(6), + VISONIC_POWERCODE_SENSOR_AUX_CONTACT(7), + MEIANTECH(8), + SA30(9), + + UNKNOWN(255); + + private final int subType; + + SubType(int subType) { + this.subType = subType; + } + + SubType(byte subType) { + this.subType = subType; + } + + public byte toByte() { + return (byte) subType; + } + + public static SubType fromByte(int input) { + for (SubType c : SubType.values()) { + if (c.subType == input) { + return c; + } + } + + return SubType.UNKNOWN; + } + } + + public enum Status { + NORMAL(0), + NORMAL_DELAYED(1), + ALARM(2), + ALARM_DELAYED(3), + MOTION(4), + NO_MOTION(5), + PANIC(6), + END_PANIC(7), + IR(8), + ARM_AWAY(9), + ARM_AWAY_DELAYED(10), + ARM_HOME(11), + ARM_HOME_DELAYED(12), + DISARM(13), + LIGHT_1_OFF(16), + LIGHT_1_ON(17), + LIGHT_2_OFF(18), + LIGHT_2_ON(19), + DARK_DETECTED(20), + LIGHT_DETECTED(21), + BATLOW(22), + PAIR_KD101(23), + NORMAL_TAMPER(128), + NORMAL_DELAYED_TAMPER(129), + ALARM_TAMPER(130), + ALARM_DELAYED_TAMPER(131), + MOTION_TAMPER(132), + NO_MOTION_TAMPER(133), + + UNKNOWN(255); + + private final int status; + + Status(int status) { + this.status = status; + } + + Status(byte status) { + this.status = status; + } + + public byte toByte() { + return (byte) status; + } + + public static Status fromByte(int input) { + for (Status status : Status.values()) { + if (status.status == input) { + return status; + } + } + + return Status.UNKNOWN; + } + } + + /* Added item for ContactTypes */ + public enum Contact { + NORMAL(0), + NORMAL_DELAYED(1), + ALARM(2), + ALARM_DELAYED(3), + NORMAL_TAMPER(128), + NORMAL_DELAYED_TAMPER(129), + ALARM_TAMPER(130), + ALARM_DELAYED_TAMPER(131), + + UNKNOWN(255); + + private final int contact; + + Contact(int contact) { + this.contact = contact; + } + + Contact(byte contact) { + this.contact = contact; + } + + public byte toByte() { + return (byte) contact; + } + + public static Contact fromByte(int input) { + for (Contact status : Contact.values()) { + if (status.contact == input) { + return status; + } + } + + return Contact.UNKNOWN; + } + } + + /* Added item for MotionTypes */ + public enum Motion { + MOTION(4), + NO_MOTION(5), + MOTION_TAMPER(132), + NO_MOTION_TAMPER(133), + + UNKNOWN(255); + + private final int motion; + + Motion(int motion) { + this.motion = motion; + } + + Motion(byte motion) { + this.motion = motion; + } + + public byte toByte() { + return (byte) motion; + } + + public static Motion fromByte(int input) { + for (Motion motion : Motion.values()) { + if (motion.motion == input) { + return motion; + } + } + + return Motion.UNKNOWN; + } + } + + private final static List supportedInputValueSelectors = Arrays.asList( + RFXComValueSelector.SIGNAL_LEVEL, RFXComValueSelector.BATTERY_LEVEL, RFXComValueSelector.STATUS, + RFXComValueSelector.CONTACT, RFXComValueSelector.MOTION); + + private final static List supportedOutputValueSelectors = Arrays + .asList(RFXComValueSelector.STATUS, RFXComValueSelector.CONTACT); + + public SubType subType = SubType.UNKNOWN; + public int sensorId = 0; + public Status status = Status.UNKNOWN; + public byte batteryLevel = 0; + public byte signalLevel = 0; + public Contact contact = Contact.UNKNOWN; + public Motion motion = Motion.UNKNOWN; + + public RFXComSecurity1Message() { + packetType = PacketType.SECURITY1; + } + + public RFXComSecurity1Message(byte[] data) { + encodeMessage(data); + } + + @Override + public String toString() { + String str = ""; + + str += super.toString(); + str += ", Sub type = " + subType; + str += ", Device Id = " + getDeviceId(); + str += ", Status = " + status; + str += ", Battery level = " + batteryLevel; + str += ", Signal level = " + signalLevel; + + return str; + } + + @Override + public void encodeMessage(byte[] data) { + + super.encodeMessage(data); + + subType = SubType.fromByte(super.subType); + sensorId = (data[4] & 0xFF) << 16 | (data[5] & 0xFF) << 8 | (data[6] & 0xFF); + + status = Status.fromByte(data[7]); + batteryLevel = (byte) ((data[8] & 0xF0) >> 4); + signalLevel = (byte) (data[8] & 0x0F); + + contact = Contact.fromByte(data[7]); + motion = Motion.fromByte(data[7]); + } + + @Override + public byte[] decodeMessage() { + + byte[] data = new byte[9]; + + data[0] = 0x08; + data[1] = RFXComBaseMessage.PacketType.SECURITY1.toByte(); + data[2] = subType.toByte(); + data[3] = seqNbr; + data[4] = (byte) ((sensorId >> 16) & 0xFF); + data[5] = (byte) ((sensorId >> 8) & 0xFF); + data[6] = (byte) (sensorId & 0xFF); + data[7] = status.toByte(); + data[8] = (byte) (((batteryLevel & 0x0F) << 4) | (signalLevel & 0x0F)); + + return data; + } + + @Override + public String getDeviceId() { + return String.valueOf(sensorId); + } + + @Override + public State convertToState(RFXComValueSelector valueSelector) throws RFXComException { + + State state = UnDefType.UNDEF; + + if (valueSelector.getItemClass() == SwitchItem.class) { + + if (valueSelector == RFXComValueSelector.MOTION) { + + switch (status) { + case MOTION: + state = OnOffType.ON; + break; + case NO_MOTION: + state = OnOffType.OFF; + break; + default: + break; + } + + } else { + throw new RFXComException("Can't convert " + valueSelector + " to SwitchItem"); + } + + } else if (valueSelector.getItemClass() == ContactItem.class) { + + if (valueSelector == RFXComValueSelector.CONTACT) { + + switch (status) { + + case NORMAL: + state = OpenClosedType.CLOSED; + break; + case NORMAL_DELAYED: + state = OpenClosedType.CLOSED; + break; + case ALARM: + state = OpenClosedType.OPEN; + break; + case ALARM_DELAYED: + state = OpenClosedType.OPEN; + break; + default: + break; + + } + + } else { + throw new RFXComException("Can't convert " + valueSelector + " to ContactItem"); + } + + } else if (valueSelector.getItemClass() == StringItem.class) { + + if (valueSelector == RFXComValueSelector.STATUS) { + + state = new StringType(status.toString()); + + } else { + throw new RFXComException("Can't convert " + valueSelector + " to StringItem"); + } + + } else if (valueSelector.getItemClass() == NumberItem.class) { + + if (valueSelector == RFXComValueSelector.SIGNAL_LEVEL) { + + state = new DecimalType(signalLevel); + + } else if (valueSelector == RFXComValueSelector.BATTERY_LEVEL) { + + state = new DecimalType(batteryLevel); + + } else { + throw new RFXComException("Can't convert " + valueSelector + " to StringItem"); + } + + } else if (valueSelector.getItemClass() == DateTimeItem.class) { + + state = new DateTimeType(); + + } else { + + throw new RFXComException("Can't convert " + valueSelector + " to " + valueSelector.getItemClass()); + } + + return state; + + } + + @Override + public void setSubType(Object subType) throws RFXComException { + this.subType = ((SubType) subType); + } + + @Override + public void setDeviceId(String deviceId) throws RFXComException { + sensorId = Integer.parseInt(deviceId); + } + + @Override + public void convertFromState(RFXComValueSelector valueSelector, Type type) throws RFXComException { + + switch (valueSelector) { + case COMMAND: + if ((type instanceof OnOffType) && (subType == SubType.X10_SECURITY_REMOTE)) { + status = (type == OnOffType.ON ? Status.ARM_AWAY_DELAYED : Status.DISARM); + } else { + throw new RFXComException("Can't convert " + type + " to Command"); + } + break; + + case STATUS: + if (type instanceof StringType) { + status = Status.valueOf(type.toString()); + } else { + throw new RFXComException("Can't convert " + type + " to Status"); + } + break; + + default: + throw new RFXComException("Can't convert " + type + " to " + valueSelector); + } + } + + @Override + public Object convertSubType(String subType) throws RFXComException { + + for (SubType s : SubType.values()) { + if (s.toString().equals(subType)) { + return s; + } + } + + // try to find sub type by number + try { + return SubType.values()[Integer.parseInt(subType)]; + } catch (Exception e) { + throw new RFXComException("Unknown sub type " + subType); + } + } + + @Override + public List getSupportedInputValueSelectors() throws RFXComException { + return supportedInputValueSelectors; + } + + @Override + public List getSupportedOutputValueSelectors() throws RFXComException { + return supportedOutputValueSelectors; + } +} diff --git a/addons/binding/org.openhab.binding.rfxcom/src/main/java/org/openhab/binding/rfxcom/internal/messages/RFXComWindMessage.java b/addons/binding/org.openhab.binding.rfxcom/src/main/java/org/openhab/binding/rfxcom/internal/messages/RFXComWindMessage.java index e44314e29d25b..97dde5f9c375a 100644 --- a/addons/binding/org.openhab.binding.rfxcom/src/main/java/org/openhab/binding/rfxcom/internal/messages/RFXComWindMessage.java +++ b/addons/binding/org.openhab.binding.rfxcom/src/main/java/org/openhab/binding/rfxcom/internal/messages/RFXComWindMessage.java @@ -1,222 +1,222 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.rfxcom.internal.messages; - -import org.eclipse.smarthome.core.library.items.NumberItem; -import org.eclipse.smarthome.core.library.types.DecimalType; -import org.eclipse.smarthome.core.types.State; -import org.eclipse.smarthome.core.types.Type; -import org.openhab.binding.rfxcom.RFXComValueSelector; -import org.openhab.binding.rfxcom.internal.exceptions.RFXComException; - -import java.util.Arrays; -import java.util.List; - -/** - * RFXCOM data class for temperature and humidity message. - * - * @author Marc SAUVEUR - Initial contribution - * @author Pauli Anttila - */ -public class RFXComWindMessage extends RFXComBaseMessage { - - public enum SubType { - WIND1(1), - WIND2(2), - WIND3(3), - WIND4(4), - WIND5(5), - WIND6(6), - WIND7(7), - - UNKNOWN(255); - - private final int subType; - - SubType(int subType) { - this.subType = subType; - } - - SubType(byte subType) { - this.subType = subType; - } - - public byte toByte() { - return (byte) subType; - } - - public static SubType fromByte(int input) { - for (SubType c : SubType.values()) { - if (c.subType == input) { - return c; - } - } - - return SubType.UNKNOWN; - } - } - - private final static List supportedInputValueSelectors = Arrays.asList( - RFXComValueSelector.SIGNAL_LEVEL, RFXComValueSelector.BATTERY_LEVEL, RFXComValueSelector.WIND_DIRECTION, - RFXComValueSelector.WIND_SPEED); - - private final static List supportedOutputValueSelectors = Arrays.asList(); - - public SubType subType = SubType.UNKNOWN; - public int sensorId = 0; - public double windDirection = 0; - public double windSpeed = 0; - public byte signalLevel = 0; - public byte batteryLevel = 0; - - public RFXComWindMessage() { - packetType = PacketType.WIND; - } - - public RFXComWindMessage(byte[] data) { - encodeMessage(data); - } - - @Override - public String toString() { - String str = ""; - - str += super.toString(); - str += ", Sub type = " + subType; - str += ", Device Id = " + getDeviceId(); - str += ", Wind direction = " + windDirection; - str += ", Wind speed = " + windSpeed; - str += ", Signal level = " + signalLevel; - str += ", Battery level = " + batteryLevel; - - return str; - } - - @Override - public void encodeMessage(byte[] data) { - - super.encodeMessage(data); - - subType = SubType.fromByte(super.subType); - sensorId = (data[4] & 0xFF) << 8 | (data[5] & 0xFF); - - windDirection = (short) ((data[6] & 0xFF) << 8 | (data[7] & 0xFF)); - windSpeed = (short) ((data[10] & 0xFF) << 8 | (data[11] & 0xFF)) * 0.1; - signalLevel = (byte) ((data[16] & 0xF0) >> 4); - batteryLevel = (byte) (data[16] & 0x0F); - } - - @Override - public byte[] decodeMessage() { - byte[] data = new byte[17]; - - data[0] = 0x10; - data[1] = PacketType.WIND.toByte(); - data[2] = subType.toByte(); - data[3] = seqNbr; - data[4] = (byte) ((sensorId & 0xFF00) >> 8); - data[5] = (byte) (sensorId & 0x00FF); - - short WindD = (short) Math.abs(windDirection); - data[6] = (byte) ((WindD >> 8) & 0xFF); - data[7] = (byte) (WindD & 0xFF); - - int WindS = (short) Math.abs(windSpeed) * 10; - data[10] = (byte) ((WindS >> 8) & 0xFF); - data[11] = (byte) (WindS & 0xFF); - - data[16] = (byte) (((signalLevel & 0x0F) << 4) | (batteryLevel & 0x0F)); - - return data; - } - - @Override - public String getDeviceId() { - return String.valueOf(sensorId); - } - - @Override - public State convertToState(RFXComValueSelector valueSelector) throws RFXComException { - - State state; - - if (valueSelector.getItemClass() == NumberItem.class) { - - if (valueSelector == RFXComValueSelector.SIGNAL_LEVEL) { - - state = new DecimalType(signalLevel); - - } else if (valueSelector == RFXComValueSelector.BATTERY_LEVEL) { - - state = new DecimalType(batteryLevel); - - } else if (valueSelector == RFXComValueSelector.WIND_DIRECTION) { - - state = new DecimalType(windDirection); - } else if (valueSelector == RFXComValueSelector.WIND_SPEED) { - - state = new DecimalType(windSpeed); - - } else { - throw new RFXComException("Can't convert " + valueSelector + " to NumberItem"); - } - - } else { - - throw new RFXComException("Can't convert " + valueSelector + " to " + valueSelector.getItemClass()); - - } - - return state; - } - - @Override - public void setSubType(Object subType) throws RFXComException { - throw new RFXComException("Not supported"); - } - - @Override - public void setDeviceId(String deviceId) throws RFXComException { - throw new RFXComException("Not supported"); - } - - @Override - public void convertFromState(RFXComValueSelector valueSelector, Type type) throws RFXComException { - - throw new RFXComException("Not supported"); - } - - @Override - public Object convertSubType(String subType) throws RFXComException { - - for (SubType s : SubType.values()) { - if (s.toString().equals(subType)) { - return s; - } - } - - // try to find sub type by number - try { - return SubType.values()[Integer.parseInt(subType)]; - } catch (Exception e) { - throw new RFXComException("Unknown sub type " + subType); - } - } - - @Override - public List getSupportedInputValueSelectors() throws RFXComException { - return supportedInputValueSelectors; - } - - @Override - public List getSupportedOutputValueSelectors() throws RFXComException { - return supportedOutputValueSelectors; - } - -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.rfxcom.internal.messages; + +import org.eclipse.smarthome.core.library.items.NumberItem; +import org.eclipse.smarthome.core.library.types.DecimalType; +import org.eclipse.smarthome.core.types.State; +import org.eclipse.smarthome.core.types.Type; +import org.openhab.binding.rfxcom.RFXComValueSelector; +import org.openhab.binding.rfxcom.internal.exceptions.RFXComException; + +import java.util.Arrays; +import java.util.List; + +/** + * RFXCOM data class for temperature and humidity message. + * + * @author Marc SAUVEUR - Initial contribution + * @author Pauli Anttila + */ +public class RFXComWindMessage extends RFXComBaseMessage { + + public enum SubType { + WIND1(1), + WIND2(2), + WIND3(3), + WIND4(4), + WIND5(5), + WIND6(6), + WIND7(7), + + UNKNOWN(255); + + private final int subType; + + SubType(int subType) { + this.subType = subType; + } + + SubType(byte subType) { + this.subType = subType; + } + + public byte toByte() { + return (byte) subType; + } + + public static SubType fromByte(int input) { + for (SubType c : SubType.values()) { + if (c.subType == input) { + return c; + } + } + + return SubType.UNKNOWN; + } + } + + private final static List supportedInputValueSelectors = Arrays.asList( + RFXComValueSelector.SIGNAL_LEVEL, RFXComValueSelector.BATTERY_LEVEL, RFXComValueSelector.WIND_DIRECTION, + RFXComValueSelector.WIND_SPEED); + + private final static List supportedOutputValueSelectors = Arrays.asList(); + + public SubType subType = SubType.UNKNOWN; + public int sensorId = 0; + public double windDirection = 0; + public double windSpeed = 0; + public byte signalLevel = 0; + public byte batteryLevel = 0; + + public RFXComWindMessage() { + packetType = PacketType.WIND; + } + + public RFXComWindMessage(byte[] data) { + encodeMessage(data); + } + + @Override + public String toString() { + String str = ""; + + str += super.toString(); + str += ", Sub type = " + subType; + str += ", Device Id = " + getDeviceId(); + str += ", Wind direction = " + windDirection; + str += ", Wind speed = " + windSpeed; + str += ", Signal level = " + signalLevel; + str += ", Battery level = " + batteryLevel; + + return str; + } + + @Override + public void encodeMessage(byte[] data) { + + super.encodeMessage(data); + + subType = SubType.fromByte(super.subType); + sensorId = (data[4] & 0xFF) << 8 | (data[5] & 0xFF); + + windDirection = (short) ((data[6] & 0xFF) << 8 | (data[7] & 0xFF)); + windSpeed = (short) ((data[10] & 0xFF) << 8 | (data[11] & 0xFF)) * 0.1; + signalLevel = (byte) ((data[16] & 0xF0) >> 4); + batteryLevel = (byte) (data[16] & 0x0F); + } + + @Override + public byte[] decodeMessage() { + byte[] data = new byte[17]; + + data[0] = 0x10; + data[1] = PacketType.WIND.toByte(); + data[2] = subType.toByte(); + data[3] = seqNbr; + data[4] = (byte) ((sensorId & 0xFF00) >> 8); + data[5] = (byte) (sensorId & 0x00FF); + + short WindD = (short) Math.abs(windDirection); + data[6] = (byte) ((WindD >> 8) & 0xFF); + data[7] = (byte) (WindD & 0xFF); + + int WindS = (short) Math.abs(windSpeed) * 10; + data[10] = (byte) ((WindS >> 8) & 0xFF); + data[11] = (byte) (WindS & 0xFF); + + data[16] = (byte) (((signalLevel & 0x0F) << 4) | (batteryLevel & 0x0F)); + + return data; + } + + @Override + public String getDeviceId() { + return String.valueOf(sensorId); + } + + @Override + public State convertToState(RFXComValueSelector valueSelector) throws RFXComException { + + State state; + + if (valueSelector.getItemClass() == NumberItem.class) { + + if (valueSelector == RFXComValueSelector.SIGNAL_LEVEL) { + + state = new DecimalType(signalLevel); + + } else if (valueSelector == RFXComValueSelector.BATTERY_LEVEL) { + + state = new DecimalType(batteryLevel); + + } else if (valueSelector == RFXComValueSelector.WIND_DIRECTION) { + + state = new DecimalType(windDirection); + } else if (valueSelector == RFXComValueSelector.WIND_SPEED) { + + state = new DecimalType(windSpeed); + + } else { + throw new RFXComException("Can't convert " + valueSelector + " to NumberItem"); + } + + } else { + + throw new RFXComException("Can't convert " + valueSelector + " to " + valueSelector.getItemClass()); + + } + + return state; + } + + @Override + public void setSubType(Object subType) throws RFXComException { + throw new RFXComException("Not supported"); + } + + @Override + public void setDeviceId(String deviceId) throws RFXComException { + throw new RFXComException("Not supported"); + } + + @Override + public void convertFromState(RFXComValueSelector valueSelector, Type type) throws RFXComException { + + throw new RFXComException("Not supported"); + } + + @Override + public Object convertSubType(String subType) throws RFXComException { + + for (SubType s : SubType.values()) { + if (s.toString().equals(subType)) { + return s; + } + } + + // try to find sub type by number + try { + return SubType.values()[Integer.parseInt(subType)]; + } catch (Exception e) { + throw new RFXComException("Unknown sub type " + subType); + } + } + + @Override + public List getSupportedInputValueSelectors() throws RFXComException { + return supportedInputValueSelectors; + } + + @Override + public List getSupportedOutputValueSelectors() throws RFXComException { + return supportedOutputValueSelectors; + } + +} diff --git a/addons/binding/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/KeyCode.java b/addons/binding/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/KeyCode.java old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/RemoteControllerException.java b/addons/binding/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/RemoteControllerException.java old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/.classpath b/addons/binding/org.openhab.binding.tellstick/.classpath old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/.project b/addons/binding/org.openhab.binding.tellstick/.project old mode 100755 new mode 100644 index 96216975833e4..a851245278840 --- a/addons/binding/org.openhab.binding.tellstick/.project +++ b/addons/binding/org.openhab.binding.tellstick/.project @@ -1,33 +1,33 @@ - - - org.openhab.binding.tellstick - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - org.eclipse.pde.ds.core.builder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - + + + org.openhab.binding.tellstick + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.ds.core.builder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/addons/binding/org.openhab.binding.tellstick/.settings/org.eclipse.jdt.core.prefs b/addons/binding/org.openhab.binding.tellstick/.settings/org.eclipse.jdt.core.prefs old mode 100755 new mode 100644 index 980b98c1d5ff1..d17b6724d17fd --- a/addons/binding/org.openhab.binding.tellstick/.settings/org.eclipse.jdt.core.prefs +++ b/addons/binding/org.openhab.binding.tellstick/.settings/org.eclipse.jdt.core.prefs @@ -1,12 +1,12 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.7 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.7 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.7 diff --git a/addons/binding/org.openhab.binding.tellstick/ESH-INF/binding/binding.xml b/addons/binding/org.openhab.binding.tellstick/ESH-INF/binding/binding.xml old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/ESH-INF/config/config.xml b/addons/binding/org.openhab.binding.tellstick/ESH-INF/config/config.xml old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/ESH-INF/thing/bridge.xml b/addons/binding/org.openhab.binding.tellstick/ESH-INF/thing/bridge.xml old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/ESH-INF/thing/devices.xml b/addons/binding/org.openhab.binding.tellstick/ESH-INF/thing/devices.xml old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/ESH-INF/thing/sensor.xml b/addons/binding/org.openhab.binding.tellstick/ESH-INF/thing/sensor.xml old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/META-INF/MANIFEST.MF b/addons/binding/org.openhab.binding.tellstick/META-INF/MANIFEST.MF old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/OSGI-INF/TellstickHandlerFactory.xml b/addons/binding/org.openhab.binding.tellstick/OSGI-INF/TellstickHandlerFactory.xml old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/build.properties b/addons/binding/org.openhab.binding.tellstick/build.properties old mode 100755 new mode 100644 index 4aa3323db78dd..31505b18dd7b8 --- a/addons/binding/org.openhab.binding.tellstick/build.properties +++ b/addons/binding/org.openhab.binding.tellstick/build.properties @@ -1,17 +1,17 @@ -source.. = src/main/java/ -output.. = target/classes -bin.includes = META-INF/,\ - .,\ - OSGI-INF/,\ - ESH-INF/,\ - lib/jna-4.0.0.jar,\ - plugin.xml,\ - lib/javatellstick-1.0.jar,\ - lib/async-http-client-2.0.19.jar,\ - lib/async-http-client-netty-utils-2.0.19.jar,\ - lib/netty-reactive-streams-1.0.8.jar,\ - lib/reactive-streams-1.0.0.jar,\ - lib/netty-all-4.0.42.Final.jar,\ - lib/netty-resolver-2.0.19.jar,\ - lib/netty-resolver-dns-2.0.19.jar - +source.. = src/main/java/ +output.. = target/classes +bin.includes = META-INF/,\ + .,\ + OSGI-INF/,\ + ESH-INF/,\ + lib/jna-4.0.0.jar,\ + plugin.xml,\ + lib/javatellstick-1.0.jar,\ + lib/async-http-client-2.0.19.jar,\ + lib/async-http-client-netty-utils-2.0.19.jar,\ + lib/netty-reactive-streams-1.0.8.jar,\ + lib/reactive-streams-1.0.0.jar,\ + lib/netty-all-4.0.42.Final.jar,\ + lib/netty-resolver-2.0.19.jar,\ + lib/netty-resolver-dns-2.0.19.jar + diff --git a/addons/binding/org.openhab.binding.tellstick/lib/javatellstick-1.0.jar b/addons/binding/org.openhab.binding.tellstick/lib/javatellstick-1.0.jar old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/lib/jna-4.0.0.jar b/addons/binding/org.openhab.binding.tellstick/lib/jna-4.0.0.jar old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/plugin.xml b/addons/binding/org.openhab.binding.tellstick/plugin.xml old mode 100755 new mode 100644 index b60f62ae57e47..5535690d3778e --- a/addons/binding/org.openhab.binding.tellstick/plugin.xml +++ b/addons/binding/org.openhab.binding.tellstick/plugin.xml @@ -1,5 +1,5 @@ - - - - - + + + + + diff --git a/addons/binding/org.openhab.binding.tellstick/pom.xml b/addons/binding/org.openhab.binding.tellstick/pom.xml old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/TellstickBindingConstants.java b/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/TellstickBindingConstants.java old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/conf/TelldusLiveConfiguration.java b/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/conf/TelldusLiveConfiguration.java old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/conf/TellstickBridgeConfiguration.java b/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/conf/TellstickBridgeConfiguration.java old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/DeviceStatusListener.java b/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/DeviceStatusListener.java old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/TelldusBridgeHandler.java b/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/TelldusBridgeHandler.java old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/TelldusDeviceController.java b/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/TelldusDeviceController.java old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/TelldusDevicesHandler.java b/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/TelldusDevicesHandler.java old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/core/TelldusCoreBridgeHandler.java b/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/core/TelldusCoreBridgeHandler.java old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/core/TelldusCoreDeviceController.java b/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/core/TelldusCoreDeviceController.java old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/live/TelldusLiveBridgeHandler.java b/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/live/TelldusLiveBridgeHandler.java old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/live/TelldusLiveDeviceController.java b/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/live/TelldusLiveDeviceController.java old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/live/xml/DataTypeValue.java b/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/live/xml/DataTypeValue.java old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/live/xml/MethodToMethodType.java b/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/live/xml/MethodToMethodType.java old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/live/xml/NameToDataType.java b/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/live/xml/NameToDataType.java old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/live/xml/NumberToBooleanMapper.java b/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/live/xml/NumberToBooleanMapper.java old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/live/xml/TelldusLiveResponse.java b/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/live/xml/TelldusLiveResponse.java old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/live/xml/TellstickNetDevice.java b/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/live/xml/TellstickNetDevice.java old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/live/xml/TellstickNetDevices.java b/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/live/xml/TellstickNetDevices.java old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/live/xml/TellstickNetSensor.java b/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/live/xml/TellstickNetSensor.java old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/live/xml/TellstickNetSensors.java b/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/handler/live/xml/TellstickNetSensors.java old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/TellstickHandlerFactory.java b/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/TellstickHandlerFactory.java old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/discovery/TellstickBridgeDiscovery.java b/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/discovery/TellstickBridgeDiscovery.java old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/discovery/TellstickDiscoveryService.java b/addons/binding/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/discovery/TellstickDiscoveryService.java old mode 100755 new mode 100644 diff --git a/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/AbstractChannelThrottler.java b/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/AbstractChannelThrottler.java index 47652c7b5499b..1b1f8209bc406 100644 --- a/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/AbstractChannelThrottler.java +++ b/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/AbstractChannelThrottler.java @@ -1,53 +1,53 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.tesla.internal.throttler; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ScheduledExecutorService; - -/** - * The {@link AbstractChannelThrottler} is abstract class implementing a - * throttler with one global execution rate, or rate limiter - * - * @author Karel Goderis - Initial contribution - */ -abstract class AbstractChannelThrottler implements ChannelThrottler { - - protected final Rate totalRate; - protected final TimeProvider timeProvider; - protected final ScheduledExecutorService scheduler; - protected final Map channels = new HashMap(); - - protected AbstractChannelThrottler(Rate totalRate, - ScheduledExecutorService scheduler, Map channels, - TimeProvider timeProvider) { - this.totalRate = totalRate; - this.scheduler = scheduler; - this.channels.putAll(channels); - this.timeProvider = timeProvider; - } - - protected synchronized long callTime(Rate channel) { - long now = timeProvider.getCurrentTimeInMillis(); - long callTime = totalRate.callTime(now); - if (channel != null) { - callTime = Math.max(callTime, channel.callTime(now)); - channel.addCall(callTime); - } - totalRate.addCall(callTime); - return callTime; - } - - protected long getThrottleDelay(Object channelKey) { - long delay = callTime(channels.get(channelKey)) - - timeProvider.getCurrentTimeInMillis(); - return delay < 0 ? 0 : delay; - } -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.tesla.internal.throttler; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ScheduledExecutorService; + +/** + * The {@link AbstractChannelThrottler} is abstract class implementing a + * throttler with one global execution rate, or rate limiter + * + * @author Karel Goderis - Initial contribution + */ +abstract class AbstractChannelThrottler implements ChannelThrottler { + + protected final Rate totalRate; + protected final TimeProvider timeProvider; + protected final ScheduledExecutorService scheduler; + protected final Map channels = new HashMap(); + + protected AbstractChannelThrottler(Rate totalRate, + ScheduledExecutorService scheduler, Map channels, + TimeProvider timeProvider) { + this.totalRate = totalRate; + this.scheduler = scheduler; + this.channels.putAll(channels); + this.timeProvider = timeProvider; + } + + protected synchronized long callTime(Rate channel) { + long now = timeProvider.getCurrentTimeInMillis(); + long callTime = totalRate.callTime(now); + if (channel != null) { + callTime = Math.max(callTime, channel.callTime(now)); + channel.addCall(callTime); + } + totalRate.addCall(callTime); + return callTime; + } + + protected long getThrottleDelay(Object channelKey) { + long delay = callTime(channels.get(channelKey)) + - timeProvider.getCurrentTimeInMillis(); + return delay < 0 ? 0 : delay; + } +} diff --git a/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/AbstractMultiRateChannelThrottler.java b/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/AbstractMultiRateChannelThrottler.java index 01409204d5180..10ea9f48823ed 100644 --- a/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/AbstractMultiRateChannelThrottler.java +++ b/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/AbstractMultiRateChannelThrottler.java @@ -1,72 +1,72 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.tesla.internal.throttler; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.concurrent.ScheduledExecutorService; - -/** - * The {@link AbstractMultiRateChannelThrottler} is abstract class implementing - * a throttler with multiple global execution rates, or rate limiters - * - * @author Karel Goderis - Initial contribution - */ -abstract class AbstractMultiRateChannelThrottler implements ChannelThrottler { - - protected final TimeProvider timeProvider; - protected final ScheduledExecutorService scheduler; - protected final Map channels = new HashMap(); - protected final ArrayList rates = new ArrayList(); - - protected AbstractMultiRateChannelThrottler(Rate rate, - ScheduledExecutorService scheduler, Map channels, - TimeProvider timeProvider) { - this.rates.add(rate); - this.scheduler = scheduler; - this.channels.putAll(channels); - this.timeProvider = timeProvider; - } - - public synchronized void addRate(Rate rate) { - this.rates.add(rate); - } - - protected synchronized long callTime(Rate channel) { - long maxCallTime = 0; - long finalCallTime = 0; - long now = timeProvider.getCurrentTimeInMillis(); - Iterator iterator = rates.iterator(); - while (iterator.hasNext()) { - Rate someRate = iterator.next(); - maxCallTime = Math.max(maxCallTime, someRate.callTime(now)); - } - - if (channel != null) { - finalCallTime = Math.max(maxCallTime, channel.callTime(now)); - channel.addCall(finalCallTime); - } - - iterator = rates.iterator(); - while (iterator.hasNext()) { - Rate someRate = iterator.next(); - someRate.addCall(finalCallTime); - } - - return finalCallTime; - } - - protected long getThrottleDelay(Object channelKey) { - long delay = callTime(channels.get(channelKey)) - - timeProvider.getCurrentTimeInMillis(); - return delay < 0 ? 0 : delay; - } -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.tesla.internal.throttler; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.concurrent.ScheduledExecutorService; + +/** + * The {@link AbstractMultiRateChannelThrottler} is abstract class implementing + * a throttler with multiple global execution rates, or rate limiters + * + * @author Karel Goderis - Initial contribution + */ +abstract class AbstractMultiRateChannelThrottler implements ChannelThrottler { + + protected final TimeProvider timeProvider; + protected final ScheduledExecutorService scheduler; + protected final Map channels = new HashMap(); + protected final ArrayList rates = new ArrayList(); + + protected AbstractMultiRateChannelThrottler(Rate rate, + ScheduledExecutorService scheduler, Map channels, + TimeProvider timeProvider) { + this.rates.add(rate); + this.scheduler = scheduler; + this.channels.putAll(channels); + this.timeProvider = timeProvider; + } + + public synchronized void addRate(Rate rate) { + this.rates.add(rate); + } + + protected synchronized long callTime(Rate channel) { + long maxCallTime = 0; + long finalCallTime = 0; + long now = timeProvider.getCurrentTimeInMillis(); + Iterator iterator = rates.iterator(); + while (iterator.hasNext()) { + Rate someRate = iterator.next(); + maxCallTime = Math.max(maxCallTime, someRate.callTime(now)); + } + + if (channel != null) { + finalCallTime = Math.max(maxCallTime, channel.callTime(now)); + channel.addCall(finalCallTime); + } + + iterator = rates.iterator(); + while (iterator.hasNext()) { + Rate someRate = iterator.next(); + someRate.addCall(finalCallTime); + } + + return finalCallTime; + } + + protected long getThrottleDelay(Object channelKey) { + long delay = callTime(channels.get(channelKey)) + - timeProvider.getCurrentTimeInMillis(); + return delay < 0 ? 0 : delay; + } +} diff --git a/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/ChannelThrottler.java b/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/ChannelThrottler.java index e7eabf94dff33..8b98a18aa58fc 100644 --- a/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/ChannelThrottler.java +++ b/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/ChannelThrottler.java @@ -1,23 +1,23 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.tesla.internal.throttler; - -import java.util.concurrent.Future; - -/** - * The {@link ChannelThrottler} defines the interface for to submit tasks to a - * throttler - * - * @author Karel Goderis - Initial contribution - */ -public interface ChannelThrottler { - Future submit(Runnable task); - - Future submit(Object channelKey, Runnable task); -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.tesla.internal.throttler; + +import java.util.concurrent.Future; + +/** + * The {@link ChannelThrottler} defines the interface for to submit tasks to a + * throttler + * + * @author Karel Goderis - Initial contribution + */ +public interface ChannelThrottler { + Future submit(Runnable task); + + Future submit(Object channelKey, Runnable task); +} diff --git a/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/QueueChannelThrottler.java b/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/QueueChannelThrottler.java index e96be501d0351..c29006c1263a2 100644 --- a/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/QueueChannelThrottler.java +++ b/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/QueueChannelThrottler.java @@ -1,116 +1,116 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.tesla.internal.throttler; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.FutureTask; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link QueueChannelThrottler} implements a throttler that maintains - * multiple execution rates, and maintains the order of calls - * - * @author Karel Goderis - Initial contribution - */ -public final class QueueChannelThrottler extends - AbstractMultiRateChannelThrottler { - - private Logger logger = LoggerFactory - .getLogger(QueueChannelThrottler.class); - - private final static int MAX_QUEUE_LENGTH = 150; - private BlockingQueue> tasks; - private final Rate overallRate; - - private final Runnable processQueueTask = new Runnable() { - @Override - public void run() { - FutureTask task = tasks.poll(); - if (task != null && !task.isCancelled()) { - task.run(); - } - } - }; - - public QueueChannelThrottler(Rate someRate) { - this(someRate, (ScheduledThreadPoolExecutor) Executors - .newScheduledThreadPool(1), new HashMap(), - TimeProvider.SYSTEM_PROVIDER, MAX_QUEUE_LENGTH); - } - - public QueueChannelThrottler(Rate someRate, - ScheduledExecutorService scheduler) { - this(someRate, scheduler, new HashMap(), - TimeProvider.SYSTEM_PROVIDER, MAX_QUEUE_LENGTH); - } - - public QueueChannelThrottler(Rate someRate, - ScheduledExecutorService scheduler, Map channels) { - this(someRate, scheduler, channels, TimeProvider.SYSTEM_PROVIDER, - MAX_QUEUE_LENGTH); - } - - public QueueChannelThrottler(Rate someRate, Map channels, - int queueLength) { - this(someRate, (ScheduledThreadPoolExecutor) Executors - .newScheduledThreadPool(1), channels, - TimeProvider.SYSTEM_PROVIDER, queueLength); - } - - public QueueChannelThrottler(Rate someRate, - ScheduledExecutorService scheduler, Map channels, - TimeProvider timeProvider, int queueLength) { - super(someRate, scheduler, channels, timeProvider); - overallRate = someRate; - tasks = new LinkedBlockingQueue>(queueLength); - - } - - @Override - public Future submit(Runnable task) { - return submit(null, task); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Override - public Future submit(Object channelKey, Runnable task) { - FutureTask runTask = new FutureTask(task, null); - try { - if (tasks.offer(runTask, overallRate.timeInMillis(), - TimeUnit.MILLISECONDS)) { - long throttledTime = channelKey == null ? callTime(null) - : callTime(channels.get(channelKey)); - long now = timeProvider.getCurrentTimeInMillis(); - scheduler.schedule(processQueueTask, throttledTime < now ? 0 - : throttledTime - now, TimeUnit.MILLISECONDS); - return runTask; - } else { - logger.warn( - "The QueueThrottler can not take the task '{}' at this point in time", - runTask.toString()); - } - } catch (InterruptedException e) { - logger.error( - "An exception occurred while scheduling a new taks: '{}'", - e.getMessage()); - } - - return null; - } -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.tesla.internal.throttler; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link QueueChannelThrottler} implements a throttler that maintains + * multiple execution rates, and maintains the order of calls + * + * @author Karel Goderis - Initial contribution + */ +public final class QueueChannelThrottler extends + AbstractMultiRateChannelThrottler { + + private Logger logger = LoggerFactory + .getLogger(QueueChannelThrottler.class); + + private final static int MAX_QUEUE_LENGTH = 150; + private BlockingQueue> tasks; + private final Rate overallRate; + + private final Runnable processQueueTask = new Runnable() { + @Override + public void run() { + FutureTask task = tasks.poll(); + if (task != null && !task.isCancelled()) { + task.run(); + } + } + }; + + public QueueChannelThrottler(Rate someRate) { + this(someRate, (ScheduledThreadPoolExecutor) Executors + .newScheduledThreadPool(1), new HashMap(), + TimeProvider.SYSTEM_PROVIDER, MAX_QUEUE_LENGTH); + } + + public QueueChannelThrottler(Rate someRate, + ScheduledExecutorService scheduler) { + this(someRate, scheduler, new HashMap(), + TimeProvider.SYSTEM_PROVIDER, MAX_QUEUE_LENGTH); + } + + public QueueChannelThrottler(Rate someRate, + ScheduledExecutorService scheduler, Map channels) { + this(someRate, scheduler, channels, TimeProvider.SYSTEM_PROVIDER, + MAX_QUEUE_LENGTH); + } + + public QueueChannelThrottler(Rate someRate, Map channels, + int queueLength) { + this(someRate, (ScheduledThreadPoolExecutor) Executors + .newScheduledThreadPool(1), channels, + TimeProvider.SYSTEM_PROVIDER, queueLength); + } + + public QueueChannelThrottler(Rate someRate, + ScheduledExecutorService scheduler, Map channels, + TimeProvider timeProvider, int queueLength) { + super(someRate, scheduler, channels, timeProvider); + overallRate = someRate; + tasks = new LinkedBlockingQueue>(queueLength); + + } + + @Override + public Future submit(Runnable task) { + return submit(null, task); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public Future submit(Object channelKey, Runnable task) { + FutureTask runTask = new FutureTask(task, null); + try { + if (tasks.offer(runTask, overallRate.timeInMillis(), + TimeUnit.MILLISECONDS)) { + long throttledTime = channelKey == null ? callTime(null) + : callTime(channels.get(channelKey)); + long now = timeProvider.getCurrentTimeInMillis(); + scheduler.schedule(processQueueTask, throttledTime < now ? 0 + : throttledTime - now, TimeUnit.MILLISECONDS); + return runTask; + } else { + logger.warn( + "The QueueThrottler can not take the task '{}' at this point in time", + runTask.toString()); + } + } catch (InterruptedException e) { + logger.error( + "An exception occurred while scheduling a new taks: '{}'", + e.getMessage()); + } + + return null; + } +} diff --git a/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/Rate.java b/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/Rate.java index 7ca2924f612d1..78b56eb90fd7a 100644 --- a/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/Rate.java +++ b/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/Rate.java @@ -1,80 +1,80 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.tesla.internal.throttler; - -import java.util.Iterator; -import java.util.LinkedList; -import java.util.ListIterator; -import java.util.concurrent.TimeUnit; - -/** - * The {@link Rate} defines a rate limiter that accepts a number of calls to be - * executed in a given time length. If the quota of calls is used, then calls - * are scheduled for the next block of time - * - * @author Karel Goderis - Initial contribution - */ -public final class Rate { - - private final int numberCalls; - private final int timeLength; - private final TimeUnit timeUnit; - private final LinkedList callHistory = new LinkedList(); - - public Rate(int numberCalls, int timeLength, TimeUnit timeUnit) { - this.numberCalls = numberCalls; - this.timeLength = timeLength; - this.timeUnit = timeUnit; - } - - public long timeInMillis() { - return timeUnit.toMillis(timeLength); - } - - void addCall(long callTime) { - callHistory.addLast(callTime); - } - - private void cleanOld(long now) { - ListIterator i = callHistory.listIterator(); - long threshold = now - timeInMillis(); - while (i.hasNext()) { - if (i.next() <= threshold) { - i.remove(); - } else { - break; - } - } - } - - long callTime(long now) { - cleanOld(now); - if (callHistory.size() < numberCalls) { - return now; - } - long lastStart = callHistory.getLast() - timeInMillis(); - long firstPeriodCall = lastStart, call; - int count = 0; - Iterator i = callHistory.descendingIterator(); - while (i.hasNext()) { - call = i.next(); - if (call < lastStart) { - break; - } else { - count++; - firstPeriodCall = call; - } - } - if (count < numberCalls) { - return firstPeriodCall + 1; - } else { - return firstPeriodCall + timeInMillis() + 1; - } - } -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.tesla.internal.throttler; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.ListIterator; +import java.util.concurrent.TimeUnit; + +/** + * The {@link Rate} defines a rate limiter that accepts a number of calls to be + * executed in a given time length. If the quota of calls is used, then calls + * are scheduled for the next block of time + * + * @author Karel Goderis - Initial contribution + */ +public final class Rate { + + private final int numberCalls; + private final int timeLength; + private final TimeUnit timeUnit; + private final LinkedList callHistory = new LinkedList(); + + public Rate(int numberCalls, int timeLength, TimeUnit timeUnit) { + this.numberCalls = numberCalls; + this.timeLength = timeLength; + this.timeUnit = timeUnit; + } + + public long timeInMillis() { + return timeUnit.toMillis(timeLength); + } + + void addCall(long callTime) { + callHistory.addLast(callTime); + } + + private void cleanOld(long now) { + ListIterator i = callHistory.listIterator(); + long threshold = now - timeInMillis(); + while (i.hasNext()) { + if (i.next() <= threshold) { + i.remove(); + } else { + break; + } + } + } + + long callTime(long now) { + cleanOld(now); + if (callHistory.size() < numberCalls) { + return now; + } + long lastStart = callHistory.getLast() - timeInMillis(); + long firstPeriodCall = lastStart, call; + int count = 0; + Iterator i = callHistory.descendingIterator(); + while (i.hasNext()) { + call = i.next(); + if (call < lastStart) { + break; + } else { + count++; + firstPeriodCall = call; + } + } + if (count < numberCalls) { + return firstPeriodCall + 1; + } else { + return firstPeriodCall + timeInMillis() + 1; + } + } +} diff --git a/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/ScheduledChannelThrottler.java b/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/ScheduledChannelThrottler.java index 337a9dcc14d16..6dd58d43cbd52 100644 --- a/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/ScheduledChannelThrottler.java +++ b/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/ScheduledChannelThrottler.java @@ -1,67 +1,67 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.tesla.internal.throttler; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -/** - * The {@link ScheduledChannelThrottler} implements a throttler that maintains a - * single execution rates, and does not maintains order of calls (thus have to - * start from back rather than try to insert things in middle) - * - * @author Karel Goderis - Initial contribution - */ -public final class ScheduledChannelThrottler extends AbstractChannelThrottler { - - public ScheduledChannelThrottler(Rate totalRate) { - this(totalRate, Executors.newSingleThreadScheduledExecutor(), - new HashMap(), TimeProvider.SYSTEM_PROVIDER); - } - - public ScheduledChannelThrottler(Rate totalRate, Map channels) { - this(totalRate, Executors.newSingleThreadScheduledExecutor(), channels, - TimeProvider.SYSTEM_PROVIDER); - } - - public ScheduledChannelThrottler(Rate totalRate, - ScheduledExecutorService scheduler, Map channels, - TimeProvider timeProvider) { - super(totalRate, scheduler, channels, timeProvider); - } - - public void submitSync(Object channelKey, Runnable task) - throws InterruptedException { - Thread.sleep(getThrottleDelay(channelKey)); - task.run(); - } - - public void submitSync(Runnable task) throws InterruptedException { - long delay = callTime(null) - timeProvider.getCurrentTimeInMillis(); - Thread.sleep(getThrottleDelay(delay)); - task.run(); - } - - @Override - public Future submit(Runnable task) { - long delay = callTime(null) - timeProvider.getCurrentTimeInMillis(); - return scheduler.schedule(task, delay < 0 ? 0 : delay, - TimeUnit.MILLISECONDS); - } - - @Override - public Future submit(Object channelKey, Runnable task) { - return scheduler.schedule(task, getThrottleDelay(channelKey), - TimeUnit.MILLISECONDS); - } -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.tesla.internal.throttler; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +/** + * The {@link ScheduledChannelThrottler} implements a throttler that maintains a + * single execution rates, and does not maintains order of calls (thus have to + * start from back rather than try to insert things in middle) + * + * @author Karel Goderis - Initial contribution + */ +public final class ScheduledChannelThrottler extends AbstractChannelThrottler { + + public ScheduledChannelThrottler(Rate totalRate) { + this(totalRate, Executors.newSingleThreadScheduledExecutor(), + new HashMap(), TimeProvider.SYSTEM_PROVIDER); + } + + public ScheduledChannelThrottler(Rate totalRate, Map channels) { + this(totalRate, Executors.newSingleThreadScheduledExecutor(), channels, + TimeProvider.SYSTEM_PROVIDER); + } + + public ScheduledChannelThrottler(Rate totalRate, + ScheduledExecutorService scheduler, Map channels, + TimeProvider timeProvider) { + super(totalRate, scheduler, channels, timeProvider); + } + + public void submitSync(Object channelKey, Runnable task) + throws InterruptedException { + Thread.sleep(getThrottleDelay(channelKey)); + task.run(); + } + + public void submitSync(Runnable task) throws InterruptedException { + long delay = callTime(null) - timeProvider.getCurrentTimeInMillis(); + Thread.sleep(getThrottleDelay(delay)); + task.run(); + } + + @Override + public Future submit(Runnable task) { + long delay = callTime(null) - timeProvider.getCurrentTimeInMillis(); + return scheduler.schedule(task, delay < 0 ? 0 : delay, + TimeUnit.MILLISECONDS); + } + + @Override + public Future submit(Object channelKey, Runnable task) { + return scheduler.schedule(task, getThrottleDelay(channelKey), + TimeUnit.MILLISECONDS); + } +} diff --git a/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/TimeProvider.java b/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/TimeProvider.java index 8dce4f1c6bc57..875556a866bc8 100644 --- a/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/TimeProvider.java +++ b/addons/binding/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/TimeProvider.java @@ -1,25 +1,25 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.tesla.internal.throttler; - -/** - * The {@link TimeProvider} provides time stamps - * - * @author Karel Goderis - Initial contribution - */ -public interface TimeProvider { - public static final TimeProvider SYSTEM_PROVIDER = new TimeProvider() { - @Override - public long getCurrentTimeInMillis() { - return System.currentTimeMillis(); - } - }; - - public long getCurrentTimeInMillis(); -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.tesla.internal.throttler; + +/** + * The {@link TimeProvider} provides time stamps + * + * @author Karel Goderis - Initial contribution + */ +public interface TimeProvider { + public static final TimeProvider SYSTEM_PROVIDER = new TimeProvider() { + @Override + public long getCurrentTimeInMillis() { + return System.currentTimeMillis(); + } + }; + + public long getCurrentTimeInMillis(); +} diff --git a/addons/binding/org.openhab.binding.vitotronic/.classpath b/addons/binding/org.openhab.binding.vitotronic/.classpath index 642bfb34f723f..a95e0906ca013 100644 --- a/addons/binding/org.openhab.binding.vitotronic/.classpath +++ b/addons/binding/org.openhab.binding.vitotronic/.classpath @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/addons/binding/org.openhab.binding.vitotronic/.project b/addons/binding/org.openhab.binding.vitotronic/.project index 79fb0c892923f..5c35eae6e94a4 100644 --- a/addons/binding/org.openhab.binding.vitotronic/.project +++ b/addons/binding/org.openhab.binding.vitotronic/.project @@ -1,33 +1,33 @@ - - - org.openhab.binding.vitotronic - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - org.eclipse.pde.ds.core.builder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - + + + org.openhab.binding.vitotronic + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.ds.core.builder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/addons/binding/org.openhab.binding.vitotronic/ESH-INF/binding/binding.xml b/addons/binding/org.openhab.binding.vitotronic/ESH-INF/binding/binding.xml index fea697e47a179..fb8d452dc669b 100644 --- a/addons/binding/org.openhab.binding.vitotronic/ESH-INF/binding/binding.xml +++ b/addons/binding/org.openhab.binding.vitotronic/ESH-INF/binding/binding.xml @@ -1,11 +1,11 @@ - - - - Vitotronic Binding - This is the binding for Vitotronic. - Stefan Andres - - + + + + Vitotronic Binding + This is the binding for Vitotronic. + Stefan Andres + + diff --git a/addons/binding/org.openhab.binding.vitotronic/ESH-INF/thing/bridge.xml b/addons/binding/org.openhab.binding.vitotronic/ESH-INF/thing/bridge.xml index 2c87a730e5584..606bf5a876cea 100644 --- a/addons/binding/org.openhab.binding.vitotronic/ESH-INF/thing/bridge.xml +++ b/addons/binding/org.openhab.binding.vitotronic/ESH-INF/thing/bridge.xml @@ -1,40 +1,40 @@ - - - - - - This bridge represents the Vitotronic Optolink adapter - - - - - network-address - - The IP address of the Optolink adapter - - - - network-address - - Port of the LAN gateway - 31113 - - - - The ID of the adapter. - - - - Refreshtime in seconds. - 300 - 600 - 60 - - - - + + + + + + This bridge represents the Vitotronic Optolink adapter + + + + + network-address + + The IP address of the Optolink adapter + + + + network-address + + Port of the LAN gateway + 31113 + + + + The ID of the adapter. + + + + Refreshtime in seconds. + 300 + 600 + 60 + + + + \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.vitotronic/ESH-INF/thing/thing-types.xml b/addons/binding/org.openhab.binding.vitotronic/ESH-INF/thing/thing-types.xml index f92af7a6e37f1..ed4036f580a38 100644 --- a/addons/binding/org.openhab.binding.vitotronic/ESH-INF/thing/thing-types.xml +++ b/addons/binding/org.openhab.binding.vitotronic/ESH-INF/thing/thing-types.xml @@ -1,481 +1,481 @@ - - - - - - - - - - - Vitotronic core system - - - - - - - - - - - - - - - - Pellet Fireplace, works for wood also - - - - - - - - - - - - - - - - - - - - - - - - Oil Fireplace - - - - - - - - - - - - - - - - - - - Storage Tank, stores heat in a water tank on 3 levels: bottom, middle, top=hot water - - - - - - - - - - - - - - - - Heating circuit controls the flow of heating water between the heating system and the radiators in the rooms - - - - - - - - - - - - - - - - - - - - - - Solar water heating (SWH): Convert sunlight into energy for water heating - - - - - - - - - - - - - - - - - - - Single temperature sensor - - - - - - - - - - - Single pump - - - - - - - - - - - - Single valve - - - - - - - - - - - - DateTime - - - - - - Number - - Outside temperature sensor - Temperature - - - - - Number - - Temperature sensor of boiler (fireplace) - Temperature - - - - - - Switch - - Pump state - - - - - - - - Number - - Temperature of flame - Temperature - - - - - Number - - Oxygen content of the exhaust air - - - - - Number - - Position of the primary air shutter - - - - - Number - - Position of the secondary air shutter - - - - - Number - - Power of the pellet burner - - - - - Number - - Count of starts - - - - - Number - - Fan Speed in rpm - - - - - Number - - Fan Speed in rpm - - - - - Number - - Ontime in hours - - - - - Number - - Consumed Pellets since start of heating in tons - - - - - - - Number - - Power of the oil burner - - - - - Number - - Actual power of the burner - - - - - Switch - - True, if errors for the burner exists - - - - - Number - - Ontime in hours - - - - - Number - - Ontime in hours - - - - - Number - - Consumed Oil since start of heating in Liter - - - - - - - Switch - - Circuit pump state - - - - - Number - - Temperature sensor in the middle of the storage tank - Temperature - - - - - Number - - Temperature sensor at the bottom of the storage tank - Temperature - - - - - Number - - Temperature sensor of the hot water - Temperature - - - - - - - Number - - Temperature sensor of the ciruit flow - Temperature - - - - - Switch - - Pump state - - - - - Number - - Operationmode - - - - - Switch - - Partymode on/off - - - - - Switch - - Savemode on/off - - - - - Number - - Target temperature of party mode - Temperature - - - - - Number - - Target temperature of save mode - Temperature - - - - - Number - - Target temperature of rooms - Temperature - - - - - Number - - The gradient relativ to outside temperature - - - - - Number - - The niveau relativ to outside temperature - - - - - - - - Number - - Actual temperature of the collector - Temperature - - - - - Number - - Actual temperature of the storage tank (solar sensor) - Temperature - - - - - Switch - - State of the pump (on/off) - - - - - Switch - - State of the load suppression (on/off) - - - - - - Number - - Produced heat since starting solar system - - - - - - - - Number - - Generic temperature sensor - Temperature - - - - - Number - - Value of a generic valve - - - - - + + + + + + + + + + + Vitotronic core system + + + + + + + + + + + + + + + + Pellet Fireplace, works for wood also + + + + + + + + + + + + + + + + + + + + + + + + Oil Fireplace + + + + + + + + + + + + + + + + + + + Storage Tank, stores heat in a water tank on 3 levels: bottom, middle, top=hot water + + + + + + + + + + + + + + + + Heating circuit controls the flow of heating water between the heating system and the radiators in the rooms + + + + + + + + + + + + + + + + + + + + + + Solar water heating (SWH): Convert sunlight into energy for water heating + + + + + + + + + + + + + + + + + + + Single temperature sensor + + + + + + + + + + + Single pump + + + + + + + + + + + + Single valve + + + + + + + + + + + + DateTime + + + + + + Number + + Outside temperature sensor + Temperature + + + + + Number + + Temperature sensor of boiler (fireplace) + Temperature + + + + + + Switch + + Pump state + + + + + + + + Number + + Temperature of flame + Temperature + + + + + Number + + Oxygen content of the exhaust air + + + + + Number + + Position of the primary air shutter + + + + + Number + + Position of the secondary air shutter + + + + + Number + + Power of the pellet burner + + + + + Number + + Count of starts + + + + + Number + + Fan Speed in rpm + + + + + Number + + Fan Speed in rpm + + + + + Number + + Ontime in hours + + + + + Number + + Consumed Pellets since start of heating in tons + + + + + + + Number + + Power of the oil burner + + + + + Number + + Actual power of the burner + + + + + Switch + + True, if errors for the burner exists + + + + + Number + + Ontime in hours + + + + + Number + + Ontime in hours + + + + + Number + + Consumed Oil since start of heating in Liter + + + + + + + Switch + + Circuit pump state + + + + + Number + + Temperature sensor in the middle of the storage tank + Temperature + + + + + Number + + Temperature sensor at the bottom of the storage tank + Temperature + + + + + Number + + Temperature sensor of the hot water + Temperature + + + + + + + Number + + Temperature sensor of the ciruit flow + Temperature + + + + + Switch + + Pump state + + + + + Number + + Operationmode + + + + + Switch + + Partymode on/off + + + + + Switch + + Savemode on/off + + + + + Number + + Target temperature of party mode + Temperature + + + + + Number + + Target temperature of save mode + Temperature + + + + + Number + + Target temperature of rooms + Temperature + + + + + Number + + The gradient relativ to outside temperature + + + + + Number + + The niveau relativ to outside temperature + + + + + + + + Number + + Actual temperature of the collector + Temperature + + + + + Number + + Actual temperature of the storage tank (solar sensor) + Temperature + + + + + Switch + + State of the pump (on/off) + + + + + Switch + + State of the load suppression (on/off) + + + + + + Number + + Produced heat since starting solar system + + + + + + + + Number + + Generic temperature sensor + Temperature + + + + + Number + + Value of a generic valve + + + + + diff --git a/addons/binding/org.openhab.binding.vitotronic/META-INF/MANIFEST.MF b/addons/binding/org.openhab.binding.vitotronic/META-INF/MANIFEST.MF index a1cac097f8a87..6aaa6c6b80b83 100644 --- a/addons/binding/org.openhab.binding.vitotronic/META-INF/MANIFEST.MF +++ b/addons/binding/org.openhab.binding.vitotronic/META-INF/MANIFEST.MF @@ -1,21 +1,21 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Vitotronic Binding -Bundle-SymbolicName: org.openhab.binding.vitotronic;singleton:=true -Bundle-Vendor: openHAB -Bundle-Version: 2.1.0.qualifier -Bundle-RequiredExecutionEnvironment: JavaSE-1.7 -Bundle-ClassPath: . -Import-Package: com.google.common.collect, - org.eclipse.smarthome.config.core, - org.eclipse.smarthome.core.items, - org.eclipse.smarthome.core.library.types, - org.eclipse.smarthome.core.thing, - org.eclipse.smarthome.core.thing.binding, - org.eclipse.smarthome.core.types, - org.osgi.framework, - org.slf4j -Service-Component: OSGI-INF/*.xml -Export-Package: org.openhab.binding.vitotronic, - org.openhab.binding.vitotronic.handler -Require-Bundle: org.eclipse.smarthome.config.discovery +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Vitotronic Binding +Bundle-SymbolicName: org.openhab.binding.vitotronic;singleton:=true +Bundle-Vendor: openHAB +Bundle-Version: 2.1.0.qualifier +Bundle-RequiredExecutionEnvironment: JavaSE-1.7 +Bundle-ClassPath: . +Import-Package: com.google.common.collect, + org.eclipse.smarthome.config.core, + org.eclipse.smarthome.core.items, + org.eclipse.smarthome.core.library.types, + org.eclipse.smarthome.core.thing, + org.eclipse.smarthome.core.thing.binding, + org.eclipse.smarthome.core.types, + org.osgi.framework, + org.slf4j +Service-Component: OSGI-INF/*.xml +Export-Package: org.openhab.binding.vitotronic, + org.openhab.binding.vitotronic.handler +Require-Bundle: org.eclipse.smarthome.config.discovery diff --git a/addons/binding/org.openhab.binding.vitotronic/OSGI-INF/VitotronicDiscovery.xml b/addons/binding/org.openhab.binding.vitotronic/OSGI-INF/VitotronicDiscovery.xml index 9f5c2a69f9cc3..5562d293d87ca 100644 --- a/addons/binding/org.openhab.binding.vitotronic/OSGI-INF/VitotronicDiscovery.xml +++ b/addons/binding/org.openhab.binding.vitotronic/OSGI-INF/VitotronicDiscovery.xml @@ -1,20 +1,20 @@ - - - - - - - - - - - + + + + + + + + + + + diff --git a/addons/binding/org.openhab.binding.vitotronic/OSGI-INF/VitotronicHandlerFactory.xml b/addons/binding/org.openhab.binding.vitotronic/OSGI-INF/VitotronicHandlerFactory.xml index 5fa7aafd99304..80bfc49b1f421 100644 --- a/addons/binding/org.openhab.binding.vitotronic/OSGI-INF/VitotronicHandlerFactory.xml +++ b/addons/binding/org.openhab.binding.vitotronic/OSGI-INF/VitotronicHandlerFactory.xml @@ -1,20 +1,20 @@ - - - - - - - - - - - + + + + + + + + + + + diff --git a/addons/binding/org.openhab.binding.vitotronic/README.md b/addons/binding/org.openhab.binding.vitotronic/README.md index 970d42f957659..9ae55adeff9ec 100644 --- a/addons/binding/org.openhab.binding.vitotronic/README.md +++ b/addons/binding/org.openhab.binding.vitotronic/README.md @@ -1,114 +1,114 @@ -# Vitotronic Binding - -Viessmann heating systems with Vitotronic has a optolink Interface for maintenance. -This interface can use for get/set data in the heating system. [see on openv](http://openv.wikispaces.com) - -The Vitotronic binding is a solution to bind this interface into openHAB2. -It supports the separation of the heating adaption from the integration in [openHAB2](http://www.openhab.org/). - -![Architectur](doc/architecture_vitotronic.jpg) - -The adapter transform the address oriented raw interface of the Vitotronic to a abstract format. -The adapter itself is not a part of the openhab2 binding. -[A alpha version is available here](https://github.com/steand/optolink) -[More Information about the adapter](https://github.com/steand/optolink/wiki) - -## Supported Things - -For easy using are the main things of a heating system are already define in this binding: - -* heating (Vitotronic core system) -* pelletburner (Pellet Fireplace, works for wood also) -* oilburner (Oil Fireplace) -* storagetank (Storage Tank, stores heat in a water tank on 3 levels: bottom, middle, top=hot water) -* circuit (Heating circuit controls the flow between the heating system and the radiators in the rooms) -* solar (Solar water heating (SWH): Convert sunlight into energy for water heating) - -For advanced used 3 basic things of a headingsystem define also. - -* temperaturesensor (Single temperature sensor) -* pump (Single pump) -* valve (Single valve) - -Note: The mapping of things and channels to the heating system addresses must be done in the adapter. - - -## Discovery - -The binding discovers the adapter with broadcast and put the found `vitotronic:bridge` into the inbox. For automatic detection the adapter and **openHAB** must be on the same LAN. The discovery itself must be start in the Paper-UI. -If the bridge isn't on the same LAN the bridge can also add manually. In this case the `IP-Address` and the `adapterID` is required. -Ãf the `vitotronic:bridge` added a second discovery will be start. It discovers all things, define in the adapter and put found things into the inbox. - -## Binding Configuration - -Binding itself has 4 configuration parameters: - -* ipAddress (The IP address of the Optolink adapter) -* port (Port of the LAN gateway. Default: 31113) -* adapterID (The ID/Name of the adapter) -* refreshInterval (Refresh time for data in seconds. Default: 600 seconds) - -If the adapter is automatic discovered the ipAddress, and adapterID will be set by discovery. -The rereshInterval can be set between 60 and 600 seconds. The minimal setting is dependent of the performance of the adapter. - - - -## Thing Configuration - -There is no configuration of Things necessary. Only some channels are set active by default. If this channels are defined in the adapter and will be used in **openHAB** it must set active manually. -Don't change the Thing Name. It is the reference to the name in the adapter. - -## Channels - -The follow channels are implemented: - -| Channel Type ID | Item Type | Description | -| --------------- | ------------ | ----------- | -| systemtime | DateTime | DateTime of the heating system | -| outside_temp | Number | Outside temperature sensor | -| boiler_temp | Number | Temperature sensor of boiler (fireplace) | -| flowuprating | Switch | Pump state of flow up rating | -| flame_temp | Number | Temperature of flame | -| airshutter_prim | Number | Position of the primary air shutter | -| airshutter_sec | Number | Position of the secondary air shutter | -| lambdasensor | Number | Oxygen content of the exhaust air | -| fanspeed | Number | Fan Speed in rpm | -| fanspeed_target | Number | Fan Speed in rpm | -| error | Switch | | -| starts | Number | Count of starts | -| ontime | Number | Ontime in hours | -| consumedpellets | Number | Consumed Pellets since start of heating in tons | -| power | Number | Power of the pellet burner | -| powerlevel | Number | Power of the oil burner | -| actualpower | Number | Actual power of the burner | -| ontimelevel1 | Number | Ontime in hours | -| ontimelevel2 | Number | Ontime in hours | -| consumedoil | Number | Consumed Oil since start of heating in Liter | -| hotwater_temp | Number | Temperature sensor of the hot water | -| middle_temp | Number | Temperature sensor in the middle of the storage tank | -| bottom_temp | Number | Temperature sensor at the bottom of the storage tank | -| circuitpump | Switch | Circuit pump state | -| flowtemperature | Number | Temperature sensor of the ciruit flow | -| pump | Switch | Pump state | -| operationmode | Number | Operationmode | -| savemode | Switch | Savemode on/off | -| partymode | Switch | Partymode on/off | -| party_temp | Number | Target temperature of party mode | -| room_temp | Number | Target temperature of rooms | -| save_temp | Number | Target temperature of save mode | -| gradient | Number | The gradient relativ to outside temperature | -| niveau | Number | The niveau relativ to outside temperature | -| collector_temp | Number | Actual temperature of the collector | -| storagetank_temp | Number | Actual temperature of the storage tank (solar sensor) | -| bufferload | Switch | State of the pump (on/off) | -| loadsuppression | Switch | State of the load suppression (on/off) | -| producedheat | Number | Produced heat since starting solar system | -| temperature | Number | Generic temperature sensor | -| valve | Number | Value of a generic valve | - - - -## Full Example - -t.b.d - +# Vitotronic Binding + +Viessmann heating systems with Vitotronic has a optolink Interface for maintenance. +This interface can use for get/set data in the heating system. [see on openv](http://openv.wikispaces.com) + +The Vitotronic binding is a solution to bind this interface into openHAB2. +It supports the separation of the heating adaption from the integration in [openHAB2](http://www.openhab.org/). + +![Architectur](doc/architecture_vitotronic.jpg) + +The adapter transform the address oriented raw interface of the Vitotronic to a abstract format. +The adapter itself is not a part of the openhab2 binding. +[A alpha version is available here](https://github.com/steand/optolink) +[More Information about the adapter](https://github.com/steand/optolink/wiki) + +## Supported Things + +For easy using are the main things of a heating system are already define in this binding: + +* heating (Vitotronic core system) +* pelletburner (Pellet Fireplace, works for wood also) +* oilburner (Oil Fireplace) +* storagetank (Storage Tank, stores heat in a water tank on 3 levels: bottom, middle, top=hot water) +* circuit (Heating circuit controls the flow between the heating system and the radiators in the rooms) +* solar (Solar water heating (SWH): Convert sunlight into energy for water heating) + +For advanced used 3 basic things of a headingsystem define also. + +* temperaturesensor (Single temperature sensor) +* pump (Single pump) +* valve (Single valve) + +Note: The mapping of things and channels to the heating system addresses must be done in the adapter. + + +## Discovery + +The binding discovers the adapter with broadcast and put the found `vitotronic:bridge` into the inbox. For automatic detection the adapter and **openHAB** must be on the same LAN. The discovery itself must be start in the Paper-UI. +If the bridge isn't on the same LAN the bridge can also add manually. In this case the `IP-Address` and the `adapterID` is required. +Ãf the `vitotronic:bridge` added a second discovery will be start. It discovers all things, define in the adapter and put found things into the inbox. + +## Binding Configuration + +Binding itself has 4 configuration parameters: + +* ipAddress (The IP address of the Optolink adapter) +* port (Port of the LAN gateway. Default: 31113) +* adapterID (The ID/Name of the adapter) +* refreshInterval (Refresh time for data in seconds. Default: 600 seconds) + +If the adapter is automatic discovered the ipAddress, and adapterID will be set by discovery. +The rereshInterval can be set between 60 and 600 seconds. The minimal setting is dependent of the performance of the adapter. + + + +## Thing Configuration + +There is no configuration of Things necessary. Only some channels are set active by default. If this channels are defined in the adapter and will be used in **openHAB** it must set active manually. +Don't change the Thing Name. It is the reference to the name in the adapter. + +## Channels + +The follow channels are implemented: + +| Channel Type ID | Item Type | Description | +| --------------- | ------------ | ----------- | +| systemtime | DateTime | DateTime of the heating system | +| outside_temp | Number | Outside temperature sensor | +| boiler_temp | Number | Temperature sensor of boiler (fireplace) | +| flowuprating | Switch | Pump state of flow up rating | +| flame_temp | Number | Temperature of flame | +| airshutter_prim | Number | Position of the primary air shutter | +| airshutter_sec | Number | Position of the secondary air shutter | +| lambdasensor | Number | Oxygen content of the exhaust air | +| fanspeed | Number | Fan Speed in rpm | +| fanspeed_target | Number | Fan Speed in rpm | +| error | Switch | | +| starts | Number | Count of starts | +| ontime | Number | Ontime in hours | +| consumedpellets | Number | Consumed Pellets since start of heating in tons | +| power | Number | Power of the pellet burner | +| powerlevel | Number | Power of the oil burner | +| actualpower | Number | Actual power of the burner | +| ontimelevel1 | Number | Ontime in hours | +| ontimelevel2 | Number | Ontime in hours | +| consumedoil | Number | Consumed Oil since start of heating in Liter | +| hotwater_temp | Number | Temperature sensor of the hot water | +| middle_temp | Number | Temperature sensor in the middle of the storage tank | +| bottom_temp | Number | Temperature sensor at the bottom of the storage tank | +| circuitpump | Switch | Circuit pump state | +| flowtemperature | Number | Temperature sensor of the ciruit flow | +| pump | Switch | Pump state | +| operationmode | Number | Operationmode | +| savemode | Switch | Savemode on/off | +| partymode | Switch | Partymode on/off | +| party_temp | Number | Target temperature of party mode | +| room_temp | Number | Target temperature of rooms | +| save_temp | Number | Target temperature of save mode | +| gradient | Number | The gradient relativ to outside temperature | +| niveau | Number | The niveau relativ to outside temperature | +| collector_temp | Number | Actual temperature of the collector | +| storagetank_temp | Number | Actual temperature of the storage tank (solar sensor) | +| bufferload | Switch | State of the pump (on/off) | +| loadsuppression | Switch | State of the load suppression (on/off) | +| producedheat | Number | Produced heat since starting solar system | +| temperature | Number | Generic temperature sensor | +| valve | Number | Value of a generic valve | + + + +## Full Example + +t.b.d + diff --git a/addons/binding/org.openhab.binding.vitotronic/build.properties b/addons/binding/org.openhab.binding.vitotronic/build.properties index 62eda9dddd8eb..66e21b90751a7 100644 --- a/addons/binding/org.openhab.binding.vitotronic/build.properties +++ b/addons/binding/org.openhab.binding.vitotronic/build.properties @@ -1,6 +1,6 @@ -source.. = src/main/java/ -output.. = target/classes -bin.includes = META-INF/,\ - .,\ - OSGI-INF/,\ +source.. = src/main/java/ +output.. = target/classes +bin.includes = META-INF/,\ + .,\ + OSGI-INF/,\ ESH-INF/ \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.vitotronic/pom.xml b/addons/binding/org.openhab.binding.vitotronic/pom.xml index 5cc873eda1a9d..0206708205424 100644 --- a/addons/binding/org.openhab.binding.vitotronic/pom.xml +++ b/addons/binding/org.openhab.binding.vitotronic/pom.xml @@ -1,19 +1,19 @@ - - - - 4.0.0 - - - org.openhab.binding - pom - 2.1.0-SNAPSHOT - - - org.openhab.binding - org.openhab.binding.vitotronic - 2.1.0-SNAPSHOT - - Vitotronic Binding - eclipse-plugin - + + + + 4.0.0 + + + org.openhab.binding + pom + 2.1.0-SNAPSHOT + + + org.openhab.binding + org.openhab.binding.vitotronic + 2.1.0-SNAPSHOT + + Vitotronic Binding + eclipse-plugin + \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/VitotronicBindingConfiguration.java b/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/VitotronicBindingConfiguration.java index 4a29053c443b3..d2a49c6875549 100644 --- a/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/VitotronicBindingConfiguration.java +++ b/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/VitotronicBindingConfiguration.java @@ -1,25 +1,25 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.vitotronic; - -/** - * The {@link VitotronicBindingConfiguration} class defines variables which are - * used for the binding configuration. - * - * @author Stefan Andres - Initial contribution - */ - -public class VitotronicBindingConfiguration { - - public String ipAddress; - public Integer port; - public String adapterId; - public Integer refreshInterval; - -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.vitotronic; + +/** + * The {@link VitotronicBindingConfiguration} class defines variables which are + * used for the binding configuration. + * + * @author Stefan Andres - Initial contribution + */ + +public class VitotronicBindingConfiguration { + + public String ipAddress; + public Integer port; + public String adapterId; + public Integer refreshInterval; + +} diff --git a/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/VitotronicBindingConstants.java b/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/VitotronicBindingConstants.java index a62aa084284dd..d5f750336374b 100644 --- a/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/VitotronicBindingConstants.java +++ b/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/VitotronicBindingConstants.java @@ -1,75 +1,75 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.vitotronic; - -import java.util.Set; -import org.eclipse.smarthome.core.thing.ThingTypeUID; -import com.google.common.collect.ImmutableSet; - -/** - * The {@link VitotronicBinding} class defines common constants, which are - * used across the whole binding. - * - * @author Stefan Andres - Initial contribution - */ -public class VitotronicBindingConstants { - - - public static final String BROADCAST_MESSAGE = "@@@@VITOTRONIC@@@@/"; - public static final int BROADCAST_PORT = 31113; - - public static final String BINDING_ID = "vitotronic"; - public static final String IP_ADDRESS = "ipAddress"; - public static final String PORT = "port"; - public static final String ADAPTER_ID = "adapterID"; - public static final String REFRESH_INTERVAL = "refreshInterval"; - public static final String DISCOVERY_INTERVAL = "discoveryInterval"; - - // List of main device types - - public static final String BRIDGE_VITOTRONIC = "bridge"; - - - // List of all Thing Type - public static final String THING_ID_HEATING = "heating"; - public static final String THING_ID_PELLETBURNER = "pelletburner"; - public static final String THING_ID_OILBURNER = "oilburner"; - public static final String THING_ID_STORAGETANK = "storagetank"; - public static final String THING_ID_CIRCUIT = "circuit"; - public static final String THING_ID_SOLAR = "solar"; - public static final String THING_ID_TEMPERATURESENSOR = "temperaturesensor"; - public static final String THING_ID_PUMP = "pump"; - public static final String THING_ID_VALVE = "valve"; - - - - - // List of all Thing Type UIDs - public final static ThingTypeUID THING_TYPE_UID_BRIDGE = new ThingTypeUID(BINDING_ID, BRIDGE_VITOTRONIC); - public final static ThingTypeUID THING_TYPE_UID_HEATING = new ThingTypeUID(BINDING_ID, THING_ID_HEATING); - public final static ThingTypeUID THING_TYPE_UID_PELLETBURNER = new ThingTypeUID(BINDING_ID, THING_ID_PELLETBURNER); - public final static ThingTypeUID THING_TYPE_UID_OILBURNER = new ThingTypeUID(BINDING_ID, THING_ID_OILBURNER); - public final static ThingTypeUID THING_TYPE_UID_STORAGETANK = new ThingTypeUID(BINDING_ID, THING_ID_STORAGETANK); - public final static ThingTypeUID THING_TYPE_UID_CIRCUIT = new ThingTypeUID(BINDING_ID, THING_ID_CIRCUIT); - public final static ThingTypeUID THING_TYPE_UID_SOLAR = new ThingTypeUID(BINDING_ID, THING_ID_SOLAR); - public final static ThingTypeUID THING_TYPE_UID_TEMPERATURESENSOR = new ThingTypeUID(BINDING_ID, THING_ID_TEMPERATURESENSOR); - public final static ThingTypeUID THING_TYPE_UID_PUMP = new ThingTypeUID(BINDING_ID, THING_ID_PUMP); - public final static ThingTypeUID THING_TYPE_UID_VALVE = new ThingTypeUID(BINDING_ID, THING_ID_VALVE); - - - public final static Set SUPPORTED_THING_TYPES_UIDS =ImmutableSet.of(THING_TYPE_UID_BRIDGE, - THING_TYPE_UID_HEATING, THING_TYPE_UID_PELLETBURNER, THING_TYPE_UID_OILBURNER, THING_TYPE_UID_STORAGETANK, - THING_TYPE_UID_CIRCUIT, THING_TYPE_UID_SOLAR, THING_TYPE_UID_TEMPERATURESENSOR, THING_TYPE_UID_PUMP, - THING_TYPE_UID_VALVE ); - - public final static Set SUPPORTED_BRIDGE_THING_TYPES_UIDS =ImmutableSet.of( - THING_TYPE_UID_BRIDGE); - - -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.vitotronic; + +import java.util.Set; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import com.google.common.collect.ImmutableSet; + +/** + * The {@link VitotronicBinding} class defines common constants, which are + * used across the whole binding. + * + * @author Stefan Andres - Initial contribution + */ +public class VitotronicBindingConstants { + + + public static final String BROADCAST_MESSAGE = "@@@@VITOTRONIC@@@@/"; + public static final int BROADCAST_PORT = 31113; + + public static final String BINDING_ID = "vitotronic"; + public static final String IP_ADDRESS = "ipAddress"; + public static final String PORT = "port"; + public static final String ADAPTER_ID = "adapterID"; + public static final String REFRESH_INTERVAL = "refreshInterval"; + public static final String DISCOVERY_INTERVAL = "discoveryInterval"; + + // List of main device types + + public static final String BRIDGE_VITOTRONIC = "bridge"; + + + // List of all Thing Type + public static final String THING_ID_HEATING = "heating"; + public static final String THING_ID_PELLETBURNER = "pelletburner"; + public static final String THING_ID_OILBURNER = "oilburner"; + public static final String THING_ID_STORAGETANK = "storagetank"; + public static final String THING_ID_CIRCUIT = "circuit"; + public static final String THING_ID_SOLAR = "solar"; + public static final String THING_ID_TEMPERATURESENSOR = "temperaturesensor"; + public static final String THING_ID_PUMP = "pump"; + public static final String THING_ID_VALVE = "valve"; + + + + + // List of all Thing Type UIDs + public final static ThingTypeUID THING_TYPE_UID_BRIDGE = new ThingTypeUID(BINDING_ID, BRIDGE_VITOTRONIC); + public final static ThingTypeUID THING_TYPE_UID_HEATING = new ThingTypeUID(BINDING_ID, THING_ID_HEATING); + public final static ThingTypeUID THING_TYPE_UID_PELLETBURNER = new ThingTypeUID(BINDING_ID, THING_ID_PELLETBURNER); + public final static ThingTypeUID THING_TYPE_UID_OILBURNER = new ThingTypeUID(BINDING_ID, THING_ID_OILBURNER); + public final static ThingTypeUID THING_TYPE_UID_STORAGETANK = new ThingTypeUID(BINDING_ID, THING_ID_STORAGETANK); + public final static ThingTypeUID THING_TYPE_UID_CIRCUIT = new ThingTypeUID(BINDING_ID, THING_ID_CIRCUIT); + public final static ThingTypeUID THING_TYPE_UID_SOLAR = new ThingTypeUID(BINDING_ID, THING_ID_SOLAR); + public final static ThingTypeUID THING_TYPE_UID_TEMPERATURESENSOR = new ThingTypeUID(BINDING_ID, THING_ID_TEMPERATURESENSOR); + public final static ThingTypeUID THING_TYPE_UID_PUMP = new ThingTypeUID(BINDING_ID, THING_ID_PUMP); + public final static ThingTypeUID THING_TYPE_UID_VALVE = new ThingTypeUID(BINDING_ID, THING_ID_VALVE); + + + public final static Set SUPPORTED_THING_TYPES_UIDS =ImmutableSet.of(THING_TYPE_UID_BRIDGE, + THING_TYPE_UID_HEATING, THING_TYPE_UID_PELLETBURNER, THING_TYPE_UID_OILBURNER, THING_TYPE_UID_STORAGETANK, + THING_TYPE_UID_CIRCUIT, THING_TYPE_UID_SOLAR, THING_TYPE_UID_TEMPERATURESENSOR, THING_TYPE_UID_PUMP, + THING_TYPE_UID_VALVE ); + + public final static Set SUPPORTED_BRIDGE_THING_TYPES_UIDS =ImmutableSet.of( + THING_TYPE_UID_BRIDGE); + + +} diff --git a/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/handler/VitotronicBridgeHandler.java b/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/handler/VitotronicBridgeHandler.java index 56bdb739d884a..2e52da940da62 100644 --- a/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/handler/VitotronicBridgeHandler.java +++ b/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/handler/VitotronicBridgeHandler.java @@ -1,446 +1,446 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.vitotronic.handler; - -/** - * The {@link VitotronicBridgeHandler} class handles the connection to the - * optolink adapter. - * - * @author Stefan Andres - Initial contribution - */ - -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintStream; -import java.net.Socket; -import java.net.UnknownHostException; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -import org.eclipse.smarthome.core.thing.Bridge; -import org.eclipse.smarthome.core.thing.ChannelUID; -import org.eclipse.smarthome.core.thing.ThingStatus; -import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; -import org.eclipse.smarthome.core.types.Command; -import org.openhab.binding.vitotronic.VitotronicBindingConfiguration; -import org.openhab.binding.vitotronic.internal.discovery.VitotronicDiscoveryService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.xml.sax.Attributes; -import org.xml.sax.ContentHandler; -import org.xml.sax.InputSource; -import org.xml.sax.Locator; -import org.xml.sax.SAXException; -import org.xml.sax.XMLReader; -import org.xml.sax.helpers.XMLReaderFactory; - -public class VitotronicBridgeHandler extends BaseBridgeHandler { - - private Logger logger = LoggerFactory.getLogger(VitotronicBridgeHandler.class); - - private String ipAddress; - private int port; - private int refreshInterval = 300; - private Socket socket; - private PrintStream out; - private InputStream inStream; - private boolean isConnect = false; - private boolean isDiscover = false; - - public VitotronicBridgeHandler(Bridge bridge) { - super(bridge); - } - - @Override - public void updateStatus(ThingStatus status) { - super.updateStatus(status); - updateThingHandlersStatus(status); - - } - - public void updateStatus() { - if (isConnect) { - updateStatus(ThingStatus.ONLINE); - } else { - updateStatus(ThingStatus.OFFLINE); - } - - } - - // Managing Thing Discovery Service - - private VitotronicDiscoveryService discoveryService = null; - - public void registerDiscoveryService(VitotronicDiscoveryService discoveryService) { - - if (discoveryService == null) { - throw new IllegalArgumentException("It's not allowed to pass a null ThingDiscoveryListener."); - } else { - this.discoveryService = discoveryService; - logger.trace("register Discovery Service"); - } - } - - public void unregisterDiscoveryService() { - - discoveryService = null; - logger.trace("unregister Discovery Service"); - - } - - // Handles Thing discovery - - private void createThing(String thingType, String thingID) { - logger.trace("Create thing Type='{}' id='{}'", thingType, thingID); - if (discoveryService != null) - discoveryService.addVitotronicThing(thingType, thingID); - } - - // Managing ThingHandler - - private Map thingHandlerMap = new HashMap(); - - public void registerVitotronicThingListener(VitotronicThingHandler thingHandler) { - if (thingHandler == null) { - throw new IllegalArgumentException("It's not allowed to pass a null ThingHandler."); - } else { - String thingID = thingHandler.getThing().getUID().getId(); - if (thingHandlerMap.get(thingID) == null) { - thingHandlerMap.put(thingID, thingHandler); - logger.trace("register thingHandler for thing: {}", thingID); - updateThingHandlerStatus(thingHandler, this.getStatus()); - sendSocketData("get " + thingID); - } else { - logger.trace("thingHandler for thing: '{}' allready registerd", thingID); - } - - } - } - - public void unregisterThingListener(VitotronicThingHandler thingHandler) { - if (thingHandler != null) { - String thingID = thingHandler.getThing().getUID().getId(); - if (thingHandlerMap.remove(thingID) == null) { - logger.trace("thingHandler for thing: {} not registered", thingID); - } else { - updateThingHandlerStatus(thingHandler, ThingStatus.OFFLINE); - } - } - - } - - private void updateThingHandlerStatus(VitotronicThingHandler thingHandler, ThingStatus status) { - thingHandler.updateStatus(status); - } - - private void updateThingHandlersStatus(ThingStatus status) { - for (Map.Entry entry : thingHandlerMap.entrySet()) { - updateThingHandlerStatus(entry.getValue(), status); - } - } - - // Background Runables - - private ScheduledFuture pollingJob; - - private Runnable pollingRunnable = new Runnable() { - @Override - public void run() { - logger.trace("Polling job called"); - if (!isConnect) { - startSocketReceiver(); - try { - Thread.sleep(5000); // Wait for connection . - } catch (InterruptedException e) { - } - } - if (isConnect) { - scanThings(); - refreshData(); - } - - } - - }; - - private synchronized void startAutomaticRefresh() { - if (pollingJob == null || pollingJob.isCancelled()) { - pollingJob = scheduler.scheduleAtFixedRate(pollingRunnable, 0, refreshInterval, TimeUnit.SECONDS); - } - } - - private void refreshData() { - logger.trace("Job: refresh Data..."); - String thingId; - String channelList; - for (Map.Entry entry : thingHandlerMap.entrySet()) { - channelList = entry.getValue().getActiveChannelListAsString(); - thingId = entry.getValue().getThing().getUID().getId(); - if (isConnect && (channelList.length() > 0)) { - logger.trace("Get Data for '{}'", thingId); - sendSocketData("get " + thingId + " " + channelList); - } - - } - } - - // Methods for ThingHandler - - public void scanThings() { - logger.trace("Job: Discover Things..."); - if (!isDiscover) { - sendSocketData("list"); - isDiscover = true; - } - - } - - public ThingStatus getStatus() { - return getThing().getStatus(); - } - - public void updateChannel(String thingId, String channelId, String value) { - sendSocketData("set " + thingId + ":" + channelId + " " + value); - } - - // internal Methods - - @Override - public void handleCommand(ChannelUID channelUID, Command command) { - // No channels - nothing to do - } - - @Override - public void initialize() { - logger.debug("Initializing Vitotronic bridge handler {}", this.toString()); - updateStatus(); - VitotronicBindingConfiguration configuration = getConfigAs(VitotronicBindingConfiguration.class); - ipAddress = configuration.ipAddress; - port = configuration.port; - refreshInterval = configuration.refreshInterval; - - isDiscover = false; - startAutomaticRefresh(); - } - - @Override - public void dispose() { - logger.debug("Dispose Vitottronic bridge handler{}", this.toString()); - - if (pollingJob != null && !pollingJob.isCancelled()) { - pollingJob.cancel(true); - pollingJob = null; - } - updateStatus(ThingStatus.OFFLINE); // Set all State to offline - } - - // Connection to adapter - - private void openSocket() { - logger.trace("Try to open connection to Optolink Adapter {}:{}", ipAddress, port); - - try { - socket = new Socket(ipAddress, port); - out = new PrintStream(socket.getOutputStream()); - inStream = socket.getInputStream(); - } catch (UnknownHostException e) { - logger.error("Can't find Host: {}:{}", ipAddress, port); - } catch (IOException e) { - logger.debug("Error in communication to Host: {}:{}", ipAddress, port); - logger.trace("Diagnostic: ", e); - } - } - - Runnable socketReceiverRunnable = new Runnable() { - - @Override - public void run() { - logger.trace("Start Background Thread for recieving data from adapter"); - try { - XMLReader xmlReader = XMLReaderFactory.createXMLReader(); - xmlReader.setContentHandler(new xmlHandler()); - logger.trace("Start Parser for optolink adapter"); - xmlReader.parse(new InputSource(inStream)); - - } catch (IOException e) { - logger.trace("Connection error from optolink adapter"); - } catch (SAXException e) { - logger.trace("XML Parser Error"); - - } - updateStatus(ThingStatus.OFFLINE); - isConnect = false; - try { - if (!socket.isClosed()) - socket.close(); - } catch (Exception e) { - } - logger.trace("Connection to optolink adapter is died ... wait for restart"); - } - - }; - - private void startSocketReceiver() { - - if (!isConnect) { - - openSocket(); - - Thread thread = new Thread(socketReceiverRunnable); - thread.setName("VitotronicSocketThread"); - thread.start(); - } - - } - - private void sendSocketData(String message) { - - try { - logger.trace("Send Message {}", message); - if (isConnect) - out.write((message + "\n").getBytes()); - } catch (IOException e) { - logger.error("Error in sending data to optolink addapter"); - logger.trace("Diagnostic: ", e); - } - - } - - // Handles all data what received from optolink adapter - - public class xmlHandler implements ContentHandler { - - boolean isData; - boolean isDefine; - boolean isThing; - boolean isChannel; - boolean isDescription; - String thingID; - String thingType; - String channelID; - String description; - VitotronicThingHandler thingHandler; - Set channels = new HashSet(); - - @Override - public void startElement(String uri, String localName, String pName, Attributes attr) throws SAXException { - try { - - // logger.trace("StartElement: {}", localName); - switch (localName) { - case "optolink": - isConnect = true; - updateStatus(ThingStatus.ONLINE); - break; - case "data": - isDefine = false; - break; - case "define": - isDefine = true; - break; - case "description": - isDescription = true; - ; - break; - case "thing": - isThing = true; - if (isDefine) - thingType = attr.getValue("type"); - thingID = attr.getValue("id"); - channels.clear(); - thingHandler = thingHandlerMap.get(thingID); - break; - case "channel": - isChannel = true; - channelID = attr.getValue("id"); - if (isDefine) { - channels.add(channelID); - } else { // is data - if (thingHandler != null) { - logger.trace("Set Data for channel '{}' value '{}'", channelID, attr.getValue("value")); - thingHandler.setChannelValue(channelID, attr.getValue("value")); - } - } - break; - } - } catch (Exception e) { - logger.error("Error in parsing data"); - logger.trace("Diagnostic: ", e); - } - - } - - @Override - public void characters(char[] ch, int start, int length) throws SAXException { - if (isDescription) { - description = new String(ch, start, length); - } - } - - @Override - public void endElement(String uri, String localName, String qName) throws SAXException { - // logger.trace("StartElement: {}", localName); - switch (localName) { - case "description": - isDescription = false; - ; - break; - case "thing": - if (isDefine) - createThing(thingType, thingID); - isThing = false; - thingHandler = null; - break; - case "channel": - isChannel = false; - break; - } - - } - - // Unused function of xmlReader - @Override - public void endDocument() throws SAXException { - } - - @Override - public void ignorableWhitespace(char[] arg0, int arg1, int arg2) throws SAXException { - } - - @Override - public void processingInstruction(String arg0, String arg1) throws SAXException { - } - - @Override - public void setDocumentLocator(Locator arg0) { - } - - @Override - public void skippedEntity(String arg0) throws SAXException { - } - - @Override - public void startDocument() throws SAXException { - } - - @Override - public void startPrefixMapping(String arg0, String arg1) throws SAXException { - } - - @Override - public void endPrefixMapping(String prefix) throws SAXException { - } - - } - -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.vitotronic.handler; + +/** + * The {@link VitotronicBridgeHandler} class handles the connection to the + * optolink adapter. + * + * @author Stefan Andres - Initial contribution + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; +import java.net.Socket; +import java.net.UnknownHostException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; +import org.eclipse.smarthome.core.types.Command; +import org.openhab.binding.vitotronic.VitotronicBindingConfiguration; +import org.openhab.binding.vitotronic.internal.discovery.VitotronicDiscoveryService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + +public class VitotronicBridgeHandler extends BaseBridgeHandler { + + private Logger logger = LoggerFactory.getLogger(VitotronicBridgeHandler.class); + + private String ipAddress; + private int port; + private int refreshInterval = 300; + private Socket socket; + private PrintStream out; + private InputStream inStream; + private boolean isConnect = false; + private boolean isDiscover = false; + + public VitotronicBridgeHandler(Bridge bridge) { + super(bridge); + } + + @Override + public void updateStatus(ThingStatus status) { + super.updateStatus(status); + updateThingHandlersStatus(status); + + } + + public void updateStatus() { + if (isConnect) { + updateStatus(ThingStatus.ONLINE); + } else { + updateStatus(ThingStatus.OFFLINE); + } + + } + + // Managing Thing Discovery Service + + private VitotronicDiscoveryService discoveryService = null; + + public void registerDiscoveryService(VitotronicDiscoveryService discoveryService) { + + if (discoveryService == null) { + throw new IllegalArgumentException("It's not allowed to pass a null ThingDiscoveryListener."); + } else { + this.discoveryService = discoveryService; + logger.trace("register Discovery Service"); + } + } + + public void unregisterDiscoveryService() { + + discoveryService = null; + logger.trace("unregister Discovery Service"); + + } + + // Handles Thing discovery + + private void createThing(String thingType, String thingID) { + logger.trace("Create thing Type='{}' id='{}'", thingType, thingID); + if (discoveryService != null) + discoveryService.addVitotronicThing(thingType, thingID); + } + + // Managing ThingHandler + + private Map thingHandlerMap = new HashMap(); + + public void registerVitotronicThingListener(VitotronicThingHandler thingHandler) { + if (thingHandler == null) { + throw new IllegalArgumentException("It's not allowed to pass a null ThingHandler."); + } else { + String thingID = thingHandler.getThing().getUID().getId(); + if (thingHandlerMap.get(thingID) == null) { + thingHandlerMap.put(thingID, thingHandler); + logger.trace("register thingHandler for thing: {}", thingID); + updateThingHandlerStatus(thingHandler, this.getStatus()); + sendSocketData("get " + thingID); + } else { + logger.trace("thingHandler for thing: '{}' allready registerd", thingID); + } + + } + } + + public void unregisterThingListener(VitotronicThingHandler thingHandler) { + if (thingHandler != null) { + String thingID = thingHandler.getThing().getUID().getId(); + if (thingHandlerMap.remove(thingID) == null) { + logger.trace("thingHandler for thing: {} not registered", thingID); + } else { + updateThingHandlerStatus(thingHandler, ThingStatus.OFFLINE); + } + } + + } + + private void updateThingHandlerStatus(VitotronicThingHandler thingHandler, ThingStatus status) { + thingHandler.updateStatus(status); + } + + private void updateThingHandlersStatus(ThingStatus status) { + for (Map.Entry entry : thingHandlerMap.entrySet()) { + updateThingHandlerStatus(entry.getValue(), status); + } + } + + // Background Runables + + private ScheduledFuture pollingJob; + + private Runnable pollingRunnable = new Runnable() { + @Override + public void run() { + logger.trace("Polling job called"); + if (!isConnect) { + startSocketReceiver(); + try { + Thread.sleep(5000); // Wait for connection . + } catch (InterruptedException e) { + } + } + if (isConnect) { + scanThings(); + refreshData(); + } + + } + + }; + + private synchronized void startAutomaticRefresh() { + if (pollingJob == null || pollingJob.isCancelled()) { + pollingJob = scheduler.scheduleAtFixedRate(pollingRunnable, 0, refreshInterval, TimeUnit.SECONDS); + } + } + + private void refreshData() { + logger.trace("Job: refresh Data..."); + String thingId; + String channelList; + for (Map.Entry entry : thingHandlerMap.entrySet()) { + channelList = entry.getValue().getActiveChannelListAsString(); + thingId = entry.getValue().getThing().getUID().getId(); + if (isConnect && (channelList.length() > 0)) { + logger.trace("Get Data for '{}'", thingId); + sendSocketData("get " + thingId + " " + channelList); + } + + } + } + + // Methods for ThingHandler + + public void scanThings() { + logger.trace("Job: Discover Things..."); + if (!isDiscover) { + sendSocketData("list"); + isDiscover = true; + } + + } + + public ThingStatus getStatus() { + return getThing().getStatus(); + } + + public void updateChannel(String thingId, String channelId, String value) { + sendSocketData("set " + thingId + ":" + channelId + " " + value); + } + + // internal Methods + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + // No channels - nothing to do + } + + @Override + public void initialize() { + logger.debug("Initializing Vitotronic bridge handler {}", this.toString()); + updateStatus(); + VitotronicBindingConfiguration configuration = getConfigAs(VitotronicBindingConfiguration.class); + ipAddress = configuration.ipAddress; + port = configuration.port; + refreshInterval = configuration.refreshInterval; + + isDiscover = false; + startAutomaticRefresh(); + } + + @Override + public void dispose() { + logger.debug("Dispose Vitottronic bridge handler{}", this.toString()); + + if (pollingJob != null && !pollingJob.isCancelled()) { + pollingJob.cancel(true); + pollingJob = null; + } + updateStatus(ThingStatus.OFFLINE); // Set all State to offline + } + + // Connection to adapter + + private void openSocket() { + logger.trace("Try to open connection to Optolink Adapter {}:{}", ipAddress, port); + + try { + socket = new Socket(ipAddress, port); + out = new PrintStream(socket.getOutputStream()); + inStream = socket.getInputStream(); + } catch (UnknownHostException e) { + logger.error("Can't find Host: {}:{}", ipAddress, port); + } catch (IOException e) { + logger.debug("Error in communication to Host: {}:{}", ipAddress, port); + logger.trace("Diagnostic: ", e); + } + } + + Runnable socketReceiverRunnable = new Runnable() { + + @Override + public void run() { + logger.trace("Start Background Thread for recieving data from adapter"); + try { + XMLReader xmlReader = XMLReaderFactory.createXMLReader(); + xmlReader.setContentHandler(new xmlHandler()); + logger.trace("Start Parser for optolink adapter"); + xmlReader.parse(new InputSource(inStream)); + + } catch (IOException e) { + logger.trace("Connection error from optolink adapter"); + } catch (SAXException e) { + logger.trace("XML Parser Error"); + + } + updateStatus(ThingStatus.OFFLINE); + isConnect = false; + try { + if (!socket.isClosed()) + socket.close(); + } catch (Exception e) { + } + logger.trace("Connection to optolink adapter is died ... wait for restart"); + } + + }; + + private void startSocketReceiver() { + + if (!isConnect) { + + openSocket(); + + Thread thread = new Thread(socketReceiverRunnable); + thread.setName("VitotronicSocketThread"); + thread.start(); + } + + } + + private void sendSocketData(String message) { + + try { + logger.trace("Send Message {}", message); + if (isConnect) + out.write((message + "\n").getBytes()); + } catch (IOException e) { + logger.error("Error in sending data to optolink addapter"); + logger.trace("Diagnostic: ", e); + } + + } + + // Handles all data what received from optolink adapter + + public class xmlHandler implements ContentHandler { + + boolean isData; + boolean isDefine; + boolean isThing; + boolean isChannel; + boolean isDescription; + String thingID; + String thingType; + String channelID; + String description; + VitotronicThingHandler thingHandler; + Set channels = new HashSet(); + + @Override + public void startElement(String uri, String localName, String pName, Attributes attr) throws SAXException { + try { + + // logger.trace("StartElement: {}", localName); + switch (localName) { + case "optolink": + isConnect = true; + updateStatus(ThingStatus.ONLINE); + break; + case "data": + isDefine = false; + break; + case "define": + isDefine = true; + break; + case "description": + isDescription = true; + ; + break; + case "thing": + isThing = true; + if (isDefine) + thingType = attr.getValue("type"); + thingID = attr.getValue("id"); + channels.clear(); + thingHandler = thingHandlerMap.get(thingID); + break; + case "channel": + isChannel = true; + channelID = attr.getValue("id"); + if (isDefine) { + channels.add(channelID); + } else { // is data + if (thingHandler != null) { + logger.trace("Set Data for channel '{}' value '{}'", channelID, attr.getValue("value")); + thingHandler.setChannelValue(channelID, attr.getValue("value")); + } + } + break; + } + } catch (Exception e) { + logger.error("Error in parsing data"); + logger.trace("Diagnostic: ", e); + } + + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + if (isDescription) { + description = new String(ch, start, length); + } + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + // logger.trace("StartElement: {}", localName); + switch (localName) { + case "description": + isDescription = false; + ; + break; + case "thing": + if (isDefine) + createThing(thingType, thingID); + isThing = false; + thingHandler = null; + break; + case "channel": + isChannel = false; + break; + } + + } + + // Unused function of xmlReader + @Override + public void endDocument() throws SAXException { + } + + @Override + public void ignorableWhitespace(char[] arg0, int arg1, int arg2) throws SAXException { + } + + @Override + public void processingInstruction(String arg0, String arg1) throws SAXException { + } + + @Override + public void setDocumentLocator(Locator arg0) { + } + + @Override + public void skippedEntity(String arg0) throws SAXException { + } + + @Override + public void startDocument() throws SAXException { + } + + @Override + public void startPrefixMapping(String arg0, String arg1) throws SAXException { + } + + @Override + public void endPrefixMapping(String prefix) throws SAXException { + } + + } + +} diff --git a/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/handler/VitotronicThingHandler.java b/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/handler/VitotronicThingHandler.java index b4bf9de7b53d5..70155d39a0049 100644 --- a/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/handler/VitotronicThingHandler.java +++ b/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/handler/VitotronicThingHandler.java @@ -1,150 +1,150 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.vitotronic.handler; - -import org.eclipse.smarthome.core.library.types.DateTimeType; -import org.eclipse.smarthome.core.library.types.DecimalType; -import org.eclipse.smarthome.core.library.types.OnOffType; -import org.eclipse.smarthome.core.thing.Bridge; -import org.eclipse.smarthome.core.thing.Channel; -import org.eclipse.smarthome.core.thing.ChannelUID; -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingStatus; -import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; -import org.eclipse.smarthome.core.thing.binding.ThingHandler; -import org.eclipse.smarthome.core.types.Command; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link VitotronicHandler} is responsible for handling commands, which are - * sent to one of the channels. - * - * @author Stefan Andres - Initial contribution - */ - -public class VitotronicThingHandler extends BaseThingHandler { - - private Logger logger = LoggerFactory.getLogger(VitotronicThingHandler.class); - - VitotronicBridgeHandler bridgeHandler; - - public VitotronicThingHandler(Thing thing) { - super(thing); - } - - @Override - public void initialize() { - bridgeHandler = getBridgeHandler(); - logger.debug("Thing Handler for {} started", getThing().getUID().getId()); - registerVitotronicThingListener(bridgeHandler); - } - - @Override - public void dispose() { - logger.debug("Thing Handler for {} stop", getThing().getUID().getId()); - unregisterVitotronicThingListener(bridgeHandler); - } - - @Override - public void handleCommand(ChannelUID channelUID, Command command) { - logger.trace("Handle command for channel '{}' command '{}'", channelUID.getId(), command.toString()); - bridgeHandler.updateChannel(getThing().getUID().getId(), channelUID.getId(), command.toString()); - - } - - @Override - public void updateStatus(ThingStatus status) { - super.updateStatus(status); - } - - private synchronized VitotronicBridgeHandler getBridgeHandler() { - - Bridge bridge = getBridge(); - if (bridge == null) { - logger.debug("Required bridge not defined for device {}."); - return null; - } else { - return getBridgeHandler(bridge); - } - - } - - private synchronized VitotronicBridgeHandler getBridgeHandler(Bridge bridge) { - - VitotronicBridgeHandler bridgeHandler = null; - - ThingHandler handler = bridge.getHandler(); - if (handler instanceof VitotronicBridgeHandler) { - bridgeHandler = (VitotronicBridgeHandler) handler; - } else { - logger.debug("No available bridge handler found yet. Bridge: {} .", bridge.getUID()); - bridgeHandler = null; - } - return bridgeHandler; - } - - private void registerVitotronicThingListener(VitotronicBridgeHandler bridgeHandler) { - if (bridgeHandler != null) { - bridgeHandler.registerVitotronicThingListener(this); - } else { - logger.debug("Can't register {} at bridge bridgeHandler is null.", this.getThing().getUID()); - } - } - - private void unregisterVitotronicThingListener(VitotronicBridgeHandler bridgeHandler) { - if (bridgeHandler != null) { - bridgeHandler.unregisterThingListener(this); - } else { - logger.debug("Can't unregister {} at bridge bridgeHandler is null.", this.getThing().getUID()); - } - - } - - public void setChannelValue(String channelId, String value) { - Channel channel = getThing().getChannel(channelId); - if (channel == null) { - logger.trace("Cannel '{}:{}' not implemented", getThing().getUID().getId(), channelId); - return; - } - - logger.trace("Set {}:{}:{} = {}", getThing().getUID().getId(), channelId, channel.getAcceptedItemType(), value); - switch (channel.getAcceptedItemType()) { - case "Number": - this.updateState(channelId, new DecimalType(value)); - break; - case "Switch": - if (value.toUpperCase().contains("ON")) { - this.updateState(channelId, OnOffType.ON); - } else { - this.updateState(channelId, OnOffType.OFF); - } - break; - case "DateTime": - this.updateState(channelId, new DateTimeType(value)); - break; - default: - logger.trace("Type '{}' for channel '{}' not implemented", channel.getAcceptedItemType(), channelId); - } - } - - public String getActiveChannelListAsString() { - String channelList = ""; - for (Channel channel : getThing().getChannels()) { - if (isLinked(channel.getUID().getId())) { - if (channelList.length() > 0) { - channelList = channelList + "," + channel.getUID().getId(); - } else { - channelList = channel.getUID().getId(); - } - } - } - return channelList; - } -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.vitotronic.handler; + +import org.eclipse.smarthome.core.library.types.DateTimeType; +import org.eclipse.smarthome.core.library.types.DecimalType; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.Channel; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.types.Command; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link VitotronicHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Stefan Andres - Initial contribution + */ + +public class VitotronicThingHandler extends BaseThingHandler { + + private Logger logger = LoggerFactory.getLogger(VitotronicThingHandler.class); + + VitotronicBridgeHandler bridgeHandler; + + public VitotronicThingHandler(Thing thing) { + super(thing); + } + + @Override + public void initialize() { + bridgeHandler = getBridgeHandler(); + logger.debug("Thing Handler for {} started", getThing().getUID().getId()); + registerVitotronicThingListener(bridgeHandler); + } + + @Override + public void dispose() { + logger.debug("Thing Handler for {} stop", getThing().getUID().getId()); + unregisterVitotronicThingListener(bridgeHandler); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + logger.trace("Handle command for channel '{}' command '{}'", channelUID.getId(), command.toString()); + bridgeHandler.updateChannel(getThing().getUID().getId(), channelUID.getId(), command.toString()); + + } + + @Override + public void updateStatus(ThingStatus status) { + super.updateStatus(status); + } + + private synchronized VitotronicBridgeHandler getBridgeHandler() { + + Bridge bridge = getBridge(); + if (bridge == null) { + logger.debug("Required bridge not defined for device {}."); + return null; + } else { + return getBridgeHandler(bridge); + } + + } + + private synchronized VitotronicBridgeHandler getBridgeHandler(Bridge bridge) { + + VitotronicBridgeHandler bridgeHandler = null; + + ThingHandler handler = bridge.getHandler(); + if (handler instanceof VitotronicBridgeHandler) { + bridgeHandler = (VitotronicBridgeHandler) handler; + } else { + logger.debug("No available bridge handler found yet. Bridge: {} .", bridge.getUID()); + bridgeHandler = null; + } + return bridgeHandler; + } + + private void registerVitotronicThingListener(VitotronicBridgeHandler bridgeHandler) { + if (bridgeHandler != null) { + bridgeHandler.registerVitotronicThingListener(this); + } else { + logger.debug("Can't register {} at bridge bridgeHandler is null.", this.getThing().getUID()); + } + } + + private void unregisterVitotronicThingListener(VitotronicBridgeHandler bridgeHandler) { + if (bridgeHandler != null) { + bridgeHandler.unregisterThingListener(this); + } else { + logger.debug("Can't unregister {} at bridge bridgeHandler is null.", this.getThing().getUID()); + } + + } + + public void setChannelValue(String channelId, String value) { + Channel channel = getThing().getChannel(channelId); + if (channel == null) { + logger.trace("Cannel '{}:{}' not implemented", getThing().getUID().getId(), channelId); + return; + } + + logger.trace("Set {}:{}:{} = {}", getThing().getUID().getId(), channelId, channel.getAcceptedItemType(), value); + switch (channel.getAcceptedItemType()) { + case "Number": + this.updateState(channelId, new DecimalType(value)); + break; + case "Switch": + if (value.toUpperCase().contains("ON")) { + this.updateState(channelId, OnOffType.ON); + } else { + this.updateState(channelId, OnOffType.OFF); + } + break; + case "DateTime": + this.updateState(channelId, new DateTimeType(value)); + break; + default: + logger.trace("Type '{}' for channel '{}' not implemented", channel.getAcceptedItemType(), channelId); + } + } + + public String getActiveChannelListAsString() { + String channelList = ""; + for (Channel channel : getThing().getChannels()) { + if (isLinked(channel.getUID().getId())) { + if (channelList.length() > 0) { + channelList = channelList + "," + channel.getUID().getId(); + } else { + channelList = channel.getUID().getId(); + } + } + } + return channelList; + } +} diff --git a/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/internal/VitotronicHandlerFactory.java b/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/internal/VitotronicHandlerFactory.java index 644db94d6236a..7665c67fc0e8c 100644 --- a/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/internal/VitotronicHandlerFactory.java +++ b/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/internal/VitotronicHandlerFactory.java @@ -1,100 +1,100 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.vitotronic.internal; - -import java.util.Hashtable; -import org.openhab.binding.vitotronic.VitotronicBindingConstants; -import org.openhab.binding.vitotronic.handler.VitotronicBridgeHandler; -import org.openhab.binding.vitotronic.handler.VitotronicThingHandler; -import org.openhab.binding.vitotronic.internal.discovery.VitotronicDiscoveryService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.eclipse.smarthome.config.core.Configuration; -import org.eclipse.smarthome.config.discovery.DiscoveryService; -import org.eclipse.smarthome.core.thing.Bridge; -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingTypeUID; -import org.eclipse.smarthome.core.thing.ThingUID; -import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; -import org.eclipse.smarthome.core.thing.binding.ThingHandler; - -/** - * The {@link VitotronicHandlerFactory} is responsible for creating things and thing - * handlers. - * - * @author Stefan Andres - Initial contribution - */ -public class VitotronicHandlerFactory extends BaseThingHandlerFactory { - - private Logger logger = LoggerFactory.getLogger(VitotronicHandlerFactory.class); - - - @Override - public boolean supportsThingType(ThingTypeUID thingTypeUID) { - logger.trace("Ask Handler for Suported Thing {}", VitotronicBindingConstants.SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)); - return VitotronicBindingConstants.SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); - } - - @Override - protected ThingHandler createHandler(Thing thing) { - logger.trace("Install Handler for Thing {}", thing.toString()); - - - ThingTypeUID thingTypeUID = thing.getThingTypeUID(); - - if (thingTypeUID.equals(VitotronicBindingConstants.THING_TYPE_UID_BRIDGE)) { - VitotronicBridgeHandler handler = new VitotronicBridgeHandler((Bridge) thing); - registerThingDiscovery(handler); - return handler; - } - - if (supportsThingType(thingTypeUID)) { - return new VitotronicThingHandler(thing); - } - - - return null; - } - - - private synchronized void registerThingDiscovery(VitotronicBridgeHandler bridgeHandler) { - VitotronicDiscoveryService discoveryService = new VitotronicDiscoveryService(bridgeHandler); - logger.trace("Try to register Discovery service on BundleID: {} Service: {}", - bundleContext.getBundle().getBundleId(), - DiscoveryService.class.getName()); - - Hashtable prop = new Hashtable(); - - bundleContext.registerService(DiscoveryService.class.getName(), discoveryService, prop); - discoveryService.activate(); - } - - - @Override - public Thing createThing(ThingTypeUID thingTypeUID, Configuration configuration, ThingUID thingUID, - ThingUID bridgeUID) { - logger.trace("Create Thing for Type {}", thingUID.toString()); - - String adapterID = (String) configuration.get(VitotronicBindingConstants.ADAPTER_ID); - - if ( VitotronicBindingConstants.THING_TYPE_UID_BRIDGE.equals(thingTypeUID)) { - - logger.trace("Create Bride: {}", adapterID); - return super.createThing(thingTypeUID, configuration, thingUID, null); - } else { - if (supportsThingType(thingTypeUID)) { - logger.trace("Create Thing: {}", adapterID); - return super.createThing(thingTypeUID, configuration, thingUID, bridgeUID); - } - } - - throw new IllegalArgumentException("The thing type " + thingTypeUID + " is not supported by the binding."); - } -} - +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.vitotronic.internal; + +import java.util.Hashtable; +import org.openhab.binding.vitotronic.VitotronicBindingConstants; +import org.openhab.binding.vitotronic.handler.VitotronicBridgeHandler; +import org.openhab.binding.vitotronic.handler.VitotronicThingHandler; +import org.openhab.binding.vitotronic.internal.discovery.VitotronicDiscoveryService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.eclipse.smarthome.config.core.Configuration; +import org.eclipse.smarthome.config.discovery.DiscoveryService; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; + +/** + * The {@link VitotronicHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Stefan Andres - Initial contribution + */ +public class VitotronicHandlerFactory extends BaseThingHandlerFactory { + + private Logger logger = LoggerFactory.getLogger(VitotronicHandlerFactory.class); + + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + logger.trace("Ask Handler for Suported Thing {}", VitotronicBindingConstants.SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)); + return VitotronicBindingConstants.SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Override + protected ThingHandler createHandler(Thing thing) { + logger.trace("Install Handler for Thing {}", thing.toString()); + + + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (thingTypeUID.equals(VitotronicBindingConstants.THING_TYPE_UID_BRIDGE)) { + VitotronicBridgeHandler handler = new VitotronicBridgeHandler((Bridge) thing); + registerThingDiscovery(handler); + return handler; + } + + if (supportsThingType(thingTypeUID)) { + return new VitotronicThingHandler(thing); + } + + + return null; + } + + + private synchronized void registerThingDiscovery(VitotronicBridgeHandler bridgeHandler) { + VitotronicDiscoveryService discoveryService = new VitotronicDiscoveryService(bridgeHandler); + logger.trace("Try to register Discovery service on BundleID: {} Service: {}", + bundleContext.getBundle().getBundleId(), + DiscoveryService.class.getName()); + + Hashtable prop = new Hashtable(); + + bundleContext.registerService(DiscoveryService.class.getName(), discoveryService, prop); + discoveryService.activate(); + } + + + @Override + public Thing createThing(ThingTypeUID thingTypeUID, Configuration configuration, ThingUID thingUID, + ThingUID bridgeUID) { + logger.trace("Create Thing for Type {}", thingUID.toString()); + + String adapterID = (String) configuration.get(VitotronicBindingConstants.ADAPTER_ID); + + if ( VitotronicBindingConstants.THING_TYPE_UID_BRIDGE.equals(thingTypeUID)) { + + logger.trace("Create Bride: {}", adapterID); + return super.createThing(thingTypeUID, configuration, thingUID, null); + } else { + if (supportsThingType(thingTypeUID)) { + logger.trace("Create Thing: {}", adapterID); + return super.createThing(thingTypeUID, configuration, thingUID, bridgeUID); + } + } + + throw new IllegalArgumentException("The thing type " + thingTypeUID + " is not supported by the binding."); + } +} + diff --git a/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/internal/discovery/VitotronicBridgeDiscovery.java b/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/internal/discovery/VitotronicBridgeDiscovery.java index e6787f063f687..a2dc2cd41562c 100644 --- a/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/internal/discovery/VitotronicBridgeDiscovery.java +++ b/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/internal/discovery/VitotronicBridgeDiscovery.java @@ -1,123 +1,123 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.vitotronic.internal.discovery; -/** - * The {@link VitotronicBridgeDiscovery} class handles the discovery of optolink adapter - * with broadcasting and put it to inbox, if found. - * - * - * @author Stefan Andres - Initial contribution - */ -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.InetAddress; -import java.util.HashMap; -import java.util.Map; -import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService; -import org.eclipse.smarthome.config.discovery.DiscoveryResult; -import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; -import org.eclipse.smarthome.core.thing.ThingUID; -import org.openhab.binding.vitotronic.VitotronicBindingConstants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class VitotronicBridgeDiscovery extends AbstractDiscoveryService { - - int adapterPort = 31113; - - private final static Logger logger = LoggerFactory.getLogger(VitotronicBridgeDiscovery.class); - - public VitotronicBridgeDiscovery() throws IllegalArgumentException { - super(VitotronicBindingConstants.SUPPORTED_BRIDGE_THING_TYPES_UIDS, 15, false); - } - - @Override - protected void startScan() { - logger.trace("Start discovery of Vitotronic Optolink Adapter (VOP)"); - adapterPort = VitotronicBindingConstants.BROADCAST_PORT; - scheduler.execute(searchRunnable); - } - - - // Runnable for search adapter - - private Runnable searchRunnable = new Runnable() { - - public void run() { - logger.trace("Start adapter discovery "); - logger.debug("Send broadcast message"); - DatagramSocket localSocket = null; - try { - localSocket = new DatagramSocket(); - localSocket.setBroadcast(true); - localSocket.setSoTimeout(10000); // Listen 10 seconds - - String broadcastMsg = VitotronicBindingConstants.BROADCAST_MESSAGE + "*"; - byte[] sendData = broadcastMsg.getBytes(); - - DatagramPacket sendPacket = new DatagramPacket(sendData, - sendData.length, - InetAddress.getByName("255.255.255.255"), adapterPort); - localSocket.send(sendPacket); - - byte[] receiveBuffer = new byte[255]; - - // Listen for answer - - DatagramPacket receivePacket = new DatagramPacket( - receiveBuffer, receiveBuffer.length); - localSocket.receive(receivePacket); - String receiveMessage = new String(receivePacket.getData()).trim(); - String receiveIP = receivePacket.getAddress().getHostAddress(); - int receivePort = receivePacket.getPort(); - logger.debug("Received Message: {} ", receiveMessage); - logger.debug("Received from Host: {}", receiveIP); - logger.debug("Received from Port: {}", receivePort); - - if (receiveMessage.startsWith(VitotronicBindingConstants.BROADCAST_MESSAGE)) { - - // register bridge - - String adapterID = receiveMessage.substring(VitotronicBindingConstants.BROADCAST_MESSAGE. - length()).toUpperCase(); - - addAdapter(receiveIP, receivePort, adapterID); - } - } catch (Exception e) { - logger.debug("No optolink adapter found!"); - } finally { - try { - if (localSocket != null) - localSocket.close(); - } catch (Exception e) { - // Ignore - } - } - } - - }; - - - private void addAdapter(String remoteIP, int remotePort, String adapterID) { - - Map properties = new HashMap<>(3); - properties.put(VitotronicBindingConstants.IP_ADDRESS, remoteIP); - properties.put(VitotronicBindingConstants.PORT, remotePort); - properties.put(VitotronicBindingConstants.ADAPTER_ID, adapterID); - - ThingUID uid = new ThingUID(VitotronicBindingConstants.THING_TYPE_UID_BRIDGE , adapterID ); - if (uid != null) { - DiscoveryResult result = DiscoveryResultBuilder.create(uid).withProperties(properties) - .withLabel(adapterID).build(); - thingDiscovered(result); - } - } - - -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.vitotronic.internal.discovery; +/** + * The {@link VitotronicBridgeDiscovery} class handles the discovery of optolink adapter + * with broadcasting and put it to inbox, if found. + * + * + * @author Stefan Andres - Initial contribution + */ +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.util.HashMap; +import java.util.Map; +import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService; +import org.eclipse.smarthome.config.discovery.DiscoveryResult; +import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.openhab.binding.vitotronic.VitotronicBindingConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class VitotronicBridgeDiscovery extends AbstractDiscoveryService { + + int adapterPort = 31113; + + private final static Logger logger = LoggerFactory.getLogger(VitotronicBridgeDiscovery.class); + + public VitotronicBridgeDiscovery() throws IllegalArgumentException { + super(VitotronicBindingConstants.SUPPORTED_BRIDGE_THING_TYPES_UIDS, 15, false); + } + + @Override + protected void startScan() { + logger.trace("Start discovery of Vitotronic Optolink Adapter (VOP)"); + adapterPort = VitotronicBindingConstants.BROADCAST_PORT; + scheduler.execute(searchRunnable); + } + + + // Runnable for search adapter + + private Runnable searchRunnable = new Runnable() { + + public void run() { + logger.trace("Start adapter discovery "); + logger.debug("Send broadcast message"); + DatagramSocket localSocket = null; + try { + localSocket = new DatagramSocket(); + localSocket.setBroadcast(true); + localSocket.setSoTimeout(10000); // Listen 10 seconds + + String broadcastMsg = VitotronicBindingConstants.BROADCAST_MESSAGE + "*"; + byte[] sendData = broadcastMsg.getBytes(); + + DatagramPacket sendPacket = new DatagramPacket(sendData, + sendData.length, + InetAddress.getByName("255.255.255.255"), adapterPort); + localSocket.send(sendPacket); + + byte[] receiveBuffer = new byte[255]; + + // Listen for answer + + DatagramPacket receivePacket = new DatagramPacket( + receiveBuffer, receiveBuffer.length); + localSocket.receive(receivePacket); + String receiveMessage = new String(receivePacket.getData()).trim(); + String receiveIP = receivePacket.getAddress().getHostAddress(); + int receivePort = receivePacket.getPort(); + logger.debug("Received Message: {} ", receiveMessage); + logger.debug("Received from Host: {}", receiveIP); + logger.debug("Received from Port: {}", receivePort); + + if (receiveMessage.startsWith(VitotronicBindingConstants.BROADCAST_MESSAGE)) { + + // register bridge + + String adapterID = receiveMessage.substring(VitotronicBindingConstants.BROADCAST_MESSAGE. + length()).toUpperCase(); + + addAdapter(receiveIP, receivePort, adapterID); + } + } catch (Exception e) { + logger.debug("No optolink adapter found!"); + } finally { + try { + if (localSocket != null) + localSocket.close(); + } catch (Exception e) { + // Ignore + } + } + } + + }; + + + private void addAdapter(String remoteIP, int remotePort, String adapterID) { + + Map properties = new HashMap<>(3); + properties.put(VitotronicBindingConstants.IP_ADDRESS, remoteIP); + properties.put(VitotronicBindingConstants.PORT, remotePort); + properties.put(VitotronicBindingConstants.ADAPTER_ID, adapterID); + + ThingUID uid = new ThingUID(VitotronicBindingConstants.THING_TYPE_UID_BRIDGE , adapterID ); + if (uid != null) { + DiscoveryResult result = DiscoveryResultBuilder.create(uid).withProperties(properties) + .withLabel(adapterID).build(); + thingDiscovered(result); + } + } + + +} diff --git a/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/internal/discovery/VitotronicDiscoveryService.java b/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/internal/discovery/VitotronicDiscoveryService.java index 3c892c74e5e05..36e2c2d2a3568 100644 --- a/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/internal/discovery/VitotronicDiscoveryService.java +++ b/addons/binding/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/internal/discovery/VitotronicDiscoveryService.java @@ -1,103 +1,103 @@ -/** - * Copyright (c) 2014-2016 by the respective copyright holders. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.binding.vitotronic.internal.discovery; - -/** - * The {@link VitotronicBridgeDiscovery} class handles the discovery of things. - * with broadcasting and put it to inbox, if found. - * - * - * @author Stefan Andres - Initial contribution - */ - -import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService; -import org.eclipse.smarthome.config.discovery.DiscoveryResult; -import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; -import org.eclipse.smarthome.core.thing.ThingUID; -import org.openhab.binding.vitotronic.VitotronicBindingConstants; -import org.openhab.binding.vitotronic.handler.VitotronicBridgeHandler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class VitotronicDiscoveryService extends AbstractDiscoveryService { - - private Logger logger = LoggerFactory.getLogger(VitotronicDiscoveryService.class); - - private VitotronicBridgeHandler vitotronicBridgeHandler; - - public VitotronicDiscoveryService(VitotronicBridgeHandler vitotronicBridgeHandler) throws IllegalArgumentException { - super(VitotronicBindingConstants.SUPPORTED_THING_TYPES_UIDS, 10, false); - this.vitotronicBridgeHandler=vitotronicBridgeHandler; - - } - - - private void addThing(ThingUID bridgeUID, String thingType, String thingID) { - logger.trace("Adding new Vitotronic thing: {}", thingID); - ThingUID thingUID = null; - switch (thingType) { - case VitotronicBindingConstants.THING_ID_HEATING : - thingUID = new ThingUID(VitotronicBindingConstants.THING_TYPE_UID_HEATING, bridgeUID, thingID); - break; - case VitotronicBindingConstants.THING_ID_PELLETBURNER : - thingUID = new ThingUID(VitotronicBindingConstants.THING_TYPE_UID_PELLETBURNER, bridgeUID, thingID); - break; - case VitotronicBindingConstants.THING_ID_STORAGETANK : - thingUID = new ThingUID(VitotronicBindingConstants.THING_TYPE_UID_STORAGETANK, bridgeUID, thingID); - break; - case VitotronicBindingConstants.THING_ID_CIRCUIT : - thingUID = new ThingUID(VitotronicBindingConstants.THING_TYPE_UID_CIRCUIT, bridgeUID, thingID); - break; - case VitotronicBindingConstants.THING_ID_SOLAR : - thingUID = new ThingUID(VitotronicBindingConstants.THING_TYPE_UID_SOLAR, bridgeUID, thingID); - break; - } - - if (thingUID != null) { - logger.trace("Adding new Discovery thingType: {} bridgeType: {}", thingUID.getThingTypeId(), bridgeUID.getThingTypeId()); - - DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID) - .withBridge(bridgeUID) - .withLabel(thingID).build(); - logger.trace("call register: {} label: {}", discoveryResult.getBindingId(), discoveryResult.getLabel() ); - thingDiscovered(discoveryResult); - } else { - logger.debug("Discovered Thing is unsupported: type '{}'", thingID); - } - - - - } - - - - public void addVitotronicThing(String thingType, String thingID) { - - addThing(vitotronicBridgeHandler.getThing().getUID(), thingType, thingID); - - } - - - - public void activate() { - vitotronicBridgeHandler.registerDiscoveryService(this); - } - - public void deactivate() { - vitotronicBridgeHandler.unregisterDiscoveryService(); - } - - - protected void startScan() { - // Scan will be done by bridge - } - - - -} +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.vitotronic.internal.discovery; + +/** + * The {@link VitotronicBridgeDiscovery} class handles the discovery of things. + * with broadcasting and put it to inbox, if found. + * + * + * @author Stefan Andres - Initial contribution + */ + +import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService; +import org.eclipse.smarthome.config.discovery.DiscoveryResult; +import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.openhab.binding.vitotronic.VitotronicBindingConstants; +import org.openhab.binding.vitotronic.handler.VitotronicBridgeHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class VitotronicDiscoveryService extends AbstractDiscoveryService { + + private Logger logger = LoggerFactory.getLogger(VitotronicDiscoveryService.class); + + private VitotronicBridgeHandler vitotronicBridgeHandler; + + public VitotronicDiscoveryService(VitotronicBridgeHandler vitotronicBridgeHandler) throws IllegalArgumentException { + super(VitotronicBindingConstants.SUPPORTED_THING_TYPES_UIDS, 10, false); + this.vitotronicBridgeHandler=vitotronicBridgeHandler; + + } + + + private void addThing(ThingUID bridgeUID, String thingType, String thingID) { + logger.trace("Adding new Vitotronic thing: {}", thingID); + ThingUID thingUID = null; + switch (thingType) { + case VitotronicBindingConstants.THING_ID_HEATING : + thingUID = new ThingUID(VitotronicBindingConstants.THING_TYPE_UID_HEATING, bridgeUID, thingID); + break; + case VitotronicBindingConstants.THING_ID_PELLETBURNER : + thingUID = new ThingUID(VitotronicBindingConstants.THING_TYPE_UID_PELLETBURNER, bridgeUID, thingID); + break; + case VitotronicBindingConstants.THING_ID_STORAGETANK : + thingUID = new ThingUID(VitotronicBindingConstants.THING_TYPE_UID_STORAGETANK, bridgeUID, thingID); + break; + case VitotronicBindingConstants.THING_ID_CIRCUIT : + thingUID = new ThingUID(VitotronicBindingConstants.THING_TYPE_UID_CIRCUIT, bridgeUID, thingID); + break; + case VitotronicBindingConstants.THING_ID_SOLAR : + thingUID = new ThingUID(VitotronicBindingConstants.THING_TYPE_UID_SOLAR, bridgeUID, thingID); + break; + } + + if (thingUID != null) { + logger.trace("Adding new Discovery thingType: {} bridgeType: {}", thingUID.getThingTypeId(), bridgeUID.getThingTypeId()); + + DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID) + .withBridge(bridgeUID) + .withLabel(thingID).build(); + logger.trace("call register: {} label: {}", discoveryResult.getBindingId(), discoveryResult.getLabel() ); + thingDiscovered(discoveryResult); + } else { + logger.debug("Discovered Thing is unsupported: type '{}'", thingID); + } + + + + } + + + + public void addVitotronicThing(String thingType, String thingID) { + + addThing(vitotronicBridgeHandler.getThing().getUID(), thingType, thingID); + + } + + + + public void activate() { + vitotronicBridgeHandler.registerDiscoveryService(this); + } + + public void deactivate() { + vitotronicBridgeHandler.unregisterDiscoveryService(); + } + + + protected void startScan() { + // Scan will be done by bridge + } + + + +} diff --git a/addons/binding/org.openhab.binding.zoneminder/.classpath b/addons/binding/org.openhab.binding.zoneminder/.classpath new file mode 100644 index 0000000000000..a95e0906ca013 --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/addons/binding/org.openhab.binding.zoneminder/.project b/addons/binding/org.openhab.binding.zoneminder/.project new file mode 100644 index 0000000000000..514ade439918a --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/.project @@ -0,0 +1,33 @@ + + + org.openhab.binding.zoneminder + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.ds.core.builder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/addons/binding/org.openhab.binding.zoneminder/ESH-INF/binding/binding.xml b/addons/binding/org.openhab.binding.zoneminder/ESH-INF/binding/binding.xml new file mode 100644 index 0000000000000..f85134801d585 --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/ESH-INF/binding/binding.xml @@ -0,0 +1,9 @@ + + + ZoneMinder Binding + This binding interfaces a ZoneMinder Server + Martin S. Eskildsen + diff --git a/addons/binding/org.openhab.binding.zoneminder/ESH-INF/config/monitor-channels.xml b/addons/binding/org.openhab.binding.zoneminder/ESH-INF/config/monitor-channels.xml new file mode 100644 index 0000000000000..e181ee57355d4 --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/ESH-INF/config/monitor-channels.xml @@ -0,0 +1,23 @@ + + + + + + The ID of the monitor in ZoneMinder + + + + Timeout in seconds when activating alarm. Default is 60 seconds + 60 + + + + Event text in ZoneMinder + Triggered from openHAB + + + \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.zoneminder/ESH-INF/config/zoneminderserver.xml b/addons/binding/org.openhab.binding.zoneminder/ESH-INF/config/zoneminderserver.xml new file mode 100644 index 0000000000000..49aa5c4c480ac --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/ESH-INF/config/zoneminderserver.xml @@ -0,0 +1,88 @@ + + + + + basic + + + + credentials + + + + network + + + + refreshConfig + + + + + advancedSettings + + + + + network-address + + The IP address or hostname of the ZoneMinder Server + + + + Protocol to connect to the ZoneMinder Server API (http or https) + http + + + + + + + + Additional path on ZoneMinder Server to access API. In a standard installation this is' /zm' + /zm + + + + User to access the ZoneMinder Server API + + + password + + Password to access the ZoneMinder Server API + + + + Port of the ZoneMinder Server API. If '0', then the port will be determined from the protocol + 0 + true + + + + Port to listen for events in (Telnet) + 6802 + true + + + + Seconds between each call to ZoneMinder Server API to refresh values in openHAB + 10 + true + + + + Minutes between each call to ZoneMinder Server to refresh Server DiskUsage in ZoneMinder. Default value is '0' (Disabled) + 0 + true + + + + If enabled new monitors on the ZoneMinder Server will automatically be added to the Inbox in openHAB + true + true + + + \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.zoneminder/ESH-INF/thing/monitor-thing.xml b/addons/binding/org.openhab.binding.zoneminder/ESH-INF/thing/monitor-thing.xml new file mode 100644 index 0000000000000..949860fe6b090 --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/ESH-INF/thing/monitor-thing.xml @@ -0,0 +1,138 @@ + + + + + + + + + + + Camera in ZoneMinder + + + + + + + + + + + + + + + + + + + + + Switch + + Switch telling if the monitor is online + + + + + Switch + + Showing the value of the checkbox 'enabled' in ZoneMinder for the monitor + + + + + Switch + + Will force an alarm from openHAB in ZoneMinder + + + + + + Switch + + set to 'ON' when one of the following is true: Motion detected, Signal lost, Force Alarm pressed, External Alarm. Else set to 'OFF' + + + + + Switch + + set to 'ON' when either channel monitor-alarm set to 'ON', or montior function is 'Mocord' or 'Record'. Else set to 'OFF' + + + + + String + + Current Monitor Status: 0=Idle, 1=Pre-alarm, 2=Alarm, 3=Alert, 4=Recording + + + + + + + + + + + + + String + + Current Monitor Function: None, Monitor, Modect, Record, Mocord, Nodect + + + + + + + + + + + + + + + String + + Cause of event: None, Signal, Motion, Forced Web, openHAB, Other + + + + + + + + + + + + + + Switch + + State of ZoneMinder Capture daemon for this monitor + + + + + Switch + + State of ZoneMinder Analysis daemon for this monitor + + + + + Switch + + State of ZoneMinder Frame daemon for this monitor + + + + diff --git a/addons/binding/org.openhab.binding.zoneminder/ESH-INF/thing/server-bridge.xml b/addons/binding/org.openhab.binding.zoneminder/ESH-INF/thing/server-bridge.xml new file mode 100644 index 0000000000000..d0c3e31b6ee80 --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/ESH-INF/thing/server-bridge.xml @@ -0,0 +1,39 @@ + + + + + + ZoneMinder Server + + + + + + + + + + + Switch + + ZoneMinder Server Online Status + + + + + Number + + ZoneMinder Server CPU Load + + + + Number + + ZoneMinder Server Disk Usage + + + + \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.zoneminder/META-INF/MANIFEST.MF b/addons/binding/org.openhab.binding.zoneminder/META-INF/MANIFEST.MF new file mode 100644 index 0000000000000..f4646dcc0f434 --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/META-INF/MANIFEST.MF @@ -0,0 +1,34 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: ZoneMinder Binding +Bundle-SymbolicName: org.openhab.binding.zoneminder;singleton:=true +Bundle-Vendor: openHAB +Bundle-Version: 2.1.0.qualifier +Bundle-RequiredExecutionEnvironment: JavaSE-1.7 +Bundle-ClassPath: ., + lib/gson-2.7.jar, + lib/guava-17.0.jar, + lib/jersey-common-2.4.1.jar, + lib/javax.ws.rs-api-2.0.1.jar, + lib/jsoup-1.10.1.jar, + lib/zoneminder4j-0.9.7.jar +Import-Package: + com.google.common.collect, + javax.ws.rs.client, + javax.ws.rs.core, + org.apache.commons.net.util, + org.eclipse.smarthome.config.core, + org.eclipse.smarthome.config.discovery, + org.eclipse.smarthome.core.library.types, + org.eclipse.smarthome.core.thing, + org.eclipse.smarthome.core.thing.binding, + org.eclipse.smarthome.core.thing.binding.builder, + org.eclipse.smarthome.core.thing.type, + org.eclipse.smarthome.core.types, + org.openhab.binding.zoneminder, + org.openhab.binding.zoneminder.handler, + org.osgi.framework, + org.slf4j +Service-Component: OSGI-INF/*.xml +Export-Package: org.openhab.binding.zoneminder, + org.openhab.binding.zoneminder.handler diff --git a/addons/binding/org.openhab.binding.zoneminder/OSGI-INF/ZoneMinderHandlerFactory.xml b/addons/binding/org.openhab.binding.zoneminder/OSGI-INF/ZoneMinderHandlerFactory.xml new file mode 100644 index 0000000000000..a220cfd1d670b --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/OSGI-INF/ZoneMinderHandlerFactory.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + diff --git a/addons/binding/org.openhab.binding.zoneminder/about.html b/addons/binding/org.openhab.binding.zoneminder/about.html new file mode 100644 index 0000000000000..7311d5ecde564 --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/about.html @@ -0,0 +1,73 @@ + + + + +About + + +

About This Content

+ +

January 18, 2017

+

License

+ +

The openHAB community makes available all content in this plug-in ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available +at http://www.eclipse.org/legal/epl-v10.html. +For purposes of the EPL, "Program" will mean the Content.

+ +

If you did not receive this Content directly from the openHAB community, the Content is +being redistributed by another party ("Redistributor") and different terms and conditions may +apply to your use of any object code in the Content. Check the Redistributor's license that was +provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise +indicated below, the terms and conditions of the EPL still apply to any source code in the Content +and such source code may be obtained at openhab.org.

+ + +

Third Party Content

+

The Content includes items that have been sourced from third parties as set out below. If you + did not receive this Content directly from the openHAB community, the following is provided + for informational purposes only, and you should look to the Redistributor's license for + terms and conditions of use.

+

+ +

+ google-gson
+ google-gson obtained from Maven central repository under + Apache License. +

+ +

+ Google Core Libraries for Java
+ Guava: Google Core Libraries for Java obtained from Maven central repository under + Apache License. +

+ +

+ java.ws.rs-api
+ Java API for RESTful Services (JAX-RS) obtained from Maven central repository under + COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL)Version 1.1. +

+ + +

+ jersey-common
+ Jersey Core Common obtained from Maven central repository under + COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL)Version 1.1. +

+ +

+ jsoup
+ Java HTML Parser obtained from Maven central repository under + MIT License. +

+ +

+ zoneminder4j
+ zoneninder4j obtained from GitHub repository under + MIT License. +

+ + + \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.zoneminder/build.properties b/addons/binding/org.openhab.binding.zoneminder/build.properties new file mode 100644 index 0000000000000..7902be407aaa4 --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/build.properties @@ -0,0 +1,8 @@ +source.. = src/main/java/ +output.. = target/classes +bin.includes = META-INF/,\ + .,\ + OSGI-INF/,\ + ESH-INF/,\ + lib/ + diff --git a/addons/binding/org.openhab.binding.zoneminder/lib/gson-2.7.jar b/addons/binding/org.openhab.binding.zoneminder/lib/gson-2.7.jar new file mode 100644 index 0000000000000..be5b59b764b56 Binary files /dev/null and b/addons/binding/org.openhab.binding.zoneminder/lib/gson-2.7.jar differ diff --git a/addons/binding/org.openhab.binding.zoneminder/lib/guava-17.0.jar b/addons/binding/org.openhab.binding.zoneminder/lib/guava-17.0.jar new file mode 100644 index 0000000000000..661fc7473f876 Binary files /dev/null and b/addons/binding/org.openhab.binding.zoneminder/lib/guava-17.0.jar differ diff --git a/addons/binding/org.openhab.binding.zoneminder/lib/javax.ws.rs-api-2.0.1.jar b/addons/binding/org.openhab.binding.zoneminder/lib/javax.ws.rs-api-2.0.1.jar new file mode 100644 index 0000000000000..7eb68b4a0abb8 Binary files /dev/null and b/addons/binding/org.openhab.binding.zoneminder/lib/javax.ws.rs-api-2.0.1.jar differ diff --git a/addons/binding/org.openhab.binding.zoneminder/lib/jersey-common-2.4.1.jar b/addons/binding/org.openhab.binding.zoneminder/lib/jersey-common-2.4.1.jar new file mode 100644 index 0000000000000..50d5e5505b8e3 Binary files /dev/null and b/addons/binding/org.openhab.binding.zoneminder/lib/jersey-common-2.4.1.jar differ diff --git a/addons/binding/org.openhab.binding.zoneminder/lib/jsoup-1.10.1.jar b/addons/binding/org.openhab.binding.zoneminder/lib/jsoup-1.10.1.jar new file mode 100644 index 0000000000000..6415d0c030e31 Binary files /dev/null and b/addons/binding/org.openhab.binding.zoneminder/lib/jsoup-1.10.1.jar differ diff --git a/addons/binding/org.openhab.binding.zoneminder/lib/zoneminder4j-0.9.7.jar b/addons/binding/org.openhab.binding.zoneminder/lib/zoneminder4j-0.9.7.jar new file mode 100644 index 0000000000000..c27173bccf1fc Binary files /dev/null and b/addons/binding/org.openhab.binding.zoneminder/lib/zoneminder4j-0.9.7.jar differ diff --git a/addons/binding/org.openhab.binding.zoneminder/pom.xml b/addons/binding/org.openhab.binding.zoneminder/pom.xml new file mode 100644 index 0000000000000..740b4defce1f4 --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/pom.xml @@ -0,0 +1,14 @@ + + + 4.0.0 + + org.openhab.binding + pom + 2.1.0-SNAPSHOT + + org.openhab.binding + org.openhab.binding.zoneminder + 2.1.0-SNAPSHOT + ZoneMinder Binding + eclipse-plugin + diff --git a/addons/binding/org.openhab.binding.zoneminder/readme.md b/addons/binding/org.openhab.binding.zoneminder/readme.md new file mode 100644 index 0000000000000..2a0332ed9b80e --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/readme.md @@ -0,0 +1,163 @@ +# Zoneminder Binding + +This binding offers integration to a ZoneMinder Server. It currently only offers to integrate to monitors (eg. cameras in ZoneMinder). It also only offers access to a limited set of values, as well as a even more limited option to update values in ZoneMinder. It requires at least ZoneMinder 1.29 with API enabled (option 'OPT_USE_API' in ZoneMinder must be enabled). The option 'OPT_TRIGGERS' must be anabled to allow OpenHAB to trip the ForceAlarm in ZoneMinder. + +## Supported Things + +This binding supports the following thing types + + + + + +
ThingThing TypeDiscoveryDescription
ZoneMinder ServerBridgeNoA ZoneMinder Server. Required version is minimum 1.29
ZoneMinder MonitorThingYesMonitor as defined in ZoneMinder Server
+ +## Getting started / Discovery +The binding consists of a Bridge (the ZoneMinder Server it self), and a number of Things, which relates to the induvidual monitors in ZoneMinder. ZoneMinder things can be configured either through the online configuration utility via discovery, or manually through the 'zoneminder.things' configuration file. The Bridge will not be autodiscovered, this behaviour is by design. That is because the ZoneMinder API can be configured to communicate on custom ports, you can even change the url from the default /zm/ to something userdefined. That makes it meaningless to scan for a ZoneMinder Server. The Bridge must therefore be added manually, this can be done from PaperUI. After adding the Bridge it will go ONLINE, and after a short while and the discovery process for monitors will start. When a new monitor is discovered it will appear in the Inbox. + + +### Bridge ### + Channel | Type | Description +-------------- | --------- | ---------------------------------- +Is Alive | Switch | Parameter indicationg if the server IsAlive +CPU load | Text | Current CPU Load of server +Disk Usage | text | Current Disk Usage on server +Server Version | Text | Version of ZoneMinder +API Version | Text | Version of API + +### Thing ### + + Channel | Type | Description +-------------- | --------- | ---------------------------------- +Is Alive | Switch | Parameter indicationg if the monitor IsAlive +Enabled | Switch | Parameter indicationg if the monitor is enabled +Name | Text | Name of Monitor +SourceType | Text | As stated in ZoneMinder (Local, Remote, File, Ffmpeg, Libvlc, cUrl) +Trigger | Switch | State of the ForceAlarm in ZoneMidner. This can both be read and set from OpenHAB. +Function | Text | Text corresponding the value in ZoneMinder: None, Monitor, Modect, Record, Mocord, Nodect +ZMC Daemon State | Switch | Run state of ZMC Daemon +ZMA Daemon State | Switch | Run state of ZMA Daemon +ZMF Daemon State | Switch | Run state of ZMF Daemon + +##Manual configuration## +###Things configuration### +``` +Bridge zoneminder:server:ZoneMinderSample [ hostname="192.168.1.55", user="", password="", telnet_port=6802, refresh_interval_disk_usage=1 ] +{ + Thing monitor monitor_1 [ monitorId=1, monitorTriggerTimeout=120, monitorEventText="Trigger activated from OpenHAB" ] +} + +``` +###Items configuration### +``` +// SERVER +Switch zmsIsAlive "Zoneminder alive [%s]" {channel="zoneminder:server:ZoneMinderSample:is-alive"} +Number zmsCpuLoad "ZoneMinder Server Load [%d]" {channel="zoneminder:server:ZoneMinderSample:cpu-load"} +Number zmsDiskUsage "ZoneMinder Disk Usage [%d]" {channel="zoneminder:server:ZoneMinderSample:disk-usage"} + +String zmsServerVersion "ZoneMinder Server Version [%s]" {channel="zoneminder:server:ZoneMinderSample:zm-version"} +String zmsServerApiVersion "ZoneMinder Server Version [%s]" {channel="zoneminder:server:ZoneMinderSample:zm-api-version"} + +// MONITOR 1 +String zmMonitor1_Name "Name [%s]" {channel="zoneminder:monitor:ZoneMinderSample:monitor_1:name"} +Switch zmMonitor1_IsAlive "Alive [%s]" {channel="zoneminder:monitor:ZoneMinderSample:monitor_1:is-alive"} +Switch zmMonitor1_Enabled "Enabled [%s]" {channel="zoneminder:monitor:ZoneMinderSample:monitor_1:enabled"} + +String zmMonitor1_SourceType "Source [%s]" {channel="zoneminder:monitor:ZoneMinderSample:monitor_1:sourcetype"} +Switch zmMonitor1_TriggerEvent "Trigger [%s]" {channel="zoneminder:monitor:ZoneMinderSample:monitor_1:trigger-event"} + +String zmMonitor1_Function "Function [%s]" {channel="zoneminder:monitor:ZoneMinderSample:monitor_1:function"} + +Switch zmMonitor1_CaptureStatus "Capture Daemon [%s]" {channel="zoneminder:monitor:ZoneMinderSample:monitor_1:daemon-capture-state"} +String zmMonitor1_CaptureStatusText "Capture statustext [%s]" {channel="zoneminder:monitor:ZoneMinderSample:monitor_1:daemon-capture-statustext"} + + +Switch zmMonitor1_AnalysisStatus "Analysis Daemon [%s]" {channel="zoneminder:monitor:ZoneMinderSample:monitor_1:daemon-analysis-state"} +String zmMonitor1_AnalysisStatusText "Analysis StatusText [%s]" {channel="zoneminder:monitor:ZoneMinderSample:monitor_1:daemon-analysis-statustext"} + + +Switch zmMonitor1_FrameStatus "Frame Daemon [%s]" {channel="zoneminder:monitor:ZoneMinderSample:monitor_1:daemon-frame-state"} +String zmMonitor1_FrameStatusText "Frame StatusText [%s]" {channel="zoneminder:monitor:ZoneMinderSample:monitor_1:daemon-frame-statustext"} + + +// Helpers +Switch zmMonitor1_Mode "Monitor active [%s]" +``` + +###Sample Rule### +``` +rule "Monitor1 TriggerEvent" +when + Item zmMonitor1_TriggerEvent changed +then + if (zmMonitor1_TriggerEvent.state == ON) { + logInfo("zoneminder.rules", "ZoneMinder TriggerEvent started") + } + else if (zmMonitor1_TriggerEvent.state == OFF) { + logInfo("zoneminder.rules", "ZoneMinder TriggerEvent stopped") + } +end + + +rule "Change Monitor1 Mode" +when + Item zmMonitor1_Mode changed +then + if (zmMonitor1_Mode.state==ON) { + sendCommand(zmMonitor1_Function, "Modect") + sendCommand(zmMonitor1_Enabled, ON) + } + else { + sendCommand(zmMonitor1_Function, "Monitor") + sendCommand(zmMonitor1_Enabled, OFF) + } +end +``` + + +###Sitemap configuration### +``` +sitemap zoneminder label="Zoneminder" +{ + Frame { + Text item=zmsIsAlive label="ZoneMinder Server [%s]" { + Frame { + Switch item=zmsIsAlive + Text item=zmsCpuLoad + Text item=zmsDiskUsage + Text item=zmsServerVersion + Text item=zmsServerApiVersion + } + } + + Text item=zmMonitor1_Function label="(Monitor-1) [%s]" { + Frame { + Text item=zmMonitor1_Name + Switch item=zmMonitor1_Enabled + Text item=zmMonitor1_SourceType + Switch item=zmMonitor1_TriggerEvent + Selection item=zmMonitor1_Function mappings=["None"=None, "Modect"=Modect, "Monitor"=Monitor, "Record"=Record, "Mocord"=Mocord, "Nodect"=Nodect] + Text item=zmMonitor1_IsAlive + Text item=zmMonitor1_CaptureStatus + Text item=zmMonitor1_CaptureStatusText + Text item=zmMonitor1_AnalysisStatus + Text item=zmMonitor1_AnalysisStatusText + Text item=zmMonitor1_FrameStatus + Text item=zmMonitor1_FrameStatusText + } + } + Frame label="Monitor Helpers" { + Switch item=zmMonitor1_Mode + } + } +} +``` +##Troubleshooting## + + + + + +
ProblemSolution
Cannot connect to ZoneMinder BridgeCheck if you can logon to ZoneMinder from your OpenHAB server (with http).
Check that it is possible to establish a Telnet connection from OpenHAB server to Zoneminder Server
Cannot connect to ZoneMinder Bridge via HTTPS, using Letsencrypt certificateVerify your Java version, if Java is below build 101, letsencrypt certificate isn't known by Java. Either use HTTP or upgrade Java to newest build.
+ + diff --git a/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/ZoneMinderConstants.java b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/ZoneMinderConstants.java new file mode 100644 index 0000000000000..671bc64ba2e9c --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/ZoneMinderConstants.java @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.zoneminder; + +import org.eclipse.smarthome.core.thing.ThingTypeUID; + +/** + * The {@link ZoneMinderConstants} class defines common constants, which are + * used across the whole binding. + * + * @author Martin S. Eskildsen - Initial contribution + */ +public class ZoneMinderConstants { + + public static final String BINDING_ID = "zoneminder"; + + // ZoneMinder Server Bridge + public static final String BRIDGE_ZONEMINDER_SERVER = "server"; + + // ZoneMinder Monitor thing + public static final String THING_ZONEMINDER_MONITOR = "monitor"; + + // ZoneMinder Server displayable name + public static final String ZONEMINDER_SERVER_NAME = "ZoneMinder Server"; + + // ZoneMinder Monitor displayable name + public static final String ZONEMINDER_MONITOR_NAME = "ZoneMinder Monitor"; + + /* + * ZoneMinder Server Constants + */ + + // Thing Type UID for Server + public final static ThingTypeUID THING_TYPE_BRIDGE_ZONEMINDER_SERVER = new ThingTypeUID(BINDING_ID, + BRIDGE_ZONEMINDER_SERVER); + + // Shared channel for all bridges / things + public final static String CHANNEL_ONLINE = "online"; + + // Channel Id's for the ZoneMinder Server + public final static String CHANNEL_SERVER_DISKUSAGE = "disk-usage"; + public final static String CHANNEL_SERVER_CPULOAD = "cpu-load"; + + // Parameters for the ZoneMinder Server + public final static String PARAM_HOSTNAME = "hostname"; + public final static String PARAM_PORT = "port"; + public final static String PARAM_REFRESH_INTERVAL_ = "refresh_interval"; + public final static String PARAM_REFRESH_INTERVAL_DISKUSAGE = "refresh_interval_disk_usage"; + + // Default values for Monitor parameters + public static final Integer DEFAULT_HTTP_PORT = 80; + public static final Integer DEFAULT_TELNET_PORT = 6802; + + /* + * ZoneMinder Monitor Constants + */ + + // Thing Type UID for Monitor + public final static ThingTypeUID THING_TYPE_THING_ZONEMINDER_MONITOR = new ThingTypeUID(BINDING_ID, + THING_ZONEMINDER_MONITOR); + /* + * Channel Id's for the ZoneMinder Monitor + */ + public final static String CHANNEL_MONITOR_ENABLED = "enabled"; + public final static String CHANNEL_MONITOR_FORCE_ALARM = "force-alarm"; + public final static String CHANNEL_MONITOR_EVENT_STATE = "alarm"; + public final static String CHANNEL_MONITOR_EVENT_CAUSE = "event-cause"; + public final static String CHANNEL_MONITOR_RECORD_STATE = "recording"; + public final static String CHANNEL_MONITOR_DETAILED_STATUS = "detailed-status"; + public final static String CHANNEL_MONITOR_FUNCTION = "function"; + + public final static String CHANNEL_MONITOR_CAPTURE_DAEMON_STATE = "capture-daemon"; + public final static String CHANNEL_MONITOR_ANALYSIS_DAEMON_STATE = "analysis-daemon"; + public final static String CHANNEL_MONITOR_FRAME_DAEMON_STATE = "frame-daemon"; + + // Parameters for the ZoneMinder Monitor + public final static String PARAMETER_MONITOR_ID = "monitorId"; + public final static String PARAMETER_MONITOR_TRIGGER_TIMEOUT = "monitorTriggerTimeout"; + public final static String PARAMETER_MONITOR_EVENTTEXT = "monitorEventText"; + + // Default values for Monitor parameters + public final static Integer PARAMETER_MONITOR_TRIGGER_TIMEOUT_DEFAULTVALUE = 60; + + public final static String PARAMETER_MONITOR_EVENTNOTE_DEFAULTVALUE = "openHAB triggered event"; + + public final static String MONITOR_EVENT_NONE = ""; + public final static String MONITOR_EVENT_SIGNAL = "Signal"; + public final static String MONITOR_EVENT_MOTION = "Motion"; + public final static String MONITOR_EVENT_FORCED_WEB = "Forced Web"; + public final static String MONITOR_EVENT_OPENHAB = "openHAB"; + +} diff --git a/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/ZoneMinderProperties.java b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/ZoneMinderProperties.java new file mode 100644 index 0000000000000..9e462742131ab --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/ZoneMinderProperties.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.zoneminder; + +public class ZoneMinderProperties { + public static final String PROPERTY_ID = "Id"; + + public static final String PROPERTY_SERVER_VERSION = "Version"; + public static final String PROPERTY_SERVER_API_VERSION = "API Version"; + public static final String PROPERTY_SERVER_USE_API = "API Enabled"; + public static final String PROPERTY_SERVER_USE_AUTHENTIFICATION = "Use Authentification"; + public static final String PROPERTY_SERVER_TRIGGERS_ENABLED = "Triggers enabled"; + + public static final String PROPERTY_MONITOR_NAME = "Name"; + public static final String PROPERTY_MONITOR_SOURCETYPE = "Sourcetype"; + + public static final String PROPERTY_MONITOR_ANALYSIS_FPS = "Analysis FPS"; + public static final String PROPERTY_MONITOR_MAXIMUM_FPS = "Maximum FPS"; + public static final String PROPERTY_MONITOR_ALARM_MAXIMUM = "Alarm Maximum FPS"; + + public static final String PROPERTY_MONITOR_IMAGE_WIDTH = "Width"; + public static final String PROPERTY_MONITOR_IMAGE_HEIGHT = "Height"; +} diff --git a/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/discovery/ZoneMinderDiscoveryService.java b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/discovery/ZoneMinderDiscoveryService.java new file mode 100644 index 0000000000000..deef7f154901d --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/discovery/ZoneMinderDiscoveryService.java @@ -0,0 +1,135 @@ +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ + +package org.openhab.binding.zoneminder.discovery; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService; +import org.eclipse.smarthome.config.discovery.DiscoveryResult; +import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; +import org.eclipse.smarthome.config.discovery.DiscoveryServiceCallback; +import org.eclipse.smarthome.config.discovery.ExtendedDiscoveryService; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.openhab.binding.zoneminder.ZoneMinderConstants; +import org.openhab.binding.zoneminder.handler.ZoneMinderServerBridgeHandler; +import org.openhab.binding.zoneminder.handler.ZoneMinderThingMonitorHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import name.eskildsen.zoneminder.IZoneMinderMonitorData; + +public class ZoneMinderDiscoveryService extends AbstractDiscoveryService implements ExtendedDiscoveryService { + private final Logger logger = LoggerFactory.getLogger(ZoneMinderDiscoveryService.class); + + private ZoneMinderServerBridgeHandler serverHandler; + private DiscoveryServiceCallback discoveryServiceCallback; + + public ZoneMinderDiscoveryService(ZoneMinderServerBridgeHandler coordinatorHandler, int searchTime) { + super(searchTime); + this.serverHandler = coordinatorHandler; + } + + public void activate() { + logger.debug("[DISCOVERY]: Activating ZoneMinder discovery service for {}", serverHandler.getThing().getUID()); + } + + @Override + public void deactivate() { + logger.debug("[DISCOVERY]: Deactivating ZoneMinder discovery service for {}", + serverHandler.getThing().getUID()); + } + + @Override + public void setDiscoveryServiceCallback(DiscoveryServiceCallback discoveryServiceCallback) { + this.discoveryServiceCallback = discoveryServiceCallback; + } + + @Override + public Set getSupportedThingTypes() { + return ZoneMinderThingMonitorHandler.SUPPORTED_THING_TYPES; + } + + @Override + public void startBackgroundDiscovery() { + logger.debug("[DISCOVERY]: Performing background discovery scan for {}", serverHandler.getThing().getUID()); + discoverMonitors(); + } + + @Override + public void startScan() { + logger.debug("[DISCOVERY]: Starting discovery scan for {}", serverHandler.getThing().getUID()); + discoverMonitors(); + } + + @Override + public synchronized void abortScan() { + super.abortScan(); + } + + @Override + protected synchronized void stopScan() { + super.stopScan(); + } + + protected String BuildMonitorLabel(String id, String name) { + return String.format("%s [%s]", ZoneMinderConstants.ZONEMINDER_MONITOR_NAME, name); + } + + protected synchronized void discoverMonitors() { + // Add all existing devices + for (IZoneMinderMonitorData monitor : serverHandler.getMonitors()) { + deviceAdded(monitor); + } + } + + private boolean monitorThingExists(ThingUID newThingUID) { + return serverHandler.getThingByUID(newThingUID) != null ? true : false; + } + + /** + * This is called once the node is fully discovered. At this point we know most of the information about + * the device including manufacturer information. + * + * @param node the node to be added + */ + + public void deviceAdded(IZoneMinderMonitorData monitor) { + try { + ThingUID bridgeUID = serverHandler.getThing().getUID(); + String monitorUID = String.format("%s-%s", ZoneMinderConstants.THING_ZONEMINDER_MONITOR, monitor.getId()); + ThingUID thingUID = new ThingUID(ZoneMinderConstants.THING_TYPE_THING_ZONEMINDER_MONITOR, bridgeUID, + monitorUID); + + // Does Monitor exist? + if (!monitorThingExists(thingUID)) { + logger.info("[DISCOVERY]: Monitor with Id='{}' and Name='{}' added", monitor.getId(), + monitor.getName()); + Map properties = new HashMap<>(0); + properties.put(ZoneMinderConstants.PARAMETER_MONITOR_ID, Integer.valueOf(monitor.getId())); + properties.put(ZoneMinderConstants.PARAMETER_MONITOR_TRIGGER_TIMEOUT, + ZoneMinderConstants.PARAMETER_MONITOR_TRIGGER_TIMEOUT_DEFAULTVALUE); + properties.put(ZoneMinderConstants.PARAMETER_MONITOR_EVENTTEXT, + ZoneMinderConstants.MONITOR_EVENT_OPENHAB); + + DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties) + .withBridge(bridgeUID).withLabel(BuildMonitorLabel(monitor.getId(), monitor.getName())).build(); + + thingDiscovered(discoveryResult); + } + } catch (Exception ex) { + logger.error("[DISCOVERY]: Error occurred when calling 'monitorAdded' from Discovery. Exception={}", + ex.getMessage()); + } + + } +} diff --git a/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/handler/ZoneMinderBaseThingHandler.java b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/handler/ZoneMinderBaseThingHandler.java new file mode 100644 index 0000000000000..3050e47d7d93d --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/handler/ZoneMinderBaseThingHandler.java @@ -0,0 +1,418 @@ +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.zoneminder.handler; + +import java.io.IOException; +import java.math.BigDecimal; +import java.security.GeneralSecurityException; +import java.util.List; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.Channel; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.ThingStatusInfo; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.State; +import org.eclipse.smarthome.core.types.UnDefType; +import org.openhab.binding.zoneminder.ZoneMinderConstants; +import org.openhab.binding.zoneminder.internal.DataRefreshPriorityEnum; +import org.openhab.binding.zoneminder.internal.config.ZoneMinderThingConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import name.eskildsen.zoneminder.IZoneMinderConnectionInfo; +import name.eskildsen.zoneminder.IZoneMinderSession; +import name.eskildsen.zoneminder.ZoneMinderFactory; +import name.eskildsen.zoneminder.exception.ZoneMinderUrlNotFoundException; + +/** + * The {@link ZoneMinderBaseThingHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Martin S. Eskildsen - Initial contribution + */ +public abstract class ZoneMinderBaseThingHandler extends BaseThingHandler implements ZoneMinderHandler { + + /** Logger for the Thing. */ + private Logger logger = LoggerFactory.getLogger(ZoneMinderBaseThingHandler.class); + + /** Bridge Handler for the Thing. */ + public ZoneMinderServerBridgeHandler zoneMinderBridgeHandler = null; + + /** This refresh status. */ + private boolean thingRefreshed = false; + + /** Unique Id of the thing in zoneminder. */ + private String zoneMinderId; + + /** ZoneMidner ConnectionInfo */ + private IZoneMinderConnectionInfo zoneMinderConnection = null; + + private Lock lockSession = new ReentrantLock(); + private IZoneMinderSession zoneMinderSession = null; + + /** Configuration from openHAB */ + protected ZoneMinderThingConfig configuration; + + private DataRefreshPriorityEnum _refreshPriority = DataRefreshPriorityEnum.SCHEDULED; + + protected boolean isOnline() { + + if (zoneMinderSession == null) { + return false; + } + + if (!zoneMinderSession.isConnected()) { + return false; + } + + return true; + } + + public DataRefreshPriorityEnum getRefreshPriority() { + return _refreshPriority; + } + + public ZoneMinderBaseThingHandler(Thing thing) { + super(thing); + } + + /** + * Initializes the monitor. + * + * @author Martin S. Eskildsen + * + */ + @Override + public void initialize() { + + super.initialize(); + try { + + } catch (Exception ex) { + logger.error("{}: BridgeHandler failed to initialize. Exception='{}'", getLogIdentifier(), ex.getMessage()); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.HANDLER_INITIALIZING_ERROR); + } finally { + } + } + + protected boolean isConnected() { + if (zoneMinderSession == null) { + return false; + } + return zoneMinderSession.isConnected(); + } + + protected IZoneMinderSession aquireSession() { + lockSession.lock(); + return zoneMinderSession; + } + + protected void releaseSession() { + lockSession.unlock(); + } + + /** + * Method to start a priority data refresh task. + */ + + protected boolean startPriorityRefresh() { + + logger.info("[MONITOR-{}]: Starting High Priority Refresh", getZoneMinderId()); + _refreshPriority = DataRefreshPriorityEnum.HIGH_PRIORITY; + return true; + } + + /** + * Method to stop the data Refresh task. + */ + protected void stopPriorityRefresh() { + logger.info("{}: Stopping Priority Refresh for Monitor", getLogIdentifier()); + _refreshPriority = DataRefreshPriorityEnum.SCHEDULED; + } + + @Override + public void dispose() { + + } + + /** + * Helper method for getting ChannelUID from ChannelId. + * + */ + public ChannelUID getChannelUIDFromChannelId(String id) { + Channel ch = thing.getChannel(id); + return ch.getUID(); + } + + protected abstract void onFetchData(); + + /** + * Method to Refresh Thing Handler. + */ + public synchronized final void refreshThing(IZoneMinderSession session, DataRefreshPriorityEnum refreshPriority) { + + if ((refreshPriority != getRefreshPriority()) && (!isConnected())) { + return; + } + + if (refreshPriority == DataRefreshPriorityEnum.HIGH_PRIORITY) { + logger.debug("{}: Performing HIGH PRIORITY refresh", getLogIdentifier()); + } else { + logger.debug("{}: Performing refresh", getLogIdentifier()); + } + + if (getZoneMinderBridgeHandler() != null) { + if (isConnected()) { + + logger.debug("{}: refreshThing(): Bridge '{}' Found for Thing '{}'!", getLogIdentifier(), + getThing().getUID(), this.getThing().getUID()); + + onFetchData(); + } + } + + Thing thing = getThing(); + List channels = thing.getChannels(); + logger.debug("{}: refreshThing(): Refreshing Thing - {}", getLogIdentifier(), thing.getUID()); + + for (Channel channel : channels) { + updateChannel(channel.getUID()); + } + + this.setThingRefreshed(true); + logger.debug("[{}: refreshThing(): Thing Refreshed - {}", getLogIdentifier(), thing.getUID()); + + } + + /** + * Get the Bridge Handler for ZoneMinder. + * + * @return zoneMinderBridgeHandler + */ + public synchronized ZoneMinderServerBridgeHandler getZoneMinderBridgeHandler() { + + if (this.zoneMinderBridgeHandler == null) { + + Bridge bridge = getBridge(); + + if (bridge == null) { + logger.debug("{}: getZoneMinderBridgeHandler(): Unable to get bridge!", getLogIdentifier()); + return null; + } + + logger.debug("{}: getZoneMinderBridgeHandler(): Bridge for '{}' - '{}'", getLogIdentifier(), + getThing().getUID(), bridge.getUID()); + ThingHandler handler = null; + try { + handler = bridge.getHandler(); + } catch (Exception ex) { + logger.debug(String.format("{}: Exception in 'getZoneMinderBridgeHandler()': {}", getLogIdentifier(), + ex.getMessage())); + } + + if (handler instanceof ZoneMinderServerBridgeHandler) { + this.zoneMinderBridgeHandler = (ZoneMinderServerBridgeHandler) handler; + } else { + logger.debug("{}: getZoneMinderBridgeHandler(): Unable to get bridge handler!", getLogIdentifier()); + } + } + + return this.zoneMinderBridgeHandler; + } + + /** + * Method to Update a Channel + * + * @param channel + */ + @Override + public void updateChannel(ChannelUID channel) { + OnOffType onOffType; + + switch (channel.getId()) { + case ZoneMinderConstants.CHANNEL_ONLINE: + updateState(channel, getChannelBoolAsOnOffState(isOnline())); + break; + default: + logger.error( + "{}: updateChannel() in base class, called for an unknown channel '{}', this channel must be handled in super class.", + getLogIdentifier(), channel.getId()); + } + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + } + + @Override + public void onBridgeConnected(ZoneMinderServerBridgeHandler bridge, IZoneMinderConnectionInfo connection) + throws IllegalArgumentException, GeneralSecurityException, IOException, ZoneMinderUrlNotFoundException { + lockSession.lock(); + try { + zoneMinderSession = ZoneMinderFactory.CreateSession(connection); + + } finally { + lockSession.unlock(); + } + } + + @Override + public void onBridgeDisconnected(ZoneMinderServerBridgeHandler bridge) { + + if (bridge.getThing().getUID().equals(getThing().getBridgeUID())) { + + this.setThingRefreshed(false); + } + + lockSession.lock(); + try { + zoneMinderSession = null; + + } finally { + lockSession.unlock(); + } + + } + + /** + * Get Channel by ChannelUID. + * + * @param {ChannelUID} channelUID Identifier of Channel + */ + public Channel getChannel(ChannelUID channelUID) { + Channel channel = null; + + List channels = getThing().getChannels(); + + for (Channel ch : channels) { + if (channelUID == ch.getUID()) { + channel = ch; + break; + } + } + + return channel; + } + + /** + * Get Thing Handler refresh status. + * + * @return thingRefresh + */ + public boolean isThingRefreshed() { + return thingRefreshed; + } + + /** + * Set Thing Handler refresh status. + * + * @param {boolean} refreshed Sets status refreshed of thing + */ + public void setThingRefreshed(boolean refreshed) { + this.thingRefreshed = refreshed; + } + + protected abstract String getZoneMinderThingType(); + + private Object getConfigValue(String configKey) { + return getThing().getConfiguration().getProperties().get(configKey); + } + + /* + * Helper to get a value from configuration as a String + * + * @author Martin S. Eskildsen + * + */ + protected String getConfigValueAsString(String configKey) { + return (String) getConfigValue(configKey); + } + + /* + * Helper to get a value from configuration as a Integer + * + * @author Martin S. Eskildsen + * + */ + protected Integer getConfigValueAsInteger(String configKey) { + return (Integer) getConfigValue(configKey); + } + + protected BigDecimal getConfigValueAsBigDecimal(String configKey) { + return (BigDecimal) getConfigValue(configKey); + } + + protected State getChannelStringAsStringState(String channelValue) { + State state = UnDefType.UNDEF; + + try { + if (isConnected()) { + state = new StringType(channelValue); + } + + } catch (Exception ex) { + logger.error(ex.getMessage()); + } + + return state; + + } + + protected State getChannelBoolAsOnOffState(boolean value) { + State state = UnDefType.UNDEF; + + try { + if (isConnected()) { + state = value ? OnOffType.ON : OnOffType.OFF; + } + + } catch (Exception ex) { + logger.error("{}: Exception occurred in 'getChannelBoolAsOnOffState()' (Exception='{}')", + getLogIdentifier(), ex.getMessage()); + } + + return state; + } + + @Override + public abstract String getLogIdentifier(); + + protected void updateThingStatus(ThingStatus thingStatus, ThingStatusDetail statusDetail, + String statusDescription) { + + ThingStatusInfo curStatusInfo = thing.getStatusInfo(); + String curDescription = ((curStatusInfo.getDescription() == null) ? "" : curStatusInfo.getDescription()); + // Status changed + if ((curStatusInfo.getStatus() != thingStatus) || (curStatusInfo.getStatusDetail() != statusDetail) + || (curDescription != statusDescription)) { + + // Update Status correspondingly + if ((thingStatus == ThingStatus.OFFLINE) && (statusDetail != ThingStatusDetail.NONE)) { + logger.info("{}: Thing status changed from '{}' to '{}' (DetailedStatus='{}', Description='{}')", + getLogIdentifier(), thing.getStatus(), thingStatus, statusDetail, statusDescription); + updateStatus(thingStatus, statusDetail, statusDescription); + } else { + logger.info("{}: Thing status changed from '{}' to '{}'", getLogIdentifier(), thing.getStatus(), + thingStatus); + updateStatus(thingStatus); + } + } + } + +} diff --git a/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/handler/ZoneMinderHandler.java b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/handler/ZoneMinderHandler.java new file mode 100644 index 0000000000000..45ed49feee514 --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/handler/ZoneMinderHandler.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.zoneminder.handler; + +import java.io.IOException; +import java.security.GeneralSecurityException; + +import org.eclipse.smarthome.core.thing.ChannelUID; + +import name.eskildsen.zoneminder.IZoneMinderConnectionInfo; +import name.eskildsen.zoneminder.exception.ZoneMinderUrlNotFoundException; + +/** + * Interface for ZoneMinder handlers. + * + * @author Martin S. Eskildsen + */ +public interface ZoneMinderHandler { + + String getZoneMinderId(); + + /** + * Method used to relate a log entry to a thing + */ + String getLogIdentifier(); + + void updateAvaliabilityStatus(IZoneMinderConnectionInfo connection); + + void updateChannel(ChannelUID channel); + + void onBridgeConnected(ZoneMinderServerBridgeHandler bridge, IZoneMinderConnectionInfo connection) + throws IllegalArgumentException, GeneralSecurityException, IOException, ZoneMinderUrlNotFoundException; + + void onBridgeDisconnected(ZoneMinderServerBridgeHandler bridge); + +} diff --git a/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/handler/ZoneMinderServerBridgeHandler.java b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/handler/ZoneMinderServerBridgeHandler.java new file mode 100644 index 0000000000000..6821e4b4d6a26 --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/handler/ZoneMinderServerBridgeHandler.java @@ -0,0 +1,1207 @@ +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.zoneminder.handler; + +import java.io.IOException; +import java.math.BigDecimal; +import java.security.GeneralSecurityException; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import javax.security.auth.login.FailedLoginException; + +import org.eclipse.smarthome.config.discovery.DiscoveryService; +import org.eclipse.smarthome.core.library.types.DecimalType; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.Channel; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.ThingStatusInfo; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.eclipse.smarthome.core.types.State; +import org.eclipse.smarthome.core.types.UnDefType; +import org.openhab.binding.zoneminder.ZoneMinderConstants; +import org.openhab.binding.zoneminder.ZoneMinderProperties; +import org.openhab.binding.zoneminder.discovery.ZoneMinderDiscoveryService; +import org.openhab.binding.zoneminder.internal.DataRefreshPriorityEnum; +import org.openhab.binding.zoneminder.internal.config.ZoneMinderBridgeServerConfig; +import org.osgi.framework.ServiceRegistration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.Sets; + +import name.eskildsen.zoneminder.IZoneMinderConnectionInfo; +import name.eskildsen.zoneminder.IZoneMinderDaemonStatus; +import name.eskildsen.zoneminder.IZoneMinderDiskUsage; +import name.eskildsen.zoneminder.IZoneMinderHostLoad; +import name.eskildsen.zoneminder.IZoneMinderHostVersion; +import name.eskildsen.zoneminder.IZoneMinderMonitorData; +import name.eskildsen.zoneminder.IZoneMinderServer; +import name.eskildsen.zoneminder.IZoneMinderSession; +import name.eskildsen.zoneminder.ZoneMinderFactory; +import name.eskildsen.zoneminder.api.config.ZoneMinderConfig; +import name.eskildsen.zoneminder.api.config.ZoneMinderConfigEnum; +import name.eskildsen.zoneminder.exception.ZoneMinderUrlNotFoundException; + +/** + * Handler for a ZoneMinder Server. + * + * @author Martin S. Eskildsen + * + */ +public class ZoneMinderServerBridgeHandler extends BaseBridgeHandler implements ZoneMinderHandler { + + public static final int TELNET_TIMEOUT = 5000; + + public static final Set SUPPORTED_THING_TYPES = Sets + .newHashSet(ZoneMinderConstants.THING_TYPE_BRIDGE_ZONEMINDER_SERVER); + + /** + * Logger + */ + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private ZoneMinderDiscoveryService discoveryService = null; + private ServiceRegistration discoveryRegistration = null; + + private ScheduledFuture taskWatchDog = null; + private int refreshFrequency = 0; + private int refreshCycleCount = 0; + + /** Connection status for the bridge. */ + private boolean connected = false; + + protected boolean _online = false; + + private Runnable watchDogRunnable = new Runnable() { + private int watchDogCount = -1; + + @Override + public void run() { + + try { + updateAvaliabilityStatus(zoneMinderConnection); + + if ((discoveryService != null) && (getBridgeConfig().getAutodiscoverThings() == true)) { + watchDogCount++; + // Run every two minutes + if ((watchDogCount % 8) == 0) { + discoveryService.startBackgroundDiscovery(); + watchDogCount = 0; + } + } + } catch (Exception exception) { + logger.error("[WATCHDOG]: Server run(): Exception: {}", exception.getMessage()); + } + } + }; + + /** + * Local copies of last fetched values from ZM + */ + private String channelCpuLoad = ""; + private String channelDiskUsage = ""; + + Boolean isInitialized = false; + + private IZoneMinderSession zoneMinderSession = null; + private IZoneMinderConnectionInfo zoneMinderConnection = null; + + private ScheduledFuture taskRefreshData = null; + private ScheduledFuture taskPriorityRefreshData = null; + + private Runnable refreshDataRunnable = new Runnable() { + @Override + public void run() { + try { + boolean fetchDiskUsage = false; + + refreshCycleCount++; + + int iMaxCycles; + boolean resetCount = false; + boolean doRefresh = false; + + // Disk Usage is disabled + if (getBridgeConfig().getRefreshIntervalLowPriorityTask() == 0) { + iMaxCycles = getBridgeConfig().getRefreshInterval(); + resetCount = true; + doRefresh = true; + + } else { + iMaxCycles = getBridgeConfig().getRefreshIntervalLowPriorityTask() * 60; + doRefresh = true; + if ((refreshCycleCount * refreshFrequency) >= (getBridgeConfig().getRefreshIntervalLowPriorityTask() + * 60)) { + fetchDiskUsage = true; + resetCount = true; + + } + } + + logger.debug( + "{}: Running Refresh data task count='{}', freq='{}', max='{}', interval='{}', intervalLow='{}'", + getLogIdentifier(), refreshCycleCount, refreshFrequency, iMaxCycles, + getBridgeConfig().getRefreshInterval(), getBridgeConfig().getRefreshIntervalLowPriorityTask()); + + if (doRefresh) { + + if (resetCount == true) { + refreshCycleCount = 0; + } + + logger.debug("{}: 'refreshDataRunnable()': (diskUsage='{}')", getLogIdentifier(), fetchDiskUsage); + + refreshThing(zoneMinderSession, fetchDiskUsage); + } + + } catch (Exception exception) { + logger.error("{}: monitorRunnable::run(): Exception: {}", getLogIdentifier(), exception); + } + } + }; + + private Runnable refreshPriorityDataRunnable = new Runnable() { + + @Override + public void run() { + try { + + // Make sure priority updates is done + for (Thing thing : getThing().getThings()) { + try { + + if (thing.getThingTypeUID().equals(ZoneMinderConstants.THING_TYPE_THING_ZONEMINDER_MONITOR)) { + Thing thingMonitor = thing; + + ZoneMinderBaseThingHandler thingHandler = (ZoneMinderBaseThingHandler) thing.getHandler(); + if (thingHandler != null) { + + if (thingHandler.getRefreshPriority() == DataRefreshPriorityEnum.HIGH_PRIORITY) { + logger.debug(String.format("[MONITOR-%s]: RefreshPriority is High Priority", + thingHandler.getZoneMinderId())); + thingHandler.refreshThing(zoneMinderSession, DataRefreshPriorityEnum.HIGH_PRIORITY); + } + } else { + logger.debug(String.format( + "[MONITOR]: refreshThing not called for monitor, since thingHandler is 'null'")); + + } + } + + } catch (NullPointerException ex) { + // This isn't critical (unless it comes over and over). There seems to be a bug so that a + // null + // pointer exception is coming every now and then. + // HAve to find the reason for that. Until thenm, don't Spamm + logger.error( + "[MONITOR]: Method 'refreshThing()' for Bridge failed for thing='{}' - Exception='{}'", + thing.getUID(), ex); + } catch (Exception ex) { + logger.error( + "[MONITOR]: Method 'refreshThing()' for Bridge failed for thing='{}' - Exception='{}'", + thing.getUID(), ex); + } + } + + } catch (Exception exception) { + logger.error("[MONITOR]: monitorRunnable::run(): Exception: ", exception); + } + } + }; + + /** + * Constructor + * + * + * @param bridge + * Bridge object representing a ZoneMinder Server + */ + public ZoneMinderServerBridgeHandler(Bridge bridge) { + super(bridge); + + logger.info("{}: Starting ZoneMinder Server Bridge Handler (Bridge='{}')", getLogIdentifier(), + bridge.getBridgeUID()); + } + + /** + * Initializes the bridge. + */ + @Override + public void initialize() { + logger.debug("[BRIDGE]: About to initialize bridge " + ZoneMinderConstants.BRIDGE_ZONEMINDER_SERVER); + super.initialize(); + try { + updateStatus(ThingStatus.OFFLINE); + logger.info("BRIDGE: ZoneMinder Server Bridge Handler Initialized"); + logger.debug("BRIDGE: HostName: {}", getBridgeConfig().getHostName()); + logger.debug("BRIDGE: Protocol: {}", getBridgeConfig().getProtocol()); + logger.debug("BRIDGE: Port HTTP(S) {}", getBridgeConfig().getHttpPort()); + logger.debug("BRIDGE: Port Telnet {}", getBridgeConfig().getTelnetPort()); + logger.debug("BRIDGE: Server Path {}", getBridgeConfig().getServerBasePath()); + logger.debug("BRIDGE: User: {}", getBridgeConfig().getUserName()); + logger.debug("BRIDGE: Refresh interval: {}", getBridgeConfig().getRefreshInterval()); + logger.debug("BRIDGE: Low prio. refresh: {}", getBridgeConfig().getRefreshIntervalLowPriorityTask()); + logger.debug("BRIDGE: Autodiscovery: {}", getBridgeConfig().getAutodiscoverThings()); + + closeConnection(); + + zoneMinderConnection = ZoneMinderFactory.CreateConnection(getBridgeConfig().getProtocol(), + getBridgeConfig().getHostName(), getBridgeConfig().getHttpPort(), getBridgeConfig().getTelnetPort(), + getBridgeConfig().getServerBasePath(), getBridgeConfig().getUserName(), + getBridgeConfig().getPassword(), 3000); + + taskRefreshData = null; + taskPriorityRefreshData = null; + + } catch (Exception ex) { + logger.error("[BRIDGE]: 'ZoneMinderServerBridgeHandler' failed to initialize. Exception='{}'", + ex.getMessage()); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.HANDLER_INITIALIZING_ERROR); + } finally { + startWatchDogTask(); + isInitialized = true; + } + } + + /** + * Method to find the lowest possible refresh rate (based on configuration) + * + * @param refreshRate + * @return + */ + protected int calculateCommonRefreshFrequency(int refreshRate) { + // Check if 30, 15, 10 or 5 seconds is possible + if ((refreshRate % 30) == 0) { + return 30; + } else if ((refreshRate % 15) == 0) { + return 15; + } else if ((refreshRate % 10) == 0) { + return 10; + } else if ((refreshRate % 5) == 0) { + return 5; + } + + // Hmm, didn't find a obvious shared value. Run every second... + return 1; + + } + + protected void startWatchDogTask() { + taskWatchDog = startTask(watchDogRunnable, 0, 15, TimeUnit.SECONDS); + } + + protected void stopWatchDogTask() { + stopTask(taskWatchDog); + taskWatchDog = null; + } + + /** + */ + @Override + public void dispose() { + try { + logger.debug("{}: Stop polling of ZoneMinder Server API", getLogIdentifier()); + + logger.info("{}: Stopping Discovery service", getLogIdentifier()); + // Remove the discovery service + if (discoveryService != null) { + discoveryService.deactivate(); + discoveryService = null; + } + + if (discoveryRegistration != null) { + discoveryRegistration.unregister(); + discoveryRegistration = null; + } + + logger.info("{}: Stopping WatchDog task", getLogIdentifier()); + stopWatchDogTask(); + + logger.info("{}: Stopping refresh data task", getLogIdentifier()); + stopTask(taskRefreshData); + } catch (Exception ex) { + } + } + + protected String getThingId() { + return getThing().getUID().getId(); + } + + @Override + public String getZoneMinderId() { + + return getThing().getUID().getAsString(); + } + + @Override + public void channelLinked(ChannelUID channelUID) { + // can be overridden by subclasses + ThingUID s1 = getThing().getUID(); + ThingTypeUID s2 = getThing().getThingTypeUID(); + logger.debug("{}: Channel '{}' was linked to '{}'", getLogIdentifier(), channelUID.getAsString(), + this.thing.getThingTypeUID()); + } + + @Override + public void channelUnlinked(ChannelUID channelUID) { + // can be overridden by subclasses + logger.debug("{}: Channel '{}' was unlinked from '{}'", getLogIdentifier(), channelUID.getAsString(), + this.thing.getThingTypeUID()); + } + + protected ArrayList getMonitors(IZoneMinderSession session) { + + if (isConnected()) { + return ZoneMinderFactory.getServerProxy(session).getMonitors(); + } + + return new ArrayList(); + + } + + protected ZoneMinderBridgeServerConfig getBridgeConfig() { + return this.getConfigAs(ZoneMinderBridgeServerConfig.class); + } + + /** + * + */ + public ZoneMinderBaseThingHandler getZoneMinderThingHandlerFromZoneMinderId(ThingTypeUID thingTypeUID, + String zoneMinderId) { + + // Inform thing handlers of connection + List things = getThing().getThings(); + + for (Thing thing : things) { + ZoneMinderBaseThingHandler thingHandler = (ZoneMinderBaseThingHandler) thing.getHandler(); + if ((thingHandler.getZoneMinderId().equals(zoneMinderId)) + && (thing.getThingTypeUID().equals(thingTypeUID))) { + return thingHandler; + } + } + return null; + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + logger.debug("{}: Update '{}' with '{}'", getLogIdentifier(), channelUID.getAsString(), command.toString()); + } + + protected synchronized void refreshThing(IZoneMinderSession session, boolean fetchDiskUsage) { + + logger.debug("{}: 'refreshThing()': Thing='{}'!", getLogIdentifier(), this.getThing().getUID()); + + List channels = getThing().getChannels(); + List things = getThing().getThings(); + + IZoneMinderServer zoneMinderServerProxy = ZoneMinderFactory.getServerProxy(session); + if (zoneMinderServerProxy == null) { + logger.warn("{}: Could not obtain ZonerMinderServerProxy ", getLogIdentifier()); + + // Make sure old data is cleared + channelCpuLoad = ""; + channelDiskUsage = ""; + + } else if (isConnected()) { + /* + * Fetch data for Bridge + */ + IZoneMinderHostLoad hostLoad = null; + try { + hostLoad = zoneMinderServerProxy.getHostCpuLoad(); + logger.debug("{}: URL='{}' ResponseCode='{}' ResponseMessage='{}'", getLogIdentifier(), + zoneMinderServerProxy.getHttpUrl(), zoneMinderServerProxy.getHttpResponseCode(), + zoneMinderServerProxy.getHttpResponseMessage()); + + } catch (FailedLoginException | ZoneMinderUrlNotFoundException | IOException ex) { + logger.error("{}: Exception thrown in call to ZoneMinderHostLoad ('{}')", getLogIdentifier(), ex); + } + + if (hostLoad == null) { + logger.warn("{}: ZoneMinderHostLoad dataset could not be obtained (received 'null')", + getLogIdentifier()); + } else if (hostLoad.getHttpResponseCode() != 200) { + logger.warn( + "BRIDGE [{}]: ZoneMinderHostLoad dataset could not be obtained (HTTP Response: Code='{}', Message='{}')", + getThingId(), hostLoad.getHttpResponseCode(), hostLoad.getHttpResponseMessage()); + + } else { + channelCpuLoad = hostLoad.getCpuLoad().toString(); + } + + if (fetchDiskUsage) { + IZoneMinderDiskUsage diskUsage = null; + try { + diskUsage = zoneMinderServerProxy.getHostDiskUsage(); + logger.debug("{}: URL='{}' ResponseCode='{}' ResponseMessage='{}'", getLogIdentifier(), + zoneMinderServerProxy.getHttpUrl(), zoneMinderServerProxy.getHttpResponseCode(), + zoneMinderServerProxy.getHttpResponseMessage()); + } catch (Exception ex) { + logger.error("{}: Exception thrown in call to ZoneMinderDiskUsage ('{}')", getLogIdentifier(), ex); + } + + if (diskUsage == null) { + logger.warn("{}: ZoneMinderDiskUsage dataset could not be obtained (received 'null')", + getLogIdentifier()); + } else if (hostLoad.getHttpResponseCode() != 200) { + logger.warn( + "{}: ZoneMinderDiskUsage dataset could not be obtained (HTTP Response: Code='{}', Message='{}')", + getLogIdentifier(), hostLoad.getHttpResponseCode(), hostLoad.getHttpResponseMessage()); + + } else { + channelDiskUsage = diskUsage.getDiskUsage(); + } + } + + } else { + _online = false; + // Make sure old data is cleared + channelCpuLoad = ""; + channelDiskUsage = ""; + } + + /* + * Update all channels on Bridge + */ + for (Channel channel : channels) { + updateChannel(channel.getUID()); + } + + /* + * Request Things attached to Bridge to refresh + */ + for (Thing thing : things) { + try { + + if (thing.getThingTypeUID().equals(ZoneMinderConstants.THING_TYPE_THING_ZONEMINDER_MONITOR)) { + Thing thingMonitor = thing; + ZoneMinderBaseThingHandler thingHandler = (ZoneMinderBaseThingHandler) thing.getHandler(); + + thingHandler.refreshThing(session, DataRefreshPriorityEnum.SCHEDULED); + } + + } catch (NullPointerException ex) { + // This isn't critical (unless it comes over and over). There seems to be a bug so that a null + // pointer exception is coming every now and then. + // HAve to find the reason for that. Until thenm, don't Spamm + logger.debug("{}: Method 'refreshThing()' for Bridge {} failed for thing='{}' - Exception='{}'", + getLogIdentifier(), this.getZoneMinderId(), thing.getUID(), ex.getMessage()); + + // Other exceptions has to be shown as errors + } catch (Exception ex) { + logger.error("{}: Method 'refreshThing()' for Bridge {} failed for thing='{}' - Exception='{}'", + getLogIdentifier(), this.getZoneMinderId(), thing.getUID(), ex.getMessage()); + } + } + + } + + /** + * Returns connection status. + */ + public synchronized Boolean isConnected() { + return connected; + } + + public boolean isOnline() { + return _online; + } + + private synchronized boolean getConnected() { + return this.connected; + } + + /** + * Set connection status. + * + * @param connected + */ + private synchronized void setConnected(boolean connected) { + + if (this.connected != connected) { + if (connected) { + try { + zoneMinderSession = ZoneMinderFactory.CreateSession(zoneMinderConnection); + } catch (FailedLoginException | IllegalArgumentException | IOException + | ZoneMinderUrlNotFoundException e) { + logger.error("BRIDGE [{}]: Call to setConencted failed with exception '{}'", getThingId(), + e.getMessage()); + } + } else { + zoneMinderSession = null; + } + this.connected = connected; + + } + + } + + /** + * Set channel 'bridge_connection'. + * + * @param connected + */ + private void setBridgeConnectionStatus(boolean connected) { + logger.debug(" {}: setBridgeConnection(): Set Bridge to {}", getLogIdentifier(), + connected ? ThingStatus.ONLINE : ThingStatus.OFFLINE); + + Bridge bridge = getBridge(); + if (bridge != null) { + ThingStatus status = bridge.getStatus(); + logger.debug("{}: Bridge ThingStatus is: {}", getLogIdentifier(), status); + } + + setConnected(connected); + } + + /** + * Set channel 'bridge_connection'. + * + * @param connected + */ + private boolean getBridgeConnectionStatus() { + return getConnected(); + } + + /** + * Runs when connection established. + * + * @throws ZoneMinderUrlNotFoundException + * @throws IOException + * @throws GeneralSecurityException + * @throws IllegalArgumentException + */ + public void onConnected() { + logger.debug("BRIDGE [{}]: onConnected(): Bridge Connected!", getThingId()); + setConnected(true); + onBridgeConnected(this, zoneMinderConnection); + + // Inform thing handlers of connection + List things = getThing().getThings(); + + for (Thing thing : things) { + ZoneMinderBaseThingHandler thingHandler = (ZoneMinderBaseThingHandler) thing.getHandler(); + + if (thingHandler != null) { + try { + thingHandler.onBridgeConnected(this, zoneMinderConnection); + } catch (IllegalArgumentException | GeneralSecurityException | IOException + | ZoneMinderUrlNotFoundException e) { + logger.error("{}: onConnected() failed - Exceprion: {}", getLogIdentifier(), e.getMessage()); + } + logger.debug("{}: onConnected(): Bridge - {}, Thing - {}, Thing Handler - {}", getLogIdentifier(), + thing.getBridgeUID(), thing.getUID(), thingHandler); + } + } + } + + /** + * Runs when disconnected. + */ + private void onDisconnected() { + logger.debug("{}: onDisconnected(): Bridge Disconnected!", getLogIdentifier()); + setConnected(false); + onBridgeDisconnected(this); + + // Inform thing handlers of disconnection + List things = getThing().getThings(); + + for (Thing thing : things) { + ZoneMinderBaseThingHandler thingHandler = (ZoneMinderBaseThingHandler) thing.getHandler(); + + if (thingHandler != null) { + thingHandler.onBridgeDisconnected(this); + logger.debug("{}: onDisconnected(): Bridge - {}, Thing - {}, Thing Handler - {}", getLogIdentifier(), + thing.getBridgeUID(), thing.getUID(), thingHandler); + } + } + } + + @Override + public void updateAvaliabilityStatus(IZoneMinderConnectionInfo connection) { + ThingStatus newStatus = ThingStatus.OFFLINE; + ThingStatusDetail statusDetail = ThingStatusDetail.NONE; + String statusDescription = ""; + + boolean _isOnline = false; + + ThingStatus prevStatus = getThing().getStatus(); + + try { + // Just perform a health check to see if we are still connected + if (prevStatus == ThingStatus.ONLINE) { + if (zoneMinderSession == null) { + newStatus = ThingStatus.ONLINE; + statusDetail = ThingStatusDetail.NONE; + statusDescription = ""; + updateBridgeStatus(newStatus, statusDetail, statusDescription); + return; + } else if (!zoneMinderSession.isConnected()) { + newStatus = ThingStatus.OFFLINE; + statusDetail = ThingStatusDetail.COMMUNICATION_ERROR; + statusDescription = "Session lost connection to ZoneMinder Server"; + updateBridgeStatus(newStatus, statusDetail, statusDescription); + logger.error("{}: {}", getLogIdentifier(), statusDescription); + return; + } + + IZoneMinderServer serverProxy = ZoneMinderFactory.getServerProxy(zoneMinderSession); + IZoneMinderDaemonStatus daemonStatus = serverProxy.getHostDaemonCheckState(); + + // If service isn't running OR we revceived a http responsecode other than 200, assume we are offline + if ((!daemonStatus.getStatus()) || (daemonStatus.getHttpResponseCode() != 200)) { + newStatus = ThingStatus.OFFLINE; + statusDetail = ThingStatusDetail.COMMUNICATION_ERROR; + statusDescription = "ZoneMinder Server Daemon not running"; + + logger.error("{}: {} (state='{}' and ResponseCode='{}')", getLogIdentifier(), statusDescription, + daemonStatus.getStatus(), daemonStatus.getHttpResponseCode()); + updateBridgeStatus(newStatus, statusDetail, statusDescription); + return; + } + + // TODO:: Check other things without being harsh???? + + newStatus = ThingStatus.ONLINE; + statusDetail = ThingStatusDetail.NONE; + statusDescription = ""; + } + // If we are OFFLINE, check everything + else if (prevStatus == ThingStatus.OFFLINE) { + + // Just wait until we are finished initializing + if (isInitialized == false) { + _online = _isOnline; + return; + } + + ZoneMinderBridgeServerConfig config = getBridgeConfig(); + + // Check if server Bridge configuration is valid + if (config == null) { + newStatus = ThingStatus.OFFLINE; + statusDetail = ThingStatusDetail.CONFIGURATION_ERROR; + statusDescription = "Configuration not found"; + logger.error("{}: Bridge OFFLINE because of '{}'", getLogIdentifier(), statusDescription); + updateBridgeStatus(newStatus, statusDetail, statusDescription); + return; + + } else if (config.getHostName() == null) { + newStatus = ThingStatus.OFFLINE; + statusDetail = ThingStatusDetail.CONFIGURATION_ERROR; + statusDescription = "Host not found in configuration"; + logger.error("{}: Bridge OFFLINE because of '{}'", getLogIdentifier(), statusDescription); + updateBridgeStatus(newStatus, statusDetail, statusDescription); + return; + } else if (config.getProtocol() == null) { + newStatus = ThingStatus.OFFLINE; + statusDetail = ThingStatusDetail.CONFIGURATION_ERROR; + statusDescription = "Unknown protocol in configuration"; + logger.error("{}: Bridge OFFLINE because of '{}'", getLogIdentifier(), statusDescription); + updateBridgeStatus(newStatus, statusDetail, statusDescription); + return; + } + + else if (config.getHttpPort() == null) { + newStatus = ThingStatus.OFFLINE; + statusDetail = ThingStatusDetail.CONFIGURATION_ERROR; + statusDescription = "Invalid HTTP port"; + logger.error("{}: Bridge OFFLINE because of '{}'", getLogIdentifier(), statusDescription); + updateBridgeStatus(newStatus, statusDetail, statusDescription); + return; + } + + else if (config.getTelnetPort() == null) { + newStatus = ThingStatus.OFFLINE; + statusDetail = ThingStatusDetail.CONFIGURATION_ERROR; + statusDescription = "Invalid telnet port"; + logger.error("{}: Bridge OFFLINE because of '{}'", getLogIdentifier(), statusDescription); + updateBridgeStatus(newStatus, statusDetail, statusDescription); + return; + } else if (!ZoneMinderFactory.isZoneMinderUrl(connection)) { + newStatus = ThingStatus.OFFLINE; + statusDetail = ThingStatusDetail.CONFIGURATION_ERROR; + statusDescription = "URL not a ZoneMinder Server"; + logger.error("{}: Bridge OFFLINE because of '{}'", getLogIdentifier(), statusDescription); + updateBridgeStatus(newStatus, statusDetail, statusDescription); + return; + } + + if (!isZoneMinderLoginValid(connection)) { + newStatus = ThingStatus.OFFLINE; + statusDetail = ThingStatusDetail.CONFIGURATION_ERROR; + statusDescription = "Cannot access ZoneMinder Server. Check provided usercredentials"; + logger.error("{}: Bridge OFFLINE because of '{}'", getLogIdentifier(), statusDescription); + updateBridgeStatus(newStatus, statusDetail, statusDescription); + return; + } + + /* + * Now we will try to establish a session + */ + + IZoneMinderSession curSession = null; + try { + curSession = ZoneMinderFactory.CreateSession(connection); + } catch (FailedLoginException | IllegalArgumentException | IOException + | ZoneMinderUrlNotFoundException ex) { + logger.error("{}: Create Session failed with exception {}", getLogIdentifier(), ex.getMessage()); + + newStatus = ThingStatus.OFFLINE; + statusDetail = ThingStatusDetail.COMMUNICATION_ERROR; + statusDescription = "Failed to connect. (Check Log)"; + logger.error("{}: Bridge OFFLINE because of '{}' Exception='{}'", getLogIdentifier(), + statusDescription, ex.getMessage()); + + updateBridgeStatus(newStatus, statusDetail, statusDescription); + return; + } + IZoneMinderServer serverProxy = ZoneMinderFactory.getServerProxy(curSession); + + // Check if server API can be accessed + if (!serverProxy.isApiEnabled()) { + newStatus = ThingStatus.OFFLINE; + statusDetail = ThingStatusDetail.CONFIGURATION_ERROR; + statusDescription = "ZoneMinder Server 'OPT_USE_API' not enabled"; + logger.error("{}: Bridge OFFLINE because of '{}'", getLogIdentifier(), statusDescription); + updateBridgeStatus(newStatus, statusDetail, statusDescription); + return; + + } else if (!serverProxy.getHostDaemonCheckState().getStatus()) { + newStatus = ThingStatus.OFFLINE; + statusDetail = ThingStatusDetail.CONFIGURATION_ERROR; + statusDescription = "ZoneMinder Server Daemon not running"; + logger.error("{}: Bridge OFFLINE because of '{}'", getLogIdentifier(), statusDescription); + updateBridgeStatus(newStatus, statusDetail, statusDescription); + return; + } + // Verify that 'OPT_TRIGGER' is set to true in ZoneMinder + else if (!serverProxy.isTriggerOptionEnabled()) { + newStatus = ThingStatus.OFFLINE; + statusDetail = ThingStatusDetail.CONFIGURATION_ERROR; + statusDescription = "ZoneMinder Server option 'OPT_TRIGGERS' not enabled"; + logger.error("{}: Bridge OFFLINE because of '{}'", getLogIdentifier(), statusDescription); + updateBridgeStatus(newStatus, statusDetail, statusDescription); + return; + } else { + // Seems like everything is as we want it :-) + _isOnline = true; + } + + if (_isOnline == true) { + zoneMinderSession = curSession; + _online = _isOnline; + newStatus = ThingStatus.ONLINE; + statusDetail = ThingStatusDetail.NONE; + statusDescription = ""; + + } else { + zoneMinderSession = null; + _online = _isOnline; + newStatus = ThingStatus.OFFLINE; + } + } + + } catch (Exception ex) { + newStatus = ThingStatus.OFFLINE; + statusDetail = ThingStatusDetail.COMMUNICATION_ERROR; + logger.error("{}: Exception occurred in updateAvailabilityStatus Exception='{}'", getLogIdentifier(), + ex.getMessage()); + statusDescription = "Error occurred (Check log)"; + + } + updateBridgeStatus(newStatus, statusDetail, statusDescription); + + // Ask child things to update their Availability Status + for (Thing thing : getThing().getThings()) { + ZoneMinderBaseThingHandler thingHandler = (ZoneMinderBaseThingHandler) thing.getHandler(); + if (thingHandler instanceof ZoneMinderThingMonitorHandler) { + try { + thingHandler.updateAvaliabilityStatus(connection); + } catch (Exception ex) { + logger.debug("{}: Failed to call 'updateAvailabilityStatus()' for '{}'", getLogIdentifier(), + thingHandler.getThing().getUID()); + } + } + + } + + } + + protected void updateBridgeStatus(ThingStatus newStatus, ThingStatusDetail statusDetail, String statusDescription) { + ThingStatusInfo curStatusInfo = thing.getStatusInfo(); + // Status changed + if ((curStatusInfo.getStatus() != newStatus) || (curStatusInfo.getStatusDetail() != statusDetail) + || (curStatusInfo.getDescription() != statusDescription)) { + + // if (thing.getStatus() != newStatus) { + logger.info("{}: Bridge status changed from '{}' to '{}'", getLogIdentifier(), thing.getStatus(), + newStatus); + + if ((newStatus == ThingStatus.ONLINE) && (curStatusInfo.getStatus() != ThingStatus.ONLINE)) { + try { + setBridgeConnectionStatus(true); + onConnected(); + } catch (IllegalArgumentException e) { + // Just ignore that here + } + } else if ((newStatus == ThingStatus.OFFLINE) && (curStatusInfo.getStatus() != ThingStatus.OFFLINE)) { + try { + setBridgeConnectionStatus(false); + onDisconnected(); + } catch (IllegalArgumentException e) { + // Just ignore that here + } + + } + // Update Status correspondingly + if ((newStatus == ThingStatus.OFFLINE) && (statusDetail != ThingStatusDetail.NONE)) { + updateStatus(newStatus, statusDetail, statusDescription); + } else { + updateStatus(newStatus); + } + } + } + + protected boolean isZoneMinderLoginValid(IZoneMinderConnectionInfo connection) { + try { + return ZoneMinderFactory.validateLogin(connection); + } catch (Exception e) { + return false; + } + + } + + @Override + public void updateChannel(ChannelUID channel) { + State state = null; + try { + + switch (channel.getId()) { + case ZoneMinderConstants.CHANNEL_ONLINE: + updateState(channel, (isOnline() ? OnOffType.ON : OnOffType.OFF)); + break; + + case ZoneMinderConstants.CHANNEL_SERVER_DISKUSAGE: + state = getServerDiskUsageState(); + break; + + case ZoneMinderConstants.CHANNEL_SERVER_CPULOAD: + state = getServerCpuLoadState(); + break; + + default: + logger.warn("{}: updateChannel(): Server '{}': No handler defined for channel='{}'", + getLogIdentifier(), thing.getLabel(), channel.getAsString()); + break; + } + + if (state != null) { + logger.debug("{}: BridgeHandler.updateChannel(): Updating channel '{}' to state='{}'", + getLogIdentifier(), channel.getId(), state.toString()); + updateState(channel.getId(), state); + } + } catch (Exception ex) { + + logger.error("{}: Error when 'updateChannel()' was called for thing='{}' (Exception='{}'", + getLogIdentifier(), channel.getId(), ex.getMessage()); + + } + } + + protected boolean openConnection() { + boolean connected = false; + if (isConnected() == false) { + logger.debug("{}: Connecting Bridge to ZoneMinder Server", getLogIdentifier()); + + try { + if (isConnected()) { + closeConnection(); + } + setConnected(connected); + + logger.info("{}: Connecting to ZoneMinder Server (result='{}'", getLogIdentifier(), connected); + + } catch (Exception exception) { + logger.error("{}: openConnection(): Exception: ", getLogIdentifier(), exception); + setConnected(false); + } finally { + if (isConnected() == false) { + closeConnection(); + } + } + + } + return isConnected(); + } + + synchronized void closeConnection() { + try { + logger.debug("{}: closeConnection(): Closed HTTP Connection!", getLogIdentifier()); + setConnected(false); + + } catch (Exception exception) { + logger.error("{}: closeConnection(): Error closing connection - {}", getLogIdentifier(), + exception.getMessage()); + } + + } + + protected State getServerCpuLoadState() { + + State state = UnDefType.UNDEF; + + try { + if ((channelCpuLoad != "") && (isConnected())) { + state = new DecimalType(new BigDecimal(channelCpuLoad)); + } + + } catch (Exception ex) { + // Deliberately kept as debug info! + logger.debug("{}: Exception='{}'", getLogIdentifier(), ex.getMessage()); + } + + return state; + } + + protected State getServerDiskUsageState() { + + State state = UnDefType.UNDEF; + + try { + if ((channelDiskUsage != "") && (isConnected())) { + state = new DecimalType(new BigDecimal(channelDiskUsage)); + } + } catch (Exception ex) { + // Deliberately kept as debug info! + logger.debug("{}: Exception {}", getLogIdentifier(), ex.getMessage()); + } + + return state; + } + + @Override + public void onBridgeConnected(ZoneMinderServerBridgeHandler bridge, IZoneMinderConnectionInfo connection) { + logger.info("{}: Brigde went ONLINE", getLogIdentifier()); + + try { + // Start the discovery service + if (discoveryService == null) { + discoveryService = new ZoneMinderDiscoveryService(this, 30); + } + discoveryService.activate(); + + if (discoveryRegistration == null) { + // And register it as an OSGi service + discoveryRegistration = bundleContext.registerService(DiscoveryService.class.getName(), + discoveryService, new Hashtable()); + } + } catch (Exception e) { + logger.error("BRIDGE [{}]: Exception occurred when starting discovery service Exception='{}'", getThingId(), + e.getMessage()); + + } + + if (taskRefreshData == null) { + + // Perform first refresh manually (we want to force update of DiskUsage) + boolean updateDiskUsage = (getBridgeConfig().getRefreshIntervalLowPriorityTask() > 0) ? true : false; + refreshThing(zoneMinderSession, updateDiskUsage); + + if (getBridgeConfig().getRefreshIntervalLowPriorityTask() != 0) { + refreshFrequency = calculateCommonRefreshFrequency(getBridgeConfig().getRefreshInterval()); + } else { + refreshFrequency = getBridgeConfig().getRefreshInterval(); + } + logger.info("BRIDGE [{}]: Calculated refresh inetrval to '{}'", getThingId(), refreshFrequency); + + if (taskRefreshData != null) { + taskRefreshData.cancel(true); + taskRefreshData = null; + } + + // Start job to handle next updates + taskRefreshData = startTask(refreshDataRunnable, refreshFrequency, refreshFrequency, TimeUnit.SECONDS); + + if (taskPriorityRefreshData != null) { + taskPriorityRefreshData.cancel(true); + taskPriorityRefreshData = null; + } + + // Only start if it is not running and Priority Frequency is higher than ordinary + if ((taskPriorityRefreshData == null) && (refreshFrequency > 1)) { + taskPriorityRefreshData = startTask(refreshPriorityDataRunnable, 0, 1, TimeUnit.SECONDS); + } + } + + // Update properties + updateMonitorProperties(zoneMinderSession); + } + + @Override + public void onBridgeDisconnected(ZoneMinderServerBridgeHandler bridge) { + logger.info("{}: Brigde went OFFLINE", getLogIdentifier()); + + // Deactivate discovery service + discoveryService.deactivate(); + + // Stopping refresh thread while OFFLINE + if (taskRefreshData != null) { + taskRefreshData.cancel(true); + taskRefreshData = null; + logger.debug("{}: Stopping DataRefresh task", getLogIdentifier()); + } + + // Stopping High priority thread while OFFLINE + if (taskPriorityRefreshData != null) { + taskPriorityRefreshData.cancel(true); + taskPriorityRefreshData = null; + logger.debug("{}: Stopping Priority DataRefresh task", getLogIdentifier()); + } + + // Make sure everything gets refreshed + for (Channel ch : getThing().getChannels()) { + handleCommand(ch.getUID(), RefreshType.REFRESH); + } + + // Inform thing handlers of disconnection + for (Thing thing : getThing().getThings()) { + ZoneMinderBaseThingHandler thingHandler = (ZoneMinderBaseThingHandler) thing.getHandler(); + + if (thingHandler != null) { + thingHandler.onBridgeDisconnected(this); + logger.debug("{}: onDisconnected(): Bridge - {}, Thing - {}, Thing Handler - {}", getLogIdentifier(), + thing.getBridgeUID(), thing.getUID(), thingHandler); + } + } + + } + + /** + * Method to start a data refresh task. + */ + protected ScheduledFuture startTask(Runnable command, long delay, long interval, TimeUnit unit) { + ScheduledFuture task = null; + logger.debug("BRIDGE [{}]: Starting ZoneMinder Bridge Monitor Task. Command='{}'", getThingId(), + command.toString()); + if (interval == 0) { + return task; + } + + if (task == null || task.isCancelled()) { + task = scheduler.scheduleWithFixedDelay(command, delay, interval, unit); + } + return task; + } + + /** + * Method to stop the datarefresh task. + */ + protected void stopTask(ScheduledFuture task) { + try { + logger.debug("{}: Stopping ZoneMinder Bridge Monitor Task. Task='{}'", getLogIdentifier(), task.toString()); + if (task != null && !task.isCancelled()) { + task.cancel(true); + } + } catch (Exception ex) { + } + + } + + public ArrayList getMonitors() { + if (isOnline()) { + + IZoneMinderServer serverProxy = ZoneMinderFactory.getServerProxy(zoneMinderSession); + ArrayList result = serverProxy.getMonitors(); + + return result; + } + return new ArrayList(); + } + + /* + * This is experimental + * Try to add different properties + */ + private void updateMonitorProperties(IZoneMinderSession session) { + // Update property information about this device + Map properties = editProperties(); + IZoneMinderServer serverProxy = ZoneMinderFactory.getServerProxy(session); + + IZoneMinderHostVersion hostVersion = null; + try { + hostVersion = serverProxy.getHostVersion(); + logger.debug("{}: URL='{}' ResponseCode='{}' ResponseMessage='{}'", getLogIdentifier(), + serverProxy.getHttpUrl(), serverProxy.getHttpResponseCode(), serverProxy.getHttpResponseMessage()); + + ZoneMinderConfig configUseApi = serverProxy.getConfig(ZoneMinderConfigEnum.ZM_OPT_USE_API); + logger.debug("{}: URL='{}' ResponseCode='{}' ResponseMessage='{}'", getLogIdentifier(), + serverProxy.getHttpUrl(), serverProxy.getHttpResponseCode(), serverProxy.getHttpResponseMessage()); + + ZoneMinderConfig configUseAuth = serverProxy.getConfig(ZoneMinderConfigEnum.ZM_OPT_USE_AUTH); + logger.debug("{}: URL='{}' ResponseCode='{}' ResponseMessage='{}'", getLogIdentifier(), + serverProxy.getHttpUrl(), serverProxy.getHttpResponseCode(), serverProxy.getHttpResponseMessage()); + + ZoneMinderConfig configTrigerrs = serverProxy.getConfig(ZoneMinderConfigEnum.ZM_OPT_TRIGGERS); + logger.debug("{}: URL='{}' ResponseCode='{}' ResponseMessage='{}'", getLogIdentifier(), + configUseApi.getHttpUrl(), configUseApi.getHttpResponseCode(), + configUseApi.getHttpResponseMessage()); + + properties.put(ZoneMinderProperties.PROPERTY_SERVER_VERSION, hostVersion.getVersion()); + properties.put(ZoneMinderProperties.PROPERTY_SERVER_API_VERSION, hostVersion.getApiVersion()); + properties.put(ZoneMinderProperties.PROPERTY_SERVER_USE_API, configUseApi.getValueAsString()); + properties.put(ZoneMinderProperties.PROPERTY_SERVER_USE_AUTHENTIFICATION, configUseAuth.getValueAsString()); + properties.put(ZoneMinderProperties.PROPERTY_SERVER_TRIGGERS_ENABLED, configTrigerrs.getValueAsString()); + } catch (FailedLoginException | ZoneMinderUrlNotFoundException | IOException e) { + logger.warn("{}: Exception occurred when updating monitor properties (Exception='{}'", getLogIdentifier(), + e.getMessage()); + } + + // Must loop over the new properties since we might have added data + boolean update = false; + Map originalProperties = editProperties(); + for (String property : properties.keySet()) { + if ((originalProperties.get(property) == null + || originalProperties.get(property).equals(properties.get(property)) == false)) { + update = true; + break; + } + } + + if (update == true) { + logger.info("{}: Properties synchronised", getLogIdentifier(), getThingId()); + updateProperties(properties); + } + } + + @Override + public String getLogIdentifier() { + String result = "[BRIDGE]"; + try { + result = String.format("[BRIDGE (%s)]", getThingId()); + } catch (Exception e) { + result = "[BRIDGE (?)]"; + } + return result; + } +} diff --git a/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/handler/ZoneMinderThingMonitorHandler.java b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/handler/ZoneMinderThingMonitorHandler.java new file mode 100644 index 0000000000000..48afaf3993829 --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/handler/ZoneMinderThingMonitorHandler.java @@ -0,0 +1,874 @@ +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.zoneminder.handler; + +import java.io.IOException; +import java.math.BigDecimal; +import java.security.GeneralSecurityException; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.Channel; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.eclipse.smarthome.core.types.State; +import org.eclipse.smarthome.core.types.UnDefType; +import org.openhab.binding.zoneminder.ZoneMinderConstants; +import org.openhab.binding.zoneminder.ZoneMinderProperties; +import org.openhab.binding.zoneminder.internal.DataRefreshPriorityEnum; +import org.openhab.binding.zoneminder.internal.config.ZoneMinderThingMonitorConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.Sets; + +import name.eskildsen.zoneminder.IZoneMinderConnectionInfo; +import name.eskildsen.zoneminder.IZoneMinderDaemonStatus; +import name.eskildsen.zoneminder.IZoneMinderEventSubscriber; +import name.eskildsen.zoneminder.IZoneMinderMonitor; +import name.eskildsen.zoneminder.IZoneMinderMonitorData; +import name.eskildsen.zoneminder.IZoneMinderSession; +import name.eskildsen.zoneminder.ZoneMinderFactory; +import name.eskildsen.zoneminder.api.event.ZoneMinderEvent; +import name.eskildsen.zoneminder.api.telnet.ZoneMinderTriggerEvent; +import name.eskildsen.zoneminder.common.ZoneMinderMonitorFunctionEnum; +import name.eskildsen.zoneminder.common.ZoneMinderMonitorStatusEnum; +import name.eskildsen.zoneminder.exception.ZoneMinderUrlNotFoundException; + +/** + * The {@link ZoneMinderThingMonitorHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Martin S. Eskildsen - Initial contribution + */ +public class ZoneMinderThingMonitorHandler extends ZoneMinderBaseThingHandler implements IZoneMinderEventSubscriber { + + public static final Set SUPPORTED_THING_TYPES = Sets + .newHashSet(ZoneMinderConstants.THING_TYPE_THING_ZONEMINDER_MONITOR); + + private static final String MONITOR_STATUS_NOT_INIT = ""; + private static final int MAX_MONITOR_STATUS_WATCH_COUNT = 3; + + /** Make sure we can log errors, warnings or what ever somewhere */ + private Logger logger = LoggerFactory.getLogger(ZoneMinderThingMonitorHandler.class); + + private String lastMonitorStatus = MONITOR_STATUS_NOT_INIT; + private Integer monitorStatusMatchCount = 3; + + private ZoneMinderThingMonitorConfig config; + + private Boolean _running = false; + + private ZoneMinderEvent curEvent = null; + + /** + * Channels + */ + private ZoneMinderMonitorFunctionEnum channelFunction = ZoneMinderMonitorFunctionEnum.NONE; + private Boolean channelEnabled = false; + private boolean channelRecordingState = false; + private boolean channelAlarmedState = false; + private String channelEventCause = ""; + private ZoneMinderMonitorStatusEnum channelMonitorStatus = ZoneMinderMonitorStatusEnum.UNKNOWN; + private boolean channelDaemonCapture = false; + private boolean channelDaemonAnalysis = false; + private boolean channelDaemonFrame = false; + private boolean channelForceAlarm = false; + + private int forceAlarmManualState = -1; + + public ZoneMinderThingMonitorHandler(Thing thing) { + super(thing); + + logger.info("{}: Starting ZoneMinder Server Thing Handler (Thing='{}')", getLogIdentifier(), thing.getUID()); + } + + @Override + public void dispose() { + } + + @Override + public String getZoneMinderId() { + if (config == null) { + logger.error("{}: Configuration for Thing '{}' is not loaded correctly.", getLogIdentifier(), + getThing().getUID()); + return ""; + } + return config.getZoneMinderId().toString(); + + } + + @Override + public void onBridgeConnected(ZoneMinderServerBridgeHandler bridge, IZoneMinderConnectionInfo connection) + throws IllegalArgumentException, GeneralSecurityException, IOException, ZoneMinderUrlNotFoundException { + + try { + logger.info("{}: Bridge '{}' connected", getLogIdentifier(), bridge.getThing().getUID().getAsString()); + super.onBridgeConnected(bridge, connection); + + ZoneMinderFactory.SubscribeMonitorEvents(connection, config.getZoneMinderId(), this); + IZoneMinderSession session = aquireSession(); + IZoneMinderMonitor monitor = ZoneMinderFactory.getMonitorProxy(session, config.getZoneMinderId()); + IZoneMinderMonitorData monitorData = monitor.getMonitorData(); + + logger.debug("{}: SourceType: {}", getLogIdentifier(), monitorData.getSourceType().name()); + logger.debug("{}: Format: {}", getLogIdentifier(), monitorData.getFormat()); + logger.debug("{}: AlarmFrameCount: {}", getLogIdentifier(), monitorData.getAlarmFrameCount()); + logger.debug("{}: AlarmMaxFPS: {}", getLogIdentifier(), monitorData.getAlarmMaxFPS()); + logger.debug("{}: AnalysisFPS: {}", getLogIdentifier(), monitorData.getAnalysisFPS()); + logger.debug("{}: Height x Width: {} x {}", getLogIdentifier(), monitorData.getHeight(), + monitorData.getWidth()); + + updateMonitorProperties(session); + + } catch (Exception ex) { + logger.error("{}: Exception occurred when calling 'onBridgeConencted()'. Exception='{}'", + getLogIdentifier(), ex.getMessage()); + + } finally { + releaseSession(); + } + + } + + @Override + public void onBridgeDisconnected(ZoneMinderServerBridgeHandler bridge) { + try { + logger.info("{}: Bridge '{}' disconnected", getLogIdentifier(), bridge.getThing().getUID().getAsString()); + + logger.info("{}: Unsubscribing from Monitor Events", getLogIdentifier(), + bridge.getThing().getUID().getAsString()); + ZoneMinderFactory.UnsubscribeMonitorEvents(config.getZoneMinderId(), this); + + logger.debug("{}: Calling parent onBridgeConnected()", getLogIdentifier()); + super.onBridgeDisconnected(bridge); + + } catch (Exception ex) { + logger.error("{}: Exception occurred when calling 'onBridgeDisonencted()'. Exception='{}'", + getLogIdentifier(), ex.getMessage()); + + } + + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + + try { + + logger.debug("{}: Channel '{}' in monitor '{}' received command='{}'", getLogIdentifier(), channelUID, + getZoneMinderId(), command); + + // Allow refresh of channels + if (command == RefreshType.REFRESH) { + updateChannel(channelUID); + return; + } + + // Communication TO Monitor + switch (channelUID.getId()) { + + // Done via Telnet connection + case ZoneMinderConstants.CHANNEL_MONITOR_FORCE_ALARM: + logger.debug( + "{}: 'handleCommand' => CHANNEL_MONITOR_FORCE_ALARM: Command '{}' received for monitor '{}'", + getLogIdentifier(), command, channelUID.getId()); + + if ((command == OnOffType.OFF) || (command == OnOffType.ON)) { + String eventText = getConfigValueAsString(ZoneMinderConstants.PARAMETER_MONITOR_EVENTTEXT); + + BigDecimal eventTimeout = getConfigValueAsBigDecimal( + ZoneMinderConstants.PARAMETER_MONITOR_TRIGGER_TIMEOUT); + + ZoneMinderServerBridgeHandler bridge = getZoneMinderBridgeHandler(); + if (bridge == null) { + logger.warn("'handleCommand()': Bridge is 'null'!"); + } + + IZoneMinderMonitor monitorProxy = ZoneMinderFactory.getMonitorProxy(aquireSession(), + getZoneMinderId()); + try { + if (command == OnOffType.ON) { + forceAlarmManualState = 1; + logger.info("{}: Activate 'ForceAlarm' to '{}' (Reason='{}', Timeout='{}')", + getLogIdentifier(), command, eventText, eventTimeout.intValue()); + + monitorProxy.activateForceAlarm(255, ZoneMinderConstants.MONITOR_EVENT_OPENHAB, + eventText, "", eventTimeout.intValue()); + + } + + else if (command == OnOffType.OFF) { + forceAlarmManualState = 0; + logger.info("{}: Cancel 'ForceAlarm'", getLogIdentifier()); + monitorProxy.deactivateForceAlarm(); + + } + + } finally { + releaseSession(); + } + + RecalculateChannelStates(); + + handleCommand(channelUID, RefreshType.REFRESH); + handleCommand(getChannelUIDFromChannelId(ZoneMinderConstants.CHANNEL_MONITOR_EVENT_STATE), + RefreshType.REFRESH); + handleCommand(getChannelUIDFromChannelId(ZoneMinderConstants.CHANNEL_MONITOR_RECORD_STATE), + RefreshType.REFRESH); + + // Force a refresh + startPriorityRefresh(); + + } + break; + + case ZoneMinderConstants.CHANNEL_MONITOR_ENABLED: + logger.debug( + "{}: 'handleCommand' => CHANNEL_MONITOR_ENABLED: Command '{}' received for monitor '{}'", + getLogIdentifier(), command, channelUID.getId()); + + if ((command == OnOffType.OFF) || (command == OnOffType.ON)) { + boolean newState = ((command == OnOffType.ON) ? true : false); + + IZoneMinderMonitor monitorProxy = ZoneMinderFactory.getMonitorProxy(aquireSession(), + getZoneMinderId()); + try { + monitorProxy.SetEnabled(newState); + } finally { + releaseSession(); + } + + channelEnabled = newState; + + logger.info("{}: Setting enabled to '{}'", getLogIdentifier(), command); + } + + handleCommand(channelUID, RefreshType.REFRESH); + break; + + case ZoneMinderConstants.CHANNEL_MONITOR_FUNCTION: + String commandString = ""; + if (ZoneMinderMonitorFunctionEnum.isValid(command.toString())) { + + commandString = ZoneMinderMonitorFunctionEnum.getEnum(command.toString()).toString(); + ZoneMinderServerBridgeHandler bridge = getZoneMinderBridgeHandler(); + + IZoneMinderMonitor monitorProxy = ZoneMinderFactory.getMonitorProxy(aquireSession(), + getZoneMinderId()); + try { + monitorProxy.SetFunction(commandString); + } finally { + releaseSession(); + } + + // Make sure local copy is set to new value + channelFunction = ZoneMinderMonitorFunctionEnum.getEnum(command.toString()); + + logger.info("{}: Setting function to '{}'", getLogIdentifier(), commandString); + + } else { + logger.error( + "{}: Value '{}' for monitor channel is not valid. Accepted values is: 'None', 'Monitor', 'Modect', Record', 'Mocord', 'Nodect'", + getLogIdentifier(), commandString); + } + handleCommand(channelUID, RefreshType.REFRESH); + break; + + // They are all readonly in the channel config. + case ZoneMinderConstants.CHANNEL_MONITOR_EVENT_STATE: + case ZoneMinderConstants.CHANNEL_MONITOR_DETAILED_STATUS: + case ZoneMinderConstants.CHANNEL_MONITOR_RECORD_STATE: + case ZoneMinderConstants.CHANNEL_ONLINE: + case ZoneMinderConstants.CHANNEL_MONITOR_EVENT_CAUSE: + case ZoneMinderConstants.CHANNEL_MONITOR_CAPTURE_DAEMON_STATE: + case ZoneMinderConstants.CHANNEL_MONITOR_ANALYSIS_DAEMON_STATE: + case ZoneMinderConstants.CHANNEL_MONITOR_FRAME_DAEMON_STATE: + // Do nothing, they are all read only + break; + default: + logger.warn("{}: Command received for an unknown channel: {}", getLogIdentifier(), + channelUID.getId()); + break; + } + } catch (Exception ex) { + logger.error("{}: handleCommand: Command='{}' failed for channel='{}' Exception='{}'", getLogIdentifier(), + command, channelUID.getId(), ex.getMessage()); + } + } + + @Override + public void initialize() { + + try { + super.initialize(); + this.config = getMonitorConfig(); + logger.info("{}: ZoneMinder Monitor Handler Initialized", getLogIdentifier()); + logger.debug("{}: Monitor Id: {}", getLogIdentifier(), config.getZoneMinderId()); + } catch (Exception ex) { + logger.error("{}: Exception occurred when calling 'initialize()'. Exception='{}'", getLogIdentifier(), + ex.getMessage()); + } + } + + @Override + public void onTrippedForceAlarm(ZoneMinderTriggerEvent event) { + try { + logger.info("{}: Received forceAlarm for monitor {}", getLogIdentifier(), event.getMonitorId()); + Channel channel = this.getThing().getChannel(ZoneMinderConstants.CHANNEL_MONITOR_DETAILED_STATUS); + Channel chEventCause = this.getThing().getChannel(ZoneMinderConstants.CHANNEL_MONITOR_EVENT_CAUSE); + + // Set Current Event to actual event + if (event.getState()) { + startPriorityRefresh(); + + } else { + curEvent = null; + } + } catch (Exception ex) { + logger.error("{}: Exception occurred inTrippedForceAlarm() Exception='{}'", getLogIdentifier(), + ex.getMessage()); + + } + } + + protected ZoneMinderThingMonitorConfig getMonitorConfig() { + return this.getConfigAs(ZoneMinderThingMonitorConfig.class); + } + + @Override + protected String getZoneMinderThingType() { + return ZoneMinderConstants.THING_ZONEMINDER_MONITOR; + } + + private Boolean isDaemonRunning(Boolean daemonStatus, String daemonStatusText) { + Boolean result = false; + + Pattern pattern = Pattern + .compile("[0-9]{2}/[0-9]{2}/[0-9]{2}\\s+([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]"); + + Matcher matcher = pattern.matcher(daemonStatusText); + + if (matcher.find()) { + + String currentMonitorStatus = daemonStatusText.substring(matcher.start(), matcher.end()); + if (lastMonitorStatus.equals(currentMonitorStatus)) { + monitorStatusMatchCount++; + } else if (lastMonitorStatus.equals(MONITOR_STATUS_NOT_INIT)) { + // We have just started, so we will assume that the monitor is running (don't set match count + // to Zero) + monitorStatusMatchCount++; + lastMonitorStatus = daemonStatusText.substring(matcher.start(), matcher.end()); + } else { + monitorStatusMatchCount = 0; + lastMonitorStatus = daemonStatusText.substring(matcher.start(), matcher.end()); + } + } + + else { + monitorStatusMatchCount = 0; + lastMonitorStatus = ""; + logger.debug("MONITOR-{}: Online(): No match found in status text.", getLogIdentifier()); + } + return daemonStatus; + } + + @Override + public void updateAvaliabilityStatus(IZoneMinderConnectionInfo connection) { + // Assume succes + ThingStatus newThingStatus = ThingStatus.ONLINE; + ThingStatusDetail thingStatusDetailed = ThingStatusDetail.NONE; + String thingStatusDescription = ""; + + ThingStatus curThingStatus = this.getThing().getStatus(); + + boolean connectionStatus = false; + // Is connected to ZoneMinder and thing is ONLINE + if (isConnected() && curThingStatus == ThingStatus.ONLINE) { + updateThingStatus(newThingStatus, thingStatusDetailed, thingStatusDescription); + return; + } + + try { + connectionStatus = ZoneMinderFactory.validateConnection(connection); + } catch (IllegalArgumentException e) { + logger.error("{}: validateConnection failed with exception='{}'", getLogIdentifier(), e.getMessage()); + newThingStatus = ThingStatus.OFFLINE; + thingStatusDetailed = ThingStatusDetail.COMMUNICATION_ERROR; + thingStatusDescription = "Could not connect to thing"; + updateThingStatus(newThingStatus, thingStatusDetailed, thingStatusDescription); + return; + } + + try { + String msg; + Bridge b = getBridge(); + + // 1. Is there a Bridge assigned? + if (getBridge() == null) { + msg = String.format("No Bridge assigned to monitor '%s'", thing.getUID()); + logger.error("{}: {}", getLogIdentifier(), msg); + newThingStatus = ThingStatus.OFFLINE; + thingStatusDetailed = ThingStatusDetail.BRIDGE_OFFLINE; + thingStatusDescription = "No Bridge assigned to monitor"; + updateThingStatus(newThingStatus, thingStatusDetailed, thingStatusDescription); + return; + } else { + logger.debug("{}: ThingAvailability: Thing '{}' has Bridge '{}' defined (Check PASSED)", + getLogIdentifier(), thing.getUID(), getBridge().getBridgeUID()); + } + + // 2. Is Bridge Online? + if (getBridge().getStatus() != ThingStatus.ONLINE) { + msg = String.format("Bridge '%s' is OFFLINE", getBridge().getBridgeUID()); + newThingStatus = ThingStatus.OFFLINE; + thingStatusDetailed = ThingStatusDetail.BRIDGE_OFFLINE; + thingStatusDescription = msg; + updateThingStatus(newThingStatus, thingStatusDetailed, thingStatusDescription); + logger.error("{}: {}", getLogIdentifier(), msg); + return; + } else { + logger.debug("{}: ThingAvailability: Bridge '{}' is ONLINE (Check PASSED)", getLogIdentifier(), + getBridge().getBridgeUID()); + } + + // 3. Is Configuration OK? + if (getMonitorConfig() == null) { + msg = String.format("No valid configuration found for '%s'", thing.getUID()); + newThingStatus = ThingStatus.OFFLINE; + thingStatusDetailed = ThingStatusDetail.CONFIGURATION_ERROR; + thingStatusDescription = msg; + updateThingStatus(newThingStatus, thingStatusDetailed, thingStatusDescription); + + logger.error("{}: {}", getLogIdentifier(), msg); + return; + } else { + logger.debug("{}: ThingAvailability: Thing '{}' has valid configuration (Check PASSED)", + getLogIdentifier(), thing.getUID()); + } + + // ZoneMinder Id for Monitor not set, we are pretty much lost then + if (getMonitorConfig().getZoneMinderId().isEmpty()) { + msg = String.format("No Id is specified for monitor '%s'", thing.getUID()); + newThingStatus = ThingStatus.OFFLINE; + thingStatusDetailed = ThingStatusDetail.CONFIGURATION_ERROR; + thingStatusDescription = msg; + updateThingStatus(newThingStatus, thingStatusDetailed, thingStatusDescription); + + logger.error("{}: {}", getLogIdentifier(), msg); + return; + } else { + logger.debug("{}: ThingAvailability: ZoneMinder Id for Thing '{}' defined (Check PASSED)", + getLogIdentifier(), thing.getUID()); + } + + // TODO:: Also look at Analysis and Frame Daemons (only if they are supposed to be running) + IZoneMinderSession session = aquireSession(); + // IZoneMinderServer serverProxy = ZoneMinderFactory.getServerProxy(session); + IZoneMinderMonitor monitorProxy = ZoneMinderFactory.getMonitorProxy(session, getZoneMinderId()); + // serverProxy.getConfig(ZoneMinderConfigEnum.ZM_OPT_); + // serverProxy.getConfig(ZoneMinderConfigEnum.ZM_OPT_FRAME_SERVER); + IZoneMinderDaemonStatus captureDaemon = monitorProxy.getCaptureDaemonStatus(); + releaseSession(); + + if (!captureDaemon.getStatus()) { + msg = String.format("Capture Daemon is not running"); + newThingStatus = ThingStatus.OFFLINE; + thingStatusDetailed = ThingStatusDetail.COMMUNICATION_ERROR; + thingStatusDescription = msg; + updateThingStatus(newThingStatus, thingStatusDetailed, thingStatusDescription); + logger.error("{}: {}", getLogIdentifier(), msg); + return; + } + newThingStatus = ThingStatus.ONLINE; + + } catch (Exception exception) { + newThingStatus = ThingStatus.OFFLINE; + thingStatusDetailed = ThingStatusDetail.COMMUNICATION_ERROR; + thingStatusDescription = "Error occurred (Check log)"; + updateThingStatus(newThingStatus, thingStatusDetailed, thingStatusDescription); + + logger.error("{}: 'ThingMonitorHandler.updateAvailabilityStatus()': Exception occurred '{}'", + getLogIdentifier(), exception.getMessage()); + + return; + } + + updateThingStatus(newThingStatus, thingStatusDetailed, thingStatusDescription); + } + + /* + * From here we update states in openHAB + * + * @see + * org.openhab.binding.zoneminder.handler.ZoneMinderBaseThingHandler#updateChannel(org.eclipse.smarthome.core.thing. + * ChannelUID) + */ + @Override + public void updateChannel(ChannelUID channel) { + State state = null; + + try { + switch (channel.getId()) { + case ZoneMinderConstants.CHANNEL_MONITOR_ENABLED: + state = getChannelBoolAsOnOffState(channelEnabled); + break; + + case ZoneMinderConstants.CHANNEL_ONLINE: + // Ask super class to handle, because this channel is shared for all things + super.updateChannel(channel); + break; + case ZoneMinderConstants.CHANNEL_MONITOR_FORCE_ALARM: + state = getChannelBoolAsOnOffState(channelForceAlarm); + break; + case ZoneMinderConstants.CHANNEL_MONITOR_EVENT_STATE: + state = getChannelBoolAsOnOffState(channelAlarmedState); + break; + + case ZoneMinderConstants.CHANNEL_MONITOR_RECORD_STATE: + state = getChannelBoolAsOnOffState(channelRecordingState); + break; + + case ZoneMinderConstants.CHANNEL_MONITOR_DETAILED_STATUS: + state = getDetailedStatus(); + break; + + case ZoneMinderConstants.CHANNEL_MONITOR_EVENT_CAUSE: + state = getChannelStringAsStringState(channelEventCause); + break; + + case ZoneMinderConstants.CHANNEL_MONITOR_FUNCTION: + state = getChannelStringAsStringState(channelFunction.toString()); + break; + + case ZoneMinderConstants.CHANNEL_MONITOR_CAPTURE_DAEMON_STATE: + state = getChannelBoolAsOnOffState(channelDaemonCapture); + break; + + case ZoneMinderConstants.CHANNEL_MONITOR_ANALYSIS_DAEMON_STATE: + state = getChannelBoolAsOnOffState(channelDaemonAnalysis); + break; + + case ZoneMinderConstants.CHANNEL_MONITOR_FRAME_DAEMON_STATE: + state = getChannelBoolAsOnOffState(channelDaemonFrame); + break; + + default: + logger.warn("{}: updateChannel(): Monitor '{}': No handler defined for channel='{}'", + getLogIdentifier(), thing.getLabel(), channel.getAsString()); + + // Ask super class to handle + super.updateChannel(channel); + } + + if (state != null) { + + logger.debug("{}: Setting channel '{}' to '{}'", getLogIdentifier(), channel.toString(), + state.toString()); + updateState(channel.getId(), state); + } + } catch (Exception ex) { + logger.error("{}: Error when 'updateChannel' was called (channelId='{}'state='{}', exception'{}')", + getLogIdentifier(), channel.toString(), state.toString(), ex.getMessage()); + } + } + + @Override + public void updateStatus(ThingStatus status) { + super.updateStatus(status); + updateState(ZoneMinderConstants.CHANNEL_ONLINE, + ((status == ThingStatus.ONLINE) ? OnOffType.ON : OnOffType.OFF)); + + } + + protected void RecalculateChannelStates() { + boolean recordingFunction = false; + boolean recordingDetailedState = false; + boolean alarmedFunction = false; + boolean alarmedDetailedState = false; + + // Calculate based on state of Function + switch (channelFunction) { + case NONE: + case MONITOR: + alarmedFunction = false; + recordingFunction = false; + break; + + case MODECT: + alarmedFunction = true; + recordingFunction = true; + break; + case RECORD: + alarmedFunction = false; + recordingFunction = true; + break; + case MOCORD: + alarmedFunction = true; + recordingFunction = true; + break; + case NODECT: + alarmedFunction = false; + recordingFunction = true; + break; + default: + recordingFunction = (curEvent != null) ? true : false; + } + logger.debug( + "{}: Recalculate channel states based on Function: Function='{}' -> alarmState='{}', recordingState='{}'", + getLogIdentifier(), channelFunction.name(), alarmedFunction, recordingFunction); + + // Calculated based on detailed Monitor Status + switch (channelMonitorStatus) { + case IDLE: + alarmedDetailedState = false; + recordingDetailedState = false; + channelForceAlarm = false; + channelEventCause = ""; + break; + + case PRE_ALARM: + alarmedDetailedState = true; + recordingDetailedState = true; + channelForceAlarm = false; + break; + + case ALARM: + alarmedDetailedState = true; + recordingDetailedState = true; + channelForceAlarm = true; + break; + + case ALERT: + alarmedDetailedState = true; + recordingDetailedState = true; + channelForceAlarm = false; + break; + + case RECORDING: + alarmedDetailedState = false; + recordingDetailedState = true; + channelForceAlarm = false; + break; + } + logger.debug( + "{}: Recalculate channel states based on Detailed State: DetailedState='{}' -> alarmState='{}', recordingState='{}'", + getLogIdentifier(), channelMonitorStatus.name(), alarmedDetailedState, recordingDetailedState); + + // Check if Force alarm was initialed from openHAB + if (forceAlarmManualState == 0) { + if (channelForceAlarm) { + channelForceAlarm = false; + } else { + forceAlarmManualState = -1; + } + } else if (forceAlarmManualState == 1) { + + if (channelForceAlarm == false) { + channelForceAlarm = true; + } else { + forceAlarmManualState = -1; + } + + } + + // Now we can conclude on the Alarmed and Recording channel state + channelRecordingState = (recordingFunction && recordingDetailedState && channelEnabled); + channelAlarmedState = (alarmedFunction && alarmedDetailedState && channelEnabled); + + } + + @Override + protected void onFetchData() { + + IZoneMinderSession session = null; + + session = aquireSession(); + try { + IZoneMinderMonitor monitorProxy = ZoneMinderFactory.getMonitorProxy(session, getZoneMinderId()); + + IZoneMinderMonitorData data = null; + IZoneMinderDaemonStatus captureDaemon = null; + IZoneMinderDaemonStatus analysisDaemon = null; + IZoneMinderDaemonStatus frameDaemon = null; + + data = monitorProxy.getMonitorData(); + logger.debug("{}: URL='{}' ResponseCode='{}' ResponseMessage='{}'", getLogIdentifier(), + monitorProxy.getHttpUrl(), monitorProxy.getHttpResponseCode(), + monitorProxy.getHttpResponseMessage()); + + captureDaemon = monitorProxy.getCaptureDaemonStatus(); + logger.debug("{}: URL='{}' ResponseCode='{}' ResponseMessage='{}'", getLogIdentifier(), + monitorProxy.getHttpUrl(), monitorProxy.getHttpResponseCode(), + monitorProxy.getHttpResponseMessage()); + + analysisDaemon = monitorProxy.getAnalysisDaemonStatus(); + logger.debug("{}: URL='{}' ResponseCode='{}' ResponseMessage='{}'", getLogIdentifier(), + monitorProxy.getHttpUrl(), monitorProxy.getHttpResponseCode(), + monitorProxy.getHttpResponseMessage()); + + frameDaemon = monitorProxy.getFrameDaemonStatus(); + logger.debug("{}: URL='{}' ResponseCode='{}' ResponseMessage='{}'", getLogIdentifier(), + monitorProxy.getHttpUrl(), monitorProxy.getHttpResponseCode(), + monitorProxy.getHttpResponseMessage()); + + if ((data.getHttpResponseCode() != 200) || (captureDaemon.getHttpResponseCode() != 200) + || (analysisDaemon.getHttpResponseCode() != 200) || (frameDaemon.getHttpResponseCode() != 200)) { + + if (data.getHttpResponseCode() != 200) { + logger.warn("{}: HTTP Response MonitorData: Code='{}', Message'{}'", getLogIdentifier(), + data.getHttpResponseCode(), data.getHttpResponseMessage()); + + channelMonitorStatus = ZoneMinderMonitorStatusEnum.UNKNOWN; + channelFunction = ZoneMinderMonitorFunctionEnum.NONE; + channelEnabled = false; + channelEventCause = ""; + } + if (captureDaemon.getHttpResponseCode() != 200) { + channelDaemonCapture = false; + logger.warn("{}: HTTP Response CaptureDaemon: Code='{}', Message'{}'", getLogIdentifier(), + captureDaemon.getHttpResponseCode(), captureDaemon.getHttpResponseMessage()); + + } + if (analysisDaemon.getHttpResponseCode() != 200) { + channelDaemonAnalysis = false; + + logger.warn("{}: HTTP Response AnalysisDaemon: Code='{}', Message='{}'", getLogIdentifier(), + analysisDaemon.getHttpResponseCode(), analysisDaemon.getHttpResponseMessage()); + + } + if (frameDaemon.getHttpResponseCode() != 200) { + channelDaemonFrame = false; + logger.warn("{}: HTTP Response MonitorData: Code='{}', Message'{}'", getLogIdentifier(), + frameDaemon.getHttpResponseCode(), frameDaemon.getHttpResponseMessage()); + + } + + } else { + if (isConnected()) { + channelMonitorStatus = monitorProxy.getMonitorDetailedStatus(); + logger.debug("{}: URL='{}' ResponseCode='{}' ResponseMessage='{}'", getLogIdentifier(), + monitorProxy.getHttpUrl(), monitorProxy.getHttpResponseCode(), + monitorProxy.getHttpResponseMessage()); + + channelFunction = data.getFunction(); + channelEnabled = data.getEnabled(); + channelEventCause = monitorProxy.getLastEvent().getCause(); + channelDaemonCapture = captureDaemon.getStatus(); + channelDaemonAnalysis = analysisDaemon.getStatus(); + channelDaemonFrame = frameDaemon.getStatus(); + } else { + channelMonitorStatus = ZoneMinderMonitorStatusEnum.UNKNOWN; + channelFunction = ZoneMinderMonitorFunctionEnum.NONE; + channelEnabled = false; + channelEventCause = ""; + channelDaemonCapture = false; + channelDaemonAnalysis = false; + channelDaemonFrame = false; + } + } + } finally { + releaseSession(); + } + + RecalculateChannelStates(); + + if ((channelForceAlarm == false) && (channelAlarmedState == false) + && (DataRefreshPriorityEnum.HIGH_PRIORITY == getRefreshPriority())) { + stopPriorityRefresh(); + } + + } + + protected State getDetailedStatus() { + State state = UnDefType.UNDEF; + + try { + if (channelMonitorStatus == ZoneMinderMonitorStatusEnum.UNKNOWN) { + state = getChannelStringAsStringState(""); + } else { + state = getChannelStringAsStringState(channelMonitorStatus.toString()); + } + + } catch (Exception ex) { + logger.debug(ex.getMessage()); + } + + return state; + + } + + /* + * This is experimental + * Try to add different properties + */ + private void updateMonitorProperties(IZoneMinderSession session) { + logger.debug("{}: Update Monitor Properties", getLogIdentifier()); + // Update property information about this device + Map properties = editProperties(); + IZoneMinderMonitor monitorProxy = ZoneMinderFactory.getMonitorProxy(session, getZoneMinderId()); + IZoneMinderMonitorData monitorData = monitorProxy.getMonitorData(); + logger.debug("{}: URL='{}' ResponseCode='{}' ResponseMessage='{}'", getLogIdentifier(), + monitorProxy.getHttpUrl(), monitorProxy.getHttpResponseCode(), monitorProxy.getHttpResponseMessage()); + + properties.put(ZoneMinderProperties.PROPERTY_ID, getLogIdentifier()); + properties.put(ZoneMinderProperties.PROPERTY_MONITOR_NAME, monitorData.getName()); + + properties.put(ZoneMinderProperties.PROPERTY_MONITOR_SOURCETYPE, monitorData.getSourceType().name()); + + properties.put(ZoneMinderProperties.PROPERTY_MONITOR_ANALYSIS_FPS, monitorData.getAnalysisFPS()); + properties.put(ZoneMinderProperties.PROPERTY_MONITOR_MAXIMUM_FPS, monitorData.getMaxFPS()); + properties.put(ZoneMinderProperties.PROPERTY_MONITOR_ALARM_MAXIMUM, monitorData.getAlarmMaxFPS()); + + properties.put(ZoneMinderProperties.PROPERTY_MONITOR_IMAGE_WIDTH, monitorData.getWidth()); + properties.put(ZoneMinderProperties.PROPERTY_MONITOR_IMAGE_HEIGHT, monitorData.getHeight()); + + // Must loop over the new properties since we might have added data + boolean update = false; + Map originalProperties = editProperties(); + for (String property : properties.keySet()) { + if ((originalProperties.get(property) == null + || originalProperties.get(property).equals(properties.get(property)) == false)) { + update = true; + break; + } + } + + if (update == true) { + logger.debug("{}: Properties synchronised", getLogIdentifier()); + updateProperties(properties); + } + } + + @Override + public String getLogIdentifier() { + String result = "[MONITOR]"; + + try { + if (config != null) { + + result = String.format("[MONITOR-%s]", config.getZoneMinderId().toString()); + } + + } catch (Exception ex) { + result = "[MONITOR]"; + } + + return result; + } +} diff --git a/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/handler/ZoneMinderThingType.java b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/handler/ZoneMinderThingType.java new file mode 100644 index 0000000000000..fb4934832e052 --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/handler/ZoneMinderThingType.java @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.zoneminder.handler; + +/** + * Enumerator for each Bridge and Thing + * + * @author Martin S. Eskildsen + */ +public enum ZoneMinderThingType { + ZoneMinderServerBridge, + ZoneMinderMonitorThing; +} diff --git a/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/DataRefreshPriorityEnum.java b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/DataRefreshPriorityEnum.java new file mode 100644 index 0000000000000..88ceed3e98bc9 --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/DataRefreshPriorityEnum.java @@ -0,0 +1,14 @@ +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.zoneminder.internal; + +public enum DataRefreshPriorityEnum { + SCHEDULED, + HIGH_PRIORITY; +} diff --git a/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/ZoneMinderHandlerFactory.java b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/ZoneMinderHandlerFactory.java new file mode 100644 index 0000000000000..8799bff2e98b5 --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/ZoneMinderHandlerFactory.java @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.zoneminder.internal; + +import java.util.Set; + +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.openhab.binding.zoneminder.ZoneMinderConstants; +import org.openhab.binding.zoneminder.handler.ZoneMinderServerBridgeHandler; +import org.openhab.binding.zoneminder.handler.ZoneMinderThingMonitorHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.Sets; + +/** + * The {@link ZoneMinderHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Martin S. Eskildsen - Initial contribution + * + */ +public class ZoneMinderHandlerFactory extends BaseThingHandlerFactory { + + private Logger logger = LoggerFactory.getLogger(ZoneMinderHandlerFactory.class); + + public static final Set SUPPORTED_THING_TYPES = Sets.union( + ZoneMinderServerBridgeHandler.SUPPORTED_THING_TYPES, ZoneMinderThingMonitorHandler.SUPPORTED_THING_TYPES); + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES.contains(thingTypeUID); + } + + @Override + protected ThingHandler createHandler(Thing thing) { + + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (thingTypeUID.equals(ZoneMinderConstants.THING_TYPE_BRIDGE_ZONEMINDER_SERVER)) { + + logger.debug("[FACTORY]: creating handler for bridge thing '{}'", thing); + ZoneMinderServerBridgeHandler bridge = new ZoneMinderServerBridgeHandler((Bridge) thing); + + return bridge; + } else if (thingTypeUID.equals(ZoneMinderConstants.THING_TYPE_THING_ZONEMINDER_MONITOR)) { + return new ZoneMinderThingMonitorHandler(thing); + } + + return null; + } + +} diff --git a/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/config/ZoneMinderBridgeServerConfig.java b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/config/ZoneMinderBridgeServerConfig.java new file mode 100644 index 0000000000000..5b93bf0937982 --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/config/ZoneMinderBridgeServerConfig.java @@ -0,0 +1,131 @@ +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.zoneminder.internal.config; + +import org.openhab.binding.zoneminder.ZoneMinderConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Configuration data according to zoneminderserver.xml + * + * @author Martin S. Eskildsen + * + */ +public class ZoneMinderBridgeServerConfig extends ZoneMinderConfig { + + private final Logger logger = LoggerFactory.getLogger(ZoneMinderBridgeServerConfig.class); + + private String hostname; + private Integer http_port; + private Integer telnet_port; + + private String protocol; + + private String urlpath; + + private String user; + private String password; + private Integer refresh_interval; + private Integer refresh_interval_disk_usage; + private Boolean autodiscover_things; + + @Override + public String getConfigId() { + return ZoneMinderConstants.BRIDGE_ZONEMINDER_SERVER; + } + + public String getHostName() { + return hostname; + } + + public void setHostName(String hostName) { + this.hostname = hostName; + } + + public Integer getHttpPort() { + if ((http_port == null) || (http_port == 0)) { + if (getProtocol().equalsIgnoreCase("http")) { + http_port = 80; + } else { + http_port = 443; + } + } + return http_port; + } + + public void setHttpPort(Integer port) { + this.http_port = port; + } + + public Integer getTelnetPort() { + return telnet_port; + } + + public void setTelnetPort(Integer telnetPort) { + this.telnet_port = telnetPort; + } + + public String getProtocol() { + return protocol; + } + + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + public String getServerBasePath() { + return urlpath; + } + + public void setServerBasePath(String urlpath) { + this.urlpath = urlpath; + } + + public String getUserName() { + return user; + } + + public void setUserName(String userName) { + this.user = user; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public Integer getRefreshInterval() { + return refresh_interval; + } + + public void setRefreshInterval(Integer refreshInterval) { + this.refresh_interval = refreshInterval; + } + + public Integer getRefreshIntervalLowPriorityTask() { + return refresh_interval_disk_usage; + } + + public void setRefreshIntervalDiskUsage(Integer refreshIntervalDiskUsage) { + this.refresh_interval_disk_usage = refreshIntervalDiskUsage; + } + + public Boolean getAutodiscoverThings() { + return autodiscover_things; + } + + public void setAutodiscoverThings(Boolean autodiscoverThings) { + this.autodiscover_things = autodiscoverThings; + } + +} diff --git a/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/config/ZoneMinderConfig.java b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/config/ZoneMinderConfig.java new file mode 100644 index 0000000000000..075af8bb69eca --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/config/ZoneMinderConfig.java @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.zoneminder.internal.config; + +/** + * base class containing Configuration in OpenHAB + * + * @author Martin S. Eskildsen + */ +public abstract class ZoneMinderConfig { + public abstract String getConfigId(); +} diff --git a/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/config/ZoneMinderThingConfig.java b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/config/ZoneMinderThingConfig.java new file mode 100644 index 0000000000000..1bffbf3f7abf0 --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/config/ZoneMinderThingConfig.java @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.zoneminder.internal.config; + +import org.openhab.binding.zoneminder.ZoneMinderConstants; + +/** + * Monitor configuration from OpenHAB. + * + * @author Martin S. Eskildsen - Initial contribution + */ +public abstract class ZoneMinderThingConfig extends ZoneMinderConfig { + + public abstract String getZoneMinderId(); + + @Override + public String getConfigId() { + return ZoneMinderConstants.THING_ZONEMINDER_MONITOR; + } + +} diff --git a/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/config/ZoneMinderThingMonitorConfig.java b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/config/ZoneMinderThingMonitorConfig.java new file mode 100644 index 0000000000000..04a726d50e561 --- /dev/null +++ b/addons/binding/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/config/ZoneMinderThingMonitorConfig.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2014-2016 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.zoneminder.internal.config; + +import org.openhab.binding.zoneminder.ZoneMinderConstants; + +/** + * Specific configuration class for Monitor COnfig. + * + * @author Martin S. Eskildsen - Initial contribution + */ +public class ZoneMinderThingMonitorConfig extends ZoneMinderThingConfig { + + // Parameters + private Integer monitorId; + + @Override + public String getConfigId() { + return ZoneMinderConstants.THING_ZONEMINDER_MONITOR; + } + + public String getId() { + return monitorId.toString(); + } + + @Override + public String getZoneMinderId() { + return monitorId.toString(); + } +} diff --git a/addons/binding/org.openhab.binding.zway/ESH-INF/i18n/zway.properties b/addons/binding/org.openhab.binding.zway/ESH-INF/i18n/zway.properties index 15e21cdba13c2..822128425fbfb 100644 --- a/addons/binding/org.openhab.binding.zway/ESH-INF/i18n/zway.properties +++ b/addons/binding/org.openhab.binding.zway/ESH-INF/i18n/zway.properties @@ -1,103 +1,103 @@ -# binding -binding.zway.name = Z-Way Binding -binding.zway.description = Z-Way is a home automation software to configure and control a Z-Wave network. The ZAutomation interface provides all Z-Wave devices and handles incoming commands. The Z-Way Binding uses this HTTP interface to load all device and make them available during the discovery process.
Besides a continuous polling of device states the opportunity to register items in Z-Way as observer is possible to get actively device state updates (for that function the related Z-Way App is currently required). - -# thing types -thing-type.zway.zwayServer.label = Z-Way Server -thing-type.zway.zwayServer.description = The Z-Way server represents a bridge with general settings and communication tasks. - -thing-type.config.zway.zwayServer.openhab.label = openHAB -thing-type.config.zway.zwayServer.openhab.description = The Z-Way server requires this information to notify the openHAB server. If Z-Way and openHAB are running on the same machine, the default value can be used. -thing-type.config.zway.zwayServer.zwayServer.label = Z-Way server -thing-type.config.zway.zwayServer.zwayServer.description = The configuration of the Z-Way server. Except for the username and password all the information detected during the discovery. -thing-type.config.zway.zwayServer.binding.label = Options -thing-type.config.zway.zwayServer.binding.description = These settings affect functions of the binding. - -thing-type.config.zway.zwayServer.openHABAlias.label = OpenHAB alias -thing-type.config.zway.zwayServer.openHABAlias.description = Alias used in openHAB connector. By default, the alias is generated. -thing-type.config.zway.zwayServer.openHABIpAddress.label = IP address -thing-type.config.zway.zwayServer.openHABIpAddress.description = The IP address or hostname of the openHAB server. If Z-Way and openHAB are running on the same machine, the default value can be used. -thing-type.config.zway.zwayServer.openHABPort.label = Port -thing-type.config.zway.zwayServer.openHABPort.description = The port of the openHAB server. -thing-type.config.zway.zwayServer.openHABProtocol.label = Protocol -thing-type.config.zway.zwayServer.openHABProtocol.description = Protocol to connect to the openHAB server (http or https). - -thing-type.config.zway.zwayServer.zwayServerIpAddress.label = IP address -thing-type.config.zway.zwayServer.zwayServerIpAddress.description = The IP address or hostname of the Z-Way server. If Z-Way and openHAB are running on the same machine, the default value can be used. -thing-type.config.zway.zwayServer.zwayServerPort.label = Port -thing-type.config.zway.zwayServer.zwayServerPort.description = The port of the Z-Way server -thing-type.config.zway.zwayServer.zwayServerProtocol.label = Protocol -thing-type.config.zway.zwayServer.zwayServerProtocol.description = Protocol to connect to the Z-Way server (http or https) -thing-type.config.zway.zwayServer.zwayServerUsername.label = Username -thing-type.config.zway.zwayServer.zwayServerUsername.description = Username to access the Z-Way server. -thing-type.config.zway.zwayServer.zwayServerPassword.label = Password -thing-type.config.zway.zwayServer.zwayServerPassword.description = Password to access the Z-Way server. - -thing-type.config.zway.zwayServer.pollingInterval.label = Polling Interval -thing-type.config.zway.zwayServer.pollingInterval.description = Refresh device states and registration from Z-Way server. -thing-type.config.zway.zwayServer.observerMechanismEnabled.label = Observer mechanism enabled -thing-type.config.zway.zwayServer.observerMechanismEnabled.description = The observer functionality is responsible for the item registration as observer in Z-Way. Attention: if disable this option, you have to setup an other synchronization mechanism like MQTT. - -thing-type.zway.zwayDevice.label = Z-Wave Device -thing-type.zway.zwayDevice.description = A Z-Wave device represents a device of real world. Each device function will be mapped to a separate channel. The bridge is necessary as an intermediary between openHAB thing and Z-Way device. - -thing-type.config.zway.zwayDevice.nodeId.label = Node Id -thing-type.config.zway.zwayDevice.nodeId.description = Node Id of the Z-Wave device - -thing-type.zway.zwayVirtualDevice.label = Z-Way Virtual Device -thing-type.zway.zwayVirtualDevice.description = A Z-Way virtual device represents one sensor, actor or Z-Way App with the corresponding channel. The bridge is necessary as an intermediary between openHAB thing and Z-Way device. - -thing-type.config.zway.zwayVirtualDevice.deviceId.label = Device Id -thing-type.config.zway.zwayVirtualDevice.deviceId.description = Device Id of virtual device - -# channel types -channel-type.zway.sensorTemperature.label = Temperature -channel-type.zway.sensorLuminosity.label = Luminiscence -channel-type.zway.sensorHumidity.label = Humidity -channel-type.zway.sensorBarometer.label = Barometer -channel-type.zway.sensorUltraviolet.label = Ultraviolet -channel-type.zway.sensorCO2.label = CarbonDioxide -channel-type.zway.sensorEnergy.label = Energy -channel-type.zway.sensorMeterKWh.label = Energy -channel-type.zway.sensorMeterW.label = Energy -channel-type.zway.sensorSmoke.label = Smoke -channel-type.zway.sensorCo.label = Gas -channel-type.zway.sensorFlood.label = Flood -channel-type.zway.sensorTamper.label = Tamper -channel-type.zway.sensorDoorWindow.label = DoorWindow -channel-type.zway.sensorMotion.label = Motion -channel-type.zway.switchPowerOutlet.label = PowerOutlet -channel-type.zway.switchColorTemperature.label = Color Temperature - -# channel type without further information -channel-type.zway.battery.label = Battery -channel-type.zway.doorlock.label = Doorlock -channel-type.zway.sensorBinary.label = Sensor binary -channel-type.zway.sensorBinary.description = This channel represents a universal channel if no further device information is available. -channel-type.zway.sensorMultilevel.label = Sensor multilevel -channel-type.zway.sensorMultilevel.description = This channel represents a universal channel if no further device information is available. -channel-type.zway.switchBinary.label = Switch binary -channel-type.zway.switchBinary.description = This channel represents a universal channel if no further device information is available. -channel-type.zway.switchMultilevel.label = Switch multilevel -channel-type.zway.switchMultilevel.description = This channel represents a universal channel if no further device information is available. -channel-type.zway.switchColor.label = Switch color -channel-type.zway.switchColor.description = This channel represents the RGBW switch device type from Z-Way. -channel-type.zway.switchControl.label = Switch control -channel-type.zway.switchControl.description = This channel represents a universal channel if no further device information is available. -channel-type.zway.thermostatMode.label = Thermostat mode -channel-type.zway.thermostatMode.description = The channel allows the control or display of a thermostat (mode). A thermostat can have up to three states (modes): off, heating and cooling. The state of heating and cooling is alternately set at the state on. -channel-type.zway.thermostatSetPoint.label = Thermostat set point - -channel-type.zway.thermostatModeV2.label = Thermostat mode (Command Class) -channel-type.zway.thermostatModeV2.description = The channel allows the control or display of a thermostat (mode) from command class. The modes differ from device to device. - -channel-type.zway.actions.label = Actions -channel-type.zway.actions.description = Available actions of the Z-Wave Controller -channel-type.zway.actions.option.REFRESH = Refresh all things - -channel-type.zway.secureInclusion.label = Secure inclusion -channel-type.zway.secureInclusion.description = Change inclusion type for further inclusions. -channel-type.zway.inclusion.label = Inclusion -channel-type.zway.inclusion.description = Start inclusion mode (after a timeout the inclusion will be automatically finished). -channel-type.zway.exclusion.label = Exclusion +# binding +binding.zway.name = Z-Way Binding +binding.zway.description = Z-Way is a home automation software to configure and control a Z-Wave network. The ZAutomation interface provides all Z-Wave devices and handles incoming commands. The Z-Way Binding uses this HTTP interface to load all device and make them available during the discovery process.
Besides a continuous polling of device states the opportunity to register items in Z-Way as observer is possible to get actively device state updates (for that function the related Z-Way App is currently required). + +# thing types +thing-type.zway.zwayServer.label = Z-Way Server +thing-type.zway.zwayServer.description = The Z-Way server represents a bridge with general settings and communication tasks. + +thing-type.config.zway.zwayServer.openhab.label = openHAB +thing-type.config.zway.zwayServer.openhab.description = The Z-Way server requires this information to notify the openHAB server. If Z-Way and openHAB are running on the same machine, the default value can be used. +thing-type.config.zway.zwayServer.zwayServer.label = Z-Way server +thing-type.config.zway.zwayServer.zwayServer.description = The configuration of the Z-Way server. Except for the username and password all the information detected during the discovery. +thing-type.config.zway.zwayServer.binding.label = Options +thing-type.config.zway.zwayServer.binding.description = These settings affect functions of the binding. + +thing-type.config.zway.zwayServer.openHABAlias.label = OpenHAB alias +thing-type.config.zway.zwayServer.openHABAlias.description = Alias used in openHAB connector. By default, the alias is generated. +thing-type.config.zway.zwayServer.openHABIpAddress.label = IP address +thing-type.config.zway.zwayServer.openHABIpAddress.description = The IP address or hostname of the openHAB server. If Z-Way and openHAB are running on the same machine, the default value can be used. +thing-type.config.zway.zwayServer.openHABPort.label = Port +thing-type.config.zway.zwayServer.openHABPort.description = The port of the openHAB server. +thing-type.config.zway.zwayServer.openHABProtocol.label = Protocol +thing-type.config.zway.zwayServer.openHABProtocol.description = Protocol to connect to the openHAB server (http or https). + +thing-type.config.zway.zwayServer.zwayServerIpAddress.label = IP address +thing-type.config.zway.zwayServer.zwayServerIpAddress.description = The IP address or hostname of the Z-Way server. If Z-Way and openHAB are running on the same machine, the default value can be used. +thing-type.config.zway.zwayServer.zwayServerPort.label = Port +thing-type.config.zway.zwayServer.zwayServerPort.description = The port of the Z-Way server +thing-type.config.zway.zwayServer.zwayServerProtocol.label = Protocol +thing-type.config.zway.zwayServer.zwayServerProtocol.description = Protocol to connect to the Z-Way server (http or https) +thing-type.config.zway.zwayServer.zwayServerUsername.label = Username +thing-type.config.zway.zwayServer.zwayServerUsername.description = Username to access the Z-Way server. +thing-type.config.zway.zwayServer.zwayServerPassword.label = Password +thing-type.config.zway.zwayServer.zwayServerPassword.description = Password to access the Z-Way server. + +thing-type.config.zway.zwayServer.pollingInterval.label = Polling Interval +thing-type.config.zway.zwayServer.pollingInterval.description = Refresh device states and registration from Z-Way server. +thing-type.config.zway.zwayServer.observerMechanismEnabled.label = Observer mechanism enabled +thing-type.config.zway.zwayServer.observerMechanismEnabled.description = The observer functionality is responsible for the item registration as observer in Z-Way. Attention: if disable this option, you have to setup an other synchronization mechanism like MQTT. + +thing-type.zway.zwayDevice.label = Z-Wave Device +thing-type.zway.zwayDevice.description = A Z-Wave device represents a device of real world. Each device function will be mapped to a separate channel. The bridge is necessary as an intermediary between openHAB thing and Z-Way device. + +thing-type.config.zway.zwayDevice.nodeId.label = Node Id +thing-type.config.zway.zwayDevice.nodeId.description = Node Id of the Z-Wave device + +thing-type.zway.zwayVirtualDevice.label = Z-Way Virtual Device +thing-type.zway.zwayVirtualDevice.description = A Z-Way virtual device represents one sensor, actor or Z-Way App with the corresponding channel. The bridge is necessary as an intermediary between openHAB thing and Z-Way device. + +thing-type.config.zway.zwayVirtualDevice.deviceId.label = Device Id +thing-type.config.zway.zwayVirtualDevice.deviceId.description = Device Id of virtual device + +# channel types +channel-type.zway.sensorTemperature.label = Temperature +channel-type.zway.sensorLuminosity.label = Luminiscence +channel-type.zway.sensorHumidity.label = Humidity +channel-type.zway.sensorBarometer.label = Barometer +channel-type.zway.sensorUltraviolet.label = Ultraviolet +channel-type.zway.sensorCO2.label = CarbonDioxide +channel-type.zway.sensorEnergy.label = Energy +channel-type.zway.sensorMeterKWh.label = Energy +channel-type.zway.sensorMeterW.label = Energy +channel-type.zway.sensorSmoke.label = Smoke +channel-type.zway.sensorCo.label = Gas +channel-type.zway.sensorFlood.label = Flood +channel-type.zway.sensorTamper.label = Tamper +channel-type.zway.sensorDoorWindow.label = DoorWindow +channel-type.zway.sensorMotion.label = Motion +channel-type.zway.switchPowerOutlet.label = PowerOutlet +channel-type.zway.switchColorTemperature.label = Color Temperature + +# channel type without further information +channel-type.zway.battery.label = Battery +channel-type.zway.doorlock.label = Doorlock +channel-type.zway.sensorBinary.label = Sensor binary +channel-type.zway.sensorBinary.description = This channel represents a universal channel if no further device information is available. +channel-type.zway.sensorMultilevel.label = Sensor multilevel +channel-type.zway.sensorMultilevel.description = This channel represents a universal channel if no further device information is available. +channel-type.zway.switchBinary.label = Switch binary +channel-type.zway.switchBinary.description = This channel represents a universal channel if no further device information is available. +channel-type.zway.switchMultilevel.label = Switch multilevel +channel-type.zway.switchMultilevel.description = This channel represents a universal channel if no further device information is available. +channel-type.zway.switchColor.label = Switch color +channel-type.zway.switchColor.description = This channel represents the RGBW switch device type from Z-Way. +channel-type.zway.switchControl.label = Switch control +channel-type.zway.switchControl.description = This channel represents a universal channel if no further device information is available. +channel-type.zway.thermostatMode.label = Thermostat mode +channel-type.zway.thermostatMode.description = The channel allows the control or display of a thermostat (mode). A thermostat can have up to three states (modes): off, heating and cooling. The state of heating and cooling is alternately set at the state on. +channel-type.zway.thermostatSetPoint.label = Thermostat set point + +channel-type.zway.thermostatModeV2.label = Thermostat mode (Command Class) +channel-type.zway.thermostatModeV2.description = The channel allows the control or display of a thermostat (mode) from command class. The modes differ from device to device. + +channel-type.zway.actions.label = Actions +channel-type.zway.actions.description = Available actions of the Z-Wave Controller +channel-type.zway.actions.option.REFRESH = Refresh all things + +channel-type.zway.secureInclusion.label = Secure inclusion +channel-type.zway.secureInclusion.description = Change inclusion type for further inclusions. +channel-type.zway.inclusion.label = Inclusion +channel-type.zway.inclusion.description = Start inclusion mode (after a timeout the inclusion will be automatically finished). +channel-type.zway.exclusion.label = Exclusion channel-type.zway.exclusion.description = Start exclusion mode (after a timeout the exclusion will be automatically finished). \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.zway/ESH-INF/i18n/zway_de.properties b/addons/binding/org.openhab.binding.zway/ESH-INF/i18n/zway_de.properties index dabb1cf331180..f079c3fb470e3 100644 --- a/addons/binding/org.openhab.binding.zway/ESH-INF/i18n/zway_de.properties +++ b/addons/binding/org.openhab.binding.zway/ESH-INF/i18n/zway_de.properties @@ -1,103 +1,103 @@ -# binding -binding.zway.name = Z-Way Binding -binding.zway.description = Das Z-Way-System ist ein Softwarepaket für den Z-Wave Funkstandard. Das System besteht im wesentlichen aus einer Firmware für Z-Wave Transceiver, einer Kommunikations- und einer Automatisierungskomponente zur Steuerung und Konfiguration des Netzwerks. Das Z-Way Binding nutzt die HTTP-Schnittstelle um alle Geräte zu laden und im Discovery-Prozess zur Verfügung zu stellen.
Neben einem Polling der Gerätezustände werden optional die resultierenden Geräte als Observer im Z-Way System registriert, um Zustandsänderungen der Geräte zu erhalten (dazu wird aktuell die Z-Way App OpenHAB Konnektor benötigt). - -# thing types -thing-type.zway.zwayServer.label = Z-Way Server -thing-type.zway.zwayServer.description = Der Z-Way Server repräsentiert das Z-Way System als Bridge mit der grundlegendene Konfiguration zum Verbindungsaufbau. Die gesamte Kommunikation mit Z-Way organisiert diese Komponente. - -thing-type.config.zway.zwayServer.openhab.label = openHAB -thing-type.config.zway.zwayServer.openhab.description = Der Z-Way Server benötigt diese Informationen um bei Statusänderungen openHAB zu benachrichtigen. Wenn Z-Way und openHAB auf dem gleichen Host ausgeführt werden, können die Standardwerte beibehalten werden. -thing-type.config.zway.zwayServer.zwayServer.label = Z-Way Server -thing-type.config.zway.zwayServer.zwayServer.description = Die Konfiguration des Z-Way Server wird bis auf den Benutzername und das Passwort während des Discovery-Prozesses ermittlt. -thing-type.config.zway.zwayServer.binding.label = Optionen -thing-type.config.zway.zwayServer.binding.description = Diese Einstellungen betreffen Funktionen des Bindings. - -thing-type.config.zway.zwayServer.openHABAlias.label = Alias -thing-type.config.zway.zwayServer.openHABAlias.description = Der Bezeichner wird für den openHAB-Konnektor benötigt und ist optional und frei wählbar, aber muss eindeutig sein. (Standard: ein generierter Wert) -thing-type.config.zway.zwayServer.openHABIpAddress.label = IP-Adresse -thing-type.config.zway.zwayServer.openHABIpAddress.description = Die Adresse unter der das openHAB-System erreichbar ist. Sollte sich der Z-Way Server und openHAB auf dem selben Rechner befinden, kann der Standardwert beibehalten werden. -thing-type.config.zway.zwayServer.openHABPort.label = Port -thing-type.config.zway.zwayServer.openHABPort.description = Der Port unter dem das openHAB-System erreichbar ist. -thing-type.config.zway.zwayServer.openHABProtocol.label = Protokoll -thing-type.config.zway.zwayServer.openHABProtocol.description = HTTP/HTTPS - -thing-type.config.zway.zwayServer.zwayServerIpAddress.label = IP-Adresse -thing-type.config.zway.zwayServer.zwayServerIpAddress.description = Die Adresse unter der Z-Way erreichbar ist. Sollte sich der Z-Way Server und openHAB auf dem selben Rechner befinden, kann der Standardwert beibehalten werden. -thing-type.config.zway.zwayServer.zwayServerPort.label = Port -thing-type.config.zway.zwayServer.zwayServerPort.description = Der Port unter dem das openHAB-System erreichbar ist. -thing-type.config.zway.zwayServer.zwayServerProtocol.label = Protokoll -thing-type.config.zway.zwayServer.zwayServerProtocol.description = HTTP/HTTPS -thing-type.config.zway.zwayServer.zwayServerUsername.label = Benutzername -thing-type.config.zway.zwayServer.zwayServerUsername.description = Benutzername für den Zugriff auf das Z-Way System. -thing-type.config.zway.zwayServer.zwayServerPassword.label = Passwort -thing-type.config.zway.zwayServer.zwayServerPassword.description = Passwort für den Zugriff auf das Z-Way System. - -thing-type.config.zway.zwayServer.pollingInterval.label = Polling Interval -thing-type.config.zway.zwayServer.pollingInterval.description = Aktualisiert den Gerätezustand und die Registrierung beim OpenHAB Konnektor -thing-type.config.zway.zwayServer.observerMechanismEnabled.label = Observer-Mechanismus -thing-type.config.zway.zwayServer.observerMechanismEnabled.description = Diese Funktion ist veranwortlich für die Aktualisierung der Gerätestatus. Achtung: Sollte die Funktion deaktiviert werden, muss ein anderer Synchronisationsmechanismus konfiguriert werden, bspw. MQTT. - -thing-type.zway.zwayDevice.label = Z-Wave Gerät -thing-type.zway.zwayDevice.description = Ein Z-Wave Gerät repräsentiert ein physisch existierendes Gerät. Dabei wird jede Gerätefunktion (Temperatursensor, Luftfeuchtigkeitsmesser usw.) einem Channel zugeordnet. Eine Bridge (Z-Way Server) wird als Vermittler zwischen openHAB und Z-Way benötigt. - -thing-type.config.zway.zwayDevice.nodeId.label = Node Id -thing-type.config.zway.zwayDevice.nodeId.description = Node Id des Geräts im Z-Wave Netzwerk - -thing-type.zway.zwayVirtualDevice.label = Z-Way virtuelles Gerät -thing-type.zway.zwayVirtualDevice.description = Ein virtuelles Gerät repräsentiert genau eine Sensor, Aktor oder ein Z-Way App mit einem Channel. Eine Bridge (Z-Way Server) wird als Vermittler zwischen openHAB und Z-Way benötigt. -thing-type.config.zway.zwayVirtualDevice.deviceId.label = Device Id -thing-type.config.zway.zwayVirtualDevice.deviceId.description = Device Id des virtuellen Geräts - -# channel types -channel-type.zway.sensorTemperature.label = Temperatur -channel-type.zway.sensorLuminosity.label = Helligkeit -channel-type.zway.sensorHumidity.label = Luftfeuchtigkeit -channel-type.zway.sensorBarometer.label = Luftdruck -channel-type.zway.sensorUltraviolet.label = Lichtintensität -channel-type.zway.sensorCO2.label = Kohlendioxid -channel-type.zway.sensorEnergy.label = Energie -channel-type.zway.sensorMeterKWh.label = Energie (kWh) -channel-type.zway.sensorMeterW.label = Energie (W) -channel-type.zway.sensorSmoke.label = Rauch -channel-type.zway.sensorCo.label = Gas -channel-type.zway.sensorFlood.label = Überflutung -channel-type.zway.sensorTamper.label = Manipulation -channel-type.zway.sensorDoorWindow.label = Tür-/Fensterkontakt -channel-type.zway.sensorMotion.label = Bewegung -channel-type.zway.switchPowerOutlet.label = Steckdose -channel-type.zway.switchColorTemperature.label = Farbtemperatur - -# channel type without further information - -channel-type.zway.battery.label = Batterie -channel-type.zway.doorlock.label = Türschloss -channel-type.zway.sensorBinary.label = Binärsensor -channel-type.zway.sensorBinary.description = Dieser Channel ist allgemeingültig für verschiedene Geräte des gleichen Gerätetyps, wenn keine weiteren Informationen zur Verfügung stehen. -channel-type.zway.sensorMultilevel.label = Multilevel-Sensor -channel-type.zway.sensorMultilevel.description = Dieser Channel ist allgemeingültig für verschiedene Geräte des gleichen Gerätetyps, wenn keine weiteren Informationen zur Verfügung stehen. -channel-type.zway.switchBinary.label = Binärschalter -channel-type.zway.switchBinary.description = Dieser Channel ist allgemeingültig für verschiedene Geräte des gleichen Gerätetyps, wenn keine weiteren Informationen zur Verfügung stehen. -channel-type.zway.switchMultilevel.label = Multilevel-Schalter -channel-type.zway.switchMultilevel.description = Dieser Channel ist allgemeingültig für verschiedene Geräte des gleichen Gerätetyps, wenn keine weiteren Informationen zur Verfügung stehen. -channel-type.zway.switchColor.label = RGB-Schalter -channel-type.zway.switchColor.description = Dieser Channel repräsentiert einen RGB-Schalter von Z-Way. -channel-type.zway.switchControl.label = Binärschalter -channel-type.zway.switchControl.description = Dieser Channel ist allgemeingültig für verschiedene Geräte des gleichen Gerätetyps, wenn keine weiteren Informationen zur Verfügung stehen. -channel-type.zway.thermostatMode.label = Thermostat Modus -channel-type.zway.thermostatMode.description = Dieser Channel erlaubt die Steuerung und Anzeige eines Thermostats (Modus). Ein Thermostat kann einer der drei Zustände einnehmen (Modi): "Aus", "Heizen" oder "Kühlen". Der Zustand "Heizen" und "Kühlen" wird wechselweise im Zustand "An" gesetzt. -channel-type.zway.thermostatSetPoint.label = Thermostat Sollwert - -channel-type.zway.thermostatModeV2.label = Thermostat Modus (Kommandoklasse) -channel-type.zway.thermostatModeV2.description = Dieser Channel erlaubt die Steuerung und Anzeige eines Thermostats (Modus) auf Basis der Kommandoklasse. Die verfügbaren Modi variieren von Gerät zu Gerät. - -channel-type.zway.actions.label = Aktionen -channel-type.zway.actions.description = Aktionen des Z-Wave Controller -channel-type.zway.actions.option.REFRESH = Alle Geräte aktualisieren - -channel-type.zway.secureInclusion.label = Sichere Inklusion -channel-type.zway.secureInclusion.description = ändert den Inklusionsmodus für folgende Inklusionen. -channel-type.zway.inclusion.label = Inklusionsmodus -channel-type.zway.inclusion.description = Starten des Inklusionsmodus (nach einem Timeout wird der Modus automatisch verlassen). -channel-type.zway.exclusion.label = Exklusionsmodus +# binding +binding.zway.name = Z-Way Binding +binding.zway.description = Das Z-Way-System ist ein Softwarepaket für den Z-Wave Funkstandard. Das System besteht im wesentlichen aus einer Firmware für Z-Wave Transceiver, einer Kommunikations- und einer Automatisierungskomponente zur Steuerung und Konfiguration des Netzwerks. Das Z-Way Binding nutzt die HTTP-Schnittstelle um alle Geräte zu laden und im Discovery-Prozess zur Verfügung zu stellen.
Neben einem Polling der Gerätezustände werden optional die resultierenden Geräte als Observer im Z-Way System registriert, um Zustandsänderungen der Geräte zu erhalten (dazu wird aktuell die Z-Way App OpenHAB Konnektor benötigt). + +# thing types +thing-type.zway.zwayServer.label = Z-Way Server +thing-type.zway.zwayServer.description = Der Z-Way Server repräsentiert das Z-Way System als Bridge mit der grundlegendene Konfiguration zum Verbindungsaufbau. Die gesamte Kommunikation mit Z-Way organisiert diese Komponente. + +thing-type.config.zway.zwayServer.openhab.label = openHAB +thing-type.config.zway.zwayServer.openhab.description = Der Z-Way Server benötigt diese Informationen um bei Statusänderungen openHAB zu benachrichtigen. Wenn Z-Way und openHAB auf dem gleichen Host ausgeführt werden, können die Standardwerte beibehalten werden. +thing-type.config.zway.zwayServer.zwayServer.label = Z-Way Server +thing-type.config.zway.zwayServer.zwayServer.description = Die Konfiguration des Z-Way Server wird bis auf den Benutzername und das Passwort während des Discovery-Prozesses ermittlt. +thing-type.config.zway.zwayServer.binding.label = Optionen +thing-type.config.zway.zwayServer.binding.description = Diese Einstellungen betreffen Funktionen des Bindings. + +thing-type.config.zway.zwayServer.openHABAlias.label = Alias +thing-type.config.zway.zwayServer.openHABAlias.description = Der Bezeichner wird für den openHAB-Konnektor benötigt und ist optional und frei wählbar, aber muss eindeutig sein. (Standard: ein generierter Wert) +thing-type.config.zway.zwayServer.openHABIpAddress.label = IP-Adresse +thing-type.config.zway.zwayServer.openHABIpAddress.description = Die Adresse unter der das openHAB-System erreichbar ist. Sollte sich der Z-Way Server und openHAB auf dem selben Rechner befinden, kann der Standardwert beibehalten werden. +thing-type.config.zway.zwayServer.openHABPort.label = Port +thing-type.config.zway.zwayServer.openHABPort.description = Der Port unter dem das openHAB-System erreichbar ist. +thing-type.config.zway.zwayServer.openHABProtocol.label = Protokoll +thing-type.config.zway.zwayServer.openHABProtocol.description = HTTP/HTTPS + +thing-type.config.zway.zwayServer.zwayServerIpAddress.label = IP-Adresse +thing-type.config.zway.zwayServer.zwayServerIpAddress.description = Die Adresse unter der Z-Way erreichbar ist. Sollte sich der Z-Way Server und openHAB auf dem selben Rechner befinden, kann der Standardwert beibehalten werden. +thing-type.config.zway.zwayServer.zwayServerPort.label = Port +thing-type.config.zway.zwayServer.zwayServerPort.description = Der Port unter dem das openHAB-System erreichbar ist. +thing-type.config.zway.zwayServer.zwayServerProtocol.label = Protokoll +thing-type.config.zway.zwayServer.zwayServerProtocol.description = HTTP/HTTPS +thing-type.config.zway.zwayServer.zwayServerUsername.label = Benutzername +thing-type.config.zway.zwayServer.zwayServerUsername.description = Benutzername für den Zugriff auf das Z-Way System. +thing-type.config.zway.zwayServer.zwayServerPassword.label = Passwort +thing-type.config.zway.zwayServer.zwayServerPassword.description = Passwort für den Zugriff auf das Z-Way System. + +thing-type.config.zway.zwayServer.pollingInterval.label = Polling Interval +thing-type.config.zway.zwayServer.pollingInterval.description = Aktualisiert den Gerätezustand und die Registrierung beim OpenHAB Konnektor +thing-type.config.zway.zwayServer.observerMechanismEnabled.label = Observer-Mechanismus +thing-type.config.zway.zwayServer.observerMechanismEnabled.description = Diese Funktion ist veranwortlich für die Aktualisierung der Gerätestatus. Achtung: Sollte die Funktion deaktiviert werden, muss ein anderer Synchronisationsmechanismus konfiguriert werden, bspw. MQTT. + +thing-type.zway.zwayDevice.label = Z-Wave Gerät +thing-type.zway.zwayDevice.description = Ein Z-Wave Gerät repräsentiert ein physisch existierendes Gerät. Dabei wird jede Gerätefunktion (Temperatursensor, Luftfeuchtigkeitsmesser usw.) einem Channel zugeordnet. Eine Bridge (Z-Way Server) wird als Vermittler zwischen openHAB und Z-Way benötigt. + +thing-type.config.zway.zwayDevice.nodeId.label = Node Id +thing-type.config.zway.zwayDevice.nodeId.description = Node Id des Geräts im Z-Wave Netzwerk + +thing-type.zway.zwayVirtualDevice.label = Z-Way virtuelles Gerät +thing-type.zway.zwayVirtualDevice.description = Ein virtuelles Gerät repräsentiert genau eine Sensor, Aktor oder ein Z-Way App mit einem Channel. Eine Bridge (Z-Way Server) wird als Vermittler zwischen openHAB und Z-Way benötigt. +thing-type.config.zway.zwayVirtualDevice.deviceId.label = Device Id +thing-type.config.zway.zwayVirtualDevice.deviceId.description = Device Id des virtuellen Geräts + +# channel types +channel-type.zway.sensorTemperature.label = Temperatur +channel-type.zway.sensorLuminosity.label = Helligkeit +channel-type.zway.sensorHumidity.label = Luftfeuchtigkeit +channel-type.zway.sensorBarometer.label = Luftdruck +channel-type.zway.sensorUltraviolet.label = Lichtintensität +channel-type.zway.sensorCO2.label = Kohlendioxid +channel-type.zway.sensorEnergy.label = Energie +channel-type.zway.sensorMeterKWh.label = Energie (kWh) +channel-type.zway.sensorMeterW.label = Energie (W) +channel-type.zway.sensorSmoke.label = Rauch +channel-type.zway.sensorCo.label = Gas +channel-type.zway.sensorFlood.label = Überflutung +channel-type.zway.sensorTamper.label = Manipulation +channel-type.zway.sensorDoorWindow.label = Tür-/Fensterkontakt +channel-type.zway.sensorMotion.label = Bewegung +channel-type.zway.switchPowerOutlet.label = Steckdose +channel-type.zway.switchColorTemperature.label = Farbtemperatur + +# channel type without further information + +channel-type.zway.battery.label = Batterie +channel-type.zway.doorlock.label = Türschloss +channel-type.zway.sensorBinary.label = Binärsensor +channel-type.zway.sensorBinary.description = Dieser Channel ist allgemeingültig für verschiedene Geräte des gleichen Gerätetyps, wenn keine weiteren Informationen zur Verfügung stehen. +channel-type.zway.sensorMultilevel.label = Multilevel-Sensor +channel-type.zway.sensorMultilevel.description = Dieser Channel ist allgemeingültig für verschiedene Geräte des gleichen Gerätetyps, wenn keine weiteren Informationen zur Verfügung stehen. +channel-type.zway.switchBinary.label = Binärschalter +channel-type.zway.switchBinary.description = Dieser Channel ist allgemeingültig für verschiedene Geräte des gleichen Gerätetyps, wenn keine weiteren Informationen zur Verfügung stehen. +channel-type.zway.switchMultilevel.label = Multilevel-Schalter +channel-type.zway.switchMultilevel.description = Dieser Channel ist allgemeingültig für verschiedene Geräte des gleichen Gerätetyps, wenn keine weiteren Informationen zur Verfügung stehen. +channel-type.zway.switchColor.label = RGB-Schalter +channel-type.zway.switchColor.description = Dieser Channel repräsentiert einen RGB-Schalter von Z-Way. +channel-type.zway.switchControl.label = Binärschalter +channel-type.zway.switchControl.description = Dieser Channel ist allgemeingültig für verschiedene Geräte des gleichen Gerätetyps, wenn keine weiteren Informationen zur Verfügung stehen. +channel-type.zway.thermostatMode.label = Thermostat Modus +channel-type.zway.thermostatMode.description = Dieser Channel erlaubt die Steuerung und Anzeige eines Thermostats (Modus). Ein Thermostat kann einer der drei Zustände einnehmen (Modi): "Aus", "Heizen" oder "Kühlen". Der Zustand "Heizen" und "Kühlen" wird wechselweise im Zustand "An" gesetzt. +channel-type.zway.thermostatSetPoint.label = Thermostat Sollwert + +channel-type.zway.thermostatModeV2.label = Thermostat Modus (Kommandoklasse) +channel-type.zway.thermostatModeV2.description = Dieser Channel erlaubt die Steuerung und Anzeige eines Thermostats (Modus) auf Basis der Kommandoklasse. Die verfügbaren Modi variieren von Gerät zu Gerät. + +channel-type.zway.actions.label = Aktionen +channel-type.zway.actions.description = Aktionen des Z-Wave Controller +channel-type.zway.actions.option.REFRESH = Alle Geräte aktualisieren + +channel-type.zway.secureInclusion.label = Sichere Inklusion +channel-type.zway.secureInclusion.description = ändert den Inklusionsmodus für folgende Inklusionen. +channel-type.zway.inclusion.label = Inklusionsmodus +channel-type.zway.inclusion.description = Starten des Inklusionsmodus (nach einem Timeout wird der Modus automatisch verlassen). +channel-type.zway.exclusion.label = Exklusionsmodus channel-type.zway.exclusion.description = Starten des Exklusionsmodus (nach einem Timeout wird der Modus automatisch verlassen). \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.zway/about.html b/addons/binding/org.openhab.binding.zway/about.html index 13d9a845d7dda..f2291f5c52abb 100644 --- a/addons/binding/org.openhab.binding.zway/about.html +++ b/addons/binding/org.openhab.binding.zway/about.html @@ -1,46 +1,46 @@ - - - - -About - - -

About This Content

- -

September 8, 2016

-

License

- -

The openHAB community makes available all content in this plug-in ("Content"). Unless otherwise -indicated below, the Content is provided to you under the terms and conditions of the -Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available -at http://www.eclipse.org/legal/epl-v10.html. -For purposes of the EPL, "Program" will mean the Content.

- -

If you did not receive this Content directly from the openHAB community, the Content is -being redistributed by another party ("Redistributor") and different terms and conditions may -apply to your use of any object code in the Content. Check the Redistributor's license that was -provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise -indicated below, the terms and conditions of the EPL still apply to any source code in the Content -and such source code may be obtained at http://www.openhab.org.

- -

Third Party Content

-

The Content includes items that have been sourced from third parties as set out below. If you - did not receive this Content directly from the openHAB community, the following is provided - for informational purposes only, and you should look to the Redistributor's license for - terms and conditions of use.

- -

- Apache Commons Lang 3.4

-
Apache License. -
Download. -

- -

- Z-Way Library for Java 0.1.7

-
Eclipse Public License - v 1.0. -
Github. -

- - + + + + +About + + +

About This Content

+ +

September 8, 2016

+

License

+ +

The openHAB community makes available all content in this plug-in ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available +at http://www.eclipse.org/legal/epl-v10.html. +For purposes of the EPL, "Program" will mean the Content.

+ +

If you did not receive this Content directly from the openHAB community, the Content is +being redistributed by another party ("Redistributor") and different terms and conditions may +apply to your use of any object code in the Content. Check the Redistributor's license that was +provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise +indicated below, the terms and conditions of the EPL still apply to any source code in the Content +and such source code may be obtained at http://www.openhab.org.

+ +

Third Party Content

+

The Content includes items that have been sourced from third parties as set out below. If you + did not receive this Content directly from the openHAB community, the following is provided + for informational purposes only, and you should look to the Redistributor's license for + terms and conditions of use.

+ +

+ Apache Commons Lang 3.4

+
Apache License. +
Download. +

+ +

+ Z-Way Library for Java 0.1.7

+
Eclipse Public License - v 1.0. +
Github. +

+ + \ No newline at end of file diff --git a/addons/binding/pom.xml b/addons/binding/pom.xml index afebd7c324799..7a2b2c6e7396e 100644 --- a/addons/binding/pom.xml +++ b/addons/binding/pom.xml @@ -68,6 +68,7 @@ org.openhab.binding.urtsi org.openhab.binding.vitotronic org.openhab.binding.yamahareceiver + org.openhab.binding.zoneminder org.openhab.binding.zway diff --git a/addons/voice/org.openhab.voice.marytts/OSGI-INF/TTSServiceMaryTTS.xml b/addons/voice/org.openhab.voice.marytts/OSGI-INF/TTSServiceMaryTTS.xml index ebb4b4a0ff072..b9384e0bddaf7 100644 --- a/addons/voice/org.openhab.voice.marytts/OSGI-INF/TTSServiceMaryTTS.xml +++ b/addons/voice/org.openhab.voice.marytts/OSGI-INF/TTSServiceMaryTTS.xml @@ -1,17 +1,17 @@ - - - - - - - - + + + + + + + + diff --git a/addons/voice/org.openhab.voice.voicerss/OSGI-INF/TTSServiceVoiceRSS.xml b/addons/voice/org.openhab.voice.voicerss/OSGI-INF/TTSServiceVoiceRSS.xml index d7fdb04fa94a2..f431e94fdd936 100644 --- a/addons/voice/org.openhab.voice.voicerss/OSGI-INF/TTSServiceVoiceRSS.xml +++ b/addons/voice/org.openhab.voice.voicerss/OSGI-INF/TTSServiceVoiceRSS.xml @@ -1,21 +1,21 @@ - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/features/openhab-addons/src/main/feature/feature.xml b/features/openhab-addons/src/main/feature/feature.xml index 84a34f3b112c4..97f95d36eadbd 100644 --- a/features/openhab-addons/src/main/feature/feature.xml +++ b/features/openhab-addons/src/main/feature/feature.xml @@ -279,6 +279,17 @@ openhab-transport-upnp mvn:org.openhab.binding/org.openhab.binding.yamahareceiver/${project.version} + + + openhab-runtime-base + mvn:org.openhab.binding/org.openhab.binding.zoneminder/${project.version} + + + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.binding/org.openhab.binding.zwave/${project.version} + openhab-runtime-base @@ -359,5 +370,16 @@ mvn:org.openhab.ui/org.openhab.ui.cometvisu.php/${project.version} mvn:org.openhab/com.caucho.quercus/4.0.45 - + + + + openhab-runtime-base + mvn:org.openhab.ui/org.openhab.ui.habmin/${project.version} + + + + openhab-runtime-base + mvn:org.openhab.ui/org.openhab.ui.habpanel/${project.version} + + diff --git a/project-orga/CONTRIBUTING.md b/project-orga/CONTRIBUTING.md deleted file mode 120000 index 44fcc63439371..0000000000000 --- a/project-orga/CONTRIBUTING.md +++ /dev/null @@ -1 +0,0 @@ -../CONTRIBUTING.md \ No newline at end of file diff --git a/project-orga/CONTRIBUTING.md b/project-orga/CONTRIBUTING.md new file mode 100644 index 0000000000000..44fcc63439371 --- /dev/null +++ b/project-orga/CONTRIBUTING.md @@ -0,0 +1 @@ +../CONTRIBUTING.md \ No newline at end of file diff --git a/project-orga/allmaintainers.sh b/project-orga/allmaintainers.sh old mode 100755 new mode 100644 diff --git a/project-orga/generate-authors.sh b/project-orga/generate-authors.sh old mode 100755 new mode 100644 diff --git a/project-orga/getmaintainer.sh b/project-orga/getmaintainer.sh old mode 100755 new mode 100644 diff --git a/project-orga/ref-tag/create.sh b/project-orga/ref-tag/create.sh old mode 100755 new mode 100644 diff --git a/targetplatform/.project b/targetplatform/.project index 13251b55a4c4c..782c1ff23ba90 100644 --- a/targetplatform/.project +++ b/targetplatform/.project @@ -1,11 +1,11 @@ - - - targetplatform - - - - - - - - + + + targetplatform + + + + + + + +