added migrated 2.x add-ons

Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
Kai Kreuzer
2020-09-21 01:58:32 +02:00
parent bbf1a7fd29
commit 6df6783b60
11662 changed files with 1302875 additions and 11 deletions

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="target/generated-sources/annotations">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="ignore_optional_problems" value="true"/>
<attribute name="m2e-apt" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="ignore_optional_problems" value="true"/>
<attribute name="m2e-apt" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.openhab.binding.modbus.stiebeleltron</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>

View File

@@ -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

View File

@@ -0,0 +1,206 @@
# Stiebel Eltron ISG Binding
This extension adds support for the Stiebel Eltron modbus protocol.
An Internet Service Gateway (ISG) with an installed modbus extension is required in order to run this binding.
In case the modbus extension is not yet installed on the ISG, the ISG Updater Tool for the update can be found here: https://www.stiebel-eltron.de/de/home/produkte-loesungen/erneuerbare_energien/regelung_energiemanagement/internet_servicegateway/isg_web/downloads.html
## Supported Things
This bundle adds the following thing types to the Modbus binding.
Note, that the things will show up under the Modbus binding.
| Thing | ThingTypeID | Description |
| ------------------ | ----------- | -------------------------------------------------- |
| Stiebel Eltron ISG | heatpump | A stiebel eltron heat pump connected through a ISG |
## Discovery
This extension does not support autodiscovery. The things need to be added manually.
A typical bridge configuration would look like this:
```
Bridge modbus:tcp:bridge [ host="10.0.0.2", port=502, id=1 ]
```
## Thing Configuration
You need first to set up a TCP Modbus bridge according to the Modbus documentation.
Things in this extension will use the selected bridge to connect to the device.
The following parameters are valid for all thing types:
| Parameter | Type | Required | Default if omitted | Description |
| --------- | ------- | -------- | ------------------ | -------------------------------------------------------------------------- |
| refresh | integer | no | 5 | Poll interval in seconds. Increase this if you encounter connection errors |
| maxTries | integer | no | 3 | Number of retries when before giving up reading from this thing. |
## Channels
Channels are grouped into channel groups.
### System State Group
This group contains general operational information about the heat pump.
| Channel ID | Item Type | Read only | Description |
| ---------------- | --------- | --------- | ------------------------------------------------------------- |
| is-heating | Contact | true | OPEN in case the heat pump is currently in heating mode |
| is-heating-water | Contact | true | OPEN in case the heat pump is currently in heating water mode |
| is-cooling | Contact | true | OPEN in case the heat pump is currently in cooling mode |
| is-pumping | Contact | true | OPEN in case the heat pump is currently in pumping mode |
| is-summer | Contact | true | OPEN in case the heat pump is currently in summer mode |
### System Parameters Group
This group contains system paramters of the heat pump.
| Channel ID | Item Type | Read only | Description |
| --------------------------- | ------------------ | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| operation-mode | Number | false | The current operation mode of the heat pump (1=ready mode, 2=program mode, 3=comfort mode, 4=eco mode, 5=heating water mode, 0=emergency mode) |
| comfort-temperature-heating | Number:Temperature | false | The current heating comfort temperature |
| eco-temperature-heating | Number:Temperature | false | The current heating eco temperature |
| comfort-temperature-water | Number:Temperature | false | The current water comfort temperature |
| eco-temperature-water | Number:Temperature | false | The current water eco temperature |
### System Information Group
This group contains general operational information about the device.
| Channel ID | Item Type | Read only | Description |
| -------------------------- | -------------------- | --------- | ----------------------------------------------------- |
| fek-temperature | Number:Temperature | true | The current temperature measured by the FEK |
| fek-temperature-setpoint | Number:Temperature | true | The current set point of the FEK temperature |
| fek-humidity | Number:Dimensionless | true | The current humidity measured by the FEK |
| fek-dewpoint | Number:Temperature | true | The current dew point temperature measured by the FEK |
| outdoor-temperature | Number:Temperature | true | The current outdoor temperature |
| hk1-temperature | Number:Temperature | true | The current temperature of the HK1 |
| hk1-temperature-setpoint | Number:Temperature | true | The current temperature set point of the HK1 |
| supply-temperature | Number:Temperature | true | The current supply temperature |
| return-temperature | Number:Temperature | true | The current return measured |
| source-temperature | Number:Temperature | true | The current sourcetemperature |
| water-temperature | Number:Temperature | true | The current water temperature |
| water-temperature-setpoint | Number:Temperature | true | The current water temperature set point |
### Energy Information Group
This group contains about the energy consumption and delivery of the heat pump.
| Channel ID | Item Type | Read only | Description |
| ----------------------- | ------------- | --------- | ------------------------------------------------ |
| production-heat-today | Number:Energy | true | The heat quantity delivered today |
| production-heat-total | Number:Energy | true | The heat quantity delivered in total |
| production-water-today | Number:Energy | true | The water heat quantity delivered today |
| production-water-total | Number:Energy | true | The water heat quantity delivered in total |
| consumption-heat-today | Number:Energy | true | The power consumption for heating today |
| consumption-heat-total | Number:Energy | true | The power consumption for heating in total |
| consumption-water-today | Number:Energy | true | The power consumption for water heating today |
| consumption-water-total | Number:Energy | true | The power consumption for water heating in total |
## Full Example
### Thing Configuration
```
Bridge modbus:tcp:bridge [ host="hostname|ip", port=502, id=1]
Thing modbus:heatpump:stiebelEltron "StiebelEltron" (modbus:tcp:modbusbridge) [ ]
```
### Item Configuration
```
Number:Temperature stiebel_eltron_temperature_ffk "Temperature FFK [%.1f °C]" <temperature> { channel="modbus:heatpump:stiebelEltron:systemInformation#fek-temperature" }
Number:Temperature stiebel_eltron_setpoint_ffk "Set point FFK [%.1f °C]" <temperature> { channel="modbus:heatpump:stiebelEltron:systemInformation#fek-temperature-setpoint" }
Number:Dimensionless stiebel_eltron_humidity_ffk "Humidity FFK [%.1f %%]" <humidity> { channel="modbus:heatpump:stiebelEltron:systemInformation#fek-humidity" }
Number:Temperature stiebel_eltron_dewpoint_ffk "Dew point FFK [%.1f °C]" <temperature> { channel="modbus:heatpump:stiebelEltron:systemInformation#fek-dewpoint" }
Number:Temperature stiebel_eltron_outdoor_temp "Outdoor temperature [%.1f °C]" { channel="modbus:heatpump:stiebelEltron:systemInformation#outdoor-temperature" }
Number:Temperature stiebel_eltron_temp_hk1 "Temperature HK1 [%.1f °C]" { channel="modbus:heatpump:stiebelEltron:systemInformation#hk1-temperature" }
Number:Temperature stiebel_eltron_setpoint_hk1 "Set point HK1 [%.1f °C]" { channel="modbus:heatpump:stiebelEltron:systemInformation#hk1-temperature-setpoint" }
Number:Temperature stiebel_eltron_temp_water "Water temperature [%.1f °C]" { channel="modbus:heatpump:stiebelEltron:systemInformation#water-temperature" }
Number:Temperature stiebel_eltron_setpoint_water "Water setpoint [%.1f °C]" { channel="modbus:heatpump:stiebelEltron:systemInformation#water-temperature-setpoint" }
Number:Temperature stiebel_eltron_source_temp "Source temperature [%.1f °C]" { channel="modbus:heatpump:stiebelEltron:systemInformation#source-temperature" }
Number:Temperature stiebel_eltron_vorlauf_temp "Supply tempertature [%.1f °C]" { channel="modbus:heatpump:stiebelEltron:systemInformation#supply-temperature" }
Number:Temperature stiebel_eltron_ruecklauf_temp "Return temperature [%.1f °C]" { channel="modbus:heatpump:stiebelEltron:systemInformation#return-temperature" }
Number stiebel_eltron_heating_comfort_temp "Heating Comfort Temperature [%.1f °C]" { channel="modbus:heatpump:stiebelEltron:systemParameter#comfort-temperature-heating" }
Number stiebel_eltron_heating_eco_temp "Heating Eco Temperature [%.1f °C]" { channel="modbus:heatpump:stiebelEltron:systemParameter#eco-temperature-heating" }
Number stiebel_eltron_water_comfort_temp "Water Comfort Temperature [%.1f °C]" { channel="modbus:heatpump:stiebelEltron:systemParameter#comfort-temperature-water" }
Number stiebel_eltron_water_eco_temp "Water Eco Temperature [%.1f °C]" { channel="modbus:heatpump:stiebelEltron:systemParameter#eco-temperature-water" }
Number stiebel_eltron_operation_mode "Operation Mode" { channel="modbus:heatpump:stiebelEltron:systemParameter#operation-mode" }
Contact stiebel_eltron_mode_pump "Pump [%d]" { channel="modbus:heatpump:stiebelEltron:systemState#is-pumping" }
Contact stiebel_eltron_mode_heating "Heating [%d]" { channel="modbus:heatpump:stiebelEltron:systemState#is-heating" }
Contact stiebel_eltron_mode_water "Heating Water [%d]" { channel="modbus:heatpump:stiebelEltron:systemState#is-heating-water" }
Contact stiebel_eltron_mode_cooling "Cooling [%d]" { channel="modbus:heatpump:stiebelEltron:systemState#is-cooling" }
Contact stiebel_eltron_mode_summer "Summer Mode [%d]" { channel="modbus:heatpump:stiebelEltron:systemState#is-summer" }
Number:Energy stiebel_eltron_production_heat_today "Heat quantity today [%.0f kWh]" { channel="modbus:heatpump:stiebelEltron:energyInformation#production_heat_today" }
Number:Energy stiebel_eltron_production_heat_total "Heat quantity total [%.3f MWh]" {channel="modbus:heatpump:stiebelEltron:energyInformation#production_heat_total"}
Number:Energy stiebel_eltron_production_water_today "Water heat quantity today [%.0f kWh]" { channel="modbus:heatpump:stiebelEltron:energyInformation#production_water_today" }
Number:Energy stiebel_eltron_production_water_total "Water heat quantity total [%.3f MWh]" {channel="modbus:heatpump:stiebelEltron:energyInformation#production_water_total"}
Number:Energy stiebel_eltron_consumption_heat_total "Heating power consumption total [%.3f MWh]" {channel="modbus:heatpump:stiebelEltron:energyInformation#consumption_heat_total"}
Number:Energy stiebel_eltron_consumption_heat_today "Heating power consumption today [%.0f kWh]" { channel="modbus:heatpump:stiebelEltron:energyInformation#consumption_heat_today" }
Number:Energy stiebel_eltron_consumption_water_today "Water heating power consumption today [%.0f kWh]" { channel="modbus:heatpump:stiebelEltron:energyInformation#consumption_water_today" }
Number:Energy stiebel_eltron_consumption_water_total "Water heating power consumption total [%.3f MWh]" {channel="modbus:heatpump:stiebelEltron:energyInformation#consumption_water_total"}
```
### Sitemap Configuration
```
Text label="Heat pumpt" icon="temperature" {
Frame label="Optation Mode" {
Default item=stiebel_eltron_mode_pump
Default item=stiebel_eltron_mode_heating
Default item=stiebel_eltron_mode_water
Default item=stiebel_eltron_mode_cooling
Default item=stiebel_eltron_mode_summer
}
Frame label= "State" {
Default item=stiebel_eltron_operation_mode icon="settings"
Default item=stiebel_eltron_outdoor_temp icon="temperature"
Default item=stiebel_eltron_temp_hk1 icon="temperature"
Default item=stiebel_eltron_setpoint_hk1 icon="temperature"
Default item=stiebel_eltron_vorlauf_temp icon="temperature"
Default item=stiebel_eltron_ruecklauf_temp icon="temperature"
Default item=stiebel_eltron_temp_water icon="temperature"
Default item=stiebel_eltron_setpoint_water icon="temperature"
Default item=stiebel_eltron_temperature_ffk icon="temperature"
Default item=stiebel_eltron_setpoint_ffk icon="temperature"
Default item=stiebel_eltron_humidity_ffk icon="humidity"
Default item=stiebel_eltron_dewpoint_ffk icon="temperature"
Default item=stiebel_eltron_source_temp icon="temperature"
}
Frame label="Paramters" {
Setpoint item=stiebel_eltron_heating_comfort_temp icon="temperature" step=1 minValue=5 maxValue=30
Setpoint item=stiebel_eltron_heating_eco_temp icon="temperature" step=1 minValue=5 maxValue=30
Setpoint item=stiebel_eltron_water_comfort_temp icon="temperature" step=1 minValue=10 maxValue=60
Setpoint item=stiebel_eltron_water_eco_temp icon="temperature" step=1 minValue=10 maxValue=60
}
Frame label="Energy consumption" {
Default item=stiebel_eltron_consumption_heat_today icon="energy"
Default item=stiebel_eltron_consumption_heat_total icon="energy"
Default item=stiebel_eltron_consumption_water_today icon="energy"
Default item=stiebel_eltron_consumption_water_total icon="energy"
}
Frame label="Heat quantity" {
Default item=stiebel_eltron_production_heat_today icon="radiator"
Default item=stiebel_eltron_production_heat_total icon="radiator"
Default item=stiebel_eltron_production_water_today icon="water"
Default item=stiebel_eltron_production_water_total icon="water"
}
}
```

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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.0.0-SNAPSHOT</version>
</parent>
<artifactId>org.openhab.binding.modbus.stiebeleltron</artifactId>
<name>openHAB Add-ons :: Bundles :: StiebelEltron Bundle</name>
<dependencies>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.modbus</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.io.transport.modbus</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.binding.modbus.stiebeleltron-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
<repository>file:${basedirRoot}/bundles/org.openhab.io.transport.modbus/target/feature/feature.xml</repository>
<feature name="openhab-binding-modbus-stiebeleltron" description="StiebelEltron Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<feature>openhab-transport-modbus</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.modbus/${project.version}</bundle>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.modbus.stiebeleltron/${project.version}</bundle>
</feature>
</features>

View File

@@ -0,0 +1,73 @@
/**
* Copyright (c) 2010-2020 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.modbus.stiebeleltron.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.modbus.ModbusBindingConstants;
import org.openhab.core.thing.ThingTypeUID;
/**
* The {@link Modbus.StiebelEltronBindingConstants} class defines common
* constants, which are used across the whole binding.
*
* @author Paul Frank - Initial contribution
*/
@NonNullByDefault
public class StiebelEltronBindingConstants {
private static final String BINDING_ID = ModbusBindingConstants.BINDING_ID;
// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_HEATPUMP = new ThingTypeUID(BINDING_ID, "heatpump");
// Channel group ids
public static final String GROUP_SYSTEM_STATE = "systemState";
public static final String GROUP_SYSTEM_PARAMETER = "systemParameter";
public static final String GROUP_SYSTEM_INFO = "systemInformation";
public static final String GROUP_ENERGY_INFO = "energyInformation";
// List of all Channel ids in device information group
public static final String CHANNEL_FEK_TEMPERATURE = "fek-temperature";
public static final String CHANNEL_FEK_TEMPERATURE_SETPOINT = "fek-temperature-setpoint";
public static final String CHANNEL_FEK_HUMIDITY = "fek-humidity";
public static final String CHANNEL_FEK_DEWPOINT = "fek-dewpoint";
public static final String CHANNEL_OUTDOOR_TEMPERATURE = "outdoor-temperature";
public static final String CHANNEL_HK1_TEMPERATURE = "hk1-temperature";
public static final String CHANNEL_HK1_TEMPERATURE_SETPOINT = "hk1-temperature-setpoint";
public static final String CHANNEL_SUPPLY_TEMPERATURE = "supply-temperature";
public static final String CHANNEL_RETURN_TEMPERATURE = "return-temperature";
public static final String CHANNEL_SOURCE_TEMPERATURE = "source-temperature";
public static final String CHANNEL_WATER_TEMPERATURE = "water-temperature";
public static final String CHANNEL_WATER_TEMPERATURE_SETPOINT = "water-temperature-setpoint";
public static final String CHANNEL_PRODUCTION_HEAT_TODAY = "production-heat-today";
public static final String CHANNEL_PRODUCTION_HEAT_TOTAL = "production-heat-total";
public static final String CHANNEL_PRODUCTION_WATER_TODAY = "production-water-today";
public static final String CHANNEL_PRODUCTION_WATER_TOTAL = "production-water-total";
public static final String CHANNEL_CONSUMPTION_HEAT_TODAY = "consumption-heat-today";
public static final String CHANNEL_CONSUMPTION_HEAT_TOTAL = "consumption-heat-total";
public static final String CHANNEL_CONSUMPTION_WATER_TODAY = "consumption-water-today";
public static final String CHANNEL_CONSUMPTION_WATER_TOTAL = "consumption-water-total";
public static final String CHANNEL_IS_HEATING = "is-heating";
public static final String CHANNEL_IS_HEATING_WATER = "is-heating-water";
public static final String CHANNEL_IS_COOLING = "is-cooling";
public static final String CHANNEL_IS_PUMPING = "is-pumping";
public static final String CHANNEL_IS_SUMMER = "is-summer";
public static final String CHANNEL_OPERATION_MODE = "operation-mode";
public static final String CHANNEL_COMFORT_TEMPERATURE_HEATING = "comfort-temperature-heating";
public static final String CHANNEL_ECO_TEMPERATURE_HEATING = "eco-temperature-heating";
public static final String CHANNEL_COMFORT_TEMPERATURE_WATER = "comfort-temperature-water";
public static final String CHANNEL_ECO_TEMPERATURE_WATER = "eco-temperature-water";
}

View File

@@ -0,0 +1,46 @@
/**
* Copyright (c) 2010-2020 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.modbus.stiebeleltron.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link Modbus.StiebelEltronConfiguration} class contains fields mapping
* thing configuration parameters.
*
* @author Paul Frank - Initial contribution
*/
@NonNullByDefault
public class StiebelEltronConfiguration {
/**
* Refresh interval in seconds
*/
private long refresh;
private int maxTries = 3;// backwards compatibility and tests
/**
* Gets refresh period in milliseconds
*/
public long getRefreshMillis() {
return refresh * 1000;
}
public int getMaxTries() {
return maxTries;
}
public void setMaxTries(int maxTries) {
this.maxTries = maxTries;
}
}

View File

@@ -0,0 +1,57 @@
/**
* Copyright (c) 2010-2020 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.modbus.stiebeleltron.internal;
import static org.openhab.binding.modbus.stiebeleltron.internal.StiebelEltronBindingConstants.THING_TYPE_HEATPUMP;
import java.util.Collections;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.modbus.stiebeleltron.internal.handler.StiebelEltronHandler;
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 Modbus.StiebelEltronHandlerFactory} is responsible for creating things and thing
* handlers.
*
* @author Paul Frank - Initial contribution
*/
@NonNullByDefault
@Component(configurationPid = "binding.stiebeleltron", service = ThingHandlerFactory.class)
public class StiebelEltronHandlerFactory extends BaseThingHandlerFactory {
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_HEATPUMP);
@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_HEATPUMP.equals(thingTypeUID)) {
return new StiebelEltronHandler(thing);
}
return null;
}
}

View File

@@ -0,0 +1,36 @@
/**
* Copyright (c) 2010-2020 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.modbus.stiebeleltron.internal.dto;
/**
* Dto class for the Energy Block
*
* @author Paul Frank - Initial contribution
*
*/
public class EnergyBlock {
public int productionHeatToday;
public int productionHeatTotalLow;
public int productionHeatTotalHigh;
public int productionWaterToday;
public int productionWaterTotalLow;
public int productionWaterTotalHigh;
public int consumptionHeatToday;
public int consumptionHeatTotalLow;
public int consumptionHeatTotalHigh;
public int consumptionWaterToday;
public int consumptionWaterTotalLow;
public int consumptionWaterTotalHigh;
}

View File

@@ -0,0 +1,35 @@
/**
* Copyright (c) 2010-2020 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.modbus.stiebeleltron.internal.dto;
/**
* Dto class for the System Information Block
*
* @author Paul Frank - Initial contribution
*
*/
public class SystemInformationBlock {
public short temperatureFek;
public short temperatureFekSetPoint;
public short humidityFek;
public short dewpointFek;
public short temperatureOutdoor;
public short temperatureHk1;
public short temperatureHk1SetPoint;
public short temperatureSupply;
public short temperatureReturn;
public short temperatureSource;
public short temperatureWater;
public short temperatureWaterSetPoint;
}

View File

@@ -0,0 +1,28 @@
/**
* Copyright (c) 2010-2020 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.modbus.stiebeleltron.internal.dto;
/**
* Dto class for the System Parameter Block
*
* @author Paul Frank - Initial contribution
*
*/
public class SystemParameterBlock {
public int operationMode;
public short comfortTemperatureHeating;
public short ecoTemperatureHeating;
public short comfortTemperatureWater;
public short ecoTemperatureWater;
}

View File

@@ -0,0 +1,24 @@
/**
* Copyright (c) 2010-2020 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.modbus.stiebeleltron.internal.dto;
/**
* Dto class for the System State Block
*
* @author Paul Frank - Initial contribution
*
*/
public class SystemStateBlock {
public int state;
}

View File

@@ -0,0 +1,32 @@
/**
* Copyright (c) 2010-2020 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.modbus.stiebeleltron.internal.handler;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* Thrown when the stiebel eltron handler sees an error.
*
* @author Paul Frank - Initial contribution
*/
@SuppressWarnings("serial")
@NonNullByDefault
public class StiebelEltronException extends Exception {
public StiebelEltronException() {
}
public StiebelEltronException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,711 @@
/**
* Copyright (c) 2010-2020 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.modbus.stiebeleltron.internal.handler;
import static org.openhab.binding.modbus.stiebeleltron.internal.StiebelEltronBindingConstants.*;
import static org.openhab.core.library.unit.SIUnits.CELSIUS;
import static org.openhab.core.library.unit.SmartHomeUnits.KILOWATT_HOUR;
import static org.openhab.core.library.unit.SmartHomeUnits.PERCENT;
import java.util.Optional;
import javax.measure.Unit;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.modbus.handler.EndpointNotInitializedException;
import org.openhab.binding.modbus.handler.ModbusEndpointThingHandler;
import org.openhab.binding.modbus.stiebeleltron.internal.StiebelEltronConfiguration;
import org.openhab.binding.modbus.stiebeleltron.internal.dto.EnergyBlock;
import org.openhab.binding.modbus.stiebeleltron.internal.dto.SystemInformationBlock;
import org.openhab.binding.modbus.stiebeleltron.internal.dto.SystemParameterBlock;
import org.openhab.binding.modbus.stiebeleltron.internal.dto.SystemStateBlock;
import org.openhab.binding.modbus.stiebeleltron.internal.parser.EnergyBlockParser;
import org.openhab.binding.modbus.stiebeleltron.internal.parser.SystemInfromationBlockParser;
import org.openhab.binding.modbus.stiebeleltron.internal.parser.SystemParameterBlockParser;
import org.openhab.binding.modbus.stiebeleltron.internal.parser.SystemStateBlockParser;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.thing.Bridge;
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.ThingStatusInfo;
import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType;
import org.openhab.core.types.State;
import org.openhab.io.transport.modbus.AsyncModbusFailure;
import org.openhab.io.transport.modbus.ModbusCommunicationInterface;
import org.openhab.io.transport.modbus.ModbusReadFunctionCode;
import org.openhab.io.transport.modbus.ModbusReadRequestBlueprint;
import org.openhab.io.transport.modbus.ModbusRegister;
import org.openhab.io.transport.modbus.ModbusRegisterArray;
import org.openhab.io.transport.modbus.ModbusWriteRegisterRequestBlueprint;
import org.openhab.io.transport.modbus.ModbusWriteRequestBlueprint;
import org.openhab.io.transport.modbus.PollTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link Modbus.StiebelEltronHandler} is responsible for handling commands,
* which are sent to one of the channels and for polling the modbus.
*
* @author Paul Frank - Initial contribution
*/
@NonNullByDefault
public class StiebelEltronHandler extends BaseThingHandler {
public abstract class AbstractBasePoller {
private final Logger logger = LoggerFactory.getLogger(StiebelEltronHandler.class);
private volatile @Nullable PollTask pollTask;
public synchronized void unregisterPollTask() {
PollTask task = pollTask;
if (task == null) {
return;
}
ModbusCommunicationInterface mycomms = StiebelEltronHandler.this.comms;
if (mycomms != null) {
mycomms.unregisterRegularPoll(task);
}
pollTask = null;
}
/**
* Register poll task This is where we set up our regular poller
*/
public synchronized void registerPollTask(int address, int length, ModbusReadFunctionCode readFunctionCode) {
logger.debug("Setting up regular polling");
ModbusCommunicationInterface mycomms = StiebelEltronHandler.this.comms;
StiebelEltronConfiguration myconfig = StiebelEltronHandler.this.config;
if (myconfig == null || mycomms == null) {
throw new IllegalStateException("registerPollTask called without proper configuration");
}
ModbusReadRequestBlueprint request = new ModbusReadRequestBlueprint(getSlaveId(), readFunctionCode, address,
length, myconfig.getMaxTries());
long refreshMillis = myconfig.getRefreshMillis();
pollTask = mycomms.registerRegularPoll(request, refreshMillis, 1000, result -> {
result.getRegisters().ifPresent(this::handlePolledData);
if (getThing().getStatus() != ThingStatus.ONLINE) {
updateStatus(ThingStatus.ONLINE);
}
}, StiebelEltronHandler.this::handleReadError);
}
public synchronized void poll() {
PollTask task = pollTask;
ModbusCommunicationInterface mycomms = StiebelEltronHandler.this.comms;
if (task != null && mycomms != null) {
mycomms.submitOneTimePoll(task.getRequest(), task.getResultCallback(), task.getFailureCallback());
}
}
protected abstract void handlePolledData(ModbusRegisterArray registers);
}
/**
* Logger instance
*/
private final Logger logger = LoggerFactory.getLogger(StiebelEltronHandler.class);
/**
* Configuration instance
*/
protected @Nullable StiebelEltronConfiguration config = null;
/**
* Parser used to convert incoming raw messages into system blocks
*/
private final SystemInfromationBlockParser systemInformationBlockParser = new SystemInfromationBlockParser();
/**
* Parser used to convert incoming raw messages into system state blocks
*/
private final SystemStateBlockParser systemstateBlockParser = new SystemStateBlockParser();
/**
* Parser used to convert incoming raw messages into system parameter blocks
*/
private final SystemParameterBlockParser systemParameterBlockParser = new SystemParameterBlockParser();
/**
* Parser used to convert incoming raw messages into model blocks
*/
private final EnergyBlockParser energyBlockParser = new EnergyBlockParser();
/**
* This is the task used to poll the device
*/
private volatile @Nullable AbstractBasePoller systemInformationPoller = null;
/**
* This is the task used to poll the device
*/
private volatile @Nullable AbstractBasePoller energyPoller = null;
/**
* This is the task used to poll the device
*/
private volatile @Nullable AbstractBasePoller systemStatePoller = null;
/**
* This is the task used to poll the device
*/
private volatile @Nullable AbstractBasePoller systemParameterPoller = null;
/**
* Communication interface to the slave endpoint we're connecting to
*/
protected volatile @Nullable ModbusCommunicationInterface comms = null;
/**
* This is the slave id, we store this once initialization is complete
*/
private volatile int slaveId;
/**
* Instances of this handler should get a reference to the modbus manager
*
* @param thing the thing to handle
* @param modbusManager the modbus manager
*/
public StiebelEltronHandler(Thing thing) {
super(thing);
}
/**
* @param address address of the value to be written on the modbus
* @param shortValue value to be written on the modbus
*/
protected void writeInt16(int address, short shortValue) {
StiebelEltronConfiguration myconfig = StiebelEltronHandler.this.config;
ModbusCommunicationInterface mycomms = StiebelEltronHandler.this.comms;
if (myconfig == null || mycomms == null) {
throw new IllegalStateException("registerPollTask called without proper configuration");
}
// big endian byte ordering
byte b1 = (byte) (shortValue >> 8);
byte b2 = (byte) shortValue;
ModbusRegister register = new ModbusRegister(b1, b2);
ModbusRegisterArray data = new ModbusRegisterArray(new ModbusRegister[] { register });
ModbusWriteRegisterRequestBlueprint request = new ModbusWriteRegisterRequestBlueprint(slaveId, address, data,
false, myconfig.getMaxTries());
mycomms.submitOneTimeWrite(request, result -> {
if (hasConfigurationError()) {
return;
}
logger.debug("Successful write, matching request {}", request);
StiebelEltronHandler.this.updateStatus(ThingStatus.ONLINE);
}, failure -> {
StiebelEltronHandler.this.handleWriteError(failure);
});
}
/**
* @param command get the value of this command.
* @return short the value of the command multiplied by 10 (see datatype 2 in
* the stiebel eltron modbus documentation)
*/
private short getScaledInt16Value(Command command) throws StiebelEltronException {
if (command instanceof QuantityType) {
QuantityType<?> c = ((QuantityType<?>) command).toUnit(CELSIUS);
if (c != null) {
return (short) (c.doubleValue() * 10);
} else {
throw new StiebelEltronException("Unsupported unit");
}
}
if (command instanceof DecimalType) {
DecimalType c = (DecimalType) command;
return (short) (c.doubleValue() * 10);
}
throw new StiebelEltronException("Unsupported command type");
}
/**
* @param command get the value of this command.
* @return short the value of the command as short
*/
private short getInt16Value(Command command) throws StiebelEltronException {
if (command instanceof DecimalType) {
DecimalType c = (DecimalType) command;
return c.shortValue();
}
throw new StiebelEltronException("Unsupported command type");
}
/**
* Handle incoming commands.
*/
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
if (RefreshType.REFRESH == command) {
String groupId = channelUID.getGroupId();
if (groupId != null) {
AbstractBasePoller poller;
switch (groupId) {
case GROUP_SYSTEM_STATE:
poller = systemStatePoller;
break;
case GROUP_SYSTEM_PARAMETER:
poller = systemParameterPoller;
break;
case GROUP_SYSTEM_INFO:
poller = systemInformationPoller;
break;
case GROUP_ENERGY_INFO:
poller = energyPoller;
break;
default:
poller = null;
break;
}
if (poller != null) {
poller.poll();
}
}
} else {
try {
if (GROUP_SYSTEM_PARAMETER.equals(channelUID.getGroupId())) {
switch (channelUID.getIdWithoutGroup()) {
case CHANNEL_OPERATION_MODE:
writeInt16(1500, getInt16Value(command));
break;
case CHANNEL_COMFORT_TEMPERATURE_HEATING:
writeInt16(1501, getScaledInt16Value(command));
break;
case CHANNEL_ECO_TEMPERATURE_HEATING:
writeInt16(1502, getScaledInt16Value(command));
break;
case CHANNEL_COMFORT_TEMPERATURE_WATER:
writeInt16(1509, getScaledInt16Value(command));
break;
case CHANNEL_ECO_TEMPERATURE_WATER:
writeInt16(1510, getScaledInt16Value(command));
break;
}
}
} catch (StiebelEltronException error) {
if (hasConfigurationError() || getThing().getStatus() == ThingStatus.OFFLINE) {
return;
}
String cls = error.getClass().getName();
String msg = error.getMessage();
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
String.format("Error with: %s: %s", cls, msg));
}
}
}
/**
* Initialization: Load the config object of the block Connect to the slave
* bridge Start the periodic polling
*/
@Override
public void initialize() {
config = getConfigAs(StiebelEltronConfiguration.class);
logger.debug("Initializing thing with properties: {}", thing.getProperties());
startUp();
}
/*
* This method starts the operation of this handler Connect to the slave bridge
* Start the periodic polling1
*/
private void startUp() {
if (comms != null) {
return;
}
ModbusEndpointThingHandler slaveEndpointThingHandler = getEndpointThingHandler();
if (slaveEndpointThingHandler == null) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, "Bridge is offline");
return;
}
try {
slaveId = slaveEndpointThingHandler.getSlaveId();
comms = slaveEndpointThingHandler.getCommunicationInterface();
} catch (EndpointNotInitializedException e) {
// this will be handled below as endpoint remains null
}
if (comms == null) {
@SuppressWarnings("null")
String label = Optional.ofNullable(getBridge()).map(b -> b.getLabel()).orElse("<null>");
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE,
String.format("Bridge '%s' not completely initialized", label));
return;
}
if (config == null) {
logger.debug("Invalid comms/config/manager ref for stiebel eltron handler");
return;
}
if (systemInformationPoller == null) {
AbstractBasePoller poller = new AbstractBasePoller() {
@Override
protected void handlePolledData(ModbusRegisterArray registers) {
handlePolledSystemInformationData(registers);
}
};
poller.registerPollTask(500, 36, ModbusReadFunctionCode.READ_INPUT_REGISTERS);
systemInformationPoller = poller;
}
if (energyPoller == null) {
AbstractBasePoller poller = new AbstractBasePoller() {
@Override
protected void handlePolledData(ModbusRegisterArray registers) {
handlePolledEnergyData(registers);
}
};
poller.registerPollTask(3500, 16, ModbusReadFunctionCode.READ_INPUT_REGISTERS);
energyPoller = poller;
}
if (systemStatePoller == null) {
AbstractBasePoller poller = new AbstractBasePoller() {
@Override
protected void handlePolledData(ModbusRegisterArray registers) {
handlePolledSystemStateData(registers);
}
};
poller.registerPollTask(2500, 2, ModbusReadFunctionCode.READ_INPUT_REGISTERS);
systemStatePoller = poller;
}
if (systemParameterPoller == null) {
AbstractBasePoller poller = new AbstractBasePoller() {
@Override
protected void handlePolledData(ModbusRegisterArray registers) {
handlePolledSystemParameterData(registers);
}
};
poller.registerPollTask(1500, 11, ModbusReadFunctionCode.READ_MULTIPLE_REGISTERS);
systemParameterPoller = poller;
}
updateStatus(ThingStatus.UNKNOWN);
}
/**
* Dispose the binding correctly
*/
@Override
public void dispose() {
tearDown();
}
/**
* Unregister the poll tasks and release the endpoint reference
*/
private void tearDown() {
AbstractBasePoller poller = systemInformationPoller;
if (poller != null) {
logger.debug("Unregistering systemInformationPoller from ModbusManager");
poller.unregisterPollTask();
systemInformationPoller = null;
}
poller = energyPoller;
if (poller != null) {
logger.debug("Unregistering energyPoller from ModbusManager");
poller.unregisterPollTask();
energyPoller = null;
}
poller = systemStatePoller;
if (poller != null) {
logger.debug("Unregistering systemStatePoller from ModbusManager");
poller.unregisterPollTask();
systemStatePoller = null;
}
poller = systemParameterPoller;
if (poller != null) {
logger.debug("Unregistering systemParameterPoller from ModbusManager");
poller.unregisterPollTask();
systemParameterPoller = null;
}
comms = null;
}
/**
* Returns the current slave id from the bridge
*/
public int getSlaveId() {
return slaveId;
}
/**
* Get the endpoint handler from the bridge this handler is connected to Checks
* that we're connected to the right type of bridge
*
* @return the endpoint handler or null if the bridge does not exist
*/
private @Nullable ModbusEndpointThingHandler getEndpointThingHandler() {
Bridge bridge = getBridge();
if (bridge == null) {
logger.debug("Bridge is null");
return null;
}
if (bridge.getStatus() != ThingStatus.ONLINE) {
logger.debug("Bridge is not online");
return null;
}
ThingHandler handler = bridge.getHandler();
if (handler == null) {
logger.debug("Bridge handler is null");
return null;
}
if (handler instanceof ModbusEndpointThingHandler) {
ModbusEndpointThingHandler slaveEndpoint = (ModbusEndpointThingHandler) handler;
return slaveEndpoint;
} else {
throw new IllegalStateException("Unexpected bridge handler: " + handler.toString());
}
}
/**
* Returns value divided by the 10
*
* @param value the value to alter
* @return the scaled value as a DecimalType
*/
protected State getScaled(Number value, Unit<?> unit) {
return QuantityType.valueOf(value.doubleValue() / 10, unit);
}
/**
* Returns high value * 1000 + low value
*
* @param high the high value
* @param low the low valze
* @return the scaled value as a DecimalType
*/
protected State getEnergyQuantity(int high, int low) {
double value = high * 1000 + low;
return QuantityType.valueOf(value, KILOWATT_HOUR);
}
/**
* This method is called each time new data has been polled from the modbus
* slave The register array is first parsed, then each of the channels are
* updated to the new values
*
* @param registers byte array read from the modbus slave
*/
protected void handlePolledSystemInformationData(ModbusRegisterArray registers) {
logger.trace("System Information block received, size: {}", registers.size());
SystemInformationBlock block = systemInformationBlockParser.parse(registers);
// System information group
updateState(channelUID(GROUP_SYSTEM_INFO, CHANNEL_FEK_TEMPERATURE), getScaled(block.temperatureFek, CELSIUS));
updateState(channelUID(GROUP_SYSTEM_INFO, CHANNEL_FEK_TEMPERATURE_SETPOINT),
getScaled(block.temperatureFekSetPoint, CELSIUS));
updateState(channelUID(GROUP_SYSTEM_INFO, CHANNEL_FEK_HUMIDITY), getScaled(block.humidityFek, PERCENT));
updateState(channelUID(GROUP_SYSTEM_INFO, CHANNEL_FEK_DEWPOINT), getScaled(block.dewpointFek, CELSIUS));
updateState(channelUID(GROUP_SYSTEM_INFO, CHANNEL_OUTDOOR_TEMPERATURE),
getScaled(block.temperatureOutdoor, CELSIUS));
updateState(channelUID(GROUP_SYSTEM_INFO, CHANNEL_HK1_TEMPERATURE), getScaled(block.temperatureHk1, CELSIUS));
updateState(channelUID(GROUP_SYSTEM_INFO, CHANNEL_HK1_TEMPERATURE_SETPOINT),
getScaled(block.temperatureHk1SetPoint, CELSIUS));
updateState(channelUID(GROUP_SYSTEM_INFO, CHANNEL_SUPPLY_TEMPERATURE),
getScaled(block.temperatureSupply, CELSIUS));
updateState(channelUID(GROUP_SYSTEM_INFO, CHANNEL_RETURN_TEMPERATURE),
getScaled(block.temperatureReturn, CELSIUS));
updateState(channelUID(GROUP_SYSTEM_INFO, CHANNEL_SOURCE_TEMPERATURE),
getScaled(block.temperatureSource, CELSIUS));
updateState(channelUID(GROUP_SYSTEM_INFO, CHANNEL_WATER_TEMPERATURE),
getScaled(block.temperatureWater, CELSIUS));
updateState(channelUID(GROUP_SYSTEM_INFO, CHANNEL_WATER_TEMPERATURE_SETPOINT),
getScaled(block.temperatureWaterSetPoint, CELSIUS));
resetCommunicationError();
}
/**
* This method is called each time new data has been polled from the modbus
* slave The register array is first parsed, then each of the channels are
* updated to the new values
*
* @param registers byte array read from the modbus slave
*/
protected void handlePolledEnergyData(ModbusRegisterArray registers) {
logger.trace("Energy block received, size: {}", registers.size());
EnergyBlock block = energyBlockParser.parse(registers);
// Energy information group
updateState(channelUID(GROUP_ENERGY_INFO, CHANNEL_PRODUCTION_HEAT_TODAY),
new QuantityType<>(block.productionHeatToday, KILOWATT_HOUR));
updateState(channelUID(GROUP_ENERGY_INFO, CHANNEL_PRODUCTION_HEAT_TOTAL),
getEnergyQuantity(block.productionHeatTotalHigh, block.productionHeatTotalLow));
updateState(channelUID(GROUP_ENERGY_INFO, CHANNEL_PRODUCTION_WATER_TODAY),
new QuantityType<>(block.productionWaterToday, KILOWATT_HOUR));
updateState(channelUID(GROUP_ENERGY_INFO, CHANNEL_PRODUCTION_WATER_TOTAL),
getEnergyQuantity(block.productionWaterTotalHigh, block.productionWaterTotalLow));
updateState(channelUID(GROUP_ENERGY_INFO, CHANNEL_CONSUMPTION_HEAT_TODAY),
new QuantityType<>(block.consumptionHeatToday, KILOWATT_HOUR));
updateState(channelUID(GROUP_ENERGY_INFO, CHANNEL_CONSUMPTION_HEAT_TOTAL),
getEnergyQuantity(block.consumptionHeatTotalHigh, block.consumptionHeatTotalLow));
updateState(channelUID(GROUP_ENERGY_INFO, CHANNEL_CONSUMPTION_WATER_TODAY),
new QuantityType<>(block.consumptionWaterToday, KILOWATT_HOUR));
updateState(channelUID(GROUP_ENERGY_INFO, CHANNEL_CONSUMPTION_WATER_TOTAL),
getEnergyQuantity(block.consumptionWaterTotalHigh, block.consumptionWaterTotalLow));
resetCommunicationError();
}
/**
* This method is called each time new data has been polled from the modbus
* slave The register array is first parsed, then each of the channels are
* updated to the new values
*
* @param registers byte array read from the modbus slave
*/
protected void handlePolledSystemStateData(ModbusRegisterArray registers) {
logger.trace("System state block received, size: {}", registers.size());
SystemStateBlock block = systemstateBlockParser.parse(registers);
boolean isHeating = (block.state & 16) != 0;
updateState(channelUID(GROUP_SYSTEM_STATE, CHANNEL_IS_HEATING),
isHeating ? OpenClosedType.OPEN : OpenClosedType.CLOSED);
updateState(channelUID(GROUP_SYSTEM_STATE, CHANNEL_IS_HEATING_WATER),
(block.state & 32) != 0 ? OpenClosedType.OPEN : OpenClosedType.CLOSED);
updateState(channelUID(GROUP_SYSTEM_STATE, CHANNEL_IS_COOLING),
(block.state & 256) != 0 ? OpenClosedType.OPEN : OpenClosedType.CLOSED);
updateState(channelUID(GROUP_SYSTEM_STATE, CHANNEL_IS_SUMMER),
(block.state & 128) != 0 ? OpenClosedType.OPEN : OpenClosedType.CLOSED);
updateState(channelUID(GROUP_SYSTEM_STATE, CHANNEL_IS_PUMPING),
(block.state & 1) != 0 ? OpenClosedType.OPEN : OpenClosedType.CLOSED);
resetCommunicationError();
}
/**
* This method is called each time new data has been polled from the modbus
* slave The register array is first parsed, then each of the channels are
* updated to the new values
*
* @param registers byte array read from the modbus slave
*/
protected void handlePolledSystemParameterData(ModbusRegisterArray registers) {
logger.trace("System state block received, size: {}", registers.size());
SystemParameterBlock block = systemParameterBlockParser.parse(registers);
updateState(channelUID(GROUP_SYSTEM_PARAMETER, CHANNEL_OPERATION_MODE), new DecimalType(block.operationMode));
updateState(channelUID(GROUP_SYSTEM_PARAMETER, CHANNEL_COMFORT_TEMPERATURE_HEATING),
getScaled(block.comfortTemperatureHeating, CELSIUS));
updateState(channelUID(GROUP_SYSTEM_PARAMETER, CHANNEL_ECO_TEMPERATURE_HEATING),
getScaled(block.ecoTemperatureHeating, CELSIUS));
updateState(channelUID(GROUP_SYSTEM_PARAMETER, CHANNEL_COMFORT_TEMPERATURE_WATER),
getScaled(block.comfortTemperatureWater, CELSIUS));
updateState(channelUID(GROUP_SYSTEM_PARAMETER, CHANNEL_ECO_TEMPERATURE_WATER),
getScaled(block.ecoTemperatureWater, CELSIUS));
resetCommunicationError();
}
/**
* @param bridgeStatusInfo
*/
@Override
public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
super.bridgeStatusChanged(bridgeStatusInfo);
if (bridgeStatusInfo.getStatus() == ThingStatus.ONLINE) {
startUp();
} else if (bridgeStatusInfo.getStatus() == ThingStatus.OFFLINE) {
tearDown();
}
}
/**
* Handle errors received during communication
*/
protected void handleReadError(AsyncModbusFailure<ModbusReadRequestBlueprint> failure) {
// Ignore all incoming data and errors if configuration is not correct
if (hasConfigurationError() || getThing().getStatus() == ThingStatus.OFFLINE) {
return;
}
String msg = failure.getCause().getMessage();
String cls = failure.getCause().getClass().getName();
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
String.format("Error with read: %s: %s", cls, msg));
}
/**
* Handle errors received during communication
*/
protected void handleWriteError(AsyncModbusFailure<ModbusWriteRequestBlueprint> failure) {
// Ignore all incoming data and errors if configuration is not correct
if (hasConfigurationError() || getThing().getStatus() == ThingStatus.OFFLINE) {
return;
}
String msg = failure.getCause().getMessage();
String cls = failure.getCause().getClass().getName();
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
String.format("Error with write: %s: %s", cls, msg));
}
/**
* Returns true, if we're in a CONFIGURATION_ERROR state
*
* @return
*/
protected boolean hasConfigurationError() {
ThingStatusInfo statusInfo = getThing().getStatusInfo();
return statusInfo.getStatus() == ThingStatus.OFFLINE
&& statusInfo.getStatusDetail() == ThingStatusDetail.CONFIGURATION_ERROR;
}
/**
* Reset communication status to ONLINE if we're in an OFFLINE state
*/
protected void resetCommunicationError() {
ThingStatusInfo statusInfo = thing.getStatusInfo();
if (ThingStatus.OFFLINE.equals(statusInfo.getStatus())
&& ThingStatusDetail.COMMUNICATION_ERROR.equals(statusInfo.getStatusDetail())) {
updateStatus(ThingStatus.ONLINE);
}
}
/**
* Returns the channel UID for the specified group and channel id
*
* @param string the channel group
* @param string the channel id in that group
* @return the globally unique channel uid
*/
ChannelUID channelUID(String group, String id) {
return new ChannelUID(getThing().getUID(), group, id);
}
}

View File

@@ -0,0 +1,127 @@
/**
* Copyright (c) 2010-2020 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.modbus.stiebeleltron.internal.parser;
import java.util.Optional;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.library.types.DecimalType;
import org.openhab.io.transport.modbus.ModbusBitUtilities;
import org.openhab.io.transport.modbus.ModbusConstants.ValueType;
import org.openhab.io.transport.modbus.ModbusRegisterArray;
/**
* Base class for parsers with some helper methods
*
* @author Nagy Attila Gabor - Initial contribution
* @author Paul Frank - Added more methods
*/
@NonNullByDefault
public class AbstractBaseParser {
/**
* Extract an optional double value
*
* @param raw the register array to extract from
* @param index the address of the field
* @return the parsed value or empty if the field is not implemented
*/
protected Optional<Double> extractOptionalDouble(ModbusRegisterArray raw, int index) {
return ModbusBitUtilities.extractStateFromRegisters(raw, index, ValueType.INT16)
.map(value -> ((double) value.intValue()) / 10.0).filter(value -> value != (short) 0x8000);
}
/**
* Extract a mandatory double value
*
* @param raw the register array to extract from
* @param index the address of the field
* @param def the default value
* @return the parsed value or the default if the field is not implemented
*/
protected Double extractDouble(ModbusRegisterArray raw, int index, double def) {
return extractOptionalDouble(raw, index).orElse(def);
}
/**
* Extract an optional int16 value
*
* @param raw the register array to extract from
* @param index the address of the field
* @return the parsed value or empty if the field is not implemented
*/
protected Optional<Short> extractOptionalInt16(ModbusRegisterArray raw, int index) {
return ModbusBitUtilities.extractStateFromRegisters(raw, index, ValueType.INT16).map(DecimalType::shortValue)
.filter(value -> value != (short) 0x8000);
}
/**
* Extract a mandatory int16 value
*
* @param raw the register array to extract from
* @param index the address of the field
* @param def the default value
* @return the parsed value or the default if the field is not implemented
*/
protected Short extractInt16(ModbusRegisterArray raw, int index, short def) {
return extractOptionalInt16(raw, index).orElse(def);
}
/**
* Extract an optional uint16 value
*
* @param raw the register array to extract from
* @param index the address of the field
* @return the parsed value or empty if the field is not implemented
*/
protected Optional<Integer> extractOptionalUInt16(ModbusRegisterArray raw, int index) {
return ModbusBitUtilities.extractStateFromRegisters(raw, index, ValueType.UINT16).map(DecimalType::intValue)
.filter(value -> value != 0xffff);
}
/**
* Extract a mandatory uint16 value
*
* @param raw the register array to extract from
* @param index the address of the field
* @param def the default value
* @return the parsed value or the default if the field is not implemented
*/
protected Integer extractUInt16(ModbusRegisterArray raw, int index, int def) {
return extractOptionalUInt16(raw, index).orElse(def);
}
/**
* Extract an optional acc32 value
*
* @param raw the register array to extract from
* @param index the address of the field
* @return the parsed value or empty if the field is not implemented
*/
protected Optional<Long> extractOptionalUInt32(ModbusRegisterArray raw, int index) {
return ModbusBitUtilities.extractStateFromRegisters(raw, index, ValueType.UINT32).map(DecimalType::longValue)
.filter(value -> value != 0);
}
/**
* Extract a mandatory acc32 value
*
* @param raw the register array to extract from
* @param index the address of the field
* @param def the default value
* @return the parsed value or default if the field is not implemented
*/
protected Long extractUnit32(ModbusRegisterArray raw, int index, long def) {
return extractOptionalUInt32(raw, index).orElse(def);
}
}

View File

@@ -0,0 +1,46 @@
/**
* Copyright (c) 2010-2020 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.modbus.stiebeleltron.internal.parser;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.modbus.stiebeleltron.internal.dto.EnergyBlock;
import org.openhab.io.transport.modbus.ModbusRegisterArray;
/**
* Parses inverter modbus data into an Energy Block
*
* @author Paul Frank - Initial contribution
*
*/
@NonNullByDefault
public class EnergyBlockParser extends AbstractBaseParser {
public EnergyBlock parse(ModbusRegisterArray raw) {
EnergyBlock block = new EnergyBlock();
block.productionHeatToday = extractUInt16(raw, 0, (short) 0);
block.productionHeatTotalLow = extractUInt16(raw, 1, (short) 0);
block.productionHeatTotalHigh = extractUInt16(raw, 2, (short) 0);
block.productionWaterToday = extractUInt16(raw, 3, (short) 0);
block.productionWaterTotalLow = extractUInt16(raw, 4, (short) 0);
block.productionWaterTotalHigh = extractUInt16(raw, 5, (short) 0);
block.consumptionHeatToday = extractUInt16(raw, 10, (short) 0);
block.consumptionHeatTotalLow = extractUInt16(raw, 11, (short) 0);
block.consumptionHeatTotalHigh = extractUInt16(raw, 12, (short) 0);
block.consumptionWaterToday = extractUInt16(raw, 13, (short) 0);
block.consumptionWaterTotalLow = extractUInt16(raw, 14, (short) 0);
block.consumptionWaterTotalHigh = extractUInt16(raw, 15, (short) 0);
return block;
}
}

View File

@@ -0,0 +1,45 @@
/**
* Copyright (c) 2010-2020 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.modbus.stiebeleltron.internal.parser;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.modbus.stiebeleltron.internal.dto.SystemInformationBlock;
import org.openhab.io.transport.modbus.ModbusRegisterArray;
/**
* Parses inverter modbus data into an SystemB Information lock
*
* @author Paul Frank - Initial contribution
*
*/
@NonNullByDefault
public class SystemInfromationBlockParser extends AbstractBaseParser {
public SystemInformationBlock parse(ModbusRegisterArray raw) {
SystemInformationBlock block = new SystemInformationBlock();
block.temperatureFek = extractInt16(raw, 2, (short) 0);
block.temperatureFekSetPoint = extractInt16(raw, 3, (short) 0);
block.humidityFek = extractInt16(raw, 4, (short) 0);
block.dewpointFek = extractInt16(raw, 5, (short) 0);
block.temperatureOutdoor = extractInt16(raw, 6, (short) 0);
block.temperatureHk1 = extractInt16(raw, 7, (short) 0);
block.temperatureHk1SetPoint = extractInt16(raw, 9, (short) 0);
block.temperatureSupply = extractInt16(raw, 12, (short) 0);
block.temperatureReturn = extractInt16(raw, 15, (short) 0);
block.temperatureWater = extractInt16(raw, 21, (short) 0);
block.temperatureWaterSetPoint = extractInt16(raw, 22, (short) 0);
block.temperatureSource = extractInt16(raw, 35, (short) 0);
return block;
}
}

View File

@@ -0,0 +1,38 @@
/**
* Copyright (c) 2010-2020 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.modbus.stiebeleltron.internal.parser;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.modbus.stiebeleltron.internal.dto.SystemParameterBlock;
import org.openhab.io.transport.modbus.ModbusRegisterArray;
/**
* Parses inverter modbus data into an System Parameter Block
*
* @author Paul Frank - Initial contribution
*
*/
@NonNullByDefault
public class SystemParameterBlockParser extends AbstractBaseParser {
public SystemParameterBlock parse(ModbusRegisterArray raw) {
SystemParameterBlock block = new SystemParameterBlock();
block.operationMode = extractUInt16(raw, 0, 0);
block.comfortTemperatureHeating = extractInt16(raw, 1, (short) 0);
block.ecoTemperatureHeating = extractInt16(raw, 2, (short) 0);
block.comfortTemperatureWater = extractInt16(raw, 9, (short) 0);
block.ecoTemperatureWater = extractInt16(raw, 10, (short) 0);
return block;
}
}

View File

@@ -0,0 +1,34 @@
/**
* Copyright (c) 2010-2020 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.modbus.stiebeleltron.internal.parser;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.modbus.stiebeleltron.internal.dto.SystemStateBlock;
import org.openhab.io.transport.modbus.ModbusRegisterArray;
/**
* Parses inverter modbus data into an System State Block
*
* @author Paul Frank - Initial contribution
*
*/
@NonNullByDefault
public class SystemStateBlockParser extends AbstractBaseParser {
public SystemStateBlock parse(ModbusRegisterArray raw) {
SystemStateBlock block = new SystemStateBlock();
block.state = extractUInt16(raw, 0, 0);
return block;
}
}

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<config-description:config-descriptions
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:config-description="https://openhab.org/schemas/config-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/config-description/v1.0.0 https://openhab.org/schemas/config-description-1.0.0.xsd">
<config-description uri="thing-type:stiebeleltron:modbusconfig">
<parameter name="refresh" type="integer" min="1" unit="s">
<label>Polling Interval</label>
<description>Poll interval in seconds. Use zero to disable automatic polling.</description>
<default>5</default>
<unitLabel>s</unitLabel>
</parameter>
<parameter name="maxTries" type="integer" min="1">
<label>Maximum Tries When Reading</label>
<default>3</default>
<description>Number of tries when reading data, if some of the reading fail. For single try, enter 1.</description>
<advanced>true</advanced>
</parameter>
</config-description>
</config-description:config-descriptions>

View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="modbus"
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">
<channel-group-type id="system-state">
<label>System State</label>
<channels>
<channel id="is-heating" typeId="is-heating-type"/>
<channel id="is-heating-water" typeId="is-heating-water-type"/>
<channel id="is-cooling" typeId="is-cooling-type"/>
<channel id="is-pumping" typeId="is-pumping-type"/>
<channel id="is-summer" typeId="is-summer-type"/>
</channels>
</channel-group-type>
<channel-group-type id="system-parameter">
<label>System Parameters</label>
<channels>
<channel id="operation-mode" typeId="operation-mode-type"/>
<channel id="comfort-temperature-heating" typeId="comfort-temperature-heating-type"/>
<channel id="eco-temperature-heating" typeId="eco-temperature-heating-type"/>
<channel id="comfort-temperature-water" typeId="comfort-temperature-water-type"/>
<channel id="eco-temperature-water" typeId="eco-temperature-water-type"/>
</channels>
</channel-group-type>
<channel-group-type id="system-information">
<label>System Information</label>
<channels>
<channel id="fek-temperature" typeId="fek-temperature-type"/>
<channel id="fek-temperature-setpoint" typeId="fek-temperature-setpoint-type"/>
<channel id="fek-humidity" typeId="fek-humidity-type"/>
<channel id="fek-dewpoint" typeId="fek-dewpoint-type"/>
<channel id="outdoor-temperature" typeId="outdoor-temperature-type"/>
<channel id="hk1-temperature" typeId="hk1-temperature-type"/>
<channel id="hk1-temperature-setpoint" typeId="hk1-temperature-setpoint-type"/>
<channel id="supply-temperature" typeId="supply-temperature-type"/>
<channel id="return-temperature" typeId="return-temperature-type"/>
<channel id="source-temperature" typeId="source-temperature-type"/>
<channel id="water-temperature" typeId="water-temperature-type"/>
<channel id="water-temperature-setpoint" typeId="water-temperature-setpoint-type"/>
</channels>
</channel-group-type>
<channel-group-type id="energy-information">
<label>Energy Information</label>
<channels>
<channel id="production-heat-today" typeId="production-heat-today-type"/>
<channel id="production-heat-total" typeId="production-heat-total-type"/>
<channel id="production-water-today" typeId="production-water-today-type"/>
<channel id="production-water-total" typeId="production-water-total-type"/>
<channel id="consumption-heat-today" typeId="consumption-heat-today-type"/>
<channel id="consumption-heat-total" typeId="consumption-heat-total-type"/>
<channel id="consumption-water-today" typeId="consumption-water-today-type"/>
<channel id="consumption-water-total" typeId="consumption-water-total-type"/>
</channels>
</channel-group-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,171 @@
<?xml version="1.0" encoding="UTF-8" ?>
<thing:thing-descriptions bindingId="modbus"
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">
<channel-type id="fek-temperature-type">
<item-type>Number:Temperature</item-type>
<label>FFK Temperature</label>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="fek-temperature-setpoint-type">
<item-type>Number:Temperature</item-type>
<label>FFK Temperature Set Point</label>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="fek-humidity-type">
<item-type>Number:Dimensionless</item-type>
<label>FFK Humidity</label>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="fek-dewpoint-type">
<item-type>Number:Temperature</item-type>
<label>FFK Dewpoint</label>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="outdoor-temperature-type">
<item-type>Number:Temperature</item-type>
<label>Outdoor Temperature</label>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="hk1-temperature-type">
<item-type>Number:Temperature</item-type>
<label>HK1 Temperature</label>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="hk1-temperature-setpoint-type">
<item-type>Number:Temperature</item-type>
<label>HK1 Temperature Set Point</label>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="supply-temperature-type">
<item-type>Number:Temperature</item-type>
<label>Supply Temperature</label>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="return-temperature-type">
<item-type>Number:Temperature</item-type>
<label>Return Temperature</label>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="source-temperature-type">
<item-type>Number:Temperature</item-type>
<label>Source Temperature</label>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="water-temperature-type">
<item-type>Number:Temperature</item-type>
<label>Water Temperature</label>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="water-temperature-setpoint-type">
<item-type>Number:Temperature</item-type>
<label>Water Temperature Set Point</label>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="production-heat-today-type">
<item-type>Number:Energy</item-type>
<label>Heat Quantity Today</label>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="production-heat-total-type">
<item-type>Number:Energy</item-type>
<label>Heat Quantity Total</label>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="production-water-today-type">
<item-type>Number:Energy</item-type>
<label>Water Heat Quantity Today</label>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="production-water-total-type">
<item-type>Number:Energy</item-type>
<label>Water Heat Quantity Total</label>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="consumption-heat-today-type">
<item-type>Number:Energy</item-type>
<label>Power Consumption for Heating Today</label>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="consumption-heat-total-type">
<item-type>Number:Energy</item-type>
<label>Power Consumption for Heating Total</label>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="consumption-water-today-type">
<item-type>Number:Energy</item-type>
<label>Power Consumption for Water Today</label>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="consumption-water-total-type">
<item-type>Number:Energy</item-type>
<label>Power Consumption for Water Total</label>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="is-heating-type">
<item-type>Contact</item-type>
<label>Currently Heating</label>
<state readOnly="true"/>
</channel-type>
<channel-type id="is-heating-water-type">
<item-type>Contact</item-type>
<label>Currently Heating Water</label>
<state readOnly="true"/>
</channel-type>
<channel-type id="is-cooling-type">
<item-type>Contact</item-type>
<label>Currently Cooling</label>
<state readOnly="true"/>
</channel-type>
<channel-type id="is-pumping-type">
<item-type>Contact</item-type>
<label>Currently Pumping</label>
<state readOnly="true"/>
</channel-type>
<channel-type id="is-summer-type">
<item-type>Contact</item-type>
<label>Summer Operation Mode</label>
<state readOnly="true"/>
</channel-type>
<channel-type id="operation-mode-type">
<item-type>Number</item-type>
<label>Operation Mode</label>
<state readOnly="true">
<options>
<option value="0">Emergency</option>
<option value="1">Ready</option>
<option value="2">Program</option>
<option value="3">Comfort</option>
<option value="4">Eco</option>
<option value="5">Water</option>
</options>
</state>
</channel-type>
<channel-type id="comfort-temperature-heating-type">
<item-type>Number:Temperature</item-type>
<label>Comfort Temperature Heating</label>
<state pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="eco-temperature-heating-type">
<item-type>Number:Temperature</item-type>
<label>Eco Temperature Heating</label>
<state pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="comfort-temperature-water-type">
<item-type>Number:Temperature</item-type>
<label>Comfort Temperature Water</label>
<state pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="eco-temperature-water-type">
<item-type>Number:Temperature</item-type>
<label>Eco Temperature Water</label>
<state pattern="%.1f %unit%"/>
</channel-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="modbus"
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="heatpump">
<supported-bridge-type-refs>
<bridge-type-ref id="tcp"/>
<bridge-type-ref id="serial"/>
</supported-bridge-type-refs>
<label>Stiebel Eltron ISG</label>
<description>Stiebel Eltron ISG connected through modbus</description>
<channel-groups>
<channel-group id="systemState" typeId="system-state"/>
<channel-group id="systemParameter" typeId="system-parameter"/>
<channel-group id="systemInformation" typeId="system-information"/>
<channel-group id="energyInformation" typeId="energy-information"/>
</channel-groups>
<config-description-ref uri="thing-type:stiebeleltron:modbusconfig"/>
</thing-type>
</thing:thing-descriptions>