]> git.basschouten.com Git - openhab-addons.git/commitdiff
[ecotouch] add Waterkotte EcoTouch binding (ported from OH1) (#10010)
authorSebastian Held <sebastian.held@gmx.de>
Tue, 27 Apr 2021 20:23:32 +0000 (22:23 +0200)
committerGitHub <noreply@github.com>
Tue, 27 Apr 2021 20:23:32 +0000 (22:23 +0200)
Signed-off-by: Sebastian Held <sebastian.held@gmx.de>
17 files changed:
CODEOWNERS
bom/openhab-addons/pom.xml
bundles/org.openhab.binding.ecotouch/NOTICE [new file with mode: 0644]
bundles/org.openhab.binding.ecotouch/README.md [new file with mode: 0644]
bundles/org.openhab.binding.ecotouch/pom.xml [new file with mode: 0644]
bundles/org.openhab.binding.ecotouch/src/main/feature/feature.xml [new file with mode: 0644]
bundles/org.openhab.binding.ecotouch/src/main/java/org/openhab/binding/ecotouch/internal/EcoTouchBindingConstants.java [new file with mode: 0644]
bundles/org.openhab.binding.ecotouch/src/main/java/org/openhab/binding/ecotouch/internal/EcoTouchConfiguration.java [new file with mode: 0644]
bundles/org.openhab.binding.ecotouch/src/main/java/org/openhab/binding/ecotouch/internal/EcoTouchConnector.java [new file with mode: 0644]
bundles/org.openhab.binding.ecotouch/src/main/java/org/openhab/binding/ecotouch/internal/EcoTouchException.java [new file with mode: 0644]
bundles/org.openhab.binding.ecotouch/src/main/java/org/openhab/binding/ecotouch/internal/EcoTouchHandler.java [new file with mode: 0644]
bundles/org.openhab.binding.ecotouch/src/main/java/org/openhab/binding/ecotouch/internal/EcoTouchHandlerFactory.java [new file with mode: 0644]
bundles/org.openhab.binding.ecotouch/src/main/java/org/openhab/binding/ecotouch/internal/EcoTouchTags.java [new file with mode: 0644]
bundles/org.openhab.binding.ecotouch/src/main/resources/OH-INF/binding/binding.xml [new file with mode: 0644]
bundles/org.openhab.binding.ecotouch/src/main/resources/OH-INF/i18n/ecotouch_de.properties [new file with mode: 0644]
bundles/org.openhab.binding.ecotouch/src/main/resources/OH-INF/thing/thing-types.xml [new file with mode: 0644]
bundles/pom.xml

index 58bea85272771a1e45218507d94d418e0b333436..403c77efe527e5c2e95a678ec0bdb5ab2b92711a 100644 (file)
@@ -66,6 +66,7 @@
 /bundles/org.openhab.binding.dwdpollenflug/ @DerOetzi
 /bundles/org.openhab.binding.dwdunwetter/ @limdul79
 /bundles/org.openhab.binding.ecobee/ @mhilbush
+/bundles/org.openhab.binding.ecotouch/ @sibbi77
 /bundles/org.openhab.binding.elerotransmitterstick/ @vbier
 /bundles/org.openhab.binding.energenie/ @hmerk
 /bundles/org.openhab.binding.enigma2/ @gdolfen
index ae1c023e9c0ad45cf85e9b9bc62dbce7fc60f3f2..0037c5b9d53250622f3f308f04064d0421143d48 100644 (file)
       <artifactId>org.openhab.binding.ecobee</artifactId>
       <version>${project.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.openhab.addons.bundles</groupId>
+      <artifactId>org.openhab.binding.ecotouch</artifactId>
+      <version>${project.version}</version>
+    </dependency>
     <dependency>
       <groupId>org.openhab.addons.bundles</groupId>
       <artifactId>org.openhab.binding.elerotransmitterstick</artifactId>
diff --git a/bundles/org.openhab.binding.ecotouch/NOTICE b/bundles/org.openhab.binding.ecotouch/NOTICE
new file mode 100644 (file)
index 0000000..38d625e
--- /dev/null
@@ -0,0 +1,13 @@
+This content is produced and maintained by the openHAB project.
+
+* Project home: https://www.openhab.org
+
+== Declared Project Licenses
+
+This program and the accompanying materials are made available under the terms
+of the Eclipse Public License 2.0 which is available at
+https://www.eclipse.org/legal/epl-2.0/.
+
+== Source Code
+
+https://github.com/openhab/openhab-addons
diff --git a/bundles/org.openhab.binding.ecotouch/README.md b/bundles/org.openhab.binding.ecotouch/README.md
new file mode 100644 (file)
index 0000000..2050f4a
--- /dev/null
@@ -0,0 +1,200 @@
+# EcoTouch Binding
+
+The openHAB EcoTouch binding allows interaction with a [Waterkotte](https://www.waterkotte.de/) heat pump.
+
+## Supported Things
+
+| Thing type      | Description                                      |
+|-----------------|--------------------------------------------------|
+| geo             | Waterkotte EcoTouch Geo + EcoVent                |
+| air             | Waterkotte EcoTouch Air + EcoVent                |
+
+This binding was tested with a Waterkotte DS 5027 Ai DS 5010.5Ai geothermal heat pump.
+
+## Discovery
+
+Discovery is not supported. You need to provide the IP address of the display unit of the heatpump.
+
+## Thing Configuration
+
+Things can be fully configured via the UI. The following information is useful when configuring things via thing configuration files.
+
+| Property                        | Type    | Default | Required | Description |
+|---------------------------------|---------|---------|----------|-------------|
+| ip                              | String  |         | yes      | IP address or hostname of the display unit of the heat pump |
+| username                        | String  |         | yes      | since software version 1.6.xx of the display unit: "waterkotte"; previously "admin". |
+| password                        | String  |         | yes      | since software version 1.6.xx of the display unit: "waterkotte"; previously "wtkadmin". |
+| refresh                         | Integer |      60 | no       | time in s after which all channels will be requested again from the heat pump |
+
+## Channels
+
+Standard channels:
+
+| Channel ID                 | Type                 | Read-Only | Description                                                     |
+|----------------------------|----------------------|-----------|-----------------------------------------------------------------|
+| adapt_heating              | Number:Temperature   | no        | Allows to adjust the heating temperature by an offset           |
+| alarm                      | Number:Dimensionless | yes       | Alarm                                                           |
+| cop_cooling                | Number:Dimensionless | yes       | COP Cooling                                                     |
+| cop_heating                | Number:Dimensionless | yes       | COP Heating                                                     |
+| enable_cooling             | Switch               | no        | Enable Cooling                                                  |
+| enable_heating             | Switch               | no        | Enable Heating                                                  |
+| enable_warmwater           | Switch               | no        | Enable Warm Water                                               |
+| power_compressor           | Number:Power         | yes       | Power Compressor                                                |
+| power_cooling              | Number:Power         | yes       | Power Cooling                                                   |
+| power_heating              | Number:Power         | yes       | Power Heating                                                   |
+| state_alarm                | Switch               | yes       | State Alarm                                                     |
+| temperature_cooling_return | Number:Temperature   | yes       | Temperature Cooling Return                                      |
+| temperature_cooling_set2   | Number:Temperature   | no        | Temperature Cooling Setpoint BMS                                |
+| temperature_flow           | Number:Temperature   | yes       | Temperature Flow                                                |
+| temperature_heating_return | Number:Temperature   | yes       | Temperature Heating Return                                      |
+| temperature_heating_set    | Number:Temperature   | yes       | Temperature Heating Setpoint                                    |
+| temperature_outside        | Number:Temperature   | yes       | The current outside temperature                                 |
+| temperature_outside_24h    | Number:Temperature   | yes       | The outside temperature averaged over one day                   |
+| temperature_return         | Number:Temperature   | yes       | Temperature Return                                              |
+| temperature_return_set     | Number:Temperature   | yes       | Temperature Return Setpoint                                     |
+| temperature_room           | Number:Temperature   | yes       | Temperature Room                                                |
+| temperature_room_1h        | Number:Temperature   | yes       | Temperature Room 1h Average                                     |
+| temperature_source_in      | Number:Temperature   | yes       | Temperature Source Input                                        |
+| temperature_source_out     | Number:Temperature   | yes       | Temperature Source Output                                       |
+| temperature_water          | Number:Temperature   | yes       | Temperature Water                                               |
+| temperature_water_set2     | Number:Temperature   | no        | Temperature Water Setpoint BMS                                  |
+
+Advanced channels:
+
+| Channel ID                       | Type                 | Read-Only | Description                                                             |
+|----------------------------------|----------------------|-----------|-------------------------------------------------------------------------|
+| compressor_power                 | Number:Dimensionless | yes       | Percent Power Compressor                                                |
+| coolEnableTemp                   | Number:Temperature   | yes       | Temperature Cooling Enable                                              |
+| date_day                         | Number:Dimensionless | yes       | Day                                                                     |
+| date_month                       | Number:Dimensionless | yes       | Month                                                                   |
+| date_year                        | Number:Dimensionless | yes       | Year                                                                    |
+| enable_pool                      | Switch               | no        | Enable Pool                                                             |
+| enable_pv                        | Switch               | no        | Enable PV                                                               |
+| hysteresis_heating               | Number:Temperature   | no        | Hysteresis Heating                                                      |
+| interruptions                    | Number:Dimensionless | yes       | Interruptions                                                           |
+| manual_4wayvalve                 | Number:Dimensionless | no        | Operating Mode 4Way Valve                                               |
+| manual_coolvalve                 | Number:Dimensionless | no        | Operating Mode Cooling Valve                                            |
+| manual_heatingpump               | Number:Dimensionless | no        | Operating Mode Heating Pump                                             |
+| manual_multiext                  | Number:Dimensionless | no        | Operating Mode Multi Ouput Ext                                          |
+| manual_poolvalve                 | Number:Dimensionless | no        | Operating Mode Pool Valve                                               |
+| manual_solarpump1                | Number:Dimensionless | no        | Operating Mode Solar Pump                                               |
+| manual_solarpump2                | Number:Dimensionless | no        | Operating Mode Solar Pump 2                                             |
+| manual_sourcepump                | Number:Dimensionless | no        | Operating Mode Source Pump                                              |
+| manual_tankpump                  | Number:Dimensionless | no        | Operating Mode Tank Pump                                                |
+| manual_valve                     | Number:Dimensionless | no        | Operating Mode Valve                                                    |
+| maxVLTemp                        | Number:Temperature   | yes       | maxVLTemp                                                               |
+| nviHeizkreisNorm                 | Number:Temperature   | no        | nviHeizkreisNorm                                                        |
+| nviNormAussen                    | Number:Temperature   | no        | nviNormAussen                                                           |
+| nviSollKuehlen                   | Number:Temperature   | yes       | nviSollKuehlen                                                          |
+| nviTHeizgrenze                   | Number:Temperature   | no        | nviTHeizgrenze                                                          |
+| nviTHeizgrenzeSoll               | Number:Temperature   | no        | nviTHeizgrenze Setpoint                                                 |
+| operating_hours_circulation_pump | Number:Time          | yes       | Operating Hours Circulation Pump                                        |
+| operating_hours_compressor1      | Number:Time          | yes       | Operating Hours Compressor 1                                            |
+| operating_hours_compressor2      | Number:Time          | yes       | Operating Hours Compressor 2                                            |
+| operating_hours_solar            | Number:Time          | yes       | Operating Hours Solar                                                   |
+| operating_hours_source_pump      | Number:Time          | yes       | Operating Hours Source Pump                                             |
+| percent_compressor               | Number:Dimensionless | yes       | Percent Compressor                                                      |
+| percent_heat_circ_pump           | Number:Dimensionless | yes       | Percent Heating Circulation Pump                                        |
+| percent_source_pump              | Number:Dimensionless | yes       | Percent Source Pump                                                     |
+| position_expansion_valve         | Number:Dimensionless | yes       | Position Expansion Valve                                                |
+| pressure_condensation            | Number:Pressure      | yes       | Pressure Condensation                                                   |
+| pressure_evaporation             | Number:Pressure      | yes       | Pressure Evaporation                                                    |
+| state                            | Number:Dimensionless | yes       | A Bitfield which encodes the state of all valves, pumps and compressors |
+| state_compressor1                | Switch               | yes       | State Compressor 1                                                      |
+| state_compressor2                | Switch               | yes       | State Compressor 2                                                      |
+| state_cooling                    | Switch               | yes       | State Cooling                                                           |
+| state_cooling4way                | Switch               | yes       | State Cooling4Way                                                       |
+| state_evd                        | Switch               | yes       | State EVD                                                               |
+| state_extheater                  | Switch               | yes       | State External Heater                                                   |
+| state_heatingpump                | Switch               | yes       | State Heating Pump                                                      |
+| state_pool                       | Switch               | yes       | State Pool                                                              |
+| state_service                    | Switch               | yes       | State Service Mode                                                      |
+| state_solar                      | Switch               | yes       | State Solar                                                             |
+| state_sourcepump                 | Switch               | yes       | State Source Pump                                                       |
+| state_water                      | Switch               | yes       | State Water                                                             |
+| tempSet0Deg                      | Number:Temperature   | yes       | Heating Setpoint at 0°C Outside                                         |
+| tempchange_cooling_pv            | Number:Temperature   | no        | Temperature Change Cooling if PV                                        |
+| tempchange_heating_pv            | Number:Temperature   | no        | Temperature Change Heating if PV                                        |
+| tempchange_pool_pv               | Number:Temperature   | no        | Temperature Change Pool if PV                                           |
+| tempchange_warmwater_pv          | Number:Temperature   | no        | Temperature Change Water if PV                                          |
+| temperature2_outside_1h          | Number:Temperature   | yes       | Temperature Outside 1h Average                                          |
+| temperature_condensation         | Number:Temperature   | yes       | Temperature Condensation                                                |
+| temperature_cooling_set          | Number:Temperature   | yes       | Temperature Cooling Setpoint                                            |
+| temperature_evaporation          | Number:Temperature   | yes       | Temperature Evaporation                                                 |
+| temperature_heating_set2         | Number:Temperature   | no        | Temperature Heating Setpoint BMS                                        |
+| temperature_outside_1h           | Number:Temperature   | yes       | The outside temperature averaged over one hour                          |
+| temperature_pool                 | Number:Temperature   | yes       | Temperature Pool                                                        |
+| temperature_pool_set             | Number:Temperature   | yes       | Temperature Pool Setpoint                                               |
+| temperature_pool_set2            | Number:Temperature   | no        | Temperature Pool Setpoint BMS                                           |
+| temperature_solar                | Number:Temperature   | yes       | Temperature Solar                                                       |
+| temperature_solar_flow           | Number:Temperature   | yes       | Temperature Solar Flow                                                  |
+| temperature_storage              | Number:Temperature   | yes       | Temperature Storage                                                     |
+| temperature_suction              | Number:Temperature   | yes       | Temperature Suction                                                     |
+| temperature_water_set            | Number:Temperature   | yes       | Temperature Water Setpoint                                              |
+| time_hour                        | Number:Dimensionless | yes       | Hour                                                                    |
+| time_minute                      | Number:Dimensionless | yes       | Minute                                                                  |
+| version_bios                     | Number:Dimensionless | yes       | Version BIOS                                                            |
+| version_controller               | Number:Dimensionless | yes       | Version Display Controller                                              |
+| version_controller_build         | Number:Dimensionless | yes       | Build Number Display Controller                                         |
+
+If the Ecovent Unit is attached to the heat pump, the following additional channels are available:
+
+| Channel ID                 | Type                 | Read-Only | Description |
+|----------------------------|----------------------|-----------|-------------|
+| ecovent_CO2_value          | Number:Dimensionless | yes       | EcoVent CO2                                                     |
+| ecovent_mode               | Number:Dimensionless | no        | EcoVent Mode (0..5: Day, Night, Timer, Party, Vacation, Bypass) |
+| ecovent_moisture_value     | Number:Dimensionless | yes       | EcoVent Air Moisture                                            |
+| ecovent_output_y1          | Number:Dimensionless | yes       | EcoVent Fan                                                     |
+| ecovent_temp_exhaust_air   | Number:Temperature   | yes       | EcoVent Temperature Exhaust Air                                 |
+| ecovent_temp_exit_air      | Number:Temperature   | yes       | EcoVent Temperature Exit Air                                    |
+| ecovent_temp_outdoor_air   | Number:Temperature   | yes       | EcoVent Temperature Outdoor Air                                 |
+| ecovent_temp_supply_air    | Number:Temperature   | yes       | EcoVent Temperature Supply Air                                  |
+
+The air heatpump has the following additional channels:
+
+| Channel ID              | Type               | Read-Only | Description             |
+|-------------------------|--------------------|-----------|-------------------------|
+| temperature_suction_air | Number:Temperature | yes       | Temperature Suction Air |
+| temperature_sump        | Number:Temperature | yes       | Temperature Sump        |
+| temperature_surrounding | Number:Temperature | yes       | Temperature Surrounding |
+
+## Example
+
+### ecotouch.things
+
+```
+Thing ecotouch:geo:heatpump "Waterkotte Heatpump" @ "basement" [ ip="192.168.1.100", username="admin", password="wtkadmin", refresh=120 ]
+```
+
+### ecotouch.items
+
+```
+Number:Temperature HeatPump_Temp_Aussen     { channel="ecotouch:geo:heatpump:temperature_outside" }
+Number:Temperature HeatPump_Temp_Aussen_1d  { channel="ecotouch:geo:heatpump:temperature_outside_24h" }
+Number:Temperature HeatPump_Temp_Quelle_in  { channel="ecotouch:geo:heatpump:temperature_source_in" }
+Number:Temperature HeatPump_Temp_Quelle_out { channel="ecotouch:geo:heatpump:temperature_source_out" }
+Number:Temperature HeatPump_Temp_Wasser     { channel="ecotouch:geo:heatpump:temperature_water" }
+Number:Temperature HeatPump_Temp_Heizen     { channel="ecotouch:geo:heatpump:temperature_heating_return" }
+Number:Power HeatPump_power_el              { channel="ecotouch:geo:heatpump:power_compressor" }
+Number:Power HeatPump_power_th              { channel="ecotouch:geo:heatpump:power_heating" }
+Number HeatPump_COP_heating                 { channel="ecotouch:geo:heatpump:cop_heating" }
+Number:Temperature HeatPump_adaptHeating    { channel="ecotouch:geo:heatpump:adapt_heating" }
+```
+
+### ecotouch.sitemap
+
+```
+sitemap ecotouch label="Waterkotte EcoTouch"
+{
+    Text item=HeatPump_Temp_Aussen
+    Text item=HeatPump_Temp_Aussen_1d
+    Text item=HeatPump_Temp_Quelle_in
+    Text item=HeatPump_Temp_Quelle_out
+    Text item=HeatPump_Temp_Wasser
+    Text item=HeatPump_Temp_Heizen
+    Text item=HeatPump_Temp_Heizen
+    Text item=HeatPump_power_th
+    Text item=HeatPump_COP_heating
+    Setpoint item=HeatPump_adaptHeating minValue=-2.0 maxValue=2.0 step=0.5
+}
+```
diff --git a/bundles/org.openhab.binding.ecotouch/pom.xml b/bundles/org.openhab.binding.ecotouch/pom.xml
new file mode 100644 (file)
index 0000000..011f0e3
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.openhab.addons.bundles</groupId>
+    <artifactId>org.openhab.addons.reactor.bundles</artifactId>
+    <version>3.1.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>org.openhab.binding.ecotouch</artifactId>
+
+  <name>openHAB Add-ons :: Bundles :: EcoTouch Binding</name>
+
+</project>
diff --git a/bundles/org.openhab.binding.ecotouch/src/main/feature/feature.xml b/bundles/org.openhab.binding.ecotouch/src/main/feature/feature.xml
new file mode 100644 (file)
index 0000000..0c8a51f
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<features name="org.openhab.binding.ecotouch-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
+       <repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
+
+       <feature name="openhab-binding-ecotouch" description="EcoTouch Binding" version="${project.version}">
+               <feature>openhab-runtime-base</feature>
+               <bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.ecotouch/${project.version}</bundle>
+       </feature>
+</features>
diff --git a/bundles/org.openhab.binding.ecotouch/src/main/java/org/openhab/binding/ecotouch/internal/EcoTouchBindingConstants.java b/bundles/org.openhab.binding.ecotouch/src/main/java/org/openhab/binding/ecotouch/internal/EcoTouchBindingConstants.java
new file mode 100644 (file)
index 0000000..59beab8
--- /dev/null
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.ecotouch.internal;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.thing.ThingTypeUID;
+
+/**
+ * The {@link EcoTouchBindingConstants} class defines common constants, which are
+ * used across the whole binding.
+ *
+ * @author Sebastian Held - Initial contribution
+ */
+@NonNullByDefault
+public class EcoTouchBindingConstants {
+
+    private static final String BINDING_ID = "ecotouch";
+
+    // List of all Thing Type UIDs
+    public static final ThingTypeUID THING_TYPE_GEO = new ThingTypeUID(BINDING_ID, "geo");
+    public static final ThingTypeUID THING_TYPE_AIR = new ThingTypeUID(BINDING_ID, "air");
+}
diff --git a/bundles/org.openhab.binding.ecotouch/src/main/java/org/openhab/binding/ecotouch/internal/EcoTouchConfiguration.java b/bundles/org.openhab.binding.ecotouch/src/main/java/org/openhab/binding/ecotouch/internal/EcoTouchConfiguration.java
new file mode 100644 (file)
index 0000000..423207f
--- /dev/null
@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.ecotouch.internal;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link EcoTouchConfiguration} class contains fields mapping thing configuration parameters.
+ *
+ * @author Sebastian Held - Initial contribution
+ */
+@NonNullByDefault
+public class EcoTouchConfiguration {
+    public String ip = "";
+    public String username = "";
+    public String password = "";
+    public Integer refresh = 60;
+}
diff --git a/bundles/org.openhab.binding.ecotouch/src/main/java/org/openhab/binding/ecotouch/internal/EcoTouchConnector.java b/bundles/org.openhab.binding.ecotouch/src/main/java/org/openhab/binding/ecotouch/internal/EcoTouchConnector.java
new file mode 100644 (file)
index 0000000..0e4ea47
--- /dev/null
@@ -0,0 +1,332 @@
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.ecotouch.internal;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLEncoder;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Network communication with Waterkotte EcoTouch heat pumps.
+ *
+ * The communication protocol was reverse engineered from the Easy-Con Android
+ * app. The meaning of the EcoTouch tags was provided by Waterkotte's technical
+ * service (by an excerpt of a developer manual).
+ *
+ * @author Sebastian Held <sebastian.held@gmx.de> - Initial contribution
+ * @since 1.5.0
+ */
+
+@NonNullByDefault
+public class EcoTouchConnector {
+    private String ip;
+    private String username;
+    private String password;
+    @Nullable
+    List<String> cookies;
+    static Pattern responsePattern = Pattern.compile("#(.+)\\s+S_OK[^0-9-]+([0-9-]+)\\s+([0-9-.]+)");
+
+    private final Logger logger = LoggerFactory.getLogger(EcoTouchConnector.class);
+
+    /**
+     * Create a network communication without having a current access token.
+     */
+    public EcoTouchConnector(String ip, String username, String password) {
+        this.ip = ip;
+        this.username = username;
+        this.password = password;
+        this.cookies = null;
+    }
+
+    /**
+     * Create a network communication with access token. This speeds up
+     * retrieving values, because the log in step is omitted.
+     */
+    public EcoTouchConnector(String ip, String username, String password, List<String> cookies) {
+        this.ip = ip;
+        this.username = username;
+        this.password = password;
+        this.cookies = cookies;
+    }
+
+    private synchronized void trylogin(boolean force) throws Exception {
+        if (!force && cookies != null) {
+            // we've a login token already
+            return;
+        }
+        login();
+    }
+
+    private void login() throws IOException {
+        cookies = null;
+        String url = null;
+        String line2 = null;
+        String cause = null;
+        try {
+            url = "http://" + ip + "/cgi/login?username=" + URLEncoder.encode(username, "UTF-8") + "&password="
+                    + URLEncoder.encode(password, "UTF-8");
+            URL loginurl = new URL(url);
+            URLConnection connection = loginurl.openConnection();
+            cookies = connection.getHeaderFields().get("Set-Cookie");
+            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
+            in.readLine();
+            line2 = in.readLine();
+        } catch (MalformedURLException e) {
+            cause = e.toString();
+        } catch (Exception e) {
+            cause = e.toString();
+        }
+
+        if (line2 != null && line2.trim().equals("#E_USER_DONT_EXIST")) {
+            throw new IOException("Username does not exist.");
+        }
+        if (line2 != null && line2.trim().equals("#E_PASS_DONT_MATCH")) {
+            throw new IOException("Password does not match.");
+        }
+        if (line2 != null && line2.trim().equals("#E_TOO_MANY_USERS")) {
+            throw new IOException("Too many users already logged in.");
+        }
+        if (cookies == null) {
+            if (cause == null)
+                throw new IOException("Cannot login");
+            else
+                throw new IOException("Cannot login: " + cause);
+        }
+    }
+
+    public void logout() {
+        if (cookies != null) {
+            try {
+                URL logouturl = new URL("http://" + ip + "/cgi/logout");
+                logouturl.openConnection();
+            } catch (Exception e) {
+            }
+            cookies = null;
+        }
+    }
+
+    /**
+     * Request a value from the heat pump
+     * 
+     * @param tag
+     *            The register to query (e.g. "A1")
+     * @return value This value is a 16-bit integer.
+     */
+    public String getValue(String tag) throws Exception {
+        Map<String, String> result = getValues(Set.of(tag));
+        String value = result.get(tag);
+        if (value == null) {
+            // failed
+            logger.debug("Cannot get value for tag '{}' from Waterkotte EcoTouch.", tag);
+            throw new EcoTouchException("invalid response from EcoTouch");
+        }
+
+        return value;
+    }
+
+    /**
+     * Request multiple values from the heat pump
+     * 
+     * @param tags
+     *            The registers to query (e.g. "A1")
+     * @return values A map of tags and their respective string values
+     */
+    public Map<String, String> getValues(Set<String> tags) throws Exception {
+        final Integer maxNum = 100;
+
+        Map<String, String> result = new HashMap<String, String>();
+        Integer counter = 1;
+        StringBuilder query = new StringBuilder();
+        Iterator<String> iter = tags.iterator();
+        while (iter.hasNext()) {
+            query.append(String.format("t%d=%s&", counter, iter.next()));
+            counter++;
+            if (counter > maxNum) {
+                query.deleteCharAt(query.length() - 1); // remove last '&'
+                String queryStr = String.format("http://%s/cgi/readTags?n=%d&", ip, maxNum) + query;
+                result.putAll(getValues(queryStr));
+                counter = 1;
+                query = new StringBuilder();
+            }
+        }
+
+        if (query.length() > 0) {
+            query.deleteCharAt(query.length() - 1); // remove last '&'
+            String queryStr = String.format("http://%s/cgi/readTags?n=%d&", ip, counter - 1) + query;
+            result.putAll(getValues(queryStr));
+        }
+
+        return result;
+    }
+
+    /**
+     * Send a request to the heat pump and evaluate the result
+     * 
+     * @param url
+     *            The URL to connect to
+     * @return values A map of tags and their respective string values
+     */
+    private Map<String, String> getValues(String url) throws Exception {
+        trylogin(false);
+        Map<String, String> result = new HashMap<String, String>();
+        int loginAttempt = 0;
+        while (loginAttempt < 2) {
+            BufferedReader reader = null;
+            try {
+                URLConnection connection = new URL(url).openConnection();
+                var localCookies = cookies;
+                if (localCookies != null) {
+                    for (String cookie : localCookies) {
+                        connection.addRequestProperty("Cookie", cookie.split(";", 2)[0]);
+                    }
+                }
+                InputStream response = connection.getInputStream();
+                reader = new BufferedReader(new InputStreamReader(response));
+                // the answer is s.th. like
+                // #A30 S_OK
+                // 192 223
+                // [...]
+                String line;
+                while ((line = reader.readLine()) != null) {
+                    String line2 = reader.readLine();
+                    if (line2 == null)
+                        break;
+                    String doubleline = line + "\n" + line2;
+                    Matcher m = responsePattern.matcher(doubleline);
+                    if (m.find()) {
+                        String tag = m.group(1);
+                        String value = m.group(3).trim();
+                        result.put(tag, value);
+                    }
+                }
+
+                if (result.isEmpty()) {
+                    // s.th. went wrong; try to log in again
+                    throw new EcoTouchException();
+                }
+
+                // succeeded
+                break;
+            } catch (Exception e) {
+                if (loginAttempt == 0) {
+                    // try to login once
+                    trylogin(true);
+                }
+                loginAttempt++;
+            } finally {
+                if (reader != null)
+                    reader.close();
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Set a value
+     * 
+     * @param tag
+     *            The register to set (e.g. "A1")
+     * @param value
+     *            The 16-bit integer to set the register to
+     * @return value This value is a 16-bit integer.
+     */
+    public int setValue(String tag, int value) throws Exception {
+        trylogin(false);
+
+        // set value
+        String url = "http://" + ip + "/cgi/writeTags?returnValue=true&n=1&t1=" + tag + "&v1=" + value;
+        StringBuilder body = null;
+        int loginAttempt = 0;
+        while (loginAttempt < 2) {
+            BufferedReader reader = null;
+            try {
+                URLConnection connection = new URL(url).openConnection();
+                var localCookies = cookies;
+                if (localCookies != null) {
+                    for (String cookie : localCookies) {
+                        connection.addRequestProperty("Cookie", cookie.split(";", 2)[0]);
+                    }
+                }
+                InputStream response = connection.getInputStream();
+                reader = new BufferedReader(new InputStreamReader(response));
+                body = new StringBuilder();
+                String line;
+                while ((line = reader.readLine()) != null) {
+                    body.append(line + "\n");
+                }
+                if (body.toString().contains("#" + tag)) {
+                    // succeeded
+                    break;
+                }
+                // s.th. went wrong; try to log in
+                throw new EcoTouchException();
+            } catch (Exception e) {
+                if (loginAttempt == 0) {
+                    // try to login once
+                    trylogin(true);
+                }
+                loginAttempt++;
+            } finally {
+                if (reader != null)
+                    reader.close();
+            }
+        }
+
+        if (body == null || !body.toString().contains("#" + tag)) {
+            // failed
+            logger.debug("Cannot get value for tag '{}' from Waterkotte EcoTouch.", tag);
+            throw new EcoTouchException("invalid response from EcoTouch");
+        }
+
+        // ok, the body now contains s.th. like
+        // #A30 S_OK
+        // 192 223
+
+        Matcher m = responsePattern.matcher(body.toString());
+        boolean b = m.find();
+        if (!b) {
+            // ill formatted response
+            logger.debug("ill formatted response: '{}'", body);
+            throw new EcoTouchException("invalid response from EcoTouch");
+        }
+
+        logger.debug("response: '{}'", body.toString());
+        return Integer.parseInt(m.group(3));
+    }
+
+    /**
+     * Authentication token. Store this and use it, when creating the next
+     * instance of this class.
+     * 
+     * @return cookies: This includes the authentication token retrieved during
+     *         log in.
+     */
+    @Nullable
+    public List<String> getCookies() {
+        return cookies;
+    }
+}
diff --git a/bundles/org.openhab.binding.ecotouch/src/main/java/org/openhab/binding/ecotouch/internal/EcoTouchException.java b/bundles/org.openhab.binding.ecotouch/src/main/java/org/openhab/binding/ecotouch/internal/EcoTouchException.java
new file mode 100644 (file)
index 0000000..bccb4e4
--- /dev/null
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.ecotouch.internal;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * Trivial Exception Class.
+ *
+ * Used to solve compiler warning: "Avoid throwing raw exception types".
+ *
+ * @author Sebastian Held <sebastian.held@gmx.de> - Initial contribution
+ * @since 3.1.0
+ */
+@NonNullByDefault
+public class EcoTouchException extends Exception {
+    private static final long serialVersionUID = -346364205220073265L;
+
+    public EcoTouchException(String errorMessage, Throwable err) {
+        super(errorMessage, err);
+    }
+
+    public EcoTouchException(String errorMessage) {
+        super(errorMessage);
+    }
+
+    public EcoTouchException() {
+        super();
+    }
+}
diff --git a/bundles/org.openhab.binding.ecotouch/src/main/java/org/openhab/binding/ecotouch/internal/EcoTouchHandler.java b/bundles/org.openhab.binding.ecotouch/src/main/java/org/openhab/binding/ecotouch/internal/EcoTouchHandler.java
new file mode 100644 (file)
index 0000000..f76daa4
--- /dev/null
@@ -0,0 +1,236 @@
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.ecotouch.internal;
+
+import static org.openhab.core.library.unit.SIUnits.*;
+import static org.openhab.core.library.unit.Units.*;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.*;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.core.library.types.DecimalType;
+import org.openhab.core.library.types.QuantityType;
+import org.openhab.core.thing.ChannelUID;
+import org.openhab.core.thing.Thing;
+import org.openhab.core.thing.ThingStatus;
+import org.openhab.core.thing.ThingStatusDetail;
+import org.openhab.core.thing.binding.BaseThingHandler;
+import org.openhab.core.types.Command;
+import org.openhab.core.types.RefreshType;
+import org.openhab.core.types.State;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The {@link EcoTouchHandler} is responsible for handling commands, which are
+ * sent to one of the channels.
+ *
+ * @author Sebastian Held - Initial contribution
+ */
+@NonNullByDefault
+public class EcoTouchHandler extends BaseThingHandler {
+
+    private @Nullable EcoTouchConnector connector = null;
+
+    private final Logger logger = LoggerFactory.getLogger(EcoTouchHandler.class);
+
+    private @Nullable EcoTouchConfiguration config = null;
+
+    private @Nullable ScheduledFuture<?> refreshJob = null;
+
+    public EcoTouchHandler(Thing thing) {
+        super(thing);
+    }
+
+    private void updateChannel(String tag, String value_str) {
+        try {
+            List<EcoTouchTags> ecoTouchTags = EcoTouchTags.fromTag(tag);
+            for (EcoTouchTags ecoTouchTag : ecoTouchTags) {
+                String channel = ecoTouchTag.getCommand();
+                BigDecimal value = ecoTouchTag.decodeValue(value_str);
+                if (ecoTouchTag == EcoTouchTags.TYPE_ADAPT_HEATING) {
+                    // this type needs special treatment
+                    // the following reads: value = value / 2 - 2
+                    value = value.divide(new BigDecimal(2), 1, RoundingMode.UNNECESSARY).subtract(new BigDecimal(2));
+                    QuantityType<?> quantity = new QuantityType<javax.measure.quantity.Temperature>(value, CELSIUS);
+                    updateState(channel, quantity);
+                } else {
+                    if (ecoTouchTag.getUnit() != ONE) {
+                        // this is a quantity type
+                        QuantityType<?> quantity = new QuantityType<>(value, ecoTouchTag.getUnit());
+                        updateState(channel, quantity);
+                    } else {
+                        DecimalType number = new DecimalType(value);
+                        updateState(channel, number);
+                    }
+                }
+            }
+        } catch (Exception e) {
+        }
+    }
+
+    @Override
+    public void handleCommand(ChannelUID channelUID, Command command) {
+        var localConnector = connector;
+        if (localConnector == null) {
+            // the binding was not initialized, yet
+            return;
+        }
+        if (command instanceof RefreshType) {
+            // request a refresh of a channel
+            try {
+                EcoTouchTags tag = EcoTouchTags.fromString(channelUID.getId());
+                if (tag != null) {
+                    String valueStr = localConnector.getValue(tag.getTagName());
+                    updateChannel(tag.getTagName(), valueStr);
+                    updateStatus(ThingStatus.ONLINE);
+                }
+            } catch (Exception e) {
+            }
+        } else {
+            // send command to heat pump
+            try {
+                EcoTouchTags ecoTouchTag = EcoTouchTags.fromString(channelUID.getId());
+                if (ecoTouchTag == EcoTouchTags.TYPE_ADAPT_HEATING) {
+                    // this type needs special treatment
+                    QuantityType<?> value = (QuantityType<?>) command;
+                    int raw = Math.round(value.floatValue() * 2 + 4);
+                    localConnector.setValue(ecoTouchTag.getTagName(), raw);
+                } else {
+                    if (ecoTouchTag.getUnit() != ONE) {
+                        if (command instanceof QuantityType) {
+                            // convert from user unit to heat pump unit
+                            QuantityType<?> value = (QuantityType<?>) command;
+                            QuantityType<?> rawUnit = value.toUnit(ecoTouchTag.getUnit());
+                            if (rawUnit != null) {
+                                int raw = rawUnit.intValue();
+                                raw *= ecoTouchTag.getDivisor();
+                                localConnector.setValue(ecoTouchTag.getTagName(), raw);
+                            }
+                        } else {
+                            logger.debug("handleCommand: requires a QuantityType");
+                        }
+                    } else {
+                        State state = (State) command;
+                        DecimalType decimalType = state.as(DecimalType.class);
+                        if (decimalType != null) {
+                            BigDecimal decimal = decimalType.toBigDecimal();
+                            decimal = decimal.multiply(new BigDecimal(ecoTouchTag.getDivisor()));
+                            int raw = decimal.intValue();
+                            localConnector.setValue(ecoTouchTag.getTagName(), raw);
+                        } else {
+                            logger.debug("cannot convert {} to a DecimalType", state);
+                        }
+                    }
+                }
+            } catch (Exception e) {
+                logger.debug("handleCommand: {}", e.toString());
+            }
+        }
+    }
+
+    @Override
+    public void initialize() {
+        config = getConfigAs(EcoTouchConfiguration.class);
+
+        var localConfig = config;
+        if (localConfig == null) {
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR);
+            return;
+        }
+
+        connector = new EcoTouchConnector(localConfig.ip, localConfig.username, localConfig.password);
+
+        scheduler.execute(() -> {
+            try {
+                // try to get a single value
+                var localConnector = connector;
+                if (localConnector == null) {
+                    updateStatus(ThingStatus.OFFLINE);
+                    return;
+                }
+                localConnector.getValue("A1");
+            } catch (IOException io) {
+                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, io.toString());
+                return;
+            } catch (Exception e) {
+                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.toString());
+                return;
+            }
+
+            updateStatus(ThingStatus.ONLINE);
+        });
+
+        // start refresh handler
+        startAutomaticRefresh();
+    }
+
+    private void startAutomaticRefresh() {
+        var localRefreshJob = refreshJob;
+        if (localRefreshJob == null || localRefreshJob.isCancelled()) {
+            Runnable runnable = () -> {
+                try {
+                    Set<String> tags = new HashSet<String>();
+                    for (EcoTouchTags ecoTouchTag : EcoTouchTags.values()) {
+                        String channel = ecoTouchTag.getCommand();
+                        boolean linked = isLinked(channel);
+                        if (linked)
+                            tags.add(ecoTouchTag.getTagName());
+                    }
+                    var localConnector = connector;
+                    if (localConnector != null) {
+                        Map<String, String> result = localConnector.getValues(tags);
+
+                        Iterator<Map.Entry<String, String>> it = result.entrySet().iterator();
+                        while (it.hasNext()) {
+                            Map.Entry<String, String> pair = it.next();
+                            updateChannel(pair.getKey(), pair.getValue());
+                        }
+                    }
+                } catch (IOException io) {
+                    updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, io.toString());
+                } catch (Exception e) {
+                    updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.toString());
+                } catch (Error e) {
+                    // during thing creation, the following error is thrown:
+                    // java.lang.NoSuchMethodError: 'org.openhab.binding.ecotouch.internal.EcoTouchTags[]
+                    // org.openhab.binding.ecotouch.internal.EcoTouchTags.values()'
+                    // not sure why... lets ignore it for now
+                    updateStatus(ThingStatus.OFFLINE);
+                }
+            };
+
+            var localConfig = config;
+            if (localConfig != null)
+                refreshJob = scheduler.scheduleWithFixedDelay(runnable, 10, localConfig.refresh, TimeUnit.SECONDS);
+        }
+    }
+
+    @Override
+    public void dispose() {
+        var localRefreshJob = refreshJob;
+        if (localRefreshJob != null && !localRefreshJob.isCancelled()) {
+            localRefreshJob.cancel(true);
+            localRefreshJob = null;
+        }
+        var localConnector = connector;
+        if (localConnector != null)
+            localConnector.logout();
+    }
+}
diff --git a/bundles/org.openhab.binding.ecotouch/src/main/java/org/openhab/binding/ecotouch/internal/EcoTouchHandlerFactory.java b/bundles/org.openhab.binding.ecotouch/src/main/java/org/openhab/binding/ecotouch/internal/EcoTouchHandlerFactory.java
new file mode 100644 (file)
index 0000000..02e1d9f
--- /dev/null
@@ -0,0 +1,60 @@
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.ecotouch.internal;
+
+import static org.openhab.binding.ecotouch.internal.EcoTouchBindingConstants.THING_TYPE_AIR;
+import static org.openhab.binding.ecotouch.internal.EcoTouchBindingConstants.THING_TYPE_GEO;
+
+import java.util.Collections;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.core.thing.Thing;
+import org.openhab.core.thing.ThingTypeUID;
+import org.openhab.core.thing.binding.BaseThingHandlerFactory;
+import org.openhab.core.thing.binding.ThingHandler;
+import org.openhab.core.thing.binding.ThingHandlerFactory;
+import org.osgi.service.component.annotations.Component;
+
+/**
+ * The {@link EcoTouchHandlerFactory} is responsible for creating things and thing
+ * handlers.
+ *
+ * @author Sebastian Held - Initial contribution
+ */
+@NonNullByDefault
+@Component(configurationPid = "binding.ecotouch", service = ThingHandlerFactory.class)
+public class EcoTouchHandlerFactory extends BaseThingHandlerFactory {
+
+    private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections
+            .unmodifiableSet(Stream.of(THING_TYPE_GEO, THING_TYPE_AIR).collect(Collectors.toSet()));
+
+    @Override
+    public boolean supportsThingType(ThingTypeUID thingTypeUID) {
+        return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
+    }
+
+    @Override
+    protected @Nullable ThingHandler createHandler(Thing thing) {
+        ThingTypeUID thingTypeUID = thing.getThingTypeUID();
+
+        if (THING_TYPE_GEO.equals(thingTypeUID) || THING_TYPE_AIR.equals(thingTypeUID)) {
+            return new EcoTouchHandler(thing);
+        }
+
+        return null;
+    }
+}
diff --git a/bundles/org.openhab.binding.ecotouch/src/main/java/org/openhab/binding/ecotouch/internal/EcoTouchTags.java b/bundles/org.openhab.binding.ecotouch/src/main/java/org/openhab/binding/ecotouch/internal/EcoTouchTags.java
new file mode 100644 (file)
index 0000000..19572aa
--- /dev/null
@@ -0,0 +1,1294 @@
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.ecotouch.internal;
+
+import static org.openhab.core.library.unit.MetricPrefix.*;
+import static org.openhab.core.library.unit.SIUnits.*;
+import static org.openhab.core.library.unit.Units.*;
+
+import java.math.BigDecimal;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.measure.Unit;
+
+/**
+ * Represents all valid commands which could be processed by this binding
+ *
+ * @author Sebastian Held <sebastian.held@gmx.de> - Initial contribution
+ * @since 1.5.0
+ */
+public enum EcoTouchTags {
+
+    // German: Außentemperatur
+    TYPE_TEMPERATURE_OUTSIDE {
+        {
+            command = "temperature_outside";
+            unit = CELSIUS;
+            tagName = "A1";
+        }
+    },
+
+    // German: Außentemperatur gemittelt über 1h
+    TYPE_TEMPERATURE_OUTSIDE_1H {
+        {
+            command = "temperature_outside_1h";
+            unit = CELSIUS;
+            tagName = "A2";
+        }
+    },
+
+    // German: Außentemperatur gemittelt über 24h
+    TYPE_TEMPERATURE_OUTSIDE_24H {
+        {
+            command = "temperature_outside_24h";
+            unit = CELSIUS;
+            tagName = "A3";
+        }
+    },
+
+    // German: Quelleneintrittstemperatur
+    TYPE_TEMPERATURE_SOURCE_IN {
+        {
+            command = "temperature_source_in";
+            unit = CELSIUS;
+            tagName = "A4";
+        }
+    },
+
+    // German: Quellenaustrittstemperatur
+    TYPE_TEMPERATURE_SOURCE_OUT {
+        {
+            command = "temperature_source_out";
+            unit = CELSIUS;
+            tagName = "A5";
+        }
+    },
+
+    // German: Verdampfungstemperatur
+    TYPE_TEMPERATURE_EVAPORATION {
+        {
+            command = "temperature_evaporation";
+            unit = CELSIUS;
+            tagName = "A6";
+        }
+    },
+
+    // German: Sauggastemperatur
+    TYPE_TEMPERATURE_SUCTION {
+        {
+            command = "temperature_suction";
+            unit = CELSIUS;
+            tagName = "A7";
+        }
+    },
+
+    // German: Verdampfungsdruck
+    TYPE_PRESSURE_EVAPORATION {
+        {
+            command = "pressure_evaporation";
+            unit = BAR;
+            tagName = "A8";
+        }
+    },
+
+    // German: Temperatur Rücklauf Soll
+    TYPE_TEMPERATURE_RETURN_SET {
+        {
+            command = "temperature_return_set";
+            unit = CELSIUS;
+            tagName = "A10";
+        }
+    },
+
+    // German: Temperatur Rücklauf
+    TYPE_TEMPERATURE_RETURN {
+        {
+            command = "temperature_return";
+            unit = CELSIUS;
+            tagName = "A11";
+        }
+    },
+
+    // German: Temperatur Vorlauf
+    TYPE_TEMPERATURE_FLOW {
+        {
+            command = "temperature_flow";
+            unit = CELSIUS;
+            tagName = "A12";
+        }
+    },
+
+    // German: Kondensationstemperatur
+    TYPE_TEMPERATURE_CONDENSATION {
+        {
+            command = "temperature_condensation";
+            unit = CELSIUS;
+            tagName = "A14";
+        }
+    },
+
+    // German: Kondensationsdruck
+    TYPE_PRESSURE_CONDENSATION {
+        {
+            command = "pressure_condensation";
+            unit = BAR;
+            tagName = "A15";
+        }
+    },
+
+    // German: Speichertemperatur
+    TYPE_TEMPERATURE_STORAGE {
+        {
+            command = "temperature_storage";
+            unit = CELSIUS;
+            tagName = "A16";
+        }
+    },
+
+    // German: Raumtemperatur
+    TYPE_TEMPERATURE_ROOM {
+        {
+            command = "temperature_room";
+            unit = CELSIUS;
+            tagName = "A17";
+        }
+    },
+
+    // German: Raumtemperatur gemittelt über 1h
+    TYPE_TEMPERATURE_ROOM_1H {
+        {
+            command = "temperature_room_1h";
+            unit = CELSIUS;
+            tagName = "A18";
+        }
+    },
+
+    // German: Warmwassertemperatur
+    TYPE_TEMPERATURE_WATER {
+        {
+            command = "temperature_water";
+            unit = CELSIUS;
+            tagName = "A19";
+        }
+    },
+
+    // German: Pooltemperatur
+    TYPE_TEMPERATURE_POOL {
+        {
+            command = "temperature_pool";
+            unit = CELSIUS;
+            tagName = "A20";
+        }
+    },
+
+    // German: Solarkollektortemperatur
+    TYPE_TEMPERATURE_SOLAR {
+        {
+            command = "temperature_solar";
+            unit = CELSIUS;
+            tagName = "A21";
+        }
+    },
+
+    // German: Solarkreis Vorlauf
+    TYPE_TEMPERATURE_SOLAR_FLOW {
+        {
+            command = "temperature_solar_flow";
+            unit = CELSIUS;
+            tagName = "A22";
+        }
+    },
+
+    // German: Ventilöffnung elektrisches Expansionsventil
+    TYPE_POSITION_EXPANSION_VALVE {
+        {
+            command = "position_expansion_valve";
+            unit = PERCENT;
+            tagName = "A23";
+        }
+    },
+
+    // German: elektrische Leistung Verdichter
+    TYPE_POWER_COMPRESSOR {
+        {
+            command = "power_compressor";
+            unit = KILO(WATT);
+            tagName = "A25";
+        }
+    },
+
+    // German: abgegebene thermische Heizleistung der Wärmepumpe
+    TYPE_POWER_HEATING {
+        {
+            command = "power_heating";
+            unit = KILO(WATT);
+            tagName = "A26";
+        }
+    },
+
+    // German: abgegebene thermische KälteLeistung der Wärmepumpe
+    TYPE_POWER_COOLING {
+        {
+            command = "power_cooling";
+            unit = KILO(WATT);
+            tagName = "A27";
+        }
+    },
+
+    // German: COP Heizleistung
+    TYPE_COP_HEATING {
+        {
+            command = "cop_heating";
+            tagName = "A28";
+        }
+    },
+
+    // German: COP Kälteleistungleistung
+    TYPE_COP_COOLING {
+        {
+            command = "cop_cooling";
+            tagName = "A29";
+        }
+    },
+
+    // German: Aktuelle Heizkreistemperatur
+    TYPE_TEMPERATURE_HEATING {
+        {
+            command = "temperature_heating_return";
+            unit = CELSIUS;
+            tagName = "A30";
+        }
+    },
+
+    // German: Geforderte Temperatur im Heizbetrieb
+    TYPE_TEMPERATURE_HEATING_SET {
+        {
+            command = "temperature_heating_set";
+            unit = CELSIUS;
+            tagName = "A31";
+        }
+    },
+
+    // German: Sollwertvorgabe Heizkreistemperatur
+    TYPE_TEMPERATURE_HEATING_SET2 {
+        {
+            command = "temperature_heating_set2";
+            unit = CELSIUS;
+            tagName = "A32";
+        }
+    },
+
+    // German: Aktuelle Kühlkreistemperatur
+    TYPE_TEMPERATURE_COOLING {
+        {
+            command = "temperature_cooling_return";
+            unit = CELSIUS;
+            tagName = "A33";
+        }
+    },
+
+    // German: Geforderte Temperatur im Kühlbetrieb
+    TYPE_TEMPERATURE_COOLING_SET {
+        {
+            command = "temperature_cooling_set";
+            unit = CELSIUS;
+            tagName = "A34";
+        }
+    },
+
+    // German: Sollwertvorgabe Kühlbetrieb
+    TYPE_TEMPERATURE_COOLING_SET2 {
+        {
+            command = "temperature_cooling_set2";
+            unit = CELSIUS;
+            tagName = "A35";
+        }
+    },
+
+    // German: Sollwert Warmwassertemperatur
+    TYPE_TEMPERATURE_WATER_SET {
+        {
+            command = "temperature_water_set";
+            unit = CELSIUS;
+            tagName = "A37";
+        }
+    },
+
+    // German: Sollwertvorgabe Warmwassertemperatur
+    TYPE_TEMPERATURE_WATER_SET2 {
+        {
+            command = "temperature_water_set2";
+            unit = CELSIUS;
+            tagName = "A38";
+        }
+    },
+
+    // German: Sollwert Poolwassertemperatur
+    TYPE_TEMPERATURE_POOL_SET {
+        {
+            command = "temperature_pool_set";
+            unit = CELSIUS;
+            tagName = "A40";
+        }
+    },
+
+    // German: Sollwertvorgabe Poolwassertemperatur
+    TYPE_TEMPERATURE_POOL_SET2 {
+        {
+            command = "temperature_pool_set2";
+            unit = CELSIUS;
+            tagName = "A41";
+        }
+    },
+
+    // German: geforderte Verdichterleistung
+    TYPE_COMPRESSOR_POWER {
+        {
+            command = "compressor_power";
+            unit = PERCENT;
+            tagName = "A50";
+        }
+    },
+
+    // German: % Heizungsumwälzpumpe
+    TYPE_PERCENT_HEAT_CIRC_PUMP {
+        {
+            command = "percent_heat_circ_pump";
+            unit = PERCENT;
+            tagName = "A51";
+        }
+    },
+
+    // German: % Quellenpumpe
+    TYPE_PERCENT_SOURCE_PUMP {
+        {
+            command = "percent_source_pump";
+            unit = PERCENT;
+            tagName = "A52";
+        }
+    },
+
+    // German: % Leistung Verdichter
+    TYPE_PERCENT_COMPRESSOR {
+        {
+            command = "percent_compressor";
+            unit = PERCENT;
+            tagName = "A58";
+        }
+    },
+
+    // German: Hysterese Heizung
+    TYPE_HYSTERESIS_HEATING {
+        {
+            command = "hysteresis_heating";
+            unit = CELSIUS;
+            tagName = "A61";
+        }
+    },
+
+    // German: Außentemperatur gemittelt über 1h (scheinbar identisch zu A2)
+    TYPE_TEMPERATURE2_OUTSIDE_1H {
+        {
+            command = "temperature2_outside_1h";
+            unit = CELSIUS;
+            tagName = "A90";
+        }
+    },
+
+    // German: Heizkurve - nviNormAussen
+    TYPE_NVINORMAUSSEN {
+        {
+            command = "nviNormAussen";
+            unit = CELSIUS;
+            tagName = "A91";
+        }
+    },
+
+    // German: Heizkurve - nviHeizkreisNorm
+    TYPE_NVIHEIZKREISNORM {
+        {
+            command = "nviHeizkreisNorm";
+            unit = CELSIUS;
+            tagName = "A92";
+        }
+    },
+
+    // German: Heizkurve - nviTHeizgrenze
+    TYPE_NVITHEIZGRENZE {
+        {
+            command = "nviTHeizgrenze";
+            unit = CELSIUS;
+            tagName = "A93";
+        }
+    },
+
+    // German: Heizkurve - nviTHeizgrenzeSoll
+    TYPE_NVITHEIZGRENZESOLL {
+        {
+            command = "nviTHeizgrenzeSoll";
+            unit = CELSIUS;
+            tagName = "A94";
+        }
+    },
+
+    // German: undokumentiert: Heizkurve max. VL-Temp (??)
+    TYPE_MAX_VL_TEMP {
+        {
+            command = "maxVLTemp";
+            unit = CELSIUS;
+            tagName = "A95";
+        }
+    },
+
+    // German: undokumentiert: Heizkreis Soll-Temp bei 0° Aussen
+    TYPE_TEMP_SET_0DEG {
+        {
+            command = "tempSet0Deg";
+            unit = CELSIUS;
+            tagName = "A97";
+        }
+    },
+
+    // German: Raum Soll
+    TYPE_TEMP_ROOM_SET {
+        {
+            command = "tempRoomSet";
+            unit = CELSIUS;
+            tagName = "A100";
+        }
+    },
+
+    // German: undokumentiert: Kühlen Einschalt-Temp. Aussentemp (??)
+    TYPE_COOLENABLETEMP {
+        {
+            command = "coolEnableTemp";
+            unit = CELSIUS;
+            tagName = "A108";
+        }
+    },
+
+    // German: Heizkurve - nviSollKuehlen
+    TYPE_NVITSOLLKUEHLEN {
+        {
+            command = "nviSollKuehlen";
+            unit = CELSIUS;
+            tagName = "A109";
+        }
+    },
+
+    // German: Temperaturveränderung Heizkreis bei PV-Ertrag
+    TYPE_TEMPCHANGE_HEATING_PV {
+        {
+            command = "tempchange_heating_pv";
+            unit = CELSIUS;
+            tagName = "A682";
+        }
+    },
+
+    // German: Temperaturveränderung Kühlkreis bei PV-Ertrag
+    TYPE_TEMPCHANGE_COOLING_PV {
+        {
+            command = "tempchange_cooling_pv";
+            unit = CELSIUS;
+            tagName = "A683";
+        }
+    },
+
+    // German: Temperaturveränderung Warmwasser bei PV-Ertrag
+    TYPE_TEMPCHANGE_WARMWATER_PV {
+        {
+            command = "tempchange_warmwater_pv";
+            unit = CELSIUS;
+            tagName = "A684";
+        }
+    },
+
+    // German: Temperaturveränderung Pool bei PV-Ertrag
+    TYPE_TEMPCHANGE_POOL_PV {
+        {
+            command = "tempchange_pool_pv";
+            unit = CELSIUS;
+            tagName = "A685";
+        }
+    },
+
+    // German: undokumentiert: Firmware-Version Regler
+    // value 10401 => 01.04.01
+    TYPE_VERSION_CONTROLLER {
+        {
+            command = "version_controller";
+            divisor = 1;
+            tagName = "I1";
+            type = Type.Word;
+        }
+    },
+
+    // German: undokumentiert: Firmware-Build Regler
+    TYPE_VERSION_CONTROLLER_BUILD {
+        {
+            command = "version_controller_build";
+            divisor = 1;
+            tagName = "I2";
+            type = Type.Word;
+        }
+    },
+
+    // German: undokumentiert: BIOS-Version
+    // value 620 => 06.20
+    TYPE_VERSION_BIOS {
+        {
+            command = "version_bios";
+            divisor = 1;
+            tagName = "I3";
+            type = Type.Word;
+        }
+    },
+
+    // German: undokumentiert: Datum: Tag
+    TYPE_DATE_DAY {
+        {
+            command = "date_day";
+            divisor = 1;
+            tagName = "I5";
+            type = Type.Word;
+        }
+    },
+
+    // German: undokumentiert: Datum: Monat
+    TYPE_DATE_MONTH {
+        {
+            command = "date_month";
+            divisor = 1;
+            tagName = "I6";
+            type = Type.Word;
+        }
+    },
+
+    // German: undokumentiert: Datum: Jahr
+    TYPE_DATE_YEAR {
+        {
+            command = "date_year";
+            divisor = 1;
+            tagName = "I7";
+            type = Type.Word;
+        }
+    },
+
+    // German: undokumentiert: Uhrzeit: Stunde
+    TYPE_TIME_HOUR {
+        {
+            command = "time_hour";
+            divisor = 1;
+            tagName = "I8";
+            type = Type.Word;
+        }
+    },
+
+    // German: undokumentiert: Uhrzeit: Minute
+    TYPE_TIME_MINUTE {
+        {
+            command = "time_minute";
+            divisor = 1;
+            tagName = "I9";
+            type = Type.Word;
+        }
+    },
+
+    // German: Betriebsstunden Verdichter 1
+    TYPE_OPERATING_HOURS_COMPRESSOR1 {
+        {
+            command = "operating_hours_compressor1";
+            divisor = 1;
+            unit = HOUR;
+            tagName = "I10";
+            type = Type.Word;
+        }
+    },
+
+    // German: Betriebsstunden Verdichter 2
+    TYPE_OPERATING_HOURS_COMPRESSOR2 {
+        {
+            command = "operating_hours_compressor2";
+            divisor = 1;
+            unit = HOUR;
+            tagName = "I14";
+            type = Type.Word;
+        }
+    },
+
+    // German: Betriebsstunden Heizungsumwälzpumpe
+    TYPE_OPERATING_HOURS_CIRCULATION_PUMP {
+        {
+            command = "operating_hours_circulation_pump";
+            divisor = 1;
+            unit = HOUR;
+            tagName = "I18";
+            type = Type.Word;
+        }
+    },
+
+    // German: Betriebsstunden Quellenpumpe
+    TYPE_OPERATING_HOURS_SOURCE_PUMP {
+        {
+            command = "operating_hours_source_pump";
+            divisor = 1;
+            unit = HOUR;
+            tagName = "I20";
+            type = Type.Word;
+        }
+    },
+
+    // German: Betriebsstunden Solarkreis
+    TYPE_OPERATING_HOURS_SOLAR {
+        {
+            command = "operating_hours_solar";
+            divisor = 1;
+            unit = HOUR;
+            tagName = "I22";
+            type = Type.Word;
+        }
+    },
+
+    // German: Handabschaltung Heizbetrieb
+    TYPE_ENABLE_HEATING {
+        {
+            command = "enable_heating";
+            divisor = 1;
+            tagName = "I30";
+            type = Type.Word;
+        }
+    },
+
+    // German: Handabschaltung Kühlbetrieb
+    TYPE_ENABLE_COOLING {
+        {
+            command = "enable_cooling";
+            divisor = 1;
+            tagName = "I31";
+            type = Type.Word;
+        }
+    },
+
+    // German: Handabschaltung Warmwasserbetrieb
+    TYPE_ENABLE_WARMWATER {
+        {
+            command = "enable_warmwater";
+            divisor = 1;
+            tagName = "I32";
+            type = Type.Word;
+        }
+    },
+
+    // German: Handabschaltung Pool_Heizbetrieb
+    TYPE_ENABLE_POOL {
+        {
+            command = "enable_pool";
+            divisor = 1;
+            tagName = "I33";
+            type = Type.Word;
+        }
+    },
+
+    // German: undokumentiert: vermutlich Betriebsmodus PV 0=Aus, 1=Auto, 2=Ein
+    TYPE_ENABLE_PV {
+        {
+            command = "enable_pv";
+            divisor = 1;
+            tagName = "I41";
+            type = Type.Word;
+        }
+    },
+
+    // German: Status der Wärmepumpenkomponenten
+    TYPE_STATE {
+        {
+            command = "state";
+            divisor = 1;
+            tagName = "I51";
+            type = Type.Word;
+        }
+    },
+
+    // German: Status der Wärmepumpenkomponenten: Quellenpumpe
+    TYPE_STATE_SOURCEPUMP {
+        {
+            command = "state_sourcepump";
+            tagName = "I51";
+            type = Type.Bitfield;
+            bitnum = 0;
+        }
+    },
+
+    // German: Status der Wärmepumpenkomponenten: Heizungsumwälzpumpe
+    TYPE_STATE_HEATINGPUMP {
+        {
+            command = "state_heatingpump";
+            tagName = "I51";
+            type = Type.Bitfield;
+            bitnum = 1;
+        }
+    },
+
+    // German: Status der Wärmepumpenkomponenten: Freigabe Regelung EVD /
+    // Magnetventil
+    TYPE_STATE_EVD {
+        {
+            command = "state_evd";
+            tagName = "I51";
+            type = Type.Bitfield;
+            bitnum = 2;
+        }
+    },
+
+    // German: Status der Wärmepumpenkomponenten: Verdichter 1
+    TYPE_STATE_compressor1 {
+        {
+            command = "state_compressor1";
+            tagName = "I51";
+            type = Type.Bitfield;
+            bitnum = 3;
+        }
+    },
+
+    // German: Status der Wärmepumpenkomponenten: Verdichter 2
+    TYPE_STATE_compressor2 {
+        {
+            command = "state_compressor2";
+            tagName = "I51";
+            type = Type.Bitfield;
+            bitnum = 4;
+        }
+    },
+
+    // German: Status der Wärmepumpenkomponenten: externer Wärmeerzeuger
+    TYPE_STATE_extheater {
+        {
+            command = "state_extheater";
+            tagName = "I51";
+            type = Type.Bitfield;
+            bitnum = 5;
+        }
+    },
+
+    // German: Status der Wärmepumpenkomponenten: Alarmausgang
+    TYPE_STATE_alarm {
+        {
+            command = "state_alarm";
+            tagName = "I51";
+            type = Type.Bitfield;
+            bitnum = 6;
+        }
+    },
+
+    // German: Status der Wärmepumpenkomponenten: Motorventil Kühlbetrieb
+    TYPE_STATE_cooling {
+        {
+            command = "state_cooling";
+            tagName = "I51";
+            type = Type.Bitfield;
+            bitnum = 7;
+        }
+    },
+
+    // German: Status der Wärmepumpenkomponenten: Motorventil Warmwasser
+    TYPE_STATE_water {
+        {
+            command = "state_water";
+            tagName = "I51";
+            type = Type.Bitfield;
+            bitnum = 8;
+        }
+    },
+
+    // German: Status der Wärmepumpenkomponenten: Motorventil Pool
+    TYPE_STATE_pool {
+        {
+            command = "state_pool";
+            tagName = "I51";
+            type = Type.Bitfield;
+            bitnum = 9;
+        }
+    },
+
+    // German: Status der Wärmepumpenkomponenten: Solarbetrieb
+    TYPE_STATE_solar {
+        {
+            command = "state_solar";
+            tagName = "I51";
+            type = Type.Bitfield;
+            bitnum = 10;
+        }
+    },
+
+    // German: Status der Wärmepumpenkomponenten: 4-Wegeventil im Kältekreis
+    TYPE_STATE_cooling4way {
+        {
+            command = "state_cooling4way";
+            tagName = "I51";
+            type = Type.Bitfield;
+            bitnum = 11;
+        }
+    },
+
+    // German: Meldungen von Ausfällen F0xx die zum Wärmepumpenausfall führen
+    TYPE_ALARM {
+        {
+            command = "alarm";
+            divisor = 1;
+            tagName = "I52";
+            type = Type.Word;
+        }
+    },
+
+    // German: Unterbrechungen
+    TYPE_INTERRUPTIONS {
+        {
+            command = "interruptions";
+            divisor = 1;
+            tagName = "I53";
+            type = Type.Word;
+        }
+    },
+
+    // German: Serviceebene (0: normal, 1: service)
+    TYPE_STATE_SERVICE {
+        {
+            command = "state_service";
+            divisor = 1;
+            tagName = "I135";
+            type = Type.Word;
+        }
+    },
+
+    // German: Temperaturanpassung für die Heizung
+    TYPE_ADAPT_HEATING {
+        {
+            command = "adapt_heating";
+            divisor = 1;
+            tagName = "I263";
+            type = Type.Word; // value range 0..8 => -2K .. +2K
+        }
+    },
+
+    // German: Raumeinfluss
+    TYPE_TEMP_ROOM_INFLUENCE {
+        {
+            command = "tempRoomInfluence";
+            divisor = 1;
+            tagName = "I264";
+            type = Type.Word; // value range 0..4 => 0%, 50%, 100%, 150%, 200%
+        }
+    },
+
+    // German: Handschaltung Heizungspumpe (H-0-A)
+    // H:Handschaltung Ein 0:Aus A:Automatik
+    // Kodierung: 0:? 1:? 2:Automatik
+    TYPE_MANUAL_HEATINGPUMP {
+        {
+            command = "manual_heatingpump";
+            divisor = 1;
+            tagName = "I1270";
+            type = Type.Word;
+        }
+    },
+
+    // German: Handschaltung Quellenpumpe (H-0-A)
+    TYPE_MANUAL_SOURCEPUMP {
+        {
+            command = "manual_sourcepump";
+            divisor = 1;
+            tagName = "I1281";
+            type = Type.Word;
+        }
+    },
+
+    // German: Handschaltung Solarpumpe 1 (H-0-A)
+    TYPE_MANUAL_SOLARPUMP1 {
+        {
+            command = "manual_solarpump1";
+            divisor = 1;
+            tagName = "I1287";
+            type = Type.Word;
+        }
+    },
+
+    // German: Handschaltung Solarpumpe 2 (H-0-A)
+    TYPE_MANUAL_SOLARPUMP2 {
+        {
+            command = "manual_solarpump2";
+            divisor = 1;
+            tagName = "I1289";
+            type = Type.Word;
+        }
+    },
+
+    // German: Handschaltung Speicherladepumpe (H-0-A)
+    TYPE_MANUAL_TANKPUMP {
+        {
+            command = "manual_tankpump";
+            divisor = 1;
+            tagName = "I1291";
+            type = Type.Word;
+        }
+    },
+
+    // German: Handschaltung Brauchwasserventil (H-0-A)
+    TYPE_MANUAL_VALVE {
+        {
+            command = "manual_valve";
+            divisor = 1;
+            tagName = "I1293";
+            type = Type.Word;
+        }
+    },
+
+    // German: Handschaltung Poolventil (H-0-A)
+    TYPE_MANUAL_POOLVALVE {
+        {
+            command = "manual_poolvalve";
+            divisor = 1;
+            tagName = "I1295";
+            type = Type.Word;
+        }
+    },
+
+    // German: Handschaltung Kühlventil (H-0-A)
+    TYPE_MANUAL_COOLVALVE {
+        {
+            command = "manual_coolvalve";
+            divisor = 1;
+            tagName = "I1297";
+            type = Type.Word;
+        }
+    },
+
+    // German: Handschaltung Vierwegeventil (H-0-A)
+    TYPE_MANUAL_4WAYVALVE {
+        {
+            command = "manual_4wayvalve";
+            divisor = 1;
+            tagName = "I1299";
+            type = Type.Word;
+        }
+    },
+
+    // German: Handschaltung Multiausgang Ext. (H-0-A)
+    TYPE_MANUAL_MULTIEXT {
+        {
+            command = "manual_multiext";
+            divisor = 1;
+            tagName = "I1319";
+            type = Type.Word;
+        }
+    },
+
+    // German: Umgebung
+    TYPE_TEMPERATURE_SURROUNDING {
+        {
+            command = "temperature_surrounding";
+            unit = CELSIUS;
+            tagName = "I2020";
+            type = Type.Analog;
+            divisor = 100;
+        }
+    },
+
+    // German: Sauggas
+    TYPE_TEMPERATURE_SUCTION_AIR {
+        {
+            command = "temperature_suction_air";
+            unit = CELSIUS;
+            tagName = "I2021";
+            type = Type.Analog;
+            divisor = 100;
+        }
+    },
+
+    // German: Ölsumpf
+    TYPE_TEMPERATURE_SUMP {
+        {
+            command = "temperature_sump";
+            unit = CELSIUS;
+            tagName = "I2023";
+            type = Type.Analog;
+            divisor = 100;
+        }
+    },
+
+    //
+    // The following tags are only available, if an Ecovent System is attached to the Ecotouch
+    //
+
+    // German: Abluft
+    // Waterkotte reference: airventilation-temperature-1
+    TYPE_ECOVENT_TEMP_EXHAUST_AIR {
+        {
+            command = "ecovent_temp_exhaust_air";
+            unit = CELSIUS;
+            tagName = "3:HREG400000";
+            type = Type.Float;
+            divisor = 1;
+        }
+    },
+
+    // German: Fortluft
+    // Waterkotte reference: airventilation-temperature-2
+    TYPE_ECOVENT_TEMP_EXIT_AIR {
+        {
+            command = "ecovent_temp_exit_air";
+            unit = CELSIUS;
+            tagName = "3:HREG400002";
+            type = Type.Float;
+            divisor = 1;
+        }
+    },
+
+    // German: Außenluft
+    // Waterkotte reference: airventilation-temperature-3
+    TYPE_ECOVENT_TEMP_OUTDOOR_AIR {
+        {
+            command = "ecovent_temp_outdoor_air";
+            unit = CELSIUS;
+            tagName = "3:HREG400004";
+            type = Type.Float;
+            divisor = 1;
+        }
+    },
+
+    // German: Zuluft
+    // Waterkotte reference: airventilation-temperature-4
+    TYPE_ECOVENT_TEMP_SUPPLY_AIR {
+        {
+            command = "ecovent_temp_supply_air";
+            unit = CELSIUS;
+            tagName = "3:HREG400006";
+            type = Type.Float;
+            divisor = 1;
+        }
+    },
+
+    // German: CO2
+    // Waterkotte reference: airventilation-co2-value
+    TYPE_ECOVENT_CO2_VALUE {
+        {
+            command = "ecovent_CO2_value";
+            unit = PARTS_PER_MILLION;
+            tagName = "3:HREG400008";
+            type = Type.Float;
+            divisor = 1;
+        }
+    },
+
+    // German: Luftfeuchtigkeit
+    // Waterkotte reference: airventilation-air-moisture-value
+    TYPE_ECOVENT_MOISTURE_VALUE {
+        {
+            command = "ecovent_moisture_value";
+            unit = PARTS_PER_MILLION;
+            tagName = "3:HREG400010";
+            type = Type.Float;
+            divisor = 1;
+        }
+    },
+
+    // German: Lüfterdrehzahl
+    // Waterkotte reference: airventilation-analog-output-y1
+    TYPE_ECOVENT_OUTPUT_Y1 {
+        {
+            command = "ecovent_output_y1";
+            unit = PERCENT;
+            tagName = "3:HREG400014";
+            type = Type.Float;
+            divisor = 1;
+        }
+    },
+
+    TYPE_ECOVENT_MODE {
+        {
+            command = "ecovent_mode";
+            tagName = "I4582";
+            type = Type.Word; // Type.Enum;
+            divisor = 1;
+            stringEnum = new String[] { "Day Mode", "Night Mode", "Timer Mode", "Party Mode", "Vacation Mode",
+                    "Bypass Mode" };
+        }
+    },
+
+    ;
+
+    /**
+     * Represents the heatpump command as it will be used in *.items
+     * configuration
+     */
+    String command;
+    /**
+     * Represents the internal raw heatpump command as it will be used in
+     * querying the heat pump
+     */
+    String tagName;
+
+    Unit<?> unit = ONE;
+
+    /**
+     * The heatpump always returns 16-bit integers encoded as ASCII. They need
+     * to be interpreted according to the context.
+     * The EcoVent unit returns floating point numbers.
+     */
+    public enum Type {
+        Analog,
+        Word,
+        Bitfield,
+        Float,
+        Enum
+    };
+
+    /**
+     * The format of the response of the heat pump
+     */
+    Type type = Type.Analog;
+
+    /**
+     * If \c type is Type.Bitfield, this determines the bit number (0-based)
+     */
+    int bitnum = 0;
+
+    /**
+     * If type is anything else than {@link Type#Bitfield} this is used as divisor for the scaled integer.
+     * Defaults to 10 and should be a power of 10 (e.g. 10, 100, 1000).
+     */
+    int divisor = 10;
+
+    /**
+     * If \c type is Type.Enum, this defines the meaning of the values (0-based)
+     */
+    String[] stringEnum = null;
+
+    /**
+     * @return command name (uses in *.items files)
+     */
+    public String getCommand() {
+        return command;
+    }
+
+    /**
+     * @return tag name (raw communication with heat pump)
+     */
+    public String getTagName() {
+        return tagName;
+    }
+
+    /**
+     * @return type: how to interpret the response from the heat pump
+     */
+    public Type getType() {
+        return type;
+    }
+
+    /**
+     * @return bitnum: if the value is a bit field, this indicates the bit
+     *         number (0-based)
+     */
+    public int getBitNum() {
+        return bitnum;
+    }
+
+    /**
+     * @return Divisor for scaled integer analog values.
+     */
+    public int getDivisor() {
+        return divisor;
+    }
+
+    public Unit<?> getUnit() {
+        return unit;
+    }
+
+    /**
+     *
+     * @param bindingConfig
+     *            command e.g. TYPE_TEMPERATURE_OUTSIDE,..
+     * @param itemClass
+     *            class to validate
+     * @return true if item class can bound to heatpumpCommand
+     */
+    // public static boolean validateBinding(EcoTouchTags bindingConfig, Class<? extends Item> itemClass) {
+    // boolean ret = false;
+    // for (EcoTouchTags c : EcoTouchTags.values()) {
+    // if (c.getCommand().equals(bindingConfig.getCommand()) && c.getItemClass().equals(itemClass)) {
+    // ret = true;
+    // break;
+    // }
+    // }
+    // return ret;
+    // }
+
+    /**
+     * Decode a raw value from the heat pump's ethernet interface into a scaled value
+     * 
+     * @param rawValue
+     * @return
+     */
+    public BigDecimal decodeValue(String rawValue) {
+        BigDecimal raw = new BigDecimal(rawValue);
+        if (type == Type.Bitfield) {
+            // ignore any scaling from \ref divisor
+            int value = raw.intValue();
+            if ((value & (1 << bitnum)) != 0)
+                return BigDecimal.ONE;
+            else
+                return BigDecimal.ZERO;
+        }
+        BigDecimal result = raw.divide(new BigDecimal(divisor));
+        return result;
+    }
+
+    /**
+     * Searches the available heat pump commands and returns the matching one.
+     *
+     * @param heatpumpCommand
+     *            command string e.g. "temperature_outside"
+     * @return matching EcoTouchTags instance, if available
+     */
+    public static EcoTouchTags fromString(String heatpumpCommand) {
+        if ("".equals(heatpumpCommand)) {
+            return null;
+        }
+        for (EcoTouchTags c : EcoTouchTags.values()) {
+            if (c.getCommand().equals(heatpumpCommand)) {
+                return c;
+            }
+        }
+
+        throw new IllegalArgumentException("cannot find EcoTouch tag for '" + heatpumpCommand + "'");
+    }
+
+    /**
+     * Searches the available heat pump commands and returns the first matching
+     * one.
+     *
+     * @param tag
+     *            raw heatpump tag e.g. "A1"
+     * @return first matching EcoTouchTags instance, if available
+     */
+    public static List<EcoTouchTags> fromTag(String tag) {
+        List<EcoTouchTags> result = new LinkedList<EcoTouchTags>();
+        for (EcoTouchTags c : EcoTouchTags.values()) {
+            if (c.getTagName().equals(tag)) {
+                result.add(c);
+            }
+        }
+
+        return result;
+    }
+}
diff --git a/bundles/org.openhab.binding.ecotouch/src/main/resources/OH-INF/binding/binding.xml b/bundles/org.openhab.binding.ecotouch/src/main/resources/OH-INF/binding/binding.xml
new file mode 100644 (file)
index 0000000..5fc729e
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<binding:binding id="ecotouch" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
+       xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
+
+       <name>EcoTouch Binding</name>
+       <description>This is the binding for a Waterkotte EcoTouch heat pump.</description>
+       <author>Sebastian Held</author>
+
+</binding:binding>
diff --git a/bundles/org.openhab.binding.ecotouch/src/main/resources/OH-INF/i18n/ecotouch_de.properties b/bundles/org.openhab.binding.ecotouch/src/main/resources/OH-INF/i18n/ecotouch_de.properties
new file mode 100644 (file)
index 0000000..6455c73
--- /dev/null
@@ -0,0 +1,247 @@
+# binding
+binding.ecotouch.name = EcoTouch Binding
+binding.ecotouch.description = Überwachung und Steuerung von Waterkotte EcoTouch Wärmepumpen
+
+# thing types (geo)
+thing-type.ecotouch.geo.label = Waterkotte EcoTouch Geo
+thing-type.ecotouch.geo.description = Waterkotte EcoTouch Geo Erdwärmepumpe
+
+# thing types (air)
+thing-type.ecotouch.air.label = Waterkotte EcoTouch Air
+thing-type.ecotouch.air.description = Waterkotte EcoTouch Air Luftwärmepumpe
+
+# thing type config description (geo)
+thing-type.config.ecotouch.geo.ip.label = IP Adresse / Hostname
+thing-type.config.ecotouch.geo.ip.description = IP Adresse oder Hostname der EcoTouch Anzeigeeinheit
+thing-type.config.ecotouch.geo.username.label = Login Benutzername
+thing-type.config.ecotouch.geo.username.description = Seit Software Version 1.6.xx der Anzeigeeinheit ist der Benutzername "waterkotte". Davor war es "admin".
+thing-type.config.ecotouch.geo.password.label = Login Passwort
+thing-type.config.ecotouch.geo.password.description = Seit Software Version 1.6.xx der Anzeigeeinheit ist das Passwort "waterkotte". Davor war es "wtkadmin".
+
+# thing type config description (air)
+thing-type.config.ecotouch.air.ip.label = IP Adresse / Hostname
+thing-type.config.ecotouch.air.ip.description = IP Adresse oder Hostname der EcoTouch Anzeigeeinheit
+thing-type.config.ecotouch.air.username.label = Login Benutzername
+thing-type.config.ecotouch.air.username.description = Seit Software Version 1.6.xx der Anzeigeeinheit ist der Benutzername "waterkotte". Davor war es "admin".
+thing-type.config.ecotouch.air.password.label = Login Passwort
+thing-type.config.ecotouch.air.password.description = Seit Software Version 1.6.xx der Anzeigeeinheit ist das Passwort "waterkotte". Davor war es "wtkadmin".
+
+# channel types
+channel-type.ecotouch.temperature_outside.label = Außentemperatur
+channel-type.ecotouch.temperature_outside.description = Aktuelle Außentemperatur
+channel-type.ecotouch.temperature_outside_1h.label = Außentemperatur gemittelt 1h
+channel-type.ecotouch.temperature_outside_1h.description = Außentemperatur gemittelt über 1 Stunde
+channel-type.ecotouch.temperature_outside_24h.label = Außentemperatur gemittelt 24h
+channel-type.ecotouch.temperature_outside_24h.description = Außentemperatur gemittelt über 24 Stunden
+channel-type.ecotouch.temperature_source_in.label = Quelleneintrittstemperatur
+channel-type.ecotouch.temperature_source_in.description = Quelleneintrittstemperatur
+channel-type.ecotouch.temperature_source_out.label = Quellenaustrittstemperatur
+channel-type.ecotouch.temperature_source_out.description = Quellenaustrittstemperatur
+channel-type.ecotouch.temperature_evaporation.label = Verdampfungstemperatur
+channel-type.ecotouch.temperature_evaporation.description = Verdampfungstemperatur
+channel-type.ecotouch.temperature_suction.label = Sauggastemperatur
+channel-type.ecotouch.temperature_suction.description = Sauggastemperatur
+channel-type.ecotouch.pressure_evaporation.label = Verdampfungsdruck
+channel-type.ecotouch.pressure_evaporation.description = Verdampfungsdruck
+channel-type.ecotouch.temperature_return_set.label = Temperatur Rücklauf Soll
+channel-type.ecotouch.temperature_return_set.description = Temperatur Rücklauf Soll
+channel-type.ecotouch.temperature_return.label = Rücklauftemperatur
+channel-type.ecotouch.temperature_return.description = Rücklauftemperatur
+channel-type.ecotouch.temperature_flow.label = Vorlauftemperatur
+channel-type.ecotouch.temperature_flow.description = Vorlauftemperatur
+channel-type.ecotouch.temperature_condensation.label = Kondensationstemperatur
+channel-type.ecotouch.temperature_condensation.description = Kondensationstemperatur
+channel-type.ecotouch.pressure_condensation.label = Kondensationsdruck
+channel-type.ecotouch.pressure_condensation.description = Kondensationsdruck
+channel-type.ecotouch.temperature_storage.label = Speichertemperatur
+channel-type.ecotouch.temperature_storage.description = Speichertemperatur
+channel-type.ecotouch.temperature_room.label = Raumtemperatur
+channel-type.ecotouch.temperature_room.description = Raumtemperatur
+channel-type.ecotouch.temperature_room_1h.label = Raumtemperatur gemittelt 1h
+channel-type.ecotouch.temperature_room_1h.description = Raumtemperatur gemittelt über 1 Stunde
+channel-type.ecotouch.temperature_water.label = Warmwassertemperatur
+channel-type.ecotouch.temperature_water.description = Aktuelle Temperatur im Warmwasserspeicher
+channel-type.ecotouch.temperature_pool.label = Pool-Temperatur
+channel-type.ecotouch.temperature_pool.description = Pool-Temperatur
+channel-type.ecotouch.temperature_solarlabel = Solarkollektortemperatur
+channel-type.ecotouch.temperature_solar.description = Solarkollektortemperatur
+channel-type.ecotouch.temperature_solar_flow.label = Solarkreis Vorlauftemperatur
+channel-type.ecotouch.temperature_solar_flow.description = Solarkreis Vorlauftemperatur
+channel-type.ecotouch.position_expansion_valve.label = Ventilöffnung el. Expansionsventil
+channel-type.ecotouch.position_expansion_valve.description = Ventilöffnung elektrisches Expansionsventil
+channel-type.ecotouch.power_compressor.label = Elektrische Antriebsleitung Verdichter
+channel-type.ecotouch.power_compressor.description = Aktuelle elektrische Antriebsleitung für den Verdichter
+channel-type.ecotouch.power_heating.label = Thermische Wärmeleistungsabgabe
+channel-type.ecotouch.power_heating.description = Aktuelle abgegebene thermische Leistung der Wärmepumpe
+channel-type.ecotouch.power_cooling.label = Thermische Kälteleistungsabgabe
+channel-type.ecotouch.power_cooling.description = Aktuelle abgegebene thermische Kälteleistung der Wärmepumpe
+channel-type.ecotouch.cop_heating.label = COP heizen
+channel-type.ecotouch.cop_heating.description = Wirkungsgrad bzw. Leitungszahl heizen
+channel-type.ecotouch.cop_cooling.label = COP kühlen
+channel-type.ecotouch.cop_cooling.description = Wirkungsgrad bzw. Leitungszahl kühlen
+channel-type.ecotouch.temperature_heating_return.label = Heizkreistemperatur
+channel-type.ecotouch.temperature_heating_return.description = Aktuelle Heizkreistemperatur
+channel-type.ecotouch.temperature_heating_set.label = Sollwert Heizbetrieb
+channel-type.ecotouch.temperature_heating_set.description = Geforderte Temperatur im Heizbetrieb
+channel-type.ecotouch.temperature_heating_set2.label = BMS Sollwert Heizbetrieb
+channel-type.ecotouch.temperature_heating_set2.description = Geforderte Heizkreistemperatur vom BMS
+channel-type.ecotouch.temperature_cooling_return.label = Kühlkreistemperatur
+channel-type.ecotouch.temperature_cooling_return.description = Aktuelle Kühlkreistemperatur
+channel-type.ecotouch.temperature_cooling_set.label = Sollwert Kühlkreistemperatur
+channel-type.ecotouch.temperature_cooling_set.description = Geforderte Kühlkreistemperatur
+channel-type.ecotouch.temperature_cooling_set2.label = BMS Sollwert Kühlkreistemperatur
+channel-type.ecotouch.temperature_cooling_set2.description = Geforderte Kühlkreistemperatur vom BMS
+channel-type.ecotouch.temperature_water_set.label = Sollwert Warmwasserspeicher
+channel-type.ecotouch.temperature_water_set.description = Geforderte Temperatur im Warmwasserspeicher
+channel-type.ecotouch.temperature_water_set2.label = BMS Sollwert Warmwasserspeicher
+channel-type.ecotouch.temperature_water_set2.description = Solltemperatur im Warmwasserspeicher vom BMS
+channel-type.ecotouch.temperature_pool_set.label = Sollwert Pool-Temperatur
+channel-type.ecotouch.temperature_pool_set.description = Geforderte Poolwasser-Temperatur
+channel-type.ecotouch.temperature_pool_set2.label = BMS Sollwert Pool-Temperatur
+channel-type.ecotouch.temperature_pool_set2.description = Geforderte Poolwasser-Temperatur vom BMS
+channel-type.ecotouch.compressor_power.label = Sollwert Verdichter
+channel-type.ecotouch.compressor_power.description = Geforderte Verdichterleistung
+channel-type.ecotouch.percent_heat_circ_pump.label = Aktivität Heizungsumwälzpumpe
+channel-type.ecotouch.percent_heat_circ_pump.description = Aktivität Heizungsumwälzpumpe
+channel-type.ecotouch.percent_source_pump.label = Aktivität Quellenpumpe
+channel-type.ecotouch.percent_source_pump.description = Aktivität Quellenpumpe
+channel-type.ecotouch.percent_compressor.label = Aktivität Verdichter
+channel-type.ecotouch.percent_compressor.description = Aktivität Verdichter
+channel-type.ecotouch.hysteresis_heating.label = Hysterese Heizung
+channel-type.ecotouch.hysteresis_heating.description = Hysterese Heizung
+channel-type.ecotouch.temperature2_outside_1h.label = Außentemperatur gemittelt 1h (A90)
+channel-type.ecotouch.temperature2_outside_1h.description =  Außentemperatur gemittelt über 1 Stunde (A90)
+channel-type.ecotouch.nviNormAussen.label = Heizkurve - nviNormAussen
+channel-type.ecotouch.nviNormAussen.description = Heizkurve - nviNormAussen
+channel-type.ecotouch.nviHeizkreisNorm.label = Heizkurve - nviHeizkreisNorm
+channel-type.ecotouch.nviHeizkreisNorm.description = Heizkurve - nviHeizkreisNorm
+channel-type.ecotouch.nviTHeizgrenze.label = Heizkurve - nviTHeizgrenze
+channel-type.ecotouch.nviTHeizgrenze.description = Heizkurve - nviTHeizgrenze
+channel-type.ecotouch.nviTHeizgrenzeSoll.label = Heizkurve - nviTHeizgrenzeSoll
+channel-type.ecotouch.nviTHeizgrenzeSoll.description = Heizkurve - nviTHeizgrenzeSoll
+channel-type.ecotouch.maxVLTemp.label = Heizkurve max. VL-Temp (?)
+channel-type.ecotouch.maxVLTemp.description = Heizkurve max. VL-Temp (?)
+channel-type.ecotouch.tempSet0Deg.label = Heizkreis Soll-Temp 0°C
+channel-type.ecotouch.tempSet0Deg.description = Heizkreis Soll-Temp bei 0°C Außentemperatur
+channel-type.ecotouch.coolEnableTemp.label = Kühlen Einschalt-Temp. Außentemp (?)
+channel-type.ecotouch.coolEnableTemp.description = Kühlen Einschalt-Temp. Außentemp (?)
+channel-type.ecotouch.nviSollKuehlen.label = Heizkurve - nviSollKuehlen
+channel-type.ecotouch.nviSollKuehlen.description = Heizkurve - nviSollKuehlen
+channel-type.ecotouch.tempchange_heating_pv.label = Änderung Heizkreis PV
+channel-type.ecotouch.tempchange_heating_pv.description = Temperaturveränderung Heizkreis bei PV-Ertrag
+channel-type.ecotouch.tempchange_cooling_pv.label = Änderung Kühlkreis PV
+channel-type.ecotouch.tempchange_cooling_pv.description = Temperaturveränderung Kühlkreis bei PV-Ertrag
+channel-type.ecotouch.tempchange_warmwater_pv.label = Änderung Warmwasser PV
+channel-type.ecotouch.tempchange_warmwater_pv.description = Temperaturveränderung Warmwasser bei PV-Ertrag
+channel-type.ecotouch.tempchange_pool_pv.label = Änderung Pool PV
+channel-type.ecotouch.tempchange_pool_pv.description = Temperaturveränderung Pool bei PV-Ertrag
+channel-type.ecotouch.version_controller.label = Firmware-Version Regler
+channel-type.ecotouch.version_controller.description = Firmware-Version Regler
+channel-type.ecotouch.version_controller_build.label = Firmware-Build Regler
+channel-type.ecotouch.version_controller_build.description = Firmware-Build Regler
+channel-type.ecotouch.version_bios.label = BIOS-Version
+channel-type.ecotouch.version_bios.description = BIOS-Version
+channel-type.ecotouch.date_day.label = Datum: Tag
+channel-type.ecotouch.date_day.description = Datum: Tag
+channel-type.ecotouch.date_month.label = Datum: Monat
+channel-type.ecotouch.date_month.description = Datum: Monat
+channel-type.ecotouch.date_year.label = Datum: Jahr
+channel-type.ecotouch.date_year.description = Datum: Jahr
+channel-type.ecotouch.time_hour.label = Uhrzeit: Stunde
+channel-type.ecotouch.time_hour.description = Uhrzeit: Stunde
+channel-type.ecotouch.time_minute.label = Uhrzeit: Minute
+channel-type.ecotouch.time_minute.description = Uhrzeit: Minute
+channel-type.ecotouch.operating_hours_compressor1.label = Stunden Verdichter 1
+channel-type.ecotouch.operating_hours_compressor1.description = Betriebsstunden Verdichter 1
+channel-type.ecotouch.operating_hours_compressor2.label = Stunden Verdichter 2
+channel-type.ecotouch.operating_hours_compressor2.description = Betriebsstunden Verdichter 2
+channel-type.ecotouch.operating_hours_circulation_pump.label = Stunden Heizungsumwälzpumpe
+channel-type.ecotouch.operating_hours_circulation_pump.description = Betriebsstunden Heizungsumwälzpumpe
+channel-type.ecotouch.operating_hours_source_pump.label = Stunden Quellenpumpe
+channel-type.ecotouch.operating_hours_source_pump.description = Betriebsstunden Quellenpumpe
+channel-type.ecotouch.operating_hours_solar.label = Stunden Solarkreis
+channel-type.ecotouch.operating_hours_solar.description = Betriebsstunden Solarkreis
+channel-type.ecotouch.enable_heating.label = Abschaltung Heizen
+channel-type.ecotouch.enable_heating.description = Handabschaltung Heizbetrieb
+channel-type.ecotouch.enable_cooling.label = Abschaltung Kühlen
+channel-type.ecotouch.enable_cooling.description = Handabschaltung Kühlbetrieb
+channel-type.ecotouch.enable_warmwater.label = Abschaltung Warmwasser
+channel-type.ecotouch.enable_warmwater.description = Handabschaltung Warmwasserbetrieb
+channel-type.ecotouch.enable_pool.label = Abschaltung Pool
+channel-type.ecotouch.enable_pool.description = Handabschaltung Pool_Heizbetrieb
+channel-type.ecotouch.enable_pv.label = Abschaltung PV
+channel-type.ecotouch.enable_pv.description = Betriebsmodus PV
+channel-type.ecotouch.state.label = Status Wärmepumpe
+channel-type.ecotouch.state.description = Status der Wärmepumpenkomponenten (Bitfeld, siehe auch die Einzelzustände)
+channel-type.ecotouch.state_sourcepump.label = Status Quellenpumpe
+channel-type.ecotouch.state_sourcepump.description = Status der Wärmepumpenkomponenten: Quellenpumpe
+channel-type.ecotouch.state_heatingpump.label = Status Heizungsumwälzpumpe
+channel-type.ecotouch.state_heatingpump.description = Status der Wärmepumpenkomponenten: Heizungsumwälzpumpe
+channel-type.ecotouch.state_evd.label = Status el. Expansionsventil
+channel-type.ecotouch.state_evd.description = Status der Wärmepumpenkomponenten: el. Expansionsventil
+channel-type.ecotouch.state_compressor1.label = Status Verdichter 1
+channel-type.ecotouch.state_compressor1.description = Status der Wärmepumpenkomponenten: Verdichter 1
+channel-type.ecotouch.state_compressor2.label = Status Verdichter 2
+channel-type.ecotouch.state_compressor2.description = Status der Wärmepumpenkomponenten: Verdichter 2
+channel-type.ecotouch.state_extheater.label = Status ext. Wärmeerzeuger
+channel-type.ecotouch.state_extheater.description = Status der Wärmepumpenkomponenten: externer Wärmeerzeuger
+channel-type.ecotouch.state_alarm.label = Status Alarmausgang
+channel-type.ecotouch.state_alarm.description = Status der Wärmepumpenkomponenten: Alarmausgang
+channel-type.ecotouch.state_cooling.label = Status Motorventil Kühlen
+channel-type.ecotouch.state_cooling.description = Status der Wärmepumpenkomponenten: Motorventil Kühlbetrieb
+channel-type.ecotouch.state_water.label = Status Motorventil Wasser
+channel-type.ecotouch.state_water.description = Status der Wärmepumpenkomponenten: Motorventil Warmwasser
+channel-type.ecotouch.state_pool.label = Status Motorventil Pool
+channel-type.ecotouch.state_pool.description = Status der Wärmepumpenkomponenten: Motorventil Pool
+channel-type.ecotouch.state_solar.label = Status Solarbetrieb
+channel-type.ecotouch.state_solar.description = Status der Wärmepumpenkomponenten: Solarbetrieb
+channel-type.ecotouch.state_cooling4way.label = Status 4-Wegeventil
+channel-type.ecotouch.state_cooling4way.description = Status der Wärmepumpenkomponenten: 4-Wegeventil im Kältekreis
+channel-type.ecotouch.alarm.label = Alarmmeldungen
+channel-type.ecotouch.alarm.description = Meldungen von Ausfällen F0xx die zum Wärmepumpenausfall führen
+channel-type.ecotouch.interruptions.label = Unterbrechungen
+channel-type.ecotouch.interruptions.description = Unterbrechungen
+channel-type.ecotouch.state_service.label = Serviceebene
+channel-type.ecotouch.state_service.description = Serviceebene
+channel-type.ecotouch.adapt_heating.label = Temperaturanpassung heizen
+channel-type.ecotouch.adapt_heating.description = Temperaturanpassung für die Heizung
+channel-type.ecotouch.manual_heatingpump.label = Heizungspumpe
+channel-type.ecotouch.manual_heatingpump.description = Handschaltung Heizungspumpe
+channel-type.ecotouch.manual_sourcepump.label = Quellenpumpe
+channel-type.ecotouch.manual_sourcepump.description = Handschaltung Quellenpumpe
+channel-type.ecotouch.manual_solarpump1.label = Solarpumpe 1
+channel-type.ecotouch.manual_solarpump1.description = Handschaltung Solarpumpe 1
+channel-type.ecotouch.manual_solarpump2.label = Solarpumpe 2
+channel-type.ecotouch.manual_solarpump2.description = Handschaltung Solarpumpe 2
+channel-type.ecotouch.manual_tankpump.label = Speicherpumpe
+channel-type.ecotouch.manual_tankpump.description = Handschaltung Speicherladepumpe
+channel-type.ecotouch.manual_valve.label = Brauchwasserventil
+channel-type.ecotouch.manual_valve.description = Handschaltung Brauchwasserventil
+channel-type.ecotouch.manual_poolvalve.label = Poolventil
+channel-type.ecotouch.manual_poolvalve.description = Handschaltung Poolventil
+channel-type.ecotouch.manual_coolvalve.label = Kühlventil
+channel-type.ecotouch.manual_coolvalve.description = Handschaltung Kühlventil
+channel-type.ecotouch.manual_4wayvalve.label = Vierwegeventil
+channel-type.ecotouch.manual_4wayvalve.description = Handschaltung Vierwegeventil
+channel-type.ecotouch.manual_multiext.label = Multiausgang Ext.
+channel-type.ecotouch.manual_multiext.description = Handschaltung Multiausgang Ext.
+channel-type.ecotouch.temperature_surrounding.label = Temperatur Umgebung
+channel-type.ecotouch.temperature_surrounding.description = Temperatur Umgebung
+channel-type.ecotouch.temperature_suction_air.label = Temperatur Sauggas
+channel-type.ecotouch.temperature_suction_air.description = Temperatur Sauggas
+channel-type.ecotouch.temperature_sump.label = Temperatur Ölsumpf
+channel-type.ecotouch.temperature_sump.description = Temperatur Ölsumpf
+channel-type.ecotouch.ecovent_temp_exhaust_air.label = EcoVent Abluft
+channel-type.ecotouch.ecovent_temp_exhaust_air.description = EcoVent Abluft
+channel-type.ecotouch.ecovent_temp_exit_air.label = EcoVent Fortluft
+channel-type.ecotouch.ecovent_temp_exit_air.description = EcoVent Fortluft
+channel-type.ecotouch.ecovent_temp_outdoor_air.label = EcoVent Außenluft
+channel-type.ecotouch.ecovent_temp_outdoor_air.description = EcoVent Außenluft
+channel-type.ecotouch.ecovent_temp_supply_air.label = EcoVent Zuluft
+channel-type.ecotouch.ecovent_temp_supply_air.description = EcoVent Zuluft
+channel-type.ecotouch.ecovent_CO2_value.label = EcoVent CO2
+channel-type.ecotouch.ecovent_CO2_value.description = EcoVent CO2
+channel-type.ecotouch.ecovent_moisture_value.label = EcoVent Luftfeuchtigkeit
+channel-type.ecotouch.ecovent_moisture_value.description = EcoVent Luftfeuchtigkeit
+channel-type.ecotouch.ecovent_output_y1.label = EcoVent Lüfterdrehzahl
+channel-type.ecotouch.ecovent_output_y1.description = EcoVent Lüfterdrehzahl
diff --git a/bundles/org.openhab.binding.ecotouch/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.ecotouch/src/main/resources/OH-INF/thing/thing-types.xml
new file mode 100644 (file)
index 0000000..1272f90
--- /dev/null
@@ -0,0 +1,943 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<thing:thing-descriptions bindingId="ecotouch"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
+       xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
+
+       <thing-type id="geo">
+               <label>Waterkotte EcoTouch Geo</label>
+               <description>Waterkotte EcoTouch Geo heat pump</description>
+               <category>HVAC</category>
+
+               <channels>
+                       <channel id="temperature_outside" typeId="temperature_outside"/>
+                       <channel id="temperature_outside_1h" typeId="temperature_outside_1h"/>
+                       <channel id="temperature_outside_24h" typeId="temperature_outside_24h"/>
+                       <channel id="temperature_source_in" typeId="temperature_source_in"/>
+                       <channel id="temperature_source_out" typeId="temperature_source_out"/>
+                       <channel id="temperature_evaporation" typeId="temperature_evaporation"/>
+                       <channel id="temperature_suction" typeId="temperature_suction"/>
+                       <channel id="pressure_evaporation" typeId="pressure_evaporation"/>
+                       <channel id="temperature_return_set" typeId="temperature_return_set"/>
+                       <channel id="temperature_return" typeId="temperature_return"/>
+                       <channel id="temperature_flow" typeId="temperature_flow"/>
+                       <channel id="temperature_condensation" typeId="temperature_condensation"/>
+                       <channel id="pressure_condensation" typeId="pressure_condensation"/>
+                       <channel id="temperature_storage" typeId="temperature_storage"/>
+                       <channel id="temperature_room" typeId="temperature_room"/>
+                       <channel id="temperature_room_1h" typeId="temperature_room_1h"/>
+                       <channel id="temperature_water" typeId="temperature_water"/>
+                       <channel id="temperature_pool" typeId="temperature_pool"/>
+                       <channel id="temperature_solar" typeId="temperature_solar"/>
+                       <channel id="temperature_solar_flow" typeId="temperature_solar_flow"/>
+                       <channel id="position_expansion_valve" typeId="position_expansion_valve"/>
+                       <channel id="power_compressor" typeId="power_compressor"/>
+                       <channel id="power_heating" typeId="power_heating"/>
+                       <channel id="power_cooling" typeId="power_cooling"/>
+                       <channel id="cop_heating" typeId="cop_heating"/>
+                       <channel id="cop_cooling" typeId="cop_cooling"/>
+                       <channel id="temperature_heating_return" typeId="temperature_heating_return"/>
+                       <channel id="temperature_heating_set" typeId="temperature_heating_set"/>
+                       <channel id="temperature_heating_set2" typeId="temperature_heating_set2"/>
+                       <channel id="temperature_cooling_return" typeId="temperature_cooling_return"/>
+                       <channel id="temperature_cooling_set" typeId="temperature_cooling_set"/>
+                       <channel id="temperature_cooling_set2" typeId="temperature_cooling_set2"/>
+                       <channel id="temperature_water_set" typeId="temperature_water_set"/>
+                       <channel id="temperature_water_set2" typeId="temperature_water_set2"/>
+                       <channel id="temperature_pool_set" typeId="temperature_pool_set"/>
+                       <channel id="temperature_pool_set2" typeId="temperature_pool_set2"/>
+                       <channel id="compressor_power" typeId="compressor_power"/>
+                       <channel id="percent_heat_circ_pump" typeId="percent_heat_circ_pump"/>
+                       <channel id="percent_source_pump" typeId="percent_source_pump"/>
+                       <channel id="percent_compressor" typeId="percent_compressor"/>
+                       <channel id="hysteresis_heating" typeId="hysteresis_heating"/>
+                       <channel id="temperature2_outside_1h" typeId="temperature2_outside_1h"/>
+                       <channel id="nviNormAussen" typeId="nviNormAussen"/>
+                       <channel id="nviHeizkreisNorm" typeId="nviHeizkreisNorm"/>
+                       <channel id="nviTHeizgrenze" typeId="nviTHeizgrenze"/>
+                       <channel id="nviTHeizgrenzeSoll" typeId="nviTHeizgrenzeSoll"/>
+                       <channel id="maxVLTemp" typeId="maxVLTemp"/>
+                       <channel id="tempSet0Deg" typeId="tempSet0Deg"/>
+                       <channel id="coolEnableTemp" typeId="coolEnableTemp"/>
+                       <channel id="nviSollKuehlen" typeId="nviSollKuehlen"/>
+                       <channel id="tempchange_heating_pv" typeId="tempchange_heating_pv"/>
+                       <channel id="tempchange_cooling_pv" typeId="tempchange_cooling_pv"/>
+                       <channel id="tempchange_warmwater_pv" typeId="tempchange_warmwater_pv"/>
+                       <channel id="tempchange_pool_pv" typeId="tempchange_pool_pv"/>
+                       <channel id="version_controller" typeId="version_controller"/>
+                       <channel id="version_controller_build" typeId="version_controller_build"/>
+                       <channel id="version_bios" typeId="version_bios"/>
+                       <channel id="date_day" typeId="date_day"/>
+                       <channel id="date_month" typeId="date_month"/>
+                       <channel id="date_year" typeId="date_year"/>
+                       <channel id="time_hour" typeId="time_hour"/>
+                       <channel id="time_minute" typeId="time_minute"/>
+                       <channel id="operating_hours_compressor1" typeId="operating_hours_compressor1"/>
+                       <channel id="operating_hours_compressor2" typeId="operating_hours_compressor2"/>
+                       <channel id="operating_hours_circulation_pump" typeId="operating_hours_circulation_pump"/>
+                       <channel id="operating_hours_source_pump" typeId="operating_hours_source_pump"/>
+                       <channel id="operating_hours_solar" typeId="operating_hours_solar"/>
+                       <channel id="enable_heating" typeId="enable_heating"/>
+                       <channel id="enable_cooling" typeId="enable_cooling"/>
+                       <channel id="enable_warmwater" typeId="enable_warmwater"/>
+                       <channel id="enable_pool" typeId="enable_pool"/>
+                       <channel id="enable_pv" typeId="enable_pv"/>
+                       <channel id="state" typeId="state"/>
+                       <channel id="state_sourcepump" typeId="state_sourcepump"/>
+                       <channel id="state_heatingpump" typeId="state_heatingpump"/>
+                       <channel id="state_evd" typeId="state_evd"/>
+                       <channel id="state_compressor1" typeId="state_compressor1"/>
+                       <channel id="state_compressor2" typeId="state_compressor2"/>
+                       <channel id="state_extheater" typeId="state_extheater"/>
+                       <channel id="state_alarm" typeId="state_alarm"/>
+                       <channel id="state_cooling" typeId="state_cooling"/>
+                       <channel id="state_water" typeId="state_water"/>
+                       <channel id="state_pool" typeId="state_pool"/>
+                       <channel id="state_solar" typeId="state_solar"/>
+                       <channel id="state_cooling4way" typeId="state_cooling4way"/>
+                       <channel id="alarm" typeId="alarm"/>
+                       <channel id="interruptions" typeId="interruptions"/>
+                       <channel id="state_service" typeId="state_service"/>
+                       <channel id="adapt_heating" typeId="adapt_heating"/>
+                       <channel id="manual_heatingpump" typeId="manual_heatingpump"/>
+                       <channel id="manual_sourcepump" typeId="manual_sourcepump"/>
+                       <channel id="manual_solarpump1" typeId="manual_solarpump1"/>
+                       <channel id="manual_solarpump2" typeId="manual_solarpump2"/>
+                       <channel id="manual_tankpump" typeId="manual_tankpump"/>
+                       <channel id="manual_valve" typeId="manual_valve"/>
+                       <channel id="manual_poolvalve" typeId="manual_poolvalve"/>
+                       <channel id="manual_coolvalve" typeId="manual_coolvalve"/>
+                       <channel id="manual_4wayvalve" typeId="manual_4wayvalve"/>
+                       <channel id="manual_multiext" typeId="manual_multiext"/>
+
+                       <channel id="ecovent_temp_exhaust_air" typeId="ecovent_temp_exhaust_air"/>
+                       <channel id="ecovent_temp_exit_air" typeId="ecovent_temp_exit_air"/>
+                       <channel id="ecovent_temp_outdoor_air" typeId="ecovent_temp_outdoor_air"/>
+                       <channel id="ecovent_temp_supply_air" typeId="ecovent_temp_supply_air"/>
+                       <channel id="ecovent_CO2_value" typeId="ecovent_CO2_value"/>
+                       <channel id="ecovent_moisture_value" typeId="ecovent_moisture_value"/>
+                       <channel id="ecovent_output_y1" typeId="ecovent_output_y1"/>
+                       <channel id="ecovent_mode" typeId="ecovent_mode"/>
+               </channels>
+
+               <config-description>
+                       <parameter name="ip" type="text" required="true">
+                               <context>network-address</context>
+                               <label>Address of Heat Pump</label>
+                               <description>Enter the IP address or the hostname of the EcoTouch display unit</description>
+                       </parameter>
+                       <parameter name="username" type="text" required="true">
+                               <label>Username</label>
+                               <description>Since Waterkotte Display software version 1.6.xx, the username default value is waterkotte. Prior to
+                                       that, the username default was admin</description>
+                       </parameter>
+                       <parameter name="password" type="text" required="true">
+                               <context>password</context>
+                               <label>Password</label>
+                               <description>Since Waterkotte Display software version 1.6.xx, the password default value is waterkotte. Prior to
+                                       that, the password default was wtkadmin</description>
+                       </parameter>
+                       <parameter name="refresh" type="integer" required="false" min="10" unit="s">
+                               <default>60</default>
+                               <label>Refresh Interval</label>
+                               <description>This is the refresh interval in seconds for all channels.</description>
+                       </parameter>
+               </config-description>
+
+       </thing-type>
+
+       <thing-type id="air">
+               <label>Waterkotte EcoTouch Air</label>
+               <description>Waterkotte EcoTouch Air heat pump</description>
+               <category>HVAC</category>
+
+               <channels>
+                       <channel id="temperature_outside" typeId="temperature_outside"/>
+                       <channel id="temperature_outside_1h" typeId="temperature_outside_1h"/>
+                       <channel id="temperature_outside_24h" typeId="temperature_outside_24h"/>
+                       <channel id="temperature_source_in" typeId="temperature_source_in"/>
+                       <channel id="temperature_source_out" typeId="temperature_source_out"/>
+                       <channel id="temperature_evaporation" typeId="temperature_evaporation"/>
+                       <channel id="temperature_suction" typeId="temperature_suction"/>
+                       <channel id="pressure_evaporation" typeId="pressure_evaporation"/>
+                       <channel id="temperature_return_set" typeId="temperature_return_set"/>
+                       <channel id="temperature_return" typeId="temperature_return"/>
+                       <channel id="temperature_flow" typeId="temperature_flow"/>
+                       <channel id="temperature_condensation" typeId="temperature_condensation"/>
+                       <channel id="pressure_condensation" typeId="pressure_condensation"/>
+                       <channel id="temperature_storage" typeId="temperature_storage"/>
+                       <channel id="temperature_room" typeId="temperature_room"/>
+                       <channel id="temperature_room_1h" typeId="temperature_room_1h"/>
+                       <channel id="temperature_water" typeId="temperature_water"/>
+                       <channel id="temperature_pool" typeId="temperature_pool"/>
+                       <channel id="temperature_solar" typeId="temperature_solar"/>
+                       <channel id="temperature_solar_flow" typeId="temperature_solar_flow"/>
+                       <channel id="position_expansion_valve" typeId="position_expansion_valve"/>
+                       <channel id="power_compressor" typeId="power_compressor"/>
+                       <channel id="power_heating" typeId="power_heating"/>
+                       <channel id="power_cooling" typeId="power_cooling"/>
+                       <channel id="cop_heating" typeId="cop_heating"/>
+                       <channel id="cop_cooling" typeId="cop_cooling"/>
+                       <channel id="temperature_heating_return" typeId="temperature_heating_return"/>
+                       <channel id="temperature_heating_set" typeId="temperature_heating_set"/>
+                       <channel id="temperature_heating_set2" typeId="temperature_heating_set2"/>
+                       <channel id="temperature_cooling_return" typeId="temperature_cooling_return"/>
+                       <channel id="temperature_cooling_set" typeId="temperature_cooling_set"/>
+                       <channel id="temperature_cooling_set2" typeId="temperature_cooling_set2"/>
+                       <channel id="temperature_water_set" typeId="temperature_water_set"/>
+                       <channel id="temperature_water_set2" typeId="temperature_water_set2"/>
+                       <channel id="temperature_pool_set" typeId="temperature_pool_set"/>
+                       <channel id="temperature_pool_set2" typeId="temperature_pool_set2"/>
+                       <channel id="compressor_power" typeId="compressor_power"/>
+                       <channel id="percent_heat_circ_pump" typeId="percent_heat_circ_pump"/>
+                       <channel id="percent_source_pump" typeId="percent_source_pump"/>
+                       <channel id="percent_compressor" typeId="percent_compressor"/>
+                       <channel id="hysteresis_heating" typeId="hysteresis_heating"/>
+                       <channel id="temperature2_outside_1h" typeId="temperature2_outside_1h"/>
+                       <channel id="nviNormAussen" typeId="nviNormAussen"/>
+                       <channel id="nviHeizkreisNorm" typeId="nviHeizkreisNorm"/>
+                       <channel id="nviTHeizgrenze" typeId="nviTHeizgrenze"/>
+                       <channel id="nviTHeizgrenzeSoll" typeId="nviTHeizgrenzeSoll"/>
+                       <channel id="maxVLTemp" typeId="maxVLTemp"/>
+                       <channel id="tempSet0Deg" typeId="tempSet0Deg"/>
+                       <channel id="coolEnableTemp" typeId="coolEnableTemp"/>
+                       <channel id="nviSollKuehlen" typeId="nviSollKuehlen"/>
+                       <channel id="tempchange_heating_pv" typeId="tempchange_heating_pv"/>
+                       <channel id="tempchange_cooling_pv" typeId="tempchange_cooling_pv"/>
+                       <channel id="tempchange_warmwater_pv" typeId="tempchange_warmwater_pv"/>
+                       <channel id="tempchange_pool_pv" typeId="tempchange_pool_pv"/>
+                       <channel id="version_controller" typeId="version_controller"/>
+                       <channel id="version_controller_build" typeId="version_controller_build"/>
+                       <channel id="version_bios" typeId="version_bios"/>
+                       <channel id="date_day" typeId="date_day"/>
+                       <channel id="date_month" typeId="date_month"/>
+                       <channel id="date_year" typeId="date_year"/>
+                       <channel id="time_hour" typeId="time_hour"/>
+                       <channel id="time_minute" typeId="time_minute"/>
+                       <channel id="operating_hours_compressor1" typeId="operating_hours_compressor1"/>
+                       <channel id="operating_hours_compressor2" typeId="operating_hours_compressor2"/>
+                       <channel id="operating_hours_circulation_pump" typeId="operating_hours_circulation_pump"/>
+                       <channel id="operating_hours_source_pump" typeId="operating_hours_source_pump"/>
+                       <channel id="operating_hours_solar" typeId="operating_hours_solar"/>
+                       <channel id="enable_heating" typeId="enable_heating"/>
+                       <channel id="enable_cooling" typeId="enable_cooling"/>
+                       <channel id="enable_warmwater" typeId="enable_warmwater"/>
+                       <channel id="enable_pool" typeId="enable_pool"/>
+                       <channel id="enable_pv" typeId="enable_pv"/>
+                       <channel id="state" typeId="state"/>
+                       <channel id="state_sourcepump" typeId="state_sourcepump"/>
+                       <channel id="state_heatingpump" typeId="state_heatingpump"/>
+                       <channel id="state_evd" typeId="state_evd"/>
+                       <channel id="state_compressor1" typeId="state_compressor1"/>
+                       <channel id="state_compressor2" typeId="state_compressor2"/>
+                       <channel id="state_extheater" typeId="state_extheater"/>
+                       <channel id="state_alarm" typeId="state_alarm"/>
+                       <channel id="state_cooling" typeId="state_cooling"/>
+                       <channel id="state_water" typeId="state_water"/>
+                       <channel id="state_pool" typeId="state_pool"/>
+                       <channel id="state_solar" typeId="state_solar"/>
+                       <channel id="state_cooling4way" typeId="state_cooling4way"/>
+                       <channel id="alarm" typeId="alarm"/>
+                       <channel id="interruptions" typeId="interruptions"/>
+                       <channel id="state_service" typeId="state_service"/>
+                       <channel id="adapt_heating" typeId="adapt_heating"/>
+                       <channel id="manual_heatingpump" typeId="manual_heatingpump"/>
+                       <channel id="manual_sourcepump" typeId="manual_sourcepump"/>
+                       <channel id="manual_solarpump1" typeId="manual_solarpump1"/>
+                       <channel id="manual_solarpump2" typeId="manual_solarpump2"/>
+                       <channel id="manual_tankpump" typeId="manual_tankpump"/>
+                       <channel id="manual_valve" typeId="manual_valve"/>
+                       <channel id="manual_poolvalve" typeId="manual_poolvalve"/>
+                       <channel id="manual_coolvalve" typeId="manual_coolvalve"/>
+                       <channel id="manual_4wayvalve" typeId="manual_4wayvalve"/>
+                       <channel id="manual_multiext" typeId="manual_multiext"/>
+
+                       <channel id="temperature_surrounding" typeId="temperature_surrounding"/>
+                       <channel id="temperature_suction_air" typeId="temperature_suction_air"/>
+                       <channel id="temperature_sump" typeId="temperature_sump"/>
+
+                       <channel id="ecovent_temp_exhaust_air" typeId="ecovent_temp_exhaust_air"/>
+                       <channel id="ecovent_temp_exit_air" typeId="ecovent_temp_exit_air"/>
+                       <channel id="ecovent_temp_outdoor_air" typeId="ecovent_temp_outdoor_air"/>
+                       <channel id="ecovent_temp_supply_air" typeId="ecovent_temp_supply_air"/>
+                       <channel id="ecovent_CO2_value" typeId="ecovent_CO2_value"/>
+                       <channel id="ecovent_moisture_value" typeId="ecovent_moisture_value"/>
+                       <channel id="ecovent_output_y1" typeId="ecovent_output_y1"/>
+                       <channel id="ecovent_mode" typeId="ecovent_mode"/>
+               </channels>
+
+               <config-description>
+                       <parameter name="ip" type="text" required="true">
+                               <context>network-address</context>
+                               <label>Address of Heat Pump</label>
+                               <description>Enter the IP address or the hostname of the EcoTouch display unit</description>
+                       </parameter>
+                       <parameter name="username" type="text" required="true">
+                               <label>Username</label>
+                               <description>Since Waterkotte Display software version 1.6.xx, the username default value is waterkotte. Prior to
+                                       that, the username default was admin</description>
+                       </parameter>
+                       <parameter name="password" type="text" required="true">
+                               <context>password</context>
+                               <label>Password</label>
+                               <description>Since Waterkotte Display software version 1.6.xx, the password default value is waterkotte. Prior to
+                                       that, the password default was wtkadmin</description>
+                       </parameter>
+                       <parameter name="refresh" type="integer" required="false" min="10" unit="s">
+                               <default>60</default>
+                               <label>Refresh Interval</label>
+                               <description>This is the refresh interval in seconds for all channels.</description>
+                       </parameter>
+               </config-description>
+
+       </thing-type>
+
+       <channel-type id="temperature_outside">
+               <item-type>Number:Temperature</item-type>
+               <label>Temperature Outside</label>
+               <description>The current outside temperature</description>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_outside_1h" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>Average Temperature 1h</label>
+               <description>The outside temperature averaged over one hour</description>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_outside_24h">
+               <item-type>Number:Temperature</item-type>
+               <label>Average Temperature 24h</label>
+               <description>The outside temperature averaged over one day</description>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_source_in">
+               <item-type>Number:Temperature</item-type>
+               <label>Temperature Source In</label>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_source_out">
+               <item-type>Number:Temperature</item-type>
+               <label>Temperature Source Out</label>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_evaporation" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>Temperature Evaporation</label>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_suction" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>Temperature Suction</label>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="pressure_evaporation" advanced="true">
+               <item-type>Number:Pressure</item-type>
+               <label>Pressure Evaporation</label>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_return_set">
+               <item-type>Number:Temperature</item-type>
+               <label>Temperature Return Set</label>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_return">
+               <item-type>Number:Temperature</item-type>
+               <label>Temperature Return</label>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_flow">
+               <item-type>Number:Temperature</item-type>
+               <label>Temperature Flow</label>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_condensation" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>Temperature Condensation</label>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="pressure_condensation" advanced="true">
+               <item-type>Number:Pressure</item-type>
+               <label>Pressure Condensation</label>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_storage" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>Temperature Storage</label>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_room">
+               <item-type>Number:Temperature</item-type>
+               <label>Temperature Room</label>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_room_1h">
+               <item-type>Number:Temperature</item-type>
+               <label>Avg. Room Temp 1h</label>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_water">
+               <item-type>Number:Temperature</item-type>
+               <label>Temperature Water</label>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_pool" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>Temperature Pool</label>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_solar" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>Temperature Solar</label>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_solar_flow" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>Temperature Solar Flow</label>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="position_expansion_valve" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Position Expansion Valve</label>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="power_compressor">
+               <item-type>Number:Power</item-type>
+               <label>Power Compressor</label>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="power_heating">
+               <item-type>Number:Power</item-type>
+               <label>Power Heating</label>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="power_cooling">
+               <item-type>Number:Power</item-type>
+               <label>Power Cooling</label>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="cop_heating">
+               <item-type>Number:Dimensionless</item-type>
+               <label>COP Heating</label>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="cop_cooling">
+               <item-type>Number:Dimensionless</item-type>
+               <label>COP Cooling</label>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_heating_return">
+               <item-type>Number:Temperature</item-type>
+               <label>Heating Return</label>
+               <description>Temperature Heating Return</description>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_heating_set">
+               <item-type>Number:Temperature</item-type>
+               <label>Heating Set</label>
+               <description>Temperature Heating Setpoint</description>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_heating_set2" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>Heating Set BMS</label>
+               <description>Temperature Heating Setpoint BMS</description>
+               <category>Temperature</category>
+               <state min="15" max="65" readOnly="false" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_cooling_return">
+               <item-type>Number:Temperature</item-type>
+               <label>Cooling Return</label>
+               <description>Temperature Cooling Return</description>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_cooling_set" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>Cooling Set</label>
+               <description>Temperature Cooling Setpoint</description>
+               <category>Temperature</category>
+               <state min="15" readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_cooling_set2">
+               <item-type>Number:Temperature</item-type>
+               <label>Cooling Set BMS</label>
+               <description>Temperature Cooling Setpoint BMS</description>
+               <category>Temperature</category>
+               <state min="5" max="26" readOnly="false" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_water_set" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>Water Set</label>
+               <description>Temperature Water Setpoint</description>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_water_set2">
+               <item-type>Number:Temperature</item-type>
+               <label>Water Set BMS</label>
+               <description>Temperature Water Setpoint BMS</description>
+               <category>Temperature</category>
+               <state min="28" max="70" readOnly="false" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_pool_set" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>Pool Set</label>
+               <description>Temperature Pool Setpoint</description>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_pool_set2" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>Pool Set BMS</label>
+               <description>Temperature Pool Setpoint BMS</description>
+               <category>Temperature</category>
+               <state min="15" max="40" readOnly="false" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="compressor_power" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Percent Power Compressor</label>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="percent_heat_circ_pump" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Percent Circulation Pump</label>
+               <description>Percent Heating Circulation Pump</description>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="percent_source_pump" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Percent Source Pump</label>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="percent_compressor" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Percent Compressor</label>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="hysteresis_heating" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>Hysteresis Heating</label>
+               <category>Temperature</category>
+               <state readOnly="false" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature2_outside_1h" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>Outside 1h Average</label>
+               <description>Temperature Outside 1h Average (A90)</description>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="nviNormAussen" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>nviNormAussen</label>
+               <state readOnly="false" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="nviHeizkreisNorm" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>nviHeizkreisNorm</label>
+               <state readOnly="false" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="nviTHeizgrenze" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>nviTHeizgrenze</label>
+               <category>Temperature</category>
+               <state readOnly="false" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="nviTHeizgrenzeSoll" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>nviTHeizgrenze Setpoint</label>
+               <category>Temperature</category>
+               <state readOnly="false" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="maxVLTemp" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>maxVLTemp</label>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="tempSet0Deg" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>Heating Set 0°C</label>
+               <description>Heating Setpoint at 0°C Outside</description>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="coolEnableTemp" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>Temperature Cooling Enable</label>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="nviSollKuehlen" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>nviSollKuehlen</label>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="tempchange_heating_pv" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>Change Heating PV</label>
+               <description>Temperature Change Heating if PV</description>
+               <category>Temperature</category>
+               <state readOnly="false" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="tempchange_cooling_pv" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>Change Cooling PV</label>
+               <description>Temperature Change Cooling if PV</description>
+               <category>Temperature</category>
+               <state readOnly="false" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="tempchange_warmwater_pv" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>Change Water PV</label>
+               <description>Temperature Change Water if PV</description>
+               <category>Temperature</category>
+               <state readOnly="false" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="tempchange_pool_pv" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>Change Pool PV</label>
+               <description>Temperature Change Pool if PV</description>
+               <category>Temperature</category>
+               <state readOnly="false" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="version_controller" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Version Controller</label>
+               <description>Version Display Controller</description>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="version_controller_build" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Build Number Controller</label>
+               <description>Build Number Display Controller</description>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="version_bios" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Version BIOS</label>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="date_day" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Day</label>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="date_month" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Month</label>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="date_year" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Year</label>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="time_hour" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Hour</label>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="time_minute" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Minute</label>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="operating_hours_compressor1" advanced="true">
+               <item-type>Number:Time</item-type>
+               <label>Hours Compressor 1</label>
+               <description>Operating Hours Compressor 1</description>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="operating_hours_compressor2" advanced="true">
+               <item-type>Number:Time</item-type>
+               <label>Hours Compressor 2</label>
+               <description>Operating Hours Compressor 2</description>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="operating_hours_circulation_pump" advanced="true">
+               <item-type>Number:Time</item-type>
+               <label>Hours Circulation Pump</label>
+               <description>Operating Hours Circulation Pump</description>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="operating_hours_source_pump" advanced="true">
+               <item-type>Number:Time</item-type>
+               <label>Hours Source Pump</label>
+               <description>Operating Hours Source Pump</description>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="operating_hours_solar" advanced="true">
+               <item-type>Number:Time</item-type>
+               <label>Hours Solar</label>
+               <description>Operating Hours Solar</description>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="enable_heating">
+               <item-type>Switch</item-type>
+               <label>Enable Heating</label>
+               <state readOnly="false"/>
+       </channel-type>
+       <channel-type id="enable_cooling">
+               <item-type>Switch</item-type>
+               <label>Enable Cooling</label>
+               <state readOnly="false"/>
+       </channel-type>
+       <channel-type id="enable_warmwater">
+               <item-type>Switch</item-type>
+               <label>Enable Water</label>
+               <description>Enable Warm Water</description>
+               <state readOnly="false"/>
+       </channel-type>
+       <channel-type id="enable_pool" advanced="true">
+               <item-type>Switch</item-type>
+               <label>Enable Pool</label>
+               <state readOnly="false"/>
+       </channel-type>
+       <channel-type id="enable_pv" advanced="true">
+               <item-type>Switch</item-type>
+               <label>Enable PV</label>
+               <state readOnly="false"/>
+       </channel-type>
+       <channel-type id="state" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>State</label>
+               <description>A Bitfield which encodes the state of all valves, pumps and compressors</description>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="state_sourcepump" advanced="true">
+               <item-type>Switch</item-type>
+               <label>State Source Pump</label>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="state_heatingpump" advanced="true">
+               <item-type>Switch</item-type>
+               <label>State Heating Pump</label>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="state_evd" advanced="true">
+               <item-type>Switch</item-type>
+               <label>State EVD</label>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="state_compressor1" advanced="true">
+               <item-type>Switch</item-type>
+               <label>State Compressor 1</label>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="state_compressor2" advanced="true">
+               <item-type>Switch</item-type>
+               <label>State Compressor 2</label>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="state_extheater" advanced="true">
+               <item-type>Switch</item-type>
+               <label>State External Heater</label>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="state_alarm">
+               <item-type>Switch</item-type>
+               <label>State Alarm</label>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="state_cooling" advanced="true">
+               <item-type>Switch</item-type>
+               <label>State Cooling</label>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="state_water" advanced="true">
+               <item-type>Switch</item-type>
+               <label>State Water</label>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="state_pool" advanced="true">
+               <item-type>Switch</item-type>
+               <label>State Pool</label>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="state_solar" advanced="true">
+               <item-type>Switch</item-type>
+               <label>State Solar</label>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="state_cooling4way" advanced="true">
+               <item-type>Switch</item-type>
+               <label>State Cooling4Way</label>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="alarm">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Alarm</label>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="interruptions" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Interruptions</label>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="state_service" advanced="true">
+               <item-type>Switch</item-type>
+               <label>State Service Mode</label>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="adapt_heating">
+               <item-type>Number:Temperature</item-type>
+               <label>Adapt Heating</label>
+               <description>Adjust the Heating Temperature by an Offset</description>
+               <category>Temperature</category>
+               <state min="-2" max="2" step="0.5" readOnly="false"/>
+       </channel-type>
+       <channel-type id="manual_heatingpump" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Enable Heating Pump</label>
+               <description>Operating Mode Heating Pump</description>
+               <state readOnly="false"/>
+       </channel-type>
+       <channel-type id="manual_sourcepump" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Enable Source Pump</label>
+               <description>Operating Mode Source Pump</description>
+               <state readOnly="false"/>
+       </channel-type>
+       <channel-type id="manual_solarpump1" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Enable Solar Pump</label>
+               <description>Operating Mode Solar Pump</description>
+               <state readOnly="false"/>
+       </channel-type>
+       <channel-type id="manual_solarpump2" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Enable Solar Pump 2</label>
+               <description>Operating Mode Solar Pump 2</description>
+               <state readOnly="false"/>
+       </channel-type>
+       <channel-type id="manual_tankpump" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Enable Tank Pump</label>
+               <description>Operating Mode Tank Pump</description>
+               <state readOnly="false"/>
+       </channel-type>
+       <channel-type id="manual_valve" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Enable Valve</label>
+               <description>Operating Mode Valve</description>
+               <state readOnly="false"/>
+       </channel-type>
+       <channel-type id="manual_poolvalve" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Enable Pool Valve</label>
+               <description>Operating Mode Pool Valve</description>
+               <state readOnly="false"/>
+       </channel-type>
+       <channel-type id="manual_coolvalve" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Enable Cooling Valve</label>
+               <description>Operating Mode Cooling Valve</description>
+               <state readOnly="false"/>
+       </channel-type>
+       <channel-type id="manual_4wayvalve" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Enable 4Way Valve</label>
+               <description>Operating Mode 4Way Valve</description>
+               <state readOnly="false"/>
+       </channel-type>
+       <channel-type id="manual_multiext" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Enable Multi Ouput</label>
+               <description>Operating Mode Multi Ouput Ext</description>
+               <state readOnly="false"/>
+       </channel-type>
+
+       <!-- The following tags are only available for Air Heat Pumps -->
+       <channel-type id="temperature_surrounding">
+               <item-type>Number:Temperature</item-type>
+               <label>Temperature Surrounding</label>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_suction_air">
+               <item-type>Number:Temperature</item-type>
+               <label>Temperature Suction Air</label>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="temperature_sump">
+               <item-type>Number:Temperature</item-type>
+               <label>Temperature Sump</label>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+
+       <!-- The following tags are only available, if an Ecovent System is attached to the Ecotouch -->
+       <channel-type id="ecovent_temp_exhaust_air">
+               <item-type>Number:Temperature</item-type>
+               <label>EcoVent Exhaust Air</label>
+               <description>EcoVent Temperature Exhaust Air</description>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="ecovent_temp_exit_air">
+               <item-type>Number:Temperature</item-type>
+               <label>EcoVent Exit Air</label>
+               <description>EcoVent Temperature Exit Air</description>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="ecovent_temp_outdoor_air">
+               <item-type>Number:Temperature</item-type>
+               <label>EcoVent Outdoor Air</label>
+               <description>EcoVent Temperature Outdoor Air</description>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="ecovent_temp_supply_air">
+               <item-type>Number:Temperature</item-type>
+               <label>EcoVent Supply Air</label>
+               <description>EcoVent Temperature Supply Air</description>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="ecovent_CO2_value">
+               <item-type>Number:Dimensionless</item-type>
+               <label>EcoVent CO2</label>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="ecovent_moisture_value">
+               <item-type>Number:Dimensionless</item-type>
+               <label>EcoVent Air Moisture</label>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="ecovent_output_y1">
+               <item-type>Number:Dimensionless</item-type>
+               <label>EcoVent Fan</label>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
+       <channel-type id="ecovent_mode">
+               <item-type>Number:Dimensionless</item-type>
+               <label>EcoVent Mode</label>
+               <description>EcoVent Mode (0..5: Day, Night, Timer, Party, Vacation, Bypass)</description>
+               <state min="0" max="5" step="1" readOnly="false"/>
+       </channel-type>
+
+</thing:thing-descriptions>
index 72196cd918725944b5fa5cbbe1fc3aadb5bf011c..0e0b3f6e779473572f0d5250ab4ca9cb13c76521 100644 (file)
@@ -98,6 +98,7 @@
     <module>org.openhab.binding.dwdpollenflug</module>
     <module>org.openhab.binding.dwdunwetter</module>
     <module>org.openhab.binding.ecobee</module>
+    <module>org.openhab.binding.ecotouch</module>
     <module>org.openhab.binding.elerotransmitterstick</module>
     <module>org.openhab.binding.energenie</module>
     <module>org.openhab.binding.enigma2</module>