mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[evohome] Add null annotation and minor refactoring (#13885)
Signed-off-by: Leo Siepel <leosiepel@gmail.com>
This commit is contained in:
parent
cb31f420ff
commit
dd21d92a80
@ -64,11 +64,12 @@ None
|
||||
|
||||
### 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. |
|
||||
| Channel Type ID | Item Type | Description |
|
||||
|-----------------|--------------------|----------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| Temperature | Number:Temperature | 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:Temperature | Allows for viewing and permanently overriding the temperature set point of the zone. Sending 0 cancels any active set point overrides. |
|
||||
|
|
||||
|
||||
## Full Example
|
||||
|
||||
@ -89,9 +90,9 @@ Bridge evohome:account:your_account_alias [ username="your_user_name", password=
|
||||
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" }
|
||||
Number:Temperature DemoZoneTemperature { channel="evohome:heatingzone:your_account_alias:your_zone_alias:Temperature" }
|
||||
String DemoZoneSetPointStatus { channel="evohome:heatingzone:your_account_alias:your_zone_alias:SetPointStatus" }
|
||||
Number:Temperature DemoZoneSetPoint { channel="evohome:heatingzone:your_account_alias:your_zone_alias:SetPoint" }
|
||||
```
|
||||
|
||||
### demo.sitemap
|
||||
|
@ -17,6 +17,7 @@ import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
@ -26,6 +27,7 @@ import org.openhab.core.thing.ThingTypeUID;
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
* @author Neil Renaud - Heating Zones
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EvohomeBindingConstants {
|
||||
|
||||
private static final String BINDING_ID = "evohome";
|
||||
|
@ -14,12 +14,15 @@ package org.openhab.binding.evohome.internal;
|
||||
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Provides an interface for a delegate that can throw a timeout
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface RunnableWithTimeout {
|
||||
|
||||
public abstract void run() throws TimeoutException;
|
||||
|
@ -18,13 +18,15 @@ import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.api.ContentResponse;
|
||||
import org.eclipse.jetty.client.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.openhab.binding.evohome.internal.api.models.v2.dto.response.Authentication;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -37,17 +39,17 @@ import com.google.gson.GsonBuilder;
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
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 final Gson gson = new GsonBuilder().create();
|
||||
|
||||
private Authentication authenticationData;
|
||||
private String applicationId;
|
||||
private @Nullable Authentication authenticationData;
|
||||
private @Nullable String applicationId;
|
||||
|
||||
public ApiAccess(HttpClient httpClient) {
|
||||
this.gson = new GsonBuilder().create();
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
@ -56,7 +58,7 @@ public class ApiAccess {
|
||||
*
|
||||
* @param authentication The authentication details to apply
|
||||
*/
|
||||
public void setAuthentication(Authentication authentication) {
|
||||
public void setAuthentication(@Nullable Authentication authentication) {
|
||||
authenticationData = authentication;
|
||||
}
|
||||
|
||||
@ -65,7 +67,7 @@ public class ApiAccess {
|
||||
*
|
||||
* @return The current authentication details
|
||||
*/
|
||||
public Authentication getAuthentication() {
|
||||
public @Nullable Authentication getAuthentication() {
|
||||
return authenticationData;
|
||||
}
|
||||
|
||||
@ -74,7 +76,7 @@ public class ApiAccess {
|
||||
*
|
||||
* @param applicationId The application id to apply
|
||||
*/
|
||||
public void setApplicationId(String applicationId) {
|
||||
public void setApplicationId(@Nullable String applicationId) {
|
||||
this.applicationId = applicationId;
|
||||
}
|
||||
|
||||
@ -89,18 +91,16 @@ public class ApiAccess {
|
||||
* @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;
|
||||
public @Nullable <TOut> TOut doRequest(HttpMethod method, String url, Map<String, String> headers,
|
||||
@Nullable String requestData, String contentType, @Nullable Class<TOut> outClass) throws TimeoutException {
|
||||
logger.debug("Requesting: [{}]", url);
|
||||
|
||||
@Nullable
|
||||
TOut retVal = null;
|
||||
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());
|
||||
}
|
||||
for (Map.Entry<String, String> header : headers.entrySet()) {
|
||||
request.header(header.getKey(), header.getValue());
|
||||
}
|
||||
|
||||
if (requestData != null) {
|
||||
@ -109,8 +109,8 @@ public class ApiAccess {
|
||||
|
||||
ContentResponse response = request.timeout(REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS).send();
|
||||
|
||||
logger.debug("Response: {}", response);
|
||||
logger.debug("\n{}\n{}", response.getHeaders(), response.getContentAsString());
|
||||
logger.trace("Response: {}", response);
|
||||
logger.trace("\n{}\n{}", response.getHeaders(), response.getContentAsString());
|
||||
|
||||
if ((response.getStatus() == HttpStatus.OK_200) || (response.getStatus() == HttpStatus.ACCEPTED_202)) {
|
||||
String reply = response.getContentAsString();
|
||||
@ -118,6 +118,10 @@ public class ApiAccess {
|
||||
if (outClass != null) {
|
||||
retVal = new Gson().fromJson(reply, outClass);
|
||||
}
|
||||
} else if ((response.getStatus() == HttpStatus.CREATED_201)) {
|
||||
// success nothing to return ignore
|
||||
} else {
|
||||
logger.debug("Request failed with unexpected response code {}", response.getStatus());
|
||||
}
|
||||
} catch (ExecutionException e) {
|
||||
logger.debug("Error in handling request: ", e);
|
||||
@ -125,7 +129,6 @@ public class ApiAccess {
|
||||
logger.debug("Handling request interrupted: ", e);
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@ -138,7 +141,7 @@ public class ApiAccess {
|
||||
* @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 {
|
||||
public @Nullable <TOut> TOut doAuthenticatedGet(String url, Class<TOut> outClass) throws TimeoutException {
|
||||
return doAuthenticatedRequest(HttpMethod.GET, url, null, outClass);
|
||||
}
|
||||
|
||||
@ -161,16 +164,16 @@ public class ApiAccess {
|
||||
* @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
|
||||
* @param requestContainer The object to use as JSON data for the request, can be null
|
||||
* @param outClass The type of the requested result, can be null
|
||||
* @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 {
|
||||
private @Nullable <TOut> TOut doRequest(HttpMethod method, String url, Map<String, String> headers,
|
||||
@Nullable Object requestContainer, @Nullable Class<TOut> outClass) throws TimeoutException {
|
||||
String json = null;
|
||||
if (requestContainer != null) {
|
||||
json = this.gson.toJson(requestContainer);
|
||||
json = gson.toJson(requestContainer);
|
||||
}
|
||||
|
||||
return doRequest(method, url, headers, json, "application/json", outClass);
|
||||
@ -188,17 +191,19 @@ public class ApiAccess {
|
||||
* @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<>();
|
||||
private @Nullable <TOut> TOut doAuthenticatedRequest(HttpMethod method, String url,
|
||||
@Nullable Object requestContainer, @Nullable Class<TOut> outClass) throws TimeoutException {
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
Authentication localAuthenticationData = authenticationData;
|
||||
String localApplicationId = applicationId;
|
||||
|
||||
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");
|
||||
if (localAuthenticationData != null) {
|
||||
headers.put("Authorization", "Bearer " + localAuthenticationData.getAccessToken());
|
||||
}
|
||||
if (localApplicationId != null) {
|
||||
headers.put("applicationId", localApplicationId);
|
||||
}
|
||||
headers.put("Accept", "application/json, application/xml, text/json, text/x-json, text/javascript, text/xml");
|
||||
|
||||
return doRequest(method, url, headers, requestContainer, outClass);
|
||||
}
|
||||
|
@ -19,18 +19,20 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.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.api.models.v2.dto.request.HeatSetPoint;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.dto.request.HeatSetPointBuilder;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.dto.request.Mode;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.dto.request.ModeBuilder;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.dto.response.Authentication;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.dto.response.Location;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.dto.response.LocationStatus;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.dto.response.Locations;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.dto.response.LocationsStatus;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.dto.response.UserAccount;
|
||||
import org.openhab.binding.evohome.internal.configuration.EvohomeAccountConfiguration;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -41,6 +43,7 @@ import org.slf4j.LoggerFactory;
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EvohomeApiClient {
|
||||
|
||||
private static final String APPLICATION_ID = "b013aa26-9724-4dbd-8897-048b9aada249";
|
||||
@ -52,8 +55,8 @@ public class EvohomeApiClient {
|
||||
private final ApiAccess apiAccess;
|
||||
|
||||
private Locations locations = new Locations();
|
||||
private UserAccount useraccount;
|
||||
private LocationsStatus locationsStatus;
|
||||
private @Nullable UserAccount useraccount;
|
||||
private @Nullable LocationsStatus locationsStatus;
|
||||
|
||||
/**
|
||||
* Creates a new API client based on the V2 API interface
|
||||
@ -72,7 +75,7 @@ public class EvohomeApiClient {
|
||||
public void close() {
|
||||
apiAccess.setAuthentication(null);
|
||||
useraccount = null;
|
||||
locations = null;
|
||||
locations = new Locations();
|
||||
locationsStatus = null;
|
||||
}
|
||||
|
||||
@ -113,7 +116,7 @@ public class EvohomeApiClient {
|
||||
return locations;
|
||||
}
|
||||
|
||||
public LocationsStatus getInstallationStatus() {
|
||||
public @Nullable LocationsStatus getInstallationStatus() {
|
||||
return locationsStatus;
|
||||
}
|
||||
|
||||
@ -139,33 +142,33 @@ public class EvohomeApiClient {
|
||||
apiAccess.doAuthenticatedPut(url, heatSetPoint);
|
||||
}
|
||||
|
||||
private UserAccount requestUserAccount() throws TimeoutException {
|
||||
private @Nullable 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) {
|
||||
Locations locations = null;
|
||||
UserAccount localAccount = useraccount;
|
||||
if (localAccount != null) {
|
||||
String url = EvohomeApiConstants.URL_V2_BASE + EvohomeApiConstants.URL_V2_INSTALLATION_INFO;
|
||||
url = String.format(url, useraccount.getUserId());
|
||||
url = String.format(url, localAccount.getUserId());
|
||||
|
||||
locations = apiAccess.doAuthenticatedGet(url, Locations.class);
|
||||
}
|
||||
return locations;
|
||||
return locations != null ? locations : new 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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -12,13 +12,17 @@
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Exception for errors from the API Client.
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EvohomeApiClientException extends Exception {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public EvohomeApiClientException() {
|
||||
}
|
||||
|
@ -12,12 +12,15 @@
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* List of evohome API constants
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EvohomeApiConstants {
|
||||
public static final String URL_V2_AUTH = "https://tccna.honeywell.com/Auth/OAuth/Token";
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.request;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.request;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
@ -43,12 +43,15 @@ public class HeatSetPoint {
|
||||
timeUntil = null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@SerializedName("heatSetpointValue")
|
||||
private double heatSetpointValue;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@SerializedName("setpointMode")
|
||||
private String setpointMode;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@SerializedName("timeUntil")
|
||||
private String timeUntil;
|
||||
}
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.request;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.request;
|
||||
|
||||
/**
|
||||
* Builder for heat set point API requests
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.request;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.request;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
@ -34,12 +34,15 @@ public class Mode {
|
||||
permanent = false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@SerializedName("systemMode")
|
||||
private String systemMode;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@SerializedName("timeUntil")
|
||||
private String timeUntil;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@SerializedName("permanent")
|
||||
private boolean permanent;
|
||||
}
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.request;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.request;
|
||||
|
||||
/**
|
||||
* Builder for mode API requests
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.request;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.request;
|
||||
|
||||
/**
|
||||
* Builder for API requests
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.request;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.request;
|
||||
|
||||
/**
|
||||
* Builder for timed API requests
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.response;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.response;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.response;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.response;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.response;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.response;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@ -21,5 +21,5 @@ import java.util.ArrayList;
|
||||
*
|
||||
*/
|
||||
public class Locations extends ArrayList<Location> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.response;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@ -21,5 +21,5 @@ import java.util.ArrayList;
|
||||
*
|
||||
*/
|
||||
public class LocationsStatus extends ArrayList<LocationStatus> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.response;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.response;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.response;
|
||||
package org.openhab.binding.evohome.internal.api.models.v2.dto.response;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -12,15 +12,18 @@
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.configuration;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Contains the configuration of the binding.
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EvohomeAccountConfiguration {
|
||||
public String username;
|
||||
public String password;
|
||||
public String applicationId;
|
||||
public String username = "";
|
||||
public String password = "";
|
||||
public String applicationId = "";
|
||||
public int refreshInterval;
|
||||
}
|
||||
|
@ -12,13 +12,16 @@
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.configuration;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Contains the configuration of the binding.
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EvohomeTemperatureControlSystemConfiguration {
|
||||
public String id;
|
||||
public String name;
|
||||
public String id = "";
|
||||
public String name = "";
|
||||
}
|
||||
|
@ -12,13 +12,16 @@
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.configuration;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Contains the common configuration definition of an evohome Thing
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EvohomeThingConfiguration {
|
||||
public String id;
|
||||
public String name;
|
||||
public String id = "";
|
||||
public String name = "";
|
||||
}
|
||||
|
@ -15,11 +15,13 @@ package org.openhab.binding.evohome.internal.discovery;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
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.api.models.v2.dto.response.Gateway;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.dto.response.Location;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.dto.response.Locations;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.dto.response.TemperatureControlSystem;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.dto.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;
|
||||
@ -37,6 +39,7 @@ import org.slf4j.LoggerFactory;
|
||||
* @author Jasper van Zuijlen - Background discovery
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EvohomeDiscoveryService extends AbstractDiscoveryService implements AccountStatusListener {
|
||||
private final Logger logger = LoggerFactory.getLogger(EvohomeDiscoveryService.class);
|
||||
private static final int TIMEOUT = 5;
|
||||
@ -86,18 +89,29 @@ public class EvohomeDiscoveryService extends AbstractDiscoveryService implements
|
||||
logger.debug("Evohome Gateway not online, scanning postponed");
|
||||
return;
|
||||
}
|
||||
Locations localEvohomeConfig = bridge.getEvohomeConfig();
|
||||
|
||||
for (Location location : bridge.getEvohomeConfig()) {
|
||||
if (localEvohomeConfig == null) {
|
||||
return;
|
||||
}
|
||||
for (Location location : localEvohomeConfig) {
|
||||
if (location == null) {
|
||||
continue;
|
||||
}
|
||||
for (Gateway gateway : location.getGateways()) {
|
||||
for (TemperatureControlSystem tcs : gateway.getTemperatureControlSystems()) {
|
||||
if (tcs == null) {
|
||||
continue;
|
||||
}
|
||||
addDisplayDiscoveryResult(location, tcs);
|
||||
for (Zone zone : tcs.getZones()) {
|
||||
addZoneDiscoveryResult(location, zone);
|
||||
if (zone != null) {
|
||||
addZoneDiscoveryResult(location, zone);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stopScan();
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.handler;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
|
||||
/**
|
||||
@ -20,6 +21,7 @@ import org.openhab.core.thing.ThingStatus;
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface AccountStatusListener {
|
||||
|
||||
/**
|
||||
|
@ -12,7 +12,9 @@
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.handler;
|
||||
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.response.Locations;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.dto.response.Locations;
|
||||
import org.openhab.binding.evohome.internal.configuration.EvohomeThingConfiguration;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.Thing;
|
||||
@ -25,8 +27,9 @@ import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
*
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class BaseEvohomeHandler extends BaseThingHandler {
|
||||
private EvohomeThingConfiguration configuration;
|
||||
private EvohomeThingConfiguration configuration = new EvohomeThingConfiguration();
|
||||
|
||||
public BaseEvohomeHandler(Thing thing) {
|
||||
super(thing);
|
||||
@ -40,14 +43,10 @@ public abstract class BaseEvohomeHandler extends BaseThingHandler {
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
configuration = null;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
if (configuration != null) {
|
||||
return configuration.id;
|
||||
}
|
||||
return null;
|
||||
return configuration.id;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -64,7 +63,7 @@ public abstract class BaseEvohomeHandler extends BaseThingHandler {
|
||||
*
|
||||
* @return The evohome brdige
|
||||
*/
|
||||
protected EvohomeAccountBridgeHandler getEvohomeBridge() {
|
||||
protected @Nullable EvohomeAccountBridgeHandler getEvohomeBridge() {
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge != null) {
|
||||
return (EvohomeAccountBridgeHandler) bridge.getHandler();
|
||||
@ -78,10 +77,10 @@ public abstract class BaseEvohomeHandler extends BaseThingHandler {
|
||||
*
|
||||
* @return The current evohome configuration
|
||||
*/
|
||||
protected Locations getEvohomeConfig() {
|
||||
EvohomeAccountBridgeHandler bridge = getEvohomeBridge();
|
||||
if (bridge != null) {
|
||||
return bridge.getEvohomeConfig();
|
||||
protected @Nullable Locations getEvohomeConfig() {
|
||||
EvohomeAccountBridgeHandler bridgeAccountHandler = getEvohomeBridge();
|
||||
if (bridgeAccountHandler != null) {
|
||||
return bridgeAccountHandler.getEvohomeConfig();
|
||||
}
|
||||
|
||||
return null;
|
||||
@ -115,7 +114,7 @@ public abstract class BaseEvohomeHandler extends BaseThingHandler {
|
||||
* @param detail The status detail value
|
||||
* @param message The message to show with the status
|
||||
*/
|
||||
protected void updateEvohomeThingStatus(ThingStatus newStatus, ThingStatusDetail detail, String message) {
|
||||
protected void updateEvohomeThingStatus(ThingStatus newStatus, ThingStatusDetail detail, @Nullable String message) {
|
||||
// Prevent spamming the log file
|
||||
if (!newStatus.equals(getThing().getStatus())) {
|
||||
updateStatus(newStatus, detail, message);
|
||||
@ -128,10 +127,7 @@ public abstract class BaseEvohomeHandler extends BaseThingHandler {
|
||||
* @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 (configuration.id == null || configuration.id.isEmpty()) {
|
||||
if (configuration.id.isEmpty()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Id not configured");
|
||||
}
|
||||
}
|
||||
|
@ -22,19 +22,21 @@ import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.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.api.models.v2.dto.response.Gateway;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.dto.response.GatewayStatus;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.dto.response.Location;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.dto.response.LocationStatus;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.dto.response.Locations;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.dto.response.LocationsStatus;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.dto.response.TemperatureControlSystem;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.dto.response.TemperatureControlSystemStatus;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.dto.response.Zone;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.dto.response.ZoneStatus;
|
||||
import org.openhab.binding.evohome.internal.configuration.EvohomeAccountConfiguration;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
@ -54,15 +56,16 @@ import org.slf4j.LoggerFactory;
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EvohomeAccountBridgeHandler extends BaseBridgeHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(EvohomeAccountBridgeHandler.class);
|
||||
private final HttpClient httpClient;
|
||||
private EvohomeAccountConfiguration configuration;
|
||||
private EvohomeApiClient apiClient;
|
||||
private EvohomeAccountConfiguration configuration = new EvohomeAccountConfiguration();
|
||||
private @Nullable EvohomeApiClient apiClient;
|
||||
private List<AccountStatusListener> listeners = new CopyOnWriteArrayList<>();
|
||||
|
||||
protected ScheduledFuture<?> refreshTask;
|
||||
protected @Nullable ScheduledFuture<?> refreshTask;
|
||||
|
||||
public EvohomeAccountBridgeHandler(Bridge thing, HttpClient httpClient) {
|
||||
super(thing);
|
||||
@ -73,13 +76,14 @@ public class EvohomeAccountBridgeHandler extends BaseBridgeHandler {
|
||||
public void initialize() {
|
||||
configuration = getConfigAs(EvohomeAccountConfiguration.class);
|
||||
|
||||
if (checkConfig()) {
|
||||
if (checkConfig(configuration)) {
|
||||
apiClient = new EvohomeApiClient(configuration, this.httpClient);
|
||||
|
||||
// Initialization can take a while, so kick it off on a separate thread
|
||||
scheduler.schedule(() -> {
|
||||
if (apiClient.login()) {
|
||||
if (checkInstallationInfoHasDuplicateIds(apiClient.getInstallationInfo())) {
|
||||
EvohomeApiClient localApiCLient = apiClient;
|
||||
if (localApiCLient != null && localApiCLient.login()) {
|
||||
if (checkInstallationInfoHasDuplicateIds(localApiCLient.getInstallationInfo())) {
|
||||
startRefreshTask();
|
||||
} else {
|
||||
updateAccountStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
@ -104,24 +108,41 @@ public class EvohomeAccountBridgeHandler extends BaseBridgeHandler {
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
}
|
||||
|
||||
public Locations getEvohomeConfig() {
|
||||
return apiClient.getInstallationInfo();
|
||||
public @Nullable Locations getEvohomeConfig() {
|
||||
EvohomeApiClient localApiCLient = apiClient;
|
||||
if (localApiCLient != null) {
|
||||
return localApiCLient.getInstallationInfo();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public LocationsStatus getEvohomeStatus() {
|
||||
return apiClient.getInstallationStatus();
|
||||
public @Nullable LocationsStatus getEvohomeStatus() {
|
||||
EvohomeApiClient localApiCLient = apiClient;
|
||||
if (localApiCLient != null) {
|
||||
return localApiCLient.getInstallationStatus();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setTcsMode(String tcsId, String mode) {
|
||||
tryToCall(() -> apiClient.setTcsMode(tcsId, mode));
|
||||
EvohomeApiClient localApiCLient = apiClient;
|
||||
if (localApiCLient != null) {
|
||||
tryToCall(() -> localApiCLient.setTcsMode(tcsId, mode));
|
||||
}
|
||||
}
|
||||
|
||||
public void setPermanentSetPoint(String zoneId, double doubleValue) {
|
||||
tryToCall(() -> apiClient.setHeatingZoneOverride(zoneId, doubleValue));
|
||||
EvohomeApiClient localApiCLient = apiClient;
|
||||
if (localApiCLient != null) {
|
||||
tryToCall(() -> localApiCLient.setHeatingZoneOverride(zoneId, doubleValue));
|
||||
}
|
||||
}
|
||||
|
||||
public void cancelSetPointOverride(String zoneId) {
|
||||
tryToCall(() -> apiClient.cancelHeatingZoneOverride(zoneId));
|
||||
EvohomeApiClient localApiCLient = apiClient;
|
||||
if (localApiCLient != null) {
|
||||
tryToCall(() -> localApiCLient.cancelHeatingZoneOverride(zoneId));
|
||||
}
|
||||
}
|
||||
|
||||
public void addAccountStatusListener(AccountStatusListener listener) {
|
||||
@ -164,26 +185,27 @@ public class EvohomeAccountBridgeHandler extends BaseBridgeHandler {
|
||||
}
|
||||
|
||||
private void disposeApiClient() {
|
||||
if (apiClient != null) {
|
||||
apiClient.logout();
|
||||
EvohomeApiClient localApiClient = apiClient;
|
||||
if (localApiClient != null) {
|
||||
localApiClient.logout();
|
||||
this.apiClient = null;
|
||||
}
|
||||
apiClient = null;
|
||||
}
|
||||
|
||||
private void disposeRefreshTask() {
|
||||
if (refreshTask != null) {
|
||||
refreshTask.cancel(true);
|
||||
ScheduledFuture<?> localRefreshTask = refreshTask;
|
||||
if (localRefreshTask != null) {
|
||||
localRefreshTask.cancel(true);
|
||||
this.refreshTask = null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkConfig() {
|
||||
private boolean checkConfig(EvohomeAccountConfiguration configuration) {
|
||||
String errorMessage = "";
|
||||
|
||||
if (configuration == null) {
|
||||
errorMessage = "Configuration is missing or corrupted";
|
||||
} else if (configuration.username == null || configuration.username.isEmpty()) {
|
||||
if (configuration.username.isBlank()) {
|
||||
errorMessage = "Username not configured";
|
||||
} else if (configuration.password == null || configuration.password.isEmpty()) {
|
||||
} else if (configuration.password.isBlank()) {
|
||||
errorMessage = "Password not configured";
|
||||
} else {
|
||||
return true;
|
||||
@ -202,7 +224,10 @@ public class EvohomeAccountBridgeHandler extends BaseBridgeHandler {
|
||||
|
||||
private void update() {
|
||||
try {
|
||||
apiClient.update();
|
||||
EvohomeApiClient localApiCLient = apiClient;
|
||||
if (localApiCLient != null) {
|
||||
localApiCLient.update();
|
||||
}
|
||||
updateAccountStatus(ThingStatus.ONLINE);
|
||||
updateThings();
|
||||
} catch (Exception e) {
|
||||
@ -215,7 +240,7 @@ public class EvohomeAccountBridgeHandler extends BaseBridgeHandler {
|
||||
updateAccountStatus(newStatus, ThingStatusDetail.NONE, null);
|
||||
}
|
||||
|
||||
private void updateAccountStatus(ThingStatus newStatus, ThingStatusDetail detail, String message) {
|
||||
private void updateAccountStatus(ThingStatus newStatus, ThingStatusDetail detail, @Nullable String message) {
|
||||
// Prevent spamming the log file
|
||||
if (!newStatus.equals(getThing().getStatus())) {
|
||||
updateStatus(newStatus, detail, message);
|
||||
@ -236,15 +261,32 @@ public class EvohomeAccountBridgeHandler extends BaseBridgeHandler {
|
||||
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());
|
||||
EvohomeApiClient localApiClient = apiClient;
|
||||
if (localApiClient != null) {
|
||||
// First, create a lookup table
|
||||
LocationsStatus localLocationsStatus = localApiClient.getInstallationStatus();
|
||||
if (localLocationsStatus != null) {
|
||||
for (LocationStatus location : localLocationsStatus) {
|
||||
for (GatewayStatus gateway : location.getGateways()) {
|
||||
if (gateway == null) {
|
||||
continue;
|
||||
}
|
||||
for (TemperatureControlSystemStatus tcs : gateway.getTemperatureControlSystems()) {
|
||||
String systemId = tcs.getSystemId();
|
||||
if (systemId != null) {
|
||||
idToTcsMap.put(systemId, tcs);
|
||||
tcsIdToGatewayMap.put(systemId, gateway);
|
||||
}
|
||||
for (ZoneStatus zone : tcs.getZones()) {
|
||||
String zoneId = zone.getZoneId();
|
||||
if (zoneId != null) {
|
||||
idToZoneMap.put(zoneId, zone);
|
||||
if (systemId != null) {
|
||||
zoneIdToTcsIdMap.put(zoneId, systemId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,10 +12,15 @@
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.handler;
|
||||
|
||||
import javax.measure.quantity.Temperature;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
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.binding.evohome.internal.api.models.v2.dto.response.ZoneStatus;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
@ -30,12 +35,14 @@ import org.openhab.core.types.RefreshType;
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
* @author Neil Renaud - Working implementation
|
||||
* @author Jasper van Zuijlen - Refactor + Permanent Zone temperature setting
|
||||
* @author Leo Siepel - Add UoM
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EvohomeHeatingZoneHandler extends BaseEvohomeHandler {
|
||||
|
||||
private static final int CANCEL_SET_POINT_OVERRIDE = 0;
|
||||
private ThingStatus tcsStatus;
|
||||
private ZoneStatus zoneStatus;
|
||||
private @Nullable ThingStatus tcsStatus;
|
||||
private @Nullable ZoneStatus zoneStatus;
|
||||
|
||||
public EvohomeHeatingZoneHandler(Thing thing) {
|
||||
super(thing);
|
||||
@ -46,7 +53,7 @@ public class EvohomeHeatingZoneHandler extends BaseEvohomeHandler {
|
||||
super.initialize();
|
||||
}
|
||||
|
||||
public void update(ThingStatus tcsStatus, ZoneStatus zoneStatus) {
|
||||
public void update(@Nullable ThingStatus tcsStatus, @Nullable ZoneStatus zoneStatus) {
|
||||
this.tcsStatus = tcsStatus;
|
||||
this.zoneStatus = zoneStatus;
|
||||
|
||||
@ -62,11 +69,11 @@ public class EvohomeHeatingZoneHandler extends BaseEvohomeHandler {
|
||||
updateEvohomeThingStatus(ThingStatus.ONLINE);
|
||||
|
||||
updateState(EvohomeBindingConstants.ZONE_TEMPERATURE_CHANNEL,
|
||||
new DecimalType(zoneStatus.getTemperature().getTemperature()));
|
||||
new QuantityType<Temperature>(zoneStatus.getTemperature().getTemperature(), SIUnits.CELSIUS));
|
||||
updateState(EvohomeBindingConstants.ZONE_SET_POINT_STATUS_CHANNEL,
|
||||
new StringType(zoneStatus.getHeatSetpoint().getSetpointMode()));
|
||||
updateState(EvohomeBindingConstants.ZONE_SET_POINT_CHANNEL,
|
||||
new DecimalType(zoneStatus.getHeatSetpoint().getTargetTemperature()));
|
||||
updateState(EvohomeBindingConstants.ZONE_SET_POINT_CHANNEL, new QuantityType<Temperature>(
|
||||
zoneStatus.getHeatSetpoint().getTargetTemperature(), SIUnits.CELSIUS));
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,16 +85,19 @@ public class EvohomeHeatingZoneHandler extends BaseEvohomeHandler {
|
||||
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);
|
||||
if (EvohomeBindingConstants.ZONE_SET_POINT_CHANNEL.equals(channelId)) {
|
||||
if (command instanceof QuantityType) {
|
||||
QuantityType<?> state = ((QuantityType<?>) command).toUnit(SIUnits.CELSIUS);
|
||||
double newTempInCelsius = state.doubleValue();
|
||||
|
||||
if (newTempInCelsius == CANCEL_SET_POINT_OVERRIDE) {
|
||||
bridge.cancelSetPointOverride(getEvohomeThingConfig().id);
|
||||
} else if (newTempInCelsius < 5) {
|
||||
newTempInCelsius = 5;
|
||||
}
|
||||
if (newTempInCelsius >= 5 && newTempInCelsius <= 35) {
|
||||
bridge.setPermanentSetPoint(getEvohomeThingConfig().id, newTempInCelsius);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,9 +12,11 @@
|
||||
*/
|
||||
package org.openhab.binding.evohome.internal.handler;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
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.binding.evohome.internal.api.models.v2.dto.response.GatewayStatus;
|
||||
import org.openhab.binding.evohome.internal.api.models.v2.dto.response.TemperatureControlSystemStatus;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
@ -29,9 +31,10 @@ import org.openhab.core.types.RefreshType;
|
||||
* @author Jasper van Zuijlen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EvohomeTemperatureControlSystemHandler extends BaseEvohomeHandler {
|
||||
private GatewayStatus gatewayStatus;
|
||||
private TemperatureControlSystemStatus tcsStatus;
|
||||
private @Nullable GatewayStatus gatewayStatus;
|
||||
private @Nullable TemperatureControlSystemStatus tcsStatus;
|
||||
|
||||
public EvohomeTemperatureControlSystemHandler(Thing thing) {
|
||||
super(thing);
|
||||
@ -42,7 +45,7 @@ public class EvohomeTemperatureControlSystemHandler extends BaseEvohomeHandler {
|
||||
super.initialize();
|
||||
}
|
||||
|
||||
public void update(GatewayStatus gatewayStatus, TemperatureControlSystemStatus tcsStatus) {
|
||||
public void update(@Nullable GatewayStatus gatewayStatus, @Nullable TemperatureControlSystemStatus tcsStatus) {
|
||||
this.gatewayStatus = gatewayStatus;
|
||||
this.tcsStatus = tcsStatus;
|
||||
|
||||
|
@ -20,19 +20,27 @@
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="temperature">
|
||||
<item-type>Number</item-type>
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Temperature</label>
|
||||
<description>Current zone temperature</description>
|
||||
<category>temperature</category>
|
||||
<state readOnly="true" pattern="%.1f °C">
|
||||
<tags>
|
||||
<tag>Measurement</tag>
|
||||
<tag>Temperature</tag>
|
||||
</tags>
|
||||
<state readOnly="true" pattern="%.1f %unit%">
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="setpoint">
|
||||
<item-type>Number</item-type>
|
||||
<item-type>Number:Temperature</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"/>
|
||||
<tags>
|
||||
<tag>Setpoint</tag>
|
||||
<tag>Temperature</tag>
|
||||
</tags>
|
||||
<state min="0.0" max="35.0" step="0.5" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="setpointstatus">
|
||||
<item-type>String</item-type>
|
||||
|
Loading…
Reference in New Issue
Block a user