mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 07:02:02 +01:00
[kermi] Initial contribution (#16329)
* [kermi] Initial working state Signed-off-by: Kai Neuhaus <code@kaineuhaus.com>
This commit is contained in:
parent
a9a02afe2a
commit
37c6d6b3eb
@ -1151,6 +1151,11 @@
|
||||
<artifactId>org.openhab.binding.modbus.helioseasycontrols</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.binding.modbus.kermi</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.binding.modbus.sbc</artifactId>
|
||||
|
235
bundles/org.openhab.binding.modbus.kermi/README.md
Normal file
235
bundles/org.openhab.binding.modbus.kermi/README.md
Normal file
@ -0,0 +1,235 @@
|
||||
# Kermi Heat pump
|
||||
|
||||
Integrates the X-Center Device (X-Center Pro) of Kermi Heat pump.
|
||||
Kermi X-Center & other attached devices (in progress) are integrated into the Modbus Binding.
|
||||
|
||||
This binding was tested and developed with Kermi x-change dynamic pro heat pump (build 2023).
|
||||
|
||||
Hint: This binding _may_ also work with devices from "Bösch" in Austria, which is a sub-brand of Kermi, they are nearly identically.
|
||||
|
||||
## Prerequisite
|
||||
|
||||
Requirement is contacting Kermi Support to activate Modbus-TCP which can be connected directly by network.
|
||||
Older devices (non-Pro ?) were connected by Modbus-RCP - maybe you can try to connect them here using a Modbus-TCP modulator (e.x. from waveshare or similar).
|
||||
|
||||
## Supported Things
|
||||
|
||||
First you need a "Modbus TCP-Bridge" which establishes the basic connection towards your X-Center device.
|
||||
|
||||
| Name | Thing Type ID | Description |
|
||||
|--------------------------|---------------|-----------------------------------------------------------------------------------------------------------------------------|
|
||||
| Kermi Heat Pump X-Center | kermi-xcenter | Provides (electric) Power values, Flow-information, PV-States, Temperatures and general Information of your Kermi Heat Pump |
|
||||
|
||||
## Discovery
|
||||
|
||||
This binding does not support autodiscovery.
|
||||
|
||||
## Device IDs
|
||||
|
||||
| Device | Device ID | Comment |
|
||||
|---------------------|-----------|-------------------------------------------------|
|
||||
| X-Center | 40 | on cascade-circuits: slave1: 41, slave2: 42, ...|
|
||||
|
||||
## Thing Configuration
|
||||
|
||||
The needed Bridge can be found in the **Modbus Binding** and have to be added manually without Discovery.
|
||||
|
||||
1. Create _Modbus TCP Slave (Bridge)_ with matching Settings of your Kermi Device:
|
||||
|
||||
- **IP Address** - IP Address or hostname of your heatpump
|
||||
- **Port** - Port of modbus on your heatpump (normally 502)
|
||||
- **Device ID** - ID on modbus, 40 is default for Kermi (see [Device IDs](#device-ids))
|
||||
|
||||
1. Create _Kermi Heat Pump X-Center_ and attach it to the previous installed _Modbus TCP Slave (Bridge)_.
|
||||
Configuration requires an appropriate Data Refresh Interval with more than 2000 Milliseconds, default is 5000.
|
||||
If it's too fast, you may experience errors in openHAB or your X-Center!
|
||||
Reboot if X-Center stops responding on network access.
|
||||
You can enable "PV Modulation" if you want to read the values (default: disabled)
|
||||
|
||||
Details on Configurations explained below.
|
||||
|
||||
### Modbus TCP Slave
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|---------|---------------------------------------------------------------|
|
||||
| host | text | IP Address or reachable hostname of your device |
|
||||
| port | integer | TCP Port of your Kermi device Modbus Settings. Default is 502 |
|
||||
| deviceId | integer | Modbus ID of your Kermi device Modbus Settings. Default is 40 |
|
||||
|
||||
### Kermi Heat Pump X-Center
|
||||
|
||||
Select as Bridge your previously created Modbus TCP Slave.
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|---------|----------------------------------------------------------------|
|
||||
| refresh | integer | Refresh Rate of X-Center values in Milliseconds (default:5000) |
|
||||
| pvEnabled | boolean | Read PV-Modulation (default:false) |
|
||||
|
||||
|
||||
### Kermi StorageSystemModule (support planned in future releases)
|
||||
|
||||
Select as Bridge a separate (second) Modbus TCP Slave.
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|---------|--------------------------------------------------------------------|
|
||||
| host | text | IP Address or reachable hostname of your device (same as X-Center) |
|
||||
| port | integer | TCP Port of your Kermi device Modbus Settings. Default is 502 |
|
||||
| deviceId | integer | Modbus ID of your Kermi device Modbus Settings. Default is 50 |
|
||||
|
||||
### Channel-Groups
|
||||
|
||||
The X-Center / StorageSystemModule device offers quite an amount of channels.
|
||||
They are grouped into 7 channel-groups:
|
||||
|
||||
- State
|
||||
- EnergySource
|
||||
- Charging Circuit
|
||||
- Power & Efficiency
|
||||
- Workhours
|
||||
- Alarm
|
||||
- PV Modulation
|
||||
|
||||
### Channels
|
||||
|
||||
#### Status
|
||||
|
||||
| Channel Id | Channel | Type | Description |
|
||||
|-----------------|-----------------|--------|----------------------------------------------------------------------|
|
||||
| global-state-id | Global State ID | Number | State of heat pump as Number, displayed as readable State-Text in UI |
|
||||
|
||||
Possible states:
|
||||
|
||||
- Standby
|
||||
- Alarm
|
||||
- DrinkingWater
|
||||
- Heating
|
||||
- Defrost
|
||||
- Preparing
|
||||
- Blocked
|
||||
- EVU Blocktime
|
||||
- Unavailable
|
||||
|
||||
#### Energy-Source
|
||||
|
||||
| Channel Id | Channel Label | Channnel Id | Type | Description |
|
||||
|----------------------------|----------------------|-------------|---------------------|-------------------------------------------------|
|
||||
| exit-temperature | Exit temperature | | Number<Temperature> | in °C - Air temperature exiting heat pump |
|
||||
| incoming-temperature | Incoming temperature | | Number<Temperature> | in °C - Air temperature incoming into heat pump |
|
||||
| temperature-sensor-outside | Temperature Outside | | Number<Temperature> | in °C - Outside Air Temperature (if connected) |
|
||||
|
||||
#### Charging Circuit
|
||||
|
||||
| Channel Id | Channel Label | Type | Description |
|
||||
|--------------------|--------------------|----------------------------|-----------------------------------------------------------------------------------|
|
||||
| flow-temperature | Flow temperature | Number<Temperature> | in °C - Water temperature **from** heat pump to drinking water or heating circuit |
|
||||
| return-temperature | Return temperature | Number<Temperature> | in °C - Water temperature returning back **to** heat pump |
|
||||
| flow-speed | Flow speed | Number<VolumetricFlowRate> | in l/min - Flow speed of the water |
|
||||
|
||||
#### Power and efficiency
|
||||
|
||||
| Channel Id | Channel Label | Type | Description |
|
||||
|--------------------------------|---------------------------------------|---------------|--------------------------------------------------|
|
||||
| cop | Current COP | Number | current cop overall (Coefficient Of Performance) |
|
||||
| cop-heating | Current COP heating | Number | cop for heating |
|
||||
| cop-drinkingwater | Current COP drinking water | Number | cop for drinking water |
|
||||
| cop-cooling | Current COP cooling | Number | cop for cooling |
|
||||
| | | | |
|
||||
| power | Current power | Number<Power> | in W (Watt) - Power overall |
|
||||
| power-heating | Current power heating | Number<Power> | in W (Watt) - Power for heating |
|
||||
| power-drinkingwater | Current power drinking water | Number<Power> | in W (Watt) - Power for drinking water |
|
||||
| power-cooling | Current power cooling | Number<Power> | in W (Watt) - Power for cooling |
|
||||
| | | | |
|
||||
| electrical-power | Current electric power | Number<Power> | in W (Watt) - electric Power overall |
|
||||
| electrical-power-heating | Current electric power heating | Number<Power> | in W (Watt) - electric Power for heating |
|
||||
| electrical-power-drinkingwater | Current electric power drinking water | Number<Power> | in W (Watt) - electric Power for drinking water |
|
||||
| electrical-power-cooling | Current electric power cooling | Number<Power> | in W (Watt) - electric Power for cooling |
|
||||
|
||||
#### Workhours
|
||||
|
||||
| Channel Id | Channel Label | Type | Description |
|
||||
|--------------------------------|--------------------------------|--------------|--------------------------------------------------------|
|
||||
| workhours-fan | Fan workhours | Number<Time> | in h (hour) - worked hours of the fan |
|
||||
| workhours-storage-loading-pump | Storage Loading Pump workhours | Number<Time> | in h (hour) - worked hours of the storage loading pump |
|
||||
| workhours-compressor | Compressor workhours | Number<Time> | in h (hour) - worked hours of the compressor |
|
||||
|
||||
#### Alarm
|
||||
|
||||
| Channel Id | Channel Label | Type | Description |
|
||||
|-------------|---------------|--------|---------------------------------|
|
||||
| alarm-state | Alarm state | Switch | On / true if an alarm is raised |
|
||||
|
||||
#### PV Modulation
|
||||
|
||||
| Channel Id | Channel Label | Type | Description |
|
||||
|-------------------------------------|-----------------------------------|---------------------|-------------------------------------------------------------------|
|
||||
| pv-state | PV Modulation Active | Switch | On / true if PV Modulation is currently active |
|
||||
| pv-power | PV Power | Numbery<Power> | in W (Watt) - Power of PV Modulation |
|
||||
| pv-target-temperature-heating | Target temperature heating | Number<Temperature> | in °C - target Temperature in PV Mode of heating (storage) |
|
||||
| pv-target-temperature-drinkingwater | Target temperature drinking water | Number<Temperature> | in °C - target Temperature in PV Mode of drinking water (storage) |
|
||||
|
||||
## Full Example
|
||||
|
||||
Attention: Configuration by file is not recommended. You can configure everything in the main UI.
|
||||
|
||||
### `kermi.things` Example
|
||||
|
||||
```java
|
||||
Bridge modbus:tcp:device "Kermi X-Center Modbus TCP" [ host="xcenter", port=502, id=40 ] {
|
||||
Bridge kermi-xcenter heatpump "Kermi X-Center Heat Pump" [ refresh=5000, pvEnabled=false ]
|
||||
}
|
||||
```
|
||||
|
||||
### Items
|
||||
|
||||
```java
|
||||
Number XCenter_Global_State_Id "X-Center Global State ID" (kermi) { channel="modbus:tcp:device:heatpump:state#global-state-id" }
|
||||
|
||||
Number:Temperature Heatpump_FlowTemperature "Flow Temperature" (kermi,persist) { channel="modbus:tcp:device:heatpump:charging-circuit#flow-temperature" }
|
||||
Number:Temperature Heatpump_ReturnTemperature "Return Temperature" (kermi,persist) { channel="modbus:tcp:device:heatpump:charging-circuit#return-temperature" }
|
||||
Number:VolumetricFlowRate Heatpump_FlowSpeed "Flow Speed" (kermi,persist) { channel="modbus:tcp:device:heatpump:charging-circuit#flow-speed" }
|
||||
|
||||
Number:Temperature Heatpump_ExitTemperature "Exit Temperature" (kermi,persist) { channel="modbus:tcp:device:heatpump:energy-source#exit-temperature" }
|
||||
Number:Temperature Heatpump_Incomingtemperature "Incoming temperature" (kermi,persist) { channel="modbus:tcp:device:heatpump:energy-source#incoming-temperature" }
|
||||
Number:Temperature Heatpump_TemperatureOutside "Temperature Outside" (kermi,persist) { channel="modbus:tcp:device:heatpump:energy-source#temperature-sensor-outside" }
|
||||
|
||||
Number Heatpump_CurrentCOP "Current COP" (kermi) { channel="modbus:tcp:device:heatpump:power-channel#cop" }
|
||||
Number Heatpump_CurrentCOPHeating "Current COP Heating" (kermi) { channel="modbus:tcp:device:heatpump:power-channel#cop-heating" }
|
||||
Number Heatpump_CurrentCOPdrinkingwater "Current COP drinking water" (kermi) { channel="modbus:tcp:device:heatpump:power-channel#cop-drinkingwater" }
|
||||
Number Heatpump_CurrentCOPCooling "Current COP Cooling" (kermi) { channel="modbus:tcp:device:heatpump:power-channel#cop-cooling" }
|
||||
Number:Power Heatpump_CurrentPower "Current Power" (kermi) { channel="modbus:tcp:device:heatpump:power-channel#power" }
|
||||
Number:Power Heatpump_Currentpowerheating "Current power heating" (kermi) { channel="modbus:tcp:device:heatpump:power-channel#power-heating" }
|
||||
Number:Power Heatpump_CurrentPowerDrinkingWater "Current Power Drinking Water" (kermi) { channel="modbus:tcp:device:heatpump:power-channel#power-drinkingwater" }
|
||||
Number:Power Heatpump_Currentpowercooling "Current power cooling" (kermi) { channel="modbus:tcp:device:heatpump:power-channel#power-cooling" }
|
||||
Number:Power Heatpump_CurrentElectricPower "Current Electric Power" (kermi) { channel="modbus:tcp:device:heatpump:power-channel#electric-power" }
|
||||
Number:Power Heatpump_CurrentElectricPowerHeating "Current Electric Power Heating" (kermi) { channel="modbus:tcp:device:heatpump:power-channel#electric-power-heating" }
|
||||
Number:Power Heatpump_Currentelectricpowerdrinkingwater "Current electric power drinking water" (kermi) { channel="modbus:tcp:device:heatpump:power-channel#electric-power-drinkingwater" }
|
||||
Number:Power Heatpump_CurrentElectricPowerCooling "Current Electric Power Cooling" (kermi) { channel="modbus:tcp:device:heatpump:power-channel#electric-power-cooling" }
|
||||
|
||||
Switch Heatpump_PVModulationActive "PV Modulation Active" (kermi) { channel="modbus:tcp:device:heatpump:pv-modulation#pv-state" }
|
||||
Number:Power Heatpump_PVPower "PV Power" (kermi) { channel="modbus:tcp:device:heatpump:pv-modulation#pv-power" }
|
||||
Number:Temperature Heatpump_PVTempHeating "PV Temp Heating" (kermi) { channel="modbus:tcp:device:heatpump:pv-modulation#pv-target-temperature-heating" }
|
||||
Number:Temperature Heatpump_PVTempDrinkingwater "PV Temp Drinkingwater" (kermi) { channel="modbus:tcp:device:heatpump:pv-modulation#pv-target-temperature-drinkingwater" }
|
||||
|
||||
Number:Time Heatpump_FanWorkhours "Fan Workhours" (kermi) { channel="modbus:tcp:device:heatpump:workhours#workhours-fan" }
|
||||
Number:Time Heatpump_StorageLoadingPumpWorkhours "StorageLoadingPump Workhours" (kermi) { channel="modbus:tcp:device:heatpump:workhours#workhours-storage-loading-pump" }
|
||||
Number:Time Heatpump_CompressorWorkhours "Compressor Workhours" (kermi) { channel="modbus:tcp:device:heatpump:workhours#workhours-compressor" }
|
||||
```
|
||||
|
||||
## Persistence
|
||||
|
||||
You can / should persist some items you want to track, maybe you track your power consumption with another device (PV-System or 'smart' electricity meter), so you can compare these values.
|
||||
|
||||
Suggestion / Optional:
|
||||
As these (power & temperature) values are long-running ones, maybe you should invest a little amount of time using influxDB as persistence (additionally to your existing default persistence in openHAB).
|
||||
InfluxDB is a good storage-solution for long terms and uses very small space for its data. Please read the documentation for better understanding how it works.
|
||||
|
||||
|
||||
### Visualization
|
||||
|
||||
As many other users I like and use the Grafana approach (in combination with influxdb).
|
||||
See here for more information [InfluxDB & Grafana Tutorial](https://community.openhab.org/t/influxdb-grafana-persistence-and-graphing/13761)
|
||||
|
||||
### Credits
|
||||
|
||||
Credits goes to Bernd Weymann (Author of E3DC-Modbus-Binding).
|
||||
I used its basic structure / code and handling of Modbus Messages for this binding. Thanks.
|
25
bundles/org.openhab.binding.modbus.kermi/pom.xml
Normal file
25
bundles/org.openhab.binding.modbus.kermi/pom.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<?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 https://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>4.3.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>org.openhab.binding.modbus.kermi</artifactId>
|
||||
|
||||
<name>openHAB Add-ons :: Bundles :: Kermi Modbus Binding</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.binding.modbus</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -0,0 +1,86 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.kermi.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.ModbusBindingConstants;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link KermiBindingConstants} class defines common constants, which are
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Kai Neuhaus - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class KermiBindingConstants {
|
||||
|
||||
public static final String STATE_AND_ALARM_READ_ERRORS = "Status And Alarm Modbus Read Errors";
|
||||
public static final String STATE_READ_ERROR = "Information Modbus Read Error";
|
||||
public static final String DATA_READ_ERROR = "Data Modbus Read Error";
|
||||
static final String PV_READ_ERROR = "PV Modbus Read Error";
|
||||
public static final String ALARM_GROUP = "xcenter-alarm";
|
||||
public static final String STATE_GROUP = "xcenter-state";
|
||||
public static final String ENERGY_SOURCE_GROUP = "xcenter-energy-source";
|
||||
public static final String CHARGING_CIRCUIT_GROUP = "xcenter-charging-circuit";
|
||||
public static final String POWER_GROUP = "xcenter-power";
|
||||
public static final String WORKHOURS_GROUP = "xcenter-workhours";
|
||||
public static final String PV_GROUP = "xcenter-pv-modulation";
|
||||
private static final String BINDING_ID = ModbusBindingConstants.BINDING_ID;
|
||||
|
||||
// Supported Thing Types
|
||||
public static final ThingTypeUID THING_TYPE_KERMI_XCENTER = new ThingTypeUID(BINDING_ID, "kermi-xcenter");
|
||||
|
||||
// Channels for State
|
||||
public static final String GLOBAL_STATE_ID_CHANNEL = "global-state-id";
|
||||
|
||||
// Alarm State
|
||||
public static final String ALARM_STATE_CHANNEL = "alarm-state";
|
||||
|
||||
// Energy Source
|
||||
public static final String FLOW_TEMPERATURE_CHANNEL = "flow-temperature";
|
||||
public static final String RETURN_TEMPERATURE_CHANNEL = "return-temperature";
|
||||
public static final String FLOW_SPEED_CHANNEL = "flow-speed";
|
||||
|
||||
// Charging Circuit
|
||||
public static final String EXIT_TEMPERATURE_CHANNEL = "exit-temperature";
|
||||
public static final String INCOMING_TEMPERATURE_CHANNEL = "incoming-temperature";
|
||||
public static final String TEMPERATURE_SENSOR_OUTSIDE_CHANNEL = "temperature-sensor-outside";
|
||||
|
||||
// Power
|
||||
public static final String COP_CHANNEL = "cop";
|
||||
public static final String COP_HEATING_CHANNEL = "cop-heating";
|
||||
public static final String COP_DRINKINGWATER_CHANNEL = "cop-drinkingwater";
|
||||
public static final String COP_COOLING_CHANNEL = "cop-cooling";
|
||||
|
||||
public static final String POWER_CHANNEL = "power";
|
||||
public static final String POWER_HEATING_CHANNEL = "power-heating";
|
||||
public static final String POWER_DRINKINGWATER_CHANNEL = "power-drinkingwater";
|
||||
public static final String POWER_COOLING_CHANNEL = "power-cooling";
|
||||
|
||||
public static final String ELECTRIC_POWER_CHANNEL = "electric-power";
|
||||
public static final String ELECTRIC_POWER_HEATING_CHANNEL = "electric-power-heating";
|
||||
public static final String ELECTRIC_POWER_DRINKINGWATER_CHANNEL = "electric-power-drinkingwater";
|
||||
public static final String ELECTRIC_POWER_COOLING_CHANNEL = "electric-power-cooling";
|
||||
|
||||
// Work hours
|
||||
public static final String WORKHOURS_FAN_CHANNEL = "workhours-fan";
|
||||
public static final String WORKHOURS_STORAGE_LOADING_PUMP_CHANNEL = "workhours-storage-loading-pump";
|
||||
public static final String WORKHOURS_COMPRESSOR_CHANNEL = "workhours-compressor";
|
||||
|
||||
// PV
|
||||
public static final String PV_STATE_CHANNEL = "pv-state";
|
||||
public static final String PV_POWER_CHANNEL = "pv-power";
|
||||
public static final String PV_TARGET_TEMPERATURE_HEATING_CHANNEL = "pv-target-temperature-heating";
|
||||
public static final String PV_TARGET_TEMPERATURE_DRINKINGWATER_CHANNEL = "pv-target-temperature-drinkingwater";
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.kermi.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link KermiConfiguration} class contains fields mapping thing configuration parameters.
|
||||
*
|
||||
* @author Kai Neuhaus - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class KermiConfiguration {
|
||||
|
||||
public int refresh = 5000;
|
||||
public boolean pvEnabled = false;
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.kermi.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.modbus.kermi.internal.handler.KermiXcenterThingHandler;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
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 KermiHandlerFactory} is responsible for creating things and thing handlers.
|
||||
*
|
||||
* @author Kai Neuhaus - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(configurationPid = "binding.kermi", service = ThingHandlerFactory.class)
|
||||
public class KermiHandlerFactory extends BaseThingHandlerFactory {
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return thingTypeUID.equals(KermiBindingConstants.THING_TYPE_KERMI_XCENTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
if (KermiBindingConstants.THING_TYPE_KERMI_XCENTER.equals(thingTypeUID)) {
|
||||
return new KermiXcenterThingHandler((Bridge) thing);
|
||||
} // else here
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.kermi.internal.dto;
|
||||
|
||||
import static org.openhab.binding.modbus.kermi.internal.modbus.KermiModbusConstans.ALARM_REG_SIZE;
|
||||
|
||||
import org.openhab.binding.modbus.kermi.internal.modbus.Data;
|
||||
import org.openhab.core.io.transport.modbus.ModbusBitUtilities;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
|
||||
/**
|
||||
* The {@link AlarmDTO} Data object for Kermi Xcenter
|
||||
*
|
||||
* @author Kai Neuhaus - Initial contribution
|
||||
*/
|
||||
public class AlarmDTO implements Data {
|
||||
|
||||
public OnOffType alarmIsActive;
|
||||
|
||||
public AlarmDTO(byte[] bArray) {
|
||||
int status = ModbusBitUtilities.extractBit(bArray, ALARM_REG_SIZE);
|
||||
alarmIsActive = OnOffType.from(status != 0);
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.kermi.internal.dto;
|
||||
|
||||
import static org.openhab.core.library.unit.Units.LITRE_PER_MINUTE;
|
||||
|
||||
import javax.measure.quantity.Temperature;
|
||||
|
||||
import org.openhab.binding.modbus.kermi.internal.modbus.Data;
|
||||
import org.openhab.core.io.transport.modbus.ValueBuffer;
|
||||
import org.openhab.core.library.dimension.VolumetricFlowRate;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
|
||||
/**
|
||||
* The {@link ChargingCircuitDTO} Data object for Kermi Xcenter
|
||||
*
|
||||
* @author Kai Neuhaus - Initial contribution
|
||||
*/
|
||||
public class ChargingCircuitDTO implements Data {
|
||||
|
||||
public QuantityType<Temperature> flowTemperature;
|
||||
public QuantityType<Temperature> returnFlowTemperature;
|
||||
public QuantityType<VolumetricFlowRate> flowSpeed;
|
||||
|
||||
public ChargingCircuitDTO(byte[] bArray) {
|
||||
ValueBuffer wrap = ValueBuffer.wrap(bArray);
|
||||
flowTemperature = QuantityType.valueOf(DataConverter.getSDoubleValue(wrap, 0.1), SIUnits.CELSIUS);
|
||||
returnFlowTemperature = QuantityType.valueOf(DataConverter.getSDoubleValue(wrap, 0.1), SIUnits.CELSIUS);
|
||||
flowSpeed = QuantityType.valueOf(DataConverter.getSDoubleValue(wrap, 0.1), LITRE_PER_MINUTE);
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.kermi.internal.dto;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.BitSet;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.io.transport.modbus.ModbusBitUtilities;
|
||||
import org.openhab.core.io.transport.modbus.ValueBuffer;
|
||||
|
||||
/**
|
||||
* The {@link DataConverter} Helper class to convert bytes from modbus into desired data format
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
* @author Kai Neuhaus - used for Modbus.Kermi Binding
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class DataConverter {
|
||||
|
||||
/**
|
||||
* Retrieves a double value from the first two bytes of the provided {@link ValueBuffer} using the given correction
|
||||
* factor.
|
||||
*
|
||||
* @param wrap The {@link ValueBuffer} from which to extract the bytes.
|
||||
* @param factor The correction factor to apply to the extracted value.
|
||||
* @return The calculated double value.
|
||||
*/
|
||||
public static double getUDoubleValue(ValueBuffer wrap, double factor) {
|
||||
return round(wrap.getUInt16() * factor, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a signed double value from the first two bytes of the provided {@link ValueBuffer} using the given
|
||||
* correction factor.
|
||||
*
|
||||
* @param wrap The {@link ValueBuffer} from which to extract the bytes. This {@link ValueBuffer} should contain at
|
||||
* least two bytes.
|
||||
* @param factor The correction factor to apply to the extracted value. This factor is used to adjust the calculated
|
||||
* value.
|
||||
* @return The calculated signed double value. The value is obtained by extracting the first two bytes from the
|
||||
* {@link ValueBuffer},
|
||||
* converting them to a signed 16-bit integer, multiplying it by the correction factor, and rounding the
|
||||
* result to two decimal places.
|
||||
*/
|
||||
public static double getSDoubleValue(ValueBuffer wrap, double factor) {
|
||||
return round(wrap.getSInt16() * factor, 2);
|
||||
}
|
||||
|
||||
public static String getString(byte[] bArray) {
|
||||
return ModbusBitUtilities.extractStringFromBytes(bArray, 0, bArray.length, StandardCharsets.US_ASCII).trim();
|
||||
}
|
||||
|
||||
public static int toInt(BitSet bitSet) {
|
||||
int intValue = 0;
|
||||
for (int bit = 0; bit < bitSet.length(); bit++) {
|
||||
if (bitSet.get(bit)) {
|
||||
intValue |= (1 << bit);
|
||||
}
|
||||
}
|
||||
return intValue;
|
||||
}
|
||||
|
||||
public static double round(double value, int places) {
|
||||
if (places < 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
long factor = (long) Math.pow(10, places);
|
||||
long tmp = Math.round(value * factor);
|
||||
return (double) tmp / factor;
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.kermi.internal.dto;
|
||||
|
||||
import javax.measure.quantity.Temperature;
|
||||
|
||||
import org.openhab.binding.modbus.kermi.internal.modbus.Data;
|
||||
import org.openhab.core.io.transport.modbus.ValueBuffer;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
|
||||
/**
|
||||
* The {@link EnergySourceDTO} Data object for Kermi Xcenter
|
||||
*
|
||||
* @author Kai Neuhaus - Initial contribution
|
||||
*/
|
||||
public class EnergySourceDTO implements Data {
|
||||
|
||||
public QuantityType<Temperature> exitTemperature;
|
||||
public QuantityType<Temperature> incomingTemperature;
|
||||
public QuantityType<Temperature> outsideTemperature;
|
||||
|
||||
public EnergySourceDTO(byte[] bArray) {
|
||||
ValueBuffer wrap = ValueBuffer.wrap(bArray);
|
||||
exitTemperature = QuantityType.valueOf(DataConverter.getSDoubleValue(wrap, 0.1), SIUnits.CELSIUS);
|
||||
incomingTemperature = QuantityType.valueOf(DataConverter.getSDoubleValue(wrap, 0.1), SIUnits.CELSIUS);
|
||||
outsideTemperature = QuantityType.valueOf(DataConverter.getSDoubleValue(wrap, 0.1), SIUnits.CELSIUS);
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.kermi.internal.dto;
|
||||
|
||||
import javax.measure.quantity.Power;
|
||||
|
||||
import org.openhab.binding.modbus.kermi.internal.modbus.Data;
|
||||
import org.openhab.core.io.transport.modbus.ValueBuffer;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
|
||||
/**
|
||||
* The {@link PowerDTO} Data object for Kermi Xcenter State Block
|
||||
*
|
||||
* @author Kai Neuhaus - Initial contribution
|
||||
*/
|
||||
public class PowerDTO implements Data {
|
||||
|
||||
public DecimalType cop;
|
||||
public DecimalType copHeating;
|
||||
public DecimalType copDrinkingwater;
|
||||
public DecimalType copCooling;
|
||||
|
||||
public QuantityType<Power> power;
|
||||
public QuantityType<Power> powerHeating;
|
||||
public QuantityType<Power> powerDrinkingwater;
|
||||
public QuantityType<Power> powerCooling;
|
||||
|
||||
public QuantityType<Power> electricPower;
|
||||
public QuantityType<Power> electricPowerHeating;
|
||||
public QuantityType<Power> electricPowerDrinkingwater;
|
||||
public QuantityType<Power> electricPowerCooling;
|
||||
|
||||
public PowerDTO(byte[] bArray) {
|
||||
|
||||
ValueBuffer wrap = ValueBuffer.wrap(bArray);
|
||||
|
||||
cop = new DecimalType(DataConverter.getUDoubleValue(wrap, 0.1));
|
||||
copHeating = new DecimalType(DataConverter.getUDoubleValue(wrap, 0.1));
|
||||
copDrinkingwater = new DecimalType(DataConverter.getUDoubleValue(wrap, 0.1));
|
||||
copCooling = new DecimalType(DataConverter.getUDoubleValue(wrap, 0.1));
|
||||
|
||||
power = QuantityType.valueOf(DataConverter.getUDoubleValue(wrap, 100), Units.WATT);
|
||||
powerHeating = QuantityType.valueOf(DataConverter.getUDoubleValue(wrap, 100), Units.WATT);
|
||||
powerDrinkingwater = QuantityType.valueOf(DataConverter.getUDoubleValue(wrap, 100), Units.WATT);
|
||||
powerCooling = QuantityType.valueOf(DataConverter.getUDoubleValue(wrap, 100), Units.WATT);
|
||||
|
||||
electricPower = QuantityType.valueOf(DataConverter.getUDoubleValue(wrap, 100), Units.WATT);
|
||||
electricPowerHeating = QuantityType.valueOf(DataConverter.getUDoubleValue(wrap, 100), Units.WATT);
|
||||
electricPowerDrinkingwater = QuantityType.valueOf(DataConverter.getUDoubleValue(wrap, 100), Units.WATT);
|
||||
electricPowerCooling = QuantityType.valueOf(DataConverter.getUDoubleValue(wrap, 100), Units.WATT);
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.kermi.internal.dto;
|
||||
|
||||
import javax.measure.quantity.Power;
|
||||
import javax.measure.quantity.Temperature;
|
||||
|
||||
import org.openhab.binding.modbus.kermi.internal.modbus.Data;
|
||||
import org.openhab.core.io.transport.modbus.ModbusBitUtilities;
|
||||
import org.openhab.core.io.transport.modbus.ValueBuffer;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
|
||||
/**
|
||||
* The {@link PvDTO} Data object for Kermi Xcenter
|
||||
*
|
||||
* @author Kai Neuhaus - Initial contribution
|
||||
*/
|
||||
public class PvDTO implements Data {
|
||||
|
||||
public OnOffType pvModulationActive;
|
||||
public QuantityType<Power> pvModulationPower;
|
||||
public QuantityType<Temperature> pvTargetTemperatureHeating;
|
||||
public QuantityType<Temperature> pvTargetTemperatureDrinkingwater;
|
||||
|
||||
public PvDTO(byte[] bArray) {
|
||||
|
||||
int modActive = ModbusBitUtilities.extractBit(bArray, 0);
|
||||
pvModulationActive = modActive == 0 ? OnOffType.OFF : OnOffType.ON;
|
||||
|
||||
ValueBuffer wrap = ValueBuffer.wrap(bArray);
|
||||
// skip first bit -> modActive-Value
|
||||
wrap.position(2);
|
||||
|
||||
pvModulationPower = QuantityType.valueOf(DataConverter.getUDoubleValue(wrap, 0.1), Units.WATT);
|
||||
pvTargetTemperatureHeating = QuantityType.valueOf(DataConverter.getUDoubleValue(wrap, 0.1), SIUnits.CELSIUS);
|
||||
pvTargetTemperatureDrinkingwater = QuantityType.valueOf(DataConverter.getUDoubleValue(wrap, 0.1),
|
||||
SIUnits.CELSIUS);
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.kermi.internal.dto;
|
||||
|
||||
import org.openhab.binding.modbus.kermi.internal.modbus.Data;
|
||||
import org.openhab.core.io.transport.modbus.ModbusBitUtilities;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
|
||||
/**
|
||||
* The {@link StateDTO} Data object for Kermi Xcenter
|
||||
*
|
||||
* @author Kai Neuhaus - Initial contribution
|
||||
*/
|
||||
public class StateDTO implements Data {
|
||||
|
||||
public DecimalType globalStateId;
|
||||
|
||||
public StateDTO(byte[] bArray) {
|
||||
int status = ModbusBitUtilities.extractBit(bArray, 0);
|
||||
globalStateId = new DecimalType(status);
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.kermi.internal.dto;
|
||||
|
||||
import javax.measure.quantity.Time;
|
||||
|
||||
import org.openhab.binding.modbus.kermi.internal.modbus.Data;
|
||||
import org.openhab.core.io.transport.modbus.ValueBuffer;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
|
||||
/**
|
||||
* The {@link WorkHoursDTO} Data object for Kermi Xcenter State Block
|
||||
*
|
||||
* @author Kai Neuhaus - Initial contribution
|
||||
*/
|
||||
public class WorkHoursDTO implements Data {
|
||||
|
||||
public QuantityType<Time> workHoursFan;
|
||||
public QuantityType<Time> workHoursStorageLoadingPump;
|
||||
public QuantityType<Time> workHoursCompressor;
|
||||
|
||||
public WorkHoursDTO(byte[] bArray) {
|
||||
|
||||
ValueBuffer wrap = ValueBuffer.wrap(bArray);
|
||||
|
||||
workHoursFan = QuantityType.valueOf(DataConverter.getUDoubleValue(wrap, 0.1), Units.HOUR);
|
||||
workHoursStorageLoadingPump = QuantityType.valueOf(DataConverter.getUDoubleValue(wrap, 0.1), Units.HOUR);
|
||||
workHoursCompressor = QuantityType.valueOf(DataConverter.getUDoubleValue(wrap, 0.1), Units.HOUR);
|
||||
}
|
||||
}
|
@ -0,0 +1,613 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.kermi.internal.handler;
|
||||
|
||||
import static org.openhab.binding.modbus.kermi.internal.KermiBindingConstants.*;
|
||||
import static org.openhab.binding.modbus.kermi.internal.modbus.KermiModbusConstans.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
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.kermi.internal.KermiBindingConstants;
|
||||
import org.openhab.binding.modbus.kermi.internal.KermiConfiguration;
|
||||
import org.openhab.binding.modbus.kermi.internal.dto.AlarmDTO;
|
||||
import org.openhab.binding.modbus.kermi.internal.dto.ChargingCircuitDTO;
|
||||
import org.openhab.binding.modbus.kermi.internal.dto.EnergySourceDTO;
|
||||
import org.openhab.binding.modbus.kermi.internal.dto.PowerDTO;
|
||||
import org.openhab.binding.modbus.kermi.internal.dto.PvDTO;
|
||||
import org.openhab.binding.modbus.kermi.internal.dto.StateDTO;
|
||||
import org.openhab.binding.modbus.kermi.internal.dto.WorkHoursDTO;
|
||||
import org.openhab.binding.modbus.kermi.internal.modbus.Data;
|
||||
import org.openhab.binding.modbus.kermi.internal.modbus.Parser;
|
||||
import org.openhab.core.io.transport.modbus.AsyncModbusFailure;
|
||||
import org.openhab.core.io.transport.modbus.AsyncModbusReadResult;
|
||||
import org.openhab.core.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.core.io.transport.modbus.ModbusReadFunctionCode;
|
||||
import org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.core.io.transport.modbus.PollTask;
|
||||
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.binding.BaseBridgeHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link KermiXcenterThingHandler} Basic modbus connection to the Kermi device(s)
|
||||
*
|
||||
* @author Kai Neuhaus - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class KermiXcenterThingHandler extends BaseBridgeHandler {
|
||||
|
||||
public enum ReadStatus {
|
||||
NOT_RECEIVED,
|
||||
READ_SUCCESS,
|
||||
READ_FAILED
|
||||
}
|
||||
|
||||
// Energy source
|
||||
private ChannelUID exitTemperatureChannel;
|
||||
private ChannelUID incomingTemperatureChannel;
|
||||
private ChannelUID outsideTemperatureChannel;
|
||||
|
||||
// Charging circuit
|
||||
private ChannelUID flowTemperatureChannel;
|
||||
private ChannelUID returnFlowTemperatureChannel;
|
||||
private ChannelUID flowSpeedChannel;
|
||||
|
||||
// Power
|
||||
private ChannelUID copChannel;
|
||||
private ChannelUID copHeatingChannel;
|
||||
private ChannelUID copDrinkingWaterChannel;
|
||||
private ChannelUID copCoolingChannel;
|
||||
|
||||
private ChannelUID powerChannel;
|
||||
private ChannelUID powerHeatingChannel;
|
||||
private ChannelUID powerDrinkingWaterChannel;
|
||||
private ChannelUID powerCoolingChannel;
|
||||
|
||||
private ChannelUID electricPowerChannel;
|
||||
private ChannelUID electricPowerHeatingChannel;
|
||||
private ChannelUID electricPowerDrinkingWaterChannel;
|
||||
private ChannelUID electricPowerCoolingChannel;
|
||||
|
||||
// Global State
|
||||
// private ChannelUID globalStateChannel;
|
||||
private ChannelUID globalStateIdChannel;
|
||||
|
||||
// Alarm State
|
||||
private ChannelUID alarmStateChannel;
|
||||
|
||||
// Work hours
|
||||
private ChannelUID workHoursFanChannel;
|
||||
private ChannelUID workHoursStorageLoadingPumpChannel;
|
||||
private ChannelUID workHoursCompressorChannel;
|
||||
|
||||
// PV Modulation
|
||||
private ChannelUID pvStateChannel;
|
||||
private ChannelUID pvPowerChannel;
|
||||
private ChannelUID pvTargetTemperatureHeatingChannel; // READ-WRITE
|
||||
private ChannelUID pvTargetTemperatureDrinkingWaterChannel; // READ-WRITE
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(KermiXcenterThingHandler.class);
|
||||
|
||||
private final Parser alarmParser = new Parser(Data.DataType.ALARM_STATE);
|
||||
private ReadStatus alarmRead = ReadStatus.NOT_RECEIVED;
|
||||
private final Parser chargingCircuitParser = new Parser(Data.DataType.CHARGING_CIRCUIT);
|
||||
private ReadStatus chargingCircuitRead = ReadStatus.NOT_RECEIVED;
|
||||
private final Parser energySourceParser = new Parser(Data.DataType.ENERGY_SOURCE);
|
||||
private ReadStatus energySourceRead = ReadStatus.NOT_RECEIVED;
|
||||
private final Parser powerParser = new Parser(Data.DataType.POWER);
|
||||
private ReadStatus powerRead = ReadStatus.NOT_RECEIVED;
|
||||
private final Parser pvParser = new Parser(Data.DataType.PV);
|
||||
private ReadStatus pvRead = ReadStatus.NOT_RECEIVED;
|
||||
private final Parser stateParser = new Parser(Data.DataType.STATE);
|
||||
private ReadStatus stateRead = ReadStatus.NOT_RECEIVED;
|
||||
private final Parser workHoursParser = new Parser(Data.DataType.WORK_HOURS);
|
||||
private ReadStatus workHoursRead = ReadStatus.NOT_RECEIVED;
|
||||
|
||||
private @Nullable PollTask alarmPoller;
|
||||
private @Nullable PollTask chargingCircuitPoller;
|
||||
private @Nullable PollTask energySourcePoller;
|
||||
private @Nullable PollTask powerPoller;
|
||||
private @Nullable PollTask pvPoller;
|
||||
private @Nullable PollTask statePoller;
|
||||
private @Nullable PollTask workHourPoller;
|
||||
|
||||
private List<@Nullable PollTask> pollTasks = new ArrayList<>();
|
||||
|
||||
private @Nullable KermiConfiguration config;
|
||||
|
||||
/**
|
||||
* Communication interface to the slave endpoint we're connecting to
|
||||
*/
|
||||
protected volatile @Nullable ModbusCommunicationInterface comms = null;
|
||||
private int slaveId;
|
||||
|
||||
public KermiXcenterThingHandler(Bridge thing) {
|
||||
super(thing);
|
||||
|
||||
// STATE
|
||||
globalStateIdChannel = channelUID(thing, KermiBindingConstants.STATE_GROUP, GLOBAL_STATE_ID_CHANNEL);
|
||||
|
||||
// ALARM
|
||||
alarmStateChannel = channelUID(thing, KermiBindingConstants.ALARM_GROUP, ALARM_STATE_CHANNEL);
|
||||
|
||||
// Energy source
|
||||
exitTemperatureChannel = channelUID(thing, KermiBindingConstants.ENERGY_SOURCE_GROUP, EXIT_TEMPERATURE_CHANNEL);
|
||||
incomingTemperatureChannel = channelUID(thing, KermiBindingConstants.ENERGY_SOURCE_GROUP,
|
||||
INCOMING_TEMPERATURE_CHANNEL);
|
||||
outsideTemperatureChannel = channelUID(thing, KermiBindingConstants.ENERGY_SOURCE_GROUP,
|
||||
TEMPERATURE_SENSOR_OUTSIDE_CHANNEL);
|
||||
|
||||
// Loading circuit
|
||||
flowTemperatureChannel = channelUID(thing, KermiBindingConstants.CHARGING_CIRCUIT_GROUP,
|
||||
FLOW_TEMPERATURE_CHANNEL);
|
||||
returnFlowTemperatureChannel = channelUID(thing, KermiBindingConstants.CHARGING_CIRCUIT_GROUP,
|
||||
RETURN_TEMPERATURE_CHANNEL);
|
||||
flowSpeedChannel = channelUID(thing, KermiBindingConstants.CHARGING_CIRCUIT_GROUP, FLOW_SPEED_CHANNEL);
|
||||
|
||||
// Power
|
||||
copChannel = channelUID(thing, KermiBindingConstants.POWER_GROUP, COP_CHANNEL);
|
||||
copHeatingChannel = channelUID(thing, KermiBindingConstants.POWER_GROUP, COP_HEATING_CHANNEL);
|
||||
copDrinkingWaterChannel = channelUID(thing, KermiBindingConstants.POWER_GROUP, COP_DRINKINGWATER_CHANNEL);
|
||||
copCoolingChannel = channelUID(thing, KermiBindingConstants.POWER_GROUP, COP_COOLING_CHANNEL);
|
||||
|
||||
powerChannel = channelUID(thing, KermiBindingConstants.POWER_GROUP, POWER_CHANNEL);
|
||||
powerHeatingChannel = channelUID(thing, KermiBindingConstants.POWER_GROUP, POWER_HEATING_CHANNEL);
|
||||
powerDrinkingWaterChannel = channelUID(thing, KermiBindingConstants.POWER_GROUP, POWER_DRINKINGWATER_CHANNEL);
|
||||
powerCoolingChannel = channelUID(thing, KermiBindingConstants.POWER_GROUP, POWER_COOLING_CHANNEL);
|
||||
|
||||
electricPowerChannel = channelUID(thing, KermiBindingConstants.POWER_GROUP, ELECTRIC_POWER_CHANNEL);
|
||||
electricPowerHeatingChannel = channelUID(thing, KermiBindingConstants.POWER_GROUP,
|
||||
ELECTRIC_POWER_HEATING_CHANNEL);
|
||||
electricPowerDrinkingWaterChannel = channelUID(thing, KermiBindingConstants.POWER_GROUP,
|
||||
ELECTRIC_POWER_DRINKINGWATER_CHANNEL);
|
||||
electricPowerCoolingChannel = channelUID(thing, KermiBindingConstants.POWER_GROUP,
|
||||
ELECTRIC_POWER_COOLING_CHANNEL);
|
||||
|
||||
// Work hours
|
||||
workHoursFanChannel = channelUID(thing, KermiBindingConstants.WORKHOURS_GROUP, WORKHOURS_FAN_CHANNEL);
|
||||
workHoursStorageLoadingPumpChannel = channelUID(thing, KermiBindingConstants.WORKHOURS_GROUP,
|
||||
WORKHOURS_STORAGE_LOADING_PUMP_CHANNEL);
|
||||
workHoursCompressorChannel = channelUID(thing, KermiBindingConstants.WORKHOURS_GROUP,
|
||||
WORKHOURS_COMPRESSOR_CHANNEL);
|
||||
|
||||
// PV Modulation
|
||||
pvStateChannel = channelUID(thing, KermiBindingConstants.PV_GROUP, PV_STATE_CHANNEL);
|
||||
pvPowerChannel = channelUID(thing, KermiBindingConstants.PV_GROUP, PV_POWER_CHANNEL);
|
||||
pvTargetTemperatureHeatingChannel = channelUID(thing, KermiBindingConstants.PV_GROUP,
|
||||
PV_TARGET_TEMPERATURE_HEATING_CHANNEL); // READ-WRITE
|
||||
pvTargetTemperatureDrinkingWaterChannel = channelUID(thing, KermiBindingConstants.PV_GROUP,
|
||||
PV_TARGET_TEMPERATURE_DRINKINGWATER_CHANNEL); // READ-WRITE
|
||||
}
|
||||
|
||||
public @Nullable ModbusCommunicationInterface getComms() {
|
||||
return comms;
|
||||
}
|
||||
|
||||
public int getSlaveId() {
|
||||
return slaveId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
// no control of Kermi device possible yet
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
scheduler.execute(() -> {
|
||||
KermiConfiguration localConfig = getConfigAs(KermiConfiguration.class);
|
||||
config = localConfig;
|
||||
|
||||
if (config == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Kermi Configuration missing");
|
||||
return;
|
||||
}
|
||||
ModbusCommunicationInterface localComms = connectEndpoint();
|
||||
if (localComms == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"Connection failure on initialize...");
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Before asking: i tried to create 1 "big poller" and separate the data from the received bytes.
|
||||
* But when polling "registers" which are not declared (from Kermi), the answer was corrupted or
|
||||
* invalid.
|
||||
* e.x. polling 100 to 150, expecting 50 registers the device returns 18 only, strange behaviour.
|
||||
* Maybe polling will be improved in future - to have not that "huge" amount of pollerTasks.
|
||||
*/
|
||||
|
||||
// very slow requests
|
||||
ModbusReadRequestBlueprint workHoursRequest = new ModbusReadRequestBlueprint(slaveId,
|
||||
ModbusReadFunctionCode.READ_MULTIPLE_REGISTERS, WORK_HOURS_REG_START, WORK_HOURS_REG_SIZE, 3);
|
||||
workHourPoller = localComms.registerRegularPoll(workHoursRequest, SLOW_POLL_REFRESH_TIME_MS,
|
||||
WARMUP_TIME_LONG, this::handleWorkHoursResult, this::handleWorkHoursFailure);
|
||||
|
||||
pollTasks.add(workHourPoller);
|
||||
|
||||
// register low speed state & alarm poller
|
||||
ModbusReadRequestBlueprint alarmRequest = new ModbusReadRequestBlueprint(slaveId,
|
||||
ModbusReadFunctionCode.READ_MULTIPLE_REGISTERS, ALARM_REG_START, ALARM_REG_SIZE, 3);
|
||||
alarmPoller = localComms.registerRegularPoll(alarmRequest, STATE_POLL_REFRESH_TIME_MS, WARMUP_TIME_LONG,
|
||||
this::handleAlarmResult, this::handleAlarmFailure);
|
||||
|
||||
pollTasks.add(alarmPoller);
|
||||
|
||||
ModbusReadRequestBlueprint stateRequest = new ModbusReadRequestBlueprint(slaveId,
|
||||
ModbusReadFunctionCode.READ_MULTIPLE_REGISTERS, STATE_REG_START, STATE_REG_SIZE, 3);
|
||||
statePoller = localComms.registerRegularPoll(stateRequest, STATE_POLL_REFRESH_TIME_MS, WARMUP_TIME_LONG,
|
||||
this::handleStateResult, this::handleStateFailure);
|
||||
|
||||
pollTasks.add(statePoller);
|
||||
|
||||
// default polling speed
|
||||
ModbusReadRequestBlueprint chargingcircuitRequest = new ModbusReadRequestBlueprint(slaveId,
|
||||
ModbusReadFunctionCode.READ_MULTIPLE_REGISTERS, CHARGING_CIRCUIT_REG_START,
|
||||
CHARGING_CIRCUIT_REG_SIZE, 3);
|
||||
chargingCircuitPoller = localComms.registerRegularPoll(chargingcircuitRequest, localConfig.refresh,
|
||||
WARMUP_TIME_SHORT, this::handleChargingCircuitResult, this::handleChargingCircuitFailure);
|
||||
|
||||
pollTasks.add(chargingCircuitPoller);
|
||||
|
||||
ModbusReadRequestBlueprint energySourceRequest = new ModbusReadRequestBlueprint(slaveId,
|
||||
ModbusReadFunctionCode.READ_MULTIPLE_REGISTERS, ENERGY_SOURCE_REG_START, ENERGY_SOURCE_REG_SIZE, 3);
|
||||
energySourcePoller = localComms.registerRegularPoll(energySourceRequest, localConfig.refresh,
|
||||
WARMUP_TIME_SHORT, this::handleEnergySourceResult, this::handleEnergySourceFailure);
|
||||
|
||||
pollTasks.add(energySourcePoller);
|
||||
|
||||
ModbusReadRequestBlueprint powerRequest = new ModbusReadRequestBlueprint(slaveId,
|
||||
ModbusReadFunctionCode.READ_MULTIPLE_REGISTERS, POWER_REG_START, POWER_REG_SIZE, 3);
|
||||
powerPoller = localComms.registerRegularPoll(powerRequest, localConfig.refresh, WARMUP_TIME_SHORT,
|
||||
this::handlePowerResult, this::handlePowerFailure);
|
||||
|
||||
pollTasks.add(powerPoller);
|
||||
|
||||
if (localConfig.pvEnabled) {
|
||||
ModbusReadRequestBlueprint pvRequest = new ModbusReadRequestBlueprint(slaveId,
|
||||
ModbusReadFunctionCode.READ_MULTIPLE_REGISTERS, PV_MODULATION_REG_START, PV_MODULATION_REG_SIZE,
|
||||
3);
|
||||
pvPoller = localComms.registerRegularPoll(pvRequest, localConfig.refresh, WARMUP_TIME_SHORT,
|
||||
this::handlePvResult, this::handlePvFailure);
|
||||
|
||||
pollTasks.add(pvPoller);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a reference to the modbus endpoint
|
||||
*/
|
||||
private @Nullable ModbusCommunicationInterface connectEndpoint() {
|
||||
if (comms != null) {
|
||||
return comms;
|
||||
}
|
||||
|
||||
ModbusEndpointThingHandler slaveEndpointThingHandler = getEndpointThingHandler();
|
||||
if (slaveEndpointThingHandler == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
logger.debug("SlaveEndpointThingHandler is null, Thing & Bridge are offline");
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
slaveId = slaveEndpointThingHandler.getSlaveId();
|
||||
comms = slaveEndpointThingHandler.getCommunicationInterface();
|
||||
} catch (EndpointNotInitializedException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Slave Endpoint not initialized");
|
||||
logger.debug("Slave Endpoint not initialized, Thing is offline");
|
||||
return null;
|
||||
}
|
||||
if (comms == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
logger.debug("CommunicationInterface is null, Thing & Bridge are offline");
|
||||
return null;
|
||||
} else {
|
||||
return comms;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
if (bridge.getHandler() instanceof ModbusEndpointThingHandler thingHandler) {
|
||||
return thingHandler;
|
||||
} else {
|
||||
logger.debug("Bridge handler null or unexpected type: {}", bridge.getHandler());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the channel UID for the specified group and channel id
|
||||
*
|
||||
* @param group String of channel group
|
||||
* @param id String the channel id in that group
|
||||
* @return the globally unique channel uid
|
||||
*/
|
||||
private ChannelUID channelUID(Thing t, String group, String id) {
|
||||
return new ChannelUID(t.getUID(), group, id);
|
||||
}
|
||||
|
||||
/******** Start ResultHandler *****************/
|
||||
|
||||
private void handleAlarmResult(AsyncModbusReadResult result) {
|
||||
if (alarmRead != ReadStatus.READ_SUCCESS) {
|
||||
// update status only if bit switches
|
||||
alarmRead = ReadStatus.READ_SUCCESS;
|
||||
updateStatus();
|
||||
}
|
||||
alarmParser.handle(result);
|
||||
Optional<Data> dtoOpt = alarmParser.parse(Data.DataType.ALARM_STATE);
|
||||
if (dtoOpt.isPresent()) {
|
||||
AlarmDTO alarmDTO = (AlarmDTO) dtoOpt.get();
|
||||
updateState(alarmStateChannel, alarmDTO.alarmIsActive);
|
||||
} else {
|
||||
logger.debug("Unable to get {} from provider {}", Data.DataType.ALARM_STATE, alarmParser.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleAlarmFailure(AsyncModbusFailure<ModbusReadRequestBlueprint> result) {
|
||||
if (alarmRead != ReadStatus.READ_FAILED) {
|
||||
// update status only if bit switches
|
||||
alarmRead = ReadStatus.READ_FAILED;
|
||||
logger.debug("Cause of failure: {}", result.getCause().getMessage());
|
||||
updateStatus();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleChargingCircuitResult(AsyncModbusReadResult result) {
|
||||
if (chargingCircuitRead != ReadStatus.READ_SUCCESS) {
|
||||
// update status only if bit switches
|
||||
chargingCircuitRead = ReadStatus.READ_SUCCESS;
|
||||
updateStatus();
|
||||
}
|
||||
chargingCircuitParser.handle(result);
|
||||
Optional<Data> dtoOpt = chargingCircuitParser.parse(Data.DataType.CHARGING_CIRCUIT);
|
||||
if (dtoOpt.isPresent()) {
|
||||
ChargingCircuitDTO chargingCircuitDTO = (ChargingCircuitDTO) dtoOpt.get();
|
||||
updateState(flowTemperatureChannel, chargingCircuitDTO.flowTemperature);
|
||||
updateState(returnFlowTemperatureChannel, chargingCircuitDTO.returnFlowTemperature);
|
||||
updateState(flowSpeedChannel, chargingCircuitDTO.flowSpeed);
|
||||
} else {
|
||||
logger.debug("Unable to get {} from provider {}", Data.DataType.CHARGING_CIRCUIT,
|
||||
chargingCircuitParser.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleChargingCircuitFailure(AsyncModbusFailure<ModbusReadRequestBlueprint> result) {
|
||||
if (chargingCircuitRead != ReadStatus.READ_FAILED) {
|
||||
// update status only if bit switches
|
||||
chargingCircuitRead = ReadStatus.READ_FAILED;
|
||||
logger.debug("Cause of failure: {}", result.getCause().getMessage());
|
||||
updateStatus();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleEnergySourceResult(AsyncModbusReadResult result) {
|
||||
if (energySourceRead != ReadStatus.READ_SUCCESS) {
|
||||
// update status only if bit switches
|
||||
energySourceRead = ReadStatus.READ_SUCCESS;
|
||||
updateStatus();
|
||||
}
|
||||
energySourceParser.handle(result);
|
||||
Optional<Data> dtoOpt = energySourceParser.parse(Data.DataType.ENERGY_SOURCE);
|
||||
if (dtoOpt.isPresent()) {
|
||||
EnergySourceDTO energySourceDTO = (EnergySourceDTO) dtoOpt.get();
|
||||
updateState(exitTemperatureChannel, energySourceDTO.exitTemperature);
|
||||
updateState(incomingTemperatureChannel, energySourceDTO.incomingTemperature);
|
||||
updateState(outsideTemperatureChannel, energySourceDTO.outsideTemperature);
|
||||
} else {
|
||||
logger.debug("Unable to get {} from provider {}", Data.DataType.ENERGY_SOURCE,
|
||||
energySourceParser.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleEnergySourceFailure(AsyncModbusFailure<ModbusReadRequestBlueprint> result) {
|
||||
if (energySourceRead != ReadStatus.READ_FAILED) {
|
||||
// update status only if bit switches
|
||||
energySourceRead = ReadStatus.READ_FAILED;
|
||||
logger.debug("Cause of failure: {}", result.getCause().getMessage());
|
||||
updateStatus();
|
||||
}
|
||||
}
|
||||
|
||||
private void handlePowerResult(AsyncModbusReadResult result) {
|
||||
if (powerRead != ReadStatus.READ_SUCCESS) {
|
||||
// update status only if bit switches
|
||||
powerRead = ReadStatus.READ_SUCCESS;
|
||||
updateStatus();
|
||||
}
|
||||
powerParser.handle(result);
|
||||
Optional<Data> dtoOpt = powerParser.parse(Data.DataType.POWER);
|
||||
if (dtoOpt.isPresent()) {
|
||||
PowerDTO powerDTO = (PowerDTO) dtoOpt.get();
|
||||
|
||||
updateState(copChannel, powerDTO.cop);
|
||||
updateState(copHeatingChannel, powerDTO.copHeating);
|
||||
updateState(copDrinkingWaterChannel, powerDTO.copDrinkingwater);
|
||||
updateState(copCoolingChannel, powerDTO.copCooling);
|
||||
|
||||
updateState(powerChannel, powerDTO.power);
|
||||
updateState(powerHeatingChannel, powerDTO.powerHeating);
|
||||
updateState(powerDrinkingWaterChannel, powerDTO.powerDrinkingwater);
|
||||
updateState(powerCoolingChannel, powerDTO.powerCooling);
|
||||
|
||||
updateState(electricPowerChannel, powerDTO.electricPower);
|
||||
updateState(electricPowerHeatingChannel, powerDTO.electricPowerHeating);
|
||||
updateState(electricPowerDrinkingWaterChannel, powerDTO.electricPowerDrinkingwater);
|
||||
updateState(electricPowerCoolingChannel, powerDTO.electricPowerCooling);
|
||||
|
||||
} else {
|
||||
logger.debug("Unable to get {} from provider {}", Data.DataType.POWER, powerParser.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private void handlePowerFailure(AsyncModbusFailure<ModbusReadRequestBlueprint> result) {
|
||||
if (powerRead != ReadStatus.READ_FAILED) {
|
||||
// update status only if bit switches
|
||||
powerRead = ReadStatus.READ_FAILED;
|
||||
logger.debug("Cause of failure: {}", result.getCause().getMessage());
|
||||
updateStatus();
|
||||
}
|
||||
}
|
||||
|
||||
private void handlePvResult(AsyncModbusReadResult result) {
|
||||
if (pvRead != ReadStatus.READ_SUCCESS) {
|
||||
// update status only if bit switches
|
||||
pvRead = ReadStatus.READ_SUCCESS;
|
||||
updateStatus();
|
||||
}
|
||||
pvParser.handle(result);
|
||||
Optional<Data> dtoOpt = pvParser.parse(Data.DataType.PV);
|
||||
if (dtoOpt.isPresent()) {
|
||||
PvDTO pvDTO = (PvDTO) dtoOpt.get();
|
||||
updateState(pvStateChannel, pvDTO.pvModulationActive);
|
||||
updateState(pvPowerChannel, pvDTO.pvModulationPower);
|
||||
updateState(pvTargetTemperatureHeatingChannel, pvDTO.pvTargetTemperatureHeating);
|
||||
updateState(pvTargetTemperatureDrinkingWaterChannel, pvDTO.pvTargetTemperatureDrinkingwater);
|
||||
} else {
|
||||
logger.debug("Unable to get {} from provider {}", Data.DataType.PV, pvParser.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private void handlePvFailure(AsyncModbusFailure<ModbusReadRequestBlueprint> result) {
|
||||
if (pvRead != ReadStatus.READ_FAILED) {
|
||||
// update status only if bit switches
|
||||
pvRead = ReadStatus.READ_FAILED;
|
||||
logger.debug("Cause of failure: {}", result.getCause().getMessage());
|
||||
updateStatus();
|
||||
}
|
||||
}
|
||||
|
||||
void handleStateResult(AsyncModbusReadResult result) {
|
||||
if (stateRead != ReadStatus.READ_SUCCESS) {
|
||||
// update status only if bit switches
|
||||
stateRead = ReadStatus.READ_SUCCESS;
|
||||
updateStatus();
|
||||
}
|
||||
stateParser.handle(result);
|
||||
Optional<Data> dtoOpt = stateParser.parse(Data.DataType.STATE);
|
||||
if (dtoOpt.isPresent()) {
|
||||
StateDTO dto = (StateDTO) dtoOpt.get();
|
||||
// updateState(globalStateChannel, dto.globalState);
|
||||
updateState(globalStateIdChannel, dto.globalStateId);
|
||||
} else {
|
||||
logger.debug("Unable to get {} from provider {}", Data.DataType.STATE, stateParser.toString());
|
||||
}
|
||||
}
|
||||
|
||||
void handleStateFailure(AsyncModbusFailure<ModbusReadRequestBlueprint> result) {
|
||||
if (stateRead != ReadStatus.READ_FAILED) {
|
||||
// update status only if bit switches
|
||||
stateRead = ReadStatus.READ_FAILED;
|
||||
logger.debug("Cause of failure: {}", result.getCause().getMessage());
|
||||
updateStatus();
|
||||
}
|
||||
}
|
||||
|
||||
void handleWorkHoursResult(AsyncModbusReadResult result) {
|
||||
workHoursParser.handle(result);
|
||||
Optional<Data> dtoOpt = workHoursParser.parse(Data.DataType.WORK_HOURS);
|
||||
if (dtoOpt.isPresent()) {
|
||||
WorkHoursDTO dto = (WorkHoursDTO) dtoOpt.get();
|
||||
updateState(workHoursFanChannel, dto.workHoursFan);
|
||||
updateState(workHoursStorageLoadingPumpChannel, dto.workHoursStorageLoadingPump);
|
||||
updateState(workHoursCompressorChannel, dto.workHoursCompressor);
|
||||
} else {
|
||||
logger.debug("Unable to get {} from provider {}", Data.DataType.WORK_HOURS, workHoursParser.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleWorkHoursFailure(AsyncModbusFailure<ModbusReadRequestBlueprint> result) {
|
||||
if (workHoursRead != ReadStatus.READ_FAILED) {
|
||||
// update status only if bit switches
|
||||
workHoursRead = ReadStatus.READ_FAILED;
|
||||
logger.debug("Cause of failure: {}", result.getCause().getMessage());
|
||||
updateStatus();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
ModbusCommunicationInterface localComms = comms;
|
||||
if (localComms != null) {
|
||||
for (PollTask p : pollTasks) {
|
||||
PollTask localPoller = p;
|
||||
if (localPoller != null) {
|
||||
localComms.unregisterRegularPoll(localPoller);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Comms will be close()'d by endpoint thing handler
|
||||
comms = null;
|
||||
}
|
||||
|
||||
private void updateStatus() {
|
||||
logger.debug("Status update: State {} Data {} WorkHours {} PV {} ", stateRead, powerRead, workHoursRead,
|
||||
pvRead);
|
||||
if (stateRead != ReadStatus.NOT_RECEIVED) { // && dataRead != ReadStatus.NOT_RECEIVED
|
||||
if (stateRead == ReadStatus.READ_SUCCESS) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
KermiBindingConstants.STATE_READ_ERROR);
|
||||
}
|
||||
if (stateRead == alarmRead) {
|
||||
// both reads are ok or else both failed
|
||||
if (stateRead == ReadStatus.READ_SUCCESS) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
KermiBindingConstants.STATE_AND_ALARM_READ_ERRORS);
|
||||
}
|
||||
} else {
|
||||
// either info or data read failed - update status with details
|
||||
if (stateRead == ReadStatus.READ_FAILED) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
KermiBindingConstants.STATE_READ_ERROR);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
KermiBindingConstants.DATA_READ_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.kermi.internal.modbus;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link Data} Marker Interface for delivered Modbus Data
|
||||
*
|
||||
* @author Kai Neuhaus - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface Data {
|
||||
enum DataType {
|
||||
STATE,
|
||||
ALARM_STATE,
|
||||
ENERGY_SOURCE,
|
||||
CHARGING_CIRCUIT,
|
||||
POWER,
|
||||
WORK_HOURS,
|
||||
PV,
|
||||
DATA // marks all types besides INFO/STATE
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.kermi.internal.modbus;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link KermiModbusConstans} Variables for register handling.
|
||||
* The numbers are taken from Kermi ExcelChart for Modbus
|
||||
* (Registers start from 0 (not 1!) so from the documented registers subtract 1)
|
||||
*
|
||||
* @author Kai Neuhaus - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class KermiModbusConstans {
|
||||
|
||||
public static final int WARMUP_TIME_LONG = 1500;
|
||||
public static final int WARMUP_TIME_SHORT = 500;
|
||||
|
||||
// "String" registers at the beginning shall be read with very low frequency - 1 hour
|
||||
public static final int SLOW_POLL_REFRESH_TIME_MS = 60 * 60 * 1000;
|
||||
|
||||
// poll every 30 seconds
|
||||
public static final int STATE_POLL_REFRESH_TIME_MS = 30 * 1000;
|
||||
|
||||
// Constants where a certain Block starts and block size. Note: General offset is -1 so INFO_REG from E3DC Modbus
|
||||
// Spec starts at 1 but it's Register 0!
|
||||
public static final int XCENTER_DATA_REG_START = 1;
|
||||
public static final int XCENTER_DATA_REG_SIZE = 111;
|
||||
|
||||
public static final int ENERGY_SOURCE_REG_START = 1;
|
||||
public static final int ENERGY_SOURCE_REG_SIZE = 3;
|
||||
|
||||
public static final int CHARGING_CIRCUIT_REG_START = 50;
|
||||
public static final int CHARGING_CIRCUIT_REG_SIZE = 3;
|
||||
|
||||
public static final int POWER_REG_START = 100;
|
||||
public static final int POWER_REG_SIZE = 12;
|
||||
|
||||
/** INFO BLOCK **/
|
||||
public static final int WORK_HOURS_REG_START = 150;
|
||||
public static final int WORK_HOURS_REG_SIZE = 3;
|
||||
|
||||
public static final int STATE_REG_START = 200;
|
||||
public static final int STATE_REG_SIZE = 1;
|
||||
|
||||
public static final int ALARM_REG_START = 250;
|
||||
public static final int ALARM_REG_SIZE = 1;
|
||||
/** END INFO BLOCK **/
|
||||
|
||||
/** PV BLOCK **/
|
||||
public static final int PV_MODULATION_REG_START = 300;
|
||||
public static final int PV_MODULATION_REG_SIZE = 4;
|
||||
|
||||
public static final int DATA_REGISTER_LENGTH = 111;
|
||||
}
|
@ -0,0 +1,144 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.kermi.internal.modbus;
|
||||
|
||||
import static org.openhab.binding.modbus.kermi.internal.modbus.KermiModbusConstans.ALARM_REG_SIZE;
|
||||
import static org.openhab.binding.modbus.kermi.internal.modbus.KermiModbusConstans.CHARGING_CIRCUIT_REG_SIZE;
|
||||
import static org.openhab.binding.modbus.kermi.internal.modbus.KermiModbusConstans.DATA_REGISTER_LENGTH;
|
||||
import static org.openhab.binding.modbus.kermi.internal.modbus.KermiModbusConstans.ENERGY_SOURCE_REG_SIZE;
|
||||
import static org.openhab.binding.modbus.kermi.internal.modbus.KermiModbusConstans.POWER_REG_SIZE;
|
||||
import static org.openhab.binding.modbus.kermi.internal.modbus.KermiModbusConstans.PV_MODULATION_REG_SIZE;
|
||||
import static org.openhab.binding.modbus.kermi.internal.modbus.KermiModbusConstans.STATE_REG_SIZE;
|
||||
import static org.openhab.binding.modbus.kermi.internal.modbus.KermiModbusConstans.WORK_HOURS_REG_SIZE;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.kermi.internal.dto.AlarmDTO;
|
||||
import org.openhab.binding.modbus.kermi.internal.dto.ChargingCircuitDTO;
|
||||
import org.openhab.binding.modbus.kermi.internal.dto.EnergySourceDTO;
|
||||
import org.openhab.binding.modbus.kermi.internal.dto.PowerDTO;
|
||||
import org.openhab.binding.modbus.kermi.internal.dto.PvDTO;
|
||||
import org.openhab.binding.modbus.kermi.internal.dto.StateDTO;
|
||||
import org.openhab.binding.modbus.kermi.internal.dto.WorkHoursDTO;
|
||||
import org.openhab.binding.modbus.kermi.internal.modbus.Data.DataType;
|
||||
import org.openhab.core.io.transport.modbus.AsyncModbusReadResult;
|
||||
import org.openhab.core.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link Parser} class receives callbacks from modbus poller
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
* @author Kai Neuhaus - adapted for Kermi
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class Parser {
|
||||
private static final int MEASURE_COUNT = 100;
|
||||
private final Logger logger = LoggerFactory.getLogger(Parser.class);
|
||||
private DataType callbackType;
|
||||
private byte[] bArray;
|
||||
private int size;
|
||||
private int counter = 0;
|
||||
private long maxDuration = Long.MIN_VALUE;
|
||||
private long minDuration = Long.MAX_VALUE;
|
||||
private long avgDuration = 0;
|
||||
|
||||
public Parser(DataType type) {
|
||||
callbackType = type;
|
||||
if (type.equals(DataType.STATE)) {
|
||||
size = (STATE_REG_SIZE) * 2;
|
||||
bArray = new byte[size];
|
||||
} else if (type.equals(DataType.ENERGY_SOURCE)) {
|
||||
size = ENERGY_SOURCE_REG_SIZE * 2;
|
||||
bArray = new byte[size];
|
||||
} else if (type.equals(DataType.CHARGING_CIRCUIT)) {
|
||||
size = CHARGING_CIRCUIT_REG_SIZE * 2;
|
||||
bArray = new byte[size];
|
||||
} else if (type.equals(DataType.POWER)) {
|
||||
size = POWER_REG_SIZE * 2;
|
||||
bArray = new byte[size];
|
||||
} else if (type.equals(DataType.ALARM_STATE)) {
|
||||
size = ALARM_REG_SIZE * 2;
|
||||
bArray = new byte[size];
|
||||
} else if (type.equals(DataType.PV)) {
|
||||
size = PV_MODULATION_REG_SIZE * 2;
|
||||
bArray = new byte[size];
|
||||
} else if (type.equals(DataType.WORK_HOURS)) {
|
||||
size = WORK_HOURS_REG_SIZE * 2;
|
||||
bArray = new byte[size];
|
||||
} else {
|
||||
size = DATA_REGISTER_LENGTH * 2;
|
||||
bArray = new byte[size];
|
||||
}
|
||||
}
|
||||
|
||||
public void handle(AsyncModbusReadResult result) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
Optional<ModbusRegisterArray> opt = result.getRegisters();
|
||||
if (opt.isPresent()) {
|
||||
setArray(opt.get().getBytes());
|
||||
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
avgDuration += duration;
|
||||
minDuration = Math.min(minDuration, duration);
|
||||
maxDuration = Math.max(maxDuration, duration);
|
||||
counter++;
|
||||
if (counter % MEASURE_COUNT == 0) {
|
||||
logger.debug("Min {} Max {} Avg {}", minDuration, maxDuration, avgDuration / MEASURE_COUNT);
|
||||
avgDuration = 0;
|
||||
minDuration = Long.MAX_VALUE;
|
||||
maxDuration = Long.MIN_VALUE;
|
||||
}
|
||||
} else {
|
||||
logger.warn("Modbus read result doesn't return expected registers");
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void setArray(byte[] b) {
|
||||
if (b.length != size) {
|
||||
logger.warn("Wrong byte size received. Should be {} but is {}. Data maybe corrupted!", size, b.length);
|
||||
}
|
||||
bArray = b.clone();
|
||||
}
|
||||
|
||||
public Optional<Data> parse(DataType type) {
|
||||
synchronized (bArray) {
|
||||
if (type.equals(DataType.STATE) && callbackType.equals(DataType.STATE)) {
|
||||
return Optional.of(new StateDTO(bArray));
|
||||
} else if (type.equals(DataType.ENERGY_SOURCE) && callbackType.equals(DataType.ENERGY_SOURCE)) {
|
||||
return Optional.of(new EnergySourceDTO(bArray));
|
||||
} else if (type.equals(DataType.CHARGING_CIRCUIT) && callbackType.equals(DataType.CHARGING_CIRCUIT)) {
|
||||
return Optional.of(new ChargingCircuitDTO(bArray));
|
||||
} else if (type.equals(DataType.POWER) && callbackType.equals(DataType.POWER)) {
|
||||
return Optional.of(new PowerDTO(bArray));
|
||||
} else if (type.equals(DataType.PV) && callbackType.equals(DataType.PV)) {
|
||||
return Optional.of(new PvDTO(bArray));
|
||||
} else if (type.equals(DataType.ALARM_STATE) && callbackType.equals(DataType.ALARM_STATE)) {
|
||||
return Optional.of(new AlarmDTO(bArray));
|
||||
} else if (type.equals(DataType.WORK_HOURS) && callbackType.equals(DataType.WORK_HOURS)) {
|
||||
return Optional.of(new WorkHoursDTO(bArray));
|
||||
}
|
||||
}
|
||||
logger.warn("Wrong Block requested. Request is {} but type is {}", type, callbackType);
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(this.getClass().getName()).append(":").append(callbackType);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
# thing types
|
||||
|
||||
thing-type.modbus.kermi-xcenter.label = Kermi X-Center Heat Pump
|
||||
thing-type.modbus.kermi-xcenter.description = Provide Energy values, String Details and general Information of your Kermi Heat Pump
|
||||
|
||||
# thing types config
|
||||
|
||||
thing-type.config.modbus.kermi-xcenter.refresh.label = Refresh Interval
|
||||
thing-type.config.modbus.kermi-xcenter.refresh.description = Refresh Rate of values in milliseconds
|
||||
thing-type.config.modbus.kermi-xcenter.pvEnabled.label = Read PV-Modulation States
|
||||
thing-type.config.modbus.kermi-xcenter.pvEnabled.description = Enabled reading of PV-Modulation (disable to skip reading)
|
||||
|
||||
# channel group types
|
||||
|
||||
channel-group-type.modbus.xcenter-alarm-values.label = Alarm Values
|
||||
channel-group-type.modbus.xcenter-alarm-values.description = Alarm State of your Kermi Heatpump X-Center
|
||||
channel-group-type.modbus.xcenter-charging-circuit-values.label = Charging Circuit
|
||||
channel-group-type.modbus.xcenter-charging-circuit-values.description = Information about the charging circuit
|
||||
channel-group-type.modbus.xcenter-energy-source-values.label = Energy-Source
|
||||
channel-group-type.modbus.xcenter-energy-source-values.description = Information about the energy-source
|
||||
channel-group-type.modbus.xcenter-power-values.label = Power and efficency
|
||||
channel-group-type.modbus.xcenter-power-values.description = Information about power and efficiency
|
||||
channel-group-type.modbus.xcenter-pv-modulation-values.label = PV Modulation
|
||||
channel-group-type.modbus.xcenter-pv-modulation-values.description = PV Modulation Information and Settings for Kermi Heatpump X-Center
|
||||
channel-group-type.modbus.xcenter-state-values.label = Status
|
||||
channel-group-type.modbus.xcenter-state-values.description = Basic Information and State of your Kermi Heatpump X-Center
|
||||
channel-group-type.modbus.xcenter-workhours-values.label = Workhours
|
||||
channel-group-type.modbus.xcenter-workhours-values.description = Basic Information of workhours
|
||||
|
||||
# channel types
|
||||
|
||||
channel-type.modbus.alarm-state-channel.label = Alarm State
|
||||
channel-type.modbus.alarm-state-channel.description = Current alarm-state of your heat pump
|
||||
|
||||
|
||||
channel-type.modbus.flow-temperature-channel.label = Flow temperature
|
||||
channel-type.modbus.flow-temperature-channel.description = B16 - Vorlauftemperatur WP
|
||||
channel-type.modbus.return-temperature-channel.label = Return temperature
|
||||
channel-type.modbus.return-temperature-channel.description = B17 - Rücklauftemperatur WP
|
||||
channel-type.modbus.flow-speed-channel.label = Flow speed
|
||||
channel-type.modbus.flow-speed-channel.description = P13 - Durchfluss WP
|
||||
|
||||
|
||||
channel-type.modbus.exit-temperature-channel.label = Exit temperature
|
||||
channel-type.modbus.exit-temperature-channel.description = B14 - Energiequelle Austrittstemperatur
|
||||
channel-type.modbus.incoming-temperature-channel.label = Incoming temperature
|
||||
channel-type.modbus.incoming-temperature-channel.description = B15 - Energiequelle Eintrittstemperatur
|
||||
channel-type.modbus.temperature-sensor-outside-channel.label = Temperature Outside
|
||||
channel-type.modbus.temperature-sensor-outside-channel.description = BOT - Außentemperaturfühler
|
||||
|
||||
|
||||
channel-type.modbus.cop-channel.label = Current COP
|
||||
channel-type.modbus.cop-channel.description = Current COP of your installation
|
||||
channel-type.modbus.cop-heating-channel.label = Current COP heating
|
||||
channel-type.modbus.cop-heating-channel.description =
|
||||
channel-type.modbus.cop-drinkingwater-channel.label = Current COP drinking water
|
||||
channel-type.modbus.cop-drinkingwater-channel.description =
|
||||
channel-type.modbus.cop-cooling-channel.label = Current COP cooling
|
||||
channel-type.modbus.cop-cooling-channel.description =
|
||||
channel-type.modbus.power-channel.label = Current power
|
||||
channel-type.modbus.power-channel.description =
|
||||
channel-type.modbus.power-heating-channel.label = Current power heating
|
||||
channel-type.modbus.power-heating-channel.description =
|
||||
channel-type.modbus.power-drinkingwater-channel.label = Current power drinking water
|
||||
channel-type.modbus.power-drinkingwater-channel.description =
|
||||
channel-type.modbus.power-cooling-channel.label = Current power cooling
|
||||
channel-type.modbus.power-cooling-channel.description =
|
||||
channel-type.modbus.electric-power-channel.label = Current electric power
|
||||
channel-type.modbus.electric-power-channel.description =
|
||||
channel-type.modbus.electric-power-heating-channel.label = Current electric power heating
|
||||
channel-type.modbus.electric-power-heating-channel.description =
|
||||
channel-type.modbus.electric-power-drinkingwater-channel.label = Current electric power drinking water
|
||||
channel-type.modbus.electric-power-drinkingwater-channel.description =
|
||||
channel-type.modbus.electric-power-cooling-channel.label = Current electric power cooling
|
||||
channel-type.modbus.electric-power-cooling-channel.description =
|
||||
|
||||
|
||||
channel-type.modbus.pv-state-channel.label = PV Modulation Active
|
||||
channel-type.modbus.pv-state-channel.description = State of PV-Modulation
|
||||
channel-type.modbus.pv-power-channel.label = PV Power
|
||||
channel-type.modbus.pv-power-channel.description =
|
||||
channel-type.modbus.pv-target-temperature-heating-channel.label = PV Temp Heating
|
||||
channel-type.modbus.pv-target-temperature-heating-channel.description =
|
||||
channel-type.modbus.pv-target-temperature-drinkingwater-channel.label = PV Temp Drinkingwater
|
||||
channel-type.modbus.pv-target-temperature-drinkingwater-channel.description =
|
||||
|
||||
|
||||
channel-type.modbus.global-state-id-channel.label = Global State
|
||||
channel-type.modbus.global-state-id-channel.description = Current mode of your heat pump
|
||||
channel-type.modbus.global-alarm-channel.label = Global Alarm State
|
||||
channel-type.modbus.global-alarm-channel.description = If there's a global alarm
|
||||
|
||||
|
||||
channel-type.modbus.workhours-fan-channel.label = Fan Workhours
|
||||
channel-type.modbus.workhours-fan-channel.description = Work hours of the fan
|
||||
channel-type.modbus.workhours-storage-loading-pump-channel.label = StorageLoadingPump Workhours
|
||||
channel-type.modbus.workhours-storage-loading-pump-channel.description = Work hours of the storage loading pump
|
||||
channel-type.modbus.workhours-compressor-channel.label = Compressor Workhours
|
||||
channel-type.modbus.workhours-compressor-channel.description = Work hours of the compressor
|
@ -0,0 +1,35 @@
|
||||
<?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">
|
||||
<bridge-type id="kermi-xcenter">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="tcp"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>Kermi Heat Pump X-Center</label>
|
||||
<description>Provide Energy values, String Details and general Information of your Kermi Heat Pump</description>
|
||||
<channel-groups>
|
||||
<channel-group id="xcenter-state" typeId="xcenter-state-values"/>
|
||||
<channel-group id="xcenter-energy-source" typeId="xcenter-energy-source-values"/>
|
||||
<channel-group id="xcenter-charging-circuit" typeId="xcenter-charging-circuit-values"/>
|
||||
<channel-group id="xcenter-power" typeId="xcenter-power-values"/>
|
||||
<channel-group id="xcenter-workhours" typeId="xcenter-workhours-values"/>
|
||||
<channel-group id="xcenter-alarm" typeId="xcenter-alarm-values"/>
|
||||
<channel-group id="xcenter-pv-modulation" typeId="xcenter-pv-modulation-values"/>
|
||||
</channel-groups>
|
||||
<config-description>
|
||||
<parameter name="refresh" type="integer" min="1000" unit="ms">
|
||||
<label>Refresh Interval</label>
|
||||
<description>Refresh Rate of X-Center values in Milliseconds</description>
|
||||
<default>5000</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="pvEnabled" type="boolean">
|
||||
<label>Read PV-Modulation States</label>
|
||||
<description>Enabled reading of PV-Modulation (disable to skip reading)</description>
|
||||
<default>false</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</bridge-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,13 @@
|
||||
<?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="xcenter-alarm-values">
|
||||
<label>Alarm</label>
|
||||
<description>Alarm State of your Kermi Heatpump X-Center</description>
|
||||
<channels>
|
||||
<channel id="alarm-state" typeId="alarm-state-channel"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,11 @@
|
||||
<?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="alarm-state-channel">
|
||||
<item-type>Contact</item-type>
|
||||
<label>Alarm State</label>
|
||||
<description>Current alarm-state of your heat pump</description>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,15 @@
|
||||
<?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="xcenter-charging-circuit-values">
|
||||
<label>Charging Circuit</label>
|
||||
<description>Information about the charging circuit</description>
|
||||
<channels>
|
||||
<channel id="flow-temperature" typeId="flow-temperature-channel"/>
|
||||
<channel id="return-temperature" typeId="return-temperature-channel"/>
|
||||
<channel id="flow-speed" typeId="flow-speed-channel"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,24 @@
|
||||
<?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="flow-temperature-channel">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Flow Temperature</label>
|
||||
<description>B16 - Flow Temperature</description>
|
||||
<state pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="return-temperature-channel">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Return Temperature</label>
|
||||
<description>B17 - Return Temperature</description>
|
||||
<state pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="flow-speed-channel">
|
||||
<item-type>Number:VolumetricFlowRate</item-type>
|
||||
<label>Flow Speed</label>
|
||||
<description>P13 - Flow speed</description>
|
||||
<state pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,15 @@
|
||||
<?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="xcenter-energy-source-values">
|
||||
<label>Energy-Source</label>
|
||||
<description>Information about the energy-source</description>
|
||||
<channels>
|
||||
<channel id="exit-temperature" typeId="exit-temperature-channel"/>
|
||||
<channel id="incoming-temperature" typeId="incoming-temperature-channel"/>
|
||||
<channel id="temperature-sensor-outside" typeId="temperature-sensor-outside-channel"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,24 @@
|
||||
<?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="exit-temperature-channel">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Exit Temperature</label>
|
||||
<description>B14 - Exit Temperature Energy Source</description>
|
||||
<state pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="incoming-temperature-channel">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Incoming temperature</label>
|
||||
<description>B15 - Incoming Temperature Energy Source</description>
|
||||
<state pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="temperature-sensor-outside-channel">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Temperature Outside</label>
|
||||
<description>BOT - Sensor Outside Temperature</description>
|
||||
<state pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,24 @@
|
||||
<?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="xcenter-power-values">
|
||||
<label>Power and Efficiency</label>
|
||||
<description>Information about power and efficiency</description>
|
||||
<channels>
|
||||
<channel id="cop" typeId="cop-channel"/>
|
||||
<channel id="cop-heating" typeId="cop-heating-channel"/>
|
||||
<channel id="cop-drinkingwater" typeId="cop-drinkingwater-channel"/>
|
||||
<channel id="cop-cooling" typeId="cop-cooling-channel"/>
|
||||
<channel id="power" typeId="power-channel"/>
|
||||
<channel id="power-heating" typeId="power-heating-channel"/>
|
||||
<channel id="power-drinkingwater" typeId="power-drinkingwater-channel"/>
|
||||
<channel id="power-cooling" typeId="power-cooling-channel"/>
|
||||
<channel id="electric-power" typeId="electric-power-channel"/>
|
||||
<channel id="electric-power-heating" typeId="electric-power-heating-channel"/>
|
||||
<channel id="electric-power-drinkingwater" typeId="electric-power-drinkingwater-channel"/>
|
||||
<channel id="electric-power-cooling" typeId="electric-power-cooling-channel"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,68 @@
|
||||
<?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="cop-channel">
|
||||
<item-type>Number</item-type>
|
||||
<label>Current COP</label>
|
||||
<state pattern="%d"/>
|
||||
</channel-type>
|
||||
<channel-type id="cop-heating-channel">
|
||||
<item-type>Number</item-type>
|
||||
<label>Current COP Heating</label>
|
||||
<state pattern="%d"/>
|
||||
</channel-type>
|
||||
<channel-type id="cop-drinkingwater-channel">
|
||||
<item-type>Number</item-type>
|
||||
<label>Current COP drinking water</label>
|
||||
<state pattern="%d"/>
|
||||
</channel-type>
|
||||
<channel-type id="cop-cooling-channel">
|
||||
<item-type>Number</item-type>
|
||||
<label>Current COP Cooling</label>
|
||||
<state pattern="%d"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="power-channel">
|
||||
<item-type>Number:Power</item-type>
|
||||
<label>Current Power</label>
|
||||
<state pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="power-heating-channel">
|
||||
<item-type>Number:Power</item-type>
|
||||
<label>Current power heating</label>
|
||||
<state pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="power-drinkingwater-channel">
|
||||
<item-type>Number:Power</item-type>
|
||||
<label>Current Power Drinking Water</label>
|
||||
<state pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="power-cooling-channel">
|
||||
<item-type>Number:Power</item-type>
|
||||
<label>Current power cooling</label>
|
||||
<state pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="electric-power-channel">
|
||||
<item-type>Number:Power</item-type>
|
||||
<label>Current Electric Power</label>
|
||||
<state pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="electric-power-heating-channel">
|
||||
<item-type>Number:Power</item-type>
|
||||
<label>Current Electric Power Heating</label>
|
||||
<state pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="electric-power-drinkingwater-channel">
|
||||
<item-type>Number:Power</item-type>
|
||||
<label>Current electric power drinking water</label>
|
||||
<state pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="electric-power-cooling-channel">
|
||||
<item-type>Number:Power</item-type>
|
||||
<label>Current Electric Power Cooling</label>
|
||||
<state pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,18 @@
|
||||
<?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="xcenter-pv-modulation-values">
|
||||
<label>PV Modulation</label>
|
||||
<description>PV Modulation Information and Settings for Kermi Heatpump X-Center</description>
|
||||
<channels>
|
||||
<channel id="pv-state" typeId="pv-state-channel"/>
|
||||
<channel id="pv-power" typeId="pv-power-channel"/>
|
||||
<!-- R/W -->
|
||||
<channel id="pv-target-temperature-heating" typeId="pv-target-temperature-heating-channel"/>
|
||||
<!-- R/W -->
|
||||
<channel id="pv-target-temperature-drinkingwater" typeId="pv-target-temperature-drinkingwater-channel"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,26 @@
|
||||
<?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="pv-state-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>PV Modulation Active</label>
|
||||
<description>State of PV-Modulation</description>
|
||||
</channel-type>
|
||||
<channel-type id="pv-power-channel">
|
||||
<item-type>Number:Power</item-type>
|
||||
<label>PV Power</label>
|
||||
<state pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="pv-target-temperature-heating-channel">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>PV Temp Heating</label>
|
||||
<state pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="pv-target-temperature-drinkingwater-channel">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>PV Temp Drinkingwater</label>
|
||||
<state pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,13 @@
|
||||
<?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="xcenter-state-values">
|
||||
<label>Status</label>
|
||||
<description>Basic Information and State of your Kermi Heatpump X-Center</description>
|
||||
<channels>
|
||||
<channel id="global-state-id" typeId="global-state-id-channel"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,29 @@
|
||||
<?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="global-state-id-channel">
|
||||
<item-type>Number</item-type>
|
||||
<label>Global State</label>
|
||||
<description>Current state of your heat pump</description>
|
||||
<state readOnly="true" pattern="%d">
|
||||
<options>
|
||||
<option value="0">Standby</option>
|
||||
<option value="1">Alarm</option>
|
||||
<option value="2">DrinkingWater</option>
|
||||
<option value="4">Heating</option>
|
||||
<option value="5">Defrost</option>
|
||||
<option value="6">Preparing</option>
|
||||
<option value="7">Blocked</option>
|
||||
<option value="8">EVU Blocktime</option>
|
||||
<option value="9">Unavailable</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="global-alarm-channel">
|
||||
<item-type>Contact</item-type>
|
||||
<label>Global Alarm State</label>
|
||||
<description>If there's a global alarm</description>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,15 @@
|
||||
<?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="xcenter-workhours-values">
|
||||
<label>Workhours</label>
|
||||
<description>Basic Information of workhours</description>
|
||||
<channels>
|
||||
<channel id="workhours-fan" typeId="workhours-fan-channel"/>
|
||||
<channel id="workhours-storage-loading-pump" typeId="workhours-storage-loading-pump-channel"/>
|
||||
<channel id="workhours-compressor" typeId="workhours-compressor-channel"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,24 @@
|
||||
<?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="workhours-fan-channel">
|
||||
<item-type unitHint="h">Number:Time</item-type>
|
||||
<label>Fan Workhours</label>
|
||||
<description>Work hours of the fan</description>
|
||||
<state pattern="%d %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="workhours-storage-loading-pump-channel">
|
||||
<item-type unitHint="h">Number:Time</item-type>
|
||||
<label>StorageLoadingPump Workhours</label>
|
||||
<description>Work hours of the storage loading pump</description>
|
||||
<state pattern="%d %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="workhours-compressor-channel">
|
||||
<item-type unitHint="h">Number:Time</item-type>
|
||||
<label>Compressor Workhours</label>
|
||||
<description>Work hours of the compressor</description>
|
||||
<state pattern="%d %unit%"/>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.kermi.internal.dto;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
/**
|
||||
* Test for {@link StateDTO} class
|
||||
*
|
||||
* @author Kai Neuhaus - Initial contribution
|
||||
*/
|
||||
public class StateDTOTest {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
}
|
||||
}
|
@ -265,6 +265,7 @@
|
||||
<module>org.openhab.binding.minecraft</module>
|
||||
<module>org.openhab.binding.modbus</module>
|
||||
<module>org.openhab.binding.modbus.e3dc</module>
|
||||
<module>org.openhab.binding.modbus.kermi</module>
|
||||
<module>org.openhab.binding.modbus.sbc</module>
|
||||
<module>org.openhab.binding.modbus.studer</module>
|
||||
<module>org.openhab.binding.modbus.sungrow</module>
|
||||
|
Loading…
Reference in New Issue
Block a user