[verisure] Adapted to new authentication process and support for non MFA activated user. (#11228) (#11265)
* [verisure] Adapted to new authentication process and support for non MFA activated user. (#11228) Signed-off-by: Jan Gustafsson <jannegpriv@gmail.com> * Updated after code review. Signed-off-by: Jan Gustafsson <jannegpriv@gmail.com> * Updated after code review. Signed-off-by: Jan Gustafsson <jannegpriv@gmail.com> * Updated after code review. Signed-off-by: Jan Gustafsson <jannegpriv@gmail.com>
This commit is contained in:
parent
ef07105b8c
commit
18d26aa821
|
@ -1,12 +1,9 @@
|
|||
# Verisure Binding
|
||||
|
||||
This is an openHAB binding for Verisure Alarm System, by Securitas Direct.
|
||||
This is an openHAB binding for Verisure Smart Alarms by Verisure Securitas.
|
||||
|
||||
This binding uses the rest API behind the Verisure My Pages:
|
||||
This binding uses a rest API used by the [Verisure My Pages webpage](https://mypages.verisure.com/login.html)
|
||||
|
||||
https://mypages.verisure.com/login.html.
|
||||
|
||||
Be aware that Verisure don't approve if you update to often, I have gotten no complaints running with a 10 minutes update interval, but officially you should use 30 minutes.
|
||||
|
||||
|
||||
## Supported Things
|
||||
|
@ -19,7 +16,7 @@ This binding supports the following thing types:
|
|||
- Water Detector (climate)
|
||||
- Siren (climate)
|
||||
- Night Control
|
||||
- Yaleman SmartLock
|
||||
- Yaleman Doorman SmartLock
|
||||
- SmartPlug
|
||||
- Door/Window Status
|
||||
- User Presence Status
|
||||
|
@ -31,11 +28,14 @@ This binding supports the following thing types:
|
|||
|
||||
## Binding Configuration
|
||||
|
||||
You will have to configure the bridge with username and password, these must be the same credentials as used when logging into https://mypages.verisure.com.
|
||||
You will have to configure the bridge with username and password of a pre-defined user on [Verisure page](https://mypages.verisure.com) that has not activated Multi Factor Authentication (MFA/2FA).
|
||||
|
||||
Verisure allows you to have more than one user so the suggestion is to use a specific user for automation that has MFA/2FA deactivated.
|
||||
**NOTE:** To be able to have full control over all SmartLock/alarm functionality, the user also needs to have Administrator rights.
|
||||
|
||||
You must also configure pin-code(s) to be able to lock/unlock the SmartLock(s) and arm/unarm the Alarm(s).
|
||||
|
||||
You must also configure your pin-code(s) to be able to lock/unlock the SmartLock(s) and arm/unarm the Alarm(s).
|
||||
|
||||
**NOTE:** To be able to have full control over all SmartLock functionality, the user has to have Administrator rights.
|
||||
|
||||
## Discovery
|
||||
|
||||
|
@ -327,6 +327,7 @@ The following channels are supported:
|
|||
* `deviceId` - Device Id
|
||||
* Since Event Log lacks a Verisure ID, the following naming convention is used for Event Log on site id 123456789: 'el123456789'. Installation ID can be found using DEBUG log settings.
|
||||
|
||||
|
||||
#### Channels
|
||||
|
||||
The following channels are supported:
|
||||
|
|
|
@ -131,22 +131,23 @@ public class VerisureBindingConstants {
|
|||
// REST URI constants
|
||||
public static final String USERNAME = "username";
|
||||
public static final String PASSWORD = "password";
|
||||
public static final String BASEURL = "https://mypages.verisure.com";
|
||||
public static final String LOGON_SUF = BASEURL + "/j_spring_security_check?locale=en_GB";
|
||||
public static final String ALARM_COMMAND = BASEURL + "/remotecontrol/armstatechange.cmd";
|
||||
public static final String SMARTLOCK_LOCK_COMMAND = BASEURL + "/remotecontrol/lockunlock.cmd";
|
||||
public static final String SMARTLOCK_SET_COMMAND = BASEURL + "/overview/setdoorlock.cmd";
|
||||
public static final String SMARTLOCK_AUTORELOCK_COMMAND = BASEURL + "/settings/setautorelock.cmd";
|
||||
public static final String SMARTLOCK_VOLUME_COMMAND = BASEURL + "/settings/setvolume.cmd";
|
||||
public static final String BASE_URL = "https://mypages.verisure.com";
|
||||
public static final String LOGON_SUF = BASE_URL + "/j_spring_security_check?locale=en_GB";
|
||||
public static final String ALARM_COMMAND = BASE_URL + "/remotecontrol/armstatechange.cmd";
|
||||
public static final String SMARTLOCK_LOCK_COMMAND = BASE_URL + "/remotecontrol/lockunlock.cmd";
|
||||
public static final String SMARTLOCK_SET_COMMAND = BASE_URL + "/overview/setdoorlock.cmd";
|
||||
public static final String SMARTLOCK_AUTORELOCK_COMMAND = BASE_URL + "/settings/setautorelock.cmd";
|
||||
public static final String SMARTLOCK_VOLUME_COMMAND = BASE_URL + "/settings/setvolume.cmd";
|
||||
|
||||
public static final String SMARTPLUG_COMMAND = BASEURL + "/settings/smartplug/onoffplug.cmd";
|
||||
public static final String SMARTPLUG_COMMAND = BASE_URL + "/settings/smartplug/onoffplug.cmd";
|
||||
public static final String START_REDIRECT = "/uk/start.html";
|
||||
public static final String START_SUF = BASEURL + START_REDIRECT;
|
||||
public static final String START_SUF = BASE_URL + START_REDIRECT;
|
||||
|
||||
// GraphQL constants
|
||||
public static final String STATUS = BASEURL + "/uk/status";
|
||||
public static final String SETTINGS = BASEURL + "/uk/settings.html?giid=";
|
||||
public static final String SET_INSTALLATION = BASEURL + "/setinstallation?giid=";
|
||||
public static final String STATUS = BASE_URL + "/uk/status";
|
||||
public static final String EXTEND = BASE_URL + "/session/extend";
|
||||
public static final String SETTINGS = BASE_URL + "/uk/settings.html?giid=";
|
||||
public static final String SET_INSTALLATION = BASE_URL + "/setinstallation?giid=";
|
||||
public static final String BASEURL_API = "https://m-api02.verisure.com";
|
||||
public static final String START_GRAPHQL = "/graphql";
|
||||
public static final String AUTH_TOKEN = "/auth/token";
|
||||
|
|
|
@ -23,8 +23,8 @@ import org.eclipse.jdt.annotation.Nullable;
|
|||
*/
|
||||
@NonNullByDefault
|
||||
public class VerisureBridgeConfiguration {
|
||||
public @Nullable String username;
|
||||
public @Nullable String password;
|
||||
public int refresh;
|
||||
public String username = "";
|
||||
public String password = "";
|
||||
public int refresh = 600;
|
||||
public @Nullable String pin;
|
||||
}
|
||||
|
|
|
@ -17,9 +17,12 @@ import static org.openhab.binding.verisure.internal.VerisureBindingConstants.*;
|
|||
import java.math.BigDecimal;
|
||||
import java.net.CookieStore;
|
||||
import java.net.HttpCookie;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -86,24 +89,30 @@ public class VerisureSession {
|
|||
private int apiServerInUseIndex = 0;
|
||||
private int numberOfEvents = 15;
|
||||
private static final String USER_NAME = "username";
|
||||
private static final String PASSWORD_NAME = "vid";
|
||||
private static final String VID = "vid";
|
||||
private static final String VS_STEPUP = "vs-stepup";
|
||||
private static final String VS_ACCESS = "vs-access";
|
||||
private String apiServerInUse = APISERVERLIST.get(apiServerInUseIndex);
|
||||
private String authstring = "";
|
||||
private @Nullable String csrf;
|
||||
private @Nullable String pinCode;
|
||||
private HttpClient httpClient;
|
||||
private @Nullable String userName = "";
|
||||
private @Nullable String password = "";
|
||||
private String userName = "";
|
||||
private String password = "";
|
||||
private String vid = "";
|
||||
private String vsAccess = "";
|
||||
private String vsStepup = "";
|
||||
|
||||
public VerisureSession(HttpClient httpClient) {
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
public boolean initialize(@Nullable String authstring, @Nullable String pinCode, @Nullable String userName) {
|
||||
public boolean initialize(@Nullable String authstring, @Nullable String pinCode, String userName, String password) {
|
||||
if (authstring != null) {
|
||||
this.authstring = authstring.substring(0);
|
||||
this.pinCode = pinCode;
|
||||
this.userName = userName;
|
||||
this.password = password;
|
||||
// Try to login to Verisure
|
||||
if (logIn()) {
|
||||
return getInstallations();
|
||||
|
@ -119,12 +128,9 @@ public class VerisureSession {
|
|||
if (logIn()) {
|
||||
if (updateStatus()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
} catch (HttpResponseException e) {
|
||||
logger.warn("Failed to do a refresh {}", e.getMessage());
|
||||
return false;
|
||||
|
@ -258,15 +264,21 @@ public class VerisureSession {
|
|||
}
|
||||
}
|
||||
|
||||
private void setPasswordFromCookie() {
|
||||
private void analyzeCookies() {
|
||||
CookieStore c = httpClient.getCookieStore();
|
||||
List<HttpCookie> cookies = c.getCookies();
|
||||
final List<HttpCookie> unmodifiableList = List.of(cookies.toArray(new HttpCookie[] {}));
|
||||
unmodifiableList.forEach(cookie -> {
|
||||
logger.trace("Response Cookie: {}", cookie);
|
||||
if (cookie.getName().equals(PASSWORD_NAME)) {
|
||||
password = cookie.getValue();
|
||||
logger.debug("Fetching vid {} from cookie", password);
|
||||
if (VID.equals(cookie.getName())) {
|
||||
vid = cookie.getValue();
|
||||
logger.debug("Fetching vid {} from cookie", vid);
|
||||
} else if (VS_ACCESS.equals(cookie.getName())) {
|
||||
vsAccess = cookie.getValue();
|
||||
logger.debug("Fetching vs-access {} from cookie", vsAccess);
|
||||
} else if (VS_STEPUP.equals(cookie.getName())) {
|
||||
vsStepup = cookie.getValue();
|
||||
logger.debug("Fetching vs-stepup {} from cookie", vsStepup);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -290,7 +302,6 @@ public class VerisureSession {
|
|||
switch (response.getStatus()) {
|
||||
case HttpStatus.OK_200:
|
||||
if (content.contains("<link href=\"/newapp")) {
|
||||
setPasswordFromCookie();
|
||||
return true;
|
||||
} else {
|
||||
logger.debug("We need to login again!");
|
||||
|
@ -313,9 +324,9 @@ public class VerisureSession {
|
|||
|
||||
private <T> @Nullable T getJSONVerisureAPI(String url, Class<T> jsonClass)
|
||||
throws ExecutionException, InterruptedException, TimeoutException, JsonSyntaxException {
|
||||
logger.debug("HTTP GET: {}", BASEURL + url);
|
||||
logger.debug("HTTP GET: {}", BASE_URL + url);
|
||||
|
||||
ContentResponse response = httpClient.GET(BASEURL + url + "?_=" + System.currentTimeMillis());
|
||||
ContentResponse response = httpClient.GET(BASE_URL + url + "?_=" + System.currentTimeMillis());
|
||||
String content = response.getContentAsString();
|
||||
logTraceWithPattern(response.getStatus(), content);
|
||||
|
||||
|
@ -325,6 +336,7 @@ public class VerisureSession {
|
|||
private ContentResponse postVerisureAPI(String url, String data, boolean isJSON)
|
||||
throws ExecutionException, InterruptedException, TimeoutException {
|
||||
logger.debug("postVerisureAPI URL: {} Data:{}", url, data);
|
||||
|
||||
Request request = httpClient.newRequest(url).method(HttpMethod.POST);
|
||||
if (isJSON) {
|
||||
request.header("content-type", "application/json");
|
||||
|
@ -334,14 +346,29 @@ public class VerisureSession {
|
|||
}
|
||||
}
|
||||
request.header("Accept", "application/json");
|
||||
if (!data.equals("empty")) {
|
||||
|
||||
if (url.contains(AUTH_LOGIN)) {
|
||||
request.header("APPLICATION_ID", "OpenHAB Verisure");
|
||||
String basicAuhentication = Base64.getEncoder().encodeToString((userName + ":" + password).getBytes());
|
||||
request.header("authorization", "Basic " + basicAuhentication);
|
||||
} else {
|
||||
if (!vid.isEmpty()) {
|
||||
request.cookie(new HttpCookie(VID, vid));
|
||||
logger.debug("Setting cookie with vid {}", vid);
|
||||
}
|
||||
if (!vsAccess.isEmpty()) {
|
||||
request.cookie(new HttpCookie(VS_ACCESS, vsAccess));
|
||||
logger.debug("Setting cookie with vs-access {}", vsAccess);
|
||||
}
|
||||
logger.debug("Setting cookie with username {}", userName);
|
||||
request.cookie(new HttpCookie(USER_NAME, userName));
|
||||
}
|
||||
|
||||
if (!"empty".equals(data)) {
|
||||
request.content(new BytesContentProvider(data.getBytes(StandardCharsets.UTF_8)),
|
||||
"application/x-www-form-urlencoded; charset=UTF-8");
|
||||
} else {
|
||||
logger.debug("Setting cookie with username {} and vid {}", userName, password);
|
||||
request.cookie(new HttpCookie(USER_NAME, userName));
|
||||
request.cookie(new HttpCookie(PASSWORD_NAME, password));
|
||||
}
|
||||
|
||||
logger.debug("HTTP POST Request {}.", request.toString());
|
||||
return request.send();
|
||||
}
|
||||
|
@ -400,6 +427,9 @@ public class VerisureSession {
|
|||
logTraceWithPattern(httpStatus, content);
|
||||
return httpStatus;
|
||||
}
|
||||
} else if (httpStatus == HttpStatus.BAD_REQUEST_400) {
|
||||
setApiServerInUse(getNextApiServer());
|
||||
url = apiServerInUse + urlString;
|
||||
} else {
|
||||
logger.debug("Failed to send POST, Http status code: {}", response.getStatus());
|
||||
}
|
||||
|
@ -417,7 +447,11 @@ public class VerisureSession {
|
|||
logTraceWithPattern(response.getStatus(), response.getContentAsString());
|
||||
|
||||
url = AUTH_LOGIN;
|
||||
return postVerisureAPI(url, "empty");
|
||||
int httpStatusCode = postVerisureAPI(url, "empty");
|
||||
analyzeCookies();
|
||||
|
||||
// return response.getStatus();
|
||||
return httpStatusCode;
|
||||
}
|
||||
|
||||
private boolean getInstallations() {
|
||||
|
@ -488,10 +522,26 @@ public class VerisureSession {
|
|||
private synchronized boolean logIn() {
|
||||
try {
|
||||
if (!areWeLoggedIn()) {
|
||||
logger.debug("Attempting to log in to mypages.verisure.com");
|
||||
String url = LOGON_SUF;
|
||||
vid = "";
|
||||
vsAccess = "";
|
||||
logger.debug("Attempting to log in to {}, remove all cookies to ensure a fresh session", BASE_URL);
|
||||
URI authUri = new URI(BASE_URL);
|
||||
CookieStore store = httpClient.getCookieStore();
|
||||
store.get(authUri).forEach(cookie -> {
|
||||
store.remove(authUri, cookie);
|
||||
});
|
||||
|
||||
String url = AUTH_LOGIN;
|
||||
int httpStatusCode = postVerisureAPI(url, "empty");
|
||||
analyzeCookies();
|
||||
if (!vsStepup.isEmpty()) {
|
||||
logger.warn("MFA is activated on this user! Not supported by binding!");
|
||||
return false;
|
||||
}
|
||||
|
||||
url = LOGON_SUF;
|
||||
logger.debug("Login URL: {}", url);
|
||||
int httpStatusCode = postVerisureAPI(url, authstring);
|
||||
httpStatusCode = postVerisureAPI(url, authstring);
|
||||
if (httpStatusCode != HttpStatus.OK_200) {
|
||||
logger.debug("Failed to login, HTTP status code: {}", httpStatusCode);
|
||||
return false;
|
||||
|
@ -500,7 +550,7 @@ public class VerisureSession {
|
|||
} else {
|
||||
return true;
|
||||
}
|
||||
} catch (ExecutionException | InterruptedException | TimeoutException e) {
|
||||
} catch (ExecutionException | InterruptedException | TimeoutException | URISyntaxException e) {
|
||||
logger.warn("Failed to login {}", e.getMessage());
|
||||
}
|
||||
return false;
|
||||
|
@ -617,16 +667,17 @@ public class VerisureSession {
|
|||
// Set location
|
||||
slThing.setLocation(doorLock.getDevice().getArea());
|
||||
slThing.setDeviceId(deviceId);
|
||||
|
||||
// Fetch more info from old endpoint
|
||||
try {
|
||||
VerisureSmartLockDTO smartLockThing = getJSONVerisureAPI(SMARTLOCK_PATH + slThing.getDeviceId(),
|
||||
VerisureSmartLockDTO.class);
|
||||
logger.debug("REST Response ({})", smartLockThing);
|
||||
slThing.setSmartLockJSON(smartLockThing);
|
||||
notifyListenersIfChanged(slThing, installation, deviceId);
|
||||
} catch (ExecutionException | InterruptedException | TimeoutException | JsonSyntaxException e) {
|
||||
logger.warn("Failed to query for smartlock status: {}", e.getMessage());
|
||||
}
|
||||
notifyListenersIfChanged(slThing, installation, deviceId);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -740,7 +791,7 @@ public class VerisureSession {
|
|||
cThing.setBatteryStatus(batteryStatus);
|
||||
}
|
||||
} catch (ExecutionException | InterruptedException | TimeoutException | JsonSyntaxException e) {
|
||||
logger.warn("Failed to query for smartlock status: {}", e.getMessage());
|
||||
logger.debug("Failed to query for battery status: {}", e.getMessage());
|
||||
}
|
||||
// Set location
|
||||
cThing.setLocation(climate.getDevice().getArea());
|
||||
|
@ -789,7 +840,7 @@ public class VerisureSession {
|
|||
dThing.setBatteryStatus(batteryStatus);
|
||||
}
|
||||
} catch (ExecutionException | InterruptedException | TimeoutException | JsonSyntaxException e) {
|
||||
logger.warn("Failed to query for smartlock status: {}", e.getMessage());
|
||||
logger.warn("Failed to query for door&window status: {}", e.getMessage());
|
||||
}
|
||||
// Set location
|
||||
dThing.setLocation(doorWindow.getDevice().getArea());
|
||||
|
@ -847,7 +898,7 @@ public class VerisureSession {
|
|||
.getUserTrackings();
|
||||
userTrackingList.forEach(userTracking -> {
|
||||
String localUserTrackingStatus = userTracking.getStatus();
|
||||
if (localUserTrackingStatus != null && localUserTrackingStatus.equals("ACTIVE")) {
|
||||
if ("ACTIVE".equals(localUserTrackingStatus)) {
|
||||
VerisureUserPresencesDTO upThing = new VerisureUserPresencesDTO();
|
||||
VerisureUserPresencesDTO.Installation inst = new VerisureUserPresencesDTO.Installation();
|
||||
inst.setUserTrackings(Collections.singletonList(userTracking));
|
||||
|
|
|
@ -75,7 +75,8 @@ public class VerisureThingDiscoveryService extends AbstractDiscoveryService
|
|||
String deviceId = thing.getDeviceId();
|
||||
if (thingUID != null) {
|
||||
if (verisureBridgeHandler != null) {
|
||||
String label = "Device Id: " + deviceId;
|
||||
String className = thing.getClass().getSimpleName();
|
||||
String label = "Type: " + className + " Device Id: " + deviceId;
|
||||
if (thing.getLocation() != null) {
|
||||
label += ", Location: " + thing.getLocation();
|
||||
}
|
||||
|
@ -84,7 +85,7 @@ public class VerisureThingDiscoveryService extends AbstractDiscoveryService
|
|||
}
|
||||
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withBridge(bridgeUID)
|
||||
.withLabel(label).withProperty(VerisureThingConfiguration.DEVICE_ID_LABEL, deviceId)
|
||||
.withRepresentationProperty(deviceId).build();
|
||||
.withRepresentationProperty(VerisureThingConfiguration.DEVICE_ID_LABEL).build();
|
||||
logger.debug("thinguid: {}, bridge {}, label {}", thingUID, bridgeUID, deviceId);
|
||||
thingDiscovered(discoveryResult);
|
||||
}
|
||||
|
|
|
@ -14,9 +14,6 @@ package org.openhab.binding.verisure.internal.handler;
|
|||
|
||||
import static org.openhab.binding.verisure.internal.VerisureBindingConstants.*;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
@ -65,7 +62,6 @@ public class VerisureBridgeHandler extends BaseBridgeHandler {
|
|||
|
||||
private String authstring = "";
|
||||
private @Nullable String pinCode;
|
||||
private static int REFRESH_SEC = 600;
|
||||
private @Nullable ScheduledFuture<?> refreshJob;
|
||||
private @Nullable ScheduledFuture<?> immediateRefreshJob;
|
||||
private @Nullable VerisureSession session;
|
||||
|
@ -104,20 +100,19 @@ public class VerisureBridgeHandler extends BaseBridgeHandler {
|
|||
public void initialize() {
|
||||
logger.debug("Initializing Verisure Binding");
|
||||
VerisureBridgeConfiguration config = getConfigAs(VerisureBridgeConfiguration.class);
|
||||
REFRESH_SEC = config.refresh;
|
||||
|
||||
this.pinCode = config.pin;
|
||||
if (config.username == null || config.password == null) {
|
||||
if (config.username.isBlank() || config.password.isBlank()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"Configuration of username and password is mandatory");
|
||||
} else if (REFRESH_SEC < 0) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Refresh time cannot negative!");
|
||||
|
||||
} else if (config.refresh < 10) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"Refresh time is lower than min value of 10!");
|
||||
} else {
|
||||
try {
|
||||
authstring = "j_username=" + config.username + "&j_password="
|
||||
+ URLEncoder.encode(config.password, StandardCharsets.UTF_8.toString())
|
||||
+ "&spring-security-redirect=" + START_REDIRECT;
|
||||
authstring = "j_username=" + config.username;
|
||||
scheduler.execute(() -> {
|
||||
|
||||
if (session == null) {
|
||||
logger.debug("Session is null, let's create a new one");
|
||||
session = new VerisureSession(this.httpClient);
|
||||
|
@ -125,18 +120,15 @@ public class VerisureBridgeHandler extends BaseBridgeHandler {
|
|||
VerisureSession session = this.session;
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
if (session != null) {
|
||||
if (!session.initialize(authstring, pinCode, config.username)) {
|
||||
logger.warn("Failed to initialize bridge, please check your credentials!");
|
||||
if (!session.initialize(authstring, pinCode, config.username, config.password)) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.HANDLER_REGISTERING_ERROR,
|
||||
"Failed to login to Verisure, please check your credentials!");
|
||||
dispose();
|
||||
initialize();
|
||||
"Failed to login to Verisure, please check your account settings! Is MFA activated?");
|
||||
return;
|
||||
}
|
||||
startAutomaticRefresh();
|
||||
startAutomaticRefresh(config.refresh);
|
||||
}
|
||||
});
|
||||
} catch (RuntimeException | UnsupportedEncodingException e) {
|
||||
} catch (RuntimeException e) {
|
||||
logger.warn("Failed to initialize: {}", e.getMessage());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||
}
|
||||
|
@ -227,12 +219,12 @@ public class VerisureBridgeHandler extends BaseBridgeHandler {
|
|||
}
|
||||
}
|
||||
|
||||
private void startAutomaticRefresh() {
|
||||
private void startAutomaticRefresh(int refresh) {
|
||||
ScheduledFuture<?> refreshJob = this.refreshJob;
|
||||
logger.debug("Start automatic refresh {}", refreshJob);
|
||||
if (refreshJob == null || refreshJob.isCancelled()) {
|
||||
try {
|
||||
this.refreshJob = scheduler.scheduleWithFixedDelay(this::refreshAndUpdateStatus, 0, REFRESH_SEC,
|
||||
this.refreshJob = scheduler.scheduleWithFixedDelay(this::refreshAndUpdateStatus, 0, refresh,
|
||||
TimeUnit.SECONDS);
|
||||
logger.debug("Scheduling at fixed delay refreshjob {}", this.refreshJob);
|
||||
} catch (RejectedExecutionException e) {
|
||||
|
|
|
@ -15,6 +15,7 @@ package org.openhab.binding.verisure.internal.handler;
|
|||
import static org.openhab.binding.verisure.internal.VerisureBindingConstants.*;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.measure.quantity.Dimensionless;
|
||||
|
@ -23,6 +24,7 @@ import javax.measure.quantity.Temperature;
|
|||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.verisure.internal.dto.VerisureBatteryStatusDTO;
|
||||
import org.openhab.binding.verisure.internal.dto.VerisureClimatesDTO;
|
||||
import org.openhab.binding.verisure.internal.dto.VerisureClimatesDTO.Climate;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
|
@ -74,27 +76,35 @@ public class VerisureClimateDeviceThingHandler extends VerisureThingHandler<Veri
|
|||
State state = getValue(channelUID.getId(), climateJSON);
|
||||
updateState(channelUID, state);
|
||||
});
|
||||
String timeStamp = climateJSON.getData().getInstallation().getClimates().get(0).getTemperatureTimestamp();
|
||||
List<Climate> climateList = climateJSON.getData().getInstallation().getClimates();
|
||||
if (climateList != null && !climateList.isEmpty()) {
|
||||
String timeStamp = climateList.get(0).getTemperatureTimestamp();
|
||||
if (timeStamp != null) {
|
||||
updateTimeStamp(timeStamp);
|
||||
}
|
||||
}
|
||||
|
||||
updateInstallationChannels(climateJSON);
|
||||
}
|
||||
|
||||
public State getValue(String channelId, VerisureClimatesDTO climateJSON) {
|
||||
List<Climate> climateList = climateJSON.getData().getInstallation().getClimates();
|
||||
switch (channelId) {
|
||||
case CHANNEL_TEMPERATURE:
|
||||
double temperature = climateJSON.getData().getInstallation().getClimates().get(0).getTemperatureValue();
|
||||
if (climateList != null && !climateList.isEmpty()) {
|
||||
double temperature = climateList.get(0).getTemperatureValue();
|
||||
return new QuantityType<Temperature>(temperature, SIUnits.CELSIUS);
|
||||
}
|
||||
case CHANNEL_HUMIDITY:
|
||||
if (climateJSON.getData().getInstallation().getClimates().get(0).isHumidityEnabled()) {
|
||||
double humidity = climateJSON.getData().getInstallation().getClimates().get(0).getHumidityValue();
|
||||
if (climateList != null && !climateList.isEmpty() && climateList.get(0).isHumidityEnabled()) {
|
||||
double humidity = climateList.get(0).getHumidityValue();
|
||||
return new QuantityType<Dimensionless>(humidity, Units.PERCENT);
|
||||
}
|
||||
case CHANNEL_HUMIDITY_ENABLED:
|
||||
boolean humidityEnabled = climateJSON.getData().getInstallation().getClimates().get(0)
|
||||
.isHumidityEnabled();
|
||||
if (climateList != null && !climateList.isEmpty()) {
|
||||
boolean humidityEnabled = climateList.get(0).isHumidityEnabled();
|
||||
return OnOffType.from(humidityEnabled);
|
||||
}
|
||||
case CHANNEL_LOCATION:
|
||||
String location = climateJSON.getLocation();
|
||||
return location != null ? new StringType(location) : UnDefType.NULL;
|
||||
|
@ -102,7 +112,7 @@ public class VerisureClimateDeviceThingHandler extends VerisureThingHandler<Veri
|
|||
VerisureBatteryStatusDTO batteryStatus = climateJSON.getBatteryStatus();
|
||||
if (batteryStatus != null) {
|
||||
String status = batteryStatus.getStatus();
|
||||
if (status != null && status.equals("CRITICAL")) {
|
||||
if ("CRITICAL".equals(status)) {
|
||||
return OnOffType.from(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ public class VerisureDoorWindowThingHandler extends VerisureThingHandler<Verisur
|
|||
VerisureBatteryStatusDTO batteryStatus = doorWindowJSON.getBatteryStatus();
|
||||
if (batteryStatus != null) {
|
||||
String status = batteryStatus.getStatus();
|
||||
if (status != null && status.equals("CRITICAL")) {
|
||||
if ("CRITICAL".equals(status)) {
|
||||
return OnOffType.from(true);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue