[verisure] Add channel for low battery warning for supported thing types (#10406) (#10580)

- Add channel for low battery warning for supported thing types

Closes #10406

Signed-off-by: Jan Gustafsson <jannegpriv@gmail.com>
This commit is contained in:
Jan Gustafsson 2021-05-05 21:27:53 +02:00 committed by GitHub
parent 940e1e53d1
commit ffa17c76c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 253 additions and 93 deletions

View File

@ -99,7 +99,7 @@ The following channels are supported:
| installationName | String | This channel reports the installation name. | | installationName | String | This channel reports the installation name. |
| installationId | Number | This channel reports the installation ID. | | installationId | Number | This channel reports the installation ID. |
| alarmStatus | String | This channel is used to arm/disarm the alarm. Available alarm status are "DISARMED", "ARMED_HOME" and "ARMED_AWAY".| | alarmStatus | String | This channel is used to arm/disarm the alarm. Available alarm status are "DISARMED", "ARMED_HOME" and "ARMED_AWAY".|
| alarmTriggerChannel | trigger | This is a trigger channel that receives events.| | alarmTriggerChannel | trigger | This is a trigger channel that receives events. |
### Verisure Yaleman SmartLock ### Verisure Yaleman SmartLock
@ -167,7 +167,8 @@ The following channels are supported:
| location | String | This channel reports the location of the device. | | location | String | This channel reports the location of the device. |
| installationName | String | This channel reports the installation name. | | installationName | String | This channel reports the installation name. |
| installationId | Number | This channel reports the installation ID. | | installationId | Number | This channel reports the installation ID. |
| smokeDetectorTriggerChannel | trigger | This is a trigger channel that receives events.| | lowBattery | Switch | This channel reports if the battery level is low. |
| smokeDetectorTriggerChannel | trigger | This is a trigger channel that receives events. |
### Verisure Water Detector ### Verisure Water Detector
@ -181,6 +182,7 @@ The following channels are supported:
The following channels are supported: The following channels are supported:
| Channel Type ID | Item Type | Description | | Channel Type ID | Item Type | Description |
|-----------------------------|-----------------------|--------------------------------------------------------------| |-----------------------------|-----------------------|--------------------------------------------------------------|
| temperature | Number:Temperature | This channel reports the current temperature. | | temperature | Number:Temperature | This channel reports the current temperature. |
@ -209,6 +211,7 @@ The following channels are supported:
| location | String | This channel reports the location. | | location | String | This channel reports the location. |
| installationName | String | This channel reports the installation name. | | installationName | String | This channel reports the installation name. |
| installationId | Number | This channel reports the installation ID. | | installationId | Number | This channel reports the installation ID. |
| lowBattery | Switch | This channel reports if the battery level is low. |
| sirenTriggerChannel | trigger | This is a trigger channel that receives events. | | sirenTriggerChannel | trigger | This is a trigger channel that receives events. |
### Verisure Night Control ### Verisure Night Control
@ -221,7 +224,6 @@ The following channels are supported:
#### Channels #### Channels
The following channels are supported: The following channels are supported:
| Channel Type ID | Item Type | Description | | Channel Type ID | Item Type | Description |
|----------------------------|-----------------------|------------------------------------------------------------| |----------------------------|-----------------------|------------------------------------------------------------|
| temperature | Number:Temperature | This channel reports the current temperature. | | temperature | Number:Temperature | This channel reports the current temperature. |
@ -229,6 +231,7 @@ The following channels are supported:
| location | String | This channel reports the location. | | location | String | This channel reports the location. |
| installationName | String | This channel reports the installation name. | | installationName | String | This channel reports the installation name. |
| installationId | Number | This channel reports the installation ID. | | installationId | Number | This channel reports the installation ID. |
| lowBattery | Switch | This channel reports if the battery level is low. |
| nightControlTriggerChannel | trigger | This is a trigger channel that receives events. | | nightControlTriggerChannel | trigger | This is a trigger channel that receives events. |
### Verisure DoorWindow Sensor ### Verisure DoorWindow Sensor
@ -249,6 +252,7 @@ The following channels are supported:
| location | String | This channel reports the location of the device. | | location | String | This channel reports the location of the device. |
| installationName | String | This channel reports the installation name. | | installationName | String | This channel reports the installation name. |
| installationId | Number | This channel reports the installation ID. | | installationId | Number | This channel reports the installation ID. |
| lowBattery | Switch | This channel reports if the battery level is low. |
| doorWindowTriggerChannel | trigger | This is a trigger channel that receives events. | | doorWindowTriggerChannel | trigger | This is a trigger channel that receives events. |
@ -323,7 +327,6 @@ The following channels are supported:
* `deviceId` - Device Id * `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. * 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 #### Channels
The following channels are supported: The following channels are supported:
@ -368,7 +371,7 @@ The following channels are supported:
To be able to get trigger events you need an active Event Log thing, you can either get it via auto-detection or create your own in a things-file. To be able to get trigger events you need an active Event Log thing, you can either get it via auto-detection or create your own in a things-file.
The following trigger events are defined per thing type: The following trigger events are defined per thing type:
| Event | Thing Type | Description | | Event Type | Thing Type | Description |
|-------------------|---------------|------------------------------------------------------------| |-------------------|---------------|------------------------------------------------------------|
| LOCK | SmartLock | SmartLock has been locked. | | LOCK | SmartLock | SmartLock has been locked. |
| UNLOCK | SmartLock | SmartLock has been locked. | | UNLOCK | SmartLock | SmartLock has been locked. |

View File

@ -104,6 +104,7 @@ public class VerisureBindingConstants {
public static final String CHANNEL_NIGHT_CONTROL_TRIGGER_CHANNEL = "nightControlTriggerChannel"; public static final String CHANNEL_NIGHT_CONTROL_TRIGGER_CHANNEL = "nightControlTriggerChannel";
public static final String CHANNEL_DOOR_WINDOW_TRIGGER_CHANNEL = "doorWindowTriggerChannel"; public static final String CHANNEL_DOOR_WINDOW_TRIGGER_CHANNEL = "doorWindowTriggerChannel";
public static final String CHANNEL_GATEWAY_TRIGGER_CHANNEL = "gatewayTriggerChannel"; public static final String CHANNEL_GATEWAY_TRIGGER_CHANNEL = "gatewayTriggerChannel";
public static final String CHANNEL_BATTERY_STATUS = "lowBattery";
// Trigger channel events // Trigger channel events
public static final String TRIGGER_EVENT_LOCK = "LOCK"; public static final String TRIGGER_EVENT_LOCK = "LOCK";
@ -162,4 +163,5 @@ public class VerisureBindingConstants {
public static final String TEMPERATURE_CONTROL_PATH = "/overview/temperaturecontrol"; public static final String TEMPERATURE_CONTROL_PATH = "/overview/temperaturecontrol";
public static final String MOUSEDETECTION_PATH = "/overview/mousedetection"; public static final String MOUSEDETECTION_PATH = "/overview/mousedetection";
public static final String CAMERA_PATH = "/overview/camera"; public static final String CAMERA_PATH = "/overview/camera";
public static final String BATTERY_STATUS = "/batterywizard/choose/device?_";
} }

View File

@ -42,6 +42,7 @@ import org.jsoup.Jsoup;
import org.jsoup.nodes.Document; import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element; import org.jsoup.nodes.Element;
import org.openhab.binding.verisure.internal.dto.VerisureAlarmsDTO; import org.openhab.binding.verisure.internal.dto.VerisureAlarmsDTO;
import org.openhab.binding.verisure.internal.dto.VerisureBatteryStatusDTO;
import org.openhab.binding.verisure.internal.dto.VerisureBroadbandConnectionsDTO; import org.openhab.binding.verisure.internal.dto.VerisureBroadbandConnectionsDTO;
import org.openhab.binding.verisure.internal.dto.VerisureClimatesDTO; import org.openhab.binding.verisure.internal.dto.VerisureClimatesDTO;
import org.openhab.binding.verisure.internal.dto.VerisureDoorWindowsDTO; import org.openhab.binding.verisure.internal.dto.VerisureDoorWindowsDTO;
@ -655,6 +656,19 @@ public class VerisureSession {
} }
} }
private @Nullable VerisureBatteryStatusDTO getBatteryStatus(String deviceId,
VerisureBatteryStatusDTO @Nullable [] batteryStatus) {
if (batteryStatus != null) {
for (VerisureBatteryStatusDTO verisureBatteryStatusDTO : batteryStatus) {
String id = verisureBatteryStatusDTO.getId();
if (id != null && id.equals(deviceId)) {
return verisureBatteryStatusDTO;
}
}
}
return null;
}
private synchronized void updateClimateStatus(VerisureInstallation installation) { private synchronized void updateClimateStatus(VerisureInstallation installation) {
BigDecimal installationId = installation.getInstallationId(); BigDecimal installationId = installation.getInstallationId();
String url = START_GRAPHQL; String url = START_GRAPHQL;
@ -671,6 +685,7 @@ public class VerisureSession {
VerisureClimatesDTO thing = postJSONVerisureAPI(url, queryQLClimates, VerisureClimatesDTO.class); VerisureClimatesDTO thing = postJSONVerisureAPI(url, queryQLClimates, VerisureClimatesDTO.class);
logger.debug("REST Response ({})", thing); logger.debug("REST Response ({})", thing);
List<VerisureClimatesDTO.Climate> climateList = thing.getData().getInstallation().getClimates(); List<VerisureClimatesDTO.Climate> climateList = thing.getData().getInstallation().getClimates();
if (climateList != null) {
climateList.forEach(climate -> { climateList.forEach(climate -> {
// If thing is Mouse detection device, then skip it, but fetch temperature from it // If thing is Mouse detection device, then skip it, but fetch temperature from it
String type = climate.getDevice().getGui().getLabel(); String type = climate.getDevice().getGui().getLabel();
@ -699,11 +714,24 @@ public class VerisureSession {
// Set unique deviceID // Set unique deviceID
String deviceId = climate.getDevice().getDeviceLabel(); String deviceId = climate.getDevice().getDeviceLabel();
if (deviceId != null) { if (deviceId != null) {
try {
VerisureBatteryStatusDTO[] batteryStatusThingArray = getJSONVerisureAPI(BATTERY_STATUS,
VerisureBatteryStatusDTO[].class);
VerisureBatteryStatusDTO batteryStatus = getBatteryStatus(deviceId,
batteryStatusThingArray);
if (batteryStatus != null) {
logger.debug("REST Response ({})", batteryStatus);
cThing.setBatteryStatus(batteryStatus);
}
} catch (ExecutionException | InterruptedException | TimeoutException | JsonSyntaxException e) {
logger.warn("Failed to query for smartlock status: {}", e.getMessage());
}
// Set location // Set location
cThing.setLocation(climate.getDevice().getArea()); cThing.setLocation(climate.getDevice().getArea());
notifyListenersIfChanged(cThing, installation, deviceId); notifyListenersIfChanged(cThing, installation, deviceId);
} }
}); });
}
} catch (ExecutionException | InterruptedException | TimeoutException | JsonSyntaxException } catch (ExecutionException | InterruptedException | TimeoutException | JsonSyntaxException
| PostToAPIException e) { | PostToAPIException e) {
logger.warn("Failed to send a POST to the API {}", e.getMessage()); logger.warn("Failed to send a POST to the API {}", e.getMessage());
@ -736,6 +764,17 @@ public class VerisureSession {
// Set unique deviceID // Set unique deviceID
String deviceId = doorWindow.getDevice().getDeviceLabel(); String deviceId = doorWindow.getDevice().getDeviceLabel();
if (deviceId != null) { if (deviceId != null) {
try {
VerisureBatteryStatusDTO[] batteryStatusThingArray = getJSONVerisureAPI(BATTERY_STATUS,
VerisureBatteryStatusDTO[].class);
VerisureBatteryStatusDTO batteryStatus = getBatteryStatus(deviceId, batteryStatusThingArray);
if (batteryStatus != null) {
logger.debug("REST Response ({})", batteryStatus);
dThing.setBatteryStatus(batteryStatus);
}
} catch (ExecutionException | InterruptedException | TimeoutException | JsonSyntaxException e) {
logger.warn("Failed to query for smartlock status: {}", e.getMessage());
}
// Set location // Set location
dThing.setLocation(doorWindow.getDevice().getArea()); dThing.setLocation(doorWindow.getDevice().getArea());
notifyListenersIfChanged(dThing, installation, deviceId); notifyListenersIfChanged(dThing, installation, deviceId);

View File

@ -264,7 +264,7 @@ public abstract class VerisureBaseThingDTO implements VerisureThingDTO {
return broadband; return broadband;
} }
public List<Climate> getClimates() { public @Nullable List<Climate> getClimates() {
return climates; return climates;
} }

View File

@ -0,0 +1,53 @@
/**
* Copyright (c) 2010-2021 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.verisure.internal.dto;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
/**
* The battery status of the Verisure System.
*
* @author Jan Gustafsson - Initial contribution
*
*/
@NonNullByDefault
public class VerisureBatteryStatusDTO {
public boolean chosen;
public @Nullable String id;
public @Nullable String pictureBase;
public @Nullable String translatedType;
public @Nullable String location;
public @Nullable String batteryInfo;
public @Nullable String status;
public @Nullable String alias;
public int index;
public boolean selectable;
public @Nullable String getId() {
return id;
}
public @Nullable String getLocation() {
return location;
}
public @Nullable String getBatteryInfo() {
return batteryInfo;
}
public @Nullable String getStatus() {
return status;
}
}

View File

@ -29,6 +29,16 @@ import com.google.gson.annotations.SerializedName;
@NonNullByDefault @NonNullByDefault
public class VerisureClimatesDTO extends VerisureBaseThingDTO { public class VerisureClimatesDTO extends VerisureBaseThingDTO {
private @Nullable VerisureBatteryStatusDTO batteryStatus;
public @Nullable VerisureBatteryStatusDTO getBatteryStatus() {
return batteryStatus;
}
public void setBatteryStatus(@Nullable VerisureBatteryStatusDTO batteryStatus) {
this.batteryStatus = batteryStatus;
}
@Override @Override
public ThingTypeUID getThingTypeUID() { public ThingTypeUID getThingTypeUID() {
String type = getData().getInstallation().getClimates().get(0).getDevice().getGui().getLabel(); String type = getData().getInstallation().getClimates().get(0).getDevice().getGui().getLabel();
@ -64,6 +74,15 @@ public class VerisureClimatesDTO extends VerisureBaseThingDTO {
if (getClass() != obj.getClass()) { if (getClass() != obj.getClass()) {
return false; return false;
} }
VerisureClimatesDTO other = (VerisureClimatesDTO) obj;
VerisureBatteryStatusDTO localBatteryStatusJSON = batteryStatus;
if (localBatteryStatusJSON == null) {
if (other.batteryStatus != null) {
return false;
}
} else if (!localBatteryStatusJSON.equals(other.batteryStatus)) {
return false;
}
return true; return true;
} }

View File

@ -29,6 +29,16 @@ import com.google.gson.annotations.SerializedName;
@NonNullByDefault @NonNullByDefault
public class VerisureDoorWindowsDTO extends VerisureBaseThingDTO { public class VerisureDoorWindowsDTO extends VerisureBaseThingDTO {
private @Nullable VerisureBatteryStatusDTO batteryStatus;
public @Nullable VerisureBatteryStatusDTO getBatteryStatus() {
return batteryStatus;
}
public void setBatteryStatus(@Nullable VerisureBatteryStatusDTO batteryStatus) {
this.batteryStatus = batteryStatus;
}
@Override @Override
public ThingTypeUID getThingTypeUID() { public ThingTypeUID getThingTypeUID() {
return THING_TYPE_DOORWINDOW; return THING_TYPE_DOORWINDOW;
@ -53,6 +63,15 @@ public class VerisureDoorWindowsDTO extends VerisureBaseThingDTO {
if (getClass() != obj.getClass()) { if (getClass() != obj.getClass()) {
return false; return false;
} }
VerisureDoorWindowsDTO other = (VerisureDoorWindowsDTO) obj;
VerisureBatteryStatusDTO localBatteryStatusJSON = batteryStatus;
if (localBatteryStatusJSON == null) {
if (other.batteryStatus != null) {
return false;
}
} else if (!localBatteryStatusJSON.equals(other.batteryStatus)) {
return false;
}
return true; return true;
} }

View File

@ -21,6 +21,7 @@ import javax.measure.quantity.Dimensionless;
import javax.measure.quantity.Temperature; import javax.measure.quantity.Temperature;
import org.eclipse.jdt.annotation.NonNullByDefault; 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;
import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.QuantityType; import org.openhab.core.library.types.QuantityType;
@ -97,6 +98,15 @@ public class VerisureClimateDeviceThingHandler extends VerisureThingHandler<Veri
case CHANNEL_LOCATION: case CHANNEL_LOCATION:
String location = climateJSON.getLocation(); String location = climateJSON.getLocation();
return location != null ? new StringType(location) : UnDefType.NULL; return location != null ? new StringType(location) : UnDefType.NULL;
case CHANNEL_BATTERY_STATUS:
VerisureBatteryStatusDTO batteryStatus = climateJSON.getBatteryStatus();
if (batteryStatus != null) {
String status = batteryStatus.getStatus();
if (status != null && status.equals("CRITICAL")) {
return OnOffType.from(true);
}
}
return OnOffType.from(false);
} }
return UnDefType.UNDEF; return UnDefType.UNDEF;
} }

View File

@ -19,8 +19,10 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.verisure.internal.dto.VerisureBatteryStatusDTO;
import org.openhab.binding.verisure.internal.dto.VerisureDoorWindowsDTO; import org.openhab.binding.verisure.internal.dto.VerisureDoorWindowsDTO;
import org.openhab.binding.verisure.internal.dto.VerisureDoorWindowsDTO.DoorWindow; import org.openhab.binding.verisure.internal.dto.VerisureDoorWindowsDTO.DoorWindow;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType; import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.library.types.StringType; import org.openhab.core.library.types.StringType;
import org.openhab.core.thing.Channel; import org.openhab.core.thing.Channel;
@ -64,7 +66,7 @@ public class VerisureDoorWindowThingHandler extends VerisureThingHandler<Verisur
getThing().getChannels().stream().map(Channel::getUID) getThing().getChannels().stream().map(Channel::getUID)
.filter(channelUID -> isLinked(channelUID) && !channelUID.getId().equals("timestamp")) .filter(channelUID -> isLinked(channelUID) && !channelUID.getId().equals("timestamp"))
.forEach(channelUID -> { .forEach(channelUID -> {
State state = getValue(channelUID.getId(), doorWindow); State state = getValue(channelUID.getId(), doorWindow, doorWindowJSON);
updateState(channelUID, state); updateState(channelUID, state);
}); });
@ -75,13 +77,22 @@ public class VerisureDoorWindowThingHandler extends VerisureThingHandler<Verisur
} }
} }
public State getValue(String channelId, DoorWindow doorWindow) { public State getValue(String channelId, DoorWindow doorWindow, VerisureDoorWindowsDTO doorWindowJSON) {
switch (channelId) { switch (channelId) {
case CHANNEL_STATE: case CHANNEL_STATE:
return "OPEN".equals(doorWindow.getState()) ? OpenClosedType.OPEN : OpenClosedType.CLOSED; return "OPEN".equals(doorWindow.getState()) ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
case CHANNEL_LOCATION: case CHANNEL_LOCATION:
String location = doorWindow.getDevice().getArea(); String location = doorWindow.getDevice().getArea();
return location != null ? new StringType(location) : UnDefType.UNDEF; return location != null ? new StringType(location) : UnDefType.UNDEF;
case CHANNEL_BATTERY_STATUS:
VerisureBatteryStatusDTO batteryStatus = doorWindowJSON.getBatteryStatus();
if (batteryStatus != null) {
String status = batteryStatus.getStatus();
if (status != null && status.equals("CRITICAL")) {
return OnOffType.from(true);
}
}
return OnOffType.from(false);
} }
return UnDefType.UNDEF; return UnDefType.UNDEF;
} }

View File

@ -160,6 +160,7 @@
<channel id="installationName" typeId="installationName"/> <channel id="installationName" typeId="installationName"/>
<channel id="installationId" typeId="installationId"/> <channel id="installationId" typeId="installationId"/>
<channel id="smokeDetectorTriggerChannel" typeId="triggerChannel"/> <channel id="smokeDetectorTriggerChannel" typeId="triggerChannel"/>
<channel id="lowBattery" typeId="system.low-battery"/>
</channels> </channels>
<properties> <properties>
@ -224,6 +225,7 @@
<channel id="installationName" typeId="installationName"/> <channel id="installationName" typeId="installationName"/>
<channel id="installationId" typeId="installationId"/> <channel id="installationId" typeId="installationId"/>
<channel id="sirenTriggerChannel" typeId="triggerChannel"/> <channel id="sirenTriggerChannel" typeId="triggerChannel"/>
<channel id="lowBattery" typeId="system.low-battery"/>
</channels> </channels>
<properties> <properties>
@ -256,6 +258,7 @@
<channel id="installationName" typeId="installationName"/> <channel id="installationName" typeId="installationName"/>
<channel id="installationId" typeId="installationId"/> <channel id="installationId" typeId="installationId"/>
<channel id="nightControlTriggerChannel" typeId="triggerChannel"/> <channel id="nightControlTriggerChannel" typeId="triggerChannel"/>
<channel id="lowBattery" typeId="system.low-battery"/>
</channels> </channels>
<properties> <properties>
@ -288,6 +291,7 @@
<channel id="installationName" typeId="installationName"/> <channel id="installationName" typeId="installationName"/>
<channel id="installationId" typeId="installationId"/> <channel id="installationId" typeId="installationId"/>
<channel id="doorWindowTriggerChannel" typeId="triggerChannel"/> <channel id="doorWindowTriggerChannel" typeId="triggerChannel"/>
<channel id="lowBattery" typeId="system.low-battery"/>
</channels> </channels>
<properties> <properties>