added migrated 2.x add-ons
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
32
bundles/org.openhab.binding.evohome/.classpath
Normal file
32
bundles/org.openhab.binding.evohome/.classpath
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="test" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
23
bundles/org.openhab.binding.evohome/.project
Normal file
23
bundles/org.openhab.binding.evohome/.project
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.openhab.binding.evohome</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
13
bundles/org.openhab.binding.evohome/NOTICE
Normal file
13
bundles/org.openhab.binding.evohome/NOTICE
Normal file
@@ -0,0 +1,13 @@
|
||||
This content is produced and maintained by the openHAB project.
|
||||
|
||||
* Project home: https://www.openhab.org
|
||||
|
||||
== Declared Project Licenses
|
||||
|
||||
This program and the accompanying materials are made available under the terms
|
||||
of the Eclipse Public License 2.0 which is available at
|
||||
https://www.eclipse.org/legal/epl-2.0/.
|
||||
|
||||
== Source Code
|
||||
|
||||
https://github.com/openhab/openhab-addons
|
||||
119
bundles/org.openhab.binding.evohome/README.md
Normal file
119
bundles/org.openhab.binding.evohome/README.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# evohome Binding
|
||||
|
||||
This binding integrates the Honeywell evohome system.
|
||||
It uses your Honeywell Total Connect Comfort account to access your locations and heating zones.
|
||||
|
||||
## Supported Things
|
||||
|
||||
The binding supports the following things:
|
||||
|
||||
* evohome Account
|
||||
* evotouch control display
|
||||
* Heating zones
|
||||
|
||||
### evohome Account
|
||||
|
||||
This thing functions as the bridge between all the other things.
|
||||
It contains your credentials and connects to the Honeywell web API.
|
||||
|
||||
|
||||
### evotouch
|
||||
|
||||
This thing represents the central display controller.
|
||||
It is used to view and change the current system mode.
|
||||
|
||||
### Heating zone
|
||||
|
||||
The heating zone thing represents the evohome heating zone.
|
||||
It displays the current temperature, the temperature set point and the status of the set point.
|
||||
It also allows you to permanently override the current temperature set point as well as canceling any active overrides.
|
||||
|
||||
## Discovery
|
||||
|
||||
After setting up the evohome account, the evotouch and heating zones available to your account will be discovered after a manual scan.
|
||||
|
||||
## Thing Configuration
|
||||
|
||||
Thing configuration is optional, it is easier to use discovery which will automatically add all your zones and displays to the inbox, once the account Thing is online.
|
||||
|
||||
### Account
|
||||
|
||||
| Name | Required | Description |
|
||||
|-----------------|----------|--------------------------------------------------------|
|
||||
| username | yes | The username of your TCC account |
|
||||
| password | yes | The password of your TCC account |
|
||||
| refreshInterval | no | The amount of time in seconds between updates (0-3000) |
|
||||
|
||||
### Display & Zone
|
||||
|
||||
| Name | Required | Description |
|
||||
|------|----------|----------------------------------------------------------------------------------------|
|
||||
| id | yes | The id which can be found by auto-discovery or the response data (using TRACE logging) |
|
||||
| name | no | A friendly name for use in the UI |
|
||||
|
||||
## Channels
|
||||
|
||||
### Account
|
||||
|
||||
None
|
||||
|
||||
### Display
|
||||
|
||||
| Channel Type ID | Item Type | Description |
|
||||
|-----------------|-----------|--------------------------------------------------------------------------------------------------------------------|
|
||||
| Mode | String | Allows to view or set the system mode. Supported values are: Auto, AutoWithEco, Away, DayOff, HeatingOff, Custom |
|
||||
|
||||
### Zone
|
||||
|
||||
| Channel Type ID | Item Type | Description |
|
||||
|-------------------|-----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| Temperature | Number | Allows for viewing the current actual temperature of the zone. |
|
||||
| SetPointStatus | String | Allows for viewing the current set point mode of the zone. |
|
||||
| SetPoint | Number | Allows for viewing and permanently overriding the temperature set point of the zone. Sending 0 cancels any active set point overrides. |
|
||||
## Full Example
|
||||
|
||||
### demo.things
|
||||
|
||||
```
|
||||
Bridge evohome:account:your_account_alias [ username="your_user_name", password="your_password" ]
|
||||
{
|
||||
display your_display_alias [ id="1234" ]
|
||||
heatingzone your_zone_alias [ id="5678" ]
|
||||
}
|
||||
```
|
||||
|
||||
### demo.items
|
||||
|
||||
```
|
||||
// evohome Display
|
||||
String DemoMode { channel="evohome:display:your_account_alias:your_display_alias:SystemMode" }
|
||||
|
||||
// evohome Heatingzone
|
||||
Number DemoZoneTemperature { channel="evohome:heatingzone:your_account_alias:your_zone_alias:Temperature" }
|
||||
String DemoZoneSetPointStatus { channel="evohome:heatingzone:your_account_alias:your_zone_alias:SetPointStatus" }
|
||||
Number DemoZoneSetPoint { channel="evohome:heatingzone:your_account_alias:your_zone_alias:SetPoint" }
|
||||
```
|
||||
|
||||
### demo.sitemap
|
||||
|
||||
```
|
||||
sitemap evohome label="evohome Menu"
|
||||
{
|
||||
Frame label="evohome display" {
|
||||
Selection label="[%s]" item=DemoMode mappings=[
|
||||
"Auto"="Normal",
|
||||
"AutoWithEco"="Eco",
|
||||
"Away"="Away",
|
||||
"DayOff"="Day Off",
|
||||
"HeatingOff"="Off",
|
||||
"Custom"="Custom"
|
||||
]
|
||||
}
|
||||
|
||||
Frame label="evohome heating zone" {
|
||||
Text label="Temperature" item=DemoZoneTemperature
|
||||
Text label="Status" item=DemoZoneSetPointStatus
|
||||
Setpoint label="Zone set point" item=DemoZoneSetPoint minValue=5 maxValue=35 step=0.5
|
||||
}
|
||||
}
|
||||
```
|
||||
17
bundles/org.openhab.binding.evohome/pom.xml
Normal file
17
bundles/org.openhab.binding.evohome/pom.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
|
||||
<version>3.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>org.openhab.binding.evohome</artifactId>
|
||||
|
||||
<name>openHAB Add-ons :: Bundles :: evohome Binding</name>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.evohome-${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-evohome" description="Evohome Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<feature>openhab-transport-http</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.evohome/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
||||
@@ -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.evohome.internal;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link EvohomeBindingConstants} class defines common constants, which are
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
* @author Neil Renaud - Heating Zones
|
||||
*/
|
||||
public class EvohomeBindingConstants {
|
||||
|
||||
private static final String BINDING_ID = "evohome";
|
||||
|
||||
// List of all Thing Type UIDs
|
||||
public static final ThingTypeUID THING_TYPE_EVOHOME_ACCOUNT = new ThingTypeUID(BINDING_ID, "account");
|
||||
public static final ThingTypeUID THING_TYPE_EVOHOME_DISPLAY = new ThingTypeUID(BINDING_ID, "display");
|
||||
public static final ThingTypeUID THING_TYPE_EVOHOME_HEATING_ZONE = new ThingTypeUID(BINDING_ID, "heatingzone");
|
||||
|
||||
// List of all Channel IDs
|
||||
public static final String DISPLAY_SYSTEM_MODE_CHANNEL = "SystemMode";
|
||||
public static final String ZONE_TEMPERATURE_CHANNEL = "Temperature";
|
||||
public static final String ZONE_SET_POINT_STATUS_CHANNEL = "SetPointStatus";
|
||||
public static final String ZONE_SET_POINT_CHANNEL = "SetPoint";
|
||||
|
||||
// List of Discovery properties
|
||||
public static final String PROPERTY_ID = "id";
|
||||
public static final String PROPERTY_NAME = "name";
|
||||
|
||||
// List of all addressable things in OH = SUPPORTED_DEVICE_THING_TYPES_UIDS + the virtual bridge
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet(
|
||||
Stream.of(THING_TYPE_EVOHOME_ACCOUNT, THING_TYPE_EVOHOME_DISPLAY, THING_TYPE_EVOHOME_HEATING_ZONE)
|
||||
.collect(Collectors.toSet()));
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.openhab.binding.evohome.internal.discovery.EvohomeDiscoveryService;
|
||||
import org.openhab.binding.evohome.internal.handler.EvohomeAccountBridgeHandler;
|
||||
import org.openhab.binding.evohome.internal.handler.EvohomeHeatingZoneHandler;
|
||||
import org.openhab.binding.evohome.internal.handler.EvohomeTemperatureControlSystemHandler;
|
||||
import org.openhab.core.config.discovery.DiscoveryService;
|
||||
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.ThingUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||
import org.osgi.framework.ServiceRegistration;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
|
||||
/**
|
||||
* Provides the thing factory for this binding
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.evohome")
|
||||
@NonNullByDefault
|
||||
public class EvohomeHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
private final Map<ThingUID, @Nullable ServiceRegistration<?>> discoveryServiceRegs = new HashMap<>();
|
||||
|
||||
private final HttpClient httpClient;
|
||||
|
||||
@Activate
|
||||
public EvohomeHandlerFactory(@Reference final HttpClientFactory httpClientFactory) {
|
||||
this.httpClient = httpClientFactory.getCommonHttpClient();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return EvohomeBindingConstants.SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
if (thingTypeUID.equals(EvohomeBindingConstants.THING_TYPE_EVOHOME_ACCOUNT)) {
|
||||
EvohomeAccountBridgeHandler bridge = new EvohomeAccountBridgeHandler((Bridge) thing, httpClient);
|
||||
registerEvohomeDiscoveryService(bridge);
|
||||
return bridge;
|
||||
} else if (thingTypeUID.equals(EvohomeBindingConstants.THING_TYPE_EVOHOME_DISPLAY)) {
|
||||
return new EvohomeTemperatureControlSystemHandler(thing);
|
||||
} else if (thingTypeUID.equals(EvohomeBindingConstants.THING_TYPE_EVOHOME_HEATING_ZONE)) {
|
||||
return new EvohomeHeatingZoneHandler(thing);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void registerEvohomeDiscoveryService(EvohomeAccountBridgeHandler evohomeBridgeHandler) {
|
||||
EvohomeDiscoveryService discoveryService = new EvohomeDiscoveryService(evohomeBridgeHandler);
|
||||
|
||||
this.discoveryServiceRegs.put(evohomeBridgeHandler.getThing().getUID(),
|
||||
bundleContext.registerService(DiscoveryService.class.getName(), discoveryService, new Hashtable<>()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThingHandler registerHandler(Thing thing) {
|
||||
return super.registerHandler(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeHandler(ThingHandler thingHandler) {
|
||||
if (thingHandler instanceof EvohomeAccountBridgeHandler) {
|
||||
ServiceRegistration<?> serviceReg = this.discoveryServiceRegs.get(thingHandler.getThing().getUID());
|
||||
if (serviceReg != null) {
|
||||
EvohomeDiscoveryService service = (EvohomeDiscoveryService) bundleContext
|
||||
.getService(serviceReg.getReference());
|
||||
if (service != null) {
|
||||
service.deactivate();
|
||||
}
|
||||
serviceReg.unregister();
|
||||
discoveryServiceRegs.remove(thingHandler.getThing().getUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.evohome.internal;
|
||||
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
/**
|
||||
* Provides an interface for a delegate that can throw a timeout
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public interface RunnableWithTimeout {
|
||||
|
||||
public abstract void run() throws TimeoutException;
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
/**
|
||||
* 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.evohome.internal.api;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.api.ContentResponse;
|
||||
import org.eclipse.jetty.client.api.Request;
|
||||
import org.eclipse.jetty.client.util.StringContentProvider;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.Authentication;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
/**
|
||||
* Provides access to (an optionally OAUTH based) API. Makes sure that all the necessary headers are set.
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class ApiAccess {
|
||||
private static final int REQUEST_TIMEOUT_SECONDS = 5;
|
||||
private final Logger logger = LoggerFactory.getLogger(ApiAccess.class);
|
||||
private final HttpClient httpClient;
|
||||
private final Gson gson;
|
||||
|
||||
private Authentication authenticationData;
|
||||
private String applicationId;
|
||||
|
||||
public ApiAccess(HttpClient httpClient) {
|
||||
this.gson = new GsonBuilder().create();
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the authentication details on the type
|
||||
*
|
||||
* @param authentication The authentication details to apply
|
||||
*/
|
||||
public void setAuthentication(Authentication authentication) {
|
||||
authenticationData = authentication;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current authentication details of the type
|
||||
*
|
||||
* @return The current authentication details
|
||||
*/
|
||||
public Authentication getAuthentication() {
|
||||
return authenticationData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the application id on the type
|
||||
*
|
||||
* @param applicationId The application id to apply
|
||||
*/
|
||||
public void setApplicationId(String applicationId) {
|
||||
this.applicationId = applicationId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Issues an HTTP request on the API's URL. Makes sure that the request is correctly formatted.
|
||||
*
|
||||
* @param method The HTTP method to use (POST, GET, ...)
|
||||
* @param url The URL to query
|
||||
* @param headers The optional additional headers to apply, can be null
|
||||
* @param requestData The optional request data to use, can be null
|
||||
* @param contentType The content type to use with the request data. Required when using requestData
|
||||
* @return The result of the request or null
|
||||
* @throws TimeoutException Thrown when a request times out
|
||||
*/
|
||||
public <TOut> TOut doRequest(HttpMethod method, String url, Map<String, String> headers, String requestData,
|
||||
String contentType, Class<TOut> outClass) throws TimeoutException {
|
||||
TOut retVal = null;
|
||||
logger.debug("Requesting: [{}]", url);
|
||||
|
||||
try {
|
||||
Request request = httpClient.newRequest(url).method(method);
|
||||
|
||||
if (headers != null) {
|
||||
for (Map.Entry<String, String> header : headers.entrySet()) {
|
||||
request.header(header.getKey(), header.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
if (requestData != null) {
|
||||
request.content(new StringContentProvider(requestData), contentType);
|
||||
}
|
||||
|
||||
ContentResponse response = request.timeout(REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS).send();
|
||||
|
||||
logger.debug("Response: {}", response);
|
||||
logger.debug("\n{}\n{}", response.getHeaders(), response.getContentAsString());
|
||||
|
||||
if ((response.getStatus() == HttpStatus.OK_200) || (response.getStatus() == HttpStatus.ACCEPTED_202)) {
|
||||
String reply = response.getContentAsString();
|
||||
|
||||
if (outClass != null) {
|
||||
retVal = new Gson().fromJson(reply, outClass);
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
logger.debug("Error in handling request: ", e);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Issues an HTTP GET request on the API's URL, using an object that is serialized to JSON as input.
|
||||
* Makes sure that the request is correctly formatted.*
|
||||
*
|
||||
* @param url The URL to query
|
||||
* @param outClass The type of the requested result
|
||||
* @return The result of the request or null
|
||||
* @throws TimeoutException Thrown when a request times out
|
||||
*/
|
||||
public <TOut> TOut doAuthenticatedGet(String url, Class<TOut> outClass) throws TimeoutException {
|
||||
return doAuthenticatedRequest(HttpMethod.GET, url, null, outClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Issues an HTTP request on the API's URL, using an object that is serialized to JSON as input.
|
||||
* Makes sure that the request is correctly formatted.*
|
||||
*
|
||||
* @param url The URL to query
|
||||
* @param requestContainer The object to use as JSON data for the request
|
||||
* @throws TimeoutException Thrown when a request times out
|
||||
*/
|
||||
public void doAuthenticatedPut(String url, Object requestContainer) throws TimeoutException {
|
||||
doAuthenticatedRequest(HttpMethod.PUT, url, requestContainer, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Issues an HTTP request on the API's URL, using an object that is serialized to JSON as input.
|
||||
* Makes sure that the request is correctly formatted.*
|
||||
*
|
||||
* @param method The HTTP method to use (POST, GET, ...)
|
||||
* @param url The URL to query
|
||||
* @param headers The optional additional headers to apply, can be null
|
||||
* @param requestContainer The object to use as JSON data for the request
|
||||
* @param outClass The type of the requested result
|
||||
* @return The result of the request or null
|
||||
* @throws TimeoutException Thrown when a request times out
|
||||
*/
|
||||
private <TOut> TOut doRequest(HttpMethod method, String url, Map<String, String> headers, Object requestContainer,
|
||||
Class<TOut> outClass) throws TimeoutException {
|
||||
String json = null;
|
||||
if (requestContainer != null) {
|
||||
json = this.gson.toJson(requestContainer);
|
||||
}
|
||||
|
||||
return doRequest(method, url, headers, json, "application/json", outClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Issues an HTTP request on the API's URL, using an object that is serialized to JSON as input and
|
||||
* using the authentication applied to the type.
|
||||
* Makes sure that the request is correctly formatted.*
|
||||
*
|
||||
* @param method The HTTP method to use (POST, GET, ...)
|
||||
* @param url The URL to query
|
||||
* @param requestContainer The object to use as JSON data for the request
|
||||
* @param outClass The type of the requested result
|
||||
* @return The result of the request or null
|
||||
* @throws TimeoutException Thrown when a request times out
|
||||
*/
|
||||
private <TOut> TOut doAuthenticatedRequest(HttpMethod method, String url, Object requestContainer,
|
||||
Class<TOut> outClass) throws TimeoutException {
|
||||
Map<String, String> headers = null;
|
||||
if (authenticationData != null) {
|
||||
headers = new HashMap<>();
|
||||
|
||||
headers.put("Authorization", "Bearer " + authenticationData.getAccessToken());
|
||||
headers.put("applicationId", applicationId);
|
||||
headers.put("Accept",
|
||||
"application/json, application/xml, text/json, text/x-json, text/javascript, text/xml");
|
||||
}
|
||||
|
||||
return doRequest(method, url, headers, requestContainer, outClass);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.request.HeatSetPoint;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.request.HeatSetPointBuilder;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.request.Mode;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.request.ModeBuilder;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.Authentication;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.Location;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.LocationStatus;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.Locations;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.LocationsStatus;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.UserAccount;
|
||||
import org.openhab.binding.evohome.internal.configuration.EvohomeAccountConfiguration;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Implementation of the evohome client V2 api
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class EvohomeApiClient {
|
||||
|
||||
private static final String APPLICATION_ID = "b013aa26-9724-4dbd-8897-048b9aada249";
|
||||
private static final String CLIENT_ID = "4a231089-d2b6-41bd-a5eb-16a0a422b999";
|
||||
private static final String CLIENT_SECRET = "1a15cdb8-42de-407b-add0-059f92c530cb";
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(EvohomeApiClient.class);
|
||||
private final HttpClient httpClient;
|
||||
private final EvohomeAccountConfiguration configuration;
|
||||
private final ApiAccess apiAccess;
|
||||
|
||||
private Locations locations = new Locations();
|
||||
private UserAccount useraccount;
|
||||
private LocationsStatus locationsStatus;
|
||||
|
||||
/**
|
||||
* Creates a new API client based on the V2 API interface
|
||||
*
|
||||
* @param configuration The configuration of the account to use
|
||||
* @throws Exception
|
||||
*/
|
||||
public EvohomeApiClient(EvohomeAccountConfiguration configuration, HttpClient httpClient) throws Exception {
|
||||
this.configuration = configuration;
|
||||
this.httpClient = httpClient;
|
||||
|
||||
try {
|
||||
httpClient.start();
|
||||
} catch (Exception e) {
|
||||
logger.error("Could not start http client", e);
|
||||
throw new EvohomeApiClientException("Could not start http client", e);
|
||||
}
|
||||
|
||||
apiAccess = new ApiAccess(httpClient);
|
||||
apiAccess.setApplicationId(APPLICATION_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the current connection to the API
|
||||
*/
|
||||
public void close() {
|
||||
apiAccess.setAuthentication(null);
|
||||
useraccount = null;
|
||||
locations = null;
|
||||
locationsStatus = null;
|
||||
|
||||
if (httpClient.isStarted()) {
|
||||
try {
|
||||
httpClient.stop();
|
||||
} catch (Exception e) {
|
||||
logger.debug("Could not stop http client.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean login() {
|
||||
boolean success = authenticateWithUsername();
|
||||
|
||||
// If the authentication succeeded, gather the basic intel as well
|
||||
if (success) {
|
||||
try {
|
||||
useraccount = requestUserAccount();
|
||||
locations = requestLocations();
|
||||
} catch (TimeoutException e) {
|
||||
logger.warn("Timeout while retrieving user and location information. Failing loging.");
|
||||
success = false;
|
||||
}
|
||||
} else {
|
||||
apiAccess.setAuthentication(null);
|
||||
logger.debug("Authorization failed");
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
public void logout() {
|
||||
close();
|
||||
}
|
||||
|
||||
public void update() {
|
||||
updateAuthentication();
|
||||
try {
|
||||
locationsStatus = requestLocationsStatus();
|
||||
} catch (TimeoutException e) {
|
||||
logger.info("Timeout on update");
|
||||
}
|
||||
}
|
||||
|
||||
public Locations getInstallationInfo() {
|
||||
return locations;
|
||||
}
|
||||
|
||||
public LocationsStatus getInstallationStatus() {
|
||||
return locationsStatus;
|
||||
}
|
||||
|
||||
public void setTcsMode(String tcsId, String mode) throws TimeoutException {
|
||||
String url = String.format(EvohomeApiConstants.URL_V2_BASE + EvohomeApiConstants.URL_V2_MODE, tcsId);
|
||||
Mode modeCommand = new ModeBuilder().setMode(mode).build();
|
||||
apiAccess.doAuthenticatedPut(url, modeCommand);
|
||||
}
|
||||
|
||||
public void setHeatingZoneOverride(String zoneId, double setPoint) throws TimeoutException {
|
||||
HeatSetPoint setPointCommand = new HeatSetPointBuilder().setSetPoint(setPoint).build();
|
||||
setHeatingZoneOverride(zoneId, setPointCommand);
|
||||
}
|
||||
|
||||
public void cancelHeatingZoneOverride(String zoneId) throws TimeoutException {
|
||||
HeatSetPoint setPointCommand = new HeatSetPointBuilder().setCancelSetPoint().build();
|
||||
setHeatingZoneOverride(zoneId, setPointCommand);
|
||||
}
|
||||
|
||||
private void setHeatingZoneOverride(String zoneId, HeatSetPoint heatSetPoint) throws TimeoutException {
|
||||
String url = EvohomeApiConstants.URL_V2_BASE + EvohomeApiConstants.URL_V2_HEAT_SETPOINT;
|
||||
url = String.format(url, zoneId);
|
||||
apiAccess.doAuthenticatedPut(url, heatSetPoint);
|
||||
}
|
||||
|
||||
private UserAccount requestUserAccount() throws TimeoutException {
|
||||
String url = EvohomeApiConstants.URL_V2_BASE + EvohomeApiConstants.URL_V2_ACCOUNT;
|
||||
return apiAccess.doAuthenticatedGet(url, UserAccount.class);
|
||||
}
|
||||
|
||||
private Locations requestLocations() throws TimeoutException {
|
||||
Locations locations = new Locations();
|
||||
if (useraccount != null) {
|
||||
String url = EvohomeApiConstants.URL_V2_BASE + EvohomeApiConstants.URL_V2_INSTALLATION_INFO;
|
||||
url = String.format(url, useraccount.getUserId());
|
||||
|
||||
locations = apiAccess.doAuthenticatedGet(url, Locations.class);
|
||||
}
|
||||
return locations;
|
||||
}
|
||||
|
||||
private LocationsStatus requestLocationsStatus() throws TimeoutException {
|
||||
LocationsStatus locationsStatus = new LocationsStatus();
|
||||
|
||||
if (locations != null) {
|
||||
for (Location location : locations) {
|
||||
String url = EvohomeApiConstants.URL_V2_BASE + EvohomeApiConstants.URL_V2_LOCATION_STATUS;
|
||||
url = String.format(url, location.getLocationInfo().getLocationId());
|
||||
LocationStatus status = apiAccess.doAuthenticatedGet(url, LocationStatus.class);
|
||||
locationsStatus.add(status);
|
||||
}
|
||||
}
|
||||
return locationsStatus;
|
||||
}
|
||||
|
||||
private boolean authenticate(String credentials, String grantType) {
|
||||
String data = credentials + "&" + "Host=rs.alarmnet.com%2F&" + "Pragma=no-cache&"
|
||||
+ "Cache-Control=no-store+no-cache&"
|
||||
+ "scope=EMEA-V1-Basic+EMEA-V1-Anonymous+EMEA-V1-Get-Current-User-Account&" + "grant_type=" + grantType
|
||||
+ "&" + "Content-Type=application%2Fx-www-form-urlencoded%3B+charset%3Dutf-8&"
|
||||
+ "Connection=Keep-Alive";
|
||||
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
String basicAuth = Base64.getEncoder().encodeToString((CLIENT_ID + ":" + CLIENT_SECRET).getBytes());
|
||||
headers.put("Authorization", "Basic " + basicAuth);
|
||||
headers.put("Accept", "application/json, application/xml, text/json, text/x-json, text/javascript, text/xml");
|
||||
|
||||
Authentication authentication;
|
||||
try {
|
||||
authentication = apiAccess.doRequest(HttpMethod.POST, EvohomeApiConstants.URL_V2_AUTH, headers, data,
|
||||
"application/x-www-form-urlencoded", Authentication.class);
|
||||
} catch (TimeoutException e) {
|
||||
// A timeout is not a successful login as well
|
||||
authentication = null;
|
||||
}
|
||||
|
||||
apiAccess.setAuthentication(authentication);
|
||||
|
||||
if (authentication != null) {
|
||||
authentication.setSystemTime(System.currentTimeMillis() / 1000);
|
||||
}
|
||||
|
||||
return (authentication != null);
|
||||
}
|
||||
|
||||
private boolean authenticateWithUsername() {
|
||||
boolean result = false;
|
||||
|
||||
try {
|
||||
String credentials = "Username=" + URLEncoder.encode(configuration.username, "UTF-8") + "&" + "Password="
|
||||
+ URLEncoder.encode(configuration.password, "UTF-8");
|
||||
result = authenticate(credentials, "password");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
logger.error("Credential conversion failed", e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean authenticateWithToken(String accessToken) {
|
||||
String credentials = "refresh_token=" + accessToken;
|
||||
return authenticate(credentials, "refresh_token");
|
||||
}
|
||||
|
||||
private void updateAuthentication() {
|
||||
Authentication authentication = apiAccess.getAuthentication();
|
||||
if (authentication == null) {
|
||||
authenticateWithUsername();
|
||||
} else {
|
||||
// Compare current time to the expiration time minus four intervals for slack
|
||||
long currentTime = System.currentTimeMillis() / 1000;
|
||||
long expiration = authentication.getSystemTime() + authentication.getExpiresIn();
|
||||
expiration -= 4 * configuration.refreshInterval;
|
||||
|
||||
// Update the access token just before it expires, but fall back to username and password
|
||||
// when it fails (i.e. refresh token had been invalidated)
|
||||
if (currentTime > expiration) {
|
||||
authenticateWithToken(authentication.getRefreshToken());
|
||||
if (apiAccess.getAuthentication() == null) {
|
||||
authenticateWithUsername();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api;
|
||||
|
||||
/**
|
||||
* Exception for errors from the API Client.
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class EvohomeApiClientException extends Exception {
|
||||
|
||||
public EvohomeApiClientException() {
|
||||
}
|
||||
|
||||
public EvohomeApiClientException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public EvohomeApiClientException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -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.evohome.internal.api;
|
||||
|
||||
/**
|
||||
* List of evohome API constants
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class EvohomeApiConstants {
|
||||
public static final String URL_V2_AUTH = "https://tccna.honeywell.com/Auth/OAuth/Token";
|
||||
|
||||
public static final String URL_V2_BASE = "https://tccna.honeywell.com/WebAPI/emea/api/v1/";
|
||||
|
||||
public static final String URL_V2_ACCOUNT = "userAccount";
|
||||
public static final String URL_V2_INSTALLATION_INFO = "location/installationInfo?userId=%s&includeTemperatureControlSystems=True";// {userId}
|
||||
public static final String URL_V2_LOCATION = "location/%s/installationInfo?includeTemperatureControlSystems=True"; // {locationId}
|
||||
public static final String URL_V2_GATEWAY = "gateway";
|
||||
public static final String URL_V2_HOT_WATER = "domesticHotWater/%s/state"; // {hardwareId}
|
||||
public static final String URL_V2_SCHEDULE = "%s/%s/schedule"; // {zone_type}, {zoneId}
|
||||
public static final String URL_V2_HEAT_SETPOINT = "temperatureZone/%s/heatSetpoint"; // {zoneId}
|
||||
public static final String URL_V2_LOCATION_STATUS = "location/%s/status?includeTemperatureControlSystems=True"; // {locationId}
|
||||
public static final String URL_V2_MODE = "temperatureControlSystem/%s/mode"; // {systemId}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* 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.evohome.internal.api.models.v2.request;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Request model for the mode
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class HeatSetPoint {
|
||||
|
||||
/**
|
||||
* Constructs an override reset
|
||||
*/
|
||||
HeatSetPoint() {
|
||||
heatSetpointValue = 0.0;
|
||||
setpointMode = "FollowSchedule";
|
||||
timeUntil = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a permanent override with the given temperature
|
||||
*
|
||||
* @param setPoint The target temperature to set the set point to
|
||||
*/
|
||||
HeatSetPoint(double setPoint) {
|
||||
// Make sure that the value is rounded toward the nearest 0.5
|
||||
heatSetpointValue = Math.round(setPoint * 2) / 2.0;
|
||||
setpointMode = "PermanentOverride";
|
||||
timeUntil = null;
|
||||
}
|
||||
|
||||
@SerializedName("heatSetpointValue")
|
||||
private double heatSetpointValue;
|
||||
|
||||
@SerializedName("setpointMode")
|
||||
private String setpointMode;
|
||||
|
||||
@SerializedName("timeUntil")
|
||||
private String timeUntil;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* 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.evohome.internal.api.models.v2.request;
|
||||
|
||||
/**
|
||||
* Builder for heat set point API requests
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class HeatSetPointBuilder implements RequestBuilder<HeatSetPoint> {
|
||||
|
||||
private double setPoint;
|
||||
private boolean hasSetPoint;
|
||||
private boolean cancelSetPoint;
|
||||
|
||||
/**
|
||||
* Creates a new heat set point command
|
||||
*
|
||||
* @return A heat set point command or null when the configuration is invalid
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public HeatSetPoint build() {
|
||||
if (cancelSetPoint) {
|
||||
return new HeatSetPoint();
|
||||
}
|
||||
if (hasSetPoint) {
|
||||
return new HeatSetPoint(setPoint);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public HeatSetPointBuilder setSetPoint(double setPoint) {
|
||||
this.hasSetPoint = true;
|
||||
this.setPoint = setPoint;
|
||||
return this;
|
||||
}
|
||||
|
||||
public HeatSetPointBuilder setCancelSetPoint() {
|
||||
cancelSetPoint = true;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -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.evohome.internal.api.models.v2.request;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Request model for the mode
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class Mode {
|
||||
|
||||
Mode(String mode) {
|
||||
systemMode = mode;
|
||||
timeUntil = null;
|
||||
permanent = true;
|
||||
}
|
||||
|
||||
Mode(String mode, int day, int month, int year) {
|
||||
systemMode = mode;
|
||||
timeUntil = String.format("%s-%s-%sT00:00:00Z", year, month, day);
|
||||
permanent = false;
|
||||
}
|
||||
|
||||
@SerializedName("systemMode")
|
||||
private String systemMode;
|
||||
|
||||
@SerializedName("timeUntil")
|
||||
private String timeUntil;
|
||||
|
||||
@SerializedName("permanent")
|
||||
private boolean permanent;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* 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.evohome.internal.api.models.v2.request;
|
||||
|
||||
/**
|
||||
* Builder for mode API requests
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class ModeBuilder extends TimedRequestBuilder<Mode> {
|
||||
|
||||
private String mode;
|
||||
private boolean hasSetMode;
|
||||
|
||||
/**
|
||||
* Creates a new mode command
|
||||
*
|
||||
* @return A mode command or null when the configuration is invalid
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public Mode build() {
|
||||
if (hasSetMode) {
|
||||
if (useEndTime()) {
|
||||
return new Mode(mode, getYear(), getMonth(), getDay());
|
||||
} else {
|
||||
return new Mode(mode);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ModeBuilder setMode(String mode) {
|
||||
this.hasSetMode = true;
|
||||
this.mode = mode;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.request;
|
||||
|
||||
/**
|
||||
* Builder for API requests
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public interface RequestBuilder<T> {
|
||||
|
||||
public T build();
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* 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.evohome.internal.api.models.v2.request;
|
||||
|
||||
/**
|
||||
* Builder for timed API requests
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public abstract class TimedRequestBuilder<T> implements RequestBuilder<T> {
|
||||
private boolean useEndTime;
|
||||
private int year;
|
||||
private int month;
|
||||
private int day;
|
||||
|
||||
public RequestBuilder<T> withEndTime(int year, int month, int day) {
|
||||
this.useEndTime = true;
|
||||
this.year = year;
|
||||
this.month = month;
|
||||
this.day = day;
|
||||
return this;
|
||||
}
|
||||
|
||||
protected boolean useEndTime() {
|
||||
return useEndTime;
|
||||
}
|
||||
|
||||
protected int getYear() {
|
||||
return year;
|
||||
}
|
||||
|
||||
protected int getMonth() {
|
||||
return month;
|
||||
}
|
||||
|
||||
protected int getDay() {
|
||||
return day;
|
||||
}
|
||||
}
|
||||
@@ -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.evohome.internal.api.models.v2.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Response model for the active fault
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class ActiveFault {
|
||||
|
||||
@SerializedName("faultType")
|
||||
private String faultType;
|
||||
|
||||
@SerializedName("since")
|
||||
private String since;
|
||||
|
||||
public String getFaultType() {
|
||||
return faultType;
|
||||
}
|
||||
}
|
||||
@@ -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.evohome.internal.api.models.v2.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Response model for the authentication
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class Authentication {
|
||||
|
||||
@SerializedName("access_token")
|
||||
private String accessToken;
|
||||
|
||||
@SerializedName("token_type")
|
||||
private String tokenType;
|
||||
|
||||
@SerializedName("expires_in")
|
||||
private int expiresIn;
|
||||
|
||||
@SerializedName("refresh_token")
|
||||
private String refreshToken;
|
||||
|
||||
@SerializedName("scope")
|
||||
private String scope;
|
||||
|
||||
/** Convenience variable for current system time in seconds */
|
||||
private long systemTime;
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public int getExpiresIn() {
|
||||
return expiresIn;
|
||||
}
|
||||
|
||||
public String getRefreshToken() {
|
||||
return refreshToken;
|
||||
}
|
||||
|
||||
public void setSystemTime(long systemTime) {
|
||||
this.systemTime = systemTime;
|
||||
}
|
||||
|
||||
public long getSystemTime() {
|
||||
return systemTime;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* 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.evohome.internal.api.models.v2.response;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Response model for the gateway
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class Gateway {
|
||||
|
||||
@SerializedName("gatewayInfo")
|
||||
private GatewayInfo gatewayInfo;
|
||||
|
||||
@SerializedName("temperatureControlSystems")
|
||||
private List<TemperatureControlSystem> temperatureControlSystems;
|
||||
|
||||
public GatewayInfo getGatewayInfo() {
|
||||
return gatewayInfo;
|
||||
}
|
||||
|
||||
public List<TemperatureControlSystem> getTemperatureControlSystems() {
|
||||
return temperatureControlSystems;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* 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.evohome.internal.api.models.v2.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Response model for the gateway info
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class GatewayInfo {
|
||||
|
||||
@SerializedName("gatewayId")
|
||||
private String gatewayId;
|
||||
|
||||
@SerializedName("mac")
|
||||
private String macAddress;
|
||||
|
||||
@SerializedName("crc")
|
||||
private String crc;
|
||||
|
||||
@SerializedName("isWiFi")
|
||||
private boolean isWifi;
|
||||
|
||||
public String getGatewayId() {
|
||||
return gatewayId;
|
||||
}
|
||||
}
|
||||
@@ -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.evohome.internal.api.models.v2.response;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Response model for the gateway status
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class GatewayStatus {
|
||||
|
||||
@SerializedName("gatewayId")
|
||||
private String gatewayId;
|
||||
|
||||
@SerializedName("temperatureControlSystems")
|
||||
private List<TemperatureControlSystemStatus> temperatureControlSystems;
|
||||
|
||||
@SerializedName("activeFaults")
|
||||
private List<ActiveFault> activeFaults;
|
||||
|
||||
public List<TemperatureControlSystemStatus> getTemperatureControlSystems() {
|
||||
return temperatureControlSystems;
|
||||
}
|
||||
|
||||
public boolean hasActiveFaults() {
|
||||
return !activeFaults.isEmpty();
|
||||
}
|
||||
|
||||
public ActiveFault getActiveFault(int index) {
|
||||
return activeFaults.get(index);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Response model for the heat set point capabilities
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class HeatSetpointCapabilities {
|
||||
|
||||
@SerializedName("maxHeatSetpoint")
|
||||
private double maxHeatSetpoint;
|
||||
|
||||
@SerializedName("minHeatSetpoint")
|
||||
private double minHeatSetpoint;
|
||||
|
||||
@SerializedName("valueResolution")
|
||||
private double valueResolution;
|
||||
|
||||
@SerializedName("allowedSetpointModes")
|
||||
private List<String> allowedSetpointModes;
|
||||
|
||||
@SerializedName("maxDuration")
|
||||
private String maxDuration;
|
||||
|
||||
@SerializedName("timingResolution")
|
||||
private String timingResolution;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Response model for the heat setpoint status
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class HeatSetpointStatus {
|
||||
|
||||
@SerializedName("targetHeatTemperature")
|
||||
private double targetTemperature;
|
||||
|
||||
@SerializedName("setpointMode")
|
||||
private String setpointMode;
|
||||
|
||||
public double getTargetTemperature() {
|
||||
return targetTemperature;
|
||||
}
|
||||
|
||||
public String getSetpointMode() {
|
||||
return setpointMode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* 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.evohome.internal.api.models.v2.response;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Response model for the location
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class Location {
|
||||
|
||||
@SerializedName("locationInfo")
|
||||
private LocationInfo locationInfo;
|
||||
|
||||
@SerializedName("gateways")
|
||||
private List<Gateway> gateways;
|
||||
|
||||
public LocationInfo getLocationInfo() {
|
||||
return locationInfo;
|
||||
}
|
||||
|
||||
public List<Gateway> getGateways() {
|
||||
return gateways;
|
||||
}
|
||||
}
|
||||
@@ -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.evohome.internal.api.models.v2.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Response model for the location info
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class LocationInfo {
|
||||
|
||||
@SerializedName("locationId")
|
||||
private String locationId;
|
||||
|
||||
@SerializedName("name")
|
||||
private String name;
|
||||
|
||||
@SerializedName("streetAddress")
|
||||
private String streetAddress;
|
||||
|
||||
@SerializedName("city")
|
||||
private String city;
|
||||
|
||||
@SerializedName("country")
|
||||
private String country;
|
||||
|
||||
@SerializedName("postcode")
|
||||
private String postcode;
|
||||
|
||||
@SerializedName("locationType")
|
||||
private String locationType;
|
||||
|
||||
@SerializedName("useDaylightSaveSwitching")
|
||||
private boolean useDaylightSaveSwitching;
|
||||
|
||||
@SerializedName("timeZone")
|
||||
private TimeZone timeZone;
|
||||
|
||||
@SerializedName("locationOwner")
|
||||
private LocationOwner locationOwner;
|
||||
|
||||
public String getLocationId() {
|
||||
return locationId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Response model for the location owner
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class LocationOwner {
|
||||
|
||||
@SerializedName("userId")
|
||||
private int userId;
|
||||
|
||||
@SerializedName("username")
|
||||
private String username;
|
||||
|
||||
@SerializedName("firstname")
|
||||
private String firstName;
|
||||
|
||||
@SerializedName("lastname")
|
||||
private String lastName;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 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.evohome.internal.api.models.v2.response;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Response model for the location status
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class LocationStatus {
|
||||
|
||||
@SerializedName("locationId")
|
||||
private String locationId;
|
||||
|
||||
@SerializedName("gateways")
|
||||
private List<GatewayStatus> gateways;
|
||||
|
||||
public LocationStatus() {
|
||||
locationId = "";
|
||||
gateways = new ArrayList<>();
|
||||
}
|
||||
|
||||
public List<GatewayStatus> getGateways() {
|
||||
return gateways;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* 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.evohome.internal.api.models.v2.response;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Alias for a list of locations
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class Locations extends ArrayList<Location> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* 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.evohome.internal.api.models.v2.response;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Alias for a list of location statuses
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class LocationsStatus extends ArrayList<LocationStatus> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 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.evohome.internal.api.models.v2.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Response model for the mode
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class Mode {
|
||||
|
||||
@SerializedName("systemMode")
|
||||
private String systemMode;
|
||||
|
||||
@SerializedName("canBePermanent")
|
||||
private boolean canBePermanent;
|
||||
|
||||
@SerializedName("canBeTemporary")
|
||||
private boolean canBeTemporary;
|
||||
|
||||
@SerializedName("timingMode")
|
||||
private String timingMode;
|
||||
|
||||
@SerializedName("maxDuration")
|
||||
private String maxDuration;
|
||||
|
||||
@SerializedName("timingResolution")
|
||||
private String timingResolution;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Response model for the schedule capabilities
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class ScheduleCapabilities {
|
||||
|
||||
@SerializedName("maxSwitchpointsPerDay")
|
||||
private int maxSwitchpointsPerDay;
|
||||
|
||||
@SerializedName("minSwitchpointsPerDay")
|
||||
private int minSwitchpointsPerDay;
|
||||
|
||||
@SerializedName("setpointValueResolution")
|
||||
private double setpointValueResolution;
|
||||
|
||||
@SerializedName("timingResolution")
|
||||
private String timingResolution;
|
||||
}
|
||||
@@ -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.evohome.internal.api.models.v2.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Response model for the system mode status
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class SystemModeStatus {
|
||||
|
||||
@SerializedName("mode")
|
||||
private String mode;
|
||||
|
||||
@SerializedName("isPermanent")
|
||||
private boolean isPermanent;
|
||||
|
||||
public String getMode() {
|
||||
return mode;
|
||||
}
|
||||
}
|
||||
@@ -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.evohome.internal.api.models.v2.response;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Response model for the temperature control system
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class TemperatureControlSystem {
|
||||
|
||||
@SerializedName("systemId")
|
||||
private String systemId;
|
||||
|
||||
@SerializedName("modelType")
|
||||
private String modelType;
|
||||
|
||||
@SerializedName("zones")
|
||||
private List<Zone> zones;
|
||||
|
||||
@SerializedName("allowedSystemModes")
|
||||
private List<Mode> allowedSystemModes;
|
||||
|
||||
public String getSystemId() {
|
||||
return systemId;
|
||||
}
|
||||
|
||||
public List<Zone> getZones() {
|
||||
return zones;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* 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.evohome.internal.api.models.v2.response;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Response model for the temperature control system status
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class TemperatureControlSystemStatus {
|
||||
|
||||
@SerializedName("systemId")
|
||||
private String systemId;
|
||||
|
||||
@SerializedName("systemModeStatus")
|
||||
private SystemModeStatus mode;
|
||||
|
||||
@SerializedName("zones")
|
||||
private List<ZoneStatus> zones;
|
||||
|
||||
@SerializedName("activeFaults")
|
||||
private List<ActiveFault> activeFaults;
|
||||
|
||||
public String getSystemId() {
|
||||
return systemId;
|
||||
}
|
||||
|
||||
public SystemModeStatus getMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
public List<ZoneStatus> getZones() {
|
||||
return zones;
|
||||
}
|
||||
}
|
||||
@@ -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.evohome.internal.api.models.v2.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Response model for the temperature status
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class TemperatureStatus {
|
||||
|
||||
@SerializedName("temperature")
|
||||
private double temperature;
|
||||
|
||||
@SerializedName("isAvailable")
|
||||
private boolean isAvailable;
|
||||
|
||||
public double getTemperature() {
|
||||
return temperature;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* 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.evohome.internal.api.models.v2.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Response model for the time zone
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class TimeZone {
|
||||
|
||||
@SerializedName("timeZoneId")
|
||||
private String timeZoneId;
|
||||
|
||||
@SerializedName("displayName")
|
||||
private String displayName;
|
||||
|
||||
@SerializedName("offsetMinutes")
|
||||
private int offsetMinutes;
|
||||
|
||||
@SerializedName("currentOffsetMinutes")
|
||||
private int currentOffsetMinutes;
|
||||
|
||||
@SerializedName("supportsDaylightSaving")
|
||||
private boolean supportsDaylightSaving;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* 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.evohome.internal.api.models.v2.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Response model for the user account
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class UserAccount {
|
||||
|
||||
@SerializedName("userId")
|
||||
private String userId;
|
||||
|
||||
@SerializedName("username")
|
||||
private String userName;
|
||||
|
||||
@SerializedName("firstname")
|
||||
private String firstName;
|
||||
|
||||
@SerializedName("lastname")
|
||||
private String lastName;
|
||||
|
||||
@SerializedName("streetAddress")
|
||||
private String streetAddress;
|
||||
|
||||
@SerializedName("city")
|
||||
private String city;
|
||||
|
||||
@SerializedName("postcode")
|
||||
private String postCode;
|
||||
|
||||
@SerializedName("country")
|
||||
private String country;
|
||||
|
||||
@SerializedName("language")
|
||||
private String language;
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* 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.evohome.internal.api.models.v2.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Response model for the zone
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class Zone {
|
||||
|
||||
@SerializedName("zoneId")
|
||||
private String zoneId;
|
||||
|
||||
@SerializedName("modelType")
|
||||
private String modelType;
|
||||
|
||||
@SerializedName("name")
|
||||
private String name;
|
||||
|
||||
@SerializedName("zoneType")
|
||||
private String zoneType;
|
||||
|
||||
@SerializedName("heatSetpointCapabilities")
|
||||
private HeatSetpointCapabilities heatSetpointCapabilities;
|
||||
|
||||
@SerializedName("scheduleCapabilities")
|
||||
private ScheduleCapabilities scheduleCapabilities;
|
||||
|
||||
public String getZoneId() {
|
||||
return zoneId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Response model for zone status
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class ZoneStatus {
|
||||
|
||||
@SerializedName("zoneId")
|
||||
private String zoneId;
|
||||
|
||||
@SerializedName("name")
|
||||
private String name;
|
||||
|
||||
@SerializedName("temperatureStatus")
|
||||
private TemperatureStatus temperature;
|
||||
|
||||
@SerializedName("setpointStatus")
|
||||
private HeatSetpointStatus heatSetpoint;
|
||||
|
||||
@SerializedName("activeFaults")
|
||||
private List<ActiveFault> activeFaults;
|
||||
|
||||
public String getZoneId() {
|
||||
return zoneId;
|
||||
}
|
||||
|
||||
public TemperatureStatus getTemperature() {
|
||||
return temperature;
|
||||
}
|
||||
|
||||
public HeatSetpointStatus getHeatSetpoint() {
|
||||
return heatSetpoint;
|
||||
}
|
||||
|
||||
public boolean hasActiveFaults() {
|
||||
return !activeFaults.isEmpty();
|
||||
}
|
||||
|
||||
public ActiveFault getActiveFault(int index) {
|
||||
return activeFaults.get(index);
|
||||
}
|
||||
}
|
||||
@@ -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.evohome.internal.configuration;
|
||||
|
||||
/**
|
||||
* Contains the configuration of the binding.
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class EvohomeAccountConfiguration {
|
||||
public String username;
|
||||
public String password;
|
||||
public String applicationId;
|
||||
public int refreshInterval;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.configuration;
|
||||
|
||||
/**
|
||||
* Contains the configuration of the binding.
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class EvohomeTemperatureControlSystemConfiguration {
|
||||
public String id;
|
||||
public String name;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.configuration;
|
||||
|
||||
/**
|
||||
* Contains the common configuration definition of an evohome Thing
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class EvohomeThingConfiguration {
|
||||
public String id;
|
||||
public String name;
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
* 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.evohome.internal.discovery;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.openhab.binding.evohome.internal.EvohomeBindingConstants;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.Gateway;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.Location;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.TemperatureControlSystem;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.Zone;
|
||||
import org.openhab.binding.evohome.internal.handler.AccountStatusListener;
|
||||
import org.openhab.binding.evohome.internal.handler.EvohomeAccountBridgeHandler;
|
||||
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||
import org.openhab.core.config.discovery.DiscoveryResult;
|
||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link EvohomeDiscoveryService} class is capable of discovering the available data from Evohome
|
||||
*
|
||||
* @author Neil Renaud - Initial contribution
|
||||
* @author Jasper van Zuijlen - Background discovery
|
||||
*
|
||||
*/
|
||||
public class EvohomeDiscoveryService extends AbstractDiscoveryService implements AccountStatusListener {
|
||||
private final Logger logger = LoggerFactory.getLogger(EvohomeDiscoveryService.class);
|
||||
private static final int TIMEOUT = 5;
|
||||
|
||||
private EvohomeAccountBridgeHandler bridge;
|
||||
private ThingUID bridgeUID;
|
||||
|
||||
public EvohomeDiscoveryService(EvohomeAccountBridgeHandler bridge) {
|
||||
super(EvohomeBindingConstants.SUPPORTED_THING_TYPES_UIDS, TIMEOUT);
|
||||
|
||||
this.bridge = bridge;
|
||||
this.bridgeUID = this.bridge.getThing().getUID();
|
||||
this.bridge.addAccountStatusListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startScan() {
|
||||
discoverDevices();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startBackgroundDiscovery() {
|
||||
discoverDevices();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void stopScan() {
|
||||
super.stopScan();
|
||||
removeOlderResults(getTimestampOfLastScan());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accountStatusChanged(ThingStatus status) {
|
||||
if (status == ThingStatus.ONLINE) {
|
||||
discoverDevices();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deactivate() {
|
||||
super.deactivate();
|
||||
bridge.removeAccountStatusListener(this);
|
||||
}
|
||||
|
||||
private void discoverDevices() {
|
||||
if (bridge.getThing().getStatus() != ThingStatus.ONLINE) {
|
||||
logger.debug("Evohome Gateway not online, scanning postponed");
|
||||
return;
|
||||
}
|
||||
|
||||
for (Location location : bridge.getEvohomeConfig()) {
|
||||
for (Gateway gateway : location.getGateways()) {
|
||||
for (TemperatureControlSystem tcs : gateway.getTemperatureControlSystems()) {
|
||||
addDisplayDiscoveryResult(location, tcs);
|
||||
for (Zone zone : tcs.getZones()) {
|
||||
addZoneDiscoveryResult(location, zone);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stopScan();
|
||||
}
|
||||
|
||||
private void addDisplayDiscoveryResult(Location location, TemperatureControlSystem tcs) {
|
||||
String id = tcs.getSystemId();
|
||||
String name = location.getLocationInfo().getName();
|
||||
ThingUID thingUID = new ThingUID(EvohomeBindingConstants.THING_TYPE_EVOHOME_DISPLAY, bridgeUID, id);
|
||||
|
||||
Map<String, Object> properties = new HashMap<>(2);
|
||||
properties.put(EvohomeBindingConstants.PROPERTY_ID, id);
|
||||
properties.put(EvohomeBindingConstants.PROPERTY_NAME, name);
|
||||
|
||||
addDiscoveredThing(thingUID, properties, name);
|
||||
}
|
||||
|
||||
private void addZoneDiscoveryResult(Location location, Zone zone) {
|
||||
String id = zone.getZoneId();
|
||||
String name = zone.getName() + " (" + location.getLocationInfo().getName() + ")";
|
||||
ThingUID thingUID = new ThingUID(EvohomeBindingConstants.THING_TYPE_EVOHOME_HEATING_ZONE, bridgeUID, id);
|
||||
|
||||
Map<String, Object> properties = new HashMap<>(2);
|
||||
properties.put(EvohomeBindingConstants.PROPERTY_ID, id);
|
||||
properties.put(EvohomeBindingConstants.PROPERTY_NAME, name);
|
||||
|
||||
addDiscoveredThing(thingUID, properties, name);
|
||||
}
|
||||
|
||||
private void addDiscoveredThing(ThingUID thingUID, Map<String, Object> properties, String displayLabel) {
|
||||
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties)
|
||||
.withBridge(bridgeUID).withLabel(displayLabel).build();
|
||||
thingDiscovered(discoveryResult);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.handler;
|
||||
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
|
||||
/**
|
||||
* Interface for a listener of the evohome account status
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public interface AccountStatusListener {
|
||||
|
||||
/**
|
||||
* Notifies the client that the status has changed.
|
||||
*
|
||||
* @param status The new status of the account thing
|
||||
*/
|
||||
public void accountStatusChanged(ThingStatus status);
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/**
|
||||
* 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.evohome.internal.handler;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.Locations;
|
||||
import org.openhab.binding.evohome.internal.configuration.EvohomeThingConfiguration;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
|
||||
/**
|
||||
* Base class for an evohome handler
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*/
|
||||
public abstract class BaseEvohomeHandler extends BaseThingHandler {
|
||||
private EvohomeThingConfiguration configuration;
|
||||
|
||||
public BaseEvohomeHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
configuration = getConfigAs(EvohomeThingConfiguration.class);
|
||||
checkConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
configuration = null;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
if (configuration != null) {
|
||||
return configuration.id;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configuration of the Thing
|
||||
*
|
||||
* @return The parsed configuration or null
|
||||
*/
|
||||
protected EvohomeThingConfiguration getEvohomeThingConfig() {
|
||||
return configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the bridge
|
||||
*
|
||||
* @return The evohome brdige
|
||||
*/
|
||||
protected EvohomeAccountBridgeHandler getEvohomeBridge() {
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge != null) {
|
||||
return (EvohomeAccountBridgeHandler) bridge.getHandler();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the evohome configuration from the bridge
|
||||
*
|
||||
* @return The current evohome configuration
|
||||
*/
|
||||
protected Locations getEvohomeConfig() {
|
||||
EvohomeAccountBridgeHandler bridge = getEvohomeBridge();
|
||||
if (bridge != null) {
|
||||
return bridge.getEvohomeConfig();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the evohome configuration from the bridge
|
||||
*
|
||||
* @return The current evohome configuration
|
||||
*/
|
||||
protected void requestUpdate() {
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge != null) {
|
||||
((EvohomeAccountBridgeHandler) bridge).getEvohomeConfig();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the status of the evohome thing when it changes
|
||||
*
|
||||
* @param newStatus The new status to update to
|
||||
*/
|
||||
protected void updateEvohomeThingStatus(ThingStatus newStatus) {
|
||||
updateEvohomeThingStatus(newStatus, ThingStatusDetail.NONE, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the status of the evohome thing when it changes
|
||||
*
|
||||
* @param newStatus The new status to update to
|
||||
* @param detail The status detail value
|
||||
* @param message The message to show with the status
|
||||
*/
|
||||
protected void updateEvohomeThingStatus(ThingStatus newStatus, ThingStatusDetail detail, String message) {
|
||||
// Prevent spamming the log file
|
||||
if (!newStatus.equals(getThing().getStatus())) {
|
||||
updateStatus(newStatus, detail, message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the configuration for validity, result is reflected in the status of the Thing
|
||||
*
|
||||
* @param configuration The configuration to check
|
||||
*/
|
||||
private void checkConfig() {
|
||||
if (configuration == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"Configuration is missing or corrupted");
|
||||
} else if (StringUtils.isEmpty(configuration.id)) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Id not configured");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
/**
|
||||
* 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.evohome.internal.handler;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.openhab.binding.evohome.internal.RunnableWithTimeout;
|
||||
import org.openhab.binding.evohome.internal.api.EvohomeApiClient;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.Gateway;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.GatewayStatus;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.Location;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.LocationStatus;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.Locations;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.LocationsStatus;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.TemperatureControlSystem;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.TemperatureControlSystemStatus;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.Zone;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.ZoneStatus;
|
||||
import org.openhab.binding.evohome.internal.configuration.EvohomeAccountConfiguration;
|
||||
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.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Provides the bridge for this binding. Controls the authentication sequence.
|
||||
* Manages the scheduler for getting updates from the API and updates the Things it contains.
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class EvohomeAccountBridgeHandler extends BaseBridgeHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(EvohomeAccountBridgeHandler.class);
|
||||
private final HttpClient httpClient;
|
||||
private EvohomeAccountConfiguration configuration;
|
||||
private EvohomeApiClient apiClient;
|
||||
private List<AccountStatusListener> listeners = new CopyOnWriteArrayList<>();
|
||||
|
||||
protected ScheduledFuture<?> refreshTask;
|
||||
|
||||
public EvohomeAccountBridgeHandler(Bridge thing, HttpClient httpClient) {
|
||||
super(thing);
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
configuration = getConfigAs(EvohomeAccountConfiguration.class);
|
||||
|
||||
if (checkConfig()) {
|
||||
try {
|
||||
apiClient = new EvohomeApiClient(configuration, this.httpClient);
|
||||
} catch (Exception e) {
|
||||
logger.error("Could not start API client", e);
|
||||
updateAccountStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"Could not create evohome API client");
|
||||
}
|
||||
|
||||
if (apiClient != null) {
|
||||
// Initialization can take a while, so kick it off on a separate thread
|
||||
scheduler.schedule(() -> {
|
||||
if (apiClient.login()) {
|
||||
if (checkInstallationInfoHasDuplicateIds(apiClient.getInstallationInfo())) {
|
||||
startRefreshTask();
|
||||
} else {
|
||||
updateAccountStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"System Information Sanity Check failed");
|
||||
}
|
||||
} else {
|
||||
updateAccountStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"Authentication failed");
|
||||
}
|
||||
}, 0, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
disposeRefreshTask();
|
||||
disposeApiClient();
|
||||
listeners.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
}
|
||||
|
||||
public Locations getEvohomeConfig() {
|
||||
return apiClient.getInstallationInfo();
|
||||
}
|
||||
|
||||
public LocationsStatus getEvohomeStatus() {
|
||||
return apiClient.getInstallationStatus();
|
||||
}
|
||||
|
||||
public void setTcsMode(String tcsId, String mode) {
|
||||
tryToCall(() -> apiClient.setTcsMode(tcsId, mode));
|
||||
}
|
||||
|
||||
public void setPermanentSetPoint(String zoneId, double doubleValue) {
|
||||
tryToCall(() -> apiClient.setHeatingZoneOverride(zoneId, doubleValue));
|
||||
}
|
||||
|
||||
public void cancelSetPointOverride(String zoneId) {
|
||||
tryToCall(() -> apiClient.cancelHeatingZoneOverride(zoneId));
|
||||
}
|
||||
|
||||
public void addAccountStatusListener(AccountStatusListener listener) {
|
||||
listeners.add(listener);
|
||||
listener.accountStatusChanged(getThing().getStatus());
|
||||
}
|
||||
|
||||
public void removeAccountStatusListener(AccountStatusListener listener) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
private void tryToCall(RunnableWithTimeout action) {
|
||||
try {
|
||||
action.run();
|
||||
} catch (TimeoutException e) {
|
||||
updateAccountStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"Timeout on executing request");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkInstallationInfoHasDuplicateIds(Locations locations) {
|
||||
boolean result = true;
|
||||
|
||||
// Make sure that there are no duplicate IDs
|
||||
Set<String> ids = new HashSet<>();
|
||||
|
||||
for (Location location : locations) {
|
||||
result &= ids.add(location.getLocationInfo().getLocationId());
|
||||
for (Gateway gateway : location.getGateways()) {
|
||||
result &= ids.add(gateway.getGatewayInfo().getGatewayId());
|
||||
for (TemperatureControlSystem tcs : gateway.getTemperatureControlSystems()) {
|
||||
result &= ids.add(tcs.getSystemId());
|
||||
for (Zone zone : tcs.getZones()) {
|
||||
result &= ids.add(zone.getZoneId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void disposeApiClient() {
|
||||
if (apiClient != null) {
|
||||
apiClient.logout();
|
||||
}
|
||||
apiClient = null;
|
||||
}
|
||||
|
||||
private void disposeRefreshTask() {
|
||||
if (refreshTask != null) {
|
||||
refreshTask.cancel(true);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkConfig() {
|
||||
String errorMessage = "";
|
||||
|
||||
if (configuration == null) {
|
||||
errorMessage = "Configuration is missing or corrupted";
|
||||
} else if (StringUtils.isEmpty(configuration.username)) {
|
||||
errorMessage = "Username not configured";
|
||||
} else if (StringUtils.isEmpty(configuration.password)) {
|
||||
errorMessage = "Password not configured";
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
updateAccountStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, errorMessage);
|
||||
return false;
|
||||
}
|
||||
|
||||
private void startRefreshTask() {
|
||||
disposeRefreshTask();
|
||||
|
||||
refreshTask = scheduler.scheduleWithFixedDelay(this::update, 0, configuration.refreshInterval,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
private void update() {
|
||||
try {
|
||||
apiClient.update();
|
||||
updateAccountStatus(ThingStatus.ONLINE);
|
||||
updateThings();
|
||||
} catch (Exception e) {
|
||||
updateAccountStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||
logger.debug("Failed to update installation status", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAccountStatus(ThingStatus newStatus) {
|
||||
updateAccountStatus(newStatus, ThingStatusDetail.NONE, null);
|
||||
}
|
||||
|
||||
private void updateAccountStatus(ThingStatus newStatus, ThingStatusDetail detail, String message) {
|
||||
// Prevent spamming the log file
|
||||
if (!newStatus.equals(getThing().getStatus())) {
|
||||
updateStatus(newStatus, detail, message);
|
||||
updateListeners(newStatus);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateListeners(ThingStatus status) {
|
||||
for (AccountStatusListener listener : listeners) {
|
||||
listener.accountStatusChanged(status);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateThings() {
|
||||
Map<String, TemperatureControlSystemStatus> idToTcsMap = new HashMap<>();
|
||||
Map<String, ZoneStatus> idToZoneMap = new HashMap<>();
|
||||
Map<String, GatewayStatus> tcsIdToGatewayMap = new HashMap<>();
|
||||
Map<String, String> zoneIdToTcsIdMap = new HashMap<>();
|
||||
Map<String, ThingStatus> idToTcsThingsStatusMap = new HashMap<>();
|
||||
|
||||
// First, create a lookup table
|
||||
for (LocationStatus location : apiClient.getInstallationStatus()) {
|
||||
for (GatewayStatus gateway : location.getGateways()) {
|
||||
for (TemperatureControlSystemStatus tcs : gateway.getTemperatureControlSystems()) {
|
||||
idToTcsMap.put(tcs.getSystemId(), tcs);
|
||||
tcsIdToGatewayMap.put(tcs.getSystemId(), gateway);
|
||||
for (ZoneStatus zone : tcs.getZones()) {
|
||||
idToZoneMap.put(zone.getZoneId(), zone);
|
||||
zoneIdToTcsIdMap.put(zone.getZoneId(), tcs.getSystemId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Then update the things by type, with pre-filtered info
|
||||
for (Thing handler : getThing().getThings()) {
|
||||
ThingHandler thingHandler = handler.getHandler();
|
||||
|
||||
if (thingHandler instanceof EvohomeTemperatureControlSystemHandler) {
|
||||
EvohomeTemperatureControlSystemHandler tcsHandler = (EvohomeTemperatureControlSystemHandler) thingHandler;
|
||||
tcsHandler.update(tcsIdToGatewayMap.get(tcsHandler.getId()), idToTcsMap.get(tcsHandler.getId()));
|
||||
idToTcsThingsStatusMap.put(tcsHandler.getId(), tcsHandler.getThing().getStatus());
|
||||
}
|
||||
if (thingHandler instanceof EvohomeHeatingZoneHandler) {
|
||||
EvohomeHeatingZoneHandler zoneHandler = (EvohomeHeatingZoneHandler) thingHandler;
|
||||
zoneHandler.update(idToTcsThingsStatusMap.get(zoneIdToTcsIdMap.get(zoneHandler.getId())),
|
||||
idToZoneMap.get(zoneHandler.getId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* 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.evohome.internal.handler;
|
||||
|
||||
import org.openhab.binding.evohome.internal.EvohomeBindingConstants;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.ZoneStatus;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
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.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
|
||||
/**
|
||||
* The {@link EvohomeHeatingZoneHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
* @author Neil Renaud - Working implementation
|
||||
* @author Jasper van Zuijlen - Refactor + Permanent Zone temperature setting
|
||||
*/
|
||||
public class EvohomeHeatingZoneHandler extends BaseEvohomeHandler {
|
||||
|
||||
private static final int CANCEL_SET_POINT_OVERRIDE = 0;
|
||||
private ThingStatus tcsStatus;
|
||||
private ZoneStatus zoneStatus;
|
||||
|
||||
public EvohomeHeatingZoneHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
}
|
||||
|
||||
public void update(ThingStatus tcsStatus, ZoneStatus zoneStatus) {
|
||||
this.tcsStatus = tcsStatus;
|
||||
this.zoneStatus = zoneStatus;
|
||||
|
||||
// Make the zone offline when the related display is offline
|
||||
// If the related display is not a thing, ignore this
|
||||
if (tcsStatus != null && tcsStatus.equals(ThingStatus.OFFLINE)) {
|
||||
updateEvohomeThingStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"Display Controller offline");
|
||||
} else if (zoneStatus == null) {
|
||||
updateEvohomeThingStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"Status not found, check the zone id");
|
||||
} else if (!handleActiveFaults(zoneStatus)) {
|
||||
updateEvohomeThingStatus(ThingStatus.ONLINE);
|
||||
|
||||
updateState(EvohomeBindingConstants.ZONE_TEMPERATURE_CHANNEL,
|
||||
new DecimalType(zoneStatus.getTemperature().getTemperature()));
|
||||
updateState(EvohomeBindingConstants.ZONE_SET_POINT_STATUS_CHANNEL,
|
||||
new StringType(zoneStatus.getHeatSetpoint().getSetpointMode()));
|
||||
updateState(EvohomeBindingConstants.ZONE_SET_POINT_CHANNEL,
|
||||
new DecimalType(zoneStatus.getHeatSetpoint().getTargetTemperature()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
if (command == RefreshType.REFRESH) {
|
||||
update(tcsStatus, zoneStatus);
|
||||
} else {
|
||||
EvohomeAccountBridgeHandler bridge = getEvohomeBridge();
|
||||
if (bridge != null) {
|
||||
String channelId = channelUID.getId();
|
||||
if (EvohomeBindingConstants.ZONE_SET_POINT_CHANNEL.equals(channelId)
|
||||
&& command instanceof DecimalType) {
|
||||
double newTemp = ((DecimalType) command).doubleValue();
|
||||
if (newTemp == CANCEL_SET_POINT_OVERRIDE) {
|
||||
bridge.cancelSetPointOverride(getEvohomeThingConfig().id);
|
||||
} else if (newTemp < 5) {
|
||||
newTemp = 5;
|
||||
}
|
||||
if (newTemp >= 5 && newTemp <= 35) {
|
||||
bridge.setPermanentSetPoint(getEvohomeThingConfig().id, newTemp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean handleActiveFaults(ZoneStatus zoneStatus) {
|
||||
if (zoneStatus.hasActiveFaults()) {
|
||||
updateEvohomeThingStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
zoneStatus.getActiveFault(0).getFaultType());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.handler;
|
||||
|
||||
import org.openhab.binding.evohome.internal.EvohomeBindingConstants;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.GatewayStatus;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.TemperatureControlSystemStatus;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
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.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
|
||||
/**
|
||||
* Handler for a temperature control system. Gets and sets global system mode.
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class EvohomeTemperatureControlSystemHandler extends BaseEvohomeHandler {
|
||||
private GatewayStatus gatewayStatus;
|
||||
private TemperatureControlSystemStatus tcsStatus;
|
||||
|
||||
public EvohomeTemperatureControlSystemHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
}
|
||||
|
||||
public void update(GatewayStatus gatewayStatus, TemperatureControlSystemStatus tcsStatus) {
|
||||
this.gatewayStatus = gatewayStatus;
|
||||
this.tcsStatus = tcsStatus;
|
||||
|
||||
if (tcsStatus == null || gatewayStatus == null) {
|
||||
updateEvohomeThingStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"Status not found, check the display id");
|
||||
} else if (!handleActiveFaults(gatewayStatus)) {
|
||||
updateEvohomeThingStatus(ThingStatus.ONLINE);
|
||||
updateState(EvohomeBindingConstants.DISPLAY_SYSTEM_MODE_CHANNEL,
|
||||
new StringType(tcsStatus.getMode().getMode()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
if (command == RefreshType.REFRESH) {
|
||||
update(gatewayStatus, tcsStatus);
|
||||
} else if (channelUID.getId().equals(EvohomeBindingConstants.DISPLAY_SYSTEM_MODE_CHANNEL)) {
|
||||
EvohomeAccountBridgeHandler bridge = getEvohomeBridge();
|
||||
if (bridge != null) {
|
||||
bridge.setTcsMode(getEvohomeThingConfig().id, command.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean handleActiveFaults(GatewayStatus gatewayStatus) {
|
||||
if (gatewayStatus.hasActiveFaults()) {
|
||||
updateEvohomeThingStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
gatewayStatus.getActiveFault(0).getFaultType());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<binding:binding id="evohome" 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>evohome Binding</name>
|
||||
<description>The evohome binding controls the Honeywell evohome system.</description>
|
||||
<author>Jasper van Zuijlen</author>
|
||||
</binding:binding>
|
||||
@@ -0,0 +1,11 @@
|
||||
# binding
|
||||
binding.evohome.name = Evohome binding
|
||||
binding.evohome.description = De evohome binding maakt het mogelijk om het Honeywell evohome systeem te besturen.
|
||||
|
||||
# thing types
|
||||
thing-type.evohome.display.label = Scherm
|
||||
thing-type.evohome.display.description = Dit Thing representeert het evohome bedieningsscherm
|
||||
|
||||
# channel types
|
||||
channel-type.evohome.systemMode.label = Systeemmodus
|
||||
channel-type.evohome.systemMode.description = Huidige systeemmodus
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="evohome"
|
||||
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">
|
||||
<!-- evohome Gateway Bridge -->
|
||||
<bridge-type id="account">
|
||||
<label>evohome Account</label>
|
||||
<description>The evohome account is used to connect to your Total Connect Comfort (TCC) using your TCC username and
|
||||
password.</description>
|
||||
<config-description>
|
||||
<parameter-group name="auth">
|
||||
<label>Authentication</label>
|
||||
<description>Contains the settings needed to authenticate against the TCC service.</description>
|
||||
</parameter-group>
|
||||
<parameter name="username" type="text" required="true" groupName="auth">
|
||||
<label>Username</label>
|
||||
<description>Your TCC Username</description>
|
||||
</parameter>
|
||||
<parameter name="password" type="text" required="true" groupName="auth">
|
||||
<label>Password</label>
|
||||
<description>Your TCC Password</description>
|
||||
<context>password</context>
|
||||
</parameter>
|
||||
<parameter name="refreshInterval" type="integer" required="false" min="15" max="3000">
|
||||
<label>Refresh Interval</label>
|
||||
<description>The refresh interval to poll TCC (in seconds).</description>
|
||||
<default>15</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</bridge-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="evohome"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<channel-type id="systemMode">
|
||||
<item-type>String</item-type>
|
||||
<label>System Mode</label>
|
||||
<description>Current system mode</description>
|
||||
<category>heating</category>
|
||||
<state pattern="%s">
|
||||
<options>
|
||||
<option value="Auto">Normal</option>
|
||||
<option value="AutoWithEco">Eco</option>
|
||||
<option value="Away">Away</option>
|
||||
<option value="DayOff">Day off</option>
|
||||
<option value="HeatingOff">Off</option>
|
||||
<option value="Custom">Custom</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="temperature">
|
||||
<item-type>Number</item-type>
|
||||
<label>Temperature</label>
|
||||
<description>Current zone temperature</description>
|
||||
<category>temperature</category>
|
||||
<state readOnly="true" pattern="%.1f °C">
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="setpoint">
|
||||
<item-type>Number</item-type>
|
||||
<label>Set Point</label>
|
||||
<description>Gets or sets the set point of this zone (0 cancels the override).</description>
|
||||
<category>heating</category>
|
||||
<state min="0.0" max="35.0" step="0.5" pattern="%.1f °C"/>
|
||||
</channel-type>
|
||||
<channel-type id="setpointstatus">
|
||||
<item-type>String</item-type>
|
||||
<label>Set Point Status</label>
|
||||
<description>Current set point status</description>
|
||||
<category>heating</category>
|
||||
<state pattern="%s" readOnly="true">
|
||||
<options>
|
||||
<option value="PermanentOverride">Permanent override</option>
|
||||
<option value="FollowSchedule">Follow schedule</option>
|
||||
<option value="TemporaryOverride">Temporary override</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="evohome"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<thing-type id="display" listed="false">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="account"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>evohome Display</label>
|
||||
<description>This represents the evohome control display.</description>
|
||||
<channels>
|
||||
<channel id="SystemMode" typeId="systemMode"/>
|
||||
</channels>
|
||||
<config-description>
|
||||
<parameter name="id" type="text" required="true" readOnly="true">
|
||||
<label>ID</label>
|
||||
<description>ID of the display</description>
|
||||
</parameter>
|
||||
<parameter name="name" type="text" required="false" readOnly="true">
|
||||
<label>Name</label>
|
||||
<description>Name of the display</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
<thing-type id="heatingzone" listed="false">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="account"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>evohome Heating Zone</label>
|
||||
<description>This represents the evohome Heating Zone.</description>
|
||||
<channels>
|
||||
<channel id="Temperature" typeId="temperature"/>
|
||||
<channel id="SetPointStatus" typeId="setpointstatus"/>
|
||||
<channel id="SetPoint" typeId="setpoint"/>
|
||||
</channels>
|
||||
<config-description>
|
||||
<parameter name="id" type="text" required="true" readOnly="true">
|
||||
<label>ID</label>
|
||||
<description>ID of the zone</description>
|
||||
</parameter>
|
||||
<parameter name="name" type="text" required="false" readOnly="true">
|
||||
<label>Name</label>
|
||||
<description>Name of the zone</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
</thing:thing-descriptions>
|
||||
Reference in New Issue
Block a user