diff --git a/AUTHORS b/AUTHORS index 050aad496b902..cea55c0766848 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,7 +1,14 @@ # This file lists all individuals having contributed content to the repository. -# If you're submitting a patch, please add your name here in alphabetical order as part of the patch. -# -# For a list of active project maintainers, see the MAINTAINERS file. -# +# For how it is generated, see `project-orga/generate-authors.sh`. + +Dancho Penev +Gerhard Riegler +Gideon le Grange +Jochen Hiller Kai Kreuzer -Thomas Eichstädt-Engelen +kaikreuzer +Karel Goderis +kgoderis +manroh +Marcel Verpaalen +Oliver Libutzki diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 042edab71b019..a3bc109d62958 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -100,6 +100,18 @@ name and email address match your git configuration. The AUTHORS file is regenerated occasionally from the git commit history, so a mismatch may result in your changes being overwritten. +### Merge approval + +openHAB maintainers use LGTM (Looks Good To Me) in comments on the code review +to indicate acceptance. + +A change requires LGTMs from an absolute majority of the maintainers of each +component affected. For example, if a change affects `docs/` and `addons/`, it +needs an absolute majority from the maintainers of `docs/` AND, separately, an +absolute majority of the maintainers of `addons/`. + +For more details see [MAINTAINERS.md](project-orga/MAINTAINERS.md) + ### Sign your work The sign-off is a simple line at the end of the explanation for the @@ -177,3 +189,29 @@ There are several exceptions to the signing requirement. Currently these are: Don't forget: being a maintainer is a time investment. Make sure you will have time to make yourself available. You don't have to be a maintainer to make a difference on the project! + +## Community Guidelines + +We want to keep the openHAB community awesome, growing and collaborative. We +need your help to keep it that way. To help with this we've come up with some +general guidelines for the community as a whole: + +* Be nice: Be courteous, respectful and polite to fellow community members: no + regional, racial, gender, or other abuse will be tolerated. We like nice people + way better than mean ones! + +* Encourage diversity and participation: Make everyone in our community + feel welcome, regardless of their background and the extent of their + contributions, and do everything possible to encourage participation in + our community. + +* Keep it legal: Basically, don't get us in trouble. Share only content that + you own, do not share private or sensitive information, and don't break the + law. + +* Stay on topic: Make sure that you are posting to the correct channel + and avoid off-topic discussions. Remember when you update an issue or + respond to an email you are potentially sending to a large number of + people. Please consider this before you update. Also remember that + nobody likes spam. + diff --git a/MAINTAINERS b/MAINTAINERS new file mode 100644 index 0000000000000..b29ed11e19e58 --- /dev/null +++ b/MAINTAINERS @@ -0,0 +1 @@ +Kai Kreuzer (@kaikreuzer) diff --git a/addons/binding/create_openhab_binding_skeleton.cmd b/addons/binding/create_openhab_binding_skeleton.cmd new file mode 100644 index 0000000000000..34b85e62fb08b --- /dev/null +++ b/addons/binding/create_openhab_binding_skeleton.cmd @@ -0,0 +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.7.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 index e360a60525455..1706be36a6ef8 100755 --- a/addons/binding/create_openhab_binding_skeleton.sh +++ b/addons/binding/create_openhab_binding_skeleton.sh @@ -5,4 +5,4 @@ camelcaseId=$1 id=`echo $camelcaseId | tr '[:upper:]' '[:lower:]'` -mvn archetype:generate -DarchetypeGroupId=org.eclipse.smarthome.archetype -DarchetypeArtifactId=org.eclipse.smarthome.archetype.binding -DarchetypeVersion=0.7.0-SNAPSHOT -DgroupId=org.openhab.binding -DartifactId=org.openhab.binding.$id -Dpackage=org.openhab.binding.$id -DarchetypeCatalog='file://../archetype-catalog.xml' -Dversion=2.0.0-SNAPSHOT -DbindingId=$id -DbindingIdCamelCase=$camelcaseId -DvendorName=openHAB -Dnamespace=org.openhab +mvn archetype:generate -N -DarchetypeGroupId=org.eclipse.smarthome.archetype -DarchetypeArtifactId=org.eclipse.smarthome.archetype.binding -DarchetypeVersion=0.8.0-SNAPSHOT -DgroupId=org.openhab.binding -DartifactId=org.openhab.binding.$id -Dpackage=org.openhab.binding.$id -DarchetypeCatalog='file://../archetype-catalog.xml' -Dversion=2.0.0-SNAPSHOT -DbindingId=$id -DbindingIdCamelCase=$camelcaseId -DvendorName=openHAB -Dnamespace=org.openhab diff --git a/addons/binding/org.openhab.binding.max/.classpath b/addons/binding/org.openhab.binding.max/.classpath new file mode 100644 index 0000000000000..a95e0906ca013 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/addons/binding/org.openhab.binding.max/.project b/addons/binding/org.openhab.binding.max/.project new file mode 100644 index 0000000000000..2ccd0db7a83d2 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/.project @@ -0,0 +1,33 @@ + + + org.openhab.binding.max + + + + + + 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.max/ESH-INF/binding/binding.xml b/addons/binding/org.openhab.binding.max/ESH-INF/binding/binding.xml new file mode 100644 index 0000000000000..9d4ebd941df56 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/ESH-INF/binding/binding.xml @@ -0,0 +1,11 @@ + + + + MAX! Binding + This is the binding for the eQ-3 MAX! Home Solution. + Marcel Verpaalen + + diff --git a/addons/binding/org.openhab.binding.max/ESH-INF/thing/bridge.xml b/addons/binding/org.openhab.binding.max/ESH-INF/thing/bridge.xml new file mode 100644 index 0000000000000..db8131503749b --- /dev/null +++ b/addons/binding/org.openhab.binding.max/ESH-INF/thing/bridge.xml @@ -0,0 +1,53 @@ + + + + + + This bridge represents the MAX!Cube LAN gateway. + + + + network_address + + The IP address of the MAX! Cube LAN gateway + true + + + port + + Port of the LAN gateway + 62910 + false + + + + The refresh interval in ms which is used to poll given MAX! Cube. + 30000 + false + + + + The Serial Number identifies one specific device. + true + + + + If set to true, the binding will leave the connection to the Cube open. + false + false + + + + In exclusive mode, how many requests are allowed until connection is closed and reopened. + 1000 + false + + + + + + + diff --git a/addons/binding/org.openhab.binding.max/ESH-INF/thing/thing-types.xml b/addons/binding/org.openhab.binding.max/ESH-INF/thing/thing-types.xml new file mode 100644 index 0000000000000..0c21f2e5c9e2c --- /dev/null +++ b/addons/binding/org.openhab.binding.max/ESH-INF/thing/thing-types.xml @@ -0,0 +1,167 @@ + + + + + + + + + + This is a MAX! HeatingThermostat + + + + + + + + + + + + + The Serial Number identifies one specific device. + true + + + + + + + + + + + This is a MAX! HeatingThermostat+ + + + + + + + + + + + + + The Serial Number identifies one specific device. + true + + + + + + + + + + + This is a MAX! WallThermostat+ + + + + + + + + + + + + + The Serial Number identifies one specific device. + true + + + + + + + + + + + This is a MAX! EcoSwitch + + + + + + + + + The Serial Number identifies one specific device. + true + + + + + + + + + + + This is a MAX! Shutter Contact + + + + + + + + + + The Serial Number identifies one specific device. + true + + + + + + Number + + Thermostat Valve Position + + + + Switch + + Battery charge Level + + + + String + + Thermostat Mode Setting + + + + Number + + Actual measured room temperature + + + + Number + + Thermostat temperature setpoint + + + + Contact + + Contact state information + + + + Switch + + Eco Mode Activated + + + \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.max/META-INF/MANIFEST.MF b/addons/binding/org.openhab.binding.max/META-INF/MANIFEST.MF new file mode 100644 index 0000000000000..3b4f1112c55cf --- /dev/null +++ b/addons/binding/org.openhab.binding.max/META-INF/MANIFEST.MF @@ -0,0 +1,25 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: MaxCube Binding +Bundle-SymbolicName: org.openhab.binding.max;singleton:=true +Bundle-Vendor: openHAB +Bundle-Version: 2.0.0.qualifier +Bundle-RequiredExecutionEnvironment: JavaSE-1.7 +Bundle-ClassPath: . +Import-Package: com.google.common.base;version="10.0.1", + com.google.common.collect, + org.apache.commons.net.util, + org.eclipse.smarthome.config.core, + org.eclipse.smarthome.config.discovery, + org.eclipse.smarthome.core.common.registry, + org.eclipse.smarthome.core.library.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/* +Export-Package: org.openhab.binding.max + + diff --git a/addons/binding/org.openhab.binding.max/OSGI-INF/MaxCubeDiscovery.xml b/addons/binding/org.openhab.binding.max/OSGI-INF/MaxCubeDiscovery.xml new file mode 100644 index 0000000000000..5ec4ae4051acb --- /dev/null +++ b/addons/binding/org.openhab.binding.max/OSGI-INF/MaxCubeDiscovery.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + diff --git a/addons/binding/org.openhab.binding.max/OSGI-INF/MaxCubeHandlerFactory.xml b/addons/binding/org.openhab.binding.max/OSGI-INF/MaxCubeHandlerFactory.xml new file mode 100644 index 0000000000000..60f833ec97be8 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/OSGI-INF/MaxCubeHandlerFactory.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + diff --git a/addons/binding/org.openhab.binding.max/build.properties b/addons/binding/org.openhab.binding.max/build.properties new file mode 100644 index 0000000000000..66e21b90751a7 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/build.properties @@ -0,0 +1,6 @@ +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.max/pom.xml b/addons/binding/org.openhab.binding.max/pom.xml new file mode 100644 index 0000000000000..ad0ada87e6436 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/pom.xml @@ -0,0 +1,19 @@ + + + + 4.0.0 + + + org.openhab.binding + pom + 2.0.0-SNAPSHOT + + + org.openhab.binding + org.openhab.binding.max + 2.0.0-SNAPSHOT + + MAX! Binding + eclipse-plugin + + diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/MaxBinding.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/MaxBinding.java new file mode 100644 index 0000000000000..21f85e89d0e87 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/MaxBinding.java @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max; + +import java.util.Collection; +import java.util.Set; + +import org.eclipse.smarthome.core.thing.ThingTypeUID; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; + +/** + * The {@link MaxBinding} class defines common constants, which are + * used across the whole binding. + * + * @author Marcel Verpaalen - Initial contribution + */ +public class MaxBinding { + + public static final String BINDING_ID = "max"; + public static final String SERIAL_NUMBER = "serialNumber"; + public static final String IP_ADDRESS = "ipAddress"; + + // List of main device types + public static final String DEVICE_THERMOSTAT = "thermostat"; + public static final String DEVICE_THERMOSTATPLUS = "thermostatplus"; + public static final String DEVICE_WALLTHERMOSTAT = "wallthermostat"; + public static final String DEVICE_ECOSWITCH = "ecoswitch"; + public static final String DEVICE_SHUTTERCONTACT = "shuttercontact"; + public static final String BRIDGE_MAXCUBE = "bridge"; + + // List of all Thing Type UIDs + public final static ThingTypeUID HEATINGTHERMOSTAT_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_THERMOSTAT); + public final static ThingTypeUID HEATINGTHERMOSTATPLUS_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_THERMOSTATPLUS); + public final static ThingTypeUID WALLTHERMOSTAT_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_WALLTHERMOSTAT); + public final static ThingTypeUID ECOSWITCH_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_ECOSWITCH); + public final static ThingTypeUID SHUTTERCONTACT_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_SHUTTERCONTACT); + public final static ThingTypeUID CUBEBRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, BRIDGE_MAXCUBE); + + // List of all Channel ids + public final static String CHANNEL_VALVE = "valve"; + public final static String CHANNEL_BATTERY = "battery_low"; + public final static String CHANNEL_MODE = "mode"; + public final static String CHANNEL_ACTUALTEMP = "actual_temp"; + public final static String CHANNEL_SETTEMP = "set_temp"; + public final static String CHANNEL_SWITCH_STATE = "eco_mode"; + public final static String CHANNEL_CONTACT_STATE = "contact_state"; + + public final static Collection SUPPORTED_THING_TYPES_UIDS = Lists.newArrayList( + HEATINGTHERMOSTAT_THING_TYPE, HEATINGTHERMOSTATPLUS_THING_TYPE, WALLTHERMOSTAT_THING_TYPE, + ECOSWITCH_THING_TYPE, SHUTTERCONTACT_THING_TYPE, CUBEBRIDGE_THING_TYPE); + + public final static Set SUPPORTED_DEVICE_THING_TYPES_UIDS =ImmutableSet.of( + HEATINGTHERMOSTAT_THING_TYPE, HEATINGTHERMOSTATPLUS_THING_TYPE, WALLTHERMOSTAT_THING_TYPE, + ECOSWITCH_THING_TYPE, SHUTTERCONTACT_THING_TYPE); + + + public final static Set SUPPORTED_BRIDGE_THING_TYPES_UIDS =ImmutableSet.of( + CUBEBRIDGE_THING_TYPE); +} diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/config/MaxCubeBridgeConfiguration.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/config/MaxCubeBridgeConfiguration.java new file mode 100644 index 0000000000000..84deead040b56 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/config/MaxCubeBridgeConfiguration.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.config; + +import org.openhab.binding.max.MaxBinding; + +/** + * Configuration class for {@link MaxBinding} bridge used to connect to the + * maxCube device. + * + * @author Marcel Verpaalen - Initial contribution + */ + +public class MaxCubeBridgeConfiguration { + + /** The IP address of the MAX!Cube LAN gateway */ + public String ipAddress; + + /** + * The port of the MAX! Cube LAN gateway as provided at + * http://www.elv.de/controller.aspx?cid=824&detail=10&detail2=3484 + */ + public Integer port; + + /** The refresh interval in ms which is used to poll given MAX! Cube */ + public Integer refreshInterval; + + /** The unique serial number for a device */ + public String serialNumber; + + /** + * If set to true, the binding will leave the connection to the cube open + * and just request new informations. This allows much higher poll rates and + * causes less load than the non-exclusive polling but has the drawback that + * no other apps (i.E. original software) can use the cube while this + * binding is running. + */ + public boolean exclusive = false; + + /** + * in exclusive mode, how many requests are allowed until connection is + * closed and reopened + */ + public Integer maxRequestsPerConnection; +} diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/Utils.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/Utils.java new file mode 100644 index 0000000000000..56a189e7c9491 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/Utils.java @@ -0,0 +1,199 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.Date; + +/** + * Utility class for common tasks within the MAX! binding package. + * + * @author Andreas Heil (info@aheil.de) + * @author Marcel Verpaalen + * + * @since 1.4.0 + */ + +public final class Utils { + + /** + * Returns the integer value of an hexadecimal number (base 16). + * + * @param hex + * the hex value to be parsed into an integer + * @return the given hex value as integer + */ + public static final int fromHex(String hex) { + return Integer.parseInt(hex, 16); + } + + /** + * Returns the hexadecimal number of a number of integer values. + * + * @param values + * the integer values to be converted into hexadecimal numbers + * @return the given numbers as hexadecimal number + */ + public static final String toHex(int... values) { + String returnValue = ""; + for (int v : values) { + returnValue += v < 16 ? "0" + Integer.toHexString(v).toUpperCase() : Integer.toHexString(v).toUpperCase(); + } + return returnValue; + } + + /** + * Returns the hexadecimal number of a bit array . + * + * @param bits + * the boolean array representing the bits to be converted into + * hexadecimal numbers + * @return the hexadecimal number + */ + public static final String toHex(boolean[] bits) { + int retVal = 0; + for (int i = 0; i < bits.length; ++i) { + retVal |= (bits[i] ? 1 : 0) << i; + } + return toHex(retVal); + } + + /** + * Converts an Java signed byte into its general (unsigned) value as being + * used in other programming languages and platforms. + * + * @param b + * the byte to be converted into its integer value + * @return the integer value represented by the given byte + */ + public static final int fromByte(byte b) { + return b & 0xFF; + } + + /** + * Resolves the date and time based based on a three byte encoded within a + * MAX!Cube L message. + * + * Date decoding (two byte) + * + *
+	 * Hex     Binary
+	 * 9D0B    1001110100001011
+	 *   MMMDDDDDM YYYYYY
+	 *   100     0        = 1000b  = 8d  = month
+	 *      11101         = 11101b = 29d = day
+	 *             001011 = 1011b  = 11d = year-2000
+	 * 
+ * + * Time decoding (one byte) + * + *
+	 * Hex     Decimal
+	 * 1F      31 * 0.5 hours = 15:30
+	 * 
+ * + * @param date + * the date to be converted based on two bytes + * @param time + * the time to be converted based on a single byte + * @return the date time based on the values provided + */ + @SuppressWarnings("deprecation") + public static Date resolveDateTime(int date, int time) { + + int month = ((date & 0xE000) >> 12) + ((date & 0x80) >> 7); + int day = (date & 0x1F00) >> 8; + int year = (date & 0x0F) + 2000; + + int hours = (int) (time * 0.5); + int minutes = (int) (60 * ((time * 0.5) - hours)); + + return new Date(year, month, day, hours, minutes); + } + + /** + * Returns a bit representation as boolean values in a reversed manner. A + * bit string 0001 0010 would be returnd as + * 0100 1000. That way, the least significant bit can be + * addressed by bits[0], the second by bits[1] and so on. + * + * @param value + * the integer value to be converted in a bit array + * @return the bit array of the input value in a reversed manner. + */ + public static boolean[] getBits(int value) { + + boolean[] bits = new boolean[8]; + + for (int i = 0; i < 8; i++) { + bits[i] = (((value >> i) & 0x1) == 1); + } + + return bits; + } + + /** + * Convert a string representation of hexadecimal to a byte array. + * + * For example: String s = "00010203" returned byte array is {0x00, 0x01, + * 0x03} + * + * @param s + * @return byte array equivalent to hex string + **/ + public static byte[] hexStringToByteArray(String s) { + + int len = s.length(); + byte[] data = new byte[len / 2]; + + for (int i = 0; i < len; i += 2) { + data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16)); + } + + return data; + } + + /** + * Convert a byte array to a string representation of hexadecimals. + * + * For example: byte array is {0x00, 0x01, 0x03} returned String s = + * "00 01 02 03" + * + * @param byte array + * @return String equivalent to hex string + **/ + static final String HEXES = "0123456789ABCDEF"; + + public static String getHex(byte[] raw) { + if (raw == null) { + return null; + } + final StringBuilder hex = new StringBuilder(3 * raw.length); + for (final byte b : raw) { + hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt((b & 0x0F))).append(" "); + } + hex.delete(hex.length() - 1, hex.length()); + return hex.toString(); + } + + /** + * Retrieves the stacktrace of an exception as string. + * + * @param e + * the exception to resolve the stacktrace from + * @return the stacktrace from the exception provided + */ + public static String getStackTrace(Exception e) { + StringWriter stringWriter = new StringWriter(); + PrintWriter printWriter = new PrintWriter(stringWriter); + e.printStackTrace(printWriter); + return stringWriter.toString(); + } +} \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/discovery/MaxCubeBridgeDiscovery.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/discovery/MaxCubeBridgeDiscovery.java new file mode 100644 index 0000000000000..5c5aaf68ff7d4 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/discovery/MaxCubeBridgeDiscovery.java @@ -0,0 +1,225 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.discovery; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.InterfaceAddress; +import java.net.NetworkInterface; +import java.net.SocketTimeoutException; +import java.util.Enumeration; +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.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.openhab.binding.max.MaxBinding; +import org.openhab.binding.max.internal.Utils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link MaxCubeBridgeDiscovery} is responsible for discovering new MAX! + * Cube LAN gateway devices on the network + * + * @author Marcel Verpaalen - Initial contribution + * + */ +public class MaxCubeBridgeDiscovery extends AbstractDiscoveryService { + + static final String MAXCUBE_DISCOVER_STRING = "eQ3Max*\0**********I"; + + private final static Logger logger = LoggerFactory.getLogger(MaxCubeBridgeDiscovery.class); + + static boolean discoveryRunning = false; + + public MaxCubeBridgeDiscovery() { + super(MaxBinding.SUPPORTED_BRIDGE_THING_TYPES_UIDS, 15); + } + + @Override + public Set getSupportedThingTypes() { + return MaxBinding.SUPPORTED_BRIDGE_THING_TYPES_UIDS; + } + + @Override + public void startScan() { + discoverCube(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.smarthome.config.discovery.AbstractDiscoveryService# + * startBackgroundDiscovery() + */ + + @Override + protected void startBackgroundDiscovery() { + discoverCube(); + } + + @Override + public boolean isBackgroundDiscoveryEnabled() { + return true; + } + + private synchronized void discoverCube() { + discoveryRunning = true; + Thread thread = new Thread("Sendbroadcast") { + public void run() { + sendDiscoveryMessage(MAXCUBE_DISCOVER_STRING); + try { + sleep(5000); + } catch (Exception e) { + } + discoveryRunning = false; + logger.trace("Done sending broadcast discovery messages."); + } + }; + thread.start(); + receiveDiscoveryMessage(); + } + + private void receiveDiscoveryMessage() { + String maxCubeIP = null; + String maxCubeName = null; + String serialNumber = null; + String rfAddress = null; + DatagramSocket bcReceipt = null; + + try { + bcReceipt = new DatagramSocket(23272); + bcReceipt.setReuseAddress(true); + bcReceipt.setSoTimeout(10000); + + while (discoveryRunning) { + // Wait for a response + byte[] recvBuf = new byte[1500]; + DatagramPacket receivePacket = new DatagramPacket(recvBuf, recvBuf.length); + bcReceipt.receive(receivePacket); + + // We have a response + String message = new String(receivePacket.getData()).trim(); + logger.trace("Broadcast response from {} : {} '{}'", receivePacket.getAddress(), message.length(), + message); + + // Check if the message is correct + if (message.startsWith("eQ3Max") && !message.equals(MAXCUBE_DISCOVER_STRING)) { + maxCubeIP = receivePacket.getAddress().getHostAddress(); + maxCubeName = message.substring(0, 8); + serialNumber = message.substring(8, 18); + byte[] unknownData = message.substring(18, 21).getBytes(); + rfAddress = Utils.getHex(message.substring(21).getBytes()).replace(" ", "").toLowerCase(); + logger.debug("MAX! Cube found on network"); + logger.debug("Found at : {}", maxCubeIP); + logger.debug("Name : {}", maxCubeName); + logger.debug("Serial : {}", serialNumber); + logger.debug("RF Address: {}", rfAddress); + logger.trace("Unknown : {}", Utils.getHex(unknownData)); + discoveryResultSubmission(maxCubeIP, serialNumber); + } + } + } catch (SocketTimeoutException e) { + logger.trace("No further response"); + } catch (IOException e) { + logger.debug("IO error during MAX! Cube discovery: {}", e.getMessage()); + } finally { + // Close the port! + try { + if (bcReceipt != null) + bcReceipt.close(); + } catch (Exception e) { + logger.debug(e.toString()); + } + } + } + + private void discoveryResultSubmission(String IpAddress, String cubeSerialNumber) { + if (cubeSerialNumber != null) { + logger.trace("Adding new MAX! Cube Lan Gateway on {} with id '{}' to Smarthome inbox", IpAddress, + cubeSerialNumber); + Map properties = new HashMap<>(2); + properties.put(MaxBinding.IP_ADDRESS, IpAddress); + properties.put(MaxBinding.SERIAL_NUMBER, cubeSerialNumber); + ThingUID uid = new ThingUID(MaxBinding.CUBEBRIDGE_THING_TYPE, cubeSerialNumber); + if (uid != null) { + DiscoveryResult result = DiscoveryResultBuilder.create(uid).withProperties(properties) + .withLabel("MAX! Cube LAN Gateway").build(); + thingDiscovered(result); + } + } + } + + /** + * Send broadcast message over all active interfaces + * + * @param discoverString + * String to be used for the discovery + */ + private void sendDiscoveryMessage(String discoverString) { + DatagramSocket bcSend = null; + // Find the MaxCube using UDP broadcast + try { + bcSend = new DatagramSocket(); + bcSend.setBroadcast(true); + + byte[] sendData = discoverString.getBytes(); + + // Broadcast the message over all the network interfaces + Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); + while (interfaces.hasMoreElements()) { + NetworkInterface networkInterface = (NetworkInterface) interfaces.nextElement(); + if (networkInterface.isLoopback() || !networkInterface.isUp()) { + continue; + } + for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses()) { + InetAddress[] broadcast = new InetAddress[3]; + broadcast[0] = InetAddress.getByName("224.0.0.1"); + broadcast[0] = InetAddress.getByName("255.255.255.255"); + broadcast[1] = interfaceAddress.getBroadcast(); + for (InetAddress bc : broadcast) { + // Send the broadcast package! + if (bc != null) { + try { + DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, bc, 23272); + bcSend.send(sendPacket); + } catch (IOException e) { + logger.debug("IO error during MAX! Cube discovery: {}", e.getMessage()); + } catch (Exception e) { + logger.info(e.getMessage(), e); + } + logger.trace("Request packet sent to: {} Interface: {}", bc.getHostAddress(), + networkInterface.getDisplayName()); + } + } + } + } + logger.trace("Done looping over all network interfaces. Now waiting for a reply!"); + + } catch (IOException e) { + logger.debug("IO error during MAX! Cube discovery: {}", e.getMessage()); + } finally { + try { + if (bcSend != null) + bcSend.close(); + } catch (Exception e) { + // Ignore + } + } + + } + +} \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/discovery/MaxDeviceDiscoveryService.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/discovery/MaxDeviceDiscoveryService.java new file mode 100644 index 0000000000000..78b36efd48586 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/discovery/MaxDeviceDiscoveryService.java @@ -0,0 +1,106 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.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.Bridge; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.openhab.binding.max.MaxBinding; +import org.openhab.binding.max.internal.handler.DeviceStatusListener; +import org.openhab.binding.max.internal.handler.MaxCubeBridgeHandler; +import org.openhab.binding.max.internal.message.Device; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link MaxDeviceDiscoveryService} class is used to discover MAX! Cube + * devices that are connected to the Lan gateway. + * + * @author Marcel Verpaalen - Initial contribution + */ +public class MaxDeviceDiscoveryService extends AbstractDiscoveryService implements DeviceStatusListener { + + private final static Logger logger = LoggerFactory.getLogger(MaxDeviceDiscoveryService.class); + + private MaxCubeBridgeHandler maxCubeBridgeHandler; + + public MaxDeviceDiscoveryService(MaxCubeBridgeHandler maxCubeBridgeHandler) { + super(MaxBinding.SUPPORTED_DEVICE_THING_TYPES_UIDS, 10, true); + this.maxCubeBridgeHandler = maxCubeBridgeHandler; + } + + public void activate() { + maxCubeBridgeHandler.registerDeviceStatusListener(this); + } + + public void deactivate() { + maxCubeBridgeHandler.unregisterDeviceStatusListener(this); + } + + @Override + public Set getSupportedThingTypes() { + return MaxBinding.SUPPORTED_DEVICE_THING_TYPES_UIDS; + } + + @Override + public void onDeviceAdded(Bridge bridge, Device device) { + logger.trace("Adding new MAX! {} with id '{}' to smarthome inbox", device.getType(), device.getSerialNumber()); + ThingUID thingUID = null; + switch (device.getType()) { + case WallMountedThermostat: + thingUID = new ThingUID(MaxBinding.WALLTHERMOSTAT_THING_TYPE, bridge.getUID(), device.getSerialNumber()); + break; + case HeatingThermostat: + thingUID = new ThingUID(MaxBinding.HEATINGTHERMOSTAT_THING_TYPE, bridge.getUID(), device.getSerialNumber()); + break; + case HeatingThermostatPlus: + thingUID = new ThingUID(MaxBinding.HEATINGTHERMOSTATPLUS_THING_TYPE, bridge.getUID(), + device.getSerialNumber()); + break; + case ShutterContact: + thingUID = new ThingUID(MaxBinding.SHUTTERCONTACT_THING_TYPE, bridge.getUID(), device.getSerialNumber()); + break; + case EcoSwitch: + thingUID = new ThingUID(MaxBinding.ECOSWITCH_THING_TYPE, bridge.getUID(), device.getSerialNumber()); + break; + default: + break; + } + if (thingUID != null) { + DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID) + .withProperty(MaxBinding.SERIAL_NUMBER, device.getSerialNumber()).withBridge(bridge.getUID()) + .withLabel(device.getType() + ": " + device.getName()) + .build(); + thingDiscovered(discoveryResult); + } else { + logger.debug("Discovered MAX! device is unsupported: type '{}' with id '{}'", device.getType(), + device.getSerialNumber()); + } + } + + @Override + protected void startScan() { + // this can be ignored here as we discover via the bridge + } + + @Override + public void onDeviceStateChanged(ThingUID bridge, Device device) { + // this can be ignored here + } + + @Override + public void onDeviceRemoved(MaxCubeBridgeHandler bridge, Device device) { + // this can be ignored here + } +} diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/factory/MaxCubeHandlerFactory.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/factory/MaxCubeHandlerFactory.java new file mode 100644 index 0000000000000..130bc5b8f61f7 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/factory/MaxCubeHandlerFactory.java @@ -0,0 +1,112 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.factory; + +import java.util.Hashtable; + +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; +import org.openhab.binding.max.MaxBinding; +import org.openhab.binding.max.internal.discovery.MaxDeviceDiscoveryService; +import org.openhab.binding.max.internal.handler.MaxCubeBridgeHandler; +import org.openhab.binding.max.internal.handler.MaxDevicesHandler; +import org.osgi.framework.ServiceRegistration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link MaxCubeHandlerFactory} is responsible for creating things and + * thing handlers. + * + * @author Marcel Verpaalen - Initial contribution + */ + +public class MaxCubeHandlerFactory extends BaseThingHandlerFactory { + + private Logger logger = LoggerFactory.getLogger(MaxCubeHandlerFactory.class); + private ServiceRegistration discoveryServiceReg; + + @Override + public Thing createThing(ThingTypeUID thingTypeUID, Configuration configuration, ThingUID thingUID, + ThingUID bridgeUID) { + + if (MaxBinding.CUBEBRIDGE_THING_TYPE.equals(thingTypeUID)) { + ThingUID cubeBridgeUID = getBridgeThingUID(thingTypeUID, thingUID, configuration); + return super.createThing(thingTypeUID, configuration, cubeBridgeUID, null); + } + if (supportsThingType(thingTypeUID)) { + ThingUID deviceUID = getMaxCubeDeviceUID(thingTypeUID, thingUID, configuration, bridgeUID); + return super.createThing(thingTypeUID, configuration, deviceUID, bridgeUID); + } + throw new IllegalArgumentException("The thing type " + thingTypeUID + " is not supported by the binding."); + } + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return MaxBinding.SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + private ThingUID getBridgeThingUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Configuration configuration) { + if (thingUID == null) { + String SerialNumber = (String) configuration.get(MaxBinding.SERIAL_NUMBER); + thingUID = new ThingUID(thingTypeUID, SerialNumber); + } + return thingUID; + } + + private ThingUID getMaxCubeDeviceUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Configuration configuration, + ThingUID bridgeUID) { + String SerialNumber = (String) configuration.get(MaxBinding.SERIAL_NUMBER); + + if (thingUID == null) { + thingUID = new ThingUID(thingTypeUID, SerialNumber, bridgeUID.getId()); + } + return thingUID; + } + + private void registerDeviceDiscoveryService(MaxCubeBridgeHandler maxCubeBridgeHandler) { + MaxDeviceDiscoveryService discoveryService = new MaxDeviceDiscoveryService(maxCubeBridgeHandler); + discoveryService.activate(); + this.discoveryServiceReg = bundleContext.registerService(DiscoveryService.class.getName(), discoveryService, + new Hashtable()); + } + + @Override + protected void removeHandler(ThingHandler thingHandler) { + if (this.discoveryServiceReg != null) { + MaxDeviceDiscoveryService service = (MaxDeviceDiscoveryService) bundleContext + .getService(discoveryServiceReg.getReference()); + service.deactivate(); + discoveryServiceReg.unregister(); + discoveryServiceReg = null; + } + super.removeHandler(thingHandler); + } + + @Override + protected ThingHandler createHandler(Thing thing) { + if (thing.getThingTypeUID().equals(MaxBinding.CUBEBRIDGE_THING_TYPE)) { + MaxCubeBridgeHandler handler = new MaxCubeBridgeHandler((Bridge) thing); + registerDeviceDiscoveryService(handler); + return handler; + } else if (supportsThingType(thing.getThingTypeUID())) { + return new MaxDevicesHandler(thing); + } else { + logger.debug("ThingHandler not found for {}", thing.getThingTypeUID()); + return null; + } + } + +} \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/handler/DeviceStatusListener.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/handler/DeviceStatusListener.java new file mode 100644 index 0000000000000..967eafa4b62e7 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/handler/DeviceStatusListener.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.handler; + +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.openhab.binding.max.internal.message.Device; + +/** + * The {@link DeviceStatusListener} is notified when a device status has changed + * or a device has been removed or added. + * + * @author Marcel Verpaalen - Initial contribution + * + */ +public interface DeviceStatusListener { + + /** + * This method is called whenever the state of the given device has changed. + * The new state can be obtained by {@link FullLight#getState()}. + * + * @param bridge + * The MAX! Cube bridge the changed device is connected to. + * @param device + * The device which received the state update. + */ + public void onDeviceStateChanged(ThingUID bridge, Device device); + + /** + * This method us called whenever a device is removed. + * + * @param bridge + * The MAX! Cube bridge the removed device was connected to. + * @param device + * The device which is removed. + */ + public void onDeviceRemoved(MaxCubeBridgeHandler bridge, Device device); + + /** + * This method us called whenever a device is added. + * + * @param bridge + * The MAX! Cube bridge the added device was connected to. + * @param device + * The device which is added. + */ + public void onDeviceAdded(Bridge bridge, Device device); + +} diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/handler/MaxCubeBridgeHandler.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/handler/MaxCubeBridgeHandler.java new file mode 100644 index 0000000000000..22de137d3e978 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/handler/MaxCubeBridgeHandler.java @@ -0,0 +1,660 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.handler; + +import static org.openhab.binding.max.MaxBinding.CHANNEL_MODE; +import static org.openhab.binding.max.MaxBinding.CHANNEL_SETTEMP; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.ConnectException; +import java.net.Socket; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.io.OutputStreamWriter; + +import org.eclipse.smarthome.core.library.types.DecimalType; +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.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.eclipse.smarthome.core.types.RefreshType; +import org.openhab.binding.max.config.MaxCubeBridgeConfiguration; +import org.openhab.binding.max.internal.Utils; +import org.openhab.binding.max.internal.message.C_Message; +import org.openhab.binding.max.internal.message.Device; +import org.openhab.binding.max.internal.message.DeviceConfiguration; +import org.openhab.binding.max.internal.message.DeviceInformation; +import org.openhab.binding.max.internal.message.H_Message; +import org.openhab.binding.max.internal.message.HeatingThermostat; +import org.openhab.binding.max.internal.message.L_Message; +import org.openhab.binding.max.internal.message.M_Message; +import org.openhab.binding.max.internal.message.Message; +import org.openhab.binding.max.internal.message.MessageType; +import org.openhab.binding.max.internal.message.S_Command; +import org.openhab.binding.max.internal.message.S_Message; +import org.openhab.binding.max.internal.message.SendCommand; +import org.openhab.binding.max.internal.message.ThermostatModeType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * {@link MaxCubeBridgeHandler} is the handler for a MAX! Cube and connects it + * to the framework. All {@link MaxDevicesHandler}s use the + * {@link MaxCubeBridgeHandler} to execute the actual commands. + * + * @author Marcel Verpaalen - Initial contribution OH2 version + * @author Andreas Heil (info@aheil.de) - OH1 version + * @author Bernd Michael Helm (bernd.helm at helmundwalter.de) - Exclusive mode + * + */ +public class MaxCubeBridgeHandler extends BaseBridgeHandler { + // TODO: optional configuration to get the actual temperature on a + // configured interval by changing the valve / temp setting + + public MaxCubeBridgeHandler(Bridge br) { + super(br); + } + + private Logger logger = LoggerFactory.getLogger(MaxCubeBridgeHandler.class); + + /** The refresh interval which is used to poll given MAX!Cube */ + private long refreshInterval = 10000; + ScheduledFuture refreshJob; + + private ArrayList devices = new ArrayList(); + private HashSet lastActiveDevices = new HashSet(); + + /** MAX! Thermostat default off temperature */ + private static final DecimalType DEFAULT_OFF_TEMPERATURE = new DecimalType(4.5); + + /** MAX! Thermostat default on temperature */ + private static final DecimalType DEFAULT_ON_TEMPERATURE = new DecimalType(30.5); + + private ArrayList configurations = new ArrayList(); + + /** maximum queue size that we're allowing */ + private static final int MAX_COMMANDS = 50; + private ArrayBlockingQueue commandQueue = new ArrayBlockingQueue(MAX_COMMANDS); + + private boolean connectionEstablished = false; + + private SendCommand lastCommandId = null; + + private String ipAddress; + private int port; + private boolean exclusive; + private int maxRequestsPerConnection; + private int requestCount = 0; + + /** + * Duty cycle of the cube + */ + private int dutyCycle = 0; + + /** + * The available memory slots of the cube + */ + private int freeMemorySlots; + + /** + * connection socket and reader/writer for execute method + */ + private Socket socket = null; + private BufferedReader reader = null; + private OutputStreamWriter writer = null; + + private boolean previousOnline = false; + + private List deviceStatusListeners = new CopyOnWriteArrayList<>(); + + private ScheduledFuture pollingJob; + private Runnable pollingRunnable = new Runnable() { + @Override + public void run() { + refreshData(); + } + }; + private ScheduledFuture sendCommandJob; + private long sendCommandInterval = 5000; + private Runnable sendCommandRunnable = new Runnable() { + @Override + public void run() { + sendCommands(); + } + }; + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if (command instanceof RefreshType) { + logger.debug("Refresh command received."); + refreshData(); + } else + logger.warn("No bridge commands defined."); + } + + @Override + public void dispose() { + logger.debug("Handler disposed."); + if (pollingJob != null && !pollingJob.isCancelled()) { + pollingJob.cancel(true); + pollingJob = null; + } + if (sendCommandJob != null && !sendCommandJob.isCancelled()) { + sendCommandJob.cancel(true); + sendCommandJob = null; + } + + clearDeviceList(); + connectionEstablished = false; + + socketClose(); + super.dispose(); + } + + @Override + public void initialize() { + logger.debug("Initializing MAX! Cube bridge handler."); + + MaxCubeBridgeConfiguration configuration = getConfigAs(MaxCubeBridgeConfiguration.class); + port = configuration.port; + ipAddress = configuration.ipAddress; + refreshInterval = configuration.refreshInterval; + exclusive = configuration.exclusive; + maxRequestsPerConnection = configuration.maxRequestsPerConnection; + logger.debug("Cube IP {}.", ipAddress); + logger.debug("Port {}.", port); + logger.debug("RefreshInterval {}.", refreshInterval); + logger.debug("Exclusive mode {}.", exclusive); + logger.debug("Max Requests {}.", maxRequestsPerConnection); + + startAutomaticRefresh(); + + // workaround for issue #92: getHandler() returns NULL after + // configuration update. : + getThing().setHandler(this); + } + + private synchronized void startAutomaticRefresh() { + if (pollingJob == null || pollingJob.isCancelled()) { + pollingJob = scheduler.scheduleAtFixedRate(pollingRunnable, 0, refreshInterval, TimeUnit.MILLISECONDS); + } + if (sendCommandJob == null || sendCommandJob.isCancelled()) { + sendCommandJob = scheduler.scheduleAtFixedRate(sendCommandRunnable, 0, sendCommandInterval, + TimeUnit.MILLISECONDS); + } + } + + /** + * Takes a command from the command queue and send it to + * {@link executeCommand} for execution. + * + */ + private synchronized void sendCommands() { + + SendCommand sendCommand = commandQueue.poll(); + if (sendCommand != null) { + executeCommand(sendCommand); + } + } + + /** + * initiates read data from the maxCube bridge + */ + private synchronized void refreshData() { + + try { + refreshDeviceData(); + if (connectionEstablished) { + updateStatus(ThingStatus.ONLINE); + previousOnline = true; + for (Device di : devices) { + if (lastActiveDevices != null && lastActiveDevices.contains(di.getSerialNumber())) { + for (DeviceStatusListener deviceStatusListener : deviceStatusListeners) { + try { + deviceStatusListener.onDeviceStateChanged(getThing().getUID(), di); + } catch (Exception e) { + logger.error("An exception occurred while calling the DeviceStatusListener", e); + } + } + } + // New device, not seen before, pass to Discovery + else { + for (DeviceStatusListener deviceStatusListener : deviceStatusListeners) { + try { + deviceStatusListener.onDeviceAdded(getThing(), di); + di.setUpdated(true); + deviceStatusListener.onDeviceStateChanged(getThing().getUID(), di); + } catch (Exception e) { + logger.error("An exception occurred while calling the DeviceStatusListener", e); + } + lastActiveDevices.add(di.getSerialNumber()); + } + } + } + } else if (previousOnline) + onConnectionLost(); + + } catch (Exception e) { + logger.debug("Exception occurred during execution: {}", e.getMessage(), e); + } + } + + public void onConnectionLost() { + logger.info("Bridge connection lost. Updating thing status to OFFLINE."); + previousOnline = false; + updateStatus(ThingStatus.OFFLINE); + } + + public void onConnection() { + logger.info("Bridge connected. Updating thing status to ONLINE."); + updateStatus(ThingStatus.ONLINE); + } + + public boolean registerDeviceStatusListener(DeviceStatusListener deviceStatusListener) { + if (deviceStatusListener == null) { + throw new NullPointerException("It's not allowed to pass a null deviceStatusListener."); + } + boolean result = deviceStatusListeners.add(deviceStatusListener); + if (result) { + // onUpdate(); + } + return result; + } + + public boolean unregisterDeviceStatusListener(DeviceStatusListener deviceStatusListener) { + boolean result = deviceStatusListeners.remove(deviceStatusListener); + if (result) { + // onUpdate(); + } + return result; + } + + public void clearDeviceList() { + lastActiveDevices = new HashSet(); + } + + /** + * Processes device command and sends it to the MAX!Cube Lan Gateway. + * + * @param serialNumber + * the serial number of the device as String + * @param channelUID + * the ChannelUID used to send the command + * @param command + * the command data + */ + + /** + * Connects to the Max!Cube Lan gateway, reads and decodes the message this + * updates device information for each connected Max!Cube device + */ + private void refreshDeviceData() { + Message message; + + for (String raw : getRawMessage()) { + + try { + logger.trace("message block: '{}'", raw); + message = processRawMessage(raw); + if (message != null) { + message.debug(logger); + processMessage(message); + } + } catch (Exception e) { + logger.info("Failed to process message received by MAX! protocol."); + logger.debug(Utils.getStackTrace(e)); + } + } + + } + + /** + * Connects to the Max!Cube Lan gateway and returns the read data + * corresponding Message. + * + * @return the raw message text as ArrayList of String + */ + private ArrayList getRawMessage() { + synchronized (MaxCubeBridgeHandler.class) { + ArrayList rawMessage = new ArrayList(); + + try { + String raw = null; + if (socket == null) { + this.socketConnect(); + } else { + if (maxRequestsPerConnection > 0 && requestCount >= maxRequestsPerConnection) { + logger.debug("maxRequestsPerConnection reached, reconnecting."); + socket.close(); + this.socketConnect(); + requestCount = 0; + } else { + + /* + * if the connection is already open (this happens in + * exclusive mode), just send a "l:\r\n" to get the + * latest live informations note that "L:\r\n" or "l:\n" + * would not work. + */ + logger.debug("Sending state request #{} to MAX! Cube", this.requestCount); + if (writer == null) { + logger.warn("Can't write to MAX! Cube"); + this.socketConnect(); + } + writer.write("l:" + '\r' + '\n'); + writer.flush(); + requestCount++; + } + } + + boolean cont = true; + while (cont) { + raw = reader.readLine(); + if (raw == null) { + cont = false; + continue; + } + rawMessage.add(raw); + if (raw.startsWith("L:")) { + cont = false; + connectionEstablished = true; + } + } + + if (!exclusive) { + socketClose(); + } + } catch (ConnectException e) { + logger.debug("Connection timed out on {} port {}", ipAddress, port); + connectionEstablished = false; + socketClose(); // reconnect on next execution + } catch (UnknownHostException e) { + logger.debug("Host error occurred during execution: {}", e.getMessage()); + connectionEstablished = false; + socketClose(); // reconnect on next execution + } catch (IOException e) { + logger.debug("IO error occurred during execution: {}", e.getMessage()); + connectionEstablished = false; + socketClose(); // reconnect on next execution + } catch (Exception e) { + logger.debug("Exception occurred during execution: {}", e.getMessage(), e); + connectionEstablished = false; + socketClose(); // reconnect on next execution + } + + return rawMessage; + } + } + + /** + * Processes the raw TCP data read from the MAX protocol, returning the + * corresponding Message. + * + * @param raw + * the raw data line read from the MAX protocol + * @return message the @Message for the given raw data + */ + private Message processRawMessage(String raw) { + + if (raw.startsWith("H:")) { + return new H_Message(raw); + } else if (raw.startsWith("M:")) { + return new M_Message(raw); + } else if (raw.startsWith("C:")) { + return new C_Message(raw); + } else if (raw.startsWith("L:")) { + return new L_Message(raw); + } else if (raw.startsWith("S:")) { + return new S_Message(raw); + } else { + logger.debug("Unknown message block: '{}'", raw); + } + return null; + } + + /** + * Processes the message + * + * @param Message + * the decoded message data + */ + private void processMessage(Message message) { + + if (message != null) { + message.debug(logger); + if (message.getType() == MessageType.M) { + M_Message msg = (M_Message) message; + for (DeviceInformation di : msg.devices) { + DeviceConfiguration c = null; + for (DeviceConfiguration conf : configurations) { + if (conf.getSerialNumber().equalsIgnoreCase(di.getSerialNumber())) { + c = conf; + break; + } + } + + if (c != null) { + configurations.remove(c); + } + + c = DeviceConfiguration.create(di); + configurations.add(c); + + c.setRoomId(di.getRoomId()); + } + } else if (message.getType() == MessageType.C) { + DeviceConfiguration c = null; + for (DeviceConfiguration conf : configurations) { + if (conf.getSerialNumber().equalsIgnoreCase(((C_Message) message).getSerialNumber())) { + c = conf; + break; + } + } + + if (c == null) { + configurations.add(DeviceConfiguration.create(message)); + } else { + c.setValues((C_Message) message); + } + } else if (message.getType() == MessageType.L) { + ((L_Message) message).updateDevices(devices, configurations); + logger.trace("{} devices found.", devices.size()); + } else if (message.getType() == MessageType.S) { + dutyCycle = ((S_Message) message).getDutyCycle(); + freeMemorySlots = ((S_Message) message).getFreeMemorySlots(); + if (((S_Message) message).isCommandDiscarded()) { + logger.info("Last Send Command discarded. Duty Cycle: {}, Free Memory Slots: {}", dutyCycle, + freeMemorySlots); + } else + logger.debug("S message. Duty Cycle: {}, Free Memory Slots: {}", dutyCycle, freeMemorySlots); + } + } + } + + private Device getDevice(String serialNumber, ArrayList devices) { + for (Device device : devices) { + if (device.getSerialNumber().toUpperCase().equals(serialNumber)) { + return device; + } + } + return null; + } + + /** + * Returns the MAX! Device decoded during the last refreshData + * + * @param serialNumber + * the serial number of the device as String + * @return device the {@link Device} information decoded in last refreshData + */ + + public Device getDevice(String serialNumber) { + return getDevice(serialNumber, devices); + } + + /** + * Takes the device command and puts it on the command queue to be processed + * by the MAX!Cube Lan Gateway. Note that if multiple commands for the same + * item-channel combination are send prior that they are processed by the + * Max!Cube, they will be removed from the queue as they would not be + * meaningful. This will improve the behavior when using sliders in the GUI. + * + * @param SendCommand + * the SendCommand containing the serial number of the device as + * String the channelUID used to send the command and the the + * command data + */ + public synchronized void queueCommand(SendCommand sendCommand) { + + if (commandQueue.offer(sendCommand)) { + if (lastCommandId != null) { + if (lastCommandId.getKey().equals(sendCommand.getKey())) { + if (commandQueue.remove(lastCommandId)) + logger.debug("Removed Command id {} ({}) from queue. Superceeded by {}", lastCommandId.getId(), + lastCommandId.getKey(), sendCommand.getId()); + } + } + lastCommandId = sendCommand; + logger.debug("Command queued id {} ({}).", sendCommand.getId(), sendCommand.getKey()); + + } else { + logger.debug("Command queued full dropping command id {} ({}).", sendCommand.getId(), sendCommand.getKey()); + } + + } + + /** + * Processes device command and sends it to the MAX!Cube Lan Gateway. + * + * @param SendCommand + * the SendCommand containing the serial number of the device as + * String the channelUID used to send the command and the the + * command data + */ + public void executeCommand(SendCommand sendCommand) { + + String serialNumber = sendCommand.getDeviceSerial(); + ChannelUID channelUID = sendCommand.getChannelUID(); + Command command = sendCommand.getCommand(); + + // send command to MAX!Cube LAN Gateway + HeatingThermostat device = (HeatingThermostat) getDevice(serialNumber, devices); + + if (device == null) { + logger.debug("Cannot send command to device with serial number {}, device not listed.", serialNumber); + return; + } + + String rfAddress = device.getRFAddress(); + String commandString = null; + + // Temperature setting + if (channelUID.getId().equals(CHANNEL_SETTEMP)) { + + if (command instanceof DecimalType || command instanceof OnOffType) { + DecimalType decimalType = DEFAULT_OFF_TEMPERATURE; + if (command instanceof DecimalType) { + decimalType = (DecimalType) command; + } else if (command instanceof OnOffType) { + decimalType = OnOffType.ON.equals(command) ? DEFAULT_ON_TEMPERATURE : DEFAULT_OFF_TEMPERATURE; + } + + S_Command cmd = new S_Command(rfAddress, device.getRoomId(), device.getMode(), + decimalType.doubleValue()); + commandString = cmd.getCommandString(); + } + // Mode setting + } else if (channelUID.getId().equals(CHANNEL_MODE)) { + if (command instanceof StringType) { + String commandContent = command.toString().trim().toUpperCase(); + S_Command cmd = null; + ThermostatModeType commandThermoType = null; + if (commandContent.contentEquals(ThermostatModeType.AUTOMATIC.toString())) { + commandThermoType = ThermostatModeType.AUTOMATIC; + cmd = new S_Command(rfAddress, device.getRoomId(), commandThermoType); + } else if (commandContent.contentEquals(ThermostatModeType.BOOST.toString())) { + commandThermoType = ThermostatModeType.BOOST; + cmd = new S_Command(rfAddress, device.getRoomId(), commandThermoType); + } else if (commandContent.contentEquals(ThermostatModeType.MANUAL.toString())) { + commandThermoType = ThermostatModeType.MANUAL; + Double setTemp = Double.parseDouble(device.getTemperatureSetpoint().toString()); + cmd = new S_Command(rfAddress, device.getRoomId(), commandThermoType, setTemp); + logger.debug("updates to MANUAL mode with temperature '{}'", setTemp); + } else { + logger.debug("Only updates to AUTOMATIC & BOOST & MANUAL supported, received value :'{}'", + commandContent); + return; + } + commandString = cmd.getCommandString(); + } + } + // Actual sending of the data to the Max!Cube Lan Gateway + synchronized (MaxCubeBridgeHandler.class) { + if (commandString != null) { + try { + if (socket == null) { + this.socketConnect(); + } + writer.write(commandString); + writer.flush(); + String raw = reader.readLine(); + Message message = processRawMessage(raw); + if (message != null) + processMessage(message); + if (!exclusive) { + socketClose(); + } + + } catch (UnknownHostException e) { + logger.warn("Cannot establish connection with MAX! Cube lan gateway while sending command to '{}'", + ipAddress); + logger.debug(Utils.getStackTrace(e)); + socketClose(); // reconnect on next execution + } catch (IOException e) { + logger.warn("Cannot write data from MAX! Cube lan gateway while connecting to '{}'", ipAddress); + logger.debug(Utils.getStackTrace(e)); + socketClose(); // reconnect on next execution + } + logger.debug("Command {} ({}) sent to MAX! Cube at IP: {}", sendCommand.getId(), sendCommand.getKey(), + ipAddress); + logger.trace("Command {} content: '{}'", sendCommand.getId(), commandString); + } else { + logger.debug("Null Command not sent to {}", ipAddress); + } + } + } + + private boolean socketConnect() throws UnknownHostException, IOException { + socket = new Socket(ipAddress, port); + logger.debug("Open new connection... to {} port {}", ipAddress, port); + reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); + writer = new OutputStreamWriter(socket.getOutputStream()); + return true; + } + + private void socketClose() { + try { + socket.close(); + } catch (Exception e) { + } + socket = null; + } + +} \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/handler/MaxDevicesHandler.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/handler/MaxDevicesHandler.java new file mode 100644 index 0000000000000..c38396e9cf011 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/handler/MaxDevicesHandler.java @@ -0,0 +1,241 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.handler; + +import static org.openhab.binding.max.MaxBinding.CHANNEL_ACTUALTEMP; +import static org.openhab.binding.max.MaxBinding.CHANNEL_BATTERY; +import static org.openhab.binding.max.MaxBinding.CHANNEL_CONTACT_STATE; +import static org.openhab.binding.max.MaxBinding.CHANNEL_MODE; +import static org.openhab.binding.max.MaxBinding.CHANNEL_SETTEMP; +import static org.openhab.binding.max.MaxBinding.CHANNEL_VALVE; + +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.eclipse.smarthome.config.core.Configuration; +import org.eclipse.smarthome.core.thing.Bridge; +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.ThingUID; +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.RefreshType; +import org.eclipse.smarthome.core.types.State; +import org.openhab.binding.max.MaxBinding; +import org.openhab.binding.max.internal.message.Device; +import org.openhab.binding.max.internal.message.EcoSwitch; +import org.openhab.binding.max.internal.message.HeatingThermostat; +import org.openhab.binding.max.internal.message.SendCommand; +import org.openhab.binding.max.internal.message.ShutterContact; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link MaxDevicesHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Marcel Verpaalen - Initial contribution + */ +public class MaxDevicesHandler extends BaseThingHandler implements DeviceStatusListener { + + private Logger logger = LoggerFactory.getLogger(MaxDevicesHandler.class); + private int refresh = 60; // refresh every minute as default + ScheduledFuture refreshJob; + private MaxCubeBridgeHandler bridgeHandler; + + private String maxCubeDeviceSerial; + private boolean forceRefresh = true; + + public MaxDevicesHandler(Thing thing) { + super(thing); + } + + /** + * {@inheritDoc} + */ + @Override + public void initialize() { + + Configuration config = getThing().getConfiguration(); + final String configDeviceId = (String) config.get(MaxBinding.SERIAL_NUMBER); + + if (configDeviceId != null) { + maxCubeDeviceSerial = configDeviceId; + } + if (maxCubeDeviceSerial != null) { + logger.debug("Initialized maxcube device handler for {}.", maxCubeDeviceSerial); + } else { + logger.debug("Initialized maxcube device missing serialNumber configuration... troubles ahead"); + } + // until we get an update put the Thing offline + updateStatus(ThingStatus.OFFLINE); + deviceOnlineWatchdog(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.smarthome.core.thing.binding.BaseThingHandler#dispose() + */ + @Override + public void dispose() { + if (refreshJob != null && !refreshJob.isCancelled()) { + refreshJob.cancel(true); + refreshJob = null; + } + updateStatus(ThingStatus.OFFLINE); + if (bridgeHandler != null) + bridgeHandler.clearDeviceList(); + if (bridgeHandler != null) + bridgeHandler.unregisterDeviceStatusListener(this); + bridgeHandler = null; + logger.debug("Thing {} {} disposed.", getThing().getUID(), maxCubeDeviceSerial); + super.dispose(); + } + + private void deviceOnlineWatchdog() { + Runnable runnable = new Runnable() { + public void run() { + try { + MaxCubeBridgeHandler bridgeHandler = getMaxCubeBridgeHandler(); + if (bridgeHandler != null) { + if (bridgeHandler.getDevice(maxCubeDeviceSerial) == null) { + updateStatus(ThingStatus.OFFLINE); + bridgeHandler = null; + } else { + updateStatus(ThingStatus.ONLINE); + } + + } else { + logger.debug("Bridge for maxcube device {} not found.", maxCubeDeviceSerial); + updateStatus(ThingStatus.OFFLINE); + } + + } catch (Exception e) { + logger.debug("Exception occurred during execution: {}", e.getMessage(), e); + bridgeHandler = null; + } + + } + }; + + refreshJob = scheduler.scheduleAtFixedRate(runnable, 0, refresh, TimeUnit.SECONDS); + } + + private synchronized MaxCubeBridgeHandler getMaxCubeBridgeHandler() { + + if (this.bridgeHandler == null) { + Bridge bridge = getBridge(); + if (bridge == null) { + logger.debug("Required bridge not defined for device {}.", maxCubeDeviceSerial); + return null; + } + ThingHandler handler = bridge.getHandler(); + if (handler instanceof MaxCubeBridgeHandler) { + this.bridgeHandler = (MaxCubeBridgeHandler) handler; + this.bridgeHandler.registerDeviceStatusListener(this); + } else { + logger.debug("No available bridge handler found for {} bridge {} .", maxCubeDeviceSerial, + bridge.getUID()); + return null; + } + } + return this.bridgeHandler; + } + + /** + * {@inheritDoc} + */ + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + MaxCubeBridgeHandler maxCubeBridge = getMaxCubeBridgeHandler(); + if (maxCubeBridge == null) { + logger.warn("maxCube LAN gateway bridge handler not found. Cannot handle command without bridge."); + return; + } + if (command instanceof RefreshType) { + forceRefresh = true; + maxCubeBridge.handleCommand(channelUID, command); + return; + } + if (maxCubeDeviceSerial == null) { + logger.warn("Serial number missing. Can't send command to device '{}'", getThing()); + return; + } + + if (channelUID.getId().equals(CHANNEL_SETTEMP) || channelUID.getId().equals(CHANNEL_MODE)) { + SendCommand sendCommand = new SendCommand(maxCubeDeviceSerial, channelUID, command); + maxCubeBridge.queueCommand(sendCommand); + } else { + logger.warn("Setting of channel {} not possible. Read-only", channelUID); + } + } + + @Override + public void onDeviceStateChanged(ThingUID bridge, Device device) { + if (device.getSerialNumber().equals(maxCubeDeviceSerial)) { + updateStatus(ThingStatus.ONLINE); + if (device.isUpdated() || forceRefresh) { + forceRefresh = false; + logger.debug("Updating states of {} {} ({}) id: {}", device.getType(), device.getName(), + device.getSerialNumber(), getThing().getUID()); + switch (device.getType()) { + case WallMountedThermostat: + case HeatingThermostat: + case HeatingThermostatPlus: + updateState(new ChannelUID(getThing().getUID(), CHANNEL_SETTEMP), + (State) ((HeatingThermostat) device).getTemperatureSetpoint()); + updateState(new ChannelUID(getThing().getUID(), CHANNEL_ACTUALTEMP), + (State) ((HeatingThermostat) device).getTemperatureActual()); + updateState(new ChannelUID(getThing().getUID(), CHANNEL_MODE), + (State) ((HeatingThermostat) device).getModeString()); + updateState(new ChannelUID(getThing().getUID(), CHANNEL_BATTERY), + (State) ((HeatingThermostat) device).getBatteryLow()); + updateState(new ChannelUID(getThing().getUID(), CHANNEL_VALVE), + (State) ((HeatingThermostat) device).getValvePosition()); + break; + case ShutterContact: + updateState(new ChannelUID(getThing().getUID(), CHANNEL_CONTACT_STATE), + (State) ((ShutterContact) device).getShutterState()); + updateState(new ChannelUID(getThing().getUID(), CHANNEL_BATTERY), + (State) ((ShutterContact) device).getBatteryLow()); + break; + case EcoSwitch: + updateState(new ChannelUID(getThing().getUID(), CHANNEL_BATTERY), + (State) ((EcoSwitch) device).getBatteryLow()); + break; + default: + logger.debug("Unhandled Device {}.", device.getType()); + break; + + } + } else + logger.debug("No changes for {} {} ({}) id: {}", device.getType(), device.getName(), + device.getSerialNumber(), getThing().getUID()); + } + } + + @Override + public void onDeviceRemoved(MaxCubeBridgeHandler bridge, Device device) { + if (device.getSerialNumber().equals(maxCubeDeviceSerial)) { + bridgeHandler.unregisterDeviceStatusListener(this); + bridgeHandler = null; + forceRefresh = true; + getThing().setStatus(ThingStatus.OFFLINE); + } + } + + @Override + public void onDeviceAdded(Bridge bridge, Device device) { + forceRefresh = true; + } + +} diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/C_Message.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/C_Message.java new file mode 100644 index 0000000000000..5084c8adc43e7 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/C_Message.java @@ -0,0 +1,214 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.message; + +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.net.util.Base64; +import org.openhab.binding.max.internal.Utils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Strings; + +/** + * The C message contains configuration about a MAX! device. + * + * @author Andreas Heil (info@aheil.de) + * @author Marcel Verpaalen - Detailed parsing, OH2 Update + * @since 1.4.0 + */ +public final class C_Message extends Message { + + private static final Logger logger = LoggerFactory.getLogger(C_Message.class); + + private String rfAddress = null; + private int length = 0; + private DeviceType deviceType = null; + private String serialNumber = null; + private String tempComfort= null; + private String tempEco = null; + private String tempSetpointMax= null; + private String tempSetpointMin= null; + private String tempOffset = null; + private String tempOpenWindow = null; + private String durationOpenWindow = null; + private String decalcification = null; + private String valveMaximum = null; + private String valveOffset = null; + private String programData = null; + private String boostDuration = null; + private String boostValve = null; + private Map properties = new HashMap<>(); + + public C_Message(String raw) { + super(raw); + String[] tokens = this.getPayload().split(Message.DELIMETER); + + rfAddress = tokens[0]; + + byte[] bytes = Base64.decodeBase64(tokens[1].getBytes()); + + int[] data = new int[bytes.length]; + + for (int i = 0; i < bytes.length; i++) { + data[i] = bytes[i] & 0xFF; + } + + length = data[0]; + if (length != data.length - 1) { + logger.debug("C_Message malformed: wrong data length. Expected bytes {}, actual bytes {}", length, data.length - 1); + } + + String rfAddress2 = Utils.toHex(data[1], data[2], data[3]); + if (!rfAddress.toUpperCase().equals(rfAddress2.toUpperCase())) { + logger.debug("C_Message malformed: wrong RF address. Expected address {}, actual address {}", rfAddress.toUpperCase(), rfAddress2.toUpperCase()); + } + + deviceType = DeviceType.create(data[4]); + + serialNumber = getSerialNumber(bytes); + if (deviceType == DeviceType.HeatingThermostatPlus || deviceType == DeviceType.HeatingThermostat || deviceType == DeviceType.WallMountedThermostat) parseHeatingThermostatData (bytes); + if (deviceType == DeviceType.EcoSwitch || deviceType == DeviceType.ShutterContact) logger.trace("Device {} type {} Data:", rfAddress, deviceType.toString() , parseData (bytes)); + } + + private String getSerialNumber(byte[] bytes) { + byte[] sn = new byte[10]; + + for (int i = 0; i < 10; i++) { + sn[i] = (byte) bytes[i + 8]; + } + + try { + return new String(sn, "UTF-8"); + } catch (UnsupportedEncodingException e) { + logger.debug("Cannot encode serial number from C message due to encoding issues."); + } + + return ""; + } + + private String parseData(byte[] bytes) { + if (bytes.length <= 18) return ""; + try{ + int DataStart = 18; + byte[] sn = new byte[bytes.length - DataStart]; + + for (int i = 0; i < sn.length; i++) { + sn[i] = (byte) bytes[i + DataStart]; + } + logger.trace("DataBytes: " + Utils.getHex(sn)); + try { + return new String(sn, "UTF-8"); + } catch (UnsupportedEncodingException e) { + logger.debug("Cannot encode device string from C message due to encoding issues."); + } + + } catch (Exception e) { + logger.debug(e.getMessage()); + logger.debug(Utils.getStackTrace(e)); + } + + return ""; + } + + private void parseHeatingThermostatData(byte[] bytes) { + try{ + + int plusDataStart = 18; + int programDataStart = 11; + tempComfort= Float.toString( bytes[plusDataStart ]/2); + tempEco = Float.toString( bytes[plusDataStart + 1]/2); + tempSetpointMax= Float.toString( bytes[plusDataStart + 2]/2); + tempSetpointMin= Float.toString( bytes[plusDataStart + 3]/2); + properties.put("Temp Comfort",tempComfort); + properties.put("Temp Eco",tempEco); + properties.put("Temp Setpoint Max",tempSetpointMax); + properties.put("Temp Setpoint Min",tempSetpointMin); + if (bytes.length < 211) { + // Device is a WallMountedThermostat + programDataStart = 4; + logger.trace("WallThermostat byte {}: {}", bytes.length -3, Float.toString( bytes[bytes.length -3]&0xFF)); + logger.trace("WallThermostat byte {}: {}", bytes.length -2, Float.toString( bytes[bytes.length -2]&0xFF)); + logger.trace("WallThermostat byte {}: {}", bytes.length -1, Float.toString( bytes[bytes.length -1]&0xFF)); + } else + { + // Device is a HeatingThermostat(+) + tempOffset = Double.toString( (bytes[plusDataStart +4 ]/2) - 3.5); + tempOpenWindow = Float.toString( bytes[plusDataStart + 5]/2); + durationOpenWindow = Float.toString( bytes[plusDataStart + 6]); + boostDuration = Float.toString( bytes[plusDataStart + 7]&0xFF >> 5 ); + boostValve = Float.toString( (bytes[plusDataStart + 7]&0x1F)*5); + decalcification = Float.toString( bytes[plusDataStart + 8]); + valveMaximum = Float.toString( bytes[plusDataStart + 9]&0xFF * 100 / 255); + valveOffset = Float.toString( bytes[plusDataStart+ 10]&0xFF * 100 / 255 ); + properties.put("Temp Offset",tempOffset); + properties.put("Temp Open Window",tempOpenWindow); + properties.put("Duration Open Windoww",durationOpenWindow); + properties.put("Duration Boost",boostDuration); + properties.put("Duration Boost",boostValve); + properties.put("Decalcification",decalcification); + properties.put("ValveMaximum",valveMaximum); + properties.put("ValveOffset",valveOffset); + } + programData = ""; + int ln = 13 * 6; //first day = Sat + String startTime = "00:00h"; + for (int char_idx = plusDataStart + programDataStart; char_idx < (plusDataStart + programDataStart + 26*7); char_idx++) { + if (ln % 13 == 0 ) { programData += "\r\n Day " + Integer.toString((ln / 13) % 7 ) + ": "; startTime = "00:00h"; } + int progTime = (bytes[char_idx+1]&0xFF ) * 5 + (bytes[char_idx]&0x01 ) * 1280 ; + int progMinutes = progTime % 60; + int progHours = (progTime - progMinutes ) / 60; + String endTime = Integer.toString(progHours) + ":" + String.format("%02d", progMinutes) + "h"; + programData += startTime + "-" + endTime + " " + Double.toString(bytes[char_idx] /4) + "C "; + startTime = endTime; + char_idx++; + ln++; + } + + + } catch (Exception e) { + logger.debug(e.getMessage()); + logger.debug(Utils.getStackTrace(e)); + } + return ; + } + + public String getSerialNumber() { + return serialNumber; + } + + @Override + public MessageType getType() { + return MessageType.C; + } + + public String getRFAddress() { + return rfAddress; + } + + public DeviceType getDeviceType() { + return deviceType; + } + + @Override + public void debug(Logger logger) { + logger.trace("=== C_Message === "); + logger.trace("\tRAW: {}", this.getPayload()); + logger.trace("DeviceType: {}" , deviceType.toString()); + logger.trace("SerialNumber: {}" , serialNumber); + logger.trace("RFAddress: {}" , rfAddress); + for(String key: properties.keySet()){ + logger.trace("{}:{}{}", key , Strings.repeat(" ",25 - key.length() ), properties.get(key)); + } + logger.trace("ProgramData: {}", programData); + } +} diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/Device.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/Device.java new file mode 100644 index 0000000000000..5d9cd0a1a1850 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/Device.java @@ -0,0 +1,316 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.message; + +import java.util.Date; +import java.util.List; + +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.OpenClosedType; +import org.openhab.binding.max.internal.Utils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Base class for devices provided by the MAX!Cube protocol. + * + * @author Andreas Heil (info@aheil.de) + * @author Marcel Verpaalen - OH2 update + * @since 1.4.0 + */ +public abstract class Device { + + private final static Logger logger = LoggerFactory.getLogger(Device.class); + + private String serialNumber = ""; + private String rfAddress = ""; + private int roomId = -1; + private DeviceConfiguration config; + + private boolean updated; + private boolean batteryLow; + + private boolean initialized; + private boolean answer; + private boolean error; + private boolean valid; + private boolean DstSettingsActive; + private boolean gatewayKnown; + private boolean panelLocked; + private boolean linkStatusError; + + public Device(DeviceConfiguration c) { + this.serialNumber = c.getSerialNumber(); + this.rfAddress = c.getRFAddress(); + this.roomId= c.getRoomId(); + this.config = c; + } + + public abstract DeviceType getType(); + + public String getName(){ + return config.getName(); + } + + private static Device create(String rfAddress, List configurations) { + Device returnValue = null; + for (DeviceConfiguration c : configurations) { + if (c.getRFAddress().toUpperCase().equals(rfAddress.toUpperCase())) { + switch (c.getDeviceType()) { + case HeatingThermostatPlus: + case HeatingThermostat: + HeatingThermostat thermostat = new HeatingThermostat(c); + thermostat.setType(c.getDeviceType()); + return thermostat; + case EcoSwitch: + return new EcoSwitch(c); + case ShutterContact: + return new ShutterContact(c); + case WallMountedThermostat: + return new WallMountedThermostat(c); + default: + return new UnsupportedDevice(c); + } + } + } + return returnValue; + } + + public static Device create(byte[] raw, List configurations) { + if (raw.length == 0) { + return null; + } + + String rfAddress = Utils.toHex(raw[0] & 0xFF, raw[1] & 0xFF, raw[2] & 0xFF); + + // Based on the RF address and the corresponding configuration, + // create the device based on the type specified in it's configuration + + Device device = Device.create(rfAddress, configurations); + if (device == null) { + logger.warn("Can't create device from received message, returning NULL."); + return null; + } + + return Device.update(raw,configurations, device); + } + + public static Device update(byte[] raw, List configurations, Device device) { + + String rfAddress = device.getRFAddress(); + + // byte 4 is skipped + + // multiple device information are encoded in those particular bytes + boolean[] bits1 = Utils.getBits(Utils.fromByte(raw[4])); + boolean[] bits2 = Utils.getBits(Utils.fromByte(raw[5])); + + device.setInitialized(bits1[1]); + device.setAnswer(bits1[2]); + device.setError(bits1[3]); + device.setValid(bits1[4]); + + device.setDstSettingActive(bits2[3]); + device.setGatewayKnown(bits2[4]); + device.setPanelLocked(bits2[5]); + device.setLinkStatusError(bits2[6]); + device.setBatteryLow(bits2[7]); + + logger.trace ("Device {} type {} L Message length: {} content: {}", rfAddress,device.getType().toString(), raw.length,Utils.getHex(raw)); + + // TODO move the device specific readings into the sub classes + switch (device.getType()) { + case WallMountedThermostat: + case HeatingThermostat: + case HeatingThermostatPlus: + HeatingThermostat heatingThermostat = (HeatingThermostat) device; + // "xxxx xx00 = automatic, xxxx xx01 = manual, xxxx xx10 = vacation, xxxx xx11 = boost": + if (bits2[1] == false && bits2[0] == false) { + heatingThermostat.setMode(ThermostatModeType.AUTOMATIC); + } else if (bits2[1] == false && bits2[0] == true) { + heatingThermostat.setMode(ThermostatModeType.MANUAL); + } else if (bits2[1] == true && bits2[0] == false) { + heatingThermostat.setMode(ThermostatModeType.VACATION); + } else if (bits2[1] == true && bits2[0] == true) { + heatingThermostat.setMode(ThermostatModeType.BOOST); + } else { + logger.debug ("Device {}: Unknown mode",rfAddress) ; + } + + heatingThermostat.setValvePosition(raw[6] & 0xFF); + heatingThermostat.setTemperatureSetpoint(raw[7] & 0x7F); + + // 9 2 858B Date until (05-09-2011) (see Encoding/Decoding + // date/time) + // B 1 2E Time until (23:00) (see Encoding/Decoding date/time) + String hexDate = Utils.toHex(raw[8] & 0xFF, raw[9] & 0xFF); + int dateValue = Utils.fromHex(hexDate); + int timeValue = raw[10] & 0xFF; + Date date = Utils.resolveDateTime(dateValue, timeValue); + heatingThermostat.setDateSetpoint(date); + + int actualTemp = 0; + if (device.getType() == DeviceType.WallMountedThermostat) { + actualTemp = (raw[11] & 0xFF) + (raw[7] & 0x80) * 2 ; + + } else { + if ( heatingThermostat.getMode() != ThermostatModeType.VACATION && + heatingThermostat.getMode() != ThermostatModeType.BOOST){ + actualTemp = (raw[8] & 0xFF ) * 256 + ( raw[9] & 0xFF ); + } else{ + logger.debug ("Device {}: No temperature reading in {} mode",rfAddress, heatingThermostat.getMode()) ; + } + } + logger.trace ("Device {}: Actual Temperature : {}",rfAddress, (double)actualTemp / 10); + heatingThermostat.setTemperatureActual((double)actualTemp / 10); + break; + case EcoSwitch: + String eCoSwitchData = Utils.toHex(raw[3] & 0xFF, raw[4] & 0xFF, raw[5] & 0xFF); + logger.trace ("EcoSwitch Device {} status bytes : {}", rfAddress, eCoSwitchData); + EcoSwitch ecoswitch = (EcoSwitch) device; + // xxxx xx10 = shutter open, xxxx xx00 = shutter closed + if (bits2[1] == true && bits2[0] == false) { + ecoswitch.setEcoMode(OnOffType.ON); + logger.trace ("Device {} status: ON", rfAddress); + } else if (bits2[1] == false && bits2[0] == false) { + ecoswitch.setEcoMode(OnOffType.OFF); + logger.trace ("Device {} status: OFF", rfAddress); + } else { + logger.trace ("Device {} status switch status Unknown (true-true)", rfAddress); + } + break; + case ShutterContact: + ShutterContact shutterContact = (ShutterContact) device; + // xxxx xx10 = shutter open, xxxx xx00 = shutter closed + if (bits2[1] == true && bits2[0] == false) { + shutterContact.setShutterState(OpenClosedType.OPEN); + logger.trace ("Device {} status: Open", rfAddress); + } else if (bits2[1] == false && bits2[0] == false) { + shutterContact.setShutterState(OpenClosedType.CLOSED); + logger.trace ("Device {} status: Closed", rfAddress); + } else { + logger.trace ("Device {} status switch status Unknown (true-true)", rfAddress); + } + + break; + default: + logger.debug("Unhandled Device. DataBytes: " + Utils.getHex(raw)); + break; + + } + return device; + } + + private final void setBatteryLow(boolean batteryLow) { + if(this.batteryLow != batteryLow) { + this.updated = true; + }else { + this.updated = false; + } + this.batteryLow = batteryLow; + } + + public final OnOffType getBatteryLow() { + return (this.batteryLow ? OnOffType.ON : OnOffType.OFF); + } + + public final String getRFAddress() { + return this.rfAddress; + } + + public final void setRFAddress(String rfAddress) { + this.rfAddress = rfAddress; + } + + public final int getRoomId() { + return roomId; + } + + public final void setRoomId(int roomId) { + this.roomId = roomId; + } + + private void setLinkStatusError(boolean linkStatusError) { + this.linkStatusError = linkStatusError; + } + + private void setPanelLocked(boolean panelLocked) { + this.panelLocked = panelLocked; + } + + private void setGatewayKnown(boolean gatewayKnown) { + this.gatewayKnown = gatewayKnown; + } + + private void setDstSettingActive(boolean dstSettingsActive) { + this.DstSettingsActive = dstSettingsActive; + } + + public boolean isDstSettingsActive() { + return DstSettingsActive; + } + + private void setValid(boolean valid) { + this.valid = valid; + } + + private void setError(boolean error) { + this.error = error; + + } + + public String getSerialNumber() { + return serialNumber; + } + + private void setInitialized(boolean initialized) { + this.initialized = initialized; + } + + private void setAnswer(boolean answer) { + this.answer = answer; + } + + public boolean isUpdated() { + return updated; + } + + public void setUpdated(boolean updated) { + this.updated = updated; + } + + public boolean isInitialized() { + return initialized; + } + + public boolean isAnswer() { + return answer; + } + + public boolean isError() { + return error; + } + + public boolean isValid() { + return valid; + } + + public boolean isGatewayKnown() { + return gatewayKnown; + } + + public boolean isPanelLocked() { + return panelLocked; + } + + public boolean isLinkStatusError() { + return linkStatusError; + } + +} \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/DeviceConfiguration.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/DeviceConfiguration.java new file mode 100644 index 0000000000000..61280338886d9 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/DeviceConfiguration.java @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.message; + + +/** +* Base class for configuration provided by the MAX!Cube C_Message. +* +* @author Andreas Heil (info@aheil.de) +* @since 1.4.0 +*/ +public final class DeviceConfiguration { + + private DeviceType deviceType = null; + private String rfAddress = null; + private String serialNumber = null; + private String name = null; + private int roomId = -1; + + private DeviceConfiguration() { + } + + public static DeviceConfiguration create(Message message) { + DeviceConfiguration configuration = new DeviceConfiguration(); + configuration.setValues((C_Message) message); + + return configuration; + } + + public static DeviceConfiguration create(DeviceInformation di) { + DeviceConfiguration configuration = new DeviceConfiguration(); + configuration.setValues(di.getRFAddress(), di.getDeviceType(), di.getSerialNumber(), di.getName()); + return configuration; + } + + + public void setValues(C_Message message) { + setValues(message.getRFAddress(), message.getDeviceType(), message.getSerialNumber()); + } + + private void setValues(String rfAddress, DeviceType deviceType, String serialNumber, String name) { + setValues(rfAddress, deviceType, serialNumber); + this.name = name; + } + + private void setValues(String rfAddress, DeviceType deviceType, String serialNumber) { + this.rfAddress = rfAddress; + this.deviceType = deviceType; + this.serialNumber = serialNumber; + } + + public String getRFAddress() { + return rfAddress; + } + + public DeviceType getDeviceType() { + return deviceType; + } + + public String getSerialNumber() { + return serialNumber; + } + + public String getName() { + return name; + } + + public int getRoomId() { + return roomId; + } + + public void setRoomId(int roomId) { + this.roomId = roomId; + } +} \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/DeviceInformation.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/DeviceInformation.java new file mode 100644 index 0000000000000..e4ce639e8095f --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/DeviceInformation.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.message; + + +/** +* Device information provided by the M message meta information. +* +* @author Andreas Heil (info@aheil.de) +* @since 1.4.0 +*/ +public class DeviceInformation { + + private DeviceType deviceType = DeviceType.Invalid; + private String serialNumber = ""; + private String rfAddress = ""; + private String name = ""; + private int roomId = -1; + + public DeviceInformation(DeviceType deviceType, String serialNumber, String rfAddress, String name, int roomId) { + this.deviceType = deviceType; + this.serialNumber = serialNumber; + this.rfAddress = rfAddress; + this.name = name; + this.roomId = roomId; + } + + public String getRFAddress() { + return rfAddress; + } + + public DeviceType getDeviceType() { + return deviceType; + } + + public String getSerialNumber() { + return serialNumber; + } + + public int getRoomId() { + return roomId; + } + + public String getName() { + return name; + } +} \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/DeviceType.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/DeviceType.java new file mode 100644 index 0000000000000..92527952fed05 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/DeviceType.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.message; + +/** +* This enumeration represents the different message types provided by the MAX!Cube protocol. +* +* @author Andreas Heil (info@aheil.de) +* @since 1.4.0 +*/ +public enum DeviceType { + Invalid(256), Cube (0), HeatingThermostat(1), HeatingThermostatPlus(2), WallMountedThermostat( + 3), ShutterContact(4), EcoSwitch(5); + + private int value; + + private DeviceType(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + public static DeviceType create(int value) { + switch(value) { + case 0: + return Cube; + case 1: + return HeatingThermostat; + case 2: + return HeatingThermostatPlus; + case 3: + return WallMountedThermostat; + case 4: + return ShutterContact; + case 5: + return EcoSwitch; + default: + return Invalid; + } + } + + public String toString() { + switch(value) { + case 0: + return "Cube"; + case 1: + return "Thermostat"; + case 2: + return "Thermostat+"; + case 3: + return "Wallmounted Thermostat"; + case 4: + return "Shutter Contact"; + case 5: + return "Eco Switch"; + default: + return "Invalid"; + } + } +} \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/EcoSwitch.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/EcoSwitch.java new file mode 100644 index 0000000000000..2e7491a30fecf --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/EcoSwitch.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.message; + +import org.eclipse.smarthome.core.library.types.OnOffType; + +/** +* MAX!Cube EcoSwitch. +* +* @author Marcel Verpaalen +* @since 1.6.0 +*/ + +public class EcoSwitch extends ShutterContact { + + private OnOffType ecoMode = null; + + /** + * Class constructor. + * @param c + */ + public EcoSwitch(DeviceConfiguration c) { + super(c); + } + @Override + public DeviceType getType() { + return DeviceType.EcoSwitch; + } + + public OnOffType getEcoMode() { + return ecoMode; + } + public void setEcoMode(OnOffType ecoMode) { + this.ecoMode = ecoMode; + } +} diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/H_Message.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/H_Message.java new file mode 100644 index 0000000000000..e86e644a4ee07 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/H_Message.java @@ -0,0 +1,105 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.message; + +import java.util.Calendar; +import java.util.HashMap; +import java.util.Map; + +import org.openhab.binding.max.internal.Utils; +import org.slf4j.Logger; + +import com.google.common.base.Strings; + + +/** +* The H message contains information about the MAX!Cube. +* +* @author Andreas Heil (info@aheil.de) +* @author Marcel Verpaalen - Details parsing +* @since 1.4.0 +*/ +public final class H_Message extends Message { + + private Calendar cal = Calendar.getInstance(); + private Map properties = new HashMap<>(); + + + private String rawSerialNumber = null; + private String rawRfHexAddress = null; + private String rawFirmwareVersion = null; + private String rawConnectionId = null; + private String rawDutyCycle = null; + private String rawFreeMemorySlots = null; + private String rawCubeTimeState = null; + private String rawNTPCounter = null; + + // yet unknown fields + private String rawUnknownfield4 = null; + + public H_Message(String raw) { + super(raw); + + String[] tokens = this.getPayload().split(Message.DELIMETER); + + if (tokens.length < 11) + { + throw new ArrayIndexOutOfBoundsException("MAX!Cube raw H_Message corrupt"); + } + + rawSerialNumber = tokens[0]; + rawRfHexAddress = tokens[1]; + rawFirmwareVersion = tokens[2]; + rawUnknownfield4 = tokens[3]; + rawConnectionId = tokens[4]; + rawDutyCycle = Integer.toString(Utils.fromHex(tokens[5])); + rawFreeMemorySlots = Integer.toString(Utils.fromHex(tokens[6])); + + setDateTime(tokens[7], tokens[8]); + + rawCubeTimeState = tokens[9]; + rawNTPCounter = Integer.toString(Utils.fromHex(tokens[10]) ) ; + properties.put("Serial number", rawSerialNumber); + properties.put("RF address (HEX)", rawRfHexAddress); + properties.put("Firmware version", rawFirmwareVersion); + properties.put("Connection ID", rawConnectionId); + properties.put("Unknown", rawUnknownfield4); + properties.put("Duty Cycle", rawDutyCycle); + properties.put("FreeMemorySlots", rawFreeMemorySlots); + properties.put("CubeTimeState", rawCubeTimeState); + properties.put("NTPCounter", rawNTPCounter); + } + + private final void setDateTime(String hexDate, String hexTime) { + + int year = Utils.fromHex(hexDate.substring(0,2)); + int month = Utils.fromHex(hexDate.substring(2, 4)); + int date = Utils.fromHex(hexDate.substring(4, 6)); + + int hours = Utils.fromHex(hexTime.substring(0, 2)); + int minutes = Utils.fromHex(hexTime.substring(2, 4)); + + cal.set(year, month, date, hours, minutes, 0); + } + + @Override + public void debug(Logger logger) { + logger.trace("=== H_Message === "); + logger.trace("\tRAW: : {}", this.getPayload()); + logger.trace("\tReading Time : {}", cal.getTime()); + for(String key: properties.keySet()){ + logger.trace("\t{}:{}{}", key , Strings.repeat(" ",25 - key.length() ), properties.get(key)); + } + } + + @Override + public MessageType getType() { + return MessageType.H; + } +} diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/HeatingThermostat.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/HeatingThermostat.java new file mode 100644 index 0000000000000..e3e6f05cf2f00 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/HeatingThermostat.java @@ -0,0 +1,145 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.message; + +import java.util.Date; + +import org.eclipse.smarthome.core.library.types.DecimalType; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.types.State; + +/** + * MAX!Cube heating thermostat. + * + * @author Andreas Heil (info@aheil.de) + * @author Marcel Verpaalen - OH2 update + * @since 1.4.0 + */ +public class HeatingThermostat extends Device { + private ThermostatModeType mode; + + /** Valve position in % */ + private int valvePosition; + + /** Temperature setpoint in degrees celcius */ + private double temperatureSetpoint; + + /** Actual Temperature in degrees celcius */ + private double temperatureActual; + + /** Date setpoint until the termperature setpoint is valid */ + private Date dateSetpoint; + + /** Device type for this thermostat **/ + private DeviceType deviceType = DeviceType.HeatingThermostat; + + public HeatingThermostat(DeviceConfiguration c) { + super(c); + } + + @Override + public DeviceType getType() { + return deviceType; + } + + /** + * Sets the DeviceType for this thermostat. + * @param DeviceType as provided by the C message + */ + void setType (DeviceType type) { + this.deviceType = type; + } + + + /** + * Returns the current mode of the thermostat. + */ + public StringType getModeString() { + return new StringType (this.mode.toString()); + } + + /** + * Returns the current mode of the thermostat. + */ + public ThermostatModeType getMode() { + return (ThermostatModeType) this.mode; + } + + void setMode(ThermostatModeType mode) { + if(this.mode != mode) setUpdated (true); + this.mode = mode; + } + + /** + * Sets the valve position for this thermostat. + * @param valvePosition the valve position as provided by the L message + */ + public void setValvePosition(int valvePosition) { + if( this.valvePosition != valvePosition) setUpdated (true); + this.valvePosition = valvePosition; + } + + /** + * Returns the current valve position of this thermostat in percent. + * + * @return + * the valve position as DecimalType + */ + public DecimalType getValvePosition() { + return new DecimalType(this.valvePosition); + } + + public void setDateSetpoint(Date date) { + this.dateSetpoint = date; + } + + public Date getDateSetpoint() { + return dateSetpoint; + } + + /** + * Sets the actual temperature for this thermostat. + * @param value the actual temperature raw value as provided by the L message + */ + public void setTemperatureActual(double value) { + if(this.temperatureActual != value ) setUpdated (true); + this.temperatureActual = value ; + } + + /** + * Returns the measured temperature of this thermostat. + * 0�C is displayed if no actual is measured. Temperature is only updated after valve position changes + * + * @return + * the actual temperature as DecimalType + */ + public State getTemperatureActual() { + return new DecimalType(this.temperatureActual); + } + + /** + * Sets the setpoint temperature for this thermostat. + * @param value the setpoint temperature raw value as provided by the L message + */ + public void setTemperatureSetpoint(int value) { + if(Math.abs(this.temperatureSetpoint - (value / 2.0)) > 0.1 ) setUpdated (true); + this.temperatureSetpoint = value / 2.0; + } + + /** + * Returns the setpoint temperature of this thermostat. + * 4.5°C is displayed as OFF, 30.5°C is displayed as On at the thermostat display. + * + * @return + * the setpoint temperature as DecimalType + */ + public State getTemperatureSetpoint() { + return new DecimalType(this.temperatureSetpoint); + } +} diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/L_Message.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/L_Message.java new file mode 100644 index 0000000000000..17961b97a3fbb --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/L_Message.java @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.message; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.openhab.binding.max.internal.Utils; +import org.openhab.binding.max.internal.message.MaxTokenizer; +import org.apache.commons.net.util.Base64; +import org.slf4j.Logger; + + +/** + * The L message contains real time information about all MAX! devices. + * + * @author Andreas Heil (info@aheil.de) + * @author Marcel Verpaalen - OH2 update + * + * @since 1.4.0 + */ +public final class L_Message extends Message { + + public L_Message(String raw) { + super(raw); + } + + public Collection getDevices(List configurations) { + + List devices = new ArrayList(); + + byte[] decodedRawMessage = Base64.decodeBase64(getPayload().getBytes()); + + MaxTokenizer tokenizer = new MaxTokenizer(decodedRawMessage); + + while (tokenizer.hasMoreElements()) { + byte[] token = tokenizer.nextElement(); + Device tempDevice = Device.create(token, configurations); + if (tempDevice != null) { + devices.add(tempDevice); + } + } + + return devices; + } + + public Collection updateDevices(List devices, List configurations) { + + byte[] decodedRawMessage = Base64.decodeBase64(getPayload().getBytes()); + + MaxTokenizer tokenizer = new MaxTokenizer(decodedRawMessage); + + while (tokenizer.hasMoreElements()) { + byte[] token = tokenizer.nextElement(); + String rfAddress = Utils.toHex(token[0] & 0xFF, token[1] & 0xFF, token[2] & 0xFF); + //logger.debug("token: "+token+" rfaddress: "+rfAddress); + + Device foundDevice = null; + for (Device device : devices) { + //logger.debug(device.getRFAddress().toUpperCase()+ " vs "+rfAddress); + if (device.getRFAddress().toUpperCase().equals(rfAddress)) { + //logger.debug("Updating device..."+rfAddress); + foundDevice = device; + } + } + if(foundDevice!= null) { + foundDevice = Device.update(token, configurations, foundDevice); + //devices.remove(token); + //devices.add(foundDevice); + }else{ + Device tempDevice = Device.create(token, configurations); + if (tempDevice != null) { + devices.add(tempDevice); + } + } + } + + return devices; + } + + @Override + public void debug(Logger logger) { + logger.trace("=== L_Message === "); + logger.trace("\tRAW:" + this.getPayload()); + } + + @Override + public MessageType getType() { + return MessageType.L; + } +} \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/M_Message.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/M_Message.java new file mode 100644 index 0000000000000..6ffb4d1b62cd5 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/M_Message.java @@ -0,0 +1,146 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.message; + +import java.util.ArrayList; + +import org.apache.commons.net.util.Base64; +import org.openhab.binding.max.MaxBinding; +import org.openhab.binding.max.internal.Utils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The M message contains metadata about the MAX!Cube setup. + * + * @author Andreas Heil (info@aheil.de) - Initial Contribution + * @author Marcel Verpaalen - Room details parse + * @since 1.4.0 + */ +public final class M_Message extends Message { + + public ArrayList rooms; + public ArrayList devices; + private Boolean hasConfiguration ; + Logger logger = LoggerFactory.getLogger(MaxBinding.class); + + + public M_Message(String raw) { + super(raw); + hasConfiguration = false; + + String[] tokens = this.getPayload().split(Message.DELIMETER); + + if (tokens.length > 1) try { + byte[] bytes = Base64.decodeBase64(tokens[2].getBytes()); + + hasConfiguration = true; + logger.trace("*** M_Message trace**** "); + logger.trace ("\tMagic? (expect 86) : {}", (int) bytes[0]); + logger.trace ("\tVersion? (expect 2): {}", (int) bytes[1]); + logger.trace ("\t#defined rooms in M: {}", (int) bytes[2]); + + + rooms = new ArrayList(); + devices = new ArrayList(); + + int roomCount = bytes[2]; + + int byteOffset = 3; // start of rooms + + /* process room */ + + for (int i = 0; i < roomCount; i++) { + + int position = bytes[byteOffset++]; + String name = ""; + + int nameLength = (int) bytes[byteOffset++] & 0xff; + for (int char_idx = 0; char_idx < nameLength; char_idx++) { + name += (char) bytes[byteOffset++]; + } + + String rfAddress = Utils.toHex(((int)bytes[byteOffset] & 0xff), ((int)bytes[byteOffset+1] & 0xff), ((int)bytes[byteOffset + 2] & 0xff)); + byteOffset += 3; + + rooms.add(new RoomInformation(position, name, rfAddress)); + } + + /* process devices */ + + int deviceCount = bytes[byteOffset++]; + + for (int deviceId = 0; deviceId < deviceCount; deviceId++) { + DeviceType deviceType = DeviceType.create(bytes[byteOffset++]); + + String rfAddress = Utils.toHex(((int)bytes[byteOffset]&0xff), ((int)bytes[byteOffset+1]&0xff), ((int)bytes[byteOffset+2]&0xff)); + byteOffset += 3; + + String serialNumber = ""; + + for (int i = 0; i < 10; i++) { + serialNumber += (char) bytes[byteOffset++]; + } + + int nameLength = (int)bytes[byteOffset++] & 0xff; + + String deviceName = ""; + + for (int char_idx = 0; char_idx < nameLength; char_idx++) { + deviceName += (char)bytes[byteOffset++]; + } + + int roomId = (int)bytes[byteOffset++] & 0xff; + devices.add(new DeviceInformation(deviceType, serialNumber, rfAddress, deviceName, roomId)); + } + } catch (Exception e) { + logger.info("Unknown error parsing the M Message"); + logger.info(e.getMessage()); + logger.debug(Utils.getStackTrace(e)); + logger.debug("\tRAW : {}", this.getPayload()); + } + else { + logger.info("No rooms defined. Configure your Max!Cube"); + hasConfiguration = false; + } + } + + @Override + public void debug(Logger logger) { + logger.trace("=== M_Message === "); + if (hasConfiguration) { + logger.trace("\tRAW : {}", this.getPayload()); + for(RoomInformation room: rooms){ + logger.trace("\t=== Rooms ==="); + logger.trace("\tRoom Pos : {}", room.getPosition()); + logger.trace("\tRoom Name : {}", room.getName()); + logger.trace("\tRoom RF Adr: {}", room.getRFAddress()); + for(DeviceInformation device: devices){ + if (room.getPosition() == device.getRoomId()) { + logger.trace("\t=== Devices ==="); + logger.trace("\tDevice Type : {}", device.getDeviceType()); + logger.trace("\tDevice Name : {}", device.getName()); + logger.trace("\tDevice Serialnr: {}", device.getSerialNumber()); + logger.trace("\tDevice RF Adr : {}", device.getRFAddress()); + logger.trace("\tRoom Id : {}", device.getRoomId()); + } + } + + } + } + else { + logger.debug("M-Message empty. No Configuration"); + } + } + + @Override + public MessageType getType() { + return MessageType.M; + } +} diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/MaxTokenizer.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/MaxTokenizer.java new file mode 100644 index 0000000000000..0f82e19a0a45d --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/MaxTokenizer.java @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.message; + +import java.util.Enumeration; + +/** +* The MaxTokenizer parses a L message into the MAX!Cube devices encoded within. The L message contains +* real time information for multiple devices. Each device starts with the length n bytes. +* The MaxTokenzier starts with the first device and chops off one device after another from the byte stream. +* +* The tokens returned consist of the payload solely, and do not contain the first byte holding the +* tokens length. +* +* @author Andreas Heil (info@aheil.de) +* @since 1.4.0 +*/ +public final class MaxTokenizer implements Enumeration { + + private int offset = 0; + + private byte[] decodedRawMessage = null; + + /** + * Creates a new MaxTokenizer. + * @param decodedRawMessage + * The Base64 decoded MAX!Cube protocol L message as byte array + */ + public MaxTokenizer(byte[] decodedRawMessage) { + this.decodedRawMessage = decodedRawMessage; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean hasMoreElements() { + return offset < decodedRawMessage.length; + } + + /** + * {@inheritDoc} + */ + @Override + public byte[] nextElement() { + byte length = decodedRawMessage[offset++]; + + // make sure to get the correct length in case > 127 + byte[] token = new byte[length & 0xFF]; + + for (int i = 0; i < (length & 0xFF); i++) { + token[i] = decodedRawMessage[offset++]; + } + + return token; + } +} \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/Message.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/Message.java new file mode 100644 index 0000000000000..83dd931411548 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/Message.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.message; + +import org.slf4j.Logger; + +/** +* Base message received by the MAX!Cube protocol. +* +* @author Andreas Heil (info@aheil.de) +* @since 1.4.0 +*/ +public abstract class Message { + + public static final String DELIMETER = ","; + + private String raw = null; + + public Message(String raw) { + this.raw = raw; + } + + public abstract void debug(Logger logger); + public abstract MessageType getType(); + + protected final String getPayload() { + return raw.substring(2, raw.length()); + } +} \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/MessageType.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/MessageType.java new file mode 100644 index 0000000000000..5f5b0d14349cb --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/MessageType.java @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.message; + +/** +* This enumeration represents the different message types provided by the MAX!Cube protocol. +* +* @author Andreas Heil (info@aheil.de) +* @since 1.4.0 +*/ +public enum MessageType { + H, M, C, L, S +} \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/RoomInformation.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/RoomInformation.java new file mode 100644 index 0000000000000..ee02b8410523f --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/RoomInformation.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.message; + +/** +* Room information provided b the M message meta information. +* +* @author Andreas Heil (info@aheil.de) +* @since 1.4.0 +*/ +public class RoomInformation { + private int position = -1; + private String name = ""; + private String rfAddress = ""; + + public RoomInformation(int position, String name, String rfAddress) { + this.position = position; + this.name = name; + this.rfAddress = rfAddress; + } + + public int getPosition() { + return position; + } + + public void setPosition(int position) { + this.position = position; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public String getRFAddress() { + return rfAddress; + } + + public void setRFAddress(String rfAddress) { + this.rfAddress = rfAddress; + } +} \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/S_Command.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/S_Command.java new file mode 100644 index 0000000000000..5b19ed906c4a1 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/S_Command.java @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.message; + +import org.apache.commons.net.util.Base64; +import org.openhab.binding.max.internal.Utils; + +/** + * Command to be send via the MAX!Cube protocol. + * + * @author Andreas Heil (info@aheil.de) + * @author Marcel Verpaalen - OH2 update + * @since 1.4.0 + */ +public class S_Command { + + private String baseString = "000440000000"; + private boolean[] bits = null; + + private String rfAddress = null; + private int roomId = -1; + + /** + * Creates a new instance of the MAX! protocol S command. + * + * @param rfAddress + * the RF address the command is for + * @param roomId + * the room ID the RF address is mapped to + * @param setpointTemperature + * the desired setpoint temperature for the device. + */ + public S_Command(String rfAddress, int roomId, ThermostatModeType mode, double setpointTemperature) { + this.rfAddress = rfAddress; + this.roomId = roomId; + + // Temperature setpoint, Temp uses 6 bits (bit 0:5), + // 20 deg C = bits 101000 = dec 40/2 = 20 deg C, + // you need 8 bits to send so add the 2 bits below (sample 10101000 = hex A8) + // bit 0,1 = 00 = Auto weekprog (no temp is needed) + + int setpointValue = (int) (setpointTemperature * 2); + bits = Utils.getBits(setpointValue); + + // default to perm setting + // AB => bit mapping + // 01 = Permanent + // 10 = Temporarily + if ( mode.equals(ThermostatModeType.MANUAL)){ + bits[7] = false; // A (MSB) + bits[6] = true; // B + } else + { + bits[7] = false ; // A (MSB) + bits[6] = false; // B + } + + } + + /** + * Creates a new instance of the MAX! protocol S command. + * + * @param rfAddress + * the RF address the command is for + * @param roomId + * the room ID the RF address is mapped to + * @param mode + * the desired mode for the device. + */ + public S_Command(String rfAddress, int roomId, ThermostatModeType mode) { + this.rfAddress = rfAddress; + this.roomId = roomId; + + // default to perm setting + // AB => bit mapping + // 01 = Permanent + // 10 = Temporarily + + switch (mode) { + case VACATION: + case MANUAL: + //not implemented needs temperature + break; + case AUTOMATIC: + bits = Utils.getBits(0); + break; + case BOOST: + bits = Utils.getBits(255); + break; + default: + // no further modes supported + } + } + + + /** + * Returns the Base64 encoded command string to be sent via the MAX! + * protocol. + * + * @return the string representing the command + */ + public String getCommandString() { + + String commandString = baseString + rfAddress + Utils.toHex(roomId) + Utils.toHex(bits); + + String encodedString = Base64.encodeBase64String(Utils.hexStringToByteArray(commandString)); + + return "s:" + encodedString; + } +} \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/S_Message.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/S_Message.java new file mode 100644 index 0000000000000..4b672f2a8154a --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/S_Message.java @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.message; + +import org.openhab.binding.max.MaxBinding; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** +* The S message contains information about Command execution results +* +* @author Bernd Michael Helm (bernd.helm at helmundwalter.de) +* @author Marcel Verpaalen - OH2 version + parsing of the message +* @since 1.6.0 +*/ +public final class S_Message extends Message { + + private int dutyCycle; + private int freeMemorySlots; + private boolean commandDiscarded = false; + + Logger logger = LoggerFactory.getLogger(MaxBinding.class); + + public S_Message(String raw) { + super(raw); + + String[] tokens = this.getPayload().split(Message.DELIMETER); + + if (tokens.length == 3){ + try{ + dutyCycle = Integer.parseInt(tokens[0],16); + commandDiscarded = tokens[1] == "1"; + freeMemorySlots = Integer.parseInt(tokens[2],16); + } catch(Exception e) { + logger.debug("Exception occurred during parsing of S message: {}", e.getMessage(), e); + } + }else + { + logger.debug("Unexpected # of tolkens ({}) received in S message: {}",tokens.length,this.getPayload()); + } + } + + public int getDutyCycle() { + return dutyCycle; + } + + public int getFreeMemorySlots() { + return freeMemorySlots; + } + + public boolean isCommandDiscarded() { + return commandDiscarded; + } + + @Override + public void debug(Logger logger) { + logger.trace("=== S_Message === "); + logger.trace("\tRAW : {}", this.getPayload()); + logger.trace("\tDutyCycle : {}", this.dutyCycle); + logger.trace("\tCommand Discarded : {}", this.commandDiscarded); + logger.trace("\tFreeMemorySlots : {}", this.freeMemorySlots); + } + + @Override + public MessageType getType() { + return MessageType.S; + } +} diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/SendCommand.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/SendCommand.java new file mode 100644 index 0000000000000..147165567a875 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/SendCommand.java @@ -0,0 +1,124 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.message; + +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.types.Command; + + +/** + * Class for sending a command. + * + * @author Marcel Verpaalen + * + */ +public final class SendCommand { + + private int id ; + private static int commandId = -1; + + private ChannelUID channelUID; + private Command command; + private String serialNumber; + private String key; + + + public SendCommand(String serialNumber,ChannelUID channelUID,Command command) { + commandId +=1; + id = commandId; + this.serialNumber = serialNumber; + this.channelUID=channelUID; + this.command=command; + setKey(); + } + + /** + * Sets the key based on the serial and channel + * This is can be used to find duplicated commands in the queue + */ + private void setKey() { + key = serialNumber+"-"+channelUID.getId() ; + } + + /** + * @return the key based on the serial and channel + * This is can be used to find duplicated commands in the queue + */ + public String getKey() { + return key ; + } + + + /** + * @return the id + */ + public int getId() { + return id; + } + + + + + + /** + * @return the channelUID + */ + public ChannelUID getChannelUID() { + return channelUID; + } + + + + /** + * @param channelUID the channelUID to set + */ + public void setChannelUID(ChannelUID channelUID) { + this.channelUID = channelUID; + setKey(); + } + + + + /** + * @return the command + */ + public Command getCommand() { + return command; + } + + + + /** + * @param command the command to set + */ + public void setCommand(Command command) { + this.command = command; + } + + + + /** + * @return the device + */ + public String getDeviceSerial() { + return serialNumber; + } + + + + /** + * @param device the device to set + */ + public void setDeviceSerial(String device) { + this.serialNumber = device; + setKey(); + } + + +} \ No newline at end of file diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/ShutterContact.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/ShutterContact.java new file mode 100644 index 0000000000000..486930f161203 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/ShutterContact.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.message; + +import org.eclipse.smarthome.core.library.types.OpenClosedType; + +/** + * MAX!Cube Shutter contact device. + * + * @author Andreas Heil (info@aheil.de) + * @author Marcel Verpaalen - OH2 update + * @since 1.4.0 + */ +public class ShutterContact extends Device { + + private OpenClosedType shutterState = null; + + public ShutterContact(DeviceConfiguration c) { + super(c); + } + + public void setShutterState(OpenClosedType shutterState) { + if(this.shutterState != shutterState ) setUpdated (true); + this.shutterState = shutterState; + } + + public OpenClosedType getShutterState() { + return shutterState; + } + + @Override + public DeviceType getType() { + return DeviceType.ShutterContact; + } + +} diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/ThermostatModeType.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/ThermostatModeType.java new file mode 100644 index 0000000000000..d5cefca752de5 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/ThermostatModeType.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.message; + +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.PrimitiveType; +import org.eclipse.smarthome.core.types.State; + +/** +* This enumeration represents the different mode types of a MAX!Cube heating thermostat. +* +* @author Andreas Heil (info@aheil.de) +* * @author Marcel Verpaalen - OH2 update +* @since 1.4.0 +*/ +public enum ThermostatModeType implements PrimitiveType, State, Command { + AUTOMATIC, MANUAL, VACATION, BOOST; + + public String format(String pattern) { + return String.format(pattern, this.toString()); + } +} diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/UnsupportedDevice.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/UnsupportedDevice.java new file mode 100644 index 0000000000000..3cc68c47149c1 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/UnsupportedDevice.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.message; + +/** +* Unsupported devices. +* +* @author Andreas Heil (info@aheil.de) +* @author Marcel Verpaalen +* @since 1.4.0 +*/ + + +public class UnsupportedDevice extends Device { + + public UnsupportedDevice(DeviceConfiguration c) { + super(c); + } + + @Override + public DeviceType getType() { + return DeviceType.Invalid; + } + + @Override + public String getName() { + return "Unsupported device"; + } + +} diff --git a/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/WallMountedThermostat.java b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/WallMountedThermostat.java new file mode 100644 index 0000000000000..319c95eae46f4 --- /dev/null +++ b/addons/binding/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/message/WallMountedThermostat.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.max.internal.message; + + +/** + * MAX!Cube wall mounted thermostat. + * + * @author Andreas Heil (info@aheil.de) + * @since 1.4.0 + */ +public class WallMountedThermostat extends HeatingThermostat { + + /** + * Class constructor. + * @param c + */ + public WallMountedThermostat(DeviceConfiguration c) { + super(c); + } + + @Override + public DeviceType getType() { + return DeviceType.WallMountedThermostat; + } +} diff --git a/addons/binding/org.openhab.binding.networkhealth/.classpath b/addons/binding/org.openhab.binding.networkhealth/.classpath new file mode 100644 index 0000000000000..a95e0906ca013 --- /dev/null +++ b/addons/binding/org.openhab.binding.networkhealth/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/addons/binding/org.openhab.binding.networkhealth/.project b/addons/binding/org.openhab.binding.networkhealth/.project new file mode 100644 index 0000000000000..9c8b1faefa3c3 --- /dev/null +++ b/addons/binding/org.openhab.binding.networkhealth/.project @@ -0,0 +1,33 @@ + + + org.openhab.binding.networkhealth + + + + + + 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.networkhealth/ESH-INF/binding/binding.xml b/addons/binding/org.openhab.binding.networkhealth/ESH-INF/binding/binding.xml new file mode 100644 index 0000000000000..98b8b55ab9ab0 --- /dev/null +++ b/addons/binding/org.openhab.binding.networkhealth/ESH-INF/binding/binding.xml @@ -0,0 +1,11 @@ + + + + NetworkHealth Binding + The Network Health Binding checks if a Device is currently on the Network or not + Marc Mettke + + diff --git a/addons/binding/org.openhab.binding.networkhealth/ESH-INF/i18n/networkhealth_de.properties b/addons/binding/org.openhab.binding.networkhealth/ESH-INF/i18n/networkhealth_de.properties new file mode 100644 index 0000000000000..d9112140f2b28 --- /dev/null +++ b/addons/binding/org.openhab.binding.networkhealth/ESH-INF/i18n/networkhealth_de.properties @@ -0,0 +1,19 @@ +# binding +binding.networkhealth.name = Network Health Binding +binding.networkhealth.description = Das Network Health Binding überprüft, ob sich ein Geräte aktuell im Netzwerk befindet oder nicht. + +# thing types +thing-type.networkhealth.DEVICE.label = Netzgerät +thing-type.networkhealth.DEVICE.description = Das Netzwerkgerät muss mit dem gleichen Netzwerk verbunden sein wie OpenHAB +thing-type.config.networkhealth.DEVICE.HOSTNAME.label = Hostname oder IP +thing-type.config.networkhealth.DEVICE.HOSTNAME.description = Hostname oder IP des Netzwerkgerätes +thing-type.config.networkhealth.DEVICE.PORT.label = Port +thing-type.config.networkhealth.DEVICE.PORT.description = Der Port an dem das Gerät erreichbar ist. +thing-type.config.networkhealth.DEVICE.TIMEOUT.label = Zeitlimit +thing-type.config.networkhealth.DEVICE.TIMEOUT.description = Gibt an, wie lange maximal gewartet werden soll, bis ein Gerät als nicht vorhanden gekenntzeichnet wird. +thing-type.config.networkhealth.DEVICE.REFRESH_INTERVAL.label = Aktualisierungsintervall +thing-type.config.networkhealth.DEVICE.REFRESH_INTERVAL.description = Spezifiziert den Aktualisierungsintervall in Millisekunden + +# channel types +channel-type.networkhealth.ONLINE.label = Online +channel-type.networkhealth.ONLINE.description = Gibt an ob das Gerät aktuell Online oder Offline ist. diff --git a/addons/binding/org.openhab.binding.networkhealth/ESH-INF/thing/thing-types.xml b/addons/binding/org.openhab.binding.networkhealth/ESH-INF/thing/thing-types.xml new file mode 100644 index 0000000000000..01a7f17fa1f2e --- /dev/null +++ b/addons/binding/org.openhab.binding.networkhealth/ESH-INF/thing/thing-types.xml @@ -0,0 +1,50 @@ + + + + + Device which must be connected to the same Network as OpenHAB + + + + + + + + Hostname or IP of the Device + true + + + + + The Port on which the Device can be accessed + 0 + + + + + States how long to wait, if a connection can not be established + 5000 + + + + + States how often a refresh shall occur + 60000 + + + + + + Switch + + States whether a device is online or not + Switch + + Network Device + + + + diff --git a/addons/binding/org.openhab.binding.networkhealth/META-INF/MANIFEST.MF b/addons/binding/org.openhab.binding.networkhealth/META-INF/MANIFEST.MF new file mode 100644 index 0000000000000..5a74e57595adf --- /dev/null +++ b/addons/binding/org.openhab.binding.networkhealth/META-INF/MANIFEST.MF @@ -0,0 +1,21 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: NetworkHealth Binding +Bundle-SymbolicName: org.openhab.binding.networkhealth;singleton:=true +Bundle-Vendor: openHAB +Bundle-Version: 2.0.0.qualifier +Bundle-RequiredExecutionEnvironment: JavaSE-1.7 +Bundle-ClassPath: . +Import-Package: com.google.common.collect, + org.apache.commons.net.util;version="3.2.0", + 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.types, + org.eclipse.smarthome.io.net.actions, + org.slf4j +Service-Component: OSGI-INF/* +Export-Package: org.openhab.binding.networkhealth, + org.openhab.binding.networkhealth.handler diff --git a/addons/binding/org.openhab.binding.networkhealth/OSGI-INF/NetworkHealthDiscovery.xml b/addons/binding/org.openhab.binding.networkhealth/OSGI-INF/NetworkHealthDiscovery.xml new file mode 100644 index 0000000000000..267bd01407a6f --- /dev/null +++ b/addons/binding/org.openhab.binding.networkhealth/OSGI-INF/NetworkHealthDiscovery.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/addons/binding/org.openhab.binding.networkhealth/OSGI-INF/NetworkHealthHandlerFactory.xml b/addons/binding/org.openhab.binding.networkhealth/OSGI-INF/NetworkHealthHandlerFactory.xml new file mode 100644 index 0000000000000..13de06036f753 --- /dev/null +++ b/addons/binding/org.openhab.binding.networkhealth/OSGI-INF/NetworkHealthHandlerFactory.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + diff --git a/addons/binding/org.openhab.binding.networkhealth/build.properties b/addons/binding/org.openhab.binding.networkhealth/build.properties new file mode 100644 index 0000000000000..66e21b90751a7 --- /dev/null +++ b/addons/binding/org.openhab.binding.networkhealth/build.properties @@ -0,0 +1,6 @@ +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.networkhealth/pom.xml b/addons/binding/org.openhab.binding.networkhealth/pom.xml new file mode 100644 index 0000000000000..8476678ffc7e4 --- /dev/null +++ b/addons/binding/org.openhab.binding.networkhealth/pom.xml @@ -0,0 +1,24 @@ + + + + 4.0.0 + + + org.openhab.binding + pom + 2.0.0-SNAPSHOT + + + + org.openhab.binding.networkhealth + org.openhab.binding.networkhealth + + + org.openhab.binding + org.openhab.binding.networkhealth + 2.0.0-SNAPSHOT + + NetworkHealth Binding + eclipse-plugin + + diff --git a/addons/binding/org.openhab.binding.networkhealth/src/main/java/org/openhab/binding/networkhealth/NetworkHealthBindingConstants.java b/addons/binding/org.openhab.binding.networkhealth/src/main/java/org/openhab/binding/networkhealth/NetworkHealthBindingConstants.java new file mode 100644 index 0000000000000..68f7daf3b6982 --- /dev/null +++ b/addons/binding/org.openhab.binding.networkhealth/src/main/java/org/openhab/binding/networkhealth/NetworkHealthBindingConstants.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others. + * 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.networkhealth; + +import java.util.Collections; +import java.util.Set; + +import org.eclipse.smarthome.core.thing.ThingTypeUID; + +/** + * The {@link NetworkHealthBindingConstants} class defines common constants, which are + * used across the whole binding. + * + * @author Marc Mettke - Initial contribution + */ +public class NetworkHealthBindingConstants { + + public static final String BINDING_ID = "networkhealth"; + + // List of all Thing Type UIDs + public final static ThingTypeUID THING_TYPE_DEVICE = new ThingTypeUID(BINDING_ID, "device"); + + // List of all Channel ids + public final static String CHANNEL_ONLINE = "online"; + + // List of all Parameters + public final static String PARAMETER_HOSTNAME = "hostname"; + public final static String PARAMETER_PORT = "port"; + public final static String PARAMETER_TIMEOUT = "timeout"; + public final static String PARAMETER_REFRESH_INTERVAL = "refresh_interval"; + + public final static Set SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_DEVICE); + +} diff --git a/addons/binding/org.openhab.binding.networkhealth/src/main/java/org/openhab/binding/networkhealth/discovery/NetworkHealthDiscoveryService.java b/addons/binding/org.openhab.binding.networkhealth/src/main/java/org/openhab/binding/networkhealth/discovery/NetworkHealthDiscoveryService.java new file mode 100644 index 0000000000000..32d3c5ef299bf --- /dev/null +++ b/addons/binding/org.openhab.binding.networkhealth/src/main/java/org/openhab/binding/networkhealth/discovery/NetworkHealthDiscoveryService.java @@ -0,0 +1,239 @@ +/** + * Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others. + * 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.networkhealth.discovery; + +import static org.openhab.binding.networkhealth.NetworkHealthBindingConstants.*; + +import java.io.IOException; +import java.net.InterfaceAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.SocketTimeoutException; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Queue; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import org.apache.commons.net.util.SubnetUtils; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.ThingUID; +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.io.net.actions.Ping; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link NetworkHealthDiscoveryService} is responsible for discovering devices on + * the current Network. It uses every Network Interface which is connect to a Network + * + * @author Marc Mettke - Initial contribution + */ + +public class NetworkHealthDiscoveryService extends AbstractDiscoveryService { + private final static int TASK_CREATING_TIME_IN_MS = 1; + private final static Object lockObject = new Object(); + + private ScheduledFuture discoveryJob; + private final Logger logger = LoggerFactory.getLogger(NetworkHealthDiscoveryService.class); + + + public NetworkHealthDiscoveryService() { + super(SUPPORTED_THING_TYPES_UIDS, 300); + } + + /** + * Handles the whole Discovery + */ + private void discoverNetwork() { + TreeSet interfaceIPs; + Queue networkIPs; + + logger.debug("Starting Device Discovery"); + interfaceIPs = getInterfaceIPs(); + networkIPs = getNetworkIPs(interfaceIPs); + startDiscovery(networkIPs); + } + + /** + * Gets every IPv4 Address on each Interface except the loopback + * The Address format is ip/subnet + * @return The collected IPv4 Addresses + */ + private TreeSet getInterfaceIPs() { + TreeSet interfaceIPs = new TreeSet(); + + try { + // For each interface ... + for (Enumeration en = NetworkInterface + .getNetworkInterfaces(); en.hasMoreElements();) { + NetworkInterface networkInterface = en.nextElement(); + if (!networkInterface.isLoopback()) { + + // .. and for each address ... + for (Iterator it = networkInterface + .getInterfaceAddresses().iterator(); it.hasNext();) { + + // ... get IP and Subnet + InterfaceAddress interfaceAddress = it.next(); + interfaceIPs.add(interfaceAddress.getAddress() + .getHostAddress() + + "/" + + interfaceAddress.getNetworkPrefixLength()); + } + } + } + } catch (SocketException e) { + } + + return interfaceIPs; + } + + /** + * Takes the interfaceIPs and fetches every IP which can be assigned on their network + * @param networkIPs The IPs which are assigned to the Network Interfaces + * @return Every single IP which can be assigned on the Networks the computer is connected to + */ + private Queue getNetworkIPs(TreeSet interfaceIPs) { + Queue networkIPs = new LinkedBlockingQueue(); + + for (Iterator it = interfaceIPs.iterator(); it.hasNext();) { + try { + // gets every ip which can be assigned on the given network + SubnetUtils utils = new SubnetUtils(it.next()); + String[] addresses = utils.getInfo().getAllAddresses(); + for (int i = 0; i < addresses.length; i++) { + networkIPs.add(addresses[i]); + } + + } catch (Exception ex) { + } + } + + return networkIPs; + } + + public Set getSupportedThingTypes() { + return SUPPORTED_THING_TYPES_UIDS; + } + + @Override + protected void startBackgroundDiscovery() { + new Thread(new Runnable() { + @Override + public void run() { + /* Devices are only discovered on users request */ + } + }).start(); + } + + /** + * Starts the DiscoveryThread for each IP on the Networks + * @param allNetworkIPs + */ + private void startDiscovery(final Queue networkIPs) { + + Runnable runnable = new Runnable() { + public void run() { + DiscoveryThread discoveryThread = null; + DiscoveryThreadResult discoveryThreadResult = new DiscoveryThreadResult() { + @Override + public void newDevice(String ip) { + submitDiscoveryResults(ip); + } + }; + + // ensures that only one thread at a time access the queue + synchronized (lockObject) { + if( networkIPs.isEmpty()) { + discoveryJob.cancel(false); + } else { + discoveryThread = new DiscoveryThread(networkIPs.remove(), discoveryThreadResult); + } + } + + if( discoveryThread != null ) + discoveryThread.start(); + } + }; + + /* Every milisecond a new thread will be created. Due to the fact that the PING has a timeout of 1 sec, + * only about 1000 Threads will be create at max */ + discoveryJob = scheduler.scheduleAtFixedRate(runnable, 0, TASK_CREATING_TIME_IN_MS, TimeUnit.MILLISECONDS); + } + + @Override + protected void startScan() { + discoverNetwork(); + } + + /** + * Submit the discovered Devices to the Smarthome inbox, + * + * @param ip The Device IP + */ + private void submitDiscoveryResults(String 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); + } + + } + +} + +/** + * Runs a Ping in its own Thread + * @author Marc Mettke - Initial contribution + */ +class DiscoveryThread extends Thread { + private final static int PING_TIMEOUT_IN_MS = 1000; + + private DiscoveryThreadResult discoveryResult; + private String ip; + + public DiscoveryThread(String ip, DiscoveryThreadResult discoveryResult) { + this.ip = ip; + this.discoveryResult = discoveryResult; + } + + @Override + public void run() { + try { + if( Ping.checkVitality(this.ip, 0, PING_TIMEOUT_IN_MS) ) { + this.discoveryResult.newDevice(this.ip); + } + } + catch (SocketTimeoutException se) { + } + catch (IOException ioe) { + } + } +} + +/** + * Callback for a new Device to be committed to Homematic + * @author Marc Mettke - Initial contribution + */ +interface DiscoveryThreadResult { + public void newDevice(String ip); +} diff --git a/addons/binding/org.openhab.binding.networkhealth/src/main/java/org/openhab/binding/networkhealth/handler/NetworkHealthHandler.java b/addons/binding/org.openhab.binding.networkhealth/src/main/java/org/openhab/binding/networkhealth/handler/NetworkHealthHandler.java new file mode 100644 index 0000000000000..08cf59ea98235 --- /dev/null +++ b/addons/binding/org.openhab.binding.networkhealth/src/main/java/org/openhab/binding/networkhealth/handler/NetworkHealthHandler.java @@ -0,0 +1,128 @@ +/** + * Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others. + * 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.networkhealth.handler; + +import static org.openhab.binding.networkhealth.NetworkHealthBindingConstants.*; + +import java.io.IOException; +import java.net.SocketTimeoutException; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.eclipse.smarthome.config.core.Configuration; +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.binding.BaseThingHandler; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.eclipse.smarthome.io.net.actions.Ping; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link NetworkHealthHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Marc Mettke - Initial contribution + */ +public class NetworkHealthHandler extends BaseThingHandler { + private Logger logger = LoggerFactory.getLogger(NetworkHealthHandler.class); + + public String hostname; + public int port; + private long refreshInterval; + ScheduledFuture refreshJob; + + public int timeout; + + + public NetworkHealthHandler(Thing thing) { + super(thing); + } + + + @Override + public void dispose() { + refreshJob.cancel(true); + } + + private void getDeviceState() { + boolean success = false; + + try { + success = Ping.checkVitality(this.hostname, this.port, this.timeout); + + logger.debug("established connection [host '{}' port '{}' timeout '{}']", new Object[] {hostname, port, timeout}); + } + catch (SocketTimeoutException se) { + logger.debug("timed out while connecting to host '{}' port '{}' timeout '{}'", new Object[] {hostname, port, timeout}); + } + catch (IOException ioe) { + logger.debug("couldn't establish network connection [host '{}' port '{}' timeout '{}']", new Object[] {hostname, port, timeout}); + } + + updateState(CHANNEL_ONLINE, success ? OnOffType.ON : OnOffType.OFF); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if (command instanceof RefreshType) { + switch (channelUID.getId()) { + case CHANNEL_ONLINE: + getDeviceState(); + break; + default: + logger.debug("Command received for an unknown channel: {}", channelUID.getId()); + break; + } + } else { + logger.debug("Command {} is not supported for channel: {}", command, channelUID.getId()); + } + } + + @Override + public void initialize() { + logger.debug("Initializing NetworkHealth handler."); + Configuration conf = this.getConfig(); + super.initialize(); + + this.hostname = String.valueOf(conf.get(PARAMETER_HOSTNAME)); + + try { + this.port = Integer.parseInt(String.valueOf(conf.get(PARAMETER_PORT))); + } catch (Exception ex) { + this.port = 0; + } + + try { + this.timeout = Integer.parseInt(String.valueOf(conf.get(PARAMETER_TIMEOUT))); + } catch (Exception ex) { + this.timeout = 5000; + } + + try { + this.refreshInterval = Long.parseLong(String.valueOf(conf.get(PARAMETER_REFRESH_INTERVAL))); + } catch (Exception ex) { + this.refreshInterval = 60000; + } + + startAutomaticRefresh(); + } + + private void startAutomaticRefresh() { + Runnable runnable = new Runnable() { + public void run() { + getDeviceState(); + } + }; + + refreshJob = scheduler.scheduleAtFixedRate(runnable, 0, refreshInterval, TimeUnit.MILLISECONDS); + } + +} diff --git a/addons/binding/org.openhab.binding.networkhealth/src/main/java/org/openhab/binding/networkhealth/internal/NetworkHealthHandlerFactory.java b/addons/binding/org.openhab.binding.networkhealth/src/main/java/org/openhab/binding/networkhealth/internal/NetworkHealthHandlerFactory.java new file mode 100644 index 0000000000000..f2e204fcbf499 --- /dev/null +++ b/addons/binding/org.openhab.binding.networkhealth/src/main/java/org/openhab/binding/networkhealth/internal/NetworkHealthHandlerFactory.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others. + * 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.networkhealth.internal; + +import static org.openhab.binding.networkhealth.NetworkHealthBindingConstants.*; + +import org.openhab.binding.networkhealth.handler.NetworkHealthHandler; + +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; + +/** + * The {@link NetworkHealthHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Marc Mettke + */ +public class NetworkHealthHandlerFactory extends BaseThingHandlerFactory { + + @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(THING_TYPE_DEVICE)) { + return new NetworkHealthHandler(thing); + } + + return null; + } +} + diff --git a/addons/binding/org.openhab.binding.sonos/OSGI-INF/SonosHandlerFactory.xml b/addons/binding/org.openhab.binding.sonos/OSGI-INF/SonosHandlerFactory.xml index b1c2c45a817ec..dae8122035c81 100644 --- a/addons/binding/org.openhab.binding.sonos/OSGI-INF/SonosHandlerFactory.xml +++ b/addons/binding/org.openhab.binding.sonos/OSGI-INF/SonosHandlerFactory.xml @@ -1,7 +1,8 @@ diff --git a/addons/binding/org.openhab.binding.sonos/pom.xml b/addons/binding/org.openhab.binding.sonos/pom.xml index 4f4c266f30dc8..15b8f5f71c6a1 100644 --- a/addons/binding/org.openhab.binding.sonos/pom.xml +++ b/addons/binding/org.openhab.binding.sonos/pom.xml @@ -9,15 +9,10 @@ 2.0.0-SNAPSHOT - - org.openhab.binding.sonos - org.openhab.binding.sonos - - org.openhab.binding org.openhab.binding.sonos - openHAB Sonos Binding + Sonos Binding eclipse-plugin diff --git a/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/SonosBindingConstants.java b/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/SonosBindingConstants.java index ad4763eee2656..ad1338d8c4b70 100644 --- a/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/SonosBindingConstants.java +++ b/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/SonosBindingConstants.java @@ -1,5 +1,6 @@ /** - * Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * * 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 diff --git a/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/config/ZonePlayerConfiguration.java b/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/config/ZonePlayerConfiguration.java index a4ccdac420575..90e60b76c1df7 100644 --- a/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/config/ZonePlayerConfiguration.java +++ b/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/config/ZonePlayerConfiguration.java @@ -1,3 +1,11 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.sonos.config; public class ZonePlayerConfiguration { diff --git a/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/discovery/ZonePlayerDiscoveryParticipant.java b/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/discovery/ZonePlayerDiscoveryParticipant.java index 33c1778bde5a9..37106c8f608cc 100644 --- a/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/discovery/ZonePlayerDiscoveryParticipant.java +++ b/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/discovery/ZonePlayerDiscoveryParticipant.java @@ -1,5 +1,6 @@ /** - * Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * * 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 diff --git a/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/handler/ZonePlayerHandler.java b/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/handler/ZonePlayerHandler.java index 70aa43aee6290..85844773005d3 100644 --- a/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/handler/ZonePlayerHandler.java +++ b/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/handler/ZonePlayerHandler.java @@ -1,5 +1,6 @@ /** - * Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * * 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 diff --git a/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosAlarm.java b/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosAlarm.java index 0212fac025b41..498fdd704abec 100644 --- a/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosAlarm.java +++ b/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosAlarm.java @@ -1,5 +1,6 @@ /** - * Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * * 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 diff --git a/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosEntry.java b/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosEntry.java index 19485d19e3ca3..3e9d8c261b0b9 100644 --- a/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosEntry.java +++ b/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosEntry.java @@ -1,5 +1,6 @@ /** - * Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * * 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 diff --git a/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosHandlerFactory.java b/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosHandlerFactory.java index bd8c2f4578429..bb76c0e2745e1 100644 --- a/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosHandlerFactory.java +++ b/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosHandlerFactory.java @@ -1,5 +1,6 @@ /** - * Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * * 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 diff --git a/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosMetaData.java b/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosMetaData.java index c2ee27374de80..a4c577d78a559 100644 --- a/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosMetaData.java +++ b/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosMetaData.java @@ -1,5 +1,6 @@ /** - * Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * * 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 diff --git a/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosXMLParser.java b/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosXMLParser.java index 5343c0b4f1557..068d4421f5a5d 100644 --- a/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosXMLParser.java +++ b/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosXMLParser.java @@ -1,5 +1,6 @@ /** - * Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * * 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 diff --git a/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosZoneGroup.java b/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosZoneGroup.java index 1523e142397fa..023160eb3c257 100644 --- a/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosZoneGroup.java +++ b/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosZoneGroup.java @@ -1,5 +1,6 @@ /** - * Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * * 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 diff --git a/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosZonePlayerState.java b/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosZonePlayerState.java index f409ac2b9b3e8..5e3da176494e1 100644 --- a/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosZonePlayerState.java +++ b/addons/binding/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosZonePlayerState.java @@ -1,5 +1,6 @@ /** - * Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * * 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 diff --git a/addons/binding/pom.xml b/addons/binding/pom.xml index 68de6fa733663..05137cfe00006 100644 --- a/addons/binding/pom.xml +++ b/addons/binding/pom.xml @@ -2,8 +2,8 @@ - org.openhab - addons + org.openhab.addons + pom 2.0.0-SNAPSHOT @@ -17,6 +17,8 @@ org.openhab.binding.sonos + org.openhab.binding.max + org.openhab.binding.networkhealth diff --git a/addons/pom.xml b/addons/pom.xml index 66e93cdf8e17e..9f48161dbfc83 100644 --- a/addons/pom.xml +++ b/addons/pom.xml @@ -3,13 +3,13 @@ org.openhab - openhab + pom 2.0.0-SNAPSHOT 4.0.0 - org.openhab - addons + org.openhab.addons + pom openHAB Add-ons diff --git a/bundles/core/org.openhab.core.compat1x/OSGI-INF/actionservicefactory.xml b/bundles/core/org.openhab.core.compat1x/OSGI-INF/actionservicefactory.xml index ffa0491b551a9..e03a711887aef 100644 --- a/bundles/core/org.openhab.core.compat1x/OSGI-INF/actionservicefactory.xml +++ b/bundles/core/org.openhab.core.compat1x/OSGI-INF/actionservicefactory.xml @@ -1,4 +1,14 @@ + diff --git a/bundles/core/org.openhab.core.compat1x/OSGI-INF/audioaction.xml b/bundles/core/org.openhab.core.compat1x/OSGI-INF/audioaction.xml index 55d08923dee9a..180692dd31256 100644 --- a/bundles/core/org.openhab.core.compat1x/OSGI-INF/audioaction.xml +++ b/bundles/core/org.openhab.core.compat1x/OSGI-INF/audioaction.xml @@ -1,7 +1,7 @@ diff --git a/bundles/core/org.openhab.core.compat1x/OSGI-INF/bindingconfigreaderfactory.xml b/bundles/core/org.openhab.core.compat1x/OSGI-INF/bindingconfigreaderfactory.xml index 14f7c3eb7bdde..c4b516889059a 100644 --- a/bundles/core/org.openhab.core.compat1x/OSGI-INF/bindingconfigreaderfactory.xml +++ b/bundles/core/org.openhab.core.compat1x/OSGI-INF/bindingconfigreaderfactory.xml @@ -1,4 +1,14 @@ + diff --git a/bundles/core/org.openhab.core.compat1x/OSGI-INF/eventbridge.xml b/bundles/core/org.openhab.core.compat1x/OSGI-INF/eventbridge.xml index f54275e7b2fbf..1f6ea9188e1b3 100644 --- a/bundles/core/org.openhab.core.compat1x/OSGI-INF/eventbridge.xml +++ b/bundles/core/org.openhab.core.compat1x/OSGI-INF/eventbridge.xml @@ -1,4 +1,14 @@ + diff --git a/bundles/core/org.openhab.core.compat1x/OSGI-INF/eventpublisherdelegate.xml b/bundles/core/org.openhab.core.compat1x/OSGI-INF/eventpublisherdelegate.xml index 4e5a5eea3fbb7..a3787bfbcca40 100644 --- a/bundles/core/org.openhab.core.compat1x/OSGI-INF/eventpublisherdelegate.xml +++ b/bundles/core/org.openhab.core.compat1x/OSGI-INF/eventpublisherdelegate.xml @@ -1,4 +1,14 @@ + diff --git a/bundles/core/org.openhab.core.compat1x/OSGI-INF/itemfactory.xml b/bundles/core/org.openhab.core.compat1x/OSGI-INF/itemfactory.xml index cc729eb3f7f61..06f3314dbdea0 100644 --- a/bundles/core/org.openhab.core.compat1x/OSGI-INF/itemfactory.xml +++ b/bundles/core/org.openhab.core.compat1x/OSGI-INF/itemfactory.xml @@ -1,7 +1,7 @@ diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/autoupdate/AutoUpdateBindingProvider.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/autoupdate/AutoUpdateBindingProvider.java index f07d06a00aa00..303f2faa0fb29 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/autoupdate/AutoUpdateBindingProvider.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/autoupdate/AutoUpdateBindingProvider.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/autoupdate/internal/AutoUpdateProviderDelegate.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/autoupdate/internal/AutoUpdateProviderDelegate.java index fca88103f66b0..3c317fe3577ca 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/autoupdate/internal/AutoUpdateProviderDelegate.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/autoupdate/internal/AutoUpdateProviderDelegate.java @@ -1,3 +1,11 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.core.autoupdate.internal; import java.util.Set; diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/AbstractActiveBinding.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/AbstractActiveBinding.java index eeb00ccf8694f..ea90317ff093d 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/AbstractActiveBinding.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/AbstractActiveBinding.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/AbstractBinding.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/AbstractBinding.java index ae2dcf88ee500..b086d15c8a782 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/AbstractBinding.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/AbstractBinding.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/BindingChangeListener.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/BindingChangeListener.java index ec6ad8430a947..b467eaa89bb24 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/BindingChangeListener.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/BindingChangeListener.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/BindingConfig.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/BindingConfig.java index a7474d8c3c7bf..ccc54ee5fbd42 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/BindingConfig.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/BindingConfig.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/BindingProvider.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/BindingProvider.java index 6aaddc07650db..3d545ae292202 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/BindingProvider.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/BindingProvider.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/internal/BindingConfigReaderDelegate.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/internal/BindingConfigReaderDelegate.java index b99eac37d4028..b93c58bfd9bed 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/internal/BindingConfigReaderDelegate.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/internal/BindingConfigReaderDelegate.java @@ -1,3 +1,11 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.core.binding.internal; import org.eclipse.smarthome.model.item.BindingConfigParseException; diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/internal/BindingConfigReaderFactory.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/internal/BindingConfigReaderFactory.java index 685bf51e2ae0c..2783aaf649740 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/internal/BindingConfigReaderFactory.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/binding/internal/BindingConfigReaderFactory.java @@ -1,3 +1,11 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.core.binding.internal; import java.util.Dictionary; diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/compat1x/internal/CompatibilityActivator.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/compat1x/internal/CompatibilityActivator.java index a04901849045f..20f4b9b860a01 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/compat1x/internal/CompatibilityActivator.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/compat1x/internal/CompatibilityActivator.java @@ -1,5 +1,6 @@ /** - * Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * * 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 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/compat1x/internal/ItemMapper.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/compat1x/internal/ItemMapper.java index 8bb7e5293f5d9..d9e93198c1aa0 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/compat1x/internal/ItemMapper.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/compat1x/internal/ItemMapper.java @@ -1,5 +1,6 @@ /** - * Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * * 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 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/events/AbstractEventSubscriber.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/events/AbstractEventSubscriber.java index ed4d62d80285b..ab3cffe032fe6 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/events/AbstractEventSubscriber.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/events/AbstractEventSubscriber.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/events/EventConstants.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/events/EventConstants.java index df1a8e31cf3cf..8ddc7c9f5f70e 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/events/EventConstants.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/events/EventConstants.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/events/EventPublisher.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/events/EventPublisher.java index 7db86cfcf6c7f..c7b4d97e5d2d5 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/events/EventPublisher.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/events/EventPublisher.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/events/EventPublisherDelegate.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/events/EventPublisherDelegate.java index ff6725f8d22dc..fa0a99db5d8ea 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/events/EventPublisherDelegate.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/events/EventPublisherDelegate.java @@ -1,3 +1,11 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.core.events; import org.eclipse.smarthome.core.events.EventPublisher; diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/events/EventSubscriber.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/events/EventSubscriber.java index cd3180846495c..74f4d32210654 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/events/EventSubscriber.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/events/EventSubscriber.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/events/internal/EventBridge.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/events/internal/EventBridge.java index ded583d4a1253..8e38d16bb1e44 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/events/internal/EventBridge.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/events/internal/EventBridge.java @@ -1,3 +1,11 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.core.events.internal; import java.util.HashMap; diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/GenericItem.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/GenericItem.java index 793875c214a44..3d6319c31a367 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/GenericItem.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/GenericItem.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/GroupFunction.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/GroupFunction.java index 3e6c7150af45c..b1076318a276f 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/GroupFunction.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/GroupFunction.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/GroupItem.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/GroupItem.java index a017596bea46f..821a49866d807 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/GroupItem.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/GroupItem.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/Item.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/Item.java index 611886e485fcf..45faf3982e5ed 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/Item.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/Item.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemFactory.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemFactory.java index fbb68a387ce7d..21d8fe43a6398 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemFactory.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemFactory.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemLookupException.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemLookupException.java index 6841ef6b28e53..d309ac016f0bc 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemLookupException.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemLookupException.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemNotFoundException.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemNotFoundException.java index 0ddc3cc6ec8d2..dc24ffb315a42 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemNotFoundException.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemNotFoundException.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemNotUniqueException.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemNotUniqueException.java index dc5c8e434352b..387b1f143b288 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemNotUniqueException.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemNotUniqueException.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemProvider.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemProvider.java index a2b70c7f26f9e..c7da907d09787 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemProvider.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemProvider.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemRegistry.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemRegistry.java index 5564a6e6716bf..28826a89d65d9 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemRegistry.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemRegistry.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemRegistryChangeListener.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemRegistryChangeListener.java index ea65f63832677..fc0650ba9484f 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemRegistryChangeListener.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemRegistryChangeListener.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemsChangeListener.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemsChangeListener.java index 59c1069d70636..d3f624d5a7f0f 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemsChangeListener.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/ItemsChangeListener.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/StateChangeListener.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/StateChangeListener.java index 6a62a7a65bbba..8acdae64d18bd 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/StateChangeListener.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/items/StateChangeListener.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/ColorItem.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/ColorItem.java index 126dba6a3b98d..2865b9e95d402 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/ColorItem.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/ColorItem.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/ContactItem.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/ContactItem.java index 27c603f2389d3..178c3b0e230a8 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/ContactItem.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/ContactItem.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/DateTimeItem.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/DateTimeItem.java index 5e195ac66a140..def35d0a2c682 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/DateTimeItem.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/DateTimeItem.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/DimmerItem.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/DimmerItem.java index a5e2fa9c594d2..91a86bea6da53 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/DimmerItem.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/DimmerItem.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/NumberItem.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/NumberItem.java index dbbf31191f673..ce1657d07001d 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/NumberItem.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/NumberItem.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/RollershutterItem.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/RollershutterItem.java index c889ff7257607..15d225f45d5dd 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/RollershutterItem.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/RollershutterItem.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/StringItem.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/StringItem.java index 9d230a2764a43..66df69c2c5093 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/StringItem.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/StringItem.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/SwitchItem.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/SwitchItem.java index 8a3e2ceaf7b75..3ba7c8369a647 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/SwitchItem.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/items/SwitchItem.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/ArithmeticGroupFunction.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/ArithmeticGroupFunction.java index 498f5134aa287..f77b696a9ce54 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/ArithmeticGroupFunction.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/ArithmeticGroupFunction.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/DateTimeType.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/DateTimeType.java index f4bd7947b916d..8e9bb2f14d7fd 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/DateTimeType.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/DateTimeType.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/DecimalType.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/DecimalType.java index b896d0480914c..e0d59cc61c463 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/DecimalType.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/DecimalType.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/HSBType.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/HSBType.java index 6cebfaf5c386c..f5e89d9169b50 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/HSBType.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/HSBType.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/IncreaseDecreaseType.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/IncreaseDecreaseType.java index 007de3907d378..b3571a21990c3 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/IncreaseDecreaseType.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/IncreaseDecreaseType.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/OnOffType.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/OnOffType.java index abed2dc292760..6143bff4ff344 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/OnOffType.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/OnOffType.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/OpenClosedType.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/OpenClosedType.java index 73b02cb3878e2..e12e404469817 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/OpenClosedType.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/OpenClosedType.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/PercentType.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/PercentType.java index 8b6a96822cd3e..d3e3a926ca9b3 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/PercentType.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/PercentType.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/StopMoveType.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/StopMoveType.java index f4e866da74d63..062e04b722859 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/StopMoveType.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/StopMoveType.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/StringType.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/StringType.java index f1999068f5110..8a55efb59becc 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/StringType.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/StringType.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/UpDownType.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/UpDownType.java index 2d87459fcb5f3..e775e966c241b 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/UpDownType.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/library/types/UpDownType.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/FilterCriteria.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/FilterCriteria.java index 3d4de0adcd1ec..9c6a013e9a7a5 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/FilterCriteria.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/FilterCriteria.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/HistoricItem.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/HistoricItem.java index f55674284c2c1..5cd56e653ff39 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/HistoricItem.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/HistoricItem.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/PersistenceService.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/PersistenceService.java index 64e6c09246b06..954c1efbaa9a4 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/PersistenceService.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/PersistenceService.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/QueryablePersistenceService.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/QueryablePersistenceService.java index 66f2faa7ba679..970a0b07a74a0 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/QueryablePersistenceService.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/QueryablePersistenceService.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/internal/PersistenceServiceDelegate.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/internal/PersistenceServiceDelegate.java index 4996661402e1a..a389fffb937c5 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/internal/PersistenceServiceDelegate.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/internal/PersistenceServiceDelegate.java @@ -1,5 +1,6 @@ /** - * Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * * 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 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/internal/PersistenceServiceFactory.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/internal/PersistenceServiceFactory.java index 0080ee700f23a..b4d68208044f2 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/internal/PersistenceServiceFactory.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/internal/PersistenceServiceFactory.java @@ -1,5 +1,6 @@ /** - * Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * * 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 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/internal/QueryablePersistenceServiceDelegate.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/internal/QueryablePersistenceServiceDelegate.java index e58eaf2595d5b..8278a5876169a 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/internal/QueryablePersistenceServiceDelegate.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/persistence/internal/QueryablePersistenceServiceDelegate.java @@ -1,5 +1,6 @@ /** - * Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * * 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 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/scriptengine/action/ActionDoc.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/scriptengine/action/ActionDoc.java index 766fc8fe4eece..f8edfe7e5853a 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/scriptengine/action/ActionDoc.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/scriptengine/action/ActionDoc.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/scriptengine/action/ActionService.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/scriptengine/action/ActionService.java index c4bed40f71869..0be4123b3258f 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/scriptengine/action/ActionService.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/scriptengine/action/ActionService.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/scriptengine/action/ParamDoc.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/scriptengine/action/ParamDoc.java index e760865d77d1f..df021b4429a62 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/scriptengine/action/ParamDoc.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/scriptengine/action/ParamDoc.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/scriptengine/action/internal/ActionServiceDelegate.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/scriptengine/action/internal/ActionServiceDelegate.java index 7821d537aaaff..a3a1212c29bf7 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/scriptengine/action/internal/ActionServiceDelegate.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/scriptengine/action/internal/ActionServiceDelegate.java @@ -1,3 +1,11 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.core.scriptengine.action.internal; import org.eclipse.smarthome.core.scriptengine.action.ActionService; diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/scriptengine/action/internal/ActionServiceFactory.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/scriptengine/action/internal/ActionServiceFactory.java index 031102bbfc97a..7ef101f1cb618 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/scriptengine/action/internal/ActionServiceFactory.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/scriptengine/action/internal/ActionServiceFactory.java @@ -1,3 +1,11 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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.core.scriptengine.action.internal; import java.util.Dictionary; diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/service/AbstractActiveService.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/service/AbstractActiveService.java index fc14aedbed19a..1272bf4462b26 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/service/AbstractActiveService.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/service/AbstractActiveService.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/transform/TransformationException.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/transform/TransformationException.java index c016783ad7cb3..03985fb6cae13 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/transform/TransformationException.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/transform/TransformationException.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/transform/TransformationHelper.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/transform/TransformationHelper.java index 70be7104fef68..7ded409483abd 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/transform/TransformationHelper.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/transform/TransformationHelper.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/transform/TransformationService.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/transform/TransformationService.java index ca82fa7030734..e0993626f1a76 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/transform/TransformationService.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/transform/TransformationService.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/transform/actions/Transformation.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/transform/actions/Transformation.java index 59c8793bd05aa..c98ab5ad8dadf 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/transform/actions/Transformation.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/transform/actions/Transformation.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/Command.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/Command.java index 5fae19f2f4ab5..8e5133042188f 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/Command.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/Command.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/ComplexType.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/ComplexType.java index b4e52b3b8280e..78ee5da4d47ea 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/ComplexType.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/ComplexType.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/EventType.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/EventType.java index bad2d6ad75a22..b8247dbafbf54 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/EventType.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/EventType.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/PrimitiveType.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/PrimitiveType.java index 95513df5d4d79..49804c4370218 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/PrimitiveType.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/PrimitiveType.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/State.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/State.java index a5086986c42d3..80ed847e5255e 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/State.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/State.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/Type.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/Type.java index 9f7739abb6518..5eab0ee14aff0 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/Type.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/Type.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/TypeParser.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/TypeParser.java index 3f0b956c6f4b3..f28815f28f1fa 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/TypeParser.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/TypeParser.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/UnDefType.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/UnDefType.java index 886de1af2d7b5..98ebfdec22bf6 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/UnDefType.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/core/types/UnDefType.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/console/Console.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/console/Console.java index 8f46fb1f5b046..623555b527ddd 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/console/Console.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/console/Console.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/console/ConsoleInterpreter.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/console/ConsoleInterpreter.java index 02f73d79c3314..51c620f2da198 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/console/ConsoleInterpreter.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/console/ConsoleInterpreter.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/multimedia/actions/Audio.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/multimedia/actions/Audio.java index 0ee5000470750..b5059a5b0782a 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/multimedia/actions/Audio.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/multimedia/actions/Audio.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/multimedia/actions/AudioActionService.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/multimedia/actions/AudioActionService.java index a9634238c36e3..2c8f3c8e999e0 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/multimedia/actions/AudioActionService.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/multimedia/actions/AudioActionService.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/net/actions/Exec.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/net/actions/Exec.java index b88c425659ff8..33fd9e1470065 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/net/actions/Exec.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/net/actions/Exec.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/net/actions/HTTP.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/net/actions/HTTP.java index 0c9aa492fc62e..8ab95c6965fbf 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/net/actions/HTTP.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/net/actions/HTTP.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/net/actions/Ping.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/net/actions/Ping.java index 7ccc51a98a639..5d939feea7f0e 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/net/actions/Ping.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/net/actions/Ping.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/net/exec/ExecUtil.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/net/exec/ExecUtil.java index 5d32810ea5750..340c2bece9d61 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/net/exec/ExecUtil.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/net/exec/ExecUtil.java @@ -1,32 +1,11 @@ /** - * openHAB, the open Home Automation Bus. - * Copyright (C) 2010-2013, openHAB.org + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * - * See the contributors.txt file in the distribution for a - * full listing of individual contributors. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - * - * Additional permission under GNU GPL version 3 section 7 - * - * If you modify this Program, or any covered work, by linking or - * combining it with Eclipse (or a modified version of that library), - * containing parts covered by the terms of the Eclipse Public License - * (EPL), the licensors of this Program grant you additional permission - * to convey the resulting work. + * 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.io.net.exec; import java.io.ByteArrayOutputStream; diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/net/http/HttpUtil.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/net/http/HttpUtil.java index b6d16d1b58394..3c0b19cdf4f02 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/net/http/HttpUtil.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/io/net/http/HttpUtil.java @@ -1,30 +1,10 @@ /** - * openHAB, the open Home Automation Bus. - * Copyright (C) 2010-2013, openHAB.org + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * - * See the contributors.txt file in the distribution for a - * full listing of individual contributors. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - * - * Additional permission under GNU GPL version 3 section 7 - * - * If you modify this Program, or any covered work, by linking or - * combining it with Eclipse (or a modified version of that library), - * containing parts covered by the terms of the Eclipse Public License - * (EPL), the licensors of this Program grant you additional permission - * to convey the resulting work. + * 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.io.net.http; diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/library/tel/internal/TelItemFactory.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/library/tel/internal/TelItemFactory.java index 10e9b21cdfa88..a96acaffd4fde 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/library/tel/internal/TelItemFactory.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/library/tel/internal/TelItemFactory.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/library/tel/items/CallItem.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/library/tel/items/CallItem.java index ccdb91b0c5c65..062e64fa3b18b 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/library/tel/items/CallItem.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/library/tel/items/CallItem.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/library/tel/items/ESHCallItem.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/library/tel/items/ESHCallItem.java index deba06ac6ec53..404d3ed04ab18 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/library/tel/items/ESHCallItem.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/library/tel/items/ESHCallItem.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/library/tel/types/CallType.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/library/tel/types/CallType.java index bb2e556f13df1..da25ab5ad48f0 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/library/tel/types/CallType.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/library/tel/types/CallType.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/library/tel/types/ESHCallType.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/library/tel/types/ESHCallType.java index 1a3744aeadf91..016e4eea464f0 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/library/tel/types/ESHCallType.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/library/tel/types/ESHCallType.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/model/item/binding/AbstractGenericBindingProvider.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/model/item/binding/AbstractGenericBindingProvider.java index e33b11eafbffb..40d320609d9f4 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/model/item/binding/AbstractGenericBindingProvider.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/model/item/binding/AbstractGenericBindingProvider.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/model/item/binding/BindingConfigParseException.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/model/item/binding/BindingConfigParseException.java index cd98a2ae6f140..387a6d874ba1b 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/model/item/binding/BindingConfigParseException.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/model/item/binding/BindingConfigParseException.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/model/item/binding/BindingConfigReader.java b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/model/item/binding/BindingConfigReader.java index d4346e42f8d2e..2ed430233f240 100644 --- a/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/model/item/binding/BindingConfigReader.java +++ b/bundles/core/org.openhab.core.compat1x/src/main/java/org/openhab/model/item/binding/BindingConfigReader.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core.init/OSGI-INF/logservice.xml b/bundles/core/org.openhab.core.init/OSGI-INF/logservice.xml index a4919f4678491..2244760443ab0 100644 --- a/bundles/core/org.openhab.core.init/OSGI-INF/logservice.xml +++ b/bundles/core/org.openhab.core.init/OSGI-INF/logservice.xml @@ -1,7 +1,7 @@ diff --git a/bundles/core/org.openhab.core/OSGI-INF/defaultsitemapprovider.xml b/bundles/core/org.openhab.core/OSGI-INF/defaultsitemapprovider.xml index 24422dd2a5f75..a0992d96f7304 100644 --- a/bundles/core/org.openhab.core/OSGI-INF/defaultsitemapprovider.xml +++ b/bundles/core/org.openhab.core/OSGI-INF/defaultsitemapprovider.xml @@ -1,4 +1,14 @@ + diff --git a/bundles/core/org.openhab.core/OSGI-INF/thingitemprovider.xml b/bundles/core/org.openhab.core/OSGI-INF/thingitemprovider.xml index 27c12926e1aff..51166816353b1 100644 --- a/bundles/core/org.openhab.core/OSGI-INF/thingitemprovider.xml +++ b/bundles/core/org.openhab.core/OSGI-INF/thingitemprovider.xml @@ -1,4 +1,14 @@ + diff --git a/bundles/core/org.openhab.core/OSGI-INF/thinglinkprovider.xml b/bundles/core/org.openhab.core/OSGI-INF/thinglinkprovider.xml index f4360bf80dcde..760e47d89173c 100644 --- a/bundles/core/org.openhab.core/OSGI-INF/thinglinkprovider.xml +++ b/bundles/core/org.openhab.core/OSGI-INF/thinglinkprovider.xml @@ -1,4 +1,14 @@ + diff --git a/bundles/core/org.openhab.core/src/main/java/org/openhab/core/internal/CoreActivator.java b/bundles/core/org.openhab.core/src/main/java/org/openhab/core/internal/CoreActivator.java index 400fd43be598e..8ac952dbca282 100644 --- a/bundles/core/org.openhab.core/src/main/java/org/openhab/core/internal/CoreActivator.java +++ b/bundles/core/org.openhab.core/src/main/java/org/openhab/core/internal/CoreActivator.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core/src/main/java/org/openhab/core/internal/inbox/AutoApproveService.java b/bundles/core/org.openhab.core/src/main/java/org/openhab/core/internal/inbox/AutoApproveService.java index 02388430edfe1..695a7bda835fd 100644 --- a/bundles/core/org.openhab.core/src/main/java/org/openhab/core/internal/inbox/AutoApproveService.java +++ b/bundles/core/org.openhab.core/src/main/java/org/openhab/core/internal/inbox/AutoApproveService.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core/src/main/java/org/openhab/core/internal/item/DefaultSitemapProvider.java b/bundles/core/org.openhab.core/src/main/java/org/openhab/core/internal/item/DefaultSitemapProvider.java index c6c32c8921db1..1b73e98f5a7fc 100644 --- a/bundles/core/org.openhab.core/src/main/java/org/openhab/core/internal/item/DefaultSitemapProvider.java +++ b/bundles/core/org.openhab.core/src/main/java/org/openhab/core/internal/item/DefaultSitemapProvider.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff --git a/bundles/core/org.openhab.core/src/main/java/org/openhab/core/internal/item/ThingItemChannelLinkProvider.java b/bundles/core/org.openhab.core/src/main/java/org/openhab/core/internal/item/ThingItemChannelLinkProvider.java index 57ccac0d20560..92cde341cbeee 100644 --- a/bundles/core/org.openhab.core/src/main/java/org/openhab/core/internal/item/ThingItemChannelLinkProvider.java +++ b/bundles/core/org.openhab.core/src/main/java/org/openhab/core/internal/item/ThingItemChannelLinkProvider.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -60,7 +60,7 @@ private Set getLinks(Thing element) { Set links = new HashSet<>(); if(thingItemUIProvider.isEnabled()) { for(Channel channel : element.getChannels()) { - links.add(new ItemChannelLink(channel.getUID().toString().replace(":", "_"), channel.getUID())); + links.add(new ItemChannelLink(channel.getUID().toString().replace(":", "_").replaceAll("#", "_"), channel.getUID())); } } return links; diff --git a/bundles/core/org.openhab.core/src/main/java/org/openhab/core/internal/item/ThingItemUIProvider.java b/bundles/core/org.openhab.core/src/main/java/org/openhab/core/internal/item/ThingItemUIProvider.java index 45fdf937dde7c..421ce9bc25079 100644 --- a/bundles/core/org.openhab.core/src/main/java/org/openhab/core/internal/item/ThingItemUIProvider.java +++ b/bundles/core/org.openhab.core/src/main/java/org/openhab/core/internal/item/ThingItemUIProvider.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2014, openHAB.org and others. + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -66,7 +66,7 @@ public String getIcon(String itemName) { } for(Thing thing : thingRegistry.getAll()) { - if(thing.getUID().toString().replaceAll(":", "_").equals(itemName)) { + if(thing.getUID().toString().replaceAll(":", "_").replaceAll("#", "_").equals(itemName)) { String icon = null; if(thing instanceof Bridge) { icon = "network"; @@ -80,7 +80,7 @@ public String getIcon(String itemName) { } } for(Channel ch : thing.getChannels()) { - if(ch.getUID().toString().replaceAll(":", "_").equals(itemName)) { + if(ch.getUID().toString().replaceAll(":", "_").replaceAll("#", "_").equals(itemName)) { if(ch.getAcceptedItemType().equals("Color")) { return "switch"; } @@ -98,7 +98,7 @@ public String getLabel(String itemName) { if(!enabled) return null; for(Thing thing : thingRegistry.getAll()) { - if(thing.getUID().toString().replaceAll(":", "_").equals(itemName)) { + if(thing.getUID().toString().replaceAll(":", "_").replaceAll("#", "_").equals(itemName)) { String label = (String) thing.getConfiguration().get("label"); if(label!=null && !label.isEmpty()) { return label; @@ -107,7 +107,7 @@ public String getLabel(String itemName) { } } for(Channel channel : thing.getChannels()) { - if(channel.getUID().toString().replaceAll(":", "_").equals(itemName)) { + if(channel.getUID().toString().replaceAll(":", "_").replaceAll("#", "_").equals(itemName)) { String label = (String) StringUtils.capitalize(channel.getUID().getId()); ThingType thingType = thingTypeRegistry.getThingType(thing.getThingTypeUID()); if(thingType!=null) { @@ -163,9 +163,9 @@ public Collection getAll() { } /*default*/ GroupItem createItemsForThing(Thing thing) { - GroupItem group = new GroupItem(thing.getUID().toString().replaceAll(":", "_")); + GroupItem group = new GroupItem(thing.getUID().toString().replaceAll(":", "_").replaceAll("#", "_")); for(Channel channel : thing.getChannels()) { - Item item = itemFactory.createItem(channel.getAcceptedItemType(), channel.getUID().toString().replaceAll(":", "_")); + Item item = itemFactory.createItem(channel.getAcceptedItemType(), channel.getUID().toString().replaceAll(":", "_").replaceAll("#", "_")); if(item!=null) { if(group.getMembers().contains(item)) { group.removeMember(item); @@ -180,7 +180,7 @@ public Collection getAll() { } } if(thing.getBridgeUID()!=null) { - group.addGroupName(thing.getBridgeUID().toString().replaceAll(":", "_")); + group.addGroupName(thing.getBridgeUID().toString().replaceAll(":", "_").replaceAll("#", "_")); } else { group.addGroupName("Things"); } @@ -282,8 +282,12 @@ public void added(Thing element) { listener.added(this, getRootItem()); } - eventPublisher.postUpdate(group.getName(), UnDefType.UNDEF); - eventPublisher.postUpdate(rootItem.getName(), UnDefType.UNDEF); + if(group.getAcceptedDataTypes().contains(UnDefType.UNDEF)) { + eventPublisher.postUpdate(group.getName(), UnDefType.UNDEF); + } + if(rootItem.getAcceptedDataTypes().contains(UnDefType.UNDEF)) { + eventPublisher.postUpdate(rootItem.getName(), UnDefType.UNDEF); + } } @Override diff --git a/bundles/io/org.openhab.io.rest.docs/.classpath b/bundles/io/org.openhab.io.rest.docs/.classpath new file mode 100644 index 0000000000000..2a566a5dc96fb --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/bundles/io/org.openhab.io.rest.docs/.project b/bundles/io/org.openhab.io.rest.docs/.project new file mode 100644 index 0000000000000..43ce9309ae002 --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/.project @@ -0,0 +1,38 @@ + + + org.openhab.io.rest.docs + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.ds.core.builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.pde.PluginNature + + diff --git a/bundles/io/org.openhab.io.rest.docs/META-INF/MANIFEST.MF b/bundles/io/org.openhab.io.rest.docs/META-INF/MANIFEST.MF new file mode 100644 index 0000000000000..8a5574edef0b8 --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/META-INF/MANIFEST.MF @@ -0,0 +1,17 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: openHAB REST Documentation +Bundle-SymbolicName: org.openhab.io.rest.docs +Bundle-Version: 2.0.0.qualifier +Import-Package: com.google.gson, + com.google.gson.annotations, + javax.servlet, + javax.servlet.http, + javax.ws.rs, + javax.ws.rs.core, + org.eclipse.smarthome.io.rest, + org.osgi.framework, + org.osgi.service.cm, + org.osgi.service.http, + org.slf4j;version="1.7.2" +Service-Component: OSGI-INF/swagger.xml diff --git a/bundles/io/org.openhab.io.rest.docs/OSGI-INF/swagger.xml b/bundles/io/org.openhab.io.rest.docs/OSGI-INF/swagger.xml new file mode 100644 index 0000000000000..a0cf5e1c700b0 --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/OSGI-INF/swagger.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + policy="dynamic" unbind="removeService"/> + diff --git a/bundles/io/org.openhab.io.rest.docs/README b/bundles/io/org.openhab.io.rest.docs/README new file mode 100644 index 0000000000000..b2d6c9e39a777 --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/README @@ -0,0 +1,3 @@ +The code of this bundle originates from the Amdatu project, see http://www.amdatu.org/components/web.html + +It is made available under the Apache license 2.0 (http://www.amdatu.org/license.html) diff --git a/bundles/io/org.openhab.io.rest.docs/build.properties b/bundles/io/org.openhab.io.rest.docs/build.properties new file mode 100644 index 0000000000000..5349a6a54fe24 --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/build.properties @@ -0,0 +1,5 @@ +bin.includes = META-INF/,\ + .,\ + OSGI-INF/,\ + swagger/ +source.. = src/main/java diff --git a/bundles/io/org.openhab.io.rest.docs/pom.xml b/bundles/io/org.openhab.io.rest.docs/pom.xml new file mode 100644 index 0000000000000..c89cb2d654be2 --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/pom.xml @@ -0,0 +1,15 @@ + + 4.0.0 + org.openhab.bundles.io + org.openhab.io.rest.docs + openHAB REST API Documentation + + eclipse-plugin + + org.openhab.bundles.io + pom + 2.0.0-SNAPSHOT + + + diff --git a/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/Description.java b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/Description.java new file mode 100644 index 0000000000000..60a5b81478ec6 --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/Description.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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 + */ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.io.rest.docs; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Use this annotation on classes, methods and parameters that you want to document. + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface Description { + public String value(); +} diff --git a/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/NoDocumentation.java b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/NoDocumentation.java new file mode 100644 index 0000000000000..556241eb89c3b --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/NoDocumentation.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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 + */ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.io.rest.docs; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Use this annotation to prevent a class or method to show up in documentation. + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface NoDocumentation { +} diff --git a/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/Notes.java b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/Notes.java new file mode 100644 index 0000000000000..61a76e1e6e2ad --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/Notes.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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 + */ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.io.rest.docs; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Use this annotation on classes, methods and parameters that you want to document. + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface Notes { + public String value(); +} \ No newline at end of file diff --git a/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/ResponseMessage.java b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/ResponseMessage.java new file mode 100644 index 0000000000000..e3a19a2a0955b --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/ResponseMessage.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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 + */ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.io.rest.docs; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Use this annotation on classes, methods and parameters that you want to document. + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface ResponseMessage { + public int code(); + + public String message(); +} \ No newline at end of file diff --git a/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/ResponseMessages.java b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/ResponseMessages.java new file mode 100644 index 0000000000000..4dcbe5f6883ce --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/ResponseMessages.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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 + */ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.io.rest.docs; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Use this annotation on classes, methods and parameters that you want to document. + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface ResponseMessages { + public ResponseMessage[] value(); +} \ No newline at end of file diff --git a/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/ReturnType.java b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/ReturnType.java new file mode 100644 index 0000000000000..90411d8080075 --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/ReturnType.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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 + */ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.io.rest.docs; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import javax.ws.rs.core.Response; + +/** + * Use this annotation on methods to set another return type for the the documentation. For + * example when return {@link Response}. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface ReturnType { + public Class value(); +} \ No newline at end of file diff --git a/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/Constants.java b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/Constants.java new file mode 100644 index 0000000000000..2ad9c9887e9e7 --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/Constants.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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 + */ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.io.rest.docs.swagger; + +public interface Constants { + + /** + * Version string used for "unversioned" APIs. + */ + String DEFAULT_API_VERSION = "0.8.0"; + + /** + * The version of the Swagger API used. + */ + String SWAGGER_API_VERSION = "1.2"; + + String PATH_PARAM = "path"; + String QUERY_PARAM = "query"; + String HEADER_PARAM = "header"; + String BODY_PARAM = "body"; + String FORM_PARAM = "form"; + + String HEADER_X_FORWARDED_PROTO = "X-Forwarded-Proto"; +} diff --git a/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/SwaggerServlet.java b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/SwaggerServlet.java new file mode 100644 index 0000000000000..81554f56853b7 --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/SwaggerServlet.java @@ -0,0 +1,257 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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 + */ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.io.rest.docs.swagger; + +import static org.openhab.io.rest.docs.swagger.Constants.*; +import static org.openhab.io.rest.docs.swagger.SwaggerUtil.documentOperations; +import static org.openhab.io.rest.docs.swagger.SwaggerUtil.getDescription; +import static org.openhab.io.rest.docs.swagger.SwaggerUtil.getPath; + +import java.io.IOException; +import java.io.PrintWriter; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.Path; +import javax.ws.rs.core.MediaType; + +import org.openhab.io.rest.docs.Description; +import org.openhab.io.rest.docs.NoDocumentation; +import org.openhab.io.rest.docs.swagger.model.SwaggerAPI; +import org.openhab.io.rest.docs.swagger.model.SwaggerAPIPath; +import org.openhab.io.rest.docs.swagger.model.SwaggerModel; +import org.openhab.io.rest.docs.swagger.model.SwaggerOperation; +import org.openhab.io.rest.docs.swagger.model.SwaggerResource; +import org.openhab.io.rest.docs.swagger.model.SwaggerResources; +import org.osgi.service.cm.ConfigurationException; +import org.osgi.service.cm.ManagedService; +import org.osgi.service.http.HttpService; +import org.osgi.service.http.NamespaceException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.Gson; + +/** + * Listens to services in the framework and analyzes them for documentation. Also implements + * the Servlet API so you can map this component to an endpoint and use it to show all + * REST APIs that are available in the framework. + */ +@SuppressWarnings("serial") +public class SwaggerServlet extends HttpServlet implements ManagedService { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private static final String ENDPOINT_KEY = "endpoint"; + private static final String DEFAULT_ENDPOINT = "/rest"; + + private static final JaxRsMethodComparator COMPARATOR = new JaxRsMethodComparator(); + + private final CopyOnWriteArrayList m_restServices = new CopyOnWriteArrayList(); + + private String m_restEndpoint = DEFAULT_ENDPOINT; + + private HttpService httpService; + + public void addService(Object service) { + Class clazz = service.getClass(); + + // Check whether it is a "real" JAX-RS component, and whether we should generate documentation for it... + if (clazz.isAnnotationPresent(Path.class) && !clazz.isAnnotationPresent(NoDocumentation.class)) { + m_restServices.addIfAbsent(service); + } + } + + public void removeService(Object service) { + m_restServices.remove(service); + } + + protected void setHttpService(HttpService httpService) { + this.httpService = httpService; + } + + protected void unsetHttpService(HttpService httpService) { + this.httpService = null; + } + + protected void activate() { + try { + httpService.registerServlet("/restdocs", this, new Hashtable<>(), httpService.createDefaultHttpContext()); + httpService.registerResources("/doc", "swagger", httpService.createDefaultHttpContext()); + } catch (ServletException e) { + logger.error("Could not start up REST documentation service: {}", e.getMessage()); + } catch (NamespaceException e) { + logger.error("Could not start up REST documentation service: {}", e.getMessage()); + } + } + + @Override + @SuppressWarnings("rawtypes") + public void updated(Dictionary properties) throws ConfigurationException { + if (properties == null) { + m_restEndpoint = DEFAULT_ENDPOINT; + } else { + Object endpoint = properties.get(ENDPOINT_KEY); + if (endpoint instanceof String) { + m_restEndpoint = (String) endpoint; + } else { + throw new ConfigurationException(ENDPOINT_KEY, "has to be a non-null string."); + } + } + } + + protected SwaggerAPI createDocumentationFor(String baseURL, Object instance) { + Class clazz = instance.getClass(); + + String rootPath = getPath(clazz.getAnnotation(Path.class)); + + // See section 3.3.1 of the JAX-RS specification v1.1... + Method[] methods = clazz.getMethods(); + Arrays.sort(methods, COMPARATOR); + + SwaggerModel models = new SwaggerModel(); + List apis = new ArrayList(); + + for (Method method : methods) { + if (method.isAnnotationPresent(NoDocumentation.class)) { + // Do not create documentation for this method... + continue; + } + + List ops = documentOperations(models, method); + if (ops.isEmpty()) { + // Not a valid JAX-RS operation... + continue; + } + + String path = getPath(method.getAnnotation(Path.class)); + String doc = getDescription(method.getAnnotation(Description.class)); + + apis.add(new SwaggerAPIPath(rootPath.concat(path), doc, ops)); + } + + return new SwaggerAPI(baseURL.concat(m_restEndpoint), rootPath, apis, models); + } + + protected SwaggerResources createResourceListingFor(String baseURL, String rootPath, Object[] instances) { + List rs = new ArrayList(); + for (Object instance : instances) { + Class clazz = instance.getClass(); + + String path = getPath(clazz.getAnnotation(Path.class)); + String doc = getDescription(clazz.getAnnotation(Description.class)); + + rs.add(new SwaggerResource(rootPath.concat(path), doc)); + } + + return new SwaggerResources(baseURL, rs); + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + String baseURL = getBaseURL(req); + String requestPath = req.getPathInfo(); + + Object[] services = m_restServices.toArray(); + + if (requestPath == null || "".equals(requestPath) || "/".equals(requestPath)) { + SwaggerResources resources = createResourceListingFor(baseURL, req.getServletPath(), services); + + writeAsJSON(resp, resources); + } else { + boolean responseWritten = false; + for (Object s : services) { + Class clazz = s.getClass(); + + String rootPathValue = getPath(clazz.getAnnotation(Path.class)); + if (requestPath.startsWith(rootPathValue)) { + SwaggerAPI apiDocs = createDocumentationFor(baseURL, s); + + writeAsJSON(resp, apiDocs); + + responseWritten = true; + } + } + + if (!responseWritten) { + // Swagger-UI b0rks when returning anything other than a valid JSON response, + // so in case we didn't write anything, simply return an empty JSON string... + writeAsJSON(resp, ""); + } + } + } + + private String getBaseURL(HttpServletRequest request) { + int port = request.getServerPort(); + + String protocol = request.getHeader(HEADER_X_FORWARDED_PROTO); + if (protocol != null) { + if ("https".equals(protocol)) { + port = 443; + } + } else { + protocol = request.isSecure() ? "https" : "http"; + } + + return protocol + "://" + request.getServerName() + ":" + port; + } + + private void writeAsJSON(HttpServletResponse resp, Object object) throws IOException { + Gson gson = new Gson(); + resp.setContentType(MediaType.APPLICATION_JSON); + PrintWriter writer = resp.getWriter(); + try { + writer.append(gson.toJson(object)); + } finally { + writer.flush(); + writer.close(); + } + } + + private static class JaxRsMethodComparator implements Comparator { + @Override + public int compare(Method o1, Method o2) { + Path pa1 = o1.getAnnotation(Path.class); + String p1 = (pa1 != null) ? pa1.value() : ""; + + Path pa2 = o2.getAnnotation(Path.class); + String p2 = (pa2 != null) ? pa2.value() : ""; + + int result = p1.compareTo(p2); + if (result == 0) { + result = o1.getName().compareTo(o2.getName()); + } + + return result; + } + } +} diff --git a/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/SwaggerUtil.java b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/SwaggerUtil.java new file mode 100644 index 0000000000000..1f5d61a7b2c8c --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/SwaggerUtil.java @@ -0,0 +1,397 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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 + */ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.io.rest.docs.swagger; + +import static javax.ws.rs.HttpMethod.DELETE; +import static javax.ws.rs.HttpMethod.GET; +import static javax.ws.rs.HttpMethod.HEAD; +import static javax.ws.rs.HttpMethod.OPTIONS; +import static javax.ws.rs.HttpMethod.POST; +import static javax.ws.rs.HttpMethod.PUT; +import static org.openhab.io.rest.docs.swagger.Constants.BODY_PARAM; +import static org.openhab.io.rest.docs.swagger.Constants.FORM_PARAM; +import static org.openhab.io.rest.docs.swagger.Constants.HEADER_PARAM; +import static org.openhab.io.rest.docs.swagger.Constants.PATH_PARAM; +import static org.openhab.io.rest.docs.swagger.Constants.QUERY_PARAM; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.WildcardType; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.HEAD; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.OPTIONS; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; + +import org.openhab.io.rest.docs.Description; +import org.openhab.io.rest.docs.Notes; +import org.openhab.io.rest.docs.ResponseMessage; +import org.openhab.io.rest.docs.ResponseMessages; +import org.openhab.io.rest.docs.ReturnType; +import org.openhab.io.rest.docs.swagger.model.SwaggerContainerType; +import org.openhab.io.rest.docs.swagger.model.SwaggerDataType; +import org.openhab.io.rest.docs.swagger.model.SwaggerModel; +import org.openhab.io.rest.docs.swagger.model.SwaggerModelProperty; +import org.openhab.io.rest.docs.swagger.model.SwaggerModelType; +import org.openhab.io.rest.docs.swagger.model.SwaggerOperation; +import org.openhab.io.rest.docs.swagger.model.SwaggerParameter; +import org.openhab.io.rest.docs.swagger.model.SwaggerResponseMessage; + +final class SwaggerUtil { + + public static List documentOperations(SwaggerModel models, Method method) { + List ops = new ArrayList(); + + Annotation[] annotations = method.getAnnotations(); + if (annotationPresent(GET.class, annotations)) { + ops.add(createOperation(models, GET, method, annotations)); + } + if (annotationPresent(PUT.class, annotations)) { + ops.add(createOperation(models, PUT, method, annotations)); + } + if (annotationPresent(POST.class, annotations)) { + ops.add(createOperation(models, POST, method, annotations)); + } + if (annotationPresent(DELETE.class, annotations)) { + ops.add(createOperation(models, DELETE, method, annotations)); + } + if (annotationPresent(HEAD.class, annotations)) { + ops.add(createOperation(models, HEAD, method, annotations)); + } + if (annotationPresent(OPTIONS.class, annotations)) { + ops.add(createOperation(models, OPTIONS, method, annotations)); + } + + return ops; + } + + public static List documentParameters(SwaggerModel models, Method method) { + List ps = new ArrayList(); + + Annotation[][] parametersAnnotations = method.getParameterAnnotations(); + Class[] parameterTypes = method.getParameterTypes(); + for (int i = 0; i < parameterTypes.length; i++) { + Class paramType = parameterTypes[i]; + Annotation[] paramAnnotations = parametersAnnotations[i]; + + boolean consumed = false; + for (Annotation a : paramAnnotations) { + if (a instanceof PathParam) { + ps.add(createParameter(models, PATH_PARAM, ((PathParam) a).value(), paramType, paramAnnotations)); + consumed = true; + } else if (a instanceof QueryParam) { + ps.add(createParameter(models, QUERY_PARAM, ((QueryParam) a).value(), paramType, paramAnnotations)); + consumed = true; + } else if (a instanceof HeaderParam) { + ps.add(createParameter(models, HEADER_PARAM, ((HeaderParam) a).value(), paramType, paramAnnotations)); + consumed = true; + } else if (a instanceof FormParam) { + ps.add(createParameter(models, FORM_PARAM, ((FormParam) a).value(), paramType, paramAnnotations)); + consumed = true; + } + if (a instanceof Context) { + // No need to report these ones, they are automatically injected by JAX-RS... + consumed = true; + } + } + + if (!consumed) { + // Add all non-consumed parameters as body-parameters (most probably complex types that need to be supplied)... + ps.add(createParameter(models, BODY_PARAM, paramType.getSimpleName(), paramType, paramAnnotations)); + } + } + + return ps; + } + + public static String getDescription(Description ann) { + return (ann != null) ? ann.value() : null; + } + + public static String getPath(Path ann) { + if (ann == null) { + return ""; + } + String value = ann.value(); + if (!value.startsWith("/") && value.length() > 1) { + return "/".concat(value); + } + return value; + } + + protected static SwaggerModelType convertToSwaggerModel(SwaggerModel models, Class type) { + Map mp = new HashMap(); + List requiredFields = new ArrayList(); + // AMDATUWEB-24 - use not only field of given type, but also of all its superclasses... + String typeName = type.getName(); + while (type != null && !Object.class.equals(type)) { + Field[] fields = type.getDeclaredFields(); + for (Field f : fields) { + String name = f.getName(); + int modifiers = f.getModifiers(); + Class fieldType = f.getType(); + + if (mp.containsKey(name)) { + // TODO name shadowing is not supported yet... + continue; + } else if (Modifier.isStatic(modifiers) || fieldType.isSynthetic()) { + continue; + } + + Description description = f.getAnnotation(Description.class); + DefaultValue defaultValue = f.getAnnotation(DefaultValue.class); + + SwaggerDataType typeInfo = convertToSwaggerType(models, fieldType); + + SwaggerModelProperty smp; + if (fieldType.isEnum()) { + smp = new SwaggerModelProperty(typeInfo, getDescription(description), getValue(defaultValue), getEnumValues(fieldType)); + } else if (fieldType.isArray() || Collection.class.isAssignableFrom(fieldType)) { + Boolean uniqueItems = Set.class.isAssignableFrom(fieldType) ? Boolean.TRUE : null; + smp = new SwaggerModelProperty(typeInfo, getDescription(description), getValue(defaultValue), uniqueItems, getContainerType(models, f)); + } else { + smp = new SwaggerModelProperty(typeInfo, getDescription(description), getValue(defaultValue)); + } + + if (Boolean.TRUE.equals(smp.required)) { + requiredFields.add(name); + } + + mp.put(name, smp); + } + type = type.getSuperclass(); + } + return new SwaggerModelType(typeName, mp, requiredFields); + } + + protected static Class getReturnType(Method method) { + ReturnType annotation = method.getAnnotation(ReturnType.class); + if (annotation != null) { + return annotation.value(); + } + + return method.getReturnType(); + } + + /** + * @see https://github.com/wordnik/swagger-core/wiki/datatypes + */ + protected static SwaggerDataType convertToSwaggerType(SwaggerModel models, Class type) { + if (Void.TYPE.equals(type)) { + return new SwaggerDataType("void"); + } else if (Integer.TYPE.equals(type) || Integer.class.isAssignableFrom(type)) { + return new SwaggerDataType("integer", "int32"); + } else if (Long.TYPE.equals(type) || Long.class.isAssignableFrom(type)) { + return new SwaggerDataType("integer", "int64"); + } else if (Float.TYPE.equals(type) || Float.class.isAssignableFrom(type)) { + return new SwaggerDataType("number", "float"); + } else if (Double.TYPE.equals(type) || Double.class.isAssignableFrom(type)) { + return new SwaggerDataType("number", "double"); + } else if (Byte.TYPE.equals(type) || Byte.class.isAssignableFrom(type)) { + return new SwaggerDataType("string", "byte"); + } else if (Boolean.TYPE.equals(type) || Boolean.class.isAssignableFrom(type)) { + return new SwaggerDataType("boolean"); + } else if (Number.class.isAssignableFrom(type)) { + return new SwaggerDataType("number"); + } else if (String.class.equals(type)) { + return new SwaggerDataType("string"); + } else if (Date.class.equals(type)) { + return new SwaggerDataType("string", "date-time"); + } else if (type.isEnum()) { + return new SwaggerDataType("string"); + } else if (type.isArray() || Collection.class.isAssignableFrom(type)) { + return new SwaggerDataType("array"); + } else { + // it's a custom type, we need to create a model for it (if it does not already exist) + String typeName = type.getName(); + if (!models.containsKey(typeName)) { + // Reserve a spot for this type, avoids circular references to cause a StackOverflow, see AMDATUWEB-10... + models.put(typeName, null); + // Overwrite the item with the actual model definition... + models.put(typeName, convertToSwaggerModel(models, type)); + } + return new SwaggerDataType(type.getName()); + } + } + + protected static SwaggerParameter createParameter(SwaggerModel models, String paramType, String paramName, + Class type, Annotation[] annotations) { + String doc = getDescription(findAnnotation(Description.class, annotations)); + String _default = getValue(findAnnotation(DefaultValue.class, annotations)); + + SwaggerDataType typeInfo = convertToSwaggerType(models, type); + + if (type.isEnum()) { + return new SwaggerParameter(paramType, paramName, doc, typeInfo, _default, getEnumValues(type)); + } + + return new SwaggerParameter(paramType, paramName, doc, typeInfo, _default); + } + + private static boolean annotationPresent(Class type, Annotation[] annotations) { + for (Annotation ann : annotations) { + if (type.isInstance(ann)) { + return true; + } + } + return false; + } + + private static SwaggerOperation createOperation(SwaggerModel models, String httpMethod, Method method, Annotation[] annotations) { + String opName = method.getName(); + SwaggerDataType returnTypeInfo = convertToSwaggerType(models, getReturnType(method)); + + List params = documentParameters(models, method); + + ResponseMessages responseMessages = findAnnotation(ResponseMessages.class, annotations); + List rms = null; + if (responseMessages != null && responseMessages.value() != null) { + rms = new ArrayList(); + for (ResponseMessage responseMessage : responseMessages.value()) { + rms.add(new SwaggerResponseMessage(responseMessage.code(), responseMessage.message())); + } + } + + String doc = getDescription(findAnnotation(Description.class, annotations)); + List produces = getValues(findAnnotation(Produces.class, annotations)); + List consumes = getValues(findAnnotation(Consumes.class, annotations)); + String notes = getValue(findAnnotation(Notes.class, annotations)); + Boolean deprecated = findAnnotation(Deprecated.class, annotations) != null; + + return new SwaggerOperation(httpMethod, opName, returnTypeInfo, params, rms, produces, consumes, doc, notes, deprecated); + } + + private static T findAnnotation(Class type, Annotation[] annotations) { + for (Annotation ann : annotations) { + if (type.isInstance(ann)) { + return type.cast(ann); + } + } + return null; + } + + private static SwaggerContainerType getContainerType(SwaggerModel models, Field field) { + Class type = getContainerType(field.getGenericType()); + + String refType = Object.class.getName(); + if (type != null) { + refType = convertToSwaggerType(models, type).dataType; + } + return new SwaggerContainerType(refType); + } + + /** + * Magic to determine the actual type of a container. + * + * @param type the supposed container type, can be null. + * @return a container type, or null if the type could not be determined. + */ + private static Class getContainerType(Type type) { + if (type instanceof Class) { + Class clazz = (Class) type; + if (clazz.isArray()) { + return clazz.getComponentType(); + } else { + return clazz; + } + } else if (type instanceof GenericArrayType) { + Type compType = ((GenericArrayType) type).getGenericComponentType(); + return getContainerType(compType); + } else if (type instanceof ParameterizedType) { + ParameterizedType paramType = (ParameterizedType) type; + + Type[] actualTypeArguments = paramType.getActualTypeArguments(); + for (Type t : actualTypeArguments) { + Class ct = getContainerType(t); + if (ct != null) { + return ct; + } + } + } else if (type instanceof WildcardType) { + // Upper bound is stronger than lower, so return the this one, if defined... + Type[] upperBounds = ((WildcardType) type).getUpperBounds(); + for (Type upperBound : upperBounds) { + Class ubt = getContainerType(upperBound); + if (ubt != null) { + return ubt; + } + } + Type[] lowerBounds = ((WildcardType) type).getLowerBounds(); + for (Type lowerBound : lowerBounds) { + Class lbt = getContainerType(lowerBound); + if (lbt != null) { + return lbt; + } + } + } + + return null; + } + + private static List getEnumValues(Class type) { + List result = new ArrayList(); + for (Object constant : type.getEnumConstants()) { + result.add(constant.toString()); + } + return result; + } + + private static String getValue(DefaultValue ann) { + return (ann != null) ? ann.value() : null; + } + + private static String getValue(Notes ann) { + return (ann != null) ? ann.value() : null; + } + + private static List getValues(Consumes ann) { + return (ann != null) ? Arrays.asList(ann.value()) : null; + } + + private static List getValues(Produces ann) { + return (ann != null) ? Arrays.asList(ann.value()) : null; + } +} diff --git a/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerAPI.java b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerAPI.java new file mode 100644 index 0000000000000..8f2335e241b22 --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerAPI.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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 + */ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.io.rest.docs.swagger.model; + +import static org.openhab.io.rest.docs.swagger.Constants.DEFAULT_API_VERSION; +import static org.openhab.io.rest.docs.swagger.Constants.SWAGGER_API_VERSION; + +import java.util.List; + +/* Data Objects for JSON, as defined in the spec: https://github.com/wordnik/swagger-core/wiki */ +public class SwaggerAPI { + public final String apiVersion; + public final String swaggerVersion; + public final String basePath; + public final String resourcePath; + public final List apis; + public final SwaggerModel models; + + public SwaggerAPI(String basePath, String resourcePath, List apis, SwaggerModel models) { + this(DEFAULT_API_VERSION, basePath, resourcePath, apis, models); + } + + public SwaggerAPI(String apiVersion, String basePath, String resourcePath, List apis, + SwaggerModel models) { + this.apiVersion = apiVersion; + this.swaggerVersion = SWAGGER_API_VERSION; + + this.basePath = basePath; + this.resourcePath = resourcePath; + this.apis = apis; + this.models = models; + } +} \ No newline at end of file diff --git a/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerAPIPath.java b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerAPIPath.java new file mode 100644 index 0000000000000..1530e3235a571 --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerAPIPath.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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 + */ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.io.rest.docs.swagger.model; + +import java.util.List; + +/* Data Objects for JSON, as defined in the spec: https://github.com/wordnik/swagger-core/wiki */ +public class SwaggerAPIPath { + public final String path; + public final String description; + public final List operations; + + public SwaggerAPIPath(String path, String description, List operations) { + this.path = path; + this.description = description; + this.operations = operations; + } +} \ No newline at end of file diff --git a/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerContainerType.java b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerContainerType.java new file mode 100644 index 0000000000000..e988fa8a686b6 --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerContainerType.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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 + */ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.io.rest.docs.swagger.model; + +import com.google.gson.annotations.SerializedName; + +/* Data Objects for JSON, as defined in the spec: https://github.com/wordnik/swagger-core/wiki */ +public class SwaggerContainerType { + @SerializedName("$ref") + public final String refType; + + public SwaggerContainerType(String refType) { + this.refType = refType; + } +} diff --git a/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerDataType.java b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerDataType.java new file mode 100644 index 0000000000000..d5df438988566 --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerDataType.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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 + */ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.io.rest.docs.swagger.model; + +/** + * Pure fabricated type to hold the data type + format for return types and/or parameters. + */ +public class SwaggerDataType { + public final String dataType; + public final String dataFormat; + + public SwaggerDataType(String dataType) { + this(dataType, null); + } + + public SwaggerDataType(String dataType, String dataFormat) { + this.dataType = dataType; + this.dataFormat = dataFormat; + } +} diff --git a/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerModel.java b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerModel.java new file mode 100644 index 0000000000000..f1e82bd9b3a57 --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerModel.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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 + */ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.io.rest.docs.swagger.model; + +import java.util.HashMap; + +@SuppressWarnings("serial") +public class SwaggerModel extends HashMap { + +} \ No newline at end of file diff --git a/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerModelProperty.java b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerModelProperty.java new file mode 100644 index 0000000000000..6c0cad57a3f47 --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerModelProperty.java @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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 + */ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.io.rest.docs.swagger.model; + +import java.util.List; + +import com.google.gson.annotations.SerializedName; + +/* Data Objects for JSON, as defined in the spec: https://github.com/wordnik/swagger-core/wiki */ +public class SwaggerModelProperty { + public final String type; + public final String format; + public final String description; + public final String defaultValue; + @SerializedName("enum") + public final List enumValues; + public final Boolean uniqueItems; + public final Boolean required; + public final SwaggerContainerType items; + + public SwaggerModelProperty(SwaggerDataType typeInfo, String description, String defaultValue) { + this.type = typeInfo.dataType; + this.format = typeInfo.dataFormat; + this.description = description; + this.defaultValue = defaultValue; + this.enumValues = null; + this.uniqueItems = null; + this.items = null; + this.required = (defaultValue == null); + } + + public SwaggerModelProperty(SwaggerDataType typeInfo, String description, String defaultValue, List enumValues) { + this.type = typeInfo.dataType; + this.format = typeInfo.dataFormat; + this.description = description; + this.defaultValue = defaultValue; + this.enumValues = enumValues; + this.uniqueItems = null; + this.items = null; + this.required = (defaultValue == null); + } + + public SwaggerModelProperty(SwaggerDataType typeInfo, String description, String defaultValue, Boolean uniqueItems, SwaggerContainerType containerType) { + this.type = typeInfo.dataType; + this.format = typeInfo.dataFormat; + this.description = description; + this.defaultValue = defaultValue; + this.uniqueItems = uniqueItems; + this.items = containerType; + this.enumValues = null; + this.required = (defaultValue == null); + } +} \ No newline at end of file diff --git a/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerModelType.java b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerModelType.java new file mode 100644 index 0000000000000..30b63a8a8597d --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerModelType.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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 + */ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.io.rest.docs.swagger.model; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/* Data Objects for JSON, as defined in the spec: https://github.com/wordnik/swagger-core/wiki */ +public class SwaggerModelType { + public final String id; + public final Map properties; + public final List required; + + public SwaggerModelType(String id, Map properties) { + this(id, properties, Collections. emptyList()); + } + + public SwaggerModelType(String id, Map properties, List required) { + this.id = id; + this.properties = properties; + this.required = required; + } +} \ No newline at end of file diff --git a/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerOperation.java b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerOperation.java new file mode 100644 index 0000000000000..3d4729bde8a71 --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerOperation.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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 + */ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.io.rest.docs.swagger.model; + +import java.util.List; + +/* Data Objects for JSON, as defined in the spec: https://github.com/wordnik/swagger-core/wiki */ +public class SwaggerOperation { + public final String method; + public final String nickname; + public final String type; + public final String format; + public final List parameters; + public final List responseMessages; + public final List consumes; + public final List produces; + public final String summary; + public final String notes; + public final String deprecated; + + public SwaggerOperation(String httpMethod, String nickname, SwaggerDataType responseType, + List parameters, List responseMessages, List produces, List consumes, String summary, String notes, Boolean deprecated) { + this.method = httpMethod; + this.nickname = nickname; + this.type = responseType.dataType; + this.format = responseType.dataFormat; + this.parameters = parameters; + this.responseMessages = responseMessages; + this.consumes = consumes; + this.produces = produces; + this.summary = summary; + this.notes = notes; + this.deprecated = Boolean.toString(deprecated); + } +} \ No newline at end of file diff --git a/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerParameter.java b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerParameter.java new file mode 100644 index 0000000000000..c9643e33ac52e --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerParameter.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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 + */ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.io.rest.docs.swagger.model; + +import java.util.List; + +import com.google.gson.annotations.SerializedName; + +/* Data Objects for JSON, as defined in the spec: https://github.com/wordnik/swagger-core/wiki */ +public class SwaggerParameter { + public final String paramType; + public final String name; + public final String description; + public final String type; + public final String format; + @SerializedName("enum") + public final List enumValues; + public final Boolean required; + public final String defaultValue; + + public SwaggerParameter(String paramType, String name, String description, SwaggerDataType type, String defaultValue) { + this.paramType = paramType; + this.name = name; + this.description = description; + this.type = type.dataType; + this.format = type.dataFormat; + this.defaultValue = defaultValue; + this.enumValues = null; + this.required = (defaultValue == null); + } + + public SwaggerParameter(String paramType, String name, String description, SwaggerDataType type, String defaultValue, List enumValues) { + this.paramType = paramType; + this.name = name; + this.description = description; + this.type = type.dataType; + this.format = type.dataFormat; + this.enumValues = enumValues; + this.defaultValue = defaultValue; + this.required = (defaultValue == null); + } +} \ No newline at end of file diff --git a/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerResource.java b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerResource.java new file mode 100644 index 0000000000000..760240fee5f7f --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerResource.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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 + */ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.io.rest.docs.swagger.model; + +/* Data Objects for JSON, as defined in the spec: https://github.com/wordnik/swagger-core/wiki */ +public class SwaggerResource { + public final String path; + public final String description; + + public SwaggerResource(String path, String description) { + this.path = path; + this.description = description; + } +} \ No newline at end of file diff --git a/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerResources.java b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerResources.java new file mode 100644 index 0000000000000..76a1935e226f7 --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerResources.java @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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 + */ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.io.rest.docs.swagger.model; + +import static org.openhab.io.rest.docs.swagger.Constants.*; + +import java.util.List; + +/* Data Objects for JSON, as defined in the spec: https://github.com/wordnik/swagger-core/wiki */ +public class SwaggerResources { + public final String apiVersion; + public final String swaggerVersion; + public String basePath; + public List apis; + + public SwaggerResources(String basePath, List apis) { + this(DEFAULT_API_VERSION, basePath, apis); + } + + public SwaggerResources(String apiVersion, String basePath, List apis) { + this.apiVersion = apiVersion; + this.swaggerVersion = SWAGGER_API_VERSION; + + this.basePath = basePath; + this.apis = apis; + } +} \ No newline at end of file diff --git a/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerResponseMessage.java b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerResponseMessage.java new file mode 100644 index 0000000000000..4bd249a9f9198 --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/src/main/java/org/openhab/io/rest/docs/swagger/model/SwaggerResponseMessage.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others. + * + * 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 + */ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.io.rest.docs.swagger.model; + +/* Data Objects for JSON, as defined in the spec: https://github.com/wordnik/swagger-core/wiki */ +public class SwaggerResponseMessage { + public final int code; + public final String message; + + public SwaggerResponseMessage(int code, String message) { + this.code = code; + this.message = message; + } +} \ No newline at end of file diff --git a/bundles/io/org.openhab.io.rest.docs/swagger/css/openhab.css b/bundles/io/org.openhab.io.rest.docs/swagger/css/openhab.css new file mode 100644 index 0000000000000..d5860deee27f1 --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/swagger/css/openhab.css @@ -0,0 +1,15 @@ +.swagger-section .icon-btn { + cursor: pointer; +} + +.swagger-section #header { + background-color: #ff6600; +} + +.swagger-section #header a#logo { + padding-left: 124px; +} + +.swagger-section #header form#api_selector .input a#explore { + background-color: #d2121c; +} \ No newline at end of file diff --git a/bundles/io/org.openhab.io.rest.docs/swagger/css/reset.css b/bundles/io/org.openhab.io.rest.docs/swagger/css/reset.css new file mode 100644 index 0000000000000..b2b078943c451 --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/swagger/css/reset.css @@ -0,0 +1,125 @@ +/* http://meyerweb.com/eric/tools/css/reset/ v2.0 | 20110126 */ +html, +body, +div, +span, +applet, +object, +iframe, +h1, +h2, +h3, +h4, +h5, +h6, +p, +blockquote, +pre, +a, +abbr, +acronym, +address, +big, +cite, +code, +del, +dfn, +em, +img, +ins, +kbd, +q, +s, +samp, +small, +strike, +strong, +sub, +sup, +tt, +var, +b, +u, +i, +center, +dl, +dt, +dd, +ol, +ul, +li, +fieldset, +form, +label, +legend, +table, +caption, +tbody, +tfoot, +thead, +tr, +th, +td, +article, +aside, +canvas, +details, +embed, +figure, +figcaption, +footer, +header, +hgroup, +menu, +nav, +output, +ruby, +section, +summary, +time, +mark, +audio, +video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +menu, +nav, +section { + display: block; +} +body { + line-height: 1; +} +ol, +ul { + list-style: none; +} +blockquote, +q { + quotes: none; +} +blockquote:before, +blockquote:after, +q:before, +q:after { + content: ''; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} diff --git a/bundles/io/org.openhab.io.rest.docs/swagger/css/screen.css b/bundles/io/org.openhab.io.rest.docs/swagger/css/screen.css new file mode 100644 index 0000000000000..f2148836bd8e9 --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/swagger/css/screen.css @@ -0,0 +1,1221 @@ +/* Original style from softwaremaniacs.org (c) Ivan Sagalaev */ +.swagger-section pre code { + display: block; + padding: 0.5em; + background: #F0F0F0; +} +.swagger-section pre code, +.swagger-section pre .subst, +.swagger-section pre .tag .title, +.swagger-section pre .lisp .title, +.swagger-section pre .clojure .built_in, +.swagger-section pre .nginx .title { + color: black; +} +.swagger-section pre .string, +.swagger-section pre .title, +.swagger-section pre .constant, +.swagger-section pre .parent, +.swagger-section pre .tag .value, +.swagger-section pre .rules .value, +.swagger-section pre .rules .value .number, +.swagger-section pre .preprocessor, +.swagger-section pre .ruby .symbol, +.swagger-section pre .ruby .symbol .string, +.swagger-section pre .aggregate, +.swagger-section pre .template_tag, +.swagger-section pre .django .variable, +.swagger-section pre .smalltalk .class, +.swagger-section pre .addition, +.swagger-section pre .flow, +.swagger-section pre .stream, +.swagger-section pre .bash .variable, +.swagger-section pre .apache .tag, +.swagger-section pre .apache .cbracket, +.swagger-section pre .tex .command, +.swagger-section pre .tex .special, +.swagger-section pre .erlang_repl .function_or_atom, +.swagger-section pre .markdown .header { + color: #800; +} +.swagger-section pre .comment, +.swagger-section pre .annotation, +.swagger-section pre .template_comment, +.swagger-section pre .diff .header, +.swagger-section pre .chunk, +.swagger-section pre .markdown .blockquote { + color: #888; +} +.swagger-section pre .number, +.swagger-section pre .date, +.swagger-section pre .regexp, +.swagger-section pre .literal, +.swagger-section pre .smalltalk .symbol, +.swagger-section pre .smalltalk .char, +.swagger-section pre .go .constant, +.swagger-section pre .change, +.swagger-section pre .markdown .bullet, +.swagger-section pre .markdown .link_url { + color: #080; +} +.swagger-section pre .label, +.swagger-section pre .javadoc, +.swagger-section pre .ruby .string, +.swagger-section pre .decorator, +.swagger-section pre .filter .argument, +.swagger-section pre .localvars, +.swagger-section pre .array, +.swagger-section pre .attr_selector, +.swagger-section pre .important, +.swagger-section pre .pseudo, +.swagger-section pre .pi, +.swagger-section pre .doctype, +.swagger-section pre .deletion, +.swagger-section pre .envvar, +.swagger-section pre .shebang, +.swagger-section pre .apache .sqbracket, +.swagger-section pre .nginx .built_in, +.swagger-section pre .tex .formula, +.swagger-section pre .erlang_repl .reserved, +.swagger-section pre .prompt, +.swagger-section pre .markdown .link_label, +.swagger-section pre .vhdl .attribute, +.swagger-section pre .clojure .attribute, +.swagger-section pre .coffeescript .property { + color: #8888ff; +} +.swagger-section pre .keyword, +.swagger-section pre .id, +.swagger-section pre .phpdoc, +.swagger-section pre .title, +.swagger-section pre .built_in, +.swagger-section pre .aggregate, +.swagger-section pre .css .tag, +.swagger-section pre .javadoctag, +.swagger-section pre .phpdoc, +.swagger-section pre .yardoctag, +.swagger-section pre .smalltalk .class, +.swagger-section pre .winutils, +.swagger-section pre .bash .variable, +.swagger-section pre .apache .tag, +.swagger-section pre .go .typename, +.swagger-section pre .tex .command, +.swagger-section pre .markdown .strong, +.swagger-section pre .request, +.swagger-section pre .status { + font-weight: bold; +} +.swagger-section pre .markdown .emphasis { + font-style: italic; +} +.swagger-section pre .nginx .built_in { + font-weight: normal; +} +.swagger-section pre .coffeescript .javascript, +.swagger-section pre .javascript .xml, +.swagger-section pre .tex .formula, +.swagger-section pre .xml .javascript, +.swagger-section pre .xml .vbscript, +.swagger-section pre .xml .css, +.swagger-section pre .xml .cdata { + opacity: 0.5; +} +.swagger-section .swagger-ui-wrap { + line-height: 1; + font-family: "Droid Sans", sans-serif; + max-width: 960px; + margin-left: auto; + margin-right: auto; +} +.swagger-section .swagger-ui-wrap b, +.swagger-section .swagger-ui-wrap strong { + font-family: "Droid Sans", sans-serif; + font-weight: bold; +} +.swagger-section .swagger-ui-wrap q, +.swagger-section .swagger-ui-wrap blockquote { + quotes: none; +} +.swagger-section .swagger-ui-wrap p { + line-height: 1.4em; + padding: 0 0 10px; + color: #333333; +} +.swagger-section .swagger-ui-wrap q:before, +.swagger-section .swagger-ui-wrap q:after, +.swagger-section .swagger-ui-wrap blockquote:before, +.swagger-section .swagger-ui-wrap blockquote:after { + content: none; +} +.swagger-section .swagger-ui-wrap .heading_with_menu h1, +.swagger-section .swagger-ui-wrap .heading_with_menu h2, +.swagger-section .swagger-ui-wrap .heading_with_menu h3, +.swagger-section .swagger-ui-wrap .heading_with_menu h4, +.swagger-section .swagger-ui-wrap .heading_with_menu h5, +.swagger-section .swagger-ui-wrap .heading_with_menu h6 { + display: block; + clear: none; + float: left; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; + width: 60%; +} +.swagger-section .swagger-ui-wrap table { + border-collapse: collapse; + border-spacing: 0; +} +.swagger-section .swagger-ui-wrap table thead tr th { + padding: 5px; + font-size: 0.9em; + color: #666666; + border-bottom: 1px solid #999999; +} +.swagger-section .swagger-ui-wrap table tbody tr:last-child td { + border-bottom: none; +} +.swagger-section .swagger-ui-wrap table tbody tr.offset { + background-color: #f0f0f0; +} +.swagger-section .swagger-ui-wrap table tbody tr td { + padding: 6px; + font-size: 0.9em; + border-bottom: 1px solid #cccccc; + vertical-align: top; + line-height: 1.3em; +} +.swagger-section .swagger-ui-wrap ol { + margin: 0px 0 10px; + padding: 0 0 0 18px; + list-style-type: decimal; +} +.swagger-section .swagger-ui-wrap ol li { + padding: 5px 0px; + font-size: 0.9em; + color: #333333; +} +.swagger-section .swagger-ui-wrap ol, +.swagger-section .swagger-ui-wrap ul { + list-style: none; +} +.swagger-section .swagger-ui-wrap h1 a, +.swagger-section .swagger-ui-wrap h2 a, +.swagger-section .swagger-ui-wrap h3 a, +.swagger-section .swagger-ui-wrap h4 a, +.swagger-section .swagger-ui-wrap h5 a, +.swagger-section .swagger-ui-wrap h6 a { + text-decoration: none; +} +.swagger-section .swagger-ui-wrap h1 a:hover, +.swagger-section .swagger-ui-wrap h2 a:hover, +.swagger-section .swagger-ui-wrap h3 a:hover, +.swagger-section .swagger-ui-wrap h4 a:hover, +.swagger-section .swagger-ui-wrap h5 a:hover, +.swagger-section .swagger-ui-wrap h6 a:hover { + text-decoration: underline; +} +.swagger-section .swagger-ui-wrap h1 span.divider, +.swagger-section .swagger-ui-wrap h2 span.divider, +.swagger-section .swagger-ui-wrap h3 span.divider, +.swagger-section .swagger-ui-wrap h4 span.divider, +.swagger-section .swagger-ui-wrap h5 span.divider, +.swagger-section .swagger-ui-wrap h6 span.divider { + color: #aaaaaa; +} +.swagger-section .swagger-ui-wrap a { + color: #547f00; +} +.swagger-section .swagger-ui-wrap a img { + border: none; +} +.swagger-section .swagger-ui-wrap article, +.swagger-section .swagger-ui-wrap aside, +.swagger-section .swagger-ui-wrap details, +.swagger-section .swagger-ui-wrap figcaption, +.swagger-section .swagger-ui-wrap figure, +.swagger-section .swagger-ui-wrap footer, +.swagger-section .swagger-ui-wrap header, +.swagger-section .swagger-ui-wrap hgroup, +.swagger-section .swagger-ui-wrap menu, +.swagger-section .swagger-ui-wrap nav, +.swagger-section .swagger-ui-wrap section, +.swagger-section .swagger-ui-wrap summary { + display: block; +} +.swagger-section .swagger-ui-wrap pre { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + background-color: #fcf6db; + border: 1px solid #e5e0c6; + padding: 10px; +} +.swagger-section .swagger-ui-wrap pre code { + line-height: 1.6em; + background: none; +} +.swagger-section .swagger-ui-wrap .content > .content-type > div > label { + clear: both; + display: block; + color: #0F6AB4; + font-size: 1.1em; + margin: 0; + padding: 15px 0 5px; +} +.swagger-section .swagger-ui-wrap .content pre { + font-size: 12px; + margin-top: 5px; + padding: 5px; +} +.swagger-section .swagger-ui-wrap .icon-btn { + cursor: pointer; +} +.swagger-section .swagger-ui-wrap .info_title { + padding-bottom: 10px; + font-weight: bold; + font-size: 25px; +} +.swagger-section .swagger-ui-wrap p.big, +.swagger-section .swagger-ui-wrap div.big p { + font-size: 1em; + margin-bottom: 10px; +} +.swagger-section .swagger-ui-wrap form.fullwidth ol li.string input, +.swagger-section .swagger-ui-wrap form.fullwidth ol li.url input, +.swagger-section .swagger-ui-wrap form.fullwidth ol li.text textarea, +.swagger-section .swagger-ui-wrap form.fullwidth ol li.numeric input { + width: 500px !important; +} +.swagger-section .swagger-ui-wrap .info_license { + padding-bottom: 5px; +} +.swagger-section .swagger-ui-wrap .info_tos { + padding-bottom: 5px; +} +.swagger-section .swagger-ui-wrap .message-fail { + color: #cc0000; +} +.swagger-section .swagger-ui-wrap .info_contact { + padding-bottom: 5px; +} +.swagger-section .swagger-ui-wrap .info_description { + padding-bottom: 10px; + font-size: 15px; +} +.swagger-section .swagger-ui-wrap .markdown ol li, +.swagger-section .swagger-ui-wrap .markdown ul li { + padding: 3px 0px; + line-height: 1.4em; + color: #333333; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.string input, +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.url input, +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.numeric input { + display: block; + padding: 4px; + width: auto; + clear: both; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.string input.title, +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.url input.title, +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.numeric input.title { + font-size: 1.3em; +} +.swagger-section .swagger-ui-wrap table.fullwidth { + width: 100%; +} +.swagger-section .swagger-ui-wrap .model-signature { + font-family: "Droid Sans", sans-serif; + font-size: 1em; + line-height: 1.5em; +} +.swagger-section .swagger-ui-wrap .model-signature .signature-nav a { + text-decoration: none; + color: #AAA; +} +.swagger-section .swagger-ui-wrap .model-signature .signature-nav a:hover { + text-decoration: underline; + color: black; +} +.swagger-section .swagger-ui-wrap .model-signature .signature-nav .selected { + color: black; + text-decoration: none; +} +.swagger-section .swagger-ui-wrap .model-signature .propType { + color: #5555aa; +} +.swagger-section .swagger-ui-wrap .model-signature pre:hover { + background-color: #ffffdd; +} +.swagger-section .swagger-ui-wrap .model-signature pre { + font-size: .85em; + line-height: 1.2em; + overflow: auto; + max-height: 200px; + cursor: pointer; +} +.swagger-section .swagger-ui-wrap .model-signature ul.signature-nav { + display: block; + margin: 0; + padding: 0; +} +.swagger-section .swagger-ui-wrap .model-signature ul.signature-nav li:last-child { + padding-right: 0; + border-right: none; +} +.swagger-section .swagger-ui-wrap .model-signature ul.signature-nav li { + float: left; + margin: 0 5px 5px 0; + padding: 2px 5px 2px 0; + border-right: 1px solid #ddd; +} +.swagger-section .swagger-ui-wrap .model-signature .propOpt { + color: #555; +} +.swagger-section .swagger-ui-wrap .model-signature .snippet small { + font-size: 0.75em; +} +.swagger-section .swagger-ui-wrap .model-signature .propOptKey { + font-style: italic; +} +.swagger-section .swagger-ui-wrap .model-signature .description .strong { + font-weight: bold; + color: #000; + font-size: .9em; +} +.swagger-section .swagger-ui-wrap .model-signature .description div { + font-size: 0.9em; + line-height: 1.5em; + margin-left: 1em; +} +.swagger-section .swagger-ui-wrap .model-signature .description .stronger { + font-weight: bold; + color: #000; +} +.swagger-section .swagger-ui-wrap .model-signature .propName { + font-weight: bold; +} +.swagger-section .swagger-ui-wrap .model-signature .signature-container { + clear: both; +} +.swagger-section .swagger-ui-wrap .body-textarea { + width: 300px; + height: 100px; + border: 1px solid #aaa; +} +.swagger-section .swagger-ui-wrap .markdown p code, +.swagger-section .swagger-ui-wrap .markdown li code { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + background-color: #f0f0f0; + color: black; + padding: 1px 3px; +} +.swagger-section .swagger-ui-wrap .required { + font-weight: bold; +} +.swagger-section .swagger-ui-wrap input.parameter { + width: 300px; + border: 1px solid #aaa; +} +.swagger-section .swagger-ui-wrap h1 { + color: black; + font-size: 1.5em; + line-height: 1.3em; + padding: 10px 0 10px 0; + font-family: "Droid Sans", sans-serif; + font-weight: bold; +} +.swagger-section .swagger-ui-wrap .heading_with_menu { + float: none; + clear: both; + overflow: hidden; + display: block; +} +.swagger-section .swagger-ui-wrap .heading_with_menu ul { + display: block; + clear: none; + float: right; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; + margin-top: 10px; +} +.swagger-section .swagger-ui-wrap h2 { + color: black; + font-size: 1.3em; + padding: 10px 0 10px 0; +} +.swagger-section .swagger-ui-wrap h2 a { + color: black; +} +.swagger-section .swagger-ui-wrap h2 span.sub { + font-size: 0.7em; + color: #999999; + font-style: italic; +} +.swagger-section .swagger-ui-wrap h2 span.sub a { + color: #777777; +} +.swagger-section .swagger-ui-wrap span.weak { + color: #666666; +} +.swagger-section .swagger-ui-wrap .message-success { + color: #89BF04; +} +.swagger-section .swagger-ui-wrap caption, +.swagger-section .swagger-ui-wrap th, +.swagger-section .swagger-ui-wrap td { + text-align: left; + font-weight: normal; + vertical-align: middle; +} +.swagger-section .swagger-ui-wrap .code { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.text textarea { + font-family: "Droid Sans", sans-serif; + height: 250px; + padding: 4px; + display: block; + clear: both; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.select select { + display: block; + clear: both; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean { + float: none; + clear: both; + overflow: hidden; + display: block; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean label { + display: block; + float: left; + clear: none; + margin: 0; + padding: 0; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean input { + display: block; + float: left; + clear: none; + margin: 0 5px 0 0; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.required label { + color: black; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li label { + display: block; + clear: both; + width: auto; + padding: 0 0 3px; + color: #666666; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li label abbr { + padding-left: 3px; + color: #888888; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li p.inline-hints { + margin-left: 0; + font-style: italic; + font-size: 0.9em; + margin: 0; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.buttons { + margin: 0; + padding: 0; +} +.swagger-section .swagger-ui-wrap span.blank, +.swagger-section .swagger-ui-wrap span.empty { + color: #888888; + font-style: italic; +} +.swagger-section .swagger-ui-wrap .markdown h3 { + color: #547f00; +} +.swagger-section .swagger-ui-wrap .markdown h4 { + color: #666666; +} +.swagger-section .swagger-ui-wrap .markdown pre { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + background-color: #fcf6db; + border: 1px solid #e5e0c6; + padding: 10px; + margin: 0 0 10px 0; +} +.swagger-section .swagger-ui-wrap .markdown pre code { + line-height: 1.6em; +} +.swagger-section .swagger-ui-wrap div.gist { + margin: 20px 0 25px 0 !important; +} +.swagger-section .swagger-ui-wrap ul#resources { + font-family: "Droid Sans", sans-serif; + font-size: 0.9em; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource { + border-bottom: 1px solid #dddddd; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource:hover div.heading h2 a, +.swagger-section .swagger-ui-wrap ul#resources li.resource.active div.heading h2 a { + color: black; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource:hover div.heading ul.options li a, +.swagger-section .swagger-ui-wrap ul#resources li.resource.active div.heading ul.options li a { + color: #555555; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource:last-child { + border-bottom: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading { + border: 1px solid transparent; + float: none; + clear: both; + overflow: hidden; + display: block; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options { + overflow: hidden; + padding: 0; + display: block; + clear: none; + float: right; + margin: 14px 10px 0 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li { + float: left; + clear: none; + margin: 0; + padding: 2px 10px; + border-right: 1px solid #dddddd; + color: #666666; + font-size: 0.9em; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a { + color: #aaaaaa; + text-decoration: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:hover { + text-decoration: underline; + color: black; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:hover, +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:active, +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a.active { + text-decoration: underline; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li:first-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li.first { + padding-left: 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li.last { + padding-right: 0; + border-right: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options:first-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options.first { + padding-left: 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 { + color: #999999; + padding-left: 0; + display: block; + clear: none; + float: left; + font-family: "Droid Sans", sans-serif; + font-weight: bold; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a { + color: #999999; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a:hover { + color: black; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation { + float: none; + clear: both; + overflow: hidden; + display: block; + margin: 0 0 10px; + padding: 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading { + float: none; + clear: both; + overflow: hidden; + display: block; + margin: 0; + padding: 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 { + display: block; + clear: none; + float: left; + width: auto; + margin: 0; + padding: 0; + line-height: 1.1em; + color: black; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path { + padding-left: 10px; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path a { + color: black; + text-decoration: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path a:hover { + text-decoration: underline; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.http_method a { + text-transform: uppercase; + text-decoration: none; + color: white; + display: inline-block; + width: 50px; + font-size: 0.7em; + text-align: center; + padding: 7px 0 4px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + -o-border-radius: 2px; + -ms-border-radius: 2px; + -khtml-border-radius: 2px; + border-radius: 2px; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span { + margin: 0; + padding: 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options { + overflow: hidden; + padding: 0; + display: block; + clear: none; + float: right; + margin: 6px 10px 0 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li { + float: left; + clear: none; + margin: 0; + padding: 2px 10px; + font-size: 0.9em; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li a { + text-decoration: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li.access { + color: black; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content { + border-top: none; + padding: 10px; + -moz-border-radius-bottomleft: 6px; + -webkit-border-bottom-left-radius: 6px; + -o-border-bottom-left-radius: 6px; + -ms-border-bottom-left-radius: 6px; + -khtml-border-bottom-left-radius: 6px; + border-bottom-left-radius: 6px; + -moz-border-radius-bottomright: 6px; + -webkit-border-bottom-right-radius: 6px; + -o-border-bottom-right-radius: 6px; + -ms-border-bottom-right-radius: 6px; + -khtml-border-bottom-right-radius: 6px; + border-bottom-right-radius: 6px; + margin: 0 0 20px; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content h4 { + font-size: 1.1em; + margin: 0; + padding: 15px 0 5px; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header { + float: none; + clear: both; + overflow: hidden; + display: block; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header a { + padding: 4px 0 0 10px; + display: inline-block; + font-size: 0.9em; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header img { + display: block; + clear: none; + float: right; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header input.submit { + display: block; + clear: none; + float: left; + padding: 6px 8px; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content form input[type='text'].error { + outline: 2px solid black; + outline-color: #cc0000; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.response div.block pre { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + padding: 10px; + font-size: 0.9em; + max-height: 400px; + overflow-y: auto; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading { + background-color: #f9f2e9; + border: 1px solid #f0e0ca; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading h3 span.http_method a { + background-color: #c5862b; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #f0e0ca; + color: #c5862b; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li a { + color: #c5862b; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content { + background-color: #faf5ee; + border: 1px solid #f0e0ca; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content h4 { + color: #c5862b; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content div.sandbox_header a { + color: #dcb67f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading { + background-color: #fcffcd; + border: 1px solid black; + border-color: #ffd20f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading h3 span.http_method a { + text-transform: uppercase; + background-color: #ffd20f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #ffd20f; + color: #ffd20f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li a { + color: #ffd20f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content { + background-color: #fcffcd; + border: 1px solid black; + border-color: #ffd20f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content h4 { + color: #ffd20f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content div.sandbox_header a { + color: #6fc992; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading { + background-color: #f5e8e8; + border: 1px solid #e8c6c7; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading h3 span.http_method a { + text-transform: uppercase; + background-color: #a41e22; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #e8c6c7; + color: #a41e22; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li a { + color: #a41e22; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content { + background-color: #f7eded; + border: 1px solid #e8c6c7; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content h4 { + color: #a41e22; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content div.sandbox_header a { + color: #c8787a; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading { + background-color: #e7f6ec; + border: 1px solid #c3e8d1; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading h3 span.http_method a { + background-color: #10a54a; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #c3e8d1; + color: #10a54a; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li a { + color: #10a54a; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content { + background-color: #ebf7f0; + border: 1px solid #c3e8d1; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content h4 { + color: #10a54a; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content div.sandbox_header a { + color: #6fc992; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading { + background-color: #FCE9E3; + border: 1px solid #F5D5C3; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading h3 span.http_method a { + background-color: #D38042; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #f0cecb; + color: #D38042; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li a { + color: #D38042; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content { + background-color: #faf0ef; + border: 1px solid #f0cecb; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content h4 { + color: #D38042; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content div.sandbox_header a { + color: #dcb67f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading { + background-color: #e7f0f7; + border: 1px solid #c3d9ec; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading h3 span.http_method a { + background-color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #c3d9ec; + color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li a { + color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content { + background-color: #ebf3f9; + border: 1px solid #c3d9ec; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content h4 { + color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content div.sandbox_header a { + color: #6fa5d2; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading { + background-color: #e7f0f7; + border: 1px solid #c3d9ec; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading h3 span.http_method a { + background-color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #c3d9ec; + color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading ul.options li a { + color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.content { + background-color: #ebf3f9; + border: 1px solid #c3d9ec; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.content h4 { + color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.content div.sandbox_header a { + color: #6fa5d2; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content { + border-top: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li.last, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li.last, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li.last, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li.last, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li.last, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li.last { + padding-right: 0; + border-right: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a:hover, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a:active, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a.active { + text-decoration: underline; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li:first-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li.first { + padding-left: 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations:first-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations.first { + padding-left: 0; +} +.swagger-section .swagger-ui-wrap p#colophon { + margin: 0 15px 40px 15px; + padding: 10px 0; + font-size: 0.8em; + border-top: 1px solid #dddddd; + font-family: "Droid Sans", sans-serif; + color: #999999; + font-style: italic; +} +.swagger-section .swagger-ui-wrap p#colophon a { + text-decoration: none; + color: #547f00; +} +.swagger-section .swagger-ui-wrap h3 { + color: black; + font-size: 1.1em; + padding: 10px 0 10px 0; +} +.swagger-section .swagger-ui-wrap .markdown ol, +.swagger-section .swagger-ui-wrap .markdown ul { + font-family: "Droid Sans", sans-serif; + margin: 5px 0 10px; + padding: 0 0 0 18px; + list-style-type: disc; +} +.swagger-section .swagger-ui-wrap form.form_box { + background-color: #ebf3f9; + border: 1px solid #c3d9ec; + padding: 10px; +} +.swagger-section .swagger-ui-wrap form.form_box label { + color: #0f6ab4 !important; +} +.swagger-section .swagger-ui-wrap form.form_box input[type=submit] { + display: block; + padding: 10px; +} +.swagger-section .swagger-ui-wrap form.form_box p.weak { + font-size: 0.8em; +} +.swagger-section .swagger-ui-wrap form.form_box p { + font-size: 0.9em; + padding: 0 0 15px; + color: #7e7b6d; +} +.swagger-section .swagger-ui-wrap form.form_box p a { + color: #646257; +} +.swagger-section .swagger-ui-wrap form.form_box p strong { + color: black; +} +.swagger-section .title { + font-style: bold; +} +.swagger-section .secondary_form { + display: none; +} +.swagger-section .main_image { + display: block; + margin-left: auto; + margin-right: auto; +} +.swagger-section .oauth_body { + margin-left: 100px; + margin-right: 100px; +} +.swagger-section .oauth_submit { + text-align: center; +} +.swagger-section .api-popup-dialog { + z-index: 10000; + position: absolute; + width: 500px; + background: #FFF; + padding: 20px; + border: 1px solid #ccc; + border-radius: 5px; + display: none; + font-size: 13px; + color: #777; +} +.swagger-section .api-popup-dialog .api-popup-title { + font-size: 24px; + padding: 10px 0; +} +.swagger-section .api-popup-dialog .api-popup-title { + font-size: 24px; + padding: 10px 0; +} +.swagger-section .api-popup-dialog p.error-msg { + padding-left: 5px; + padding-bottom: 5px; +} +.swagger-section .api-popup-dialog button.api-popup-authbtn { + height: 30px; +} +.swagger-section .api-popup-dialog button.api-popup-cancel { + height: 30px; +} +.swagger-section .api-popup-scopes { + padding: 10px 20px; +} +.swagger-section .api-popup-scopes li { + padding: 5px 0; + line-height: 20px; +} +.swagger-section .api-popup-scopes .api-scope-desc { + padding-left: 20px; + font-style: italic; +} +.swagger-section .api-popup-scopes li input { + position: relative; + top: 2px; +} +.swagger-section .api-popup-actions { + padding-top: 10px; +} +.swagger-section .access { + float: right; +} +.swagger-section .auth { + float: right; +} +.swagger-section #api_information_panel { + position: absolute; + background: #FFF; + border: 1px solid #ccc; + border-radius: 5px; + display: none; + font-size: 13px; + max-width: 300px; + line-height: 30px; + color: black; + padding: 5px; +} +.swagger-section #api_information_panel p .api-msg-enabled { + color: green; +} +.swagger-section #api_information_panel p .api-msg-disabled { + color: red; +} +.swagger-section .api-ic { + height: 18px; + vertical-align: middle; + display: inline-block; + background: url(../images/explorer_icons.png) no-repeat; +} +.swagger-section .ic-info { + background-position: 0 0; + width: 18px; + margin-top: -7px; + margin-left: 4px; +} +.swagger-section .ic-warning { + background-position: -60px 0; + width: 18px; + margin-top: -7px; + margin-left: 4px; +} +.swagger-section .ic-error { + background-position: -30px 0; + width: 18px; + margin-top: -7px; + margin-left: 4px; +} +.swagger-section .ic-off { + background-position: -90px 0; + width: 58px; + margin-top: -4px; + cursor: pointer; +} +.swagger-section .ic-on { + background-position: -160px 0; + width: 58px; + margin-top: -4px; + cursor: pointer; +} +.swagger-section #header { + background-color: #89bf04; + padding: 14px; +} +.swagger-section #header a#logo { + font-size: 1.5em; + font-weight: bold; + text-decoration: none; + background: transparent url(../images/logo_small.png) no-repeat left center; + padding: 20px 0 20px 40px; + color: white; +} +.swagger-section #header form#api_selector { + display: block; + clear: none; + float: right; +} +.swagger-section #header form#api_selector .input { + display: block; + clear: none; + float: left; + margin: 0 10px 0 0; +} +.swagger-section #header form#api_selector .input input#input_apiKey { + width: 200px; +} +.swagger-section #header form#api_selector .input input#input_baseUrl { + width: 400px; +} +.swagger-section #header form#api_selector .input a#explore { + display: block; + text-decoration: none; + font-weight: bold; + padding: 6px 8px; + font-size: 0.9em; + color: white; + background-color: #547f00; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + -o-border-radius: 4px; + -ms-border-radius: 4px; + -khtml-border-radius: 4px; + border-radius: 4px; +} +.swagger-section #header form#api_selector .input a#explore:hover { + background-color: #547f00; +} +.swagger-section #header form#api_selector .input input { + font-size: 0.9em; + padding: 3px; + margin: 0; +} +.swagger-section #content_message { + margin: 10px 15px; + font-style: italic; + color: #999999; +} +.swagger-section #message-bar { + min-height: 30px; + text-align: center; + padding-top: 10px; +} diff --git a/bundles/io/org.openhab.io.rest.docs/swagger/images/logo_small.png b/bundles/io/org.openhab.io.rest.docs/swagger/images/logo_small.png new file mode 100644 index 0000000000000..9629a19088e81 Binary files /dev/null and b/bundles/io/org.openhab.io.rest.docs/swagger/images/logo_small.png differ diff --git a/bundles/io/org.openhab.io.rest.docs/swagger/images/throbber.gif b/bundles/io/org.openhab.io.rest.docs/swagger/images/throbber.gif new file mode 100644 index 0000000000000..06393889242fb Binary files /dev/null and b/bundles/io/org.openhab.io.rest.docs/swagger/images/throbber.gif differ diff --git a/bundles/io/org.openhab.io.rest.docs/swagger/index.html b/bundles/io/org.openhab.io.rest.docs/swagger/index.html new file mode 100644 index 0000000000000..5807c65c824ca --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/swagger/index.html @@ -0,0 +1,83 @@ + + + + openHAB REST API Documentation + + + + + + + + + + + + + + + + + + + + + + + + +
 
+
+ + diff --git a/bundles/io/org.openhab.io.rest.docs/swagger/lib/backbone-min.js b/bundles/io/org.openhab.io.rest.docs/swagger/lib/backbone-min.js new file mode 100644 index 0000000000000..c1c0d4fff28ff --- /dev/null +++ b/bundles/io/org.openhab.io.rest.docs/swagger/lib/backbone-min.js @@ -0,0 +1,38 @@ +// Backbone.js 0.9.2 + +// (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc. +// Backbone may be freely distributed under the MIT license. +// For all details and documentation: +// http://backbonejs.org +(function(){var l=this,y=l.Backbone,z=Array.prototype.slice,A=Array.prototype.splice,g;g="undefined"!==typeof exports?exports:l.Backbone={};g.VERSION="0.9.2";var f=l._;!f&&"undefined"!==typeof require&&(f=require("underscore"));var i=l.jQuery||l.Zepto||l.ender;g.setDomLibrary=function(a){i=a};g.noConflict=function(){l.Backbone=y;return this};g.emulateHTTP=!1;g.emulateJSON=!1;var p=/\s+/,k=g.Events={on:function(a,b,c){var d,e,f,g,j;if(!b)return this;a=a.split(p);for(d=this._callbacks||(this._callbacks= +{});e=a.shift();)f=(j=d[e])?j.tail:{},f.next=g={},f.context=c,f.callback=b,d[e]={tail:g,next:j?j.next:f};return this},off:function(a,b,c){var d,e,h,g,j,q;if(e=this._callbacks){if(!a&&!b&&!c)return delete this._callbacks,this;for(a=a?a.split(p):f.keys(e);d=a.shift();)if(h=e[d],delete e[d],h&&(b||c))for(g=h.tail;(h=h.next)!==g;)if(j=h.callback,q=h.context,b&&j!==b||c&&q!==c)this.on(d,j,q);return this}},trigger:function(a){var b,c,d,e,f,g;if(!(d=this._callbacks))return this;f=d.all;a=a.split(p);for(g= +z.call(arguments,1);b=a.shift();){if(c=d[b])for(e=c.tail;(c=c.next)!==e;)c.callback.apply(c.context||this,g);if(c=f){e=c.tail;for(b=[b].concat(g);(c=c.next)!==e;)c.callback.apply(c.context||this,b)}}return this}};k.bind=k.on;k.unbind=k.off;var o=g.Model=function(a,b){var c;a||(a={});b&&b.parse&&(a=this.parse(a));if(c=n(this,"defaults"))a=f.extend({},c,a);b&&b.collection&&(this.collection=b.collection);this.attributes={};this._escapedAttributes={};this.cid=f.uniqueId("c");this.changed={};this._silent= +{};this._pending={};this.set(a,{silent:!0});this.changed={};this._silent={};this._pending={};this._previousAttributes=f.clone(this.attributes);this.initialize.apply(this,arguments)};f.extend(o.prototype,k,{changed:null,_silent:null,_pending:null,idAttribute:"id",initialize:function(){},toJSON:function(){return f.clone(this.attributes)},get:function(a){return this.attributes[a]},escape:function(a){var b;if(b=this._escapedAttributes[a])return b;b=this.get(a);return this._escapedAttributes[a]=f.escape(null== +b?"":""+b)},has:function(a){return null!=this.get(a)},set:function(a,b,c){var d,e;f.isObject(a)||null==a?(d=a,c=b):(d={},d[a]=b);c||(c={});if(!d)return this;d instanceof o&&(d=d.attributes);if(c.unset)for(e in d)d[e]=void 0;if(!this._validate(d,c))return!1;this.idAttribute in d&&(this.id=d[this.idAttribute]);var b=c.changes={},h=this.attributes,g=this._escapedAttributes,j=this._previousAttributes||{};for(e in d){a=d[e];if(!f.isEqual(h[e],a)||c.unset&&f.has(h,e))delete g[e],(c.silent?this._silent: +b)[e]=!0;c.unset?delete h[e]:h[e]=a;!f.isEqual(j[e],a)||f.has(h,e)!=f.has(j,e)?(this.changed[e]=a,c.silent||(this._pending[e]=!0)):(delete this.changed[e],delete this._pending[e])}c.silent||this.change(c);return this},unset:function(a,b){(b||(b={})).unset=!0;return this.set(a,null,b)},clear:function(a){(a||(a={})).unset=!0;return this.set(f.clone(this.attributes),a)},fetch:function(a){var a=a?f.clone(a):{},b=this,c=a.success;a.success=function(d,e,f){if(!b.set(b.parse(d,f),a))return!1;c&&c(b,d)}; +a.error=g.wrapError(a.error,b,a);return(this.sync||g.sync).call(this,"read",this,a)},save:function(a,b,c){var d,e;f.isObject(a)||null==a?(d=a,c=b):(d={},d[a]=b);c=c?f.clone(c):{};if(c.wait){if(!this._validate(d,c))return!1;e=f.clone(this.attributes)}a=f.extend({},c,{silent:!0});if(d&&!this.set(d,c.wait?a:c))return!1;var h=this,i=c.success;c.success=function(a,b,e){b=h.parse(a,e);if(c.wait){delete c.wait;b=f.extend(d||{},b)}if(!h.set(b,c))return false;i?i(h,a):h.trigger("sync",h,a,c)};c.error=g.wrapError(c.error, +h,c);b=this.isNew()?"create":"update";b=(this.sync||g.sync).call(this,b,this,c);c.wait&&this.set(e,a);return b},destroy:function(a){var a=a?f.clone(a):{},b=this,c=a.success,d=function(){b.trigger("destroy",b,b.collection,a)};if(this.isNew())return d(),!1;a.success=function(e){a.wait&&d();c?c(b,e):b.trigger("sync",b,e,a)};a.error=g.wrapError(a.error,b,a);var e=(this.sync||g.sync).call(this,"delete",this,a);a.wait||d();return e},url:function(){var a=n(this,"urlRoot")||n(this.collection,"url")||t(); +return this.isNew()?a:a+("/"==a.charAt(a.length-1)?"":"/")+encodeURIComponent(this.id)},parse:function(a){return a},clone:function(){return new this.constructor(this.attributes)},isNew:function(){return null==this.id},change:function(a){a||(a={});var b=this._changing;this._changing=!0;for(var c in this._silent)this._pending[c]=!0;var d=f.extend({},a.changes,this._silent);this._silent={};for(c in d)this.trigger("change:"+c,this,this.get(c),a);if(b)return this;for(;!f.isEmpty(this._pending);){this._pending= +{};this.trigger("change",this,a);for(c in this.changed)!this._pending[c]&&!this._silent[c]&&delete this.changed[c];this._previousAttributes=f.clone(this.attributes)}this._changing=!1;return this},hasChanged:function(a){return!arguments.length?!f.isEmpty(this.changed):f.has(this.changed,a)},changedAttributes:function(a){if(!a)return this.hasChanged()?f.clone(this.changed):!1;var b,c=!1,d=this._previousAttributes,e;for(e in a)if(!f.isEqual(d[e],b=a[e]))(c||(c={}))[e]=b;return c},previous:function(a){return!arguments.length|| +!this._previousAttributes?null:this._previousAttributes[a]},previousAttributes:function(){return f.clone(this._previousAttributes)},isValid:function(){return!this.validate(this.attributes)},_validate:function(a,b){if(b.silent||!this.validate)return!0;var a=f.extend({},this.attributes,a),c=this.validate(a,b);if(!c)return!0;b&&b.error?b.error(this,c,b):this.trigger("error",this,c,b);return!1}});var r=g.Collection=function(a,b){b||(b={});b.model&&(this.model=b.model);b.comparator&&(this.comparator=b.comparator); +this._reset();this.initialize.apply(this,arguments);a&&this.reset(a,{silent:!0,parse:b.parse})};f.extend(r.prototype,k,{model:o,initialize:function(){},toJSON:function(a){return this.map(function(b){return b.toJSON(a)})},add:function(a,b){var c,d,e,g,i,j={},k={},l=[];b||(b={});a=f.isArray(a)?a.slice():[a];c=0;for(d=a.length;c=b))this.iframe=i('