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. |
|
| power-consumption | Number:Power | ☐ | Current power consumption (W) of the device. |
|
||||||
| energy-consumption | Number:Energy | ☐ | Cumulated energy consumption (Wh) 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.
|
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. |
|
| purity-rating | String | ☐ | Rating of current measured purity. |
|
||||||
| air-description | String | ☐ | Overall description of the air quality. |
|
| air-description | String | ☐ | Overall description of the air quality. |
|
||||||
| combined-rating | String | ☐ | Combined rating 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
|
### Door/Window Contact
|
||||||
|
|
||||||
@ -75,6 +77,8 @@ Detects open windows and doors.
|
|||||||
| Channel Type ID | Item Type | Writable | Description |
|
| Channel Type ID | Item Type | Writable | Description |
|
||||||
| --------------- | --------- | :------: | ---------------------------- |
|
| --------------- | --------- | :------: | ---------------------------- |
|
||||||
| contact | Contact | ☐ | Contact state of the device. |
|
| 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
|
### 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 |
|
| Channel Type ID | Item Type | Writable | Description |
|
||||||
| --------------- | --------- | :------: | ------------------------------ |
|
| --------------- | --------- | :------: | ------------------------------ |
|
||||||
| latest-motion | DateTime | ☐ | The date of the latest motion. |
|
| 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
|
### Shutter Control
|
||||||
|
|
||||||
@ -107,6 +113,8 @@ Radiator thermostat
|
|||||||
| temperature | Number:Temperature | ☐ | Current measured temperature. |
|
| temperature | Number:Temperature | ☐ | Current measured temperature. |
|
||||||
| valve-tappet-position | Number:Dimensionless | ☐ | Current open ratio of valve tappet (0 to 100). |
|
| valve-tappet-position | Number:Dimensionless | ☐ | Current open ratio of valve tappet (0 to 100). |
|
||||||
| child-lock | Switch | ☑ | Indicates if child lock is active. |
|
| 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
|
### 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. |
|
| temperature | Number:Temperature | ☐ | Current measured temperature. |
|
||||||
| humidity | Number:Dimensionless | ☐ | Current measured humidity (0 to 100). |
|
| 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
|
### 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_ARM_ACTION = "arm-action";
|
||||||
public static final String CHANNEL_DISARM_ACTION = "disarm-action";
|
public static final String CHANNEL_DISARM_ACTION = "disarm-action";
|
||||||
public static final String CHANNEL_MUTE_ACTION = "mute-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
|
// static device/service names
|
||||||
public static final String SERVICE_INTRUSION_DETECTION = "intrusionDetectionSystem";
|
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 serviceName Name of service the update came from.
|
||||||
* @param stateData Current state of device service. Serialized as JSON.
|
* @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
|
// Check services of device to correctly
|
||||||
for (DeviceService<? extends BoschSHCServiceState> deviceService : this.services) {
|
for (DeviceService<? extends BoschSHCServiceState> deviceService : this.services) {
|
||||||
BoschSHCService<? extends BoschSHCServiceState> service = deviceService.service;
|
BoschSHCService<? extends BoschSHCServiceState> service = deviceService.service;
|
||||||
|
|||||||
@ -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
|
* see https://apidocs.bosch-smarthome.com/local/index.html
|
||||||
*
|
*
|
||||||
* @param serviceName the name of the service
|
* @param serviceName the name of the service
|
||||||
* @param deviceId the device identifier
|
* @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) {
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -30,7 +30,7 @@ import org.eclipse.jetty.http.HttpStatus;
|
|||||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCHandler;
|
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.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.LongPollResult;
|
||||||
import org.openhab.binding.boschshc.internal.devices.bridge.dto.Room;
|
import org.openhab.binding.boschshc.internal.devices.bridge.dto.Room;
|
||||||
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
|
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
|
||||||
@ -51,6 +51,7 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -299,52 +300,96 @@ public class BridgeHandler extends BaseBridgeHandler {
|
|||||||
/**
|
/**
|
||||||
* Bridge callback handler for the results of long polls.
|
* Bridge callback handler for the results of long polls.
|
||||||
*
|
*
|
||||||
* It will check the result and
|
* It will check the results and
|
||||||
* forward the received to the bosch thing handlers.
|
* forward the received states to the Bosch thing handlers.
|
||||||
*
|
*
|
||||||
* @param result Results from Long Polling
|
* @param result Results from Long Polling
|
||||||
*/
|
*/
|
||||||
private void handleLongPollResult(LongPollResult result) {
|
private void handleLongPollResult(LongPollResult result) {
|
||||||
for (DeviceStatusUpdate update : result.result) {
|
for (DeviceServiceData deviceServiceData : result.result) {
|
||||||
if (update != null && update.state != null) {
|
handleDeviceServiceData(deviceServiceData);
|
||||||
logger.debug("Got update for service {} of type {}: {}", update.id, update.type, update.state);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var updateDeviceId = update.deviceId;
|
/**
|
||||||
if (updateDeviceId == null) {
|
* Processes a single long poll result.
|
||||||
continue;
|
*
|
||||||
}
|
* @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;
|
var updateDeviceId = deviceServiceData.deviceId;
|
||||||
|
if (updateDeviceId == null || state == null) {
|
||||||
Bridge bridge = this.getThing();
|
return;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -470,7 +515,7 @@ public class BridgeHandler extends BaseBridgeHandler {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String url = httpClient.getServiceUrl(stateName, deviceId);
|
String url = httpClient.getServiceStateUrl(stateName, deviceId);
|
||||||
logger.debug("getState(): Requesting \"{}\" from Bosch: {} via {}", stateName, deviceId, url);
|
logger.debug("getState(): Requesting \"{}\" from Bosch: {} via {}", stateName, deviceId, url);
|
||||||
return getState(httpClient, url, stateClass);
|
return getState(httpClient, url, stateClass);
|
||||||
}
|
}
|
||||||
@ -566,7 +611,7 @@ public class BridgeHandler extends BaseBridgeHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create request
|
// Create request
|
||||||
String url = httpClient.getServiceUrl(serviceName, deviceId);
|
String url = httpClient.getServiceStateUrl(serviceName, deviceId);
|
||||||
Request request = httpClient.createRequest(url, PUT, state);
|
Request request = httpClient.createRequest(url, PUT, state);
|
||||||
|
|
||||||
// Send request
|
// Send request
|
||||||
@ -611,4 +656,18 @@ public class BridgeHandler extends BaseBridgeHandler {
|
|||||||
Request request = httpClient.createRequest(url, POST, requestBody);
|
Request request = httpClient.createRequest(url, POST, requestBody);
|
||||||
return request.send();
|
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;
|
package org.openhab.binding.boschshc.internal.devices.bridge.dto;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.boschshc.internal.services.dto.BoschSHCServiceState;
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.annotations.SerializedName;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a device status update as represented by the Smart Home
|
* 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 Stefan Kästle - Initial contribution
|
||||||
* @author Christian Oeing - refactorings of e.g. server registration
|
* @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.
|
* Url path of the service the update came from.
|
||||||
*/
|
*/
|
||||||
public String path;
|
public String path;
|
||||||
|
|
||||||
/**
|
|
||||||
* The type of message.
|
|
||||||
*/
|
|
||||||
@SerializedName("@type")
|
|
||||||
public String type;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name of service the update came from.
|
* Name of service the update came from.
|
||||||
*/
|
*/
|
||||||
@ -44,15 +39,26 @@ public class DeviceStatusUpdate {
|
|||||||
/**
|
/**
|
||||||
* Current state of device. Serialized as JSON.
|
* Current state of device. Serialized as JSON.
|
||||||
*/
|
*/
|
||||||
public JsonElement state;
|
public @Nullable JsonElement state;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Id of device the update is for.
|
* Id of device the update is for.
|
||||||
*/
|
*/
|
||||||
public @Nullable String deviceId;
|
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
|
@Override
|
||||||
public String toString() {
|
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"}
|
* ],"jsonrpc":"2.0"}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public ArrayList<DeviceStatusUpdate> result;
|
public ArrayList<DeviceServiceData> result;
|
||||||
public String jsonrpc;
|
public String jsonrpc;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,7 @@ import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConst
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
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.exceptions.BoschSHCException;
|
||||||
import org.openhab.binding.boschshc.internal.services.latestmotion.LatestMotionService;
|
import org.openhab.binding.boschshc.internal.services.latestmotion.LatestMotionService;
|
||||||
import org.openhab.binding.boschshc.internal.services.latestmotion.dto.LatestMotionServiceState;
|
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
|
* @author Christian Oeing - Use service instead of custom logic
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class MotionDetectorHandler extends BoschSHCDeviceHandler {
|
public class MotionDetectorHandler extends AbstractBatteryPoweredDeviceHandler {
|
||||||
|
|
||||||
public MotionDetectorHandler(Thing thing) {
|
public MotionDetectorHandler(Thing thing) {
|
||||||
super(thing);
|
super(thing);
|
||||||
|
|||||||
@ -12,14 +12,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.openhab.binding.boschshc.internal.devices.thermostat;
|
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.*;
|
||||||
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 java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
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.exceptions.BoschSHCException;
|
||||||
import org.openhab.binding.boschshc.internal.services.childlock.ChildLockService;
|
import org.openhab.binding.boschshc.internal.services.childlock.ChildLockService;
|
||||||
import org.openhab.binding.boschshc.internal.services.childlock.dto.ChildLockServiceState;
|
import org.openhab.binding.boschshc.internal.services.childlock.dto.ChildLockServiceState;
|
||||||
@ -37,7 +35,7 @@ import org.openhab.core.types.Command;
|
|||||||
* @author Christian Oeing - Initial contribution
|
* @author Christian Oeing - Initial contribution
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public final class ThermostatHandler extends BoschSHCDeviceHandler {
|
public final class ThermostatHandler extends AbstractBatteryPoweredDeviceHandler {
|
||||||
|
|
||||||
private ChildLockService childLockService;
|
private ChildLockService childLockService;
|
||||||
|
|
||||||
@ -48,6 +46,8 @@ public final class ThermostatHandler extends BoschSHCDeviceHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void initializeServices() throws BoschSHCException {
|
protected void initializeServices() throws BoschSHCException {
|
||||||
|
super.initializeServices();
|
||||||
|
|
||||||
this.createService(TemperatureLevelService::new, this::updateChannels, List.of(CHANNEL_TEMPERATURE));
|
this.createService(TemperatureLevelService::new, this::updateChannels, List.of(CHANNEL_TEMPERATURE));
|
||||||
this.createService(ValveTappetService::new, this::updateChannels, List.of(CHANNEL_VALVE_TAPPET_POSITION));
|
this.createService(ValveTappetService::new, this::updateChannels, List.of(CHANNEL_VALVE_TAPPET_POSITION));
|
||||||
this.registerService(this.childLockService, this::updateChannels, List.of(CHANNEL_CHILD_LOCK));
|
this.registerService(this.childLockService, this::updateChannels, List.of(CHANNEL_CHILD_LOCK));
|
||||||
|
|||||||
@ -12,14 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.openhab.binding.boschshc.internal.devices.twinguard;
|
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.*;
|
||||||
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 java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -27,7 +20,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.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.exceptions.BoschSHCException;
|
||||||
import org.openhab.binding.boschshc.internal.services.airqualitylevel.AirQualityLevelService;
|
import org.openhab.binding.boschshc.internal.services.airqualitylevel.AirQualityLevelService;
|
||||||
import org.openhab.binding.boschshc.internal.services.airqualitylevel.dto.AirQualityLevelServiceState;
|
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
|
* @author Christian Oeing - Use service instead of custom logic
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class TwinguardHandler extends BoschSHCDeviceHandler {
|
public class TwinguardHandler extends AbstractBatteryPoweredDeviceHandler {
|
||||||
|
|
||||||
public TwinguardHandler(Thing thing) {
|
public TwinguardHandler(Thing thing) {
|
||||||
super(thing);
|
super(thing);
|
||||||
|
|||||||
@ -12,13 +12,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.openhab.binding.boschshc.internal.devices.wallthermostat;
|
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.*;
|
||||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_TEMPERATURE;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
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.exceptions.BoschSHCException;
|
||||||
import org.openhab.binding.boschshc.internal.services.humiditylevel.HumidityLevelService;
|
import org.openhab.binding.boschshc.internal.services.humiditylevel.HumidityLevelService;
|
||||||
import org.openhab.binding.boschshc.internal.services.humiditylevel.dto.HumidityLevelServiceState;
|
import org.openhab.binding.boschshc.internal.services.humiditylevel.dto.HumidityLevelServiceState;
|
||||||
@ -32,7 +31,7 @@ import org.openhab.core.thing.Thing;
|
|||||||
* @author Christian Oeing - Initial contribution
|
* @author Christian Oeing - Initial contribution
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public final class WallThermostatHandler extends BoschSHCDeviceHandler {
|
public final class WallThermostatHandler extends AbstractBatteryPoweredDeviceHandler {
|
||||||
|
|
||||||
public WallThermostatHandler(Thing thing) {
|
public WallThermostatHandler(Thing thing) {
|
||||||
super(thing);
|
super(thing);
|
||||||
@ -40,6 +39,8 @@ public final class WallThermostatHandler extends BoschSHCDeviceHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void initializeServices() throws BoschSHCException {
|
protected void initializeServices() throws BoschSHCException {
|
||||||
|
super.initializeServices();
|
||||||
|
|
||||||
this.createService(TemperatureLevelService::new, this::updateChannels, List.of(CHANNEL_TEMPERATURE));
|
this.createService(TemperatureLevelService::new, this::updateChannels, List.of(CHANNEL_TEMPERATURE));
|
||||||
this.createService(HumidityLevelService::new, this::updateChannels, List.of(CHANNEL_HUMIDITY));
|
this.createService(HumidityLevelService::new, this::updateChannels, List.of(CHANNEL_HUMIDITY));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,7 @@ import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConst
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
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.exceptions.BoschSHCException;
|
||||||
import org.openhab.binding.boschshc.internal.services.shuttercontact.ShutterContactService;
|
import org.openhab.binding.boschshc.internal.services.shuttercontact.ShutterContactService;
|
||||||
import org.openhab.binding.boschshc.internal.services.shuttercontact.ShutterContactState;
|
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
|
* @author Stefan Kästle - Initial contribution
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class WindowContactHandler extends BoschSHCDeviceHandler {
|
public class WindowContactHandler extends AbstractBatteryPoweredDeviceHandler {
|
||||||
|
|
||||||
public WindowContactHandler(Thing thing) {
|
public WindowContactHandler(Thing thing) {
|
||||||
super(thing);
|
super(thing);
|
||||||
@ -40,6 +40,8 @@ public class WindowContactHandler extends BoschSHCDeviceHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void initializeServices() throws BoschSHCException {
|
protected void initializeServices() throws BoschSHCException {
|
||||||
|
super.initializeServices();
|
||||||
|
|
||||||
this.createService(ShutterContactService::new, this::updateChannels, List.of(CHANNEL_CONTACT));
|
this.createService(ShutterContactService::new, this::updateChannels, List.of(CHANNEL_CONTACT));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -159,7 +159,7 @@ public abstract class BoschSHCService<TState extends BoschSHCServiceState> exten
|
|||||||
*
|
*
|
||||||
* @param stateData Current state of service. Serialized as JSON.
|
* @param stateData Current state of service. Serialized as JSON.
|
||||||
*/
|
*/
|
||||||
public void onStateUpdate(JsonElement stateData) {
|
public void onStateUpdate(@Nullable JsonElement stateData) {
|
||||||
@Nullable
|
@Nullable
|
||||||
TState state = BoschSHCServiceState.fromJson(stateData, this.stateClass);
|
TState state = BoschSHCServiceState.fromJson(stateData, this.stateClass);
|
||||||
if (state == null) {
|
if (state == null) {
|
||||||
|
|||||||
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -40,7 +40,7 @@ public class BoschSHCServiceState {
|
|||||||
private @Nullable String stateType = null;
|
private @Nullable String stateType = null;
|
||||||
|
|
||||||
@SerializedName("@type")
|
@SerializedName("@type")
|
||||||
private final String type;
|
public final String type;
|
||||||
|
|
||||||
protected BoschSHCServiceState(String type) {
|
protected BoschSHCServiceState(String type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
|||||||
@ -53,7 +53,7 @@
|
|||||||
<bridge-type-ref id="shc"/>
|
<bridge-type-ref id="shc"/>
|
||||||
</supported-bridge-type-refs>
|
</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>
|
<description>The Twinguard smoke detector warns you in case of fire and constantly monitors the air.</description>
|
||||||
|
|
||||||
<channels>
|
<channels>
|
||||||
@ -65,6 +65,8 @@
|
|||||||
<channel id="air-description" typeId="air-description"/>
|
<channel id="air-description" typeId="air-description"/>
|
||||||
<channel id="purity-rating" typeId="purity-rating"/>
|
<channel id="purity-rating" typeId="purity-rating"/>
|
||||||
<channel id="combined-rating" typeId="combined-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>
|
</channels>
|
||||||
|
|
||||||
<config-description-ref uri="thing-type:boschshc:device"/>
|
<config-description-ref uri="thing-type:boschshc:device"/>
|
||||||
@ -81,6 +83,8 @@
|
|||||||
|
|
||||||
<channels>
|
<channels>
|
||||||
<channel id="contact" typeId="contact"/>
|
<channel id="contact" typeId="contact"/>
|
||||||
|
<channel id="battery-level" typeId="system.battery-level"/>
|
||||||
|
<channel id="low-battery" typeId="system.low-battery"/>
|
||||||
</channels>
|
</channels>
|
||||||
|
|
||||||
<config-description-ref uri="thing-type:boschshc:device"/>
|
<config-description-ref uri="thing-type:boschshc:device"/>
|
||||||
@ -98,6 +102,8 @@
|
|||||||
|
|
||||||
<channels>
|
<channels>
|
||||||
<channel id="latest-motion" typeId="latest-motion"/>
|
<channel id="latest-motion" typeId="latest-motion"/>
|
||||||
|
<channel id="battery-level" typeId="system.battery-level"/>
|
||||||
|
<channel id="low-battery" typeId="system.low-battery"/>
|
||||||
</channels>
|
</channels>
|
||||||
|
|
||||||
<config-description-ref uri="thing-type:boschshc:device"/>
|
<config-description-ref uri="thing-type:boschshc:device"/>
|
||||||
@ -132,6 +138,8 @@
|
|||||||
<channel id="temperature" typeId="temperature"/>
|
<channel id="temperature" typeId="temperature"/>
|
||||||
<channel id="valve-tappet-position" typeId="valve-tappet-position"/>
|
<channel id="valve-tappet-position" typeId="valve-tappet-position"/>
|
||||||
<channel id="child-lock" typeId="child-lock"/>
|
<channel id="child-lock" typeId="child-lock"/>
|
||||||
|
<channel id="battery-level" typeId="system.battery-level"/>
|
||||||
|
<channel id="low-battery" typeId="system.low-battery"/>
|
||||||
</channels>
|
</channels>
|
||||||
|
|
||||||
<config-description-ref uri="thing-type:boschshc:device"/>
|
<config-description-ref uri="thing-type:boschshc:device"/>
|
||||||
@ -167,6 +175,8 @@
|
|||||||
<channels>
|
<channels>
|
||||||
<channel id="temperature" typeId="temperature"/>
|
<channel id="temperature" typeId="temperature"/>
|
||||||
<channel id="humidity" typeId="humidity"/>
|
<channel id="humidity" typeId="humidity"/>
|
||||||
|
<channel id="battery-level" typeId="system.battery-level"/>
|
||||||
|
<channel id="low-battery" typeId="system.low-battery"/>
|
||||||
</channels>
|
</channels>
|
||||||
|
|
||||||
<config-description-ref uri="thing-type:boschshc:device"/>
|
<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.OnOffType;
|
||||||
import org.openhab.core.library.types.QuantityType;
|
import org.openhab.core.library.types.QuantityType;
|
||||||
import org.openhab.core.thing.ChannelUID;
|
import org.openhab.core.thing.ChannelUID;
|
||||||
import org.openhab.core.thing.ThingTypeUID;
|
|
||||||
import org.openhab.core.thing.ThingUID;
|
import org.openhab.core.thing.ThingUID;
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
@ -60,8 +59,6 @@ public abstract class AbstractPowerSwitchHandlerTest<T extends AbstractPowerSwit
|
|||||||
public void testHandleCommand()
|
public void testHandleCommand()
|
||||||
throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException {
|
throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException {
|
||||||
|
|
||||||
when(getThing().getUID()).thenReturn(new ThingUID("boschshc", "abcdef"));
|
|
||||||
|
|
||||||
getFixture().handleCommand(new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_POWER_SWITCH),
|
getFixture().handleCommand(new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_POWER_SWITCH),
|
||||||
OnOffType.ON);
|
OnOffType.ON);
|
||||||
verify(getBridgeHandler()).putState(eq(getDeviceID()), eq("PowerSwitch"), serviceStateCaptor.capture());
|
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);
|
assertSame(PowerSwitchState.OFF, state.switchState);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract ThingTypeUID getThingTypeUID();
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateChannel_PowerSwitchState() {
|
public void testUpdateChannel_PowerSwitchState() {
|
||||||
when(getThing().getUID()).thenReturn(new ThingUID("boschshc", "abcdef"));
|
|
||||||
|
|
||||||
JsonElement jsonObject = JsonParser
|
JsonElement jsonObject = JsonParser
|
||||||
.parseString("{\n" + " \"@type\": \"powerSwitchState\",\n" + " \"switchState\": \"ON\"\n" + "}");
|
.parseString("{\n" + " \"@type\": \"powerSwitchState\",\n" + " \"switchState\": \"ON\"\n" + "}");
|
||||||
getFixture().processUpdate("PowerSwitch", jsonObject);
|
getFixture().processUpdate("PowerSwitch", jsonObject);
|
||||||
@ -97,8 +90,6 @@ public abstract class AbstractPowerSwitchHandlerTest<T extends AbstractPowerSwit
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateChannel_PowerMeterServiceState() {
|
public void testUpdateChannel_PowerMeterServiceState() {
|
||||||
when(getThing().getUID()).thenReturn(new ThingUID("boschshc", "abcdef"));
|
|
||||||
|
|
||||||
JsonElement jsonObject = JsonParser.parseString("{\n" + " \"@type\": \"powerMeterState\",\n"
|
JsonElement jsonObject = JsonParser.parseString("{\n" + " \"@type\": \"powerMeterState\",\n"
|
||||||
+ " \"powerConsumption\": \"23\",\n" + " \"energyConsumption\": 42\n" + "}");
|
+ " \"powerConsumption\": \"23\",\n" + " \"energyConsumption\": 42\n" + "}");
|
||||||
getFixture().processUpdate("PowerMeter", jsonObject);
|
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.ThingStatus;
|
||||||
import org.openhab.core.thing.ThingStatusDetail;
|
import org.openhab.core.thing.ThingStatusDetail;
|
||||||
import org.openhab.core.thing.ThingStatusInfo;
|
import org.openhab.core.thing.ThingStatusInfo;
|
||||||
|
import org.openhab.core.thing.ThingTypeUID;
|
||||||
import org.openhab.core.thing.ThingUID;
|
import org.openhab.core.thing.ThingUID;
|
||||||
import org.openhab.core.thing.binding.ThingHandlerCallback;
|
import org.openhab.core.thing.binding.ThingHandlerCallback;
|
||||||
|
|
||||||
@ -57,6 +58,7 @@ public abstract class AbstractSHCHandlerTest<T extends BoschSHCHandler> {
|
|||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void beforeEach() {
|
public void beforeEach() {
|
||||||
fixture = createFixture();
|
fixture = createFixture();
|
||||||
|
lenient().when(thing.getUID()).thenReturn(getThingUID());
|
||||||
when(thing.getBridgeUID()).thenReturn(new ThingUID("boschshc", "shc", "myBridgeUID"));
|
when(thing.getBridgeUID()).thenReturn(new ThingUID("boschshc", "shc", "myBridgeUID"));
|
||||||
when(callback.getBridge(any())).thenReturn(bridge);
|
when(callback.getBridge(any())).thenReturn(bridge);
|
||||||
fixture.setCallback(callback);
|
fixture.setCallback(callback);
|
||||||
@ -72,6 +74,12 @@ public abstract class AbstractSHCHandlerTest<T extends BoschSHCHandler> {
|
|||||||
return fixture;
|
return fixture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected ThingUID getThingUID() {
|
||||||
|
return new ThingUID(getThingTypeUID(), "abcdef");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract ThingTypeUID getThingTypeUID();
|
||||||
|
|
||||||
protected Configuration getConfiguration() {
|
protected Configuration getConfiguration() {
|
||||||
return new Configuration();
|
return new Configuration();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -71,10 +71,16 @@ class BoschHttpClientTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getServiceUrl() {
|
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"));
|
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
|
@Test
|
||||||
void isAccessPossible() throws InterruptedException {
|
void isAccessPossible() throws InterruptedException {
|
||||||
assertFalse(httpClient.isAccessPossible());
|
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…
x
Reference in New Issue
Block a user