added migrated 2.x add-ons
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.digitalstrom-${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-digitalstrom" description="digitalSTROM Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<feature>openhab-transport-mdns</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.digitalstrom/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
||||
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.scene.constants.SceneTypes;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link DigitalSTROMBindingConstants} class defines common constants, which are
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Mathias Siegele - Initial contribution
|
||||
*/
|
||||
public class DigitalSTROMBindingConstants {
|
||||
|
||||
public static final String BINDING_ID = "digitalstrom";
|
||||
|
||||
// List of all Thing Type IDs
|
||||
public static final String THING_TYPE_ID_DSS_BRIDGE = "dssBridge";
|
||||
public static final String THING_TYPE_ID_ZONE_TEMERATURE_CONTROL = "zoneTemperatureControl";
|
||||
|
||||
// List of all Thing Type UIDs
|
||||
public static final ThingTypeUID THING_TYPE_DSS_BRIDGE = new ThingTypeUID(BINDING_ID, THING_TYPE_ID_DSS_BRIDGE);
|
||||
public static final ThingTypeUID THING_TYPE_ZONE_TEMERATURE_CONTROL = new ThingTypeUID(BINDING_ID,
|
||||
THING_TYPE_ID_ZONE_TEMERATURE_CONTROL);
|
||||
|
||||
public static final ThingTypeUID THING_TYPE_APP_SCENE = new ThingTypeUID(BINDING_ID, SceneTypes.APARTMENT_SCENE);
|
||||
public static final ThingTypeUID THING_TYPE_ZONE_SCENE = new ThingTypeUID(BINDING_ID, SceneTypes.ZONE_SCENE);
|
||||
public static final ThingTypeUID THING_TYPE_GROUP_SCENE = new ThingTypeUID(BINDING_ID, SceneTypes.GROUP_SCENE);
|
||||
public static final ThingTypeUID THING_TYPE_NAMED_SCENE = new ThingTypeUID(BINDING_ID, SceneTypes.NAMED_SCENE);
|
||||
|
||||
// scene
|
||||
public static final String CHANNEL_ID_SCENE = "scene";
|
||||
|
||||
// sensor
|
||||
public static final String CHANNEL_ID_TOTAL_ACTIVE_POWER = "totalActivePower";
|
||||
public static final String CHANNEL_ID_TOTAL_ELECTRIC_METER = "totalElectricMeter";
|
||||
|
||||
// options combined switches
|
||||
public static final String OPTION_COMBINED_BOTH_OFF = "0";
|
||||
public static final String OPTION_COMBINED_BOTH_ON = "200";
|
||||
public static final String OPTION_COMBINED_FIRST_ON = "90";
|
||||
public static final String OPTION_COMBINED_SECOND_ON = "130";
|
||||
|
||||
/* config URIs */
|
||||
public static final String DEVICE_CONFIG = "binding:digitalstrom:device";
|
||||
public static final String GRAY_DEVICE_CONFIG = "binding:digitalstrom:grayDevice";
|
||||
public static final String DSS_BRIDE_CONFIG = "binding:digitalstrom:dssBridge";
|
||||
|
||||
/* Bridge config properties */
|
||||
|
||||
public static final String HOST = "dSSAddress";
|
||||
public static final String USER_NAME = "userName";
|
||||
public static final String PASSWORD = "password";
|
||||
public static final String APPLICATION_TOKEN = "applicationToken";
|
||||
public static final String DS_ID = "dSID";
|
||||
public static final String DS_NAME = "dS-Installation-Name";
|
||||
public static final String SENSOR_DATA_UPDATE_INTERVAL = "sensorDataUpdateInterval";
|
||||
public static final String TOTAL_POWER_UPDATE_INTERVAL = "totalPowerUpdateInterval";
|
||||
public static final String DEFAULT_TRASH_DEVICE_DELETE_TIME_KEY = "defaultTrashBinDeleteTime";
|
||||
public static final String SENSOR_WAIT_TIME = "sensorWaitTime";
|
||||
|
||||
public static final String SERVER_CERT = "serverCert";
|
||||
|
||||
/* Device info properties */
|
||||
|
||||
public static final String DEVICE_UID = "dSUID";
|
||||
public static final String DEVICE_NAME = "deviceName";
|
||||
public static final String DEVICE_DSID = "dSID";
|
||||
public static final String DEVICE_HW_INFO = "hwInfo";
|
||||
public static final String DEVICE_ZONE_ID = "zoneID";
|
||||
public static final String DEVICE_GROUPS = "groups";
|
||||
public static final String DEVICE_OUTPUT_MODE = "outputmode";
|
||||
public static final String DEVICE_FUNCTIONAL_COLOR_GROUP = "funcColorGroup";
|
||||
public static final String DEVICE_METER_ID = "meterDSID";
|
||||
public static final String DEVICE_BINARAY_INPUTS = "binarayInputs";
|
||||
|
||||
// Device properties scene
|
||||
public static final String DEVICE_SCENE = "scene"; // + number of scene
|
||||
|
||||
// Sensor data channel properties
|
||||
public static final String ACTIVE_POWER_REFRESH_PRIORITY = "activePowerRefreshPriority";
|
||||
public static final String ELECTRIC_METER_REFRESH_PRIORITY = "electricMeterRefreshPriority";
|
||||
public static final String OUTPUT_CURRENT_REFRESH_PRIORITY = "outputCurrentRefreshPriority";
|
||||
|
||||
/* Scene config */
|
||||
public static final String ZONE_ID = "zoneID";
|
||||
public static final String GROUP_ID = "groupID";
|
||||
public static final String SCENE_ID = "sceneID";
|
||||
|
||||
// circuit properties
|
||||
public static final String HW_NAME = "hwName";
|
||||
public static final String HW_VERSION = "hwVersion";
|
||||
public static final String SW_VERSION = "swVersion";
|
||||
public static final String API_VERSION = "apiVersion";
|
||||
public static final String DSP_SW_VERSION = "armSwVersion";
|
||||
public static final String ARM_SW_VERSION = "dspSwVersion";
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal;
|
||||
|
||||
import static org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.openhab.binding.digitalstrom.internal.discovery.DiscoveryServiceManager;
|
||||
import org.openhab.binding.digitalstrom.internal.handler.BridgeHandler;
|
||||
import org.openhab.binding.digitalstrom.internal.handler.CircuitHandler;
|
||||
import org.openhab.binding.digitalstrom.internal.handler.DeviceHandler;
|
||||
import org.openhab.binding.digitalstrom.internal.handler.SceneHandler;
|
||||
import org.openhab.binding.digitalstrom.internal.handler.ZoneTemperatureControlHandler;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.ConnectionManager;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.impl.ConnectionManagerImpl;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.constants.JSONApiResponseKeysEnum;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
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 DigitalSTROMHandlerFactory} is responsible for creating things and thing
|
||||
* handlers.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Mathias Siegele - Initial contribution
|
||||
*/
|
||||
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.digitalstrom")
|
||||
public class DigitalSTROMHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(DigitalSTROMHandlerFactory.class);
|
||||
private final Map<String, DiscoveryServiceManager> discoveryServiceManagers = new HashMap<>();
|
||||
|
||||
private Map<ThingUID, BridgeHandler> bridgeHandlers;
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return BridgeHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)
|
||||
|| SceneHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)
|
||||
|| DeviceHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)
|
||||
|| ZoneTemperatureControlHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)
|
||||
|| CircuitHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Thing createThing(ThingTypeUID thingTypeUID, Configuration configuration, ThingUID thingUID,
|
||||
ThingUID bridgeUID) {
|
||||
if (BridgeHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
|
||||
ThingUID dSSUID = getBridgeThingUID(thingTypeUID, thingUID, configuration);
|
||||
if (dSSUID != null) {
|
||||
return super.createThing(thingTypeUID, configuration, dSSUID, null);
|
||||
} else {
|
||||
logger.error("Can't generate thing UID for thing type {}"
|
||||
+ ", because digitalSTROM-Server is not reachable. Please check these points:\n"
|
||||
+ "Are the server address and portnumber correct?\n" + "Is the server turned on?\n"
|
||||
+ "Is the network configured correctly?", thingTypeUID);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (DeviceHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
|
||||
ThingUID dsDeviceUID = getDeviceUID(thingTypeUID, thingUID, configuration, bridgeUID);
|
||||
return super.createThing(thingTypeUID, configuration, dsDeviceUID, bridgeUID);
|
||||
}
|
||||
|
||||
if (CircuitHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
|
||||
ThingUID dsDeviceUID = getDeviceUID(thingTypeUID, thingUID, configuration, bridgeUID);
|
||||
return super.createThing(thingTypeUID, configuration, dsDeviceUID, bridgeUID);
|
||||
}
|
||||
|
||||
if (ZoneTemperatureControlHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
|
||||
ThingUID zoneTempConUID = getZoneTemperatureControlUID(thingTypeUID, thingUID, configuration, bridgeUID);
|
||||
return super.createThing(thingTypeUID, configuration, zoneTempConUID, bridgeUID);
|
||||
}
|
||||
|
||||
if (SceneHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
|
||||
ThingUID dsSceneUID = getSceneUID(thingTypeUID, thingUID, configuration, bridgeUID);
|
||||
return super.createThing(thingTypeUID, configuration, dsSceneUID, bridgeUID);
|
||||
}
|
||||
throw new IllegalArgumentException(
|
||||
"The thing type " + thingTypeUID + " is not supported by the digitalSTROM binding.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (BridgeHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
|
||||
BridgeHandler handler = new BridgeHandler((Bridge) thing);
|
||||
if (bridgeHandlers == null) {
|
||||
bridgeHandlers = new HashMap<>();
|
||||
}
|
||||
bridgeHandlers.put(thing.getUID(), handler);
|
||||
DiscoveryServiceManager discoveryServiceManager = new DiscoveryServiceManager(handler);
|
||||
discoveryServiceManager.registerDiscoveryServices(bundleContext);
|
||||
discoveryServiceManagers.put(handler.getThing().getUID().getAsString(), discoveryServiceManager);
|
||||
return handler;
|
||||
}
|
||||
|
||||
if (DeviceHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
|
||||
return new DeviceHandler(thing);
|
||||
}
|
||||
|
||||
if (CircuitHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
|
||||
return new CircuitHandler(thing);
|
||||
}
|
||||
|
||||
if (ZoneTemperatureControlHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
|
||||
return new ZoneTemperatureControlHandler(thing);
|
||||
}
|
||||
|
||||
if (SceneHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
|
||||
return new SceneHandler(thing);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ThingUID getDeviceUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Configuration configuration,
|
||||
ThingUID bridgeUID) {
|
||||
if (thingUID == null && StringUtils.isNotBlank((String) configuration.get(DEVICE_DSID))) {
|
||||
return new ThingUID(thingTypeUID, bridgeUID, configuration.get(DEVICE_DSID).toString());
|
||||
}
|
||||
return thingUID;
|
||||
}
|
||||
|
||||
private ThingUID getZoneTemperatureControlUID(ThingTypeUID thingTypeUID, ThingUID thingUID,
|
||||
Configuration configuration, ThingUID bridgeUID) {
|
||||
if (thingUID == null) {
|
||||
Integer zoneID = ZoneTemperatureControlHandler.getZoneID(configuration, bridgeHandlers.get(bridgeUID));
|
||||
if (zoneID > ZoneTemperatureControlHandler.ZONE_ID_NOT_EXISTS) {
|
||||
return new ThingUID(thingTypeUID, bridgeUID, zoneID.toString());
|
||||
} else {
|
||||
switch (zoneID) {
|
||||
case ZoneTemperatureControlHandler.ZONE_ID_NOT_EXISTS:
|
||||
logger.error("Configured zone '{}' does not exist, please check your configuration.",
|
||||
configuration.get(DigitalSTROMBindingConstants.ZONE_ID));
|
||||
break;
|
||||
case ZoneTemperatureControlHandler.ZONE_ID_NOT_SET:
|
||||
logger.error("ZoneID is missing at your configuration.");
|
||||
break;
|
||||
case ZoneTemperatureControlHandler.BRIDGE_IS_NULL:
|
||||
logger.error("Bridge is missing, can not check the zoneID.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return thingUID;
|
||||
}
|
||||
|
||||
private ThingUID getSceneUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Configuration configuration,
|
||||
ThingUID bridgeUID) {
|
||||
if (thingUID != null) {
|
||||
return thingUID;
|
||||
}
|
||||
String sceneID = SceneHandler.getSceneID(configuration, bridgeHandlers.get(bridgeUID));
|
||||
switch (sceneID) {
|
||||
case SceneHandler.SCENE_WRONG:
|
||||
logger.error(
|
||||
"Configured scene '{}' does not exist or can not be used, please check your configuration.",
|
||||
configuration.get(DigitalSTROMBindingConstants.SCENE_ID));
|
||||
break;
|
||||
case SceneHandler.ZONE_WRONG:
|
||||
logger.error("Configured zone '{}' does not exist, please check your configuration.",
|
||||
configuration.get(DigitalSTROMBindingConstants.ZONE_ID));
|
||||
break;
|
||||
case SceneHandler.GROUP_WRONG:
|
||||
logger.error("Configured group '{}' does not exist, please check your configuration.",
|
||||
configuration.get(DigitalSTROMBindingConstants.GROUP_ID));
|
||||
break;
|
||||
case SceneHandler.NO_STRUC_MAN:
|
||||
logger.error("Waiting for building digitalSTROM model.");
|
||||
break;
|
||||
case SceneHandler.NO_SCENE:
|
||||
logger.error("No Scene-ID is set!");
|
||||
break;
|
||||
case SceneHandler.NO_BRIDGE:
|
||||
logger.error("No related bridge found!");
|
||||
default:
|
||||
return new ThingUID(thingTypeUID, bridgeUID, sceneID);
|
||||
}
|
||||
return thingUID;
|
||||
}
|
||||
|
||||
private ThingUID getBridgeThingUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Configuration configuration) {
|
||||
if (thingUID != null) {
|
||||
return thingUID;
|
||||
}
|
||||
String dSID;
|
||||
if (StringUtils.isBlank((String) configuration.get(DS_ID))) {
|
||||
dSID = getDSSid(configuration);
|
||||
if (dSID != null) {
|
||||
configuration.put(DS_ID, dSID);
|
||||
}
|
||||
} else {
|
||||
dSID = configuration.get(DS_ID).toString();
|
||||
}
|
||||
if (dSID != null) {
|
||||
return new ThingUID(thingTypeUID, dSID);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String getDSSid(Configuration configuration) {
|
||||
String dSID = null;
|
||||
if (StringUtils.isNotBlank((String) configuration.get(HOST))) {
|
||||
String host = configuration.get(HOST).toString();
|
||||
String applicationToken = null;
|
||||
String user = null;
|
||||
String pw = null;
|
||||
|
||||
if (StringUtils.isNotBlank((String) configuration.get(APPLICATION_TOKEN))) {
|
||||
applicationToken = configuration.get(APPLICATION_TOKEN).toString();
|
||||
}
|
||||
|
||||
if (checkUserPassword(configuration)) {
|
||||
user = configuration.get(USER_NAME).toString();
|
||||
pw = configuration.get(PASSWORD).toString();
|
||||
}
|
||||
ConnectionManager connMan = new ConnectionManagerImpl(host, user, pw, applicationToken, false, true);
|
||||
Map<String, String> dsidMap = connMan.getDigitalSTROMAPI().getDSID(connMan.getSessionToken());
|
||||
if (dsidMap != null) {
|
||||
dSID = dsidMap.get(JSONApiResponseKeysEnum.DSID.getKey());
|
||||
}
|
||||
}
|
||||
return dSID;
|
||||
}
|
||||
|
||||
private boolean checkUserPassword(Configuration configuration) {
|
||||
return StringUtils.isNotBlank((String) configuration.get(USER_NAME))
|
||||
&& StringUtils.isNotBlank((String) configuration.get(PASSWORD));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void removeHandler(ThingHandler thingHandler) {
|
||||
if (thingHandler instanceof BridgeHandler) {
|
||||
String uid = thingHandler.getThing().getUID().getAsString();
|
||||
if (discoveryServiceManagers.get(uid) != null) {
|
||||
discoveryServiceManagers.get(uid).unregisterDiscoveryServices(bundleContext);
|
||||
discoveryServiceManagers.remove(uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.discovery;
|
||||
|
||||
import java.net.HttpURLConnection;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.config.Config;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.DsAPI;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.constants.JSONApiResponseKeysEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.impl.DsAPIImpl;
|
||||
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.config.discovery.DiscoveryService;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Deactivate;
|
||||
import org.osgi.service.component.annotations.Modified;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link BridgeDiscoveryService} is responsible for discovering digitalSTROM-Server, if the server is in the
|
||||
* local network and is reachable through "dss.local." with default port number "8080". It uses the central
|
||||
* {@link AbstractDiscoveryService}.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
@Component(service = DiscoveryService.class, immediate = true, configurationPid = "discovery.digitalstrom")
|
||||
public class BridgeDiscoveryService extends AbstractDiscoveryService {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(BridgeDiscoveryService.class);
|
||||
public static final String HOST_ADDRESS = "dss.local.";
|
||||
|
||||
private final Runnable resultCreater = new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
createResult();
|
||||
}
|
||||
|
||||
private void createResult() {
|
||||
ThingUID uid = getThingUID();
|
||||
|
||||
if (uid != null) {
|
||||
Map<String, Object> properties = new HashMap<>(2);
|
||||
properties.put(DigitalSTROMBindingConstants.HOST, HOST_ADDRESS);
|
||||
DiscoveryResult result = DiscoveryResultBuilder.create(uid).withProperties(properties)
|
||||
.withLabel("digitalSTROM-Server").build();
|
||||
thingDiscovered(result);
|
||||
}
|
||||
}
|
||||
|
||||
private ThingUID getThingUID() {
|
||||
DsAPI digitalSTROMClient = new DsAPIImpl(HOST_ADDRESS, Config.DEFAULT_CONNECTION_TIMEOUT,
|
||||
Config.DEFAULT_READ_TIMEOUT, true);
|
||||
String dSID = null;
|
||||
switch (digitalSTROMClient.checkConnection("123")) {
|
||||
case HttpURLConnection.HTTP_OK:
|
||||
case HttpURLConnection.HTTP_UNAUTHORIZED:
|
||||
case HttpURLConnection.HTTP_FORBIDDEN:
|
||||
Map<String, String> dsidMap = digitalSTROMClient.getDSID(null);
|
||||
if (dsidMap != null) {
|
||||
dSID = dsidMap.get(JSONApiResponseKeysEnum.DSID.getKey());
|
||||
}
|
||||
if (StringUtils.isNotBlank(dSID)) {
|
||||
return new ThingUID(DigitalSTROMBindingConstants.THING_TYPE_DSS_BRIDGE, dSID);
|
||||
} else {
|
||||
logger.error("Can't get server dSID to generate ThingUID. Please add the server manually.");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new {@link BridgeDiscoveryService}.
|
||||
*/
|
||||
public BridgeDiscoveryService() {
|
||||
super(new HashSet<>(Arrays.asList(DigitalSTROMBindingConstants.THING_TYPE_DSS_BRIDGE)), 10, false);
|
||||
}
|
||||
|
||||
@Activate
|
||||
@Override
|
||||
protected void activate(Map<String, Object> configProperties) {
|
||||
super.activate(configProperties);
|
||||
}
|
||||
|
||||
@Deactivate
|
||||
@Override
|
||||
protected void deactivate() {
|
||||
super.deactivate();
|
||||
}
|
||||
|
||||
@Modified
|
||||
@Override
|
||||
protected void modified(Map<String, Object> configProperties) {
|
||||
super.modified(configProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startScan() {
|
||||
scheduler.execute(resultCreater);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.discovery;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.jmdns.ServiceInfo;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.config.Config;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.DsAPI;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.constants.JSONApiResponseKeysEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.impl.DsAPIImpl;
|
||||
import org.openhab.core.config.discovery.DiscoveryResult;
|
||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||
import org.openhab.core.config.discovery.mdns.MDNSDiscoveryParticipant;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link BridgeMDNSDiscoveryParticipant} is responsible for discovering digitalSTROM-Server. It uses the central
|
||||
* {@link MDNSDiscoveryService}.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*
|
||||
*/
|
||||
@Component(service = MDNSDiscoveryParticipant.class, immediate = true)
|
||||
public class BridgeMDNSDiscoveryParticipant implements MDNSDiscoveryParticipant {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(BridgeMDNSDiscoveryParticipant.class);
|
||||
|
||||
@Override
|
||||
public Set<ThingTypeUID> getSupportedThingTypeUIDs() {
|
||||
return Collections.singleton(DigitalSTROMBindingConstants.THING_TYPE_DSS_BRIDGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServiceType() {
|
||||
return "_tcp.local.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiscoveryResult createResult(ServiceInfo service) {
|
||||
if (service.getApplication().contains("dssweb")) {
|
||||
ThingUID uid = getThingUID(service);
|
||||
|
||||
if (uid != null) {
|
||||
String hostAddress = service.getName() + "." + service.getDomain() + ".";
|
||||
Map<String, Object> properties = new HashMap<>(2);
|
||||
properties.put(DigitalSTROMBindingConstants.HOST, hostAddress);
|
||||
return DiscoveryResultBuilder.create(uid).withProperties(properties)
|
||||
.withRepresentationProperty(uid.getId()).withLabel("digitalSTROM-Server").build();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThingUID getThingUID(ServiceInfo service) {
|
||||
if (service.getApplication().contains("dssweb")) {
|
||||
String hostAddress = service.getName() + "." + service.getDomain() + ".";
|
||||
DsAPI digitalSTROMClient = new DsAPIImpl(hostAddress, Config.DEFAULT_CONNECTION_TIMEOUT,
|
||||
Config.DEFAULT_READ_TIMEOUT, true);
|
||||
Map<String, String> dsidMap = digitalSTROMClient.getDSID(null);
|
||||
String dSID = null;
|
||||
if (dsidMap != null) {
|
||||
dSID = dsidMap.get(JSONApiResponseKeysEnum.DSID.getKey());
|
||||
}
|
||||
if (StringUtils.isNotBlank(dSID)) {
|
||||
return new ThingUID(DigitalSTROMBindingConstants.THING_TYPE_DSS_BRIDGE, dSID);
|
||||
} else {
|
||||
logger.error("Can't get server dSID to generate thing UID. Please add the server manually.");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.discovery;
|
||||
|
||||
import static org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants.BINDING_ID;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants;
|
||||
import org.openhab.binding.digitalstrom.internal.handler.BridgeHandler;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.Circuit;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.Device;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.GeneralDeviceInformation;
|
||||
import org.openhab.binding.digitalstrom.internal.providers.DsDeviceThingTypeProvider;
|
||||
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.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link DeviceDiscoveryService} discovers all digitalSTROM-Devices, of one supported device-color-type. The
|
||||
* device-color-type has to be given to the {@link #DeviceDiscoveryService(BridgeHandler, ThingTypeUID)} as
|
||||
* {@link ThingTypeUID}. The supported {@link ThingTypeUID} can be found at
|
||||
* {@link DeviceHandler#SUPPORTED_THING_TYPES}.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class DeviceDiscoveryService extends AbstractDiscoveryService {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(DeviceDiscoveryService.class);
|
||||
|
||||
private final BridgeHandler bridgeHandler;
|
||||
private final String deviceType;
|
||||
private final ThingUID bridgeUID;
|
||||
|
||||
public static final int TIMEOUT = 10;
|
||||
|
||||
/**
|
||||
* Creates a new {@link DeviceDiscoveryService} for the given supported {@link ThingTypeUID}.
|
||||
*
|
||||
* @param bridgeHandler (must not be null)
|
||||
* @param supportedThingType (must not be null)
|
||||
* @throws IllegalArgumentException see {@link AbstractDiscoveryService#AbstractDiscoveryService(int)}
|
||||
*/
|
||||
public DeviceDiscoveryService(BridgeHandler bridgeHandler, ThingTypeUID supportedThingType)
|
||||
throws IllegalArgumentException {
|
||||
super(new HashSet<>(Arrays.asList(supportedThingType)), TIMEOUT, true);
|
||||
this.deviceType = supportedThingType.getId();
|
||||
this.bridgeHandler = bridgeHandler;
|
||||
bridgeUID = bridgeHandler.getThing().getUID();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deactivates the {@link DeviceDiscoveryService} and removes the {@link DiscoveryResult}s.
|
||||
*/
|
||||
@Override
|
||||
public void deactivate() {
|
||||
logger.debug("deactivate discovery service for device type {} thing types are: {}", deviceType,
|
||||
super.getSupportedThingTypes().toString());
|
||||
removeOlderResults(new Date().getTime());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startScan() {
|
||||
if (bridgeHandler != null) {
|
||||
if (!DsDeviceThingTypeProvider.SupportedThingTypes.circuit.toString().equals(deviceType)) {
|
||||
List<Device> devices = bridgeHandler.getDevices();
|
||||
if (devices != null) {
|
||||
for (Device device : devices) {
|
||||
onDeviceAddedInternal(device);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
List<Circuit> circuits = bridgeHandler.getCircuits();
|
||||
if (circuits != null) {
|
||||
for (Circuit circuit : circuits) {
|
||||
onDeviceAddedInternal(circuit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void stopScan() {
|
||||
super.stopScan();
|
||||
removeOlderResults(getTimestampOfLastScan());
|
||||
}
|
||||
|
||||
private void onDeviceAddedInternal(GeneralDeviceInformation device) {
|
||||
boolean isSupported = false;
|
||||
if (device instanceof Device) {
|
||||
Device tempDevice = (Device) device;
|
||||
if ((tempDevice.isSensorDevice() && deviceType.equals(tempDevice.getHWinfo().replaceAll("-", "")))
|
||||
|| (deviceType.equals(tempDevice.getHWinfo().substring(0, 2))
|
||||
&& (tempDevice.isDeviceWithOutput() || tempDevice.isBinaryInputDevice())
|
||||
&& tempDevice.isPresent())) {
|
||||
isSupported = true;
|
||||
}
|
||||
} else if (device instanceof Circuit
|
||||
&& DsDeviceThingTypeProvider.SupportedThingTypes.circuit.toString().equals(deviceType)) {
|
||||
isSupported = true;
|
||||
}
|
||||
if (isSupported) {
|
||||
ThingUID thingUID = getThingUID(device);
|
||||
if (thingUID != null) {
|
||||
Map<String, Object> properties = new HashMap<>(1);
|
||||
properties.put(DigitalSTROMBindingConstants.DEVICE_DSID, device.getDSID().getValue());
|
||||
String deviceName = null;
|
||||
if (StringUtils.isNotBlank(device.getName())) {
|
||||
deviceName = device.getName();
|
||||
} else {
|
||||
// if no name is set, the dSID will be used as name
|
||||
deviceName = device.getDSID().getValue();
|
||||
}
|
||||
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties)
|
||||
.withBridge(bridgeUID).withLabel(deviceName).build();
|
||||
|
||||
thingDiscovered(discoveryResult);
|
||||
} else {
|
||||
if (device instanceof Device) {
|
||||
logger.debug("Discovered unsupported device hardware type '{}' with uid {}",
|
||||
((Device) device).getHWinfo(), device.getDSUID());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (device instanceof Device) {
|
||||
logger.debug(
|
||||
"Discovered device with disabled or no output mode. Device was not added to inbox. "
|
||||
+ "Device information: hardware info: {}, dSUID: {}, device-name: {}, output value: {}",
|
||||
((Device) device).getHWinfo(), device.getDSUID(), device.getName(),
|
||||
((Device) device).getOutputMode());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ThingUID getThingUID(GeneralDeviceInformation device) {
|
||||
ThingUID bridgeUID = bridgeHandler.getThing().getUID();
|
||||
ThingTypeUID thingTypeUID = null;
|
||||
if (device instanceof Device) {
|
||||
Device tempDevice = (Device) device;
|
||||
thingTypeUID = new ThingTypeUID(BINDING_ID, tempDevice.getHWinfo().substring(0, 2));
|
||||
if (tempDevice.isSensorDevice() && deviceType.equals(tempDevice.getHWinfo().replaceAll("-", ""))) {
|
||||
thingTypeUID = new ThingTypeUID(BINDING_ID, deviceType);
|
||||
}
|
||||
} else {
|
||||
thingTypeUID = new ThingTypeUID(BINDING_ID,
|
||||
DsDeviceThingTypeProvider.SupportedThingTypes.circuit.toString());
|
||||
}
|
||||
if (getSupportedThingTypes().contains(thingTypeUID)) {
|
||||
String thingDeviceId = device.getDSID().toString();
|
||||
ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, thingDeviceId);
|
||||
return thingUID;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the {@link Thing} of the given {@link Device}.
|
||||
*
|
||||
* @param device (must not be null)
|
||||
*/
|
||||
public void onDeviceRemoved(GeneralDeviceInformation device) {
|
||||
ThingUID thingUID = getThingUID(device);
|
||||
|
||||
if (thingUID != null) {
|
||||
thingRemoved(thingUID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link DiscoveryResult} for the given {@link Device}, if the {@link Device} is supported and the
|
||||
* {@link Device#getOutputMode()} is unequal {@link OutputModeEnum#DISABLED}.
|
||||
*
|
||||
* @param device (must not be null)
|
||||
*/
|
||||
public void onDeviceAdded(GeneralDeviceInformation device) {
|
||||
if (super.isBackgroundDiscoveryEnabled()) {
|
||||
onDeviceAddedInternal(device);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of this {@link DeviceDiscoveryService}.
|
||||
*
|
||||
* @return id of the service
|
||||
*/
|
||||
public String getID() {
|
||||
return deviceType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.discovery;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants;
|
||||
import org.openhab.binding.digitalstrom.internal.handler.BridgeHandler;
|
||||
import org.openhab.binding.digitalstrom.internal.handler.CircuitHandler;
|
||||
import org.openhab.binding.digitalstrom.internal.handler.DeviceHandler;
|
||||
import org.openhab.binding.digitalstrom.internal.handler.SceneHandler;
|
||||
import org.openhab.binding.digitalstrom.internal.handler.ZoneTemperatureControlHandler;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.climate.TemperatureControlSensorTransmitter;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.climate.jsonresponsecontainer.impl.TemperatureControlStatus;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.DeviceStatusListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.SceneStatusListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.TemperatureControlStatusListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.Circuit;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.Device;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.GeneralDeviceInformation;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.DeviceStateUpdate;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.ChangeableDeviceConfigEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.scene.InternalScene;
|
||||
import org.openhab.binding.digitalstrom.internal.providers.DsDeviceThingTypeProvider;
|
||||
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||
import org.openhab.core.config.discovery.DiscoveryService;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.type.ThingType;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.framework.ServiceRegistration;
|
||||
|
||||
/**
|
||||
* The {@link DiscoveryServiceManager} manages the different scene and device discovery services and informs them about
|
||||
* new added or removed scenes and devices.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class DiscoveryServiceManager
|
||||
implements SceneStatusListener, DeviceStatusListener, TemperatureControlStatusListener {
|
||||
|
||||
private final Map<String, AbstractDiscoveryService> discoveryServices;
|
||||
private final Map<String, ServiceRegistration<?>> discoveryServiceRegs = new HashMap<>();
|
||||
private final String bridgeUID;
|
||||
|
||||
/**
|
||||
* Creates a new {@link DiscoveryServiceManager} and generates automatically all {@link SceneDiscoveryService}s and
|
||||
* {@link DeviceDiscoveryService}s for all supported {@link ThingType}s of the {@link DeviceHandler} and
|
||||
* {@link SceneHandler}.
|
||||
*
|
||||
* @param bridgeHandler (must not be null)
|
||||
*/
|
||||
public DiscoveryServiceManager(BridgeHandler bridgeHandler) {
|
||||
bridgeUID = bridgeHandler.getThing().getUID().getAsString();
|
||||
discoveryServices = new HashMap<>(SceneHandler.SUPPORTED_THING_TYPES.size()
|
||||
+ DeviceHandler.SUPPORTED_THING_TYPES.size() + CircuitHandler.SUPPORTED_THING_TYPES.size()
|
||||
+ ZoneTemperatureControlHandler.SUPPORTED_THING_TYPES.size());
|
||||
for (ThingTypeUID type : SceneHandler.SUPPORTED_THING_TYPES) {
|
||||
discoveryServices.put(type.getId(), new SceneDiscoveryService(bridgeHandler, type));
|
||||
}
|
||||
for (ThingTypeUID type : DeviceHandler.SUPPORTED_THING_TYPES) {
|
||||
discoveryServices.put(type.getId(), new DeviceDiscoveryService(bridgeHandler, type));
|
||||
}
|
||||
for (ThingTypeUID type : CircuitHandler.SUPPORTED_THING_TYPES) {
|
||||
discoveryServices.put(type.getId(), new DeviceDiscoveryService(bridgeHandler, type));
|
||||
}
|
||||
for (ThingTypeUID type : ZoneTemperatureControlHandler.SUPPORTED_THING_TYPES) {
|
||||
discoveryServices.put(type.getId(), new ZoneTemperatureControlDiscoveryService(bridgeHandler, type));
|
||||
}
|
||||
bridgeHandler.registerSceneStatusListener(this);
|
||||
bridgeHandler.registerDeviceStatusListener(this);
|
||||
bridgeHandler.registerTemperatureControlStatusListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deactivates all {@link SceneDiscoveryService}s and {@link DeviceDiscoveryService}s of this
|
||||
* {@link DiscoveryServiceManager} and unregisters them from the given {@link BundleContext}.
|
||||
*
|
||||
* @param bundleContext (must not be null)
|
||||
*/
|
||||
public void unregisterDiscoveryServices(BundleContext bundleContext) {
|
||||
if (discoveryServices != null) {
|
||||
for (AbstractDiscoveryService service : discoveryServices.values()) {
|
||||
if (service instanceof SceneDiscoveryService) {
|
||||
SceneDiscoveryService sceneDisServ = (SceneDiscoveryService) service;
|
||||
ServiceRegistration<?> serviceReg = this.discoveryServiceRegs.get(bridgeUID + sceneDisServ.getID());
|
||||
sceneDisServ.deactivate();
|
||||
serviceReg.unregister();
|
||||
discoveryServiceRegs.remove(bridgeUID + sceneDisServ.getID());
|
||||
}
|
||||
if (service instanceof DeviceDiscoveryService) {
|
||||
DeviceDiscoveryService devDisServ = (DeviceDiscoveryService) service;
|
||||
ServiceRegistration<?> serviceReg = this.discoveryServiceRegs.get(bridgeUID + devDisServ.getID());
|
||||
devDisServ.deactivate();
|
||||
serviceReg.unregister();
|
||||
discoveryServiceRegs.remove(bridgeUID + devDisServ.getID());
|
||||
}
|
||||
if (service instanceof ZoneTemperatureControlDiscoveryService) {
|
||||
ZoneTemperatureControlDiscoveryService devDisServ = (ZoneTemperatureControlDiscoveryService) service;
|
||||
ServiceRegistration<?> serviceReg = this.discoveryServiceRegs.get(bridgeUID + devDisServ.getID());
|
||||
devDisServ.deactivate();
|
||||
serviceReg.unregister();
|
||||
discoveryServiceRegs.remove(bridgeUID + devDisServ.getID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all {@link SceneDiscoveryService}s and {@link DeviceDiscoveryService}s of this
|
||||
* {@link DiscoveryServiceManager} to the given {@link BundleContext}.
|
||||
*
|
||||
* @param bundleContext (must not be null)
|
||||
*/
|
||||
public void registerDiscoveryServices(BundleContext bundleContext) {
|
||||
if (discoveryServices != null) {
|
||||
for (AbstractDiscoveryService service : discoveryServices.values()) {
|
||||
if (service instanceof SceneDiscoveryService) {
|
||||
this.discoveryServiceRegs.put(bridgeUID + ((SceneDiscoveryService) service).getID(), bundleContext
|
||||
.registerService(DiscoveryService.class.getName(), service, new Hashtable<>()));
|
||||
}
|
||||
if (service instanceof DeviceDiscoveryService) {
|
||||
this.discoveryServiceRegs.put(bridgeUID + ((DeviceDiscoveryService) service).getID(), bundleContext
|
||||
.registerService(DiscoveryService.class.getName(), service, new Hashtable<>()));
|
||||
}
|
||||
if (service instanceof ZoneTemperatureControlDiscoveryService) {
|
||||
this.discoveryServiceRegs
|
||||
.put(bridgeUID + ((ZoneTemperatureControlDiscoveryService) service).getID(), bundleContext
|
||||
.registerService(DiscoveryService.class.getName(), service, new Hashtable<>()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSceneStatusListenerID() {
|
||||
return SceneStatusListener.SCENE_DISCOVERY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSceneStateChanged(boolean flag) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSceneRemoved(InternalScene scene) {
|
||||
if (discoveryServices.get(scene.getSceneType()) != null) {
|
||||
((SceneDiscoveryService) discoveryServices.get(scene.getSceneType())).onSceneRemoved(scene);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSceneAdded(InternalScene scene) {
|
||||
if (discoveryServices.get(scene.getSceneType()) != null) {
|
||||
((SceneDiscoveryService) discoveryServices.get(scene.getSceneType())).onSceneAdded(scene);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceStateChanged(DeviceStateUpdate deviceStateUpdate) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceRemoved(GeneralDeviceInformation device) {
|
||||
if (device instanceof Device) {
|
||||
String id = ((Device) device).getHWinfo().substring(0, 2);
|
||||
if (((Device) device).isSensorDevice()) {
|
||||
id = ((Device) device).getHWinfo().replace("-", "");
|
||||
}
|
||||
if (discoveryServices.get(id) != null) {
|
||||
((DeviceDiscoveryService) discoveryServices.get(id)).onDeviceRemoved(device);
|
||||
}
|
||||
}
|
||||
if (device instanceof Circuit) {
|
||||
if (discoveryServices.get(DsDeviceThingTypeProvider.SupportedThingTypes.circuit.toString()) != null) {
|
||||
((DeviceDiscoveryService) discoveryServices
|
||||
.get(DsDeviceThingTypeProvider.SupportedThingTypes.circuit.toString())).onDeviceRemoved(device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceAdded(GeneralDeviceInformation device) {
|
||||
if (device instanceof Device) {
|
||||
String id = ((Device) device).getHWinfo().substring(0, 2);
|
||||
if (((Device) device).isSensorDevice()) {
|
||||
id = ((Device) device).getHWinfo();
|
||||
}
|
||||
if (discoveryServices.get(id) != null) {
|
||||
((DeviceDiscoveryService) discoveryServices.get(id)).onDeviceAdded(device);
|
||||
}
|
||||
}
|
||||
if (device instanceof Circuit) {
|
||||
if (discoveryServices.get(DsDeviceThingTypeProvider.SupportedThingTypes.circuit.toString()) != null) {
|
||||
((DeviceDiscoveryService) discoveryServices
|
||||
.get(DsDeviceThingTypeProvider.SupportedThingTypes.circuit.toString())).onDeviceAdded(device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceConfigChanged(ChangeableDeviceConfigEnum whatConfig) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSceneConfigAdded(short sceneId) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDeviceStatusListenerID() {
|
||||
return DeviceStatusListener.DEVICE_DISCOVERY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configChanged(TemperatureControlStatus tempControlStatus) {
|
||||
// currently only this thing-type exists
|
||||
if (discoveryServices.get(DigitalSTROMBindingConstants.THING_TYPE_ZONE_TEMERATURE_CONTROL.toString()) != null) {
|
||||
((ZoneTemperatureControlDiscoveryService) discoveryServices
|
||||
.get(DigitalSTROMBindingConstants.THING_TYPE_ZONE_TEMERATURE_CONTROL.toString()))
|
||||
.configChanged(tempControlStatus);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerTemperatureSensorTransmitter(
|
||||
TemperatureControlSensorTransmitter temperatureSensorTransreciver) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getTemperationControlStatusListenrID() {
|
||||
return TemperatureControlStatusListener.DISCOVERY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTargetTemperatureChanged(Float newValue) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onControlValueChanged(Integer newValue) {
|
||||
// nothing to do
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.discovery;
|
||||
|
||||
import static org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.handler.BridgeHandler;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.FuncNameAndColorGroupEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.scene.InternalScene;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.scene.constants.SceneEnum;
|
||||
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.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link SceneDiscoveryService} discovers all digitalSTROM-scene of one supported scene-type. The scene-type has to
|
||||
* be given to the {@link #SceneDiscoveryService(BridgeHandler, ThingTypeUID)} as
|
||||
* {@link ThingTypeUID}. The supported {@link ThingTypeUID} can be found at {@link SceneHandler#SUPPORTED_THING_TYPES}
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class SceneDiscoveryService extends AbstractDiscoveryService {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(SceneDiscoveryService.class);
|
||||
private final BridgeHandler bridgeHandler;
|
||||
private final String sceneType;
|
||||
|
||||
public static final int TIMEOUT = 10;
|
||||
|
||||
/**
|
||||
* Creates a new {@link SceneDiscoveryService} for the given supportedThingType.
|
||||
*
|
||||
* @param bridgeHandler (must not be null)
|
||||
* @param supportedThingType (must not be null)
|
||||
* @throws IllegalArgumentException see {@link AbstractDiscoveryService#AbstractDiscoveryService(int)}
|
||||
*/
|
||||
public SceneDiscoveryService(BridgeHandler bridgeHandler, ThingTypeUID supportedThingType)
|
||||
throws IllegalArgumentException {
|
||||
super(new HashSet<>(Arrays.asList(supportedThingType)), TIMEOUT, false);
|
||||
this.sceneType = supportedThingType.getId();
|
||||
this.bridgeHandler = bridgeHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deactivates the {@link SceneDiscoveryService} and removes the {@link DiscoveryResult}s.
|
||||
*/
|
||||
@Override
|
||||
public void deactivate() {
|
||||
logger.debug("deactivate discovery service for scene type {} remove thing tyspes {}", sceneType,
|
||||
super.getSupportedThingTypes());
|
||||
removeOlderResults(new Date().getTime());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startScan() {
|
||||
if (bridgeHandler != null) {
|
||||
if (bridgeHandler.getScenes() != null) {
|
||||
for (InternalScene scene : bridgeHandler.getScenes()) {
|
||||
onSceneAddedInternal(scene);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void stopScan() {
|
||||
super.stopScan();
|
||||
removeOlderResults(getTimestampOfLastScan());
|
||||
}
|
||||
|
||||
private void onSceneAddedInternal(InternalScene scene) {
|
||||
logger.debug("{}", scene.getSceneType());
|
||||
if (scene.getSceneType().equals(sceneType)) {
|
||||
if (!ignoredScene(scene.getSceneID()) && !ignoreGroup(scene.getGroupID())) {
|
||||
ThingUID thingUID = getThingUID(scene);
|
||||
if (thingUID != null) {
|
||||
ThingUID bridgeUID = bridgeHandler.getThing().getUID();
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
properties.put(ZONE_ID, scene.getZoneID());
|
||||
properties.put(GROUP_ID, scene.getGroupID());
|
||||
if (SceneEnum.containsScene(scene.getSceneID())) {
|
||||
properties.put(SCENE_ID, SceneEnum.getScene(scene.getSceneID()).toString());
|
||||
} else {
|
||||
logger.debug("discovered scene: name '{}' with id {} have an invalid scene-ID",
|
||||
scene.getSceneName(), scene.getID());
|
||||
}
|
||||
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties)
|
||||
.withBridge(bridgeUID).withLabel(scene.getSceneName()).build();
|
||||
|
||||
thingDiscovered(discoveryResult);
|
||||
|
||||
} else {
|
||||
logger.debug("discovered unsupported scene: name '{}' with id {}", scene.getSceneName(),
|
||||
scene.getID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean ignoreGroup(Short groupID) {
|
||||
if (FuncNameAndColorGroupEnum.getMode(groupID) != null) {
|
||||
switch (FuncNameAndColorGroupEnum.getMode(groupID)) {
|
||||
case TEMPERATION_CONTROL:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean ignoredScene(short sceneID) {
|
||||
switch (SceneEnum.getScene(sceneID)) {
|
||||
case INCREMENT:
|
||||
case DECREMENT:
|
||||
case STOP:
|
||||
case MINIMUM:
|
||||
case MAXIMUM:
|
||||
case DEVICE_ON:
|
||||
case DEVICE_OFF:
|
||||
case DEVICE_STOP:
|
||||
case AREA_1_INCREMENT:
|
||||
case AREA_1_DECREMENT:
|
||||
case AREA_1_STOP:
|
||||
case AREA_2_INCREMENT:
|
||||
case AREA_2_DECREMENT:
|
||||
case AREA_2_STOP:
|
||||
case AREA_3_INCREMENT:
|
||||
case AREA_3_DECREMENT:
|
||||
case AREA_3_STOP:
|
||||
case AREA_4_INCREMENT:
|
||||
case AREA_4_DECREMENT:
|
||||
case AREA_4_STOP:
|
||||
case AREA_STEPPING_CONTINUE:
|
||||
case ENERGY_OVERLOAD:
|
||||
case ALARM_SIGNAL:
|
||||
case AUTO_STANDBY:
|
||||
case ZONE_ACTIVE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private ThingUID getThingUID(InternalScene scene) {
|
||||
ThingUID bridgeUID = bridgeHandler.getThing().getUID();
|
||||
ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, sceneType);
|
||||
|
||||
if (getSupportedThingTypes().contains(thingTypeUID)) {
|
||||
String thingSceneId = scene.getID();
|
||||
ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, thingSceneId);
|
||||
return thingUID;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of this {@link SceneDiscoveryService}.
|
||||
*
|
||||
* @return id of this service
|
||||
*/
|
||||
public String getID() {
|
||||
return sceneType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link DiscoveryResult} of the given {@link InternalScene}, if the scene exists, if it is allowed to
|
||||
* use the scene
|
||||
* and if the scene is not one of the following scenes:
|
||||
* <ul>
|
||||
* <li>{@link SceneEnum#INCREMENT}</li>
|
||||
* <li>{@link SceneEnum#DECREMENT}</li>
|
||||
* <li>{@link SceneEnum#STOP}</li>
|
||||
* <li>{@link SceneEnum#MINIMUM}</li>
|
||||
* <li>{@link SceneEnum#MAXIMUM}</li>
|
||||
* <li>{@link SceneEnum#AUTO_OFF}</li>
|
||||
* <li>{@link SceneEnum#DEVICE_ON}</li>
|
||||
* <li>{@link SceneEnum#DEVICE_OFF}</li>
|
||||
* <li>{@link SceneEnum#DEVICE_STOP}</li>
|
||||
* <li>{@link SceneEnum#AREA_1_INCREMENT}</li>
|
||||
* <li>{@link SceneEnum#AREA_1_DECREMENT}</li>
|
||||
* <li>{@link SceneEnum#AREA_1_STOP}</li>
|
||||
* <li>{@link SceneEnum#AREA_2_INCREMENT}</li>
|
||||
* <li>{@link SceneEnum#AREA_2_DECREMENT}</li>
|
||||
* <li>{@link SceneEnum#AREA_2_STOP}</li>
|
||||
* <li>{@link SceneEnum#AREA_3_INCREMENT}</li>
|
||||
* <li>{@link SceneEnum#AREA_3_DECREMENT}</li>
|
||||
* <li>{@link SceneEnum#AREA_3_STOP}</li>
|
||||
* <li>{@link SceneEnum#AREA_4_INCREMENT}</li>
|
||||
* <li>{@link SceneEnum#AREA_4_DECREMENT}</li>
|
||||
* <li>{@link SceneEnum#AREA_4_STOP}</li>
|
||||
* <li>{@link SceneEnum#AREA_STEPPING_CONTINUE}</li>
|
||||
* <li>{@link SceneEnum#ENERGY_OVERLOAD}</li>
|
||||
* <li>{@link SceneEnum#ALARM_SIGNAL}</li>
|
||||
* <li>{@link SceneEnum#AUTO_STANDBY}</li>
|
||||
* <li>{@link SceneEnum#ZONE_ACTIVE}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param scene (must not be null)
|
||||
*/
|
||||
public void onSceneAdded(InternalScene scene) {
|
||||
if (super.isBackgroundDiscoveryEnabled()) {
|
||||
onSceneAddedInternal(scene);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the {@link DiscoveryResult} of the given {@link InternalScene}.
|
||||
*
|
||||
* @param scene (must not be null)
|
||||
*/
|
||||
public void onSceneRemoved(InternalScene scene) {
|
||||
ThingUID thingUID = getThingUID(scene);
|
||||
if (thingUID != null) {
|
||||
thingRemoved(thingUID);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.discovery;
|
||||
|
||||
import static org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants.BINDING_ID;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants;
|
||||
import org.openhab.binding.digitalstrom.internal.handler.BridgeHandler;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.climate.jsonresponsecontainer.impl.TemperatureControlStatus;
|
||||
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.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link ZoneTemperatureControlDiscoveryService} discovers all digitalSTROM zones which have temperature control
|
||||
* configured. The thing-type has to be given to the
|
||||
* {@link #ZoneTemperatureControlDiscoveryService(BridgeHandler, ThingTypeUID)} as {@link ThingTypeUID}. The supported
|
||||
* {@link ThingTypeUID} can be found at {@link ZoneTemperatureControlHandler#SUPPORTED_THING_TYPES}
|
||||
*
|
||||
* @author Michael Ochel
|
||||
* @author Matthias Siegele
|
||||
*/
|
||||
public class ZoneTemperatureControlDiscoveryService extends AbstractDiscoveryService {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(ZoneTemperatureControlDiscoveryService.class);
|
||||
BridgeHandler bridgeHandler;
|
||||
private final ThingUID bridgeUID;
|
||||
private final String thingTypeID;
|
||||
|
||||
public static final int TIMEOUT = 10;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ZoneTemperatureControlDiscoveryService}.
|
||||
*
|
||||
* @param bridgeHandler must not be null
|
||||
* @param supportedThingType must not be null
|
||||
* @throws IllegalArgumentException see {@link AbstractDiscoveryService#AbstractDiscoveryService(int)}
|
||||
*/
|
||||
public ZoneTemperatureControlDiscoveryService(BridgeHandler bridgeHandler, ThingTypeUID supportedThingType)
|
||||
throws IllegalArgumentException {
|
||||
super(new HashSet<>(Arrays.asList(supportedThingType)), TIMEOUT, true);
|
||||
bridgeUID = bridgeHandler.getThing().getUID();
|
||||
this.bridgeHandler = bridgeHandler;
|
||||
thingTypeID = supportedThingType.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startScan() {
|
||||
for (TemperatureControlStatus tempConStat : bridgeHandler.getTemperatureControlStatusFromAllZones()) {
|
||||
internalConfigChanged(tempConStat);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deactivate() {
|
||||
logger.debug("Deactivate discovery service for zone teperature control type remove thing types {}",
|
||||
super.getSupportedThingTypes());
|
||||
removeOlderResults(new Date().getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for the background discovery
|
||||
*
|
||||
* @see org.openhab.binding.digitalstrom.internal.lib.listener.TemperatureControlStatusListener#configChanged(TemperatureControlStatus)
|
||||
* @param tempControlStatus can be null
|
||||
*/
|
||||
public void configChanged(TemperatureControlStatus tempControlStatus) {
|
||||
if (isBackgroundDiscoveryEnabled()) {
|
||||
internalConfigChanged(tempControlStatus);
|
||||
}
|
||||
}
|
||||
|
||||
private void internalConfigChanged(TemperatureControlStatus tempControlStatus) {
|
||||
if (tempControlStatus == null) {
|
||||
return;
|
||||
}
|
||||
if (tempControlStatus.isNotSetOff()) {
|
||||
logger.debug("found configured zone TemperatureControlStatus = {}", tempControlStatus);
|
||||
|
||||
ThingUID thingUID = getThingUID(tempControlStatus);
|
||||
if (thingUID != null) {
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
properties.put(DigitalSTROMBindingConstants.ZONE_ID, tempControlStatus.getZoneID());
|
||||
String zoneName = tempControlStatus.getZoneName();
|
||||
if (StringUtils.isBlank(zoneName)) {
|
||||
zoneName = tempControlStatus.getZoneID().toString();
|
||||
}
|
||||
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties)
|
||||
.withBridge(bridgeUID).withLabel(zoneName).build();
|
||||
thingDiscovered(discoveryResult);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ThingUID getThingUID(TemperatureControlStatus tempControlStatus) {
|
||||
ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, thingTypeID);
|
||||
if (getSupportedThingTypes().contains(thingTypeUID)) {
|
||||
String thingID = tempControlStatus.getZoneID().toString();
|
||||
ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, thingID);
|
||||
return thingUID;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of this {@link ZoneTemperatureControlDiscoveryService}.
|
||||
*
|
||||
* @return id of the service
|
||||
*/
|
||||
public String getID() {
|
||||
return thingTypeID;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,852 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.handler;
|
||||
|
||||
import static org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.climate.jsonresponsecontainer.impl.TemperatureControlStatus;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.config.Config;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.event.EventListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.ConnectionListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.DeviceStatusListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.ManagerStatusListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.SceneStatusListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.TemperatureControlStatusListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.TotalPowerConsumptionListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.stateenums.ManagerStates;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.stateenums.ManagerTypes;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.ConnectionManager;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.DeviceStatusManager;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.SceneManager;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.StructureManager;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.impl.ConnectionManagerImpl;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.impl.DeviceStatusManagerImpl;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.impl.SceneManagerImpl;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.impl.StructureManagerImpl;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.impl.TemperatureControlManager;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.Circuit;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.Device;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.DeviceStateUpdate;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.MeteringTypeEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.MeteringUnitsEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.scene.InternalScene;
|
||||
import org.openhab.binding.digitalstrom.internal.providers.DsChannelTypeProvider;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
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.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.BaseBridgeHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.builder.ThingStatusInfoBuilder;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link BridgeHandler} is the handler for a digitalSTROM-Server and connects it to
|
||||
* the framework.<br>
|
||||
* All {@link DeviceHandler}s and {@link SceneHandler}s use the {@link BridgeHandler} to execute the actual
|
||||
* commands.<br>
|
||||
* <br>
|
||||
* The {@link BridgeHandler} also:
|
||||
* <ul>
|
||||
* <li>manages the {@link DeviceStatusManager} (starts, stops, register {@link DeviceStatusListener},
|
||||
* register {@link SceneStatusListener} and so on)</li>
|
||||
* <li>creates and load the configurations in the {@link Config}.</li>
|
||||
* <li>implements {@link ManagerStatusListener} to manage the expiration of the Thing initializations</li>
|
||||
* <li>implements the {@link ConnectionListener} to manage the {@link ThingStatus} of this {@link BridgeHandler}</li>
|
||||
* <li>and implements the {@link TotalPowerConsumptionListener} to update his Channels.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class BridgeHandler extends BaseBridgeHandler
|
||||
implements ConnectionListener, TotalPowerConsumptionListener, ManagerStatusListener {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(BridgeHandler.class);
|
||||
|
||||
/**
|
||||
* Contains all supported thing types of this handler
|
||||
*/
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_DSS_BRIDGE);
|
||||
|
||||
private static final long RECONNECT_TRACKER_INTERVAL = 15;
|
||||
|
||||
/* DS-Manager */
|
||||
private ConnectionManager connMan;
|
||||
private StructureManager structMan;
|
||||
private SceneManager sceneMan;
|
||||
private DeviceStatusManager devStatMan;
|
||||
private TemperatureControlManager tempContMan;
|
||||
|
||||
private EventListener eventListener;
|
||||
private ScheduledFuture<?> reconnectTracker;
|
||||
|
||||
private DeviceStatusListener deviceDiscovery;
|
||||
private SceneStatusListener sceneDiscovery;
|
||||
private TemperatureControlStatusListener temperatureControlDiscovery;
|
||||
private Config config;
|
||||
|
||||
List<SceneStatusListener> unregisterSceneStatusListeners;
|
||||
private short connectionTimeoutCounter = 0;
|
||||
private final short ignoredTimeouts = 5;
|
||||
|
||||
private class Initializer implements Runnable {
|
||||
|
||||
BridgeHandler bridge;
|
||||
Config config;
|
||||
|
||||
public Initializer(BridgeHandler bridge, Config config) {
|
||||
this.bridge = bridge;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
logger.debug("Checking connection");
|
||||
if (connMan == null) {
|
||||
connMan = new ConnectionManagerImpl(config, bridge, true);
|
||||
} else {
|
||||
connMan.registerConnectionListener(bridge);
|
||||
connMan.configHasBeenUpdated();
|
||||
}
|
||||
|
||||
logger.debug("Initializing digitalSTROM Manager ");
|
||||
if (eventListener == null) {
|
||||
eventListener = new EventListener(connMan);
|
||||
}
|
||||
if (structMan == null) {
|
||||
structMan = new StructureManagerImpl();
|
||||
}
|
||||
if (sceneMan == null) {
|
||||
sceneMan = new SceneManagerImpl(connMan, structMan, bridge, eventListener);
|
||||
}
|
||||
if (devStatMan == null) {
|
||||
devStatMan = new DeviceStatusManagerImpl(connMan, structMan, sceneMan, bridge, eventListener);
|
||||
} else {
|
||||
devStatMan.registerStatusListener(bridge);
|
||||
}
|
||||
|
||||
devStatMan.registerTotalPowerConsumptionListener(bridge);
|
||||
|
||||
if (connMan.checkConnection()) {
|
||||
logger.debug("connection established, start services");
|
||||
if (TemperatureControlManager.isHeatingControllerInstallated(connMan)) {
|
||||
if (tempContMan == null) {
|
||||
tempContMan = new TemperatureControlManager(connMan, eventListener,
|
||||
temperatureControlDiscovery);
|
||||
temperatureControlDiscovery = null;
|
||||
} else {
|
||||
if (temperatureControlDiscovery != null) {
|
||||
tempContMan.registerTemperatureControlStatusListener(temperatureControlDiscovery);
|
||||
}
|
||||
}
|
||||
}
|
||||
structMan.generateZoneGroupNames(connMan);
|
||||
devStatMan.start();
|
||||
eventListener.start();
|
||||
}
|
||||
|
||||
boolean configChanged = false;
|
||||
Configuration configuration = bridge.getConfig();
|
||||
if (connMan.getApplicationToken() != null) {
|
||||
configuration.remove(USER_NAME);
|
||||
configuration.remove(PASSWORD);
|
||||
logger.debug("Application-Token is: {}", connMan.getApplicationToken());
|
||||
configuration.put(APPLICATION_TOKEN, connMan.getApplicationToken());
|
||||
configChanged = true;
|
||||
}
|
||||
Map<String, String> properties = editProperties();
|
||||
String dSSname = connMan.getDigitalSTROMAPI().getInstallationName(connMan.getSessionToken());
|
||||
if (dSSname != null) {
|
||||
properties.put(DS_NAME, dSSname);
|
||||
}
|
||||
Map<String, String> dsidMap = connMan.getDigitalSTROMAPI().getDSID(connMan.getSessionToken());
|
||||
if (dsidMap != null) {
|
||||
logger.debug("{}", dsidMap);
|
||||
properties.putAll(dsidMap);
|
||||
}
|
||||
Map<String, String> versions = connMan.getDigitalSTROMAPI().getSystemVersion();
|
||||
if (versions != null) {
|
||||
properties.putAll(versions);
|
||||
}
|
||||
if (StringUtils.isBlank(getThing().getProperties().get(DigitalSTROMBindingConstants.SERVER_CERT))
|
||||
&& StringUtils.isNotBlank(config.getCert())) {
|
||||
properties.put(DigitalSTROMBindingConstants.SERVER_CERT, config.getCert());
|
||||
}
|
||||
logger.debug("update properties");
|
||||
updateProperties(properties);
|
||||
|
||||
if (configChanged) {
|
||||
updateConfiguration(configuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link BridgeHandler}.
|
||||
*
|
||||
* @param bridge must not be null
|
||||
*/
|
||||
public BridgeHandler(Bridge bridge) {
|
||||
super(bridge);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("Initializing digitalSTROM-BridgeHandler");
|
||||
updateStatus(ThingStatus.ONLINE, ThingStatusDetail.CONFIGURATION_PENDING, "Checking configuration...");
|
||||
// Start an extra thread to readout the configuration and check the connection, because it takes sometimes more
|
||||
// than 5000 milliseconds and the handler will suspend (ThingStatus.UNINITIALIZED).
|
||||
Config config = loadAndCheckConfig();
|
||||
|
||||
if (config != null) {
|
||||
logger.debug("{}", config.toString());
|
||||
scheduler.execute(new Initializer(this, config));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkLoginConfig(Config config) {
|
||||
if ((StringUtils.isNotBlank(config.getUserName()) && StringUtils.isNotBlank(config.getPassword()))
|
||||
|| StringUtils.isNotBlank(config.getAppToken())) {
|
||||
return true;
|
||||
}
|
||||
onConnectionStateChange(CONNECTION_LOST, NO_USER_PASSWORD);
|
||||
return false;
|
||||
}
|
||||
|
||||
private Config loadAndCheckConfig() {
|
||||
Configuration thingConfig = super.getConfig();
|
||||
Config config = loadAndCheckConnectionData(thingConfig);
|
||||
if (config == null) {
|
||||
return null;
|
||||
}
|
||||
logger.debug("Loading configuration");
|
||||
List<String> numberExc = new ArrayList<>();
|
||||
// Parameters can't be null, because of an existing default value.
|
||||
if (thingConfig.get(DigitalSTROMBindingConstants.SENSOR_DATA_UPDATE_INTERVAL) instanceof BigDecimal) {
|
||||
config.setSensordataRefreshInterval(
|
||||
((BigDecimal) thingConfig.get(DigitalSTROMBindingConstants.SENSOR_DATA_UPDATE_INTERVAL)).intValue()
|
||||
* 1000);
|
||||
} else {
|
||||
numberExc.add("\"Sensor update interval\" ( "
|
||||
+ thingConfig.get(DigitalSTROMBindingConstants.SENSOR_DATA_UPDATE_INTERVAL) + ")");
|
||||
}
|
||||
if (thingConfig.get(DigitalSTROMBindingConstants.TOTAL_POWER_UPDATE_INTERVAL) instanceof BigDecimal) {
|
||||
config.setTotalPowerUpdateInterval(
|
||||
((BigDecimal) thingConfig.get(DigitalSTROMBindingConstants.TOTAL_POWER_UPDATE_INTERVAL)).intValue()
|
||||
* 1000);
|
||||
} else {
|
||||
numberExc.add("\"Total power update interval\" ("
|
||||
+ thingConfig.get(DigitalSTROMBindingConstants.TOTAL_POWER_UPDATE_INTERVAL) + ")");
|
||||
}
|
||||
if (thingConfig.get(DigitalSTROMBindingConstants.SENSOR_WAIT_TIME) instanceof BigDecimal) {
|
||||
config.setSensorReadingWaitTime(
|
||||
((BigDecimal) thingConfig.get(DigitalSTROMBindingConstants.SENSOR_WAIT_TIME)).intValue() * 1000);
|
||||
} else {
|
||||
numberExc.add("\"Wait time sensor reading\" ("
|
||||
+ thingConfig.get(DigitalSTROMBindingConstants.SENSOR_WAIT_TIME) + ")");
|
||||
}
|
||||
if (thingConfig.get(DigitalSTROMBindingConstants.DEFAULT_TRASH_DEVICE_DELETE_TIME_KEY) instanceof BigDecimal) {
|
||||
config.setTrashDeviceDeleteTime(
|
||||
((BigDecimal) thingConfig.get(DigitalSTROMBindingConstants.DEFAULT_TRASH_DEVICE_DELETE_TIME_KEY))
|
||||
.intValue());
|
||||
} else {
|
||||
numberExc.add("\"Days to be slaked trash bin devices\" ("
|
||||
+ thingConfig.get(DigitalSTROMBindingConstants.DEFAULT_TRASH_DEVICE_DELETE_TIME_KEY) + ")");
|
||||
}
|
||||
if (!numberExc.isEmpty()) {
|
||||
String excText = "The field ";
|
||||
for (int i = 0; i < numberExc.size(); i++) {
|
||||
excText = excText + numberExc.get(i);
|
||||
if (i < numberExc.size() - 2) {
|
||||
excText = excText + ", ";
|
||||
} else if (i < numberExc.size() - 1) {
|
||||
excText = excText + " and ";
|
||||
}
|
||||
}
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, excText + " have to be a number.");
|
||||
return null;
|
||||
}
|
||||
if (StringUtils.isNotBlank(getThing().getProperties().get(DigitalSTROMBindingConstants.SERVER_CERT))) {
|
||||
config.setCert(getThing().getProperties().get(DigitalSTROMBindingConstants.SERVER_CERT));
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
private Config loadAndCheckConnectionData(Configuration thingConfig) {
|
||||
if (this.config == null) {
|
||||
this.config = new Config();
|
||||
}
|
||||
// load and check connection and authorization data
|
||||
if (StringUtils.isNotBlank((String) thingConfig.get(HOST))) {
|
||||
config.setHost(thingConfig.get(HOST).toString());
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"The connection to the digitalSTROM-Server can't established, because the host address is missing. Please set the host address.");
|
||||
return null;
|
||||
}
|
||||
if (thingConfig.get(USER_NAME) != null) {
|
||||
config.setUserName(thingConfig.get(USER_NAME).toString());
|
||||
} else {
|
||||
config.setUserName(null);
|
||||
}
|
||||
if (thingConfig.get(PASSWORD) != null) {
|
||||
config.setPassword(thingConfig.get(PASSWORD).toString());
|
||||
} else {
|
||||
config.setPassword(null);
|
||||
}
|
||||
if (thingConfig.get(APPLICATION_TOKEN) != null) {
|
||||
config.setAppToken(thingConfig.get(APPLICATION_TOKEN).toString());
|
||||
} else {
|
||||
config.setAppToken(null);
|
||||
}
|
||||
|
||||
if (!checkLoginConfig(config)) {
|
||||
return null;
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("Handler disposed");
|
||||
if (reconnectTracker != null && !reconnectTracker.isCancelled()) {
|
||||
reconnectTracker.cancel(true);
|
||||
}
|
||||
if (eventListener != null) {
|
||||
eventListener.stop();
|
||||
}
|
||||
if (devStatMan != null) {
|
||||
devStatMan.unregisterTotalPowerConsumptionListener();
|
||||
devStatMan.unregisterStatusListener();
|
||||
this.devStatMan.stop();
|
||||
}
|
||||
if (connMan != null) {
|
||||
connMan.unregisterConnectionListener();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof RefreshType) {
|
||||
channelLinked(channelUID);
|
||||
} else {
|
||||
logger.debug("Command {} is not supported for channel: {}", command, channelUID.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleRemoval() {
|
||||
for (Thing thing : getThing().getThings()) {
|
||||
// Inform Thing-Child's about removed bridge.
|
||||
final ThingHandler thingHandler = thing.getHandler();
|
||||
if (thingHandler != null) {
|
||||
thingHandler.bridgeStatusChanged(ThingStatusInfoBuilder.create(ThingStatus.REMOVED).build());
|
||||
}
|
||||
}
|
||||
if (StringUtils.isNotBlank((String) super.getConfig().get(APPLICATION_TOKEN))) {
|
||||
if (connMan == null) {
|
||||
Config config = loadAndCheckConnectionData(this.getConfig());
|
||||
if (config != null) {
|
||||
this.connMan = new ConnectionManagerImpl(config, null, false);
|
||||
} else {
|
||||
updateStatus(ThingStatus.REMOVED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (connMan.removeApplicationToken()) {
|
||||
logger.debug("Application-Token deleted");
|
||||
}
|
||||
}
|
||||
updateStatus(ThingStatus.REMOVED);
|
||||
}
|
||||
|
||||
/* methods to store listener */
|
||||
|
||||
/**
|
||||
* Registers a new {@link DeviceStatusListener} on the {@link DeviceStatusManager}.
|
||||
*
|
||||
* @param deviceStatusListener (must not be null)
|
||||
*/
|
||||
public synchronized void registerDeviceStatusListener(DeviceStatusListener deviceStatusListener) {
|
||||
if (this.devStatMan != null) {
|
||||
if (deviceStatusListener == null) {
|
||||
throw new IllegalArgumentException("It's not allowed to pass null.");
|
||||
}
|
||||
|
||||
if (deviceStatusListener.getDeviceStatusListenerID() != null) {
|
||||
if (devStatMan.getManagerState().equals(ManagerStates.RUNNING)) {
|
||||
devStatMan.registerDeviceListener(deviceStatusListener);
|
||||
} else if (deviceStatusListener.getDeviceStatusListenerID()
|
||||
.equals(DeviceStatusListener.DEVICE_DISCOVERY)) {
|
||||
devStatMan.registerDeviceListener(deviceStatusListener);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("It's not allowed to pass a DeviceStatusListener with ID = null.");
|
||||
}
|
||||
} else {
|
||||
if (deviceStatusListener.getDeviceStatusListenerID().equals(DeviceStatusListener.DEVICE_DISCOVERY)) {
|
||||
deviceDiscovery = deviceStatusListener;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a new {@link DeviceStatusListener} on the {@link BridgeHandler}.
|
||||
*
|
||||
* @param deviceStatusListener (must not be null)
|
||||
*/
|
||||
public void unregisterDeviceStatusListener(DeviceStatusListener deviceStatusListener) {
|
||||
if (this.devStatMan != null) {
|
||||
if (deviceStatusListener.getDeviceStatusListenerID() != null) {
|
||||
this.devStatMan.unregisterDeviceListener(deviceStatusListener);
|
||||
} else {
|
||||
throw new IllegalArgumentException("It's not allowed to pass a DeviceStatusListener with ID = null.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new {@link SceneStatusListener} on the {@link BridgeHandler}.
|
||||
*
|
||||
* @param sceneStatusListener (must not be null)
|
||||
*/
|
||||
public synchronized void registerSceneStatusListener(SceneStatusListener sceneStatusListener) {
|
||||
if (this.sceneMan != null) {
|
||||
if (sceneStatusListener == null) {
|
||||
throw new IllegalArgumentException("It's not allowed to pass null.");
|
||||
}
|
||||
|
||||
if (sceneStatusListener.getSceneStatusListenerID() != null) {
|
||||
this.sceneMan.registerSceneListener(sceneStatusListener);
|
||||
} else {
|
||||
throw new IllegalArgumentException("It's not allowed to pass a SceneStatusListener with ID = null.");
|
||||
}
|
||||
} else {
|
||||
if (sceneStatusListener.getSceneStatusListenerID().equals(SceneStatusListener.SCENE_DISCOVERY)) {
|
||||
sceneDiscovery = sceneStatusListener;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a new {@link SceneStatusListener} on the {@link DeviceStatusManager}.
|
||||
*
|
||||
* @param sceneStatusListener (must not be null)
|
||||
*/
|
||||
public void unregisterSceneStatusListener(SceneStatusListener sceneStatusListener) {
|
||||
if (this.sceneMan != null) {
|
||||
if (sceneStatusListener.getSceneStatusListenerID() != null) {
|
||||
this.sceneMan.unregisterSceneListener(sceneStatusListener);
|
||||
} else {
|
||||
throw new IllegalArgumentException("It's not allowed to pass a SceneStatusListener with ID = null..");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Has to be called from a removed Thing-Child to rediscovers the Thing.
|
||||
*
|
||||
* @param id = scene or device id (must not be null)
|
||||
*/
|
||||
public void childThingRemoved(String id) {
|
||||
if (id != null && id.split("-").length == 3) {
|
||||
InternalScene scene = sceneMan.getInternalScene(id);
|
||||
if (scene != null) {
|
||||
sceneMan.removeInternalScene(id);
|
||||
sceneMan.addInternalScene(scene);
|
||||
}
|
||||
} else {
|
||||
devStatMan.removeDevice(id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegate a stop command from a Thing to the {@link DeviceStatusManager#sendStopComandsToDSS(Device)}.
|
||||
*
|
||||
* @param device can be null
|
||||
*/
|
||||
public void stopOutputValue(Device device) {
|
||||
this.devStatMan.sendStopComandsToDSS(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelLinked(ChannelUID channelUID) {
|
||||
if (devStatMan != null) {
|
||||
MeteringTypeEnum meteringType = DsChannelTypeProvider.getMeteringType(channelUID.getId());
|
||||
if (meteringType != null) {
|
||||
if (meteringType.equals(MeteringTypeEnum.ENERGY)) {
|
||||
onEnergyMeterValueChanged(devStatMan.getTotalEnergyMeterValue());
|
||||
} else {
|
||||
onTotalPowerConsumptionChanged(devStatMan.getTotalPowerConsumption());
|
||||
}
|
||||
} else {
|
||||
logger.warn("Channel with id {} is not known for the thing with id {}.", channelUID.getId(),
|
||||
getThing().getUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTotalPowerConsumptionChanged(int newPowerConsumption) {
|
||||
updateChannelState(MeteringTypeEnum.CONSUMPTION, MeteringUnitsEnum.WH, newPowerConsumption);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnergyMeterValueChanged(int newEnergyMeterValue) {
|
||||
updateChannelState(MeteringTypeEnum.ENERGY, MeteringUnitsEnum.WH, newEnergyMeterValue * 0.001);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnergyMeterWsValueChanged(int newEnergyMeterValue) {
|
||||
// not needed
|
||||
}
|
||||
|
||||
private void updateChannelState(MeteringTypeEnum meteringType, MeteringUnitsEnum meteringUnit, double value) {
|
||||
String channelID = DsChannelTypeProvider.getMeteringChannelID(meteringType, meteringUnit, true);
|
||||
if (getThing().getChannel(channelID) != null) {
|
||||
updateState(channelID, new DecimalType(value));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionStateChange(String newConnectionState) {
|
||||
switch (newConnectionState) {
|
||||
case CONNECTION_LOST:
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"The connection to the digitalSTROM-Server cannot be established.");
|
||||
startReconnectTracker();
|
||||
return;
|
||||
case CONNECTION_RESUMED:
|
||||
if (connectionTimeoutCounter > 0) {
|
||||
// reset connection timeout counter
|
||||
connectionTimeoutCounter = 0;
|
||||
if (connMan.checkConnection()) {
|
||||
restartServices();
|
||||
setStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case APPLICATION_TOKEN_GENERATED:
|
||||
if (connMan != null) {
|
||||
Configuration config = this.getConfig();
|
||||
config.remove(USER_NAME);
|
||||
config.remove(PASSWORD);
|
||||
config.put(APPLICATION_TOKEN, connMan.getApplicationToken());
|
||||
this.updateConfiguration(config);
|
||||
}
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void setStatus(ThingStatus status) {
|
||||
logger.debug("set status to: {}", status);
|
||||
updateStatus(status);
|
||||
for (Thing thing : getThing().getThings()) {
|
||||
ThingHandler handler = thing.getHandler();
|
||||
if (handler != null) {
|
||||
handler.bridgeStatusChanged(getThing().getStatusInfo());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void startReconnectTracker() {
|
||||
if (reconnectTracker == null || reconnectTracker.isCancelled()) {
|
||||
logger.debug("Connection lost, stop all services and start reconnectTracker.");
|
||||
stopServices();
|
||||
reconnectTracker = scheduler.scheduleWithFixedDelay(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (connMan != null) {
|
||||
boolean conStat = connMan.checkConnection();
|
||||
logger.debug("check connection = {}", conStat);
|
||||
if (conStat) {
|
||||
restartServices();
|
||||
reconnectTracker.cancel(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, RECONNECT_TRACKER_INTERVAL, RECONNECT_TRACKER_INTERVAL, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
private void stopServices() {
|
||||
if (devStatMan != null && !devStatMan.getManagerState().equals(ManagerStates.STOPPED)) {
|
||||
devStatMan.stop();
|
||||
}
|
||||
if (eventListener != null && eventListener.isStarted()) {
|
||||
eventListener.stop();
|
||||
}
|
||||
}
|
||||
|
||||
private void restartServices() {
|
||||
logger.debug("reconnect, stop reconnection tracker and restart services");
|
||||
if (reconnectTracker != null && !reconnectTracker.isCancelled()) {
|
||||
reconnectTracker.cancel(true);
|
||||
}
|
||||
stopServices();
|
||||
if (devStatMan != null) {
|
||||
devStatMan.start();
|
||||
}
|
||||
if (eventListener != null) {
|
||||
eventListener.start();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionStateChange(String newConnectionState, String reason) {
|
||||
if (newConnectionState.equals(NOT_AUTHENTICATED) || newConnectionState.equals(CONNECTION_LOST)) {
|
||||
switch (reason) {
|
||||
case WRONG_APP_TOKEN:
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"User defined Application-Token is wrong. "
|
||||
+ "Please set user name and password to generate an Application-Token or set an valid Application-Token.");
|
||||
stopServices();
|
||||
return;
|
||||
case WRONG_USER_OR_PASSWORD:
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"The set username or password is wrong.");
|
||||
stopServices();
|
||||
return;
|
||||
case NO_USER_PASSWORD:
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"No username or password is set to generate Application-Token. Please set user name and password or Application-Token.");
|
||||
stopServices();
|
||||
return;
|
||||
case CONNECTON_TIMEOUT:
|
||||
// ignore the first connection timeout
|
||||
if (connectionTimeoutCounter++ > ignoredTimeouts) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"Connection lost because connection timeout to Server.");
|
||||
break;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
case HOST_NOT_FOUND:
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"Server not found! Please check these points:\n" + " - Is digitalSTROM-Server turned on?\n"
|
||||
+ " - Is the host address correct?\n"
|
||||
+ " - Is the ethernet cable connection established?");
|
||||
break;
|
||||
case UNKNOWN_HOST:
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"Unknown host name, please check the set host name!");
|
||||
break;
|
||||
case INVALID_URL:
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Invalid URL is set.");
|
||||
break;
|
||||
case CONNECTION_LOST:
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"IOException / Connection lost.");
|
||||
break;
|
||||
case SSL_HANDSHAKE_ERROR:
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"SSL Handshake error / Connection lost.");
|
||||
break;
|
||||
default:
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, reason);
|
||||
}
|
||||
// reset connection timeout counter
|
||||
connectionTimeoutCounter = 0;
|
||||
startReconnectTracker();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all {@link Device}'s.
|
||||
*
|
||||
* @return device list (cannot be null)
|
||||
*/
|
||||
public List<Device> getDevices() {
|
||||
return this.structMan != null && this.structMan.getDeviceMap() != null
|
||||
? new LinkedList<>(this.structMan.getDeviceMap().values())
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link StructureManager}.
|
||||
*
|
||||
* @return StructureManager
|
||||
*/
|
||||
public StructureManager getStructureManager() {
|
||||
return this.structMan;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates a scene command of a Thing to the
|
||||
* {@link DeviceStatusManager#sendSceneComandsToDSS(InternalScene, boolean)}
|
||||
*
|
||||
* @param scene the called scene
|
||||
* @param call_undo (true = call scene | false = undo scene)
|
||||
*/
|
||||
public void sendSceneComandToDSS(InternalScene scene, boolean call_undo) {
|
||||
if (devStatMan != null) {
|
||||
devStatMan.sendSceneComandsToDSS(scene, call_undo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates a device command of a Thing to the
|
||||
* {@link DeviceStatusManager#sendComandsToDSS(Device, DeviceStateUpdate)}
|
||||
*
|
||||
* @param device can be null
|
||||
* @param deviceStateUpdate can be null
|
||||
*/
|
||||
public void sendComandsToDSS(Device device, DeviceStateUpdate deviceStateUpdate) {
|
||||
if (devStatMan != null) {
|
||||
devStatMan.sendComandsToDSS(device, deviceStateUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all {@link InternalScene}'s.
|
||||
*
|
||||
* @return Scene list (cannot be null)
|
||||
*/
|
||||
public List<InternalScene> getScenes() {
|
||||
return sceneMan != null ? sceneMan.getScenes() : new LinkedList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link ConnectionManager}.
|
||||
*
|
||||
* @return ConnectionManager
|
||||
*/
|
||||
public ConnectionManager getConnectionManager() {
|
||||
return this.connMan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusChanged(ManagerTypes managerType, ManagerStates state) {
|
||||
if (managerType.equals(ManagerTypes.DEVICE_STATUS_MANAGER)) {
|
||||
switch (state) {
|
||||
case INITIALIZING:
|
||||
if (deviceDiscovery != null) {
|
||||
devStatMan.registerDeviceListener(deviceDiscovery);
|
||||
deviceDiscovery = null;
|
||||
}
|
||||
logger.debug("Building digitalSTROM model");
|
||||
break;
|
||||
case RUNNING:
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
break;
|
||||
case STOPPED:
|
||||
if (!getThing().getStatusInfo().getStatusDetail().equals(ThingStatusDetail.COMMUNICATION_ERROR)
|
||||
&& !getThing().getStatusInfo().getStatusDetail()
|
||||
.equals(ThingStatusDetail.CONFIGURATION_ERROR)) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "DeviceStatusManager is stopped.");
|
||||
devStatMan.start();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (managerType.equals(ManagerTypes.SCENE_MANAGER)) {
|
||||
switch (state) {
|
||||
case GENERATING_SCENES:
|
||||
logger.debug("SceneManager reports that he is generating scenes");
|
||||
if (sceneDiscovery != null) {
|
||||
sceneMan.registerSceneListener(sceneDiscovery);
|
||||
sceneDiscovery = null;
|
||||
}
|
||||
break;
|
||||
case RUNNING:
|
||||
logger.debug("SceneManager reports that he is running");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link List} of all {@link Circuit}'s.
|
||||
*
|
||||
* @return circuit list
|
||||
*/
|
||||
public List<Circuit> getCircuits() {
|
||||
logger.debug("circuits: {}", structMan.getCircuitMap().values().toString());
|
||||
return structMan != null && structMan.getCircuitMap() != null
|
||||
? new LinkedList<>(structMan.getCircuitMap().values())
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link TemperatureControlManager} or null if no one exist.
|
||||
*
|
||||
* @return {@link TemperatureControlManager}
|
||||
*/
|
||||
public TemperatureControlManager getTemperatureControlManager() {
|
||||
return tempContMan;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given {@link TemperatureControlStatusListener} to the {@link TemperatureControlManager}.
|
||||
*
|
||||
* @param temperatureControlStatusListener can be null
|
||||
*/
|
||||
public void registerTemperatureControlStatusListener(
|
||||
TemperatureControlStatusListener temperatureControlStatusListener) {
|
||||
if (tempContMan != null) {
|
||||
tempContMan.registerTemperatureControlStatusListener(temperatureControlStatusListener);
|
||||
} else if (TemperatureControlStatusListener.DISCOVERY
|
||||
.equals(temperatureControlStatusListener.getTemperationControlStatusListenrID())) {
|
||||
this.temperatureControlDiscovery = temperatureControlStatusListener;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters the given {@link TemperatureControlStatusListener} from the {@link TemperatureControlManager}.
|
||||
*
|
||||
* @param temperatureControlStatusListener can be null
|
||||
*/
|
||||
public void unregisterTemperatureControlStatusListener(
|
||||
TemperatureControlStatusListener temperatureControlStatusListener) {
|
||||
if (tempContMan != null) {
|
||||
tempContMan.unregisterTemperatureControlStatusListener(temperatureControlStatusListener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* see {@link TemperatureControlManager#getTemperatureControlStatusFromAllZones()}
|
||||
*
|
||||
* @return all temperature control status objects
|
||||
*/
|
||||
public Collection<TemperatureControlStatus> getTemperatureControlStatusFromAllZones() {
|
||||
return tempContMan != null ? tempContMan.getTemperatureControlStatusFromAllZones() : new LinkedList<>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.handler;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.DeviceStatusListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.Circuit;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.Device;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.GeneralDeviceInformation;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.CachedMeteringValue;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.DeviceStateUpdate;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.ChangeableDeviceConfigEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.MeteringTypeEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.MeteringUnitsEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.providers.DsChannelTypeProvider;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
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.ThingTypeUID;
|
||||
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 CircuitHandler} is responsible for handling the configuration and updating the metering channels of a
|
||||
* digitalStrom circuit. <br>
|
||||
* <br>
|
||||
* For that it uses the {@link BridgeHandler} to register this class as a {@link DeviceStatusListener} to get informed
|
||||
* about changes from the accompanying {@link Circuit}.
|
||||
*
|
||||
* @author Michael Ochel
|
||||
* @author Matthias Siegele
|
||||
*/
|
||||
public class CircuitHandler extends BaseThingHandler implements DeviceStatusListener {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CircuitHandler.class);
|
||||
|
||||
/**
|
||||
* Contains all supported thing types of this handler, will be filled by DsDeviceThingTypeProvider.
|
||||
*/
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>();
|
||||
|
||||
private String dSID;
|
||||
private Circuit circuit;
|
||||
|
||||
private BridgeHandler dssBridgeHandler;
|
||||
|
||||
/**
|
||||
* Creates a new {@link CircuitHandler}.
|
||||
*
|
||||
* @param thing must not be null
|
||||
*/
|
||||
public CircuitHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("Initializing CircuitHandler.");
|
||||
if (StringUtils.isNotBlank((String) getConfig().get(DigitalSTROMBindingConstants.DEVICE_DSID))) {
|
||||
dSID = getConfig().get(DigitalSTROMBindingConstants.DEVICE_DSID).toString();
|
||||
final Bridge bridge = getBridge();
|
||||
if (bridge != null) {
|
||||
bridgeStatusChanged(bridge.getStatusInfo());
|
||||
} else {
|
||||
// Set status to OFFLINE if no bridge is available e.g. because the bridge has been removed and the
|
||||
// Thing was reinitialized.
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "Bridge is missing!");
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "dSID is missing");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("Handler disposed... unregister DeviceStatusListener");
|
||||
if (dSID != null) {
|
||||
if (dssBridgeHandler != null) {
|
||||
dssBridgeHandler.unregisterDeviceStatusListener(this);
|
||||
}
|
||||
}
|
||||
circuit = null;
|
||||
}
|
||||
|
||||
private synchronized BridgeHandler getDssBridgeHandler() {
|
||||
if (this.dssBridgeHandler == null) {
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge == null) {
|
||||
logger.debug("Bride cannot be found");
|
||||
return null;
|
||||
}
|
||||
ThingHandler handler = bridge.getHandler();
|
||||
|
||||
if (handler instanceof BridgeHandler) {
|
||||
dssBridgeHandler = (BridgeHandler) handler;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return dssBridgeHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void thingUpdated(Thing thing) {
|
||||
this.thing = thing;
|
||||
if (circuit == null) {
|
||||
initialize();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
|
||||
if (bridgeStatusInfo.getStatus().equals(ThingStatus.ONLINE)) {
|
||||
if (dSID != null) {
|
||||
if (getDssBridgeHandler() != null) {
|
||||
if (circuit == null) {
|
||||
updateStatus(ThingStatus.ONLINE, ThingStatusDetail.CONFIGURATION_PENDING,
|
||||
"waiting for listener registration");
|
||||
dssBridgeHandler.registerDeviceStatusListener(this);
|
||||
} else {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE);
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "No dSID is set!");
|
||||
}
|
||||
}
|
||||
if (bridgeStatusInfo.getStatus().equals(ThingStatus.OFFLINE)) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
}
|
||||
if (bridgeStatusInfo.getStatus().equals(ThingStatus.REMOVED)) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "Bridge has been removed.");
|
||||
}
|
||||
logger.debug("Set status to {}", getThing().getStatusInfo());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
// the same handling like total metering values
|
||||
if (dssBridgeHandler != null) {
|
||||
dssBridgeHandler.handleCommand(channelUID, command);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceStateChanged(DeviceStateUpdate deviceStateUpdate) {
|
||||
if (deviceStateUpdate != null && DeviceStateUpdate.UPDATE_CIRCUIT_METER.equals(deviceStateUpdate.getType())) {
|
||||
if (deviceStateUpdate.getValue() instanceof CachedMeteringValue) {
|
||||
CachedMeteringValue cachedVal = (CachedMeteringValue) deviceStateUpdate.getValue();
|
||||
if (MeteringUnitsEnum.WH.equals(cachedVal.getMeteringUnit())) {
|
||||
if (cachedVal.getMeteringType().equals(MeteringTypeEnum.ENERGY)) {
|
||||
updateState(getChannelID(cachedVal), new DecimalType(cachedVal.getValue() * 0.001));
|
||||
} else {
|
||||
updateState(getChannelID(cachedVal), new DecimalType(cachedVal.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceRemoved(GeneralDeviceInformation device) {
|
||||
if (device instanceof Circuit) {
|
||||
this.circuit = (Circuit) device;
|
||||
if (this.getThing().getStatus().equals(ThingStatus.ONLINE)) {
|
||||
if (!((Device) circuit).isPresent()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE,
|
||||
"Circuit is not present in the digitalSTROM-System.");
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE,
|
||||
"Circuit is not avaible in the digitalSTROM-System.");
|
||||
}
|
||||
|
||||
}
|
||||
logger.debug("Set status to {}", getThing().getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceAdded(GeneralDeviceInformation device) {
|
||||
if (device instanceof Circuit) {
|
||||
this.circuit = (Circuit) device;
|
||||
if (this.circuit.isPresent()) {
|
||||
ThingStatusInfo statusInfo = this.dssBridgeHandler.getThing().getStatusInfo();
|
||||
updateStatus(statusInfo.getStatus(), statusInfo.getStatusDetail(), statusInfo.getDescription());
|
||||
logger.debug("Set status to {}", getThing().getStatus());
|
||||
|
||||
checkCircuitInfoProperties(this.circuit);
|
||||
|
||||
// load first channel values
|
||||
onCircuitStateInitial(this.circuit);
|
||||
return;
|
||||
}
|
||||
}
|
||||
onDeviceRemoved(device);
|
||||
}
|
||||
|
||||
private void checkCircuitInfoProperties(Circuit device) {
|
||||
boolean propertiesChanged = false;
|
||||
Map<String, String> properties = editProperties();
|
||||
// check device info
|
||||
if (device.getName() != null) {
|
||||
properties.put(DigitalSTROMBindingConstants.DEVICE_NAME, device.getName());
|
||||
propertiesChanged = true;
|
||||
}
|
||||
if (device.getDSUID() != null) {
|
||||
properties.put(DigitalSTROMBindingConstants.DEVICE_UID, device.getDSUID());
|
||||
propertiesChanged = true;
|
||||
}
|
||||
if (device.getHwName() != null) {
|
||||
properties.put(DigitalSTROMBindingConstants.HW_NAME, device.getHwName());
|
||||
propertiesChanged = true;
|
||||
}
|
||||
if (device.getHwVersionString() != null) {
|
||||
properties.put(DigitalSTROMBindingConstants.HW_VERSION, device.getHwVersionString());
|
||||
propertiesChanged = true;
|
||||
}
|
||||
if (device.getSwVersion() != null) {
|
||||
properties.put(DigitalSTROMBindingConstants.SW_VERSION, device.getSwVersion());
|
||||
propertiesChanged = true;
|
||||
}
|
||||
if (device.getApiVersion() != null) {
|
||||
properties.put(DigitalSTROMBindingConstants.API_VERSION, device.getApiVersion().toString());
|
||||
propertiesChanged = true;
|
||||
}
|
||||
if (device.getDspSwVersion() != null) {
|
||||
properties.put(DigitalSTROMBindingConstants.DSP_SW_VERSION, device.getDspSwVersion().toString());
|
||||
propertiesChanged = true;
|
||||
}
|
||||
if (device.getArmSwVersion() != null) {
|
||||
properties.put(DigitalSTROMBindingConstants.ARM_SW_VERSION, device.getArmSwVersion().toString());
|
||||
propertiesChanged = true;
|
||||
}
|
||||
if (propertiesChanged) {
|
||||
super.updateProperties(properties);
|
||||
propertiesChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void onCircuitStateInitial(Circuit circuit) {
|
||||
if (circuit != null) {
|
||||
for (CachedMeteringValue cachedMeterValue : circuit.getAllCachedMeteringValues()) {
|
||||
if (cachedMeterValue != null && MeteringUnitsEnum.WH.equals(cachedMeterValue.getMeteringUnit())) {
|
||||
String channelID = getChannelID(cachedMeterValue);
|
||||
if (isLinked(channelID)) {
|
||||
channelLinked(new ChannelUID(getThing().getUID(), channelID));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getChannelID(CachedMeteringValue cachedMeterValue) {
|
||||
return DsChannelTypeProvider.getMeteringChannelID(cachedMeterValue.getMeteringType(),
|
||||
cachedMeterValue.getMeteringUnit(), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelLinked(ChannelUID channelUID) {
|
||||
if (circuit != null) {
|
||||
MeteringTypeEnum meteringType = DsChannelTypeProvider.getMeteringType(channelUID.getId());
|
||||
double val = circuit.getMeteringValue(meteringType, MeteringUnitsEnum.WH);
|
||||
if (val > -1) {
|
||||
if (meteringType.equals(MeteringTypeEnum.ENERGY)) {
|
||||
updateState(channelUID, new DecimalType(val * 0.001));
|
||||
} else {
|
||||
updateState(channelUID, new DecimalType(val));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceConfigChanged(ChangeableDeviceConfigEnum whatConfig) {
|
||||
// nothing to do, will be registered again
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSceneConfigAdded(short sceneID) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDeviceStatusListenerID() {
|
||||
return this.dSID;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,977 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.handler;
|
||||
|
||||
import static org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.GeneralLibConstance;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.config.Config;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.DeviceStatusListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.Device;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.GeneralDeviceInformation;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.DeviceSceneSpec;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.DeviceStateUpdate;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.ChangeableDeviceConfigEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.DeviceBinarayInputEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.OutputModeEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.SensorEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.DeviceBinaryInput;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.DeviceStateUpdateImpl;
|
||||
import org.openhab.binding.digitalstrom.internal.providers.DsChannelTypeProvider;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.IncreaseDecreaseType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.library.types.StopMoveType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.library.types.UpDownType;
|
||||
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.ThingStatusDetail;
|
||||
import org.openhab.core.thing.ThingStatusInfo;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.builder.ChannelBuilder;
|
||||
import org.openhab.core.thing.binding.builder.ThingBuilder;
|
||||
import org.openhab.core.thing.type.ChannelTypeUID;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link DeviceHandler} is responsible for handling the configuration, load supported channels of a
|
||||
* digitalSTROM device and handling commands, which are sent to one of the channels. <br>
|
||||
* <br>
|
||||
* For that it uses the {@link BridgeHandler} and the {@link DeviceStateUpdate} mechanism of the {@link Device} to
|
||||
* execute the actual command and implements the {@link DeviceStatusListener} to get informed about changes from the
|
||||
* accompanying {@link Device}.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class DeviceHandler extends BaseThingHandler implements DeviceStatusListener {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(DeviceHandler.class);
|
||||
|
||||
/**
|
||||
* Contains all supported thing types of this handler, will be filled by DsDeviceThingTypeProvider.
|
||||
*/
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>();
|
||||
|
||||
public static final String TWO_STAGE_SWITCH_IDENTICATOR = "2";
|
||||
public static final String THREE_STAGE_SWITCH_IDENTICATOR = "3";
|
||||
|
||||
private String dSID;
|
||||
private Device device;
|
||||
private BridgeHandler dssBridgeHandler;
|
||||
|
||||
private Command lastComand;
|
||||
private String currentChannel;
|
||||
private List<String> loadedSensorChannels;
|
||||
|
||||
/**
|
||||
* Creates a new {@link DeviceHandler}.
|
||||
*
|
||||
* @param thing must not be null
|
||||
*/
|
||||
public DeviceHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("Initializing DeviceHandler.");
|
||||
if (StringUtils.isNotBlank((String) getConfig().get(DigitalSTROMBindingConstants.DEVICE_DSID))) {
|
||||
dSID = getConfig().get(DigitalSTROMBindingConstants.DEVICE_DSID).toString();
|
||||
final Bridge bridge = getBridge();
|
||||
if (bridge != null) {
|
||||
bridgeStatusChanged(bridge.getStatusInfo());
|
||||
} else {
|
||||
// Set status to OFFLINE if no bridge is available e.g. because the bridge has been removed and the
|
||||
// Thing was reinitialized.
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "Bridge is missing!");
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "dSID is missing");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("Handler disposed... unregister DeviceStatusListener");
|
||||
if (dSID != null) {
|
||||
if (dssBridgeHandler != null) {
|
||||
dssBridgeHandler.unregisterDeviceStatusListener(this);
|
||||
}
|
||||
}
|
||||
if (device != null) {
|
||||
device.setSensorDataRefreshPriority(Config.REFRESH_PRIORITY_NEVER, Config.REFRESH_PRIORITY_NEVER,
|
||||
Config.REFRESH_PRIORITY_NEVER);
|
||||
}
|
||||
device = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleRemoval() {
|
||||
if (getDssBridgeHandler() != null) {
|
||||
this.dssBridgeHandler.childThingRemoved(dSID);
|
||||
}
|
||||
updateStatus(ThingStatus.REMOVED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void thingUpdated(Thing thing) {
|
||||
this.thing = thing;
|
||||
if (device == null) {
|
||||
initialize();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
|
||||
if (bridgeStatusInfo.getStatus().equals(ThingStatus.ONLINE)) {
|
||||
if (dSID != null) {
|
||||
if (getDssBridgeHandler() != null) {
|
||||
if (device == null) {
|
||||
updateStatus(ThingStatus.ONLINE, ThingStatusDetail.CONFIGURATION_PENDING,
|
||||
"waiting for listener registration");
|
||||
dssBridgeHandler.registerDeviceStatusListener(this);
|
||||
} else {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE);
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "No dSID is set!");
|
||||
}
|
||||
}
|
||||
if (bridgeStatusInfo.getStatus().equals(ThingStatus.OFFLINE)) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
}
|
||||
if (bridgeStatusInfo.getStatus().equals(ThingStatus.REMOVED)) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "Bridge has been removed.");
|
||||
}
|
||||
logger.debug("Set status to {}", getThing().getStatusInfo());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
BridgeHandler dssBridgeHandler = getDssBridgeHandler();
|
||||
if (dssBridgeHandler == null) {
|
||||
logger.debug("BridgeHandler not found. Cannot handle command without bridge.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (device == null) {
|
||||
logger.debug(
|
||||
"Device not known on StructureManager or DeviceStatusListener is not registerd. Cannot handle command.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (command instanceof RefreshType) {
|
||||
try {
|
||||
SensorEnum sensorType = SensorEnum.valueOf(channelUID.getId());
|
||||
dssBridgeHandler.sendComandsToDSS(device, new DeviceStateUpdateImpl(sensorType, 1));
|
||||
} catch (IllegalArgumentException e) {
|
||||
dssBridgeHandler.sendComandsToDSS(device,
|
||||
new DeviceStateUpdateImpl(DeviceStateUpdate.REFRESH_OUTPUT, 0));
|
||||
}
|
||||
} else if (!device.isShade()) {
|
||||
if (DsChannelTypeProvider.isOutputChannel(channelUID.getId())) {
|
||||
if (command instanceof PercentType) {
|
||||
device.setOutputValue(
|
||||
(short) fromPercentToValue(((PercentType) command).intValue(), device.getMaxOutputValue()));
|
||||
} else if (command instanceof OnOffType) {
|
||||
if (OnOffType.ON.equals(command)) {
|
||||
device.setIsOn(true);
|
||||
} else {
|
||||
device.setIsOn(false);
|
||||
}
|
||||
} else if (command instanceof IncreaseDecreaseType) {
|
||||
if (IncreaseDecreaseType.INCREASE.equals(command)) {
|
||||
device.increase();
|
||||
} else {
|
||||
device.decrease();
|
||||
}
|
||||
} else if (command instanceof StringType) {
|
||||
device.setOutputValue(Short.parseShort(((StringType) command).toString()));
|
||||
}
|
||||
} else {
|
||||
logger.debug("Command sent to an unknown channel id: {}", channelUID);
|
||||
}
|
||||
} else {
|
||||
if (channelUID.getId().contains(DsChannelTypeProvider.ANGLE)) {
|
||||
if (command instanceof PercentType) {
|
||||
device.setAnglePosition(
|
||||
(short) fromPercentToValue(((PercentType) command).intValue(), device.getMaxSlatAngle()));
|
||||
} else if (command instanceof OnOffType) {
|
||||
if (OnOffType.ON.equals(command)) {
|
||||
device.setAnglePosition(device.getMaxSlatAngle());
|
||||
} else {
|
||||
device.setAnglePosition(device.getMinSlatAngle());
|
||||
}
|
||||
} else if (command instanceof IncreaseDecreaseType) {
|
||||
if (IncreaseDecreaseType.INCREASE.equals(command)) {
|
||||
device.increaseSlatAngle();
|
||||
} else {
|
||||
device.decreaseSlatAngle();
|
||||
}
|
||||
}
|
||||
} else if (channelUID.getId().contains(DsChannelTypeProvider.SHADE)) {
|
||||
if (command instanceof PercentType) {
|
||||
int percent = ((PercentType) command).intValue();
|
||||
if (!device.getHWinfo().equals("GR-KL200")) {
|
||||
percent = 100 - percent;
|
||||
}
|
||||
device.setSlatPosition(fromPercentToValue(percent, device.getMaxSlatPosition()));
|
||||
this.lastComand = command;
|
||||
} else if (command instanceof StopMoveType) {
|
||||
if (StopMoveType.MOVE.equals(command)) {
|
||||
handleCommand(channelUID, this.lastComand);
|
||||
} else {
|
||||
dssBridgeHandler.stopOutputValue(device);
|
||||
}
|
||||
} else if (command instanceof UpDownType) {
|
||||
if (UpDownType.UP.equals(command)) {
|
||||
device.setIsOpen(true);
|
||||
this.lastComand = command;
|
||||
} else {
|
||||
device.setIsOpen(false);
|
||||
this.lastComand = command;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.debug("Command sent to an unknown channel id: {}", channelUID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int fromPercentToValue(int percent, int max) {
|
||||
if (percent < 0 || percent == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (max < 0 || max == 0) {
|
||||
return 0;
|
||||
}
|
||||
return (int) (max * ((float) percent / 100));
|
||||
}
|
||||
|
||||
private synchronized BridgeHandler getDssBridgeHandler() {
|
||||
if (this.dssBridgeHandler == null) {
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge == null) {
|
||||
logger.debug("Bride cannot be found");
|
||||
return null;
|
||||
}
|
||||
ThingHandler handler = bridge.getHandler();
|
||||
|
||||
if (handler instanceof BridgeHandler) {
|
||||
dssBridgeHandler = (BridgeHandler) handler;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return dssBridgeHandler;
|
||||
}
|
||||
|
||||
private boolean sensorChannelsLoaded() {
|
||||
return loadedSensorChannels != null && !loadedSensorChannels.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onDeviceStateChanged(DeviceStateUpdate deviceStateUpdate) {
|
||||
if (device != null) {
|
||||
if (deviceStateUpdate != null) {
|
||||
if (sensorChannelsLoaded()) {
|
||||
if (deviceStateUpdate.isSensorUpdateType()) {
|
||||
updateState(getSensorChannelID(deviceStateUpdate.getTypeAsSensorEnum()),
|
||||
new DecimalType(deviceStateUpdate.getValueAsFloat()));
|
||||
logger.debug("Update ESH-State");
|
||||
return;
|
||||
}
|
||||
if (deviceStateUpdate.isBinarayInputType()) {
|
||||
if (deviceStateUpdate.getValueAsShort() == 1) {
|
||||
updateState(getBinaryInputChannelID(deviceStateUpdate.getTypeAsDeviceBinarayInputEnum()),
|
||||
OnOffType.ON);
|
||||
} else {
|
||||
updateState(getBinaryInputChannelID(deviceStateUpdate.getTypeAsDeviceBinarayInputEnum()),
|
||||
OnOffType.OFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!device.isShade()) {
|
||||
if (currentChannel != null) {
|
||||
switch (deviceStateUpdate.getType()) {
|
||||
case DeviceStateUpdate.OUTPUT_DECREASE:
|
||||
case DeviceStateUpdate.OUTPUT_INCREASE:
|
||||
case DeviceStateUpdate.OUTPUT:
|
||||
if (currentChannel.contains(DsChannelTypeProvider.DIMMER)) {
|
||||
if (deviceStateUpdate.getValueAsInteger() > 0) {
|
||||
updateState(currentChannel, new PercentType(fromValueToPercent(
|
||||
deviceStateUpdate.getValueAsInteger(), device.getMaxOutputValue())));
|
||||
} else {
|
||||
updateState(currentChannel, OnOffType.OFF);
|
||||
}
|
||||
} else if (currentChannel.contains(DsChannelTypeProvider.STAGE)) {
|
||||
if (currentChannel.contains(TWO_STAGE_SWITCH_IDENTICATOR)) {
|
||||
updateState(currentChannel,
|
||||
new StringType(convertStageValue((short) 2, device.getOutputValue())));
|
||||
} else {
|
||||
updateState(currentChannel,
|
||||
new StringType(convertStageValue((short) 3, device.getOutputValue())));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DeviceStateUpdate.ON_OFF:
|
||||
if (currentChannel.contains(DsChannelTypeProvider.STAGE)) {
|
||||
onDeviceStateChanged(new DeviceStateUpdateImpl(DeviceStateUpdate.OUTPUT,
|
||||
device.getOutputValue()));
|
||||
}
|
||||
if (deviceStateUpdate.getValueAsInteger() > 0) {
|
||||
updateState(currentChannel, OnOffType.ON);
|
||||
} else {
|
||||
updateState(currentChannel, OnOffType.OFF);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int percent = 0;
|
||||
switch (deviceStateUpdate.getType()) {
|
||||
case DeviceStateUpdate.SLAT_DECREASE:
|
||||
case DeviceStateUpdate.SLAT_INCREASE:
|
||||
case DeviceStateUpdate.SLATPOSITION:
|
||||
percent = fromValueToPercent(deviceStateUpdate.getValueAsInteger(),
|
||||
device.getMaxSlatPosition());
|
||||
break;
|
||||
case DeviceStateUpdate.OPEN_CLOSE:
|
||||
if (deviceStateUpdate.getValueAsInteger() > 0) {
|
||||
percent = 100;
|
||||
}
|
||||
break;
|
||||
case DeviceStateUpdate.OPEN_CLOSE_ANGLE:
|
||||
if (device.isBlind() && currentChannel != null) {
|
||||
if (deviceStateUpdate.getValueAsInteger() > 0) {
|
||||
updateState(currentChannel, PercentType.HUNDRED);
|
||||
} else {
|
||||
updateState(currentChannel, PercentType.ZERO);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case DeviceStateUpdate.SLAT_ANGLE_DECREASE:
|
||||
case DeviceStateUpdate.SLAT_ANGLE_INCREASE:
|
||||
case DeviceStateUpdate.SLAT_ANGLE:
|
||||
if (device.isBlind() && currentChannel != null) {
|
||||
updateState(currentChannel,
|
||||
new PercentType(fromValueToPercent(deviceStateUpdate.getValueAsInteger(),
|
||||
device.getMaxSlatAngle())));
|
||||
}
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if (!device.getHWinfo().equals("GR-KL210")) {
|
||||
percent = 100 - percent;
|
||||
}
|
||||
updateState(DsChannelTypeProvider.SHADE, new PercentType(percent));
|
||||
}
|
||||
logger.debug("Update ESH-State");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int fromValueToPercent(int value, int max) {
|
||||
if (value <= 0 || max <= 0) {
|
||||
return 0;
|
||||
}
|
||||
int percentValue = new BigDecimal(value * ((float) 100 / max)).setScale(0, BigDecimal.ROUND_HALF_UP).intValue();
|
||||
return percentValue < 0 ? 0 : percentValue > 100 ? 100 : percentValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onDeviceRemoved(GeneralDeviceInformation device) {
|
||||
if (device instanceof Device) {
|
||||
this.device = (Device) device;
|
||||
if (this.getThing().getStatus().equals(ThingStatus.ONLINE)) {
|
||||
if (!((Device) device).isPresent()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE,
|
||||
"Device is not present in the digitalSTROM-System.");
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE,
|
||||
"Device is not avaible in the digitalSTROM-System.");
|
||||
}
|
||||
|
||||
}
|
||||
logger.debug("Set status to {}", getThing().getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onDeviceAdded(GeneralDeviceInformation device) {
|
||||
if (device instanceof Device) {
|
||||
this.device = (Device) device;
|
||||
if (this.device.isPresent()) {
|
||||
ThingStatusInfo statusInfo = this.dssBridgeHandler.getThing().getStatusInfo();
|
||||
updateStatus(statusInfo.getStatus(), statusInfo.getStatusDetail(), statusInfo.getDescription());
|
||||
logger.debug("Set status to {}", getThing().getStatus());
|
||||
|
||||
// load scene configurations persistently into the thing
|
||||
for (Short i : this.device.getSavedScenes()) {
|
||||
onSceneConfigAdded(i);
|
||||
}
|
||||
logger.debug("Load saved scene specification into device");
|
||||
this.device.saveConfigSceneSpecificationIntoDevice(getThing().getProperties());
|
||||
|
||||
checkDeviceInfoProperties(this.device);
|
||||
// load sensor priorities into the device and load sensor channels of the thing
|
||||
if (!this.device.isShade()) {
|
||||
loadSensorChannels();
|
||||
// check and load output channel of the thing
|
||||
checkOutputChannel();
|
||||
} else if (this.device.isBlind()) {
|
||||
// load channel for set the angle of jalousie devices
|
||||
String channelTypeID = DsChannelTypeProvider.getOutputChannelTypeID(
|
||||
((Device) device).getFunctionalColorGroup(), ((Device) device).getOutputMode());
|
||||
loadOutputChannel(new ChannelTypeUID(BINDING_ID, channelTypeID),
|
||||
DsChannelTypeProvider.getItemType(channelTypeID));
|
||||
}
|
||||
|
||||
// load first channel values
|
||||
onDeviceStateInitial(this.device);
|
||||
return;
|
||||
}
|
||||
}
|
||||
onDeviceRemoved(device);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates device info properties.
|
||||
*
|
||||
* @param device (must not be null)
|
||||
*/
|
||||
private void checkDeviceInfoProperties(Device device) {
|
||||
boolean propertiesChanged = false;
|
||||
Map<String, String> properties = editProperties();
|
||||
// check device info
|
||||
if (device.getName() != null) {
|
||||
properties.put(DigitalSTROMBindingConstants.DEVICE_NAME, device.getName());
|
||||
propertiesChanged = true;
|
||||
}
|
||||
if (device.getDSUID() != null) {
|
||||
properties.put(DigitalSTROMBindingConstants.DEVICE_UID, device.getDSUID());
|
||||
propertiesChanged = true;
|
||||
}
|
||||
if (device.getHWinfo() != null) {
|
||||
properties.put(DigitalSTROMBindingConstants.DEVICE_HW_INFO, device.getHWinfo());
|
||||
propertiesChanged = true;
|
||||
}
|
||||
if (device.getZoneId() != -1) {
|
||||
properties.put(DigitalSTROMBindingConstants.DEVICE_ZONE_ID, device.getZoneId() + "");
|
||||
propertiesChanged = true;
|
||||
}
|
||||
if (device.getGroups() != null) {
|
||||
properties.put(DigitalSTROMBindingConstants.DEVICE_GROUPS, device.getGroups().toString());
|
||||
propertiesChanged = true;
|
||||
}
|
||||
if (device.getOutputMode() != null) {
|
||||
properties.put(DigitalSTROMBindingConstants.DEVICE_OUTPUT_MODE, device.getOutputMode().toString());
|
||||
propertiesChanged = true;
|
||||
}
|
||||
if (device.getFunctionalColorGroup() != null) {
|
||||
properties.put(DigitalSTROMBindingConstants.DEVICE_FUNCTIONAL_COLOR_GROUP,
|
||||
device.getFunctionalColorGroup().toString());
|
||||
propertiesChanged = true;
|
||||
}
|
||||
if (device.getMeterDSID() != null) {
|
||||
properties.put(DigitalSTROMBindingConstants.DEVICE_METER_ID, device.getMeterDSID().toString());
|
||||
propertiesChanged = true;
|
||||
}
|
||||
if (!device.getBinaryInputs().isEmpty()) {
|
||||
properties.put(DigitalSTROMBindingConstants.DEVICE_BINARAY_INPUTS, getBinarayInputList());
|
||||
propertiesChanged = true;
|
||||
}
|
||||
if (propertiesChanged) {
|
||||
super.updateProperties(properties);
|
||||
propertiesChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
private String getBinarayInputList() {
|
||||
List<String> binarayInputs = new ArrayList<>(device.getBinaryInputs().size());
|
||||
for (DeviceBinaryInput binInput : device.getBinaryInputs()) {
|
||||
DeviceBinarayInputEnum devBinInp = DeviceBinarayInputEnum.getdeviceBinarayInput(binInput.getInputType());
|
||||
if (devBinInp != null) {
|
||||
binarayInputs.add(devBinInp.toString().toLowerCase());
|
||||
}
|
||||
}
|
||||
return binarayInputs.toString();
|
||||
}
|
||||
|
||||
private void loadSensorChannels() {
|
||||
if (device != null && device.isPresent()) {
|
||||
// load sensor priorities into the device
|
||||
boolean configChanged = false;
|
||||
Configuration config = getThing().getConfiguration();
|
||||
logger.debug("Add sensor priorities to the device");
|
||||
|
||||
String activePowerPrio = Config.REFRESH_PRIORITY_NEVER;
|
||||
if (config.get(DigitalSTROMBindingConstants.ACTIVE_POWER_REFRESH_PRIORITY) != null) {
|
||||
activePowerPrio = config.get(DigitalSTROMBindingConstants.ACTIVE_POWER_REFRESH_PRIORITY).toString();
|
||||
} else {
|
||||
config.put(DigitalSTROMBindingConstants.ACTIVE_POWER_REFRESH_PRIORITY, Config.REFRESH_PRIORITY_NEVER);
|
||||
configChanged = true;
|
||||
}
|
||||
// By devices with output mode WIPE the active power always will be read out to check, if the device is not
|
||||
// in standby any more.
|
||||
if (OutputModeEnum.WIPE.equals(device.getOutputMode())
|
||||
&& activePowerPrio.equals(Config.REFRESH_PRIORITY_NEVER)) {
|
||||
config.put(DigitalSTROMBindingConstants.ACTIVE_POWER_REFRESH_PRIORITY, Config.REFRESH_PRIORITY_LOW);
|
||||
configChanged = true;
|
||||
}
|
||||
|
||||
String outputCurrentPrio = Config.REFRESH_PRIORITY_NEVER;
|
||||
if (config.get(DigitalSTROMBindingConstants.OUTPUT_CURRENT_REFRESH_PRIORITY) != null) {
|
||||
outputCurrentPrio = config.get(DigitalSTROMBindingConstants.OUTPUT_CURRENT_REFRESH_PRIORITY).toString();
|
||||
} else {
|
||||
config.put(DigitalSTROMBindingConstants.OUTPUT_CURRENT_REFRESH_PRIORITY, Config.REFRESH_PRIORITY_NEVER);
|
||||
configChanged = true;
|
||||
}
|
||||
|
||||
String electricMeterPrio = Config.REFRESH_PRIORITY_NEVER;
|
||||
if (config.get(DigitalSTROMBindingConstants.ELECTRIC_METER_REFRESH_PRIORITY) != null) {
|
||||
electricMeterPrio = config.get(DigitalSTROMBindingConstants.ELECTRIC_METER_REFRESH_PRIORITY).toString();
|
||||
} else {
|
||||
config.put(DigitalSTROMBindingConstants.ELECTRIC_METER_REFRESH_PRIORITY, Config.REFRESH_PRIORITY_NEVER);
|
||||
configChanged = true;
|
||||
}
|
||||
|
||||
if (configChanged) {
|
||||
super.updateConfiguration(config);
|
||||
configChanged = false;
|
||||
}
|
||||
|
||||
device.setSensorDataRefreshPriority(activePowerPrio, electricMeterPrio, outputCurrentPrio);
|
||||
logger.debug(
|
||||
"add sensor prioritys: active power = {}, output current = {}, electric meter = {} to device with id {}",
|
||||
activePowerPrio, outputCurrentPrio, electricMeterPrio, device.getDSID());
|
||||
|
||||
// check and load sensor channels of the thing
|
||||
checkSensorChannel();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean addLoadedSensorChannel(String sensorChannelType) {
|
||||
if (loadedSensorChannels == null) {
|
||||
loadedSensorChannels = new LinkedList<>();
|
||||
}
|
||||
if (!loadedSensorChannels.contains(sensorChannelType.toString())) {
|
||||
return loadedSensorChannels.add(sensorChannelType.toString());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean removeLoadedSensorChannel(String sensorChannelType) {
|
||||
if (loadedSensorChannels == null) {
|
||||
return false;
|
||||
}
|
||||
return loadedSensorChannels.remove(sensorChannelType);
|
||||
}
|
||||
|
||||
private boolean isSensorChannelLoaded(String sensorChannelType) {
|
||||
if (loadedSensorChannels == null) {
|
||||
return false;
|
||||
}
|
||||
return loadedSensorChannels.contains(sensorChannelType);
|
||||
}
|
||||
|
||||
private void checkSensorChannel() {
|
||||
List<Channel> channelList = new LinkedList<>(this.getThing().getChannels());
|
||||
|
||||
boolean channelListChanged = false;
|
||||
|
||||
// if sensor channels with priority never are loaded delete these channels
|
||||
if (!channelList.isEmpty()) {
|
||||
Iterator<Channel> channelInter = channelList.iterator();
|
||||
while (channelInter.hasNext()) {
|
||||
Channel channel = channelInter.next();
|
||||
String channelID = channel.getUID().getId();
|
||||
if (channelID.startsWith(DsChannelTypeProvider.BINARY_INPUT_PRE)) {
|
||||
DeviceBinarayInputEnum devBinInput = getBinaryInput(channelID);
|
||||
if (device.getBinaryInput(devBinInput) != null) {
|
||||
addLoadedSensorChannel(channelID);
|
||||
} else {
|
||||
logger.debug("remove {} binary input channel", channelID);
|
||||
channelInter.remove();
|
||||
channelListChanged = removeLoadedSensorChannel(channelID);
|
||||
}
|
||||
} else {
|
||||
SensorEnum sensorType = getSensorEnum(channelID);
|
||||
if (sensorType != null) {
|
||||
if (SensorEnum.isPowerSensor(sensorType)) {
|
||||
if (device.checkPowerSensorRefreshPriorityNever(sensorType)) {
|
||||
logger.debug("remove {} sensor channel", channelID);
|
||||
channelInter.remove();
|
||||
channelListChanged = removeLoadedSensorChannel(channelID);
|
||||
} else {
|
||||
addLoadedSensorChannel(channelID);
|
||||
}
|
||||
} else {
|
||||
if (device.supportsSensorType(sensorType)) {
|
||||
addLoadedSensorChannel(channelID);
|
||||
} else {
|
||||
logger.debug("remove {} sensor channel", channelID);
|
||||
channelInter.remove();
|
||||
removeLoadedSensorChannel(channelID);
|
||||
channelListChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (SensorEnum sensorType : device.getPowerSensorTypes()) {
|
||||
if (!device.checkPowerSensorRefreshPriorityNever(sensorType)
|
||||
&& !isSensorChannelLoaded(getSensorChannelID(sensorType))) {
|
||||
logger.debug("create {} sensor channel", sensorType.toString());
|
||||
channelList.add(getSensorChannel(sensorType));
|
||||
channelListChanged = addLoadedSensorChannel(getSensorChannelID(sensorType));
|
||||
}
|
||||
}
|
||||
if (device.hasClimateSensors()) {
|
||||
for (SensorEnum sensorType : device.getClimateSensorTypes()) {
|
||||
if (!isSensorChannelLoaded(getSensorChannelID(sensorType))) {
|
||||
logger.debug("create {} sensor channel", sensorType.toString());
|
||||
channelList.add(getSensorChannel(sensorType));
|
||||
channelListChanged = addLoadedSensorChannel(getSensorChannelID(sensorType));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (device.isBinaryInputDevice()) {
|
||||
for (DeviceBinaryInput binInput : device.getBinaryInputs()) {
|
||||
DeviceBinarayInputEnum binInputType = DeviceBinarayInputEnum
|
||||
.getdeviceBinarayInput(binInput.getInputType());
|
||||
if (binInputType != null && !isSensorChannelLoaded(getBinaryInputChannelID(binInputType))) {
|
||||
logger.debug("create {} sensor channel", binInputType.toString());
|
||||
channelList.add(getBinaryChannel(binInputType));
|
||||
channelListChanged = addLoadedSensorChannel(getBinaryInputChannelID(binInputType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (channelListChanged) {
|
||||
logger.debug("load new channel list");
|
||||
ThingBuilder thingBuilder = editThing();
|
||||
thingBuilder.withChannels(channelList);
|
||||
updateThing(thingBuilder.build());
|
||||
}
|
||||
}
|
||||
|
||||
private Channel getSensorChannel(SensorEnum sensorType) {
|
||||
return ChannelBuilder.create(getSensorChannelUID(sensorType), "Number")
|
||||
.withType(DsChannelTypeProvider.getSensorChannelUID(sensorType)).build();
|
||||
}
|
||||
|
||||
private Channel getBinaryChannel(DeviceBinarayInputEnum binaryInputType) {
|
||||
return ChannelBuilder.create(getBinaryInputChannelUID(binaryInputType), "Switch")
|
||||
.withType(DsChannelTypeProvider.getBinaryInputChannelUID(binaryInputType)).build();
|
||||
}
|
||||
|
||||
private void checkOutputChannel() {
|
||||
if (device == null) {
|
||||
logger.debug("Can not load a channel without a device!");
|
||||
return;
|
||||
}
|
||||
// if the device have no output channel or it is disabled all output channels will be deleted
|
||||
if (!device.isDeviceWithOutput()) {
|
||||
loadOutputChannel(null, null);
|
||||
}
|
||||
String channelTypeID = DsChannelTypeProvider.getOutputChannelTypeID(device.getFunctionalColorGroup(),
|
||||
device.getOutputMode());
|
||||
logger.debug("load channel: typeID={}, itemType={}",
|
||||
DsChannelTypeProvider.getOutputChannelTypeID(device.getFunctionalColorGroup(), device.getOutputMode()),
|
||||
DsChannelTypeProvider.getItemType(channelTypeID));
|
||||
if (channelTypeID != null && (currentChannel == null || !currentChannel.equals(channelTypeID))) {
|
||||
loadOutputChannel(new ChannelTypeUID(BINDING_ID, channelTypeID),
|
||||
DsChannelTypeProvider.getItemType(channelTypeID));
|
||||
}
|
||||
}
|
||||
|
||||
private void loadOutputChannel(ChannelTypeUID channelTypeUID, String acceptedItemType) {
|
||||
if (channelTypeUID == null || acceptedItemType == null) {
|
||||
return;
|
||||
}
|
||||
currentChannel = channelTypeUID.getId();
|
||||
|
||||
List<Channel> channelList = new LinkedList<>(this.getThing().getChannels());
|
||||
boolean channelIsAlreadyLoaded = false;
|
||||
boolean channelListChanged = false;
|
||||
|
||||
if (!channelList.isEmpty()) {
|
||||
Iterator<Channel> channelInter = channelList.iterator();
|
||||
while (channelInter.hasNext()) {
|
||||
Channel eshChannel = channelInter.next();
|
||||
if (DsChannelTypeProvider.isOutputChannel(eshChannel.getUID().getId())) {
|
||||
if (!eshChannel.getUID().getId().equals(currentChannel)
|
||||
&& !(device.isShade() && eshChannel.getUID().getId().equals(DsChannelTypeProvider.SHADE))) {
|
||||
channelInter.remove();
|
||||
channelListChanged = true;
|
||||
} else {
|
||||
if (!eshChannel.getUID().getId().equals(DsChannelTypeProvider.SHADE)) {
|
||||
channelIsAlreadyLoaded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!channelIsAlreadyLoaded && currentChannel != null) {
|
||||
Channel channel = ChannelBuilder
|
||||
.create(new ChannelUID(this.getThing().getUID(), channelTypeUID.getId()), acceptedItemType)
|
||||
.withType(channelTypeUID).build();
|
||||
channelList.add(channel);
|
||||
channelListChanged = true;
|
||||
}
|
||||
|
||||
if (channelListChanged) {
|
||||
ThingBuilder thingBuilder = editThing();
|
||||
thingBuilder.withChannels(channelList);
|
||||
updateThing(thingBuilder.build());
|
||||
logger.debug("load channel: {} with item: {}", channelTypeUID.getAsString(), acceptedItemType);
|
||||
}
|
||||
}
|
||||
|
||||
private ChannelUID getSensorChannelUID(SensorEnum sensorType) {
|
||||
return new ChannelUID(getThing().getUID(), getSensorChannelID(sensorType));
|
||||
}
|
||||
|
||||
private String getSensorChannelID(SensorEnum sensorType) {
|
||||
return sensorType.toString().toLowerCase();
|
||||
}
|
||||
|
||||
private ChannelUID getBinaryInputChannelUID(DeviceBinarayInputEnum binaryInputType) {
|
||||
return new ChannelUID(getThing().getUID(), getBinaryInputChannelID(binaryInputType));
|
||||
}
|
||||
|
||||
private String getBinaryInputChannelID(DeviceBinarayInputEnum binaryInputType) {
|
||||
return DsChannelTypeProvider.BINARY_INPUT_PRE + binaryInputType.toString().toLowerCase();
|
||||
}
|
||||
|
||||
private DeviceBinarayInputEnum getBinaryInput(String channelID) {
|
||||
try {
|
||||
return DeviceBinarayInputEnum
|
||||
.valueOf(channelID.replace(DsChannelTypeProvider.BINARY_INPUT_PRE, "").toUpperCase());
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private SensorEnum getSensorEnum(String channelID) {
|
||||
try {
|
||||
return SensorEnum.valueOf(channelID.toUpperCase());
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelLinked(ChannelUID channelUID) {
|
||||
if (device != null) {
|
||||
SensorEnum sensorType = getSensorEnum(channelUID.getId());
|
||||
if (sensorType != null) {
|
||||
Float val = device.getFloatSensorValue(sensorType);
|
||||
if (val != null) {
|
||||
updateState(channelUID, new DecimalType(val));
|
||||
}
|
||||
}
|
||||
Short val = device.getBinaryInputState(getBinaryInput(channelUID.getId()));
|
||||
if (val != null) {
|
||||
if (val == 1) {
|
||||
updateState(channelUID, OnOffType.ON);
|
||||
} else {
|
||||
updateState(channelUID, OnOffType.OFF);
|
||||
}
|
||||
}
|
||||
|
||||
if (channelUID.getId().contains(DsChannelTypeProvider.DIMMER)) {
|
||||
if (device.isOn()) {
|
||||
updateState(channelUID,
|
||||
new PercentType(fromValueToPercent(device.getOutputValue(), device.getMaxOutputValue())));
|
||||
} else {
|
||||
updateState(channelUID, new PercentType(0));
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (channelUID.getId().contains(DsChannelTypeProvider.SWITCH)) {
|
||||
if (device.isOn()) {
|
||||
updateState(channelUID, OnOffType.ON);
|
||||
} else {
|
||||
updateState(channelUID, OnOffType.OFF);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (channelUID.getId().contains(DsChannelTypeProvider.SHADE)) {
|
||||
updateState(channelUID,
|
||||
new PercentType(fromValueToPercent(device.getSlatPosition(), device.getMaxSlatPosition())));
|
||||
return;
|
||||
}
|
||||
if (channelUID.getId().contains(DsChannelTypeProvider.ANGLE)) {
|
||||
updateState(channelUID,
|
||||
new PercentType(fromValueToPercent(device.getAnglePosition(), device.getMaxSlatAngle())));
|
||||
return;
|
||||
}
|
||||
if (channelUID.getId().contains(DsChannelTypeProvider.STAGE)) {
|
||||
if (channelUID.getId().contains(TWO_STAGE_SWITCH_IDENTICATOR)) {
|
||||
updateState(channelUID, new StringType(convertStageValue((short) 2, device.getOutputValue())));
|
||||
return;
|
||||
}
|
||||
if (channelUID.getId().contains(THREE_STAGE_SWITCH_IDENTICATOR)) {
|
||||
updateState(channelUID, new StringType(convertStageValue((short) 3, device.getOutputValue())));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String convertStageValue(short stage, short value) {
|
||||
switch (stage) {
|
||||
case 2:
|
||||
if (value < 85) {
|
||||
return OPTION_COMBINED_BOTH_OFF;
|
||||
} else if (value >= 85 && value < 170) {
|
||||
return OPTION_COMBINED_FIRST_ON;
|
||||
} else if (value >= 170 && value <= 255) {
|
||||
return OPTION_COMBINED_BOTH_ON;
|
||||
}
|
||||
case 3:
|
||||
if (value < 64) {
|
||||
return OPTION_COMBINED_BOTH_OFF;
|
||||
} else if (value >= 64 && value < 128) {
|
||||
return OPTION_COMBINED_FIRST_ON;
|
||||
} else if (value >= 128 && value < 192) {
|
||||
return OPTION_COMBINED_SECOND_ON;
|
||||
} else if (value >= 192 && value <= 255) {
|
||||
return OPTION_COMBINED_BOTH_ON;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void onDeviceStateInitial(Device device) {
|
||||
if (device != null) {
|
||||
if (currentChannel != null) {
|
||||
if (isLinked(currentChannel)) {
|
||||
channelLinked(new ChannelUID(getThing().getUID(), currentChannel));
|
||||
}
|
||||
}
|
||||
if (!device.isShade()) {
|
||||
if (loadedSensorChannels != null) {
|
||||
for (String sensor : loadedSensorChannels) {
|
||||
Channel channel = getThing().getChannel(sensor);
|
||||
if (channel != null && isLinked(sensor)) {
|
||||
channelLinked(channel.getUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (isLinked(DsChannelTypeProvider.SHADE)) {
|
||||
channelLinked(new ChannelUID(getThing().getUID(), DsChannelTypeProvider.SHADE));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onSceneConfigAdded(short sceneId) {
|
||||
if (device != null) {
|
||||
String saveScene = "";
|
||||
DeviceSceneSpec sceneSpec = device.getSceneConfig(sceneId);
|
||||
if (sceneSpec != null) {
|
||||
saveScene = sceneSpec.toString();
|
||||
}
|
||||
|
||||
Integer[] sceneValue = device.getSceneOutputValue(sceneId);
|
||||
if (sceneValue[GeneralLibConstance.SCENE_ARRAY_INDEX_VALUE] != -1) {
|
||||
saveScene = saveScene + ", sceneValue: " + sceneValue[0];
|
||||
}
|
||||
if (sceneValue[GeneralLibConstance.SCENE_ARRAY_INDEX_ANGLE] != -1) {
|
||||
saveScene = saveScene + ", sceneAngle: " + sceneValue[1];
|
||||
}
|
||||
String key = DigitalSTROMBindingConstants.DEVICE_SCENE + sceneId;
|
||||
if (!saveScene.isEmpty()) {
|
||||
logger.debug("Save scene configuration: [{}] to thing with UID {}", saveScene, getThing().getUID());
|
||||
super.updateProperty(key, saveScene);
|
||||
// persist the new property
|
||||
// super.updateThing(editThing().build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceConfigChanged(ChangeableDeviceConfigEnum whichConfig) {
|
||||
if (whichConfig != null) {
|
||||
switch (whichConfig) {
|
||||
case DEVICE_NAME:
|
||||
super.updateProperty(DEVICE_NAME, device.getName());
|
||||
break;
|
||||
case METER_DSID:
|
||||
super.updateProperty(DEVICE_METER_ID, device.getMeterDSID().getValue());
|
||||
break;
|
||||
case ZONE_ID:
|
||||
super.updateProperty(DEVICE_ZONE_ID, device.getZoneId() + "");
|
||||
break;
|
||||
case GROUPS:
|
||||
super.updateProperty(DEVICE_GROUPS, device.getGroups().toString());
|
||||
break;
|
||||
case FUNCTIONAL_GROUP:
|
||||
super.updateProperty(DEVICE_FUNCTIONAL_COLOR_GROUP, device.getFunctionalColorGroup().toString());
|
||||
checkOutputChannel();
|
||||
break;
|
||||
case OUTPUT_MODE:
|
||||
super.updateProperty(DEVICE_OUTPUT_MODE, device.getOutputMode().toString());
|
||||
checkOutputChannel();
|
||||
break;
|
||||
case BINARY_INPUTS:
|
||||
super.updateProperty(DEVICE_BINARAY_INPUTS, getBinarayInputList());
|
||||
checkSensorChannel();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDeviceStatusListenerID() {
|
||||
return this.dSID;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,367 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.handler;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.SceneStatusListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.StructureManager;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.scene.InternalScene;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.scene.constants.SceneEnum;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
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.ThingTypeUID;
|
||||
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 SceneHandler} is responsible for handling commands, which are sent to the channel of an
|
||||
* DigitalSTROM-Scene.<br>
|
||||
* For that it uses the {@link BridgeHandler} to execute the actual command and implements the
|
||||
* {@link SceneStatusListener} to get informed about changes from the accompanying {@link InternalScene}.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class SceneHandler extends BaseThingHandler implements SceneStatusListener {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(SceneHandler.class);
|
||||
/**
|
||||
* Contains all supported thing types of this handler.
|
||||
*/
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(Arrays.asList(
|
||||
DigitalSTROMBindingConstants.THING_TYPE_APP_SCENE, DigitalSTROMBindingConstants.THING_TYPE_GROUP_SCENE,
|
||||
DigitalSTROMBindingConstants.THING_TYPE_ZONE_SCENE, DigitalSTROMBindingConstants.THING_TYPE_NAMED_SCENE));
|
||||
|
||||
/**
|
||||
* Configured scene does not exist or cannot be used.
|
||||
*/
|
||||
public static final String SCENE_WRONG = "sceneWrong";
|
||||
/**
|
||||
* Configured zone does not exist.
|
||||
*/
|
||||
public static final String ZONE_WRONG = "zoneWrong";
|
||||
/**
|
||||
* Configured group does not exist.
|
||||
*/
|
||||
public static final String GROUP_WRONG = "groupWrong";
|
||||
/**
|
||||
* StructureManager in BridgeHandler is null
|
||||
*/
|
||||
public static final String NO_STRUC_MAN = "noStrucMan";
|
||||
/**
|
||||
* Configured scene is null.
|
||||
*/
|
||||
public static final String NO_SCENE = "noScene";
|
||||
/**
|
||||
* BridgeHandler is null.
|
||||
*/
|
||||
public static final String NO_BRIDGE = "noBridge";
|
||||
|
||||
private BridgeHandler bridgeHandler;
|
||||
private InternalScene scene;
|
||||
private String sceneThingID;
|
||||
|
||||
/**
|
||||
* Creates a new {@link SceneHandler}.
|
||||
*
|
||||
* @param thing must not be null
|
||||
*/
|
||||
public SceneHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("Initializing SceneHandler");
|
||||
final Bridge bridge = getBridge();
|
||||
if (bridge != null) {
|
||||
bridgeStatusChanged(bridge.getStatusInfo());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("Handler disposed... unregistering SceneStatusListener");
|
||||
if (sceneThingID != null) {
|
||||
BridgeHandler dssBridgeHandler = getBridgeHandler();
|
||||
if (dssBridgeHandler != null) {
|
||||
getBridgeHandler().unregisterSceneStatusListener(this);
|
||||
}
|
||||
sceneThingID = null;
|
||||
scene = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleRemoval() {
|
||||
if (getBridgeHandler() != null) {
|
||||
this.bridgeHandler.childThingRemoved(sceneThingID);
|
||||
}
|
||||
updateStatus(ThingStatus.REMOVED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
|
||||
if (bridgeStatusInfo.getStatus().equals(ThingStatus.ONLINE)) {
|
||||
if (getBridgeHandler() != null) {
|
||||
if (scene == null) {
|
||||
String sceneID = getSceneID(getConfig(), bridgeHandler);
|
||||
switch (sceneID) {
|
||||
case SCENE_WRONG:
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"Configured scene '" + getConfig().get(DigitalSTROMBindingConstants.SCENE_ID)
|
||||
+ "' does not exist or cannot be used, please check the configuration.");
|
||||
break;
|
||||
case ZONE_WRONG:
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"Configured zone '" + getConfig().get(DigitalSTROMBindingConstants.ZONE_ID)
|
||||
+ "' does not exist, please check the configuration.");
|
||||
break;
|
||||
case GROUP_WRONG:
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"Configured group '" + getConfig().get(DigitalSTROMBindingConstants.GROUP_ID)
|
||||
+ "' does not exist, please check the configuration.");
|
||||
break;
|
||||
case NO_STRUC_MAN:
|
||||
updateStatus(ThingStatus.ONLINE, ThingStatusDetail.CONFIGURATION_PENDING,
|
||||
"Waiting for building digitalSTROM model.");
|
||||
break;
|
||||
case NO_SCENE:
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"No Scene-ID is set!");
|
||||
break;
|
||||
default:
|
||||
this.sceneThingID = sceneID;
|
||||
updateStatus(ThingStatus.ONLINE, ThingStatusDetail.CONFIGURATION_PENDING,
|
||||
"Waiting for listener registration");
|
||||
logger.debug("Set status on {}", getThing().getStatus());
|
||||
this.bridgeHandler.registerSceneStatusListener(this);
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE);
|
||||
}
|
||||
}
|
||||
if (bridgeStatusInfo.getStatus().equals(ThingStatus.OFFLINE)) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
}
|
||||
if (bridgeStatusInfo.getStatus().equals(ThingStatus.REMOVED)) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "Bridge has been removed.");
|
||||
}
|
||||
logger.debug("Set status to {}", getThing().getStatusInfo());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the configuration and returns a unique Scene-ID or error string.<br>
|
||||
* The {@link StructureManager} of the {@link BridgeHandler} is used for checking the existing configured zone and
|
||||
* group. The {@link SceneEnum} will be used to check, if the configured scene exists and is allowed to use.<br>
|
||||
* If the check succeed the scene-ID will be returned in format "[zoneID]-[groupID]-[SceneID]", otherwise one of the
|
||||
* following errors {@link String}s will returned:
|
||||
* <ul>
|
||||
* <li>{@link #SCENE_WRONG}: Configured scene does not exist or cannot be used.</li>
|
||||
* <li>{@link #ZONE_WRONG} Configured zone does not exist.</li>
|
||||
* <li>{@link #GROUP_WRONG}: Configured group does not exist.</li>
|
||||
* <li>{@link #NO_STRUC_MAN}: StructureManager in BridgeHandler is null.</li>
|
||||
* <li>{@link #NO_SCENE}: Configured scene is null.</li>
|
||||
* <li>{@link #NO_BRIDGE}: BridgeHandler is null.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param configuration (must not be null)
|
||||
* @param bridgeHandler (can be null)
|
||||
* @return unique Scene-ID or error string
|
||||
*/
|
||||
public static String getSceneID(Configuration configuration, BridgeHandler bridgeHandler) {
|
||||
if (configuration == null) {
|
||||
throw new IllegalArgumentException("configuration cannot be null");
|
||||
}
|
||||
if (bridgeHandler == null) {
|
||||
return NO_BRIDGE;
|
||||
}
|
||||
String configZoneID;
|
||||
String configGroupID;
|
||||
String configSceneID;
|
||||
|
||||
short sceneID;
|
||||
int zoneID;
|
||||
short groupID;
|
||||
|
||||
if (configuration.get(DigitalSTROMBindingConstants.ZONE_ID) != null) {
|
||||
configZoneID = configuration.get(DigitalSTROMBindingConstants.ZONE_ID).toString();
|
||||
} else {
|
||||
configZoneID = "";
|
||||
}
|
||||
if (configuration.get(DigitalSTROMBindingConstants.GROUP_ID) != null) {
|
||||
configGroupID = configuration.get(DigitalSTROMBindingConstants.GROUP_ID).toString();
|
||||
} else {
|
||||
configGroupID = "";
|
||||
}
|
||||
if (configuration.get(DigitalSTROMBindingConstants.SCENE_ID) != null) {
|
||||
configSceneID = configuration.get(DigitalSTROMBindingConstants.SCENE_ID).toString();
|
||||
} else {
|
||||
configSceneID = "";
|
||||
}
|
||||
if (!configSceneID.isEmpty()) {
|
||||
try {
|
||||
sceneID = Short.parseShort(configSceneID);
|
||||
if (!SceneEnum.containsScene(sceneID)) {
|
||||
return SCENE_WRONG;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
try {
|
||||
sceneID = SceneEnum.valueOf(configSceneID.replace(" ", "_").toUpperCase()).getSceneNumber();
|
||||
} catch (IllegalArgumentException e1) {
|
||||
return SCENE_WRONG;
|
||||
}
|
||||
}
|
||||
|
||||
StructureManager strucMan = bridgeHandler.getStructureManager();
|
||||
if (strucMan != null) {
|
||||
if (configZoneID.isEmpty()) {
|
||||
zoneID = 0;
|
||||
} else {
|
||||
try {
|
||||
zoneID = Integer.parseInt(configZoneID);
|
||||
if (!strucMan.checkZoneID(zoneID)) {
|
||||
return ZONE_WRONG;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
zoneID = strucMan.getZoneId(configZoneID);
|
||||
if (zoneID == -1) {
|
||||
return ZONE_WRONG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (configGroupID.isEmpty()) {
|
||||
groupID = 0;
|
||||
} else {
|
||||
try {
|
||||
groupID = Short.parseShort(configGroupID);
|
||||
if (!strucMan.checkZoneGroupID(zoneID, groupID)) {
|
||||
return GROUP_WRONG;
|
||||
}
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
String zoneName = strucMan.getZoneName(zoneID);
|
||||
groupID = strucMan.getZoneGroupId(zoneName, configGroupID);
|
||||
}
|
||||
|
||||
if (groupID == -1) {
|
||||
return GROUP_WRONG;
|
||||
}
|
||||
}
|
||||
return zoneID + "-" + groupID + "-" + sceneID;
|
||||
} else {
|
||||
return NO_STRUC_MAN;
|
||||
}
|
||||
} else {
|
||||
return NO_SCENE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
BridgeHandler dssBridgeHandler = getBridgeHandler();
|
||||
if (dssBridgeHandler == null) {
|
||||
logger.debug("BridgeHandler not found. Cannot handle command without bridge.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (channelUID.getId().equals(DigitalSTROMBindingConstants.CHANNEL_ID_SCENE)) {
|
||||
if (command instanceof OnOffType) {
|
||||
if (OnOffType.ON.equals(command)) {
|
||||
this.bridgeHandler.sendSceneComandToDSS(scene, true);
|
||||
} else {
|
||||
this.bridgeHandler.sendSceneComandToDSS(scene, false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.warn("Command sent to an unknown channel id: {}", channelUID);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized BridgeHandler getBridgeHandler() {
|
||||
if (this.bridgeHandler == null) {
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge == null) {
|
||||
logger.debug("Bridge cannot be found");
|
||||
return null;
|
||||
}
|
||||
ThingHandler handler = bridge.getHandler();
|
||||
|
||||
if (handler instanceof BridgeHandler) {
|
||||
this.bridgeHandler = (BridgeHandler) handler;
|
||||
} else {
|
||||
logger.debug("BridgeHandler cannot be found");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return this.bridgeHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSceneStateChanged(boolean flag) {
|
||||
if (flag) {
|
||||
updateState(DigitalSTROMBindingConstants.CHANNEL_ID_SCENE, OnOffType.ON);
|
||||
} else {
|
||||
updateState(DigitalSTROMBindingConstants.CHANNEL_ID_SCENE, OnOffType.OFF);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelLinked(ChannelUID channelUID) {
|
||||
if (scene != null && channelUID.getId().equals(DigitalSTROMBindingConstants.CHANNEL_ID_SCENE)) {
|
||||
onSceneStateChanged(scene.isActive());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSceneRemoved(InternalScene scene) {
|
||||
this.scene = scene;
|
||||
updateStatus(ThingStatus.OFFLINE);
|
||||
logger.debug("Set status on {}", getThing().getStatus());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSceneAdded(InternalScene scene) {
|
||||
logger.debug("Scene {} added", scene.getID());
|
||||
if (this.bridgeHandler != null) {
|
||||
ThingStatusInfo statusInfo = this.bridgeHandler.getThing().getStatusInfo();
|
||||
updateStatus(statusInfo.getStatus(), statusInfo.getStatusDetail(), statusInfo.getDescription());
|
||||
logger.debug("Set status on {}", getThing().getStatus());
|
||||
}
|
||||
this.scene = scene;
|
||||
onSceneStateChanged(scene.isActive());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSceneStatusListenerID() {
|
||||
return this.sceneThingID;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,358 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.handler;
|
||||
|
||||
import static org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants.BINDING_ID;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.climate.TemperatureControlSensorTransmitter;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.climate.constants.ControlModes;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.climate.constants.ControlStates;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.climate.jsonresponsecontainer.impl.TemperatureControlStatus;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.TemperatureControlStatusListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.StructureManager;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.impl.TemperatureControlManager;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.FunctionalColorGroupEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.OutputModeEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.providers.DsChannelTypeProvider;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.IncreaseDecreaseType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
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.ThingStatusDetail;
|
||||
import org.openhab.core.thing.ThingStatusInfo;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.builder.ChannelBuilder;
|
||||
import org.openhab.core.thing.binding.builder.ThingBuilder;
|
||||
import org.openhab.core.thing.type.ChannelTypeUID;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link ZoneTemperatureControlHandler} is responsible for handling the configuration, to load the supported
|
||||
* channel of a
|
||||
* digitalSTROM zone, which has a temperature control configured, and handling commands, which are sent to the channel.
|
||||
* <br>
|
||||
* <br>
|
||||
* For that it uses the {@link BridgeHandler} to register itself as {@link TemperatureControlStatusListener} at the
|
||||
* {@link TemperatureControlManager} to get informed by status changes. Through the registration as
|
||||
* {@link TemperatureControlStatusListener} a {@link TemperatureControlSensorTransmitter} will be registered to this
|
||||
* {@link ZoneTemperatureControlHandler}, which is needed to set the temperature or the control value of a zone.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class ZoneTemperatureControlHandler extends BaseThingHandler implements TemperatureControlStatusListener {
|
||||
|
||||
/**
|
||||
* Contains all supported thing types of this handler
|
||||
*/
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(
|
||||
Arrays.asList(DigitalSTROMBindingConstants.THING_TYPE_ZONE_TEMERATURE_CONTROL));
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(ZoneTemperatureControlHandler.class);
|
||||
|
||||
private TemperatureControlSensorTransmitter temperatureSensorTransmitter;
|
||||
|
||||
private BridgeHandler dssBridgeHandler;
|
||||
private Integer zoneID;
|
||||
private String currentChannelID;
|
||||
private Float currentValue = 0f;
|
||||
private final Float step = 1f;
|
||||
|
||||
// check zoneID error codes
|
||||
public static final int ZONE_ID_NOT_EXISTS = -1;
|
||||
public static final int ZONE_ID_NOT_SET = -2;
|
||||
public static final int BRIDGE_IS_NULL = -3;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ZoneTemperatureControlHandler}.
|
||||
*
|
||||
* @param thing must not be null
|
||||
*/
|
||||
public ZoneTemperatureControlHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("Initializing DeviceHandler.");
|
||||
if (getConfig().get(DigitalSTROMBindingConstants.ZONE_ID) != null) {
|
||||
final Bridge bridge = getBridge();
|
||||
if (bridge != null) {
|
||||
bridgeStatusChanged(bridge.getStatusInfo());
|
||||
} else {
|
||||
// Set status to OFFLINE, if no bridge is available e.g. because the bridge has been removed and the
|
||||
// Thing was reinitialized.
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "Bridge is missing!");
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "zoneID is missing");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configured zoneID of the given {@link Configuration}. If the zoneID does't exist or can't be checked
|
||||
* {@link #ZONE_ID_NOT_EXISTS}, {@link #ZONE_ID_NOT_SET} or {@link #BRIDGE_IS_NULL} will be returned.
|
||||
*
|
||||
* @param config the {@link Configuration} to be checked
|
||||
* @param bridge the responsible {@link BridgeHandler}
|
||||
* @return zoneID the existing dS zoneID or a error constant
|
||||
*/
|
||||
public static int getZoneID(Configuration config, BridgeHandler bridge) {
|
||||
if (config == null || config.get(DigitalSTROMBindingConstants.ZONE_ID) == null) {
|
||||
return ZONE_ID_NOT_SET;
|
||||
}
|
||||
if (bridge == null) {
|
||||
return BRIDGE_IS_NULL;
|
||||
}
|
||||
String configZoneID = config.get(DigitalSTROMBindingConstants.ZONE_ID).toString();
|
||||
int zoneID;
|
||||
StructureManager strucMan = bridge.getStructureManager();
|
||||
if (strucMan != null) {
|
||||
try {
|
||||
zoneID = Integer.parseInt(configZoneID);
|
||||
if (!strucMan.checkZoneID(zoneID)) {
|
||||
zoneID = ZONE_ID_NOT_EXISTS;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
zoneID = strucMan.getZoneId(configZoneID);
|
||||
}
|
||||
return zoneID;
|
||||
}
|
||||
return ZONE_ID_NOT_EXISTS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("Handler disposed... unregister DeviceStatusListener");
|
||||
if (zoneID != null) {
|
||||
if (dssBridgeHandler != null) {
|
||||
dssBridgeHandler.unregisterTemperatureControlStatusListener(this);
|
||||
}
|
||||
temperatureSensorTransmitter = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
|
||||
if (bridgeStatusInfo.getStatus().equals(ThingStatus.ONLINE)) {
|
||||
int tempZoneID = getZoneID(getConfig(), getDssBridgeHandler());
|
||||
if (tempZoneID == ZONE_ID_NOT_EXISTS) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"Configured zone '" + getConfig().get(DigitalSTROMBindingConstants.ZONE_ID)
|
||||
+ "' does not exist, please check the configuration.");
|
||||
} else {
|
||||
this.zoneID = tempZoneID;
|
||||
}
|
||||
if (zoneID != null) {
|
||||
if (getDssBridgeHandler() != null && temperatureSensorTransmitter == null) {
|
||||
dssBridgeHandler.registerTemperatureControlStatusListener(this);
|
||||
updateStatus(ThingStatus.ONLINE, ThingStatusDetail.CONFIGURATION_PENDING,
|
||||
"waiting for listener registration");
|
||||
} else {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "No zoneID is set!");
|
||||
}
|
||||
}
|
||||
if (bridgeStatusInfo.getStatus().equals(ThingStatus.OFFLINE)) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
}
|
||||
if (bridgeStatusInfo.getStatus().equals(ThingStatus.REMOVED)) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "Bridge has been removed.");
|
||||
}
|
||||
logger.debug("Set status to {}", getThing().getStatusInfo());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
BridgeHandler dssBridgeHandler = getDssBridgeHandler();
|
||||
if (dssBridgeHandler == null) {
|
||||
logger.debug("BridgeHandler not found. Cannot handle command without bridge.");
|
||||
return;
|
||||
}
|
||||
if (temperatureSensorTransmitter == null && zoneID != null) {
|
||||
logger.debug(
|
||||
"Device not known on TemperationControlManager or temperatureSensorTransreciver is not registerd. Cannot handle command.");
|
||||
return;
|
||||
}
|
||||
if (channelUID.getId().equals(currentChannelID)) {
|
||||
if (command instanceof PercentType || command instanceof DecimalType) {
|
||||
sendCommandAndUpdateChannel(((DecimalType) command).floatValue());
|
||||
} else if (command instanceof OnOffType) {
|
||||
if (OnOffType.ON.equals(command)) {
|
||||
if (isTemperature()) {
|
||||
sendCommandAndUpdateChannel(TemperatureControlSensorTransmitter.MAX_TEMP);
|
||||
} else {
|
||||
sendCommandAndUpdateChannel(TemperatureControlSensorTransmitter.MAX_CONTROLL_VALUE);
|
||||
}
|
||||
} else {
|
||||
if (isTemperature()) {
|
||||
sendCommandAndUpdateChannel(0f);
|
||||
} else {
|
||||
sendCommandAndUpdateChannel(TemperatureControlSensorTransmitter.MIN_CONTROLL_VALUE);
|
||||
}
|
||||
}
|
||||
} else if (command instanceof IncreaseDecreaseType) {
|
||||
if (IncreaseDecreaseType.INCREASE.equals(command)) {
|
||||
sendCommandAndUpdateChannel(currentValue + step);
|
||||
} else {
|
||||
sendCommandAndUpdateChannel(currentValue - step);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.debug("Command sent to an unknown channel id: {}", channelUID);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isTemperature() {
|
||||
return currentChannelID.contains(DsChannelTypeProvider.TEMPERATURE_CONTROLLED);
|
||||
}
|
||||
|
||||
private void sendCommandAndUpdateChannel(Float newValue) {
|
||||
if (isTemperature()) {
|
||||
if (temperatureSensorTransmitter.pushTargetTemperature(zoneID, newValue)) {
|
||||
currentValue = newValue;
|
||||
updateState(currentChannelID, new DecimalType(newValue));
|
||||
}
|
||||
} else {
|
||||
if (temperatureSensorTransmitter.pushControlValue(zoneID, newValue)) {
|
||||
currentValue = newValue;
|
||||
updateState(currentChannelID, new PercentType(newValue.intValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized BridgeHandler getDssBridgeHandler() {
|
||||
if (this.dssBridgeHandler == null) {
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge == null) {
|
||||
logger.debug("Bride cannot be found");
|
||||
return null;
|
||||
}
|
||||
ThingHandler handler = bridge.getHandler();
|
||||
|
||||
if (handler instanceof BridgeHandler) {
|
||||
dssBridgeHandler = (BridgeHandler) handler;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return dssBridgeHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void configChanged(TemperatureControlStatus tempControlStatus) {
|
||||
if (tempControlStatus != null && tempControlStatus.isNotSetOff()) {
|
||||
ControlModes controlMode = ControlModes.getControlMode(tempControlStatus.getControlMode());
|
||||
ControlStates controlState = ControlStates.getControlState(tempControlStatus.getControlState());
|
||||
if (controlMode != null && controlState != null) {
|
||||
logger.debug("config changed: {}", tempControlStatus.toString());
|
||||
if (controlMode.equals(ControlModes.OFF) && currentChannelID != null) {
|
||||
currentChannelID = null;
|
||||
loadChannel();
|
||||
} else if (controlMode.equals(ControlModes.PID_CONTROL)
|
||||
&& (currentChannelID == null
|
||||
|| !currentChannelID.contains(DsChannelTypeProvider.TEMPERATURE_CONTROLLED))
|
||||
&& !controlState.equals(ControlStates.EMERGENCY)) {
|
||||
currentChannelID = DsChannelTypeProvider.getOutputChannelTypeID(FunctionalColorGroupEnum.BLUE,
|
||||
OutputModeEnum.TEMPRETURE_PWM);
|
||||
loadChannel();
|
||||
currentValue = tempControlStatus.getNominalValue();
|
||||
updateState(currentChannelID, new DecimalType(currentValue.doubleValue()));
|
||||
} else if (!controlMode.equals(ControlModes.PID_CONTROL) && !controlMode.equals(ControlModes.OFF)) {
|
||||
currentChannelID = DsChannelTypeProvider.getOutputChannelTypeID(FunctionalColorGroupEnum.BLUE,
|
||||
OutputModeEnum.HEATING_PWM);
|
||||
loadChannel();
|
||||
currentValue = tempControlStatus.getControlValue();
|
||||
updateState(currentChannelID, new PercentType(fixPercent(currentValue.intValue())));
|
||||
if (controlState.equals(ControlStates.EMERGENCY)) {
|
||||
updateStatus(ThingStatus.ONLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"The communication with temperation sensor fails. Temperature control state emergency (temperature control though the control value) is active.");
|
||||
}
|
||||
}
|
||||
Map<String, String> properties = editProperties();
|
||||
properties.put("controlDSUID", tempControlStatus.getControlDSUID());
|
||||
properties.put("controlMode", controlMode.getKey());
|
||||
properties.put("controlState", controlState.getKey());
|
||||
updateProperties(properties);
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"digitalSTROM temperature control is for this zone not configured in.");
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void loadChannel() {
|
||||
List<Channel> newChannelList = new ArrayList<>(1);
|
||||
if (currentChannelID != null) {
|
||||
newChannelList.add(ChannelBuilder
|
||||
.create(new ChannelUID(this.getThing().getUID(), currentChannelID),
|
||||
DsChannelTypeProvider.getItemType(currentChannelID))
|
||||
.withType(new ChannelTypeUID(BINDING_ID, currentChannelID)).build());
|
||||
}
|
||||
ThingBuilder thingBuilder = editThing();
|
||||
thingBuilder.withChannels(newChannelList);
|
||||
updateThing(thingBuilder.build());
|
||||
logger.debug("load channel: {} with item: {}", currentChannelID,
|
||||
DsChannelTypeProvider.getItemType(currentChannelID));
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onTargetTemperatureChanged(Float newValue) {
|
||||
if (isTemperature()) {
|
||||
updateState(currentChannelID, new DecimalType(newValue));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onControlValueChanged(Integer newValue) {
|
||||
if (!isTemperature()) {
|
||||
updateState(currentChannelID, new PercentType(fixPercent(newValue)));
|
||||
}
|
||||
}
|
||||
|
||||
private int fixPercent(int value) {
|
||||
return value < 0 ? 0 : value > 100 ? 100 : value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerTemperatureSensorTransmitter(
|
||||
TemperatureControlSensorTransmitter temperatureSensorTransreciver) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
this.temperatureSensorTransmitter = temperatureSensorTransreciver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getTemperationControlStatusListenrID() {
|
||||
return zoneID;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib;
|
||||
|
||||
/**
|
||||
* The {@link GeneralLibConstance} contains all relevant library constants.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class GeneralLibConstance {
|
||||
|
||||
/**
|
||||
* digitalSTROMs broadcast zone id.
|
||||
*/
|
||||
public static final int BROADCAST_ZONE_GROUP_ID = 0;
|
||||
|
||||
/**
|
||||
* digitalSTROMs broadcast zone string by query response.
|
||||
*/
|
||||
public static final String QUERY_BROADCAST_ZONE_STRING = "zone0";
|
||||
|
||||
/**
|
||||
* Scene-Array index for the scene value.
|
||||
*/
|
||||
public static final int SCENE_ARRAY_INDEX_VALUE = 0;
|
||||
/**
|
||||
* Scene-Array index for the scene value.
|
||||
*/
|
||||
public static final int SCENE_ARRAY_INDEX_ANGLE = 1;
|
||||
|
||||
/**
|
||||
* The highest read out priority for
|
||||
* {@link org.openhab.binding.digitalstrom.internal.lib.sensorjobexecutor.sensorjob.SensorJob}s.
|
||||
*/
|
||||
public static final int HIGHEST_READ_OUT_PRIORITY = 0;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.climate;
|
||||
|
||||
/**
|
||||
* The {@link TemperatureControlSensorTransmitter} can be implement by subclasses to implement a
|
||||
* transmitter which can be used to push the target temperature or control value to a digitalSTROM zone.
|
||||
*
|
||||
* @author Michael Ochel - initial contributer
|
||||
* @author Matthias Siegele - initial contributer
|
||||
*/
|
||||
public interface TemperatureControlSensorTransmitter {
|
||||
|
||||
/**
|
||||
* Maximal temperature, which can be set as target temperature in digitalSTROM.
|
||||
*/
|
||||
static float MAX_TEMP = 50f;
|
||||
|
||||
/**
|
||||
* Minimal temperature, which can be set as target temperature in digitalSTROM.
|
||||
*/
|
||||
static float MIN_TEMP = -43.15f;
|
||||
|
||||
/**
|
||||
* Maximal control value, which can be set as target temperature in digitalSTROM.
|
||||
*/
|
||||
static float MAX_CONTROLL_VALUE = 100f;
|
||||
|
||||
/**
|
||||
* Minimal control value, which can be set as target temperature in digitalSTROM.
|
||||
*/
|
||||
static float MIN_CONTROLL_VALUE = 0f;
|
||||
|
||||
/**
|
||||
* Pushes a new target temperature to a digitalSTROM zone.
|
||||
*
|
||||
* @param zoneID (must not be null)
|
||||
* @param newValue (must not be null)
|
||||
* @return true, if the push was successfully
|
||||
*/
|
||||
boolean pushTargetTemperature(Integer zoneID, Float newValue);
|
||||
|
||||
/**
|
||||
* Pushes a new control value to a digitalSTROM zone.
|
||||
*
|
||||
* @param zoneID (must not be null)
|
||||
* @param newValue (must not be null)
|
||||
* @return true, if the push was successfully
|
||||
*/
|
||||
boolean pushControlValue(Integer zoneID, Float newValue);
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.climate.constants;
|
||||
|
||||
/**
|
||||
* The {@link ControlModes} contains all digitalSTROM heating control modes.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public enum ControlModes {
|
||||
|
||||
OFF((short) 0, "off"),
|
||||
PID_CONTROL((short) 1, "pid-control"),
|
||||
ZONE_FOLLOWER((short) 2, "zone-follower"),
|
||||
FIXED_VALUE((short) 3, "fixed-value"),
|
||||
MANUAL((short) 4, "manual");
|
||||
|
||||
private final Short id;
|
||||
private final String key;
|
||||
|
||||
private static final ControlModes[] CONTROL_MODES = new ControlModes[ControlModes.values().length];
|
||||
|
||||
static {
|
||||
for (ControlModes controlMode : ControlModes.values()) {
|
||||
CONTROL_MODES[controlMode.id] = controlMode;
|
||||
}
|
||||
}
|
||||
|
||||
private ControlModes(short id, String key) {
|
||||
this.id = id;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key of the operation mode.
|
||||
*
|
||||
* @return key
|
||||
*/
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of the operation mode.
|
||||
*
|
||||
* @return ID
|
||||
*/
|
||||
public Short getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link ControlModes} of the given control mode id.
|
||||
*
|
||||
* @param id of the control mode
|
||||
* @return control mode
|
||||
*/
|
||||
public static ControlModes getControlMode(short id) {
|
||||
try {
|
||||
return CONTROL_MODES[id];
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.climate.constants;
|
||||
|
||||
/**
|
||||
* The {@link ControlStates} contains all digitalSTROM heating control states.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public enum ControlStates {
|
||||
|
||||
INTERNAL((short) 0, "internal"),
|
||||
EXTERNAL((short) 1, "external"),
|
||||
EXBACKUP((short) 2, "exbackup"),
|
||||
EMERGENCY((short) 3, "emergency");
|
||||
|
||||
private final Short id;
|
||||
private final String key;
|
||||
private static final ControlStates[] CONTROL_STATES = new ControlStates[ControlStates.values().length];
|
||||
|
||||
static {
|
||||
for (ControlStates controlState : ControlStates.values()) {
|
||||
CONTROL_STATES[controlState.id] = controlState;
|
||||
}
|
||||
}
|
||||
|
||||
private ControlStates(short id, String key) {
|
||||
this.id = id;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key of the operation mode.
|
||||
*
|
||||
* @return key
|
||||
*/
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of the operation mode.
|
||||
*
|
||||
* @return ID
|
||||
*/
|
||||
public Short getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link ControlStates} of the given control state id.
|
||||
*
|
||||
* @param id of the control state
|
||||
* @return control state
|
||||
*/
|
||||
public static ControlStates getControlState(short id) {
|
||||
try {
|
||||
return CONTROL_STATES[id];
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.digitalstrom.internal.lib.climate.constants;
|
||||
|
||||
/**
|
||||
* The {@link OperationModes} contains all digitalSTROM heating operation states.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public enum OperationModes {
|
||||
|
||||
OFF((short) 0, "Off"),
|
||||
COMFORT((short) 1, "Comfort"),
|
||||
ECONEMY((short) 2, "Econemy"),
|
||||
NOT_USED((short) 3, "NotUsed"),
|
||||
NIGHT((short) 4, "Night"),
|
||||
HOLLYDAY((short) 5, "Holliday"),
|
||||
COOLING((short) 6, "Cooling"),
|
||||
COOLING_OFF((short) 7, "CoolingOff");
|
||||
|
||||
private final Short id;
|
||||
private final String key;
|
||||
|
||||
private static final OperationModes[] OPERATION_MODES = new OperationModes[OperationModes.values().length];
|
||||
|
||||
static {
|
||||
for (OperationModes operationMode : OperationModes.values()) {
|
||||
OPERATION_MODES[operationMode.id] = operationMode;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link OperationModes} of the given operation mode id.
|
||||
*
|
||||
* @param id of the operation mode
|
||||
* @return operation mode
|
||||
*/
|
||||
public static OperationModes getOperationMode(short id) {
|
||||
try {
|
||||
return OPERATION_MODES[id];
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private OperationModes(short id, String key) {
|
||||
this.id = id;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key of the operation mode.
|
||||
*
|
||||
* @return key
|
||||
*/
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of the operation mode.
|
||||
*
|
||||
* @return ID
|
||||
*/
|
||||
public Short getID() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.climate.datatypes;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.SensorEnum;
|
||||
|
||||
/**
|
||||
* The {@link AssignSensorType} assigns a sensor type of a zone to the dSUID of the sensor-device.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class AssignSensorType {
|
||||
|
||||
private final SensorEnum sensorType;
|
||||
private final String dsuid;
|
||||
|
||||
/**
|
||||
* Create a new {@link AssignSensorType}.
|
||||
*
|
||||
* @param sensorType must not be null
|
||||
* @param dSUID must not be null
|
||||
*/
|
||||
public AssignSensorType(SensorEnum sensorType, String dSUID) {
|
||||
this.sensorType = sensorType;
|
||||
dsuid = dSUID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sensor type as {@link SensorEnum}.
|
||||
*
|
||||
* @return the sensor type
|
||||
*/
|
||||
public SensorEnum getSensorType() {
|
||||
return sensorType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the dSUID of the assign sensor-device.
|
||||
*
|
||||
* @return the dSUID
|
||||
*/
|
||||
public String getDSUID() {
|
||||
return dsuid;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AssignSensorType [SENSOR_TYPE=" + sensorType + ", dSUID=" + dsuid + "]";
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((dsuid == null) ? 0 : dsuid.hashCode());
|
||||
result = prime * result + ((sensorType == null) ? 0 : sensorType.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof AssignSensorType)) {
|
||||
return false;
|
||||
}
|
||||
AssignSensorType other = (AssignSensorType) obj;
|
||||
if (dsuid == null) {
|
||||
if (other.dsuid != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!dsuid.equals(other.dsuid)) {
|
||||
return false;
|
||||
}
|
||||
if (sensorType != other.sensorType) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.climate.datatypes;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.SensorEnum;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link CachedSensorValue} holds a read sensor value. For that the {@link CachedSensorValue} includes the sensor
|
||||
* type, sensor value and a the timestamp.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class CachedSensorValue {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CachedSensorValue.class);
|
||||
|
||||
private final SensorEnum sensorType;
|
||||
private final Float sensorValue;
|
||||
private final String timestamp;
|
||||
|
||||
/**
|
||||
* Create a new {@link CachedSensorValue}.
|
||||
*
|
||||
* @param sensorType must not be null
|
||||
* @param sensorValue must not be null
|
||||
* @param timestamp must not be null
|
||||
*/
|
||||
public CachedSensorValue(SensorEnum sensorType, Float sensorValue, String timestamp) {
|
||||
this.sensorType = sensorType;
|
||||
this.sensorValue = sensorValue;
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sensor type as {@link SensorEnum}.
|
||||
*
|
||||
* @return the sensorType
|
||||
*/
|
||||
public SensorEnum getSensorType() {
|
||||
return sensorType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sensor value.
|
||||
*
|
||||
* @return the sensorValue
|
||||
*/
|
||||
public Float getSensorValue() {
|
||||
return sensorValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the timestamp as {@link String}.
|
||||
*
|
||||
* @return the timestamp
|
||||
*/
|
||||
public String getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time stamp as {@link Date}.
|
||||
*
|
||||
* @return the timeStamp
|
||||
*/
|
||||
public Date getTimestampAsDate() {
|
||||
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SS");
|
||||
try {
|
||||
return formatter.parse(timestamp);
|
||||
} catch (ParseException e) {
|
||||
logger.error("A ParseException occurred by parsing date string: {}", timestamp, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CachedSensorValue [SENSOR_TYPE=" + sensorType + ", SENSOR_VALUE=" + sensorValue + ", TIMESTAMP="
|
||||
+ timestamp + "]";
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((sensorType == null) ? 0 : sensorType.hashCode());
|
||||
result = prime * result + ((sensorValue == null) ? 0 : sensorValue.hashCode());
|
||||
result = prime * result + ((timestamp == null) ? 0 : timestamp.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof CachedSensorValue)) {
|
||||
return false;
|
||||
}
|
||||
CachedSensorValue other = (CachedSensorValue) obj;
|
||||
if (sensorType != other.sensorType) {
|
||||
return false;
|
||||
}
|
||||
if (sensorValue == null) {
|
||||
if (other.sensorValue != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!sensorValue.equals(other.sensorValue)) {
|
||||
return false;
|
||||
}
|
||||
if (timestamp == null) {
|
||||
if (other.timestamp != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!timestamp.equals(other.timestamp)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.climate.jsonresponsecontainer;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.climate.datatypes.CachedSensorValue;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.constants.JSONApiResponseKeysEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.SensorEnum;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link BaseSensorValues} is a base implementation of sensor response of the digitalSTROM-json-API.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public abstract class BaseSensorValues {
|
||||
|
||||
private List<CachedSensorValue> sensorValues;
|
||||
|
||||
/**
|
||||
* Adds a sensor value through the digitalSTROM-API response as {@link JsonObject}. The boolean outdoor has to be
|
||||
* set to indicate that it is an outdoor or indoor value (needed to choose the right sensor type).
|
||||
*
|
||||
* @param jObject must not be null
|
||||
* @param outdoor (true = outdoor; false = indoor)
|
||||
*/
|
||||
protected void addSensorValue(JsonObject jObject, boolean outdoor) {
|
||||
if (jObject.get(JSONApiResponseKeysEnum.TEMPERATION_VALUE.getKey()) != null) {
|
||||
SensorEnum sensorType = SensorEnum.TEMPERATURE_INDOORS;
|
||||
if (outdoor) {
|
||||
sensorType = SensorEnum.TEMPERATURE_OUTDOORS;
|
||||
}
|
||||
addSensorValue(new CachedSensorValue(sensorType,
|
||||
jObject.get(JSONApiResponseKeysEnum.TEMPERATION_VALUE.getKey()).getAsFloat(),
|
||||
jObject.get(JSONApiResponseKeysEnum.TEMPERATION_VALUE_TIME.getKey()).getAsString()));
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.HUMIDITY_VALUE.getKey()) != null) {
|
||||
SensorEnum sensorType = SensorEnum.RELATIVE_HUMIDITY_INDOORS;
|
||||
if (outdoor) {
|
||||
sensorType = SensorEnum.RELATIVE_HUMIDITY_OUTDOORS;
|
||||
}
|
||||
addSensorValue(new CachedSensorValue(sensorType,
|
||||
jObject.get(JSONApiResponseKeysEnum.HUMIDITY_VALUE.getKey()).getAsFloat(),
|
||||
jObject.get(JSONApiResponseKeysEnum.HUMIDITY_VALUE_TIME.getKey()).getAsString()));
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CO2_CONCENTRATION_VALUE.getKey()) != null) {
|
||||
addSensorValue(new CachedSensorValue(SensorEnum.CARBON_DIOXIDE,
|
||||
jObject.get(JSONApiResponseKeysEnum.CO2_CONCENTRATION_VALUE.getKey()).getAsFloat(),
|
||||
jObject.get(JSONApiResponseKeysEnum.CO2_CONCENTRATION_VALUE_TIME.getKey()).getAsString()));
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.BRIGHTNESS_VALUE.getKey()) != null) {
|
||||
SensorEnum sensorType = SensorEnum.BRIGHTNESS_INDOORS;
|
||||
if (outdoor) {
|
||||
sensorType = SensorEnum.BRIGHTNESS_OUTDOORS;
|
||||
}
|
||||
addSensorValue(new CachedSensorValue(sensorType,
|
||||
jObject.get(JSONApiResponseKeysEnum.BRIGHTNESS_VALUE.getKey()).getAsFloat(),
|
||||
jObject.get(JSONApiResponseKeysEnum.BRIGHTNESS_VALUE_TIME.getKey()).getAsString()));
|
||||
}
|
||||
}
|
||||
|
||||
private void addSensorValue(CachedSensorValue cachedSensorValue) {
|
||||
if (sensorValues == null) {
|
||||
sensorValues = new LinkedList<>();
|
||||
sensorValues.add(cachedSensorValue);
|
||||
} else {
|
||||
sensorValues.add(cachedSensorValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the available sensor types.
|
||||
*
|
||||
* @return available sensor types
|
||||
*/
|
||||
public List<SensorEnum> getAvailableSensorTypes() {
|
||||
List<SensorEnum> sensorTypes = new LinkedList<>();
|
||||
if (sensorValues != null) {
|
||||
for (CachedSensorValue cSensorValue : sensorValues) {
|
||||
sensorTypes.add(cSensorValue.getSensorType());
|
||||
}
|
||||
}
|
||||
return sensorTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link CachedSensorValue}'s as {@link List}.
|
||||
*
|
||||
* @return list of {@link CachedSensorValue}'s
|
||||
*/
|
||||
public List<CachedSensorValue> getCachedSensorValues() {
|
||||
return sensorValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link CachedSensorValue} of the given sensor type or null, if no {@link CachedSensorValue} for the
|
||||
* given sensor type exists.
|
||||
*
|
||||
* @param sensorType can be null
|
||||
* @return the {@link CachedSensorValue} of the given sensorType or null
|
||||
*/
|
||||
public CachedSensorValue getCachedSensorValue(SensorEnum sensorType) {
|
||||
if (sensorType != null && sensorValues != null) {
|
||||
for (CachedSensorValue cSensorValue : sensorValues) {
|
||||
if (cSensorValue.getSensorType().equals(sensorType)) {
|
||||
return cSensorValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, if the given sensor type exist, otherwise false.
|
||||
*
|
||||
* @param sensorType can be null
|
||||
* @return true, if the given sensor type exist, otherwise false
|
||||
*/
|
||||
public boolean existSensorValue(SensorEnum sensorType) {
|
||||
return getCachedSensorValue(sensorType) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, is sensor values exists, otherwise false.
|
||||
*
|
||||
* @return true, if sensor values exists, otherwise false
|
||||
*/
|
||||
public boolean existSensorValues() {
|
||||
return sensorValues != null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SensorValues [sensorValues=" + sensorValues + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.climate.jsonresponsecontainer;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.climate.constants.ControlModes;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.constants.JSONApiResponseKeysEnum;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link BaseTemperatureControl} is a base implementation for temperature controls status and configurations. For
|
||||
* that it extends the {@link BaseZoneIdentifier}.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public abstract class BaseTemperatureControl extends BaseZoneIdentifier {
|
||||
|
||||
protected String controlDSUID;
|
||||
protected Short controlMode;
|
||||
|
||||
/**
|
||||
* Creates a new {@link BaseTemperatureControl} through the {@link JsonObject} which will be returned by an zone
|
||||
* call.<br>
|
||||
* Because zone calls do not include a zoneID or zoneName in the json response, the zoneID and zoneName have to
|
||||
* be handed over the constructor.
|
||||
*
|
||||
* @param jObject must not be null
|
||||
* @param zoneID must not be null
|
||||
* @param zoneName can be null
|
||||
*/
|
||||
public BaseTemperatureControl(JsonObject jObject, Integer zoneID, String zoneName) {
|
||||
super(zoneID, zoneName);
|
||||
init(jObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link BaseTemperatureControl} through the {@link JsonObject} which will be returned by an
|
||||
* apartment call.
|
||||
*
|
||||
* @param jObject must not be null
|
||||
*/
|
||||
public BaseTemperatureControl(JsonObject jObject) {
|
||||
super(jObject);
|
||||
init(jObject);
|
||||
}
|
||||
|
||||
private void init(JsonObject jObject) {
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CONTROL_MODE.getKey()) != null) {
|
||||
this.controlMode = jObject.get(JSONApiResponseKeysEnum.CONTROL_MODE.getKey()).getAsShort();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CONTROL_DSUID.getKey()) != null) {
|
||||
this.controlDSUID = jObject.get(JSONApiResponseKeysEnum.CONTROL_DSUID.getKey()).getAsString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the dSUID of the control sensor for heating of the zone.
|
||||
*
|
||||
* @return the controlDSUID
|
||||
*/
|
||||
public String getControlDSUID() {
|
||||
return controlDSUID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns controlMode for heating of the zone.
|
||||
*
|
||||
* @return the controlMode
|
||||
*/
|
||||
public Short getControlMode() {
|
||||
return controlMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, if heating for this zone is not set off (set {@link ControlModes} = {@link ControlModes#OFF}),
|
||||
* otherwise false.
|
||||
*
|
||||
* @return true, if the set {@link ControlModes} is not {@link ControlModes#OFF}
|
||||
*/
|
||||
public Boolean isNotSetOff() {
|
||||
return !ControlModes.OFF.getID().equals(controlMode);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.climate.jsonresponsecontainer;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.constants.JSONApiResponseKeysEnum;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link BaseZoneIdentifier} is a base implementation of the {@link ZoneIdentifier}.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public abstract class BaseZoneIdentifier implements ZoneIdentifier {
|
||||
|
||||
protected Integer zoneID;
|
||||
protected String zoneName;
|
||||
|
||||
/**
|
||||
* Creates a new {@link BaseZoneIdentifier} with an zone id and zone name.
|
||||
*
|
||||
* @param zoneID must not be null
|
||||
* @param zoneName can be null
|
||||
*/
|
||||
public BaseZoneIdentifier(Integer zoneID, String zoneName) {
|
||||
this.zoneID = zoneID;
|
||||
this.zoneName = zoneName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link BaseZoneIdentifier} through the {@link JsonObject} of the response of an digitalSTROM-API
|
||||
* apartment call.
|
||||
*
|
||||
* @param jObject must not be null
|
||||
*/
|
||||
public BaseZoneIdentifier(JsonObject jObject) {
|
||||
if (jObject.get(JSONApiResponseKeysEnum.ID.getKey()) != null) {
|
||||
this.zoneID = jObject.get(JSONApiResponseKeysEnum.ID.getKey()).getAsInt();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.NAME.getKey()) != null) {
|
||||
this.zoneName = jObject.get(JSONApiResponseKeysEnum.NAME.getKey()).getAsString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getZoneID() {
|
||||
return zoneID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getZoneName() {
|
||||
return zoneName;
|
||||
}
|
||||
}
|
||||
@@ -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.digitalstrom.internal.lib.climate.jsonresponsecontainer;
|
||||
|
||||
/**
|
||||
* The {@link ZoneIdentifier} can be implement to identify a zone.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public interface ZoneIdentifier {
|
||||
|
||||
/**
|
||||
* Returns the zoneID of this zone.
|
||||
*
|
||||
* @return the zoneID
|
||||
*/
|
||||
Integer getZoneID();
|
||||
|
||||
/**
|
||||
* Returns the zoneName of this zone.
|
||||
*
|
||||
* @return the zoneName
|
||||
*/
|
||||
String getZoneName();
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.climate.jsonresponsecontainer.impl;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.climate.datatypes.AssignSensorType;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.climate.jsonresponsecontainer.BaseZoneIdentifier;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.constants.JSONApiResponseKeysEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.SensorEnum;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link AssignedSensors} acts as container for the digitalSTROM json-method <i>getAssignedSensors</i>. So the
|
||||
* {@link AssignedSensors} contains all {@link AssignSensorType}s of a zone.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class AssignedSensors extends BaseZoneIdentifier {
|
||||
|
||||
private List<AssignSensorType> sensors;
|
||||
|
||||
/**
|
||||
* Creates a new {@link AssignedSensors} through the {@link JsonObject} that will be returned by an apartment call.
|
||||
*
|
||||
* @param jObject must not be null
|
||||
*/
|
||||
public AssignedSensors(JsonObject jObject) {
|
||||
super(jObject);
|
||||
init(jObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link AssignedSensors} through the {@link JsonObject} which will be returned by an zone call.
|
||||
* Because of zone calls does not include a zoneID or zoneName in the json response, the zoneID and zoneName have to
|
||||
* be handed over the constructor.
|
||||
*
|
||||
* @param jObject must not be null
|
||||
* @param zoneID must not be null
|
||||
* @param zoneName can be null
|
||||
*/
|
||||
public AssignedSensors(JsonObject jObject, Integer zoneID, String zoneName) {
|
||||
super(zoneID, zoneName);
|
||||
init(jObject);
|
||||
}
|
||||
|
||||
private void init(JsonObject jObject) {
|
||||
if (jObject.get(JSONApiResponseKeysEnum.SENSORS.getKey()) != null
|
||||
&& jObject.get(JSONApiResponseKeysEnum.SENSORS.getKey()).isJsonArray()) {
|
||||
JsonArray jArray = jObject.get(JSONApiResponseKeysEnum.SENSORS.getKey()).getAsJsonArray();
|
||||
if (jArray.size() != 0) {
|
||||
sensors = new LinkedList<>();
|
||||
Iterator<JsonElement> iter = jArray.iterator();
|
||||
while (iter.hasNext()) {
|
||||
JsonObject assignedSensor = iter.next().getAsJsonObject();
|
||||
Short sensorType = null;
|
||||
String meterDSUID = null;
|
||||
if (assignedSensor.get(JSONApiResponseKeysEnum.SENSOR_TYPE.getKey()) != null) {
|
||||
sensorType = assignedSensor.get(JSONApiResponseKeysEnum.SENSOR_TYPE.getKey()).getAsShort();
|
||||
}
|
||||
if (assignedSensor.get(JSONApiResponseKeysEnum.DSUID_LOWER_CASE.getKey()) != null) {
|
||||
meterDSUID = assignedSensor.get(JSONApiResponseKeysEnum.DSUID_LOWER_CASE.getKey())
|
||||
.getAsString();
|
||||
}
|
||||
sensors.add(new AssignSensorType(SensorEnum.getSensor(sensorType), meterDSUID));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link List} of all assigned sensor types as {@link SensorEnum} of a zone.
|
||||
*
|
||||
* @return list of all assigned sensor types
|
||||
*/
|
||||
public List<SensorEnum> getAssignedZoneSensorTypes() {
|
||||
List<SensorEnum> sensorTypes = new LinkedList<>();
|
||||
if (sensors != null) {
|
||||
for (AssignSensorType aSensorValue : sensors) {
|
||||
sensorTypes.add(aSensorValue.getSensorType());
|
||||
}
|
||||
}
|
||||
return sensorTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link List} of all {@link AssignSensorType} of a zone.
|
||||
*
|
||||
* @return list of {@link AssignSensorType}s
|
||||
*/
|
||||
public List<AssignSensorType> getAssignedSensorTypes() {
|
||||
return sensors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link AssignSensorType} of the given sensorType or null, if the given sensorType does not exist.
|
||||
*
|
||||
* @param sensorType can be null
|
||||
* @return the {@link AssignSensorType} of the given sensorType or null
|
||||
*/
|
||||
public AssignSensorType getAssignedSensorType(SensorEnum sensorType) {
|
||||
if (sensorType != null && sensors != null) {
|
||||
for (AssignSensorType aSensorValue : sensors) {
|
||||
if (aSensorValue.getSensorType().equals(sensorType)) {
|
||||
return aSensorValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, if the given sensorType exists at the zone, otherwise false.
|
||||
*
|
||||
* @param sensorType can be null
|
||||
* @return true, if sensorType exists, otherwise false
|
||||
*/
|
||||
public boolean existSensorType(SensorEnum sensorType) {
|
||||
return getAssignedSensorType(sensorType) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, if sensors exists at the zone, otherwise false.
|
||||
*
|
||||
* @return true, if sensors exists, otherwise false
|
||||
*/
|
||||
public boolean existsAssignedSensors() {
|
||||
return sensors != null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AssignedSensors [sensors=" + sensors + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.climate.jsonresponsecontainer.impl;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.climate.jsonresponsecontainer.BaseSensorValues;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.climate.jsonresponsecontainer.ZoneIdentifier;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.constants.JSONApiResponseKeysEnum;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link SensorValues} acts as container for the digitalSTROM json-method <i>getSensorValues</i>. So the
|
||||
* {@link SensorValues} contains all {@link CachedSensorValue}s of a zone.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class SensorValues extends BaseSensorValues implements ZoneIdentifier {
|
||||
|
||||
private Integer zoneID;
|
||||
private String zoneName;
|
||||
|
||||
/**
|
||||
* Creates a new {@link SensorValues} through the {@link JsonObject} that will be returned by an apartment call.
|
||||
*
|
||||
* @param jObject must not be null
|
||||
*/
|
||||
public SensorValues(JsonObject jObject) {
|
||||
if (jObject.get(JSONApiResponseKeysEnum.ID.getKey()) != null) {
|
||||
this.zoneID = jObject.get(JSONApiResponseKeysEnum.ID.getKey()).getAsInt();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.NAME.getKey()) != null) {
|
||||
this.zoneName = jObject.get(JSONApiResponseKeysEnum.NAME.getKey()).getAsString();
|
||||
}
|
||||
init(jObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link SensorValues} through the {@link JsonObject} which will be returned by an zone call.
|
||||
* Because of zone calls does not include a zoneID or zoneName in the json response, the zoneID and zoneName have to
|
||||
* be handed over the constructor.
|
||||
*
|
||||
* @param jObject must not be null
|
||||
* @param zoneID must not be null
|
||||
* @param zoneName can be null
|
||||
*/
|
||||
public SensorValues(JsonObject jObject, Integer zoneID, String zoneName) {
|
||||
this.zoneID = zoneID;
|
||||
this.zoneName = zoneName;
|
||||
init(jObject);
|
||||
}
|
||||
|
||||
private void init(JsonObject jObject) {
|
||||
if (jObject.get(JSONApiResponseKeysEnum.VALUES.getKey()).isJsonArray()) {
|
||||
JsonArray jArray = jObject.get(JSONApiResponseKeysEnum.VALUES.getKey()).getAsJsonArray();
|
||||
if (jArray.size() != 0) {
|
||||
Iterator<JsonElement> iter = jArray.iterator();
|
||||
while (iter.hasNext()) {
|
||||
JsonObject cachedSensorValue = iter.next().getAsJsonObject();
|
||||
super.addSensorValue(cachedSensorValue, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SensorValues [zoneID=" + zoneID + ", zoneName=" + zoneName + ", " + super.toString() + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getZoneID() {
|
||||
return zoneID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getZoneName() {
|
||||
return zoneName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.climate.jsonresponsecontainer.impl;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.climate.jsonresponsecontainer.BaseTemperatureControl;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.constants.JSONApiResponseKeysEnum;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link TemperatureControlConfig} acts as container for the digitalSTROM json-method
|
||||
* <i>getTemperatureControlConfig</i>. So the {@link TemperatureControlConfig} contains all heating control
|
||||
* configurations of a zone.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class TemperatureControlConfig extends BaseTemperatureControl {
|
||||
|
||||
private Integer referenceZone;
|
||||
private Float ctrlOffset;
|
||||
private Float manualValue;
|
||||
private Float emergencyValue;
|
||||
private Float ctrlKp;
|
||||
private Float ctrlTs;
|
||||
private Float ctrlTi;
|
||||
private Float ctrlKd;
|
||||
private Float ctrlImin;
|
||||
private Float ctrlImax;
|
||||
private Float ctrlYmin;
|
||||
private Float ctrlYmax;
|
||||
private Boolean ctrlAntiWindUp;
|
||||
private Boolean ctrlKeepFloorWarm;
|
||||
|
||||
/**
|
||||
* Creates a new {@link TemperatureControlConfig} through the {@link JsonObject} which will be returned by an
|
||||
* apartment call.
|
||||
*
|
||||
* @param jObject must not be null
|
||||
*/
|
||||
public TemperatureControlConfig(JsonObject jObject) {
|
||||
super(jObject);
|
||||
init(jObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link TemperatureControlConfig} through the {@link JsonObject} which will be returned by an zone
|
||||
* call.<br>
|
||||
* Because of zone calls does not include a zoneID or zoneName in the json response, the zoneID and zoneName have to
|
||||
* be handed over the constructor.
|
||||
*
|
||||
* @param jObject must not be null
|
||||
* @param zoneID must not be null
|
||||
* @param zoneName can be null
|
||||
*/
|
||||
public TemperatureControlConfig(JsonObject jObject, Integer zoneID, String zoneName) {
|
||||
super(jObject, zoneID, zoneName);
|
||||
init(jObject);
|
||||
}
|
||||
|
||||
private void init(JsonObject jObject) {
|
||||
if (isNotSetOff()) {
|
||||
if (controlMode == 1) {
|
||||
if (jObject.get(JSONApiResponseKeysEnum.EMERGENCY_VALUE.getKey()) != null) {
|
||||
this.emergencyValue = jObject.get(JSONApiResponseKeysEnum.EMERGENCY_VALUE.getKey()).getAsFloat();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CTRL_KP.getKey()) != null) {
|
||||
this.ctrlKp = jObject.get(JSONApiResponseKeysEnum.CTRL_KP.getKey()).getAsFloat();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CTRL_TS.getKey()) != null) {
|
||||
this.ctrlTs = jObject.get(JSONApiResponseKeysEnum.CTRL_TS.getKey()).getAsFloat();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CTRL_TI.getKey()) != null) {
|
||||
this.ctrlTi = jObject.get(JSONApiResponseKeysEnum.CTRL_TI.getKey()).getAsFloat();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CTRL_KD.getKey()) != null) {
|
||||
this.ctrlKd = jObject.get(JSONApiResponseKeysEnum.CTRL_KD.getKey()).getAsFloat();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CTRL_MIN.getKey()) != null) {
|
||||
this.ctrlImin = jObject.get(JSONApiResponseKeysEnum.CTRL_MIN.getKey()).getAsFloat();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CTRL_MAX.getKey()) != null) {
|
||||
this.ctrlImax = jObject.get(JSONApiResponseKeysEnum.CTRL_MAX.getKey()).getAsFloat();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CTRL_Y_MIN.getKey()) != null) {
|
||||
this.ctrlYmin = jObject.get(JSONApiResponseKeysEnum.CTRL_Y_MIN.getKey()).getAsFloat();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CTRL_Y_MAX.getKey()) != null) {
|
||||
this.ctrlYmax = jObject.get(JSONApiResponseKeysEnum.CTRL_Y_MAX.getKey()).getAsFloat();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CTRL_KEEP_FLOOR_WARM.getKey()) != null) {
|
||||
this.ctrlKeepFloorWarm = jObject.get(JSONApiResponseKeysEnum.CTRL_KEEP_FLOOR_WARM.getKey())
|
||||
.getAsBoolean();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CTRL_ANTI_WIND_UP.getKey()) != null) {
|
||||
this.ctrlAntiWindUp = jObject.get(JSONApiResponseKeysEnum.CTRL_ANTI_WIND_UP.getKey())
|
||||
.getAsBoolean();
|
||||
}
|
||||
}
|
||||
if (controlMode == 2) {
|
||||
if (jObject.get(JSONApiResponseKeysEnum.REFERENCE_ZONE.getKey()) != null) {
|
||||
this.referenceZone = jObject.get(JSONApiResponseKeysEnum.REFERENCE_ZONE.getKey()).getAsInt();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CTRL_OFFSET.getKey()) != null) {
|
||||
this.ctrlOffset = jObject.get(JSONApiResponseKeysEnum.CTRL_OFFSET.getKey()).getAsFloat();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the refenceZone, if control-mode is {@link ControlModes#ZONE_FOLLOWER}, otherwise null.
|
||||
*
|
||||
* @return the referenceZone
|
||||
*/
|
||||
public Integer getReferenceZone() {
|
||||
return referenceZone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ctrlOffset, if control-mode is {@link ControlModes#PID_CONTROL}, otherwise null.
|
||||
*
|
||||
* @return the ctrlOffset
|
||||
*/
|
||||
public Float getCtrlOffset() {
|
||||
return ctrlOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the manualValue, if control-mode is {@link ControlModes#MANUAL}, otherwise null.
|
||||
*
|
||||
* @return the manualValue
|
||||
*/
|
||||
public Float getManualValue() {
|
||||
return manualValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the emergencyValue, if control-mode is {@link ControlModes#PID_CONTROL}, otherwise null.
|
||||
*
|
||||
* @return the emergencyValue
|
||||
*/
|
||||
public Float getEmergencyValue() {
|
||||
return emergencyValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ctrlKp, if control-mode is {@link ControlModes#PID_CONTROL}, otherwise null.
|
||||
*
|
||||
* @return the ctrlKp
|
||||
*/
|
||||
public Float getCtrlKp() {
|
||||
return ctrlKp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ctrlTs, if control-mode is {@link ControlModes#PID_CONTROL}, otherwise null.
|
||||
*
|
||||
* @return the ctrlTs
|
||||
*/
|
||||
public Float getCtrlTs() {
|
||||
return ctrlTs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ctrlTi, if control-mode is {@link ControlModes#PID_CONTROL}, otherwise null.
|
||||
*
|
||||
* @return the ctrlTi
|
||||
*/
|
||||
public Float getCtrlTi() {
|
||||
return ctrlTi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ctrlKd, if control-mode is {@link ControlModes#PID_CONTROL}, otherwise null.
|
||||
*
|
||||
* @return the ctrlKd
|
||||
*/
|
||||
public Float getCtrlKd() {
|
||||
return ctrlKd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ctrlImin, if control-mode is {@link ControlModes#PID_CONTROL}, otherwise null.
|
||||
*
|
||||
* @return the ctrlImin
|
||||
*/
|
||||
public Float getCtrlImin() {
|
||||
return ctrlImin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ctrlImax, if control-mode is {@link ControlModes#PID_CONTROL}, otherwise null.
|
||||
*
|
||||
* @return the ctrlImax
|
||||
*/
|
||||
public Float getCtrlImax() {
|
||||
return ctrlImax;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ctrlYmin, if control-mode is {@link ControlModes#PID_CONTROL}, otherwise null.
|
||||
*
|
||||
* @return the ctrlYmin
|
||||
*/
|
||||
public Float getCtrlYmin() {
|
||||
return ctrlYmin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ctrlYmax, if control-mode is {@link ControlModes#PID_CONTROL}, otherwise null.
|
||||
*
|
||||
* @return the ctrlYmax
|
||||
*/
|
||||
public Float getCtrlYmax() {
|
||||
return ctrlYmax;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ctrlAntiWindUp, if control-mode is {@link ControlModes#PID_CONTROL}, otherwise null.
|
||||
*
|
||||
* @return the ctrlAntiWindUp
|
||||
*/
|
||||
public Boolean getCtrlAntiWindUp() {
|
||||
return ctrlAntiWindUp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ctrlKeepFloorWarm, if control-mode is {@link ControlModes#PID_CONTROL}, otherwise null.
|
||||
*
|
||||
* @return the ctrlKeepFloorWarm
|
||||
*/
|
||||
public Boolean getCtrlKeepFloorWarm() {
|
||||
return ctrlKeepFloorWarm;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TemperatureControlConfig [referenceZone=" + referenceZone + ", ctrlOffset=" + ctrlOffset
|
||||
+ ", manualValue=" + manualValue + ", emergencyValue=" + emergencyValue + ", ctrlKp=" + ctrlKp
|
||||
+ ", ctrlTs=" + ctrlTs + ", ctrlTi=" + ctrlTi + ", ctrlKd=" + ctrlKd + ", ctrlImin=" + ctrlImin
|
||||
+ ", ctrlImax=" + ctrlImax + ", ctrlYmin=" + ctrlYmin + ", ctrlYmax=" + ctrlYmax + ", ctrlAntiWindUp="
|
||||
+ ctrlAntiWindUp + ", ctrlKeepFloorWarm=" + ctrlKeepFloorWarm + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.climate.jsonresponsecontainer.impl;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.climate.jsonresponsecontainer.BaseTemperatureControl;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.constants.JSONApiResponseKeysEnum;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link TemperatureControlInternals} acts as container for the digitalSTROM json-method
|
||||
* <i>getTemperatureControlInternals</i>. So the {@link TemperatureControlInternals} contains all internal heating
|
||||
* control configurations of a zone.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class TemperatureControlInternals extends BaseTemperatureControl {
|
||||
|
||||
private Short controlState;
|
||||
private Float ctrlTRecent;
|
||||
private Float ctrlTReference;
|
||||
private Float ctrlTError;
|
||||
private Float ctrlTErrorPrev;
|
||||
private Float ctrlIntegral;
|
||||
private Float ctrlYp;
|
||||
private Float ctrlYi;
|
||||
private Float ctrlYd;
|
||||
private Float ctrlY;
|
||||
private Short ctrlAntiWindUp;
|
||||
|
||||
/**
|
||||
* Creates a new {@link TemperatureControlInternals} through the {@link JsonObject} which will be returned by an
|
||||
* zone
|
||||
* call.<br>
|
||||
* Because of zone calls does not include a zoneID or zoneName in the json response, the zoneID and zoneName have to
|
||||
* be handed over the constructor.
|
||||
*
|
||||
* @param jObject must not be null
|
||||
* @param zoneID must not be null
|
||||
* @param zoneName can be null
|
||||
*/
|
||||
public TemperatureControlInternals(JsonObject jObject, Integer zoneID, String zoneName) {
|
||||
super(jObject, zoneID, zoneName);
|
||||
if (isNotSetOff()) {
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CONTROL_STATE.getKey()) != null) {
|
||||
this.controlState = jObject.get(JSONApiResponseKeysEnum.CONTROL_STATE.getKey()).getAsShort();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CTRL_T_RECENT.getKey()) != null) {
|
||||
this.ctrlTRecent = jObject.get(JSONApiResponseKeysEnum.CTRL_T_RECENT.getKey()).getAsFloat();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CTRL_T_REFERENCE.getKey()) != null) {
|
||||
this.ctrlTReference = jObject.get(JSONApiResponseKeysEnum.CTRL_T_REFERENCE.getKey()).getAsFloat();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CTRL_T_ERROR.getKey()) != null) {
|
||||
this.ctrlTError = jObject.get(JSONApiResponseKeysEnum.CTRL_T_ERROR.getKey()).getAsFloat();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CTRL_T_ERROR_PREV.getKey()) != null) {
|
||||
this.ctrlTErrorPrev = jObject.get(JSONApiResponseKeysEnum.CTRL_T_ERROR_PREV.getKey()).getAsFloat();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CTRL_INTEGRAL.getKey()) != null) {
|
||||
this.ctrlIntegral = jObject.get(JSONApiResponseKeysEnum.CTRL_INTEGRAL.getKey()).getAsFloat();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CTRL_YP.getKey()) != null) {
|
||||
this.ctrlY = jObject.get(JSONApiResponseKeysEnum.CTRL_YP.getKey()).getAsFloat();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CTRL_YI.getKey()) != null) {
|
||||
this.ctrlYi = jObject.get(JSONApiResponseKeysEnum.CTRL_YI.getKey()).getAsFloat();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CTRL_YD.getKey()) != null) {
|
||||
this.ctrlYd = jObject.get(JSONApiResponseKeysEnum.CTRL_YD.getKey()).getAsFloat();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CTRL_Y.getKey()) != null) {
|
||||
this.ctrlY = jObject.get(JSONApiResponseKeysEnum.CTRL_Y.getKey()).getAsFloat();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CTRL_ANTI_WIND_UP.getKey()) != null) {
|
||||
this.ctrlAntiWindUp = jObject.get(JSONApiResponseKeysEnum.CTRL_ANTI_WIND_UP.getKey()).getAsShort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the controleState for heating of the zone.
|
||||
*
|
||||
* @return the controlState
|
||||
*/
|
||||
public Short getControlState() {
|
||||
return controlState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ctrlTRecent for heating of the zone.
|
||||
*
|
||||
* @return the ctrlTRecent
|
||||
*/
|
||||
public Float getCtrlTRecent() {
|
||||
return ctrlTRecent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ctrlTReference for heating of the zone.
|
||||
*
|
||||
* @return the ctrlTReference
|
||||
*/
|
||||
public Float getCtrlTReference() {
|
||||
return ctrlTReference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ctrlTError for heating of the zone.
|
||||
*
|
||||
* @return the ctrlTError
|
||||
*/
|
||||
public Float getCtrlTError() {
|
||||
return ctrlTError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ctrlTErrorPrev for heating of the zone.
|
||||
*
|
||||
* @return the ctrlTErrorPrev
|
||||
*/
|
||||
public Float getCtrlTErrorPrev() {
|
||||
return ctrlTErrorPrev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ctrlIntegral for heating of the zone.
|
||||
*
|
||||
* @return the ctrlIntegral
|
||||
*/
|
||||
public Float getCtrlIntegral() {
|
||||
return ctrlIntegral;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ctrlYp for heating of the zone.
|
||||
*
|
||||
* @return the ctrlYp
|
||||
*/
|
||||
public Float getCtrlYp() {
|
||||
return ctrlYp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ctrlYi for heating of the zone.
|
||||
*
|
||||
* @return the ctrlYi
|
||||
*/
|
||||
public Float getCtrlYi() {
|
||||
return ctrlYi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ctrlYd for heating of the zone.
|
||||
*
|
||||
* @return the ctrlYd
|
||||
*/
|
||||
public Float getCtrlYd() {
|
||||
return ctrlYd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ctrlY for heating of the zone.
|
||||
*
|
||||
* @return the ctrlY
|
||||
*/
|
||||
public Float getCtrlY() {
|
||||
return ctrlY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ctrlAntiWindUp for heating of the zone.
|
||||
*
|
||||
* @return the ctrlAntiWindUp
|
||||
*/
|
||||
public Short getCtrlAntiWindUp() {
|
||||
return ctrlAntiWindUp;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TemperatureControlInternals [controlState=" + controlState + ", ctrlTRecent=" + ctrlTRecent
|
||||
+ ", ctrlTReference=" + ctrlTReference + ", ctrlTError=" + ctrlTError + ", ctrlTErrorPrev="
|
||||
+ ctrlTErrorPrev + ", ctrlIntegral=" + ctrlIntegral + ", ctrlYp=" + ctrlYp + ", ctrlYi=" + ctrlYi
|
||||
+ ", ctrlYd=" + ctrlYd + ", ctrlY=" + ctrlY + ", ctrlAntiWindUp=" + ctrlAntiWindUp + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.climate.jsonresponsecontainer.impl;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.climate.jsonresponsecontainer.BaseTemperatureControl;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.constants.JSONApiResponseKeysEnum;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link TemperatureControlStatus} acts as container for the digitalSTROM json-method
|
||||
* <i>getTemperatureControlStatus</i>. So the {@link TemperatureControlStatus} contains all heating
|
||||
* control status information of a zone.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class TemperatureControlStatus extends BaseTemperatureControl {
|
||||
|
||||
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss");
|
||||
|
||||
private Short controlState;
|
||||
private Short operationMode;
|
||||
private Float temperature;
|
||||
private String temperatureTime;
|
||||
private Float nominalValue;
|
||||
private String nominalValueTime;
|
||||
private Float controlValue;
|
||||
private String controlValueTime;
|
||||
|
||||
/**
|
||||
* Creates a new {@link TemperatureControlStatus} through the {@link JsonObject} which will be returned by an
|
||||
* apartment call.
|
||||
*
|
||||
* @param jObject must not be null
|
||||
*/
|
||||
public TemperatureControlStatus(JsonObject jObject) {
|
||||
super(jObject);
|
||||
init(jObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link TemperatureControlStatus} through the {@link JsonObject} which will be returned by an zone
|
||||
* call.<br>
|
||||
* Because of zone calls does not include a zoneID or zoneName in the json response, the zoneID and zoneName have to
|
||||
* be handed over the constructor.
|
||||
*
|
||||
* @param jObject must not be null
|
||||
* @param zoneID must not be null
|
||||
* @param zoneName can be null
|
||||
*/
|
||||
public TemperatureControlStatus(JsonObject jObject, Integer zoneID, String zoneName) {
|
||||
super(jObject, zoneID, zoneName);
|
||||
init(jObject);
|
||||
}
|
||||
|
||||
private void init(JsonObject jObject) {
|
||||
if (isNotSetOff()) {
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CONTROL_STATE.getKey()) != null) {
|
||||
this.controlState = jObject.get(JSONApiResponseKeysEnum.CONTROL_STATE.getKey()).getAsShort();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.OPERATION_MODE.getKey()) != null) {
|
||||
this.operationMode = jObject.get(JSONApiResponseKeysEnum.OPERATION_MODE.getKey()).getAsShort();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.TEMPERATION_VALUE.getKey()) != null) {
|
||||
this.temperature = jObject.get(JSONApiResponseKeysEnum.TEMPERATION_VALUE.getKey()).getAsFloat();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.NOMINAL_VALUE.getKey()) != null) {
|
||||
this.nominalValue = jObject.get(JSONApiResponseKeysEnum.NOMINAL_VALUE.getKey()).getAsFloat();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CONTROL_VALUE.getKey()) != null) {
|
||||
this.controlValue = jObject.get(JSONApiResponseKeysEnum.CONTROL_VALUE.getKey()).getAsFloat();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.TEMPERATION_VALUE_TIME.getKey()) != null) {
|
||||
this.temperatureTime = jObject.get(JSONApiResponseKeysEnum.TEMPERATION_VALUE_TIME.getKey())
|
||||
.getAsString();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.NOMINAL_VALUE_TIME.getKey()) != null) {
|
||||
this.nominalValueTime = jObject.get(JSONApiResponseKeysEnum.NOMINAL_VALUE_TIME.getKey()).getAsString();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CONTROL_VALUE_TIME.getKey()) != null) {
|
||||
this.controlValueTime = jObject.get(JSONApiResponseKeysEnum.CONTROL_VALUE_TIME.getKey()).getAsString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the controleState for heating of the zone.
|
||||
*
|
||||
* @return the controlState
|
||||
*/
|
||||
public Short getControlState() {
|
||||
return controlState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the operationMode for heating of the zone.
|
||||
*
|
||||
* @return the operationMode
|
||||
*/
|
||||
public Short getOperationMode() {
|
||||
return operationMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current temperature of the zone.
|
||||
*
|
||||
* @return the temperature
|
||||
*/
|
||||
public Float getTemperature() {
|
||||
return temperature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the timestamp when the temperature was read out as {@link Date}.
|
||||
*
|
||||
* @return the temperatureTime
|
||||
* @throws ParseException see {@link DateFormat#parse(String)}
|
||||
*/
|
||||
public Date getTemperatureTimeAsDate() throws ParseException {
|
||||
return formatter.parse(temperatureTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the timestamp when the temperature was read out as {@link String}.
|
||||
*
|
||||
* @return the temperatureTime
|
||||
*/
|
||||
public String getTemperatureTimeAsString() {
|
||||
return temperatureTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the nominal value for heating of the zone.
|
||||
*
|
||||
* @return the nominalValue
|
||||
*/
|
||||
public Float getNominalValue() {
|
||||
return nominalValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the timestamp as {@link Date} for the nominal value of the zone.
|
||||
*
|
||||
* @return the nominalValueTime
|
||||
* @throws ParseException see {@link DateFormat#parse(String)}
|
||||
*/
|
||||
public Date getNominalValueTimeAsDate() throws ParseException {
|
||||
return formatter.parse(nominalValueTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the timestamp as {@link String} for the nominal value of the zone.
|
||||
*
|
||||
* @return the nominalValueTime
|
||||
*/
|
||||
public String getNominalValueTimeAsString() {
|
||||
return nominalValueTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the control value for heating of the zone.
|
||||
*
|
||||
* @return the controlValue
|
||||
*/
|
||||
public Float getControlValue() {
|
||||
return controlValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns timestamp as {@link Date} for the control value for heating of the zone.
|
||||
*
|
||||
* @return the controlValueTime
|
||||
* @throws ParseException see {@link DateFormat#parse(String)}
|
||||
*/
|
||||
public Date getControlValueTimeAsDate() throws ParseException {
|
||||
return formatter.parse(controlValueTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns timestamp as {@link String} for the control value for heating of the zone.
|
||||
*
|
||||
* @return the controlValueTime
|
||||
*/
|
||||
public String getControlValueTimeAsString() {
|
||||
return controlValueTime;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TemperatureControlStatus [controlMode=" + controlMode + ", controlState=" + controlState
|
||||
+ ", operationMode=" + operationMode + ", temperature=" + temperature + ", temperatureTime="
|
||||
+ temperatureTime + ", nominalValue=" + nominalValue + ", nominalValueTime=" + nominalValueTime
|
||||
+ ", controlValue=" + controlValue + ", controlValueTime=" + controlValueTime + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.climate.jsonresponsecontainer.impl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.climate.constants.OperationModes;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.climate.jsonresponsecontainer.BaseZoneIdentifier;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.constants.JSONApiResponseKeysEnum;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link TemperatureControlValues} acts as container for the digitalSTROM json-method
|
||||
* <i>getTemperatureControlValues</i>. So the {@link TemperatureControlValues} contains all temperature
|
||||
* control values information of a zone.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class TemperatureControlValues extends BaseZoneIdentifier {
|
||||
|
||||
private Map<OperationModes, Float> temperatureControlValues;
|
||||
private String controlDSUID;
|
||||
private Boolean isConfigured;
|
||||
|
||||
/**
|
||||
* Creates a new {@link TemperatureControlValues} through the {@link JsonObject} which will be returned by an
|
||||
* apartment call.
|
||||
*
|
||||
* @param jObject must not be null
|
||||
*/
|
||||
public TemperatureControlValues(JsonObject jObject) {
|
||||
super(jObject);
|
||||
init(jObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link TemperatureControlValues} through the {@link JsonObject} which will be returned by an zone
|
||||
* call.<br>
|
||||
* Because of zone calls does not include a zoneID or zoneName in the json response, the zoneID and zoneName have to
|
||||
* be handed over the constructor.
|
||||
*
|
||||
* @param jObject must not be null
|
||||
* @param zoneID must not be null
|
||||
* @param zoneName can be null
|
||||
*/
|
||||
public TemperatureControlValues(JsonObject jObject, Integer zoneID, String zoneName) {
|
||||
super(zoneID, zoneName);
|
||||
init(jObject);
|
||||
}
|
||||
|
||||
private void init(JsonObject jObject) {
|
||||
if (jObject.get(JSONApiResponseKeysEnum.IS_CONFIGURED.getKey()) != null) {
|
||||
this.isConfigured = jObject.get(JSONApiResponseKeysEnum.IS_CONFIGURED.getKey()).getAsBoolean();
|
||||
}
|
||||
if (isConfigured) {
|
||||
if (jObject.get(JSONApiResponseKeysEnum.CONTROL_DSUID.getKey()) != null) {
|
||||
this.controlDSUID = jObject.get(JSONApiResponseKeysEnum.CONTROL_DSUID.getKey()).getAsString();
|
||||
}
|
||||
temperatureControlValues = new HashMap<>(OperationModes.values().length);
|
||||
for (OperationModes opMode : OperationModes.values()) {
|
||||
if (jObject.get(opMode.getKey()) != null) {
|
||||
temperatureControlValues.put(opMode, jObject.get(opMode.getKey()).getAsFloat());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TemperatureControlStatus#getControlDSUID()
|
||||
* @return the controlDSUID
|
||||
*/
|
||||
public String getControlDSUID() {
|
||||
return controlDSUID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TemperatureControlStatus#getIsConfigured()
|
||||
* @return the isConfigured
|
||||
*/
|
||||
public Boolean getIsConfigured() {
|
||||
return isConfigured;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set temperature of the given operation mode.
|
||||
*
|
||||
* @param operationMode must not be null
|
||||
* @return temperature of the operation mode
|
||||
*/
|
||||
public Float getTemperation(OperationModes operationMode) {
|
||||
return temperatureControlValues.get(operationMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the available operation modes as {@link Set}.
|
||||
*
|
||||
* @return available operation modes
|
||||
*/
|
||||
public Set<OperationModes> getOperationModes() {
|
||||
return temperatureControlValues.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Map} that maps the available operation modes to the set values.
|
||||
*
|
||||
* @return Map with operation modes and their values
|
||||
*/
|
||||
public Map<OperationModes, Float> getTemperatureControlValues() {
|
||||
return temperatureControlValues;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TemperatureControlValues [temperatureControlValues=" + temperatureControlValues + ", controlDSUID="
|
||||
+ controlDSUID + ", isConfigured=" + isConfigured + "]";
|
||||
}
|
||||
}
|
||||
@@ -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.digitalstrom.internal.lib.climate.jsonresponsecontainer.impl;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.climate.jsonresponsecontainer.BaseSensorValues;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.constants.JSONApiResponseKeysEnum;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link WeatherSensorData} acts as container for the digitalSTROM json-method <i>getSensorValues</i>. The
|
||||
* {@link WeatherSensorData} contains all {@link CachedSensorValue}s and weather service information of the
|
||||
* digitalSTROM-server, if a weather service is set.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class WeatherSensorData extends BaseSensorValues {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(WeatherSensorData.class);
|
||||
|
||||
private String weatherIconId;
|
||||
private String weatherConditionId;
|
||||
private String weatherServiceId;
|
||||
private String weatherServiceTime;
|
||||
|
||||
/**
|
||||
* Creates a new {@link SensorValues} through the {@link JsonObject} that will be returned by an apartment call.
|
||||
*
|
||||
* @param jObject must not be null
|
||||
*/
|
||||
public WeatherSensorData(JsonObject jObject) {
|
||||
super.addSensorValue(jObject, true);
|
||||
if (jObject.get(JSONApiResponseKeysEnum.WEATHER_ICON_ID.getKey()) != null) {
|
||||
weatherIconId = jObject.get(JSONApiResponseKeysEnum.WEATHER_ICON_ID.getKey()).getAsString();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.WEATHER_CONDITION_ID.getKey()) != null) {
|
||||
weatherConditionId = jObject.get(JSONApiResponseKeysEnum.WEATHER_CONDITION_ID.getKey()).getAsString();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.WEATHER_SERVICE_ID.getKey()) != null) {
|
||||
weatherServiceId = jObject.get(JSONApiResponseKeysEnum.WEATHER_SERVICE_ID.getKey()).getAsString();
|
||||
}
|
||||
if (jObject.get(JSONApiResponseKeysEnum.WEATHER_SERVICE_TIME.getKey()) != null) {
|
||||
weatherServiceTime = jObject.get(JSONApiResponseKeysEnum.WEATHER_SERVICE_TIME.getKey()).getAsString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the weather icon id of the set weather service.
|
||||
*
|
||||
* @return the weatherIconId
|
||||
*/
|
||||
public String getWeatherIconId() {
|
||||
return weatherIconId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the weather condition id of the set weather service.
|
||||
*
|
||||
* @return the weatherConditionId
|
||||
*/
|
||||
public String getWeatherConditionId() {
|
||||
return weatherConditionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the weather service id of the set weather service.
|
||||
*
|
||||
* @return the weatherServiceId
|
||||
*/
|
||||
public String getWeatherServiceId() {
|
||||
return weatherServiceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the weather service time as {@link String} of the set weather service.
|
||||
*
|
||||
* @return the weatherServiceTime as {@link String}
|
||||
*/
|
||||
public String getWeatherServiceTimeAsSting() {
|
||||
return weatherServiceTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the weather service time as {@link Date} of the set weather service.
|
||||
*
|
||||
* @return the weatherServiceTime as {@link Date}
|
||||
*/
|
||||
public Date getWeatherServiceTimeAsDate() {
|
||||
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SS");
|
||||
try {
|
||||
return formatter.parse(weatherServiceTime);
|
||||
} catch (ParseException e) {
|
||||
logger.error("A ParseException occurred by parsing date string: {}", weatherServiceTime, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WeatherSensorData [weatherIconId=" + weatherIconId + ", weatherConditionId=" + weatherConditionId
|
||||
+ ", weatherServiceId=" + weatherServiceId + ", weatherServiceTime=" + weatherServiceTime + ", "
|
||||
+ super.toString() + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,622 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.config;
|
||||
|
||||
/**
|
||||
* The {@link Config} contains all configurations for the digitalSTROM-Library.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class Config {
|
||||
|
||||
/* Client configuration */
|
||||
// connection configuration
|
||||
/**
|
||||
* The default application name to generate the application token.
|
||||
*/
|
||||
public static final String DEFAULT_APPLICATION_NAME = "openHAB";
|
||||
/**
|
||||
* Defines the used tread pool name to get a thread pool from {@link ThreadPoolManager}.
|
||||
*/
|
||||
public static final String THREADPOOL_NAME = "digitalSTROM";
|
||||
|
||||
private String applicationName = DEFAULT_APPLICATION_NAME;
|
||||
|
||||
private String host;
|
||||
private String userName;
|
||||
private String password;
|
||||
private String appToken;
|
||||
private String trustCertPath;
|
||||
private String cert;
|
||||
|
||||
// Timeouts
|
||||
/**
|
||||
* Default connection timeout
|
||||
*/
|
||||
public static final int DEFAULT_CONNECTION_TIMEOUT = 4000;
|
||||
/**
|
||||
* High connection timeout for requests that take some time.
|
||||
*/
|
||||
public static final int HIGH_CONNECTION_TIMEOUT = 60000;
|
||||
/**
|
||||
* Default read timeout
|
||||
*/
|
||||
public static final int DEFAULT_READ_TIMEOUT = 10000;
|
||||
/**
|
||||
* High read timeout for requests that take some time.
|
||||
*/
|
||||
public static final int HIGH_READ_TIMEOUT = 60000;
|
||||
/**
|
||||
* Default connection timeout for sensor readings from devices
|
||||
*/
|
||||
public static final int DEFAULT_SENSORDATA_CONNECTION_TIMEOUT = 4000;
|
||||
/**
|
||||
* Default read timeout for sensor readings from devices
|
||||
*/
|
||||
public static final int DEFAULT_SENSORDATA_READ_TIMEOUT = 20000;
|
||||
|
||||
private int connectionTimeout = DEFAULT_CONNECTION_TIMEOUT;
|
||||
private int readTimeout = DEFAULT_READ_TIMEOUT;
|
||||
private int sensordataConnectionTimeout = DEFAULT_SENSORDATA_CONNECTION_TIMEOUT;
|
||||
private int sensordataReadTimeout = DEFAULT_SENSORDATA_READ_TIMEOUT;
|
||||
|
||||
/* Internal Configurations */
|
||||
// Trash Bin Config
|
||||
/**
|
||||
* The default number of days after the trash devices is deleted.
|
||||
*/
|
||||
public static final int DEFAULT_TRASH_DEVICE_DELETE_TIME = 7;
|
||||
private int trashDeviceDeleteTime = DEFAULT_TRASH_DEVICE_DELETE_TIME;
|
||||
|
||||
/**
|
||||
* The default milliseconds after the trash devices will be checked if its time to delete.
|
||||
*/
|
||||
public static final int DEFAULT_BIN_CHECK_TIME = 360000; // in milliseconds
|
||||
private int binCheckTime = DEFAULT_BIN_CHECK_TIME; // in milliseconds
|
||||
|
||||
// Device update config
|
||||
|
||||
/**
|
||||
* Default interval of the polling frequency in milliseconds. The digitalSTROM-rules state that the
|
||||
* polling interval must to be at least 1 second.
|
||||
*/
|
||||
public static final int DEFAULT_POLLING_FREQUENCY = 1000; // in milliseconds
|
||||
private int pollingFrequency = DEFAULT_POLLING_FREQUENCY; // in milliseconds
|
||||
|
||||
/* Sensordata */
|
||||
// Sensodata read config
|
||||
|
||||
/**
|
||||
* The default interval to refresh the sensor data.
|
||||
*/
|
||||
public static final int DEFAULT_SENSORDATA_REFRESH_INTERVAL = 60000;
|
||||
private int sensordataRefreshInterval = DEFAULT_SENSORDATA_REFRESH_INTERVAL;
|
||||
|
||||
/**
|
||||
* The default interval to refresh the total power sensor data.
|
||||
*/
|
||||
public static final int DEFAULT_TOTAL_POWER_UPDATE_INTERVAL = 30000;
|
||||
private int totalPowerUpdateInterval = DEFAULT_TOTAL_POWER_UPDATE_INTERVAL;
|
||||
|
||||
/**
|
||||
* Default time to wait between another {@link SensorJob} can be executed on a circuit.
|
||||
*/
|
||||
public static final int DEFAULT_SENSOR_READING_WAIT_TIME = 60000;
|
||||
private int sensorReadingWaitTime = DEFAULT_SENSOR_READING_WAIT_TIME;
|
||||
|
||||
// sensor data Prioritys
|
||||
/**
|
||||
* Priority for never refresh the sensor value.
|
||||
*/
|
||||
public static final String REFRESH_PRIORITY_NEVER = "never";
|
||||
/**
|
||||
* Priority for refresh the sensor value with low priority.
|
||||
*/
|
||||
public static final String REFRESH_PRIORITY_LOW = "low";
|
||||
/**
|
||||
* Priority for refresh the sensor value with medium priority.
|
||||
*/
|
||||
public static final String REFRESH_PRIORITY_MEDIUM = "medium";
|
||||
/**
|
||||
* Priority for refresh the sensor value with high priority.
|
||||
*/
|
||||
public static final String REFRESH_PRIORITY_HIGH = "high";
|
||||
|
||||
// max sensor reading cyclic to wait
|
||||
/**
|
||||
* The default factor to prioritize medium {@link SensorJob}s down.
|
||||
*/
|
||||
public static final long DEFAULT_MEDIUM_PRIORITY_FACTOR = 5;
|
||||
/**
|
||||
* The default factor to prioritize low {@link SensorJob}s down.
|
||||
*/
|
||||
public static final long DEFAULT_LOW_PRIORITY_FACTOR = 10;
|
||||
|
||||
private long mediumPriorityFactor = DEFAULT_MEDIUM_PRIORITY_FACTOR;
|
||||
private long lowPriorityFactor = DEFAULT_LOW_PRIORITY_FACTOR;
|
||||
|
||||
/**
|
||||
* Defines the event polling interval of the {@link EventListener} in milliseconds.
|
||||
*/
|
||||
private int eventListenerRefreshinterval = DEFAULT_POLLING_FREQUENCY;
|
||||
|
||||
/**
|
||||
* The default max standby active power for a device. It's needed to set a {@link Device} with output mode
|
||||
* {@link OutputModeEnum#WIPE} on if it isen't any more in standby mode.
|
||||
*/
|
||||
public static final int DEFAULT_STANDBY_ACTIVE_POWER = 2;
|
||||
|
||||
private int standbyActivePower = DEFAULT_STANDBY_ACTIVE_POWER;
|
||||
|
||||
/**
|
||||
* Creates a new {@link Config} and set the given hostAddress, userName, password and applicationToken. The other
|
||||
* configurations will be set to default.
|
||||
*
|
||||
* @param hostAddress of the digitalSTROM-Server, must not be null
|
||||
* @param userName to login, can be null
|
||||
* @param password to login, can be null
|
||||
* @param applicationToken to login , can be null
|
||||
*/
|
||||
public Config(String hostAddress, String userName, String password, String applicationToken) {
|
||||
this.host = hostAddress;
|
||||
this.userName = userName;
|
||||
this.password = password;
|
||||
this.appToken = applicationToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Config} with default values.
|
||||
*/
|
||||
public Config() {
|
||||
// config with default values
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the host name from the server.
|
||||
*
|
||||
* @return the host address
|
||||
*/
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the host name of the Server.
|
||||
* <br>
|
||||
* <br>
|
||||
* <b>Note:</b><br>
|
||||
* If the host dosen't use the default port (8080), the port has to be set after the host name. e.g.
|
||||
* <i>my-digitalSTROM-Server.com:58080</i>
|
||||
*
|
||||
* @param hostAddress of the digitalSTROM-Server
|
||||
*/
|
||||
public void setHost(String hostAddress) {
|
||||
this.host = hostAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the username.
|
||||
*
|
||||
* @return the username
|
||||
*/
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the username.
|
||||
*
|
||||
* @param userName to set
|
||||
*/
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the password.
|
||||
*
|
||||
* @return the password
|
||||
*/
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the password.
|
||||
*
|
||||
* @param password to set
|
||||
*/
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Application-Token.
|
||||
*
|
||||
* @return the Application-Token
|
||||
*/
|
||||
public String getAppToken() {
|
||||
return appToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Application-Token.
|
||||
*
|
||||
* @param applicationToken to set
|
||||
*/
|
||||
public void setAppToken(String applicationToken) {
|
||||
this.appToken = applicationToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the connection timeout.
|
||||
*
|
||||
* @return the connection timeout
|
||||
*/
|
||||
public int getConnectionTimeout() {
|
||||
return connectionTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the connection timeout.
|
||||
*
|
||||
* @param connectionTimeout to set
|
||||
*/
|
||||
public void setConnectionTimeout(int connectionTimeout) {
|
||||
this.connectionTimeout = connectionTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the read timeout.
|
||||
*
|
||||
* @return the read timeout
|
||||
*/
|
||||
public int getReadTimeout() {
|
||||
return readTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the read timeout.
|
||||
*
|
||||
* @param readTimeout the readTimeout to set
|
||||
*/
|
||||
public void setReadTimeout(int readTimeout) {
|
||||
this.readTimeout = readTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the connection timeout for sensor readings from devices.
|
||||
*
|
||||
* @return the connection sensor data timeout
|
||||
*/
|
||||
public int getSensordataConnectionTimeout() {
|
||||
return sensordataConnectionTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the connection timeout for sensor readings from devices.
|
||||
*
|
||||
* @param sensordataConnectionTimeout to set
|
||||
*/
|
||||
public void setSensordataConnectionTimeout(int sensordataConnectionTimeout) {
|
||||
this.sensordataConnectionTimeout = sensordataConnectionTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the read timeout for sensor readings from devices.
|
||||
*
|
||||
* @return the read sensor data timeout
|
||||
*/
|
||||
public int getSensordataReadTimeout() {
|
||||
return sensordataReadTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the connection timeout for sensor readings from devices.
|
||||
*
|
||||
* @param sensordataReadTimeout to set
|
||||
*/
|
||||
public void setSensordataReadTimeout(int sensordataReadTimeout) {
|
||||
this.sensordataReadTimeout = sensordataReadTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path to the SSL-Certificate.
|
||||
*
|
||||
* @return the path to the trust certification
|
||||
*/
|
||||
public String getTrustCertPath() {
|
||||
return trustCertPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the SSL-Certificate of the server.
|
||||
*
|
||||
* @return the SSL-Certificate of the server
|
||||
*/
|
||||
public String getCert() {
|
||||
return cert;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the SSL-Certificate of the server, will be set automatically by the {@link HttpTransportImpl} if no
|
||||
* SSL-Certification path is set.
|
||||
*
|
||||
* @param cert of the digitalSTROM-Server to set
|
||||
*/
|
||||
public void setCert(String cert) {
|
||||
this.cert = cert;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the path to the SSL-Certificate. It can be a absolute or relative path.
|
||||
*
|
||||
* @param trustCertPath path to a SSL-Certificate
|
||||
*/
|
||||
public void setTrustCertPath(String trustCertPath) {
|
||||
this.trustCertPath = trustCertPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of days after the trash devices is deleted.
|
||||
*
|
||||
* @return the trash-device delete time in days
|
||||
*/
|
||||
public int getTrashDeviceDeleteTime() {
|
||||
return trashDeviceDeleteTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of days after the trash devices is deleted.
|
||||
*
|
||||
* @param trashDeviceDeleteTime in days
|
||||
*/
|
||||
public void setTrashDeviceDeleteTime(int trashDeviceDeleteTime) {
|
||||
this.trashDeviceDeleteTime = trashDeviceDeleteTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the milliseconds after the trash devices will be checked, if its time to delete.
|
||||
*
|
||||
* @return the bin check time in milliseconds
|
||||
*/
|
||||
public int getBinCheckTime() {
|
||||
return binCheckTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the milliseconds after the trash devices will be checked, if its time to delete.
|
||||
*
|
||||
* @param binCheckTime in milliseconds
|
||||
*/
|
||||
public void setBinCheckTime(int binCheckTime) {
|
||||
this.binCheckTime = binCheckTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the interval of the polling frequency in milliseconds. The digitalSTROM-rules state that the
|
||||
* polling interval must to be at least 1 second.
|
||||
*
|
||||
* @return the pollingFrequency in milliseconds
|
||||
*/
|
||||
public int getPollingFrequency() {
|
||||
return pollingFrequency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the interval of the polling frequency in milliseconds. The digitalSTROM-rules state that the
|
||||
* polling interval must to be at least 1 second.
|
||||
*
|
||||
* @param pollingFrequency to set
|
||||
*/
|
||||
public void setPollingFrequency(int pollingFrequency) {
|
||||
this.pollingFrequency = pollingFrequency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the interval in milliseconds to refresh the sensor data.
|
||||
*
|
||||
* @return the sensor data refresh interval in milliseconds
|
||||
*/
|
||||
public int getSensordataRefreshInterval() {
|
||||
return sensordataRefreshInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the interval in milliseconds to refresh the sensor data.
|
||||
*
|
||||
* @param sensordataRefreshInterval in milliseconds.
|
||||
*/
|
||||
public void setSensordataRefreshInterval(int sensordataRefreshInterval) {
|
||||
this.sensordataRefreshInterval = sensordataRefreshInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the interval to refresh the total power sensor data.
|
||||
*
|
||||
* @return the total power update interval in milliseconds.
|
||||
*/
|
||||
public int getTotalPowerUpdateInterval() {
|
||||
return totalPowerUpdateInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the interval in milliseconds to refresh the total power sensor data.
|
||||
*
|
||||
* @param totalPowerUpdateInterval in milliseconds
|
||||
*/
|
||||
public void setTotalPowerUpdateInterval(int totalPowerUpdateInterval) {
|
||||
this.totalPowerUpdateInterval = totalPowerUpdateInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time in milliseconds to wait between another {@link SensorJob} can be executed on a circuit.
|
||||
*
|
||||
* @return the sensor reading wait time in milliseconds
|
||||
*/
|
||||
public int getSensorReadingWaitTime() {
|
||||
return sensorReadingWaitTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the time in milliseconds to wait between another {@link SensorJob} can be executed on a circuit.
|
||||
*
|
||||
* @param sensorReadingWaitTime in milliseconds
|
||||
*/
|
||||
public void setSensorReadingWaitTime(int sensorReadingWaitTime) {
|
||||
this.sensorReadingWaitTime = sensorReadingWaitTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the factor to prioritize medium {@link SensorJob}s in the {@link SensorJobExecutor} down.
|
||||
*
|
||||
* @return the medium priority factor
|
||||
*/
|
||||
public long getMediumPriorityFactor() {
|
||||
return mediumPriorityFactor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the factor to prioritize medium {@link SensorJob}s in the {@link SensorJobExecutor} down.
|
||||
*
|
||||
* @param mediumPriorityFactor to set
|
||||
*/
|
||||
public void setMediumPriorityFactor(long mediumPriorityFactor) {
|
||||
this.mediumPriorityFactor = mediumPriorityFactor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the factor to prioritize low {@link SensorJob}s in the {@link SensorJobExecutor} down.
|
||||
*
|
||||
* @return the low priority factor
|
||||
*/
|
||||
public long getLowPriorityFactor() {
|
||||
return lowPriorityFactor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the factor to prioritize low {@link SensorJob}s in the {@link SensorJobExecutor}down.
|
||||
*
|
||||
* @param lowPriorityFactor to set
|
||||
*/
|
||||
public void setLowPriorityFactor(long lowPriorityFactor) {
|
||||
this.lowPriorityFactor = lowPriorityFactor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the polling interval in milliseconds to poll the {@link Event}s in the {@link EventListener}.
|
||||
*
|
||||
* @return the EventListener refresh interval in milliseconds
|
||||
*/
|
||||
public int getEventListenerRefreshinterval() {
|
||||
return eventListenerRefreshinterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the polling interval in milliseconds to poll the {@link Event}s in the {@link EventListener}.
|
||||
*
|
||||
* @param eventListenerRefreshinterval to set
|
||||
*/
|
||||
public void setEventListenerRefreshinterval(int eventListenerRefreshinterval) {
|
||||
this.eventListenerRefreshinterval = eventListenerRefreshinterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the max standby active power for a device. It's needed to set a {@link Device} with output mode
|
||||
* {@link OutputModeEnum#WIPE} on if it isen't any more in standby mode.
|
||||
*
|
||||
* @return the standby active power
|
||||
*/
|
||||
public int getStandbyActivePower() {
|
||||
return standbyActivePower;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the max standby active power for a device. It's needed to set a {@link Device} with output mode
|
||||
* {@link OutputModeEnum#WIPE} on if it isen't any more in standby mode.
|
||||
*
|
||||
* @param standbyActivePower to set
|
||||
*/
|
||||
public void setStandbyActivePower(int standbyActivePower) {
|
||||
this.standbyActivePower = standbyActivePower;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the application name to generate the application token.
|
||||
*
|
||||
* @return the applicationName
|
||||
*/
|
||||
public String getApplicationName() {
|
||||
return applicationName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the application name to generate the application token.
|
||||
*
|
||||
* @param applicationName to set
|
||||
*/
|
||||
public void setApplicationName(String applicationName) {
|
||||
this.applicationName = applicationName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the configured username and password from this {@link Config}.
|
||||
*/
|
||||
public void removeUsernameAndPassword() {
|
||||
this.userName = null;
|
||||
this.password = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates this {@link Config} with the configuration of given {@link Config}.
|
||||
*
|
||||
* @param config new config
|
||||
*/
|
||||
public void updateConfig(Config config) {
|
||||
setHost(config.getHost());
|
||||
setUserName(config.getUserName());
|
||||
setPassword(config.getPassword());
|
||||
setAppToken(config.getAppToken());
|
||||
setConnectionTimeout(config.getConnectionTimeout());
|
||||
setReadTimeout(config.getReadTimeout());
|
||||
setSensordataConnectionTimeout(config.getSensordataConnectionTimeout());
|
||||
setSensordataReadTimeout(config.getSensordataReadTimeout());
|
||||
setTrustCertPath(config.getTrustCertPath());
|
||||
setTrashDeviceDeleteTime(config.getTrashDeviceDeleteTime());
|
||||
setBinCheckTime(config.getBinCheckTime());
|
||||
setPollingFrequency(config.getPollingFrequency());
|
||||
setSensordataRefreshInterval(config.getSensordataRefreshInterval());
|
||||
setTotalPowerUpdateInterval(config.getTotalPowerUpdateInterval());
|
||||
setSensorReadingWaitTime(config.getSensorReadingWaitTime());
|
||||
setMediumPriorityFactor(config.getMediumPriorityFactor());
|
||||
setLowPriorityFactor(config.getLowPriorityFactor());
|
||||
setEventListenerRefreshinterval(config.getEventListenerRefreshinterval());
|
||||
setStandbyActivePower(config.getStandbyActivePower());
|
||||
setApplicationName(config.getApplicationName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Config [applicationName=" + applicationName + ", host=" + host + ", userName=" + userName
|
||||
+ ", password=" + password + ", appToken=" + appToken + ", connectionTimeout=" + connectionTimeout
|
||||
+ ", readTimeout=" + readTimeout + ", sensordataConnectionTimeout=" + sensordataConnectionTimeout
|
||||
+ ", sensordataReadTimeout=" + sensordataReadTimeout + ", trustCertPath=" + trustCertPath
|
||||
+ ", trashDeviceDeleteTime=" + trashDeviceDeleteTime + ", binCheckTime=" + binCheckTime
|
||||
+ ", pollingFrequency=" + pollingFrequency + ", sensordataRefreshInterval=" + sensordataRefreshInterval
|
||||
+ ", totalPowerUpdateInterval=" + totalPowerUpdateInterval + ", sensorReadingWaitTime="
|
||||
+ sensorReadingWaitTime + ", mediumPriorityFactor=" + mediumPriorityFactor + ", lowPriorityFactor="
|
||||
+ lowPriorityFactor + ", eventListenerRefreshinterval=" + eventListenerRefreshinterval
|
||||
+ ", standbyActivePower=" + standbyActivePower + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.event;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.event.types.EventItem;
|
||||
|
||||
/**
|
||||
* The {@link EventHandler} can be implemented to get informed by {@link EventItem}'s through the {@link EventListener}.
|
||||
* <br>
|
||||
* For that the {@link #getSupportetEvents()} and {@link #supportsEvent(String)} methods have to be implemented, so that
|
||||
* the {@link EventListener} knows whitch events it has to subscribe at the digitalSTROM-server and which handler has
|
||||
* to be informed. <br>
|
||||
* The implementation of the {@link EventHandler} also has to be registered through
|
||||
* {@link EventListener#addEventHandler(EventHandler)} to the {@link EventListener} and the {@link EventListener} has to
|
||||
* be started.<br>
|
||||
* <br>
|
||||
* To handle the {@link EventItem} the method {@link #handleEvent(EventItem)} has to be implemented.
|
||||
*
|
||||
* @author Michael Ochel
|
||||
* @author Matthias Siegele
|
||||
*/
|
||||
public interface EventHandler {
|
||||
|
||||
/**
|
||||
* Handles a {@link EventItem} e.g. which was detected by the {@link EventListener}.
|
||||
*
|
||||
* @param eventItem to handle
|
||||
*/
|
||||
void handleEvent(EventItem eventItem);
|
||||
|
||||
/**
|
||||
* Returns a {@link List} that contains the supported events.
|
||||
*
|
||||
* @return supported events
|
||||
*/
|
||||
List<String> getSupportedEvents();
|
||||
|
||||
/**
|
||||
* Returns true, if the {@link EventHandler} supports the given event.
|
||||
*
|
||||
* @param eventName to check
|
||||
* @return true, if event is supported, otherwise false
|
||||
*/
|
||||
boolean supportsEvent(String eventName);
|
||||
|
||||
/**
|
||||
* Returns the unique id of the {@link EventHandler}.
|
||||
*
|
||||
* @return uid of the EventHandler
|
||||
*/
|
||||
String getUID();
|
||||
|
||||
/**
|
||||
* Sets a {@link EventListener} to this {@link EventHandler}.
|
||||
*
|
||||
* @param eventListener to set
|
||||
*/
|
||||
void setEventListener(EventListener eventListener);
|
||||
|
||||
/**
|
||||
* Unsets a {@link EventListener} to this {@link EventHandler}.
|
||||
*
|
||||
* @param eventListener to unset
|
||||
*/
|
||||
void unsetEventListener(EventListener eventListener);
|
||||
}
|
||||
@@ -0,0 +1,419 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.event;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.config.Config;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.event.types.Event;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.event.types.EventItem;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.event.types.JSONEventImpl;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.ConnectionManager;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.constants.JSONApiResponseKeysEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.impl.JSONResponseHandler;
|
||||
import org.openhab.core.common.ThreadPoolManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link EventListener} listens for events which will be thrown by the digitalSTROM-Server and it notifies the
|
||||
* added {@link EventHandler} about the detected events, if it supports the event-type.<br>
|
||||
* You can add {@link EventHandler}'s through the constructors or the methods {@link #addEventHandler(EventHandler)} and
|
||||
* {@link #addEventHandlers(List)}.<br>
|
||||
* You can also delete a {@link EventHandler} though the method {@link #removeEventHandler(EventHandler)}.<br>
|
||||
* If the {@link EventListener} is started, both methods subscribe respectively unsubscribe the event-types of the
|
||||
* {@link EventHandler}/s automatically.<br>
|
||||
* If you want to dynamically subscribe event-types, e.g. because a configuration has changed and a
|
||||
* {@link EventHandler} needs to be informed of another event-type, you can use the methods
|
||||
* {@link #addSubscribe(String)} or {@link #addSubscribeEvents(List)} to add more than one event-type. To remove a
|
||||
* subscribed event you can use the method {@link #removeSubscribe(String, String)}, you also have to change the return
|
||||
* of the {@link EventHandler} methods {@link EventHandler#getSupportetEvents()} and
|
||||
* {@link EventHandler#supportsEvent(String)}.
|
||||
* <br>
|
||||
* To start and stop the listening you have to call the methods {@link #start()} and {@link #stop()}.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class EventListener {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(EventListener.class);
|
||||
private final ScheduledExecutorService scheduler = ThreadPoolManager.getScheduledPool(Config.THREADPOOL_NAME);
|
||||
public static final int SUBSCRIBE_DELAY = 500;
|
||||
private ScheduledFuture<?> pollingScheduler;
|
||||
private ScheduledFuture<?> subscriptionScheduler;
|
||||
|
||||
private int subscriptionID = 15;
|
||||
private final int timeout = 500;
|
||||
private final List<String> subscribedEvents = Collections.synchronizedList(new LinkedList<>());
|
||||
private boolean subscribed = false;
|
||||
|
||||
// error message
|
||||
public static final String INVALID_SESSION = "Invalid session!";
|
||||
public static final String TOKEN_NOT_FOUND = "token not found."; // Complete text: "Event subscription token not
|
||||
// found."
|
||||
|
||||
private final ConnectionManager connManager;
|
||||
private final List<EventHandler> eventHandlers = Collections.synchronizedList(new LinkedList<>());
|
||||
private final Config config;
|
||||
private boolean isStarted = false;
|
||||
|
||||
/**
|
||||
* Creates a new {@link EventListener} to listen to the supported event-types of the given eventHandler and notify
|
||||
* about a detected event.<br>
|
||||
* <br>
|
||||
* To get notified by events you have to call {@link #start()}.
|
||||
*
|
||||
* @param connectionManager must not be null
|
||||
* @param eventHandler must not be null
|
||||
*/
|
||||
public EventListener(ConnectionManager connectionManager, EventHandler eventHandler) {
|
||||
this.connManager = connectionManager;
|
||||
this.config = connectionManager.getConfig();
|
||||
addEventHandler(eventHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* This constructor can add more than one {@link EventHandler} as a list of {@link EventHandler}'s.
|
||||
*
|
||||
* @param connectionManager must not be null
|
||||
* @param eventHandlers list of {@link EventHandler}'s must not be null
|
||||
* @see #EventListener(ConnectionManager, EventHandler)
|
||||
*/
|
||||
public EventListener(ConnectionManager connectionManager, List<EventHandler> eventHandlers) {
|
||||
this.connManager = connectionManager;
|
||||
this.config = connectionManager.getConfig();
|
||||
addEventHandlers(eventHandlers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link EventListener} without a {@link EventHandler}<br>
|
||||
* <br>
|
||||
* To get notified by events you have to call {@link #start()} and {@link #addEventHandler(EventHandler)} or
|
||||
* {@link #addEventHandlers(List)}.
|
||||
*
|
||||
* @param connectionManager must not be null
|
||||
*/
|
||||
public EventListener(ConnectionManager connectionManager) {
|
||||
this.connManager = connectionManager;
|
||||
this.config = connectionManager.getConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops this {@link EventListener} and unsubscribe events.
|
||||
*/
|
||||
public synchronized void stop() {
|
||||
logger.debug("Stop EventListener");
|
||||
isStarted = false;
|
||||
internalStop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, if the {@link EventListener} is started.
|
||||
*
|
||||
* @return true, if is started
|
||||
*/
|
||||
public boolean isStarted() {
|
||||
return isStarted;
|
||||
}
|
||||
|
||||
private void internalStop() {
|
||||
if (subscriptionScheduler != null && !subscriptionScheduler.isCancelled()) {
|
||||
subscriptionScheduler.cancel(true);
|
||||
subscriptionScheduler = null;
|
||||
}
|
||||
if (pollingScheduler != null && !pollingScheduler.isCancelled()) {
|
||||
pollingScheduler.cancel(true);
|
||||
pollingScheduler = null;
|
||||
unsubscribe();
|
||||
logger.debug("internal stop EventListener");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts this {@link EventListener} and subscribe events.
|
||||
*/
|
||||
public synchronized void start() {
|
||||
logger.debug("Start EventListener");
|
||||
isStarted = true;
|
||||
internalStart();
|
||||
}
|
||||
|
||||
private void internalStart() {
|
||||
if (!eventHandlers.isEmpty() && (pollingScheduler == null || pollingScheduler.isCancelled())) {
|
||||
pollingScheduler = scheduler.scheduleWithFixedDelay(runableListener, 0,
|
||||
config.getEventListenerRefreshinterval(), TimeUnit.MILLISECONDS);
|
||||
logger.debug("internal start EventListener");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link List} of {@link EventHandler}'s and subscribe the supported event-types, if the
|
||||
* {@link EventListener} is started and the event-types are not already subscribed.
|
||||
*
|
||||
* @param eventHandlers to add
|
||||
*/
|
||||
public void addEventHandlers(List<EventHandler> eventHandlers) {
|
||||
if (eventHandlers != null) {
|
||||
for (EventHandler eventHandler : eventHandlers) {
|
||||
addEventHandler(eventHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link EventHandler}'s and subscribe the supported event-types, if the
|
||||
* {@link EventListener} is started and the event-types are not already subscribed.<br>
|
||||
* <br>
|
||||
* <b>Note:</b><br>
|
||||
* If {@link #start()} was called before the {@link EventListener} will start now, otherwise you have to call
|
||||
* {@link #start()} to get notified by events.
|
||||
*
|
||||
* @param eventHandler to add
|
||||
*/
|
||||
public void addEventHandler(EventHandler eventHandler) {
|
||||
if (eventHandler != null) {
|
||||
boolean handlerExist = false;
|
||||
for (EventHandler handler : eventHandlers) {
|
||||
if (handler.getUID().equals(eventHandler.getUID())) {
|
||||
handlerExist = true;
|
||||
}
|
||||
}
|
||||
if (!handlerExist) {
|
||||
eventHandlers.add(eventHandler);
|
||||
addSubscribeEvents(eventHandler.getSupportedEvents());
|
||||
logger.debug("eventHandler: {} added", eventHandler.getUID());
|
||||
if (isStarted) {
|
||||
internalStart();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a {@link EventHandler} and unsubscribes the supported event-types, if the
|
||||
* {@link EventListener} is started and no other {@link EventHandler} needed the event-types.
|
||||
*
|
||||
* @param eventHandler to remove
|
||||
*/
|
||||
public void removeEventHandler(EventHandler eventHandler) {
|
||||
if (eventHandler != null && eventHandlers.contains(eventHandler)) {
|
||||
List<String> tempSubsList = new ArrayList<>();
|
||||
int index = -1;
|
||||
EventHandler intEventHandler = null;
|
||||
boolean subscribedEventsChanged = false;
|
||||
for (int i = 0; i < eventHandlers.size(); i++) {
|
||||
intEventHandler = eventHandlers.get(i);
|
||||
if (intEventHandler.getUID().equals(eventHandler.getUID())) {
|
||||
index = i;
|
||||
} else {
|
||||
tempSubsList.addAll(intEventHandler.getSupportedEvents());
|
||||
}
|
||||
}
|
||||
if (index != -1) {
|
||||
intEventHandler = eventHandlers.remove(index);
|
||||
for (String eventName : intEventHandler.getSupportedEvents()) {
|
||||
if (!tempSubsList.contains(eventName)) {
|
||||
subscribedEvents.remove(eventName);
|
||||
subscribedEventsChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (subscribedEventsChanged) {
|
||||
// Because of the json-call unsubscribe?eventName=XY&subscriptionID=Z doesn't work like it is explained
|
||||
// in the dS-JSON-API, the whole EventListener will be restarted. The problem is, that not only the
|
||||
// given eventName, rather all events of the subscitionID will be deleted.
|
||||
restartListener();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a subscribed event and unsubscibe it, if it is not needed by other {@link EventHandler}'s.
|
||||
*
|
||||
* @param unsubscribeEvent event name to unsubscibe
|
||||
* @param eventHandlerID EventHandler-ID of the EventHandler that unsubscibe a event
|
||||
*/
|
||||
public void removeSubscribe(String unsubscribeEvent, String eventHandlerID) {
|
||||
if (subscribedEvents != null && !subscribedEvents.contains(unsubscribeEvent)) {
|
||||
boolean eventNeededByAnotherHandler = false;
|
||||
for (EventHandler handler : eventHandlers) {
|
||||
if (!handler.getUID().equals(eventHandlerID)) {
|
||||
eventNeededByAnotherHandler = handler.getSupportedEvents().contains(unsubscribeEvent);
|
||||
}
|
||||
}
|
||||
if (!eventNeededByAnotherHandler) {
|
||||
logger.debug("unsubscribeEvent: {} is not needed by other EventHandler's... unsubscribe it",
|
||||
unsubscribeEvent);
|
||||
subscribedEvents.remove(unsubscribeEvent);
|
||||
restartListener();
|
||||
} else {
|
||||
logger.debug("unsubscribeEvent: {} is needed by other EventHandler's... dosen't unsubscribe it",
|
||||
unsubscribeEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void restartListener() {
|
||||
internalStop();
|
||||
if (!eventHandlers.isEmpty() && isStarted) {
|
||||
logger.debug("Min one subscribed events was deleted, EventListener will be restarted");
|
||||
internalStart();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a event and subscribed it, if it is not subscribed already.
|
||||
*
|
||||
* @param subscribeEvent event name to subscribe
|
||||
*/
|
||||
public void addSubscribe(String subscribeEvent) {
|
||||
if (!subscribedEvents.contains(subscribeEvent)) {
|
||||
subscribedEvents.add(subscribeEvent);
|
||||
logger.debug("subscibeEvent: {} added", subscribeEvent);
|
||||
if (subscribed) {
|
||||
subscribe(subscribeEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the events of the {@link List} and subscribe them, if a event is not subscribed already.
|
||||
*
|
||||
* @param subscribeEvents event name to subscribe
|
||||
*/
|
||||
public void addSubscribeEvents(List<String> subscribeEvents) {
|
||||
for (String eventName : subscribeEvents) {
|
||||
subscribe(eventName);
|
||||
}
|
||||
}
|
||||
|
||||
private void getSubscriptionID() {
|
||||
boolean subscriptionIDavailable = false;
|
||||
while (!subscriptionIDavailable) {
|
||||
String response = connManager.getDigitalSTROMAPI().getEvent(connManager.getSessionToken(), subscriptionID,
|
||||
timeout);
|
||||
|
||||
JsonObject responseObj = JSONResponseHandler.toJsonObject(response);
|
||||
|
||||
if (JSONResponseHandler.checkResponse(responseObj)) {
|
||||
subscriptionID++;
|
||||
} else {
|
||||
String errorStr = null;
|
||||
if (responseObj != null && responseObj.get(JSONApiResponseKeysEnum.MESSAGE.getKey()) != null) {
|
||||
errorStr = responseObj.get(JSONApiResponseKeysEnum.MESSAGE.getKey()).getAsString();
|
||||
}
|
||||
if (errorStr != null && errorStr.contains(TOKEN_NOT_FOUND)) {
|
||||
subscriptionIDavailable = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean subscribe(String eventName) {
|
||||
if (!subscribed) {
|
||||
getSubscriptionID();
|
||||
}
|
||||
subscribed = connManager.getDigitalSTROMAPI().subscribeEvent(connManager.getSessionToken(), eventName,
|
||||
subscriptionID, config.getConnectionTimeout(), config.getReadTimeout());
|
||||
|
||||
if (subscribed) {
|
||||
logger.debug("subscribed event: {} to subscriptionID: {}", eventName, subscriptionID);
|
||||
} else {
|
||||
logger.error(
|
||||
"Couldn't subscribe event {} ... maybe timeout because system is too busy ... event will be tried to subscribe later again ... ",
|
||||
eventName);
|
||||
}
|
||||
return subscribed;
|
||||
}
|
||||
|
||||
private void subscribe(final List<String> evetNames) {
|
||||
final Iterator<String> eventNameIter = evetNames.iterator();
|
||||
subscriptionScheduler = scheduler.scheduleWithFixedDelay(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (eventNameIter.hasNext()) {
|
||||
subscribe(eventNameIter.next());
|
||||
}
|
||||
subscriptionScheduler.cancel(true);
|
||||
}
|
||||
}, 0, SUBSCRIBE_DELAY, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
private final Runnable runableListener = new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (subscribed) {
|
||||
String response = connManager.getDigitalSTROMAPI().getEvent(connManager.getSessionToken(),
|
||||
subscriptionID, timeout);
|
||||
JsonObject responseObj = JSONResponseHandler.toJsonObject(response);
|
||||
|
||||
if (JSONResponseHandler.checkResponse(responseObj)) {
|
||||
JsonObject obj = JSONResponseHandler.getResultJsonObject(responseObj);
|
||||
if (obj != null && obj.get(JSONApiResponseKeysEnum.EVENTS.getKey()).isJsonArray()) {
|
||||
JsonArray array = obj.get(JSONApiResponseKeysEnum.EVENTS.getKey()).getAsJsonArray();
|
||||
handleEvent(array);
|
||||
}
|
||||
} else {
|
||||
String errorStr = null;
|
||||
if (responseObj != null && responseObj.get(JSONApiResponseKeysEnum.MESSAGE.getKey()) != null) {
|
||||
errorStr = responseObj.get(JSONApiResponseKeysEnum.MESSAGE.getKey()).getAsString();
|
||||
}
|
||||
if (errorStr != null && (errorStr.equals(INVALID_SESSION) || errorStr.contains(TOKEN_NOT_FOUND))) {
|
||||
unsubscribe();
|
||||
subscribe(subscribedEvents);
|
||||
} else if (errorStr != null) {
|
||||
pollingScheduler.cancel(true);
|
||||
logger.error("Unknown error message at event response: {}", errorStr);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
subscribe(subscribedEvents);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void unsubscribe() {
|
||||
for (String eventName : this.subscribedEvents) {
|
||||
connManager.getDigitalSTROMAPI().unsubscribeEvent(this.connManager.getSessionToken(), eventName,
|
||||
this.subscriptionID, config.getConnectionTimeout(), config.getReadTimeout());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleEvent(JsonArray array) {
|
||||
if (array.size() > 0) {
|
||||
Event event = new JSONEventImpl(array);
|
||||
for (EventItem item : event.getEventItems()) {
|
||||
logger.debug("detect event {}", item.toString());
|
||||
for (EventHandler handler : eventHandlers) {
|
||||
if (handler.supportsEvent(item.getName())) {
|
||||
logger.debug("inform handler with id {} about event {}", handler.getUID(), item.toString());
|
||||
handler.handleEvent(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.event.constants;
|
||||
|
||||
/**
|
||||
* The {@link EventNames} contains all needed event names to subscribe at the digitalSTROM server.
|
||||
*
|
||||
* @author Michael Ochel
|
||||
* @author Matthias Siegele
|
||||
*/
|
||||
public class EventNames {
|
||||
|
||||
public static final String ZONE_SENSOR_VALUE = "zoneSensorValue";
|
||||
public static final String HEATING_CONTROL_OPERATION_MODE = "heating-controller.operation-mode";
|
||||
public static final String STATE_CHANGED = "stateChange";
|
||||
public static final String CALL_SCENE = "callScene";
|
||||
public static final String UNDO_SCENE = "undoScene";
|
||||
public static final String DEVICE_SENSOR_VALUE = "deviceSensorValue";
|
||||
public static final String DEVICE_BINARY_INPUT_EVENT = "deviceBinaryInputEvent";
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.event.constants;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The {@link EventResponseEnum} contains digitalSTROM-Event properties of the events at {@link EventNames}.
|
||||
*
|
||||
* @author Michael Ochel
|
||||
* @author Mathias Siegele
|
||||
*/
|
||||
public enum EventResponseEnum {
|
||||
|
||||
// general
|
||||
NAME("Name"),
|
||||
PROPERTIES("properties"),
|
||||
SOURCE("source"),
|
||||
SET("set"),
|
||||
DSID("dsid"),
|
||||
ZONEID("zoneID"),
|
||||
GROUPID("groupID"),
|
||||
IS_APARTMENT("isApartment"),
|
||||
IS_GROUP("isGroup"),
|
||||
IS_DEVICE("isDevice"),
|
||||
IS_SERVICE("isService"),
|
||||
|
||||
// scene event
|
||||
FORCED("forced"),
|
||||
ORIGEN_TOKEN("originToken"),
|
||||
CALL_ORIGEN("callOrigin"),
|
||||
ORIGEN_DSUID("originDSUID"),
|
||||
SCENEID("sceneID"),
|
||||
ORIGIN_DEVICEID("originDeviceID"),
|
||||
|
||||
// device/zone sensor value
|
||||
SENSOR_VALUE_FLOAT("sensorValueFloat"),
|
||||
SENSOR_TYPE("sensorType"),
|
||||
SENSOR_VALUE("sensorValue"),
|
||||
SENSOR_INDEX("sensorIndex"),
|
||||
|
||||
// state changed
|
||||
OLD_VALUE("oldvalue"),
|
||||
STATE_NAME("statename"),
|
||||
STATE("state"),
|
||||
VALUE("value"),
|
||||
|
||||
// operation mode
|
||||
ACTIONS("actions"),
|
||||
OPERATION_MODE("operationMode"),
|
||||
FORCED_UPDATE("forceUpdate"),
|
||||
|
||||
// binary input
|
||||
INPUT_TYPE("inputType"),
|
||||
INPUT_STATE("inputState"),
|
||||
INPUT_INDEX("inputIndex");
|
||||
|
||||
private final String id;
|
||||
static final Map<String, EventResponseEnum> EVENT_RESPONSE_FIELDS = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (EventResponseEnum ev : EventResponseEnum.values()) {
|
||||
EVENT_RESPONSE_FIELDS.put(ev.getId(), ev);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, if the given property exists at the ESH event properties, otherwise false.
|
||||
*
|
||||
* @param property to check
|
||||
* @return contains property (true = yes | false = no)
|
||||
*/
|
||||
public static boolean containsId(String property) {
|
||||
return EVENT_RESPONSE_FIELDS.keySet().contains(property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link EventResponseEnum} to the given property.
|
||||
*
|
||||
* @param property to get
|
||||
* @return EventPropertyEnum
|
||||
*/
|
||||
public static EventResponseEnum getProperty(String property) {
|
||||
return EVENT_RESPONSE_FIELDS.get(property);
|
||||
}
|
||||
|
||||
private EventResponseEnum(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the id of this {@link EventResponseEnum}.
|
||||
*
|
||||
* @return id of this {@link EventResponseEnum}
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.event.types;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The {@link Event} represents a digitalSTROM-Event.
|
||||
*
|
||||
* @author Alexander Betker
|
||||
*/
|
||||
public interface Event {
|
||||
|
||||
/**
|
||||
* Returns a list of the {@link EventItem}s of this Event.
|
||||
*
|
||||
* @return List of {@link EventItem}s
|
||||
*/
|
||||
List<EventItem> getEventItems();
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.event.types;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.event.constants.EventResponseEnum;
|
||||
|
||||
/**
|
||||
* The {@link EventItem} represents a event item of an digitalSTROM-Event.
|
||||
*
|
||||
* @author Alexander Betker
|
||||
* @author Michael Ochel - add getSource()
|
||||
* @author Matthias Siegele - add getSource()
|
||||
*/
|
||||
public interface EventItem {
|
||||
|
||||
/**
|
||||
* Returns the name of this {@link EventItem}.
|
||||
*
|
||||
* @return name of this {@link EventItem}
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Returns {@link HashMap} with the properties fiels of this {@link EventItem}.
|
||||
* The key is a {@link EventResponseEnum} and represents the property name
|
||||
* and the value is the property value.
|
||||
*
|
||||
* @return the properties of this {@link EventItem}
|
||||
*/
|
||||
Map<EventResponseEnum, String> getProperties();
|
||||
|
||||
/**
|
||||
* Returns {@link HashMap} with the source fields of this {@link EventItem}.
|
||||
* The key is a {@link EventResponseEnum} and represents the property name
|
||||
* and the value is the property value.
|
||||
*
|
||||
* @return the properties of this {@link EventItem}
|
||||
*/
|
||||
Map<EventResponseEnum, String> getSource();
|
||||
}
|
||||
@@ -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.digitalstrom.internal.lib.event.types;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.event.constants.EventResponseEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.constants.JSONApiResponseKeysEnum;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link EventItemImpl} is the implementation of the {@link EventItem}.
|
||||
*
|
||||
* @author Michael Ochel
|
||||
* @author Mathias Siegele
|
||||
*/
|
||||
public class EventItemImpl implements EventItem {
|
||||
|
||||
private final String name;
|
||||
private Map<EventResponseEnum, String> properties;
|
||||
private Map<EventResponseEnum, String> source;
|
||||
|
||||
/**
|
||||
* Creates a new {@link EventItemImpl} from the given digitalSTROM-Event-Item {@link JsonObject}.
|
||||
*
|
||||
* @param jsonEventItem must not be null
|
||||
*/
|
||||
public EventItemImpl(JsonObject jsonEventItem) {
|
||||
name = jsonEventItem.get(JSONApiResponseKeysEnum.NAME.getKey()).getAsString();
|
||||
|
||||
if (jsonEventItem.get(JSONApiResponseKeysEnum.PROPERTIES.getKey()).isJsonObject()) {
|
||||
Set<Entry<String, JsonElement>> propObjEntrySet = jsonEventItem
|
||||
.get(JSONApiResponseKeysEnum.PROPERTIES.getKey()).getAsJsonObject().entrySet();
|
||||
properties = new HashMap<>(propObjEntrySet.size());
|
||||
for (Entry<String, JsonElement> entry : propObjEntrySet) {
|
||||
if (EventResponseEnum.containsId(entry.getKey())) {
|
||||
addProperty(EventResponseEnum.getProperty(entry.getKey()), entry.getValue().getAsString());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (jsonEventItem.get(JSONApiResponseKeysEnum.SOURCE.getKey()).isJsonObject()) {
|
||||
Set<Entry<String, JsonElement>> sourceObjEntrySet = jsonEventItem
|
||||
.get(JSONApiResponseKeysEnum.SOURCE.getKey()).getAsJsonObject().entrySet();
|
||||
source = new HashMap<>(sourceObjEntrySet.size());
|
||||
for (Entry<String, JsonElement> entry : sourceObjEntrySet) {
|
||||
if (EventResponseEnum.containsId(entry.getKey())) {
|
||||
addSource(EventResponseEnum.getProperty(entry.getKey()), entry.getValue().getAsString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addProperty(EventResponseEnum propertieKey, String value) {
|
||||
properties.put(propertieKey, value);
|
||||
}
|
||||
|
||||
private void addSource(EventResponseEnum sourceKey, String value) {
|
||||
source.put(sourceKey, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<EventResponseEnum, String> getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<EventResponseEnum, String> getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EventItemImpl [name=" + name + ", properties=" + properties + ", source=" + source + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.event.types;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link JSONEventImpl} is the implementation of the {@link Event}.
|
||||
*
|
||||
* @author Alexander Betker
|
||||
*/
|
||||
public class JSONEventImpl implements Event {
|
||||
|
||||
private List<EventItem> eventItemList;
|
||||
|
||||
/**
|
||||
* Creates a new {@link JSONEventImpl} from the given digitalSTROM-Event {@link JsonArray}.
|
||||
*
|
||||
* @param jsonEventArray must not be null
|
||||
*/
|
||||
public JSONEventImpl(JsonArray jsonEventArray) {
|
||||
this.eventItemList = new LinkedList<>();
|
||||
for (int i = 0; i < jsonEventArray.size(); i++) {
|
||||
if (jsonEventArray.get(i) instanceof JsonObject) {
|
||||
this.eventItemList.add(new EventItemImpl((JsonObject) jsonEventArray.get(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EventItem> getEventItems() {
|
||||
return eventItemList;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.listener;
|
||||
|
||||
/**
|
||||
* The {@link ConnectionListener} is notified if the connection state of digitalSTROM-Server has changed.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*
|
||||
*/
|
||||
public interface ConnectionListener {
|
||||
|
||||
/* Connection-States */
|
||||
/**
|
||||
* State, if you're not authenticated on the digitalSTROM-Server.
|
||||
*/
|
||||
final String NOT_AUTHENTICATED = "notAuth";
|
||||
/**
|
||||
* State, if the connection to the digitalSTROM-Server is lost.
|
||||
*/
|
||||
final String CONNECTION_LOST = "connLost";
|
||||
/**
|
||||
* State, if a ssl handshake problem occured while communicating with the digitalSTROM-Server.
|
||||
*/
|
||||
final String SSL_HANDSHAKE_ERROR = "sslHandshakeError";
|
||||
/**
|
||||
* State, if the connection to the digitalSTROM-Server is resumed.
|
||||
*/
|
||||
final String CONNECTION_RESUMED = "connResumed";
|
||||
/**
|
||||
* State, if the Application-Token is generated.
|
||||
*/
|
||||
final String APPLICATION_TOKEN_GENERATED = "appGen";
|
||||
|
||||
/* Not authentication reasons */
|
||||
/**
|
||||
* State, if the given Application-Token cannot be used.
|
||||
*/
|
||||
final String WRONG_APP_TOKEN = "wrongAppT";
|
||||
/**
|
||||
* State, if the given username or password cannot be used.
|
||||
*/
|
||||
final String WRONG_USER_OR_PASSWORD = "wrongUserOrPasswd";
|
||||
/**
|
||||
* State, if no username or password is set and the given application-token cannot be used or is null.
|
||||
*/
|
||||
final String NO_USER_PASSWORD = "noUserPasswd";
|
||||
|
||||
/**
|
||||
* State, if the connection timed out.
|
||||
*/
|
||||
final String CONNECTON_TIMEOUT = "connTimeout";
|
||||
|
||||
/**
|
||||
* State, if the host address cannot be found.
|
||||
*/
|
||||
final String HOST_NOT_FOUND = "hostNotFound";
|
||||
|
||||
/**
|
||||
* State, if the host address is unknown.
|
||||
*/
|
||||
final String UNKNOWN_HOST = "unknownHost";
|
||||
|
||||
/**
|
||||
* State, if the the URL is invalid.
|
||||
*/
|
||||
final String INVALID_URL = "invalideURL";
|
||||
|
||||
/**
|
||||
* This method is called whenever the connection state has changed from {@link #CONNECTION_LOST}
|
||||
* to {@link #CONNECTION_RESUMED} and vice versa. It also will be called if the application-token is generated over
|
||||
* {@link #APPLICATION_TOKEN_GENERATED}.
|
||||
*
|
||||
* @param newConnectionState of the connection
|
||||
*/
|
||||
void onConnectionStateChange(String newConnectionState);
|
||||
|
||||
/**
|
||||
* This method is called whenever the connection state has changed to {@link #NOT_AUTHENTICATED} or
|
||||
* {@link #CONNECTION_LOST}
|
||||
* and also passes the reason why. Reason can be:
|
||||
* <ul>
|
||||
* <li>{@link #WRONG_APP_TOKEN} if the given application-token can't be used.</li>
|
||||
* <li>{@link #WRONG_USER_OR_PASSWORD} if the given user name or password can't be used.</li>
|
||||
* <li>{@link #NO_USER_PASSWORD} if no user name or password is set and the given application-token can't be used.
|
||||
* <li>{@link #HOST_NOT_FOUND} if the host can't be found.
|
||||
* <li>{@link #INVALID_URL} if the the URL is invalid.
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* @param newConnectionState of the connection
|
||||
* @param reason why the connection is failed
|
||||
*/
|
||||
void onConnectionStateChange(String newConnectionState, String reason);
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.listener;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.GeneralDeviceInformation;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.DeviceStateUpdate;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.ChangeableDeviceConfigEnum;
|
||||
|
||||
/**
|
||||
* The {@link DeviceStatusListener} is notified, if a {@link Device} status or configuration has changed, if a scene
|
||||
* configuration is added to a {@link Device} or if a device has been added or removed. The {@link DeviceStatusListener}
|
||||
* can be also registered by a {@link Circuit} to get informed by configuration or status changes.
|
||||
* <p>
|
||||
* By implementation with the id {@link #DEVICE_DISCOVERY} this listener can be used as a device discovery to get
|
||||
* informed, if a new {@link Device} or {@link Circuit} is added or removed from the digitalSTROM-System.<br>
|
||||
* For that the {@link DeviceStatusListener} has to be registered on the
|
||||
* {@link DeviceStatusManager#registerDeviceListener(DeviceStatusListener)}. Then the {@link DeviceStatusListener} gets
|
||||
* informed by the methods {@link #onDeviceAdded(Object)} and {@link #onDeviceRemoved(Object)}.
|
||||
* </p>
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*
|
||||
*/
|
||||
public interface DeviceStatusListener {
|
||||
|
||||
/**
|
||||
* ID of the device discovery listener.
|
||||
*/
|
||||
static final String DEVICE_DISCOVERY = "DeviceDiscovery";
|
||||
|
||||
/**
|
||||
* This method is called whenever the state of the {@link Device} has changed and passes the new device state as an
|
||||
* {@link DeviceStateUpdate} object.
|
||||
*
|
||||
* @param deviceStateUpdate new device status
|
||||
*/
|
||||
void onDeviceStateChanged(DeviceStateUpdate deviceStateUpdate);
|
||||
|
||||
/**
|
||||
* This method is called whenever a device is removed.
|
||||
*
|
||||
* @param device which is removed
|
||||
*/
|
||||
void onDeviceRemoved(GeneralDeviceInformation device);
|
||||
|
||||
/**
|
||||
* This method is called whenever a device is added.
|
||||
*
|
||||
* @param device which is added
|
||||
*/
|
||||
void onDeviceAdded(GeneralDeviceInformation device);
|
||||
|
||||
/**
|
||||
* This method is called whenever a configuration of an device has changed. What configuration has changed
|
||||
* can be see by the given parameter whatConfig to handle the change.<br>
|
||||
* Please have a look at {@link ChangeableDeviceConfigEnum} to see what configuration are changeable.
|
||||
*
|
||||
* @param whatConfig has changed
|
||||
*/
|
||||
void onDeviceConfigChanged(ChangeableDeviceConfigEnum whatConfig);
|
||||
|
||||
/**
|
||||
* This method is called whenever a scene configuration is added to a device.
|
||||
*
|
||||
* @param sceneID of a read scene configuration
|
||||
*/
|
||||
void onSceneConfigAdded(short sceneID);
|
||||
|
||||
/**
|
||||
* Returns the id of this {@link DeviceStatusListener}.
|
||||
*
|
||||
* @return the device listener id
|
||||
*/
|
||||
String getDeviceStatusListenerID();
|
||||
}
|
||||
@@ -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.digitalstrom.internal.lib.listener;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.stateenums.ManagerStates;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.stateenums.ManagerTypes;
|
||||
|
||||
/**
|
||||
* The {@link ManagerStatusListener} is notified, if the state of digitalSTROM-Manager has changed.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public interface ManagerStatusListener {
|
||||
|
||||
/**
|
||||
* This method is called whenever the state of an digitalSTROM-Manager has changed.<br>
|
||||
* For that it passes the {@link ManagerTypes} and the new {@link ManagerStates}.
|
||||
*
|
||||
* @param managerType of the digitalSTROM-Manager
|
||||
* @param newState of the digitalSTROM-Manager
|
||||
*/
|
||||
void onStatusChanged(ManagerTypes managerType, ManagerStates newState);
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.listener;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.scene.InternalScene;
|
||||
|
||||
/**
|
||||
* The {@link SceneStatusListener} is notified, if a {@link InternalScene} status has changed or a
|
||||
* {@link InternalScene} has been removed or added.
|
||||
*
|
||||
* <p>
|
||||
* By implementation with the id {@link #SCENE_DISCOVERY} this listener can be used as a scene discovery to get
|
||||
* informed, if a new {@link InternalScene}s is added or removed from the digitalSTROM-System.<br>
|
||||
* For that the {@link SceneStatusListener} has to be registered on the
|
||||
* {@link SceneManager#registerSceneListener(SceneStatusListener)}. Then the {@link SceneStatusListener} gets
|
||||
* informed by the methods {@link #onSceneAdded(InternalScene)} and {@link #onSceneRemoved(InternalScene)}.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public interface SceneStatusListener {
|
||||
|
||||
/**
|
||||
* The {@link SceneStatusListener} id for the discovery implementation.
|
||||
*/
|
||||
static final String SCENE_DISCOVERY = "SceneDiscovery";
|
||||
|
||||
/**
|
||||
* This method is called whenever the state of the {@link InternalScene} has changed.
|
||||
*
|
||||
* @param newState (true = call | false = undo)
|
||||
*/
|
||||
void onSceneStateChanged(boolean newState);
|
||||
|
||||
/**
|
||||
* This method is called whenever a {@link InternalScene} is removed.
|
||||
*
|
||||
* @param scene that was removed
|
||||
*/
|
||||
void onSceneRemoved(InternalScene scene);
|
||||
|
||||
/**
|
||||
* This method is called whenever a {@link InternalScene} is added.
|
||||
*
|
||||
* @param scene that was added
|
||||
*/
|
||||
void onSceneAdded(InternalScene scene);
|
||||
|
||||
/**
|
||||
* Return the id of this {@link SceneStatusListener}.
|
||||
*
|
||||
* @return the scene listener id
|
||||
*/
|
||||
String getSceneStatusListenerID();
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.listener;
|
||||
|
||||
/**
|
||||
* The {@link SystemStateChangeListener} can be implemented to get informed by digitalSTROM system state changes. It
|
||||
* has to be registered by supported classes, e.g. the {@link TemperatureControlManager} or self implemented classes.
|
||||
*
|
||||
* @author Michael Ochel
|
||||
* @author Matthias Siegele
|
||||
*/
|
||||
public interface SystemStateChangeListener {
|
||||
|
||||
/**
|
||||
* Will be called, if a digitalSTROM system state has changed.
|
||||
*
|
||||
* @param stateType of the digitalSTROM system state
|
||||
* @param newState of the digitalSTROM system state
|
||||
*/
|
||||
void onSystemStateChanged(String stateType, String newState);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.listener;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.climate.TemperatureControlSensorTransmitter;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.climate.jsonresponsecontainer.impl.TemperatureControlStatus;
|
||||
|
||||
/**
|
||||
* The {@link TemperatureControlStatusListener} can be implemented to get informed by configuration and status changes.
|
||||
* <br>
|
||||
* It also can be implemented as discovery, than the id have to be {@link #DISCOVERY}.
|
||||
*
|
||||
* @author Michael Ochel
|
||||
* @author Matthias Siegele
|
||||
*
|
||||
*/
|
||||
public interface TemperatureControlStatusListener {
|
||||
|
||||
/**
|
||||
* The id for discovery.
|
||||
*/
|
||||
static Integer DISCOVERY = -2;
|
||||
|
||||
/**
|
||||
* Will be called, if the configuration of the {@link TemperatureControlStatus} has changed.
|
||||
*
|
||||
* @param tempControlStatus that has changed
|
||||
*/
|
||||
void configChanged(TemperatureControlStatus tempControlStatus);
|
||||
|
||||
/**
|
||||
* Will be called, if the target temperature has changed.
|
||||
*
|
||||
* @param newValue of the target temperature
|
||||
*/
|
||||
void onTargetTemperatureChanged(Float newValue);
|
||||
|
||||
/**
|
||||
* Will be called, if the control value has changed.
|
||||
*
|
||||
* @param newValue of the control value
|
||||
*/
|
||||
void onControlValueChanged(Integer newValue);
|
||||
|
||||
/**
|
||||
* Registers a {@link TemperatureControlSensorTransmitter}.
|
||||
*
|
||||
* @param temperatureSensorTransmitter to register
|
||||
*/
|
||||
void registerTemperatureSensorTransmitter(TemperatureControlSensorTransmitter temperatureSensorTransmitter);
|
||||
|
||||
/**
|
||||
* Returns the id of this {@link TemperatureControlStatusListener}.
|
||||
*
|
||||
* @return id
|
||||
*/
|
||||
Integer getTemperationControlStatusListenrID();
|
||||
}
|
||||
@@ -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.digitalstrom.internal.lib.listener;
|
||||
|
||||
/**
|
||||
* The {@link TotalPowerConsumptionListener} is notified, if the total power consumption or the total electric meter
|
||||
* value has changed.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*
|
||||
*/
|
||||
public interface TotalPowerConsumptionListener {
|
||||
|
||||
/**
|
||||
* This method is called whenever the total power consumption of the digitalSTROM-System has changed.
|
||||
*
|
||||
* @param newPowerConsumption of the digitalSTROM-System
|
||||
*/
|
||||
void onTotalPowerConsumptionChanged(int newPowerConsumption);
|
||||
|
||||
/**
|
||||
* This method is called whenever the total energy meter value in Wh of the digitalSTROM-System has changed.
|
||||
*
|
||||
* @param newEnergyMeterValue of the digitalSTROM-System
|
||||
*/
|
||||
void onEnergyMeterValueChanged(int newEnergyMeterValue);
|
||||
|
||||
/**
|
||||
* This method is called whenever the total energy meter value in Ws of the digitalSTROM-System has changed.
|
||||
*
|
||||
* @param newEnergyMeterValue of the digitalSTROM-System
|
||||
*/
|
||||
void onEnergyMeterWsValueChanged(int newEnergyMeterValue);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.listener.stateenums;
|
||||
|
||||
/**
|
||||
* The {@link ManagerStates} contains all reachable states of the digitalSTROM-Manager in {@link ManagerTypes}
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public enum ManagerStates {
|
||||
RUNNING,
|
||||
STOPPED,
|
||||
INITIALIZING,
|
||||
GENERATING_SCENES
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.listener.stateenums;
|
||||
|
||||
/**
|
||||
* The {@link ManagerTypes} contains all reachable digitalSTROM-Managers, which have states.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*
|
||||
*/
|
||||
public enum ManagerTypes {
|
||||
DEVICE_STATUS_MANAGER,
|
||||
SCENE_MANAGER,
|
||||
CONNECTION_MANAGER
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.manager;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.config.Config;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.ConnectionListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.DsAPI;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.HttpTransport;
|
||||
|
||||
/**
|
||||
* The {@link ConnectionManager} manages the connection to a digitalSTROM-Server.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public interface ConnectionManager {
|
||||
|
||||
public static final int GENERAL_EXCEPTION = -1;
|
||||
public static final int MALFORMED_URL_EXCEPTION = -2;
|
||||
public static final int CONNECTION_EXCEPTION = -3;
|
||||
public static final int SOCKET_TIMEOUT_EXCEPTION = -4;
|
||||
public static final int UNKNOWN_HOST_EXCEPTION = -5;
|
||||
public static final int AUTHENTIFICATION_PROBLEM = -6;
|
||||
public static final int SSL_HANDSHAKE_EXCEPTION = -7;
|
||||
|
||||
/**
|
||||
* Returns the {@link HttpTransport} to execute queries or special commands on the digitalSTROM-Server.
|
||||
*
|
||||
* @return the HttpTransport
|
||||
*/
|
||||
HttpTransport getHttpTransport();
|
||||
|
||||
/**
|
||||
* Returns the {@link DsAPI} to execute commands on the digitalSTROM-Server.
|
||||
*
|
||||
* @return the DsAPI
|
||||
*/
|
||||
DsAPI getDigitalSTROMAPI();
|
||||
|
||||
/**
|
||||
* This method has to be called before each command to check the connection to the digitalSTROM-Server.
|
||||
* It examines the connection to the server, sets a new Session-Token, if it is expired and sets a new
|
||||
* Application-Token, if none it set at the digitalSTROM-Server. It also outputs the specific connection failure.
|
||||
*
|
||||
* @return true if the connection is established and false if not
|
||||
*/
|
||||
boolean checkConnection();
|
||||
|
||||
/**
|
||||
* Returns the current Session-Token.
|
||||
*
|
||||
* @return Session-Token
|
||||
*/
|
||||
String getSessionToken();
|
||||
|
||||
/**
|
||||
* Returns the auto-generated or user defined Application-Token.
|
||||
*
|
||||
* @return Application-Token
|
||||
*/
|
||||
String getApplicationToken();
|
||||
|
||||
/**
|
||||
* Registers a {@link ConnectionListener} to this {@link ConnectionManager}.
|
||||
*
|
||||
* @param connectionListener to register
|
||||
*/
|
||||
void registerConnectionListener(ConnectionListener connectionListener);
|
||||
|
||||
/**
|
||||
* Unregisters the {@link ConnectionListener} from this {@link ConnectionManager}.
|
||||
*/
|
||||
void unregisterConnectionListener();
|
||||
|
||||
/**
|
||||
* Revokes the saved Application-Token from the digitalSTROM-Server and returns true if the Application-Token was
|
||||
* revoke successful, otherwise false.
|
||||
*
|
||||
* @return successful = true, otherwise false
|
||||
*/
|
||||
boolean removeApplicationToken();
|
||||
|
||||
/**
|
||||
* Updates the login configuration.
|
||||
*
|
||||
* @param hostAddress of the digitalSTROM-Server
|
||||
* @param username to login
|
||||
* @param password to login
|
||||
* @param applicationToken to login
|
||||
*/
|
||||
void updateConfig(String hostAddress, String username, String password, String applicationToken);
|
||||
|
||||
/**
|
||||
* Updates the {@link Config} with the given config.
|
||||
*
|
||||
* @param config to update
|
||||
*/
|
||||
void updateConfig(Config config);
|
||||
|
||||
/**
|
||||
* Returns the {@link Config}.
|
||||
*
|
||||
* @return the config
|
||||
*/
|
||||
Config getConfig();
|
||||
|
||||
/**
|
||||
* Informs this {@link ConnectionManager} that the {@link Config} has been updated.
|
||||
*/
|
||||
void configHasBeenUpdated();
|
||||
|
||||
/**
|
||||
* Generates and returns a new session token.
|
||||
*
|
||||
* @return new session token
|
||||
*/
|
||||
String getNewSessionToken();
|
||||
|
||||
/**
|
||||
* Checks the connection through the given HTTP-Response-Code or exception code. If a {@link ConnectionListener} is
|
||||
* registered this method also informs the registered {@link ConnectionListener} if the connection state has
|
||||
* changed. <br>
|
||||
* <br>
|
||||
* <b>Exception-Codes:</b><br>
|
||||
* <b>{@link #GENERAL_EXCEPTION}</b> general exception<br>
|
||||
* <b>{@link #MALFORMED_URL_EXCEPTION}</b> MalformedURLException<br>
|
||||
* <b>{@link #CONNECTION_EXCEPTION}</b> java.net.ConnectException<br>
|
||||
* <b>{@link #SOCKET_TIMEOUT_EXCEPTION}</b> SocketTimeoutException<br>
|
||||
* <b>{@link #UNKNOWN_HOST_EXCEPTION}</b> java.net.UnknownHostException<br>
|
||||
* <br>
|
||||
* <b>Code for authentication problems:</b> {@link #AUTHENTIFICATION_PROBLEM}<br>
|
||||
*
|
||||
*
|
||||
* @param code exception or HTTP-Response-Code
|
||||
* @return true, if connection is valid
|
||||
*/
|
||||
boolean checkConnection(int code);
|
||||
|
||||
/**
|
||||
* Returns true, if connection is established, otherwise false.
|
||||
*
|
||||
* @return true, if connection is established, otherwise false
|
||||
*/
|
||||
boolean connectionEstablished();
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.manager;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.event.EventHandler;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.ConnectionListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.DeviceStatusListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.ManagerStatusListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.SceneStatusListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.TotalPowerConsumptionListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.stateenums.ManagerStates;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.stateenums.ManagerTypes;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.sensorjobexecutor.sensorjob.SensorJob;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.Device;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.DeviceStateUpdate;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.scene.InternalScene;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* The {@link DeviceStatusManager} is responsible for the synchronization between the internal model of the
|
||||
* digitalSTROM-devices and the real existing digitalSTROM-devices. You can change the state of an device by sending a
|
||||
* direct command to the devices or by calling a scene. Furthermore the {@link DeviceStatusManager} get informed over
|
||||
* the {@link SceneManager} by the {@link EventListener} if scenes are called by external sources. All
|
||||
* configurations of the physically device will be synchronized to the internally managed model and updated as required.
|
||||
* The {@link DeviceStatusManager} also initializes {@link SensorJob}'s with the {@link SensorJobExecutor} and
|
||||
* {@link SceneReadingJobExecutor} to update required sensor and scene data.
|
||||
*
|
||||
* <p>
|
||||
* Therefore the {@link DeviceStatusManager} uses the {@link StructureManager} for the internal management of the
|
||||
* structure of the digitalSTROM-system, {@link ConnectionManager} to check the connectivity,
|
||||
* {@link SceneManager} to identify externally called scenes and to update the affected devices of these
|
||||
* called scenes to the internal model. The most methods of the above-named managers will be directly called over the
|
||||
* {@link DeviceStatusManager}, because they are linked to the affected managers.
|
||||
*
|
||||
* <p>
|
||||
* To get informed by all relevant information you can register some useful listeners. Here the list of all listeners
|
||||
* which can registered or unregistered:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>{@link DeviceStatusListener} over {@link #registerDeviceListener(DeviceStatusListener)} respectively
|
||||
* {@link #unregisterDeviceListener(DeviceStatusListener)}</li>
|
||||
* <li>{@link SceneStatusListener} over {@link #registerSceneListener(SceneStatusListener)} respectively
|
||||
* {@link #unregisterSceneListener(SceneStatusListener)}</li>
|
||||
* <li>{@link TotalPowerConsumptionListener} over
|
||||
* {@link #registerTotalPowerConsumptionListener(TotalPowerConsumptionListener)} respectively
|
||||
* {@link #unregisterTotalPowerConsumptionListener()}</li>
|
||||
* <li>{@link ManagerStatusListener} over {@link #registerStatusListener(ManagerStatusListener)}
|
||||
* respectively {@link #unregisterStatusListener()}</li>
|
||||
* <li>{@link ConnectionListener} over {@link #registerDeviceListener(DeviceStatusListener)} respectively
|
||||
* {@link #unregisterDeviceListener(DeviceStatusListener)}</li>
|
||||
* </ul>
|
||||
* For what the listener can be used please have a look at the listener.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public interface DeviceStatusManager extends EventHandler {
|
||||
|
||||
/**
|
||||
* Starts the working process for device synchronization. It also starts the {@link SensorJobExecutor} and the
|
||||
* {@link SceneReadingJobExecutor} and the {@link SceneManager}.
|
||||
*/
|
||||
void start();
|
||||
|
||||
/**
|
||||
* Stops the working process for device synchronization. It also stops the {@link SensorJobExecutor} and the
|
||||
* {@link SceneReadingJobExecutor} and the {@link SceneManager}.
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* This method sends a call scene command for the given {@link InternalScene}, if call_undo is true otherwise it
|
||||
* sends a undo command.
|
||||
* <br>
|
||||
* It also updates the scene state, if the command was send successful.
|
||||
*
|
||||
* @param scene to call
|
||||
* @param call_undo (true = call | false = undo)
|
||||
*/
|
||||
void sendSceneComandsToDSS(InternalScene scene, boolean call_undo);
|
||||
|
||||
/**
|
||||
* This method sends a stop command for the given {@link Device}.
|
||||
* <br>
|
||||
* It also reads out the current output value of the device and updates it, if the command was send successful.
|
||||
*
|
||||
* @param device which will send a stop command
|
||||
*/
|
||||
void sendStopComandsToDSS(Device device);
|
||||
|
||||
/**
|
||||
* This method sends the command for the given {@link DeviceStateUpdate} for the given {@link Device}. Please have a
|
||||
* look at {@link DeviceStateUpdate} to see what types is there and how the value {@link DeviceStateUpdate} will be
|
||||
* evaluated.
|
||||
* <br>
|
||||
* It also updates the device if the command was send successful.
|
||||
*
|
||||
* @param device device which will send a command
|
||||
* @param deviceStateUpdate command to send
|
||||
*/
|
||||
void sendComandsToDSS(Device device, DeviceStateUpdate deviceStateUpdate);
|
||||
|
||||
/**
|
||||
* This method adds a {@link SensorJob} with the appropriate priority to the {@link SensorJob}.
|
||||
*
|
||||
* @param sensorJob to update sensor data
|
||||
* @param priority to update
|
||||
*/
|
||||
void updateSensorData(SensorJob sensorJob, String priority);
|
||||
|
||||
/**
|
||||
* This method adds a {@link SensorJob} with the appropriate priority to the {@link SceneReadingJobExecutor}.
|
||||
*
|
||||
* @param device device which will update scene data
|
||||
* @param deviceStateUpdate scene data to update
|
||||
*/
|
||||
void updateSceneData(Device device, DeviceStateUpdate deviceStateUpdate);
|
||||
|
||||
/**
|
||||
* Registers the given {@link DeviceStatusListener} to the {@link Device}, if it exists or registers it as a
|
||||
* device discovery, if the id of the {@link DeviceStatusListener} is {@link DeviceStatusListener#DEVICE_DISCOVERY}.
|
||||
*
|
||||
* @param deviceListener to rigister
|
||||
*/
|
||||
void registerDeviceListener(DeviceStatusListener deviceListener);
|
||||
|
||||
/**
|
||||
* Unregisters the given {@link DeviceStatusListener} from the {@link Device}, if it exists or unregisters the
|
||||
* device discovery, if the id of the {@link DeviceStatusListener} is {@link DeviceStatusListener#DEVICE_DISCOVERY}.
|
||||
*
|
||||
* @param deviceListener to unregister
|
||||
*/
|
||||
void unregisterDeviceListener(DeviceStatusListener deviceListener);
|
||||
|
||||
/**
|
||||
* Registers the given {@link TotalPowerConsumptionListener} to this {@link DeviceStatusManager}.
|
||||
*
|
||||
* @param totalPowerConsumptionListener to register
|
||||
*/
|
||||
void registerTotalPowerConsumptionListener(TotalPowerConsumptionListener totalPowerConsumptionListener);
|
||||
|
||||
/**
|
||||
* Unregisters the {@link TotalPowerConsumptionListener} from this {@link DeviceStatusManager}.
|
||||
*/
|
||||
void unregisterTotalPowerConsumptionListener();
|
||||
|
||||
/**
|
||||
* Registers the given {@link SceneStatusListener} to the {@link InternalScene}, if it exists or registers it as a
|
||||
* scene discovery to the {@link SceneManager}, if the id of the {@link SceneStatusListener} is
|
||||
* {@link SceneStatusListener#SCENE_DISCOVERY}.
|
||||
*
|
||||
* @param sceneListener to register
|
||||
*/
|
||||
void registerSceneListener(SceneStatusListener sceneListener);
|
||||
|
||||
/**
|
||||
* Unregisters the given {@link SceneStatusListener} from the {@link InternalScene} if it exist or unregisters the
|
||||
* scene discovery from the {@link SceneManager}, if the id of the {@link SceneStatusListener} is
|
||||
* {@link SceneStatusListener#SCENE_DISCOVERY}.
|
||||
*
|
||||
* @param sceneListener to unregister
|
||||
*/
|
||||
void unregisterSceneListener(SceneStatusListener sceneListener);
|
||||
|
||||
/**
|
||||
* Registers the given {@link ConnectionListener} to the {@link ConnectionManager}.
|
||||
*
|
||||
* @param connectionListener to register
|
||||
*/
|
||||
void registerConnectionListener(ConnectionListener connectionListener);
|
||||
|
||||
/**
|
||||
* Unregisters the {@link ConnectionListener} from the {@link ConnectionManager}.
|
||||
*/
|
||||
void unregisterConnectionListener();
|
||||
|
||||
/**
|
||||
* Removes the {@link Device} with the given dSID from the internal model, if it exists.
|
||||
*
|
||||
* @param dSID of the {@link Device} which will be removed
|
||||
*/
|
||||
void removeDevice(String dSID);
|
||||
|
||||
/**
|
||||
* Registers the given {@link ManagerStatusListener} to all available managers. What manager are available please
|
||||
* have a look at {@link ManagerTypes}.
|
||||
*
|
||||
* @param statusListener to register
|
||||
*/
|
||||
void registerStatusListener(ManagerStatusListener statusListener);
|
||||
|
||||
/**
|
||||
* Unregisters the {@link ManagerStatusListener} from all available managers. What manager are available please have
|
||||
* a look at {@link ManagerTypes}.
|
||||
*/
|
||||
void unregisterStatusListener();
|
||||
|
||||
/**
|
||||
* Returns the {@link ManagerTypes} of this class.
|
||||
*
|
||||
* @return these {@link ManagerTypes}
|
||||
*/
|
||||
ManagerTypes getManagerType();
|
||||
|
||||
/**
|
||||
* Returns the current {@link ManagerStates}.
|
||||
*
|
||||
* @return current {@link ManagerStates}
|
||||
*/
|
||||
ManagerStates getManagerState();
|
||||
|
||||
/**
|
||||
* Reads the current total power consumption out and returns it.
|
||||
*
|
||||
* @return the current total power consumption
|
||||
*/
|
||||
int getTotalPowerConsumption();
|
||||
|
||||
/**
|
||||
* Reads the current total energy meter value in Wh out and returns it.
|
||||
*
|
||||
* @return the current total energy meter value Wh
|
||||
*/
|
||||
int getTotalEnergyMeterValue();
|
||||
|
||||
/**
|
||||
* Reads the current total energy meter value in Ws out and returns it.
|
||||
*
|
||||
* @return the current total energy meter value in Ws
|
||||
*/
|
||||
int getTotalEnergyMeterWsValue();
|
||||
}
|
||||
@@ -0,0 +1,252 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.manager;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.event.EventHandler;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.ManagerStatusListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.SceneStatusListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.stateenums.ManagerStates;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.stateenums.ManagerTypes;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.Device;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.scene.InternalScene;
|
||||
|
||||
/**
|
||||
* The {@link SceneManager} manages all functions concerning scenes without sending the commands itself.
|
||||
*
|
||||
* <p>
|
||||
* So it manages a list of all {@link InternalScene} they called in the past or was generated by calling
|
||||
* {@link #generateScenes()}.<br>
|
||||
* Through this class you can also register {@link SceneStatusListener}'s to the {@link InternalScene}'s or register a
|
||||
* scene discovery. With {@link #addEcho(String)} or {@link #addEcho(String, short)} scene calls form the library can be
|
||||
* ignored. To update the state of an {@link InternalScene} or {@link Device} the methods
|
||||
* {@link #callInternalScene(InternalScene)}, {@link #callInternalScene(String)},
|
||||
* {@link #callDeviceScene(Device, Short)}
|
||||
* , {@link #callDeviceScene(String, Short)} etc. can be used.
|
||||
*
|
||||
* <p>
|
||||
* If you call the {@link #start()} method a {@link EventListener} will be started to handle scene calls and undos from
|
||||
* the outside.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*
|
||||
*/
|
||||
public interface SceneManager extends EventHandler {
|
||||
|
||||
/**
|
||||
* Activates the given {@link InternalScene}, if it exists. Otherwise it will be added to the scene list and
|
||||
* activated, if it is a callable scene.
|
||||
*
|
||||
* @param scene to call
|
||||
*/
|
||||
void callInternalScene(InternalScene scene);
|
||||
|
||||
/**
|
||||
* Activates a {@link InternalScene} with the given id, if it exists. Otherwise a new
|
||||
* {@link InternalScene} will be created and activated, if it is a callable scene.
|
||||
*
|
||||
* @param sceneID of the scene to call
|
||||
*/
|
||||
void callInternalScene(String sceneID);
|
||||
|
||||
/**
|
||||
* Call the given sceneID on the {@link Device} with the given dSID, if the {@link Device} exists.
|
||||
*
|
||||
* @param dSID of the {@link Device} to call
|
||||
* @param sceneID of the scene to call
|
||||
*/
|
||||
void callDeviceScene(String dSID, Short sceneID);
|
||||
|
||||
/**
|
||||
* Call the given sceneID on the given {@link Device}, if the {@link Device} exists.
|
||||
*
|
||||
* @param device to call
|
||||
* @param sceneID to call
|
||||
*/
|
||||
void callDeviceScene(Device device, Short sceneID);
|
||||
|
||||
/**
|
||||
* Deactivates the given {@link InternalScene}, if it exists. Otherwise it will added to the scene list and
|
||||
* deactivated, if it is a callable scene.
|
||||
*
|
||||
* @param scene to undo
|
||||
*/
|
||||
void undoInternalScene(InternalScene scene);
|
||||
|
||||
/**
|
||||
* Deactivates a {@link InternalScene} with the given sceneID, if it exists. Otherwise a new
|
||||
* {@link InternalScene} will be created and deactivated, if it is a callable scene.
|
||||
*
|
||||
* @param sceneID of the scene to undo
|
||||
*/
|
||||
void undoInternalScene(String sceneID);
|
||||
|
||||
/**
|
||||
* Undo the last scene on the {@link Device} with the given dSID, if the {@link Device} exists.
|
||||
*
|
||||
* @param dSID of the {@link Device} to undo
|
||||
*/
|
||||
void undoDeviceScene(String dSID);
|
||||
|
||||
/**
|
||||
* Undo the last scene on the {@link Device}, if the {@link Device} exists.
|
||||
*
|
||||
* @param device the {@link Device} to undo
|
||||
*/
|
||||
void undoDeviceScene(Device device);
|
||||
|
||||
/**
|
||||
* Registers the given {@link SceneStatusListener} to the {@link InternalScene}, if it exists or registers it as a
|
||||
* Scene-Discovery if the id of the {@link SceneStatusListener} is {@link SceneStatusListener#SCENE_DISCOVERY}.
|
||||
*
|
||||
* @param sceneListener to register
|
||||
*/
|
||||
void registerSceneListener(SceneStatusListener sceneListener);
|
||||
|
||||
/**
|
||||
* Unregisters the given {@link SceneStatusListener} from the {@link InternalScene}, if it exists or unregisters the
|
||||
* Scene-Discovery, if the id of the {@link SceneStatusListener} is {@link SceneStatusListener#SCENE_DISCOVERY}.
|
||||
*
|
||||
* @param sceneListener to register
|
||||
*/
|
||||
void unregisterSceneListener(SceneStatusListener sceneListener);
|
||||
|
||||
/**
|
||||
* Adds the given {@link InternalScene} to the scene list, if it is a callable scene.
|
||||
*
|
||||
* @param intScene to add
|
||||
*/
|
||||
void addInternalScene(InternalScene intScene);
|
||||
|
||||
/**
|
||||
* Adds the scene call with the given dSID and sceneId as an echo to ignore them by detecting the {@link EventItem}.
|
||||
*
|
||||
* @param dSID of the {@link Device} that will be ignored
|
||||
* @param sceneId of the scene that will be ignored
|
||||
*/
|
||||
void addEcho(String dSID, short sceneId);
|
||||
|
||||
/**
|
||||
* Adds the scene call with the given internal scene id as an echo to ignore them by detecting the {@link EventItem}
|
||||
* .
|
||||
*
|
||||
* @param internalSceneID to ignore
|
||||
*/
|
||||
void addEcho(String internalSceneID);
|
||||
|
||||
/**
|
||||
* Returns the list of all {@link InternalScene}.
|
||||
*
|
||||
* @return list of all scenes
|
||||
*/
|
||||
List<InternalScene> getScenes();
|
||||
|
||||
/**
|
||||
* Returns true, if all reachable scenes are already generated, otherwise false.
|
||||
*
|
||||
* @return true = reachable scenes generated, otherwise false
|
||||
*/
|
||||
boolean scenesGenerated();
|
||||
|
||||
/**
|
||||
* Generates all reachable scenes.
|
||||
*
|
||||
*/
|
||||
void generateScenes();
|
||||
|
||||
/**
|
||||
* Will be called from the {@link SceneDiscovery}, if a scene type is generated or is fail.<br>
|
||||
* For that the scenesGenerated char array has four chars. Each char represents one scene type in the following
|
||||
* direction:
|
||||
* <ul>
|
||||
* <li><b>first:</b> named scenes</li>
|
||||
* <li><b>second:</b> apartment scenes</li>
|
||||
* <li><b>third:</b> zone scenes</li>
|
||||
* <li><b>fourth</b>: group scenes, if they can call by push buttons</li>
|
||||
* </ul>
|
||||
* If a scene type is not generated the char is "0". If a scene type is generated the char is "1" and, if it is fail
|
||||
* the char is "2".
|
||||
*
|
||||
* @param scenesGenerated array
|
||||
*/
|
||||
void scenesGenerated(char[] scenesGenerated);
|
||||
|
||||
/**
|
||||
* Returns true, if a discovery is registered, otherwise false.
|
||||
*
|
||||
* @return true discovery is registered, otherwise false
|
||||
*/
|
||||
boolean isDiscoveryRegistrated();
|
||||
|
||||
/**
|
||||
* Starts the {@link EventListener}.
|
||||
*/
|
||||
void start();
|
||||
|
||||
/**
|
||||
* Stops the {@link EventListener}.
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* Removes the {@link InternalScene} with the given sceneID.
|
||||
*
|
||||
* @param sceneID of the {@link InternalScene} to remove
|
||||
*/
|
||||
void removeInternalScene(String sceneID);
|
||||
|
||||
/**
|
||||
* Returns the {@link InternalScene} with the given sceneID.
|
||||
*
|
||||
* @param sceneID of the {@link InternalScene}
|
||||
* @return internal scenes
|
||||
*/
|
||||
InternalScene getInternalScene(String sceneID);
|
||||
|
||||
/**
|
||||
* Registers the given {@link ManagerStatusListener} to this class.
|
||||
*
|
||||
* @param statusListener to register
|
||||
*/
|
||||
void registerStatusListener(ManagerStatusListener statusListener);
|
||||
|
||||
/**
|
||||
* Unregisters the {@link ManagerStatusListener} from this class.
|
||||
*/
|
||||
void unregisterStatusListener();
|
||||
|
||||
/**
|
||||
* Returns the {@link ManagerTypes} of this class.
|
||||
*
|
||||
* @return these {@link ManagerTypes}
|
||||
*/
|
||||
ManagerTypes getManagerType();
|
||||
|
||||
/**
|
||||
* Returns the current {@link ManagerStates}.
|
||||
*
|
||||
* @return current {@link ManagerStates}
|
||||
*/
|
||||
ManagerStates getManagerState();
|
||||
|
||||
/**
|
||||
* Calls a scene without inform the scene discovery about the conceivably new {@link InternalScene}.
|
||||
*
|
||||
* @param zoneID to call
|
||||
* @param groupID to call
|
||||
* @param sceneID to call
|
||||
*/
|
||||
void callInternalSceneWithoutDiscovery(Integer zoneID, Short groupID, Short sceneID);
|
||||
}
|
||||
@@ -0,0 +1,267 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.manager;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.Circuit;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.Device;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.DSID;
|
||||
|
||||
/**
|
||||
* The {@link StructureManager} builds the internal model of the digitalSTROM-System.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public interface StructureManager {
|
||||
|
||||
/**
|
||||
* Generates the zone- and group-names.
|
||||
*
|
||||
* @param connectionManager must not be null
|
||||
* @return true, if it's generated, otherwise false
|
||||
*/
|
||||
boolean generateZoneGroupNames(ConnectionManager connectionManager);
|
||||
|
||||
/**
|
||||
* Returns the name of a zone or null, if the given zoneID dose not exists.<br>
|
||||
* Note: Zone-names have to be generated over {@link #generateZoneGroupNames(ConnectionManager)}.
|
||||
*
|
||||
* @param zoneID of the zone
|
||||
* @return zone-name
|
||||
*/
|
||||
String getZoneName(int zoneID);
|
||||
|
||||
/**
|
||||
* Returns the id of a given zone-name or -1, if the given zone-name dose not exists.<br>
|
||||
* Note: Zone-names have to be generated over {@link #generateZoneGroupNames(ConnectionManager)}.
|
||||
*
|
||||
* @param zoneName of the zone
|
||||
* @return zoneID
|
||||
*/
|
||||
int getZoneId(String zoneName);
|
||||
|
||||
/**
|
||||
* Returns the name of the given groupID from the given zoneID or null, if the zoneID or groupID dose not exists.
|
||||
* <br>
|
||||
* Note: Zone-group-names have to be generated over {@link #generateZoneGroupNames(ConnectionManager)}.
|
||||
*
|
||||
* @param zoneID of the group
|
||||
* @param groupID of the group
|
||||
* @return group-name
|
||||
*/
|
||||
String getZoneGroupName(int zoneID, short groupID);
|
||||
|
||||
/**
|
||||
* Returns the groupID of the given group-name from the given zone name or -1, if the zone-name or group name dose
|
||||
* not exists.<br>
|
||||
* Note: Zone-group-names have to be generated over {@link #generateZoneGroupNames(ConnectionManager)}.
|
||||
*
|
||||
* @param zoneName of the group
|
||||
* @param groupName of the group
|
||||
* @return group-id
|
||||
*/
|
||||
short getZoneGroupId(String zoneName, String groupName);
|
||||
|
||||
/**
|
||||
* Returns a new {@link Map} of all {@link Device}'s with the {@link DSID} as key and the {@link Device} as value.
|
||||
* If no devices are found, an empty {@link Map} will be returned.
|
||||
*
|
||||
* @return device-map (cannot be null)
|
||||
*/
|
||||
Map<DSID, Device> getDeviceMap();
|
||||
|
||||
/**
|
||||
* Returns a reference to the {@link Map} of all {@link Device}'s with the {@link DSID} as key and the
|
||||
* {@link Device} as value. If no devices are found, an empty {@link Map} will be returned.
|
||||
*
|
||||
* @return reference device-map
|
||||
*/
|
||||
Map<DSID, Device> getDeviceHashMapReference();
|
||||
|
||||
/**
|
||||
* Returns the reference of the structure as {@link Map}[zoneID, {@link Map}[groupID,
|
||||
* {@link List}[{@link Device}]]].
|
||||
*
|
||||
* @return structure reference
|
||||
*/
|
||||
Map<Integer, Map<Short, List<Device>>> getStructureReference();
|
||||
|
||||
/**
|
||||
* Returns the Map of all groups as format HashMap[Short, List[Device]].
|
||||
*
|
||||
* @param zoneID of the zone
|
||||
* @return groups
|
||||
*/
|
||||
Map<Short, List<Device>> getGroupsFromZoneX(int zoneID);
|
||||
|
||||
/**
|
||||
* Returns the reference {@link List} of the {@link Device}'s of an zone-group.
|
||||
*
|
||||
* @param zoneID of the zone
|
||||
* @param groupID of the group
|
||||
* @return reference device-list
|
||||
*/
|
||||
List<Device> getReferenceDeviceListFromZoneXGroupX(int zoneID, short groupID);
|
||||
|
||||
/**
|
||||
* Returns the {@link Device} of the given dSID as {@link String} or null if no {@link Device} exists.
|
||||
*
|
||||
* @param dSID of the device
|
||||
* @return device
|
||||
*/
|
||||
Device getDeviceByDSID(String dSID);
|
||||
|
||||
/**
|
||||
* Returns the {@link Device} of the given dSID as {@link DSID} or null if no {@link Device} exists.
|
||||
*
|
||||
* @param dSID of the device
|
||||
* @return device
|
||||
*/
|
||||
Device getDeviceByDSID(DSID dSID);
|
||||
|
||||
/**
|
||||
* Returns the {@link Device} of the given dSUID or null if no {@link Device} exists.
|
||||
*
|
||||
* @param dSUID of the device
|
||||
* @return the {@link Device} with the given dSUID
|
||||
*/
|
||||
Device getDeviceByDSUID(String dSUID);
|
||||
|
||||
/**
|
||||
* Updates a {@link Device} of the structure.
|
||||
*
|
||||
* @param oldZone ID
|
||||
* @param oldGroups ID's
|
||||
* @param device new {@link Device}
|
||||
*/
|
||||
void updateDevice(int oldZone, List<Short> oldGroups, Device device);
|
||||
|
||||
/**
|
||||
* Updates a {@link Device} of the structure.
|
||||
*
|
||||
* @param device to update
|
||||
*/
|
||||
void updateDevice(Device device);
|
||||
|
||||
/**
|
||||
* Deletes a {@link Device} from the structure.
|
||||
*
|
||||
* @param device to delete
|
||||
*/
|
||||
void deleteDevice(Device device);
|
||||
|
||||
/**
|
||||
* Adds a {@link Device} to the structure.
|
||||
*
|
||||
* @param device to add
|
||||
*/
|
||||
void addDeviceToStructure(Device device);
|
||||
|
||||
/**
|
||||
* Returns a {@link Set} of all zoneID's
|
||||
*
|
||||
* @return zoneID's
|
||||
*/
|
||||
Set<Integer> getZoneIDs();
|
||||
|
||||
/**
|
||||
* Returns true, if a zone with the given zoneID exists, otherwise false.
|
||||
*
|
||||
* @param zoneID to check
|
||||
* @return true = zoneID exists | false = zoneID not exists
|
||||
*/
|
||||
boolean checkZoneID(int zoneID);
|
||||
|
||||
/**
|
||||
* Returns true, if a zone-group with the given zoneID and groupID exists, otherwise false.
|
||||
*
|
||||
* @param zoneID to check
|
||||
* @param groupID to check
|
||||
* @return true = zoneID or groupID exists | false = zoneID or groupID not exists
|
||||
*/
|
||||
boolean checkZoneGroupID(int zoneID, short groupID);
|
||||
|
||||
/**
|
||||
* Adds the given {@link List} of {@link Circuit}'s to this {@link StructureManager}.
|
||||
*
|
||||
* @param referenceCircuitList to add
|
||||
*/
|
||||
void addCircuitList(List<Circuit> referenceCircuitList);
|
||||
|
||||
/**
|
||||
* Adds the given {@link Circuit} to this {@link StructureManager}.
|
||||
*
|
||||
* @param circuit to add
|
||||
* @return the old {@link Circuit}, if the given {@link Circuit} was already added.
|
||||
*/
|
||||
Circuit addCircuit(Circuit circuit);
|
||||
|
||||
/**
|
||||
* Returns the {@link Circuit} with the given {@link DSID}.
|
||||
*
|
||||
* @param dSID of the {@link Circuit} to get
|
||||
* @return the {@link Circuit} with the given {@link DSID}
|
||||
*/
|
||||
Circuit getCircuitByDSID(DSID dSID);
|
||||
|
||||
/**
|
||||
* Returns the {@link Circuit} with the given dSID as {@link String}.
|
||||
*
|
||||
* @param dSID of the {@link Circuit} to get
|
||||
* @return the {@link Circuit} with the given dSID
|
||||
*/
|
||||
Circuit getCircuitByDSID(String dSID);
|
||||
|
||||
/**
|
||||
* Returns the {@link Circuit} with the given dSUID as {@link String}.
|
||||
*
|
||||
* @param dSUID of the {@link Circuit} to get
|
||||
* @return the {@link Circuit} with the given dSUID
|
||||
*/
|
||||
Circuit getCircuitByDSUID(String dSUID);
|
||||
|
||||
/**
|
||||
* Updates the configuration of an added {@link Circuit} through a new {@link Circuit} object.
|
||||
*
|
||||
* @param newCircuit to update
|
||||
* @return {@link Circuit} with the old configuration
|
||||
*/
|
||||
Circuit updateCircuitConfig(Circuit newCircuit);
|
||||
|
||||
/**
|
||||
* Deletes the {@link Circuit} with the given {@link DSID}.
|
||||
*
|
||||
* @param dSID of the {@link Circuit} to remove
|
||||
* @return the removed {@link Circuit}
|
||||
*/
|
||||
Circuit deleteCircuit(DSID dSID);
|
||||
|
||||
/**
|
||||
* Deletes the {@link Circuit} with the given dSUID.
|
||||
*
|
||||
* @param dSUID of the {@link Circuit} to remove
|
||||
* @return the removed {@link Circuit}
|
||||
*/
|
||||
Circuit deleteCircuit(String dSUID);
|
||||
|
||||
/**
|
||||
* Returns a {@link Map} of all {@link Circuit}'s which are added to this {@link StructureManager}.
|
||||
*
|
||||
* @return {@link Map} of all added {@link Circuit}'s
|
||||
*/
|
||||
Map<DSID, Circuit> getCircuitMap();
|
||||
}
|
||||
@@ -0,0 +1,542 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.manager.impl;
|
||||
|
||||
import java.net.HttpURLConnection;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.config.Config;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.ConnectionListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.ConnectionManager;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.DsAPI;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.HttpTransport;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.impl.DsAPIImpl;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.impl.HttpTransportImpl;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link ConnectionManagerImpl} is the implementation of the {@link ConnectionManager}.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class ConnectionManagerImpl implements ConnectionManager {
|
||||
|
||||
/**
|
||||
* Query to get all enabled application tokens. Can be executed with {@link DsAPI#query(String, String)} or
|
||||
* {@link DsAPI#query2(String, String)}.
|
||||
*/
|
||||
public final String QUERY_GET_ENABLED_APPLICATION_TOKENS = "/system/security/applicationTokens/enabled/*(*)";
|
||||
private final Logger logger = LoggerFactory.getLogger(ConnectionManagerImpl.class);
|
||||
|
||||
private Config config;
|
||||
private ConnectionListener connListener;
|
||||
private HttpTransport transport;
|
||||
private String sessionToken;
|
||||
private Boolean connectionEstablished = false;
|
||||
private boolean genAppToken;
|
||||
private DsAPI digitalSTROMClient;
|
||||
|
||||
/**
|
||||
* The same constructor like {@link #ConnectionManagerImpl(String, String, String, String)}, but the connection
|
||||
* timeout and read timeout can be set, too.
|
||||
*
|
||||
* @param hostArddress (must not be null)
|
||||
* @param connectTimeout (if connectTimeout is lower than 0 the {@link Config#DEFAULT_CONNECTION_TIMEOUT} will be
|
||||
* set)
|
||||
* @param readTimeout (if readTimeout is lower than 0 the {@link Config#DEFAULT_CONNECTION_TIMEOUT} will be set)
|
||||
* @param username (can be null, if application token is set)
|
||||
* @param password (can be null, if application token is set
|
||||
* @param applicationToken (can be null, if username and password is set)
|
||||
* @see #ConnectionManagerImpl(String, String, String, String)
|
||||
*/
|
||||
public ConnectionManagerImpl(String hostArddress, int connectTimeout, int readTimeout, String username,
|
||||
String password, String applicationToken) {
|
||||
init(hostArddress, connectTimeout, readTimeout, username, password, applicationToken, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ConnectionManagerImpl} through a {@link Config} object, which has all configurations set.
|
||||
*
|
||||
* @param config (must not be null)
|
||||
*/
|
||||
public ConnectionManagerImpl(Config config) {
|
||||
init(config, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The same constructor like {@link #ConnectionManagerImpl(Config)}, but a {@link ConnectionListener} can be
|
||||
* registered, too.
|
||||
*
|
||||
* @param config (must not be null)
|
||||
* @param connectionListener (can be null)
|
||||
* @see #ConnectionManagerImpl(Config)
|
||||
*/
|
||||
public ConnectionManagerImpl(Config config, ConnectionListener connectionListener) {
|
||||
this.connListener = connectionListener;
|
||||
init(config, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The same constructor like {@link #ConnectionManagerImpl(Config, ConnectionListener)}, but through genApToken it
|
||||
* can be set, if a application token will be automatically generated.
|
||||
*
|
||||
* @param config (must not be null)
|
||||
* @param connectionListener (can be null)
|
||||
* @param genAppToken (true = application token will be generated, otherwise false)
|
||||
* @see #ConnectionManagerImpl(Config, ConnectionListener)
|
||||
*/
|
||||
public ConnectionManagerImpl(Config config, ConnectionListener connectionListener, boolean genAppToken) {
|
||||
this.connListener = connectionListener;
|
||||
this.genAppToken = genAppToken;
|
||||
init(config, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ConnectionManagerImpl} with the given parameters, which are needed to create the
|
||||
* {@link HttpTransport} and to login into the digitalSTROM server. If the application token is null and the
|
||||
* username and password are valid, a application token will be automatically generated or a existing application
|
||||
* token for the at {@link Config#getApplicationName()} set application name will be set.
|
||||
*
|
||||
* @param hostAddress (must not be null)
|
||||
* @param username (can be null, if application token is set)
|
||||
* @param password (can be null, if application token is set
|
||||
* @param applicationToken (can be null, if username and password is set)
|
||||
*/
|
||||
public ConnectionManagerImpl(String hostAddress, String username, String password, String applicationToken) {
|
||||
init(hostAddress, -1, -1, username, password, applicationToken, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The same constructor like {@link #ConnectionManagerImpl(String, String, String, String)}, but without username
|
||||
* and password.
|
||||
*
|
||||
* @param hostAddress (must not be null)
|
||||
* @param applicationToken (must not be null)
|
||||
*/
|
||||
public ConnectionManagerImpl(String hostAddress, String applicationToken) {
|
||||
init(hostAddress, -1, -1, null, null, applicationToken, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The same constructor like {@link #ConnectionManagerImpl(String, String, String, String)}, but without application
|
||||
* token.
|
||||
*
|
||||
* @param hostAddress (must not be null)
|
||||
* @param username (must not be null)
|
||||
* @param password (must not be null)
|
||||
* @see #ConnectionManagerImpl(String, String, String, String)
|
||||
*/
|
||||
public ConnectionManagerImpl(String hostAddress, String username, String password) {
|
||||
init(hostAddress, -1, -1, username, password, null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The same constructor like {@link #ConnectionManagerImpl(String, String, String)}, but a
|
||||
* {@link ConnectionListener} can be set, too.
|
||||
*
|
||||
* @param hostAddress (must not be null)
|
||||
* @param username (must not be null)
|
||||
* @param password (must not be null)
|
||||
* @param connectionListener (can be null)
|
||||
* @see #ConnectionManagerImpl(String, String, String)
|
||||
*/
|
||||
public ConnectionManagerImpl(String hostAddress, String username, String password,
|
||||
ConnectionListener connectionListener) {
|
||||
this.connListener = connectionListener;
|
||||
init(hostAddress, -1, -1, username, password, null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The same constructor like {@link #ConnectionManagerImpl(String, String, String, String)}, but a
|
||||
* {@link ConnectionListener} can be set, too.
|
||||
*
|
||||
* @param hostAddress (must not be null)
|
||||
* @param username (can be null, if application token is set)
|
||||
* @param password (can be null, if application token is set)
|
||||
* @param applicationToken (can be null, if username and password is set)
|
||||
* @param connectionListener (can be null)
|
||||
* @see #ConnectionManagerImpl(String, String, String, String)
|
||||
*/
|
||||
public ConnectionManagerImpl(String hostAddress, String username, String password, String applicationToken,
|
||||
ConnectionListener connectionListener) {
|
||||
this.connListener = connectionListener;
|
||||
init(hostAddress, -1, -1, username, password, null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The same constructor like {@link #ConnectionManagerImpl(String, String, String)}, but through genApToken it
|
||||
* can be set, if a application token will be automatically generated.
|
||||
*
|
||||
* @param hostAddress (must not be null)
|
||||
* @param username (must not be null)
|
||||
* @param password (must not be null)
|
||||
* @param genAppToken (true = application token will be generated, otherwise false)
|
||||
* @see #ConnectionManagerImpl(String, String, String, String)
|
||||
*/
|
||||
public ConnectionManagerImpl(String hostAddress, String username, String password, boolean genAppToken) {
|
||||
this.genAppToken = genAppToken;
|
||||
init(hostAddress, -1, -1, username, password, null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The same constructor like {@link #ConnectionManagerImpl(String, String, String, String)}, but through genApToken
|
||||
* it can be set, if a application token will be automatically generated.
|
||||
*
|
||||
* @param hostAddress (must not be null)
|
||||
* @param username (can be null, if application token is set)
|
||||
* @param password (can be null, if application token is set)
|
||||
* @param applicationToken (can be null, if username and password is set)
|
||||
* @param genAppToken (true = application token will be generated, otherwise false)
|
||||
* @see #ConnectionManagerImpl(String, String, String, String)
|
||||
*/
|
||||
public ConnectionManagerImpl(String hostAddress, String username, String password, String applicationToken,
|
||||
boolean genAppToken) {
|
||||
this.genAppToken = genAppToken;
|
||||
init(hostAddress, -1, -1, username, password, applicationToken, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The same constructor like {@link #ConnectionManagerImpl(String, String, String, String, boolean)}, but through
|
||||
* acceptAllCerts it can be set, if all SSL-Certificates will be accept.
|
||||
*
|
||||
* @param hostAddress (must not be null)
|
||||
* @param username (can be null, if application token is set)
|
||||
* @param password (can be null, if application token is set)
|
||||
* @param applicationToken (can be null, if username and password is set)
|
||||
* @param genAppToken (true = application token will be generated, otherwise false)
|
||||
* @param acceptAllCerts (true = all SSL-Certificates will be accept, otherwise false)
|
||||
* @see #ConnectionManagerImpl(String, String, String, String, boolean)
|
||||
*/
|
||||
public ConnectionManagerImpl(String hostAddress, String username, String password, String applicationToken,
|
||||
boolean genAppToken, boolean acceptAllCerts) {
|
||||
this.genAppToken = genAppToken;
|
||||
init(hostAddress, -1, -1, username, password, applicationToken, acceptAllCerts);
|
||||
}
|
||||
|
||||
/**
|
||||
* The same constructor like {@link #ConnectionManagerImpl(String, String, String, String, boolean)}, but a
|
||||
* {@link ConnectionListener} can be set, too.
|
||||
*
|
||||
* @param hostAddress (must not be null)
|
||||
* @param username (can be null, if application token is set)
|
||||
* @param password (can be null, if application token is set)
|
||||
* @param applicationToken (can be null, if username and password is set)
|
||||
* @param genAppToken (true = application token will be generated, otherwise false)
|
||||
* @param connectionListener (can be null)
|
||||
* @see #ConnectionManagerImpl(String, String, String, String, boolean)
|
||||
*/
|
||||
public ConnectionManagerImpl(String hostAddress, String username, String password, String applicationToken,
|
||||
boolean genAppToken, ConnectionListener connectionListener) {
|
||||
this.connListener = connectionListener;
|
||||
this.genAppToken = genAppToken;
|
||||
init(hostAddress, -1, -1, username, password, applicationToken, false);
|
||||
}
|
||||
|
||||
private void init(String hostAddress, int connectionTimeout, int readTimeout, String username, String password,
|
||||
String applicationToken, boolean acceptAllCerts) {
|
||||
config = new Config(hostAddress, username, password, applicationToken);
|
||||
if (connectionTimeout >= 0) {
|
||||
config.setConnectionTimeout(connectionTimeout);
|
||||
}
|
||||
if (readTimeout >= 0) {
|
||||
config.setReadTimeout(readTimeout);
|
||||
}
|
||||
init(config, acceptAllCerts);
|
||||
}
|
||||
|
||||
private void init(Config config, boolean acceptAllCerts) {
|
||||
this.config = config;
|
||||
this.transport = new HttpTransportImpl(this, acceptAllCerts);
|
||||
this.digitalSTROMClient = new DsAPIImpl(transport);
|
||||
if (this.genAppToken) {
|
||||
this.onNotAuthenticated();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpTransport getHttpTransport() {
|
||||
return transport;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DsAPI getDigitalSTROMAPI() {
|
||||
return this.digitalSTROMClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSessionToken() {
|
||||
return this.sessionToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNewSessionToken() {
|
||||
if (this.genAppToken) {
|
||||
if (StringUtils.isNotBlank(config.getAppToken())) {
|
||||
sessionToken = this.digitalSTROMClient.loginApplication(config.getAppToken());
|
||||
} else if (codeIsAuthentificationFaild()) {
|
||||
onNotAuthenticated();
|
||||
}
|
||||
} else {
|
||||
sessionToken = this.digitalSTROMClient.login(this.config.getUserName(), this.config.getPassword());
|
||||
}
|
||||
return sessionToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean checkConnection() {
|
||||
return checkConnection(this.digitalSTROMClient.checkConnection(null));
|
||||
}
|
||||
|
||||
private final short code = HttpURLConnection.HTTP_OK;
|
||||
|
||||
private boolean codeIsAuthentificationFaild() {
|
||||
return this.code == HttpURLConnection.HTTP_FORBIDDEN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkConnection(int code) {
|
||||
switch (code) {
|
||||
case HttpURLConnection.HTTP_INTERNAL_ERROR:
|
||||
case HttpURLConnection.HTTP_OK:
|
||||
if (!connectionEstablished) {
|
||||
onConnectionResumed();
|
||||
}
|
||||
break;
|
||||
case HttpURLConnection.HTTP_UNAUTHORIZED:
|
||||
connectionEstablished = false;
|
||||
break;
|
||||
case HttpURLConnection.HTTP_FORBIDDEN:
|
||||
getNewSessionToken();
|
||||
if (sessionToken != null) {
|
||||
if (!connectionEstablished) {
|
||||
onConnectionResumed();
|
||||
}
|
||||
} else {
|
||||
if (this.genAppToken) {
|
||||
onNotAuthenticated();
|
||||
}
|
||||
connectionEstablished = false;
|
||||
}
|
||||
break;
|
||||
case ConnectionManager.MALFORMED_URL_EXCEPTION:
|
||||
onConnectionLost(ConnectionListener.INVALID_URL);
|
||||
break;
|
||||
case ConnectionManager.CONNECTION_EXCEPTION:
|
||||
case ConnectionManager.SOCKET_TIMEOUT_EXCEPTION:
|
||||
onConnectionLost(ConnectionListener.CONNECTON_TIMEOUT);
|
||||
break;
|
||||
case ConnectionManager.SSL_HANDSHAKE_EXCEPTION:
|
||||
onConnectionLost(ConnectionListener.SSL_HANDSHAKE_ERROR);
|
||||
break;
|
||||
case ConnectionManager.GENERAL_EXCEPTION:
|
||||
onConnectionLost(ConnectionListener.CONNECTION_LOST);
|
||||
break;
|
||||
case ConnectionManager.UNKNOWN_HOST_EXCEPTION:
|
||||
onConnectionLost(ConnectionListener.UNKNOWN_HOST);
|
||||
break;
|
||||
case ConnectionManager.AUTHENTIFICATION_PROBLEM:
|
||||
if (connListener != null) {
|
||||
if (config.getAppToken() != null) {
|
||||
connListener.onConnectionStateChange(ConnectionListener.NOT_AUTHENTICATED,
|
||||
ConnectionListener.WRONG_APP_TOKEN);
|
||||
} else {
|
||||
connListener.onConnectionStateChange(ConnectionListener.NOT_AUTHENTICATED,
|
||||
ConnectionListener.WRONG_USER_OR_PASSWORD);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HttpURLConnection.HTTP_NOT_FOUND:
|
||||
onConnectionLost(ConnectionListener.HOST_NOT_FOUND);
|
||||
break;
|
||||
}
|
||||
return connectionEstablished;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean connectionEstablished() {
|
||||
return connectionEstablished;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called whenever the connection to the digitalSTROM-Server is available,
|
||||
* but requests are not allowed due to a missing or invalid authentication.
|
||||
*/
|
||||
private void onNotAuthenticated() {
|
||||
String applicationToken = null;
|
||||
boolean isAuthenticated = false;
|
||||
if (StringUtils.isNotBlank(config.getAppToken())) {
|
||||
sessionToken = digitalSTROMClient.loginApplication(config.getAppToken());
|
||||
if (sessionToken != null) {
|
||||
isAuthenticated = true;
|
||||
} else {
|
||||
if (connListener != null) {
|
||||
connListener.onConnectionStateChange(ConnectionListener.NOT_AUTHENTICATED,
|
||||
ConnectionListener.WRONG_APP_TOKEN);
|
||||
if (!checkUserPassword()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (checkUserPassword()) {
|
||||
if (!isAuthenticated) {
|
||||
// if an application-token for the application exists, use this application-token and test host is
|
||||
// reachable
|
||||
logger.debug("check existing application-tokens");
|
||||
sessionToken = digitalSTROMClient.login(config.getUserName(), config.getPassword());
|
||||
if (sessionToken != null) {
|
||||
JsonObject jObj = digitalSTROMClient.query(sessionToken, QUERY_GET_ENABLED_APPLICATION_TOKENS);
|
||||
|
||||
if (jObj != null) {
|
||||
if (jObj.get("enabled") != null && jObj.get("enabled").isJsonArray()) {
|
||||
JsonArray jArray = jObj.get("enabled").getAsJsonArray();
|
||||
// application-token check
|
||||
for (int i = 0; i < jArray.size(); i++) {
|
||||
JsonObject appToken = jArray.get(i).getAsJsonObject();
|
||||
if (appToken.get("applicationName") != null && appToken.get("applicationName")
|
||||
.getAsString().equals(config.getApplicationName())) {
|
||||
// found application-token, set as application-token
|
||||
applicationToken = appToken.get("token").getAsString();
|
||||
logger.debug("found application-token {} for application {}", applicationToken,
|
||||
config.getApplicationName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (applicationToken == null) {
|
||||
// no token found, generate applicationToken
|
||||
applicationToken = this.digitalSTROMClient
|
||||
.requestAppplicationToken(config.getApplicationName());
|
||||
logger.debug(
|
||||
"no application-token for application {} found, generate a application-token {}",
|
||||
config.getApplicationName(), applicationToken);
|
||||
if (StringUtils.isNotBlank(applicationToken)) {
|
||||
// enable applicationToken
|
||||
if (!digitalSTROMClient.enableApplicationToken(applicationToken,
|
||||
digitalSTROMClient.login(config.getUserName(), config.getPassword()))) {
|
||||
// if enable failed set application-token = null so thats not will be set
|
||||
applicationToken = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (applicationToken != null) {
|
||||
logger.debug("application-token can be used");
|
||||
config.setAppToken(applicationToken);
|
||||
isAuthenticated = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (connListener != null) {
|
||||
connListener.onConnectionStateChange(ConnectionListener.NOT_AUTHENTICATED,
|
||||
ConnectionListener.WRONG_USER_OR_PASSWORD);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// remove password and username, to don't store them persistently
|
||||
if (isAuthenticated) {
|
||||
config.removeUsernameAndPassword();
|
||||
if (connListener != null) {
|
||||
connListener.onConnectionStateChange(ConnectionListener.APPLICATION_TOKEN_GENERATED);
|
||||
}
|
||||
}
|
||||
} else if (!isAuthenticated) {
|
||||
if (connListener != null) {
|
||||
connListener.onConnectionStateChange(ConnectionListener.NOT_AUTHENTICATED,
|
||||
ConnectionListener.NO_USER_PASSWORD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkUserPassword() {
|
||||
if (StringUtils.isNotBlank(config.getUserName()) && StringUtils.isNotBlank(config.getPassword())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called whenever the connection to the digitalSTROM-Server is lost.
|
||||
*
|
||||
* @param reason
|
||||
*/
|
||||
private void onConnectionLost(String reason) {
|
||||
if (connListener != null) {
|
||||
connListener.onConnectionStateChange(ConnectionListener.CONNECTION_LOST, reason);
|
||||
}
|
||||
connectionEstablished = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called whenever the connection to the digitalSTROM-Server is resumed.
|
||||
*/
|
||||
private void onConnectionResumed() {
|
||||
if (connListener != null) {
|
||||
connListener.onConnectionStateChange(ConnectionListener.CONNECTION_RESUMED);
|
||||
}
|
||||
connectionEstablished = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerConnectionListener(ConnectionListener listener) {
|
||||
this.connListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterConnectionListener() {
|
||||
this.connListener = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getApplicationToken() {
|
||||
return config.getAppToken();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeApplicationToken() {
|
||||
if (StringUtils.isNotBlank(config.getAppToken())) {
|
||||
return digitalSTROMClient.revokeToken(config.getAppToken(), null);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateConfig(String host, String username, String password, String applicationToken) {
|
||||
init(host, -1, -1, username, password, applicationToken, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateConfig(Config config) {
|
||||
if (this.config != null) {
|
||||
this.config.updateConfig(config);
|
||||
} else {
|
||||
this.config = config;
|
||||
}
|
||||
init(this.config, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configHasBeenUpdated() {
|
||||
init(this.config, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Config getConfig() {
|
||||
return this.config;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,556 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.manager.impl;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.event.EventListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.event.constants.EventNames;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.event.constants.EventResponseEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.event.types.EventItem;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.ManagerStatusListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.SceneStatusListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.stateenums.ManagerStates;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.stateenums.ManagerTypes;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.ConnectionManager;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.SceneManager;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.StructureManager;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.Device;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.DSID;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.scene.InternalScene;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.scene.SceneDiscovery;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.scene.constants.SceneEnum;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link SceneManagerImpl} is the implementation of the {@link SceneManager}.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class SceneManagerImpl implements SceneManager {
|
||||
|
||||
/**
|
||||
* Contains all supported event-types.
|
||||
*/
|
||||
public static final List<String> SUPPORTED_EVENTS = Arrays.asList(EventNames.CALL_SCENE, EventNames.UNDO_SCENE);
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(SceneManagerImpl.class);
|
||||
|
||||
private final List<String> echoBox = Collections.synchronizedList(new LinkedList<>());
|
||||
private final Map<String, InternalScene> internalSceneMap = Collections.synchronizedMap(new HashMap<>());
|
||||
|
||||
private EventListener eventListener;
|
||||
private final StructureManager structureManager;
|
||||
private final ConnectionManager connectionManager;
|
||||
private final SceneDiscovery discovery;
|
||||
private ManagerStatusListener statusListener;
|
||||
|
||||
private ManagerStates state = ManagerStates.STOPPED;
|
||||
private boolean scenesGenerated = false;
|
||||
|
||||
/**
|
||||
* Creates a new {@link SceneManagerImpl} through the given managers.
|
||||
*
|
||||
* @param connectionManager (must not be null)
|
||||
* @param structureManager (must not be null)
|
||||
*/
|
||||
public SceneManagerImpl(ConnectionManager connectionManager, StructureManager structureManager) {
|
||||
this.structureManager = structureManager;
|
||||
this.connectionManager = connectionManager;
|
||||
this.discovery = new SceneDiscovery(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same constructor like {@link #SceneManagerImpl(ConnectionManager, StructureManager)}, but a
|
||||
* {@link ManagerStatusListener} can be set, too.
|
||||
*
|
||||
* @param connectionManager (must not be null)
|
||||
* @param structureManager (must not be null)
|
||||
* @param statusListener (can be null)
|
||||
* @see #SceneManagerImpl(ConnectionManager, StructureManager)
|
||||
*/
|
||||
public SceneManagerImpl(ConnectionManager connectionManager, StructureManager structureManager,
|
||||
ManagerStatusListener statusListener) {
|
||||
this.structureManager = structureManager;
|
||||
this.connectionManager = connectionManager;
|
||||
this.discovery = new SceneDiscovery(this);
|
||||
this.statusListener = statusListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same constructor like {@link #SceneManagerImpl(ConnectionManager, StructureManager, ManagerStatusListener)}, but
|
||||
* a {@link EventListener} can be set, too.
|
||||
*
|
||||
* @param connectionManager (must not be null)
|
||||
* @param structureManager (must not be null)
|
||||
* @param statusListener (can be null)
|
||||
* @param eventListener (can be null)
|
||||
* @see #SceneManagerImpl(ConnectionManager, StructureManager, ManagerStatusListener)
|
||||
*/
|
||||
public SceneManagerImpl(ConnectionManager connectionManager, StructureManager structureManager,
|
||||
ManagerStatusListener statusListener, EventListener eventListener) {
|
||||
this.structureManager = structureManager;
|
||||
this.connectionManager = connectionManager;
|
||||
this.discovery = new SceneDiscovery(this);
|
||||
this.statusListener = statusListener;
|
||||
this.eventListener = eventListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
logger.debug("start SceneManager");
|
||||
if (eventListener == null) {
|
||||
logger.debug("no EventListener is set, create a new EventListener");
|
||||
eventListener = new EventListener(connectionManager, this);
|
||||
} else {
|
||||
logger.debug("EventListener is set, add this SceneManager as EventHandler");
|
||||
eventListener.addEventHandler(this);
|
||||
}
|
||||
eventListener.start();
|
||||
logger.debug("start SceneManager");
|
||||
stateChanged(ManagerStates.RUNNING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
logger.debug("stop SceneManager");
|
||||
if (eventListener != null) {
|
||||
eventListener.removeEventHandler(this);
|
||||
}
|
||||
this.discovery.stop();
|
||||
this.stateChanged(ManagerStates.STOPPED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEvent(EventItem eventItem) {
|
||||
if (eventItem == null) {
|
||||
return;
|
||||
}
|
||||
boolean isCallScene = true;
|
||||
String isCallStr = eventItem.getName();
|
||||
if (isCallStr != null) {
|
||||
isCallScene = isCallStr.equals(EventNames.CALL_SCENE);
|
||||
}
|
||||
|
||||
boolean isDeviceCall = false;
|
||||
String deviceCallStr = eventItem.getSource().get(EventResponseEnum.IS_DEVICE);
|
||||
if (deviceCallStr != null) {
|
||||
isDeviceCall = Boolean.parseBoolean(deviceCallStr);
|
||||
}
|
||||
|
||||
if (isDeviceCall) {
|
||||
String dsidStr = null;
|
||||
dsidStr = eventItem.getSource().get(EventResponseEnum.DSID);
|
||||
short sceneId = -1;
|
||||
String sceneStr = eventItem.getProperties().get(EventResponseEnum.SCENEID);
|
||||
if (sceneStr != null) {
|
||||
try {
|
||||
sceneId = Short.parseShort(sceneStr);
|
||||
} catch (java.lang.NumberFormatException e) {
|
||||
logger.error("An exception occurred, while handling event at parsing sceneID: {}", sceneStr, e);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isEcho(dsidStr, sceneId)) {
|
||||
logger.debug("{} event for device: {}", eventItem.getName(), dsidStr);
|
||||
if (isCallScene) {
|
||||
this.callDeviceScene(dsidStr, sceneId);
|
||||
} else {
|
||||
this.undoDeviceScene(dsidStr);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
String intSceneID = null;
|
||||
String zoneIDStr = eventItem.getSource().get(EventResponseEnum.ZONEID);
|
||||
String groupIDStr = eventItem.getSource().get(EventResponseEnum.GROUPID);
|
||||
String sceneIDStr = eventItem.getProperties().get(EventResponseEnum.SCENEID);
|
||||
|
||||
if (zoneIDStr != null && sceneIDStr != null && groupIDStr != null) {
|
||||
intSceneID = zoneIDStr + "-" + groupIDStr + "-" + sceneIDStr;
|
||||
if (!isEcho(intSceneID)) {
|
||||
logger.debug("{} event for scene: {}-{}-{}", eventItem.getName(), zoneIDStr, groupIDStr,
|
||||
sceneIDStr);
|
||||
if (isCallScene) {
|
||||
this.callInternalScene(intSceneID);
|
||||
} else {
|
||||
this.undoInternalScene(intSceneID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isEcho(String dsid, short sceneId) {
|
||||
// sometimes the dS-event has a dSUID saved in the dSID
|
||||
String echo = (structureManager.getDeviceByDSUID(dsid) != null
|
||||
? structureManager.getDeviceByDSUID(dsid).getDSID().getValue()
|
||||
: dsid) + "-" + sceneId;
|
||||
logger.debug("An echo scene event was detected: {}", echo);
|
||||
return isEcho(echo);
|
||||
}
|
||||
|
||||
private boolean isEcho(String echoID) {
|
||||
if (echoBox.contains(echoID)) {
|
||||
echoBox.remove(echoID);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ... we want to ignore own 'command-echos'
|
||||
@Override
|
||||
public void addEcho(String dsid, short sceneId) {
|
||||
addEcho(dsid + "-" + sceneId);
|
||||
}
|
||||
|
||||
// ... we want to ignore own 'command-echos'
|
||||
@Override
|
||||
public void addEcho(String internalSceneID) {
|
||||
echoBox.add(internalSceneID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void callInternalScene(InternalScene scene) {
|
||||
InternalScene intScene = this.internalSceneMap.get(scene.getID());
|
||||
if (intScene != null) {
|
||||
intScene.activateScene();
|
||||
} else {
|
||||
if (SceneEnum.getScene(scene.getSceneID()) != null
|
||||
&& structureManager.checkZoneGroupID(scene.getZoneID(), scene.getGroupID())) {
|
||||
scene.addReferenceDevices(this.structureManager.getReferenceDeviceListFromZoneXGroupX(scene.getZoneID(),
|
||||
scene.getGroupID()));
|
||||
this.internalSceneMap.put(scene.getID(), scene);
|
||||
scene.activateScene();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void callInternalSceneWithoutDiscovery(Integer zoneID, Short groupID, Short sceneID) {
|
||||
InternalScene intScene = this.internalSceneMap.get(zoneID + "-" + groupID + "-" + sceneID);
|
||||
if (intScene != null) {
|
||||
intScene.activateScene();
|
||||
} else {
|
||||
InternalScene scene = new InternalScene(zoneID, groupID, sceneID, null);
|
||||
if (structureManager.checkZoneGroupID(scene.getZoneID(), scene.getGroupID())) {
|
||||
scene.addReferenceDevices(this.structureManager.getReferenceDeviceListFromZoneXGroupX(scene.getZoneID(),
|
||||
scene.getGroupID()));
|
||||
scene.activateScene();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void callInternalScene(String sceneID) {
|
||||
InternalScene intScene = this.internalSceneMap.get(sceneID);
|
||||
if (intScene != null) {
|
||||
logger.debug("activating existing scene {}", intScene.getSceneName());
|
||||
intScene.activateScene();
|
||||
} else {
|
||||
intScene = createNewScene(sceneID);
|
||||
if (intScene != null) {
|
||||
logger.debug("created new scene, activating it: {}", intScene.getSceneName());
|
||||
discovery.sceneDiscoverd(intScene);
|
||||
intScene.activateScene();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInternalScene(InternalScene intScene) {
|
||||
if (!this.internalSceneMap.containsKey(intScene.getID())) {
|
||||
if (SceneEnum.getScene(intScene.getSceneID()) != null
|
||||
&& structureManager.checkZoneGroupID(intScene.getZoneID(), intScene.getGroupID())) {
|
||||
intScene.addReferenceDevices(this.structureManager
|
||||
.getReferenceDeviceListFromZoneXGroupX(intScene.getZoneID(), intScene.getGroupID()));
|
||||
this.internalSceneMap.put(intScene.getID(), intScene);
|
||||
|
||||
}
|
||||
} else {
|
||||
InternalScene oldScene = this.internalSceneMap.get(intScene.getID());
|
||||
String oldSceneName = this.internalSceneMap.get(intScene.getID()).getSceneName();
|
||||
String newSceneName = intScene.getSceneName();
|
||||
if ((oldSceneName.contains("Zone:") && oldSceneName.contains("Group:") && oldSceneName.contains("Scene:"))
|
||||
&& !(newSceneName.contains("Zone:") && newSceneName.contains("Group:")
|
||||
&& newSceneName.contains("Scene:"))) {
|
||||
oldScene.setSceneName(newSceneName);
|
||||
this.discovery.sceneDiscoverd(oldScene);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeInternalScene(String sceneID) {
|
||||
this.internalSceneMap.remove(sceneID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InternalScene getInternalScene(String sceneID) {
|
||||
return this.internalSceneMap.get(sceneID);
|
||||
}
|
||||
|
||||
private InternalScene createNewScene(String sceneID) {
|
||||
String[] sceneData = sceneID.split("-");
|
||||
if (sceneData.length == 3) {
|
||||
int zoneID = Integer.parseInt(sceneData[0]);
|
||||
short groupID = Short.parseShort(sceneData[1]);
|
||||
short sceneNumber = Short.parseShort(sceneData[2]);
|
||||
String sceneName = null;
|
||||
sceneName = connectionManager.getDigitalSTROMAPI().getSceneName(connectionManager.getSessionToken(), zoneID,
|
||||
null, groupID, sceneNumber);
|
||||
InternalScene intScene = null;
|
||||
if (SceneEnum.getScene(sceneNumber) != null && structureManager.checkZoneGroupID(zoneID, groupID)) {
|
||||
if (sceneName == null) {
|
||||
if (structureManager.getZoneName(zoneID) != null) {
|
||||
sceneName = "Zone: " + structureManager.getZoneName(zoneID);
|
||||
if (structureManager.getZoneGroupName(zoneID, groupID) != null) {
|
||||
sceneName = sceneName + " Group: " + structureManager.getZoneGroupName(zoneID, groupID);
|
||||
} else {
|
||||
sceneName = sceneName + " Group: " + groupID;
|
||||
}
|
||||
} else {
|
||||
if (structureManager.getZoneGroupName(zoneID, groupID) != null) {
|
||||
sceneName = "Zone: " + zoneID + " Group: "
|
||||
+ structureManager.getZoneGroupName(zoneID, groupID);
|
||||
} else {
|
||||
sceneName = "Zone: " + zoneID + " Group: " + groupID;
|
||||
}
|
||||
}
|
||||
sceneName = sceneName + " Scene: "
|
||||
+ SceneEnum.getScene(sceneNumber).toString().toLowerCase().replace("_", " ");
|
||||
}
|
||||
intScene = new InternalScene(zoneID, groupID, sceneNumber, sceneName);
|
||||
}
|
||||
return intScene;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void callDeviceScene(String dSID, Short sceneID) {
|
||||
Device device = this.structureManager.getDeviceByDSID(new DSID(dSID));
|
||||
if (device != null) {
|
||||
device.internalCallScene(sceneID);
|
||||
} else {
|
||||
device = this.structureManager.getDeviceByDSUID(dSID);
|
||||
if (device != null) {
|
||||
device.internalCallScene(sceneID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void callDeviceScene(Device device, Short sceneID) {
|
||||
if (device != null) {
|
||||
callDeviceScene(device.getDSID().toString(), sceneID);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undoInternalScene(InternalScene scene) {
|
||||
if (scene != null) {
|
||||
undoInternalScene(scene.getID());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undoInternalScene(String sceneID) {
|
||||
InternalScene intScene = this.internalSceneMap.get(sceneID);
|
||||
if (intScene != null) {
|
||||
logger.debug("deactivating existing scene {}", intScene.getSceneName());
|
||||
intScene.deactivateScene();
|
||||
} else {
|
||||
intScene = createNewScene(sceneID);
|
||||
if (intScene != null) {
|
||||
logger.debug("created new scene, deactivating it: {}", intScene.getSceneName());
|
||||
intScene.deactivateScene();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undoDeviceScene(String dSID) {
|
||||
Device device = this.structureManager.getDeviceByDSID(new DSID(dSID));
|
||||
if (device != null) {
|
||||
device.internalUndoScene();
|
||||
} else {
|
||||
device = this.structureManager.getDeviceByDSUID(dSID);
|
||||
if (device != null) {
|
||||
device.internalUndoScene();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undoDeviceScene(Device device) {
|
||||
if (device != null) {
|
||||
undoDeviceScene(device.getDSID().toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSceneListener(SceneStatusListener sceneListener) {
|
||||
if (sceneListener != null) {
|
||||
String id = sceneListener.getSceneStatusListenerID();
|
||||
if (id.equals(SceneStatusListener.SCENE_DISCOVERY)) {
|
||||
discovery.registerSceneDiscovery(sceneListener);
|
||||
logger.debug("Scene-Discovery registrated");
|
||||
for (InternalScene scene : internalSceneMap.values()) {
|
||||
discovery.sceneDiscoverd(scene);
|
||||
}
|
||||
} else {
|
||||
InternalScene intScene = internalSceneMap.get(sceneListener.getSceneStatusListenerID());
|
||||
if (intScene != null) {
|
||||
intScene.registerSceneListener(sceneListener);
|
||||
} else {
|
||||
addInternalScene(createNewScene(id));
|
||||
registerSceneListener(sceneListener);
|
||||
}
|
||||
logger.debug("SceneStatusListener with id {} is registrated", sceneListener.getSceneStatusListenerID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterSceneListener(SceneStatusListener sceneListener) {
|
||||
if (sceneListener != null) {
|
||||
String id = sceneListener.getSceneStatusListenerID();
|
||||
if (id.equals(SceneStatusListener.SCENE_DISCOVERY)) {
|
||||
this.discovery.unRegisterDiscovery();
|
||||
logger.debug("Scene-Discovery unregistrated");
|
||||
} else {
|
||||
InternalScene intScene = this.internalSceneMap.get(sceneListener.getSceneStatusListenerID());
|
||||
if (intScene != null) {
|
||||
intScene.unregisterSceneListener();
|
||||
}
|
||||
logger.debug("SceneStatusListener with id {} is unregistrated",
|
||||
sceneListener.getSceneStatusListenerID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean scenesGenerated() {
|
||||
return scenesGenerated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateScenes() {
|
||||
stateChanged(ManagerStates.GENERATING_SCENES);
|
||||
logger.debug("start generating scenes");
|
||||
discovery.generateAllScenes(connectionManager, structureManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scenesGenerated(char[] scenesGenerated) {
|
||||
if (String.valueOf(scenesGenerated).equals("1111")) {
|
||||
this.scenesGenerated = true;
|
||||
stateChanged(ManagerStates.RUNNING);
|
||||
}
|
||||
if (String.valueOf(scenesGenerated).contains("2")) {
|
||||
String type = "nan";
|
||||
switch (String.valueOf(scenesGenerated).indexOf("2")) {
|
||||
case 0:
|
||||
type = "namedScens";
|
||||
break;
|
||||
case 1:
|
||||
type = "appScenes";
|
||||
break;
|
||||
case 2:
|
||||
type = "zoneScenes";
|
||||
break;
|
||||
case 3:
|
||||
type = "reachableScenes";
|
||||
break;
|
||||
}
|
||||
logger.debug("Not all scenes are generated, try it again. Scene type {} is not generated.", type);
|
||||
stateChanged(ManagerStates.RUNNING);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDiscoveryRegistrated() {
|
||||
return this.discovery != null;
|
||||
}
|
||||
|
||||
private void stateChanged(ManagerStates state) {
|
||||
this.state = state;
|
||||
if (statusListener != null) {
|
||||
statusListener.onStatusChanged(ManagerTypes.SCENE_MANAGER, state);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagerTypes getManagerType() {
|
||||
return ManagerTypes.SCENE_MANAGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized ManagerStates getManagerState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<InternalScene> getScenes() {
|
||||
return this.internalSceneMap != null ? new LinkedList<>(this.internalSceneMap.values()) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerStatusListener(ManagerStatusListener statusListener) {
|
||||
this.statusListener = statusListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterStatusListener() {
|
||||
this.statusListener = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUID() {
|
||||
return this.getClass().getSimpleName() + "-" + SUPPORTED_EVENTS.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSupportedEvents() {
|
||||
return SUPPORTED_EVENTS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsEvent(String eventName) {
|
||||
return SUPPORTED_EVENTS.contains(eventName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEventListener(EventListener eventListener) {
|
||||
if (this.eventListener != null) {
|
||||
this.eventListener.removeEventHandler(this);
|
||||
}
|
||||
this.eventListener = eventListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsetEventListener(EventListener eventListener) {
|
||||
if (this.eventListener != null) {
|
||||
this.eventListener.removeEventHandler(this);
|
||||
}
|
||||
this.eventListener = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,424 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.manager.impl;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.ConnectionManager;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.StructureManager;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.DsAPI;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.AbstractGeneralDeviceInformations;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.Circuit;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.Device;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.CachedMeteringValue;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.DSID;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link StructureManagerImpl} is the implementation of the {@link StructureManager}.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class StructureManagerImpl implements StructureManager {
|
||||
|
||||
private class ZoneGroupsNameAndIDMap {
|
||||
public final String zoneName;
|
||||
public final int zoneID;
|
||||
|
||||
private final Map<Short, String> groupIdNames;
|
||||
private final Map<String, Short> groupNameIds;
|
||||
|
||||
public ZoneGroupsNameAndIDMap(final int zoneID, final String zoneName, JsonArray groups) {
|
||||
this.zoneID = zoneID;
|
||||
this.zoneName = zoneName;
|
||||
|
||||
groupIdNames = new HashMap<>(groups.size());
|
||||
groupNameIds = new HashMap<>(groups.size());
|
||||
for (int k = 0; k < groups.size(); k++) {
|
||||
short groupID = ((JsonObject) groups.get(k)).get("group").getAsShort();
|
||||
String groupName = ((JsonObject) groups.get(k)).get("name").getAsString();
|
||||
groupIdNames.put(groupID, groupName);
|
||||
groupNameIds.put(groupName, groupID);
|
||||
}
|
||||
}
|
||||
|
||||
public String getGroupName(Short groupID) {
|
||||
return groupIdNames.get(groupID);
|
||||
}
|
||||
|
||||
public short getGroupID(String groupName) {
|
||||
final Short tmp = groupNameIds.get(groupName);
|
||||
return tmp != null ? tmp : -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query to get all zone and group names. Can be executed with {@link DsAPI#query(String, String)} or
|
||||
* {@link DsAPI#query2(String, String)}.
|
||||
*/
|
||||
public static final String ZONE_GROUP_NAMES = "/apartment/zones/*(ZoneID,name)/groups/*(group,name)";
|
||||
|
||||
private final Map<Integer, Map<Short, List<Device>>> zoneGroupDeviceMap = Collections
|
||||
.synchronizedMap(new HashMap<>());
|
||||
private final Map<DSID, Device> deviceMap = Collections.synchronizedMap(new HashMap<>());
|
||||
private final Map<DSID, Circuit> circuitMap = Collections.synchronizedMap(new HashMap<>());
|
||||
private final Map<String, DSID> dSUIDToDSIDMap = Collections.synchronizedMap(new HashMap<>());
|
||||
|
||||
private Map<Integer, ZoneGroupsNameAndIDMap> zoneGroupIdNameMap;
|
||||
private Map<String, ZoneGroupsNameAndIDMap> zoneGroupNameIdMap;
|
||||
|
||||
/**
|
||||
* Creates a new {@link StructureManagerImpl} with the {@link Device}s of the given referenceDeviceList.
|
||||
*
|
||||
* @param referenceDeviceList to add
|
||||
*/
|
||||
public StructureManagerImpl(List<Device> referenceDeviceList) {
|
||||
handleStructure(referenceDeviceList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link StructureManagerImpl} with the {@link Device}s of the given referenceDeviceList.
|
||||
*
|
||||
* @param referenceDeviceList to add
|
||||
* @param referenceCircuitList to add
|
||||
*/
|
||||
public StructureManagerImpl(List<Device> referenceDeviceList, List<Circuit> referenceCircuitList) {
|
||||
handleStructure(referenceDeviceList);
|
||||
addCircuitList(referenceCircuitList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link StructureManagerImpl} without {@link Device}s.
|
||||
*/
|
||||
public StructureManagerImpl() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean generateZoneGroupNames(ConnectionManager connectionManager) {
|
||||
JsonObject resultJsonObj = connectionManager.getDigitalSTROMAPI().query(connectionManager.getSessionToken(),
|
||||
ZONE_GROUP_NAMES);
|
||||
if (resultJsonObj != null && resultJsonObj.get("zones") instanceof JsonArray) {
|
||||
JsonArray zones = (JsonArray) resultJsonObj.get("zones");
|
||||
if (zoneGroupIdNameMap == null) {
|
||||
zoneGroupIdNameMap = new HashMap<>(zones.size());
|
||||
zoneGroupNameIdMap = new HashMap<>(zones.size());
|
||||
}
|
||||
if (zones != null) {
|
||||
for (int i = 0; i < zones.size(); i++) {
|
||||
if (((JsonObject) zones.get(i)).get("groups") instanceof JsonArray) {
|
||||
JsonArray groups = (JsonArray) ((JsonObject) zones.get(i)).get("groups");
|
||||
ZoneGroupsNameAndIDMap zoneGoupIdNameMap = new ZoneGroupsNameAndIDMap(
|
||||
((JsonObject) zones.get(i)).get("ZoneID").getAsInt(),
|
||||
((JsonObject) zones.get(i)).get("name").getAsString(), groups);
|
||||
|
||||
zoneGroupIdNameMap.put(zoneGoupIdNameMap.zoneID, zoneGoupIdNameMap);
|
||||
zoneGroupNameIdMap.put(zoneGoupIdNameMap.zoneName, zoneGoupIdNameMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getZoneName(int zoneID) {
|
||||
if (zoneGroupIdNameMap == null) {
|
||||
return null;
|
||||
}
|
||||
final ZoneGroupsNameAndIDMap tmp = zoneGroupIdNameMap.get(zoneID);
|
||||
return tmp != null ? tmp.zoneName : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getZoneGroupName(int zoneID, short groupID) {
|
||||
if (zoneGroupIdNameMap == null) {
|
||||
return null;
|
||||
}
|
||||
final ZoneGroupsNameAndIDMap tmp = zoneGroupIdNameMap.get(zoneID);
|
||||
return tmp != null ? tmp.getGroupName(groupID) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getZoneId(String zoneName) {
|
||||
if (zoneGroupNameIdMap == null) {
|
||||
return -1;
|
||||
}
|
||||
final ZoneGroupsNameAndIDMap tmp = zoneGroupNameIdMap.get(zoneName);
|
||||
return tmp != null ? tmp.zoneID : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkZoneID(int zoneID) {
|
||||
return getGroupsFromZoneX(zoneID) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkZoneGroupID(int zoneID, short groupID) {
|
||||
final Map<Short, List<Device>> tmp = getGroupsFromZoneX(zoneID);
|
||||
return tmp != null ? tmp.get(groupID) != null : false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getZoneGroupId(String zoneName, String groupName) {
|
||||
if (zoneGroupNameIdMap == null) {
|
||||
return -1;
|
||||
}
|
||||
final ZoneGroupsNameAndIDMap tmp = zoneGroupNameIdMap.get(zoneName);
|
||||
return tmp != null ? tmp.getGroupID(groupName) : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<DSID, Device> getDeviceMap() {
|
||||
return new HashMap<>(deviceMap);
|
||||
}
|
||||
|
||||
private void putDeviceToHashMap(Device device) {
|
||||
if (device.getDSID() != null) {
|
||||
deviceMap.put(device.getDSID(), device);
|
||||
addDSIDtoDSUID((AbstractGeneralDeviceInformations) device);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method build the digitalSTROM structure as an {@link HashMap} with the zone id as key
|
||||
* and an {@link HashMap} as value. This {@link HashMap} has the group id as key and a {@link List}
|
||||
* with all digitalSTROM {@link Device}s.<br>
|
||||
* <br>
|
||||
* <b>Note:</b> the zone id 0 is the broadcast address and the group id 0, too.
|
||||
*/
|
||||
private void handleStructure(List<Device> deviceList) {
|
||||
Map<Short, List<Device>> groupXHashMap = new HashMap<>();
|
||||
groupXHashMap.put((short) 0, deviceList);
|
||||
|
||||
zoneGroupDeviceMap.put(0, groupXHashMap);
|
||||
|
||||
for (Device device : deviceList) {
|
||||
addDeviceToStructure(device);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<DSID, Device> getDeviceHashMapReference() {
|
||||
return deviceMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Integer, Map<Short, List<Device>>> getStructureReference() {
|
||||
return zoneGroupDeviceMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Short, List<Device>> getGroupsFromZoneX(int zoneID) {
|
||||
return zoneGroupDeviceMap.get(zoneID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Device> getReferenceDeviceListFromZoneXGroupX(int zoneID, short groupID) {
|
||||
final Map<Short, List<Device>> tmp = getGroupsFromZoneX(zoneID);
|
||||
return tmp != null ? tmp.get(groupID) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Device getDeviceByDSID(String dSID) {
|
||||
return getDeviceByDSID(new DSID(dSID));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Device getDeviceByDSID(DSID dSID) {
|
||||
return deviceMap.get(dSID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Device getDeviceByDSUID(String dSUID) {
|
||||
final DSID tmp = dSUIDToDSIDMap.get(dSUID);
|
||||
return tmp != null ? getDeviceByDSID(tmp) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDevice(int oldZone, List<Short> oldGroups, Device device) {
|
||||
int intOldZoneID = oldZone;
|
||||
if (intOldZoneID == -1) {
|
||||
intOldZoneID = device.getZoneId();
|
||||
}
|
||||
deleteDevice(intOldZoneID, oldGroups, device);
|
||||
addDeviceToStructure(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDevice(Device device) {
|
||||
if (device != null) {
|
||||
int oldZoneID = -1;
|
||||
List<Short> oldGroups = null;
|
||||
Device internalDevice = this.getDeviceByDSID(device.getDSID());
|
||||
if (internalDevice != null) {
|
||||
if (device.getZoneId() != internalDevice.getZoneId()) {
|
||||
oldZoneID = internalDevice.getZoneId();
|
||||
internalDevice.setZoneId(device.getZoneId());
|
||||
}
|
||||
|
||||
if (!internalDevice.getGroups().equals(device.getGroups())) {
|
||||
oldGroups = internalDevice.getGroups();
|
||||
internalDevice.setGroups(device.getGroups());
|
||||
}
|
||||
|
||||
if (deleteDevice(oldZoneID, oldGroups, internalDevice)) {
|
||||
addDeviceToStructure(internalDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteDevice(Device device) {
|
||||
dSUIDToDSIDMap.remove(device.getDSUID());
|
||||
deviceMap.remove(device.getDSID());
|
||||
deleteDevice(device.getZoneId(), device.getGroups(), device);
|
||||
}
|
||||
|
||||
private boolean deleteDevice(int zoneID, List<Short> groups, Device device) {
|
||||
List<Short> intGroups = groups;
|
||||
int intZoneID = zoneID;
|
||||
if (intGroups != null || intZoneID >= 0) {
|
||||
if (intGroups == null) {
|
||||
intGroups = device.getGroups();
|
||||
}
|
||||
if (intZoneID == -1) {
|
||||
intZoneID = device.getZoneId();
|
||||
}
|
||||
for (Short groupID : intGroups) {
|
||||
List<Device> deviceList = getReferenceDeviceListFromZoneXGroupX(intZoneID, groupID);
|
||||
if (deviceList != null) {
|
||||
deviceList.remove(device);
|
||||
}
|
||||
deviceList = getReferenceDeviceListFromZoneXGroupX(0, groupID);
|
||||
if (deviceList != null) {
|
||||
deviceList.remove(device);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDeviceToStructure(Device device) {
|
||||
putDeviceToHashMap(device);
|
||||
|
||||
addDevicetoZoneXGroupX(0, (short) 0, device);
|
||||
int zoneID = device.getZoneId();
|
||||
addDevicetoZoneXGroupX(zoneID, (short) 0, device);
|
||||
|
||||
for (Short groupID : device.getGroups()) {
|
||||
addDevicetoZoneXGroupX(zoneID, groupID, device);
|
||||
|
||||
if (groupID <= 16) {
|
||||
addDevicetoZoneXGroupX(0, groupID, device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addDevicetoZoneXGroupX(int zoneID, short groupID, Device device) {
|
||||
Map<Short, List<Device>> groupXHashMap = zoneGroupDeviceMap.get(zoneID);
|
||||
if (groupXHashMap == null) {
|
||||
groupXHashMap = new HashMap<>();
|
||||
zoneGroupDeviceMap.put(zoneID, groupXHashMap);
|
||||
}
|
||||
List<Device> groupDeviceList = groupXHashMap.get(groupID);
|
||||
if (groupDeviceList == null) {
|
||||
groupDeviceList = new LinkedList<>();
|
||||
groupDeviceList.add(device);
|
||||
groupXHashMap.put(groupID, groupDeviceList);
|
||||
} else {
|
||||
if (!groupDeviceList.contains(device)) {
|
||||
groupDeviceList.add(device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Integer> getZoneIDs() {
|
||||
return zoneGroupDeviceMap.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCircuitList(List<Circuit> referenceCircuitList) {
|
||||
for (Circuit circuit : referenceCircuitList) {
|
||||
addCircuit(circuit);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Circuit addCircuit(Circuit circuit) {
|
||||
addDSIDtoDSUID((AbstractGeneralDeviceInformations) circuit);
|
||||
return circuitMap.put(circuit.getDSID(), circuit);
|
||||
}
|
||||
|
||||
private void addDSIDtoDSUID(AbstractGeneralDeviceInformations deviceInfo) {
|
||||
if (deviceInfo.getDSID() != null) {
|
||||
dSUIDToDSIDMap.put(deviceInfo.getDSUID(), deviceInfo.getDSID());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Circuit getCircuitByDSID(DSID dSID) {
|
||||
return circuitMap.get(dSID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Circuit getCircuitByDSUID(String dSUID) {
|
||||
final DSID tmp = dSUIDToDSIDMap.get(dSUID);
|
||||
return tmp != null ? getCircuitByDSID(tmp) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Circuit getCircuitByDSID(String dSID) {
|
||||
return getCircuitByDSID(new DSID(dSID));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Circuit updateCircuitConfig(Circuit newCircuit) {
|
||||
Circuit intCircuit = circuitMap.get(newCircuit.getDSID());
|
||||
if (intCircuit != null && !intCircuit.equals(newCircuit)) {
|
||||
for (CachedMeteringValue meteringValue : intCircuit.getAllCachedMeteringValues()) {
|
||||
newCircuit.addMeteringValue(meteringValue);
|
||||
}
|
||||
if (intCircuit.isListenerRegisterd()) {
|
||||
newCircuit.registerDeviceStatusListener(intCircuit.getDeviceStatusListener());
|
||||
}
|
||||
}
|
||||
return addCircuit(newCircuit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Circuit deleteCircuit(DSID dSID) {
|
||||
return circuitMap.remove(dSID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Circuit deleteCircuit(String dSUID) {
|
||||
return deleteCircuit(dSUIDToDSIDMap.get(dSUID));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<DSID, Circuit> getCircuitMap() {
|
||||
return new HashMap<>(circuitMap);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,447 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.manager.impl;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.climate.TemperatureControlSensorTransmitter;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.climate.jsonresponsecontainer.impl.TemperatureControlStatus;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.event.EventHandler;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.event.EventListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.event.constants.EventNames;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.event.constants.EventResponseEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.event.types.EventItem;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.SystemStateChangeListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.TemperatureControlStatusListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.ConnectionManager;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.DsAPI;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.FuncNameAndColorGroupEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.SensorEnum;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link TemperatureControlManager} is responsible for handling the zone temperature control of the digitalSTROM
|
||||
* zones. For that it implements a {@link EventHandler} to get informed by control changes, like the target temperature.
|
||||
* It also implement the {@link TemperatureControlSensorTransmitter}, so the zone temperature can be set through this
|
||||
* class. <br>
|
||||
* <br>
|
||||
* To check, if the heating-control-app is installed at the digitalSTROM server the static method
|
||||
* {@link #isHeatingControllerInstallated(ConnectionManager)} can be used.<br>
|
||||
* <br>
|
||||
* To get informed by status changes tow listener types can be registered to the {@link TemperatureControlManager}:<br>
|
||||
* {@link TemperatureControlStatusListener}, to get informed by configuration and status changes or as discovery.<br>
|
||||
* {@link SystemStateChangeListener}, to get informed by heating water system changes. The heating system states are
|
||||
* {@link #STATE_HEATING_WATER_SYSTEM_OFF}, {@link #STATE_HEATING_WATER_SYSTEM_COLD_WATER} and
|
||||
* {@link #STATE_HEATING_WATER_SYSTEM_COLD_WATER}<br>
|
||||
* <br>
|
||||
* The {@link TemperatureControlManager} also contains some helpful static constants, like
|
||||
* {@link #GET_HEATING_WATER_SYSTEM_STATE_PATH} to get the current heating water system state through
|
||||
* {@link DsAPI#propertyTreeGetString(String, String)}.
|
||||
*
|
||||
* @author Michael Ochel - initial contributer
|
||||
* @author Matthias Siegele - initial contributer
|
||||
*/
|
||||
public class TemperatureControlManager implements EventHandler, TemperatureControlSensorTransmitter {
|
||||
|
||||
private final List<String> SUPPORTED_EVENTS = Arrays.asList(EventNames.HEATING_CONTROL_OPERATION_MODE);
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(TemperatureControlManager.class);
|
||||
|
||||
private final ConnectionManager connectionMananager;
|
||||
private final DsAPI dSapi;
|
||||
private final EventListener eventListener;
|
||||
private boolean isConfigured = false;
|
||||
|
||||
private HashMap<Integer, TemperatureControlStatusListener> zoneTemperationControlListenerMap;
|
||||
private HashMap<Integer, TemperatureControlStatus> temperationControlStatus;
|
||||
private TemperatureControlStatusListener discovery;
|
||||
private SystemStateChangeListener systemStateChangeListener;
|
||||
|
||||
/**
|
||||
* Name of the digitalSTROM heating water system state.
|
||||
*/
|
||||
public static final String STATE_NAME_HEATING_WATER_SYSTEM = "heating_water_system";
|
||||
/**
|
||||
* digitalSTROM heating water system state as string for off.
|
||||
*/
|
||||
public static final String STATE_HEATING_WATER_SYSTEM_OFF = "off"; // val=0
|
||||
/**
|
||||
* digitalSTROM heating water system state as string for hot water.
|
||||
*/
|
||||
public static final String STATE_HEATING_WATER_SYSTEM_HOT_WATER = "hot water"; // val=1
|
||||
/**
|
||||
* digitalSTROM heating water system state as string for cold water.
|
||||
*/
|
||||
public static final String STATE_HEATING_WATER_SYSTEM_COLD_WATER = "cold water"; // val=2
|
||||
|
||||
/**
|
||||
* Path to get the current digitalSTROM heating water system state through
|
||||
* {@link DsAPI#propertyTreeGetString(String, String)}.
|
||||
*/
|
||||
public static final String GET_HEATING_WATER_SYSTEM_STATE_PATH = "/usr/states/heating_water_system/state";
|
||||
/**
|
||||
* Path to get the current digitalSTROM heating controller nodes through
|
||||
* {@link DsAPI#propertyTreeGetString(String, String)}.
|
||||
* Can be used e.g. to check, if the digitalSTROM heating controller app is installed at the digitalSTROM server.
|
||||
*/
|
||||
public static final String GET_HEATING_HEATING_CONTROLLER_CHILDREN_PATH = "/scripts/heating-controller/";
|
||||
|
||||
/**
|
||||
* Action for set operation mode at {@link EventNames#HEATING_CONTROL_OPERATION_MODE}.
|
||||
*/
|
||||
public static final String SET_OPERATION_MODE = "setOperationMode";
|
||||
/**
|
||||
* Action for evaluate real active mode at {@link EventNames#HEATING_CONTROL_OPERATION_MODE}. Will be called after
|
||||
* {@link #SET_OPERATION_MODE} or if the configuration of a zone temperature control status has changed.
|
||||
*/
|
||||
public static final String EVALUATE_REAL_ACTIVE_MODE = "evaluateRealActiveMode";
|
||||
|
||||
private String currentHeatingWaterSystemStage;
|
||||
|
||||
private final List<String> echoBox = Collections.synchronizedList(new LinkedList<>());
|
||||
|
||||
/**
|
||||
* Creates a new {@link TemperatureControlManager}. The {@link ConnectionManager} is needed. The other fields are
|
||||
* only needed, if you want to get automatically informed by status changes through the {@link EventListener} and/or
|
||||
* get informed by new configured zones as discovery.
|
||||
*
|
||||
* @param connectionMananager (must not be null)
|
||||
* @param eventListener (can be null)
|
||||
* @param discovery (can be null)
|
||||
*/
|
||||
public TemperatureControlManager(ConnectionManager connectionMananager, EventListener eventListener,
|
||||
TemperatureControlStatusListener discovery) {
|
||||
this(connectionMananager, eventListener, discovery, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same constructor like
|
||||
* {@link #TemperatureControlManager(ConnectionManager, EventListener, TemperatureControlStatusListener)}, but it
|
||||
* can be set a {@link SystemStateChangeListener}, too.
|
||||
*
|
||||
* @param connectionMananager (must not be null)
|
||||
* @param eventListener (can be null)
|
||||
* @param discovery (can be null)
|
||||
* @param systemStateChangeListener (can be null)
|
||||
* @see #TemperatureControlManager(ConnectionManager, EventListener, TemperatureControlStatusListener)
|
||||
*/
|
||||
public TemperatureControlManager(ConnectionManager connectionMananager, EventListener eventListener,
|
||||
TemperatureControlStatusListener discovery, SystemStateChangeListener systemStateChangeListener) {
|
||||
this.connectionMananager = connectionMananager;
|
||||
this.dSapi = connectionMananager.getDigitalSTROMAPI();
|
||||
this.systemStateChangeListener = systemStateChangeListener;
|
||||
this.discovery = discovery;
|
||||
this.eventListener = eventListener;
|
||||
checkZones();
|
||||
if (eventListener != null) {
|
||||
if (isConfigured) {
|
||||
SUPPORTED_EVENTS.add(EventNames.ZONE_SENSOR_VALUE);
|
||||
if (systemStateChangeListener != null) {
|
||||
SUPPORTED_EVENTS.add(EventNames.STATE_CHANGED);
|
||||
}
|
||||
}
|
||||
eventListener.addEventHandler(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks all digitalSTROM zones, if temperature control is configured. If a zone with configured temperature
|
||||
* control is found, it will be stored, the flag for {@link #isConfigured()} will be set to true and the discovery
|
||||
* will be informed, if a discovery is registered.
|
||||
*/
|
||||
public void checkZones() {
|
||||
List<TemperatureControlStatus> temperationControlStatus = dSapi
|
||||
.getApartmentTemperatureControlStatus(connectionMananager.getSessionToken());
|
||||
if (!temperationControlStatus.isEmpty()) {
|
||||
for (TemperatureControlStatus tempConStat : temperationControlStatus) {
|
||||
addTemperatureControlStatus(tempConStat);
|
||||
}
|
||||
if (isConfigured && systemStateChangeListener != null) {
|
||||
currentHeatingWaterSystemStage = dSapi.propertyTreeGetString(connectionMananager.getSessionToken(),
|
||||
GET_HEATING_WATER_SYSTEM_STATE_PATH);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, if the digitalSTROM heating controller app is installed.
|
||||
*
|
||||
* @param connectionManager (must not be null)
|
||||
* @return true, if heating controller app is installed, otherwise false
|
||||
*/
|
||||
public static boolean isHeatingControllerInstallated(ConnectionManager connectionManager) {
|
||||
return connectionManager.getDigitalSTROMAPI().propertyTreeGetChildren(connectionManager.getSessionToken(),
|
||||
GET_HEATING_HEATING_CONTROLLER_CHILDREN_PATH) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all zone which have temperature controlled configured.
|
||||
*
|
||||
* @return all temperature controlled zones
|
||||
*/
|
||||
public Collection<TemperatureControlStatus> getTemperatureControlStatusFromAllZones() {
|
||||
return temperationControlStatus != null ? this.temperationControlStatus.values() : new LinkedList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a {@link TemperatureControlStatusListener} for a zone, if the temperation control for this zone is
|
||||
* configured. It can be also register a {@link TemperatureControlStatusListener} as discovery, if the
|
||||
* {@link TemperatureControlStatusListener#getTemperationControlStatusListenrID()} returns
|
||||
* {@link TemperatureControlStatusListener#DISCOVERY}.
|
||||
*
|
||||
* @param temperatureControlStatusListener to register
|
||||
*/
|
||||
public void registerTemperatureControlStatusListener(
|
||||
TemperatureControlStatusListener temperatureControlStatusListener) {
|
||||
if (temperatureControlStatusListener != null) {
|
||||
if (temperatureControlStatusListener.getTemperationControlStatusListenrID()
|
||||
.equals(TemperatureControlStatusListener.DISCOVERY)) {
|
||||
logger.debug("discovery is registered");
|
||||
this.discovery = temperatureControlStatusListener;
|
||||
if (temperationControlStatus != null) {
|
||||
for (TemperatureControlStatus tempConStat : temperationControlStatus.values()) {
|
||||
discovery.configChanged(tempConStat);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (zoneTemperationControlListenerMap == null) {
|
||||
zoneTemperationControlListenerMap = new HashMap<>();
|
||||
}
|
||||
TemperatureControlStatus tempConStat = checkAndGetTemperatureControlStatus(
|
||||
temperatureControlStatusListener.getTemperationControlStatusListenrID());
|
||||
if (tempConStat != null) {
|
||||
logger.debug("register listener with id {}",
|
||||
temperatureControlStatusListener.getTemperationControlStatusListenrID());
|
||||
zoneTemperationControlListenerMap.put(
|
||||
temperatureControlStatusListener.getTemperationControlStatusListenrID(),
|
||||
temperatureControlStatusListener);
|
||||
temperatureControlStatusListener.registerTemperatureSensorTransmitter(this);
|
||||
}
|
||||
temperatureControlStatusListener.configChanged(tempConStat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a {@link TemperatureControlStatusListener}, if it exist.
|
||||
*
|
||||
* @param temperatureControlStatusListener to unregister
|
||||
*/
|
||||
public void unregisterTemperatureControlStatusListener(
|
||||
TemperatureControlStatusListener temperatureControlStatusListener) {
|
||||
if (temperatureControlStatusListener != null) {
|
||||
if (temperatureControlStatusListener.getTemperationControlStatusListenrID()
|
||||
.equals(TemperatureControlStatusListener.DISCOVERY)) {
|
||||
this.discovery = null;
|
||||
return;
|
||||
}
|
||||
if (discovery != null && zoneTemperationControlListenerMap
|
||||
.remove(temperatureControlStatusListener.getTemperationControlStatusListenrID()) != null) {
|
||||
discovery.configChanged(temperationControlStatus
|
||||
.get(temperatureControlStatusListener.getTemperationControlStatusListenrID()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link TemperatureControlStatus} for the given zone, if the temperature control is configured,
|
||||
* otherwise it will be returned null.
|
||||
*
|
||||
* @param zoneID to check
|
||||
* @return {@link TemperatureControlStatus} if the temperature control is configured, otherwise null
|
||||
*/
|
||||
public TemperatureControlStatus checkAndGetTemperatureControlStatus(Integer zoneID) {
|
||||
TemperatureControlStatus tempConStat = this.temperationControlStatus.get(zoneID);
|
||||
if (tempConStat.isNotSetOff()) {
|
||||
return tempConStat;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isEcho(Integer zoneID, SensorEnum sensorType, Float value) {
|
||||
return echoBox.remove(zoneID + "-" + sensorType.getSensorType() + "-" + value);
|
||||
}
|
||||
|
||||
private void addEcho(Integer zoneID, SensorEnum sensorType, Float value) {
|
||||
echoBox.add(zoneID + "-" + sensorType.getSensorType() + "-" + value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEvent(EventItem eventItem) {
|
||||
logger.debug("detect event: {}", eventItem.toString());
|
||||
if (eventItem.getName().equals(EventNames.ZONE_SENSOR_VALUE)) {
|
||||
if (zoneTemperationControlListenerMap != null) {
|
||||
if (SensorEnum.ROOM_TEMPERATURE_SET_POINT.getSensorType().toString()
|
||||
.equals(eventItem.getProperties().get(EventResponseEnum.SENSOR_TYPE))) {
|
||||
Integer zoneID = Integer.parseInt(eventItem.getSource().get(EventResponseEnum.ZONEID));
|
||||
if (zoneTemperationControlListenerMap.get(zoneID) != null) {
|
||||
Float newValue = Float
|
||||
.parseFloat(eventItem.getProperties().get(EventResponseEnum.SENSOR_VALUE_FLOAT));
|
||||
if (!isEcho(zoneID, SensorEnum.ROOM_TEMPERATURE_CONTROL_VARIABLE, newValue)) {
|
||||
zoneTemperationControlListenerMap.get(zoneID).onTargetTemperatureChanged(newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (SensorEnum.ROOM_TEMPERATURE_CONTROL_VARIABLE.getSensorType().toString()
|
||||
.equals(eventItem.getProperties().get(EventResponseEnum.SENSOR_TYPE))) {
|
||||
Integer zoneID = Integer.parseInt(eventItem.getSource().get(EventResponseEnum.ZONEID));
|
||||
if (zoneTemperationControlListenerMap.get(zoneID) != null) {
|
||||
Float newValue = Float
|
||||
.parseFloat(eventItem.getProperties().get(EventResponseEnum.SENSOR_VALUE_FLOAT));
|
||||
if (!isEcho(zoneID, SensorEnum.ROOM_TEMPERATURE_CONTROL_VARIABLE, newValue)) {
|
||||
zoneTemperationControlListenerMap.get(zoneID).onControlValueChanged(newValue.intValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (eventItem.getName().equals(EventNames.HEATING_CONTROL_OPERATION_MODE)) {
|
||||
if (EVALUATE_REAL_ACTIVE_MODE.equals(eventItem.getProperties().get(EventResponseEnum.ACTIONS))) {
|
||||
Integer zoneID = Integer.parseInt(eventItem.getProperties().get(EventResponseEnum.ZONEID));
|
||||
TemperatureControlStatus temperationControlStatus = dSapi
|
||||
.getZoneTemperatureControlStatus(connectionMananager.getSessionToken(), zoneID, null);
|
||||
if (temperationControlStatus != null) {
|
||||
addTemperatureControlStatus(temperationControlStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (eventItem.getName().equals(EventNames.STATE_CHANGED)) {
|
||||
if (STATE_NAME_HEATING_WATER_SYSTEM.equals(eventItem.getProperties().get(EventResponseEnum.STATE_NAME))) {
|
||||
currentHeatingWaterSystemStage = eventItem.getProperties().get(EventResponseEnum.STATE);
|
||||
logger.debug("heating water system state changed to {}", currentHeatingWaterSystemStage);
|
||||
if (systemStateChangeListener != null) {
|
||||
systemStateChangeListener.onSystemStateChanged(STATE_NAME_HEATING_WATER_SYSTEM,
|
||||
currentHeatingWaterSystemStage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addTemperatureControlStatus(TemperatureControlStatus temperationControlStatus) {
|
||||
if (temperationControlStatus.isNotSetOff()) {
|
||||
if (this.temperationControlStatus == null) {
|
||||
this.temperationControlStatus = new HashMap<>();
|
||||
}
|
||||
if (this.temperationControlStatus.get(temperationControlStatus.getZoneID()) == null && discovery != null) {
|
||||
discovery.configChanged(temperationControlStatus);
|
||||
if (!isConfigured) {
|
||||
isConfigured = true;
|
||||
}
|
||||
}
|
||||
this.temperationControlStatus.put(temperationControlStatus.getZoneID(), temperationControlStatus);
|
||||
if (zoneTemperationControlListenerMap != null
|
||||
&& zoneTemperationControlListenerMap.get(temperationControlStatus.getZoneID()) != null) {
|
||||
zoneTemperationControlListenerMap.get(temperationControlStatus.getZoneID())
|
||||
.configChanged(temperationControlStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSupportedEvents() {
|
||||
return SUPPORTED_EVENTS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsEvent(String eventName) {
|
||||
return SUPPORTED_EVENTS.contains(eventName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUID() {
|
||||
return getClass().getSimpleName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEventListener(EventListener eventListener) {
|
||||
eventListener.addEventHandler(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsetEventListener(EventListener eventListener) {
|
||||
eventListener.removeEventHandler(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pushTargetTemperature(Integer zoneID, Float newValue) {
|
||||
if (checkAndGetTemperatureControlStatus(zoneID) != null) {
|
||||
if (dSapi.pushZoneSensorValue(connectionMananager.getSessionToken(), zoneID, null, (short) 0, null,
|
||||
newValue, SensorEnum.ROOM_TEMPERATURE_SET_POINT)) {
|
||||
addEcho(zoneID, SensorEnum.ROOM_TEMPERATURE_SET_POINT, newValue);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pushControlValue(Integer zoneID, Float newValue) {
|
||||
if (checkAndGetTemperatureControlStatus(zoneID) != null) {
|
||||
if (dSapi.pushZoneSensorValue(connectionMananager.getSessionToken(), zoneID, null,
|
||||
FuncNameAndColorGroupEnum.TEMPERATION_CONTROL.getFunctionalColorGroup(), null, newValue,
|
||||
SensorEnum.ROOM_TEMPERATURE_CONTROL_VARIABLE)) {
|
||||
addEcho(zoneID, SensorEnum.ROOM_TEMPERATURE_CONTROL_VARIABLE, newValue);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, if minimum one zone has temperature control configured.
|
||||
*
|
||||
* @return true, if minimum one zone has temperature control configured, otherwise false
|
||||
*/
|
||||
public boolean isConfigured() {
|
||||
return isConfigured;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current heating water system state, if a {@link SystemStateChangeListener} is registered, otherwise
|
||||
* null.
|
||||
*
|
||||
* @return the current heating water system state or null, if no {@link SystemStateChangeListener}
|
||||
*/
|
||||
public String getHeatingWaterSystemState() {
|
||||
return currentHeatingWaterSystemStage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given {@link SystemStateChangeListener}, which will be informed about heating system water state
|
||||
* changes.
|
||||
*
|
||||
* @param systemStateChangeListener to register
|
||||
*/
|
||||
public void registerSystemStateChangeListener(SystemStateChangeListener systemStateChangeListener) {
|
||||
if (eventListener != null) {
|
||||
SUPPORTED_EVENTS.add(EventNames.STATE_CHANGED);
|
||||
eventListener.addSubscribe(EventNames.STATE_CHANGED);
|
||||
}
|
||||
this.systemStateChangeListener = systemStateChangeListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a registered {@link SystemStateChangeListener}.
|
||||
*/
|
||||
public void unregisterSystemStateChangeListener() {
|
||||
this.systemStateChangeListener = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.sensorjobexecutor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.config.Config;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.ConnectionManager;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.sensorjobexecutor.sensorjob.SensorJob;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.DsAPI;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.Device;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.DSID;
|
||||
import org.openhab.core.common.ThreadPoolManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link AbstractSensorJobExecutor} provides the working process to execute implementations of {@link SensorJob}'s
|
||||
* in the time interval set at the {@link Config}.
|
||||
* <p>
|
||||
* The following methods can be overridden by subclasses to implement a execution priority:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>{@link #addLowPriorityJob(SensorJob)}</li>
|
||||
* <li>{@link #addMediumPriorityJob(SensorJob)}</li>
|
||||
* <li>{@link #addHighPriorityJob(SensorJob)}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractSensorJobExecutor {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(AbstractSensorJobExecutor.class);
|
||||
|
||||
private final ScheduledExecutorService scheduler = ThreadPoolManager.getScheduledPool(Config.THREADPOOL_NAME);
|
||||
private Map<DSID, ScheduledFuture<?>> pollingSchedulers;
|
||||
|
||||
private final DsAPI dSAPI;
|
||||
protected Config config;
|
||||
private final ConnectionManager connectionManager;
|
||||
|
||||
private final List<CircuitScheduler> circuitSchedulerList = new LinkedList<>();
|
||||
|
||||
private class ExecutorRunnable implements Runnable {
|
||||
private final CircuitScheduler circuit;
|
||||
|
||||
public ExecutorRunnable(CircuitScheduler circuit) {
|
||||
this.circuit = circuit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// pollingSchedulers is not final and might be set to null by another thread. See #8214
|
||||
Map<DSID, ScheduledFuture<?>> pollingSchedulers = AbstractSensorJobExecutor.this.pollingSchedulers;
|
||||
|
||||
SensorJob sensorJob = circuit.getNextSensorJob();
|
||||
DSID meter = circuit.getMeterDSID();
|
||||
|
||||
if (sensorJob != null) {
|
||||
sensorJob.execute(dSAPI, connectionManager.getSessionToken());
|
||||
}
|
||||
if (circuit.noMoreJobs() && pollingSchedulers != null) {
|
||||
logger.debug("no more jobs... stop circuit schedduler with id = {}", meter);
|
||||
ScheduledFuture<?> scheduler = pollingSchedulers.get(meter);
|
||||
if (scheduler != null) {
|
||||
scheduler.cancel(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link AbstractSensorJobExecutor}.
|
||||
*
|
||||
* @param connectionManager must not be null
|
||||
*/
|
||||
public AbstractSensorJobExecutor(ConnectionManager connectionManager) {
|
||||
this.connectionManager = connectionManager;
|
||||
config = connectionManager.getConfig();
|
||||
this.dSAPI = connectionManager.getDigitalSTROMAPI();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops all circuit schedulers.
|
||||
*/
|
||||
public synchronized void shutdown() {
|
||||
if (pollingSchedulers != null) {
|
||||
for (ScheduledFuture<?> scheduledExecutor : pollingSchedulers.values()) {
|
||||
scheduledExecutor.cancel(true);
|
||||
}
|
||||
pollingSchedulers = null;
|
||||
logger.debug("stop all circuit schedulers.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts all circuit schedulers.
|
||||
*/
|
||||
public synchronized void startExecutor() {
|
||||
logger.debug("start all circuit schedulers.");
|
||||
if (pollingSchedulers == null) {
|
||||
pollingSchedulers = new HashMap<>();
|
||||
}
|
||||
if (circuitSchedulerList != null && !circuitSchedulerList.isEmpty()) {
|
||||
for (CircuitScheduler circuit : circuitSchedulerList) {
|
||||
startSchedduler(circuit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void startSchedduler(CircuitScheduler circuit) {
|
||||
if (pollingSchedulers != null) {
|
||||
if (pollingSchedulers.get(circuit.getMeterDSID()) == null
|
||||
|| pollingSchedulers.get(circuit.getMeterDSID()).isCancelled()) {
|
||||
pollingSchedulers.put(circuit.getMeterDSID(),
|
||||
scheduler.scheduleWithFixedDelay(new ExecutorRunnable(circuit), circuit.getNextExecutionDelay(),
|
||||
config.getSensorReadingWaitTime(), TimeUnit.MILLISECONDS));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a high priority {@link SensorJob}.
|
||||
*
|
||||
* @param sensorJob to add
|
||||
*/
|
||||
public void addHighPriorityJob(SensorJob sensorJob) {
|
||||
// can be Overridden to implement a priority
|
||||
addSensorJobToCircuitScheduler(sensorJob);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a medium priority {@link SensorJob}.
|
||||
*
|
||||
* @param sensorJob to add
|
||||
*/
|
||||
public void addMediumPriorityJob(SensorJob sensorJob) {
|
||||
// can be overridden to implement a priority
|
||||
addSensorJobToCircuitScheduler(sensorJob);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a low priority {@link SensorJob}.
|
||||
*
|
||||
* @param sensorJob to add
|
||||
*/
|
||||
public void addLowPriorityJob(SensorJob sensorJob) {
|
||||
// can be overridden to implement a priority
|
||||
addSensorJobToCircuitScheduler(sensorJob);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link SensorJob} with a given priority .
|
||||
*
|
||||
* @param sensorJob to add
|
||||
* @param priority to update
|
||||
*/
|
||||
public void addPriorityJob(SensorJob sensorJob, long priority) {
|
||||
if (sensorJob == null) {
|
||||
return;
|
||||
}
|
||||
sensorJob.setInitalisationTime(priority);
|
||||
addSensorJobToCircuitScheduler(sensorJob);
|
||||
logger.debug("Add SensorJob from device with dSID {} and priority {} to AbstractJobExecutor",
|
||||
sensorJob.getDSID(), priority);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given {@link SensorJob}.
|
||||
*
|
||||
* @param sensorJob to add
|
||||
*/
|
||||
protected void addSensorJobToCircuitScheduler(SensorJob sensorJob) {
|
||||
synchronized (this.circuitSchedulerList) {
|
||||
CircuitScheduler circuit = getCircuitScheduler(sensorJob.getMeterDSID());
|
||||
if (circuit != null) {
|
||||
circuit.addSensorJob(sensorJob);
|
||||
} else {
|
||||
circuit = new CircuitScheduler(sensorJob, config);
|
||||
this.circuitSchedulerList.add(circuit);
|
||||
}
|
||||
startSchedduler(circuit);
|
||||
}
|
||||
}
|
||||
|
||||
private CircuitScheduler getCircuitScheduler(DSID dsid) {
|
||||
for (CircuitScheduler circuit : this.circuitSchedulerList) {
|
||||
if (circuit.getMeterDSID().equals(dsid)) {
|
||||
return circuit;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all SensorJobs of a specific {@link Device}.
|
||||
*
|
||||
* @param device to remove
|
||||
*/
|
||||
public void removeSensorJobs(Device device) {
|
||||
if (device != null) {
|
||||
CircuitScheduler circuit = getCircuitScheduler(device.getMeterDSID());
|
||||
if (circuit != null) {
|
||||
circuit.removeSensorJob(device.getDSID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the {@link SensorJob} with the given ID.
|
||||
*
|
||||
* @param device needed for the meterDSID
|
||||
* @param ID of the {@link SensorJob} to remove
|
||||
*/
|
||||
public void removeSensorJob(Device device, String ID) {
|
||||
if (device != null && ID != null) {
|
||||
CircuitScheduler circuit = getCircuitScheduler(device.getMeterDSID());
|
||||
if (circuit != null) {
|
||||
circuit.removeSensorJob(ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.sensorjobexecutor;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.PriorityQueue;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.config.Config;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.sensorjobexecutor.sensorjob.SensorJob;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.DSID;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This {@link CircuitScheduler} represents a circuit in the digitalSTROM-System and manages the priorities and
|
||||
* execution times for the {@link SensorJob}s on this circuit.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class CircuitScheduler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CircuitScheduler.class);
|
||||
|
||||
private class SensorJobComparator implements Comparator<SensorJob> {
|
||||
|
||||
@Override
|
||||
public int compare(SensorJob job1, SensorJob job2) {
|
||||
return ((Long) job1.getInitalisationTime()).compareTo(job2.getInitalisationTime());
|
||||
}
|
||||
}
|
||||
|
||||
private final DSID meterDSID;
|
||||
private long nextExecutionTime = System.currentTimeMillis();
|
||||
private final PriorityQueue<SensorJob> sensorJobQueue = new PriorityQueue<>(10, new SensorJobComparator());
|
||||
private final Config config;
|
||||
|
||||
/**
|
||||
* Creates a new {@link CircuitScheduler}.
|
||||
*
|
||||
* @param meterDSID must not be null
|
||||
* @param config must not be null
|
||||
* @throws IllegalArgumentException if the meterDSID is null
|
||||
*/
|
||||
public CircuitScheduler(DSID meterDSID, Config config) {
|
||||
if (meterDSID == null) {
|
||||
throw new IllegalArgumentException("The meterDSID must not be null!");
|
||||
}
|
||||
this.meterDSID = meterDSID;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link CircuitScheduler} and add the first {@link SensorJob} to this {@link CircuitScheduler}.
|
||||
*
|
||||
* @param sensorJob to add, must not be null
|
||||
* @param config must not be null
|
||||
*/
|
||||
public CircuitScheduler(SensorJob sensorJob, Config config) {
|
||||
this.meterDSID = sensorJob.getMeterDSID();
|
||||
this.sensorJobQueue.add(sensorJob);
|
||||
this.config = config;
|
||||
logger.debug("create circuitScheduler: {} and add sensorJob: {}", this.getMeterDSID(),
|
||||
sensorJob.getDSID().toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the meterDSID of the dS-Meter in which the {@link SensorJob}s will be executed.
|
||||
*
|
||||
* @return meterDSID
|
||||
*/
|
||||
public DSID getMeterDSID() {
|
||||
return this.meterDSID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new SensorJob to this {@link CircuitScheduler}, if no {@link SensorJob} with a higher priority exists.
|
||||
*
|
||||
* @param sensorJob to add
|
||||
*/
|
||||
public void addSensorJob(SensorJob sensorJob) {
|
||||
synchronized (sensorJobQueue) {
|
||||
if (!this.sensorJobQueue.contains(sensorJob)) {
|
||||
sensorJobQueue.add(sensorJob);
|
||||
logger.debug("Add sensorJob: {} to circuitScheduler: {}", sensorJob.toString(), this.getMeterDSID());
|
||||
} else if (checkSensorJobPrio(sensorJob)) {
|
||||
logger.debug("add sensorJob: {} with higher priority to circuitScheduler: {}", sensorJob.toString(),
|
||||
this.getMeterDSID());
|
||||
} else {
|
||||
logger.debug("sensorJob: {} allready exist with a higher priority", sensorJob.getDSID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkSensorJobPrio(SensorJob sensorJob) {
|
||||
synchronized (sensorJobQueue) {
|
||||
for (Iterator<SensorJob> iter = sensorJobQueue.iterator(); iter.hasNext();) {
|
||||
SensorJob existSensorJob = iter.next();
|
||||
if (existSensorJob.equals(sensorJob)) {
|
||||
if (sensorJob.getInitalisationTime() < existSensorJob.getInitalisationTime()) {
|
||||
iter.remove();
|
||||
sensorJobQueue.add(sensorJob);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next {@link SensorJob} which can be executed or null, if there are no more {@link SensorJob} to
|
||||
* execute or the wait time between the {@link SensorJob}s executions has not expired yet.
|
||||
*
|
||||
* @return next SensorJob or null
|
||||
*/
|
||||
public SensorJob getNextSensorJob() {
|
||||
synchronized (sensorJobQueue) {
|
||||
if (sensorJobQueue.peek() != null && this.nextExecutionTime <= System.currentTimeMillis()) {
|
||||
nextExecutionTime = System.currentTimeMillis() + config.getSensorReadingWaitTime();
|
||||
return sensorJobQueue.poll();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time when the next {@link SensorJob} can be executed.
|
||||
*
|
||||
* @return next SesnorJob execution time
|
||||
*/
|
||||
public Long getNextExecutionTime() {
|
||||
return this.nextExecutionTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the delay when the next {@link SensorJob} can be executed.
|
||||
*
|
||||
* @return next SesnorJob execution delay
|
||||
*/
|
||||
public Long getNextExecutionDelay() {
|
||||
long delay = this.nextExecutionTime - System.currentTimeMillis();
|
||||
return delay > 0 ? delay : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all {@link SensorJob} of a specific {@link Device} with the given {@link DSID}.
|
||||
*
|
||||
* @param dSID of the device
|
||||
*/
|
||||
public void removeSensorJob(DSID dSID) {
|
||||
synchronized (sensorJobQueue) {
|
||||
for (Iterator<SensorJob> iter = sensorJobQueue.iterator(); iter.hasNext();) {
|
||||
SensorJob job = iter.next();
|
||||
if (job.getDSID().equals(dSID)) {
|
||||
iter.remove();
|
||||
logger.debug("Remove SensorJob with ID {}.", job.getID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the {@link SensorJob} with the given ID .
|
||||
*
|
||||
* @param id of the {@link SensorJob}
|
||||
*/
|
||||
public void removeSensorJob(String id) {
|
||||
synchronized (sensorJobQueue) {
|
||||
for (Iterator<SensorJob> iter = sensorJobQueue.iterator(); iter.hasNext();) {
|
||||
SensorJob job = iter.next();
|
||||
if (job.getID().equals(id)) {
|
||||
iter.remove();
|
||||
logger.debug("Remove SensorJob with ID {}.", id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
logger.debug("No SensorJob with ID {} found, cannot remove a not existing SensorJob.", id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, if there are no more {@link SensorJob}s to execute, otherwise false.
|
||||
*
|
||||
* @return no more SensorJobs? (true | false)
|
||||
*/
|
||||
public boolean noMoreJobs() {
|
||||
synchronized (sensorJobQueue) {
|
||||
return this.sensorJobQueue.isEmpty();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.sensorjobexecutor;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.ConnectionManager;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.sensorjobexecutor.sensorjob.SensorJob;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link SceneReadingJobExecutor} is the implementation of the {@link AbstractSensorJobExecutor} to execute
|
||||
* digitalSTROM-Device scene configuration {@link SensorJob}'s e.g. {@link SceneConfigReadingJob} and
|
||||
* {@link SceneOutputValueReadingJob}.
|
||||
* <p>
|
||||
* In addition priorities can be assigned to jobs therefore the {@link SceneReadingJobExecutor} offers the methods
|
||||
* {@link #addHighPriorityJob(SensorJob)}, {@link #addMediumPriorityJob(SensorJob)} and
|
||||
* {@link #addLowPriorityJob(SensorJob)}.
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>NOTE:</b><br>
|
||||
* In contrast to the {@link SensorJobExecutor} the {@link SceneReadingJobExecutor} will execute {@link SensorJob}'s
|
||||
* with high priority always before medium priority {@link SensorJob}s and so on.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class SceneReadingJobExecutor extends AbstractSensorJobExecutor {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(SceneReadingJobExecutor.class);
|
||||
|
||||
/**
|
||||
* Creates a new {@link SceneReadingJobExecutor}.
|
||||
*
|
||||
* @param connectionManager must not be null
|
||||
*/
|
||||
public SceneReadingJobExecutor(ConnectionManager connectionManager) {
|
||||
super(connectionManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addHighPriorityJob(SensorJob sensorJob) {
|
||||
if (sensorJob == null) {
|
||||
return;
|
||||
}
|
||||
sensorJob.setInitalisationTime(0);
|
||||
addSensorJobToCircuitScheduler(sensorJob);
|
||||
logger.debug("Add SceneReadingJob from device with dSID {} and high-priority to SceneReadingSobExecutor",
|
||||
sensorJob.getDSID());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMediumPriorityJob(SensorJob sensorJob) {
|
||||
if (sensorJob == null) {
|
||||
return;
|
||||
}
|
||||
sensorJob.setInitalisationTime(1);
|
||||
addSensorJobToCircuitScheduler(sensorJob);
|
||||
logger.debug("Add SceneReadingJob from device with dSID {} and medium-priority to SceneReadingJobExecutor",
|
||||
sensorJob.getDSID());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLowPriorityJob(SensorJob sensorJob) {
|
||||
if (sensorJob == null) {
|
||||
return;
|
||||
}
|
||||
sensorJob.setInitalisationTime(2);
|
||||
addSensorJobToCircuitScheduler(sensorJob);
|
||||
logger.debug("Add SceneReadingJob from device with dSID {} and low-priority to SceneReadingJobExecutor",
|
||||
sensorJob.getDSID());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.sensorjobexecutor;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.ConnectionManager;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.sensorjobexecutor.sensorjob.SensorJob;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link SensorJobExecutor} is the implementation of the {@link AbstractSensorJobExecutor} to execute
|
||||
* digitalSTROM-Device {@link SensorJob}'s e.g. {@link DeviceConsumptionSensorJob} and
|
||||
* {@link DeviceOutputValueSensorJob}.
|
||||
* <p>
|
||||
* In addition priorities can be assigned to jobs, but the following list shows the maximum evaluation of a
|
||||
* {@link SensorJob} per priority.
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>low priority: read cycles before execution is set in {@link Config}</li>
|
||||
* <li>medium priority: read cycles before execution is set in {@link Config}</li>
|
||||
* <li>high priority: read cycles before execution 0</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class SensorJobExecutor extends AbstractSensorJobExecutor {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(SensorJobExecutor.class);
|
||||
|
||||
private final long mediumFactor = super.config.getSensorReadingWaitTime() * super.config.getMediumPriorityFactor();
|
||||
private final long lowFactor = super.config.getSensorReadingWaitTime() * super.config.getLowPriorityFactor();
|
||||
|
||||
/**
|
||||
* Creates a new {@link SensorJobExecutor}.
|
||||
*
|
||||
* @param connectionManager must not be null
|
||||
*/
|
||||
public SensorJobExecutor(ConnectionManager connectionManager) {
|
||||
super(connectionManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addHighPriorityJob(SensorJob sensorJob) {
|
||||
if (sensorJob == null) {
|
||||
return;
|
||||
}
|
||||
addSensorJobToCircuitScheduler(sensorJob);
|
||||
logger.debug("Add SensorJob from device with dSID {} and high-priority to SensorJobExecutor",
|
||||
sensorJob.getDSID());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMediumPriorityJob(SensorJob sensorJob) {
|
||||
if (sensorJob == null) {
|
||||
return;
|
||||
}
|
||||
sensorJob.setInitalisationTime(sensorJob.getInitalisationTime() + this.mediumFactor);
|
||||
addSensorJobToCircuitScheduler(sensorJob);
|
||||
logger.debug("Add SensorJob from device with dSID {} and medium-priority to SensorJobExecutor",
|
||||
sensorJob.getDSID());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLowPriorityJob(SensorJob sensorJob) {
|
||||
if (sensorJob == null) {
|
||||
return;
|
||||
}
|
||||
sensorJob.setInitalisationTime(sensorJob.getInitalisationTime() + this.lowFactor);
|
||||
addSensorJobToCircuitScheduler(sensorJob);
|
||||
logger.debug("Add SensorJob from device with dSID {} and low-priority to SensorJobExecutor",
|
||||
sensorJob.getDSID());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.sensorjobexecutor.sensorjob;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.DsAPI;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.DSID;
|
||||
|
||||
/**
|
||||
* The {@link SensorJob} represents an executable job to read out digitalSTROM-Sensors or device configurations like
|
||||
* scene values.<br>
|
||||
* It can be added to an implementation of the {@link AbstractSensorJobExecutor} e.g. {@link SceneReadingJobExecutor} or
|
||||
* {@link SensorJobExecutor}.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public interface SensorJob {
|
||||
|
||||
/**
|
||||
* Returns the dSID of the {@link Device} for which this job is to be created.
|
||||
*
|
||||
* @return dSID from the device
|
||||
*/
|
||||
DSID getDSID();
|
||||
|
||||
/**
|
||||
* Returns the dSID of the digitalSTROM-Meter on which this job is to be created.
|
||||
*
|
||||
* @return dSID from the device meter
|
||||
*/
|
||||
DSID getMeterDSID();
|
||||
|
||||
/**
|
||||
* Executes the SensorJob.
|
||||
*
|
||||
* @param dSAPI must not be null
|
||||
* @param sessionToken to login
|
||||
*/
|
||||
void execute(DsAPI dSAPI, String sessionToken);
|
||||
|
||||
/**
|
||||
* Returns the time when the {@link SensorJob} was initialized.
|
||||
*
|
||||
* @return the initialization time
|
||||
*/
|
||||
long getInitalisationTime();
|
||||
|
||||
/**
|
||||
* Sets the time when the {@link SensorJob} was initialized e.g. to manages the priority of this {@link SensorJob}.
|
||||
*
|
||||
* @param time to set
|
||||
*/
|
||||
void setInitalisationTime(long time);
|
||||
|
||||
/**
|
||||
* Returns the id of this {@link SensorJob}.
|
||||
*
|
||||
* @return id
|
||||
*/
|
||||
String getID();
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.sensorjobexecutor.sensorjob.impl;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.sensorjobexecutor.sensorjob.SensorJob;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.DsAPI;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.Device;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.SensorEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.DSID;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link DeviceConsumptionSensorJob} is the implementation of a {@link SensorJob}
|
||||
* for reading out the current value of the of a digitalSTROM-Device sensor and updates the {@link Device}.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class DeviceConsumptionSensorJob implements SensorJob {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(DeviceConsumptionSensorJob.class);
|
||||
private final Device device;
|
||||
private final SensorEnum sensorType;
|
||||
private final DSID meterDSID;
|
||||
private long initalisationTime = 0;
|
||||
private boolean updateDevice = true;
|
||||
|
||||
/**
|
||||
* Creates a new {@link DeviceConsumptionSensorJob}. Through updateDevice you can set, if the {@link Device} will be
|
||||
* updates automatically.
|
||||
*
|
||||
* @param device to update
|
||||
* @param type to update
|
||||
* @param updateDevice (true = automatically device, otherwise false)
|
||||
* @see #DeviceConsumptionSensorJob(Device, SensorEnum)
|
||||
*/
|
||||
public DeviceConsumptionSensorJob(Device device, SensorEnum type, boolean updateDevice) {
|
||||
this.device = device;
|
||||
this.sensorType = type;
|
||||
this.meterDSID = device.getMeterDSID();
|
||||
this.initalisationTime = System.currentTimeMillis();
|
||||
this.updateDevice = updateDevice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link DeviceConsumptionSensorJob} with the given {@link SensorEnum} for the given {@link Device}
|
||||
* and automatically {@link Device} update.
|
||||
*
|
||||
* @param device to update
|
||||
* @param type to update
|
||||
*/
|
||||
public DeviceConsumptionSensorJob(Device device, SensorEnum type) {
|
||||
this.device = device;
|
||||
this.sensorType = type;
|
||||
this.meterDSID = device.getMeterDSID();
|
||||
this.initalisationTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(DsAPI digitalSTROM, String token) {
|
||||
int consumption = digitalSTROM.getDeviceSensorValue(token, this.device.getDSID(), null, null,
|
||||
device.getSensorIndex(sensorType));
|
||||
logger.debug("Executes {} new device consumption is {}", this.toString(), consumption);
|
||||
if (updateDevice) {
|
||||
device.setDeviceSensorDsValueBySensorJob(sensorType, consumption);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof DeviceConsumptionSensorJob) {
|
||||
DeviceConsumptionSensorJob other = (DeviceConsumptionSensorJob) obj;
|
||||
String device = this.device.getDSID().getValue() + this.sensorType.getSensorType();
|
||||
return device.equals(other.device.getDSID().getValue() + other.sensorType.getSensorType());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new String(this.device.getDSID().getValue() + this.sensorType.getSensorType()).hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DSID getDSID() {
|
||||
return device.getDSID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DSID getMeterDSID() {
|
||||
return this.meterDSID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getInitalisationTime() {
|
||||
return this.initalisationTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInitalisationTime(long time) {
|
||||
this.initalisationTime = time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DeviceConsumptionSensorJob [sensorType=" + sensorType + ", sensorIndex="
|
||||
+ device.getSensorIndex(sensorType) + ", deviceDSID : " + device.getDSID().getValue() + ", meterDSID="
|
||||
+ meterDSID + ", initalisationTime=" + initalisationTime + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return getID(device, sensorType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the id for a {@link DeviceConsumptionSensorJob} with the given {@link Device} and {@link SensorEnum}.
|
||||
*
|
||||
* @param device to update
|
||||
* @param sensorType to update
|
||||
* @return id
|
||||
*/
|
||||
public static String getID(Device device, SensorEnum sensorType) {
|
||||
return DeviceConsumptionSensorJob.class.getSimpleName() + "-" + device.getDSID().getValue() + "-"
|
||||
+ sensorType.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.sensorjobexecutor.sensorjob.impl;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.sensorjobexecutor.sensorjob.SensorJob;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.DsAPI;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.Device;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.DeviceConstants;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.DeviceStateUpdate;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.DSID;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.DeviceStateUpdateImpl;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link DeviceOutputValueSensorJob} is the implementation of a {@link SensorJob}
|
||||
* for reading out the current device output value of a digitalSTROM-Device and update the {@link Device}.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class DeviceOutputValueSensorJob implements SensorJob {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(DeviceOutputValueSensorJob.class);
|
||||
private final Device device;
|
||||
private short index = 0;
|
||||
private final DSID meterDSID;
|
||||
private long initalisationTime = 0;
|
||||
|
||||
/**
|
||||
* Creates a new {@link DeviceOutputValueSensorJob} for the given {@link Device}.
|
||||
*
|
||||
* @param device to update
|
||||
*/
|
||||
public DeviceOutputValueSensorJob(Device device) {
|
||||
this.device = device;
|
||||
if (device.isShade()) {
|
||||
this.index = DeviceConstants.DEVICE_SENSOR_SLAT_POSITION_OUTPUT;
|
||||
} else {
|
||||
this.index = DeviceConstants.DEVICE_SENSOR_OUTPUT;
|
||||
}
|
||||
this.meterDSID = device.getMeterDSID();
|
||||
this.initalisationTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(DsAPI digitalSTROM, String token) {
|
||||
int value = digitalSTROM.getDeviceOutputValue(token, this.device.getDSID(), null, null, index);
|
||||
logger.debug("Device output value on Demand : {}, dSID: {}", value, this.device.getDSID().getValue());
|
||||
|
||||
if (value != 1) {
|
||||
switch (this.index) {
|
||||
case 0:
|
||||
this.device.updateInternalDeviceState(new DeviceStateUpdateImpl(DeviceStateUpdate.OUTPUT, value));
|
||||
return;
|
||||
case 2:
|
||||
this.device.updateInternalDeviceState(
|
||||
new DeviceStateUpdateImpl(DeviceStateUpdate.SLATPOSITION, value));
|
||||
if (device.isBlind()) {
|
||||
value = digitalSTROM.getDeviceOutputValue(token, this.device.getDSID(), null, null,
|
||||
DeviceConstants.DEVICE_SENSOR_SLAT_ANGLE_OUTPUT);
|
||||
logger.debug("Device angle output value on Demand : {}, dSID: {}", value,
|
||||
this.device.getDSID().getValue());
|
||||
if (value != 1) {
|
||||
this.device.updateInternalDeviceState(
|
||||
new DeviceStateUpdateImpl(DeviceStateUpdate.SLAT_ANGLE, value));
|
||||
}
|
||||
}
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof DeviceOutputValueSensorJob) {
|
||||
DeviceOutputValueSensorJob other = (DeviceOutputValueSensorJob) obj;
|
||||
String key = this.device.getDSID().getValue() + this.index;
|
||||
return key.equals((other.device.getDSID().getValue() + other.index));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new String(this.device.getDSID().getValue() + this.index).hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DSID getDSID() {
|
||||
return device.getDSID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DSID getMeterDSID() {
|
||||
return this.meterDSID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getInitalisationTime() {
|
||||
return this.initalisationTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInitalisationTime(long time) {
|
||||
this.initalisationTime = time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DeviceOutputValueSensorJob [deviceDSID : " + device.getDSID().getValue() + ", meterDSID=" + meterDSID
|
||||
+ ", initalisationTime=" + initalisationTime + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return getID(device);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the id for a {@link DeviceOutputValueSensorJob} with the given {@link Device}.
|
||||
*
|
||||
* @param device to update
|
||||
* @return id
|
||||
*/
|
||||
public static String getID(Device device) {
|
||||
return DeviceOutputValueSensorJob.class.getSimpleName() + "-" + device.getDSID().getValue();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.sensorjobexecutor.sensorjob.impl;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.sensorjobexecutor.sensorjob.SensorJob;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.DsAPI;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.Device;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.DeviceSceneSpec;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.DSID;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link SceneConfigReadingJob} is the implementation of a {@link SensorJob}
|
||||
* for reading out a scene output value of a digitalSTROM-Device and store it into the {@link Device}.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class SceneConfigReadingJob implements SensorJob {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(SceneConfigReadingJob.class);
|
||||
|
||||
private final Device device;
|
||||
private short sceneID = 0;
|
||||
private final DSID meterDSID;
|
||||
private long initalisationTime = 0;
|
||||
|
||||
/**
|
||||
* Creates a new {@link SceneConfigReadingJob} for the given {@link Device} and the given sceneID.
|
||||
*
|
||||
* @param device to update
|
||||
* @param sceneID to update
|
||||
*/
|
||||
public SceneConfigReadingJob(Device device, short sceneID) {
|
||||
this.device = device;
|
||||
this.sceneID = sceneID;
|
||||
this.meterDSID = device.getMeterDSID();
|
||||
this.initalisationTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(DsAPI digitalSTROM, String token) {
|
||||
DeviceSceneSpec sceneConfig = digitalSTROM.getDeviceSceneMode(token, device.getDSID(), null, null, sceneID);
|
||||
|
||||
if (sceneConfig != null) {
|
||||
device.addSceneConfig(sceneID, sceneConfig);
|
||||
logger.debug("UPDATED scene configuration for dSID: {}, sceneID: {}, configuration: {}",
|
||||
this.device.getDSID(), sceneID, sceneConfig);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof SceneConfigReadingJob) {
|
||||
SceneConfigReadingJob other = (SceneConfigReadingJob) obj;
|
||||
String str = other.device.getDSID().getValue() + "-" + other.sceneID;
|
||||
return (this.device.getDSID().getValue() + "-" + this.sceneID).equals(str);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new String(this.device.getDSID().getValue() + this.sceneID).hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DSID getDSID() {
|
||||
return device.getDSID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DSID getMeterDSID() {
|
||||
return this.meterDSID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getInitalisationTime() {
|
||||
return this.initalisationTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInitalisationTime(long time) {
|
||||
this.initalisationTime = time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SceneConfigReadingJob [sceneID: " + sceneID + ", deviceDSID : " + device.getDSID().getValue()
|
||||
+ ", meterDSID=" + meterDSID + ", initalisationTime=" + initalisationTime + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return getID(device, sceneID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the id for a {@link SceneConfigReadingJob} with the given {@link Device} and sceneID.
|
||||
*
|
||||
* @param device to update
|
||||
* @param sceneID to update
|
||||
* @return id
|
||||
*/
|
||||
public static String getID(Device device, Short sceneID) {
|
||||
return SceneConfigReadingJob.class.getSimpleName() + "-" + device.getDSID().getValue() + "-" + sceneID;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.sensorjobexecutor.sensorjob.impl;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.sensorjobexecutor.sensorjob.SensorJob;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.DsAPI;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.Device;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.DSID;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link SceneOutputValueReadingJob} is the implementation of a {@link SensorJob}
|
||||
* for reading out a scene configuration of a digitalSTROM-Device and store it into the {@link Device}.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class SceneOutputValueReadingJob implements SensorJob {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(SceneOutputValueReadingJob.class);
|
||||
|
||||
private final Device device;
|
||||
private short sceneID = 0;
|
||||
private final DSID meterDSID;
|
||||
private long initalisationTime = 0;
|
||||
|
||||
/**
|
||||
* Creates a new {@link SceneOutputValueReadingJob} for the given {@link Device} and the given sceneID.
|
||||
*
|
||||
* @param device to update
|
||||
* @param sceneID to update
|
||||
*/
|
||||
public SceneOutputValueReadingJob(Device device, short sceneID) {
|
||||
this.device = device;
|
||||
this.sceneID = sceneID;
|
||||
this.meterDSID = device.getMeterDSID();
|
||||
this.initalisationTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(DsAPI digitalSTROM, String token) {
|
||||
int[] sceneValue = digitalSTROM.getSceneValue(token, this.device.getDSID(), null, null, this.sceneID);
|
||||
|
||||
if (sceneValue[0] != -1) {
|
||||
if (device.isBlind()) {
|
||||
device.setSceneOutputValue(this.sceneID, sceneValue[0], sceneValue[1]);
|
||||
} else {
|
||||
device.setSceneOutputValue(this.sceneID, sceneValue[0]);
|
||||
}
|
||||
logger.debug("UPDATED sceneOutputValue for dsid: {}, sceneID: {}, value: {}, angle: {}",
|
||||
this.device.getDSID(), sceneID, sceneValue[0], sceneValue[1]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof SceneOutputValueReadingJob) {
|
||||
SceneOutputValueReadingJob other = (SceneOutputValueReadingJob) obj;
|
||||
String str = other.device.getDSID().getValue() + "-" + other.sceneID;
|
||||
return (this.device.getDSID().getValue() + "-" + this.sceneID).equals(str);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new String(this.device.getDSID().getValue() + this.sceneID).hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DSID getDSID() {
|
||||
return device.getDSID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DSID getMeterDSID() {
|
||||
return this.meterDSID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getInitalisationTime() {
|
||||
return this.initalisationTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInitalisationTime(long time) {
|
||||
this.initalisationTime = time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SceneOutputValueReadingJob [sceneID: " + sceneID + ", deviceDSID : " + device.getDSID().getValue()
|
||||
+ ", meterDSID=" + meterDSID + ", initalisationTime=" + initalisationTime + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return getID(device, sceneID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the id for a {@link SceneOutputValueReadingJob} with the given {@link Device} and sceneID.
|
||||
*
|
||||
* @param device to update
|
||||
* @param sceneID to update
|
||||
* @return id
|
||||
*/
|
||||
public static String getID(Device device, Short sceneID) {
|
||||
return DeviceOutputValueSensorJob.class.getSimpleName() + "-" + device.getDSID().getValue() + "-" + sceneID;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.serverconnection;
|
||||
|
||||
/**
|
||||
* The {@link HttpTransport} executes an request to the DigitalSTROM-Server.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public interface HttpTransport {
|
||||
|
||||
/**
|
||||
* Executes a digitalSTROM-request through calling {@link #execute(String, int, int)} with default connection time
|
||||
* out and read timeout.
|
||||
*
|
||||
* @param request to execute
|
||||
* @return response
|
||||
*/
|
||||
String execute(String request);
|
||||
|
||||
/**
|
||||
* Executes a digitalSTROM-request.
|
||||
*
|
||||
* @param request to execute
|
||||
* @param connectTimeout of execution
|
||||
* @param readTimeout of execution
|
||||
* @return response
|
||||
*/
|
||||
String execute(String request, int connectTimeout, int readTimeout);
|
||||
|
||||
/**
|
||||
* Executes a digitalSTROM test request and returns the HTTP-Code.
|
||||
*
|
||||
* @param testRequest to execute
|
||||
* @return HTTP-Code
|
||||
*/
|
||||
int checkConnection(String testRequest);
|
||||
|
||||
/**
|
||||
* Returns the connection timeout for sensor data readings.
|
||||
*
|
||||
* @return sensor data connection timeout
|
||||
*/
|
||||
int getSensordataConnectionTimeout();
|
||||
|
||||
/**
|
||||
* Returns the read timeout for sensor data readings.
|
||||
*
|
||||
* @return sensor data read timeout
|
||||
*/
|
||||
int getSensordataReadTimeout();
|
||||
|
||||
/**
|
||||
* Saves the SSL-Certificate in a file at the given path.
|
||||
*
|
||||
* @param path to save
|
||||
* @return absolute path
|
||||
*/
|
||||
String writePEMCertFile(String path);
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.serverconnection.constants;
|
||||
|
||||
/**
|
||||
* The {@link JSONApiResponseKeysEnum} contains digitalSTROM-JSON response keys.
|
||||
*
|
||||
* @author Alexander Betker - initial contributer
|
||||
* @author Michael Ochel completely changed and updated only methods remained
|
||||
* @author Matthias Siegele completely changed and updated only methods remained
|
||||
*/
|
||||
public enum JSONApiResponseKeysEnum {
|
||||
|
||||
// GENERAL
|
||||
OK("ok"),
|
||||
MESSAGE("message"),
|
||||
RESULT("result"),
|
||||
|
||||
// STRUCTURE
|
||||
APARTMENT("apartment"),
|
||||
DS_METERS("dSMeters"),
|
||||
ZONES("zones"),
|
||||
CIRCUITS("circuits"),
|
||||
DEVICES("devices"),
|
||||
GROUPS("groups"),
|
||||
REACHABLE_SCENES("reachableScenes"),
|
||||
|
||||
// SENSORS
|
||||
// device
|
||||
CONSUMPTION("consumption"),
|
||||
SENSOR_VALUE("sensorValue"),
|
||||
SENSOR_INDEX("sensorIndex"),
|
||||
METER_VALUE("meterValue"),
|
||||
TYPE("type"),
|
||||
|
||||
// meter sensors
|
||||
POWER_CONSUMPTION("powerConsumption"),
|
||||
ENERGY_METER_VALUE("energyMeterValue"),
|
||||
ENERGY_METER_VALUE_WS("energyMeterValueWs"),
|
||||
RESOLUTIONS("resolutions"),
|
||||
RESOLUTION("resolution"),
|
||||
SERIES("series"),
|
||||
UNIT("unit"),
|
||||
VALUES("values"),
|
||||
DATE("date"),
|
||||
|
||||
// zone/apartment sensors
|
||||
SENSOR_TYPE("sensorType"),
|
||||
TEMPERATION_VALUE("TemperatureValue"),
|
||||
TEMPERATION_VALUE_TIME("TemperatureValueTime"),
|
||||
HUMIDITY_VALUE("HumidityValue"),
|
||||
HUMIDITY_VALUE_TIME("HumidityValueTime"),
|
||||
BRIGHTNESS_VALUE("BrightnessValue"),
|
||||
BRIGHTNESS_VALUE_TIME("BrightnessValueTime"),
|
||||
CO2_CONCENTRATION_VALUE("CO2ConcentrationValue"),
|
||||
CO2_CONCENTRATION_VALUE_TIME("CO2ConcentrationValueTime"),
|
||||
SENSORS("sensors"),
|
||||
WEATHER_ICON_ID("WeatherIconId"),
|
||||
WEATHER_CONDITION_ID("WeatherConditionId"),
|
||||
WEATHER_SERVICE_ID("WeatherServiceId"),
|
||||
WEATHER_SERVICE_TIME("WeatherServiceTime"),
|
||||
|
||||
// IDs
|
||||
DSID("dSID"),
|
||||
DSUID("dSUID"),
|
||||
DSID_LOWER_CASE("dsid"),
|
||||
METER_DSID("meterDSID"),
|
||||
ZONE_ID("ZoneID"),
|
||||
ZONE_ID_Lower_Z("zoneID"),
|
||||
DSUID_LOWER_CASE("dsuid"),
|
||||
GROUP_ID("groupID"),
|
||||
METER_ID("meterID"),
|
||||
ID("id"),
|
||||
SCENE_ID("sceneID"),
|
||||
NAME("name"),
|
||||
DISPLAY_ID("DisplayID"),
|
||||
|
||||
// DEVICE
|
||||
// status
|
||||
IS_PRESENT("isPresent"),
|
||||
IS_VALID("isValid"),
|
||||
IS_ON("isOn"),
|
||||
PRESENT("present"),
|
||||
ON("on"),
|
||||
// descriptions
|
||||
FUNCTION_ID("functionID"),
|
||||
PRODUCT_REVISION("productRevision"),
|
||||
PRODUCT_ID("productID"),
|
||||
HW_INFO("hwInfo"),
|
||||
OUTPUT_MODE("outputMode"),
|
||||
BUTTON_ID("buttonID"),
|
||||
HAS_TAG("hasTag"),
|
||||
TAGS("tags"),
|
||||
REVISION_ID("revisionID"),
|
||||
|
||||
// config
|
||||
CLASS("class"),
|
||||
INDEX("index"),
|
||||
VALUE("value"),
|
||||
|
||||
DONT_CARE("dontCare"),
|
||||
LOCAL_PRIO("localPrio"),
|
||||
SPECIAL_MODE("specialMode"),
|
||||
FLASH_MODE("flashMode"),
|
||||
LEDCON_INDEX("ledconIndex"),
|
||||
DIM_TIME_INDEX("dimtimeIndex"),
|
||||
UP("up"),
|
||||
DOWN("down"),
|
||||
|
||||
// event table
|
||||
TEST("test"),
|
||||
ACTION("action"),
|
||||
HYSTERSIS("hysteresis"),
|
||||
VALIDITY("validity"),
|
||||
|
||||
// EVENTS
|
||||
EVENTS("events"),
|
||||
PROPERTIES("properties"),
|
||||
EVENT_INDEX("eventIndex"),
|
||||
EVENT_NAME("eventName"),
|
||||
|
||||
// SYSTEM & LOGIN
|
||||
VERSION("version"),
|
||||
TIME("time"),
|
||||
TOKEN("token"),
|
||||
APPLICATION_TOKEN("applicationToken"),
|
||||
|
||||
SELF("self"),
|
||||
|
||||
// CLIMATE
|
||||
IS_CONFIGURED("IsConfigured"),
|
||||
CONTROL_MODE("ControlMode"),
|
||||
CONTROL_STATE("ControlState"),
|
||||
CONTROL_DSUID("ControlDSUID"),
|
||||
OPERATION_MODE("OperationMode"),
|
||||
TEMPERATURE_VALUE("TemperatureValue"),
|
||||
NOMINAL_VALUE("NominalValue"),
|
||||
CONTROL_VALUE("ControlValue"),
|
||||
TEMPERATURE_VALUE_TIME("TemperatureValueTime"),
|
||||
NOMINAL_VALUE_TIME("NominalValueTime"),
|
||||
CONTROL_VALUE_TIME("ControlValueTime"),
|
||||
CTRL_T_RECENT("CtrlTRecent"),
|
||||
CTRL_T_REFERENCE("CtrlTReference"),
|
||||
CTRL_T_ERROR("CtrlTError"),
|
||||
CTRL_T_ERROR_PREV("CtrlTErrorPrev"),
|
||||
CTRL_INTEGRAL("CtrlIntegral"),
|
||||
CTRL_YP("CtrlYp"),
|
||||
CTRL_YI("CtrlYi"),
|
||||
CTRL_YD("CtrlYd"),
|
||||
CTRL_Y("CtrlY"),
|
||||
CTRL_ANTI_WIND_UP("CtrlAntiWindUp"),
|
||||
REFERENCE_ZONE("ReferenceZone"),
|
||||
CTRL_OFFSET("CtrlOffset"),
|
||||
EMERGENCY_VALUE("EmergencyValue"),
|
||||
CTRL_KP("CtrlKp"),
|
||||
CTRL_TS("CtrlTs"),
|
||||
CTRL_TI("CtrlTi"),
|
||||
CTRL_KD("CtrlKd"),
|
||||
CTRL_MIN("CtrlImin"),
|
||||
CTRL_MAX("CtrlImax"),
|
||||
CTRL_Y_MIN("CtrlYmin"),
|
||||
CTRL_Y_MAX("CtrlYmax"),
|
||||
CTRL_KEEP_FLOOR_WARM("CtrlKeepFloorWarm"),
|
||||
|
||||
// UNDEF
|
||||
COLOR_SELECT("colorSelect"),
|
||||
MODE_SELECT("modeSelect"),
|
||||
DIM_MODE("dimMode"),
|
||||
RGB_MODE("rgbMode"),
|
||||
GROUP_COLOR_MODE("groupColorMode"),
|
||||
SOURCE("source"),
|
||||
IS_SCENE_DEVICE("isSceneDevice"),
|
||||
|
||||
// Circuit
|
||||
HW_VERSION("hwVersion"),
|
||||
HW_VERSION_STRING("hwVersionString"),
|
||||
SW_VERSION("swVersion"),
|
||||
ARM_SW_VERSION("armSwVersion"),
|
||||
DSP_SW_VERSION("dspSwVersion"),
|
||||
API_VERSION("apiVersion"),
|
||||
HW_NAME("hwName"),
|
||||
BUS_MEMBER_TYPE("busMemberType"),
|
||||
HAS_DEVICES("hasDevices"),
|
||||
HAS_METERING("hasMetering"),
|
||||
VDC_CONFIG_URL("VdcConfigURL"),
|
||||
VDC_MODEL_UID("VdcModelUID"),
|
||||
VDC_HARDWARE_GUID("VdcHardwareGuid"),
|
||||
VDC_HARDWARE_MODEL_GUID("VdcHardwareModelGuid"),
|
||||
VDC_VENDOR_GUID("VdcVendorGuid"),
|
||||
VDC_OEM_GUID("VdcOemGuid"),
|
||||
IGNORE_ACTIONS_FROM_NEW_DEVICES("ignoreActionsFromNewDevices"),
|
||||
|
||||
DS_METER_DSID("DSMeterDSID"),
|
||||
HW_INFO_UPPER_HW("HWInfo"),
|
||||
VALID("valid"),
|
||||
VALUE_DS("valueDS"),
|
||||
TIMESTAMP("timestamp"),
|
||||
SENSOR_INPUTS("sensorInputs"),
|
||||
GROUP("group"),
|
||||
LAST_CALL_SCENE("lastCalledScene"),
|
||||
ANGLE("angle"),
|
||||
|
||||
// Binary inputs
|
||||
BINARY_INPUTS("binaryInputs"),
|
||||
STATE("state"),
|
||||
STATE_VALUE("stateValue"),
|
||||
TARGET_GROUP_TYPE("targetGroupType"),
|
||||
TARGET_GROUP("targetGroup"),
|
||||
INPUT_TYPE("inputType"),
|
||||
INPUT_ID("inputId");
|
||||
|
||||
private final String key;
|
||||
|
||||
private JSONApiResponseKeysEnum(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key.
|
||||
*
|
||||
* @return key
|
||||
*/
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,605 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.serverconnection.impl;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.URL;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.Security;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Base64;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.config.Config;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.manager.ConnectionManager;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.HttpTransport;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.simpledsrequestbuilder.constants.ParameterKeys;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link HttpTransportImpl} executes an request to the digitalSTROM-Server.
|
||||
* <p>
|
||||
* If a {@link Config} is given at the constructor. It sets the SSL-Certificate what is set in
|
||||
* {@link Config#getCert()}. If there is no SSL-Certificate, but an path to an external SSL-Certificate file what is set
|
||||
* in {@link Config#getTrustCertPath()} this will be set. If no SSL-Certificate is set in the {@link Config} it will be
|
||||
* red out from the server and set in {@link Config#setCert(String)}.
|
||||
*
|
||||
* <p>
|
||||
* If no {@link Config} is given the SSL-Certificate will be stored locally.
|
||||
*
|
||||
* <p>
|
||||
* The method {@link #writePEMCertFile(String)} saves the SSL-Certificate in a file at the given path. If all
|
||||
* SSL-Certificates shout be ignored the flag <i>exeptAllCerts</i> have to be true at the constructor
|
||||
* </p>
|
||||
* <p>
|
||||
* If a {@link ConnectionManager} is given at the constructor, the session-token is not needed by requests and the
|
||||
* {@link ConnectionListener}, which is registered at the {@link ConnectionManager}, will be automatically informed
|
||||
* about
|
||||
* connection state changes through the {@link #execute(String, int, int)} method.
|
||||
* </p>
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public class HttpTransportImpl implements HttpTransport {
|
||||
|
||||
private static final String LINE_SEPERATOR = System.getProperty("line.separator");
|
||||
private static final String BEGIN_CERT = "-----BEGIN CERTIFICATE-----" + LINE_SEPERATOR;
|
||||
private static final String END_CERT = LINE_SEPERATOR + "-----END CERTIFICATE-----" + LINE_SEPERATOR;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(HttpTransportImpl.class);
|
||||
private static final short MAY_A_NEW_SESSION_TOKEN_IS_NEEDED = 1;
|
||||
|
||||
private String uri;
|
||||
|
||||
private int connectTimeout;
|
||||
private int readTimeout;
|
||||
|
||||
private Config config;
|
||||
|
||||
private ConnectionManager connectionManager;
|
||||
|
||||
private String cert;
|
||||
private SSLSocketFactory sslSocketFactory;
|
||||
private final HostnameVerifier hostnameVerifier = new HostnameVerifier() {
|
||||
|
||||
@Override
|
||||
public boolean verify(String arg0, SSLSession arg1) {
|
||||
return arg0.equals(arg1.getPeerHost()) || arg0.contains("dss.local.");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new {@link HttpTransportImpl} with registration of the given {@link ConnectionManager} and set ignore
|
||||
* all SSL-Certificates. The {@link Config} will be automatically added from the configurations of the given
|
||||
* {@link ConnectionManager}.
|
||||
*
|
||||
* @param connectionManager to check connection, can be null
|
||||
* @param exeptAllCerts (true = all will ignore)
|
||||
*/
|
||||
public HttpTransportImpl(ConnectionManager connectionManager, boolean exeptAllCerts) {
|
||||
this.connectionManager = connectionManager;
|
||||
this.config = connectionManager.getConfig();
|
||||
init(config.getHost(), config.getConnectionTimeout(), config.getReadTimeout(), exeptAllCerts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link HttpTransportImpl} with configurations of the given {@link Config} and set ignore all
|
||||
* SSL-Certificates.
|
||||
*
|
||||
* @param config to get configurations, must not be null
|
||||
* @param exeptAllCerts (true = all will ignore)
|
||||
*/
|
||||
public HttpTransportImpl(Config config, boolean exeptAllCerts) {
|
||||
this.config = config;
|
||||
init(config.getHost(), config.getConnectionTimeout(), config.getReadTimeout(), exeptAllCerts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link HttpTransportImpl} with configurations of the given {@link Config}.
|
||||
*
|
||||
* @param config to get configurations, must not be null
|
||||
*/
|
||||
public HttpTransportImpl(Config config) {
|
||||
this.config = config;
|
||||
init(config.getHost(), config.getConnectionTimeout(), config.getReadTimeout(), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link HttpTransportImpl}.
|
||||
*
|
||||
* @param uri of the server, must not be null
|
||||
*/
|
||||
public HttpTransportImpl(String uri) {
|
||||
init(uri, Config.DEFAULT_CONNECTION_TIMEOUT, Config.DEFAULT_READ_TIMEOUT, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link HttpTransportImpl} and set ignore all SSL-Certificates.
|
||||
*
|
||||
* @param uri of the server, must not be null
|
||||
* @param exeptAllCerts (true = all will ignore)
|
||||
*/
|
||||
public HttpTransportImpl(String uri, boolean exeptAllCerts) {
|
||||
init(uri, Config.DEFAULT_CONNECTION_TIMEOUT, Config.DEFAULT_READ_TIMEOUT, exeptAllCerts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link HttpTransportImpl}.
|
||||
*
|
||||
* @param uri of the server, must not be null
|
||||
* @param connectTimeout to set
|
||||
* @param readTimeout to set
|
||||
*/
|
||||
public HttpTransportImpl(String uri, int connectTimeout, int readTimeout) {
|
||||
init(uri, connectTimeout, readTimeout, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link HttpTransportImpl} and set ignore all SSL-Certificates..
|
||||
*
|
||||
* @param uri of the server, must not be null
|
||||
* @param connectTimeout to set
|
||||
* @param readTimeout to set
|
||||
* @param exeptAllCerts (true = all will ignore)
|
||||
*/
|
||||
public HttpTransportImpl(String uri, int connectTimeout, int readTimeout, boolean exeptAllCerts) {
|
||||
init(uri, connectTimeout, readTimeout, exeptAllCerts);
|
||||
}
|
||||
|
||||
private void init(String uri, int connectTimeout, int readTimeout, boolean exeptAllCerts) {
|
||||
logger.debug("init HttpTransportImpl");
|
||||
this.uri = fixURI(uri);
|
||||
this.connectTimeout = connectTimeout;
|
||||
this.readTimeout = readTimeout;
|
||||
// Check SSL Certificate
|
||||
if (exeptAllCerts) {
|
||||
sslSocketFactory = generateSSLContextWhichAcceptAllSSLCertificats();
|
||||
} else {
|
||||
if (config != null) {
|
||||
cert = config.getCert();
|
||||
logger.debug("generate SSLcontext from config cert");
|
||||
if (StringUtils.isNotBlank(cert)) {
|
||||
sslSocketFactory = generateSSLContextFromPEMCertString(cert);
|
||||
} else {
|
||||
if (StringUtils.isNotBlank(config.getTrustCertPath())) {
|
||||
logger.debug("generate SSLcontext from config cert path");
|
||||
cert = readPEMCertificateStringFromFile(config.getTrustCertPath());
|
||||
if (StringUtils.isNotBlank(cert)) {
|
||||
sslSocketFactory = generateSSLContextFromPEMCertString(cert);
|
||||
}
|
||||
} else {
|
||||
logger.debug("generate SSLcontext from server");
|
||||
cert = getPEMCertificateFromServer(this.uri);
|
||||
sslSocketFactory = generateSSLContextFromPEMCertString(cert);
|
||||
if (sslSocketFactory != null) {
|
||||
config.setCert(cert);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.debug("generate SSLcontext from server");
|
||||
cert = getPEMCertificateFromServer(this.uri);
|
||||
sslSocketFactory = generateSSLContextFromPEMCertString(cert);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String fixURI(String uri) {
|
||||
String fixedURI = uri;
|
||||
if (!fixedURI.startsWith("https://")) {
|
||||
fixedURI = "https://" + fixedURI;
|
||||
}
|
||||
if (fixedURI.split(":").length != 3) {
|
||||
fixedURI = fixedURI + ":8080";
|
||||
}
|
||||
return fixedURI;
|
||||
}
|
||||
|
||||
private String fixRequest(String request) {
|
||||
return request.replace(" ", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String execute(String request) {
|
||||
return execute(request, this.connectTimeout, this.readTimeout);
|
||||
}
|
||||
|
||||
private short loginCounter = 0;
|
||||
|
||||
@Override
|
||||
public String execute(String request, int connectTimeout, int readTimeout) {
|
||||
// NOTE: We will only show exceptions in the debug level, because they will be handled in the checkConnection()
|
||||
// method and this changes the bridge state. If a command was send it fails than and a sensorJob will be
|
||||
// execute the next time, by TimeOutExceptions. By other exceptions the checkConnection() method handles it in
|
||||
// max 1 second.
|
||||
String response = null;
|
||||
HttpsURLConnection connection = null;
|
||||
try {
|
||||
String correctedRequest = checkSessionToken(request);
|
||||
connection = getConnection(correctedRequest, connectTimeout, readTimeout);
|
||||
if (connection != null) {
|
||||
connection.connect();
|
||||
final int responseCode = connection.getResponseCode();
|
||||
if (responseCode != HttpURLConnection.HTTP_FORBIDDEN) {
|
||||
if (responseCode == HttpURLConnection.HTTP_INTERNAL_ERROR) {
|
||||
response = IOUtils.toString(connection.getErrorStream());
|
||||
} else {
|
||||
response = IOUtils.toString(connection.getInputStream());
|
||||
}
|
||||
if (response != null) {
|
||||
if (!response.contains("Authentication failed")) {
|
||||
if (loginCounter > 0) {
|
||||
connectionManager.checkConnection(responseCode);
|
||||
}
|
||||
loginCounter = 0;
|
||||
} else {
|
||||
connectionManager.checkConnection(ConnectionManager.AUTHENTIFICATION_PROBLEM);
|
||||
loginCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
connection.disconnect();
|
||||
if (response == null && connectionManager != null
|
||||
&& loginCounter <= MAY_A_NEW_SESSION_TOKEN_IS_NEEDED) {
|
||||
if (responseCode == HttpURLConnection.HTTP_FORBIDDEN) {
|
||||
execute(addSessionToken(correctedRequest, connectionManager.getNewSessionToken()),
|
||||
connectTimeout, readTimeout);
|
||||
loginCounter++;
|
||||
} else {
|
||||
connectionManager.checkConnection(responseCode);
|
||||
loginCounter++;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
} catch (SocketTimeoutException e) {
|
||||
informConnectionManager(ConnectionManager.SOCKET_TIMEOUT_EXCEPTION);
|
||||
} catch (java.net.ConnectException e) {
|
||||
informConnectionManager(ConnectionManager.CONNECTION_EXCEPTION);
|
||||
} catch (MalformedURLException e) {
|
||||
informConnectionManager(ConnectionManager.MALFORMED_URL_EXCEPTION);
|
||||
} catch (java.net.UnknownHostException e) {
|
||||
informConnectionManager(ConnectionManager.UNKNOWN_HOST_EXCEPTION);
|
||||
} catch (SSLHandshakeException e) {
|
||||
informConnectionManager(ConnectionManager.SSL_HANDSHAKE_EXCEPTION);
|
||||
} catch (IOException e) {
|
||||
logger.error("An IOException occurred: ", e);
|
||||
informConnectionManager(ConnectionManager.GENERAL_EXCEPTION);
|
||||
} finally {
|
||||
if (connection != null) {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean informConnectionManager(int code) {
|
||||
if (connectionManager != null && loginCounter < MAY_A_NEW_SESSION_TOKEN_IS_NEEDED) {
|
||||
connectionManager.checkConnection(code);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private String checkSessionToken(String request) {
|
||||
if (checkNeededSessionToken(request)) {
|
||||
if (connectionManager != null) {
|
||||
String sessionToken = connectionManager.getSessionToken();
|
||||
if (sessionToken == null) {
|
||||
return addSessionToken(request, connectionManager.getNewSessionToken());
|
||||
}
|
||||
return addSessionToken(request, sessionToken);
|
||||
}
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
private boolean checkNeededSessionToken(String request) {
|
||||
String functionName = StringUtils.substringAfterLast(StringUtils.substringBefore(request, "?"), "/");
|
||||
return !DsAPIImpl.METHODS_MUST_NOT_BE_LOGGED_IN.contains(functionName);
|
||||
}
|
||||
|
||||
private String addSessionToken(String request, String sessionToken) {
|
||||
String correctedRequest = request;
|
||||
if (!correctedRequest.contains(ParameterKeys.TOKEN)) {
|
||||
if (correctedRequest.contains("?")) {
|
||||
correctedRequest = correctedRequest + "&" + ParameterKeys.TOKEN + "=" + sessionToken;
|
||||
} else {
|
||||
correctedRequest = correctedRequest + "?" + ParameterKeys.TOKEN + "=" + sessionToken;
|
||||
}
|
||||
} else {
|
||||
correctedRequest = StringUtils.replaceOnce(correctedRequest, StringUtils.substringBefore(
|
||||
StringUtils.substringAfter(correctedRequest, ParameterKeys.TOKEN + "="), "&"), sessionToken);
|
||||
|
||||
}
|
||||
return correctedRequest;
|
||||
}
|
||||
|
||||
private HttpsURLConnection getConnection(String request, int connectTimeout, int readTimeout) throws IOException {
|
||||
String correctedRequest = request;
|
||||
if (StringUtils.isNotBlank(correctedRequest)) {
|
||||
correctedRequest = fixRequest(correctedRequest);
|
||||
URL url = new URL(this.uri + correctedRequest);
|
||||
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
|
||||
if (connection != null) {
|
||||
connection.setConnectTimeout(connectTimeout);
|
||||
connection.setReadTimeout(readTimeout);
|
||||
if (sslSocketFactory != null) {
|
||||
connection.setSSLSocketFactory(sslSocketFactory);
|
||||
}
|
||||
if (hostnameVerifier != null) {
|
||||
connection.setHostnameVerifier(hostnameVerifier);
|
||||
}
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int checkConnection(String testRequest) {
|
||||
try {
|
||||
HttpsURLConnection connection = getConnection(testRequest, connectTimeout, readTimeout);
|
||||
if (connection != null) {
|
||||
connection.connect();
|
||||
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
if (IOUtils.toString(connection.getInputStream()).contains("Authentication failed")) {
|
||||
return ConnectionManager.AUTHENTIFICATION_PROBLEM;
|
||||
}
|
||||
}
|
||||
connection.disconnect();
|
||||
return connection.getResponseCode();
|
||||
} else {
|
||||
return ConnectionManager.GENERAL_EXCEPTION;
|
||||
}
|
||||
} catch (SocketTimeoutException e) {
|
||||
return ConnectionManager.SOCKET_TIMEOUT_EXCEPTION;
|
||||
} catch (java.net.ConnectException e) {
|
||||
return ConnectionManager.CONNECTION_EXCEPTION;
|
||||
} catch (MalformedURLException e) {
|
||||
return ConnectionManager.MALFORMED_URL_EXCEPTION;
|
||||
} catch (java.net.UnknownHostException e) {
|
||||
return ConnectionManager.UNKNOWN_HOST_EXCEPTION;
|
||||
} catch (IOException e) {
|
||||
return ConnectionManager.GENERAL_EXCEPTION;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSensordataConnectionTimeout() {
|
||||
return config != null ? config.getSensordataConnectionTimeout() : Config.DEFAULT_SENSORDATA_CONNECTION_TIMEOUT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSensordataReadTimeout() {
|
||||
return config != null ? config.getSensordataReadTimeout() : Config.DEFAULT_SENSORDATA_READ_TIMEOUT;
|
||||
}
|
||||
|
||||
private String readPEMCertificateStringFromFile(String path) {
|
||||
if (StringUtils.isBlank(path)) {
|
||||
logger.error("Path is empty.");
|
||||
} else {
|
||||
File dssCert = new File(path);
|
||||
if (dssCert.exists()) {
|
||||
if (path.endsWith(".crt")) {
|
||||
try {
|
||||
InputStream certInputStream = new FileInputStream(dssCert);
|
||||
String cert = IOUtils.toString(certInputStream);
|
||||
if (cert.startsWith(BEGIN_CERT)) {
|
||||
return cert;
|
||||
} else {
|
||||
logger.error("File is not a PEM certificate file. PEM-Certificats starts with: {}",
|
||||
BEGIN_CERT);
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
logger.error("Can't find a certificate file at the path: {}\nPlease check the path!", path);
|
||||
} catch (IOException e) {
|
||||
logger.error("An IOException occurred: ", e);
|
||||
}
|
||||
} else {
|
||||
logger.error("File is not a certificate (.crt) file.");
|
||||
}
|
||||
} else {
|
||||
logger.error("File not found");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String writePEMCertFile(String path) {
|
||||
String correctedPath = StringUtils.trimToEmpty(path);
|
||||
File certFilePath;
|
||||
if (StringUtils.isNotBlank(correctedPath)) {
|
||||
certFilePath = new File(correctedPath);
|
||||
boolean pathExists = certFilePath.exists();
|
||||
if (!pathExists) {
|
||||
pathExists = certFilePath.mkdirs();
|
||||
}
|
||||
if (pathExists && !correctedPath.endsWith("/")) {
|
||||
correctedPath = correctedPath + "/";
|
||||
}
|
||||
}
|
||||
InputStream certInputStream = IOUtils.toInputStream(cert);
|
||||
X509Certificate trustedCert;
|
||||
try {
|
||||
trustedCert = (X509Certificate) CertificateFactory.getInstance("X.509")
|
||||
.generateCertificate(certInputStream);
|
||||
|
||||
certFilePath = new File(
|
||||
correctedPath + trustedCert.getSubjectDN().getName().split(",")[0].substring(2) + ".crt");
|
||||
if (!certFilePath.exists()) {
|
||||
certFilePath.createNewFile();
|
||||
FileWriter writer = new FileWriter(certFilePath, true);
|
||||
writer.write(cert);
|
||||
writer.flush();
|
||||
writer.close();
|
||||
return certFilePath.getAbsolutePath();
|
||||
} else {
|
||||
logger.error("File allready exists!");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.error("An IOException occurred: ", e);
|
||||
} catch (CertificateException e1) {
|
||||
logger.error("A CertificateException occurred: ", e1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private SSLSocketFactory generateSSLContextFromPEMCertString(String pemCert) {
|
||||
if (StringUtils.isNotBlank(pemCert) && pemCert.startsWith(BEGIN_CERT)) {
|
||||
try {
|
||||
InputStream certInputStream = IOUtils.toInputStream(pemCert);
|
||||
final X509Certificate trustedCert = (X509Certificate) CertificateFactory.getInstance("X.509")
|
||||
.generateCertificate(certInputStream);
|
||||
|
||||
final TrustManager[] trustManager = new TrustManager[] { new X509TrustManager() {
|
||||
|
||||
@Override
|
||||
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
|
||||
throws CertificateException {
|
||||
if (!certs[0].equals(trustedCert)) {
|
||||
throw new CertificateException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
|
||||
throws CertificateException {
|
||||
if (!certs[0].equals(trustedCert)) {
|
||||
throw new CertificateException();
|
||||
}
|
||||
}
|
||||
} };
|
||||
|
||||
SSLContext sslContext = SSLContext.getInstance("SSL");
|
||||
sslContext.init(null, trustManager, new java.security.SecureRandom());
|
||||
return sslContext.getSocketFactory();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
logger.error("A NoSuchAlgorithmException occurred: ", e);
|
||||
} catch (KeyManagementException e) {
|
||||
logger.error("A KeyManagementException occurred: ", e);
|
||||
} catch (CertificateException e) {
|
||||
logger.error("A CertificateException occurred: ", e);
|
||||
}
|
||||
} else {
|
||||
logger.error("Cert is empty");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getPEMCertificateFromServer(String host) {
|
||||
HttpsURLConnection connection = null;
|
||||
try {
|
||||
URL url = new URL(host);
|
||||
|
||||
connection = (HttpsURLConnection) url.openConnection();
|
||||
connection.setHostnameVerifier(hostnameVerifier);
|
||||
connection.setSSLSocketFactory(generateSSLContextWhichAcceptAllSSLCertificats());
|
||||
connection.connect();
|
||||
|
||||
java.security.cert.Certificate[] cert = connection.getServerCertificates();
|
||||
connection.disconnect();
|
||||
|
||||
byte[] by = ((X509Certificate) cert[0]).getEncoded();
|
||||
if (by.length != 0) {
|
||||
return BEGIN_CERT + Base64.getEncoder().encodeToString(by) + END_CERT;
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
if (!informConnectionManager(ConnectionManager.MALFORMED_URL_EXCEPTION)) {
|
||||
logger.error("A MalformedURLException occurred: ", e);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
short code = ConnectionManager.GENERAL_EXCEPTION;
|
||||
if (e instanceof java.net.ConnectException) {
|
||||
code = ConnectionManager.CONNECTION_EXCEPTION;
|
||||
} else if (e instanceof java.net.UnknownHostException) {
|
||||
code = ConnectionManager.UNKNOWN_HOST_EXCEPTION;
|
||||
}
|
||||
if (!informConnectionManager(code) || code == -1) {
|
||||
logger.error("An IOException occurred: ", e);
|
||||
}
|
||||
} catch (CertificateEncodingException e) {
|
||||
logger.error("A CertificateEncodingException occurred: ", e);
|
||||
} finally {
|
||||
if (connection != null) {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private SSLSocketFactory generateSSLContextWhichAcceptAllSSLCertificats() {
|
||||
Security.addProvider(Security.getProvider("SunJCE"));
|
||||
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
|
||||
|
||||
@Override
|
||||
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
|
||||
}
|
||||
} };
|
||||
|
||||
try {
|
||||
SSLContext sslContext = SSLContext.getInstance("SSL");
|
||||
|
||||
sslContext.init(null, trustAllCerts, new SecureRandom());
|
||||
|
||||
return sslContext.getSocketFactory();
|
||||
} catch (KeyManagementException e) {
|
||||
logger.error("A KeyManagementException occurred", e);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
logger.error("A NoSuchAlgorithmException occurred", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.serverconnection.impl;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.constants.JSONApiResponseKeysEnum;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
/**
|
||||
* The {@link JSONResponseHandler} checks an digitalSTROM-JSON response and can parse it to an {@link JsonObject}.
|
||||
*
|
||||
* @author Alexander Betker - Initial contribution
|
||||
* @author Alex Maier - Initial contribution
|
||||
* @author Michael Ochel - add Java-Doc, make methods static and change from SimpleJSON to GSON
|
||||
* @author Matthias Siegele - add Java-Doc, make methods static and change from SimpleJSON to GSON
|
||||
*/
|
||||
public class JSONResponseHandler {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(JSONResponseHandler.class);
|
||||
|
||||
/**
|
||||
* Checks the digitalSTROM-JSON response and return true if it was successful, otherwise false.
|
||||
*
|
||||
* @param jsonResponse to check
|
||||
* @return true, if successful
|
||||
*/
|
||||
public static boolean checkResponse(JsonObject jsonResponse) {
|
||||
if (jsonResponse == null) {
|
||||
return false;
|
||||
} else if (jsonResponse.get(JSONApiResponseKeysEnum.OK.getKey()) != null) {
|
||||
return jsonResponse.get(JSONApiResponseKeysEnum.OK.getKey()).getAsBoolean();
|
||||
} else {
|
||||
String message = "unknown message";
|
||||
if (jsonResponse.get(JSONApiResponseKeysEnum.MESSAGE.getKey()) != null) {
|
||||
message = jsonResponse.get(JSONApiResponseKeysEnum.MESSAGE.getKey()).getAsString();
|
||||
}
|
||||
LOGGER.error("JSONResponseHandler: error in json request. Error message : {}", message);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link JsonObject} from the given digitalSTROM-JSON response {@link String} or null if the json
|
||||
* response was empty.
|
||||
*
|
||||
* @param jsonResponse to convert
|
||||
* @return jsonObject
|
||||
*/
|
||||
public static JsonObject toJsonObject(String jsonResponse) {
|
||||
if (jsonResponse != null && !jsonResponse.trim().equals("")) {
|
||||
try {
|
||||
return (JsonObject) new JsonParser().parse(jsonResponse);
|
||||
} catch (JsonParseException e) {
|
||||
LOGGER.error("An JsonParseException occurred by parsing jsonRequest: {}", jsonResponse, e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result {@link JsonObject} from the given digitalSTROM-JSON response {@link JsonObject}.
|
||||
*
|
||||
* @param jsonObject of response
|
||||
* @return json result object
|
||||
*/
|
||||
public static JsonObject getResultJsonObject(JsonObject jsonObject) {
|
||||
if (jsonObject != null) {
|
||||
return jsonObject.get(JSONApiResponseKeysEnum.RESULT.getKey()).getAsJsonObject();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,306 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.serverconnection.simpledsrequestbuilder;
|
||||
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import org.apache.commons.lang.NullArgumentException;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.simpledsrequestbuilder.constants.ExeptionConstants;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.simpledsrequestbuilder.constants.InterfaceKeys;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.simpledsrequestbuilder.constants.ParameterKeys;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.DSID;
|
||||
|
||||
/**
|
||||
* The {@link SimpleRequestBuilder} build a request string.<br>
|
||||
* <br>
|
||||
* <i><b>Code example</b><br>
|
||||
* String requestString = {@link SimpleRequestBuilder}.{@link #buildNewRequest(String)}.<br>
|
||||
* <span style="padding-left:14em">{@link #addRequestClass(String)}.<br>
|
||||
* </span>
|
||||
* <span style="padding-left:14em">{@link #addFunction(String)}.<br>
|
||||
* </span>
|
||||
* <span style="padding-left:14em">{@link #addParameter(String, String)}. (optional)<br>
|
||||
* </span>
|
||||
* <span style="padding-left:14em">{@link #addParameter(String, String)}. (optional)<br>
|
||||
* </span>
|
||||
* <span style="padding-left:14em">{@link #buildRequestString()};<br>
|
||||
* </span></i>
|
||||
*
|
||||
* @author Michael Ochel - initial contributer
|
||||
* @author Matthias Siegele - initial contributer
|
||||
*/
|
||||
public class SimpleRequestBuilder {
|
||||
|
||||
// states
|
||||
private boolean functionIsChosen = false;
|
||||
private boolean parameterIsAdded = false;
|
||||
private boolean classIsChosen = false;
|
||||
|
||||
private String request;
|
||||
private static SimpleRequestBuilder builder;
|
||||
private static final Lock LOCK = new ReentrantLock();
|
||||
|
||||
private SimpleRequestBuilder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link SimpleRequestBuilder} with the given intefaceKey as chosen request-interface.
|
||||
*
|
||||
* @param interfaceKey must not be null
|
||||
* @return simpleRequestBuilder with chosen interface
|
||||
* @throws NullArgumentException if the interfaceKey is null
|
||||
*/
|
||||
public static SimpleRequestBuilder buildNewRequest(String interfaceKey) throws NullArgumentException {
|
||||
if (builder == null) {
|
||||
builder = new SimpleRequestBuilder();
|
||||
}
|
||||
LOCK.lock();
|
||||
return builder.buildNewRequestInt(interfaceKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link SimpleRequestBuilder} with the intefaceKey "Json" as chosen request-interface and adds the given
|
||||
* requestClass to the request-string.
|
||||
*
|
||||
* @param requestClassKey must not be null
|
||||
* @return simpleRequestBuilder with chosen requestClass
|
||||
* @throws IllegalArgumentException if a requestClass is already chosen
|
||||
* @throws NullArgumentException if the requestClassKey is null
|
||||
*/
|
||||
public static SimpleRequestBuilder buildNewJsonRequest(String requestClassKey)
|
||||
throws NullArgumentException, IllegalArgumentException {
|
||||
return buildNewRequest(InterfaceKeys.JSON).addRequestClass(requestClassKey);
|
||||
}
|
||||
|
||||
private SimpleRequestBuilder buildNewRequestInt(String interfaceKey) {
|
||||
if (interfaceKey == null) {
|
||||
throw new NullArgumentException("interfaceKey");
|
||||
}
|
||||
request = "/" + interfaceKey + "/";
|
||||
classIsChosen = false;
|
||||
functionIsChosen = false;
|
||||
parameterIsAdded = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a requestClass to the request-string.
|
||||
*
|
||||
* @param requestClassKey must not be null
|
||||
* @return simpleRequestBuilder with chosen requestClass
|
||||
* @throws IllegalArgumentException if a requestClass is already chosen
|
||||
* @throws NullArgumentException if the requestClassKey is null
|
||||
*/
|
||||
public SimpleRequestBuilder addRequestClass(String requestClassKey)
|
||||
throws IllegalArgumentException, NullArgumentException {
|
||||
return builder.addRequestClassInt(requestClassKey);
|
||||
}
|
||||
|
||||
private SimpleRequestBuilder addRequestClassInt(String requestClassKey) {
|
||||
if (!classIsChosen && requestClassKey != null) {
|
||||
classIsChosen = true;
|
||||
request = request + requestClassKey + "/";
|
||||
} else {
|
||||
if (!classIsChosen) {
|
||||
throw new IllegalArgumentException(ExeptionConstants.CLASS_ALREADY_ADDED);
|
||||
} else {
|
||||
throw new NullArgumentException("requestClassKey");
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a function to the request-string.
|
||||
*
|
||||
* @param functionKey must not be null
|
||||
* @return SimpleRequestBuilder with chosen function
|
||||
* @throws IllegalArgumentException if a function is already chosen
|
||||
* @throws NullArgumentException if the functionKey is null
|
||||
*/
|
||||
public SimpleRequestBuilder addFunction(String functionKey) throws IllegalArgumentException, NullArgumentException {
|
||||
return builder.addFunctionInt(functionKey);
|
||||
}
|
||||
|
||||
private SimpleRequestBuilder addFunctionInt(String functionKey) {
|
||||
if (!classIsChosen) {
|
||||
throw new IllegalArgumentException(ExeptionConstants.NO_CLASS_ADDED);
|
||||
}
|
||||
if (!functionIsChosen) {
|
||||
if (functionKey != null) {
|
||||
functionIsChosen = true;
|
||||
request = request + functionKey;
|
||||
} else {
|
||||
throw new NullArgumentException("functionKey");
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException(ExeptionConstants.FUNCTION_ALLREADY_ADDED);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a parameter to the request-string, if the parameter value is not null.
|
||||
*
|
||||
* @param parameterKey must not be null
|
||||
* @param parameterValue can be null
|
||||
* @return SimpleRequestBuilder with added parameter
|
||||
* @throws IllegalArgumentException if no class and function added
|
||||
* @throws NullArgumentException if the parameterKey is null
|
||||
*/
|
||||
public SimpleRequestBuilder addParameter(String parameterKey, String parameterValue)
|
||||
throws IllegalArgumentException, NullArgumentException {
|
||||
return builder.addParameterInt(parameterKey, parameterValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the default parameter for zone-requests to the request-string, if the parameter value is not null.
|
||||
*
|
||||
* @param sessionToken
|
||||
* @param zoneID
|
||||
* @param zoneName
|
||||
* @return SimpleRequestBuilder with added parameter
|
||||
* @throws IllegalArgumentException if no class and function added
|
||||
* @throws NullArgumentException if the parameterKey is null
|
||||
*/
|
||||
public SimpleRequestBuilder addDefaultZoneParameter(String sessionToken, Integer zoneID, String zoneName)
|
||||
throws IllegalArgumentException, NullArgumentException {
|
||||
return addParameter(ParameterKeys.TOKEN, sessionToken).addParameter(ParameterKeys.ID, objectToString(zoneID))
|
||||
.addParameter(ParameterKeys.NAME, zoneName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a parameter for group-requests t the request-string, if the parameter value is not null.
|
||||
*
|
||||
* @param sessionToken
|
||||
* @param groupID
|
||||
* @param groupName
|
||||
* @return SimpleRequestBuilder with added parameter
|
||||
* @throws IllegalArgumentException if no class and function added
|
||||
* @throws NullArgumentException if the parameterKey is null
|
||||
*/
|
||||
public SimpleRequestBuilder addDefaultGroupParameter(String sessionToken, Short groupID, String groupName)
|
||||
throws IllegalArgumentException, NullArgumentException {
|
||||
return addParameter(ParameterKeys.TOKEN, sessionToken)
|
||||
.addParameter(ParameterKeys.GROUP_ID, objectToString(groupID))
|
||||
.addParameter(ParameterKeys.GROUP_NAME, groupName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a parameter for zone-group-requests t the request-string, if the parameter value is not null.
|
||||
*
|
||||
* @param sessionToken
|
||||
* @param zoneID
|
||||
* @param zoneName
|
||||
* @param groupID
|
||||
* @param groupName
|
||||
* @return SimpleRequestBuilder with added parameter
|
||||
* @throws IllegalArgumentException if no class and function added
|
||||
* @throws NullArgumentException if the parameterKey is null
|
||||
*/
|
||||
public SimpleRequestBuilder addDefaultZoneGroupParameter(String sessionToken, Integer zoneID, String zoneName,
|
||||
Short groupID, String groupName) throws IllegalArgumentException, NullArgumentException {
|
||||
return addDefaultZoneParameter(sessionToken, zoneID, zoneName)
|
||||
.addParameter(ParameterKeys.GROUP_ID, objectToString(groupID))
|
||||
.addParameter(ParameterKeys.GROUP_NAME, groupName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a parameter for device-requests the request-string, if the parameter value is not null.
|
||||
*
|
||||
* @param sessionToken
|
||||
* @param dsid
|
||||
* @param dSUID
|
||||
* @param name
|
||||
* @return SimpleRequestBuilder with added parameter
|
||||
* @throws IllegalArgumentException if no class and function added
|
||||
* @throws NullArgumentException if the parameterKey is null
|
||||
*/
|
||||
public SimpleRequestBuilder addDefaultDeviceParameter(String sessionToken, DSID dsid, String dSUID, String name)
|
||||
throws IllegalArgumentException, NullArgumentException {
|
||||
return addParameter(ParameterKeys.TOKEN, sessionToken).addParameter(ParameterKeys.DSID, objectToString(dsid))
|
||||
.addParameter(ParameterKeys.DSUID, dSUID).addParameter(ParameterKeys.NAME, name);
|
||||
}
|
||||
|
||||
private SimpleRequestBuilder addParameterInt(String parameterKey, String parameterValue) {
|
||||
if (allRight()) {
|
||||
if (parameterKey == null) {
|
||||
throw new NullArgumentException("parameterKey");
|
||||
}
|
||||
if (parameterValue != null) {
|
||||
if (!parameterIsAdded) {
|
||||
parameterIsAdded = true;
|
||||
request = request + "?" + parameterKey + "=" + parameterValue;
|
||||
} else {
|
||||
request = request + "&" + parameterKey + "=" + parameterValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the request string.
|
||||
*
|
||||
* @return request string
|
||||
* @throws IllegalArgumentException if no class or function is added.
|
||||
*/
|
||||
public String buildRequestString() throws IllegalArgumentException {
|
||||
String request = builder.buildRequestStringInt();
|
||||
LOCK.unlock();
|
||||
return request;
|
||||
}
|
||||
|
||||
private String buildRequestStringInt() {
|
||||
return allRight() ? request : null;
|
||||
}
|
||||
|
||||
private boolean allRight() {
|
||||
if (!classIsChosen) {
|
||||
throw new IllegalArgumentException(ExeptionConstants.NO_CLASS_ADDED);
|
||||
}
|
||||
if (!functionIsChosen) {
|
||||
throw new IllegalArgumentException(ExeptionConstants.NO_FUNCTION);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an {@link Object} to a {@link String} or null, if the obj was null or it was a negative {@link Number}.
|
||||
*
|
||||
* @param obj can be null
|
||||
* @return the {@link String} or null
|
||||
*/
|
||||
public static String objectToString(Object obj) {
|
||||
if (obj == null) {
|
||||
return null;
|
||||
}
|
||||
if (obj instanceof DSID) {
|
||||
return ((DSID) obj).getValue();
|
||||
}
|
||||
if (obj instanceof Number) {
|
||||
return ((Number) obj).intValue() > -1 ? obj.toString() : null;
|
||||
}
|
||||
return obj.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#equals()
|
||||
*/
|
||||
public boolean equals(SimpleRequestBuilder builder) {
|
||||
return this.request.contains(builder.request);
|
||||
}
|
||||
}
|
||||
@@ -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.digitalstrom.internal.lib.serverconnection.simpledsrequestbuilder.constants;
|
||||
|
||||
/**
|
||||
* The {@link ClassKeys} contains digitalSTROM-JSON class keys.
|
||||
*
|
||||
* @author Michael Ochel - initial contributer
|
||||
* @author Matthias Siegele - initial contributer
|
||||
*/
|
||||
public class ClassKeys {
|
||||
|
||||
public static final String APARTMENT = "apartment";
|
||||
public static final String ZONE = "zone";
|
||||
public static final String DEVICE = "device";
|
||||
public static final String CIRCUIT = "circuit";
|
||||
public static final String STRUCTURE = "structure";
|
||||
public static final String EVENT = "event";
|
||||
public static final String METERING = "metering";
|
||||
public static final String SYSTEM = "system";
|
||||
public static final String PROPERTY_TREE = "property";
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.serverconnection.simpledsrequestbuilder.constants;
|
||||
|
||||
/**
|
||||
* The {@link ExeptionConstants} contains the {@link SimpleRequestBuilder} exception strings.
|
||||
*
|
||||
* @author Michael Ochel - initial contributer
|
||||
* @author Matthias Siegele - initial contributer
|
||||
*/
|
||||
public class ExeptionConstants {
|
||||
public static final String NO_CLASS_ADDED = "No class added! Please add a class first!";
|
||||
public static final String CLASS_ALREADY_ADDED = "A class is already added! You can only add one class!";
|
||||
public static final String FUNCTION_ALLREADY_ADDED = "A function is already added! You can only add one function!";
|
||||
public static final String NO_FUNCTION = "No function added! Please add a function!";
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.serverconnection.simpledsrequestbuilder.constants;
|
||||
|
||||
/**
|
||||
* The {@link FunctionKeys} contains digitalSTROM-JSON function keys.
|
||||
*
|
||||
* @author Michael Ochel - initial contributer
|
||||
* @author Matthias Siegele - initial contributer
|
||||
*/
|
||||
public class FunctionKeys {
|
||||
|
||||
public static final String CALL_SCENE = "callScene";
|
||||
public static final String SAVE_SCENE = "saveScene";
|
||||
public static final String LOGIN = "login";
|
||||
public static final String LOGOUT = "logout";
|
||||
public static final String UNDO_SCENE = "undoScene";
|
||||
public static final String TURN_ON = "turnOn";
|
||||
public static final String TURN_OFF = "turnOff";
|
||||
public static final String INCREASE_VALUE = "increaseValue";
|
||||
public static final String DECREASE_VALUE = "decreaseValue";
|
||||
public static final String GET_STRUCTURE = "getStructure";
|
||||
public static final String GET_DEVICES = "getDevices";
|
||||
public static final String GET_CIRCUITS = "getCircuits";
|
||||
public static final String LOGIN_APPLICATION = "loginApplication";
|
||||
public static final String GET_NAME = "getName";
|
||||
public static final String SET_NAME = "setName";
|
||||
public static final String SUBSCRIBE = "subscribe";
|
||||
public static final String UNSUBSCRIBE = "unsubscribe";
|
||||
public static final String GET = "get";
|
||||
public static final String SET_VALUE = "setValue";
|
||||
public static final String GET_CONSUMPTION = "getConsumption";
|
||||
public static final String RESCAN = "rescan";
|
||||
public static final String SCENE_SET_NAME = "sceneSetName";
|
||||
public static final String SCENE_GET_NAME = "sceneGetName";
|
||||
public static final String PUSH_SENSOR_VALUES = "pushSensorValues";
|
||||
public static final String GET_REACHABLE_SCENES = "getReachableScenes";
|
||||
public static final String GET_STATE = "getState";
|
||||
public static final String GET_GROUPS = "getGroups";
|
||||
public static final String GET_ENERGY_METER_VALUE = "getEnergyMeterValue";
|
||||
public static final String GET_STRING = "getString";
|
||||
public static final String GET_INTEGER = "getInteger";
|
||||
public static final String GET_BOOLEAN = "getBoolean";
|
||||
public static final String SET_STRING = "setString";
|
||||
public static final String SET_INTEGER = "setInteger";
|
||||
public static final String SET_BOOLEAN = "setBoolean";
|
||||
public static final String GET_CHILDREN = "getChildren";
|
||||
public static final String SET_FLAG = "setFlag";
|
||||
public static final String GET_FLAGS = "getFlags";
|
||||
public static final String QUERY = "query";
|
||||
public static final String REMOVE = "remove";
|
||||
public static final String GET_TYPE = "getType";
|
||||
public static final String GET_SPEC = "getSpec";
|
||||
public static final String VERSION = "version";
|
||||
public static final String TIME = "time";
|
||||
public static final String FROM_APARTMENT = "fromApartment";
|
||||
public static final String BY_ZONE = "byZone";
|
||||
public static final String BY_GROUP = "byGroup";
|
||||
public static final String BY_DSID = "byDSID";
|
||||
public static final String ADD = "add";
|
||||
public static final String SUBTRACT = "subtract";
|
||||
public static final String LOGGED_IN_USER = "loggedInUser";
|
||||
public static final String ZONE_ADD_DEVICE = "zoneAddDevice";
|
||||
public static final String ADD_ZONE = "addZone";
|
||||
public static final String REMOVE_ZONE = "removeZone";
|
||||
public static final String REMOVE_DEVICE = "removeDevice";
|
||||
public static final String PERSIST_SET = "persistSet";
|
||||
public static final String UNPERSIST_SET = "unpersistSet";
|
||||
public static final String ADD_GROUP = "addGroup";
|
||||
public static final String GROUP_ADD_DEVICE = "groupAddDevice";
|
||||
public static final String GROUP_REMOVE_DEVICE = "groupRemoveDevice";
|
||||
public static final String GET_RESOLUTIONS = "getResolutions";
|
||||
public static final String GET_SERIES = "getSeries";
|
||||
public static final String GET_VALUES = "getValues";
|
||||
public static final String GET_LATEST = "getLatest";
|
||||
public static final String ADD_TAG = "addTag";
|
||||
public static final String REMOVE_TAG = "removeTag";
|
||||
public static final String HAS_TAG = "hasTag";
|
||||
public static final String GET_TAGS = "getTags";
|
||||
public static final String LOCK = "lock";
|
||||
public static final String UNLOCK = "unlock";
|
||||
public static final String GET_SENSOR_EVENT_TABLE_ENTRY = "getSensorEventTableEntry";
|
||||
public static final String SET_SENSOR_EVENT_TABLE_ENTRY = "setSensorEventTableEntry";
|
||||
public static final String ADD_TO_AREA = "addToArea";
|
||||
public static final String REMOVE_FROM_AREA = "removeFromArea";
|
||||
public static final String SET_CONFIG = "setConfig";
|
||||
public static final String GET_CONFIG = "getConfig";
|
||||
public static final String GET_CONFIG_WORD = "getConfigWord";
|
||||
public static final String SET_JOKER_GROUP = "setJokerGroup";
|
||||
public static final String SET_BUTTON_ID = "setButtonID";
|
||||
public static final String SET_BUTTON_INPUT_MODE = "setButtonInputMode";
|
||||
public static final String SET_OUTPUT_MODE = "setOutputMode";
|
||||
public static final String SET_PROG_MODE = "setProgMode";
|
||||
public static final String GET_OUTPUT_VALUE = "getOutputValue";
|
||||
public static final String SET_OUTPUT_VALUE = "setOutputValue";
|
||||
public static final String GET_SCENE_MODE = "getSceneMode";
|
||||
public static final String SET_SCENE_MODE = "setSceneMode";
|
||||
public static final String GET_TRANSITION_TIME = "getTransitionTime";
|
||||
public static final String SET_TRANSITION_TIME = "setTransitionTime";
|
||||
public static final String GET_LED_MODE = "getLedMode";
|
||||
public static final String SET_LED_MODE = "setLedMode";
|
||||
public static final String GET_SENSOR_VALUE = "getSensorValue";
|
||||
public static final String GET_SENSOR_TYPE = "getSensorType";
|
||||
public static final String GET_DSID = "getDSID";
|
||||
public static final String ENABLE_APPLICATION_TOKEN = "enableToken";
|
||||
public static final String REQUEST_APPLICATION_TOKEN = "requestApplicationToken";
|
||||
public static final String REVOKE_TOKEN = "revokeToken";
|
||||
public static final String GET_SCENE_VALUE = "getSceneValue";
|
||||
public static final String GET_TEMPERATURE_CONTROL_STATUS = "getTemperatureControlStatus";
|
||||
public static final String GET_TEMPERATURE_CONTROL_CONFIG = "getTemperatureControlConfig";
|
||||
public static final String GET_TEMPERATURE_CONTROL_VALUES = "getTemperatureControlValues";
|
||||
public static final String GET_ASSIGNED_SENSORS = "getAssignedSensors";
|
||||
public static final String SET_TEMEPERATURE_CONTROL_STATE = "setTemperatureControlState";
|
||||
public static final String SET_TEMEPERATURE_CONTROL_VALUE = "setTemperatureControlValue";
|
||||
public static final String GET_SENSOR_VALUES = "getSensorValues";
|
||||
public static final String SET_SENSOR_SOURCE = "setSensorSource";
|
||||
public static final String GET_TEMPERATURE_CONTROL_INTERNALS = "getTemperatureControlInternals";
|
||||
public static final String SET_TEMPERATION_CONTROL_CONFIG = "setTemperatureControlConfig";
|
||||
public static final String QUERY2 = "query2";
|
||||
public static final String BLINK = "blink";
|
||||
public static final String PUSH_SENSOR_VALUE = "pushSensorValue";
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.serverconnection.simpledsrequestbuilder.constants;
|
||||
|
||||
/**
|
||||
* The {@link InterfaceKeys} contains digitalSTROM-JSON interface keys.
|
||||
*
|
||||
* @author Michael Ochel - initial contributer
|
||||
* @author Matthias Siegele - initial contributer
|
||||
*/
|
||||
public class InterfaceKeys {
|
||||
public static final String JSON = "json";
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.serverconnection.simpledsrequestbuilder.constants;
|
||||
|
||||
/**
|
||||
* The {@link ParameterKeys} contains digitalSTROM-JSON parameter keys.
|
||||
*
|
||||
* @author Michael Ochel - initial contributer
|
||||
* @author Matthias Siegele - initial contributer
|
||||
*/
|
||||
public class ParameterKeys {
|
||||
public static final String TOKEN = "token";
|
||||
public static final String APPLICATION_TOKEN = "applicationToken";
|
||||
public static final String APPLICATION_NAME = "applicationName";
|
||||
public static final String NAME = "name";
|
||||
public static final String NEW_NAME = "newName";
|
||||
public static final String DSID = "dsid";
|
||||
public static final String SCENENUMBER = "sceneNumber";
|
||||
public static final String LOGIN_TOKEN = "loginToken";
|
||||
public static final String USER = "user";
|
||||
public static final String PASSWORD = "password";
|
||||
public static final String SUBSCRIPTIONID = "subscriptionID";
|
||||
public static final String TIMEOUT = "timeout";
|
||||
public static final String GROUP_ID = "groupID";
|
||||
public static final String GROUP_NAME = "groupName";
|
||||
public static final String VALUE = "value";
|
||||
public static final String FORCE = "force";
|
||||
public static final String ID = "id";
|
||||
public static final String ENABLE = "enable";
|
||||
public static final String DISABLE = "disable";
|
||||
public static final String UNASSIGNED = "unassigned";
|
||||
public static final String SOURCE_DSID = "sourceDSID";
|
||||
public static final String SENSOR_TYPE = "sensorType";
|
||||
public static final String SENSOR_VALUE = "sensorValue";
|
||||
public static final String FLAG = "flag";
|
||||
public static final String PATH = "path";
|
||||
public static final String RAISE = "raise";
|
||||
public static final String CONTEXT = "context";
|
||||
public static final String LOCATION = "location";
|
||||
public static final String SELF = "self";
|
||||
public static final String ZONE_ID = "zoneID";
|
||||
public static final String ZONE_NAME = "zoneName";
|
||||
public static final String OTHER = "other";
|
||||
public static final String DEVICE_ID = "deviceID";
|
||||
public static final String UNIT = "unit";
|
||||
public static final String START_TIME = "startTime";
|
||||
public static final String END_TIME = "endTime";
|
||||
public static final String VALUE_COUNT = "valueCount";
|
||||
public static final String RESOLUTION = "resolution";
|
||||
public static final String TYPE = "type";
|
||||
public static final String FROM = "from";
|
||||
public static final String TAG = "tag";
|
||||
public static final String CLASS = "class";
|
||||
public static final String INDEX = "index";
|
||||
public static final String BUTTON_ID = "buttonID";
|
||||
public static final String MODE_ID = "modeID";
|
||||
public static final String MODE = "mode";
|
||||
public static final String OFFSET = "offset";
|
||||
public static final String SCENE_ID = "sceneID";
|
||||
public static final String DONT_CARE = "dontCare";
|
||||
public static final String LOCAL_PRIO = "localPrio";
|
||||
public static final String SPECIAL_MODE = "specialMode";
|
||||
public static final String FLASH_MODE = "flashMode";
|
||||
public static final String LED_CON_INDEX = "ledconIndex";
|
||||
public static final String DIM_TIME_INDEX = "dimtimeIndex";
|
||||
public static final String UP = "up";
|
||||
public static final String DOWN = "down";
|
||||
public static final String COLOR_SELECT = "colorSelect";
|
||||
public static final String MODE_SELECT = "modeSelect";
|
||||
public static final String DIM_MODE = "dimMode";
|
||||
public static final String RGB_MODE = "rgbMode";
|
||||
public static final String GROUP_COLOR_MODE = "groupColorMode";
|
||||
public static final String SENSOR_INDEX = "sensorIndex";
|
||||
public static final String EVENT_INDEX = "eventIndex";
|
||||
public static final String AREA_SCENE = "areaScene";
|
||||
public static final String EVENT_NAME = "eventName";
|
||||
public static final String TEST = "test";
|
||||
public static final String HYSTERSIS = "hysteresis";
|
||||
public static final String VALIDITY = "validity";
|
||||
public static final String ACTION = "action";
|
||||
public static final String BUTTON_NUMBER = "buttonNumber";
|
||||
public static final String CLICK_TYPE = "clickType";
|
||||
public static final String SCENE_DEVICE_MODE = "sceneDeviceMode";
|
||||
public static final String CONTROL_STATE = "ControlState";
|
||||
public static final String CONTROL_VALUE = "ControlValue";
|
||||
public static final String QUERY = "query";
|
||||
public static final String CONTROL_MODE = "ControlMode";
|
||||
public static final String CONTROL_DSUID = "ControlDSUID";
|
||||
public static final String CTRL_OFFSET = "CtrlOffset";
|
||||
public static final String REFERENCE_ZONE = "ReferenceZone";
|
||||
public static final String EMERGENCY_VALUE = "EmergencyValue";
|
||||
public static final String MANUAL_VALUE = "ManualValue";
|
||||
public static final String CTRL_KP = "CtrlKp";
|
||||
public static final String CTRL_TS = "CtrlTs";
|
||||
public static final String CTRL_TI = "CtrlTi";
|
||||
public static final String CTRL_KD = "CtrlKd";
|
||||
public static final String CTRL_I_MIN = "CtrlImin";
|
||||
public static final String CTRL_I_MAX = "CtrlImax";
|
||||
public static final String CTRL_Y_MIN = "CtrlYmin";
|
||||
public static final String CTRL_Y_MAX = "CtrlYmax";
|
||||
public static final String CTRL_ANTI_WIND_UP = "CtrlAntiWindUp";
|
||||
public static final String CTRL_KEEP_FLOOR_WARM = "CtrlKeepFloorWarm";
|
||||
public static final String SOURCE_DSUID = "sourceDSUID";
|
||||
public static final String DSUID = "dsuid";
|
||||
}
|
||||
@@ -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.digitalstrom.internal.lib.structure;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The {@link Apartment} represents a digitalSTROM-Apartment.
|
||||
*
|
||||
* @author Alexander Betker - initial contributer
|
||||
* @author Michael Ochel - add java-doc
|
||||
* @author Matthias Siegele - add java-doc
|
||||
*/
|
||||
public interface Apartment {
|
||||
|
||||
/**
|
||||
* Returns the {@link Map} of all digitalSTROM-Zones with the zone id as key and the {@link Zone} as value.
|
||||
*
|
||||
* @return map of all zones
|
||||
*/
|
||||
Map<Integer, Zone> getZoneMap();
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.structure;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The {@link DetailedGroupInfo} represents a digitalSTROM-Group with a list of all dSUID's of the included
|
||||
* digitalSTROM-Devices.
|
||||
*
|
||||
* @author Alexander Betker - initial contributer
|
||||
* @author Michael Ochel - add java-doc
|
||||
* @author Matthias Siegele - add java-doc
|
||||
*/
|
||||
public interface DetailedGroupInfo extends Group {
|
||||
|
||||
/**
|
||||
* Returns the list of all dSUID's of the included digitalSTROM-Devices.
|
||||
*
|
||||
* @return list of all dSUID
|
||||
*/
|
||||
List<String> getDeviceList();
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.structure;
|
||||
|
||||
/**
|
||||
* The {@link Group} represents a digitalSTROM-Group.
|
||||
*
|
||||
* @author Alexander Betker - initial contributer
|
||||
* @author Michael Ochel - add java-doc
|
||||
* @author Matthias Siegele - add java-doc
|
||||
*/
|
||||
public interface Group {
|
||||
|
||||
/**
|
||||
* Returns the group id of this {@link Group}.
|
||||
*
|
||||
* @return group id
|
||||
*/
|
||||
short getGroupID();
|
||||
|
||||
/**
|
||||
* Returns the name of this {@link Group}.
|
||||
*
|
||||
* @return group name
|
||||
*/
|
||||
String getGroupName();
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.structure;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.Device;
|
||||
|
||||
/**
|
||||
* The {@link Zone} represents a digitalSTROM-Zone.
|
||||
*
|
||||
* @author Alexander Betker - initial contributer
|
||||
* @author Michael Ochel - add java-doc
|
||||
* @author Matthias Siegele - add java-doc
|
||||
*/
|
||||
public interface Zone {
|
||||
|
||||
/**
|
||||
* Returns the zone id of this {@link Zone}.
|
||||
*
|
||||
* @return zoneID
|
||||
*/
|
||||
int getZoneId();
|
||||
|
||||
/**
|
||||
* Sets the zone id of this {@link Zone}.
|
||||
*
|
||||
* @param id to set
|
||||
*/
|
||||
void setZoneId(int id);
|
||||
|
||||
/**
|
||||
* Returns the zone name of this {@link Zone}.
|
||||
*
|
||||
* @return zone name
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Sets the zone name of this {@link Zone}.
|
||||
*
|
||||
* @param name to set
|
||||
*/
|
||||
void setName(String name);
|
||||
|
||||
/**
|
||||
* Returns the {@link List} of all included groups as {@link DetailedGroupInfo}.
|
||||
*
|
||||
* @return list of all groups
|
||||
*/
|
||||
List<DetailedGroupInfo> getGroups();
|
||||
|
||||
/**
|
||||
* Adds a group as {@link DetailedGroupInfo}.
|
||||
*
|
||||
* @param group to add
|
||||
*/
|
||||
void addGroup(DetailedGroupInfo group);
|
||||
|
||||
/**
|
||||
* Returns a {@link List} of all included {@link Device}'s.
|
||||
*
|
||||
* @return device list
|
||||
*/
|
||||
List<Device> getDevices();
|
||||
|
||||
/**
|
||||
* Adds a {@link Device} to this {@link Zone}.
|
||||
*
|
||||
* @param device to add
|
||||
*/
|
||||
void addDevice(Device device);
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.structure.devices;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.DeviceStatusListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.serverconnection.constants.JSONApiResponseKeysEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.ChangeableDeviceConfigEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.DSID;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link AbstractGeneralDeviceInformations} is a abstract implementation of {@link GeneralDeviceInformations} and
|
||||
* can be implement by subclasses which contains the same device informations like dSID and/or mechanismen like the
|
||||
* {@link DeviceStatusListener}.
|
||||
*
|
||||
* @author Michael Ochel - initial contributer
|
||||
* @author Matthias Siegele - initial contributer
|
||||
*/
|
||||
public abstract class AbstractGeneralDeviceInformations implements GeneralDeviceInformation {
|
||||
|
||||
protected DSID dsid;
|
||||
protected String dSUID;
|
||||
protected Boolean isPresent;
|
||||
protected Boolean isValide;
|
||||
protected String name;
|
||||
protected String displayID;
|
||||
protected DeviceStatusListener listener;
|
||||
|
||||
/**
|
||||
* Creates a new {@link AbstractGeneralDeviceInformations} through the digitalSTROM json response as
|
||||
* {@link JsonObject}.
|
||||
*
|
||||
* @param jsonDeviceObject json response of the digitalSTROM-Server, must not be null
|
||||
*/
|
||||
public AbstractGeneralDeviceInformations(JsonObject jsonDeviceObject) {
|
||||
if (jsonDeviceObject.get(JSONApiResponseKeysEnum.NAME.getKey()) != null) {
|
||||
name = jsonDeviceObject.get(JSONApiResponseKeysEnum.NAME.getKey()).getAsString();
|
||||
}
|
||||
if (jsonDeviceObject.get(JSONApiResponseKeysEnum.ID.getKey()) != null) {
|
||||
dsid = new DSID(jsonDeviceObject.get(JSONApiResponseKeysEnum.ID.getKey()).getAsString());
|
||||
} else if (jsonDeviceObject.get(JSONApiResponseKeysEnum.DSID.getKey()) != null) {
|
||||
dsid = new DSID(jsonDeviceObject.get(JSONApiResponseKeysEnum.DSID.getKey()).getAsString());
|
||||
} else if (jsonDeviceObject.get(JSONApiResponseKeysEnum.DSID_LOWER_CASE.getKey()) != null) {
|
||||
dsid = new DSID(jsonDeviceObject.get(JSONApiResponseKeysEnum.DSID_LOWER_CASE.getKey()).getAsString());
|
||||
}
|
||||
if (jsonDeviceObject.get(JSONApiResponseKeysEnum.DSUID.getKey()) != null) {
|
||||
dSUID = jsonDeviceObject.get(JSONApiResponseKeysEnum.DSUID.getKey()).getAsString();
|
||||
}
|
||||
if (jsonDeviceObject.get(JSONApiResponseKeysEnum.DISPLAY_ID.getKey()) != null) {
|
||||
displayID = jsonDeviceObject.get(JSONApiResponseKeysEnum.DISPLAY_ID.getKey()).getAsString();
|
||||
}
|
||||
if (jsonDeviceObject.get(JSONApiResponseKeysEnum.IS_PRESENT.getKey()) != null) {
|
||||
isPresent = jsonDeviceObject.get(JSONApiResponseKeysEnum.IS_PRESENT.getKey()).getAsBoolean();
|
||||
} else if (jsonDeviceObject.get(JSONApiResponseKeysEnum.PRESENT.getKey()) != null) {
|
||||
isPresent = jsonDeviceObject.get(JSONApiResponseKeysEnum.PRESENT.getKey()).getAsBoolean();
|
||||
}
|
||||
if (jsonDeviceObject.get(JSONApiResponseKeysEnum.IS_VALID.getKey()) != null) {
|
||||
isValide = jsonDeviceObject.get(JSONApiResponseKeysEnum.IS_VALID.getKey()).getAsBoolean();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setName(String name) {
|
||||
this.name = name;
|
||||
if (listener != null) {
|
||||
listener.onDeviceConfigChanged(ChangeableDeviceConfigEnum.DEVICE_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DSID getDSID() {
|
||||
return dsid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDSUID() {
|
||||
return this.dSUID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean isPresent() {
|
||||
return isPresent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIsPresent(boolean isPresent) {
|
||||
this.isPresent = isPresent;
|
||||
if (listener != null) {
|
||||
if (!isPresent) {
|
||||
listener.onDeviceRemoved(this);
|
||||
} else {
|
||||
listener.onDeviceAdded(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean isValid() {
|
||||
return isValide;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIsValid(boolean isValide) {
|
||||
this.isValide = isValide;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerDeviceStatusListener(DeviceStatusListener listener) {
|
||||
if (listener != null) {
|
||||
this.listener = listener;
|
||||
listener.onDeviceAdded(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceStatusListener unregisterDeviceStatusListener() {
|
||||
DeviceStatusListener listener = this.listener;
|
||||
this.listener = null;
|
||||
return listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isListenerRegisterd() {
|
||||
return listener != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceStatusListener getDeviceStatusListener() {
|
||||
return listener;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((dSUID == null) ? 0 : dSUID.hashCode());
|
||||
result = prime * result + ((displayID == null) ? 0 : displayID.hashCode());
|
||||
result = prime * result + ((dsid == null) ? 0 : dsid.hashCode());
|
||||
result = prime * result + ((isPresent == null) ? 0 : isPresent.hashCode());
|
||||
result = prime * result + ((isValide == null) ? 0 : isValide.hashCode());
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof AbstractGeneralDeviceInformations)) {
|
||||
return false;
|
||||
}
|
||||
AbstractGeneralDeviceInformations other = (AbstractGeneralDeviceInformations) obj;
|
||||
if (dSUID == null) {
|
||||
if (other.dSUID != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!dSUID.equals(other.dSUID)) {
|
||||
return false;
|
||||
}
|
||||
if (displayID == null) {
|
||||
if (other.displayID != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!displayID.equals(other.displayID)) {
|
||||
return false;
|
||||
}
|
||||
if (dsid == null) {
|
||||
if (other.dsid != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!dsid.equals(other.dsid)) {
|
||||
return false;
|
||||
}
|
||||
if (isPresent == null) {
|
||||
if (other.isPresent != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!isPresent.equals(other.isPresent)) {
|
||||
return false;
|
||||
}
|
||||
if (isValide == null) {
|
||||
if (other.isValide != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!isValide.equals(other.isValide)) {
|
||||
return false;
|
||||
}
|
||||
if (name == null) {
|
||||
if (other.name != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!name.equals(other.name)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayID() {
|
||||
return displayID;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,293 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.structure.devices;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.CachedMeteringValue;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.MeteringTypeEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.MeteringUnitsEnum;
|
||||
|
||||
/**
|
||||
* The {@link Circuit} represents a circuit of the digitalStrom system. For that all information will be able to get and
|
||||
* set through the same named getter- and setter-methods. To get informed about status and configuration changes a
|
||||
* {@link DeviceStatusListener} can be registered. For that and to get the general device informations like the dSID the
|
||||
* {@link Circuit} implements the {@link GeneralDeviceInformations} interface.
|
||||
*
|
||||
* @author Michael Ochel - initial contributer
|
||||
* @author Matthias Siegele - initial contributer
|
||||
*/
|
||||
public interface Circuit extends GeneralDeviceInformation {
|
||||
|
||||
/**
|
||||
* Returns the hardware version of this {@link Circuit} as {@link Integer}.
|
||||
*
|
||||
* @return hardware version
|
||||
*/
|
||||
Integer getHwVersion();
|
||||
|
||||
/**
|
||||
* Sets the hardware version of this {@link Circuit} as {@link Integer}.
|
||||
*
|
||||
* @param hwVersion the new hardware version as {@link Integer}
|
||||
*/
|
||||
void setHwVersion(Integer hwVersion);
|
||||
|
||||
/**
|
||||
* Returns the hardware version of this {@link Circuit} as {@link String}.
|
||||
*
|
||||
* @return hardware version
|
||||
*/
|
||||
String getHwVersionString();
|
||||
|
||||
/**
|
||||
* Sets the hardware version of this {@link Circuit} as {@link String}.
|
||||
*
|
||||
* @param hwVersionString the new hardware version as {@link Integer}
|
||||
*/
|
||||
void setHwVersionString(String hwVersionString);
|
||||
|
||||
/**
|
||||
* Returns the software version of this {@link Circuit} as {@link String}.
|
||||
*
|
||||
* @return the software version
|
||||
*/
|
||||
String getSwVersion();
|
||||
|
||||
/**
|
||||
* Sets the software version of this {@link Circuit} as {@link String}.
|
||||
*
|
||||
* @param swVersion the new software version
|
||||
*/
|
||||
void setSwVersion(String swVersion);
|
||||
|
||||
/**
|
||||
* Returns the arm software version of this {@link Circuit} as {@link Integer}.
|
||||
*
|
||||
* @return the arm software version
|
||||
*/
|
||||
Integer getArmSwVersion();
|
||||
|
||||
/**
|
||||
* Sets the arm software version of this {@link Circuit} as {@link Integer}.
|
||||
*
|
||||
* @param armSwVersion the new arm software version
|
||||
*/
|
||||
void setArmSwVersion(Integer armSwVersion);
|
||||
|
||||
/**
|
||||
* Returns the dsp software version of this {@link Circuit} as {@link Integer}.
|
||||
*
|
||||
* @return the dsp softwaree version
|
||||
*/
|
||||
Integer getDspSwVersion();
|
||||
|
||||
/**
|
||||
* Sets the dsp software version of this {@link Circuit} as {@link Integer}.
|
||||
*
|
||||
* @param dspSwVersion the new dsp software version
|
||||
*/
|
||||
void setDspSwVersion(Integer dspSwVersion);
|
||||
|
||||
/**
|
||||
* Returns the api version of this {@link Circuit} as {@link Integer}.
|
||||
*
|
||||
* @return the api version as {@link Integer}
|
||||
*/
|
||||
Integer getApiVersion();
|
||||
|
||||
/**
|
||||
* Setss the api version of this {@link Circuit} as {@link Integer}.
|
||||
*
|
||||
* @param apiVersion the new api version
|
||||
*/
|
||||
void setApiVersion(Integer apiVersion);
|
||||
|
||||
/**
|
||||
* Returns the hardware name of this {@link Circuit}.
|
||||
*
|
||||
* @return the hardware name
|
||||
*/
|
||||
String getHwName();
|
||||
|
||||
/**
|
||||
* Sets the hardware name of this {@link Circuit}.
|
||||
*
|
||||
* @param hwName the new hardware name
|
||||
*/
|
||||
void setHwName(String hwName);
|
||||
|
||||
/**
|
||||
* Returns the bus member type of this {@link Circuit} as {@link Integer}.
|
||||
*
|
||||
* @return the bus member type
|
||||
*/
|
||||
Integer getBusMemberType();
|
||||
|
||||
/**
|
||||
* Sets the bus member type of this {@link Circuit} as {@link Integer}.
|
||||
*
|
||||
* @param busMemberType the new bus member type
|
||||
*/
|
||||
void setBusMemberType(Integer busMemberType);
|
||||
|
||||
/**
|
||||
* Returns true, if this {@link Circuit} has connected {@link Device}'s, otherwise false.
|
||||
*
|
||||
* @return true, if {@link Device}'s are connected
|
||||
*/
|
||||
Boolean getHasDevices();
|
||||
|
||||
/**
|
||||
* Sets the connected devices flag.
|
||||
*
|
||||
* @param hasDevices the new connected devices flag
|
||||
*/
|
||||
void setHasDevices(Boolean hasDevices);
|
||||
|
||||
/**
|
||||
* Returns true, if this {@link Circuit} is valid to metering power data, otherwise false.
|
||||
*
|
||||
* @return true, if is valid to metering power data
|
||||
*/
|
||||
Boolean getHasMetering();
|
||||
|
||||
/**
|
||||
* Sets the flag hasMetering.
|
||||
*
|
||||
* @param hasMetering the new hasMetering flag.
|
||||
*/
|
||||
void setHasMetering(Boolean hasMetering);
|
||||
|
||||
/**
|
||||
* Returns the vdc configuration URL of this {@link Circuit} as {@link String}.
|
||||
*
|
||||
* @return the vdc configuration URL
|
||||
*/
|
||||
String getVdcConfigURL();
|
||||
|
||||
/**
|
||||
* Sets the vdc configuration URL of this {@link Circuit} as {@link String}.
|
||||
*
|
||||
* @param vdcConfigURL the new vdc configuration URL
|
||||
*/
|
||||
void setVdcConfigURL(String vdcConfigURL);
|
||||
|
||||
/**
|
||||
* Returns the vdc mode UID of this {@link Circuit} as {@link String}.
|
||||
*
|
||||
* @return the vdc mode UID
|
||||
*/
|
||||
String getVdcModelUID();
|
||||
|
||||
/**
|
||||
* Sets the vdc mode UID of this {@link Circuit} as {@link String}.
|
||||
*
|
||||
* @param vdcModelUID the new vdc mode UID
|
||||
*/
|
||||
void setVdcModelUID(String vdcModelUID);
|
||||
|
||||
/**
|
||||
* Returns the vdc hardware GUID of this {@link Circuit} as {@link String}.
|
||||
*
|
||||
* @return the vdc hardware GUID
|
||||
*/
|
||||
String getVdcHardwareGuid();
|
||||
|
||||
/**
|
||||
* Sets the vdc hardware GUID of this {@link Circuit} as {@link String}.
|
||||
*
|
||||
* @param vdcHardwareGuid the new vdc hardware GUID
|
||||
*/
|
||||
void setVdcHardwareGuid(String vdcHardwareGuid);
|
||||
|
||||
/**
|
||||
* Returns the vdc hardware model GUID of this {@link Circuit} as {@link String}.
|
||||
*
|
||||
* @return the vdc hardware mode GUID
|
||||
*/
|
||||
String getVdcHardwareModelGuid();
|
||||
|
||||
/**
|
||||
* Sets the vdc hardware model GUID of this {@link Circuit} as {@link String}.
|
||||
*
|
||||
* @param vdcHardwareModelGuid the new vdc model GUID
|
||||
*/
|
||||
void setVdcHardwareModelGuid(String vdcHardwareModelGuid);
|
||||
|
||||
/**
|
||||
* Returns the vdc vendor GUID of this {@link Circuit} as {@link String}.
|
||||
*
|
||||
* @return the vdc vendor GUID
|
||||
*/
|
||||
String getVdcVendorGuid();
|
||||
|
||||
/**
|
||||
* Sets the vdc vendor GUID of this {@link Circuit} as {@link String}.
|
||||
*
|
||||
* @param vdcVendorGuid the new vdc vendor GUID
|
||||
*/
|
||||
void setVdcVendorGuid(String vdcVendorGuid);
|
||||
|
||||
/**
|
||||
* Returns the vdc oem GUID of this {@link Circuit} as {@link String}.
|
||||
*
|
||||
* @return the vdc oem GUID
|
||||
*/
|
||||
String getVdcOemGuid();
|
||||
|
||||
/**
|
||||
* Sets the vdc oem GUID of this {@link Circuit} as {@link String}.
|
||||
*
|
||||
* @param vdcOemGuid the new vdc oem GUID
|
||||
*/
|
||||
void setVdcOemGuid(String vdcOemGuid);
|
||||
|
||||
/**
|
||||
* Returns true, if actions from new {@link Device}'s will be ignored by this {@link Circuit}, otherwise false.
|
||||
*
|
||||
* @return true, if actions form new device will be ignored
|
||||
*/
|
||||
Boolean getIgnoreActionsFromNewDevices();
|
||||
|
||||
/**
|
||||
* Sets the flag for ignore actions from new {@link Device}'s.
|
||||
*
|
||||
* @param ignoreActionsFromNewDevices the new ignore actions from new devices flag
|
||||
*/
|
||||
void setIgnoreActionsFromNewDevices(Boolean ignoreActionsFromNewDevices);
|
||||
|
||||
/**
|
||||
* Adds a new {@link CachedMeteringValue} or update the existing, if the new one is newer.
|
||||
*
|
||||
* @param cachedMeteringValue the new {@link CachedMeteringValue}
|
||||
*/
|
||||
void addMeteringValue(CachedMeteringValue cachedMeteringValue);
|
||||
|
||||
/**
|
||||
* Returns the value of the given {@link CachedMeteringValue} through the {@link MeteringTypeEnum} and
|
||||
* {@link MeteringUnitsEnum}.
|
||||
*
|
||||
* @param meteringType (must not be null)
|
||||
* @param meteringUnit (can be null, default is {@link MeteringUnitsEnum#WH})
|
||||
* @return the metering value or -1, if the metering value dose not exist
|
||||
*/
|
||||
double getMeteringValue(MeteringTypeEnum meteringType, MeteringUnitsEnum meteringUnit);
|
||||
|
||||
/**
|
||||
* Returns the {@link List} of all {@link CachedMeteringValue}'s.
|
||||
*
|
||||
* @return list of all {@link CachedMeteringValue}
|
||||
*/
|
||||
List<CachedMeteringValue> getAllCachedMeteringValues();
|
||||
}
|
||||
@@ -0,0 +1,870 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.structure.devices;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.config.Config;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.event.types.EventItem;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.DeviceSceneSpec;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.DeviceStateUpdate;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.DeviceBinarayInputEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.FunctionalColorGroupEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.OutputModeEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.SensorEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.DSID;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.DeviceBinaryInput;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.DeviceSensorValue;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.scene.InternalScene;
|
||||
|
||||
/**
|
||||
* The {@link Device} represents a digitalSTROM internal stored device.
|
||||
*
|
||||
* @author Alexander Betker - Initial contribution
|
||||
* @author Michael Ochel - add methods for ESH, new functionalities and JavaDoc
|
||||
* @author Mathias Siegele - add methods for ESH, new functionalities and JavaDoc
|
||||
*/
|
||||
public interface Device extends GeneralDeviceInformation {
|
||||
|
||||
/**
|
||||
* Returns the id of the dS-Meter in which the device is registered.
|
||||
*
|
||||
* @return meterDSID
|
||||
*/
|
||||
DSID getMeterDSID();
|
||||
|
||||
/**
|
||||
* Sets the id of the dS-Meter in which the device is registered.
|
||||
*
|
||||
* @param meterDSID to set
|
||||
*/
|
||||
|
||||
void setMeterDSID(String meterDSID);
|
||||
|
||||
/**
|
||||
* Returns the hardware info of this device.
|
||||
* You can see all available hardware info at
|
||||
* http://www.digitalstrom.com/Partner/Support/Techn-Dokumentation/
|
||||
*
|
||||
* @return hardware info
|
||||
*/
|
||||
String getHWinfo();
|
||||
|
||||
/**
|
||||
* Returns the zone id in which this device is in.
|
||||
*
|
||||
* @return zoneID
|
||||
*/
|
||||
int getZoneId();
|
||||
|
||||
/**
|
||||
* Sets the zoneID of this device.
|
||||
*
|
||||
* @param zoneID to set
|
||||
*/
|
||||
void setZoneId(int zoneID);
|
||||
|
||||
/**
|
||||
* Returns true, if this device is on, otherwise false.
|
||||
*
|
||||
* @return is on (true = on | false = off)
|
||||
*/
|
||||
boolean isOn();
|
||||
|
||||
/**
|
||||
* Adds an on command as {@link DeviceStateUpdate}, if the flag is true or off command, if it is false to the list
|
||||
* of
|
||||
* outstanding commands.
|
||||
*
|
||||
* @param flag (true = on | false = off)
|
||||
*/
|
||||
void setIsOn(boolean flag);
|
||||
|
||||
/**
|
||||
* Returns true, if this shade device is open, otherwise false.
|
||||
*
|
||||
* @return is on (true = open | false = closed)
|
||||
*/
|
||||
boolean isOpen();
|
||||
|
||||
/**
|
||||
* Adds an open command as {@link DeviceStateUpdate}, if the flag is true or closed command, if it is false to the
|
||||
* list of outstanding commands.
|
||||
*
|
||||
* @param flag (true = open | false = closed)
|
||||
*/
|
||||
void setIsOpen(boolean flag);
|
||||
|
||||
/**
|
||||
* Returns true, if this device is dimmable, otherwise false.
|
||||
*
|
||||
* @return is dimmable (true = yes | false = no)
|
||||
*/
|
||||
boolean isDimmable();
|
||||
|
||||
/**
|
||||
* Returns true, if this device is a shade device (grey), otherwise false.
|
||||
*
|
||||
* @return is shade (true = yes | false = no)
|
||||
*/
|
||||
boolean isShade();
|
||||
|
||||
/**
|
||||
* Returns true, if the device output mode isn't disabled.
|
||||
*
|
||||
* @return have output mode (true = yes | false = no)
|
||||
*/
|
||||
boolean isDeviceWithOutput();
|
||||
|
||||
/**
|
||||
* Returns the current functional color group of this device.
|
||||
* For more informations please have a look at {@link FunctionalColorGroupEnum}.
|
||||
*
|
||||
* @return current functional color group
|
||||
*/
|
||||
FunctionalColorGroupEnum getFunctionalColorGroup();
|
||||
|
||||
/**
|
||||
* Sets the functional color group of this device.
|
||||
*
|
||||
* @param fuctionalColorGroup to set
|
||||
*/
|
||||
void setFunctionalColorGroup(FunctionalColorGroupEnum fuctionalColorGroup);
|
||||
|
||||
/**
|
||||
* Returns the current output mode of this device.
|
||||
* Some devices are able to have different output modes e.g. the device GE-KM200 is able to
|
||||
* be in dimm mode, switch mode or disabled.
|
||||
* For more informations please have a look at {@link OutputModeEnum}.
|
||||
*
|
||||
* @return the current output mode of this device
|
||||
*/
|
||||
OutputModeEnum getOutputMode();
|
||||
|
||||
/**
|
||||
* Adds an increase command as {@link DeviceStateUpdate} to the list of outstanding commands.
|
||||
*/
|
||||
void increase();
|
||||
|
||||
/**
|
||||
* Adds an decrease command as {@link DeviceStateUpdate} to the list of outstanding commands.
|
||||
*/
|
||||
void decrease();
|
||||
|
||||
/**
|
||||
* Returns the current slat position of this device.
|
||||
*
|
||||
* @return current slat position
|
||||
*/
|
||||
int getSlatPosition();
|
||||
|
||||
/**
|
||||
* Adds an set slat position command as {@link DeviceStateUpdate} with the given slat position to the list of
|
||||
* outstanding commands.
|
||||
*
|
||||
* @param slatPosition to set
|
||||
*/
|
||||
void setSlatPosition(int slatPosition);
|
||||
|
||||
/**
|
||||
* Returns the maximal slat position value of this device.
|
||||
*
|
||||
* @return maximal slat position value
|
||||
*/
|
||||
int getMaxSlatPosition();
|
||||
|
||||
/**
|
||||
* Returns the minimal slat position value of this device.
|
||||
*
|
||||
* @return minimal slat position value
|
||||
*/
|
||||
int getMinSlatPosition();
|
||||
|
||||
/**
|
||||
* Returns the current output value of this device.
|
||||
* This can be the slat position or the brightness of this device.
|
||||
*
|
||||
* @return current output value
|
||||
*/
|
||||
short getOutputValue();
|
||||
|
||||
/**
|
||||
* Adds an set output value command as {@link DeviceStateUpdate} with the given output value to the list of
|
||||
* outstanding commands.
|
||||
*
|
||||
* @param outputValue to set
|
||||
*/
|
||||
void setOutputValue(short outputValue);
|
||||
|
||||
/**
|
||||
* Returns the maximal output value of this device.
|
||||
*
|
||||
* @return maximal output value
|
||||
*/
|
||||
short getMaxOutputValue();
|
||||
|
||||
/**
|
||||
* Returns a list with group id's in which the device is part of.
|
||||
*
|
||||
* @return List of group id's
|
||||
*/
|
||||
List<Short> getGroups();
|
||||
|
||||
/**
|
||||
* Adds the given groupID to the group list.
|
||||
*
|
||||
* @param groupID to add
|
||||
*/
|
||||
void addGroup(Short groupID);
|
||||
|
||||
/**
|
||||
* Overrides the existing group list with the given new.
|
||||
*
|
||||
* @param newGroupList to set
|
||||
*/
|
||||
void setGroups(List<Short> newGroupList);
|
||||
|
||||
/**
|
||||
* Returns the scene output value of this device of the given scene id as {@link Integer} array. The first field is
|
||||
* the output value and the second is the angle value or -1 if no angle value exists.
|
||||
* If the method returns null, this scene id isn't read yet.
|
||||
*
|
||||
* @param sceneID of the scene
|
||||
* @return scene output value and scene angle value or null, if it isn't read out yet
|
||||
*/
|
||||
Integer[] getSceneOutputValue(short sceneID);
|
||||
|
||||
/**
|
||||
* Sets the scene output value of this device for the given scene id and scene output value.
|
||||
*
|
||||
* @param sceneId to set
|
||||
* @param sceneOutputValue to set
|
||||
*/
|
||||
void setSceneOutputValue(short sceneId, int sceneOutputValue);
|
||||
|
||||
/**
|
||||
* This configuration is very important. The devices can
|
||||
* be configured to not react to some commands (scene calls).
|
||||
* So you can't imply that a device automatically turns on (by default yes,
|
||||
* but if someone configured his own scenes, then maybe not) after a
|
||||
* scene call. This method returns true or false, if the configuration
|
||||
* for this sceneID already has been read
|
||||
*
|
||||
* @param sceneId the sceneID
|
||||
* @return true if this device has the configuration for this specific scene
|
||||
*/
|
||||
boolean containsSceneConfig(short sceneId);
|
||||
|
||||
/**
|
||||
* Add the config for this scene. The config has the configuration
|
||||
* for the specific sceneID.
|
||||
*
|
||||
* @param sceneId scene call id
|
||||
* @param sceneSpec config for this sceneID
|
||||
*/
|
||||
void addSceneConfig(short sceneId, DeviceSceneSpec sceneSpec);
|
||||
|
||||
/**
|
||||
* Get the config for this scene. The config has the configuration
|
||||
* for the specific sceneID.
|
||||
*
|
||||
* @param sceneId scene call id
|
||||
* @return sceneSpec config for this sceneID
|
||||
*/
|
||||
DeviceSceneSpec getSceneConfig(short sceneId);
|
||||
|
||||
/**
|
||||
* Should the device react on this scene call or not .
|
||||
*
|
||||
* @param sceneId scene call id
|
||||
* @return true, if this device should react on this sceneID
|
||||
*/
|
||||
boolean doIgnoreScene(short sceneId);
|
||||
|
||||
// follow methods added by Michael Ochel and Matthias Siegele
|
||||
/**
|
||||
* Returns true, if all sensor data are up to date or false if some have to be updated.
|
||||
*
|
||||
* @return is up to date (true = yes | false = no)
|
||||
*/
|
||||
boolean isSensorDataUpToDate();
|
||||
|
||||
/**
|
||||
* Sets the priority to refresh the data of the sensors to the given priorities.
|
||||
* They can be never, low, medium or high.
|
||||
*
|
||||
* @param powerConsumptionRefreshPriority to set
|
||||
* @param electricMeterRefreshPriority to set
|
||||
* @param energyMeterRefreshPriority to set
|
||||
*/
|
||||
void setSensorDataRefreshPriority(String powerConsumptionRefreshPriority, String electricMeterRefreshPriority,
|
||||
String energyMeterRefreshPriority);
|
||||
|
||||
/**
|
||||
* Returns true, if the device is up to date.
|
||||
*
|
||||
* @return digitalSTROM-Device is up to date (true = yes | false = no)
|
||||
*/
|
||||
boolean isDeviceUpToDate();
|
||||
|
||||
/**
|
||||
* Returns the next {@link DeviceStateUpdate} to update the digitalSTROM-Device on the digitalSTROM-Server.
|
||||
*
|
||||
* @return DeviceStateUpdate for digitalSTROM-Device
|
||||
*/
|
||||
DeviceStateUpdate getNextDeviceUpdateState();
|
||||
|
||||
/**
|
||||
* Update the internal stored device object.
|
||||
*
|
||||
* @param deviceStateUpdate to update
|
||||
*/
|
||||
void updateInternalDeviceState(DeviceStateUpdate deviceStateUpdate);
|
||||
|
||||
/**
|
||||
* Call the given {@link InternalScene} on this {@link Device} and updates it.
|
||||
*
|
||||
* @param scene to call
|
||||
*/
|
||||
void callInternalScene(InternalScene scene);
|
||||
|
||||
/**
|
||||
* Undo the given {@link InternalScene} on this {@link Device} and updates it.
|
||||
*
|
||||
* @param scene to undo
|
||||
*/
|
||||
void undoInternalScene(InternalScene scene);
|
||||
|
||||
/**
|
||||
* Initial a call scene for the given scene number.
|
||||
*
|
||||
* @param sceneNumber to call
|
||||
*/
|
||||
void callScene(Short sceneNumber);
|
||||
|
||||
/**
|
||||
* Returns the current active {@link InternalScene}, otherwise null.
|
||||
*
|
||||
* @return active {@link InternalScene} or null
|
||||
*/
|
||||
InternalScene getAcitiveScene();
|
||||
|
||||
/**
|
||||
* Undo the active scene if a scene is active.
|
||||
*/
|
||||
void undoScene();
|
||||
|
||||
/**
|
||||
* Checks the scene configuration for the given scene number and initial a scene configuration reading with the
|
||||
* given priority if no scene configuration exists.
|
||||
*
|
||||
* @param sceneNumber to check
|
||||
* @param prio to update
|
||||
*/
|
||||
void checkSceneConfig(Short sceneNumber, short prio);
|
||||
|
||||
/**
|
||||
* Sets the given output mode as new output mode of this {@link Device}.
|
||||
*
|
||||
* @param newOutputMode to set
|
||||
*/
|
||||
void setOutputMode(OutputModeEnum newOutputMode);
|
||||
|
||||
/**
|
||||
* Returns a {@link List} of all saved scene-IDs configurations.
|
||||
*
|
||||
* @return a {@link List} of all saved scene-IDs
|
||||
*/
|
||||
List<Short> getSavedScenes();
|
||||
|
||||
/**
|
||||
* Initializes a internal device update as call scene for the given scene number.
|
||||
*
|
||||
* @param sceneNumber to call
|
||||
*/
|
||||
void internalCallScene(Short sceneNumber);
|
||||
|
||||
/**
|
||||
* Initializes a internal device update as undo scene.
|
||||
*/
|
||||
void internalUndoScene();
|
||||
|
||||
/**
|
||||
* Returns true, if this {@link Device} is a device with a switch output mode.
|
||||
*
|
||||
* @return true, if it is a switch otherwise false
|
||||
*/
|
||||
boolean isSwitch();
|
||||
|
||||
/**
|
||||
* Sets the given {@link Config} as new {@link Config}.
|
||||
*
|
||||
* @param config to set
|
||||
*/
|
||||
void setConfig(Config config);
|
||||
|
||||
/**
|
||||
* Returns the current angle position of the {@link Device}.
|
||||
*
|
||||
* @return current angle position
|
||||
*/
|
||||
short getAnglePosition();
|
||||
|
||||
/**
|
||||
* Adds an set angle value command as {@link DeviceStateUpdate} with the given angle value to the list of
|
||||
* outstanding commands.
|
||||
*
|
||||
* @param angle to set
|
||||
*/
|
||||
void setAnglePosition(int angle);
|
||||
|
||||
/**
|
||||
* Sets the scene output value and scene output angle of this device for the given scene id, scene output value and
|
||||
* scene output angle.
|
||||
*
|
||||
* @param sceneId to set
|
||||
* @param value to set
|
||||
* @param angle to set
|
||||
*/
|
||||
void setSceneOutputValue(short sceneId, int value, int angle);
|
||||
|
||||
/**
|
||||
* Returns the max angle value of the slat.
|
||||
*
|
||||
* @return max slat angle
|
||||
*/
|
||||
int getMaxSlatAngle();
|
||||
|
||||
/**
|
||||
* Returns the min angle value of the slat.
|
||||
*
|
||||
* @return min slat angle
|
||||
*/
|
||||
int getMinSlatAngle();
|
||||
|
||||
/**
|
||||
* Returns true, if it is a blind device.
|
||||
*
|
||||
* @return is blind (true = yes | false = no
|
||||
*/
|
||||
boolean isBlind();
|
||||
|
||||
/**
|
||||
* Saves scene configurations from the given sceneProperties in the {@link Device}. <br>
|
||||
* The {@link Map} has to be like the following format:
|
||||
* <ul>
|
||||
* <li><b>Key:</b> scene[sceneID]</li>
|
||||
* <li><b>Value:</b> {Scene: [sceneID], dontcare: [don't care flag], localPrio: [local prio flag], specialMode:
|
||||
* [special mode flag]}(0..1), {sceneValue: [scene value], sceneAngle: [scene angle]}(0..1))</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param sceneProperties to save
|
||||
*/
|
||||
void saveConfigSceneSpecificationIntoDevice(Map<String, String> sceneProperties);
|
||||
|
||||
/**
|
||||
* Returns the min output value.
|
||||
*
|
||||
* @return min output value
|
||||
*/
|
||||
short getMinOutputValue();
|
||||
|
||||
/**
|
||||
* Adds a slat increase command as {@link DeviceStateUpdate} to the list of outstanding commands.
|
||||
*/
|
||||
void increaseSlatAngle();
|
||||
|
||||
/**
|
||||
* Adds a slat decrease command as {@link DeviceStateUpdate} to the list of outstanding commands.
|
||||
*/
|
||||
void decreaseSlatAngle();
|
||||
|
||||
/**
|
||||
* Saves scene configurations from the given sceneProperties in the {@link Device}. <br>
|
||||
* <br>
|
||||
* <b>The {@link String} has to be like the following format:</b><br>
|
||||
* {[sceneID] = }(1){Scene: [sceneID], dontcare: [don't care flag], localPrio: [local prio flag], specialMode:
|
||||
* [special mode flag]}(0..1), {sceneValue: [sceneValue]{, sceneAngle: [scene angle]}(0..1)}{\n}(0..1)<br>
|
||||
* <br>
|
||||
* e.g. "10 = Scene: PRESET_4, dontcare: false, localPrio: false, specialMode: false, flashMode: false, sceneValue:
|
||||
* 0\n"
|
||||
*
|
||||
* @param propertries to save
|
||||
*/
|
||||
void saveConfigSceneSpecificationIntoDevice(String propertries);
|
||||
|
||||
/**
|
||||
* Returns true, if this {@link Device} is a sensor device. That means, that this {@link Device} has no output
|
||||
* channel
|
||||
* ({@link OutputModeEnum#DISABLED}), but climate sensors.
|
||||
*
|
||||
* @return true, if it is a sensor device
|
||||
*/
|
||||
boolean isSensorDevice();
|
||||
|
||||
/**
|
||||
* Returns true, if this {@link Device} is a heating device. That means, that the output mode of this {@link Device}
|
||||
* is one of the following modes {@link OutputModeEnum#PWM} or {@link OutputModeEnum#SWITCH} and the
|
||||
* {@link FuncNameAndColorGroupEnum} is {@link FuncNameAndColorGroupEnum#HEATING}.
|
||||
*
|
||||
* @return true, if it is a heating device
|
||||
*/
|
||||
boolean isHeatingDevice();
|
||||
|
||||
/**
|
||||
* Sets the refresh priority for the given power sensor as {@link SensorEnum}. <br>
|
||||
* <b>Note:</b><br>
|
||||
* 1. The device must have this sensor type, otherwise the set has no effect.<br>
|
||||
* <br>
|
||||
* 2. Valid priorities are:<br>
|
||||
* - {@link Config#REFRESH_PRIORITY_NEVER}<br>
|
||||
* - {@link Config#REFRESH_PRIORITY_LOW}<br>
|
||||
* - {@link Config#REFRESH_PRIORITY_MEDIUM}<br>
|
||||
* - {@link Config#REFRESH_PRIORITY_HIGH}<br>
|
||||
* <br>
|
||||
* 3. Valid sensor types are:<br>
|
||||
* - {@link SensorEnum#POWER_CONSUMPTION}<br>
|
||||
* - {@link SensorEnum#OUTPUT_CURRENT}<br>
|
||||
* - {@link SensorEnum#ELECTRIC_METER}<br>
|
||||
* - {@link SensorEnum#ACTIVE_POWER}<br>
|
||||
*
|
||||
* @param powerSensorType the power sensor to set
|
||||
* @param refreshPriority the new refresh priority
|
||||
*/
|
||||
void setSensorDataRefreshPriority(SensorEnum powerSensorType, String refreshPriority);
|
||||
|
||||
/**
|
||||
* Returns the refresh priority of the given power sensor type as {@link SensorEnum}. If the sensor type is not
|
||||
* supported by
|
||||
* this {@link Device} or it is not a power sensor it will be returned null.
|
||||
*
|
||||
* @param powerSensorType of the sensor
|
||||
* @return the refresh priority
|
||||
*/
|
||||
String getPowerSensorRefreshPriority(SensorEnum powerSensorType);
|
||||
|
||||
/**
|
||||
* Returns a {@link List} with all power sensors, which are supported by this {@link Device}.
|
||||
*
|
||||
* @return all supported power sensors
|
||||
*/
|
||||
List<SensorEnum> getPowerSensorTypes();
|
||||
|
||||
/**
|
||||
* Returns a {@link List} with all climate sensors, which are supported by this {@link Device}.
|
||||
*
|
||||
* @return all supported climate sensors
|
||||
*/
|
||||
List<SensorEnum> getClimateSensorTypes();
|
||||
|
||||
/**
|
||||
* Returns all {@link DeviceSensorValue}'s of this {@link Device}.
|
||||
*
|
||||
* @return list of all {@link DeviceSensorValue}'s
|
||||
*/
|
||||
List<DeviceSensorValue> getDeviceSensorValues();
|
||||
|
||||
/**
|
||||
* Sets the given {@link DeviceSensorValue}. That means the given {@link DeviceSensorValue} will be added, if this
|
||||
* type of {@link DeviceSensorValue} does not exist before, otherwise the existing {@link DeviceSensorValue} will be
|
||||
* updated,
|
||||
* if the given {@link DeviceSensorValue} is newer.
|
||||
*
|
||||
* @param deviceSensorValue the new device sensor value
|
||||
*/
|
||||
void setDeviceSensorValue(DeviceSensorValue deviceSensorValue);
|
||||
|
||||
/**
|
||||
* Returns the {@link DeviceSensorValue} of the given sensor type as {@link SensorEnum} or null, if no
|
||||
* {@link DeviceSensorValue} exists for the given sensor type.
|
||||
*
|
||||
* @param sensorType of the sensor
|
||||
* @return the {@link DeviceSensorValue} or null
|
||||
*/
|
||||
DeviceSensorValue getDeviceSensorValue(SensorEnum sensorType);
|
||||
|
||||
/**
|
||||
* Returns the {@link DeviceSensorValue} of the given sensor index as {@link Short} or null, if no
|
||||
* {@link DeviceSensorValue} exists for the given sensor index.
|
||||
*
|
||||
* @param sensorIndex of the sensor
|
||||
* @return the {@link DeviceSensorValue} or null
|
||||
*/
|
||||
DeviceSensorValue getDeviceSensorValue(Short sensorIndex);
|
||||
|
||||
/**
|
||||
* Returns the sensor index for the given sensor type as {@link SensorEnum} of the {@link Device} or null, if the
|
||||
* sensor type does not exist. It will be needed to readout the current sensor value of the digitalSTROM device.
|
||||
*
|
||||
* @param sensorType of the sensor
|
||||
* @return sensor index for the sensor type
|
||||
*/
|
||||
Short getSensorIndex(SensorEnum sensorType);
|
||||
|
||||
/**
|
||||
* Returns the sensor type as {@link SensorEnum} of the given sensor index or null, if the given sensor type does
|
||||
* not exist.
|
||||
*
|
||||
* @param sensorIndex of the sensor
|
||||
* @return the sensor type or null
|
||||
*/
|
||||
SensorEnum getSensorType(Short sensorIndex);
|
||||
|
||||
/**
|
||||
* Returns the internal digitalSTROM sensor value for the given sensor type as {@link SensorEnum}, if the sensor
|
||||
* type exists and the value is valid. The resolution can be found at {@link SensorEnum}.
|
||||
*
|
||||
* @param sensorType of the sensor
|
||||
* @return the internal digitalSTROM sensor value or null
|
||||
*/
|
||||
Integer getDsSensorValue(SensorEnum sensorType);
|
||||
|
||||
/**
|
||||
* Returns the internal digitalSTROM sensor value for the given sensor index as {@link Short}, if the sensor
|
||||
* index exists and the value is valid. The resolution can be found at {@link SensorEnum}.
|
||||
*
|
||||
* @param sensorIndex of the sensor
|
||||
* @return the internal digitalSTROM sensor value or null
|
||||
*/
|
||||
Integer getDsSensorValue(Short sensorIndex);
|
||||
|
||||
/**
|
||||
* Returns the float sensor value for the given sensor type as {@link SensorEnum}, if the sensor
|
||||
* type exists and the value is valid. The resolution can be found at {@link SensorEnum}.
|
||||
*
|
||||
* @param sensorType of the sensor
|
||||
* @return the float sensor value or null
|
||||
*/
|
||||
Float getFloatSensorValue(SensorEnum sensorType);
|
||||
|
||||
/**
|
||||
* Returns the float sensor value for the given sensor index as {@link Short}, if the sensor
|
||||
* index exists and the value is valid. The resolution can be found at {@link SensorEnum}.
|
||||
*
|
||||
* @param sensorIndex of the sensor
|
||||
* @return the float sensor value or null
|
||||
*/
|
||||
Float getFloatSensorValue(Short sensorIndex);
|
||||
|
||||
/**
|
||||
* Sets the float sensor value for a given sensor type as {@link SensorEnum}. If the sensor type does not exist, it
|
||||
* will be returned false.
|
||||
*
|
||||
* @param sensorType of the sensor
|
||||
* @param floatSensorValue the new float sensor value
|
||||
* @return true, if it was successful, otherwise false
|
||||
*/
|
||||
boolean setFloatSensorValue(SensorEnum sensorType, Float floatSensorValue);
|
||||
|
||||
/**
|
||||
* Sets the float sensor value for a given sensor index as {@link Short}. If the sensor type does not exist, it
|
||||
* will be returned false.
|
||||
*
|
||||
* @param sensorIndex of the sensor
|
||||
* @param floatSensorValue the new float sensor value
|
||||
* @return true, if it was successful, otherwise false
|
||||
*/
|
||||
boolean setFloatSensorValue(Short sensorIndex, Float floatSensorValue);
|
||||
|
||||
/**
|
||||
* Sets the internal digitalSTROM sensor value for a given sensor index as {@link Short}. If the sensor index does
|
||||
* not exist, it will be returned false.
|
||||
*
|
||||
* @param sensorIndex of the sensor
|
||||
* @param dSSensorValue the new internal digitalSTROM sensor value
|
||||
* @return true, if it was successful, otherwise false
|
||||
*/
|
||||
boolean setDsSensorValue(Short sensorIndex, Integer dSSensorValue);
|
||||
|
||||
/**
|
||||
* Sets the internal digitalSTROM sensor value for a given sensor type as {@link SensorEnum}. If the sensor type
|
||||
* does
|
||||
* not exist, it will be returned false.
|
||||
*
|
||||
* @param sensorType of the sensor
|
||||
* @param dSSensorValue the new internal digitalSTROM sensor value
|
||||
* @return true, if it was successful, otherwise false
|
||||
*/
|
||||
boolean setDsSensorValue(SensorEnum sensorType, Integer dSSensorValue);
|
||||
|
||||
/**
|
||||
* Sets the internal digitalSTROM and float sensor value for a given sensor index as {@link Short}. If the sensor
|
||||
* index does not exist, it will be returned false.
|
||||
*
|
||||
* @param sensorIndex of the sensor
|
||||
* @param dSSensorValue the new internal digitalSTROM sensor value
|
||||
* @param floatSensorValue the new float sensor value
|
||||
* @return true, if it was successful, otherwise false
|
||||
*/
|
||||
boolean setDsSensorValue(Short sensorIndex, Integer dSSensorValue, Float floatSensorValue);
|
||||
|
||||
/**
|
||||
* Sets the internal digitalSTROM and float sensor value for a given sensor type as {@link SensorEnum}. If the
|
||||
* sensor type does not exist, it will be returned false.
|
||||
*
|
||||
* @param sensorType of the sensor
|
||||
* @param dSSensorValue the new internal digitalSTROM sensor value
|
||||
* @param floatSensorValue the new float sensor value
|
||||
* @return true, if it was successful, otherwise false
|
||||
*/
|
||||
boolean setDsSensorValue(SensorEnum sensorType, Integer dSSensorValue, Float floatSensorValue);
|
||||
|
||||
/**
|
||||
* Returns true, if this {@link Device} has sensors, otherwise false.
|
||||
*
|
||||
* @return true, if device has sensors
|
||||
*/
|
||||
boolean hasSensors();
|
||||
|
||||
/**
|
||||
* Returns true, if this {@link Device} has climate sensors, otherwise false.
|
||||
*
|
||||
* @return true, if device has climate sensors
|
||||
*/
|
||||
boolean hasClimateSensors();
|
||||
|
||||
/**
|
||||
* Returns true, if this {@link Device} has power sensors, otherwise false.
|
||||
*
|
||||
* @return true, if device has power sensors
|
||||
*/
|
||||
boolean hasPowerSensors();
|
||||
|
||||
/**
|
||||
* Only needed for {@link DeviceConsumptionSensorJob}'s. To set the internal digitalSTROM sensor value please use
|
||||
* {@link #setDsSensorValue(SensorEnum, Integer)}.
|
||||
*
|
||||
* @param sensorType of the sensor
|
||||
* @param value new value
|
||||
*/
|
||||
void setDeviceSensorDsValueBySensorJob(SensorEnum sensorType, Integer value);
|
||||
|
||||
/**
|
||||
* Enables the internal sensor echo box for {@link EventNames#DEVICE_SENSOR_VALUE} events.
|
||||
*/
|
||||
void enableSensorEchoBox();
|
||||
|
||||
/**
|
||||
* Disables the internal sensor echo box for {@link EventNames#DEVICE_SENSOR_VALUE} events.
|
||||
*/
|
||||
void disableSensorEchoBox();
|
||||
|
||||
/**
|
||||
* Returns true, if the internal sensor echo box is enabled, otherwise false.
|
||||
*
|
||||
* @return true, if the internal sensor echo box is enabled
|
||||
*/
|
||||
boolean isSensorEchoBoxEnabled();
|
||||
|
||||
/**
|
||||
* Sets the {@link DeviceSensorValue} through a {@link EventItem} of the type
|
||||
* {@link EventNames#DEVICE_SENSOR_VALUE}.
|
||||
*
|
||||
* @param event of the sensor update
|
||||
*/
|
||||
void setDeviceSensorByEvent(EventItem event);
|
||||
|
||||
/**
|
||||
* Returns true, if the refresh priority of the given power sensor type as {@link SensorEnum} is equals
|
||||
* {@link Config#REFRESH_PRIORITY_NEVER}, otherwise false.
|
||||
*
|
||||
* @param powerSensorType of the sensor
|
||||
* @return true, if refresh priority is never
|
||||
*/
|
||||
boolean checkPowerSensorRefreshPriorityNever(SensorEnum powerSensorType);
|
||||
|
||||
/**
|
||||
* Returns true, if the given sensor type as {@link SensorEnum} is supported by this {@link Device}, otherwise
|
||||
* false.
|
||||
*
|
||||
* @param sensorType of the sensor
|
||||
* @return true, if the sensor type is supported
|
||||
*/
|
||||
boolean supportsSensorType(SensorEnum sensorType);
|
||||
|
||||
/**
|
||||
* Returns true, if this {@link Device} is a temperature controlled device, otherwise false. That means, that the
|
||||
* output mode is one of the output modes in
|
||||
* {@link OutputModeEnum#outputModeIsTemperationControlled(OutputModeEnum)}.
|
||||
*
|
||||
* @return true, if this {@link Device} is a temperature controlled
|
||||
*/
|
||||
boolean isTemperatureControlledDevice();
|
||||
|
||||
/**
|
||||
* Returns true, if this {@link Device} is a binary input device. That means it have no output mode
|
||||
* ({@link OutputModeEnum#DISABLED}), but {@link DeviceBinaryInput}'s.
|
||||
*
|
||||
* @return true, if this {@link Device} is a binary input device
|
||||
*/
|
||||
boolean isBinaryInputDevice();
|
||||
|
||||
/**
|
||||
* Returns a {@link List} which contains all currently configured {@link DeviceBinaryInput}'s.
|
||||
*
|
||||
* @return list with all configured {@link DeviceBinaryInput}'s
|
||||
*/
|
||||
List<DeviceBinaryInput> getBinaryInputs();
|
||||
|
||||
/**
|
||||
* Returns the {@link DeviceBinaryInput} of the given binary input type as {@link DeviceBinarayInputEnum}} or null,
|
||||
* if the binary input type does not exist.
|
||||
*
|
||||
* @param binaryInputType of the {@link DeviceBinaryInput}
|
||||
* @return the {@link DeviceBinaryInput} or null
|
||||
*/
|
||||
DeviceBinaryInput getBinaryInput(DeviceBinarayInputEnum binaryInputType);
|
||||
|
||||
/**
|
||||
* Returns the state of the given binary input type as {@link DeviceBinarayInputEnum}} or null, if the binary input
|
||||
* type does not exist.
|
||||
*
|
||||
* @param binaryInputType of the {@link DeviceBinaryInput}
|
||||
* @return state of the given binary input type or null
|
||||
*/
|
||||
Short getBinaryInputState(DeviceBinarayInputEnum binaryInputType);
|
||||
|
||||
/**
|
||||
* Sets the state of an existing {@link DeviceBinaryInput}. If the given {@link DeviceBinarayInputEnum} does not
|
||||
* exist, it will returned false, otherwise true.
|
||||
*
|
||||
* @param binaryInputType of the {@link DeviceBinaryInput}
|
||||
* @param newState the new state
|
||||
* @return true, if it was successful, otherwise false
|
||||
*/
|
||||
boolean setBinaryInputState(DeviceBinarayInputEnum binaryInputType, Short newState);
|
||||
|
||||
/**
|
||||
* Sets the given {@link List} of {@link DeviceBinaryInput}'s as supported binary inputs.
|
||||
*
|
||||
* @param newBinaryInputs to set
|
||||
*/
|
||||
void setBinaryInputs(List<DeviceBinaryInput> newBinaryInputs);
|
||||
|
||||
/**
|
||||
* Returns true, if the given power sensor type as {@link SensorEnum} is up to date and does not need a refresh,
|
||||
* otherwise it will returned false.
|
||||
*
|
||||
* @param powerSensorType of the sensor
|
||||
* @return true, if the power sensor is up to date
|
||||
*/
|
||||
boolean isPowerSensorUpToDate(SensorEnum powerSensorType);
|
||||
|
||||
/**
|
||||
* Returns a {@link List} of all supported sensor types as {@link SensorEnum}.
|
||||
*
|
||||
* @return all supported sensor types
|
||||
*/
|
||||
List<SensorEnum> getSensorTypes();
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.structure.devices;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.listener.DeviceStatusListener;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.DSID;
|
||||
|
||||
/**
|
||||
* The {@link GeneralDeviceInformations} interface contains all informations of digitalSTROM devices, which are
|
||||
* identical for all device types. It also contains the methods to implement the mechanism of the
|
||||
* {@link DeviceStatusListener}.
|
||||
*
|
||||
* @author Michael Ochel - initial contributer
|
||||
* @author Matthias Siegele - initial contributer
|
||||
*/
|
||||
public interface GeneralDeviceInformation {
|
||||
|
||||
/**
|
||||
* Returns the user defined name of this device.
|
||||
*
|
||||
* @return name of this device
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Sets the name of this device;
|
||||
*
|
||||
* @param name to set
|
||||
*/
|
||||
void setName(String name);
|
||||
|
||||
/**
|
||||
* Returns the dSID of this device.
|
||||
*
|
||||
* @return {@link DSID} dSID
|
||||
*/
|
||||
DSID getDSID();
|
||||
|
||||
/**
|
||||
* Returns the dSUID of this device.
|
||||
*
|
||||
* @return dSID
|
||||
*/
|
||||
String getDSUID();
|
||||
|
||||
/**
|
||||
* This device is available in his zone or not.
|
||||
* Every 24h the dSM (meter) checks, if the devices are
|
||||
* plugged in
|
||||
*
|
||||
* @return true, if device is available otherwise false
|
||||
*/
|
||||
Boolean isPresent();
|
||||
|
||||
/**
|
||||
* Sets this device is available in his zone or not.
|
||||
*
|
||||
* @param isPresent (true = available | false = not available)
|
||||
*/
|
||||
void setIsPresent(boolean isPresent);
|
||||
|
||||
/**
|
||||
* Register a {@link DeviceStatusListener} to this {@link Device}.
|
||||
*
|
||||
* @param deviceStatuslistener to register
|
||||
*/
|
||||
void registerDeviceStatusListener(DeviceStatusListener deviceStatuslistener);
|
||||
|
||||
/**
|
||||
* Unregister the {@link DeviceStatusListener} to this {@link Device} if it exists.
|
||||
*
|
||||
* @return the unregistered {@link DeviceStatusListener} or null if no one was registered
|
||||
*/
|
||||
DeviceStatusListener unregisterDeviceStatusListener();
|
||||
|
||||
/**
|
||||
* Returns true, if a {@link DeviceStatusListener} is registered to this {@link Device}, otherwise false.
|
||||
*
|
||||
* @return return true, if a lister is registered, otherwise false
|
||||
*/
|
||||
boolean isListenerRegisterd();
|
||||
|
||||
/**
|
||||
* Returns true, if this device is valid, otherwise false.
|
||||
*
|
||||
* @return true, if valid
|
||||
*/
|
||||
Boolean isValid();
|
||||
|
||||
/**
|
||||
* Sets the valid state.
|
||||
*
|
||||
* @param isValid the new valid state
|
||||
*/
|
||||
void setIsValid(boolean isValid);
|
||||
|
||||
/**
|
||||
* Returns the in the digitalSTROM web interface displayed dSID.
|
||||
*
|
||||
* @return displayed dSID
|
||||
*/
|
||||
String getDisplayID();
|
||||
|
||||
/**
|
||||
* Returns the registered {@link DeviceStatusListener} or null, if no {@link DeviceStatusListener} is registered
|
||||
*
|
||||
* @return the registered {@link DeviceStatusListener} or null
|
||||
*/
|
||||
DeviceStatusListener getDeviceStatusListener();
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.structure.devices.deviceparameters;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.MeteringTypeEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.MeteringUnitsEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.DSID;
|
||||
|
||||
/**
|
||||
* The {@link CachedMeteringValue} saves the metering value of an digitalSTROM-Circuit.
|
||||
*
|
||||
* @author Alexander Betker - Initial contribution
|
||||
* @author Michael Ochel - add methods getDateAsDate(), getMeteringType() and getMeteringUnit(); add missing java-doc
|
||||
* @author Matthias Siegele - add methods getDateAsDate(), getMeteringType() and getMeteringUnit(); add missing java-doc
|
||||
*/
|
||||
public interface CachedMeteringValue {
|
||||
|
||||
/**
|
||||
* Returns the {@link DSID} of the digitalSTROM-Circuit.
|
||||
*
|
||||
* @return dSID of circuit
|
||||
*/
|
||||
DSID getDsid();
|
||||
|
||||
/**
|
||||
* Returns the saved sensor value.
|
||||
*
|
||||
* @return sensor value
|
||||
*/
|
||||
double getValue();
|
||||
|
||||
/**
|
||||
* Returns the timestamp when the sensor value was read out as {@link String}.
|
||||
*
|
||||
* @return read out timestamp
|
||||
*/
|
||||
String getDate();
|
||||
|
||||
/**
|
||||
* Returns the timestamp when the sensor value was read out as {@link Date}.
|
||||
*
|
||||
* @return read out timestamp
|
||||
*/
|
||||
Date getDateAsDate();
|
||||
|
||||
/**
|
||||
* Returns the {@link MeteringTypeEnum} of this {@link CachedMeteringValue}.
|
||||
*
|
||||
* @return metering type as {@link MeteringTypeEnum}
|
||||
*/
|
||||
MeteringTypeEnum getMeteringType();
|
||||
|
||||
/**
|
||||
* Returns the {@link MeteringUnitsEnum} of this {@link CachedMeteringValue}.
|
||||
*
|
||||
* @return metering unit as {@link MeteringUnitsEnum}
|
||||
*/
|
||||
MeteringUnitsEnum getMeteringUnit();
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.structure.devices.deviceparameters;
|
||||
|
||||
/**
|
||||
* The {@link DeviceConfig} saves device configurations.
|
||||
*
|
||||
* @author Alexander Betker - initial contributer
|
||||
* @author Michael Ochel - add missing java-doc
|
||||
* @author Matthias Siegele - add missing java-doc
|
||||
*/
|
||||
public interface DeviceConfig {
|
||||
|
||||
/**
|
||||
* Returns the digitalSTROM-Device parameter class.
|
||||
*
|
||||
* @return configuration class
|
||||
*/
|
||||
int getConfigurationClass();
|
||||
|
||||
/**
|
||||
* Returns the digitalSTROM-Device configuration index.
|
||||
*
|
||||
* @return configuration index
|
||||
*/
|
||||
int getIndex();
|
||||
|
||||
/**
|
||||
* Returns the digitalSTROM-Device configuration value.
|
||||
*
|
||||
* @return configuration value
|
||||
*/
|
||||
int getValue();
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.structure.devices.deviceparameters;
|
||||
|
||||
/**
|
||||
* The {@link DeviceConstants} contains some constants for digitalSTROM devices.
|
||||
*
|
||||
* @author Alexander Betker - Initial contribution
|
||||
* @author Michael Ochel - updated constants
|
||||
* @author Matthias Siegele - updated constants
|
||||
*/
|
||||
public interface DeviceConstants {
|
||||
|
||||
/** digitalSTROM dim step for lights (this value is not in percent!) */
|
||||
static final short DIM_STEP_LIGHT = 11;
|
||||
|
||||
/** move step for roller shutters (this value is not in percent!) */
|
||||
static final short MOVE_STEP_ROLLERSHUTTER = 983;
|
||||
|
||||
/** move step for slats angle by blind/jalousie (this value is not in percent!) */
|
||||
static final short ANGLE_STEP_SLAT = 11;
|
||||
|
||||
/** default move step (this value is not in percent!) */
|
||||
static final short DEFAULT_MOVE_STEP = 11;
|
||||
|
||||
/** default max output value */
|
||||
static final short DEFAULT_MAX_OUTPUTVALUE = 255;
|
||||
|
||||
/** max output value if device (lamp - yellow) is on */
|
||||
static final short MAX_OUTPUT_VALUE_LIGHT = 255;
|
||||
|
||||
/** is open (special case: awning/marquee - closed) */
|
||||
static final int MAX_ROLLERSHUTTER = 65535;
|
||||
|
||||
/** is closed (special case: awning/marquee - open) */
|
||||
static final short MIN_ROLLERSHUTTER = 0;
|
||||
|
||||
/** max slat angle by blind/jalousie */
|
||||
static final short MAX_SLAT_ANGLE = 255;
|
||||
|
||||
/** min slat angle by blind/jalousie */
|
||||
static final short MIN_SLAT_ANGLE = 0;
|
||||
|
||||
/** you can't dim deeper than this value */
|
||||
static final short MIN_DIM_VALUE = 16;
|
||||
|
||||
/** this is the index to get the output value (min-, max value) of almost all devices */
|
||||
static final short DEVICE_SENSOR_OUTPUT = 0;
|
||||
|
||||
/** this is the index to get the output value (min-, max value) of shade devices */
|
||||
static final short DEVICE_SENSOR_SLAT_POSITION_OUTPUT = 2;
|
||||
|
||||
/** this index is needed to get the angle of the slats (if device is a blind/jalousie) */
|
||||
static final short DEVICE_SENSOR_SLAT_ANGLE_OUTPUT = 4;
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.structure.devices.deviceparameters;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.scene.constants.Scene;
|
||||
|
||||
/**
|
||||
* The {@link DeviceSceneSpec} saves a digitalSTROM-Device scene mode.
|
||||
*
|
||||
* @author Alexander Betker - initial contributer
|
||||
* @author Michael Ochel - add missing java-doc
|
||||
* @author Matthias Siegele - add missing java-doc
|
||||
*/
|
||||
public interface DeviceSceneSpec {
|
||||
|
||||
/**
|
||||
* Returns the sceneID.
|
||||
*
|
||||
* @return sceneID
|
||||
*/
|
||||
Scene getScene();
|
||||
|
||||
/**
|
||||
* Returns true, if the don't care flag is set, otherwise false.
|
||||
*
|
||||
* @return true, if dont't care is set, otherwise false
|
||||
*/
|
||||
boolean isDontCare();
|
||||
|
||||
/**
|
||||
* Sets the don't care flag.
|
||||
*
|
||||
* @param dontcare to set
|
||||
*/
|
||||
void setDontcare(boolean dontcare);
|
||||
|
||||
/**
|
||||
* Returns true, if the local priority flag is set, otherwise false.
|
||||
*
|
||||
* @return true, if local priority is, set otherwise false
|
||||
*/
|
||||
boolean isLocalPrio();
|
||||
|
||||
/**
|
||||
* Sets the local priority flag.
|
||||
*
|
||||
* @param localPrio to set
|
||||
*/
|
||||
void setLocalPrio(boolean localPrio);
|
||||
|
||||
/**
|
||||
* Returns true, if the special mode flag is set, otherwise false.
|
||||
*
|
||||
* @return true, if special mode is set, otherwise false
|
||||
*/
|
||||
boolean isSpecialMode();
|
||||
|
||||
/**
|
||||
* Sets the special mode flag.
|
||||
*
|
||||
* @param specialMode to set
|
||||
*/
|
||||
void setSpecialMode(boolean specialMode);
|
||||
|
||||
/**
|
||||
* Returns true, if the flash mode flag is set, otherwise false.
|
||||
*
|
||||
* @return true, if flash mode is set, otherwise false
|
||||
*/
|
||||
boolean isFlashMode();
|
||||
|
||||
/**
|
||||
* Sets the flash mode flag.
|
||||
*
|
||||
* @param flashMode to set
|
||||
*/
|
||||
void setFlashMode(boolean flashMode);
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.structure.devices.deviceparameters;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.DeviceBinarayInputEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.SensorEnum;
|
||||
|
||||
/**
|
||||
* Represents a device state update for lights, joker, shades and sensor data.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*/
|
||||
public interface DeviceStateUpdate {
|
||||
|
||||
// Update types
|
||||
// in certain circumstances it is also better to rename SLAT_ANGLE to e.g. SECONDARY_OUTPUT
|
||||
// light
|
||||
static final String OUTPUT = "output";
|
||||
static final String ON_OFF = "OnOff";
|
||||
static final String OUTPUT_INCREASE = "outputIncrese";
|
||||
static final String OUTPUT_DECREASE = "outputDecrese";
|
||||
static final String OUTPUT_STOP = "outputStop";
|
||||
static final String OUTPUT_MOVE = "outputMove";
|
||||
|
||||
// shades
|
||||
static final String SLATPOSITION = "slatposition";
|
||||
static final String SLAT_ANGLE = "slatAngle";
|
||||
static final String SLAT_INCREASE = "slatIncrese";
|
||||
static final String SLAT_DECREASE = "slatDecrese";
|
||||
static final String SLAT_ANGLE_INCREASE = "slatAngleIncrese";
|
||||
static final String SLAT_ANGLE_DECREASE = "slatAngleDecrese";
|
||||
static final String OPEN_CLOSE = "openClose";
|
||||
static final String OPEN_CLOSE_ANGLE = "openCloseAngle";
|
||||
static final String SLAT_MOVE = "slatMove";
|
||||
static final String SLAT_STOP = "slatStop";
|
||||
|
||||
// sensor data
|
||||
static final String UPDATE_OUTPUT_VALUE = "outputValue";
|
||||
static final String UPDATE_DEVICE_SENSOR = "deviceSensor-";
|
||||
|
||||
// metering data
|
||||
static final String UPDATE_CIRCUIT_METER = "circuitMeter";
|
||||
|
||||
// binary inputs
|
||||
static final String BINARY_INPUT = "binaryInput-";
|
||||
|
||||
// scene
|
||||
/** A scene call can have the value between 0 and 127. */
|
||||
static final String UPDATE_CALL_SCENE = "callScene";
|
||||
static final String UPDATE_UNDO_SCENE = "undoScene";
|
||||
static final String UPDATE_SCENE_OUTPUT = "sceneOutput";
|
||||
static final String UPDATE_SCENE_CONFIG = "sceneConfig";
|
||||
|
||||
// general
|
||||
/** command to refresh the output value of an device. */
|
||||
static final String REFRESH_OUTPUT = "refreshOutput";
|
||||
|
||||
// standard values
|
||||
static final int ON_VALUE = 1;
|
||||
static final int OFF_VALUE = -1;
|
||||
|
||||
/**
|
||||
* Returns the state update value.
|
||||
* <p>
|
||||
* <b>NOTE:</b>
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>For all OnOff-types the value for off is lower than 0 and for on higher than 0.</li>
|
||||
* <li>For all Increase- and Decrease-types the value is the new output value.</li>
|
||||
* <li>For SceneCall-type the value is between 0 and 127.</li>
|
||||
* <li>For all SceneUndo-types the value is the new output value.</li>
|
||||
* <li>For all SensorUpdate-types will read the sensor data directly, if the value is 0, otherwise a
|
||||
* {@link SensorJob} will be added to the {@link SensorJobExecutor}.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @return new state value
|
||||
*/
|
||||
Object getValue();
|
||||
|
||||
/**
|
||||
* Returns the value as {@link Integer}.
|
||||
*
|
||||
* @return integer value
|
||||
* @see #getValue()
|
||||
*/
|
||||
Integer getValueAsInteger();
|
||||
|
||||
/**
|
||||
* Returns the value as {@link String}.
|
||||
*
|
||||
* @return string value
|
||||
* @see #getValue()
|
||||
*/
|
||||
String getValueAsString();
|
||||
|
||||
/**
|
||||
* Returns the value as {@link Short}.
|
||||
*
|
||||
* @return short value
|
||||
* @see #getValue()
|
||||
*/
|
||||
Short getValueAsShort();
|
||||
|
||||
/**
|
||||
* Returns the value as {@link Float}.
|
||||
*
|
||||
* @return float value
|
||||
* @see #getValue()
|
||||
*/
|
||||
Float getValueAsFloat();
|
||||
|
||||
/**
|
||||
* Returns the value as {@link Short}-array.
|
||||
*
|
||||
* @return short[] value
|
||||
* @see #getValue()
|
||||
*/
|
||||
Short[] getValueAsShortArray();
|
||||
|
||||
/**
|
||||
* Returns the state update type.
|
||||
*
|
||||
* @return state update type
|
||||
*/
|
||||
String getType();
|
||||
|
||||
/**
|
||||
* Returns the update type as {@link SensorEnum} or null, if the type is not a {@link #UPDATE_DEVICE_SENSOR} type.
|
||||
*
|
||||
* @return type as {@link SensorEnum} or null
|
||||
*/
|
||||
SensorEnum getTypeAsSensorEnum();
|
||||
|
||||
/**
|
||||
* Returns true, if this {@link DeviceStateUpdate} is a {@link #UPDATE_DEVICE_SENSOR} type, otherwise false.
|
||||
*
|
||||
* @return true, if it is a sensor type
|
||||
*/
|
||||
boolean isSensorUpdateType();
|
||||
|
||||
/**
|
||||
* Returns the scene id of this {@link DeviceStateUpdate}, if this {@link DeviceStateUpdate} is a scene update type,
|
||||
* otherwise it will be returned -1.
|
||||
*
|
||||
* @return the scene id or -1
|
||||
*/
|
||||
Short getSceneId();
|
||||
|
||||
/**
|
||||
* Returns the scene configuration or output reading priority, if this {@link DeviceStateUpdate} is a
|
||||
* {@link #UPDATE_SCENE_CONFIG} or {@link #UPDATE_SCENE_OUTPUT} type.
|
||||
*
|
||||
* @return scene reading priority
|
||||
*/
|
||||
Short getScenePriority();
|
||||
|
||||
/**
|
||||
* Returns true, if this {@link DeviceStateUpdate} is a {@link #UPDATE_SCENE_CONFIG} or {@link #UPDATE_SCENE_OUTPUT}
|
||||
* type, otherwise false.
|
||||
*
|
||||
* @return true, if it is a scene reading type
|
||||
*/
|
||||
boolean isSceneUpdateType();
|
||||
|
||||
/**
|
||||
* Returns the update type as {@link DeviceBinarayInputEnum} or null, if the type is not a {@link #BINARY_INPUT}
|
||||
* type.
|
||||
*
|
||||
* @return type as {@link DeviceBinarayInputEnum} or null
|
||||
*/
|
||||
DeviceBinarayInputEnum getTypeAsDeviceBinarayInputEnum();
|
||||
|
||||
/**
|
||||
* Returns true, if this {@link DeviceStateUpdate} is a {@link #BINARY_INPUT} type, otherwise false.
|
||||
*
|
||||
* @return true, if it is a binary input type
|
||||
*/
|
||||
boolean isBinarayInputType();
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.structure.devices.deviceparameters.constants;
|
||||
|
||||
/**
|
||||
* The {@link ChangeableDeviceConfigEnum} lists all changeable device configurations.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
*
|
||||
*/
|
||||
public enum ChangeableDeviceConfigEnum {
|
||||
METER_DSID,
|
||||
DEVICE_NAME,
|
||||
ZONE_ID,
|
||||
GROUPS,
|
||||
FUNCTIONAL_GROUP,
|
||||
OUTPUT_MODE,
|
||||
BINARY_INPUTS
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.structure.devices.deviceparameters.constants;
|
||||
|
||||
/**
|
||||
* This enum contains all binary inputs with they id. <br>
|
||||
*
|
||||
* @author Michael Ochel - initial contributer
|
||||
* @author Matthias Siegele - initial contributer
|
||||
*/
|
||||
public enum DeviceBinarayInputEnum {
|
||||
|
||||
/*
|
||||
* Taken from http://developer.digitalstrom.org/Architecture/ds-basics.pdf#5f
|
||||
*
|
||||
* Input Type | Assigned Index | Natural Device and Description
|
||||
* Presence | 1 | Presence detector
|
||||
* Brightness | 2 | ---
|
||||
* Presence in darkness | 3 | Presence detector with activated internal twilight sensor
|
||||
* Twilight | 4 | Twilight sensor
|
||||
* Motion | 5 | Motion detector
|
||||
* Motion in darkness | 6 | Motion detect or with activated internal twilight sensor
|
||||
* Smoke | 7 | Smoke Detector
|
||||
* Wind strength above limit | 8 | Wind monitor with user-adjusted wind strength threshold
|
||||
* Rain | 9 | Rain monitor
|
||||
* Sun radiation | 10 | Sun light above threshold
|
||||
* Temperature below limit | 11 | Room thermostat with used-adjusted temperature threshold
|
||||
* Battery status is low | 12 | electric battery is running out of power
|
||||
* Window is open | 13 | Window contact
|
||||
* Door is open | 14 | Door contact
|
||||
* Window is tilted | 15 | Window handle; window is tilted instead of fully opened
|
||||
* Garage door is open | 16 | Garage door contact
|
||||
* Sun protection | 17 | Protect against too much sun light
|
||||
* Frost | 18 | Frost detector
|
||||
* --dS-Basics Version: v1.3-branch August 19, 2015, Table 16: Binary input types--
|
||||
*
|
||||
* Heating operation on/off | 19 |
|
||||
* Change-over heating/cooling | 20 |
|
||||
* --dS-web-interface server-version: 1.21.1--
|
||||
*
|
||||
*
|
||||
* Target Function | Assigned Index
|
||||
* Joker | 8
|
||||
* --dS-Basics Version: v1.3-branch August 19, 2015, Table 17: Binary input target functions--
|
||||
*/
|
||||
|
||||
PRESENCE((short) 1),
|
||||
BRIGHTNESS((short) 2),
|
||||
PRESENCE_IN_DARKNESS((short) 3),
|
||||
TWILIGHT((short) 4),
|
||||
MOTION((short) 5),
|
||||
MOTION_IN_DARKNESS((short) 6),
|
||||
SMOKE((short) 7),
|
||||
WIND_STRENGHT_ABOVE_LIMIT((short) 8),
|
||||
RAIN((short) 9),
|
||||
SUN_RADIATION((short) 10),
|
||||
TEMPERATION_BELOW_LIMIT((short) 11),
|
||||
BATTERY_STATUS_IS_LOW((short) 12),
|
||||
WINDOW_IS_OPEN((short) 13),
|
||||
DOOR_IS_OPEN((short) 14),
|
||||
WINDOW_IS_TILTED((short) 15),
|
||||
GARAGE_DOOR_IS_OPEN((short) 16),
|
||||
SUN_PROTECTION((short) 17),
|
||||
FROST((short) 18),
|
||||
HEATING_OPERATION_ON_OFF((short) 19),
|
||||
CHANGE_OVER_HEATING_COOLING((short) 20);
|
||||
|
||||
private final Short binaryInputType;
|
||||
private static DeviceBinarayInputEnum[] deviceBinarayInputs = new DeviceBinarayInputEnum[DeviceBinarayInputEnum
|
||||
.values().length];
|
||||
|
||||
static {
|
||||
for (DeviceBinarayInputEnum deviceBinarayInput : DeviceBinarayInputEnum.values()) {
|
||||
deviceBinarayInputs[deviceBinarayInput.binaryInputType - 1] = deviceBinarayInput;
|
||||
}
|
||||
}
|
||||
|
||||
private DeviceBinarayInputEnum(Short binaryInputType) {
|
||||
this.binaryInputType = binaryInputType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the id of this {@link DeviceBinarayInputEnum}.
|
||||
*
|
||||
* @return id
|
||||
*/
|
||||
public Short getBinaryInputType() {
|
||||
return binaryInputType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link DeviceBinarayInputEnum} of the given id or null, if no {@link DeviceBinarayInputEnum} exist
|
||||
* for the id.
|
||||
*
|
||||
* @param binaryInputTypeID of the {@link DeviceBinarayInputEnum}
|
||||
* @return the {@link DeviceBinarayInputEnum} of the id
|
||||
*/
|
||||
public static DeviceBinarayInputEnum getdeviceBinarayInput(Short binaryInputTypeID) {
|
||||
try {
|
||||
return deviceBinarayInputs[binaryInputTypeID - 1];
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.structure.devices.deviceparameters.constants;
|
||||
|
||||
/**
|
||||
* The {@link DeviceParameterClassEnum} lists all digitalSTROM-device parameter classes.
|
||||
*
|
||||
* @author Alexander Betker - initial contributer
|
||||
* @version digitalSTROM-API 1.14.5
|
||||
*/
|
||||
public enum DeviceParameterClassEnum {
|
||||
|
||||
/**
|
||||
* communication specific parameters
|
||||
*/
|
||||
CLASS_0(0),
|
||||
|
||||
/**
|
||||
* digitalSTROM device specific parameters
|
||||
*/
|
||||
CLASS_1(1),
|
||||
|
||||
/**
|
||||
* function specific parameters
|
||||
*/
|
||||
CLASS_3(3),
|
||||
|
||||
/**
|
||||
* sensor event table
|
||||
*/
|
||||
CLASS_6(6),
|
||||
|
||||
/**
|
||||
* output status
|
||||
*
|
||||
* possible OffsetParameters:
|
||||
* - READ_OUTPUT
|
||||
*/
|
||||
CLASS_64(64),
|
||||
|
||||
/**
|
||||
* read scene table
|
||||
* use index/offset 0-127
|
||||
*/
|
||||
CLASS_128(128);
|
||||
|
||||
private final int classIndex;
|
||||
|
||||
DeviceParameterClassEnum(int index) {
|
||||
this.classIndex = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the {@link DeviceParameterClassEnum}.
|
||||
*
|
||||
* @return index
|
||||
*/
|
||||
public Integer getClassIndex() {
|
||||
return this.classIndex;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.structure.devices.deviceparameters.constants;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The {@link FuncNameAndColorGroupEnum} contains all digitalSTROM functional group names and links to their
|
||||
* {@link FunctionalColorGroupEnum}.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
* @see <a href="http://developer.digitalstrom.org/Architecture/ds-basics.pdf">ds-basics.pdf
|
||||
* "Table 1: digitalSTROM functional groups and their colors", page 9</a>
|
||||
*/
|
||||
public enum FuncNameAndColorGroupEnum {
|
||||
/*
|
||||
* | Number | Name | Color | Function |
|
||||
* --------------------------------------------------------------------------------------
|
||||
* | 1 | Lights | Yellow | Room lights |
|
||||
* | 2 | Blinds | Gray | Blinds or shades outside |
|
||||
* | 12 | Curtains | Gray | Curtains and blinds inside |
|
||||
* | 3 | Heating | Blue | Heating |
|
||||
* | 9 | Cooling | Blue | Cooling |
|
||||
* | 10 | Ventilation | Blue | Ventilation |
|
||||
* | 11 | Window | Blue | Window |
|
||||
* | 48 | Temperature Control | Blue | Single room temperature control |
|
||||
* | 4 | Audio | Cyan | Playing music or radio |
|
||||
* | 5 | Video | Magenta | TV, Video |
|
||||
* | 8 | Joker | Black | Configurable behaviour |
|
||||
* | n/a | Single Device | White | Various, individual per device |
|
||||
* | n/a | Security | Red | Security related functions, Alarms |
|
||||
* | n/a | Access | Green | Access related functions, door bell |
|
||||
*
|
||||
*/
|
||||
LIGHTS((short) 1, FunctionalColorGroupEnum.getColorGroup((short) 1)),
|
||||
BLINDS((short) 2, FunctionalColorGroupEnum.getColorGroup((short) 2)),
|
||||
CURTAINS((short) 12, FunctionalColorGroupEnum.getColorGroup((short) 12)),
|
||||
HEATING((short) 3, FunctionalColorGroupEnum.getColorGroup((short) 3)),
|
||||
COOLING((short) 9, FunctionalColorGroupEnum.getColorGroup((short) 9)),
|
||||
VENTILATION((short) 10, FunctionalColorGroupEnum.getColorGroup((short) 10)),
|
||||
WINDOW((short) 11, FunctionalColorGroupEnum.getColorGroup((short) 11)),
|
||||
TEMPERATION_CONTROL((short) 48, FunctionalColorGroupEnum.getColorGroup((short) 48)),
|
||||
AUDIO((short) 4, FunctionalColorGroupEnum.getColorGroup((short) 4)),
|
||||
VIDEO((short) 5, FunctionalColorGroupEnum.getColorGroup((short) 5)),
|
||||
JOKER((short) 8, FunctionalColorGroupEnum.getColorGroup((short) 8)),
|
||||
SINGLE_DEVICE((short) -1, FunctionalColorGroupEnum.getColorGroup((short) -1)),
|
||||
SECURITY((short) -2, FunctionalColorGroupEnum.getColorGroup((short) -2)),
|
||||
ACCESS((short) -3, FunctionalColorGroupEnum.getColorGroup((short) -3));
|
||||
|
||||
private final short colorGroup;
|
||||
private final FunctionalColorGroupEnum color;
|
||||
|
||||
static final Map<Short, FuncNameAndColorGroupEnum> COLOR_GROUPS = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (FuncNameAndColorGroupEnum colorGroup : FuncNameAndColorGroupEnum.values()) {
|
||||
COLOR_GROUPS.put(colorGroup.getFunctionalColorGroup(), colorGroup);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, if contains the given output mode id in DigitalSTROM, otherwise false.
|
||||
*
|
||||
* @param functionalNameGroupID to be checked
|
||||
* @return true, if contains
|
||||
*/
|
||||
public static boolean containsColorGroup(Short functionalNameGroupID) {
|
||||
return COLOR_GROUPS.keySet().contains(functionalNameGroupID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link FuncNameAndColorGroupEnum} of the given functional name group id.
|
||||
*
|
||||
* @param functionalNameGroupID of the {@link FuncNameAndColorGroupEnum}
|
||||
* @return FunctionalNameAndColorGroupEnum
|
||||
*/
|
||||
public static FuncNameAndColorGroupEnum getMode(Short functionalNameGroupID) {
|
||||
return COLOR_GROUPS.get(functionalNameGroupID);
|
||||
}
|
||||
|
||||
private FuncNameAndColorGroupEnum(short functionalColorGroupID, FunctionalColorGroupEnum functionalColorGroup) {
|
||||
this.colorGroup = functionalColorGroupID;
|
||||
this.color = functionalColorGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the functional name group id form this Object.
|
||||
*
|
||||
* @return functional name group id
|
||||
*/
|
||||
public Short getFunctionalColorGroup() {
|
||||
return colorGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link FunctionalColorGroupEnum} form this Object.
|
||||
*
|
||||
* @return FunctionalColorGroupEnum
|
||||
*/
|
||||
public FunctionalColorGroupEnum getFunctionalColor() {
|
||||
return color;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.structure.devices.deviceparameters.constants;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The {@link FunctionalColorGroupEnum} contains all digitalSTROM functional color groups.
|
||||
*
|
||||
* @author Michael Ochel - Initial contribution
|
||||
* @author Matthias Siegele - Initial contribution
|
||||
* @see <a href="http://developer.digitalstrom.org/Architecture/ds-basics.pdf">ds-basics.pdf,
|
||||
* "Table 1: digitalSTROM functional groups and their colors", page 9 [04.09.2015]</a>
|
||||
*/
|
||||
public enum FunctionalColorGroupEnum {
|
||||
/*
|
||||
* | Number | Name | Color | Function |
|
||||
* --------------------------------------------------------------------------------------
|
||||
* | 1 | Lights | Yellow | Room lights |
|
||||
* | 2 | Blinds | Gray | Blinds or shades outside |
|
||||
* | 12 | Curtains | Gray | Curtains and blinds inside |
|
||||
* | 3 | Heating | Blue | Heating |
|
||||
* | 9 | Cooling | Blue | Cooling |
|
||||
* | 10 | Ventilation | Blue | Ventilation |
|
||||
* | 11 | Window | Blue | Window |
|
||||
* | 48 | Temperature Control | Blue | Single room temperature control |
|
||||
* | 4 | Audio | Cyan | Playing music or radio |
|
||||
* | 5 | Video | Magenta | TV, Video |
|
||||
* | 8 | Joker | Black | Configurable behaviour |
|
||||
* | n/a | Single Device | White | Various, individual per device |
|
||||
* | n/a | Security | Red | Security related functions, Alarms |
|
||||
* | n/a | Access | Green | Access related functions, door bell |
|
||||
*
|
||||
*/
|
||||
YELLOW(Arrays.asList((short) 1)),
|
||||
GREY(Arrays.asList((short) 2, (short) 12)),
|
||||
BLUE(Arrays.asList((short) 3, (short) 9, (short) 10, (short) 11, (short) 48)),
|
||||
CYAN(Arrays.asList((short) 4)),
|
||||
MAGENTA(Arrays.asList((short) 5)),
|
||||
BLACK(Arrays.asList((short) 8)),
|
||||
WHITE(Arrays.asList((short) -1)),
|
||||
RED(Arrays.asList((short) -2)),
|
||||
GREEN(Arrays.asList((short) -3));
|
||||
|
||||
private final List<Short> colorGroup;
|
||||
|
||||
static final Map<Short, FunctionalColorGroupEnum> COLOR_GROUPS = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (FunctionalColorGroupEnum colorGroup : FunctionalColorGroupEnum.values()) {
|
||||
for (Short colorGroupID : colorGroup.getFunctionalColorGroup()) {
|
||||
COLOR_GROUPS.put(colorGroupID, colorGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, if contains the given functional color group id in digitalSTROM exits, otherwise false.
|
||||
*
|
||||
* @param functionalColorGroupID to be checked
|
||||
* @return true, if contains
|
||||
*/
|
||||
public static boolean containsColorGroup(Short functionalColorGroupID) {
|
||||
return COLOR_GROUPS.keySet().contains(functionalColorGroupID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link FunctionalColorGroupEnum} of the given color id.
|
||||
*
|
||||
* @param functionalColorGroupID of the {@link FunctionalColorGroupEnum}
|
||||
* @return {@link FunctionalColorGroupEnum} of the id
|
||||
*/
|
||||
public static FunctionalColorGroupEnum getColorGroup(Short functionalColorGroupID) {
|
||||
return COLOR_GROUPS.get(functionalColorGroupID);
|
||||
}
|
||||
|
||||
private FunctionalColorGroupEnum(List<Short> functionalColorGroupID) {
|
||||
this.colorGroup = functionalColorGroupID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the functional color group id's as {@link List} of this {@link FunctionalColorGroupEnum}.
|
||||
*
|
||||
* @return functional color group id's
|
||||
*/
|
||||
public List<Short> getFunctionalColorGroup() {
|
||||
return colorGroup;
|
||||
}
|
||||
}
|
||||
@@ -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.digitalstrom.internal.lib.structure.devices.deviceparameters.constants;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The {@link MeteringTypeEnum} lists all available digitalSTROM metering types.
|
||||
*
|
||||
* @author Alexander Betker - initial contributer
|
||||
* @author Michael Ochel - add MeteringUnitEnum list
|
||||
* @author Matthias Siegele - add MeteringUnitEnum list
|
||||
*/
|
||||
public enum MeteringTypeEnum {
|
||||
ENERGY(Arrays.asList(MeteringUnitsEnum.WH, MeteringUnitsEnum.WS)),
|
||||
// currently null by request getLast
|
||||
// energyDelta(Lists.newArrayList(MeteringUnitsEnum.Wh, MeteringUnitsEnum.Ws)),
|
||||
CONSUMPTION(Arrays.asList(MeteringUnitsEnum.WH));
|
||||
|
||||
private final List<MeteringUnitsEnum> meteringUnits;
|
||||
|
||||
private MeteringTypeEnum(List<MeteringUnitsEnum> meteringUnits) {
|
||||
this.meteringUnits = meteringUnits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the available units as {@link List} for this {@link MeteringTypeEnum}.
|
||||
*
|
||||
* @return units
|
||||
*/
|
||||
public List<MeteringUnitsEnum> getMeteringUnitList() {
|
||||
return meteringUnits;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* 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.digitalstrom.internal.lib.structure.devices.deviceparameters.constants;
|
||||
|
||||
/**
|
||||
* The {@link MeteringUnitsEnum} lists all available digitalSTROM metering units.
|
||||
*
|
||||
* @author Alexander Betker - initial contributer
|
||||
* @author Michael Ochel - remove W, because it does not exist any more
|
||||
* @author Matthias Siegele - remove W, because it does not exist any more
|
||||
*/
|
||||
public enum MeteringUnitsEnum {
|
||||
WH("Wh"),
|
||||
WS("Ws");
|
||||
|
||||
public final String unit;
|
||||
|
||||
private MeteringUnitsEnum(String unit) {
|
||||
this.unit = unit;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user