added migrated 2.x add-ons
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.vitotronic-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
|
||||
|
||||
<feature name="openhab-binding-vitotronic" description="Vitotronic Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.vitotronic/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
||||
@@ -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.vitotronic.internal;
|
||||
|
||||
/**
|
||||
* The {@link VitotronicBindingConfiguration} class defines variables which are
|
||||
* used for the binding configuration.
|
||||
*
|
||||
* @author Stefan Andres - Initial contribution
|
||||
*/
|
||||
|
||||
public class VitotronicBindingConfiguration {
|
||||
|
||||
public String ipAddress;
|
||||
public Integer port;
|
||||
public String adapterId;
|
||||
public Integer refreshInterval;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* 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.vitotronic.internal;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link VitotronicBinding} class defines common constants, which are
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Stefan Andres - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VitotronicBindingConstants {
|
||||
|
||||
public static final String BROADCAST_MESSAGE = "@@@@VITOTRONIC@@@@/";
|
||||
public static final int BROADCAST_PORT = 31113;
|
||||
|
||||
public static final String BINDING_ID = "vitotronic";
|
||||
public static final String IP_ADDRESS = "ipAddress";
|
||||
public static final String PORT = "port";
|
||||
public static final String ADAPTER_ID = "adapterID";
|
||||
public static final String REFRESH_INTERVAL = "refreshInterval";
|
||||
public static final String DISCOVERY_INTERVAL = "discoveryInterval";
|
||||
|
||||
// List of main device types
|
||||
public static final String BRIDGE_VITOTRONIC = "bridge";
|
||||
|
||||
// List of all Thing Type
|
||||
public static final String THING_ID_HEATING = "heating";
|
||||
public static final String THING_ID_GASBURNER = "gasburner";
|
||||
public static final String THING_ID_PELLETBURNER = "pelletburner";
|
||||
public static final String THING_ID_OILBURNER = "oilburner";
|
||||
public static final String THING_ID_STORAGETANK = "storagetank";
|
||||
public static final String THING_ID_CIRCUIT = "circuit";
|
||||
public static final String THING_ID_SOLAR = "solar";
|
||||
public static final String THING_ID_TEMPERATURESENSOR = "temperaturesensor";
|
||||
public static final String THING_ID_PUMP = "pump";
|
||||
public static final String THING_ID_VALVE = "valve";
|
||||
|
||||
// List of all Thing Type UIDs
|
||||
public static final ThingTypeUID THING_TYPE_UID_BRIDGE = new ThingTypeUID(BINDING_ID, BRIDGE_VITOTRONIC);
|
||||
public static final ThingTypeUID THING_TYPE_UID_HEATING = new ThingTypeUID(BINDING_ID, THING_ID_HEATING);
|
||||
public static final ThingTypeUID THING_TYPE_UID_GASBURNER = new ThingTypeUID(BINDING_ID, THING_ID_GASBURNER);
|
||||
public static final ThingTypeUID THING_TYPE_UID_PELLETBURNER = new ThingTypeUID(BINDING_ID, THING_ID_PELLETBURNER);
|
||||
public static final ThingTypeUID THING_TYPE_UID_OILBURNER = new ThingTypeUID(BINDING_ID, THING_ID_OILBURNER);
|
||||
public static final ThingTypeUID THING_TYPE_UID_STORAGETANK = new ThingTypeUID(BINDING_ID, THING_ID_STORAGETANK);
|
||||
public static final ThingTypeUID THING_TYPE_UID_CIRCUIT = new ThingTypeUID(BINDING_ID, THING_ID_CIRCUIT);
|
||||
public static final ThingTypeUID THING_TYPE_UID_SOLAR = new ThingTypeUID(BINDING_ID, THING_ID_SOLAR);
|
||||
public static final ThingTypeUID THING_TYPE_UID_TEMPERATURESENSOR = new ThingTypeUID(BINDING_ID,
|
||||
THING_ID_TEMPERATURESENSOR);
|
||||
public static final ThingTypeUID THING_TYPE_UID_PUMP = new ThingTypeUID(BINDING_ID, THING_ID_PUMP);
|
||||
public static final ThingTypeUID THING_TYPE_UID_VALVE = new ThingTypeUID(BINDING_ID, THING_ID_VALVE);
|
||||
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet(Stream
|
||||
.of(THING_TYPE_UID_BRIDGE, THING_TYPE_UID_GASBURNER, THING_TYPE_UID_HEATING, THING_TYPE_UID_PELLETBURNER,
|
||||
THING_TYPE_UID_OILBURNER, THING_TYPE_UID_STORAGETANK, THING_TYPE_UID_CIRCUIT, THING_TYPE_UID_SOLAR,
|
||||
THING_TYPE_UID_TEMPERATURESENSOR, THING_TYPE_UID_PUMP, THING_TYPE_UID_VALVE)
|
||||
.collect(Collectors.toSet()));
|
||||
|
||||
public static final Set<ThingTypeUID> SUPPORTED_BRIDGE_THING_TYPES_UIDS = Collections
|
||||
.singleton(THING_TYPE_UID_BRIDGE);
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* 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.vitotronic.internal;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.vitotronic.internal.discovery.VitotronicDiscoveryService;
|
||||
import org.openhab.binding.vitotronic.internal.handler.VitotronicBridgeHandler;
|
||||
import org.openhab.binding.vitotronic.internal.handler.VitotronicThingHandler;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.config.discovery.DiscoveryService;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
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;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link VitotronicHandlerFactory} is responsible for creating things and thing
|
||||
* handlers.
|
||||
*
|
||||
* @author Stefan Andres - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.vitotronic")
|
||||
public class VitotronicHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(VitotronicHandlerFactory.class);
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
logger.trace("Ask Handler for Supported Thing {}",
|
||||
VitotronicBindingConstants.SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID));
|
||||
return VitotronicBindingConstants.SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
logger.trace("Install Handler for Thing {}", thing.getUID());
|
||||
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (thingTypeUID.equals(VitotronicBindingConstants.THING_TYPE_UID_BRIDGE)) {
|
||||
VitotronicBridgeHandler handler = new VitotronicBridgeHandler((Bridge) thing);
|
||||
registerThingDiscovery(handler);
|
||||
return handler;
|
||||
}
|
||||
|
||||
if (supportsThingType(thingTypeUID)) {
|
||||
return new VitotronicThingHandler(thing);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private synchronized void registerThingDiscovery(VitotronicBridgeHandler bridgeHandler) {
|
||||
VitotronicDiscoveryService discoveryService = new VitotronicDiscoveryService(bridgeHandler);
|
||||
logger.trace("Try to register Discovery service on BundleID: {} Service: {}",
|
||||
bundleContext.getBundle().getBundleId(), DiscoveryService.class.getName());
|
||||
bundleContext.registerService(DiscoveryService.class.getName(), discoveryService, new Hashtable<>());
|
||||
discoveryService.activate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Thing createThing(ThingTypeUID thingTypeUID, Configuration configuration,
|
||||
@Nullable ThingUID thingUID, @Nullable ThingUID bridgeUID) {
|
||||
logger.trace("Create Thing for Type {}", thingUID);
|
||||
|
||||
String adapterID = (String) configuration.get(VitotronicBindingConstants.ADAPTER_ID);
|
||||
|
||||
if (VitotronicBindingConstants.THING_TYPE_UID_BRIDGE.equals(thingTypeUID)) {
|
||||
logger.trace("Create Bridge: {}", adapterID);
|
||||
return super.createThing(thingTypeUID, configuration, thingUID, null);
|
||||
} else {
|
||||
if (supportsThingType(thingTypeUID)) {
|
||||
logger.trace("Create Thing: {}", adapterID);
|
||||
return super.createThing(thingTypeUID, configuration, thingUID, bridgeUID);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* 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.vitotronic.internal.discovery;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.vitotronic.internal.VitotronicBindingConstants;
|
||||
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||
import org.openhab.core.config.discovery.DiscoveryService;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link VitotronicBridgeDiscovery} class handles the discovery of optolink adapter
|
||||
* with broadcasting and put it to inbox, if found.
|
||||
*
|
||||
*
|
||||
* @author Stefan Andres - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(service = DiscoveryService.class, immediate = true, configurationPid = "discovery.vitotronic")
|
||||
public class VitotronicBridgeDiscovery extends AbstractDiscoveryService {
|
||||
|
||||
private int adapterPort = 31113;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(VitotronicBridgeDiscovery.class);
|
||||
|
||||
public VitotronicBridgeDiscovery() throws IllegalArgumentException {
|
||||
super(VitotronicBindingConstants.SUPPORTED_BRIDGE_THING_TYPES_UIDS, 15, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startScan() {
|
||||
logger.trace("Start discovery of Vitotronic Optolink Adapter (VOP)");
|
||||
adapterPort = VitotronicBindingConstants.BROADCAST_PORT;
|
||||
scheduler.execute(searchRunnable);
|
||||
}
|
||||
|
||||
// Runnable for search adapter
|
||||
|
||||
private Runnable searchRunnable = () -> {
|
||||
logger.trace("Start adapter discovery ");
|
||||
logger.debug("Send broadcast message");
|
||||
try (DatagramSocket localSocket = new DatagramSocket()) {
|
||||
localSocket.setBroadcast(true);
|
||||
localSocket.setSoTimeout(10000); // Listen 10 seconds
|
||||
|
||||
String broadcastMsg = VitotronicBindingConstants.BROADCAST_MESSAGE + "*";
|
||||
byte[] sendData = broadcastMsg.getBytes();
|
||||
|
||||
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length,
|
||||
InetAddress.getByName("255.255.255.255"), adapterPort);
|
||||
localSocket.send(sendPacket);
|
||||
|
||||
byte[] receiveBuffer = new byte[255];
|
||||
|
||||
// Listen for answer
|
||||
|
||||
DatagramPacket receivePacket = new DatagramPacket(receiveBuffer, receiveBuffer.length);
|
||||
localSocket.receive(receivePacket);
|
||||
String receiveMessage = new String(receivePacket.getData()).trim();
|
||||
String receiveIP = receivePacket.getAddress().getHostAddress();
|
||||
int receivePort = receivePacket.getPort();
|
||||
logger.debug("Received Message: {} ", receiveMessage);
|
||||
logger.debug("Received from Host: {}", receiveIP);
|
||||
logger.debug("Received from Port: {}", receivePort);
|
||||
|
||||
if (receiveMessage.startsWith(VitotronicBindingConstants.BROADCAST_MESSAGE)) {
|
||||
// register bridge
|
||||
String adapterID = receiveMessage.substring(VitotronicBindingConstants.BROADCAST_MESSAGE.length())
|
||||
.toUpperCase();
|
||||
addAdapter(receiveIP, receivePort, adapterID);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.debug("No optolink adapter found!");
|
||||
}
|
||||
};
|
||||
|
||||
private void addAdapter(String remoteIP, int remotePort, String adapterID) {
|
||||
Map<String, Object> properties = new HashMap<>(3);
|
||||
properties.put(VitotronicBindingConstants.IP_ADDRESS, remoteIP);
|
||||
properties.put(VitotronicBindingConstants.PORT, remotePort);
|
||||
properties.put(VitotronicBindingConstants.ADAPTER_ID, adapterID);
|
||||
|
||||
ThingUID uid = new ThingUID(VitotronicBindingConstants.THING_TYPE_UID_BRIDGE, adapterID);
|
||||
thingDiscovered(DiscoveryResultBuilder.create(uid).withProperties(properties).withLabel(adapterID).build());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* 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.vitotronic.internal.discovery;
|
||||
|
||||
import static org.openhab.binding.vitotronic.internal.VitotronicBindingConstants.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.vitotronic.internal.VitotronicBindingConstants;
|
||||
import org.openhab.binding.vitotronic.internal.handler.VitotronicBridgeHandler;
|
||||
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||
import org.openhab.core.config.discovery.DiscoveryResult;
|
||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link VitotronicBridgeDiscovery} class handles the discovery of things.
|
||||
* with broadcasting and put it to inbox, if found.
|
||||
*
|
||||
*
|
||||
* @author Stefan Andres - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VitotronicDiscoveryService extends AbstractDiscoveryService {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(VitotronicDiscoveryService.class);
|
||||
|
||||
private VitotronicBridgeHandler vitotronicBridgeHandler;
|
||||
|
||||
public VitotronicDiscoveryService(VitotronicBridgeHandler vitotronicBridgeHandler) throws IllegalArgumentException {
|
||||
super(VitotronicBindingConstants.SUPPORTED_THING_TYPES_UIDS, 10, false);
|
||||
this.vitotronicBridgeHandler = vitotronicBridgeHandler;
|
||||
}
|
||||
|
||||
private void addThing(ThingUID bridgeUID, String thingType, String thingID) {
|
||||
logger.trace("Adding new Vitotronic thing: {}", thingID);
|
||||
ThingUID thingUID = null;
|
||||
switch (thingType) {
|
||||
case THING_ID_HEATING:
|
||||
thingUID = new ThingUID(THING_TYPE_UID_HEATING, bridgeUID, thingID);
|
||||
break;
|
||||
case THING_ID_GASBURNER:
|
||||
thingUID = new ThingUID(THING_TYPE_UID_GASBURNER, bridgeUID, thingID);
|
||||
break;
|
||||
case THING_ID_PELLETBURNER:
|
||||
thingUID = new ThingUID(THING_TYPE_UID_PELLETBURNER, bridgeUID, thingID);
|
||||
break;
|
||||
case THING_ID_STORAGETANK:
|
||||
thingUID = new ThingUID(THING_TYPE_UID_STORAGETANK, bridgeUID, thingID);
|
||||
break;
|
||||
case THING_ID_CIRCUIT:
|
||||
thingUID = new ThingUID(THING_TYPE_UID_CIRCUIT, bridgeUID, thingID);
|
||||
break;
|
||||
case THING_ID_SOLAR:
|
||||
thingUID = new ThingUID(THING_TYPE_UID_SOLAR, bridgeUID, thingID);
|
||||
break;
|
||||
}
|
||||
|
||||
if (thingUID != null) {
|
||||
logger.trace("Adding new Discovery thingType: {} bridgeType: {}", thingUID, bridgeUID);
|
||||
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withBridge(bridgeUID)
|
||||
.withLabel(thingID).build();
|
||||
logger.trace("call register: {} label: {}", discoveryResult.getBindingId(), discoveryResult.getLabel());
|
||||
thingDiscovered(discoveryResult);
|
||||
} else {
|
||||
logger.debug("Discovered Thing is unsupported: type '{}'", thingID);
|
||||
}
|
||||
}
|
||||
|
||||
public void addVitotronicThing(String thingType, String thingID) {
|
||||
addThing(vitotronicBridgeHandler.getThing().getUID(), thingType, thingID);
|
||||
}
|
||||
|
||||
public void activate() {
|
||||
vitotronicBridgeHandler.registerDiscoveryService(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deactivate() {
|
||||
vitotronicBridgeHandler.unregisterDiscoveryService();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startScan() {
|
||||
// Scan will be done by bridge
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,420 @@
|
||||
/**
|
||||
* 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.vitotronic.internal.handler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.openhab.binding.vitotronic.internal.VitotronicBindingConfiguration;
|
||||
import org.openhab.binding.vitotronic.internal.discovery.VitotronicDiscoveryService;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.binding.BaseBridgeHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
/**
|
||||
* The {@link VitotronicBridgeHandler} class handles the connection to the
|
||||
* optolink adapter.
|
||||
*
|
||||
* @author Stefan Andres - Initial contribution
|
||||
*/
|
||||
public class VitotronicBridgeHandler extends BaseBridgeHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(VitotronicBridgeHandler.class);
|
||||
|
||||
private String ipAddress;
|
||||
private int port;
|
||||
private int refreshInterval = 300;
|
||||
private Socket socket;
|
||||
private PrintStream out;
|
||||
private InputStream inStream;
|
||||
private boolean isConnect = false;
|
||||
private boolean isDiscover = false;
|
||||
|
||||
public VitotronicBridgeHandler(Bridge bridge) {
|
||||
super(bridge);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStatus(ThingStatus status) {
|
||||
super.updateStatus(status);
|
||||
updateThingHandlersStatus(status);
|
||||
}
|
||||
|
||||
public void updateStatus() {
|
||||
if (isConnect) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE);
|
||||
}
|
||||
}
|
||||
|
||||
// Managing Thing Discovery Service
|
||||
|
||||
private VitotronicDiscoveryService discoveryService = null;
|
||||
|
||||
public void registerDiscoveryService(VitotronicDiscoveryService discoveryService) {
|
||||
if (discoveryService == null) {
|
||||
throw new IllegalArgumentException("It's not allowed to pass a null ThingDiscoveryListener.");
|
||||
} else {
|
||||
this.discoveryService = discoveryService;
|
||||
logger.trace("register Discovery Service");
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterDiscoveryService() {
|
||||
discoveryService = null;
|
||||
logger.trace("unregister Discovery Service");
|
||||
}
|
||||
|
||||
// Handles Thing discovery
|
||||
|
||||
private void createThing(String thingType, String thingID) {
|
||||
logger.trace("Create thing Type='{}' id='{}'", thingType, thingID);
|
||||
if (discoveryService != null) {
|
||||
discoveryService.addVitotronicThing(thingType, thingID);
|
||||
}
|
||||
}
|
||||
|
||||
// Managing ThingHandler
|
||||
|
||||
private Map<String, VitotronicThingHandler> thingHandlerMap = new HashMap<>();
|
||||
|
||||
public void registerVitotronicThingListener(VitotronicThingHandler thingHandler) {
|
||||
if (thingHandler == null) {
|
||||
throw new IllegalArgumentException("It's not allowed to pass a null ThingHandler.");
|
||||
} else {
|
||||
String thingID = thingHandler.getThing().getUID().getId();
|
||||
if (thingHandlerMap.get(thingID) == null) {
|
||||
thingHandlerMap.put(thingID, thingHandler);
|
||||
logger.trace("register thingHandler for thing: {}", thingID);
|
||||
updateThingHandlerStatus(thingHandler, this.getStatus());
|
||||
sendSocketData("get " + thingID);
|
||||
} else {
|
||||
logger.trace("thingHandler for thing: '{}' already registered", thingID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterThingListener(VitotronicThingHandler thingHandler) {
|
||||
if (thingHandler != null) {
|
||||
String thingID = thingHandler.getThing().getUID().getId();
|
||||
if (thingHandlerMap.remove(thingID) == null) {
|
||||
logger.trace("thingHandler for thing: {} not registered", thingID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateThingHandlerStatus(VitotronicThingHandler thingHandler, ThingStatus status) {
|
||||
thingHandler.updateStatus(status);
|
||||
}
|
||||
|
||||
private void updateThingHandlersStatus(ThingStatus status) {
|
||||
for (Map.Entry<String, VitotronicThingHandler> entry : thingHandlerMap.entrySet()) {
|
||||
updateThingHandlerStatus(entry.getValue(), status);
|
||||
}
|
||||
}
|
||||
|
||||
// Background Runables
|
||||
|
||||
private ScheduledFuture<?> pollingJob;
|
||||
|
||||
private Runnable pollingRunnable = () -> {
|
||||
logger.trace("Polling job called");
|
||||
if (!isConnect) {
|
||||
startSocketReceiver();
|
||||
try {
|
||||
Thread.sleep(5000); // Wait for connection .
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (isConnect) {
|
||||
scanThings();
|
||||
refreshData();
|
||||
}
|
||||
};
|
||||
|
||||
private synchronized void startAutomaticRefresh() {
|
||||
if (pollingJob == null || pollingJob.isCancelled()) {
|
||||
pollingJob = scheduler.scheduleWithFixedDelay(pollingRunnable, 0, refreshInterval, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshData() {
|
||||
logger.trace("Job: refresh Data...");
|
||||
for (Map.Entry<String, VitotronicThingHandler> entry : thingHandlerMap.entrySet()) {
|
||||
String channelList = entry.getValue().getActiveChannelListAsString();
|
||||
String thingId = entry.getValue().getThing().getUID().getId();
|
||||
if (isConnect && (channelList.length() > 0)) {
|
||||
logger.trace("Get Data for '{}'", thingId);
|
||||
sendSocketData("get " + thingId + " " + channelList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Methods for ThingHandler
|
||||
|
||||
public void scanThings() {
|
||||
logger.trace("Job: Discover Things...");
|
||||
if (!isDiscover) {
|
||||
sendSocketData("list");
|
||||
isDiscover = true;
|
||||
}
|
||||
}
|
||||
|
||||
public ThingStatus getStatus() {
|
||||
return getThing().getStatus();
|
||||
}
|
||||
|
||||
public void updateChannel(String thingId, String channelId, String value) {
|
||||
sendSocketData("set " + thingId + ":" + channelId + " " + value);
|
||||
}
|
||||
|
||||
// internal Methods
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
// No channels - nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("Initializing Vitotronic bridge handler {}", getThing().getUID());
|
||||
updateStatus();
|
||||
VitotronicBindingConfiguration configuration = getConfigAs(VitotronicBindingConfiguration.class);
|
||||
ipAddress = configuration.ipAddress;
|
||||
port = configuration.port;
|
||||
refreshInterval = configuration.refreshInterval;
|
||||
|
||||
isDiscover = false;
|
||||
startAutomaticRefresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("Dispose Vitotronic bridge handler {}", getThing().getUID());
|
||||
|
||||
if (pollingJob != null && !pollingJob.isCancelled()) {
|
||||
pollingJob.cancel(true);
|
||||
pollingJob = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Connection to adapter
|
||||
|
||||
private void openSocket() {
|
||||
logger.trace("Try to open connection to Optolink Adapter {}:{}", ipAddress, port);
|
||||
|
||||
try {
|
||||
socket = new Socket(ipAddress, port);
|
||||
out = new PrintStream(socket.getOutputStream());
|
||||
inStream = socket.getInputStream();
|
||||
} catch (UnknownHostException e) {
|
||||
logger.error("Can't find Host: {}:{}", ipAddress, port);
|
||||
} catch (IOException e) {
|
||||
logger.debug("Error in communication to Host: {}:{}", ipAddress, port);
|
||||
logger.trace("Diagnostic: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
Runnable socketReceiverRunnable = () -> {
|
||||
logger.trace("Start Background Thread for recieving data from adapter");
|
||||
try {
|
||||
XMLReader xmlReader = XMLReaderFactory.createXMLReader();
|
||||
xmlReader.setContentHandler(new XmlHandler());
|
||||
logger.trace("Start Parser for optolink adapter");
|
||||
xmlReader.parse(new InputSource(inStream));
|
||||
|
||||
} catch (IOException e) {
|
||||
logger.trace("Connection error from optolink adapter");
|
||||
} catch (SAXException e) {
|
||||
logger.trace("XML Parser Error");
|
||||
|
||||
}
|
||||
updateStatus(ThingStatus.OFFLINE);
|
||||
isConnect = false;
|
||||
try {
|
||||
if (!socket.isClosed()) {
|
||||
socket.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
logger.trace("Connection to optolink adapter is died ... wait for restart");
|
||||
};
|
||||
|
||||
private void startSocketReceiver() {
|
||||
if (!isConnect) {
|
||||
openSocket();
|
||||
|
||||
Thread thread = new Thread(socketReceiverRunnable);
|
||||
thread.setName("VitotronicSocketThread");
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
||||
private void sendSocketData(String message) {
|
||||
try {
|
||||
logger.trace("Send Message {}", message);
|
||||
if (isConnect) {
|
||||
if (message.matches("^set.*REFRESH$")) {
|
||||
String[] msgParts = message.split(" ");
|
||||
String[] thingChannel = msgParts[1].split(":");
|
||||
message = "get " + thingChannel[0] + " " + thingChannel[1];
|
||||
}
|
||||
out.write((message + "\n").getBytes());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.error("Error in sending data to optolink adapter");
|
||||
logger.trace("Diagnostic: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Handles all data what received from optolink adapter
|
||||
|
||||
public class XmlHandler implements ContentHandler {
|
||||
boolean isData;
|
||||
boolean isDefine;
|
||||
boolean isThing;
|
||||
boolean isChannel;
|
||||
boolean isDescription;
|
||||
String thingID;
|
||||
String thingType;
|
||||
String channelID;
|
||||
String description;
|
||||
VitotronicThingHandler thingHandler;
|
||||
Set<String> channels = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String pName, Attributes attr) throws SAXException {
|
||||
try {
|
||||
switch (localName) {
|
||||
case "optolink":
|
||||
isConnect = true;
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
break;
|
||||
case "data":
|
||||
isDefine = false;
|
||||
break;
|
||||
case "define":
|
||||
isDefine = true;
|
||||
break;
|
||||
case "description":
|
||||
isDescription = true;
|
||||
break;
|
||||
case "thing":
|
||||
isThing = true;
|
||||
if (isDefine) {
|
||||
thingType = attr.getValue("type");
|
||||
}
|
||||
thingID = attr.getValue("id");
|
||||
channels.clear();
|
||||
thingHandler = thingHandlerMap.get(thingID);
|
||||
break;
|
||||
case "channel":
|
||||
isChannel = true;
|
||||
channelID = attr.getValue("id");
|
||||
if (isDefine) {
|
||||
channels.add(channelID);
|
||||
} else { // is data
|
||||
if (thingHandler != null) {
|
||||
logger.trace("Set Data for channel '{}' value '{}'", channelID, attr.getValue("value"));
|
||||
thingHandler.setChannelValue(channelID, attr.getValue("value"));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Error in parsing data");
|
||||
logger.trace("Diagnostic: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters(char[] ch, int start, int length) throws SAXException {
|
||||
if (isDescription) {
|
||||
description = new String(ch, start, length);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String qName) throws SAXException {
|
||||
switch (localName) {
|
||||
case "description":
|
||||
isDescription = false;
|
||||
break;
|
||||
case "thing":
|
||||
if (isDefine) {
|
||||
createThing(thingType, thingID);
|
||||
}
|
||||
isThing = false;
|
||||
thingHandler = null;
|
||||
break;
|
||||
case "channel":
|
||||
isChannel = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Unused function of xmlReader
|
||||
@Override
|
||||
public void endDocument() throws SAXException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ignorableWhitespace(char[] arg0, int arg1, int arg2) throws SAXException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processingInstruction(String arg0, String arg1) throws SAXException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDocumentLocator(Locator arg0) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void skippedEntity(String arg0) throws SAXException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startDocument() throws SAXException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startPrefixMapping(String arg0, String arg1) throws SAXException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endPrefixMapping(String prefix) throws SAXException {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/**
|
||||
* 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.vitotronic.internal.handler;
|
||||
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.Channel;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link VitotronicHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Stefan Andres - Initial contribution
|
||||
*/
|
||||
|
||||
public class VitotronicThingHandler extends BaseThingHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(VitotronicThingHandler.class);
|
||||
|
||||
private VitotronicBridgeHandler bridgeHandler;
|
||||
|
||||
public VitotronicThingHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
bridgeHandler = getBridgeHandler();
|
||||
logger.debug("Thing Handler for {} started", getThing().getUID().getId());
|
||||
registerVitotronicThingListener(bridgeHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("Thing Handler for {} stop", getThing().getUID().getId());
|
||||
unregisterVitotronicThingListener(bridgeHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
logger.trace("Handle command for channel '{}' command '{}'", channelUID.getId(), command);
|
||||
bridgeHandler.updateChannel(getThing().getUID().getId(), channelUID.getId(), command.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStatus(ThingStatus status) {
|
||||
super.updateStatus(status);
|
||||
}
|
||||
|
||||
private synchronized VitotronicBridgeHandler getBridgeHandler() {
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge == null) {
|
||||
logger.debug("Required bridge not defined for device {}.", getThing().getUID());
|
||||
return null;
|
||||
} else {
|
||||
return getBridgeHandler(bridge);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized VitotronicBridgeHandler getBridgeHandler(Bridge bridge) {
|
||||
VitotronicBridgeHandler bridgeHandler = null;
|
||||
|
||||
ThingHandler handler = bridge.getHandler();
|
||||
if (handler instanceof VitotronicBridgeHandler) {
|
||||
bridgeHandler = (VitotronicBridgeHandler) handler;
|
||||
} else {
|
||||
logger.debug("No available bridge handler found yet. Bridge: {} .", bridge.getUID());
|
||||
bridgeHandler = null;
|
||||
}
|
||||
return bridgeHandler;
|
||||
}
|
||||
|
||||
private void registerVitotronicThingListener(VitotronicBridgeHandler bridgeHandler) {
|
||||
if (bridgeHandler != null) {
|
||||
bridgeHandler.registerVitotronicThingListener(this);
|
||||
} else {
|
||||
logger.debug("Can't register {} at bridge bridgeHandler is null.", this.getThing().getUID());
|
||||
}
|
||||
}
|
||||
|
||||
private void unregisterVitotronicThingListener(VitotronicBridgeHandler bridgeHandler) {
|
||||
if (bridgeHandler != null) {
|
||||
bridgeHandler.unregisterThingListener(this);
|
||||
} else {
|
||||
logger.debug("Can't unregister {} at bridge bridgeHandler is null.", this.getThing().getUID());
|
||||
}
|
||||
}
|
||||
|
||||
public void setChannelValue(String channelId, String value) {
|
||||
Channel channel = getThing().getChannel(channelId);
|
||||
if (channel == null) {
|
||||
logger.trace("Cannel '{}:{}' not implemented", getThing().getUID().getId(), channelId);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.trace("Set {}:{}:{} = {}", getThing().getUID().getId(), channelId, channel.getAcceptedItemType(), value);
|
||||
switch (channel.getAcceptedItemType()) {
|
||||
case "Number":
|
||||
this.updateState(channelId, new DecimalType(value));
|
||||
break;
|
||||
case "String":
|
||||
this.updateState(channelId, new StringType(value));
|
||||
break;
|
||||
case "Switch":
|
||||
if (value.toUpperCase().contains("ON")) {
|
||||
this.updateState(channelId, OnOffType.ON);
|
||||
} else {
|
||||
this.updateState(channelId, OnOffType.OFF);
|
||||
}
|
||||
break;
|
||||
case "DateTime":
|
||||
this.updateState(channelId, new DateTimeType(value));
|
||||
break;
|
||||
default:
|
||||
logger.trace("Type '{}' for channel '{}' not implemented", channel.getAcceptedItemType(), channelId);
|
||||
}
|
||||
}
|
||||
|
||||
public String getActiveChannelListAsString() {
|
||||
String channelList = "";
|
||||
for (Channel channel : getThing().getChannels()) {
|
||||
if (isLinked(channel.getUID().getId())) {
|
||||
if (channelList.length() > 0) {
|
||||
channelList = channelList + "," + channel.getUID().getId();
|
||||
} else {
|
||||
channelList = channel.getUID().getId();
|
||||
}
|
||||
}
|
||||
}
|
||||
return channelList;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<binding:binding id="vitotronic" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
|
||||
|
||||
<name>Vitotronic Binding</name>
|
||||
<description>This is the binding for Vitotronic.</description>
|
||||
<author>Stefan Andres</author>
|
||||
|
||||
</binding:binding>
|
||||
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="vitotronic"
|
||||
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="bridge">
|
||||
<label>Bridge Vitotronic Optolink Adapter</label>
|
||||
<description>This bridge represents the Vitotronic Optolink adapter
|
||||
</description>
|
||||
|
||||
<config-description>
|
||||
<parameter name="ipAddress" type="text" required="true">
|
||||
<context>network-address</context>
|
||||
<label>IP Address</label>
|
||||
<description>The IP address of the Optolink adapter</description>
|
||||
</parameter>
|
||||
<parameter name="port" type="integer" required="false" min="1024" max="49151">
|
||||
<context>network-address</context>
|
||||
<label>Adapter Port</label>
|
||||
<description>Port of the LAN gateway</description>
|
||||
<default>31113</default>
|
||||
</parameter>
|
||||
<parameter name="adapterID" type="text" required="true">
|
||||
<label>Adapter ID</label>
|
||||
<description>The ID of the adapter.</description>
|
||||
</parameter>
|
||||
<parameter name="refreshInterval" type="integer" required="false" min="60" max="600">
|
||||
<context>refresh</context>
|
||||
<label>Refresh Interval</label>
|
||||
<description>Refreshtime in seconds.</description>
|
||||
<default>300</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</bridge-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,652 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="vitotronic"
|
||||
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 -->
|
||||
<thing-type id="heating">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Vitotronic</label>
|
||||
<description>Vitotronic core system</description>
|
||||
|
||||
<channels>
|
||||
<channel id="systemtime" typeId="systemtime"/>
|
||||
<channel id="outside_temp" typeId="outside_temp"/>
|
||||
<channel id="boiler_temp" typeId="boiler_temp"/>
|
||||
<channel id="malfunction" typeId="malfunction"/>
|
||||
</channels>
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="gasburner">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Gas Burner</label>
|
||||
<description>Condensing Technology Gas Burner</description>
|
||||
|
||||
<channels>
|
||||
<channel id="powerlevel" typeId="powerlevel">
|
||||
<description>Power of the gas burner</description>
|
||||
</channel>
|
||||
<channel id="exhaust_temp" typeId="exhaust_temp"/>
|
||||
</channels>
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="pelletburner">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Pellet Burner</label>
|
||||
<description>Pellet Fireplace, works for wood also </description>
|
||||
|
||||
<channels>
|
||||
<channel id="flame_temp" typeId="flame_temp"/>
|
||||
<channel id="airshutter_prim" typeId="airshutter_prim"/>
|
||||
<channel id="airshutter_sec" typeId="airshutter_sec"/>
|
||||
<channel id="lambdasensor" typeId="lambdasensor"/>
|
||||
<channel id="fanspeed" typeId="fanspeed"/>
|
||||
<channel id="fanspeed_target" typeId="fanspeed_target"/>
|
||||
<channel id="error" typeId="error"/>
|
||||
<channel id="starts" typeId="starts"/>
|
||||
<channel id="ontime" typeId="ontime"/>
|
||||
<channel id="consumedpellets" typeId="consumedpellets"/>
|
||||
<channel id="powerlevel" typeId="powerlevel">
|
||||
<description>Power of the pellet burner</description>
|
||||
</channel>
|
||||
<channel id="flowuprating" typeId="flowuprating"/>
|
||||
</channels>
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="oilburner">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Oil Burner</label>
|
||||
<description>Oil Fireplace</description>
|
||||
|
||||
<channels>
|
||||
<channel id="powerlevel" typeId="powerlevel">
|
||||
<description>Power of the oil burner</description>
|
||||
</channel>
|
||||
<channel id="actualpower" typeId="actualpower"/>
|
||||
<channel id="error" typeId="error"/>
|
||||
<channel id="starts" typeId="starts"/>
|
||||
<channel id="ontimelevel1" typeId="ontimelevel1"/>
|
||||
<channel id="ontimelevel2" typeId="ontimelevel2"/>
|
||||
<channel id="consumedoil" typeId="consumedoil"/>
|
||||
</channels>
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="storagetank">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Hotwater Storagetank</label>
|
||||
<description>Storage Tank, stores heat in a water tank on 3 levels: bottom, middle, top=hot water</description>
|
||||
|
||||
<channels>
|
||||
<channel id="hotwater_temp" typeId="hotwater_temp"/>
|
||||
<channel id="hotwater_temp_setpoint" typeId="hotwater_temp_setpoint"/>
|
||||
<channel id="middle_temp" typeId="middle_temp"/>
|
||||
<channel id="bottom_temp" typeId="bottom_temp"/>
|
||||
<channel id="circuitpump" typeId="circuitpump"/>
|
||||
</channels>
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="circuit">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Circuit</label>
|
||||
<description>Heating circuit controls the flow of heating water between the heating system and the radiators in the
|
||||
rooms</description>
|
||||
|
||||
<channels>
|
||||
<channel id="flowtemperature" typeId="flow_temp"/>
|
||||
<channel id="pump" typeId="pump"/>
|
||||
<channel id="operationmode" typeId="operationmode"/>
|
||||
<channel id="savemode" typeId="savemode"/>
|
||||
<channel id="partymode" typeId="partymode"/>
|
||||
<channel id="party_temp_setpoint" typeId="party_temp_setpoint"/>
|
||||
<channel id="room_temp" typeId="room_temp"/>
|
||||
<channel id="room_temp_setpoint" typeId="room_temp_setpoint"/>
|
||||
<channel id="save_temp_setpoint" typeId="save_temp_setpoint"/>
|
||||
<channel id="gradient" typeId="gradient"/>
|
||||
<channel id="niveau" typeId="niveau"/>
|
||||
<channel id="timer_MO" typeId="timer">
|
||||
<label>Monday Heating Timer</label>
|
||||
<description>On/Off timer for Monday. Up to 4 timers can be set</description>
|
||||
<properties>
|
||||
<property name="address">3000</property>
|
||||
<property name="type">timer</property>
|
||||
<property name="divider">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
<channel id="timer_TU" typeId="timer">
|
||||
<label>Tuesday Heating Timer</label>
|
||||
<description>On/Off timer for Tuesday. Up to 4 timers can be set</description>
|
||||
<properties>
|
||||
<property name="address">3008</property>
|
||||
<property name="type">timer</property>
|
||||
<property name="divider">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
<channel id="timer_WE" typeId="timer">
|
||||
<label>Wednesday Heating Timer</label>
|
||||
<description>On/Off timer for Wednesday. Up to 4 timers can be set</description>
|
||||
<properties>
|
||||
<property name="address">3010</property>
|
||||
<property name="type">timer</property>
|
||||
<property name="divider">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
<channel id="timer_TH" typeId="timer">
|
||||
<label>Thursday Heating Timer</label>
|
||||
<description>On/Off timer for Thursday. Up to 4 timers can be set</description>
|
||||
<properties>
|
||||
<property name="address">3018</property>
|
||||
<property name="type">timer</property>
|
||||
<property name="divider">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
<channel id="timer_FR" typeId="timer">
|
||||
<label>Friday Heating Timer</label>
|
||||
<description>On/Off timer for Friday. Up to 4 timers can be set</description>
|
||||
<properties>
|
||||
<property name="address">3020</property>
|
||||
<property name="type">timer</property>
|
||||
<property name="divider">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
<channel id="timer_SA" typeId="timer">
|
||||
<label>Saturday Heating Timer</label>
|
||||
<description>On/Off timer for Saturday. Up to 4 timers can be set</description>
|
||||
<properties>
|
||||
<property name="address">3028</property>
|
||||
<property name="type">timer</property>
|
||||
<property name="divider">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
<channel id="timer_SU" typeId="timer">
|
||||
<label>Sunday Heating Timer</label>
|
||||
<description>On/Off timer for Sunday. Up to 4 timers can be set</description>
|
||||
<properties>
|
||||
<property name="address">3030</property>
|
||||
<property name="type">timer</property>
|
||||
<property name="divider">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
<channel id="timer_ww_MO" typeId="timer">
|
||||
<label>Monday Hot Water Timer</label>
|
||||
<description>On/Off timer for Monday. Up to 4 timers can be set</description>
|
||||
<properties>
|
||||
<property name="address">2100</property>
|
||||
<property name="type">timer</property>
|
||||
<property name="divider">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
<channel id="timer_ww_TU" typeId="timer">
|
||||
<label>Tuesday Hot Water Timer</label>
|
||||
<description>On/Off timer for Tuesday. Up to 4 timers can be set</description>
|
||||
<properties>
|
||||
<property name="address">2108</property>
|
||||
<property name="type">timer</property>
|
||||
<property name="divider">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
<channel id="timer_ww_WE" typeId="timer">
|
||||
<label>Wednesday Hot Water Timer</label>
|
||||
<description>On/Off timer for Wednesday. Up to 4 timers can be set</description>
|
||||
<properties>
|
||||
<property name="address">2110</property>
|
||||
<property name="type">timer</property>
|
||||
<property name="divider">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
<channel id="timer_ww_TH" typeId="timer">
|
||||
<label>Thursday Hot Water Timer</label>
|
||||
<description>On/Off timer for Thursday. Up to 4 timers can be set</description>
|
||||
<properties>
|
||||
<property name="address">2118</property>
|
||||
<property name="type">timer</property>
|
||||
<property name="divider">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
<channel id="timer_ww_FR" typeId="timer">
|
||||
<label>Friday Hot Water Timer</label>
|
||||
<description>On/Off timer for Friday. Up to 4 timers can be set</description>
|
||||
<properties>
|
||||
<property name="address">2120</property>
|
||||
<property name="type">timer</property>
|
||||
<property name="divider">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
<channel id="timer_ww_SA" typeId="timer">
|
||||
<label>Saturday Hot Water Timer</label>
|
||||
<description>On/Off timer for Saturday. Up to 4 timers can be set</description>
|
||||
<properties>
|
||||
<property name="address">2128</property>
|
||||
<property name="type">timer</property>
|
||||
<property name="divider">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
<channel id="timer_ww_SU" typeId="timer">
|
||||
<label>Sunday Hot Water Timer</label>
|
||||
<description>On/Off timer for Sunday. Up to 4 timers can be set</description>
|
||||
<properties>
|
||||
<property name="address">2130</property>
|
||||
<property name="type">timer</property>
|
||||
<property name="divider">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
</channels>
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="solar">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Solar Heating</label>
|
||||
<description>Solar water heating (SWH): Convert sunlight into energy for water heating</description>
|
||||
|
||||
<channels>
|
||||
<channel id="collector_temp" typeId="collector_temp"/>
|
||||
<channel id="storagetank_temp" typeId="storagetank_temp"/>
|
||||
<channel id="bufferload" typeId="bufferload"/>
|
||||
<channel id="loadsuppression" typeId="loadsuppression"/>
|
||||
<channel id="ontime" typeId="ontime"/>
|
||||
<channel id="producedheat" typeId="producedheat"/>
|
||||
</channels>
|
||||
</thing-type>
|
||||
|
||||
<!-- Things for single use -->
|
||||
|
||||
<thing-type id="temperaturesensor">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>Temperature Sensor</label>
|
||||
<description>Single temperature sensor</description>
|
||||
<channels>
|
||||
<channel id="value" typeId="temperature"/>
|
||||
</channels>
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="pump">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>Pump</label>
|
||||
<description>Single pump</description>
|
||||
<channels>
|
||||
<channel id="value" typeId="pump"/>
|
||||
</channels>
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="valve">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>Valve</label>
|
||||
<description>Single valve</description>
|
||||
<channels>
|
||||
<channel id="valve" typeId="valve"/>
|
||||
</channels>
|
||||
</thing-type>
|
||||
|
||||
<!-- Channel Type -->
|
||||
|
||||
<!-- Channel Types for heating -->
|
||||
|
||||
<channel-type id="systemtime">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>DateTime of the Heating System</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="outside_temp">
|
||||
<item-type>Number</item-type>
|
||||
<label>Outside Temperature</label>
|
||||
<description>Outside temperature sensor</description>
|
||||
<category>Temperature</category>
|
||||
<state pattern="%.1f °C" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="boiler_temp">
|
||||
<item-type>Number</item-type>
|
||||
<label>Boiler</label>
|
||||
<description>Temperature sensor of boiler (fireplace)</description>
|
||||
<category>Temperature</category>
|
||||
<state pattern="%.1f °C" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="malfunction">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Heating Malfunction</label>
|
||||
<description>General Malfunction state of the heating</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<!-- Channel Types for Gas Burner -->
|
||||
|
||||
<channel-type id="powerlevel">
|
||||
<item-type>Number</item-type>
|
||||
<label>Power Level</label>
|
||||
<state pattern="%d %%" readOnly="true" max="100" min="0"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="exhaust_temp">
|
||||
<item-type>Number</item-type>
|
||||
<label>Exhaust Temperature</label>
|
||||
<description>Actual temperature of the exhaust</description>
|
||||
<category>Temperature</category>
|
||||
<state pattern="%.1f °C" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<!-- Channel Types for Pellet Burner -->
|
||||
|
||||
<channel-type id="flame_temp">
|
||||
<item-type>Number</item-type>
|
||||
<label>Flame</label>
|
||||
<description>Temperature of flame</description>
|
||||
<category>Temperature</category>
|
||||
<state pattern="%.1f °C" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="lambdasensor" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Lambdasensor (O2)</label>
|
||||
<description>Oxygen content of the exhaust air</description>
|
||||
<state pattern="%.2f %%" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="airshutter_prim" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Primary Airshutter</label>
|
||||
<description>Position of the primary air shutter</description>
|
||||
<state pattern="%d %%" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="airshutter_sec" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Secondary Airshutter</label>
|
||||
<description>Position of the secondary air shutter</description>
|
||||
<state pattern="%d %%" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="starts" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Starts</label>
|
||||
<description>Count of starts</description>
|
||||
<state pattern="%d" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="fanspeed">
|
||||
<item-type>Number</item-type>
|
||||
<label>Fan Speed</label>
|
||||
<description>Fan Speed in rpm</description>
|
||||
<state pattern="%d rpm" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="fanspeed_target" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Target Fan Speed</label>
|
||||
<description>Fan Speed in rpm</description>
|
||||
<state pattern="%d rpm" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="ontime" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>On Time</label>
|
||||
<description>Ontime in hours</description>
|
||||
<state pattern="%.2f h" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="consumedpellets" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Consumed Pellets</label>
|
||||
<description>Consumed Pellets since start of heating in tons</description>
|
||||
<state pattern="%.2f t" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="flowuprating" advanced="true">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Pump</label>
|
||||
<description>Pump state</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<!-- Channel Types for Oil Burner -->
|
||||
|
||||
<channel-type id="actualpower">
|
||||
<item-type>Number</item-type>
|
||||
<label>Actual Power Level</label>
|
||||
<description>Actual power of the burner</description>
|
||||
<state pattern="%d %%" readOnly="true" max="100" min="0"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="error" advanced="true">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Errors</label>
|
||||
<description>True, if errors for the burner exists</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="ontimelevel1" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>On Time Level 1</label>
|
||||
<description>Ontime in hours</description>
|
||||
<state pattern="%.2f h" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="ontimelevel2" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>On Time Level 2</label>
|
||||
<description>Ontime in hours</description>
|
||||
<state pattern="%.2f h" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="consumedoil" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Consumed Oil</label>
|
||||
<description>Consumed Oil since start of heating in Liter</description>
|
||||
<state pattern="%f l" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<!-- Channel Types for storagetank -->
|
||||
|
||||
<channel-type id="circuitpump">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Circuit Pump</label>
|
||||
<description>Circuit pump state</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="middle_temp">
|
||||
<item-type>Number</item-type>
|
||||
<label>Middle</label>
|
||||
<description>Temperature sensor in the middle of the storage tank</description>
|
||||
<category>Temperature</category>
|
||||
<state pattern="%.1f °C" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="bottom_temp">
|
||||
<item-type>Number</item-type>
|
||||
<label>Bottom</label>
|
||||
<description>Temperature sensor at the bottom of the storage tank</description>
|
||||
<category>Temperature</category>
|
||||
<state pattern="%.1f °C" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="hotwater_temp">
|
||||
<item-type>Number</item-type>
|
||||
<label>Hot Water</label>
|
||||
<description>Temperature sensor of the hot water</description>
|
||||
<category>Temperature</category>
|
||||
<state pattern="%.1f °C" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="hotwater_temp_setpoint">
|
||||
<item-type>Number</item-type>
|
||||
<label>Hotwater TempSet</label>
|
||||
<description>Set the hot water temperature</description>
|
||||
<category>Temperature</category>
|
||||
<state pattern="%d °C" readOnly="false" max="60" min="30" step="1"/>
|
||||
</channel-type>
|
||||
|
||||
<!-- Channel Types for circuit -->
|
||||
|
||||
<channel-type id="flow_temp">
|
||||
<item-type>Number</item-type>
|
||||
<label>Flow</label>
|
||||
<description>Temperature sensor of the circuit flow</description>
|
||||
<category>Temperature</category>
|
||||
<state pattern="%.1f °C" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="pump">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Pump</label>
|
||||
<description>Pump state</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="operationmode">
|
||||
<item-type>Number</item-type>
|
||||
<label>Operationmode</label>
|
||||
<description>Operationmode</description>
|
||||
<state pattern="%d" readOnly="false" max="4" min="0" step="1"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="partymode">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Partymode</label>
|
||||
<description>Partymode on/off</description>
|
||||
<state readOnly="false"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="savemode">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Savemode</label>
|
||||
<description>Savemode on/off</description>
|
||||
<state readOnly="false"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="party_temp_setpoint" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Partymode TempSet</label>
|
||||
<description>Target temperature of party mode</description>
|
||||
<category>Temperature</category>
|
||||
<state min="6" step="1" pattern="%.1f °C" readOnly="false"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="save_temp_setpoint" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Savemode TempSet</label>
|
||||
<description>Target temperature of save mode</description>
|
||||
<category>Temperature</category>
|
||||
<state min="6" step="1" pattern="%.1f °C" readOnly="false"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="room_temp" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Room Temp</label>
|
||||
<description>Temperature of rooms</description>
|
||||
<category>Temperature</category>
|
||||
<state pattern="%.1f °C" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="room_temp_setpoint">
|
||||
<item-type>Number</item-type>
|
||||
<label>Room TempSet</label>
|
||||
<description>Target temperature of rooms</description>
|
||||
<category>Temperature</category>
|
||||
<state min="6" step="1" pattern="%.1f °C" readOnly="false"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="gradient" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Gradient</label>
|
||||
<description>The gradient relative to outside temperature</description>
|
||||
<state pattern="%.1f" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="niveau" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Niveau</label>
|
||||
<description>The niveau relative to outside temperature</description>
|
||||
<state pattern="%.1f" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="timer" advanced="true">
|
||||
<item-type>String</item-type>
|
||||
<label>Timer for Heating or Warm Water</label>
|
||||
<state pattern="%s" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<!-- Channel Type for solar -->
|
||||
|
||||
<channel-type id="collector_temp">
|
||||
<item-type>Number</item-type>
|
||||
<label>Collector</label>
|
||||
<description>Actual temperature of the collector</description>
|
||||
<category>Temperature</category>
|
||||
<state pattern="%.1f °C" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="storagetank_temp">
|
||||
<item-type>Number</item-type>
|
||||
<label>Storagetank</label>
|
||||
<description>Actual temperature of the storage tank (solar sensor)</description>
|
||||
<category>Temperature</category>
|
||||
<state pattern="%.1f °C" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="bufferload">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Buffer Load Pump</label>
|
||||
<description>State of the pump (on/off)</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="loadsuppression" advanced="true">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Load Suppression</label>
|
||||
<description>State of the load suppression (on/off)</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="producedheat" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Produced Heat</label>
|
||||
<description>Produced heat since starting solar system</description>
|
||||
<state pattern="%.2f kWh" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<!-- single types -->
|
||||
|
||||
<channel-type id="temperature">
|
||||
<item-type>Number</item-type>
|
||||
<label>Temperature</label>
|
||||
<description>Generic temperature sensor</description>
|
||||
<category>Temperature</category>
|
||||
<state pattern="%.1f °C" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="valve">
|
||||
<item-type>Number</item-type>
|
||||
<label>Valve</label>
|
||||
<description>Value of a generic valve</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
||||
Reference in New Issue
Block a user