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>
|
||||
@@ -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.discovery;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.MockitoAnnotations.initMocks;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.HttpContentResponse;
|
||||
import org.eclipse.jetty.client.HttpResponse;
|
||||
import org.eclipse.jetty.client.api.Request;
|
||||
import org.eclipse.jetty.server.Response;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
import org.mockito.Mock;
|
||||
import org.openhab.binding.draytonwiser.internal.DraytonWiserBindingConstants;
|
||||
import org.openhab.binding.draytonwiser.internal.api.DraytonWiserApi;
|
||||
import org.openhab.binding.draytonwiser.internal.api.DraytonWiserApiException;
|
||||
import org.openhab.binding.draytonwiser.internal.handler.HeatHubConfiguration;
|
||||
import org.openhab.binding.draytonwiser.internal.handler.HeatHubHandler;
|
||||
import org.openhab.binding.draytonwiser.internal.model.DomainDTO;
|
||||
import org.openhab.binding.draytonwiser.internal.model.DraytonWiserDTO;
|
||||
import org.openhab.core.config.discovery.DiscoveryResult;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
|
||||
/**
|
||||
* Test class for {@link DraytonWiserDiscoveryService}.
|
||||
*
|
||||
* @author Hilbrand Bouwkamp - Initial contribution
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class DraytonWiserDiscoveryServiceTest {
|
||||
|
||||
@Mock
|
||||
private HeatHubHandler bridgeHandler;
|
||||
@Mock
|
||||
private Bridge bridge;
|
||||
@Mock
|
||||
private HttpClient httpClient;
|
||||
@Mock
|
||||
private Request request;
|
||||
|
||||
private DraytonWiserApi api;
|
||||
private final String jsonFile;
|
||||
private final int expectedResults;
|
||||
|
||||
public DraytonWiserDiscoveryServiceTest(final String jsonFile, final int expectedResults) {
|
||||
this.jsonFile = jsonFile;
|
||||
this.expectedResults = expectedResults;
|
||||
}
|
||||
|
||||
@Parameters(name = "{0}")
|
||||
public static List<Object[]> data() {
|
||||
return Arrays.asList(new Object[] { "../test1.json", 11 }, new Object[] { "../test2.json", 22 });
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
initMocks(this);
|
||||
api = new DraytonWiserApi(httpClient);
|
||||
api.setConfiguration(new HeatHubConfiguration());
|
||||
|
||||
doReturn(request).when(httpClient).newRequest((String) any());
|
||||
doReturn(request).when(request).method((String) any());
|
||||
doReturn(request).when(request).header((String) any(), any());
|
||||
doReturn(request).when(request).content(any());
|
||||
doReturn(request).when(request).timeout(anyLong(), any());
|
||||
doReturn(bridge).when(bridgeHandler).getThing();
|
||||
doReturn(new ThingUID(DraytonWiserBindingConstants.THING_TYPE_BRIDGE, "1")).when(bridge).getUID();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiscovery() throws IOException, URISyntaxException, InterruptedException, TimeoutException,
|
||||
ExecutionException, DraytonWiserApiException {
|
||||
final byte[] content = Files.readAllBytes(Paths.get(getClass().getResource(jsonFile).toURI()));
|
||||
final HttpResponse response = new HttpResponse(null, null);
|
||||
response.status(Response.SC_OK);
|
||||
doReturn(new HttpContentResponse(response, content, null, null)).when(request).send();
|
||||
final List<DiscoveryResult> discoveryResults = new ArrayList<>();
|
||||
final DraytonWiserDiscoveryService service = new DraytonWiserDiscoveryService() {
|
||||
@Override
|
||||
protected void thingDiscovered(final DiscoveryResult discoveryResult) {
|
||||
discoveryResults.add(discoveryResult);
|
||||
}
|
||||
};
|
||||
service.setThingHandler(bridgeHandler);
|
||||
final DomainDTO domain = api.getDomain();
|
||||
|
||||
if (domain == null) {
|
||||
fail("DomainDTO object is null");
|
||||
} else {
|
||||
service.onRefresh(new DraytonWiserDTO(domain));
|
||||
assertThat(discoveryResults.size(), is(expectedResults));
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,847 @@
|
||||
{
|
||||
"System": {
|
||||
"PairingStatus": "Paired",
|
||||
"TimeZoneOffset": 0,
|
||||
"AutomaticDaylightSaving": true,
|
||||
"SystemMode": "Heat",
|
||||
"Version": 6,
|
||||
"FotaEnabled": true,
|
||||
"ValveProtectionEnabled": false,
|
||||
"EcoModeEnabled": true,
|
||||
"AwayModeAffectsHotWater": true,
|
||||
"AwayModeSetPointLimit": 100,
|
||||
"BoilerSettings": {
|
||||
"ControlType": "HeatSourceType_OpenTherm",
|
||||
"FuelType": "Gas",
|
||||
"CycleRate": "CPH_6",
|
||||
"OnOffHysteresis": 5
|
||||
},
|
||||
"CoolingModeDefaultSetpoint": 210,
|
||||
"CoolingAwayModeSetpointLimit": 240,
|
||||
"ComfortModeEnabled": true,
|
||||
"PreheatTimeLimit": 10800,
|
||||
"DegradedModeSetpointThreshold": 180,
|
||||
"UnixTime": 1592420000,
|
||||
"ActiveSystemVersion": "2.52.0-fcdebef127",
|
||||
"BrandName": "WiserHeat",
|
||||
"CloudConnectionStatus": "Connected",
|
||||
"LocalDateAndTime": {
|
||||
"Year": 2020,
|
||||
"Month": "June",
|
||||
"Date": 17,
|
||||
"Day": "Wednesday",
|
||||
"Time": 1234
|
||||
},
|
||||
"HeatingButtonOverrideState": "Off",
|
||||
"UserOverridesActive": true,
|
||||
"HotWaterButtonOverrideState": "Off",
|
||||
"OpenThermConnectionStatus": "Connected"
|
||||
},
|
||||
"Cloud": {
|
||||
"Environment": "Prod",
|
||||
"DetailedPublishing": true,
|
||||
"EnableDiagnosticTelemetry": false,
|
||||
"WiserApiHost": "api-nl.wiserair.com",
|
||||
"BootStrapApiHost": "bootstrap.gl.struxurewarecloud.com"
|
||||
},
|
||||
"HeatingChannel": [
|
||||
{
|
||||
"id": 1,
|
||||
"Name": "Channel-1",
|
||||
"RoomIds": [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6
|
||||
],
|
||||
"PercentageDemand": 0,
|
||||
"DemandOnOffOutput": "Off",
|
||||
"HeatingRelayState": "Off",
|
||||
"IsSmartValvePreventingDemand": true
|
||||
}
|
||||
],
|
||||
"Room": [
|
||||
{
|
||||
"id": 1,
|
||||
"ManualSetPoint": 200,
|
||||
"OverrideType": "Manual",
|
||||
"OverrideSetpoint": 200,
|
||||
"ScheduleId": 1,
|
||||
"ComfortModeScore": 1905,
|
||||
"HeatingRate": 2719,
|
||||
"RoomStatId": 10,
|
||||
"SmartValveIds": [
|
||||
21
|
||||
],
|
||||
"UfhRelayIds": [],
|
||||
"Name": "Master Bedroom",
|
||||
"Mode": "Auto",
|
||||
"DemandType": "Modulating",
|
||||
"WindowDetectionActive": true,
|
||||
"ControlSequenceOfOperation": "HeatingOnly",
|
||||
"HeatingType": "HydronicRadiator",
|
||||
"CalculatedTemperature": 242,
|
||||
"CurrentSetPoint": 200,
|
||||
"PercentageDemand": 0,
|
||||
"ControlOutputState": "Off",
|
||||
"WindowState": "Closed",
|
||||
"SetpointOrigin": "FromManualOverride",
|
||||
"DisplayedSetPoint": 200,
|
||||
"ScheduledSetPoint": 200,
|
||||
"RoundedAlexaTemperature": 240,
|
||||
"EffectiveMode": "Auto",
|
||||
"PercentageDemandForItrv": 0
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"ManualSetPoint": 210,
|
||||
"OverrideType": "EcoIQ",
|
||||
"OverrideSetpoint": 180,
|
||||
"ScheduleId": 2,
|
||||
"ComfortModeScore": 1049,
|
||||
"HeatingRate": 3228,
|
||||
"RoomStatId": 11,
|
||||
"SmartValveIds": [
|
||||
23,
|
||||
22,
|
||||
24,
|
||||
25
|
||||
],
|
||||
"UfhRelayIds": [],
|
||||
"Name": "Downstairs",
|
||||
"Mode": "Auto",
|
||||
"DemandType": "Modulating",
|
||||
"WindowDetectionActive": true,
|
||||
"ControlSequenceOfOperation": "HeatingOnly",
|
||||
"HeatingType": "HydronicRadiator",
|
||||
"CalculatedTemperature": 229,
|
||||
"CurrentSetPoint": 180,
|
||||
"PercentageDemand": 0,
|
||||
"ControlOutputState": "Off",
|
||||
"WindowState": "Closed",
|
||||
"SetpointOrigin": "FromEcoIQ",
|
||||
"DisplayedSetPoint": 210,
|
||||
"ScheduledSetPoint": 210,
|
||||
"AwayModeSuppressed": false,
|
||||
"RoundedAlexaTemperature": 230,
|
||||
"EffectiveMode": "Auto",
|
||||
"PercentageDemandForItrv": 0
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"ManualSetPoint": 180,
|
||||
"OverrideType": "EcoIQ",
|
||||
"OverrideSetpoint": 180,
|
||||
"ScheduleId": 3,
|
||||
"ComfortModeScore": 580,
|
||||
"HeatingRate": 882,
|
||||
"SmartValveIds": [
|
||||
26
|
||||
],
|
||||
"UfhRelayIds": [],
|
||||
"Name": "Hallway",
|
||||
"Mode": "Auto",
|
||||
"DemandType": "Modulating",
|
||||
"WindowDetectionActive": true,
|
||||
"ControlSequenceOfOperation": "HeatingOnly",
|
||||
"HeatingType": "HydronicRadiator",
|
||||
"CalculatedTemperature": 224,
|
||||
"CurrentSetPoint": 180,
|
||||
"PercentageDemand": 0,
|
||||
"ControlOutputState": "Off",
|
||||
"WindowState": "Closed",
|
||||
"SetpointOrigin": "FromEcoIQ",
|
||||
"DisplayedSetPoint": 200,
|
||||
"ScheduledSetPoint": 200,
|
||||
"AwayModeSuppressed": false,
|
||||
"RoundedAlexaTemperature": 225,
|
||||
"EffectiveMode": "Auto",
|
||||
"PercentageDemandForItrv": 0
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"ManualSetPoint": 180,
|
||||
"ScheduleId": 4,
|
||||
"ComfortModeScore": 6128,
|
||||
"HeatingRate": 3292,
|
||||
"RoomStatId": 13,
|
||||
"SmartValveIds": [
|
||||
27
|
||||
],
|
||||
"UfhRelayIds": [],
|
||||
"Name": "Front Bedroom",
|
||||
"Mode": "Auto",
|
||||
"DemandType": "Modulating",
|
||||
"WindowDetectionActive": true,
|
||||
"ControlSequenceOfOperation": "HeatingOnly",
|
||||
"HeatingType": "HydronicRadiator",
|
||||
"CalculatedTemperature": 241,
|
||||
"CurrentSetPoint": 180,
|
||||
"PercentageDemand": 0,
|
||||
"ControlOutputState": "Off",
|
||||
"WindowState": "Closed",
|
||||
"SetpointOrigin": "FromSchedule",
|
||||
"DisplayedSetPoint": 180,
|
||||
"ScheduledSetPoint": 180,
|
||||
"AwayModeSuppressed": false,
|
||||
"RoundedAlexaTemperature": 240,
|
||||
"EffectiveMode": "Auto",
|
||||
"PercentageDemandForItrv": 0
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"ManualSetPoint": 200,
|
||||
"OverrideType": "None",
|
||||
"ScheduleId": 5,
|
||||
"ComfortModeScore": 30510,
|
||||
"HeatingRate": 1680,
|
||||
"RoomStatId": 12,
|
||||
"SmartValveIds": [
|
||||
29
|
||||
],
|
||||
"UfhRelayIds": [],
|
||||
"Name": "Nursery",
|
||||
"Mode": "Auto",
|
||||
"DemandType": "Modulating",
|
||||
"WindowDetectionActive": true,
|
||||
"ControlSequenceOfOperation": "HeatingOnly",
|
||||
"HeatingType": "HydronicRadiator",
|
||||
"CalculatedTemperature": 237,
|
||||
"CurrentSetPoint": 200,
|
||||
"PercentageDemand": 0,
|
||||
"ControlOutputState": "Off",
|
||||
"WindowState": "Closed",
|
||||
"SetpointOrigin": "FromSchedule",
|
||||
"DisplayedSetPoint": 200,
|
||||
"ScheduledSetPoint": 200,
|
||||
"RoundedAlexaTemperature": 235,
|
||||
"EffectiveMode": "Auto",
|
||||
"PercentageDemandForItrv": 0
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"ManualSetPoint": 180,
|
||||
"ScheduleId": 6,
|
||||
"ComfortModeScore": 3155,
|
||||
"HeatingRate": 1817,
|
||||
"RoomStatId": 14,
|
||||
"SmartValveIds": [
|
||||
30
|
||||
],
|
||||
"UfhRelayIds": [],
|
||||
"Name": "Study",
|
||||
"Mode": "Auto",
|
||||
"DemandType": "Modulating",
|
||||
"WindowDetectionActive": true,
|
||||
"ControlSequenceOfOperation": "HeatingOnly",
|
||||
"HeatingType": "HydronicRadiator",
|
||||
"CalculatedTemperature": 247,
|
||||
"CurrentSetPoint": 180,
|
||||
"PercentageDemand": 0,
|
||||
"ControlOutputState": "Off",
|
||||
"WindowState": "Closed",
|
||||
"SetpointOrigin": "FromSchedule",
|
||||
"DisplayedSetPoint": 180,
|
||||
"ScheduledSetPoint": 180,
|
||||
"AwayModeSuppressed": false,
|
||||
"RoundedAlexaTemperature": 245,
|
||||
"EffectiveMode": "Auto",
|
||||
"PercentageDemandForItrv": 0
|
||||
}
|
||||
],
|
||||
"Device": [
|
||||
{
|
||||
"id": 0,
|
||||
"NodeId": 0,
|
||||
"ProductType": "Controller",
|
||||
"ProductIdentifier": "Controller",
|
||||
"ActiveFirmwareVersion": "2.52.0",
|
||||
"ModelIdentifier": "WT714R1S0902",
|
||||
"DeviceLockEnabled": false,
|
||||
"DisplayedSignalStrength": "VeryGood",
|
||||
"ReceptionOfController": {
|
||||
"Rssi": -33
|
||||
},
|
||||
"ReceptionOfDevice": {
|
||||
"Rssi": 0,
|
||||
"Lqi": 255
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"NodeId": 10,
|
||||
"ProductType": "RoomStat",
|
||||
"ProductIdentifier": "RoomStat",
|
||||
"ActiveFirmwareVersion": "04E1000900042002",
|
||||
"ModelIdentifier": "Thermostat",
|
||||
"HardwareVersion": "0",
|
||||
"SerialNumber": "0000000000000000",
|
||||
"ProductModel": "Thermostat",
|
||||
"OtaImageQueryCount": 0,
|
||||
"LastOtaImageQueryCount": 2,
|
||||
"ParentNodeId": 63230,
|
||||
"DeviceLockEnabled": false,
|
||||
"DisplayedSignalStrength": "VeryGood",
|
||||
"BatteryVoltage": 28,
|
||||
"BatteryLevel": "Normal",
|
||||
"ReceptionOfController": {
|
||||
"Rssi": -60,
|
||||
"Lqi": 160
|
||||
},
|
||||
"ReceptionOfDevice": {
|
||||
"Rssi": -80,
|
||||
"Lqi": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 21,
|
||||
"NodeId": 45065,
|
||||
"ProductType": "iTRV",
|
||||
"ProductIdentifier": "iTRV",
|
||||
"ActiveFirmwareVersion": "0201000000042002",
|
||||
"ModelIdentifier": "iTRV",
|
||||
"HardwareVersion": "0",
|
||||
"SerialNumber": "1111111111111111",
|
||||
"ProductModel": "",
|
||||
"OtaImageQueryCount": 0,
|
||||
"LastOtaImageQueryCount": 0,
|
||||
"ParentNodeId": 0,
|
||||
"DeviceLockEnabled": true,
|
||||
"DisplayedSignalStrength": "Poor",
|
||||
"BatteryVoltage": 26,
|
||||
"BatteryLevel": "Low",
|
||||
"ReceptionOfController": {
|
||||
"Rssi": -82,
|
||||
"Lqi": 72
|
||||
},
|
||||
"ReceptionOfDevice": {
|
||||
"Rssi": -73,
|
||||
"Lqi": 108
|
||||
},
|
||||
"PendingZigbeeMessageMask": 0
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"NodeId": 11,
|
||||
"ProductType": "RoomStat",
|
||||
"ProductIdentifier": "RoomStat",
|
||||
"ActiveFirmwareVersion": "04E1000900042002",
|
||||
"ModelIdentifier": "Thermostat",
|
||||
"HardwareVersion": "1",
|
||||
"SerialNumber": "2222222222222222",
|
||||
"ProductModel": "Thermostat",
|
||||
"OtaImageQueryCount": 0,
|
||||
"LastOtaImageQueryCount": 2,
|
||||
"ParentNodeId": 0,
|
||||
"DeviceLockEnabled": false,
|
||||
"DisplayedSignalStrength": "VeryGood",
|
||||
"BatteryVoltage": 29,
|
||||
"BatteryLevel": "Normal",
|
||||
"ReceptionOfController": {
|
||||
"Rssi": -60,
|
||||
"Lqi": 160
|
||||
},
|
||||
"ReceptionOfDevice": {
|
||||
"Rssi": -56,
|
||||
"Lqi": 176
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 41,
|
||||
"NodeId": 63230,
|
||||
"ProductType": "SmartPlug",
|
||||
"ProductIdentifier": "OwonSmartplug",
|
||||
"ActiveFirmwareVersion": "",
|
||||
"ModelIdentifier": "WSP402",
|
||||
"HardwareVersion": "",
|
||||
"SerialNumber": "3333333333333333",
|
||||
"ProductModel": "",
|
||||
"OtaImageQueryCount": 0,
|
||||
"LastOtaImageQueryCount": 0,
|
||||
"DeviceLockEnabled": false,
|
||||
"DisplayedSignalStrength": "Good",
|
||||
"ReceptionOfDevice": {
|
||||
"Rssi": -81,
|
||||
"Lqi": 76
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 22,
|
||||
"NodeId": 22,
|
||||
"ProductType": "iTRV",
|
||||
"ProductIdentifier": "iTRV",
|
||||
"ActiveFirmwareVersion": "0201000000042002",
|
||||
"ModelIdentifier": "iTRV",
|
||||
"HardwareVersion": "0",
|
||||
"SerialNumber": "4444444444444444",
|
||||
"ProductModel": "iTRV",
|
||||
"OtaImageQueryCount": 0,
|
||||
"LastOtaImageQueryCount": 1,
|
||||
"ParentNodeId": 0,
|
||||
"DeviceLockEnabled": true,
|
||||
"DisplayedSignalStrength": "VeryGood",
|
||||
"BatteryVoltage": 29,
|
||||
"BatteryLevel": "Normal",
|
||||
"ReceptionOfController": {
|
||||
"Rssi": -48,
|
||||
"Lqi": 212
|
||||
},
|
||||
"ReceptionOfDevice": {
|
||||
"Rssi": -42,
|
||||
"Lqi": 232
|
||||
},
|
||||
"PendingZigbeeMessageMask": 0
|
||||
},
|
||||
{
|
||||
"id": 23,
|
||||
"NodeId": 54921,
|
||||
"ProductType": "iTRV",
|
||||
"ProductIdentifier": "iTRV",
|
||||
"ActiveFirmwareVersion": "0201000000042002",
|
||||
"ModelIdentifier": "iTRV",
|
||||
"HardwareVersion": "0",
|
||||
"SerialNumber": "5555555555555555",
|
||||
"ProductModel": "iTRV",
|
||||
"OtaImageQueryCount": 0,
|
||||
"LastOtaImageQueryCount": 0,
|
||||
"ParentNodeId": 0,
|
||||
"DeviceLockEnabled": false,
|
||||
"DisplayedSignalStrength": "Medium",
|
||||
"BatteryVoltage": 30,
|
||||
"BatteryLevel": "Normal",
|
||||
"ReceptionOfController": {
|
||||
"Rssi": -77,
|
||||
"Lqi": 92
|
||||
},
|
||||
"ReceptionOfDevice": {
|
||||
"Rssi": -67,
|
||||
"Lqi": 132
|
||||
},
|
||||
"PendingZigbeeMessageMask": 0
|
||||
},
|
||||
{
|
||||
"id": 24,
|
||||
"NodeId": 27963,
|
||||
"ProductType": "iTRV",
|
||||
"ProductIdentifier": "iTRV",
|
||||
"ActiveFirmwareVersion": "0201000000042002",
|
||||
"ModelIdentifier": "iTRV",
|
||||
"HardwareVersion": "0",
|
||||
"SerialNumber": "6666666666666666",
|
||||
"ProductModel": "iTRV",
|
||||
"OtaImageQueryCount": 0,
|
||||
"LastOtaImageQueryCount": 1,
|
||||
"ParentNodeId": 0,
|
||||
"DeviceLockEnabled": true,
|
||||
"DisplayedSignalStrength": "Good",
|
||||
"BatteryVoltage": 26,
|
||||
"BatteryLevel": "Low",
|
||||
"ReceptionOfController": {
|
||||
"Rssi": -68,
|
||||
"Lqi": 128
|
||||
},
|
||||
"ReceptionOfDevice": {
|
||||
"Rssi": -62,
|
||||
"Lqi": 152
|
||||
},
|
||||
"PendingZigbeeMessageMask": 0
|
||||
},
|
||||
{
|
||||
"id": 25,
|
||||
"NodeId": 25,
|
||||
"ProductType": "iTRV",
|
||||
"ProductIdentifier": "iTRV",
|
||||
"ActiveFirmwareVersion": "0201000000042002",
|
||||
"ModelIdentifier": "iTRV",
|
||||
"HardwareVersion": "0",
|
||||
"SerialNumber": "7777777777777777",
|
||||
"ProductModel": "iTRV",
|
||||
"OtaImageQueryCount": 0,
|
||||
"LastOtaImageQueryCount": 1,
|
||||
"ParentNodeId": 0,
|
||||
"DeviceLockEnabled": true,
|
||||
"DisplayedSignalStrength": "VeryGood",
|
||||
"BatteryVoltage": 26,
|
||||
"BatteryLevel": "Low",
|
||||
"ReceptionOfController": {
|
||||
"Rssi": -60,
|
||||
"Lqi": 160
|
||||
},
|
||||
"ReceptionOfDevice": {
|
||||
"Rssi": -53,
|
||||
"Lqi": 188
|
||||
},
|
||||
"PendingZigbeeMessageMask": 0
|
||||
},
|
||||
{
|
||||
"id": 26,
|
||||
"NodeId": 26,
|
||||
"ProductType": "iTRV",
|
||||
"ProductIdentifier": "iTRV",
|
||||
"ActiveFirmwareVersion": "0201000000042002",
|
||||
"ModelIdentifier": "iTRV",
|
||||
"HardwareVersion": "0",
|
||||
"SerialNumber": "8888888888888888",
|
||||
"ProductModel": "iTRV",
|
||||
"OtaImageQueryCount": 0,
|
||||
"LastOtaImageQueryCount": 1,
|
||||
"ParentNodeId": 0,
|
||||
"DeviceLockEnabled": false,
|
||||
"DisplayedSignalStrength": "Medium",
|
||||
"BatteryVoltage": 26,
|
||||
"BatteryLevel": "Low",
|
||||
"ReceptionOfController": {
|
||||
"Rssi": -79,
|
||||
"Lqi": 84
|
||||
},
|
||||
"ReceptionOfDevice": {
|
||||
"Rssi": -70,
|
||||
"Lqi": 120
|
||||
},
|
||||
"PendingZigbeeMessageMask": 0
|
||||
},
|
||||
{
|
||||
"id": 27,
|
||||
"NodeId": 27,
|
||||
"ProductType": "iTRV",
|
||||
"ProductIdentifier": "iTRV",
|
||||
"ActiveFirmwareVersion": "0201000000042002",
|
||||
"ModelIdentifier": "iTRV",
|
||||
"HardwareVersion": "0",
|
||||
"SerialNumber": "9999999999999999",
|
||||
"ProductModel": "iTRV",
|
||||
"OtaImageQueryCount": 0,
|
||||
"LastOtaImageQueryCount": 1,
|
||||
"ParentNodeId": 63230,
|
||||
"DeviceLockEnabled": true,
|
||||
"DisplayedSignalStrength": "Good",
|
||||
"BatteryVoltage": 31,
|
||||
"BatteryLevel": "Normal",
|
||||
"ReceptionOfController": {
|
||||
"Rssi": -65,
|
||||
"Lqi": 140
|
||||
},
|
||||
"ReceptionOfDevice": {
|
||||
"Rssi": -80,
|
||||
"Lqi": 80
|
||||
},
|
||||
"PendingZigbeeMessageMask": 0
|
||||
},
|
||||
{
|
||||
"id": 29,
|
||||
"NodeId": 29,
|
||||
"ProductType": "iTRV",
|
||||
"ProductIdentifier": "iTRV",
|
||||
"ActiveFirmwareVersion": "0201000000042002",
|
||||
"ModelIdentifier": "iTRV",
|
||||
"HardwareVersion": "0",
|
||||
"SerialNumber": "AAAAAAAAAAAAAAAA",
|
||||
"ProductModel": "iTRV",
|
||||
"OtaImageQueryCount": 0,
|
||||
"LastOtaImageQueryCount": 1,
|
||||
"ParentNodeId": 0,
|
||||
"DeviceLockEnabled": true,
|
||||
"DisplayedSignalStrength": "Good",
|
||||
"BatteryVoltage": 27,
|
||||
"BatteryLevel": "OneThird",
|
||||
"ReceptionOfController": {
|
||||
"Rssi": -63,
|
||||
"Lqi": 148
|
||||
},
|
||||
"ReceptionOfDevice": {
|
||||
"Rssi": -58,
|
||||
"Lqi": 168
|
||||
},
|
||||
"PendingZigbeeMessageMask": 0
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"NodeId": 12,
|
||||
"ProductType": "RoomStat",
|
||||
"ProductIdentifier": "RoomStat",
|
||||
"ActiveFirmwareVersion": "04E1000900042002",
|
||||
"ModelIdentifier": "Thermostat",
|
||||
"HardwareVersion": "1",
|
||||
"SerialNumber": "BBBBBBBBBBBBBBBB",
|
||||
"ProductModel": "Thermostat",
|
||||
"OtaImageQueryCount": 0,
|
||||
"LastOtaImageQueryCount": 2,
|
||||
"ParentNodeId": 0,
|
||||
"DeviceLockEnabled": false,
|
||||
"DisplayedSignalStrength": "Medium",
|
||||
"BatteryVoltage": 29,
|
||||
"BatteryLevel": "Normal",
|
||||
"ReceptionOfController": {
|
||||
"Rssi": -76,
|
||||
"Lqi": 96
|
||||
},
|
||||
"ReceptionOfDevice": {
|
||||
"Rssi": -66,
|
||||
"Lqi": 136
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 30,
|
||||
"NodeId": 30,
|
||||
"ProductType": "iTRV",
|
||||
"ProductIdentifier": "iTRV",
|
||||
"ActiveFirmwareVersion": "0201000000042002",
|
||||
"ModelIdentifier": "iTRV",
|
||||
"HardwareVersion": "0",
|
||||
"SerialNumber": "CCCCCCCCCCCCCCCC",
|
||||
"ProductModel": "iTRV",
|
||||
"OtaImageQueryCount": 0,
|
||||
"LastOtaImageQueryCount": 1,
|
||||
"ParentNodeId": 0,
|
||||
"DeviceLockEnabled": false,
|
||||
"DisplayedSignalStrength": "Medium",
|
||||
"BatteryVoltage": 26,
|
||||
"BatteryLevel": "Low",
|
||||
"ReceptionOfController": {
|
||||
"Rssi": -74,
|
||||
"Lqi": 104
|
||||
},
|
||||
"ReceptionOfDevice": {
|
||||
"Rssi": -68,
|
||||
"Lqi": 128
|
||||
},
|
||||
"PendingZigbeeMessageMask": 0
|
||||
},
|
||||
{
|
||||
"id": 13,
|
||||
"NodeId": 13,
|
||||
"ProductType": "RoomStat",
|
||||
"ProductIdentifier": "RoomStat",
|
||||
"ActiveFirmwareVersion": "04E1000900042002",
|
||||
"ModelIdentifier": "Thermostat",
|
||||
"HardwareVersion": "1",
|
||||
"SerialNumber": "DDDDDDDDDDDDDDDD",
|
||||
"ProductModel": "Thermostat",
|
||||
"OtaImageQueryCount": 0,
|
||||
"LastOtaImageQueryCount": 0,
|
||||
"ParentNodeId": 0,
|
||||
"DeviceLockEnabled": false,
|
||||
"DisplayedSignalStrength": "Medium",
|
||||
"BatteryVoltage": 26,
|
||||
"BatteryLevel": "Normal",
|
||||
"ReceptionOfController": {
|
||||
"Rssi": -77,
|
||||
"Lqi": 92
|
||||
},
|
||||
"ReceptionOfDevice": {
|
||||
"Rssi": -69,
|
||||
"Lqi": 124
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 14,
|
||||
"NodeId": 14,
|
||||
"ProductType": "RoomStat",
|
||||
"ProductIdentifier": "RoomStat",
|
||||
"ActiveFirmwareVersion": "04E1000900042002",
|
||||
"ModelIdentifier": "Thermostat",
|
||||
"HardwareVersion": "1",
|
||||
"SerialNumber": "EEEEEEEEEEEEEEEE",
|
||||
"ProductModel": "Thermostat",
|
||||
"OtaImageQueryCount": 1,
|
||||
"LastOtaImageQueryCount": 1,
|
||||
"ParentNodeId": 0,
|
||||
"DeviceLockEnabled": false,
|
||||
"DisplayedSignalStrength": "Medium",
|
||||
"BatteryVoltage": 29,
|
||||
"BatteryLevel": "Normal",
|
||||
"ReceptionOfController": {
|
||||
"Rssi": -77,
|
||||
"Lqi": 92
|
||||
},
|
||||
"ReceptionOfDevice": {
|
||||
"Rssi": -69,
|
||||
"Lqi": 124
|
||||
}
|
||||
}
|
||||
],
|
||||
"Zigbee": {
|
||||
"Error72Reset": 32,
|
||||
"JPANCount": 27,
|
||||
"NetworkChannel": 25,
|
||||
"UpdateEBLState": "Successful",
|
||||
"CurrentEBLFile": "CICIE-1.0.1-c8271d47.ebl",
|
||||
"TargetEBLFile": "CICIE-1.0.1-c8271d47.ebl",
|
||||
"UpdateAttempts": 1,
|
||||
"ZigbeeModuleVersion": "1.0.1-c8271d47",
|
||||
"ZigbeeEUI": "FFFFFFFFFFFFFFFF"
|
||||
},
|
||||
"UpgradeInfo": [
|
||||
{
|
||||
"id": 1,
|
||||
"FirmwareFilename": "0201000000042002FOTA.BIN"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"FirmwareFilename": "0401000000010005FOTA.BIN"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"FirmwareFilename": "0401010100010005FOTA.BIN"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"FirmwareFilename": "0441000000010005FOTA.BIN"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"FirmwareFilename": "0441010100010005FOTA.BIN"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"FirmwareFilename": "04E1000900042002FOTA.BIN"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"FirmwareFilename": "05E1000900000023FOTA.BIN"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"FirmwareFilename": "0A00000000032000FOTA.BIN"
|
||||
}
|
||||
],
|
||||
"SmartValve": [
|
||||
{
|
||||
"id": 21,
|
||||
"MountingOrientation": "Vertical",
|
||||
"SetPoint": 200,
|
||||
"MeasuredTemperature": 238,
|
||||
"PercentageDemand": 0,
|
||||
"WindowState": "Closed",
|
||||
"ExternalRoomStatTemperature": 242
|
||||
},
|
||||
{
|
||||
"id": 22,
|
||||
"MountingOrientation": "Vertical",
|
||||
"SetPoint": 180,
|
||||
"MeasuredTemperature": 218,
|
||||
"PercentageDemand": 0,
|
||||
"WindowState": "Closed",
|
||||
"ExternalRoomStatTemperature": 229
|
||||
},
|
||||
{
|
||||
"id": 23,
|
||||
"MountingOrientation": "Vertical",
|
||||
"SetPoint": 180,
|
||||
"MeasuredTemperature": 227,
|
||||
"PercentageDemand": 0,
|
||||
"WindowState": "Closed",
|
||||
"ExternalRoomStatTemperature": 229
|
||||
},
|
||||
{
|
||||
"id": 24,
|
||||
"MountingOrientation": "Vertical",
|
||||
"SetPoint": 180,
|
||||
"MeasuredTemperature": 222,
|
||||
"PercentageDemand": 0,
|
||||
"WindowState": "Closed",
|
||||
"ExternalRoomStatTemperature": 229
|
||||
},
|
||||
{
|
||||
"id": 25,
|
||||
"MountingOrientation": "Vertical",
|
||||
"SetPoint": 180,
|
||||
"MeasuredTemperature": 229,
|
||||
"PercentageDemand": 0,
|
||||
"WindowState": "Closed",
|
||||
"ExternalRoomStatTemperature": 229
|
||||
},
|
||||
{
|
||||
"id": 26,
|
||||
"MountingOrientation": "Vertical",
|
||||
"SetPoint": 180,
|
||||
"MeasuredTemperature": 224,
|
||||
"PercentageDemand": 0,
|
||||
"WindowState": "Closed"
|
||||
},
|
||||
{
|
||||
"id": 27,
|
||||
"MountingOrientation": "Vertical",
|
||||
"SetPoint": 180,
|
||||
"MeasuredTemperature": 233,
|
||||
"PercentageDemand": 0,
|
||||
"WindowState": "Closed",
|
||||
"ExternalRoomStatTemperature": 241
|
||||
},
|
||||
{
|
||||
"id": 29,
|
||||
"MountingOrientation": "Vertical",
|
||||
"SetPoint": 200,
|
||||
"MeasuredTemperature": 233,
|
||||
"PercentageDemand": 0,
|
||||
"WindowState": "Closed",
|
||||
"ExternalRoomStatTemperature": 237
|
||||
},
|
||||
{
|
||||
"id": 30,
|
||||
"MountingOrientation": "Vertical",
|
||||
"SetPoint": 180,
|
||||
"MeasuredTemperature": 239,
|
||||
"PercentageDemand": 0,
|
||||
"WindowState": "Closed",
|
||||
"ExternalRoomStatTemperature": 247
|
||||
}
|
||||
],
|
||||
"RoomStat": [
|
||||
{
|
||||
"id": 10,
|
||||
"SetPoint": 200,
|
||||
"MeasuredTemperature": 242,
|
||||
"MeasuredHumidity": 50
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"SetPoint": 180,
|
||||
"MeasuredTemperature": 229,
|
||||
"MeasuredHumidity": 55
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"SetPoint": 200,
|
||||
"MeasuredTemperature": 237,
|
||||
"MeasuredHumidity": 54
|
||||
},
|
||||
{
|
||||
"id": 13,
|
||||
"SetPoint": 180,
|
||||
"MeasuredTemperature": 241,
|
||||
"MeasuredHumidity": 51
|
||||
},
|
||||
{
|
||||
"id": 14,
|
||||
"SetPoint": 180,
|
||||
"MeasuredTemperature": 247,
|
||||
"MeasuredHumidity": 52
|
||||
}
|
||||
],
|
||||
"SmartPlug": [
|
||||
{
|
||||
"id": 41,
|
||||
"ScheduleId": 2000,
|
||||
"ManualState": "Off",
|
||||
"Name": "Booster",
|
||||
"Mode": "Manual",
|
||||
"AwayAction": "NoChange",
|
||||
"OutputState": "Off",
|
||||
"ControlSource": "FromManualMode",
|
||||
"ScheduledState": "Off"
|
||||
}
|
||||
],
|
||||
"DeviceCapabilityMatrix": {
|
||||
"Roomstat": true,
|
||||
"ITRV": true,
|
||||
"SmartPlug": true,
|
||||
"UFH": false,
|
||||
"UFHFloorTempSensor": false,
|
||||
"UFHDewSensor": false,
|
||||
"HACT": false,
|
||||
"LACT": false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user