Skip to content

Commit 37c6d6b

Browse files
authored
[kermi] Initial contribution (openhab#16329)
* [kermi] Initial working state Signed-off-by: Kai Neuhaus <[email protected]>
1 parent a9a02af commit 37c6d6b

36 files changed

+2157
-0
lines changed

bom/openhab-addons/pom.xml

+5
Original file line numberDiff line numberDiff line change
@@ -1151,6 +1151,11 @@
11511151
<artifactId>org.openhab.binding.modbus.helioseasycontrols</artifactId>
11521152
<version>${project.version}</version>
11531153
</dependency>
1154+
<dependency>
1155+
<groupId>org.openhab.addons.bundles</groupId>
1156+
<artifactId>org.openhab.binding.modbus.kermi</artifactId>
1157+
<version>${project.version}</version>
1158+
</dependency>
11541159
<dependency>
11551160
<groupId>org.openhab.addons.bundles</groupId>
11561161
<artifactId>org.openhab.binding.modbus.sbc</artifactId>

bundles/org.openhab.binding.modbus.kermi/README.md

+235
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<parent>
8+
<groupId>org.openhab.addons.bundles</groupId>
9+
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
10+
<version>4.3.0-SNAPSHOT</version>
11+
</parent>
12+
13+
<artifactId>org.openhab.binding.modbus.kermi</artifactId>
14+
15+
<name>openHAB Add-ons :: Bundles :: Kermi Modbus Binding</name>
16+
17+
<dependencies>
18+
<dependency>
19+
<groupId>org.openhab.addons.bundles</groupId>
20+
<artifactId>org.openhab.binding.modbus</artifactId>
21+
<version>${project.version}</version>
22+
<scope>provided</scope>
23+
</dependency>
24+
</dependencies>
25+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/**
2+
* Copyright (c) 2010-2024 Contributors to the openHAB project
3+
*
4+
* See the NOTICE file(s) distributed with this work for additional
5+
* information.
6+
*
7+
* This program and the accompanying materials are made available under the
8+
* terms of the Eclipse Public License 2.0 which is available at
9+
* http://www.eclipse.org/legal/epl-2.0
10+
*
11+
* SPDX-License-Identifier: EPL-2.0
12+
*/
13+
package org.openhab.binding.modbus.kermi.internal;
14+
15+
import org.eclipse.jdt.annotation.NonNullByDefault;
16+
import org.openhab.binding.modbus.ModbusBindingConstants;
17+
import org.openhab.core.thing.ThingTypeUID;
18+
19+
/**
20+
* The {@link KermiBindingConstants} class defines common constants, which are
21+
* used across the whole binding.
22+
*
23+
* @author Kai Neuhaus - Initial contribution
24+
*/
25+
@NonNullByDefault
26+
public class KermiBindingConstants {
27+
28+
public static final String STATE_AND_ALARM_READ_ERRORS = "Status And Alarm Modbus Read Errors";
29+
public static final String STATE_READ_ERROR = "Information Modbus Read Error";
30+
public static final String DATA_READ_ERROR = "Data Modbus Read Error";
31+
static final String PV_READ_ERROR = "PV Modbus Read Error";
32+
public static final String ALARM_GROUP = "xcenter-alarm";
33+
public static final String STATE_GROUP = "xcenter-state";
34+
public static final String ENERGY_SOURCE_GROUP = "xcenter-energy-source";
35+
public static final String CHARGING_CIRCUIT_GROUP = "xcenter-charging-circuit";
36+
public static final String POWER_GROUP = "xcenter-power";
37+
public static final String WORKHOURS_GROUP = "xcenter-workhours";
38+
public static final String PV_GROUP = "xcenter-pv-modulation";
39+
private static final String BINDING_ID = ModbusBindingConstants.BINDING_ID;
40+
41+
// Supported Thing Types
42+
public static final ThingTypeUID THING_TYPE_KERMI_XCENTER = new ThingTypeUID(BINDING_ID, "kermi-xcenter");
43+
44+
// Channels for State
45+
public static final String GLOBAL_STATE_ID_CHANNEL = "global-state-id";
46+
47+
// Alarm State
48+
public static final String ALARM_STATE_CHANNEL = "alarm-state";
49+
50+
// Energy Source
51+
public static final String FLOW_TEMPERATURE_CHANNEL = "flow-temperature";
52+
public static final String RETURN_TEMPERATURE_CHANNEL = "return-temperature";
53+
public static final String FLOW_SPEED_CHANNEL = "flow-speed";
54+
55+
// Charging Circuit
56+
public static final String EXIT_TEMPERATURE_CHANNEL = "exit-temperature";
57+
public static final String INCOMING_TEMPERATURE_CHANNEL = "incoming-temperature";
58+
public static final String TEMPERATURE_SENSOR_OUTSIDE_CHANNEL = "temperature-sensor-outside";
59+
60+
// Power
61+
public static final String COP_CHANNEL = "cop";
62+
public static final String COP_HEATING_CHANNEL = "cop-heating";
63+
public static final String COP_DRINKINGWATER_CHANNEL = "cop-drinkingwater";
64+
public static final String COP_COOLING_CHANNEL = "cop-cooling";
65+
66+
public static final String POWER_CHANNEL = "power";
67+
public static final String POWER_HEATING_CHANNEL = "power-heating";
68+
public static final String POWER_DRINKINGWATER_CHANNEL = "power-drinkingwater";
69+
public static final String POWER_COOLING_CHANNEL = "power-cooling";
70+
71+
public static final String ELECTRIC_POWER_CHANNEL = "electric-power";
72+
public static final String ELECTRIC_POWER_HEATING_CHANNEL = "electric-power-heating";
73+
public static final String ELECTRIC_POWER_DRINKINGWATER_CHANNEL = "electric-power-drinkingwater";
74+
public static final String ELECTRIC_POWER_COOLING_CHANNEL = "electric-power-cooling";
75+
76+
// Work hours
77+
public static final String WORKHOURS_FAN_CHANNEL = "workhours-fan";
78+
public static final String WORKHOURS_STORAGE_LOADING_PUMP_CHANNEL = "workhours-storage-loading-pump";
79+
public static final String WORKHOURS_COMPRESSOR_CHANNEL = "workhours-compressor";
80+
81+
// PV
82+
public static final String PV_STATE_CHANNEL = "pv-state";
83+
public static final String PV_POWER_CHANNEL = "pv-power";
84+
public static final String PV_TARGET_TEMPERATURE_HEATING_CHANNEL = "pv-target-temperature-heating";
85+
public static final String PV_TARGET_TEMPERATURE_DRINKINGWATER_CHANNEL = "pv-target-temperature-drinkingwater";
86+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* Copyright (c) 2010-2024 Contributors to the openHAB project
3+
*
4+
* See the NOTICE file(s) distributed with this work for additional
5+
* information.
6+
*
7+
* This program and the accompanying materials are made available under the
8+
* terms of the Eclipse Public License 2.0 which is available at
9+
* http://www.eclipse.org/legal/epl-2.0
10+
*
11+
* SPDX-License-Identifier: EPL-2.0
12+
*/
13+
package org.openhab.binding.modbus.kermi.internal;
14+
15+
import org.eclipse.jdt.annotation.NonNullByDefault;
16+
17+
/**
18+
* The {@link KermiConfiguration} class contains fields mapping thing configuration parameters.
19+
*
20+
* @author Kai Neuhaus - Initial contribution
21+
*/
22+
@NonNullByDefault
23+
public class KermiConfiguration {
24+
25+
public int refresh = 5000;
26+
public boolean pvEnabled = false;
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* Copyright (c) 2010-2024 Contributors to the openHAB project
3+
*
4+
* See the NOTICE file(s) distributed with this work for additional
5+
* information.
6+
*
7+
* This program and the accompanying materials are made available under the
8+
* terms of the Eclipse Public License 2.0 which is available at
9+
* http://www.eclipse.org/legal/epl-2.0
10+
*
11+
* SPDX-License-Identifier: EPL-2.0
12+
*/
13+
package org.openhab.binding.modbus.kermi.internal;
14+
15+
import org.eclipse.jdt.annotation.NonNullByDefault;
16+
import org.eclipse.jdt.annotation.Nullable;
17+
import org.openhab.binding.modbus.kermi.internal.handler.KermiXcenterThingHandler;
18+
import org.openhab.core.thing.Bridge;
19+
import org.openhab.core.thing.Thing;
20+
import org.openhab.core.thing.ThingTypeUID;
21+
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
22+
import org.openhab.core.thing.binding.ThingHandler;
23+
import org.openhab.core.thing.binding.ThingHandlerFactory;
24+
import org.osgi.service.component.annotations.Component;
25+
26+
/**
27+
* The {@link KermiHandlerFactory} is responsible for creating things and thing handlers.
28+
*
29+
* @author Kai Neuhaus - Initial contribution
30+
*/
31+
@NonNullByDefault
32+
@Component(configurationPid = "binding.kermi", service = ThingHandlerFactory.class)
33+
public class KermiHandlerFactory extends BaseThingHandlerFactory {
34+
@Override
35+
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
36+
return thingTypeUID.equals(KermiBindingConstants.THING_TYPE_KERMI_XCENTER);
37+
}
38+
39+
@Override
40+
protected @Nullable ThingHandler createHandler(Thing thing) {
41+
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
42+
if (KermiBindingConstants.THING_TYPE_KERMI_XCENTER.equals(thingTypeUID)) {
43+
return new KermiXcenterThingHandler((Bridge) thing);
44+
} // else here
45+
return null;
46+
}
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* Copyright (c) 2010-2024 Contributors to the openHAB project
3+
*
4+
* See the NOTICE file(s) distributed with this work for additional
5+
* information.
6+
*
7+
* This program and the accompanying materials are made available under the
8+
* terms of the Eclipse Public License 2.0 which is available at
9+
* http://www.eclipse.org/legal/epl-2.0
10+
*
11+
* SPDX-License-Identifier: EPL-2.0
12+
*/
13+
package org.openhab.binding.modbus.kermi.internal.dto;
14+
15+
import static org.openhab.binding.modbus.kermi.internal.modbus.KermiModbusConstans.ALARM_REG_SIZE;
16+
17+
import org.openhab.binding.modbus.kermi.internal.modbus.Data;
18+
import org.openhab.core.io.transport.modbus.ModbusBitUtilities;
19+
import org.openhab.core.library.types.OnOffType;
20+
21+
/**
22+
* The {@link AlarmDTO} Data object for Kermi Xcenter
23+
*
24+
* @author Kai Neuhaus - Initial contribution
25+
*/
26+
public class AlarmDTO implements Data {
27+
28+
public OnOffType alarmIsActive;
29+
30+
public AlarmDTO(byte[] bArray) {
31+
int status = ModbusBitUtilities.extractBit(bArray, ALARM_REG_SIZE);
32+
alarmIsActive = OnOffType.from(status != 0);
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* Copyright (c) 2010-2024 Contributors to the openHAB project
3+
*
4+
* See the NOTICE file(s) distributed with this work for additional
5+
* information.
6+
*
7+
* This program and the accompanying materials are made available under the
8+
* terms of the Eclipse Public License 2.0 which is available at
9+
* http://www.eclipse.org/legal/epl-2.0
10+
*
11+
* SPDX-License-Identifier: EPL-2.0
12+
*/
13+
package org.openhab.binding.modbus.kermi.internal.dto;
14+
15+
import static org.openhab.core.library.unit.Units.LITRE_PER_MINUTE;
16+
17+
import javax.measure.quantity.Temperature;
18+
19+
import org.openhab.binding.modbus.kermi.internal.modbus.Data;
20+
import org.openhab.core.io.transport.modbus.ValueBuffer;
21+
import org.openhab.core.library.dimension.VolumetricFlowRate;
22+
import org.openhab.core.library.types.QuantityType;
23+
import org.openhab.core.library.unit.SIUnits;
24+
25+
/**
26+
* The {@link ChargingCircuitDTO} Data object for Kermi Xcenter
27+
*
28+
* @author Kai Neuhaus - Initial contribution
29+
*/
30+
public class ChargingCircuitDTO implements Data {
31+
32+
public QuantityType<Temperature> flowTemperature;
33+
public QuantityType<Temperature> returnFlowTemperature;
34+
public QuantityType<VolumetricFlowRate> flowSpeed;
35+
36+
public ChargingCircuitDTO(byte[] bArray) {
37+
ValueBuffer wrap = ValueBuffer.wrap(bArray);
38+
flowTemperature = QuantityType.valueOf(DataConverter.getSDoubleValue(wrap, 0.1), SIUnits.CELSIUS);
39+
returnFlowTemperature = QuantityType.valueOf(DataConverter.getSDoubleValue(wrap, 0.1), SIUnits.CELSIUS);
40+
flowSpeed = QuantityType.valueOf(DataConverter.getSDoubleValue(wrap, 0.1), LITRE_PER_MINUTE);
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/**
2+
* Copyright (c) 2010-2024 Contributors to the openHAB project
3+
*
4+
* See the NOTICE file(s) distributed with this work for additional
5+
* information.
6+
*
7+
* This program and the accompanying materials are made available under the
8+
* terms of the Eclipse Public License 2.0 which is available at
9+
* http://www.eclipse.org/legal/epl-2.0
10+
*
11+
* SPDX-License-Identifier: EPL-2.0
12+
*/
13+
package org.openhab.binding.modbus.kermi.internal.dto;
14+
15+
import java.nio.charset.StandardCharsets;
16+
import java.util.BitSet;
17+
18+
import org.eclipse.jdt.annotation.NonNullByDefault;
19+
import org.openhab.core.io.transport.modbus.ModbusBitUtilities;
20+
import org.openhab.core.io.transport.modbus.ValueBuffer;
21+
22+
/**
23+
* The {@link DataConverter} Helper class to convert bytes from modbus into desired data format
24+
*
25+
* @author Bernd Weymann - Initial contribution
26+
* @author Kai Neuhaus - used for Modbus.Kermi Binding
27+
*/
28+
@NonNullByDefault
29+
public class DataConverter {
30+
31+
/**
32+
* Retrieves a double value from the first two bytes of the provided {@link ValueBuffer} using the given correction
33+
* factor.
34+
*
35+
* @param wrap The {@link ValueBuffer} from which to extract the bytes.
36+
* @param factor The correction factor to apply to the extracted value.
37+
* @return The calculated double value.
38+
*/
39+
public static double getUDoubleValue(ValueBuffer wrap, double factor) {
40+
return round(wrap.getUInt16() * factor, 2);
41+
}
42+
43+
/**
44+
* Retrieves a signed double value from the first two bytes of the provided {@link ValueBuffer} using the given
45+
* correction factor.
46+
*
47+
* @param wrap The {@link ValueBuffer} from which to extract the bytes. This {@link ValueBuffer} should contain at
48+
* least two bytes.
49+
* @param factor The correction factor to apply to the extracted value. This factor is used to adjust the calculated
50+
* value.
51+
* @return The calculated signed double value. The value is obtained by extracting the first two bytes from the
52+
* {@link ValueBuffer},
53+
* converting them to a signed 16-bit integer, multiplying it by the correction factor, and rounding the
54+
* result to two decimal places.
55+
*/
56+
public static double getSDoubleValue(ValueBuffer wrap, double factor) {
57+
return round(wrap.getSInt16() * factor, 2);
58+
}
59+
60+
public static String getString(byte[] bArray) {
61+
return ModbusBitUtilities.extractStringFromBytes(bArray, 0, bArray.length, StandardCharsets.US_ASCII).trim();
62+
}
63+
64+
public static int toInt(BitSet bitSet) {
65+
int intValue = 0;
66+
for (int bit = 0; bit < bitSet.length(); bit++) {
67+
if (bitSet.get(bit)) {
68+
intValue |= (1 << bit);
69+
}
70+
}
71+
return intValue;
72+
}
73+
74+
public static double round(double value, int places) {
75+
if (places < 0) {
76+
throw new IllegalArgumentException();
77+
}
78+
79+
long factor = (long) Math.pow(10, places);
80+
long tmp = Math.round(value * factor);
81+
return (double) tmp / factor;
82+
}
83+
}

0 commit comments

Comments
 (0)