added migrated 2.x add-ons
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.modbus.stiebeleltron-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||
<repository>file:${basedirRoot}/bundles/org.openhab.io.transport.modbus/target/feature/feature.xml</repository>
|
||||
|
||||
<feature name="openhab-binding-modbus-stiebeleltron" description="StiebelEltron Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<feature>openhab-transport-modbus</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.modbus/${project.version}</bundle>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.modbus.stiebeleltron/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.modbus.stiebeleltron.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.ModbusBindingConstants;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link Modbus.StiebelEltronBindingConstants} class defines common
|
||||
* constants, which are used across the whole binding.
|
||||
*
|
||||
* @author Paul Frank - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class StiebelEltronBindingConstants {
|
||||
|
||||
private static final String BINDING_ID = ModbusBindingConstants.BINDING_ID;
|
||||
|
||||
// List of all Thing Type UIDs
|
||||
public static final ThingTypeUID THING_TYPE_HEATPUMP = new ThingTypeUID(BINDING_ID, "heatpump");
|
||||
|
||||
// Channel group ids
|
||||
public static final String GROUP_SYSTEM_STATE = "systemState";
|
||||
public static final String GROUP_SYSTEM_PARAMETER = "systemParameter";
|
||||
public static final String GROUP_SYSTEM_INFO = "systemInformation";
|
||||
public static final String GROUP_ENERGY_INFO = "energyInformation";
|
||||
|
||||
// List of all Channel ids in device information group
|
||||
public static final String CHANNEL_FEK_TEMPERATURE = "fek-temperature";
|
||||
public static final String CHANNEL_FEK_TEMPERATURE_SETPOINT = "fek-temperature-setpoint";
|
||||
public static final String CHANNEL_FEK_HUMIDITY = "fek-humidity";
|
||||
public static final String CHANNEL_FEK_DEWPOINT = "fek-dewpoint";
|
||||
public static final String CHANNEL_OUTDOOR_TEMPERATURE = "outdoor-temperature";
|
||||
public static final String CHANNEL_HK1_TEMPERATURE = "hk1-temperature";
|
||||
public static final String CHANNEL_HK1_TEMPERATURE_SETPOINT = "hk1-temperature-setpoint";
|
||||
public static final String CHANNEL_SUPPLY_TEMPERATURE = "supply-temperature";
|
||||
public static final String CHANNEL_RETURN_TEMPERATURE = "return-temperature";
|
||||
public static final String CHANNEL_SOURCE_TEMPERATURE = "source-temperature";
|
||||
public static final String CHANNEL_WATER_TEMPERATURE = "water-temperature";
|
||||
public static final String CHANNEL_WATER_TEMPERATURE_SETPOINT = "water-temperature-setpoint";
|
||||
|
||||
public static final String CHANNEL_PRODUCTION_HEAT_TODAY = "production-heat-today";
|
||||
public static final String CHANNEL_PRODUCTION_HEAT_TOTAL = "production-heat-total";
|
||||
public static final String CHANNEL_PRODUCTION_WATER_TODAY = "production-water-today";
|
||||
public static final String CHANNEL_PRODUCTION_WATER_TOTAL = "production-water-total";
|
||||
public static final String CHANNEL_CONSUMPTION_HEAT_TODAY = "consumption-heat-today";
|
||||
public static final String CHANNEL_CONSUMPTION_HEAT_TOTAL = "consumption-heat-total";
|
||||
public static final String CHANNEL_CONSUMPTION_WATER_TODAY = "consumption-water-today";
|
||||
public static final String CHANNEL_CONSUMPTION_WATER_TOTAL = "consumption-water-total";
|
||||
|
||||
public static final String CHANNEL_IS_HEATING = "is-heating";
|
||||
public static final String CHANNEL_IS_HEATING_WATER = "is-heating-water";
|
||||
public static final String CHANNEL_IS_COOLING = "is-cooling";
|
||||
public static final String CHANNEL_IS_PUMPING = "is-pumping";
|
||||
public static final String CHANNEL_IS_SUMMER = "is-summer";
|
||||
|
||||
public static final String CHANNEL_OPERATION_MODE = "operation-mode";
|
||||
public static final String CHANNEL_COMFORT_TEMPERATURE_HEATING = "comfort-temperature-heating";
|
||||
public static final String CHANNEL_ECO_TEMPERATURE_HEATING = "eco-temperature-heating";
|
||||
public static final String CHANNEL_COMFORT_TEMPERATURE_WATER = "comfort-temperature-water";
|
||||
public static final String CHANNEL_ECO_TEMPERATURE_WATER = "eco-temperature-water";
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.modbus.stiebeleltron.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link Modbus.StiebelEltronConfiguration} class contains fields mapping
|
||||
* thing configuration parameters.
|
||||
*
|
||||
* @author Paul Frank - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class StiebelEltronConfiguration {
|
||||
/**
|
||||
* Refresh interval in seconds
|
||||
*/
|
||||
private long refresh;
|
||||
|
||||
private int maxTries = 3;// backwards compatibility and tests
|
||||
|
||||
/**
|
||||
* Gets refresh period in milliseconds
|
||||
*/
|
||||
public long getRefreshMillis() {
|
||||
return refresh * 1000;
|
||||
}
|
||||
|
||||
public int getMaxTries() {
|
||||
return maxTries;
|
||||
}
|
||||
|
||||
public void setMaxTries(int maxTries) {
|
||||
this.maxTries = maxTries;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.modbus.stiebeleltron.internal;
|
||||
|
||||
import static org.openhab.binding.modbus.stiebeleltron.internal.StiebelEltronBindingConstants.THING_TYPE_HEATPUMP;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.modbus.stiebeleltron.internal.handler.StiebelEltronHandler;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
|
||||
/**
|
||||
* The {@link Modbus.StiebelEltronHandlerFactory} is responsible for creating things and thing
|
||||
* handlers.
|
||||
*
|
||||
* @author Paul Frank - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(configurationPid = "binding.stiebeleltron", service = ThingHandlerFactory.class)
|
||||
public class StiebelEltronHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_HEATPUMP);
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (THING_TYPE_HEATPUMP.equals(thingTypeUID)) {
|
||||
return new StiebelEltronHandler(thing);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.modbus.stiebeleltron.internal.dto;
|
||||
|
||||
/**
|
||||
* Dto class for the Energy Block
|
||||
*
|
||||
* @author Paul Frank - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class EnergyBlock {
|
||||
|
||||
public int productionHeatToday;
|
||||
public int productionHeatTotalLow;
|
||||
public int productionHeatTotalHigh;
|
||||
public int productionWaterToday;
|
||||
public int productionWaterTotalLow;
|
||||
public int productionWaterTotalHigh;
|
||||
|
||||
public int consumptionHeatToday;
|
||||
public int consumptionHeatTotalLow;
|
||||
public int consumptionHeatTotalHigh;
|
||||
public int consumptionWaterToday;
|
||||
public int consumptionWaterTotalLow;
|
||||
public int consumptionWaterTotalHigh;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.modbus.stiebeleltron.internal.dto;
|
||||
|
||||
/**
|
||||
* Dto class for the System Information Block
|
||||
*
|
||||
* @author Paul Frank - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class SystemInformationBlock {
|
||||
|
||||
public short temperatureFek;
|
||||
public short temperatureFekSetPoint;
|
||||
public short humidityFek;
|
||||
public short dewpointFek;
|
||||
public short temperatureOutdoor;
|
||||
public short temperatureHk1;
|
||||
public short temperatureHk1SetPoint;
|
||||
public short temperatureSupply;
|
||||
public short temperatureReturn;
|
||||
public short temperatureSource;
|
||||
public short temperatureWater;
|
||||
public short temperatureWaterSetPoint;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.modbus.stiebeleltron.internal.dto;
|
||||
|
||||
/**
|
||||
* Dto class for the System Parameter Block
|
||||
*
|
||||
* @author Paul Frank - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class SystemParameterBlock {
|
||||
|
||||
public int operationMode;
|
||||
public short comfortTemperatureHeating;
|
||||
public short ecoTemperatureHeating;
|
||||
public short comfortTemperatureWater;
|
||||
public short ecoTemperatureWater;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.modbus.stiebeleltron.internal.dto;
|
||||
|
||||
/**
|
||||
* Dto class for the System State Block
|
||||
*
|
||||
* @author Paul Frank - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class SystemStateBlock {
|
||||
|
||||
public int state;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.modbus.stiebeleltron.internal.handler;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Thrown when the stiebel eltron handler sees an error.
|
||||
*
|
||||
* @author Paul Frank - Initial contribution
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@NonNullByDefault
|
||||
public class StiebelEltronException extends Exception {
|
||||
|
||||
public StiebelEltronException() {
|
||||
}
|
||||
|
||||
public StiebelEltronException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,711 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.modbus.stiebeleltron.internal.handler;
|
||||
|
||||
import static org.openhab.binding.modbus.stiebeleltron.internal.StiebelEltronBindingConstants.*;
|
||||
import static org.openhab.core.library.unit.SIUnits.CELSIUS;
|
||||
import static org.openhab.core.library.unit.SmartHomeUnits.KILOWATT_HOUR;
|
||||
import static org.openhab.core.library.unit.SmartHomeUnits.PERCENT;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.measure.Unit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.modbus.handler.EndpointNotInitializedException;
|
||||
import org.openhab.binding.modbus.handler.ModbusEndpointThingHandler;
|
||||
import org.openhab.binding.modbus.stiebeleltron.internal.StiebelEltronConfiguration;
|
||||
import org.openhab.binding.modbus.stiebeleltron.internal.dto.EnergyBlock;
|
||||
import org.openhab.binding.modbus.stiebeleltron.internal.dto.SystemInformationBlock;
|
||||
import org.openhab.binding.modbus.stiebeleltron.internal.dto.SystemParameterBlock;
|
||||
import org.openhab.binding.modbus.stiebeleltron.internal.dto.SystemStateBlock;
|
||||
import org.openhab.binding.modbus.stiebeleltron.internal.parser.EnergyBlockParser;
|
||||
import org.openhab.binding.modbus.stiebeleltron.internal.parser.SystemInfromationBlockParser;
|
||||
import org.openhab.binding.modbus.stiebeleltron.internal.parser.SystemParameterBlockParser;
|
||||
import org.openhab.binding.modbus.stiebeleltron.internal.parser.SystemStateBlockParser;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OpenClosedType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.ThingStatusInfo;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.io.transport.modbus.AsyncModbusFailure;
|
||||
import org.openhab.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.io.transport.modbus.ModbusReadFunctionCode;
|
||||
import org.openhab.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.ModbusRegister;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.io.transport.modbus.ModbusWriteRegisterRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.ModbusWriteRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.PollTask;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link Modbus.StiebelEltronHandler} is responsible for handling commands,
|
||||
* which are sent to one of the channels and for polling the modbus.
|
||||
*
|
||||
* @author Paul Frank - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class StiebelEltronHandler extends BaseThingHandler {
|
||||
|
||||
public abstract class AbstractBasePoller {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(StiebelEltronHandler.class);
|
||||
|
||||
private volatile @Nullable PollTask pollTask;
|
||||
|
||||
public synchronized void unregisterPollTask() {
|
||||
PollTask task = pollTask;
|
||||
if (task == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ModbusCommunicationInterface mycomms = StiebelEltronHandler.this.comms;
|
||||
if (mycomms != null) {
|
||||
mycomms.unregisterRegularPoll(task);
|
||||
}
|
||||
pollTask = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register poll task This is where we set up our regular poller
|
||||
*/
|
||||
public synchronized void registerPollTask(int address, int length, ModbusReadFunctionCode readFunctionCode) {
|
||||
|
||||
logger.debug("Setting up regular polling");
|
||||
|
||||
ModbusCommunicationInterface mycomms = StiebelEltronHandler.this.comms;
|
||||
StiebelEltronConfiguration myconfig = StiebelEltronHandler.this.config;
|
||||
if (myconfig == null || mycomms == null) {
|
||||
throw new IllegalStateException("registerPollTask called without proper configuration");
|
||||
}
|
||||
|
||||
ModbusReadRequestBlueprint request = new ModbusReadRequestBlueprint(getSlaveId(), readFunctionCode, address,
|
||||
length, myconfig.getMaxTries());
|
||||
|
||||
long refreshMillis = myconfig.getRefreshMillis();
|
||||
|
||||
pollTask = mycomms.registerRegularPoll(request, refreshMillis, 1000, result -> {
|
||||
result.getRegisters().ifPresent(this::handlePolledData);
|
||||
if (getThing().getStatus() != ThingStatus.ONLINE) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
}, StiebelEltronHandler.this::handleReadError);
|
||||
}
|
||||
|
||||
public synchronized void poll() {
|
||||
PollTask task = pollTask;
|
||||
ModbusCommunicationInterface mycomms = StiebelEltronHandler.this.comms;
|
||||
if (task != null && mycomms != null) {
|
||||
mycomms.submitOneTimePoll(task.getRequest(), task.getResultCallback(), task.getFailureCallback());
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void handlePolledData(ModbusRegisterArray registers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logger instance
|
||||
*/
|
||||
private final Logger logger = LoggerFactory.getLogger(StiebelEltronHandler.class);
|
||||
|
||||
/**
|
||||
* Configuration instance
|
||||
*/
|
||||
protected @Nullable StiebelEltronConfiguration config = null;
|
||||
/**
|
||||
* Parser used to convert incoming raw messages into system blocks
|
||||
*/
|
||||
private final SystemInfromationBlockParser systemInformationBlockParser = new SystemInfromationBlockParser();
|
||||
/**
|
||||
* Parser used to convert incoming raw messages into system state blocks
|
||||
*/
|
||||
private final SystemStateBlockParser systemstateBlockParser = new SystemStateBlockParser();
|
||||
/**
|
||||
* Parser used to convert incoming raw messages into system parameter blocks
|
||||
*/
|
||||
private final SystemParameterBlockParser systemParameterBlockParser = new SystemParameterBlockParser();
|
||||
/**
|
||||
* Parser used to convert incoming raw messages into model blocks
|
||||
*/
|
||||
private final EnergyBlockParser energyBlockParser = new EnergyBlockParser();
|
||||
/**
|
||||
* This is the task used to poll the device
|
||||
*/
|
||||
private volatile @Nullable AbstractBasePoller systemInformationPoller = null;
|
||||
/**
|
||||
* This is the task used to poll the device
|
||||
*/
|
||||
private volatile @Nullable AbstractBasePoller energyPoller = null;
|
||||
/**
|
||||
* This is the task used to poll the device
|
||||
*/
|
||||
private volatile @Nullable AbstractBasePoller systemStatePoller = null;
|
||||
/**
|
||||
* This is the task used to poll the device
|
||||
*/
|
||||
private volatile @Nullable AbstractBasePoller systemParameterPoller = null;
|
||||
/**
|
||||
* Communication interface to the slave endpoint we're connecting to
|
||||
*/
|
||||
protected volatile @Nullable ModbusCommunicationInterface comms = null;
|
||||
|
||||
/**
|
||||
* This is the slave id, we store this once initialization is complete
|
||||
*/
|
||||
private volatile int slaveId;
|
||||
|
||||
/**
|
||||
* Instances of this handler should get a reference to the modbus manager
|
||||
*
|
||||
* @param thing the thing to handle
|
||||
* @param modbusManager the modbus manager
|
||||
*/
|
||||
public StiebelEltronHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param address address of the value to be written on the modbus
|
||||
* @param shortValue value to be written on the modbus
|
||||
*/
|
||||
protected void writeInt16(int address, short shortValue) {
|
||||
StiebelEltronConfiguration myconfig = StiebelEltronHandler.this.config;
|
||||
ModbusCommunicationInterface mycomms = StiebelEltronHandler.this.comms;
|
||||
|
||||
if (myconfig == null || mycomms == null) {
|
||||
throw new IllegalStateException("registerPollTask called without proper configuration");
|
||||
}
|
||||
// big endian byte ordering
|
||||
byte b1 = (byte) (shortValue >> 8);
|
||||
byte b2 = (byte) shortValue;
|
||||
|
||||
ModbusRegister register = new ModbusRegister(b1, b2);
|
||||
ModbusRegisterArray data = new ModbusRegisterArray(new ModbusRegister[] { register });
|
||||
|
||||
ModbusWriteRegisterRequestBlueprint request = new ModbusWriteRegisterRequestBlueprint(slaveId, address, data,
|
||||
false, myconfig.getMaxTries());
|
||||
|
||||
mycomms.submitOneTimeWrite(request, result -> {
|
||||
if (hasConfigurationError()) {
|
||||
return;
|
||||
}
|
||||
logger.debug("Successful write, matching request {}", request);
|
||||
StiebelEltronHandler.this.updateStatus(ThingStatus.ONLINE);
|
||||
}, failure -> {
|
||||
StiebelEltronHandler.this.handleWriteError(failure);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param command get the value of this command.
|
||||
* @return short the value of the command multiplied by 10 (see datatype 2 in
|
||||
* the stiebel eltron modbus documentation)
|
||||
*/
|
||||
private short getScaledInt16Value(Command command) throws StiebelEltronException {
|
||||
if (command instanceof QuantityType) {
|
||||
QuantityType<?> c = ((QuantityType<?>) command).toUnit(CELSIUS);
|
||||
if (c != null) {
|
||||
return (short) (c.doubleValue() * 10);
|
||||
} else {
|
||||
throw new StiebelEltronException("Unsupported unit");
|
||||
}
|
||||
}
|
||||
if (command instanceof DecimalType) {
|
||||
DecimalType c = (DecimalType) command;
|
||||
return (short) (c.doubleValue() * 10);
|
||||
}
|
||||
throw new StiebelEltronException("Unsupported command type");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param command get the value of this command.
|
||||
* @return short the value of the command as short
|
||||
*/
|
||||
private short getInt16Value(Command command) throws StiebelEltronException {
|
||||
if (command instanceof DecimalType) {
|
||||
DecimalType c = (DecimalType) command;
|
||||
return c.shortValue();
|
||||
}
|
||||
throw new StiebelEltronException("Unsupported command type");
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle incoming commands.
|
||||
*/
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
if (RefreshType.REFRESH == command) {
|
||||
String groupId = channelUID.getGroupId();
|
||||
if (groupId != null) {
|
||||
AbstractBasePoller poller;
|
||||
switch (groupId) {
|
||||
case GROUP_SYSTEM_STATE:
|
||||
poller = systemStatePoller;
|
||||
break;
|
||||
case GROUP_SYSTEM_PARAMETER:
|
||||
poller = systemParameterPoller;
|
||||
break;
|
||||
case GROUP_SYSTEM_INFO:
|
||||
poller = systemInformationPoller;
|
||||
break;
|
||||
case GROUP_ENERGY_INFO:
|
||||
poller = energyPoller;
|
||||
break;
|
||||
default:
|
||||
poller = null;
|
||||
break;
|
||||
}
|
||||
if (poller != null) {
|
||||
poller.poll();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
if (GROUP_SYSTEM_PARAMETER.equals(channelUID.getGroupId())) {
|
||||
switch (channelUID.getIdWithoutGroup()) {
|
||||
case CHANNEL_OPERATION_MODE:
|
||||
writeInt16(1500, getInt16Value(command));
|
||||
break;
|
||||
case CHANNEL_COMFORT_TEMPERATURE_HEATING:
|
||||
writeInt16(1501, getScaledInt16Value(command));
|
||||
break;
|
||||
case CHANNEL_ECO_TEMPERATURE_HEATING:
|
||||
writeInt16(1502, getScaledInt16Value(command));
|
||||
break;
|
||||
case CHANNEL_COMFORT_TEMPERATURE_WATER:
|
||||
writeInt16(1509, getScaledInt16Value(command));
|
||||
break;
|
||||
case CHANNEL_ECO_TEMPERATURE_WATER:
|
||||
writeInt16(1510, getScaledInt16Value(command));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (StiebelEltronException error) {
|
||||
if (hasConfigurationError() || getThing().getStatus() == ThingStatus.OFFLINE) {
|
||||
return;
|
||||
}
|
||||
String cls = error.getClass().getName();
|
||||
String msg = error.getMessage();
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
String.format("Error with: %s: %s", cls, msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialization: Load the config object of the block Connect to the slave
|
||||
* bridge Start the periodic polling
|
||||
*/
|
||||
@Override
|
||||
public void initialize() {
|
||||
config = getConfigAs(StiebelEltronConfiguration.class);
|
||||
logger.debug("Initializing thing with properties: {}", thing.getProperties());
|
||||
|
||||
startUp();
|
||||
}
|
||||
|
||||
/*
|
||||
* This method starts the operation of this handler Connect to the slave bridge
|
||||
* Start the periodic polling1
|
||||
*/
|
||||
private void startUp() {
|
||||
|
||||
if (comms != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ModbusEndpointThingHandler slaveEndpointThingHandler = getEndpointThingHandler();
|
||||
if (slaveEndpointThingHandler == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, "Bridge is offline");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
slaveId = slaveEndpointThingHandler.getSlaveId();
|
||||
|
||||
comms = slaveEndpointThingHandler.getCommunicationInterface();
|
||||
} catch (EndpointNotInitializedException e) {
|
||||
// this will be handled below as endpoint remains null
|
||||
}
|
||||
|
||||
if (comms == null) {
|
||||
@SuppressWarnings("null")
|
||||
String label = Optional.ofNullable(getBridge()).map(b -> b.getLabel()).orElse("<null>");
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE,
|
||||
String.format("Bridge '%s' not completely initialized", label));
|
||||
return;
|
||||
}
|
||||
|
||||
if (config == null) {
|
||||
logger.debug("Invalid comms/config/manager ref for stiebel eltron handler");
|
||||
return;
|
||||
}
|
||||
|
||||
if (systemInformationPoller == null) {
|
||||
AbstractBasePoller poller = new AbstractBasePoller() {
|
||||
@Override
|
||||
protected void handlePolledData(ModbusRegisterArray registers) {
|
||||
handlePolledSystemInformationData(registers);
|
||||
}
|
||||
};
|
||||
poller.registerPollTask(500, 36, ModbusReadFunctionCode.READ_INPUT_REGISTERS);
|
||||
systemInformationPoller = poller;
|
||||
}
|
||||
if (energyPoller == null) {
|
||||
AbstractBasePoller poller = new AbstractBasePoller() {
|
||||
@Override
|
||||
protected void handlePolledData(ModbusRegisterArray registers) {
|
||||
handlePolledEnergyData(registers);
|
||||
}
|
||||
};
|
||||
poller.registerPollTask(3500, 16, ModbusReadFunctionCode.READ_INPUT_REGISTERS);
|
||||
energyPoller = poller;
|
||||
}
|
||||
if (systemStatePoller == null) {
|
||||
AbstractBasePoller poller = new AbstractBasePoller() {
|
||||
@Override
|
||||
protected void handlePolledData(ModbusRegisterArray registers) {
|
||||
handlePolledSystemStateData(registers);
|
||||
}
|
||||
};
|
||||
poller.registerPollTask(2500, 2, ModbusReadFunctionCode.READ_INPUT_REGISTERS);
|
||||
systemStatePoller = poller;
|
||||
}
|
||||
if (systemParameterPoller == null) {
|
||||
AbstractBasePoller poller = new AbstractBasePoller() {
|
||||
@Override
|
||||
protected void handlePolledData(ModbusRegisterArray registers) {
|
||||
handlePolledSystemParameterData(registers);
|
||||
}
|
||||
};
|
||||
poller.registerPollTask(1500, 11, ModbusReadFunctionCode.READ_MULTIPLE_REGISTERS);
|
||||
systemParameterPoller = poller;
|
||||
}
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispose the binding correctly
|
||||
*/
|
||||
@Override
|
||||
public void dispose() {
|
||||
tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister the poll tasks and release the endpoint reference
|
||||
*/
|
||||
private void tearDown() {
|
||||
AbstractBasePoller poller = systemInformationPoller;
|
||||
if (poller != null) {
|
||||
logger.debug("Unregistering systemInformationPoller from ModbusManager");
|
||||
poller.unregisterPollTask();
|
||||
|
||||
systemInformationPoller = null;
|
||||
}
|
||||
|
||||
poller = energyPoller;
|
||||
if (poller != null) {
|
||||
logger.debug("Unregistering energyPoller from ModbusManager");
|
||||
poller.unregisterPollTask();
|
||||
|
||||
energyPoller = null;
|
||||
}
|
||||
|
||||
poller = systemStatePoller;
|
||||
if (poller != null) {
|
||||
logger.debug("Unregistering systemStatePoller from ModbusManager");
|
||||
poller.unregisterPollTask();
|
||||
|
||||
systemStatePoller = null;
|
||||
}
|
||||
|
||||
poller = systemParameterPoller;
|
||||
if (poller != null) {
|
||||
logger.debug("Unregistering systemParameterPoller from ModbusManager");
|
||||
poller.unregisterPollTask();
|
||||
|
||||
systemParameterPoller = null;
|
||||
}
|
||||
|
||||
comms = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current slave id from the bridge
|
||||
*/
|
||||
public int getSlaveId() {
|
||||
return slaveId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the endpoint handler from the bridge this handler is connected to Checks
|
||||
* that we're connected to the right type of bridge
|
||||
*
|
||||
* @return the endpoint handler or null if the bridge does not exist
|
||||
*/
|
||||
private @Nullable ModbusEndpointThingHandler getEndpointThingHandler() {
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge == null) {
|
||||
logger.debug("Bridge is null");
|
||||
return null;
|
||||
}
|
||||
if (bridge.getStatus() != ThingStatus.ONLINE) {
|
||||
logger.debug("Bridge is not online");
|
||||
return null;
|
||||
}
|
||||
|
||||
ThingHandler handler = bridge.getHandler();
|
||||
if (handler == null) {
|
||||
logger.debug("Bridge handler is null");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (handler instanceof ModbusEndpointThingHandler) {
|
||||
ModbusEndpointThingHandler slaveEndpoint = (ModbusEndpointThingHandler) handler;
|
||||
return slaveEndpoint;
|
||||
} else {
|
||||
throw new IllegalStateException("Unexpected bridge handler: " + handler.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns value divided by the 10
|
||||
*
|
||||
* @param value the value to alter
|
||||
* @return the scaled value as a DecimalType
|
||||
*/
|
||||
protected State getScaled(Number value, Unit<?> unit) {
|
||||
return QuantityType.valueOf(value.doubleValue() / 10, unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns high value * 1000 + low value
|
||||
*
|
||||
* @param high the high value
|
||||
* @param low the low valze
|
||||
* @return the scaled value as a DecimalType
|
||||
*/
|
||||
protected State getEnergyQuantity(int high, int low) {
|
||||
double value = high * 1000 + low;
|
||||
return QuantityType.valueOf(value, KILOWATT_HOUR);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called each time new data has been polled from the modbus
|
||||
* slave The register array is first parsed, then each of the channels are
|
||||
* updated to the new values
|
||||
*
|
||||
* @param registers byte array read from the modbus slave
|
||||
*/
|
||||
protected void handlePolledSystemInformationData(ModbusRegisterArray registers) {
|
||||
logger.trace("System Information block received, size: {}", registers.size());
|
||||
|
||||
SystemInformationBlock block = systemInformationBlockParser.parse(registers);
|
||||
|
||||
// System information group
|
||||
updateState(channelUID(GROUP_SYSTEM_INFO, CHANNEL_FEK_TEMPERATURE), getScaled(block.temperatureFek, CELSIUS));
|
||||
updateState(channelUID(GROUP_SYSTEM_INFO, CHANNEL_FEK_TEMPERATURE_SETPOINT),
|
||||
getScaled(block.temperatureFekSetPoint, CELSIUS));
|
||||
updateState(channelUID(GROUP_SYSTEM_INFO, CHANNEL_FEK_HUMIDITY), getScaled(block.humidityFek, PERCENT));
|
||||
updateState(channelUID(GROUP_SYSTEM_INFO, CHANNEL_FEK_DEWPOINT), getScaled(block.dewpointFek, CELSIUS));
|
||||
updateState(channelUID(GROUP_SYSTEM_INFO, CHANNEL_OUTDOOR_TEMPERATURE),
|
||||
getScaled(block.temperatureOutdoor, CELSIUS));
|
||||
updateState(channelUID(GROUP_SYSTEM_INFO, CHANNEL_HK1_TEMPERATURE), getScaled(block.temperatureHk1, CELSIUS));
|
||||
updateState(channelUID(GROUP_SYSTEM_INFO, CHANNEL_HK1_TEMPERATURE_SETPOINT),
|
||||
getScaled(block.temperatureHk1SetPoint, CELSIUS));
|
||||
updateState(channelUID(GROUP_SYSTEM_INFO, CHANNEL_SUPPLY_TEMPERATURE),
|
||||
getScaled(block.temperatureSupply, CELSIUS));
|
||||
updateState(channelUID(GROUP_SYSTEM_INFO, CHANNEL_RETURN_TEMPERATURE),
|
||||
getScaled(block.temperatureReturn, CELSIUS));
|
||||
updateState(channelUID(GROUP_SYSTEM_INFO, CHANNEL_SOURCE_TEMPERATURE),
|
||||
getScaled(block.temperatureSource, CELSIUS));
|
||||
updateState(channelUID(GROUP_SYSTEM_INFO, CHANNEL_WATER_TEMPERATURE),
|
||||
getScaled(block.temperatureWater, CELSIUS));
|
||||
updateState(channelUID(GROUP_SYSTEM_INFO, CHANNEL_WATER_TEMPERATURE_SETPOINT),
|
||||
getScaled(block.temperatureWaterSetPoint, CELSIUS));
|
||||
|
||||
resetCommunicationError();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called each time new data has been polled from the modbus
|
||||
* slave The register array is first parsed, then each of the channels are
|
||||
* updated to the new values
|
||||
*
|
||||
* @param registers byte array read from the modbus slave
|
||||
*/
|
||||
protected void handlePolledEnergyData(ModbusRegisterArray registers) {
|
||||
logger.trace("Energy block received, size: {}", registers.size());
|
||||
|
||||
EnergyBlock block = energyBlockParser.parse(registers);
|
||||
|
||||
// Energy information group
|
||||
updateState(channelUID(GROUP_ENERGY_INFO, CHANNEL_PRODUCTION_HEAT_TODAY),
|
||||
new QuantityType<>(block.productionHeatToday, KILOWATT_HOUR));
|
||||
updateState(channelUID(GROUP_ENERGY_INFO, CHANNEL_PRODUCTION_HEAT_TOTAL),
|
||||
getEnergyQuantity(block.productionHeatTotalHigh, block.productionHeatTotalLow));
|
||||
updateState(channelUID(GROUP_ENERGY_INFO, CHANNEL_PRODUCTION_WATER_TODAY),
|
||||
new QuantityType<>(block.productionWaterToday, KILOWATT_HOUR));
|
||||
updateState(channelUID(GROUP_ENERGY_INFO, CHANNEL_PRODUCTION_WATER_TOTAL),
|
||||
getEnergyQuantity(block.productionWaterTotalHigh, block.productionWaterTotalLow));
|
||||
updateState(channelUID(GROUP_ENERGY_INFO, CHANNEL_CONSUMPTION_HEAT_TODAY),
|
||||
new QuantityType<>(block.consumptionHeatToday, KILOWATT_HOUR));
|
||||
updateState(channelUID(GROUP_ENERGY_INFO, CHANNEL_CONSUMPTION_HEAT_TOTAL),
|
||||
getEnergyQuantity(block.consumptionHeatTotalHigh, block.consumptionHeatTotalLow));
|
||||
updateState(channelUID(GROUP_ENERGY_INFO, CHANNEL_CONSUMPTION_WATER_TODAY),
|
||||
new QuantityType<>(block.consumptionWaterToday, KILOWATT_HOUR));
|
||||
updateState(channelUID(GROUP_ENERGY_INFO, CHANNEL_CONSUMPTION_WATER_TOTAL),
|
||||
getEnergyQuantity(block.consumptionWaterTotalHigh, block.consumptionWaterTotalLow));
|
||||
|
||||
resetCommunicationError();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called each time new data has been polled from the modbus
|
||||
* slave The register array is first parsed, then each of the channels are
|
||||
* updated to the new values
|
||||
*
|
||||
* @param registers byte array read from the modbus slave
|
||||
*/
|
||||
protected void handlePolledSystemStateData(ModbusRegisterArray registers) {
|
||||
logger.trace("System state block received, size: {}", registers.size());
|
||||
|
||||
SystemStateBlock block = systemstateBlockParser.parse(registers);
|
||||
boolean isHeating = (block.state & 16) != 0;
|
||||
updateState(channelUID(GROUP_SYSTEM_STATE, CHANNEL_IS_HEATING),
|
||||
isHeating ? OpenClosedType.OPEN : OpenClosedType.CLOSED);
|
||||
updateState(channelUID(GROUP_SYSTEM_STATE, CHANNEL_IS_HEATING_WATER),
|
||||
(block.state & 32) != 0 ? OpenClosedType.OPEN : OpenClosedType.CLOSED);
|
||||
updateState(channelUID(GROUP_SYSTEM_STATE, CHANNEL_IS_COOLING),
|
||||
(block.state & 256) != 0 ? OpenClosedType.OPEN : OpenClosedType.CLOSED);
|
||||
updateState(channelUID(GROUP_SYSTEM_STATE, CHANNEL_IS_SUMMER),
|
||||
(block.state & 128) != 0 ? OpenClosedType.OPEN : OpenClosedType.CLOSED);
|
||||
updateState(channelUID(GROUP_SYSTEM_STATE, CHANNEL_IS_PUMPING),
|
||||
(block.state & 1) != 0 ? OpenClosedType.OPEN : OpenClosedType.CLOSED);
|
||||
|
||||
resetCommunicationError();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called each time new data has been polled from the modbus
|
||||
* slave The register array is first parsed, then each of the channels are
|
||||
* updated to the new values
|
||||
*
|
||||
* @param registers byte array read from the modbus slave
|
||||
*/
|
||||
protected void handlePolledSystemParameterData(ModbusRegisterArray registers) {
|
||||
logger.trace("System state block received, size: {}", registers.size());
|
||||
|
||||
SystemParameterBlock block = systemParameterBlockParser.parse(registers);
|
||||
updateState(channelUID(GROUP_SYSTEM_PARAMETER, CHANNEL_OPERATION_MODE), new DecimalType(block.operationMode));
|
||||
|
||||
updateState(channelUID(GROUP_SYSTEM_PARAMETER, CHANNEL_COMFORT_TEMPERATURE_HEATING),
|
||||
getScaled(block.comfortTemperatureHeating, CELSIUS));
|
||||
updateState(channelUID(GROUP_SYSTEM_PARAMETER, CHANNEL_ECO_TEMPERATURE_HEATING),
|
||||
getScaled(block.ecoTemperatureHeating, CELSIUS));
|
||||
updateState(channelUID(GROUP_SYSTEM_PARAMETER, CHANNEL_COMFORT_TEMPERATURE_WATER),
|
||||
getScaled(block.comfortTemperatureWater, CELSIUS));
|
||||
updateState(channelUID(GROUP_SYSTEM_PARAMETER, CHANNEL_ECO_TEMPERATURE_WATER),
|
||||
getScaled(block.ecoTemperatureWater, CELSIUS));
|
||||
|
||||
resetCommunicationError();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bridgeStatusInfo
|
||||
*/
|
||||
@Override
|
||||
public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
|
||||
super.bridgeStatusChanged(bridgeStatusInfo);
|
||||
|
||||
if (bridgeStatusInfo.getStatus() == ThingStatus.ONLINE) {
|
||||
startUp();
|
||||
} else if (bridgeStatusInfo.getStatus() == ThingStatus.OFFLINE) {
|
||||
tearDown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle errors received during communication
|
||||
*/
|
||||
protected void handleReadError(AsyncModbusFailure<ModbusReadRequestBlueprint> failure) {
|
||||
// Ignore all incoming data and errors if configuration is not correct
|
||||
if (hasConfigurationError() || getThing().getStatus() == ThingStatus.OFFLINE) {
|
||||
return;
|
||||
}
|
||||
String msg = failure.getCause().getMessage();
|
||||
String cls = failure.getCause().getClass().getName();
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
String.format("Error with read: %s: %s", cls, msg));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle errors received during communication
|
||||
*/
|
||||
protected void handleWriteError(AsyncModbusFailure<ModbusWriteRequestBlueprint> failure) {
|
||||
// Ignore all incoming data and errors if configuration is not correct
|
||||
if (hasConfigurationError() || getThing().getStatus() == ThingStatus.OFFLINE) {
|
||||
return;
|
||||
}
|
||||
String msg = failure.getCause().getMessage();
|
||||
String cls = failure.getCause().getClass().getName();
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
String.format("Error with write: %s: %s", cls, msg));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, if we're in a CONFIGURATION_ERROR state
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected boolean hasConfigurationError() {
|
||||
ThingStatusInfo statusInfo = getThing().getStatusInfo();
|
||||
return statusInfo.getStatus() == ThingStatus.OFFLINE
|
||||
&& statusInfo.getStatusDetail() == ThingStatusDetail.CONFIGURATION_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset communication status to ONLINE if we're in an OFFLINE state
|
||||
*/
|
||||
protected void resetCommunicationError() {
|
||||
ThingStatusInfo statusInfo = thing.getStatusInfo();
|
||||
if (ThingStatus.OFFLINE.equals(statusInfo.getStatus())
|
||||
&& ThingStatusDetail.COMMUNICATION_ERROR.equals(statusInfo.getStatusDetail())) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the channel UID for the specified group and channel id
|
||||
*
|
||||
* @param string the channel group
|
||||
* @param string the channel id in that group
|
||||
* @return the globally unique channel uid
|
||||
*/
|
||||
ChannelUID channelUID(String group, String id) {
|
||||
return new ChannelUID(getThing().getUID(), group, id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.modbus.stiebeleltron.internal.parser;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.io.transport.modbus.ModbusBitUtilities;
|
||||
import org.openhab.io.transport.modbus.ModbusConstants.ValueType;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
|
||||
/**
|
||||
* Base class for parsers with some helper methods
|
||||
*
|
||||
* @author Nagy Attila Gabor - Initial contribution
|
||||
* @author Paul Frank - Added more methods
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AbstractBaseParser {
|
||||
|
||||
/**
|
||||
* Extract an optional double value
|
||||
*
|
||||
* @param raw the register array to extract from
|
||||
* @param index the address of the field
|
||||
* @return the parsed value or empty if the field is not implemented
|
||||
*/
|
||||
protected Optional<Double> extractOptionalDouble(ModbusRegisterArray raw, int index) {
|
||||
return ModbusBitUtilities.extractStateFromRegisters(raw, index, ValueType.INT16)
|
||||
.map(value -> ((double) value.intValue()) / 10.0).filter(value -> value != (short) 0x8000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a mandatory double value
|
||||
*
|
||||
* @param raw the register array to extract from
|
||||
* @param index the address of the field
|
||||
* @param def the default value
|
||||
* @return the parsed value or the default if the field is not implemented
|
||||
*/
|
||||
protected Double extractDouble(ModbusRegisterArray raw, int index, double def) {
|
||||
return extractOptionalDouble(raw, index).orElse(def);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract an optional int16 value
|
||||
*
|
||||
* @param raw the register array to extract from
|
||||
* @param index the address of the field
|
||||
* @return the parsed value or empty if the field is not implemented
|
||||
*/
|
||||
protected Optional<Short> extractOptionalInt16(ModbusRegisterArray raw, int index) {
|
||||
return ModbusBitUtilities.extractStateFromRegisters(raw, index, ValueType.INT16).map(DecimalType::shortValue)
|
||||
.filter(value -> value != (short) 0x8000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a mandatory int16 value
|
||||
*
|
||||
* @param raw the register array to extract from
|
||||
* @param index the address of the field
|
||||
* @param def the default value
|
||||
* @return the parsed value or the default if the field is not implemented
|
||||
*/
|
||||
protected Short extractInt16(ModbusRegisterArray raw, int index, short def) {
|
||||
return extractOptionalInt16(raw, index).orElse(def);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract an optional uint16 value
|
||||
*
|
||||
* @param raw the register array to extract from
|
||||
* @param index the address of the field
|
||||
* @return the parsed value or empty if the field is not implemented
|
||||
*/
|
||||
protected Optional<Integer> extractOptionalUInt16(ModbusRegisterArray raw, int index) {
|
||||
return ModbusBitUtilities.extractStateFromRegisters(raw, index, ValueType.UINT16).map(DecimalType::intValue)
|
||||
.filter(value -> value != 0xffff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a mandatory uint16 value
|
||||
*
|
||||
* @param raw the register array to extract from
|
||||
* @param index the address of the field
|
||||
* @param def the default value
|
||||
* @return the parsed value or the default if the field is not implemented
|
||||
*/
|
||||
protected Integer extractUInt16(ModbusRegisterArray raw, int index, int def) {
|
||||
return extractOptionalUInt16(raw, index).orElse(def);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract an optional acc32 value
|
||||
*
|
||||
* @param raw the register array to extract from
|
||||
* @param index the address of the field
|
||||
* @return the parsed value or empty if the field is not implemented
|
||||
*/
|
||||
protected Optional<Long> extractOptionalUInt32(ModbusRegisterArray raw, int index) {
|
||||
return ModbusBitUtilities.extractStateFromRegisters(raw, index, ValueType.UINT32).map(DecimalType::longValue)
|
||||
.filter(value -> value != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a mandatory acc32 value
|
||||
*
|
||||
* @param raw the register array to extract from
|
||||
* @param index the address of the field
|
||||
* @param def the default value
|
||||
* @return the parsed value or default if the field is not implemented
|
||||
*/
|
||||
protected Long extractUnit32(ModbusRegisterArray raw, int index, long def) {
|
||||
return extractOptionalUInt32(raw, index).orElse(def);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.modbus.stiebeleltron.internal.parser;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.stiebeleltron.internal.dto.EnergyBlock;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
|
||||
/**
|
||||
* Parses inverter modbus data into an Energy Block
|
||||
*
|
||||
* @author Paul Frank - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EnergyBlockParser extends AbstractBaseParser {
|
||||
|
||||
public EnergyBlock parse(ModbusRegisterArray raw) {
|
||||
EnergyBlock block = new EnergyBlock();
|
||||
|
||||
block.productionHeatToday = extractUInt16(raw, 0, (short) 0);
|
||||
block.productionHeatTotalLow = extractUInt16(raw, 1, (short) 0);
|
||||
block.productionHeatTotalHigh = extractUInt16(raw, 2, (short) 0);
|
||||
block.productionWaterToday = extractUInt16(raw, 3, (short) 0);
|
||||
block.productionWaterTotalLow = extractUInt16(raw, 4, (short) 0);
|
||||
block.productionWaterTotalHigh = extractUInt16(raw, 5, (short) 0);
|
||||
|
||||
block.consumptionHeatToday = extractUInt16(raw, 10, (short) 0);
|
||||
block.consumptionHeatTotalLow = extractUInt16(raw, 11, (short) 0);
|
||||
block.consumptionHeatTotalHigh = extractUInt16(raw, 12, (short) 0);
|
||||
block.consumptionWaterToday = extractUInt16(raw, 13, (short) 0);
|
||||
block.consumptionWaterTotalLow = extractUInt16(raw, 14, (short) 0);
|
||||
block.consumptionWaterTotalHigh = extractUInt16(raw, 15, (short) 0);
|
||||
return block;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.modbus.stiebeleltron.internal.parser;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.stiebeleltron.internal.dto.SystemInformationBlock;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
|
||||
/**
|
||||
* Parses inverter modbus data into an SystemB Information lock
|
||||
*
|
||||
* @author Paul Frank - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class SystemInfromationBlockParser extends AbstractBaseParser {
|
||||
|
||||
public SystemInformationBlock parse(ModbusRegisterArray raw) {
|
||||
SystemInformationBlock block = new SystemInformationBlock();
|
||||
|
||||
block.temperatureFek = extractInt16(raw, 2, (short) 0);
|
||||
block.temperatureFekSetPoint = extractInt16(raw, 3, (short) 0);
|
||||
block.humidityFek = extractInt16(raw, 4, (short) 0);
|
||||
block.dewpointFek = extractInt16(raw, 5, (short) 0);
|
||||
block.temperatureOutdoor = extractInt16(raw, 6, (short) 0);
|
||||
block.temperatureHk1 = extractInt16(raw, 7, (short) 0);
|
||||
block.temperatureHk1SetPoint = extractInt16(raw, 9, (short) 0);
|
||||
block.temperatureSupply = extractInt16(raw, 12, (short) 0);
|
||||
block.temperatureReturn = extractInt16(raw, 15, (short) 0);
|
||||
block.temperatureWater = extractInt16(raw, 21, (short) 0);
|
||||
block.temperatureWaterSetPoint = extractInt16(raw, 22, (short) 0);
|
||||
block.temperatureSource = extractInt16(raw, 35, (short) 0);
|
||||
return block;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.modbus.stiebeleltron.internal.parser;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.stiebeleltron.internal.dto.SystemParameterBlock;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
|
||||
/**
|
||||
* Parses inverter modbus data into an System Parameter Block
|
||||
*
|
||||
* @author Paul Frank - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class SystemParameterBlockParser extends AbstractBaseParser {
|
||||
|
||||
public SystemParameterBlock parse(ModbusRegisterArray raw) {
|
||||
SystemParameterBlock block = new SystemParameterBlock();
|
||||
|
||||
block.operationMode = extractUInt16(raw, 0, 0);
|
||||
block.comfortTemperatureHeating = extractInt16(raw, 1, (short) 0);
|
||||
block.ecoTemperatureHeating = extractInt16(raw, 2, (short) 0);
|
||||
block.comfortTemperatureWater = extractInt16(raw, 9, (short) 0);
|
||||
block.ecoTemperatureWater = extractInt16(raw, 10, (short) 0);
|
||||
return block;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.modbus.stiebeleltron.internal.parser;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.stiebeleltron.internal.dto.SystemStateBlock;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
|
||||
/**
|
||||
* Parses inverter modbus data into an System State Block
|
||||
*
|
||||
* @author Paul Frank - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class SystemStateBlockParser extends AbstractBaseParser {
|
||||
|
||||
public SystemStateBlock parse(ModbusRegisterArray raw) {
|
||||
SystemStateBlock block = new SystemStateBlock();
|
||||
|
||||
block.state = extractUInt16(raw, 0, 0);
|
||||
return block;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<config-description:config-descriptions
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:config-description="https://openhab.org/schemas/config-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/config-description/v1.0.0 https://openhab.org/schemas/config-description-1.0.0.xsd">
|
||||
|
||||
<config-description uri="thing-type:stiebeleltron:modbusconfig">
|
||||
|
||||
<parameter name="refresh" type="integer" min="1" unit="s">
|
||||
<label>Polling Interval</label>
|
||||
<description>Poll interval in seconds. Use zero to disable automatic polling.</description>
|
||||
<default>5</default>
|
||||
<unitLabel>s</unitLabel>
|
||||
</parameter>
|
||||
|
||||
<parameter name="maxTries" type="integer" min="1">
|
||||
<label>Maximum Tries When Reading</label>
|
||||
<default>3</default>
|
||||
<description>Number of tries when reading data, if some of the reading fail. For single try, enter 1.</description>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
|
||||
</config-description>
|
||||
|
||||
</config-description:config-descriptions>
|
||||
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="modbus"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<channel-group-type id="system-state">
|
||||
<label>System State</label>
|
||||
<channels>
|
||||
<channel id="is-heating" typeId="is-heating-type"/>
|
||||
<channel id="is-heating-water" typeId="is-heating-water-type"/>
|
||||
<channel id="is-cooling" typeId="is-cooling-type"/>
|
||||
<channel id="is-pumping" typeId="is-pumping-type"/>
|
||||
<channel id="is-summer" typeId="is-summer-type"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="system-parameter">
|
||||
<label>System Parameters</label>
|
||||
<channels>
|
||||
<channel id="operation-mode" typeId="operation-mode-type"/>
|
||||
<channel id="comfort-temperature-heating" typeId="comfort-temperature-heating-type"/>
|
||||
<channel id="eco-temperature-heating" typeId="eco-temperature-heating-type"/>
|
||||
<channel id="comfort-temperature-water" typeId="comfort-temperature-water-type"/>
|
||||
<channel id="eco-temperature-water" typeId="eco-temperature-water-type"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="system-information">
|
||||
<label>System Information</label>
|
||||
<channels>
|
||||
<channel id="fek-temperature" typeId="fek-temperature-type"/>
|
||||
<channel id="fek-temperature-setpoint" typeId="fek-temperature-setpoint-type"/>
|
||||
<channel id="fek-humidity" typeId="fek-humidity-type"/>
|
||||
<channel id="fek-dewpoint" typeId="fek-dewpoint-type"/>
|
||||
<channel id="outdoor-temperature" typeId="outdoor-temperature-type"/>
|
||||
<channel id="hk1-temperature" typeId="hk1-temperature-type"/>
|
||||
<channel id="hk1-temperature-setpoint" typeId="hk1-temperature-setpoint-type"/>
|
||||
<channel id="supply-temperature" typeId="supply-temperature-type"/>
|
||||
<channel id="return-temperature" typeId="return-temperature-type"/>
|
||||
<channel id="source-temperature" typeId="source-temperature-type"/>
|
||||
<channel id="water-temperature" typeId="water-temperature-type"/>
|
||||
<channel id="water-temperature-setpoint" typeId="water-temperature-setpoint-type"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="energy-information">
|
||||
<label>Energy Information</label>
|
||||
<channels>
|
||||
<channel id="production-heat-today" typeId="production-heat-today-type"/>
|
||||
<channel id="production-heat-total" typeId="production-heat-total-type"/>
|
||||
<channel id="production-water-today" typeId="production-water-today-type"/>
|
||||
<channel id="production-water-total" typeId="production-water-total-type"/>
|
||||
<channel id="consumption-heat-today" typeId="consumption-heat-today-type"/>
|
||||
<channel id="consumption-heat-total" typeId="consumption-heat-total-type"/>
|
||||
<channel id="consumption-water-today" typeId="consumption-water-today-type"/>
|
||||
<channel id="consumption-water-total" typeId="consumption-water-total-type"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,171 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<thing:thing-descriptions bindingId="modbus"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<channel-type id="fek-temperature-type">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>FFK Temperature</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="fek-temperature-setpoint-type">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>FFK Temperature Set Point</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="fek-humidity-type">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>FFK Humidity</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="fek-dewpoint-type">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>FFK Dewpoint</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="outdoor-temperature-type">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Outdoor Temperature</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="hk1-temperature-type">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>HK1 Temperature</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="hk1-temperature-setpoint-type">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>HK1 Temperature Set Point</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="supply-temperature-type">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Supply Temperature</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="return-temperature-type">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Return Temperature</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="source-temperature-type">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Source Temperature</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="water-temperature-type">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Water Temperature</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="water-temperature-setpoint-type">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Water Temperature Set Point</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
|
||||
<channel-type id="production-heat-today-type">
|
||||
<item-type>Number:Energy</item-type>
|
||||
<label>Heat Quantity Today</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="production-heat-total-type">
|
||||
<item-type>Number:Energy</item-type>
|
||||
<label>Heat Quantity Total</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="production-water-today-type">
|
||||
<item-type>Number:Energy</item-type>
|
||||
<label>Water Heat Quantity Today</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="production-water-total-type">
|
||||
<item-type>Number:Energy</item-type>
|
||||
<label>Water Heat Quantity Total</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="consumption-heat-today-type">
|
||||
<item-type>Number:Energy</item-type>
|
||||
<label>Power Consumption for Heating Today</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="consumption-heat-total-type">
|
||||
<item-type>Number:Energy</item-type>
|
||||
<label>Power Consumption for Heating Total</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="consumption-water-today-type">
|
||||
<item-type>Number:Energy</item-type>
|
||||
<label>Power Consumption for Water Today</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="consumption-water-total-type">
|
||||
<item-type>Number:Energy</item-type>
|
||||
<label>Power Consumption for Water Total</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="is-heating-type">
|
||||
<item-type>Contact</item-type>
|
||||
<label>Currently Heating</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="is-heating-water-type">
|
||||
<item-type>Contact</item-type>
|
||||
<label>Currently Heating Water</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="is-cooling-type">
|
||||
<item-type>Contact</item-type>
|
||||
<label>Currently Cooling</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="is-pumping-type">
|
||||
<item-type>Contact</item-type>
|
||||
<label>Currently Pumping</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="is-summer-type">
|
||||
<item-type>Contact</item-type>
|
||||
<label>Summer Operation Mode</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="operation-mode-type">
|
||||
<item-type>Number</item-type>
|
||||
<label>Operation Mode</label>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="0">Emergency</option>
|
||||
<option value="1">Ready</option>
|
||||
<option value="2">Program</option>
|
||||
<option value="3">Comfort</option>
|
||||
<option value="4">Eco</option>
|
||||
<option value="5">Water</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="comfort-temperature-heating-type">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Comfort Temperature Heating</label>
|
||||
<state pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="eco-temperature-heating-type">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Eco Temperature Heating</label>
|
||||
<state pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="comfort-temperature-water-type">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Comfort Temperature Water</label>
|
||||
<state pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="eco-temperature-water-type">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Eco Temperature Water</label>
|
||||
<state pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="modbus"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<thing-type id="heatpump">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="tcp"/>
|
||||
<bridge-type-ref id="serial"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>Stiebel Eltron ISG</label>
|
||||
<description>Stiebel Eltron ISG connected through modbus</description>
|
||||
|
||||
<channel-groups>
|
||||
<channel-group id="systemState" typeId="system-state"/>
|
||||
<channel-group id="systemParameter" typeId="system-parameter"/>
|
||||
<channel-group id="systemInformation" typeId="system-information"/>
|
||||
<channel-group id="energyInformation" typeId="energy-information"/>
|
||||
</channel-groups>
|
||||
|
||||
<config-description-ref uri="thing-type:stiebeleltron:modbusconfig"/>
|
||||
|
||||
</thing-type>
|
||||
|
||||
|
||||
</thing:thing-descriptions>
|
||||
Reference in New Issue
Block a user