added migrated 2.x add-ons
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.draytonwiser-${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-draytonwiser" description="DraytonWiser Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.draytonwiser/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
||||
@@ -0,0 +1,160 @@
|
||||
/**
|
||||
* 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.draytonwiser.internal;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
|
||||
/**
|
||||
* The {@link DraytonWiserBindingConstants} class defines common constants, which are
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class DraytonWiserBindingConstants {
|
||||
|
||||
public static final String BINDING_ID = "draytonwiser";
|
||||
|
||||
public static final String REFRESH_INTERVAL = "refresh";
|
||||
public static final int DEFAULT_REFRESH_SECONDS = 60;
|
||||
|
||||
public static final int OFFLINE_TEMPERATURE = -32768;
|
||||
|
||||
// Web Service Endpoints
|
||||
public static final String DEVICE_ENDPOINT = "data/domain/Device/";
|
||||
public static final String ROOMSTATS_ENDPOINT = "data/domain/RoomStat/";
|
||||
public static final String TRVS_ENDPOINT = "data/domain/SmartValve/";
|
||||
public static final String ROOMS_ENDPOINT = "data/domain/Room/";
|
||||
public static final String HEATCHANNELS_ENDPOINT = "data/domain/HeatingChannel/";
|
||||
public static final String SYSTEM_ENDPOINT = "data/domain/System/";
|
||||
public static final String STATION_ENDPOINT = "data/network/Station/";
|
||||
public static final String DOMAIN_ENDPOINT = "data/domain/";
|
||||
public static final String HOTWATER_ENDPOINT = "data/domain/HotWater/";
|
||||
public static final String SMARTPLUG_ENDPOINT = "data/domain/SmartPlug/";
|
||||
|
||||
// bridge
|
||||
public static final ThingTypeUID THING_TYPE_BRIDGE = new ThingTypeUID(BINDING_ID, "heathub");
|
||||
|
||||
// List of all Thing Type UIDs
|
||||
public static final ThingTypeUID THING_TYPE_CONTROLLER = new ThingTypeUID(BINDING_ID, "boiler-controller");
|
||||
public static final ThingTypeUID THING_TYPE_ROOM = new ThingTypeUID(BINDING_ID, "room");
|
||||
public static final ThingTypeUID THING_TYPE_ROOMSTAT = new ThingTypeUID(BINDING_ID, "roomstat");
|
||||
public static final ThingTypeUID THING_TYPE_ITRV = new ThingTypeUID(BINDING_ID, "itrv");
|
||||
public static final ThingTypeUID THING_TYPE_HOTWATER = new ThingTypeUID(BINDING_ID, "hotwater");
|
||||
public static final ThingTypeUID THING_TYPE_SMARTPLUG = new ThingTypeUID(BINDING_ID, "smart-plug");
|
||||
|
||||
// properties
|
||||
public static final String PROP_ADDRESS = "networkAddress";
|
||||
public static final String PROP_SERIAL_NUMBER = "serialNumber";
|
||||
public static final String PROP_NAME = "name";
|
||||
public static final String PROP_ID = "id";
|
||||
|
||||
// List of all Channel ids
|
||||
public static final String CHANNEL_CURRENT_TEMPERATURE = "currentTemperature";
|
||||
public static final String CHANNEL_CURRENT_HUMIDITY = "currentHumidity";
|
||||
public static final String CHANNEL_CURRENT_SETPOINT = "currentSetPoint";
|
||||
public static final String CHANNEL_CURRENT_BATTERY_VOLTAGE = "currentBatteryVoltage";
|
||||
public static final String CHANNEL_CURRENT_BATTERY_LEVEL = "currentBatteryLevel";
|
||||
public static final String CHANNEL_CURRENT_WISER_BATTERY_LEVEL = "currentWiserBatteryLevel";
|
||||
public static final String CHANNEL_CURRENT_DEMAND = "currentDemand";
|
||||
public static final String CHANNEL_HEAT_REQUEST = "heatRequest";
|
||||
public static final String CHANNEL_CURRENT_SIGNAL_RSSI = "currentSignalRSSI";
|
||||
public static final String CHANNEL_CURRENT_SIGNAL_LQI = "currentSignalLQI";
|
||||
public static final String CHANNEL_CURRENT_SIGNAL_STRENGTH = "currentSignalStrength";
|
||||
public static final String CHANNEL_CURRENT_WISER_SIGNAL_STRENGTH = "currentWiserSignalStrength";
|
||||
public static final String CHANNEL_HEATING_OVERRIDE = "heatingOverride";
|
||||
public static final String CHANNEL_HOT_WATER_OVERRIDE = "hotWaterOverride";
|
||||
public static final String CHANNEL_HEATCHANNEL_1_DEMAND = "heatChannel1Demand";
|
||||
public static final String CHANNEL_HEATCHANNEL_2_DEMAND = "heatChannel2Demand";
|
||||
public static final String CHANNEL_HEATCHANNEL_1_DEMAND_STATE = "heatChannel1DemandState";
|
||||
public static final String CHANNEL_HEATCHANNEL_2_DEMAND_STATE = "heatChannel2DemandState";
|
||||
public static final String CHANNEL_HOTWATER_DEMAND_STATE = "hotWaterDemandState";
|
||||
public static final String CHANNEL_AWAY_MODE_STATE = "awayModeState";
|
||||
public static final String CHANNEL_ECO_MODE_STATE = "ecoModeState";
|
||||
public static final String CHANNEL_MANUAL_MODE_STATE = "manualModeState";
|
||||
public static final String CHANNEL_ZIGBEE_CONNECTED = "zigbeeConnected";
|
||||
public static final String CHANNEL_HOT_WATER_SETPOINT = "hotWaterSetPoint";
|
||||
public static final String CHANNEL_HOT_WATER_BOOST_DURATION = "hotWaterBoostDuration";
|
||||
public static final String CHANNEL_HOT_WATER_BOOSTED = "hotWaterBoosted";
|
||||
public static final String CHANNEL_HOT_WATER_BOOST_REMAINING = "hotWaterBoostRemaining";
|
||||
public static final String CHANNEL_ROOM_BOOST_DURATION = "roomBoostDuration";
|
||||
public static final String CHANNEL_ROOM_BOOSTED = "roomBoosted";
|
||||
public static final String CHANNEL_ROOM_BOOST_REMAINING = "roomBoostRemaining";
|
||||
public static final String CHANNEL_ROOM_WINDOW_STATE_DETECTION = "windowStateDetection";
|
||||
public static final String CHANNEL_ROOM_WINDOW_STATE = "windowState";
|
||||
public static final String CHANNEL_DEVICE_LOCKED = "deviceLocked";
|
||||
public static final String CHANNEL_SMARTPLUG_OUTPUT_STATE = "plugOutputState";
|
||||
public static final String CHANNEL_SMARTPLUG_AWAY_ACTION = "plugAwayAction";
|
||||
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections
|
||||
.unmodifiableSet(new HashSet<>(Arrays.asList(THING_TYPE_CONTROLLER, THING_TYPE_ROOM, THING_TYPE_ROOMSTAT,
|
||||
THING_TYPE_BRIDGE, THING_TYPE_ITRV, THING_TYPE_HOTWATER, THING_TYPE_SMARTPLUG)));
|
||||
|
||||
// Lookups from text representations to useful values
|
||||
|
||||
public enum SignalStrength {
|
||||
VERYGOOD(4),
|
||||
GOOD(3),
|
||||
MEDIUM(2),
|
||||
POOR(1),
|
||||
NOSIGNAL(0);
|
||||
|
||||
private final int signalStrength;
|
||||
|
||||
SignalStrength(final int signalStrength) {
|
||||
this.signalStrength = signalStrength;
|
||||
}
|
||||
|
||||
public static State toSignalStrength(final String strength) {
|
||||
try {
|
||||
return new DecimalType(SignalStrength.valueOf(strength.toUpperCase()).signalStrength);
|
||||
} catch (final IllegalArgumentException e) {
|
||||
// Catch unrecognized values.
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum BatteryLevel {
|
||||
FULL(100),
|
||||
NORMAL(80),
|
||||
TWOTHIRDS(60),
|
||||
ONETHIRD(40),
|
||||
LOW(20),
|
||||
CRITICAL(0);
|
||||
|
||||
private final int batteryLevel;
|
||||
|
||||
private BatteryLevel(final int batteryLevel) {
|
||||
this.batteryLevel = batteryLevel;
|
||||
}
|
||||
|
||||
public static State toBatteryLevel(final String level) {
|
||||
try {
|
||||
return new DecimalType(BatteryLevel.valueOf(level.toUpperCase()).batteryLevel);
|
||||
} catch (final IllegalArgumentException e) {
|
||||
// Catch unrecognized values.
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* 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.draytonwiser.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.openhab.binding.draytonwiser.internal.handler.ControllerHandler;
|
||||
import org.openhab.binding.draytonwiser.internal.handler.HeatHubHandler;
|
||||
import org.openhab.binding.draytonwiser.internal.handler.HotWaterHandler;
|
||||
import org.openhab.binding.draytonwiser.internal.handler.RoomHandler;
|
||||
import org.openhab.binding.draytonwiser.internal.handler.RoomStatHandler;
|
||||
import org.openhab.binding.draytonwiser.internal.handler.SmartPlugHandler;
|
||||
import org.openhab.binding.draytonwiser.internal.handler.TRVHandler;
|
||||
import org.openhab.core.io.net.http.HttpClientFactory;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
|
||||
/**
|
||||
* The {@link DraytonWiserHandlerFactory} is responsible for creating things and thing
|
||||
* handlers.
|
||||
*
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
*/
|
||||
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.draytonwiser")
|
||||
@NonNullByDefault
|
||||
public class DraytonWiserHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
private final HttpClient httpClient;
|
||||
|
||||
@Activate
|
||||
public DraytonWiserHandlerFactory(@Reference final HttpClientFactory factory) {
|
||||
httpClient = factory.getCommonHttpClient();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(final ThingTypeUID thingTypeUID) {
|
||||
return DraytonWiserBindingConstants.SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ThingHandler createHandler(final Thing thing) {
|
||||
final ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (DraytonWiserBindingConstants.THING_TYPE_BRIDGE.equals(thingTypeUID)) {
|
||||
return new HeatHubHandler((Bridge) thing, httpClient);
|
||||
} else if (DraytonWiserBindingConstants.THING_TYPE_ROOM.equals(thingTypeUID)) {
|
||||
return new RoomHandler(thing);
|
||||
} else if (DraytonWiserBindingConstants.THING_TYPE_ROOMSTAT.equals(thingTypeUID)) {
|
||||
return new RoomStatHandler(thing);
|
||||
} else if (DraytonWiserBindingConstants.THING_TYPE_ITRV.equals(thingTypeUID)) {
|
||||
return new TRVHandler(thing);
|
||||
} else if (DraytonWiserBindingConstants.THING_TYPE_CONTROLLER.equals(thingTypeUID)) {
|
||||
return new ControllerHandler(thing);
|
||||
} else if (DraytonWiserBindingConstants.THING_TYPE_HOTWATER.equals(thingTypeUID)) {
|
||||
return new HotWaterHandler(thing);
|
||||
} else if (DraytonWiserBindingConstants.THING_TYPE_SMARTPLUG.equals(thingTypeUID)) {
|
||||
return new SmartPlugHandler(thing);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* 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.draytonwiser.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.draytonwiser.internal.model.DraytonWiserDTO;
|
||||
|
||||
/**
|
||||
* Listener for item/sensor updates.
|
||||
*
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface DraytonWiserRefreshListener {
|
||||
|
||||
void onRefresh(DraytonWiserDTO domain);
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
/**
|
||||
* 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.draytonwiser.internal.api;
|
||||
|
||||
import static org.openhab.binding.draytonwiser.internal.DraytonWiserBindingConstants.*;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.api.ContentResponse;
|
||||
import org.eclipse.jetty.client.util.StringContentProvider;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.openhab.binding.draytonwiser.internal.handler.HeatHubConfiguration;
|
||||
import org.openhab.binding.draytonwiser.internal.model.DomainDTO;
|
||||
import org.openhab.binding.draytonwiser.internal.model.StationDTO;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.FieldNamingPolicy;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
/**
|
||||
* Class with api specific call code.
|
||||
*
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
* @author Hilbrand Bouwkamp - Moved Api specific code to it's own class
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class DraytonWiserApi {
|
||||
|
||||
public static final Gson GSON = new GsonBuilder().setFieldNamingStrategy(FieldNamingPolicy.UPPER_CAMEL_CASE)
|
||||
.create();
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(DraytonWiserApi.class);
|
||||
private final HttpClient httpClient;
|
||||
|
||||
private HeatHubConfiguration configuration = new HeatHubConfiguration();
|
||||
private int failCount;
|
||||
|
||||
public DraytonWiserApi(final HttpClient httpClient) {
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
public void setConfiguration(final HeatHubConfiguration configuration) {
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
public @Nullable StationDTO getStation() throws DraytonWiserApiException {
|
||||
final ContentResponse response = sendMessageToHeatHub(STATION_ENDPOINT, HttpMethod.GET);
|
||||
|
||||
return response == null ? null : GSON.fromJson(response.getContentAsString(), StationDTO.class);
|
||||
}
|
||||
|
||||
public @Nullable DomainDTO getDomain() throws DraytonWiserApiException {
|
||||
final ContentResponse response = sendMessageToHeatHub(DOMAIN_ENDPOINT, HttpMethod.GET);
|
||||
|
||||
if (response == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return GSON.fromJson(response.getContentAsString(), DomainDTO.class);
|
||||
} catch (final JsonSyntaxException e) {
|
||||
logger.debug("Could not parse Json content: {}", e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void setRoomSetPoint(final int roomId, final int setPoint) throws DraytonWiserApiException {
|
||||
final String payload = "{\"RequestOverride\":{\"Type\":\"Manual\", \"SetPoint\":" + setPoint + "}}";
|
||||
|
||||
sendMessageToHeatHub(ROOMS_ENDPOINT + roomId, "PATCH", payload);
|
||||
}
|
||||
|
||||
public void setRoomManualMode(final int roomId, final boolean manualMode) throws DraytonWiserApiException {
|
||||
String payload = "{\"Mode\":\"" + (manualMode ? "Manual" : "Auto") + "\"}";
|
||||
sendMessageToHeatHub(ROOMS_ENDPOINT + roomId, "PATCH", payload);
|
||||
payload = "{\"RequestOverride\":{\"Type\":\"None\",\"Originator\" :\"App\",\"DurationMinutes\":0,\"SetPoint\":0}}";
|
||||
sendMessageToHeatHub(ROOMS_ENDPOINT + roomId, "PATCH", payload);
|
||||
}
|
||||
|
||||
public void setRoomWindowStateDetection(final int roomId, final boolean windowStateDetection)
|
||||
throws DraytonWiserApiException {
|
||||
final String payload = windowStateDetection ? "true" : "false";
|
||||
sendMessageToHeatHub(ROOMS_ENDPOINT + roomId + "/WindowDetectionActive", "PATCH", payload);
|
||||
}
|
||||
|
||||
public void setRoomBoostActive(final int roomId, final int setPoint, final int duration)
|
||||
throws DraytonWiserApiException {
|
||||
final String payload = "{\"RequestOverride\":{\"Type\":\"Manual\",\"Originator\" :\"App\",\"DurationMinutes\":"
|
||||
+ duration + ",\"SetPoint\":" + setPoint + "}}";
|
||||
sendMessageToHeatHub(ROOMS_ENDPOINT + roomId, "PATCH", payload);
|
||||
}
|
||||
|
||||
public void setRoomBoostInactive(final int roomId) throws DraytonWiserApiException {
|
||||
final String payload = "{\"RequestOverride\":{\"Type\":\"None\",\"Originator\" :\"App\",\"DurationMinutes\":0,\"SetPoint\":0}}";
|
||||
sendMessageToHeatHub(ROOMS_ENDPOINT + roomId, "PATCH", payload);
|
||||
}
|
||||
|
||||
public void setHotWaterManualMode(final boolean manualMode) throws DraytonWiserApiException {
|
||||
String payload = "{\"Mode\":\"" + (manualMode ? "Manual" : "Auto") + "\"}";
|
||||
sendMessageToHeatHub(HOTWATER_ENDPOINT + "2", "PATCH", payload);
|
||||
payload = "{\"RequestOverride\":{\"Type\":\"None\",\"Originator\" :\"App\",\"DurationMinutes\":0,\"SetPoint\":0}}";
|
||||
sendMessageToHeatHub(HOTWATER_ENDPOINT + "2", "PATCH", payload);
|
||||
}
|
||||
|
||||
public void setHotWaterSetPoint(final int setPoint) throws DraytonWiserApiException {
|
||||
final String payload = "{\"RequestOverride\":{\"Type\":\"Manual\", \"SetPoint\":" + setPoint + "}}";
|
||||
sendMessageToHeatHub(HOTWATER_ENDPOINT + "2", "PATCH", payload);
|
||||
}
|
||||
|
||||
public void setHotWaterBoostActive(final int duration) throws DraytonWiserApiException {
|
||||
final String payload = "{\"RequestOverride\":{\"Type\":\"Manual\",\"Originator\" :\"App\",\"DurationMinutes\":"
|
||||
+ duration + ",\"SetPoint\":1100}}";
|
||||
sendMessageToHeatHub(HOTWATER_ENDPOINT + "2", "PATCH", payload);
|
||||
}
|
||||
|
||||
public void setHotWaterBoostInactive() throws DraytonWiserApiException {
|
||||
final String payload = "{\"RequestOverride\":{\"Type\":\"None\",\"Originator\" :\"App\",\"DurationMinutes\":0,\"SetPoint\":0}}";
|
||||
sendMessageToHeatHub(HOTWATER_ENDPOINT + "2", "PATCH", payload);
|
||||
}
|
||||
|
||||
public void setAwayMode(final boolean awayMode) throws DraytonWiserApiException {
|
||||
final int setPoint = configuration.awaySetPoint * 10;
|
||||
|
||||
String payload = "{\"Type\":" + (awayMode ? "2" : "0") + ", \"setPoint\":" + (awayMode ? setPoint : "0") + "}";
|
||||
sendMessageToHeatHub(SYSTEM_ENDPOINT + "RequestOverride", "PATCH", payload);
|
||||
payload = "{\"Type\":" + (awayMode ? "2" : "0") + ", \"setPoint\":" + (awayMode ? "-200" : "0") + "}";
|
||||
sendMessageToHeatHub(HOTWATER_ENDPOINT + "2/RequestOverride", "PATCH", payload);
|
||||
}
|
||||
|
||||
public void setDeviceLocked(final int deviceId, final boolean locked) throws DraytonWiserApiException {
|
||||
final String payload = locked ? "true" : "false";
|
||||
sendMessageToHeatHub(DEVICE_ENDPOINT + deviceId + "/DeviceLockEnabled", "PATCH", payload);
|
||||
}
|
||||
|
||||
public void setEcoMode(final boolean ecoMode) throws DraytonWiserApiException {
|
||||
final String payload = "{\"EcoModeEnabled\":" + ecoMode + "}";
|
||||
sendMessageToHeatHub(SYSTEM_ENDPOINT, "PATCH", payload);
|
||||
}
|
||||
|
||||
public void setSmartPlugManualMode(final int id, final boolean manualMode) throws DraytonWiserApiException {
|
||||
final String payload = "{\"Mode\":\"" + (manualMode ? "Manual" : "Auto") + "\"}";
|
||||
sendMessageToHeatHub(SMARTPLUG_ENDPOINT + id, "PATCH", payload);
|
||||
}
|
||||
|
||||
public void setSmartPlugOutputState(final int id, final boolean outputState) throws DraytonWiserApiException {
|
||||
final String payload = "{\"RequestOutput\":\"" + (outputState ? "On" : "Off") + "\"}";
|
||||
sendMessageToHeatHub(SMARTPLUG_ENDPOINT + id, "PATCH", payload);
|
||||
}
|
||||
|
||||
public void setSmartPlugAwayAction(final int id, final boolean awayAction) throws DraytonWiserApiException {
|
||||
final String payload = "{\"AwayAction\":\"" + (awayAction ? "Off" : "NoChange") + "\"}";
|
||||
sendMessageToHeatHub(SMARTPLUG_ENDPOINT + id, "PATCH", payload);
|
||||
}
|
||||
|
||||
private synchronized @Nullable ContentResponse sendMessageToHeatHub(final String path, final HttpMethod method)
|
||||
throws DraytonWiserApiException {
|
||||
return sendMessageToHeatHub(path, method.asString(), "");
|
||||
}
|
||||
|
||||
private synchronized @Nullable ContentResponse sendMessageToHeatHub(final String path, final String method,
|
||||
final String content) throws DraytonWiserApiException {
|
||||
// we need to keep track of the number of times that the heat hub has "failed" to respond.
|
||||
// we only actually report a failure if we hit an error state 3 or more times
|
||||
try {
|
||||
logger.debug("Sending message to heathub: {}", path);
|
||||
final StringContentProvider contentProvider = new StringContentProvider(content);
|
||||
final ContentResponse response = httpClient
|
||||
.newRequest("http://" + configuration.networkAddress + "/" + path).method(method)
|
||||
.header("SECRET", configuration.secret).content(contentProvider).timeout(10, TimeUnit.SECONDS)
|
||||
.send();
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Reponse (Status:{}): {}", response.getStatus(), response.getContentAsString());
|
||||
}
|
||||
if (response.getStatus() == HttpStatus.OK_200) {
|
||||
failCount = 0;
|
||||
return response;
|
||||
} else if (response.getStatus() == HttpStatus.UNAUTHORIZED_401) {
|
||||
failCount++;
|
||||
if (failCount > 2) {
|
||||
throw new DraytonWiserApiException("Invalid authorization token");
|
||||
}
|
||||
} else {
|
||||
failCount++;
|
||||
if (failCount > 2) {
|
||||
throw new DraytonWiserApiException("Heathub didn't repond after " + failCount + " retries");
|
||||
}
|
||||
}
|
||||
} catch (final TimeoutException e) {
|
||||
failCount++;
|
||||
if (failCount > 2) {
|
||||
logger.debug("Heathub didn't repond in time: {}", e.getMessage());
|
||||
throw new DraytonWiserApiException("Heathub didn't repond in time", e);
|
||||
}
|
||||
} catch (final InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
} catch (final ExecutionException e) {
|
||||
logger.debug("Execution Exception: {}", e.getMessage(), e);
|
||||
throw new DraytonWiserApiException(e.getMessage(), e);
|
||||
} catch (final RuntimeException e) {
|
||||
logger.debug("Unexpected error: {}", e.getMessage(), e);
|
||||
throw new DraytonWiserApiException(e.getMessage(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -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.draytonwiser.internal.api;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Exception thrown in case of api problems.
|
||||
*
|
||||
* @author Hilbrand Bouwkamp - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class DraytonWiserApiException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public DraytonWiserApiException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public DraytonWiserApiException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
/**
|
||||
* 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.draytonwiser.internal.discovery;
|
||||
|
||||
import static org.openhab.binding.draytonwiser.internal.DraytonWiserBindingConstants.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.draytonwiser.internal.DraytonWiserRefreshListener;
|
||||
import org.openhab.binding.draytonwiser.internal.handler.DraytonWiserPropertyHelper;
|
||||
import org.openhab.binding.draytonwiser.internal.handler.HeatHubHandler;
|
||||
import org.openhab.binding.draytonwiser.internal.model.DeviceDTO;
|
||||
import org.openhab.binding.draytonwiser.internal.model.DraytonWiserDTO;
|
||||
import org.openhab.binding.draytonwiser.internal.model.HotWaterDTO;
|
||||
import org.openhab.binding.draytonwiser.internal.model.RoomDTO;
|
||||
import org.openhab.binding.draytonwiser.internal.model.RoomStatDTO;
|
||||
import org.openhab.binding.draytonwiser.internal.model.SmartPlugDTO;
|
||||
import org.openhab.binding.draytonwiser.internal.model.SmartValveDTO;
|
||||
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.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link DraytonWiserDiscoveryService} is used to discover devices that are connected to a Heat Hub.
|
||||
*
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class DraytonWiserDiscoveryService extends AbstractDiscoveryService
|
||||
implements DiscoveryService, ThingHandlerService, DraytonWiserRefreshListener {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(DraytonWiserDiscoveryService.class);
|
||||
|
||||
private @Nullable HeatHubHandler bridgeHandler;
|
||||
private @Nullable ThingUID bridgeUID;
|
||||
|
||||
public DraytonWiserDiscoveryService() {
|
||||
super(SUPPORTED_THING_TYPES_UIDS, 30, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate() {
|
||||
super.activate(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deactivate() {
|
||||
super.deactivate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startScan() {
|
||||
final HeatHubHandler handler = bridgeHandler;
|
||||
if (handler != null) {
|
||||
removeOlderResults(getTimestampOfLastScan());
|
||||
handler.setDiscoveryService(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefresh(final DraytonWiserDTO domainDTOProxy) {
|
||||
logger.debug("Received data from Drayton Wise device. Parsing to discover devices.");
|
||||
onControllerAdded(domainDTOProxy);
|
||||
domainDTOProxy.getRooms().forEach(this::onRoomAdded);
|
||||
domainDTOProxy.getRoomStats().forEach(r -> onRoomStatAdded(domainDTOProxy, r));
|
||||
domainDTOProxy.getSmartValves().forEach(sv -> onSmartValveAdded(domainDTOProxy, sv));
|
||||
domainDTOProxy.getHotWater().forEach(hw -> onHotWaterAdded(domainDTOProxy, hw));
|
||||
domainDTOProxy.getSmartPlugs().forEach(sp -> onSmartPlugAdded(domainDTOProxy, sp));
|
||||
}
|
||||
|
||||
private void onControllerAdded(final DraytonWiserDTO domainDTOProxy) {
|
||||
final DeviceDTO device = domainDTOProxy.getExtendedDeviceProperties(0);
|
||||
|
||||
if (device != null) {
|
||||
logger.debug("Controller discovered, model: {}", device.getModelIdentifier());
|
||||
onThingWithId(THING_TYPE_CONTROLLER, "controller", device, "Controller");
|
||||
}
|
||||
}
|
||||
|
||||
private void onHotWaterAdded(final DraytonWiserDTO domainDTOProxy, final HotWaterDTO hotWater) {
|
||||
final Integer hotWaterId = hotWater.getId();
|
||||
final String roomName = getRoomName(domainDTOProxy, hotWaterId);
|
||||
|
||||
onThingWithId(THING_TYPE_HOTWATER, "hotwater" + hotWaterId, null,
|
||||
(roomName.isEmpty() ? "" : (roomName + " - ")) + "Hot Water");
|
||||
}
|
||||
|
||||
private void onThingWithId(final ThingTypeUID deviceType, final String deviceTypeId,
|
||||
@Nullable final DeviceDTO device, final String name) {
|
||||
logger.debug("{} discovered: {}", deviceTypeId, name);
|
||||
ThingUID localBridgeUID = this.bridgeUID;
|
||||
if (localBridgeUID != null) {
|
||||
final Map<String, Object> properties = new HashMap<>();
|
||||
|
||||
properties.put(PROP_ID, deviceTypeId);
|
||||
if (device != null) {
|
||||
DraytonWiserPropertyHelper.setGeneralDeviceProperties(device, properties);
|
||||
}
|
||||
final DiscoveryResult discoveryResult = DiscoveryResultBuilder
|
||||
.create(new ThingUID(deviceType, localBridgeUID, deviceTypeId)).withBridge(localBridgeUID)
|
||||
.withProperties(properties).withRepresentationProperty(PROP_ID).withLabel(name).build();
|
||||
|
||||
thingDiscovered(discoveryResult);
|
||||
}
|
||||
}
|
||||
|
||||
private void onRoomStatAdded(final DraytonWiserDTO domainDTOProxy, final RoomStatDTO roomStat) {
|
||||
final Integer roomStatId = roomStat.getId();
|
||||
final DeviceDTO device = domainDTOProxy.getExtendedDeviceProperties(roomStatId);
|
||||
|
||||
if (device != null) {
|
||||
onThingWithSerialNumber(THING_TYPE_ROOMSTAT, "Thermostat", device, getRoomName(domainDTOProxy, roomStatId));
|
||||
}
|
||||
}
|
||||
|
||||
private void onRoomAdded(final RoomDTO room) {
|
||||
ThingUID localBridgeUID = this.bridgeUID;
|
||||
if (localBridgeUID != null) {
|
||||
final Map<String, Object> properties = new HashMap<>();
|
||||
|
||||
logger.debug("Room discovered: {}", room.getName());
|
||||
properties.put(PROP_NAME, room.getName());
|
||||
final DiscoveryResult discoveryResult = DiscoveryResultBuilder
|
||||
.create(new ThingUID(THING_TYPE_ROOM, localBridgeUID,
|
||||
room.getName().replaceAll("[^A-Za-z0-9]", "").toLowerCase()))
|
||||
.withBridge(localBridgeUID).withProperties(properties).withRepresentationProperty(PROP_NAME)
|
||||
.withLabel(room.getName()).build();
|
||||
|
||||
thingDiscovered(discoveryResult);
|
||||
}
|
||||
}
|
||||
|
||||
private void onSmartValveAdded(final DraytonWiserDTO domainDTOProxy, final SmartValveDTO smartValve) {
|
||||
final Integer smartValueId = smartValve.getId();
|
||||
final DeviceDTO device = domainDTOProxy.getExtendedDeviceProperties(smartValueId);
|
||||
|
||||
if (device != null) {
|
||||
onThingWithSerialNumber(THING_TYPE_ITRV, "TRV", device, getRoomName(domainDTOProxy, smartValueId));
|
||||
}
|
||||
}
|
||||
|
||||
private void onSmartPlugAdded(final DraytonWiserDTO domainDTOProxy, final SmartPlugDTO smartPlug) {
|
||||
final DeviceDTO device = domainDTOProxy.getExtendedDeviceProperties(smartPlug.getId());
|
||||
|
||||
if (device != null) {
|
||||
onThingWithSerialNumber(THING_TYPE_SMARTPLUG, "Smart Plug", device, smartPlug.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private String getRoomName(final DraytonWiserDTO domainDTOProxy, final Integer roomId) {
|
||||
final RoomDTO assignedRoom = domainDTOProxy.getRoomForDeviceId(roomId);
|
||||
return assignedRoom == null ? "" : assignedRoom.getName();
|
||||
}
|
||||
|
||||
private void onThingWithSerialNumber(final ThingTypeUID deviceType, final String deviceTypeName,
|
||||
final DeviceDTO device, final String name) {
|
||||
final String serialNumber = device.getSerialNumber();
|
||||
logger.debug("{} discovered, serialnumber: {}", deviceTypeName, serialNumber);
|
||||
ThingUID localBridgeUID = this.bridgeUID;
|
||||
if (localBridgeUID != null) {
|
||||
final Map<String, Object> properties = new HashMap<>();
|
||||
|
||||
DraytonWiserPropertyHelper.setPropertiesWithSerialNumber(device, properties);
|
||||
final DiscoveryResult discoveryResult = DiscoveryResultBuilder
|
||||
.create(new ThingUID(deviceType, localBridgeUID, serialNumber)).withBridge(localBridgeUID)
|
||||
.withProperties(properties).withRepresentationProperty(PROP_SERIAL_NUMBER)
|
||||
.withLabel((name.isEmpty() ? "" : (name + " - ")) + deviceTypeName).build();
|
||||
|
||||
thingDiscovered(discoveryResult);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void stopScan() {
|
||||
final HeatHubHandler handler = bridgeHandler;
|
||||
|
||||
if (handler != null) {
|
||||
handler.unsetDiscoveryService();
|
||||
}
|
||||
super.stopScan();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setThingHandler(@Nullable final ThingHandler handler) {
|
||||
if (handler instanceof HeatHubHandler) {
|
||||
bridgeHandler = (HeatHubHandler) handler;
|
||||
bridgeUID = handler.getThing().getUID();
|
||||
} else {
|
||||
bridgeHandler = null;
|
||||
bridgeUID = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ThingHandler getThingHandler() {
|
||||
return bridgeHandler;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* 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.draytonwiser.internal.discovery;
|
||||
|
||||
import static org.openhab.binding.draytonwiser.internal.DraytonWiserBindingConstants.*;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.jmdns.ServiceInfo;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
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 DraytonWiserMDNSDiscoveryParticipant} is responsible for discovering Drayton Wiser Heat Hubs. It uses the
|
||||
* central MDNS Discovery Service.
|
||||
*
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(service = MDNSDiscoveryParticipant.class, configurationPid = "mdnsdiscovery.draytonwiser")
|
||||
public class DraytonWiserMDNSDiscoveryParticipant implements MDNSDiscoveryParticipant {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(DraytonWiserMDNSDiscoveryParticipant.class);
|
||||
|
||||
@Override
|
||||
public Set<ThingTypeUID> getSupportedThingTypeUIDs() {
|
||||
return Collections.singleton(THING_TYPE_BRIDGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServiceType() {
|
||||
return "_http._tcp.local.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable DiscoveryResult createResult(final ServiceInfo service) {
|
||||
if (service.getApplication().contains("http")) {
|
||||
final ThingUID uid = getThingUID(service);
|
||||
|
||||
if (uid != null) {
|
||||
logger.debug("Discovered Heat Hub '{}' with uid: {}", service.getName(), uid);
|
||||
final Map<String, Object> properties = new HashMap<>(2);
|
||||
final InetAddress[] addresses = service.getInetAddresses();
|
||||
|
||||
if (addresses.length > 0 && addresses[0] != null) {
|
||||
properties.put(PROP_ADDRESS, addresses[0].getHostAddress());
|
||||
properties.put(REFRESH_INTERVAL, DEFAULT_REFRESH_SECONDS);
|
||||
}
|
||||
|
||||
return DiscoveryResultBuilder.create(uid).withProperties(properties)
|
||||
.withRepresentationProperty(PROP_ADDRESS).withLabel("Heat Hub - " + service.getName()).build();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ThingUID getThingUID(final ServiceInfo service) {
|
||||
if (service.getType() != null && service.getType().equals(getServiceType())
|
||||
&& service.getName().contains("WiserHeat")) {
|
||||
logger.trace("Discovered a Drayton Wiser Heat Hub thing with name '{}'", service.getName());
|
||||
return new ThingUID(THING_TYPE_BRIDGE, service.getName());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
* 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.draytonwiser.internal.handler;
|
||||
|
||||
import static org.openhab.binding.draytonwiser.internal.DraytonWiserBindingConstants.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.draytonwiser.internal.DraytonWiserBindingConstants.SignalStrength;
|
||||
import org.openhab.binding.draytonwiser.internal.api.DraytonWiserApiException;
|
||||
import org.openhab.binding.draytonwiser.internal.handler.ControllerHandler.ControllerData;
|
||||
import org.openhab.binding.draytonwiser.internal.model.DeviceDTO;
|
||||
import org.openhab.binding.draytonwiser.internal.model.DraytonWiserDTO;
|
||||
import org.openhab.binding.draytonwiser.internal.model.HeatingChannelDTO;
|
||||
import org.openhab.binding.draytonwiser.internal.model.HotWaterDTO;
|
||||
import org.openhab.binding.draytonwiser.internal.model.StationDTO;
|
||||
import org.openhab.binding.draytonwiser.internal.model.SystemDTO;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.library.unit.SmartHomeUnits;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
|
||||
/**
|
||||
* The {@link ControllerHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
* @author Hilbrand Bouwkamp - Simplified handler to handle null data
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ControllerHandler extends DraytonWiserThingHandler<ControllerData> {
|
||||
|
||||
public ControllerHandler(final Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleCommand(final String channelId, final Command command) throws DraytonWiserApiException {
|
||||
if (command instanceof OnOffType) {
|
||||
final boolean onOffState = OnOffType.ON.equals(command);
|
||||
|
||||
if (CHANNEL_AWAY_MODE_STATE.equals(channelId)) {
|
||||
setAwayMode(onOffState);
|
||||
} else if (CHANNEL_ECO_MODE_STATE.equals(channelId)) {
|
||||
setEcoMode(onOffState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void refresh() {
|
||||
updateState(CHANNEL_HEATING_OVERRIDE, this::getHeatingOverride);
|
||||
updateState(CHANNEL_CURRENT_SIGNAL_RSSI, this::getRSSI);
|
||||
updateState(CHANNEL_CURRENT_WISER_SIGNAL_STRENGTH, this::getWiserSignalStrength);
|
||||
updateState(CHANNEL_CURRENT_SIGNAL_STRENGTH, this::getSignalStrength);
|
||||
updateState(CHANNEL_HEATCHANNEL_1_DEMAND, this::getHeatChannel1Demand);
|
||||
updateState(CHANNEL_HEATCHANNEL_2_DEMAND, this::getHeatChannel2Demand);
|
||||
updateState(CHANNEL_HEATCHANNEL_1_DEMAND_STATE, this::getHeatChannel1DemandState);
|
||||
updateState(CHANNEL_HEATCHANNEL_2_DEMAND_STATE, this::getHeatChannel2DemandState);
|
||||
updateState(CHANNEL_AWAY_MODE_STATE, this::getAwayModeState);
|
||||
updateState(CHANNEL_ECO_MODE_STATE, this::getEcoModeState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ControllerData collectData(final DraytonWiserDTO domainDTOProxy)
|
||||
throws DraytonWiserApiException {
|
||||
final StationDTO station = getApi().getStation();
|
||||
final DeviceDTO device = domainDTOProxy.getExtendedDeviceProperties(0);
|
||||
final SystemDTO system = domainDTOProxy.getSystem();
|
||||
final List<HeatingChannelDTO> heatingChannels = domainDTOProxy.getHeatingChannels();
|
||||
final List<HotWaterDTO> hotWaterChannels = domainDTOProxy.getHotWater();
|
||||
|
||||
return station != null && device != null && system != null
|
||||
? new ControllerData(device, system, station, heatingChannels, hotWaterChannels)
|
||||
: null;
|
||||
}
|
||||
|
||||
private State getHeatingOverride() {
|
||||
return OnOffType.from("ON".equalsIgnoreCase(getData().system.getHeatingButtonOverrideState()));
|
||||
}
|
||||
|
||||
private State getRSSI() {
|
||||
return new DecimalType(getData().station.getRSSI().getCurrent());
|
||||
}
|
||||
|
||||
private State getWiserSignalStrength() {
|
||||
return new StringType(getData().device.getDisplayedSignalStrength());
|
||||
}
|
||||
|
||||
private State getSignalStrength() {
|
||||
return SignalStrength.toSignalStrength(getData().device.getDisplayedSignalStrength());
|
||||
}
|
||||
|
||||
private State getHeatChannel1Demand() {
|
||||
return getData().heatingChannels.size() >= 1
|
||||
? new QuantityType<>(getData().heatingChannels.get(0).getPercentageDemand(), SmartHomeUnits.PERCENT)
|
||||
: UnDefType.UNDEF;
|
||||
}
|
||||
|
||||
private State getHeatChannel2Demand() {
|
||||
return getData().heatingChannels.size() >= 2
|
||||
? new QuantityType<>(getData().heatingChannels.get(1).getPercentageDemand(), SmartHomeUnits.PERCENT)
|
||||
: UnDefType.UNDEF;
|
||||
}
|
||||
|
||||
private State getHeatChannel1DemandState() {
|
||||
return OnOffType.from(getData().heatingChannels.size() >= 1
|
||||
&& "ON".equalsIgnoreCase(getData().heatingChannels.get(0).getHeatingRelayState()));
|
||||
}
|
||||
|
||||
private State getHeatChannel2DemandState() {
|
||||
return OnOffType.from(getData().heatingChannels.size() >= 2
|
||||
&& "ON".equalsIgnoreCase(getData().heatingChannels.get(1).getHeatingRelayState()));
|
||||
}
|
||||
|
||||
private State getAwayModeState() {
|
||||
return OnOffType.from(getData().system.getOverrideType() != null
|
||||
&& "AWAY".equalsIgnoreCase(getData().system.getOverrideType()));
|
||||
}
|
||||
|
||||
private State getEcoModeState() {
|
||||
return OnOffType.from(getData().system.getEcoModeEnabled() != null && getData().system.getEcoModeEnabled());
|
||||
}
|
||||
|
||||
private void setAwayMode(final Boolean awayMode) throws DraytonWiserApiException {
|
||||
getApi().setAwayMode(awayMode);
|
||||
}
|
||||
|
||||
private void setEcoMode(final Boolean ecoMode) throws DraytonWiserApiException {
|
||||
getApi().setEcoMode(ecoMode);
|
||||
}
|
||||
|
||||
static class ControllerData {
|
||||
public final DeviceDTO device;
|
||||
public final SystemDTO system;
|
||||
public final StationDTO station;
|
||||
public final List<HeatingChannelDTO> heatingChannels;
|
||||
public final List<HotWaterDTO> hotWaterChannels;
|
||||
|
||||
public ControllerData(final DeviceDTO device, final SystemDTO system, final StationDTO station,
|
||||
final List<HeatingChannelDTO> heatingChannels, final List<HotWaterDTO> hotWaterChannels) {
|
||||
this.device = device;
|
||||
this.system = system;
|
||||
this.station = station;
|
||||
this.heatingChannels = heatingChannels;
|
||||
this.hotWaterChannels = hotWaterChannels;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.draytonwiser.internal.handler;
|
||||
|
||||
import static org.openhab.binding.draytonwiser.internal.DraytonWiserBindingConstants.PROP_SERIAL_NUMBER;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.draytonwiser.internal.model.DeviceDTO;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
* @author Hilbrand Bouwkamp - Put all device property setting in a separate class
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public final class DraytonWiserPropertyHelper {
|
||||
|
||||
private DraytonWiserPropertyHelper() {
|
||||
// helper class
|
||||
}
|
||||
|
||||
public static void setPropertiesWithSerialNumber(final DeviceDTO device, final Map<String, Object> properties) {
|
||||
properties.put(PROP_SERIAL_NUMBER, device.getSerialNumber());
|
||||
setGeneralDeviceProperties(device, properties);
|
||||
}
|
||||
|
||||
public static void setGeneralDeviceProperties(final DeviceDTO device,
|
||||
final Map<String, ? super String> properties) {
|
||||
properties.put("Device Type", device.getProductIdentifier());
|
||||
properties.put("Firmware Version", device.getActiveFirmwareVersion());
|
||||
properties.put("Manufacturer", device.getManufacturer());
|
||||
properties.put("Model", device.getModelIdentifier());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
/**
|
||||
* 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.draytonwiser.internal.handler;
|
||||
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.draytonwiser.internal.DraytonWiserRefreshListener;
|
||||
import org.openhab.binding.draytonwiser.internal.api.DraytonWiserApi;
|
||||
import org.openhab.binding.draytonwiser.internal.api.DraytonWiserApiException;
|
||||
import org.openhab.binding.draytonwiser.internal.model.DraytonWiserDTO;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.ThingStatusInfo;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.thing.util.ThingHandlerHelper;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link DraytonWiserThingHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
* @author Hilbrand Bouwkamp - Moved generic code from subclasses to this class
|
||||
*/
|
||||
@NonNullByDefault
|
||||
abstract class DraytonWiserThingHandler<T> extends BaseThingHandler implements DraytonWiserRefreshListener {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private @Nullable DraytonWiserApi api;
|
||||
private @Nullable T data;
|
||||
private @Nullable DraytonWiserDTO draytonWiseDTO;
|
||||
private @Nullable ScheduledFuture<?> handleCommandRefreshFuture;
|
||||
|
||||
protected DraytonWiserThingHandler(final Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
final HeatHubHandler bridgeHandler = getHeatHubHandler();
|
||||
|
||||
if (bridgeHandler == null) {
|
||||
api = null;
|
||||
} else {
|
||||
api = bridgeHandler.getApi();
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void handleCommand(final ChannelUID channelUID, final Command command) {
|
||||
final HeatHubHandler heatHubHandler = getHeatHubHandler();
|
||||
|
||||
if (heatHubHandler == null) {
|
||||
return; // if null status will be updated to offline
|
||||
}
|
||||
if (command instanceof RefreshType) {
|
||||
heatHubHandler.refresh();
|
||||
} else {
|
||||
final DraytonWiserApi api = this.api;
|
||||
|
||||
if (api != null && data != null) {
|
||||
try {
|
||||
handleCommand(channelUID.getId(), command);
|
||||
// cancel previous refresh, but wait for it to finish, so no forced cancel
|
||||
disposehandleCommandRefreshFuture(false);
|
||||
// update the state after the heathub has had time to react
|
||||
handleCommandRefreshFuture = scheduler.schedule(heatHubHandler::refresh, 5, TimeUnit.SECONDS);
|
||||
} catch (final DraytonWiserApiException e) {
|
||||
logger.warn("Failed to handle command {} for channel {}: {}", command, channelUID, e.getMessage());
|
||||
logger.trace("DraytonWiserApiException", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void disposehandleCommandRefreshFuture(final boolean force) {
|
||||
final ScheduledFuture<?> future = handleCommandRefreshFuture;
|
||||
|
||||
if (future != null) {
|
||||
future.cancel(force);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void dispose() {
|
||||
disposehandleCommandRefreshFuture(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the actual command. This method is only called when api and device cache are not null.
|
||||
*
|
||||
* @param channelId Channel id part of the Channel UID
|
||||
* @param command the command to perform
|
||||
* @throws DraytonWiserApiException
|
||||
*/
|
||||
protected abstract void handleCommand(String channelId, Command command) throws DraytonWiserApiException;
|
||||
|
||||
@Override
|
||||
public final void onRefresh(final DraytonWiserDTO draytonWiseDTO) {
|
||||
this.draytonWiseDTO = draytonWiseDTO;
|
||||
try {
|
||||
if (ThingHandlerHelper.isHandlerInitialized(this)) {
|
||||
data = api == null ? null : collectData(draytonWiseDTO);
|
||||
refresh();
|
||||
if (data == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
|
||||
"No data received");
|
||||
} else {
|
||||
if (getThing().getStatus() != ThingStatus.ONLINE) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (final RuntimeException | DraytonWiserApiException e) {
|
||||
logger.debug("Exception occurred during refresh: {}", e.getMessage(), e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to refresh the channels state.
|
||||
*/
|
||||
protected abstract void refresh();
|
||||
|
||||
/**
|
||||
* Conditionally updates the state. If no data or no api set the state will be set to UNDEF.
|
||||
*
|
||||
* @param channelId String id of the channel to update
|
||||
* @param stateFunction function to return the state, called when api and data are available
|
||||
*/
|
||||
protected void updateState(final String channelId, final Supplier<State> stateFunction) {
|
||||
final State state = api == null || data == null ? UnDefType.UNDEF : stateFunction.get();
|
||||
|
||||
updateState(channelId, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the handler specific data object only if all data is available.
|
||||
* If not all data is available it should return null.
|
||||
*
|
||||
* @param draytonWiseDTO data object with domain data as received from the hub
|
||||
* @return handler data object if available else null
|
||||
* @throws DraytonWiserApiException
|
||||
*/
|
||||
protected abstract @Nullable T collectData(DraytonWiserDTO draytonWiseDTO) throws DraytonWiserApiException;
|
||||
|
||||
protected DraytonWiserApi getApi() {
|
||||
final DraytonWiserApi api = this.api;
|
||||
|
||||
if (api == null) {
|
||||
throw new IllegalStateException("API not set");
|
||||
}
|
||||
return api;
|
||||
}
|
||||
|
||||
protected T getData() {
|
||||
final @Nullable T data = this.data;
|
||||
|
||||
if (data == null) {
|
||||
throw new IllegalStateException("Data not set");
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
protected DraytonWiserDTO getDraytonWiseDTO() {
|
||||
final DraytonWiserDTO draytonWiseDTO = this.draytonWiseDTO;
|
||||
|
||||
if (draytonWiseDTO == null) {
|
||||
throw new IllegalStateException("DraytonWiseDTO not set");
|
||||
}
|
||||
return draytonWiseDTO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bridgeStatusChanged(final ThingStatusInfo bridgeStatusInfo) {
|
||||
if (bridgeStatusInfo.getStatus() == ThingStatus.ONLINE) {
|
||||
if (getThing().getStatus() != ThingStatus.ONLINE) {
|
||||
final HeatHubHandler bridgeHandler = getHeatHubHandler();
|
||||
|
||||
api = bridgeHandler == null ? null : bridgeHandler.getApi();
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
}
|
||||
}
|
||||
|
||||
private @Nullable HeatHubHandler getHeatHubHandler() {
|
||||
final Bridge bridge = getBridge();
|
||||
|
||||
if (bridge == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
return null;
|
||||
} else {
|
||||
return (HeatHubHandler) bridge.getHandler();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.draytonwiser.internal.handler;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* @author Hilbrand Bouwkamp - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class HeatHubConfiguration {
|
||||
public String networkAddress = "";
|
||||
public String secret = "";
|
||||
public int refresh;
|
||||
public int awaySetPoint;
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/**
|
||||
* 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.draytonwiser.internal.handler;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.openhab.binding.draytonwiser.internal.DraytonWiserRefreshListener;
|
||||
import org.openhab.binding.draytonwiser.internal.api.DraytonWiserApi;
|
||||
import org.openhab.binding.draytonwiser.internal.api.DraytonWiserApiException;
|
||||
import org.openhab.binding.draytonwiser.internal.discovery.DraytonWiserDiscoveryService;
|
||||
import org.openhab.binding.draytonwiser.internal.model.DeviceDTO;
|
||||
import org.openhab.binding.draytonwiser.internal.model.DomainDTO;
|
||||
import org.openhab.binding.draytonwiser.internal.model.DraytonWiserDTO;
|
||||
import org.openhab.core.cache.ExpiringCache;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.binding.BaseBridgeHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.openhab.core.thing.util.ThingHandlerHelper;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link HeatHubHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
* @author Hilbrand Bouwkamp - Moved api and helper code to separate classes
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class HeatHubHandler extends BaseBridgeHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(HeatHubHandler.class);
|
||||
private final DraytonWiserApi api;
|
||||
private final ExpiringCache<Boolean> refreshCache = new ExpiringCache<>(3, this::actualRefresh);
|
||||
|
||||
private boolean updateProperties;
|
||||
private @Nullable DraytonWiserRefreshListener discoveryService;
|
||||
private @Nullable ScheduledFuture<?> refreshJob;
|
||||
|
||||
public HeatHubHandler(final Bridge thing, final HttpClient httpClient) {
|
||||
super(thing);
|
||||
api = new DraytonWiserApi(httpClient);
|
||||
}
|
||||
|
||||
public DraytonWiserApi getApi() {
|
||||
return api;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Class<? extends ThingHandlerService>> getServices() {
|
||||
return Collections.singleton(DraytonWiserDiscoveryService.class);
|
||||
}
|
||||
|
||||
public void setDiscoveryService(final DraytonWiserRefreshListener discoveryService) {
|
||||
this.discoveryService = discoveryService;
|
||||
refreshCache.invalidateValue();
|
||||
refresh();
|
||||
}
|
||||
|
||||
public void unsetDiscoveryService() {
|
||||
discoveryService = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(final ChannelUID channelUID, final Command command) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("Initializing Drayton Wiser Heat Hub handler");
|
||||
final HeatHubConfiguration configuration = getConfigAs(HeatHubConfiguration.class);
|
||||
api.setConfiguration(configuration);
|
||||
updateProperties = true;
|
||||
refreshJob = scheduler.scheduleWithFixedDelay(this::refresh, 0, configuration.refresh, TimeUnit.SECONDS);
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
refreshCache.getValue();
|
||||
}
|
||||
|
||||
private @Nullable Boolean actualRefresh() {
|
||||
try {
|
||||
if (ThingHandlerHelper.isHandlerInitialized(this)) {
|
||||
logger.debug("Refreshing devices");
|
||||
final DomainDTO domain = api.getDomain();
|
||||
|
||||
if (domain == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
|
||||
"No data received");
|
||||
} else {
|
||||
if (getThing().getStatus() != ThingStatus.ONLINE) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
final DraytonWiserDTO draytonWiseDTO = new DraytonWiserDTO(domain);
|
||||
|
||||
updateProperties(draytonWiseDTO);
|
||||
notifyListeners(draytonWiseDTO);
|
||||
}
|
||||
logger.debug("Finished refreshing devices");
|
||||
}
|
||||
} catch (final RuntimeException | DraytonWiserApiException e) {
|
||||
logger.debug("Exception occurred during execution: {}", e.getMessage(), e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, e.getMessage());
|
||||
return null;
|
||||
}
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void childHandlerInitialized(final ThingHandler childHandler, final Thing childThing) {
|
||||
refresh();
|
||||
}
|
||||
|
||||
private void updateProperties(final DraytonWiserDTO draytonWiseDTO) {
|
||||
if (updateProperties) {
|
||||
final DeviceDTO device = draytonWiseDTO.getExtendedDeviceProperties(0);
|
||||
|
||||
if (device != null) {
|
||||
final Map<String, String> properties = editProperties();
|
||||
DraytonWiserPropertyHelper.setGeneralDeviceProperties(device, properties);
|
||||
updateProperties(properties);
|
||||
updateProperties = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
final ScheduledFuture<?> future = refreshJob;
|
||||
|
||||
if (future != null) {
|
||||
future.cancel(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyListeners(final DraytonWiserDTO domain) {
|
||||
final DraytonWiserRefreshListener discoveryListener = discoveryService;
|
||||
|
||||
if (discoveryListener != null) {
|
||||
discoveryListener.onRefresh(domain);
|
||||
}
|
||||
getThing().getThings().stream().map(Thing::getHandler)
|
||||
.filter(handler -> handler instanceof DraytonWiserRefreshListener)
|
||||
.map(DraytonWiserRefreshListener.class::cast).forEach(listener -> listener.onRefresh(domain));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/**
|
||||
* 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.draytonwiser.internal.handler;
|
||||
|
||||
import static org.openhab.binding.draytonwiser.internal.DraytonWiserBindingConstants.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.measure.quantity.Time;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.draytonwiser.internal.api.DraytonWiserApiException;
|
||||
import org.openhab.binding.draytonwiser.internal.handler.HotWaterHandler.HotWaterData;
|
||||
import org.openhab.binding.draytonwiser.internal.model.DraytonWiserDTO;
|
||||
import org.openhab.binding.draytonwiser.internal.model.HotWaterDTO;
|
||||
import org.openhab.binding.draytonwiser.internal.model.SystemDTO;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.SmartHomeUnits;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.State;
|
||||
|
||||
/**
|
||||
* The {@link HotWaterHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
* @author Hilbrand Bouwkamp - Simplified handler to handle null data
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class HotWaterHandler extends DraytonWiserThingHandler<HotWaterData> {
|
||||
|
||||
public HotWaterHandler(final Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleCommand(final String channelId, final Command command) throws DraytonWiserApiException {
|
||||
if (command instanceof OnOffType && CHANNEL_MANUAL_MODE_STATE.equals(channelId)) {
|
||||
setManualMode(OnOffType.ON.equals(command));
|
||||
} else if (command instanceof OnOffType && CHANNEL_HOT_WATER_SETPOINT.equals(channelId)) {
|
||||
setSetPoint(OnOffType.ON.equals(command));
|
||||
} else if (command instanceof DecimalType && CHANNEL_HOT_WATER_BOOST_DURATION.equals(channelId)) {
|
||||
setBoostDuration(Math.round((Float.parseFloat(command.toString()) * 60)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void refresh() {
|
||||
updateState(CHANNEL_HOT_WATER_OVERRIDE, this::getHotWaterOverride);
|
||||
updateState(CHANNEL_HOTWATER_DEMAND_STATE, this::getHotWaterDemandState);
|
||||
updateState(CHANNEL_MANUAL_MODE_STATE, this::getManualModeState);
|
||||
updateState(CHANNEL_HOT_WATER_SETPOINT, this::getSetPointState);
|
||||
updateState(CHANNEL_HOT_WATER_BOOSTED, this::getBoostedState);
|
||||
updateState(CHANNEL_HOT_WATER_BOOST_REMAINING, this::getBoostRemainingState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable HotWaterData collectData(final DraytonWiserDTO domainDTOProxy) {
|
||||
final SystemDTO system = domainDTOProxy.getSystem();
|
||||
final List<HotWaterDTO> hotWater = domainDTOProxy.getHotWater();
|
||||
|
||||
return system == null ? null : new HotWaterData(system, hotWater);
|
||||
}
|
||||
|
||||
private State getHotWaterOverride() {
|
||||
return OnOffType.from("ON".equalsIgnoreCase(getData().system.getHotWaterButtonOverrideState()));
|
||||
}
|
||||
|
||||
private State getHotWaterDemandState() {
|
||||
final List<HotWaterDTO> hotWater = getData().hotWater;
|
||||
return OnOffType.from(hotWater.size() >= 1 && "ON".equalsIgnoreCase(hotWater.get(0).getHotWaterRelayState()));
|
||||
}
|
||||
|
||||
private State getManualModeState() {
|
||||
final List<HotWaterDTO> hotWater = getData().hotWater;
|
||||
return OnOffType.from(hotWater.size() >= 1 && "MANUAL".equalsIgnoreCase(hotWater.get(0).getMode()));
|
||||
}
|
||||
|
||||
private State getSetPointState() {
|
||||
final List<HotWaterDTO> hotWater = getData().hotWater;
|
||||
return OnOffType.from(hotWater.size() >= 1 && "ON".equalsIgnoreCase(hotWater.get(0).getWaterHeatingState()));
|
||||
}
|
||||
|
||||
private void setManualMode(final boolean manualMode) throws DraytonWiserApiException {
|
||||
getApi().setHotWaterManualMode(manualMode);
|
||||
}
|
||||
|
||||
private void setSetPoint(final boolean setPointMode) throws DraytonWiserApiException {
|
||||
getApi().setHotWaterSetPoint(setPointMode ? 1100 : -200);
|
||||
}
|
||||
|
||||
private void setBoostDuration(final int durationMinutes) throws DraytonWiserApiException {
|
||||
if (durationMinutes > 0) {
|
||||
getApi().setHotWaterBoostActive(durationMinutes);
|
||||
} else {
|
||||
getApi().setHotWaterBoostInactive();
|
||||
}
|
||||
}
|
||||
|
||||
private State getBoostedState() {
|
||||
if (getData().hotWater.size() >= 1) {
|
||||
final HotWaterDTO firstChannel = getData().hotWater.get(0);
|
||||
|
||||
if (firstChannel.getOverrideTimeoutUnixTime() != null
|
||||
&& !"NONE".equalsIgnoreCase(firstChannel.getOverrideType())) {
|
||||
return OnOffType.ON;
|
||||
}
|
||||
}
|
||||
|
||||
updateState(CHANNEL_HOT_WATER_BOOST_DURATION, DecimalType.ZERO);
|
||||
|
||||
return OnOffType.OFF;
|
||||
}
|
||||
|
||||
private State getBoostRemainingState() {
|
||||
if (getData().hotWater.size() >= 1) {
|
||||
final HotWaterDTO firstChannel = getData().hotWater.get(0);
|
||||
final Integer overrideTimeout = firstChannel.getOverrideTimeoutUnixTime();
|
||||
|
||||
if (overrideTimeout != null && !"NONE".equalsIgnoreCase(firstChannel.getOverrideType())) {
|
||||
return new QuantityType<Time>(overrideTimeout - (System.currentTimeMillis() / 1000L),
|
||||
SmartHomeUnits.SECOND);
|
||||
}
|
||||
}
|
||||
return new QuantityType<Time>(0, SmartHomeUnits.SECOND);
|
||||
}
|
||||
|
||||
static class HotWaterData {
|
||||
public final SystemDTO system;
|
||||
public final List<HotWaterDTO> hotWater;
|
||||
|
||||
public HotWaterData(final SystemDTO system, final List<HotWaterDTO> hotWater) {
|
||||
this.system = system;
|
||||
this.hotWater = hotWater;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
/**
|
||||
* 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.draytonwiser.internal.handler;
|
||||
|
||||
import static org.openhab.binding.draytonwiser.internal.DraytonWiserBindingConstants.*;
|
||||
|
||||
import javax.measure.quantity.Time;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.draytonwiser.internal.api.DraytonWiserApiException;
|
||||
import org.openhab.binding.draytonwiser.internal.model.DraytonWiserDTO;
|
||||
import org.openhab.binding.draytonwiser.internal.model.RoomDTO;
|
||||
import org.openhab.binding.draytonwiser.internal.model.RoomStatDTO;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.OpenClosedType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
import org.openhab.core.library.unit.SmartHomeUnits;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
|
||||
/**
|
||||
* The {@link RoomHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
* @author Hilbrand Bouwkamp - Simplified handler to handle null data
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class RoomHandler extends DraytonWiserThingHandler<RoomDTO> {
|
||||
|
||||
private String name = "";
|
||||
|
||||
public RoomHandler(final Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
name = (String) getConfig().get("name");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleCommand(final String channelId, final Command command) throws DraytonWiserApiException {
|
||||
switch (channelId) {
|
||||
case CHANNEL_CURRENT_SETPOINT:
|
||||
if (command instanceof QuantityType) {
|
||||
setSetPoint((QuantityType<?>) command);
|
||||
}
|
||||
break;
|
||||
case CHANNEL_MANUAL_MODE_STATE:
|
||||
if (command instanceof OnOffType) {
|
||||
setManualMode(OnOffType.ON.equals(command));
|
||||
}
|
||||
break;
|
||||
case CHANNEL_ROOM_BOOST_DURATION:
|
||||
if (command instanceof DecimalType) {
|
||||
setBoostDuration(Math.round((((DecimalType) command).floatValue() * 60)));
|
||||
}
|
||||
break;
|
||||
case CHANNEL_ROOM_WINDOW_STATE_DETECTION:
|
||||
if (command instanceof OnOffType) {
|
||||
setWindowStateDetection(OnOffType.ON.equals(command));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void refresh() {
|
||||
updateState(CHANNEL_CURRENT_TEMPERATURE, this::getTemperature);
|
||||
updateState(CHANNEL_CURRENT_HUMIDITY, this::getHumidity);
|
||||
updateState(CHANNEL_CURRENT_SETPOINT, this::getSetPoint);
|
||||
updateState(CHANNEL_CURRENT_DEMAND, this::getDemand);
|
||||
updateState(CHANNEL_HEAT_REQUEST, this::getHeatRequest);
|
||||
updateState(CHANNEL_MANUAL_MODE_STATE, this::getManualModeState);
|
||||
updateState(CHANNEL_ROOM_BOOSTED, this::getBoostedState);
|
||||
updateState(CHANNEL_ROOM_BOOST_REMAINING, this::getBoostRemainingState);
|
||||
updateState(CHANNEL_ROOM_WINDOW_STATE_DETECTION, this::getWindowDetectionState);
|
||||
updateState(CHANNEL_ROOM_WINDOW_STATE, this::getWindowState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable RoomDTO collectData(final DraytonWiserDTO domainDTOProxy) {
|
||||
return domainDTOProxy.getRoomByName(name);
|
||||
}
|
||||
|
||||
private State getSetPoint() {
|
||||
return new QuantityType<>(getData().getCurrentSetPoint() / 10.0, SIUnits.CELSIUS);
|
||||
}
|
||||
|
||||
private void setSetPoint(final QuantityType<?> command) throws DraytonWiserApiException {
|
||||
if (getData().getId() != null) {
|
||||
final QuantityType<?> value = command.toUnit(SIUnits.CELSIUS);
|
||||
|
||||
if (value != null) {
|
||||
final int newSetPoint = (int) Math.round(value.doubleValue() * 10);
|
||||
|
||||
getApi().setRoomSetPoint(getData().getId(), newSetPoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private State getHumidity() {
|
||||
if (getData().getId() != null && getData().getRoomStatId() != null) {
|
||||
final RoomStatDTO roomStat = getDraytonWiseDTO().getRoomStat(getData().getRoomStatId());
|
||||
|
||||
if (roomStat != null) {
|
||||
final Integer humidity = roomStat.getMeasuredHumidity();
|
||||
|
||||
return humidity == null ? UnDefType.UNDEF : new QuantityType<>(humidity, SmartHomeUnits.PERCENT);
|
||||
}
|
||||
}
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
|
||||
private State getTemperature() {
|
||||
final int fullScaleTemp = getData().getCalculatedTemperature();
|
||||
|
||||
return OFFLINE_TEMPERATURE == fullScaleTemp ? UnDefType.UNDEF
|
||||
: new QuantityType<>(fullScaleTemp / 10.0, SIUnits.CELSIUS);
|
||||
}
|
||||
|
||||
private State getDemand() {
|
||||
return new QuantityType<>(getData().getPercentageDemand(), SmartHomeUnits.PERCENT);
|
||||
}
|
||||
|
||||
private State getHeatRequest() {
|
||||
return OnOffType.from(getData().getControlOutputState());
|
||||
}
|
||||
|
||||
private State getManualModeState() {
|
||||
return OnOffType.from("MANUAL".equalsIgnoreCase(getData().getMode()));
|
||||
}
|
||||
|
||||
private void setManualMode(final boolean manualMode) throws DraytonWiserApiException {
|
||||
getApi().setRoomManualMode(getData().getId(), manualMode);
|
||||
}
|
||||
|
||||
private void setWindowStateDetection(final boolean stateDetection) throws DraytonWiserApiException {
|
||||
getApi().setRoomWindowStateDetection(getData().getId(), stateDetection);
|
||||
}
|
||||
|
||||
private State getBoostedState() {
|
||||
if (getData().getOverrideTimeoutUnixTime() != null && !"NONE".equalsIgnoreCase(getData().getOverrideType())) {
|
||||
return OnOffType.ON;
|
||||
}
|
||||
updateState(CHANNEL_ROOM_BOOST_DURATION, DecimalType.ZERO);
|
||||
return OnOffType.OFF;
|
||||
}
|
||||
|
||||
private State getBoostRemainingState() {
|
||||
final Integer overrideTimeout = getData().getOverrideTimeoutUnixTime();
|
||||
if (overrideTimeout != null && !"NONE".equalsIgnoreCase(getData().getOverrideType())) {
|
||||
return new QuantityType<Time>(overrideTimeout - (System.currentTimeMillis() / 1000L),
|
||||
SmartHomeUnits.SECOND);
|
||||
}
|
||||
return new QuantityType<Time>(0, SmartHomeUnits.SECOND);
|
||||
}
|
||||
|
||||
private void setBoostDuration(final int durationMinutes) throws DraytonWiserApiException {
|
||||
if (durationMinutes > 0) {
|
||||
getApi().setRoomBoostActive(getData().getId(), getData().getCalculatedTemperature() + 20, durationMinutes);
|
||||
} else {
|
||||
getApi().setRoomBoostInactive(getData().getId());
|
||||
}
|
||||
}
|
||||
|
||||
private State getWindowDetectionState() {
|
||||
return OnOffType.from(getData().getWindowDetectionActive());
|
||||
}
|
||||
|
||||
private State getWindowState() {
|
||||
if (getData().getWindowState() != null && "OPEN".equalsIgnoreCase(getData().getWindowState())) {
|
||||
return OpenClosedType.OPEN;
|
||||
}
|
||||
return OpenClosedType.CLOSED;
|
||||
}
|
||||
}
|
||||
@@ -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.draytonwiser.internal.handler;
|
||||
|
||||
import static org.openhab.binding.draytonwiser.internal.DraytonWiserBindingConstants.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.draytonwiser.internal.DraytonWiserBindingConstants.BatteryLevel;
|
||||
import org.openhab.binding.draytonwiser.internal.DraytonWiserBindingConstants.SignalStrength;
|
||||
import org.openhab.binding.draytonwiser.internal.api.DraytonWiserApiException;
|
||||
import org.openhab.binding.draytonwiser.internal.handler.RoomStatHandler.RoomStatData;
|
||||
import org.openhab.binding.draytonwiser.internal.model.DeviceDTO;
|
||||
import org.openhab.binding.draytonwiser.internal.model.DraytonWiserDTO;
|
||||
import org.openhab.binding.draytonwiser.internal.model.RoomStatDTO;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
import org.openhab.core.library.unit.SmartHomeUnits;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
|
||||
/**
|
||||
* The {@link RoomStatHandler} is responsible for handling commands, which are sent to one of the channels.
|
||||
*
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
* @author Hilbrand Bouwkamp - Simplified handler to handle null data
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class RoomStatHandler extends DraytonWiserThingHandler<RoomStatData> {
|
||||
|
||||
private String serialNumber = "";
|
||||
|
||||
public RoomStatHandler(final Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
serialNumber = getConfig().get("serialNumber").toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleCommand(final String channelId, final Command command) throws DraytonWiserApiException {
|
||||
if (command instanceof OnOffType && CHANNEL_DEVICE_LOCKED.equals(channelId)) {
|
||||
setDeviceLocked(OnOffType.ON.equals(command));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void refresh() {
|
||||
updateState(CHANNEL_CURRENT_TEMPERATURE, this::getTemperature);
|
||||
updateState(CHANNEL_CURRENT_HUMIDITY, this::getHumidity);
|
||||
updateState(CHANNEL_CURRENT_SETPOINT, this::getSetPoint);
|
||||
updateState(CHANNEL_CURRENT_SIGNAL_RSSI, this::getSignalRSSI);
|
||||
updateState(CHANNEL_CURRENT_SIGNAL_LQI, this::getSignalLQI);
|
||||
updateState(CHANNEL_CURRENT_BATTERY_VOLTAGE, this::getBatteryVoltage);
|
||||
updateState(CHANNEL_CURRENT_WISER_SIGNAL_STRENGTH, this::getWiserSignalStrength);
|
||||
updateState(CHANNEL_CURRENT_SIGNAL_STRENGTH, this::getSignalStrength);
|
||||
updateState(CHANNEL_CURRENT_WISER_BATTERY_LEVEL, this::getWiserBatteryLevel);
|
||||
updateState(CHANNEL_CURRENT_BATTERY_LEVEL, this::getBatteryLevel);
|
||||
updateState(CHANNEL_ZIGBEE_CONNECTED, this::getZigbeeConnected);
|
||||
updateState(CHANNEL_DEVICE_LOCKED, this::getDeviceLocked);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable RoomStatData collectData(final DraytonWiserDTO domainDTOProxy) {
|
||||
final RoomStatDTO roomStat = domainDTOProxy.getRoomStat(serialNumber);
|
||||
final DeviceDTO device = roomStat == null ? null : domainDTOProxy.getExtendedDeviceProperties(roomStat.getId());
|
||||
|
||||
return roomStat == null || device == null ? null : new RoomStatData(roomStat, device);
|
||||
}
|
||||
|
||||
private State getSetPoint() {
|
||||
return new QuantityType<>(getData().roomStat.getSetPoint() / 10.0, SIUnits.CELSIUS);
|
||||
}
|
||||
|
||||
private State getHumidity() {
|
||||
final Integer humidity = getData().roomStat.getMeasuredHumidity();
|
||||
|
||||
return humidity == null ? UnDefType.UNDEF : new QuantityType<>(humidity, SmartHomeUnits.PERCENT);
|
||||
}
|
||||
|
||||
private State getTemperature() {
|
||||
final int fullScaleTemp = getData().roomStat.getMeasuredTemperature();
|
||||
|
||||
return OFFLINE_TEMPERATURE == fullScaleTemp ? UnDefType.UNDEF
|
||||
: new QuantityType<>(fullScaleTemp / 10.0, SIUnits.CELSIUS);
|
||||
}
|
||||
|
||||
private State getSignalRSSI() {
|
||||
return new DecimalType(getData().device.getRssi());
|
||||
}
|
||||
|
||||
private State getSignalLQI() {
|
||||
return new DecimalType(getData().device.getLqi());
|
||||
}
|
||||
|
||||
private State getWiserSignalStrength() {
|
||||
return new StringType(getData().device.getDisplayedSignalStrength());
|
||||
}
|
||||
|
||||
private State getSignalStrength() {
|
||||
return SignalStrength.toSignalStrength(getData().device.getDisplayedSignalStrength());
|
||||
}
|
||||
|
||||
private State getBatteryVoltage() {
|
||||
return new QuantityType<>(getData().device.getBatteryVoltage() / 10.0, SmartHomeUnits.VOLT);
|
||||
}
|
||||
|
||||
private State getWiserBatteryLevel() {
|
||||
return new StringType(getData().device.getBatteryLevel());
|
||||
}
|
||||
|
||||
private State getBatteryLevel() {
|
||||
return BatteryLevel.toBatteryLevel(getData().device.getBatteryLevel());
|
||||
}
|
||||
|
||||
private State getZigbeeConnected() {
|
||||
return OnOffType.from(OFFLINE_TEMPERATURE != getData().roomStat.getMeasuredTemperature());
|
||||
}
|
||||
|
||||
private State getDeviceLocked() {
|
||||
return getData().device.getDeviceLockEnabled() == null ? UnDefType.UNDEF
|
||||
: OnOffType.from(getData().device.getDeviceLockEnabled());
|
||||
}
|
||||
|
||||
private void setDeviceLocked(final boolean state) throws DraytonWiserApiException {
|
||||
getApi().setDeviceLocked(getData().device.getId(), state);
|
||||
}
|
||||
|
||||
static class RoomStatData {
|
||||
public final RoomStatDTO roomStat;
|
||||
public final DeviceDTO device;
|
||||
|
||||
public RoomStatData(final RoomStatDTO roomStat, final DeviceDTO device) {
|
||||
this.roomStat = roomStat;
|
||||
this.device = device;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/**
|
||||
* 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.draytonwiser.internal.handler;
|
||||
|
||||
import static org.openhab.binding.draytonwiser.internal.DraytonWiserBindingConstants.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.draytonwiser.internal.api.DraytonWiserApiException;
|
||||
import org.openhab.binding.draytonwiser.internal.handler.SmartPlugHandler.SmartPlugData;
|
||||
import org.openhab.binding.draytonwiser.internal.model.DeviceDTO;
|
||||
import org.openhab.binding.draytonwiser.internal.model.DraytonWiserDTO;
|
||||
import org.openhab.binding.draytonwiser.internal.model.SmartPlugDTO;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
|
||||
/**
|
||||
* The {@link SmartPlugHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
* @author Hilbrand Bouwkamp - Simplified handler to handle null data
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class SmartPlugHandler extends DraytonWiserThingHandler<SmartPlugData> {
|
||||
|
||||
private String serialNumber = "";
|
||||
|
||||
public SmartPlugHandler(final Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
serialNumber = getConfig().get("serialNumber").toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleCommand(final String channelId, final Command command) throws DraytonWiserApiException {
|
||||
if (command instanceof OnOffType) {
|
||||
switch (channelId) {
|
||||
case CHANNEL_DEVICE_LOCKED:
|
||||
setDeviceLocked(OnOffType.ON.equals(command));
|
||||
break;
|
||||
case CHANNEL_SMARTPLUG_OUTPUT_STATE:
|
||||
setOutputState(OnOffType.ON.equals(command));
|
||||
break;
|
||||
case CHANNEL_SMARTPLUG_AWAY_ACTION:
|
||||
setAwayAction(OnOffType.ON.equals(command));
|
||||
break;
|
||||
case CHANNEL_MANUAL_MODE_STATE:
|
||||
setManualMode(OnOffType.ON.equals(command));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void refresh() {
|
||||
updateState(CHANNEL_SMARTPLUG_OUTPUT_STATE, this::getOutputState);
|
||||
updateState(CHANNEL_SMARTPLUG_AWAY_ACTION, this::getAwayAction);
|
||||
updateState(CHANNEL_CURRENT_SIGNAL_RSSI, this::getSignalRSSI);
|
||||
updateState(CHANNEL_CURRENT_SIGNAL_LQI, this::getSignalLQI);
|
||||
updateState(CHANNEL_ZIGBEE_CONNECTED, this::getZigbeeConnected);
|
||||
updateState(CHANNEL_DEVICE_LOCKED, this::getDeviceLocked);
|
||||
updateState(CHANNEL_MANUAL_MODE_STATE, this::getManualModeState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable SmartPlugData collectData(final DraytonWiserDTO domainDTOProxy) {
|
||||
final SmartPlugDTO smartPlug = domainDTOProxy.getSmartPlug(serialNumber);
|
||||
final DeviceDTO device = smartPlug == null ? null
|
||||
: domainDTOProxy.getExtendedDeviceProperties(smartPlug.getId());
|
||||
|
||||
return smartPlug == null || device == null ? null : new SmartPlugData(smartPlug, device);
|
||||
}
|
||||
|
||||
private State getAwayAction() {
|
||||
return OnOffType.from("off".equalsIgnoreCase(getData().smartPlug.getAwayAction()));
|
||||
}
|
||||
|
||||
private State getOutputState() {
|
||||
final String outputState = getData().smartPlug.getOutputState();
|
||||
return outputState == null ? UnDefType.UNDEF : OnOffType.from(outputState);
|
||||
}
|
||||
|
||||
private State getSignalRSSI() {
|
||||
return new DecimalType(getData().device.getRssi());
|
||||
}
|
||||
|
||||
private State getSignalLQI() {
|
||||
return new DecimalType(getData().device.getLqi());
|
||||
}
|
||||
|
||||
private State getZigbeeConnected() {
|
||||
return getData().device.getLqi() == null ? OnOffType.OFF : OnOffType.ON;
|
||||
}
|
||||
|
||||
private State getDeviceLocked() {
|
||||
return getData().device.getDeviceLockEnabled() == null ? UnDefType.UNDEF
|
||||
: OnOffType.from(getData().device.getDeviceLockEnabled());
|
||||
}
|
||||
|
||||
private void setDeviceLocked(final Boolean state) throws DraytonWiserApiException {
|
||||
getApi().setDeviceLocked(getData().device.getId(), state);
|
||||
}
|
||||
|
||||
private State getManualModeState() {
|
||||
return OnOffType.from("MANUAL".equalsIgnoreCase(getData().smartPlug.getMode()));
|
||||
}
|
||||
|
||||
private void setManualMode(final Boolean manualMode) throws DraytonWiserApiException {
|
||||
getApi().setSmartPlugManualMode(getData().smartPlug.getId(), manualMode);
|
||||
}
|
||||
|
||||
private void setOutputState(final Boolean outputState) throws DraytonWiserApiException {
|
||||
getApi().setSmartPlugOutputState(getData().smartPlug.getId(), outputState);
|
||||
}
|
||||
|
||||
private void setAwayAction(final Boolean awayAction) throws DraytonWiserApiException {
|
||||
getApi().setSmartPlugAwayAction(getData().smartPlug.getId(), awayAction);
|
||||
}
|
||||
|
||||
static class SmartPlugData {
|
||||
public final SmartPlugDTO smartPlug;
|
||||
public final DeviceDTO device;
|
||||
|
||||
public SmartPlugData(final SmartPlugDTO smartPlug, final DeviceDTO device) {
|
||||
this.smartPlug = smartPlug;
|
||||
this.device = device;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
* 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.draytonwiser.internal.handler;
|
||||
|
||||
import static org.openhab.binding.draytonwiser.internal.DraytonWiserBindingConstants.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.draytonwiser.internal.DraytonWiserBindingConstants.BatteryLevel;
|
||||
import org.openhab.binding.draytonwiser.internal.DraytonWiserBindingConstants.SignalStrength;
|
||||
import org.openhab.binding.draytonwiser.internal.api.DraytonWiserApiException;
|
||||
import org.openhab.binding.draytonwiser.internal.handler.TRVHandler.SmartValveData;
|
||||
import org.openhab.binding.draytonwiser.internal.model.DeviceDTO;
|
||||
import org.openhab.binding.draytonwiser.internal.model.DraytonWiserDTO;
|
||||
import org.openhab.binding.draytonwiser.internal.model.SmartValveDTO;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
import org.openhab.core.library.unit.SmartHomeUnits;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
|
||||
/**
|
||||
* The {@link TRVHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
* @author Hilbrand Bouwkamp - Simplified handler to handle null data
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class TRVHandler extends DraytonWiserThingHandler<SmartValveData> {
|
||||
|
||||
private String serialNumber = "";
|
||||
|
||||
public TRVHandler(final Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
serialNumber = getConfig().get("serialNumber").toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleCommand(final String channelId, final Command command) throws DraytonWiserApiException {
|
||||
if (command instanceof OnOffType && CHANNEL_DEVICE_LOCKED.equals(channelId)) {
|
||||
setDeviceLocked(OnOffType.ON.equals(command));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void refresh() {
|
||||
updateState(CHANNEL_CURRENT_TEMPERATURE, this::getTemperature);
|
||||
updateState(CHANNEL_CURRENT_DEMAND, this::getDemand);
|
||||
updateState(CHANNEL_CURRENT_SETPOINT, this::getSetPoint);
|
||||
updateState(CHANNEL_CURRENT_SIGNAL_RSSI, this::getSignalRSSI);
|
||||
updateState(CHANNEL_CURRENT_SIGNAL_LQI, this::getSignalLQI);
|
||||
updateState(CHANNEL_CURRENT_BATTERY_VOLTAGE, this::getBatteryVoltage);
|
||||
updateState(CHANNEL_CURRENT_WISER_SIGNAL_STRENGTH, this::getWiserSignalStrength);
|
||||
updateState(CHANNEL_CURRENT_SIGNAL_STRENGTH, this::getSignalStrength);
|
||||
updateState(CHANNEL_CURRENT_WISER_BATTERY_LEVEL, this::getWiserBatteryLevel);
|
||||
updateState(CHANNEL_CURRENT_BATTERY_LEVEL, this::getBatteryLevel);
|
||||
updateState(CHANNEL_ZIGBEE_CONNECTED, this::getZigbeeConnected);
|
||||
updateState(CHANNEL_DEVICE_LOCKED, this::getDeviceLocked);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable SmartValveData collectData(final DraytonWiserDTO domainDTOProxy) {
|
||||
final SmartValveDTO smartValve = domainDTOProxy.getSmartValve(serialNumber);
|
||||
final DeviceDTO device = smartValve == null ? null
|
||||
: domainDTOProxy.getExtendedDeviceProperties(smartValve.getId());
|
||||
|
||||
return smartValve == null || device == null ? null : new SmartValveData(smartValve, device);
|
||||
}
|
||||
|
||||
private State getSetPoint() {
|
||||
return new QuantityType<>(getData().smartValve.getSetPoint() / 10.0, SIUnits.CELSIUS);
|
||||
}
|
||||
|
||||
private State getDemand() {
|
||||
return new QuantityType<>(getData().smartValve.getPercentageDemand(), SmartHomeUnits.PERCENT);
|
||||
}
|
||||
|
||||
private State getTemperature() {
|
||||
final int fullScaleTemp = getData().smartValve.getMeasuredTemperature();
|
||||
|
||||
return OFFLINE_TEMPERATURE == fullScaleTemp ? UnDefType.UNDEF
|
||||
: new QuantityType<>(fullScaleTemp / 10.0, SIUnits.CELSIUS);
|
||||
}
|
||||
|
||||
private State getSignalRSSI() {
|
||||
return new DecimalType(getData().device.getRssi());
|
||||
}
|
||||
|
||||
private State getSignalLQI() {
|
||||
return new DecimalType(getData().device.getLqi());
|
||||
}
|
||||
|
||||
private State getWiserSignalStrength() {
|
||||
return new StringType(getData().device.getDisplayedSignalStrength());
|
||||
}
|
||||
|
||||
private State getSignalStrength() {
|
||||
return SignalStrength.toSignalStrength(getData().device.getDisplayedSignalStrength());
|
||||
}
|
||||
|
||||
private State getBatteryVoltage() {
|
||||
return new QuantityType<>(getData().device.getBatteryVoltage() / 10.0, SmartHomeUnits.VOLT);
|
||||
}
|
||||
|
||||
private State getWiserBatteryLevel() {
|
||||
return new StringType(getData().device.getBatteryLevel());
|
||||
}
|
||||
|
||||
private State getBatteryLevel() {
|
||||
return BatteryLevel.toBatteryLevel(getData().device.getBatteryLevel());
|
||||
}
|
||||
|
||||
private State getZigbeeConnected() {
|
||||
return OnOffType.from(getData().smartValve.getMeasuredTemperature() != OFFLINE_TEMPERATURE);
|
||||
}
|
||||
|
||||
private State getDeviceLocked() {
|
||||
final Boolean locked = getData().device.getDeviceLockEnabled();
|
||||
|
||||
return locked == null ? UnDefType.UNDEF : OnOffType.from(locked);
|
||||
}
|
||||
|
||||
private void setDeviceLocked(final Boolean state) throws DraytonWiserApiException {
|
||||
getApi().setDeviceLocked(getData().device.getId(), state);
|
||||
}
|
||||
|
||||
static class SmartValveData {
|
||||
public final SmartValveDTO smartValve;
|
||||
public final DeviceDTO device;
|
||||
|
||||
public SmartValveData(final SmartValveDTO smartValve, final DeviceDTO device) {
|
||||
this.smartValve = smartValve;
|
||||
this.device = device;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.draytonwiser.internal.model;
|
||||
|
||||
/**
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
*/
|
||||
public class BoilerSettingsDTO {
|
||||
|
||||
private String controlType;
|
||||
private String fuelType;
|
||||
private String cycleRate;
|
||||
|
||||
public String getControlType() {
|
||||
return controlType;
|
||||
}
|
||||
|
||||
public void setControlType(final String controlType) {
|
||||
this.controlType = controlType;
|
||||
}
|
||||
|
||||
public String getFuelType() {
|
||||
return fuelType;
|
||||
}
|
||||
|
||||
public void setFuelType(final String fuelType) {
|
||||
this.fuelType = fuelType;
|
||||
}
|
||||
|
||||
public String getCycleRate() {
|
||||
return cycleRate;
|
||||
}
|
||||
|
||||
public void setCycleRate(final String cycleRate) {
|
||||
this.cycleRate = cycleRate;
|
||||
}
|
||||
}
|
||||
@@ -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.draytonwiser.internal.model;
|
||||
|
||||
/**
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
*/
|
||||
public class DetectedAccessPointDTO {
|
||||
|
||||
private String sSID;
|
||||
private Integer channel;
|
||||
private String securityMode;
|
||||
private Integer rSSI;
|
||||
|
||||
public String getSSID() {
|
||||
return sSID;
|
||||
}
|
||||
|
||||
public void setSSID(final String sSID) {
|
||||
this.sSID = sSID;
|
||||
}
|
||||
|
||||
public Integer getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public void setChannel(final Integer channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
public String getSecurityMode() {
|
||||
return securityMode;
|
||||
}
|
||||
|
||||
public void setSecurityMode(final String securityMode) {
|
||||
this.securityMode = securityMode;
|
||||
}
|
||||
|
||||
public Integer getRSSI() {
|
||||
return rSSI;
|
||||
}
|
||||
}
|
||||
@@ -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.draytonwiser.internal.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
*/
|
||||
public class DeviceDTO {
|
||||
|
||||
@SerializedName("id")
|
||||
private Integer id;
|
||||
private String productType;
|
||||
private String productIdentifier;
|
||||
private String activeFirmwareVersion;
|
||||
private String manufacturer;
|
||||
private String modelIdentifier;
|
||||
private String hardwareVersion;
|
||||
private String serialNumber;
|
||||
private String productRange;
|
||||
private String productModel;
|
||||
private String productFamily;
|
||||
private String displayedSignalStrength;
|
||||
private Integer batteryVoltage;
|
||||
private String batteryLevel;
|
||||
private Integer rssi;
|
||||
private Integer lqi;
|
||||
private ReceptionDTO receptionOfDevice;
|
||||
private ReceptionDTO receptionOfController;
|
||||
private Boolean deviceLockEnabled;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getProductType() {
|
||||
return productType;
|
||||
}
|
||||
|
||||
public String getProductIdentifier() {
|
||||
return productIdentifier;
|
||||
}
|
||||
|
||||
public String getActiveFirmwareVersion() {
|
||||
return activeFirmwareVersion;
|
||||
}
|
||||
|
||||
public String getManufacturer() {
|
||||
return manufacturer;
|
||||
}
|
||||
|
||||
public String getModelIdentifier() {
|
||||
return modelIdentifier;
|
||||
}
|
||||
|
||||
public String getHardwareVersion() {
|
||||
return hardwareVersion;
|
||||
}
|
||||
|
||||
public String getSerialNumber() {
|
||||
return serialNumber;
|
||||
}
|
||||
|
||||
public String getProductRange() {
|
||||
return productRange;
|
||||
}
|
||||
|
||||
public String getProductModel() {
|
||||
return productModel;
|
||||
}
|
||||
|
||||
public String getProductFamily() {
|
||||
return productFamily;
|
||||
}
|
||||
|
||||
public String getDisplayedSignalStrength() {
|
||||
return displayedSignalStrength;
|
||||
}
|
||||
|
||||
public int getBatteryVoltage() {
|
||||
return batteryVoltage == null ? Integer.MIN_VALUE : batteryVoltage;
|
||||
}
|
||||
|
||||
public String getBatteryLevel() {
|
||||
return batteryLevel;
|
||||
}
|
||||
|
||||
public Integer getRssi() {
|
||||
if (rssi != null) {
|
||||
return rssi;
|
||||
}
|
||||
|
||||
// JSON response changed with firmware update to include RSSI and LQI on a separate object
|
||||
return receptionOfDevice == null ? null : receptionOfDevice.getRSSI();
|
||||
}
|
||||
|
||||
public Integer getLqi() {
|
||||
if (lqi != null) {
|
||||
return lqi;
|
||||
}
|
||||
|
||||
return receptionOfDevice == null ? null : receptionOfDevice.getLQI();
|
||||
}
|
||||
|
||||
public ReceptionDTO getReceptionOfController() {
|
||||
return receptionOfController;
|
||||
}
|
||||
|
||||
public Boolean getDeviceLockEnabled() {
|
||||
return deviceLockEnabled;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* 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.draytonwiser.internal.model;
|
||||
|
||||
/**
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
*/
|
||||
public class DhcpStatusDTO {
|
||||
|
||||
private String status;
|
||||
private Long leaseStartTime;
|
||||
private Long leaseTime;
|
||||
private String iPv4Address;
|
||||
private String iPv4SubnetMask;
|
||||
private String iPv4DefaultGateway;
|
||||
private String iPv4PrimaryDNS;
|
||||
private String iPv4SecondaryDNS;
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public Long getLeaseStartTime() {
|
||||
return leaseStartTime;
|
||||
}
|
||||
|
||||
public Long getLeaseTime() {
|
||||
return leaseTime;
|
||||
}
|
||||
|
||||
public String getIPv4Address() {
|
||||
return iPv4Address;
|
||||
}
|
||||
|
||||
public String getIPv4SubnetMask() {
|
||||
return iPv4SubnetMask;
|
||||
}
|
||||
|
||||
public String getIPv4DefaultGateway() {
|
||||
return iPv4DefaultGateway;
|
||||
}
|
||||
|
||||
public String getIPv4PrimaryDNS() {
|
||||
return iPv4PrimaryDNS;
|
||||
}
|
||||
|
||||
public String getIPv4SecondaryDNS() {
|
||||
return iPv4SecondaryDNS;
|
||||
}
|
||||
}
|
||||
@@ -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.draytonwiser.internal.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
*/
|
||||
public class DomainDTO {
|
||||
|
||||
private SystemDTO system;
|
||||
private List<HeatingChannelDTO> heatingChannel;
|
||||
private List<HotWaterDTO> hotWater;
|
||||
private List<RoomDTO> room;
|
||||
private List<DeviceDTO> device;
|
||||
private List<SmartValveDTO> smartValve;
|
||||
private List<RoomStatDTO> roomStat;
|
||||
private List<SmartPlugDTO> smartPlug;
|
||||
|
||||
public SystemDTO getSystem() {
|
||||
return system;
|
||||
}
|
||||
|
||||
public void setSystem(final SystemDTO system) {
|
||||
this.system = system;
|
||||
}
|
||||
|
||||
public List<HeatingChannelDTO> getHeatingChannel() {
|
||||
return heatingChannel;
|
||||
}
|
||||
|
||||
public void setHeatingChannel(final List<HeatingChannelDTO> heatingChannel) {
|
||||
this.heatingChannel = heatingChannel;
|
||||
}
|
||||
|
||||
public List<HotWaterDTO> getHotWater() {
|
||||
return hotWater;
|
||||
}
|
||||
|
||||
public void setHotWater(final List<HotWaterDTO> hotWater) {
|
||||
this.hotWater = hotWater;
|
||||
}
|
||||
|
||||
public List<RoomDTO> getRoom() {
|
||||
return room;
|
||||
}
|
||||
|
||||
public void setRoom(final List<RoomDTO> room) {
|
||||
this.room = room;
|
||||
}
|
||||
|
||||
public List<DeviceDTO> getDevice() {
|
||||
return device;
|
||||
}
|
||||
|
||||
public void setDevice(final List<DeviceDTO> device) {
|
||||
this.device = device;
|
||||
}
|
||||
|
||||
public List<SmartValveDTO> getSmartValve() {
|
||||
return smartValve;
|
||||
}
|
||||
|
||||
public void setSmartValve(final List<SmartValveDTO> smartValve) {
|
||||
this.smartValve = smartValve;
|
||||
}
|
||||
|
||||
public List<RoomStatDTO> getRoomStat() {
|
||||
return roomStat;
|
||||
}
|
||||
|
||||
public void setRoomStat(final List<RoomStatDTO> roomStat) {
|
||||
this.roomStat = roomStat;
|
||||
}
|
||||
|
||||
public List<SmartPlugDTO> getSmartPlug() {
|
||||
return smartPlug;
|
||||
}
|
||||
|
||||
public void setSmartPlug(final List<SmartPlugDTO> smartPlug) {
|
||||
this.smartPlug = smartPlug;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
* 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.draytonwiser.internal.model;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Helper class to get specific data from the domain object.
|
||||
*
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
* @author Hilbrand Bouwkamp - Moved domain object helper code to it's own class
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class DraytonWiserDTO {
|
||||
|
||||
private final DomainDTO domain;
|
||||
|
||||
public DraytonWiserDTO(final DomainDTO domain) {
|
||||
this.domain = domain;
|
||||
}
|
||||
|
||||
public List<RoomStatDTO> getRoomStats() {
|
||||
return domain.getRoomStat() == null ? Collections.emptyList() : domain.getRoomStat();
|
||||
}
|
||||
|
||||
public List<SmartValveDTO> getSmartValves() {
|
||||
return domain.getSmartValve() == null ? Collections.emptyList() : domain.getSmartValve();
|
||||
}
|
||||
|
||||
public List<SmartPlugDTO> getSmartPlugs() {
|
||||
return domain.getSmartPlug() == null ? Collections.emptyList() : domain.getSmartPlug();
|
||||
}
|
||||
|
||||
public List<RoomDTO> getRooms() {
|
||||
return domain.getRoom() == null ? Collections.emptyList() : domain.getRoom();
|
||||
}
|
||||
|
||||
public @Nullable RoomDTO getRoomByName(final String name) {
|
||||
for (final RoomDTO room : domain.getRoom()) {
|
||||
if (room.getName().equalsIgnoreCase(name)) {
|
||||
return room;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public @Nullable RoomStatDTO getRoomStat(final String serialNumber) {
|
||||
final Integer id = getIdFromSerialNumber(serialNumber);
|
||||
|
||||
return id == null ? null : getRoomStat(id);
|
||||
}
|
||||
|
||||
public @Nullable RoomStatDTO getRoomStat(final int id) {
|
||||
for (final RoomStatDTO roomStat : domain.getRoomStat()) {
|
||||
if (roomStat.getId().equals(id)) {
|
||||
return roomStat;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public @Nullable SmartPlugDTO getSmartPlug(final String serialNumber) {
|
||||
final Integer id = getIdFromSerialNumber(serialNumber);
|
||||
|
||||
if (id == null) {
|
||||
return null;
|
||||
}
|
||||
for (final SmartPlugDTO smartPlug : domain.getSmartPlug()) {
|
||||
if (smartPlug.getId().equals(id)) {
|
||||
return smartPlug;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public @Nullable DeviceDTO getExtendedDeviceProperties(final int id) {
|
||||
for (final DeviceDTO device : domain.getDevice()) {
|
||||
if (device.getId().equals(id)) {
|
||||
return device;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public @Nullable SystemDTO getSystem() {
|
||||
return domain.getSystem();
|
||||
}
|
||||
|
||||
public List<HeatingChannelDTO> getHeatingChannels() {
|
||||
return domain.getHeatingChannel() == null ? Collections.emptyList() : domain.getHeatingChannel();
|
||||
}
|
||||
|
||||
public List<HotWaterDTO> getHotWater() {
|
||||
return domain.getHotWater() == null ? Collections.emptyList() : domain.getHotWater();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public RoomDTO getRoomForDeviceId(final Integer id) {
|
||||
for (final RoomDTO room : domain.getRoom()) {
|
||||
if (room != null) {
|
||||
if (room.getRoomStatId() != null && room.getRoomStatId().equals(id)) {
|
||||
return room;
|
||||
}
|
||||
|
||||
final List<Integer> trvs = room.getSmartValveIds();
|
||||
if (trvs != null) {
|
||||
for (final Integer itrv : trvs) {
|
||||
if (itrv.equals(id)) {
|
||||
return room;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public @Nullable SmartValveDTO getSmartValve(final String serialNumber) {
|
||||
final Integer id = getIdFromSerialNumber(serialNumber);
|
||||
|
||||
if (id == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (final SmartValveDTO smartValve : domain.getSmartValve()) {
|
||||
if (smartValve.getId().equals(id)) {
|
||||
return smartValve;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private @Nullable Integer getIdFromSerialNumber(final String serialNumber) {
|
||||
for (final DeviceDTO device : domain.getDevice()) {
|
||||
if (device.getSerialNumber() != null
|
||||
&& device.getSerialNumber().toLowerCase().equals(serialNumber.toLowerCase())) {
|
||||
return device.getId();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* 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.draytonwiser.internal.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
*/
|
||||
public class HeatingChannelDTO {
|
||||
|
||||
@SerializedName("id")
|
||||
private Integer id;
|
||||
private String name;
|
||||
private List<Integer> roomIds;
|
||||
private Integer percentageDemand;
|
||||
private String demandOnOffOutput;
|
||||
private String heatingRelayState;
|
||||
private Boolean isSmartValvePreventingDemand;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public List<Integer> getRoomIds() {
|
||||
return roomIds;
|
||||
}
|
||||
|
||||
public void setRoomIds(final List<Integer> roomIds) {
|
||||
this.roomIds = roomIds;
|
||||
}
|
||||
|
||||
public Integer getPercentageDemand() {
|
||||
return percentageDemand;
|
||||
}
|
||||
|
||||
public String getDemandOnOffOutput() {
|
||||
return demandOnOffOutput;
|
||||
}
|
||||
|
||||
public String getHeatingRelayState() {
|
||||
return heatingRelayState;
|
||||
}
|
||||
|
||||
public Boolean getIsSmartValvePreventingDemand() {
|
||||
return isSmartValvePreventingDemand;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* 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.draytonwiser.internal.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
*/
|
||||
public class HotWaterDTO {
|
||||
|
||||
@SerializedName("id")
|
||||
private Integer id;
|
||||
private String overrideType;
|
||||
private String mode;
|
||||
private String waterHeatingState;
|
||||
private String hotWaterRelayState;
|
||||
private Integer overrideTimeoutUnixTime;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getOverrideType() {
|
||||
return overrideType;
|
||||
}
|
||||
|
||||
public String getMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
public String getWaterHeatingState() {
|
||||
return waterHeatingState;
|
||||
}
|
||||
|
||||
public String getHotWaterRelayState() {
|
||||
return hotWaterRelayState;
|
||||
}
|
||||
|
||||
public Integer getOverrideTimeoutUnixTime() {
|
||||
return overrideTimeoutUnixTime;
|
||||
}
|
||||
}
|
||||
@@ -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.draytonwiser.internal.model;
|
||||
|
||||
/**
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
*/
|
||||
public class LocalDateAndTimeDTO {
|
||||
|
||||
private Integer year;
|
||||
private String month;
|
||||
private Integer date;
|
||||
private String day;
|
||||
private Integer time;
|
||||
|
||||
public Integer getYear() {
|
||||
return year;
|
||||
}
|
||||
|
||||
public String getMonth() {
|
||||
return month;
|
||||
}
|
||||
|
||||
public Integer getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public String getDay() {
|
||||
return day;
|
||||
}
|
||||
|
||||
public Integer getTime() {
|
||||
return time;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* 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.draytonwiser.internal.model;
|
||||
|
||||
/**
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
*/
|
||||
public class NetworkInterfaceDTO {
|
||||
|
||||
private String interfaceName;
|
||||
private String hostName;
|
||||
private String dhcpMode;
|
||||
private String iPv4HostAddress;
|
||||
private String iPv4SubnetMask;
|
||||
private String iPv4DefaultGateway;
|
||||
private String iPv4PrimaryDNS;
|
||||
private String iPv4SecondaryDNS;
|
||||
|
||||
public String getInterfaceName() {
|
||||
return interfaceName;
|
||||
}
|
||||
|
||||
public String getHostName() {
|
||||
return hostName;
|
||||
}
|
||||
|
||||
public String getDhcpMode() {
|
||||
return dhcpMode;
|
||||
}
|
||||
|
||||
public String getIPv4HostAddress() {
|
||||
return iPv4HostAddress;
|
||||
}
|
||||
|
||||
public String getIPv4SubnetMask() {
|
||||
return iPv4SubnetMask;
|
||||
}
|
||||
|
||||
public String getIPv4DefaultGateway() {
|
||||
return iPv4DefaultGateway;
|
||||
}
|
||||
|
||||
public String getIPv4PrimaryDNS() {
|
||||
return iPv4PrimaryDNS;
|
||||
}
|
||||
|
||||
public String getIPv4SecondaryDNS() {
|
||||
return iPv4SecondaryDNS;
|
||||
}
|
||||
}
|
||||
@@ -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.draytonwiser.internal.model;
|
||||
|
||||
/**
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
*/
|
||||
public class ReceptionDTO {
|
||||
|
||||
private Integer rssi;
|
||||
private Integer lqi;
|
||||
|
||||
public Integer getRSSI() {
|
||||
return rssi;
|
||||
}
|
||||
|
||||
public Integer getLQI() {
|
||||
return lqi;
|
||||
}
|
||||
}
|
||||
@@ -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.draytonwiser.internal.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
*/
|
||||
public class RoomDTO {
|
||||
|
||||
@SerializedName("id")
|
||||
private Integer id;
|
||||
private Integer overrideSetpoint;
|
||||
private Integer roomStatId;
|
||||
private List<Integer> smartValveIds;
|
||||
private String name;
|
||||
private String mode;
|
||||
private String demandType;
|
||||
private int calculatedTemperature;
|
||||
private int currentSetPoint;
|
||||
private Integer percentageDemand;
|
||||
private String controlOutputState;
|
||||
private String windowState;
|
||||
private Integer displayedSetPoint;
|
||||
private String overrideType;
|
||||
private Boolean windowDetectionActive;
|
||||
private Integer overrideTimeoutUnixTime;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(final Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Integer getOverrideTimeoutUnixTime() {
|
||||
return overrideTimeoutUnixTime;
|
||||
}
|
||||
|
||||
public Integer getOverrideSetpoint() {
|
||||
return overrideSetpoint;
|
||||
}
|
||||
|
||||
public void setOverrideSetpoint(final Integer overrideSetpoint) {
|
||||
this.overrideSetpoint = overrideSetpoint;
|
||||
}
|
||||
|
||||
public Integer getRoomStatId() {
|
||||
return roomStatId;
|
||||
}
|
||||
|
||||
public void setRoomStatId(final Integer roomStatId) {
|
||||
this.roomStatId = roomStatId;
|
||||
}
|
||||
|
||||
public List<Integer> getSmartValveIds() {
|
||||
return smartValveIds;
|
||||
}
|
||||
|
||||
public void setSmartValveIds(final List<Integer> smartValveIds) {
|
||||
this.smartValveIds = smartValveIds;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
public void setMode(final String mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
public String getDemandType() {
|
||||
return demandType;
|
||||
}
|
||||
|
||||
public void setDemandType(final String demandType) {
|
||||
this.demandType = demandType;
|
||||
}
|
||||
|
||||
public int getCalculatedTemperature() {
|
||||
return calculatedTemperature;
|
||||
}
|
||||
|
||||
public int getCurrentSetPoint() {
|
||||
return currentSetPoint < 0 ? 0 : currentSetPoint;
|
||||
}
|
||||
|
||||
public void setCurrentSetPoint(final Integer currentSetPoint) {
|
||||
this.currentSetPoint = currentSetPoint;
|
||||
}
|
||||
|
||||
public Integer getPercentageDemand() {
|
||||
return percentageDemand;
|
||||
}
|
||||
|
||||
public String getControlOutputState() {
|
||||
return controlOutputState;
|
||||
}
|
||||
|
||||
public String getWindowState() {
|
||||
return windowState;
|
||||
}
|
||||
|
||||
public Integer getDisplayedSetPoint() {
|
||||
return displayedSetPoint;
|
||||
}
|
||||
|
||||
public void setDisplayedSetPoint(final Integer displayedSetPoint) {
|
||||
this.displayedSetPoint = displayedSetPoint;
|
||||
}
|
||||
|
||||
public String getOverrideType() {
|
||||
return overrideType;
|
||||
}
|
||||
|
||||
public Boolean getWindowDetectionActive() {
|
||||
return windowDetectionActive;
|
||||
}
|
||||
}
|
||||
@@ -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.draytonwiser.internal.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
*/
|
||||
public class RoomStatDTO {
|
||||
|
||||
@SerializedName("id")
|
||||
private Integer id;
|
||||
private int setPoint;
|
||||
private Integer measuredTemperature;
|
||||
private Integer measuredHumidity;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public int getSetPoint() {
|
||||
return Math.max(0, setPoint);
|
||||
}
|
||||
|
||||
public void setSetPoint(final Integer setPoint) {
|
||||
this.setPoint = setPoint;
|
||||
}
|
||||
|
||||
public Integer getMeasuredTemperature() {
|
||||
return measuredTemperature;
|
||||
}
|
||||
|
||||
public Integer getMeasuredHumidity() {
|
||||
return measuredHumidity;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.draytonwiser.internal.model;
|
||||
|
||||
/**
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
*/
|
||||
public class RssiDTO {
|
||||
|
||||
private Integer current;
|
||||
private Integer min;
|
||||
private Integer max;
|
||||
|
||||
public Integer getCurrent() {
|
||||
return current;
|
||||
}
|
||||
|
||||
public Integer getMin() {
|
||||
return min;
|
||||
}
|
||||
|
||||
public Integer getMax() {
|
||||
return max;
|
||||
}
|
||||
}
|
||||
@@ -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.draytonwiser.internal.model;
|
||||
|
||||
/**
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
*/
|
||||
public class SetPointDTO {
|
||||
|
||||
private Integer time;
|
||||
private Integer degreesC;
|
||||
|
||||
public Integer getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public Integer getDegreesC() {
|
||||
return degreesC;
|
||||
}
|
||||
}
|
||||
@@ -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.draytonwiser.internal.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
*/
|
||||
public class SmartPlugDTO {
|
||||
|
||||
@SerializedName("id")
|
||||
private Integer id;
|
||||
private String name;
|
||||
private String manualState;
|
||||
private String mode;
|
||||
private String awayAction;
|
||||
private String outputState;
|
||||
private String controlSource;
|
||||
private String scheduledState;
|
||||
private String targetState;
|
||||
private Integer debounceCount;
|
||||
private String overrideState;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getManualState() {
|
||||
return manualState;
|
||||
}
|
||||
|
||||
public String getAwayAction() {
|
||||
return awayAction;
|
||||
}
|
||||
|
||||
public String getOutputState() {
|
||||
return outputState;
|
||||
}
|
||||
|
||||
public String getControlSource() {
|
||||
return controlSource;
|
||||
}
|
||||
|
||||
public String getScheduledState() {
|
||||
return scheduledState;
|
||||
}
|
||||
|
||||
public String getTargetState() {
|
||||
return targetState;
|
||||
}
|
||||
|
||||
public Integer getDebounceCount() {
|
||||
return debounceCount;
|
||||
}
|
||||
|
||||
public String getOverrideState() {
|
||||
return overrideState;
|
||||
}
|
||||
|
||||
public String getMode() {
|
||||
return mode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* 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.draytonwiser.internal.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
*/
|
||||
public class SmartValveDTO {
|
||||
|
||||
@SerializedName("id")
|
||||
private Integer id;
|
||||
private int setPoint;
|
||||
private int measuredTemperature;
|
||||
private Integer percentageDemand;
|
||||
private String windowState;
|
||||
private Integer externalRoomStatTemperature;
|
||||
private String mountingOrientation;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public int getSetPoint() {
|
||||
return Math.max(0, setPoint);
|
||||
}
|
||||
|
||||
public void setSetPoint(final Integer setPoint) {
|
||||
this.setPoint = setPoint;
|
||||
}
|
||||
|
||||
public int getMeasuredTemperature() {
|
||||
return measuredTemperature;
|
||||
}
|
||||
|
||||
public Integer getPercentageDemand() {
|
||||
return percentageDemand;
|
||||
}
|
||||
|
||||
public String getWindowState() {
|
||||
return windowState;
|
||||
}
|
||||
|
||||
public Integer getExternalRoomStatTemperature() {
|
||||
return externalRoomStatTemperature;
|
||||
}
|
||||
|
||||
public String getMountingOrientation() {
|
||||
return mountingOrientation;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
* 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.draytonwiser.internal.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
*/
|
||||
public class StationDTO {
|
||||
|
||||
private Boolean enabled;
|
||||
private String sSID;
|
||||
private String securityMode;
|
||||
private Long scanSlotTime;
|
||||
private Integer scanSlots;
|
||||
private NetworkInterfaceDTO networkInterface;
|
||||
private String connectionStatus;
|
||||
private DhcpStatusDTO dhcpStatus;
|
||||
private Boolean scanning;
|
||||
private List<DetectedAccessPointDTO> detectedAccessPoints;
|
||||
private Integer connectionFailures;
|
||||
private String mdnsHostname;
|
||||
private String macAddress;
|
||||
private RssiDTO rSSI;
|
||||
private Integer channel;
|
||||
|
||||
public Boolean getEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(final Boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public String getSSID() {
|
||||
return sSID;
|
||||
}
|
||||
|
||||
public void setSSID(final String sSID) {
|
||||
this.sSID = sSID;
|
||||
}
|
||||
|
||||
public String getSecurityMode() {
|
||||
return securityMode;
|
||||
}
|
||||
|
||||
public void setSecurityMode(final String securityMode) {
|
||||
this.securityMode = securityMode;
|
||||
}
|
||||
|
||||
public Long getScanSlotTime() {
|
||||
return scanSlotTime;
|
||||
}
|
||||
|
||||
public void setScanSlotTime(final Long scanSlotTime) {
|
||||
this.scanSlotTime = scanSlotTime;
|
||||
}
|
||||
|
||||
public Integer getScanSlots() {
|
||||
return scanSlots;
|
||||
}
|
||||
|
||||
public void setScanSlots(final Integer scanSlots) {
|
||||
this.scanSlots = scanSlots;
|
||||
}
|
||||
|
||||
public NetworkInterfaceDTO getNetworkInterface() {
|
||||
return networkInterface;
|
||||
}
|
||||
|
||||
public void setNetworkInterface(final NetworkInterfaceDTO networkInterface) {
|
||||
this.networkInterface = networkInterface;
|
||||
}
|
||||
|
||||
public String getConnectionStatus() {
|
||||
return connectionStatus;
|
||||
}
|
||||
|
||||
public void setConnectionStatus(final String connectionStatus) {
|
||||
this.connectionStatus = connectionStatus;
|
||||
}
|
||||
|
||||
public DhcpStatusDTO getDhcpStatus() {
|
||||
return dhcpStatus;
|
||||
}
|
||||
|
||||
public void setDhcpStatus(final DhcpStatusDTO dhcpStatus) {
|
||||
this.dhcpStatus = dhcpStatus;
|
||||
}
|
||||
|
||||
public Boolean getScanning() {
|
||||
return scanning;
|
||||
}
|
||||
|
||||
public void setScanning(final Boolean scanning) {
|
||||
this.scanning = scanning;
|
||||
}
|
||||
|
||||
public List<DetectedAccessPointDTO> getDetectedAccessPoints() {
|
||||
return detectedAccessPoints;
|
||||
}
|
||||
|
||||
public void setDetectedAccessPoints(final List<DetectedAccessPointDTO> detectedAccessPoints) {
|
||||
this.detectedAccessPoints = detectedAccessPoints;
|
||||
}
|
||||
|
||||
public Integer getConnectionFailures() {
|
||||
return connectionFailures;
|
||||
}
|
||||
|
||||
public void setConnectionFailures(final Integer connectionFailures) {
|
||||
this.connectionFailures = connectionFailures;
|
||||
}
|
||||
|
||||
public String getMdnsHostname() {
|
||||
return mdnsHostname;
|
||||
}
|
||||
|
||||
public void setMdnsHostname(final String mdnsHostname) {
|
||||
this.mdnsHostname = mdnsHostname;
|
||||
}
|
||||
|
||||
public String getMacAddress() {
|
||||
return macAddress;
|
||||
}
|
||||
|
||||
public void setMacAddress(final String macAddress) {
|
||||
this.macAddress = macAddress;
|
||||
}
|
||||
|
||||
public RssiDTO getRSSI() {
|
||||
return rSSI;
|
||||
}
|
||||
|
||||
public void setRSSI(final RssiDTO rSSI) {
|
||||
this.rSSI = rSSI;
|
||||
}
|
||||
|
||||
public Integer getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public void setChannel(final Integer channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/**
|
||||
* 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.draytonwiser.internal.model;
|
||||
|
||||
/**
|
||||
* @author Andrew Schofield - Initial contribution
|
||||
*/
|
||||
public class SystemDTO {
|
||||
|
||||
private String pairingStatus;
|
||||
private String overrideType;
|
||||
private Integer overrideSetpoint;
|
||||
private Integer timeZoneOffset;
|
||||
private Boolean automaticDaylightSaving;
|
||||
private Integer version;
|
||||
private Boolean fotaEnabled;
|
||||
private Boolean valveProtectionEnabled;
|
||||
private Boolean ecoModeEnabled;
|
||||
private BoilerSettingsDTO boilerSettings;
|
||||
private Long unixTime;
|
||||
private String cloudConnectionStatus;
|
||||
private String zigbeeModuleVersion;
|
||||
private String zigbeeEui;
|
||||
private LocalDateAndTimeDTO localDateAndTime;
|
||||
private String heatingButtonOverrideState;
|
||||
private String hotWaterButtonOverrideState;
|
||||
|
||||
public String getPairingStatus() {
|
||||
return pairingStatus;
|
||||
}
|
||||
|
||||
public void setPairingStatus(final String pairingStatus) {
|
||||
this.pairingStatus = pairingStatus;
|
||||
}
|
||||
|
||||
public String getOverrideType() {
|
||||
return overrideType;
|
||||
}
|
||||
|
||||
public Integer getOverrideSetpoint() {
|
||||
return overrideSetpoint;
|
||||
}
|
||||
|
||||
public Integer getTimeZoneOffset() {
|
||||
return timeZoneOffset;
|
||||
}
|
||||
|
||||
public void setTimeZoneOffset(final Integer timeZoneOffset) {
|
||||
this.timeZoneOffset = timeZoneOffset;
|
||||
}
|
||||
|
||||
public Boolean getAutomaticDaylightSaving() {
|
||||
return automaticDaylightSaving;
|
||||
}
|
||||
|
||||
public void setAutomaticDaylightSaving(final Boolean automaticDaylightSaving) {
|
||||
this.automaticDaylightSaving = automaticDaylightSaving;
|
||||
}
|
||||
|
||||
public Integer getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(final Integer version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public Boolean getFotaEnabled() {
|
||||
return fotaEnabled;
|
||||
}
|
||||
|
||||
public void setFotaEnabled(final Boolean fotaEnabled) {
|
||||
this.fotaEnabled = fotaEnabled;
|
||||
}
|
||||
|
||||
public Boolean getValveProtectionEnabled() {
|
||||
return valveProtectionEnabled;
|
||||
}
|
||||
|
||||
public void setValveProtectionEnabled(final Boolean valveProtectionEnabled) {
|
||||
this.valveProtectionEnabled = valveProtectionEnabled;
|
||||
}
|
||||
|
||||
public Boolean getEcoModeEnabled() {
|
||||
return ecoModeEnabled;
|
||||
}
|
||||
|
||||
public void setEcoModeEnabled(final Boolean ecoModeEnabled) {
|
||||
this.ecoModeEnabled = ecoModeEnabled;
|
||||
}
|
||||
|
||||
public BoilerSettingsDTO getBoilerSettings() {
|
||||
return boilerSettings;
|
||||
}
|
||||
|
||||
public void setBoilerSettings(final BoilerSettingsDTO boilerSettings) {
|
||||
this.boilerSettings = boilerSettings;
|
||||
}
|
||||
|
||||
public Long getUnixTime() {
|
||||
return unixTime;
|
||||
}
|
||||
|
||||
public void setUnixTime(final Long unixTime) {
|
||||
this.unixTime = unixTime;
|
||||
}
|
||||
|
||||
public String getCloudConnectionStatus() {
|
||||
return cloudConnectionStatus;
|
||||
}
|
||||
|
||||
public void setCloudConnectionStatus(final String cloudConnectionStatus) {
|
||||
this.cloudConnectionStatus = cloudConnectionStatus;
|
||||
}
|
||||
|
||||
public String getZigbeeModuleVersion() {
|
||||
return zigbeeModuleVersion;
|
||||
}
|
||||
|
||||
public void setZigbeeModuleVersion(final String zigbeeModuleVersion) {
|
||||
this.zigbeeModuleVersion = zigbeeModuleVersion;
|
||||
}
|
||||
|
||||
public String getZigbeeEui() {
|
||||
return zigbeeEui;
|
||||
}
|
||||
|
||||
public void setZigbeeEui(final String zigbeeEui) {
|
||||
this.zigbeeEui = zigbeeEui;
|
||||
}
|
||||
|
||||
public LocalDateAndTimeDTO getLocalDateAndTime() {
|
||||
return localDateAndTime;
|
||||
}
|
||||
|
||||
public void setLocalDateAndTime(final LocalDateAndTimeDTO localDateAndTime) {
|
||||
this.localDateAndTime = localDateAndTime;
|
||||
}
|
||||
|
||||
public String getHeatingButtonOverrideState() {
|
||||
return heatingButtonOverrideState;
|
||||
}
|
||||
|
||||
public void setHeatingButtonOverrideState(final String heatingButtonOverrideState) {
|
||||
this.heatingButtonOverrideState = heatingButtonOverrideState;
|
||||
}
|
||||
|
||||
public String getHotWaterButtonOverrideState() {
|
||||
return hotWaterButtonOverrideState;
|
||||
}
|
||||
|
||||
public void setHotWaterButtonOverrideState(final String hotWaterButtonOverrideState) {
|
||||
this.hotWaterButtonOverrideState = hotWaterButtonOverrideState;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<binding:binding id="draytonwiser" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
|
||||
|
||||
<name>DraytonWiser Binding</name>
|
||||
<description>This is the binding for Drayton Wiser smart heating system.</description>
|
||||
<author>Andrew Schofield</author>
|
||||
|
||||
</binding:binding>
|
||||
@@ -0,0 +1,425 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="draytonwiser"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<!-- Bridge Thing Type -->
|
||||
<bridge-type id="heathub">
|
||||
<label>HeatHub</label>
|
||||
<description>A Drayton Wiser HeatHub acting as a bridge to Thermostats and TRVs</description>
|
||||
|
||||
<representation-property>networkAddress</representation-property>
|
||||
|
||||
<config-description>
|
||||
<parameter name="networkAddress" type="text" required="true">
|
||||
<context>network-address</context>
|
||||
<label>Network Address</label>
|
||||
<description>Network address of the HeatHub</description>
|
||||
</parameter>
|
||||
<parameter name="secret" type="text" required="true">
|
||||
<label>Authorisation Token</label>
|
||||
<description>Auth token required to access the API</description>
|
||||
</parameter>
|
||||
<parameter name="refresh" type="integer" unit="s">
|
||||
<label>Refresh Interval</label>
|
||||
<description>Interval in seconds between automatic refreshes</description>
|
||||
<default>10</default>
|
||||
</parameter>
|
||||
<parameter name="awaySetPoint" type="integer">
|
||||
<label>Away Mode Set Point</label>
|
||||
<description>Set point temperature for away mode in degrees celsius</description>
|
||||
<default>16</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</bridge-type>
|
||||
|
||||
<!-- Controller Thing Type -->
|
||||
<thing-type id="boiler-controller">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="heathub"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Boiler Controller</label>
|
||||
<description>The controller attached to the boiler</description>
|
||||
|
||||
<channels>
|
||||
<channel id="heatingOverride" typeId="heatingOverride-channel"/>
|
||||
<channel id="heatChannel1Demand" typeId="heatChannelDemand-channel">
|
||||
<label>Channel 1 Heat Demand</label>
|
||||
</channel>
|
||||
<channel id="heatChannel1DemandState" typeId="demandState-channel">
|
||||
<label>Channel 1 Requesting Heat</label>
|
||||
</channel>
|
||||
<channel id="heatChannel2Demand" typeId="heatChannelDemand-channel">
|
||||
<label>Channel 2 Heat Demand</label>
|
||||
</channel>
|
||||
<channel id="heatChannel2DemandState" typeId="demandState-channel">
|
||||
<label>Channel 2 Requesting Heat</label>
|
||||
</channel>
|
||||
<channel id="awayModeState" typeId="awayModeState-channel"/>
|
||||
<channel id="ecoModeState" typeId="ecoModeState-channel"/>
|
||||
<channel id="currentSignalRSSI" typeId="signalRSSI-channel"/>
|
||||
<channel id="currentSignalStrength" typeId="system.signal-strength"/>
|
||||
<channel id="currentWiserSignalStrength" typeId="wiserSignalStrength-channel"/>
|
||||
</channels>
|
||||
|
||||
<representation-property>id</representation-property>
|
||||
</thing-type>
|
||||
|
||||
<!-- Hot Water Thing Type -->
|
||||
<thing-type id="hotwater">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="heathub"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Hot Water</label>
|
||||
<description>The hot water heating system</description>
|
||||
|
||||
<channels>
|
||||
<channel id="hotWaterOverride" typeId="hotWaterOverride-channel"/>
|
||||
<channel id="hotWaterDemandState" typeId="demandState-channel">
|
||||
<label>Hot Water Requesting Heat</label>
|
||||
<description>Hot Water is requesting heat</description>
|
||||
</channel>
|
||||
<channel id="manualModeState" typeId="manualModeState-channel"/>
|
||||
<channel id="hotWaterSetPoint" typeId="hotWaterSetPoint-channel"/>
|
||||
<channel id="hotWaterBoostDuration" typeId="boostDuration-channel">
|
||||
<description>Duration to boost hot water for</description>
|
||||
</channel>
|
||||
<channel id="hotWaterBoosted" typeId="boosted-channel">
|
||||
<description>Is the hot water currently being boosted</description>
|
||||
</channel>
|
||||
<channel id="hotWaterBoostRemaining" typeId="boostRemaining-channel"/>
|
||||
</channels>
|
||||
|
||||
<representation-property>id</representation-property>
|
||||
</thing-type>
|
||||
|
||||
<!-- Room Thing Type -->
|
||||
<thing-type id="room">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="heathub"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Room</label>
|
||||
<description>A Room that contains a thermostat and/or TRV</description>
|
||||
|
||||
<channels>
|
||||
<channel id="currentTemperature" typeId="currentTemperature-channel"/>
|
||||
<channel id="currentHumidity" typeId="atmospheric-humidity-channel"/>
|
||||
<channel id="currentSetPoint" typeId="currentSetPoint-channel"/>
|
||||
<channel id="currentDemand" typeId="demandPercent-channel"/>
|
||||
<channel id="heatRequest" typeId="heatRequest-channel"/>
|
||||
<channel id="manualModeState" typeId="manualModeState-channel"/>
|
||||
<channel id="roomBoostDuration" typeId="boostDuration-channel">
|
||||
<description>Duration to boost the temperature for</description>
|
||||
</channel>
|
||||
<channel id="roomBoosted" typeId="boosted-channel">
|
||||
<description>Is the room temperature currently being boosted</description>
|
||||
</channel>
|
||||
<channel id="roomBoostRemaining" typeId="boostRemaining-channel"/>
|
||||
<channel id="windowStateDetection" typeId="windowStateDetection-channel"/>
|
||||
<channel id="windowState" typeId="windowState-channel"/>
|
||||
</channels>
|
||||
|
||||
<representation-property>name</representation-property>
|
||||
|
||||
<config-description>
|
||||
<parameter name="name" type="text" required="true">
|
||||
<label>Room Name</label>
|
||||
<description>The room name as it appears in the Wiser app</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<!-- Room Thermostat Thing Type -->
|
||||
<thing-type id="roomstat">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="heathub"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Thermostat</label>
|
||||
<description>Wireless Thermostat device</description>
|
||||
|
||||
<channels>
|
||||
<channel id="currentTemperature" typeId="currentTemperature-channel"/>
|
||||
<channel id="currentHumidity" typeId="atmospheric-humidity-channel"/>
|
||||
<channel id="currentSetPoint" typeId="currentSetPoint-channel"/>
|
||||
<channel id="currentBatteryVoltage" typeId="batteryVoltage-channel"/>
|
||||
<channel id="currentBatteryLevel" typeId="system.battery-level"/>
|
||||
<channel id="currentWiserBatteryLevel" typeId="wiserBatteryLevel-channel"/>
|
||||
<channel id="currentSignalRSSI" typeId="signalRSSI-channel"/>
|
||||
<channel id="currentSignalLQI" typeId="signalLQI-channel"/>
|
||||
<channel id="currentSignalStrength" typeId="system.signal-strength"/>
|
||||
<channel id="currentWiserSignalStrength" typeId="wiserSignalStrength-channel"/>
|
||||
<channel id="zigbeeConnected" typeId="zigbeeConnected-channel"/>
|
||||
<channel id="deviceLocked" typeId="deviceLocked-channel"/>
|
||||
</channels>
|
||||
|
||||
<representation-property>serialNumber</representation-property>
|
||||
|
||||
<config-description>
|
||||
<parameter name="serialNumber" type="text" required="true">
|
||||
<label>Serial Number</label>
|
||||
<description>Device Serial Number</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<!-- TRV Thing Type -->
|
||||
<thing-type id="itrv">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="heathub"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>iTRV</label>
|
||||
<description>Thermostatic Radiator Valve</description>
|
||||
|
||||
<channels>
|
||||
<channel id="currentTemperature" typeId="currentTemperature-channel"/>
|
||||
<channel id="currentSetPoint" typeId="currentSetPoint-channel"/>
|
||||
<channel id="currentDemand" typeId="demandPercent-channel"/>
|
||||
<channel id="currentBatteryVoltage" typeId="batteryVoltage-channel"/>
|
||||
<channel id="currentBatteryLevel" typeId="system.battery-level"/>
|
||||
<channel id="currentWiserBatteryLevel" typeId="wiserBatteryLevel-channel"/>
|
||||
<channel id="currentSignalRSSI" typeId="signalRSSI-channel"/>
|
||||
<channel id="currentSignalLQI" typeId="signalLQI-channel"/>
|
||||
<channel id="currentSignalStrength" typeId="system.signal-strength"/>
|
||||
<channel id="currentWiserSignalStrength" typeId="wiserSignalStrength-channel"/>
|
||||
<channel id="zigbeeConnected" typeId="zigbeeConnected-channel"/>
|
||||
<channel id="deviceLocked" typeId="deviceLocked-channel"/>
|
||||
</channels>
|
||||
|
||||
<representation-property>serialNumber</representation-property>
|
||||
|
||||
<config-description>
|
||||
<parameter name="serialNumber" type="text" required="true">
|
||||
<label>Serial Number</label>
|
||||
<description>Device Serial Number</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<!-- Smart Plug Thing Type -->
|
||||
<thing-type id="smart-plug">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="heathub"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Smart Plug</label>
|
||||
<description>Remote controlled Plug Socket</description>
|
||||
|
||||
<channels>
|
||||
<channel id="plugOutputState" typeId="plugOutputState-channel"/>
|
||||
<channel id="plugAwayAction" typeId="plugAwayAction-channel"/>
|
||||
<channel id="currentSignalRSSI" typeId="signalRSSI-channel"/>
|
||||
<channel id="currentSignalLQI" typeId="signalLQI-channel"/>
|
||||
<channel id="zigbeeConnected" typeId="zigbeeConnected-channel"/>
|
||||
<channel id="deviceLocked" typeId="deviceLocked-channel"/>
|
||||
<channel id="manualModeState" typeId="manualModeState-channel"/>
|
||||
</channels>
|
||||
|
||||
<representation-property>serialNumber</representation-property>
|
||||
|
||||
<config-description>
|
||||
<parameter name="serialNumber" type="text" required="true">
|
||||
<label>Serial Number</label>
|
||||
<description>Device Serial Number</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<!-- Channel Types -->
|
||||
<channel-type id="currentTemperature-channel">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Temperature</label>
|
||||
<description>Current temperature</description>
|
||||
<category>Temperature</category>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="atmospheric-humidity-channel">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Humidity</label>
|
||||
<description>Current relative humidity</description>
|
||||
<category>Humidity</category>
|
||||
<state readOnly="true" pattern="%.0f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="currentSetPoint-channel">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Set Point</label>
|
||||
<description>Current set point</description>
|
||||
<category>Temperature</category>
|
||||
<state readOnly="false" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="batteryVoltage-channel" advanced="true">
|
||||
<item-type>Number:ElectricPotential</item-type>
|
||||
<label>Battery Voltage</label>
|
||||
<description>Current Battery Voltage for the device</description>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="demandPercent-channel">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Current Heat Demand</label>
|
||||
<description>Current heat demand in %</description>
|
||||
<state readOnly="true" pattern="%d %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="heatRequest-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Currently Requesting Heat</label>
|
||||
<description>Is this room requesting heat</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="heatingOverride-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Heating Override</label>
|
||||
<description>The heating override button has been pressed</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="hotWaterOverride-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Hot Water Override</label>
|
||||
<description>The hot water override button has been pressed</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="signalRSSI-channel" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Signal RSSI</label>
|
||||
<description>The reported network signal RSSI</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="signalLQI-channel" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Signal LQI</label>
|
||||
<description>The reported network signal LQI</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="wiserSignalStrength-channel" advanced="true">
|
||||
<item-type>String</item-type>
|
||||
<label>Signal Strength (Wiser)</label>
|
||||
<description>The reported network signal strength</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="wiserBatteryLevel-channel" advanced="true">
|
||||
<item-type>String</item-type>
|
||||
<label>Battery Level (Wiser)</label>
|
||||
<description>Current Battery Level for the device</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="heatChannelDemand-channel">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Heat Demand</label>
|
||||
<description>Current heat demand in %</description>
|
||||
<state readOnly="true" pattern="%d %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="demandState-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Requesting Heat</label>
|
||||
<description>Current channel is requesting heat</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="awayModeState-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Away Mode Active</label>
|
||||
<description>Away mode has been activated</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="awayModeSetPoint-channel" advanced="true">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Away Mode Set Point</label>
|
||||
<description>Away Mode Set Point</description>
|
||||
<category>Temperature</category>
|
||||
<state readOnly="false" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="ecoModeState-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Eco Mode Enabled</label>
|
||||
<description>Eco Mode activation state (EcoIQ)</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="manualModeState-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Manual Mode Enabled</label>
|
||||
<description>Manual Mode activation state</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="zigbeeConnected-channel" advanced="true">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Device Connected</label>
|
||||
<description>Is the device still connected to the ZigBee network</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="hotWaterSetPoint-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Set Point</label>
|
||||
<description>Hot water heating set point switch</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="boostDuration-channel">
|
||||
<item-type>Number</item-type>
|
||||
<label>Boost Duration</label>
|
||||
<description>Duration in hours to boost hot water for</description>
|
||||
<state pattern="%.1f h" min="0" max="3" step="0.5"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="boosted-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Is Boosted</label>
|
||||
<description>Is the hot water currently being boosted</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="boostRemaining-channel">
|
||||
<item-type>Number:Time</item-type>
|
||||
<label>Boost Remaining</label>
|
||||
<description>How long until the boost deactivates</description>
|
||||
<state readOnly="true" pattern="%.0f min"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="windowStateDetection-channel" advanced="true">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Open Window Detection</label>
|
||||
<description>Is window detection turned on</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="windowState-channel">
|
||||
<item-type>Contact</item-type>
|
||||
<label>Window State</label>
|
||||
<description>Is the window open or closed</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="deviceLocked-channel" advanced="true">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Device Locked</label>
|
||||
<description>Has the device been locked to prevent local changes</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="plugOutputState-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Plug State</label>
|
||||
<description>Is the smart plug switched on or off</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="plugAwayAction-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Plug Off in Away Mode</label>
|
||||
<description>Should the smart plug switch off when in away mode</description>
|
||||
</channel-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
Reference in New Issue
Block a user