mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
This change adds support for obtaining the battery state for the following devices: * Motion Detector * Thermostat * Twinguard * Wall Thermostat * Window/Door Contact The following changes were made: * Add system.battery-level and system.low-battery channels to Motion Detector, Thermostat, Twinguard, Wall Thermostat and Window/Door Contact * Add constant for battery-level and low-battery channels in BoschSHCBindingConstants * Implement abstract handler and service for battery-powered devices * Let appropriate devices inherit the abstract implementation * Add missing super calls in initializeServices() methods * Rename existing getServiceURL() to getServiceStateURL() in HTTP client * Add methods to retrieve service states without the suffix "/state" in the URL * Rename DeviceStatusUpdate to DeviceServiceData * Let DeviceServiceData extend BoschSHCServiceState * Extend DeviceServiceData DTO with model for faults * Enhance bridge handler: handle updates without state sub-objects, extract methods to enhance readability * Add unit tests for all affected devices * Minor code enhancements * Update documentation Signed-off-by: David Pace <dev@davidpace.de>
This commit is contained in:
parent
49fe49c1a9
commit
49fa349590
@ -49,7 +49,7 @@ A compact smart plug with energy monitoring capabilities.
|
||||
| power-consumption | Number:Power | ☐ | Current power consumption (W) of the device. |
|
||||
| energy-consumption | Number:Energy | ☐ | Cumulated energy consumption (Wh) of the device. |
|
||||
|
||||
### Twinguard smoke detector
|
||||
### Twinguard Smoke Detector
|
||||
|
||||
The Twinguard smoke detector warns you in case of fire and constantly monitors the air.
|
||||
|
||||
@ -65,6 +65,8 @@ The Twinguard smoke detector warns you in case of fire and constantly monitors t
|
||||
| purity-rating | String | ☐ | Rating of current measured purity. |
|
||||
| air-description | String | ☐ | Overall description of the air quality. |
|
||||
| combined-rating | String | ☐ | Combined rating of the air quality. |
|
||||
| battery-level | Number | ☐ | Current battery level percentage as integer number. Bosch-specific battery levels are mapped to numbers as follows: `OK`: 100, `LOW_BATTERY`: 10, `CRITICAL_LOW`: 1, `CRITICALLY_LOW_BATTERY`: 1, `NOT_AVAILABLE`: `UNDEF`. |
|
||||
| low-battery | Switch | ☐ | Indicates whether the battery is low (`ON`) or OK (`OFF`). |
|
||||
|
||||
### Door/Window Contact
|
||||
|
||||
@ -75,6 +77,8 @@ Detects open windows and doors.
|
||||
| Channel Type ID | Item Type | Writable | Description |
|
||||
| --------------- | --------- | :------: | ---------------------------- |
|
||||
| contact | Contact | ☐ | Contact state of the device. |
|
||||
| battery-level | Number | ☐ | Current battery level percentage as integer number. Bosch-specific battery levels are mapped to numbers as follows: `OK`: 100, `LOW_BATTERY`: 10, `CRITICAL_LOW`: 1, `CRITICALLY_LOW_BATTERY`: 1, `NOT_AVAILABLE`: `UNDEF`. |
|
||||
| low-battery | Switch | ☐ | Indicates whether the battery is low (`ON`) or OK (`OFF`). |
|
||||
|
||||
### Motion Detector
|
||||
|
||||
@ -85,6 +89,8 @@ Detects every movement through an intelligent combination of passive infra-red t
|
||||
| Channel Type ID | Item Type | Writable | Description |
|
||||
| --------------- | --------- | :------: | ------------------------------ |
|
||||
| latest-motion | DateTime | ☐ | The date of the latest motion. |
|
||||
| battery-level | Number | ☐ | Current battery level percentage as integer number. Bosch-specific battery levels are mapped to numbers as follows: `OK`: 100, `LOW_BATTERY`: 10, `CRITICAL_LOW`: 1, `CRITICALLY_LOW_BATTERY`: 1, `NOT_AVAILABLE`: `UNDEF`. |
|
||||
| low-battery | Switch | ☐ | Indicates whether the battery is low (`ON`) or OK (`OFF`). |
|
||||
|
||||
### Shutter Control
|
||||
|
||||
@ -107,6 +113,8 @@ Radiator thermostat
|
||||
| temperature | Number:Temperature | ☐ | Current measured temperature. |
|
||||
| valve-tappet-position | Number:Dimensionless | ☐ | Current open ratio of valve tappet (0 to 100). |
|
||||
| child-lock | Switch | ☑ | Indicates if child lock is active. |
|
||||
| battery-level | Number | ☐ | Current battery level percentage as integer number. Bosch-specific battery levels are mapped to numbers as follows: `OK`: 100, `LOW_BATTERY`: 10, `CRITICAL_LOW`: 1, `CRITICALLY_LOW_BATTERY`: 1, `NOT_AVAILABLE`: `UNDEF`. |
|
||||
| low-battery | Switch | ☐ | Indicates whether the battery is low (`ON`) or OK (`OFF`). |
|
||||
|
||||
### Climate Control
|
||||
|
||||
@ -129,6 +137,8 @@ Display of the current room temperature as well as the relative humidity in the
|
||||
| --------------- | -------------------- | :------: | ------------------------------------- |
|
||||
| temperature | Number:Temperature | ☐ | Current measured temperature. |
|
||||
| humidity | Number:Dimensionless | ☐ | Current measured humidity (0 to 100). |
|
||||
| battery-level | Number | ☐ | Current battery level percentage as integer number. Bosch-specific battery levels are mapped to numbers as follows: `OK`: 100, `LOW_BATTERY`: 10, `CRITICAL_LOW`: 1, `CRITICALLY_LOW_BATTERY`: 1, `NOT_AVAILABLE`: `UNDEF`. |
|
||||
| low-battery | Switch | ☐ | Indicates whether the battery is low (`ON`) or OK (`OFF`). |
|
||||
|
||||
### Security Camera 360
|
||||
|
||||
|
@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.boschshc.internal.devices;
|
||||
|
||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.boschshc.internal.devices.bridge.dto.DeviceServiceData;
|
||||
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
|
||||
import org.openhab.binding.boschshc.internal.services.batterylevel.BatteryLevel;
|
||||
import org.openhab.binding.boschshc.internal.services.batterylevel.BatteryLevelService;
|
||||
import org.openhab.core.thing.Thing;
|
||||
|
||||
/**
|
||||
* Abstract implementation for battery-powered devices.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AbstractBatteryPoweredDeviceHandler extends BoschSHCDeviceHandler {
|
||||
|
||||
/**
|
||||
* Service to monitor the battery level of the device
|
||||
*/
|
||||
private final BatteryLevelService batteryLevelService;
|
||||
|
||||
public AbstractBatteryPoweredDeviceHandler(Thing thing) {
|
||||
super(thing);
|
||||
this.batteryLevelService = new BatteryLevelService();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initializeServices() throws BoschSHCException {
|
||||
super.initializeServices();
|
||||
|
||||
registerService(batteryLevelService, this::updateChannels, List.of(CHANNEL_BATTERY_LEVEL, CHANNEL_LOW_BATTERY),
|
||||
true);
|
||||
}
|
||||
|
||||
private void updateChannels(DeviceServiceData deviceServiceData) {
|
||||
BatteryLevel batteryLevel = BatteryLevel.fromDeviceServiceData(deviceServiceData);
|
||||
super.updateState(CHANNEL_BATTERY_LEVEL, batteryLevel.toState());
|
||||
super.updateState(CHANNEL_LOW_BATTERY, batteryLevel.toLowBatteryState());
|
||||
}
|
||||
}
|
@ -74,6 +74,8 @@ public class BoschSHCBindingConstants {
|
||||
public static final String CHANNEL_ARM_ACTION = "arm-action";
|
||||
public static final String CHANNEL_DISARM_ACTION = "disarm-action";
|
||||
public static final String CHANNEL_MUTE_ACTION = "mute-action";
|
||||
public static final String CHANNEL_BATTERY_LEVEL = "battery-level";
|
||||
public static final String CHANNEL_LOW_BATTERY = "low-battery";
|
||||
|
||||
// static device/service names
|
||||
public static final String SERVICE_INTRUSION_DETECTION = "intrusionDetectionSystem";
|
||||
|
@ -161,7 +161,7 @@ public abstract class BoschSHCHandler extends BaseThingHandler {
|
||||
* @param serviceName Name of service the update came from.
|
||||
* @param stateData Current state of device service. Serialized as JSON.
|
||||
*/
|
||||
public void processUpdate(String serviceName, JsonElement stateData) {
|
||||
public void processUpdate(String serviceName, @Nullable JsonElement stateData) {
|
||||
// Check services of device to correctly
|
||||
for (DeviceService<? extends BoschSHCServiceState> deviceService : this.services) {
|
||||
BoschSHCService<? extends BoschSHCServiceState> service = deviceService.service;
|
||||
|
@ -77,7 +77,7 @@ public class BoschHttpClient extends HttpClient {
|
||||
/**
|
||||
* Returns the pairing URL for the Bosch SHC clients, using port 8443.
|
||||
* See https://github.com/BoschSmartHome/bosch-shc-api-docs/blob/master/postman/README.md
|
||||
*
|
||||
*
|
||||
* @return URL for pairing
|
||||
*/
|
||||
public String getPairingUrl() {
|
||||
@ -86,7 +86,7 @@ public class BoschHttpClient extends HttpClient {
|
||||
|
||||
/**
|
||||
* Returns a Bosch SHC URL for the endpoint, using port 8444.
|
||||
*
|
||||
*
|
||||
* @param endpoint a endpoint, see https://apidocs.bosch-smarthome.com/local/index.html
|
||||
* @return Bosch SHC URL for passed endpoint
|
||||
*/
|
||||
@ -96,7 +96,7 @@ public class BoschHttpClient extends HttpClient {
|
||||
|
||||
/**
|
||||
* Returns a SmartHome URL for the endpoint - shortcut of {@link BoschSslUtil::getBoschShcUrl()}
|
||||
*
|
||||
*
|
||||
* @param endpoint a endpoint, see https://apidocs.bosch-smarthome.com/local/index.html
|
||||
* @return SmartHome URL for passed endpoint
|
||||
*/
|
||||
@ -105,15 +105,41 @@ public class BoschHttpClient extends HttpClient {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a device & service URL.
|
||||
* Returns a URL to get or put a service state.
|
||||
* <p>
|
||||
* Example:
|
||||
*
|
||||
* <pre>
|
||||
* https://localhost:8444/smarthome/devices/hdm:ZigBee:000d6f0016d1cdae/services/AirQualityLevel/state
|
||||
* </pre>
|
||||
*
|
||||
* see https://apidocs.bosch-smarthome.com/local/index.html
|
||||
*
|
||||
*
|
||||
* @param serviceName the name of the service
|
||||
* @param deviceId the device identifier
|
||||
* @return SmartHome URL for passed endpoint
|
||||
* @return a URL to get or put a service state
|
||||
*/
|
||||
public String getServiceStateUrl(String serviceName, String deviceId) {
|
||||
return this.getBoschSmartHomeUrl(String.format("devices/%s/services/%s/state", deviceId, serviceName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a URL to get general information about a service.
|
||||
* <p>
|
||||
* Example:
|
||||
*
|
||||
* <pre>
|
||||
* https://localhost:8444/smarthome/devices/hdm:ZigBee:000d6f0016d1cdae/services/BatteryLevel
|
||||
* </pre>
|
||||
*
|
||||
* In some cases this URL has to be used to get the service state, for example for battery levels.
|
||||
*
|
||||
* @param serviceName the name of the service
|
||||
* @param deviceId the device identifier
|
||||
* @return a URL to retrieve general service information
|
||||
*/
|
||||
public String getServiceUrl(String serviceName, String deviceId) {
|
||||
return this.getBoschSmartHomeUrl(String.format("devices/%s/services/%s/state", deviceId, serviceName));
|
||||
return this.getBoschSmartHomeUrl(String.format("devices/%s/services/%s", deviceId, serviceName));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -177,7 +203,7 @@ public class BoschHttpClient extends HttpClient {
|
||||
/**
|
||||
* Pairs this client with the Bosch SHC.
|
||||
* Press pairing button on the Bosch Smart Home Controller!
|
||||
*
|
||||
*
|
||||
* @return true if pairing was successful, otherwise false
|
||||
* @throws InterruptedException in case of an interrupt
|
||||
*/
|
||||
@ -228,7 +254,7 @@ public class BoschHttpClient extends HttpClient {
|
||||
|
||||
/**
|
||||
* Creates a HTTP request.
|
||||
*
|
||||
*
|
||||
* @param url for the HTTP request
|
||||
* @param method for the HTTP request
|
||||
* @return created HTTP request instance
|
||||
@ -239,7 +265,7 @@ public class BoschHttpClient extends HttpClient {
|
||||
|
||||
/**
|
||||
* Creates a HTTP request.
|
||||
*
|
||||
*
|
||||
* @param url for the HTTP request
|
||||
* @param method for the HTTP request
|
||||
* @param content for the HTTP request
|
||||
@ -265,7 +291,7 @@ public class BoschHttpClient extends HttpClient {
|
||||
|
||||
/**
|
||||
* Sends a request and expects a response of the specified type.
|
||||
*
|
||||
*
|
||||
* @param request Request to send
|
||||
* @param responseContentClass Type of expected response
|
||||
* @param contentValidator Checks if the parsed response is valid
|
||||
|
@ -30,7 +30,7 @@ import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCHandler;
|
||||
import org.openhab.binding.boschshc.internal.devices.bridge.dto.Device;
|
||||
import org.openhab.binding.boschshc.internal.devices.bridge.dto.DeviceStatusUpdate;
|
||||
import org.openhab.binding.boschshc.internal.devices.bridge.dto.DeviceServiceData;
|
||||
import org.openhab.binding.boschshc.internal.devices.bridge.dto.LongPollResult;
|
||||
import org.openhab.binding.boschshc.internal.devices.bridge.dto.Room;
|
||||
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
|
||||
@ -51,6 +51,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
/**
|
||||
@ -299,52 +300,96 @@ public class BridgeHandler extends BaseBridgeHandler {
|
||||
/**
|
||||
* Bridge callback handler for the results of long polls.
|
||||
*
|
||||
* It will check the result and
|
||||
* forward the received to the bosch thing handlers.
|
||||
* It will check the results and
|
||||
* forward the received states to the Bosch thing handlers.
|
||||
*
|
||||
* @param result Results from Long Polling
|
||||
*/
|
||||
private void handleLongPollResult(LongPollResult result) {
|
||||
for (DeviceStatusUpdate update : result.result) {
|
||||
if (update != null && update.state != null) {
|
||||
logger.debug("Got update for service {} of type {}: {}", update.id, update.type, update.state);
|
||||
for (DeviceServiceData deviceServiceData : result.result) {
|
||||
handleDeviceServiceData(deviceServiceData);
|
||||
}
|
||||
}
|
||||
|
||||
var updateDeviceId = update.deviceId;
|
||||
if (updateDeviceId == null) {
|
||||
continue;
|
||||
}
|
||||
/**
|
||||
* Processes a single long poll result.
|
||||
*
|
||||
* @param deviceServiceData object representing a single long poll result
|
||||
*/
|
||||
private void handleDeviceServiceData(@Nullable DeviceServiceData deviceServiceData) {
|
||||
if (deviceServiceData != null) {
|
||||
JsonElement state = obtainState(deviceServiceData);
|
||||
|
||||
logger.debug("Got update for device {}", updateDeviceId);
|
||||
logger.debug("Got update for service {} of type {}: {}", deviceServiceData.id, deviceServiceData.type,
|
||||
state);
|
||||
|
||||
boolean handled = false;
|
||||
|
||||
Bridge bridge = this.getThing();
|
||||
for (Thing childThing : bridge.getThings()) {
|
||||
// All children of this should implement BoschSHCHandler
|
||||
@Nullable
|
||||
ThingHandler baseHandler = childThing.getHandler();
|
||||
if (baseHandler != null && baseHandler instanceof BoschSHCHandler) {
|
||||
BoschSHCHandler handler = (BoschSHCHandler) baseHandler;
|
||||
@Nullable
|
||||
String deviceId = handler.getBoschID();
|
||||
|
||||
handled = true;
|
||||
logger.debug("Registered device: {} - looking for {}", deviceId, updateDeviceId);
|
||||
|
||||
if (deviceId != null && updateDeviceId.equals(deviceId)) {
|
||||
logger.debug("Found child: {} - calling processUpdate (id: {}) with {}", handler, update.id,
|
||||
update.state);
|
||||
handler.processUpdate(update.id, update.state);
|
||||
}
|
||||
} else {
|
||||
logger.warn("longPoll: child handler for {} does not implement Bosch SHC handler", baseHandler);
|
||||
}
|
||||
}
|
||||
|
||||
if (!handled) {
|
||||
logger.debug("Could not find a thing for device ID: {}", updateDeviceId);
|
||||
}
|
||||
var updateDeviceId = deviceServiceData.deviceId;
|
||||
if (updateDeviceId == null || state == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
logger.debug("Got update for device {}", updateDeviceId);
|
||||
|
||||
forwardStateToHandlers(deviceServiceData, state, updateDeviceId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the actual state object from the given {@link DeviceServiceData} instance.
|
||||
* <p>
|
||||
* In some special cases like the <code>BatteryLevel</code> service the {@link DeviceServiceData} object itself
|
||||
* contains the state.
|
||||
* In all other cases, the state is contained in a sub-object named <code>state</code>.
|
||||
*
|
||||
* @param deviceServiceData the {@link DeviceServiceData} object from which the state should be obtained
|
||||
* @return the state sub-object or the {@link DeviceServiceData} object itself
|
||||
*/
|
||||
@Nullable
|
||||
private JsonElement obtainState(DeviceServiceData deviceServiceData) {
|
||||
// the battery level service receives no individual state object but rather requires the DeviceServiceData
|
||||
// structure
|
||||
if ("BatteryLevel".equals(deviceServiceData.id)) {
|
||||
return gson.toJsonTree(deviceServiceData);
|
||||
}
|
||||
|
||||
return deviceServiceData.state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to find handlers for the device with the given ID and forwards the received state to the handlers.
|
||||
*
|
||||
* @param deviceServiceData object representing updates received in long poll results
|
||||
* @param state the received state object as JSON element
|
||||
* @param updateDeviceId the ID of the device for which the state update was received
|
||||
*/
|
||||
private void forwardStateToHandlers(DeviceServiceData deviceServiceData, JsonElement state, String updateDeviceId) {
|
||||
boolean handled = false;
|
||||
|
||||
Bridge bridge = this.getThing();
|
||||
for (Thing childThing : bridge.getThings()) {
|
||||
// All children of this should implement BoschSHCHandler
|
||||
@Nullable
|
||||
ThingHandler baseHandler = childThing.getHandler();
|
||||
if (baseHandler != null && baseHandler instanceof BoschSHCHandler) {
|
||||
BoschSHCHandler handler = (BoschSHCHandler) baseHandler;
|
||||
@Nullable
|
||||
String deviceId = handler.getBoschID();
|
||||
|
||||
handled = true;
|
||||
logger.debug("Registered device: {} - looking for {}", deviceId, updateDeviceId);
|
||||
|
||||
if (deviceId != null && updateDeviceId.equals(deviceId)) {
|
||||
logger.debug("Found child: {} - calling processUpdate (id: {}) with {}", handler,
|
||||
deviceServiceData.id, state);
|
||||
handler.processUpdate(deviceServiceData.id, state);
|
||||
}
|
||||
} else {
|
||||
logger.warn("longPoll: child handler for {} does not implement Bosch SHC handler", baseHandler);
|
||||
}
|
||||
}
|
||||
|
||||
if (!handled) {
|
||||
logger.debug("Could not find a thing for device ID: {}", updateDeviceId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -447,7 +492,7 @@ public class BridgeHandler extends BaseBridgeHandler {
|
||||
* Query the Bosch Smart Home Controller for the state of the given device.
|
||||
* <p>
|
||||
* The URL used for retrieving the state has the following structure:
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* https://{IP}:8444/smarthome/devices/{deviceId}/services/{serviceName}/state
|
||||
* </pre>
|
||||
@ -470,14 +515,14 @@ public class BridgeHandler extends BaseBridgeHandler {
|
||||
return null;
|
||||
}
|
||||
|
||||
String url = httpClient.getServiceUrl(stateName, deviceId);
|
||||
String url = httpClient.getServiceStateUrl(stateName, deviceId);
|
||||
logger.debug("getState(): Requesting \"{}\" from Bosch: {} via {}", stateName, deviceId, url);
|
||||
return getState(httpClient, url, stateClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the Bosch Smart Home Controller for the state using an explicit endpoint.
|
||||
*
|
||||
*
|
||||
* @param <T> Type to which the resulting JSON should be deserialized to
|
||||
* @param endpoint The destination endpoint part of the URL
|
||||
* @param stateClass Class to convert the resulting JSON to
|
||||
@ -503,7 +548,7 @@ public class BridgeHandler extends BaseBridgeHandler {
|
||||
|
||||
/**
|
||||
* Sends a HTTP GET request in order to retrieve a state from the Bosch Smart Home Controller.
|
||||
*
|
||||
*
|
||||
* @param <T> Type to which the resulting JSON should be deserialized to
|
||||
* @param httpClient HTTP client used for sending the request
|
||||
* @param url URL at which the state should be retrieved
|
||||
@ -566,7 +611,7 @@ public class BridgeHandler extends BaseBridgeHandler {
|
||||
}
|
||||
|
||||
// Create request
|
||||
String url = httpClient.getServiceUrl(serviceName, deviceId);
|
||||
String url = httpClient.getServiceStateUrl(serviceName, deviceId);
|
||||
Request request = httpClient.createRequest(url, PUT, state);
|
||||
|
||||
// Send request
|
||||
@ -575,7 +620,7 @@ public class BridgeHandler extends BaseBridgeHandler {
|
||||
|
||||
/**
|
||||
* Sends a HTTP POST request without a request body to the given endpoint.
|
||||
*
|
||||
*
|
||||
* @param endpoint The destination endpoint part of the URL
|
||||
* @return the HTTP response
|
||||
* @throws InterruptedException
|
||||
@ -589,7 +634,7 @@ public class BridgeHandler extends BaseBridgeHandler {
|
||||
|
||||
/**
|
||||
* Sends a HTTP POST request with a request body to the given endpoint.
|
||||
*
|
||||
*
|
||||
* @param <T> Type of the request
|
||||
* @param endpoint The destination endpoint part of the URL
|
||||
* @param requestBody object representing the request body to be sent, may be <code>null</code>
|
||||
@ -611,4 +656,18 @@ public class BridgeHandler extends BaseBridgeHandler {
|
||||
Request request = httpClient.createRequest(url, POST, requestBody);
|
||||
return request.send();
|
||||
}
|
||||
|
||||
public @Nullable DeviceServiceData getServiceData(String deviceId, String serviceName)
|
||||
throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException {
|
||||
@Nullable
|
||||
BoschHttpClient httpClient = this.httpClient;
|
||||
if (httpClient == null) {
|
||||
logger.warn("HttpClient not initialized");
|
||||
return null;
|
||||
}
|
||||
|
||||
String url = httpClient.getServiceUrl(serviceName, deviceId);
|
||||
logger.debug("getState(): Requesting \"{}\" from Bosch: {} via {}", serviceName, deviceId, url);
|
||||
return getState(httpClient, url, DeviceServiceData.class);
|
||||
}
|
||||
}
|
||||
|
@ -13,9 +13,9 @@
|
||||
package org.openhab.binding.boschshc.internal.devices.bridge.dto;
|
||||
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.boschshc.internal.services.dto.BoschSHCServiceState;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Represents a device status update as represented by the Smart Home
|
||||
@ -24,18 +24,13 @@ import com.google.gson.annotations.SerializedName;
|
||||
* @author Stefan Kästle - Initial contribution
|
||||
* @author Christian Oeing - refactorings of e.g. server registration
|
||||
*/
|
||||
public class DeviceStatusUpdate {
|
||||
public class DeviceServiceData extends BoschSHCServiceState {
|
||||
|
||||
/**
|
||||
* Url path of the service the update came from.
|
||||
*/
|
||||
public String path;
|
||||
|
||||
/**
|
||||
* The type of message.
|
||||
*/
|
||||
@SerializedName("@type")
|
||||
public String type;
|
||||
|
||||
/**
|
||||
* Name of service the update came from.
|
||||
*/
|
||||
@ -44,15 +39,26 @@ public class DeviceStatusUpdate {
|
||||
/**
|
||||
* Current state of device. Serialized as JSON.
|
||||
*/
|
||||
public JsonElement state;
|
||||
public @Nullable JsonElement state;
|
||||
|
||||
/**
|
||||
* Id of device the update is for.
|
||||
*/
|
||||
public @Nullable String deviceId;
|
||||
|
||||
/**
|
||||
* An optional object containing information about device faults.
|
||||
* <p>
|
||||
* Example: low battery warnings are stored as faults with category <code>WARNING</code>
|
||||
*/
|
||||
public @Nullable Faults faults;
|
||||
|
||||
public DeviceServiceData() {
|
||||
super("DeviceServiceData");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.deviceId + "state: " + this.type;
|
||||
return this.deviceId + " state: " + this.type;
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.boschshc.internal.devices.bridge.dto;
|
||||
|
||||
/**
|
||||
* A fault entry containing a category and a type.
|
||||
* <p>
|
||||
* Example JSON:
|
||||
*
|
||||
* <pre>
|
||||
* {
|
||||
* "type":"LOW_BATTERY",
|
||||
* "category":"WARNING"
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class Fault {
|
||||
public String type;
|
||||
public String category;
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.boschshc.internal.devices.bridge.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A container object for faults that can be contained in {@link DeviceServiceData}.
|
||||
* <p>
|
||||
* Example JSON:
|
||||
*
|
||||
* <pre>
|
||||
* "faults": {
|
||||
* "entries": [
|
||||
* {
|
||||
* "type":"LOW_BATTERY",
|
||||
* "category":"WARNING"
|
||||
* }
|
||||
* ]
|
||||
}
|
||||
* </pre>
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class Faults {
|
||||
|
||||
public List<Fault> entries;
|
||||
}
|
@ -35,6 +35,6 @@ public class LongPollResult {
|
||||
* ],"jsonrpc":"2.0"}
|
||||
*/
|
||||
|
||||
public ArrayList<DeviceStatusUpdate> result;
|
||||
public ArrayList<DeviceServiceData> result;
|
||||
public String jsonrpc;
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConst
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCDeviceHandler;
|
||||
import org.openhab.binding.boschshc.internal.devices.AbstractBatteryPoweredDeviceHandler;
|
||||
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
|
||||
import org.openhab.binding.boschshc.internal.services.latestmotion.LatestMotionService;
|
||||
import org.openhab.binding.boschshc.internal.services.latestmotion.dto.LatestMotionServiceState;
|
||||
@ -32,7 +32,7 @@ import org.openhab.core.thing.Thing;
|
||||
* @author Christian Oeing - Use service instead of custom logic
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class MotionDetectorHandler extends BoschSHCDeviceHandler {
|
||||
public class MotionDetectorHandler extends AbstractBatteryPoweredDeviceHandler {
|
||||
|
||||
public MotionDetectorHandler(Thing thing) {
|
||||
super(thing);
|
||||
|
@ -12,14 +12,12 @@
|
||||
*/
|
||||
package org.openhab.binding.boschshc.internal.devices.thermostat;
|
||||
|
||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_CHILD_LOCK;
|
||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_TEMPERATURE;
|
||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_VALVE_TAPPET_POSITION;
|
||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCDeviceHandler;
|
||||
import org.openhab.binding.boschshc.internal.devices.AbstractBatteryPoweredDeviceHandler;
|
||||
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
|
||||
import org.openhab.binding.boschshc.internal.services.childlock.ChildLockService;
|
||||
import org.openhab.binding.boschshc.internal.services.childlock.dto.ChildLockServiceState;
|
||||
@ -33,11 +31,11 @@ import org.openhab.core.types.Command;
|
||||
|
||||
/**
|
||||
* Handler for a thermostat device.
|
||||
*
|
||||
*
|
||||
* @author Christian Oeing - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public final class ThermostatHandler extends BoschSHCDeviceHandler {
|
||||
public final class ThermostatHandler extends AbstractBatteryPoweredDeviceHandler {
|
||||
|
||||
private ChildLockService childLockService;
|
||||
|
||||
@ -48,6 +46,8 @@ public final class ThermostatHandler extends BoschSHCDeviceHandler {
|
||||
|
||||
@Override
|
||||
protected void initializeServices() throws BoschSHCException {
|
||||
super.initializeServices();
|
||||
|
||||
this.createService(TemperatureLevelService::new, this::updateChannels, List.of(CHANNEL_TEMPERATURE));
|
||||
this.createService(ValveTappetService::new, this::updateChannels, List.of(CHANNEL_VALVE_TAPPET_POSITION));
|
||||
this.registerService(this.childLockService, this::updateChannels, List.of(CHANNEL_CHILD_LOCK));
|
||||
@ -67,7 +67,7 @@ public final class ThermostatHandler extends BoschSHCDeviceHandler {
|
||||
/**
|
||||
* Updates the channels which are linked to the {@link TemperatureLevelService}
|
||||
* of the device.
|
||||
*
|
||||
*
|
||||
* @param state Current state of {@link TemperatureLevelService}.
|
||||
*/
|
||||
private void updateChannels(TemperatureLevelServiceState state) {
|
||||
@ -77,7 +77,7 @@ public final class ThermostatHandler extends BoschSHCDeviceHandler {
|
||||
/**
|
||||
* Updates the channels which are linked to the {@link ValveTappetService} of
|
||||
* the device.
|
||||
*
|
||||
*
|
||||
* @param state Current state of {@link ValveTappetService}.
|
||||
*/
|
||||
private void updateChannels(ValveTappetServiceState state) {
|
||||
@ -87,7 +87,7 @@ public final class ThermostatHandler extends BoschSHCDeviceHandler {
|
||||
/**
|
||||
* Updates the channels which are linked to the {@link ChildLockService} of the
|
||||
* device.
|
||||
*
|
||||
*
|
||||
* @param state Current state of {@link ChildLockService}.
|
||||
*/
|
||||
private void updateChannels(ChildLockServiceState state) {
|
||||
|
@ -12,14 +12,7 @@
|
||||
*/
|
||||
package org.openhab.binding.boschshc.internal.devices.twinguard;
|
||||
|
||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_AIR_DESCRIPTION;
|
||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_COMBINED_RATING;
|
||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_HUMIDITY;
|
||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_HUMIDITY_RATING;
|
||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_PURITY;
|
||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_PURITY_RATING;
|
||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_TEMPERATURE;
|
||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_TEMPERATURE_RATING;
|
||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -27,7 +20,7 @@ import javax.measure.quantity.Dimensionless;
|
||||
import javax.measure.quantity.Temperature;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCDeviceHandler;
|
||||
import org.openhab.binding.boschshc.internal.devices.AbstractBatteryPoweredDeviceHandler;
|
||||
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
|
||||
import org.openhab.binding.boschshc.internal.services.airqualitylevel.AirQualityLevelService;
|
||||
import org.openhab.binding.boschshc.internal.services.airqualitylevel.dto.AirQualityLevelServiceState;
|
||||
@ -44,7 +37,7 @@ import org.openhab.core.thing.Thing;
|
||||
* @author Christian Oeing - Use service instead of custom logic
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class TwinguardHandler extends BoschSHCDeviceHandler {
|
||||
public class TwinguardHandler extends AbstractBatteryPoweredDeviceHandler {
|
||||
|
||||
public TwinguardHandler(Thing thing) {
|
||||
super(thing);
|
||||
|
@ -12,13 +12,12 @@
|
||||
*/
|
||||
package org.openhab.binding.boschshc.internal.devices.wallthermostat;
|
||||
|
||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_HUMIDITY;
|
||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_TEMPERATURE;
|
||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCDeviceHandler;
|
||||
import org.openhab.binding.boschshc.internal.devices.AbstractBatteryPoweredDeviceHandler;
|
||||
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
|
||||
import org.openhab.binding.boschshc.internal.services.humiditylevel.HumidityLevelService;
|
||||
import org.openhab.binding.boschshc.internal.services.humiditylevel.dto.HumidityLevelServiceState;
|
||||
@ -28,11 +27,11 @@ import org.openhab.core.thing.Thing;
|
||||
|
||||
/**
|
||||
* Handler for a wall thermostat device.
|
||||
*
|
||||
*
|
||||
* @author Christian Oeing - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public final class WallThermostatHandler extends BoschSHCDeviceHandler {
|
||||
public final class WallThermostatHandler extends AbstractBatteryPoweredDeviceHandler {
|
||||
|
||||
public WallThermostatHandler(Thing thing) {
|
||||
super(thing);
|
||||
@ -40,13 +39,15 @@ public final class WallThermostatHandler extends BoschSHCDeviceHandler {
|
||||
|
||||
@Override
|
||||
protected void initializeServices() throws BoschSHCException {
|
||||
super.initializeServices();
|
||||
|
||||
this.createService(TemperatureLevelService::new, this::updateChannels, List.of(CHANNEL_TEMPERATURE));
|
||||
this.createService(HumidityLevelService::new, this::updateChannels, List.of(CHANNEL_HUMIDITY));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the channels which are linked to the {@link TemperatureLevelService} of the device.
|
||||
*
|
||||
*
|
||||
* @param state Current state of {@link TemperatureLevelService}.
|
||||
*/
|
||||
private void updateChannels(TemperatureLevelServiceState state) {
|
||||
@ -55,7 +56,7 @@ public final class WallThermostatHandler extends BoschSHCDeviceHandler {
|
||||
|
||||
/**
|
||||
* Updates the channels which are linked to the {@link HumidityLevelService} of the device.
|
||||
*
|
||||
*
|
||||
* @param state Current state of {@link HumidityLevelService}.
|
||||
*/
|
||||
private void updateChannels(HumidityLevelServiceState state) {
|
||||
|
@ -17,7 +17,7 @@ import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConst
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCDeviceHandler;
|
||||
import org.openhab.binding.boschshc.internal.devices.AbstractBatteryPoweredDeviceHandler;
|
||||
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
|
||||
import org.openhab.binding.boschshc.internal.services.shuttercontact.ShutterContactService;
|
||||
import org.openhab.binding.boschshc.internal.services.shuttercontact.ShutterContactState;
|
||||
@ -32,7 +32,7 @@ import org.openhab.core.types.State;
|
||||
* @author Stefan Kästle - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class WindowContactHandler extends BoschSHCDeviceHandler {
|
||||
public class WindowContactHandler extends AbstractBatteryPoweredDeviceHandler {
|
||||
|
||||
public WindowContactHandler(Thing thing) {
|
||||
super(thing);
|
||||
@ -40,6 +40,8 @@ public class WindowContactHandler extends BoschSHCDeviceHandler {
|
||||
|
||||
@Override
|
||||
protected void initializeServices() throws BoschSHCException {
|
||||
super.initializeServices();
|
||||
|
||||
this.createService(ShutterContactService::new, this::updateChannels, List.of(CHANNEL_CONTACT));
|
||||
}
|
||||
|
||||
|
@ -32,17 +32,17 @@ import com.google.gson.JsonElement;
|
||||
* same endpoint.
|
||||
* <p>
|
||||
* The endpoints of this service have the following URL structure:
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* https://{IP}:8444/smarthome/devices/{deviceId}/services/{serviceName}/state
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* The HTTP client of the bridge will use <code>GET</code> requests to retrieve the state and <code>PUT</code> requests
|
||||
* to set the state.
|
||||
* <p>
|
||||
* The services of the devices and their official APIs can be found
|
||||
* <a href="https://apidocs.bosch-smarthome.com/local/">here</a>.
|
||||
*
|
||||
*
|
||||
* @author Christian Oeing - Initial contribution
|
||||
* @author David Pace - Service abstraction
|
||||
*/
|
||||
@ -63,7 +63,7 @@ public abstract class BoschSHCService<TState extends BoschSHCServiceState> exten
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
*
|
||||
* @param serviceName Unique name of the service.
|
||||
* @param stateClass State class that this service uses for data transfers
|
||||
* from/to the device.
|
||||
@ -75,7 +75,7 @@ public abstract class BoschSHCService<TState extends BoschSHCServiceState> exten
|
||||
|
||||
/**
|
||||
* Initializes the service
|
||||
*
|
||||
*
|
||||
* @param bridgeHandler Bridge to use for communication from/to the device
|
||||
* @param deviceId Id of device this service is for
|
||||
* @param stateUpdateListener Function to call when a state update was received
|
||||
@ -89,7 +89,7 @@ public abstract class BoschSHCService<TState extends BoschSHCServiceState> exten
|
||||
|
||||
/**
|
||||
* Returns the class of the state this service provides.
|
||||
*
|
||||
*
|
||||
* @return Class of the state this service provides.
|
||||
*/
|
||||
public Class<TState> getStateClass() {
|
||||
@ -98,7 +98,7 @@ public abstract class BoschSHCService<TState extends BoschSHCServiceState> exten
|
||||
|
||||
/**
|
||||
* Requests the current state of the service and updates it.
|
||||
*
|
||||
*
|
||||
* @throws ExecutionException
|
||||
* @throws TimeoutException
|
||||
* @throws InterruptedException
|
||||
@ -114,7 +114,7 @@ public abstract class BoschSHCService<TState extends BoschSHCServiceState> exten
|
||||
|
||||
/**
|
||||
* Requests the current state of the device with the specified id.
|
||||
*
|
||||
*
|
||||
* @return Current state of the device.
|
||||
* @throws ExecutionException
|
||||
* @throws TimeoutException
|
||||
@ -136,7 +136,7 @@ public abstract class BoschSHCService<TState extends BoschSHCServiceState> exten
|
||||
|
||||
/**
|
||||
* Sets the state of the device with the specified id.
|
||||
*
|
||||
*
|
||||
* @param state State to set.
|
||||
* @throws InterruptedException
|
||||
* @throws ExecutionException
|
||||
@ -156,10 +156,10 @@ public abstract class BoschSHCService<TState extends BoschSHCServiceState> exten
|
||||
|
||||
/**
|
||||
* A state update was received from the bridge
|
||||
*
|
||||
*
|
||||
* @param stateData Current state of service. Serialized as JSON.
|
||||
*/
|
||||
public void onStateUpdate(JsonElement stateData) {
|
||||
public void onStateUpdate(@Nullable JsonElement stateData) {
|
||||
@Nullable
|
||||
TState state = BoschSHCServiceState.fromJson(stateData, this.stateClass);
|
||||
if (state == null) {
|
||||
@ -171,7 +171,7 @@ public abstract class BoschSHCService<TState extends BoschSHCServiceState> exten
|
||||
|
||||
/**
|
||||
* A state update was received from the bridge.
|
||||
*
|
||||
*
|
||||
* @param state Current state of service as an instance of the state class.
|
||||
*/
|
||||
private void onStateUpdate(TState state) {
|
||||
@ -184,7 +184,7 @@ public abstract class BoschSHCService<TState extends BoschSHCServiceState> exten
|
||||
/**
|
||||
* Allows a service to handle a command and create a new state out of it.
|
||||
* The new state still has to be set via setState.
|
||||
*
|
||||
*
|
||||
* @param command Command to handle
|
||||
* @throws BoschSHCException If service can not handle command
|
||||
*/
|
||||
|
@ -0,0 +1,119 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.boschshc.internal.services.batterylevel;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.boschshc.internal.devices.bridge.dto.DeviceServiceData;
|
||||
import org.openhab.binding.boschshc.internal.devices.bridge.dto.Fault;
|
||||
import org.openhab.binding.boschshc.internal.devices.bridge.dto.Faults;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
|
||||
/**
|
||||
* Possible battery levels.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum BatteryLevel {
|
||||
OK,
|
||||
LOW_BATTERY,
|
||||
CRITICAL_LOW,
|
||||
CRITICALLY_LOW_BATTERY,
|
||||
NOT_AVAILABLE;
|
||||
|
||||
/**
|
||||
* Derives a battery level by analyzing the fault elements in the given device service data.
|
||||
* <p>
|
||||
* Note that no fault elements are present when the battery level is OK.
|
||||
*
|
||||
* @param deviceServiceData a device service data model
|
||||
* @return the derived battery level
|
||||
*/
|
||||
public static BatteryLevel fromDeviceServiceData(DeviceServiceData deviceServiceData) {
|
||||
Faults faults = deviceServiceData.faults;
|
||||
if (faults == null || faults.entries == null || faults.entries.isEmpty()) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
for (Fault faultEntry : faults.entries) {
|
||||
if ("warning".equalsIgnoreCase(faultEntry.category)) {
|
||||
BatteryLevel batteryLevelState = BatteryLevel.get(faultEntry.type);
|
||||
if (batteryLevelState != null) {
|
||||
return batteryLevelState;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the corresponding battery level for the given string or <code>null</code> if no state matches.
|
||||
*
|
||||
* @param identifier the battery level identifier
|
||||
*
|
||||
* @return the matching battery level or <code>null</code>
|
||||
*/
|
||||
public static @Nullable BatteryLevel get(String identifier) {
|
||||
for (BatteryLevel batteryLevelState : values()) {
|
||||
if (batteryLevelState.toString().equalsIgnoreCase(identifier)) {
|
||||
return batteryLevelState;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a Bosch-specific battery level to a percentage for the <code>system.battery-level</code> channel.
|
||||
*
|
||||
* @return a percentage between 0 and 100 as integer
|
||||
*/
|
||||
public State toState() {
|
||||
switch (this) {
|
||||
case LOW_BATTERY:
|
||||
return new DecimalType(10);
|
||||
case CRITICAL_LOW:
|
||||
case CRITICALLY_LOW_BATTERY:
|
||||
return new DecimalType(1);
|
||||
case NOT_AVAILABLE:
|
||||
return UnDefType.UNDEF;
|
||||
default:
|
||||
return new DecimalType(100);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a Bosch-specific battery level to an <code>ON</code>/<code>OFF</code> state for the
|
||||
* <code>system.low-battery</code> channel.
|
||||
* <p>
|
||||
* If the result is <code>ON</code>, the battery is low; if the result is <code>OFF</code> the battery level is OK.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public OnOffType toLowBatteryState() {
|
||||
switch (this) {
|
||||
case LOW_BATTERY:
|
||||
case CRITICAL_LOW:
|
||||
case CRITICALLY_LOW_BATTERY:
|
||||
return OnOffType.ON;
|
||||
default:
|
||||
return OnOffType.OFF;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.boschshc.internal.services.batterylevel;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.boschshc.internal.devices.bridge.BridgeHandler;
|
||||
import org.openhab.binding.boschshc.internal.devices.bridge.dto.DeviceServiceData;
|
||||
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
|
||||
import org.openhab.binding.boschshc.internal.services.BoschSHCService;
|
||||
|
||||
/**
|
||||
* Service to retrieve battery levels.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class BatteryLevelService extends BoschSHCService<DeviceServiceData> {
|
||||
|
||||
public BatteryLevelService() {
|
||||
super("BatteryLevel", DeviceServiceData.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable DeviceServiceData getState()
|
||||
throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException {
|
||||
|
||||
String deviceId = getDeviceId();
|
||||
if (deviceId == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
BridgeHandler bridgeHandler = getBridgeHandler();
|
||||
if (bridgeHandler == null) {
|
||||
return null;
|
||||
}
|
||||
return bridgeHandler.getServiceData(deviceId, getServiceName());
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@ import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Base Bosch Smart Home Controller service state.
|
||||
*
|
||||
*
|
||||
* @author Christian Oeing - Initial contribution
|
||||
*/
|
||||
public class BoschSHCServiceState {
|
||||
@ -40,7 +40,7 @@ public class BoschSHCServiceState {
|
||||
private @Nullable String stateType = null;
|
||||
|
||||
@SerializedName("@type")
|
||||
private final String type;
|
||||
public final String type;
|
||||
|
||||
protected BoschSHCServiceState(String type) {
|
||||
this.type = type;
|
||||
|
@ -53,7 +53,7 @@
|
||||
<bridge-type-ref id="shc"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>TwinGuard</label>
|
||||
<label>Twinguard</label>
|
||||
<description>The Twinguard smoke detector warns you in case of fire and constantly monitors the air.</description>
|
||||
|
||||
<channels>
|
||||
@ -65,6 +65,8 @@
|
||||
<channel id="air-description" typeId="air-description"/>
|
||||
<channel id="purity-rating" typeId="purity-rating"/>
|
||||
<channel id="combined-rating" typeId="combined-rating"/>
|
||||
<channel id="battery-level" typeId="system.battery-level"/>
|
||||
<channel id="low-battery" typeId="system.low-battery"/>
|
||||
</channels>
|
||||
|
||||
<config-description-ref uri="thing-type:boschshc:device"/>
|
||||
@ -81,6 +83,8 @@
|
||||
|
||||
<channels>
|
||||
<channel id="contact" typeId="contact"/>
|
||||
<channel id="battery-level" typeId="system.battery-level"/>
|
||||
<channel id="low-battery" typeId="system.low-battery"/>
|
||||
</channels>
|
||||
|
||||
<config-description-ref uri="thing-type:boschshc:device"/>
|
||||
@ -98,6 +102,8 @@
|
||||
|
||||
<channels>
|
||||
<channel id="latest-motion" typeId="latest-motion"/>
|
||||
<channel id="battery-level" typeId="system.battery-level"/>
|
||||
<channel id="low-battery" typeId="system.low-battery"/>
|
||||
</channels>
|
||||
|
||||
<config-description-ref uri="thing-type:boschshc:device"/>
|
||||
@ -132,6 +138,8 @@
|
||||
<channel id="temperature" typeId="temperature"/>
|
||||
<channel id="valve-tappet-position" typeId="valve-tappet-position"/>
|
||||
<channel id="child-lock" typeId="child-lock"/>
|
||||
<channel id="battery-level" typeId="system.battery-level"/>
|
||||
<channel id="low-battery" typeId="system.low-battery"/>
|
||||
</channels>
|
||||
|
||||
<config-description-ref uri="thing-type:boschshc:device"/>
|
||||
@ -167,6 +175,8 @@
|
||||
<channels>
|
||||
<channel id="temperature" typeId="temperature"/>
|
||||
<channel id="humidity" typeId="humidity"/>
|
||||
<channel id="battery-level" typeId="system.battery-level"/>
|
||||
<channel id="low-battery" typeId="system.low-battery"/>
|
||||
</channels>
|
||||
|
||||
<config-description-ref uri="thing-type:boschshc:device"/>
|
||||
|
@ -0,0 +1,113 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.boschshc.internal.devices;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
/**
|
||||
* Abstract test implementation for battery-powered devices.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
* @param <T> type of the battery-powered device to be tested
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class AbstractBatteryPoweredDeviceHandlerTest<T extends AbstractBatteryPoweredDeviceHandler>
|
||||
extends AbstractBoschSHCDeviceHandlerTest<T> {
|
||||
|
||||
@Test
|
||||
public void testProcessUpdate_BatteryLevel_LowBattery() {
|
||||
JsonElement deviceServiceData = JsonParser.parseString("{ \n" + " \"@type\":\"DeviceServiceData\",\n"
|
||||
+ " \"path\":\"/devices/hdm:ZigBee:000d6f0004b93361/services/BatteryLevel\",\n"
|
||||
+ " \"id\":\"BatteryLevel\",\n" + " \"deviceId\":\"hdm:ZigBee:000d6f0004b93361\",\n"
|
||||
+ " \"faults\":{ \n" + " \"entries\":[\n" + " {\n"
|
||||
+ " \"type\":\"LOW_BATTERY\",\n" + " \"category\":\"WARNING\"\n" + " }\n"
|
||||
+ " ]\n" + " }\n" + "}");
|
||||
getFixture().processUpdate("BatteryLevel", deviceServiceData);
|
||||
verify(getCallback()).stateUpdated(
|
||||
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_BATTERY_LEVEL),
|
||||
new DecimalType(10));
|
||||
verify(getCallback()).stateUpdated(
|
||||
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_LOW_BATTERY), OnOffType.ON);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessUpdate_BatteryLevel_CriticalLow() {
|
||||
JsonElement deviceServiceData = JsonParser.parseString("{ \n" + " \"@type\":\"DeviceServiceData\",\n"
|
||||
+ " \"path\":\"/devices/hdm:ZigBee:000d6f0004b93361/services/BatteryLevel\",\n"
|
||||
+ " \"id\":\"BatteryLevel\",\n" + " \"deviceId\":\"hdm:ZigBee:000d6f0004b93361\",\n"
|
||||
+ " \"faults\":{ \n" + " \"entries\":[\n" + " {\n"
|
||||
+ " \"type\":\"CRITICAL_LOW\",\n" + " \"category\":\"WARNING\"\n"
|
||||
+ " }\n" + " ]\n" + " }\n" + "}");
|
||||
getFixture().processUpdate("BatteryLevel", deviceServiceData);
|
||||
verify(getCallback()).stateUpdated(
|
||||
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_BATTERY_LEVEL),
|
||||
new DecimalType(1));
|
||||
verify(getCallback()).stateUpdated(
|
||||
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_LOW_BATTERY), OnOffType.ON);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessUpdate_BatteryLevel_CriticallyLowBattery() {
|
||||
JsonElement deviceServiceData = JsonParser.parseString("{ \n" + " \"@type\":\"DeviceServiceData\",\n"
|
||||
+ " \"path\":\"/devices/hdm:ZigBee:000d6f0004b93361/services/BatteryLevel\",\n"
|
||||
+ " \"id\":\"BatteryLevel\",\n" + " \"deviceId\":\"hdm:ZigBee:000d6f0004b93361\",\n"
|
||||
+ " \"faults\":{ \n" + " \"entries\":[\n" + " {\n"
|
||||
+ " \"type\":\"CRITICALLY_LOW_BATTERY\",\n" + " \"category\":\"WARNING\"\n"
|
||||
+ " }\n" + " ]\n" + " }\n" + "}");
|
||||
getFixture().processUpdate("BatteryLevel", deviceServiceData);
|
||||
verify(getCallback()).stateUpdated(
|
||||
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_BATTERY_LEVEL),
|
||||
new DecimalType(1));
|
||||
verify(getCallback()).stateUpdated(
|
||||
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_LOW_BATTERY), OnOffType.ON);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessUpdate_BatteryLevel_OK() {
|
||||
JsonElement deviceServiceData = JsonParser.parseString("{ \n" + " \"@type\":\"DeviceServiceData\",\n"
|
||||
+ " \"path\":\"/devices/hdm:ZigBee:000d6f0004b93361/services/BatteryLevel\",\n"
|
||||
+ " \"id\":\"BatteryLevel\",\n" + " \"deviceId\":\"hdm:ZigBee:000d6f0004b93361\" }");
|
||||
getFixture().processUpdate("BatteryLevel", deviceServiceData);
|
||||
verify(getCallback()).stateUpdated(
|
||||
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_BATTERY_LEVEL),
|
||||
new DecimalType(100));
|
||||
verify(getCallback()).stateUpdated(
|
||||
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_LOW_BATTERY), OnOffType.OFF);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessUpdate_BatteryLevel_NotAvailable() {
|
||||
JsonElement deviceServiceData = JsonParser.parseString("{ \n" + " \"@type\":\"DeviceServiceData\",\n"
|
||||
+ " \"path\":\"/devices/hdm:ZigBee:000d6f0004b93361/services/BatteryLevel\",\n"
|
||||
+ " \"id\":\"BatteryLevel\",\n" + " \"deviceId\":\"hdm:ZigBee:000d6f0004b93361\",\n"
|
||||
+ " \"faults\":{ \n" + " \"entries\":[\n" + " {\n"
|
||||
+ " \"type\":\"NOT_AVAILABLE\",\n" + " \"category\":\"WARNING\"\n"
|
||||
+ " }\n" + " ]\n" + " }\n" + "}");
|
||||
getFixture().processUpdate("BatteryLevel", deviceServiceData);
|
||||
verify(getCallback()).stateUpdated(
|
||||
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_BATTERY_LEVEL), UnDefType.UNDEF);
|
||||
verify(getCallback()).stateUpdated(
|
||||
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_LOW_BATTERY), OnOffType.OFF);
|
||||
}
|
||||
}
|
@ -31,7 +31,6 @@ import org.openhab.binding.boschshc.internal.services.powerswitch.dto.PowerSwitc
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
@ -60,8 +59,6 @@ public abstract class AbstractPowerSwitchHandlerTest<T extends AbstractPowerSwit
|
||||
public void testHandleCommand()
|
||||
throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException {
|
||||
|
||||
when(getThing().getUID()).thenReturn(new ThingUID("boschshc", "abcdef"));
|
||||
|
||||
getFixture().handleCommand(new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_POWER_SWITCH),
|
||||
OnOffType.ON);
|
||||
verify(getBridgeHandler()).putState(eq(getDeviceID()), eq("PowerSwitch"), serviceStateCaptor.capture());
|
||||
@ -76,12 +73,8 @@ public abstract class AbstractPowerSwitchHandlerTest<T extends AbstractPowerSwit
|
||||
assertSame(PowerSwitchState.OFF, state.switchState);
|
||||
}
|
||||
|
||||
protected abstract ThingTypeUID getThingTypeUID();
|
||||
|
||||
@Test
|
||||
public void testUpdateChannel_PowerSwitchState() {
|
||||
when(getThing().getUID()).thenReturn(new ThingUID("boschshc", "abcdef"));
|
||||
|
||||
JsonElement jsonObject = JsonParser
|
||||
.parseString("{\n" + " \"@type\": \"powerSwitchState\",\n" + " \"switchState\": \"ON\"\n" + "}");
|
||||
getFixture().processUpdate("PowerSwitch", jsonObject);
|
||||
@ -97,8 +90,6 @@ public abstract class AbstractPowerSwitchHandlerTest<T extends AbstractPowerSwit
|
||||
|
||||
@Test
|
||||
public void testUpdateChannel_PowerMeterServiceState() {
|
||||
when(getThing().getUID()).thenReturn(new ThingUID("boschshc", "abcdef"));
|
||||
|
||||
JsonElement jsonObject = JsonParser.parseString("{\n" + " \"@type\": \"powerMeterState\",\n"
|
||||
+ " \"powerConsumption\": \"23\",\n" + " \"energyConsumption\": 42\n" + "}");
|
||||
getFixture().processUpdate("PowerMeter", jsonObject);
|
||||
|
@ -27,6 +27,7 @@ import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.ThingStatusInfo;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.thing.binding.ThingHandlerCallback;
|
||||
|
||||
@ -57,6 +58,7 @@ public abstract class AbstractSHCHandlerTest<T extends BoschSHCHandler> {
|
||||
@BeforeEach
|
||||
public void beforeEach() {
|
||||
fixture = createFixture();
|
||||
lenient().when(thing.getUID()).thenReturn(getThingUID());
|
||||
when(thing.getBridgeUID()).thenReturn(new ThingUID("boschshc", "shc", "myBridgeUID"));
|
||||
when(callback.getBridge(any())).thenReturn(bridge);
|
||||
fixture.setCallback(callback);
|
||||
@ -72,6 +74,12 @@ public abstract class AbstractSHCHandlerTest<T extends BoschSHCHandler> {
|
||||
return fixture;
|
||||
}
|
||||
|
||||
protected ThingUID getThingUID() {
|
||||
return new ThingUID(getThingTypeUID(), "abcdef");
|
||||
}
|
||||
|
||||
protected abstract ThingTypeUID getThingTypeUID();
|
||||
|
||||
protected Configuration getConfiguration() {
|
||||
return new Configuration();
|
||||
}
|
||||
|
@ -71,10 +71,16 @@ class BoschHttpClientTest {
|
||||
|
||||
@Test
|
||||
void getServiceUrl() {
|
||||
assertEquals("https://127.0.0.1:8444/smarthome/devices/testDevice/services/testService/state",
|
||||
assertEquals("https://127.0.0.1:8444/smarthome/devices/testDevice/services/testService",
|
||||
httpClient.getServiceUrl("testService", "testDevice"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getServiceStateUrl() {
|
||||
assertEquals("https://127.0.0.1:8444/smarthome/devices/testDevice/services/testService/state",
|
||||
httpClient.getServiceStateUrl("testService", "testDevice"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isAccessPossible() throws InterruptedException {
|
||||
assertFalse(httpClient.isAccessPossible());
|
||||
|
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.boschshc.internal.devices.motiondetector;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.boschshc.internal.devices.AbstractBatteryPoweredDeviceHandlerTest;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link MotionDetectorHandler}.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class MotionDetectorHandlerTest extends AbstractBatteryPoweredDeviceHandlerTest<MotionDetectorHandler> {
|
||||
|
||||
@Override
|
||||
protected MotionDetectorHandler createFixture() {
|
||||
return new MotionDetectorHandler(getThing());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDeviceID() {
|
||||
return "hdm:ZigBee:000d6f0012fd2571";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ThingTypeUID getThingTypeUID() {
|
||||
return BoschSHCBindingConstants.THING_TYPE_MOTION_DETECTOR;
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.boschshc.internal.devices.thermostat;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.boschshc.internal.devices.AbstractBatteryPoweredDeviceHandlerTest;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link ThermostatHandler}.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ThermostatHandlerTest extends AbstractBatteryPoweredDeviceHandlerTest<ThermostatHandler> {
|
||||
|
||||
@Override
|
||||
protected ThermostatHandler createFixture() {
|
||||
return new ThermostatHandler(getThing());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDeviceID() {
|
||||
return "hdm:ZigBee:000d6f0017f1ace2";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ThingTypeUID getThingTypeUID() {
|
||||
return BoschSHCBindingConstants.THING_TYPE_THERMOSTAT;
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.boschshc.internal.devices.twinguard;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.boschshc.internal.devices.AbstractBatteryPoweredDeviceHandlerTest;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link TwinguardHandler}.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class TwinguardHandlerTest extends AbstractBatteryPoweredDeviceHandlerTest<TwinguardHandler> {
|
||||
|
||||
@Override
|
||||
protected TwinguardHandler createFixture() {
|
||||
return new TwinguardHandler(getThing());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDeviceID() {
|
||||
return "hdm:ZigBee:000d6f0016d1a193";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ThingTypeUID getThingTypeUID() {
|
||||
return BoschSHCBindingConstants.THING_TYPE_TWINGUARD;
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.boschshc.internal.devices.wallthermostat;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.boschshc.internal.devices.AbstractBatteryPoweredDeviceHandlerTest;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link WallThermostatHandler}.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class WallThermostatHandlerTest extends AbstractBatteryPoweredDeviceHandlerTest<WallThermostatHandler> {
|
||||
|
||||
@Override
|
||||
protected WallThermostatHandler createFixture() {
|
||||
return new WallThermostatHandler(getThing());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDeviceID() {
|
||||
return "hdm:ZigBee:000d6f0016d1a193";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ThingTypeUID getThingTypeUID() {
|
||||
return BoschSHCBindingConstants.THING_TYPE_WALL_THERMOSTAT;
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.boschshc.internal.devices.windowcontact;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.boschshc.internal.devices.AbstractBatteryPoweredDeviceHandlerTest;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link WindowContactHandler}.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class WindowContactHandlerTest extends AbstractBatteryPoweredDeviceHandlerTest<WindowContactHandler> {
|
||||
|
||||
@Override
|
||||
protected WindowContactHandler createFixture() {
|
||||
return new WindowContactHandler(getThing());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDeviceID() {
|
||||
return "hdm:HomeMaticIP:3014D711A000009D545DEB39D";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ThingTypeUID getThingTypeUID() {
|
||||
return BoschSHCBindingConstants.THING_TYPE_WINDOW_CONTACT;
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.boschshc.internal.services.batterylevel;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.binding.boschshc.internal.devices.bridge.dto.DeviceServiceData;
|
||||
import org.openhab.binding.boschshc.internal.devices.bridge.dto.Fault;
|
||||
import org.openhab.binding.boschshc.internal.devices.bridge.dto.Faults;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link BatteryLevel}.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
class BatteryLevelTest {
|
||||
|
||||
@Test
|
||||
void testGet() {
|
||||
assertSame(BatteryLevel.OK, BatteryLevel.get("OK"));
|
||||
assertSame(BatteryLevel.OK, BatteryLevel.get("ok"));
|
||||
assertSame(BatteryLevel.LOW_BATTERY, BatteryLevel.get("LOW_BATTERY"));
|
||||
assertSame(BatteryLevel.LOW_BATTERY, BatteryLevel.get("low_battery"));
|
||||
assertSame(BatteryLevel.CRITICAL_LOW, BatteryLevel.get("CRITICAL_LOW"));
|
||||
assertSame(BatteryLevel.CRITICAL_LOW, BatteryLevel.get("critical_low"));
|
||||
assertSame(BatteryLevel.CRITICALLY_LOW_BATTERY, BatteryLevel.get("CRITICALLY_LOW_BATTERY"));
|
||||
assertSame(BatteryLevel.CRITICALLY_LOW_BATTERY, BatteryLevel.get("critically_low_battery"));
|
||||
assertSame(BatteryLevel.NOT_AVAILABLE, BatteryLevel.get("NOT_AVAILABLE"));
|
||||
assertSame(BatteryLevel.NOT_AVAILABLE, BatteryLevel.get("not_available"));
|
||||
assertNull(BatteryLevel.get("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFromDeviceServiceData() {
|
||||
DeviceServiceData deviceServiceData = new DeviceServiceData();
|
||||
assertSame(BatteryLevel.OK, BatteryLevel.fromDeviceServiceData(deviceServiceData));
|
||||
|
||||
Faults faults = new Faults();
|
||||
deviceServiceData.faults = faults;
|
||||
assertSame(BatteryLevel.OK, BatteryLevel.fromDeviceServiceData(deviceServiceData));
|
||||
|
||||
ArrayList<Fault> entries = new ArrayList<>();
|
||||
faults.entries = entries;
|
||||
assertSame(BatteryLevel.OK, BatteryLevel.fromDeviceServiceData(deviceServiceData));
|
||||
|
||||
Fault fault = new Fault();
|
||||
entries.add(fault);
|
||||
assertSame(BatteryLevel.OK, BatteryLevel.fromDeviceServiceData(deviceServiceData));
|
||||
|
||||
fault.category = "WARNING";
|
||||
fault.type = "LOW_BATTERY";
|
||||
assertSame(BatteryLevel.LOW_BATTERY, BatteryLevel.fromDeviceServiceData(deviceServiceData));
|
||||
|
||||
fault.type = "CRITICAL_LOW";
|
||||
assertSame(BatteryLevel.CRITICAL_LOW, BatteryLevel.fromDeviceServiceData(deviceServiceData));
|
||||
|
||||
fault.type = "CRITICALLY_LOW_BATTERY";
|
||||
assertSame(BatteryLevel.CRITICALLY_LOW_BATTERY, BatteryLevel.fromDeviceServiceData(deviceServiceData));
|
||||
|
||||
fault.type = "FOO";
|
||||
assertSame(BatteryLevel.OK, BatteryLevel.fromDeviceServiceData(deviceServiceData));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testToState() {
|
||||
assertEquals(new DecimalType(100), BatteryLevel.OK.toState());
|
||||
assertEquals(new DecimalType(10), BatteryLevel.LOW_BATTERY.toState());
|
||||
assertEquals(new DecimalType(1), BatteryLevel.CRITICAL_LOW.toState());
|
||||
assertEquals(new DecimalType(1), BatteryLevel.CRITICALLY_LOW_BATTERY.toState());
|
||||
assertEquals(UnDefType.UNDEF, BatteryLevel.NOT_AVAILABLE.toState());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testToLowBatteryState() {
|
||||
assertEquals(OnOffType.OFF, BatteryLevel.OK.toLowBatteryState());
|
||||
assertEquals(OnOffType.ON, BatteryLevel.LOW_BATTERY.toLowBatteryState());
|
||||
assertEquals(OnOffType.ON, BatteryLevel.CRITICAL_LOW.toLowBatteryState());
|
||||
assertEquals(OnOffType.ON, BatteryLevel.CRITICALLY_LOW_BATTERY.toLowBatteryState());
|
||||
assertEquals(OnOffType.OFF, BatteryLevel.NOT_AVAILABLE.toLowBatteryState());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user