mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-25 14:55:55 +01:00
* [boschshc] Support for Bosch Intrusion Detection System (#12700) * Add thing and channel definitions for intrusion detection system * Extract handler abstraction for devices with non-configurable device IDs * Extract service abstractions for write-only services (i.e. services that can not receive states from the bridge) * Add handler, services and DTO implementations for the intrusion detection system * Add detailed Javadocs * Generalize mechanism to actively fetch initial states for certain services * Add unit tests * Add documentation closes #12700 * [boschshc] Documentation and formatting enhancements Signed-off-by: David Pace <dev@davidpace.de>
This commit is contained in:
parent
50831fff14
commit
c16e9df7a0
@ -14,6 +14,7 @@ Binding for the Bosch Smart Home.
|
||||
- [Wall Thermostat](#wall-thermostat)
|
||||
- [Security Camera 360](#security-camera-360)
|
||||
- [Security Camera Eyes](#security-camera-eyes)
|
||||
- [Intrusion Detection System](#intrusion-detection-system)
|
||||
- [Limitations](#limitations)
|
||||
- [Discovery](#discovery)
|
||||
- [Bridge Configuration](#bridge-configuration)
|
||||
@ -138,6 +139,22 @@ Outdoor security camera with motion detection and light.
|
||||
| privacy-mode | Switch | ☑ | If privacy mode is enabled, the camera is disabled and vice versa. |
|
||||
| camera-notification | Switch | ☑ | Enables or disables notifications for the camera. |
|
||||
|
||||
### Intrusion Detection System
|
||||
|
||||
Allows to retrieve notifications in case of intrusions. The system can be armed and disarmed and alarms can be muted.
|
||||
|
||||
**Thing Type ID**: `intrusion-detection-system`
|
||||
|
||||
| Channel Type ID | Item Type | Writable | Description |
|
||||
| ---------------------------- | -------------------- | :------: | -------------------------------------------------------------- |
|
||||
| system-availability | Switch | ☐ | Indicates whether the intrusion detection system is available. |
|
||||
| arming-state | String | ☐ | Read-only channel to retrieve the current arming state. Possible values are `SYSTEM_ARMING`, `SYSTEM_ARMED` and `SYSTEM_DISARMED`. |
|
||||
| alarm-state | String | ☐ | Read-only channel to retrieve the current alarm state. Possible values are `ALARM_OFF`, `PRE_ALARM`, `ALARM_ON`, `ALARM_MUTED` and `UNKNOWN`. |
|
||||
| active-configuration-profile | String | ☐ | The name of the active configuration profile used for the intrusion detection system. |
|
||||
| arm-action | String | ☑ | Arms the intrusion detection system using the given profile ID (default is "0"). |
|
||||
| disarm-action | Switch | ☑ | Disarms the intrusion detection system when an ON command is received. |
|
||||
| mute-action | Switch | ☑ | Mutes the alarm when an ON command is received. |
|
||||
|
||||
## Limitations
|
||||
|
||||
- Discovery of Things
|
||||
|
@ -22,6 +22,7 @@ import org.openhab.core.thing.ThingTypeUID;
|
||||
* @author Stefan Kästle - Initial contribution
|
||||
* @author Christian Oeing - added Shutter Control, ThermostatHandler
|
||||
* @author Christian Oeing - Added WallThermostatHandler
|
||||
* @author David Pace - Added cameras and intrusion detection system
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class BoschSHCBindingConstants {
|
||||
@ -41,6 +42,8 @@ public class BoschSHCBindingConstants {
|
||||
public static final ThingTypeUID THING_TYPE_WALL_THERMOSTAT = new ThingTypeUID(BINDING_ID, "wall-thermostat");
|
||||
public static final ThingTypeUID THING_TYPE_CAMERA_360 = new ThingTypeUID(BINDING_ID, "security-camera-360");
|
||||
public static final ThingTypeUID THING_TYPE_CAMERA_EYES = new ThingTypeUID(BINDING_ID, "security-camera-eyes");
|
||||
public static final ThingTypeUID THING_TYPE_INTRUSION_DETECTION_SYSTEM = new ThingTypeUID(BINDING_ID,
|
||||
"intrusion-detection-system");
|
||||
|
||||
// List of all Channel IDs
|
||||
// Auto-generated from thing-types.xml via script, don't modify
|
||||
@ -63,4 +66,14 @@ public class BoschSHCBindingConstants {
|
||||
public static final String CHANNEL_CHILD_LOCK = "child-lock";
|
||||
public static final String CHANNEL_PRIVACY_MODE = "privacy-mode";
|
||||
public static final String CHANNEL_CAMERA_NOTIFICATION = "camera-notification";
|
||||
public static final String CHANNEL_SYSTEM_AVAILABILITY = "system-availability";
|
||||
public static final String CHANNEL_ARMING_STATE = "arming-state";
|
||||
public static final String CHANNEL_ALARM_STATE = "alarm-state";
|
||||
public static final String CHANNEL_ACTIVE_CONFIGURATION_PROFILE = "active-configuration-profile";
|
||||
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";
|
||||
|
||||
// static device/service names
|
||||
public static final String SERVICE_INTRUSION_DETECTION = "intrusionDetectionSystem";
|
||||
}
|
||||
|
@ -0,0 +1,95 @@
|
||||
/**
|
||||
* 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 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.exceptions.BoschSHCException;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
|
||||
/**
|
||||
* Handler for physical Bosch devices with configurable IDs (as opposed to system services, which have static IDs).
|
||||
* <p>
|
||||
* The device ID of physical devices has to be configured in the thing configuration.
|
||||
* <p>
|
||||
* Examples for physical device IDs are:
|
||||
*
|
||||
* <pre>
|
||||
* hdm:Cameras:d20354de-44b5-3acc-924c-24c98d59da42
|
||||
* hdm:ZigBee:000d6f0016d1cdae
|
||||
* </pre>
|
||||
*
|
||||
* @author Stefan Kästle - Initial contribution
|
||||
* @author Christian Oeing - refactorings of e.g. server registration
|
||||
* @author David Pace - Handler abstraction
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class BoschSHCDeviceHandler extends BoschSHCHandler {
|
||||
|
||||
/**
|
||||
* Bosch SHC configuration loaded from openHAB configuration.
|
||||
*/
|
||||
private @Nullable BoschSHCConfiguration config;
|
||||
|
||||
public BoschSHCDeviceHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
|
||||
var config = this.config = getConfigAs(BoschSHCConfiguration.class);
|
||||
|
||||
String deviceId = config.id;
|
||||
if (deviceId == null || deviceId.isBlank()) {
|
||||
this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"@text/offline.conf-error.empty-device-id");
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to get device info to make sure the device exists
|
||||
try {
|
||||
var bridgeHandler = this.getBridgeHandler();
|
||||
var info = bridgeHandler.getDeviceInfo(deviceId);
|
||||
logger.trace("Device initialized:\n{}", info);
|
||||
} catch (TimeoutException | ExecutionException | BoschSHCException e) {
|
||||
this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
|
||||
return;
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
super.initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique id of the Bosch device.
|
||||
*
|
||||
* @return Unique id of the Bosch device.
|
||||
*/
|
||||
public @Nullable String getBoschID() {
|
||||
if (config != null) {
|
||||
return config.id;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -24,6 +24,9 @@ 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.exceptions.BoschSHCException;
|
||||
import org.openhab.binding.boschshc.internal.services.AbstractBoschSHCService;
|
||||
import org.openhab.binding.boschshc.internal.services.AbstractStatelessBoschSHCService;
|
||||
import org.openhab.binding.boschshc.internal.services.AbstractStatelessBoschSHCServiceWithRequestBody;
|
||||
import org.openhab.binding.boschshc.internal.services.BoschSHCService;
|
||||
import org.openhab.binding.boschshc.internal.services.dto.BoschSHCServiceState;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
@ -42,10 +45,11 @@ import com.google.gson.JsonElement;
|
||||
|
||||
/**
|
||||
* The {@link BoschSHCHandler} represents Bosch Things. Each type of device
|
||||
* inherits from this abstract thing handler.
|
||||
* or system service inherits from this abstract thing handler.
|
||||
*
|
||||
* @author Stefan Kästle - Initial contribution
|
||||
* @author Christian Oeing - refactorings of e.g. server registration
|
||||
* @author David Pace - Handler abstraction
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class BoschSHCHandler extends BaseThingHandler {
|
||||
@ -83,33 +87,36 @@ public abstract class BoschSHCHandler extends BaseThingHandler {
|
||||
|
||||
protected final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
/**
|
||||
* Bosch SHC configuration loaded from openHAB configuration.
|
||||
*/
|
||||
private @Nullable BoschSHCConfiguration config;
|
||||
|
||||
/**
|
||||
* Services of the device.
|
||||
*/
|
||||
private List<DeviceService<? extends BoschSHCServiceState>> services = new ArrayList<>();
|
||||
|
||||
public BoschSHCHandler(Thing thing) {
|
||||
protected BoschSHCHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique id of the Bosch device.
|
||||
* Returns the unique id of the Bosch device or service.
|
||||
* <p>
|
||||
* For physical devices, the ID looks like
|
||||
*
|
||||
* <pre>
|
||||
* hdm:Cameras:d20354de-44b5-3acc-924c-24c98d59da42
|
||||
* hdm:ZigBee:000d6f0016d1c087
|
||||
* </pre>
|
||||
*
|
||||
* For virtual devices / services, static IDs like the following are used:
|
||||
*
|
||||
* <pre>
|
||||
* ventilationService
|
||||
* smokeDetectionSystem
|
||||
* intrusionDetectionSystem
|
||||
* </pre>
|
||||
*
|
||||
* @return Unique id of the Bosch device.
|
||||
* @return Unique ID of the Bosch device or service.
|
||||
*/
|
||||
public @Nullable String getBoschID() {
|
||||
BoschSHCConfiguration config = this.config;
|
||||
if (config != null) {
|
||||
return config.id;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public abstract @Nullable String getBoschID();
|
||||
|
||||
/**
|
||||
* Initializes this handler. Use this method to register all services of the device with
|
||||
@ -117,24 +124,6 @@ public abstract class BoschSHCHandler extends BaseThingHandler {
|
||||
*/
|
||||
@Override
|
||||
public void initialize() {
|
||||
var config = this.config = getConfigAs(BoschSHCConfiguration.class);
|
||||
|
||||
String deviceId = config.id;
|
||||
if (deviceId == null || deviceId.isEmpty()) {
|
||||
this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"@text/offline.conf-error.empty-device-id");
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to get device info to make sure the device exists
|
||||
try {
|
||||
var bridgeHandler = this.getBridgeHandler();
|
||||
var info = bridgeHandler.getDeviceInfo(deviceId);
|
||||
logger.trace("Device initialized:\n{}", info.toString());
|
||||
} catch (InterruptedException | TimeoutException | ExecutionException | BoschSHCException e) {
|
||||
this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize device services
|
||||
try {
|
||||
@ -273,16 +262,95 @@ public abstract class BoschSHCHandler extends BaseThingHandler {
|
||||
protected <TService extends BoschSHCService<TState>, TState extends BoschSHCServiceState> void registerService(
|
||||
TService service, Consumer<TState> stateUpdateListener, Collection<String> affectedChannels)
|
||||
throws BoschSHCException {
|
||||
BridgeHandler bridgeHandler = this.getBridgeHandler();
|
||||
registerService(service, stateUpdateListener, affectedChannels, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a service for this device.
|
||||
*
|
||||
* @param <TService> Type of service.
|
||||
* @param <TState> Type of service state.
|
||||
* @param service Service to register.
|
||||
* @param stateUpdateListener Function to call when a state update was received
|
||||
* from the device.
|
||||
* @param affectedChannels Channels which are affected by the state of this
|
||||
* service.
|
||||
* @param shouldFetchInitialState indicates whether the initial state should be actively requested from the device
|
||||
* or service. Useful if state updates are not included in long poll results.
|
||||
* @throws BoschSHCException If bridge for handler is not set or an invalid bridge is set.
|
||||
* @throws BoschSHCException If no device id is set.
|
||||
*/
|
||||
protected <TService extends BoschSHCService<TState>, TState extends BoschSHCServiceState> void registerService(
|
||||
TService service, Consumer<TState> stateUpdateListener, Collection<String> affectedChannels,
|
||||
boolean shouldFetchInitialState) throws BoschSHCException {
|
||||
|
||||
String deviceId = verifyBoschID();
|
||||
service.initialize(getBridgeHandler(), deviceId, stateUpdateListener);
|
||||
this.registerService(service, affectedChannels);
|
||||
|
||||
if (shouldFetchInitialState) {
|
||||
fetchInitialState(service, stateUpdateListener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Actively requests the initial state for the given service. This is required if long poll results do not contain
|
||||
* status updates for the given service.
|
||||
*
|
||||
* @param <TService> Type of the service for which the state should be obtained
|
||||
* @param <TState> Type of the objects to serialize and deserialize the service state
|
||||
* @param service Service for which the state should be requested
|
||||
* @param stateUpdateListener Function to process the obtained state
|
||||
*/
|
||||
private <TService extends BoschSHCService<TState>, TState extends BoschSHCServiceState> void fetchInitialState(
|
||||
TService service, Consumer<TState> stateUpdateListener) {
|
||||
|
||||
try {
|
||||
@Nullable
|
||||
TState serviceState = service.getState();
|
||||
if (serviceState != null) {
|
||||
stateUpdateListener.accept(serviceState);
|
||||
}
|
||||
} catch (TimeoutException | ExecutionException | BoschSHCException e) {
|
||||
logger.debug("Could not retrieve the initial state for service {} of device {}", service.getServiceName(),
|
||||
getBoschID());
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
logger.debug("Could not retrieve the initial state for service {} of device {}", service.getServiceName(),
|
||||
getBoschID());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a write-only service that does not receive states from the bridge.
|
||||
* <p>
|
||||
* Examples for such services are the actions of the intrusion detection service.
|
||||
*
|
||||
* @param <TService> Type of service.
|
||||
* @param service Service to register.
|
||||
* @throws BoschSHCException If no device ID is set.
|
||||
*/
|
||||
protected <TService extends AbstractBoschSHCService> void registerStatelessService(TService service)
|
||||
throws BoschSHCException {
|
||||
|
||||
String deviceId = verifyBoschID();
|
||||
service.initialize(getBridgeHandler(), deviceId);
|
||||
// do not register in service list because the service can not receive state updates
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that a Bosch device or service ID is set and throws an exception if this is not the case.
|
||||
*
|
||||
* @return the Bosch ID, if present
|
||||
* @throws BoschSHCException if no Bosch ID is set
|
||||
*/
|
||||
private String verifyBoschID() throws BoschSHCException {
|
||||
String deviceId = this.getBoschID();
|
||||
if (deviceId == null) {
|
||||
throw new BoschSHCException(
|
||||
String.format("Could not register service for %s, no device id set", this.getThing()));
|
||||
}
|
||||
|
||||
service.initialize(bridgeHandler, deviceId, stateUpdateListener);
|
||||
this.registerService(service, affectedChannels);
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -367,4 +435,45 @@ public abstract class BoschSHCHandler extends BaseThingHandler {
|
||||
Collection<String> affectedChannels) {
|
||||
this.services.add(new DeviceService<TState>(service, affectedChannels));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a HTTP POST request with empty body.
|
||||
*
|
||||
* @param <TService> Type of service.
|
||||
* @param service Service implementing the action
|
||||
*/
|
||||
protected <TService extends AbstractStatelessBoschSHCService> void postAction(TService service) {
|
||||
try {
|
||||
service.postAction();
|
||||
} catch (ExecutionException | TimeoutException e) {
|
||||
this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
|
||||
String.format("Error while triggering action %s", service.getEndpoint()));
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
|
||||
String.format("Error while triggering action %s", service.getEndpoint()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a HTTP POST request with the given request body.
|
||||
*
|
||||
* @param <TService> Type of service.
|
||||
* @param <TState> Type of the request to be sent.
|
||||
* @param service Service implementing the action
|
||||
* @param request Request object to be serialized to JSON
|
||||
*/
|
||||
protected <TService extends AbstractStatelessBoschSHCServiceWithRequestBody<TState>, TState extends BoschSHCServiceState> void postAction(
|
||||
TService service, TState request) {
|
||||
try {
|
||||
service.postAction(request);
|
||||
} catch (ExecutionException | TimeoutException e) {
|
||||
this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
|
||||
String.format("Error while triggering action %s", service.getEndpoint()));
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
|
||||
String.format("Error while triggering action %s", service.getEndpoint()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.boschshc.internal.devices.bridge.BridgeHandler;
|
||||
import org.openhab.binding.boschshc.internal.devices.camera.CameraHandler;
|
||||
import org.openhab.binding.boschshc.internal.devices.climatecontrol.ClimateControlHandler;
|
||||
import org.openhab.binding.boschshc.internal.devices.intrusion.IntrusionDetectionHandler;
|
||||
import org.openhab.binding.boschshc.internal.devices.lightcontrol.LightControlHandler;
|
||||
import org.openhab.binding.boschshc.internal.devices.motiondetector.MotionDetectorHandler;
|
||||
import org.openhab.binding.boschshc.internal.devices.shuttercontrol.ShutterControlHandler;
|
||||
@ -46,6 +47,7 @@ import org.osgi.service.component.annotations.Component;
|
||||
* @author Stefan Kästle - Initial contribution
|
||||
* @author Christian Oeing - Added Shutter Control and ThermostatHandler; refactored handler mapping
|
||||
* @author Christian Oeing - Added WallThermostatHandler
|
||||
* @author David Pace - Added cameras and intrusion detection system
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(configurationPid = "binding.boschshc", service = ThingHandlerFactory.class)
|
||||
@ -72,7 +74,8 @@ public class BoschSHCHandlerFactory extends BaseThingHandlerFactory {
|
||||
new ThingTypeHandlerMapping(THING_TYPE_CLIMATE_CONTROL, ClimateControlHandler::new),
|
||||
new ThingTypeHandlerMapping(THING_TYPE_WALL_THERMOSTAT, WallThermostatHandler::new),
|
||||
new ThingTypeHandlerMapping(THING_TYPE_CAMERA_360, CameraHandler::new),
|
||||
new ThingTypeHandlerMapping(THING_TYPE_CAMERA_EYES, CameraHandler::new));
|
||||
new ThingTypeHandlerMapping(THING_TYPE_CAMERA_EYES, CameraHandler::new),
|
||||
new ThingTypeHandlerMapping(THING_TYPE_INTRUSION_DETECTION_SYSTEM, IntrusionDetectionHandler::new));
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
|
@ -59,6 +59,7 @@ import com.google.gson.reflect.TypeToken;
|
||||
* @author Stefan Kästle - Initial contribution
|
||||
* @author Gerd Zanker - added HttpClient with pairing support
|
||||
* @author Christian Oeing - refactorings of e.g. server registration
|
||||
* @author David Pace - Added support for custom endpoints and HTTP POST requests
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class BridgeHandler extends BaseBridgeHandler {
|
||||
@ -75,7 +76,13 @@ public class BridgeHandler extends BaseBridgeHandler {
|
||||
*/
|
||||
private final LongPolling longPolling;
|
||||
|
||||
private @Nullable BoschHttpClient httpClient;
|
||||
/**
|
||||
* HTTP client for all communications to and from the bridge.
|
||||
* <p>
|
||||
* This member is package-protected to enable mocking in unit tests.
|
||||
*/
|
||||
/* package */ @Nullable
|
||||
BoschHttpClient httpClient;
|
||||
|
||||
private @Nullable ScheduledFuture<?> scheduledPairing;
|
||||
|
||||
@ -300,14 +307,14 @@ public class BridgeHandler extends BaseBridgeHandler {
|
||||
private void handleLongPollResult(LongPollResult result) {
|
||||
for (DeviceStatusUpdate update : result.result) {
|
||||
if (update != null && update.state != null) {
|
||||
logger.debug("Got update of type {}: {}", update.type, update.state);
|
||||
logger.debug("Got update for service {} of type {}: {}", update.id, update.type, update.state);
|
||||
|
||||
var updateDeviceId = update.deviceId;
|
||||
if (updateDeviceId == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
logger.debug("Got update for {}", updateDeviceId);
|
||||
logger.debug("Got update for device {}", updateDeviceId);
|
||||
|
||||
boolean handled = false;
|
||||
|
||||
@ -437,11 +444,18 @@ public class BridgeHandler extends BaseBridgeHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the Bosch Smart Home Controller for the state of the given thing.
|
||||
* 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>
|
||||
*
|
||||
* @param deviceId Id of device to get state for
|
||||
* @param stateName Name of the state to query
|
||||
* @param stateClass Class to convert the resulting JSON to
|
||||
* @return the deserialized state object, may be <code>null</code>
|
||||
* @throws ExecutionException
|
||||
* @throws TimeoutException
|
||||
* @throws InterruptedException
|
||||
@ -457,26 +471,68 @@ public class BridgeHandler extends BaseBridgeHandler {
|
||||
}
|
||||
|
||||
String url = httpClient.getServiceUrl(stateName, deviceId);
|
||||
Request request = httpClient.createRequest(url, GET).header("Accept", "application/json");
|
||||
logger.debug("getState(): Requesting \"{}\" from Bosch: {} via {}", stateName, deviceId, url);
|
||||
return getState(httpClient, url, stateClass);
|
||||
}
|
||||
|
||||
logger.debug("refreshState: Requesting \"{}\" from Bosch: {} via {}", stateName, deviceId, url);
|
||||
/**
|
||||
* 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
|
||||
* @return the deserialized state object, may be <code>null</code>
|
||||
* @throws InterruptedException
|
||||
* @throws TimeoutException
|
||||
* @throws ExecutionException
|
||||
* @throws BoschSHCException
|
||||
*/
|
||||
public <T extends BoschSHCServiceState> @Nullable T getState(String endpoint, Class<T> stateClass)
|
||||
throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException {
|
||||
@Nullable
|
||||
BoschHttpClient httpClient = this.httpClient;
|
||||
if (httpClient == null) {
|
||||
logger.warn("HttpClient not initialized");
|
||||
return null;
|
||||
}
|
||||
|
||||
String url = httpClient.getBoschSmartHomeUrl(endpoint);
|
||||
logger.debug("getState(): Requesting from Bosch: {}", url);
|
||||
return getState(httpClient, url, stateClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param stateClass Class to convert the resulting JSON to
|
||||
* @return the deserialized state object, may be <code>null</code>
|
||||
* @throws InterruptedException
|
||||
* @throws TimeoutException
|
||||
* @throws ExecutionException
|
||||
* @throws BoschSHCException
|
||||
*/
|
||||
protected <T extends BoschSHCServiceState> @Nullable T getState(BoschHttpClient httpClient, String url,
|
||||
Class<T> stateClass) throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException {
|
||||
Request request = httpClient.createRequest(url, GET).header("Accept", "application/json");
|
||||
|
||||
ContentResponse contentResponse = request.send();
|
||||
|
||||
String content = contentResponse.getContentAsString();
|
||||
logger.debug("refreshState: Request complete: [{}] - return code: {}", content, contentResponse.getStatus());
|
||||
logger.debug("getState(): Request complete: [{}] - return code: {}", content, contentResponse.getStatus());
|
||||
|
||||
int statusCode = contentResponse.getStatus();
|
||||
if (statusCode != 200) {
|
||||
JsonRestExceptionResponse errorResponse = gson.fromJson(content, JsonRestExceptionResponse.class);
|
||||
if (errorResponse != null) {
|
||||
throw new BoschSHCException(String.format(
|
||||
"State request for service %s of device %s failed with status code %d and error code %s",
|
||||
stateName, deviceId, errorResponse.statusCode, errorResponse.errorCode));
|
||||
throw new BoschSHCException(
|
||||
String.format("State request with URL %s failed with status code %d and error code %s", url,
|
||||
errorResponse.statusCode, errorResponse.errorCode));
|
||||
} else {
|
||||
throw new BoschSHCException(
|
||||
String.format("State request for service %s of device %s failed with status code %d", stateName,
|
||||
deviceId, statusCode));
|
||||
String.format("State request with URL %s failed with status code %d", url, statusCode));
|
||||
}
|
||||
}
|
||||
|
||||
@ -516,4 +572,43 @@ public class BridgeHandler extends BaseBridgeHandler {
|
||||
// Send request
|
||||
return request.send();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @throws TimeoutException
|
||||
* @throws ExecutionException
|
||||
*/
|
||||
public @Nullable Response postAction(String endpoint)
|
||||
throws InterruptedException, TimeoutException, ExecutionException {
|
||||
return postAction(endpoint, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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>
|
||||
* @return the HTTP response
|
||||
* @throws InterruptedException
|
||||
* @throws TimeoutException
|
||||
* @throws ExecutionException
|
||||
*/
|
||||
public <T extends BoschSHCServiceState> @Nullable Response postAction(String endpoint, @Nullable T requestBody)
|
||||
throws InterruptedException, TimeoutException, ExecutionException {
|
||||
@Nullable
|
||||
BoschHttpClient httpClient = this.httpClient;
|
||||
if (httpClient == null) {
|
||||
logger.warn("HttpClient not initialized");
|
||||
return null;
|
||||
}
|
||||
|
||||
String url = httpClient.getBoschSmartHomeUrl(endpoint);
|
||||
Request request = httpClient.createRequest(url, POST, requestBody);
|
||||
return request.send();
|
||||
}
|
||||
}
|
||||
|
@ -16,12 +16,9 @@ import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConst
|
||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_PRIVACY_MODE;
|
||||
|
||||
import java.util.List;
|
||||
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.BoschSHCHandler;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCDeviceHandler;
|
||||
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
|
||||
import org.openhab.binding.boschshc.internal.services.cameranotification.CameraNotificationService;
|
||||
import org.openhab.binding.boschshc.internal.services.cameranotification.CameraNotificationState;
|
||||
@ -54,7 +51,7 @@ import org.openhab.core.types.Command;
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class CameraHandler extends BoschSHCHandler {
|
||||
public class CameraHandler extends BoschSHCDeviceHandler {
|
||||
|
||||
private PrivacyModeService privacyModeService;
|
||||
private CameraNotificationService cameraNotificationService;
|
||||
@ -69,60 +66,9 @@ public class CameraHandler extends BoschSHCHandler {
|
||||
protected void initializeServices() throws BoschSHCException {
|
||||
super.initializeServices();
|
||||
|
||||
this.registerService(this.privacyModeService, this::updateChannels, List.of(CHANNEL_PRIVACY_MODE));
|
||||
this.registerService(this.cameraNotificationService, this::updateChannels,
|
||||
List.of(CHANNEL_CAMERA_NOTIFICATION));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
requestInitialStates();
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the initial states for relevant services.
|
||||
* <p>
|
||||
* If this is not done, items associated with the corresponding channels with stay in an uninitialized state
|
||||
* (<code>null</code>).
|
||||
* This in turn leads to events not being fired properly when switches are used in the UI.
|
||||
* <p>
|
||||
* Unfortunately the long poll results do not contain camera-related updates, so this is the current approach
|
||||
* to get the initial states.
|
||||
*/
|
||||
private void requestInitialStates() {
|
||||
requestInitialPrivacyState();
|
||||
requestInitialNotificationState();
|
||||
}
|
||||
|
||||
private void requestInitialPrivacyState() {
|
||||
try {
|
||||
@Nullable
|
||||
PrivacyModeServiceState serviceState = privacyModeService.getState();
|
||||
if (serviceState != null) {
|
||||
super.updateState(CHANNEL_PRIVACY_MODE, serviceState.value.toOnOffType());
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
logger.debug("Could not retrieve the initial privacy state of camera {}", getBoschID());
|
||||
} catch (TimeoutException | ExecutionException | BoschSHCException e) {
|
||||
logger.debug("Could not retrieve the initial privacy state of camera {}", getBoschID());
|
||||
}
|
||||
}
|
||||
|
||||
private void requestInitialNotificationState() {
|
||||
try {
|
||||
@Nullable
|
||||
CameraNotificationServiceState serviceState = cameraNotificationService.getState();
|
||||
if (serviceState != null) {
|
||||
super.updateState(CHANNEL_CAMERA_NOTIFICATION, serviceState.value.toOnOffType());
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
logger.debug("Could not retrieve the initial notification state of camera {}", getBoschID());
|
||||
} catch (TimeoutException | ExecutionException | BoschSHCException e) {
|
||||
logger.debug("Could not retrieve the initial notification state of camera {}", getBoschID());
|
||||
}
|
||||
this.registerService(this.privacyModeService, this::updateChannels, List.of(CHANNEL_PRIVACY_MODE), true);
|
||||
this.registerService(this.cameraNotificationService, this::updateChannels, List.of(CHANNEL_CAMERA_NOTIFICATION),
|
||||
true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -18,7 +18,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.BoschSHCHandler;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCDeviceHandler;
|
||||
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
|
||||
import org.openhab.binding.boschshc.internal.services.roomclimatecontrol.RoomClimateControlService;
|
||||
import org.openhab.binding.boschshc.internal.services.roomclimatecontrol.dto.RoomClimateControlServiceState;
|
||||
@ -36,7 +36,7 @@ import org.openhab.core.types.Command;
|
||||
* @author Christian Oeing - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public final class ClimateControlHandler extends BoschSHCHandler {
|
||||
public final class ClimateControlHandler extends BoschSHCDeviceHandler {
|
||||
|
||||
private RoomClimateControlService roomClimateControlService;
|
||||
|
||||
|
@ -0,0 +1,159 @@
|
||||
/**
|
||||
* 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.intrusion;
|
||||
|
||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_ACTIVE_CONFIGURATION_PROFILE;
|
||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_ALARM_STATE;
|
||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_ARMING_STATE;
|
||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_ARM_ACTION;
|
||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_DISARM_ACTION;
|
||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_MUTE_ACTION;
|
||||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_SYSTEM_AVAILABILITY;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCHandler;
|
||||
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
|
||||
import org.openhab.binding.boschshc.internal.services.intrusion.IntrusionDetectionControlStateService;
|
||||
import org.openhab.binding.boschshc.internal.services.intrusion.IntrusionDetectionSystemStateService;
|
||||
import org.openhab.binding.boschshc.internal.services.intrusion.SurveillanceAlarmService;
|
||||
import org.openhab.binding.boschshc.internal.services.intrusion.actions.arm.ArmActionService;
|
||||
import org.openhab.binding.boschshc.internal.services.intrusion.actions.arm.dto.ArmActionRequest;
|
||||
import org.openhab.binding.boschshc.internal.services.intrusion.actions.disarm.DisarmActionService;
|
||||
import org.openhab.binding.boschshc.internal.services.intrusion.actions.mute.MuteActionService;
|
||||
import org.openhab.binding.boschshc.internal.services.intrusion.dto.IntrusionDetectionControlState;
|
||||
import org.openhab.binding.boschshc.internal.services.intrusion.dto.IntrusionDetectionSystemState;
|
||||
import org.openhab.binding.boschshc.internal.services.intrusion.dto.SurveillanceAlarmState;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.types.Command;
|
||||
|
||||
/**
|
||||
* Handler for the intrusion detection alarm system.
|
||||
* <p>
|
||||
* It supports
|
||||
* <ul>
|
||||
* <li>Obtaining the current intrusion detection system state</li>
|
||||
* <li>Receiving updates related to the detection control state</li>
|
||||
* <li>Receiving updates related to surveillance alarm events</li>
|
||||
* <li>Arming the system</li>
|
||||
* <li>Disarming the system</li>
|
||||
* <li>Muting the alarm</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class IntrusionDetectionHandler extends BoschSHCHandler {
|
||||
|
||||
private IntrusionDetectionSystemStateService intrusionDetectionSystemStateService;
|
||||
private IntrusionDetectionControlStateService intrusionDetectionControlStateService;
|
||||
private SurveillanceAlarmService surveillanceAlarmService;
|
||||
private ArmActionService armActionService;
|
||||
private DisarmActionService disarmActionService;
|
||||
private MuteActionService muteActionService;
|
||||
|
||||
public IntrusionDetectionHandler(Thing thing) {
|
||||
super(thing);
|
||||
this.intrusionDetectionSystemStateService = new IntrusionDetectionSystemStateService();
|
||||
this.intrusionDetectionControlStateService = new IntrusionDetectionControlStateService();
|
||||
this.surveillanceAlarmService = new SurveillanceAlarmService();
|
||||
this.armActionService = new ArmActionService();
|
||||
this.disarmActionService = new DisarmActionService();
|
||||
this.muteActionService = new MuteActionService();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getBoschID() {
|
||||
return BoschSHCBindingConstants.SERVICE_INTRUSION_DETECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initializeServices() throws BoschSHCException {
|
||||
super.initializeServices();
|
||||
|
||||
this.registerService(intrusionDetectionSystemStateService, this::updateChannels,
|
||||
List.of(CHANNEL_SYSTEM_AVAILABILITY, CHANNEL_ARMING_STATE, CHANNEL_ALARM_STATE,
|
||||
CHANNEL_ACTIVE_CONFIGURATION_PROFILE),
|
||||
true);
|
||||
this.registerService(intrusionDetectionControlStateService, this::updateChannels,
|
||||
List.of(CHANNEL_ARMING_STATE));
|
||||
this.registerService(surveillanceAlarmService, this::updateChannels, List.of(CHANNEL_ALARM_STATE));
|
||||
this.registerStatelessService(armActionService);
|
||||
this.registerStatelessService(disarmActionService);
|
||||
this.registerStatelessService(muteActionService);
|
||||
}
|
||||
|
||||
private void updateChannels(IntrusionDetectionSystemState systemState) {
|
||||
super.updateState(CHANNEL_SYSTEM_AVAILABILITY, OnOffType.from(systemState.systemAvailability.available));
|
||||
super.updateState(CHANNEL_ARMING_STATE, new StringType(systemState.armingState.state.toString()));
|
||||
super.updateState(CHANNEL_ALARM_STATE, new StringType(systemState.alarmState.value.toString()));
|
||||
super.updateState(CHANNEL_ACTIVE_CONFIGURATION_PROFILE,
|
||||
new StringType(systemState.activeConfigurationProfile.profileId));
|
||||
}
|
||||
|
||||
private void updateChannels(IntrusionDetectionControlState controlState) {
|
||||
super.updateState(CHANNEL_ARMING_STATE, new StringType(controlState.value.toString()));
|
||||
}
|
||||
|
||||
private void updateChannels(SurveillanceAlarmState surveillanceAlarmState) {
|
||||
super.updateState(CHANNEL_ALARM_STATE, new StringType(surveillanceAlarmState.value.toString()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
super.handleCommand(channelUID, command);
|
||||
|
||||
switch (channelUID.getId()) {
|
||||
case CHANNEL_ARM_ACTION:
|
||||
if (command instanceof StringType) {
|
||||
armIntrusionDetectionSystem((StringType) command);
|
||||
}
|
||||
break;
|
||||
case CHANNEL_DISARM_ACTION:
|
||||
if (command instanceof OnOffType) {
|
||||
disarmIntrusionDetectionSystem((OnOffType) command);
|
||||
}
|
||||
break;
|
||||
case CHANNEL_MUTE_ACTION:
|
||||
if (command instanceof OnOffType) {
|
||||
muteIntrusionDetectionSystem((OnOffType) command);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void armIntrusionDetectionSystem(StringType profileIdCommand) {
|
||||
ArmActionRequest armActionRequest = new ArmActionRequest();
|
||||
armActionRequest.profileId = profileIdCommand.toFullString();
|
||||
postAction(armActionService, armActionRequest);
|
||||
}
|
||||
|
||||
private void disarmIntrusionDetectionSystem(OnOffType command) {
|
||||
if (command == OnOffType.ON) {
|
||||
postAction(disarmActionService);
|
||||
}
|
||||
}
|
||||
|
||||
private void muteIntrusionDetectionSystem(OnOffType command) {
|
||||
if (command == OnOffType.ON) {
|
||||
postAction(muteActionService);
|
||||
}
|
||||
}
|
||||
}
|
@ -20,7 +20,7 @@ import javax.measure.quantity.Energy;
|
||||
import javax.measure.quantity.Power;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCHandler;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCDeviceHandler;
|
||||
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
|
||||
import org.openhab.binding.boschshc.internal.services.powermeter.PowerMeterService;
|
||||
import org.openhab.binding.boschshc.internal.services.powermeter.dto.PowerMeterServiceState;
|
||||
@ -41,7 +41,7 @@ import org.openhab.core.types.State;
|
||||
* @author Stefan Kästle - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class LightControlHandler extends BoschSHCHandler {
|
||||
public class LightControlHandler extends BoschSHCDeviceHandler {
|
||||
|
||||
private final PowerSwitchService powerSwitchService;
|
||||
|
||||
|
@ -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.BoschSHCHandler;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCDeviceHandler;
|
||||
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 BoschSHCHandler {
|
||||
public class MotionDetectorHandler extends BoschSHCDeviceHandler {
|
||||
|
||||
public MotionDetectorHandler(Thing thing) {
|
||||
super(thing);
|
||||
|
@ -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.BoschSHCHandler;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCDeviceHandler;
|
||||
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
|
||||
import org.openhab.binding.boschshc.internal.services.shuttercontrol.OperationState;
|
||||
import org.openhab.binding.boschshc.internal.services.shuttercontrol.ShutterControlService;
|
||||
@ -35,7 +35,7 @@ import org.openhab.core.types.Command;
|
||||
* @author Christian Oeing - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ShutterControlHandler extends BoschSHCHandler {
|
||||
public class ShutterControlHandler extends BoschSHCDeviceHandler {
|
||||
/**
|
||||
* Utility functions to convert data between Bosch things and openHAB items
|
||||
*/
|
||||
|
@ -19,7 +19,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.BoschSHCHandler;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCDeviceHandler;
|
||||
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;
|
||||
@ -37,7 +37,7 @@ import org.openhab.core.types.Command;
|
||||
* @author Christian Oeing - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public final class ThermostatHandler extends BoschSHCHandler {
|
||||
public final class ThermostatHandler extends BoschSHCDeviceHandler {
|
||||
|
||||
private ChildLockService childLockService;
|
||||
|
||||
|
@ -27,7 +27,7 @@ import javax.measure.quantity.Dimensionless;
|
||||
import javax.measure.quantity.Temperature;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCHandler;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCDeviceHandler;
|
||||
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 +44,7 @@ import org.openhab.core.thing.Thing;
|
||||
* @author Christian Oeing - Use service instead of custom logic
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class TwinguardHandler extends BoschSHCHandler {
|
||||
public class TwinguardHandler extends BoschSHCDeviceHandler {
|
||||
|
||||
public TwinguardHandler(Thing thing) {
|
||||
super(thing);
|
||||
|
@ -18,7 +18,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.BoschSHCHandler;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCDeviceHandler;
|
||||
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;
|
||||
@ -32,7 +32,7 @@ import org.openhab.core.thing.Thing;
|
||||
* @author Christian Oeing - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public final class WallThermostatHandler extends BoschSHCHandler {
|
||||
public final class WallThermostatHandler extends BoschSHCDeviceHandler {
|
||||
|
||||
public WallThermostatHandler(Thing thing) {
|
||||
super(thing);
|
||||
|
@ -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.BoschSHCHandler;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCDeviceHandler;
|
||||
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 BoschSHCHandler {
|
||||
public class WindowContactHandler extends BoschSHCDeviceHandler {
|
||||
|
||||
public WindowContactHandler(Thing thing) {
|
||||
super(thing);
|
||||
|
@ -0,0 +1,72 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.boschshc.internal.devices.bridge.BridgeHandler;
|
||||
|
||||
/**
|
||||
* Base class for Bosch Smart Home services containing what all services have in common.
|
||||
* <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
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class AbstractBoschSHCService {
|
||||
|
||||
/**
|
||||
* Unique service name
|
||||
*/
|
||||
private final String serviceName;
|
||||
|
||||
/**
|
||||
* Bridge to use for communication from/to the device
|
||||
*/
|
||||
private @Nullable BridgeHandler bridgeHandler;
|
||||
|
||||
/**
|
||||
* Id of device the service belongs to
|
||||
*/
|
||||
private @Nullable String deviceId;
|
||||
|
||||
protected AbstractBoschSHCService(String serviceName) {
|
||||
this.serviceName = serviceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the service
|
||||
*
|
||||
* @param bridgeHandler Bridge to use for communication from/to the device
|
||||
* @param deviceId Id of device this service is for
|
||||
*/
|
||||
public void initialize(BridgeHandler bridgeHandler, String deviceId) {
|
||||
this.bridgeHandler = bridgeHandler;
|
||||
this.deviceId = deviceId;
|
||||
}
|
||||
|
||||
public String getServiceName() {
|
||||
return serviceName;
|
||||
}
|
||||
|
||||
protected @Nullable BridgeHandler getBridgeHandler() {
|
||||
return bridgeHandler;
|
||||
}
|
||||
|
||||
protected @Nullable String getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.boschshc.internal.devices.bridge.BridgeHandler;
|
||||
|
||||
/**
|
||||
* Abstract implementation for services that only allow setting states via HTTP POST requests.
|
||||
* State-less services can not receive any states from the bridge.
|
||||
* <p>
|
||||
* This implementation does not support request bodies when submitting the POST request.
|
||||
* Request bodies are supported by the subclass {@link AbstractStatelessBoschSHCServiceWithRequestBody}.
|
||||
* <p>
|
||||
* Examples for this kind of service are the following actions of the intrusion detection system:
|
||||
*
|
||||
* <pre>
|
||||
* /intrusion/actions/arm
|
||||
* /intrusion/actions/disarm
|
||||
* /intrusion/actions/mute
|
||||
* </pre>
|
||||
* <p>
|
||||
* The services of the devices and their official APIs can be found
|
||||
* <a href="https://apidocs.bosch-smarthome.com/local/">here</a>.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class AbstractStatelessBoschSHCService extends AbstractBoschSHCService {
|
||||
|
||||
private String endpoint;
|
||||
|
||||
protected AbstractStatelessBoschSHCService(String serviceName, String endpoint) {
|
||||
super(serviceName);
|
||||
this.endpoint = endpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a HTTP POST request without request body to the endpoint specified by {@link #endpoint}.
|
||||
*
|
||||
* @throws InterruptedException
|
||||
* @throws TimeoutException
|
||||
* @throws ExecutionException
|
||||
*/
|
||||
public void postAction() throws InterruptedException, TimeoutException, ExecutionException {
|
||||
BridgeHandler bridgeHandler = getBridgeHandler();
|
||||
if (bridgeHandler == null)
|
||||
return;
|
||||
|
||||
bridgeHandler.postAction(endpoint);
|
||||
}
|
||||
|
||||
public String getEndpoint() {
|
||||
return endpoint;
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.boschshc.internal.devices.bridge.BridgeHandler;
|
||||
import org.openhab.binding.boschshc.internal.services.dto.BoschSHCServiceState;
|
||||
|
||||
/**
|
||||
* Abstract implementation for services that allow setting states via HTTP POST requests containing a JSON request body.
|
||||
* State-less services can not receive any states from the bridge.
|
||||
* <p>
|
||||
* An example of such a service is the <code>arm</code> action of the intrusion detection system.
|
||||
* <p>
|
||||
* The services of the devices and their official APIs can be found
|
||||
* <a href="https://apidocs.bosch-smarthome.com/local/">here</a>.
|
||||
*
|
||||
* @param <TRequest> Type to represent JSON requests sent by this service
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class AbstractStatelessBoschSHCServiceWithRequestBody<TRequest extends BoschSHCServiceState>
|
||||
extends AbstractStatelessBoschSHCService {
|
||||
|
||||
protected AbstractStatelessBoschSHCServiceWithRequestBody(String serviceName, String endpoint) {
|
||||
super(serviceName, endpoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a HTTP POST request containing the serialized request body to the endpoint specified by
|
||||
* {@link #getEndpoint()}.
|
||||
*
|
||||
* @param request a JSON object representing the request body
|
||||
* @throws InterruptedException
|
||||
* @throws TimeoutException
|
||||
* @throws ExecutionException
|
||||
*/
|
||||
public void postAction(TRequest request) throws InterruptedException, TimeoutException, ExecutionException {
|
||||
BridgeHandler bridgeHandler = getBridgeHandler();
|
||||
if (bridgeHandler == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
bridgeHandler.postAction(getEndpoint(), request);
|
||||
}
|
||||
}
|
@ -28,37 +28,34 @@ import org.slf4j.LoggerFactory;
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
/**
|
||||
* Base class of a service of a Bosch Smart Home device. The services of the
|
||||
* devices and their official APIs can be found here:
|
||||
* https://apidocs.bosch-smarthome.com/local/
|
||||
* Abstract implementation of a service that supports reading and writing its state using the same JSON message and the
|
||||
* 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
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class BoschSHCService<TState extends BoschSHCServiceState> {
|
||||
public abstract class BoschSHCService<TState extends BoschSHCServiceState> extends AbstractBoschSHCService {
|
||||
|
||||
protected final Logger logger = LoggerFactory.getLogger(BoschSHCService.class);
|
||||
|
||||
/**
|
||||
* Unique service name
|
||||
*/
|
||||
private final String serviceName;
|
||||
|
||||
/**
|
||||
* Class of service state
|
||||
*/
|
||||
private final Class<TState> stateClass;
|
||||
|
||||
/**
|
||||
* Bridge to use for communication from/to the device
|
||||
*/
|
||||
private @Nullable BridgeHandler bridgeHandler;
|
||||
|
||||
/**
|
||||
* Id of device the service belongs to
|
||||
*/
|
||||
private @Nullable String deviceId;
|
||||
|
||||
/**
|
||||
* Function to call after receiving state updates from the device
|
||||
*/
|
||||
@ -72,7 +69,7 @@ public abstract class BoschSHCService<TState extends BoschSHCServiceState> {
|
||||
* from/to the device.
|
||||
*/
|
||||
protected BoschSHCService(String serviceName, Class<TState> stateClass) {
|
||||
this.serviceName = serviceName;
|
||||
super(serviceName);
|
||||
this.stateClass = stateClass;
|
||||
}
|
||||
|
||||
@ -86,20 +83,10 @@ public abstract class BoschSHCService<TState extends BoschSHCServiceState> {
|
||||
*/
|
||||
public void initialize(BridgeHandler bridgeHandler, String deviceId,
|
||||
@Nullable Consumer<TState> stateUpdateListener) {
|
||||
this.bridgeHandler = bridgeHandler;
|
||||
this.deviceId = deviceId;
|
||||
super.initialize(bridgeHandler, deviceId);
|
||||
this.stateUpdateListener = stateUpdateListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique name of this service.
|
||||
*
|
||||
* @return Unique name of the service.
|
||||
*/
|
||||
public String getServiceName() {
|
||||
return this.serviceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the class of the state this service provides.
|
||||
*
|
||||
@ -136,15 +123,15 @@ public abstract class BoschSHCService<TState extends BoschSHCServiceState> {
|
||||
*/
|
||||
public @Nullable TState getState()
|
||||
throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException {
|
||||
String deviceId = this.deviceId;
|
||||
String deviceId = getDeviceId();
|
||||
if (deviceId == null) {
|
||||
return null;
|
||||
}
|
||||
BridgeHandler bridgeHandler = this.bridgeHandler;
|
||||
BridgeHandler bridgeHandler = getBridgeHandler();
|
||||
if (bridgeHandler == null) {
|
||||
return null;
|
||||
}
|
||||
return bridgeHandler.getState(deviceId, this.serviceName, this.stateClass);
|
||||
return bridgeHandler.getState(deviceId, getServiceName(), getStateClass());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -156,15 +143,15 @@ public abstract class BoschSHCService<TState extends BoschSHCServiceState> {
|
||||
* @throws TimeoutException
|
||||
*/
|
||||
public void setState(TState state) throws InterruptedException, TimeoutException, ExecutionException {
|
||||
String deviceId = this.deviceId;
|
||||
String deviceId = getDeviceId();
|
||||
if (deviceId == null) {
|
||||
return;
|
||||
}
|
||||
BridgeHandler bridgeHandler = this.bridgeHandler;
|
||||
BridgeHandler bridgeHandler = getBridgeHandler();
|
||||
if (bridgeHandler == null) {
|
||||
return;
|
||||
}
|
||||
bridgeHandler.putState(deviceId, this.serviceName, state);
|
||||
bridgeHandler.putState(deviceId, getServiceName(), state);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,80 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
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.exceptions.BoschSHCException;
|
||||
import org.openhab.binding.boschshc.internal.services.dto.BoschSHCServiceState;
|
||||
|
||||
/**
|
||||
* Abstract implementation of a system service that does not represent a physical device.
|
||||
* Examples for system services are the intrusion detection system and the water detection system.
|
||||
* <p>
|
||||
* The endpoints to retrieve system states are different from the ones for physical devices, i.e. they do not follow the
|
||||
* pattern
|
||||
*
|
||||
* <pre>
|
||||
* https://{IP}:8444/smarthome/devices/{deviceId}/services/{serviceName}/state
|
||||
* </pre>
|
||||
*
|
||||
* Instead, system services have endpoints like
|
||||
*
|
||||
* <pre>
|
||||
* /intrusion/states/system
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* The services of the devices and their official APIs can be found
|
||||
* <a href="https://apidocs.bosch-smarthome.com/local/">here</a>.
|
||||
*
|
||||
* @param <TState> type used for representing the service state
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class BoschSHCSystemService<TState extends BoschSHCServiceState> extends BoschSHCService<TState> {
|
||||
|
||||
private String endpoint;
|
||||
|
||||
/**
|
||||
* Constructs a system service instance.
|
||||
*
|
||||
* @param serviceName name of the service, such as <code>intrusionDetectionService</code>
|
||||
* @param stateClass the class representing states of the system
|
||||
* @param endpoint the part of the URL after <code>https://{IP}:8444/smarthome/</code>, e.g.
|
||||
* <code>intrusion/states/system</code>
|
||||
*/
|
||||
protected BoschSHCSystemService(String serviceName, Class<TState> stateClass, String endpoint) {
|
||||
super(serviceName, stateClass);
|
||||
this.endpoint = endpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the endpoint directly instead of constructing a device-specific URL.
|
||||
*/
|
||||
@Override
|
||||
public @Nullable TState getState()
|
||||
throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException {
|
||||
|
||||
BridgeHandler bridgeHandler = getBridgeHandler();
|
||||
if (bridgeHandler == null) {
|
||||
return null;
|
||||
}
|
||||
return bridgeHandler.getState(this.endpoint, getStateClass());
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* 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.intrusion;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.boschshc.internal.services.BoschSHCService;
|
||||
import org.openhab.binding.boschshc.internal.services.intrusion.dto.IntrusionDetectionControlState;
|
||||
|
||||
/**
|
||||
* Allows to retrieve the control state of the intrusion detection system.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class IntrusionDetectionControlStateService extends BoschSHCService<IntrusionDetectionControlState> {
|
||||
|
||||
public IntrusionDetectionControlStateService() {
|
||||
super("IntrusionDetectionControl", IntrusionDetectionControlState.class);
|
||||
}
|
||||
}
|
@ -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.services.intrusion;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants;
|
||||
import org.openhab.binding.boschshc.internal.services.BoschSHCSystemService;
|
||||
import org.openhab.binding.boschshc.internal.services.intrusion.dto.IntrusionDetectionSystemState;
|
||||
|
||||
/**
|
||||
* Allows to retrieve the system state of the intrusion detection system.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class IntrusionDetectionSystemStateService extends BoschSHCSystemService<IntrusionDetectionSystemState> {
|
||||
|
||||
public IntrusionDetectionSystemStateService() {
|
||||
super(BoschSHCBindingConstants.SERVICE_INTRUSION_DETECTION, IntrusionDetectionSystemState.class,
|
||||
"intrusion/states/system");
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* 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.intrusion;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.boschshc.internal.services.BoschSHCService;
|
||||
import org.openhab.binding.boschshc.internal.services.intrusion.dto.SurveillanceAlarmState;
|
||||
|
||||
/**
|
||||
* Service to handle intrusion detection events.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class SurveillanceAlarmService extends BoschSHCService<SurveillanceAlarmState> {
|
||||
|
||||
public SurveillanceAlarmService() {
|
||||
super("SurveillanceAlarm", SurveillanceAlarmState.class);
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* 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.intrusion.actions.arm;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants;
|
||||
import org.openhab.binding.boschshc.internal.services.AbstractStatelessBoschSHCServiceWithRequestBody;
|
||||
import org.openhab.binding.boschshc.internal.services.intrusion.actions.arm.dto.ArmActionRequest;
|
||||
|
||||
/**
|
||||
* Service to arm the intrusion detection system using a specified profile.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ArmActionService extends AbstractStatelessBoschSHCServiceWithRequestBody<ArmActionRequest> {
|
||||
|
||||
public ArmActionService() {
|
||||
super(BoschSHCBindingConstants.SERVICE_INTRUSION_DETECTION, "intrusion/actions/arm");
|
||||
}
|
||||
}
|
@ -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.services.intrusion.actions.arm.dto;
|
||||
|
||||
import org.openhab.binding.boschshc.internal.services.dto.BoschSHCServiceState;
|
||||
|
||||
/**
|
||||
* DTO for arming the intrusion detection system using a specified profile.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class ArmActionRequest extends BoschSHCServiceState {
|
||||
|
||||
public ArmActionRequest() {
|
||||
super("armRequest");
|
||||
}
|
||||
|
||||
/**
|
||||
* The ID of the profile to be used for arming the system.
|
||||
*/
|
||||
public String profileId;
|
||||
}
|
@ -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.services.intrusion.actions.disarm;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants;
|
||||
import org.openhab.binding.boschshc.internal.services.AbstractStatelessBoschSHCService;
|
||||
|
||||
/**
|
||||
* Service for disarming the intrusion detection system.
|
||||
* <p>
|
||||
* This service does not require a DTO because it uses a simple HTTP POST request without a request body.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class DisarmActionService extends AbstractStatelessBoschSHCService {
|
||||
|
||||
public DisarmActionService() {
|
||||
super(BoschSHCBindingConstants.SERVICE_INTRUSION_DETECTION, "intrusion/actions/disarm");
|
||||
}
|
||||
}
|
@ -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.services.intrusion.actions.mute;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants;
|
||||
import org.openhab.binding.boschshc.internal.services.AbstractStatelessBoschSHCService;
|
||||
|
||||
/**
|
||||
* Service to mute the intrusion detection system.
|
||||
* <p>
|
||||
* This service does not require a DTO because it uses a simple HTTP POST request without a request body.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class MuteActionService extends AbstractStatelessBoschSHCService {
|
||||
|
||||
public MuteActionService() {
|
||||
super(BoschSHCBindingConstants.SERVICE_INTRUSION_DETECTION, "intrusion/actions/mute");
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* 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.intrusion.dto;
|
||||
|
||||
/**
|
||||
* Represents the active configuration profile of the intrusion detection system.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class ActiveConfigurationProfileData {
|
||||
|
||||
/**
|
||||
* The ID of the active configuration profile (default: <code>"0"</code>)
|
||||
*/
|
||||
public String profileId;
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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.intrusion.dto;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Possible alarm states of the intrusion detection system.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum AlarmState {
|
||||
ALARM_OFF,
|
||||
PRE_ALARM,
|
||||
ALARM_ON,
|
||||
ALARM_MUTED,
|
||||
UNKNOWN;
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* 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.intrusion.dto;
|
||||
|
||||
/**
|
||||
* DTO for the alarm state of the intrusion detection system.
|
||||
* <p>
|
||||
* Example data:
|
||||
*
|
||||
* <pre>
|
||||
* "alarmState": {
|
||||
* "value": "ALARM_OFF",
|
||||
* "incidents": [
|
||||
* {
|
||||
* "id": "string",
|
||||
* "triggerName": "string",
|
||||
* "type": "SYSTEM_ARMED",
|
||||
* "time": 0,
|
||||
* "location": "string",
|
||||
* "locationId": "string"
|
||||
* }
|
||||
* ],
|
||||
* "deleted": true,
|
||||
* "id": "string"
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* <b>Note:</b> Incidents are not supported yet as they do not seem to be included in the responses from the bridge.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class AlarmStateData {
|
||||
|
||||
public AlarmState value;
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 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.intrusion.dto;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Possible arming state values of the intrusion detection system.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum ArmingState {
|
||||
SYSTEM_ARMED,
|
||||
SYSTEM_ARMING,
|
||||
SYSTEM_DISARMED;
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* 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.intrusion.dto;
|
||||
|
||||
/**
|
||||
* DTO for the arming state of the intrusion detection system.
|
||||
* <p>
|
||||
* Example data:
|
||||
*
|
||||
* <pre>
|
||||
* "armingState": {
|
||||
* "remainingTimeUntilArmed": 0,
|
||||
* "state": "SYSTEM_ARMING",
|
||||
* "deleted": true,
|
||||
* "id": "string"
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class ArmingStateData {
|
||||
|
||||
public long remainingTimeUntilArmed;
|
||||
|
||||
public ArmingState state;
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/**
|
||||
* 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.intrusion.dto;
|
||||
|
||||
import org.openhab.binding.boschshc.internal.services.dto.BoschSHCServiceState;
|
||||
|
||||
/**
|
||||
* A state which is periodically sent by the intrusion detection control state while arming.
|
||||
* <p>
|
||||
* Example data:
|
||||
*
|
||||
* <pre>
|
||||
* {
|
||||
* "@type": "intrusionDetectionControlState",
|
||||
* "activeProfile": "0",
|
||||
* "alarmActivationDelayTime": 30,
|
||||
* "actuators": [
|
||||
* {
|
||||
* "readonly": false,
|
||||
* "active": true,
|
||||
* "id": "intrusion:video"
|
||||
* },
|
||||
* {
|
||||
* "readonly": false,
|
||||
* "active": false,
|
||||
* "id": "intrusion:siren"
|
||||
* }
|
||||
* ],
|
||||
* "remainingTimeUntilArmed": 29559,
|
||||
* "armActivationDelayTime": 30,
|
||||
* "triggers": [
|
||||
* {
|
||||
* "readonly": false,
|
||||
* "active": true,
|
||||
* "id": "hdm:ZigBee:000d6f0012f02378"
|
||||
* }
|
||||
* ],
|
||||
* "value": "SYSTEM_ARMING"
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class IntrusionDetectionControlState extends BoschSHCServiceState {
|
||||
|
||||
public IntrusionDetectionControlState() {
|
||||
super("intrusionDetectionControlState");
|
||||
}
|
||||
|
||||
public String activeProfile;
|
||||
|
||||
public int alarmActivationDelayTime;
|
||||
|
||||
public long remainingTimeUntilArmed;
|
||||
|
||||
public int armActivationDelayTime;
|
||||
|
||||
public ArmingState value;
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/**
|
||||
* 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.intrusion.dto;
|
||||
|
||||
import org.openhab.binding.boschshc.internal.services.dto.BoschSHCServiceState;
|
||||
|
||||
/**
|
||||
* Represents the state of the intrusion detection system as reported by the Bosch Smart Home Controller.
|
||||
* <p>
|
||||
* Example data:
|
||||
*
|
||||
* <pre>
|
||||
* {
|
||||
* "@type": "systemState",
|
||||
* "systemAvailability": {
|
||||
* "@type": "systemAvailabilityState",
|
||||
* "available": true,
|
||||
* "deleted": false
|
||||
* },
|
||||
* "armingState": {
|
||||
* "@type": "armingState",
|
||||
* "state": "SYSTEM_DISARMED",
|
||||
* "deleted": false
|
||||
* },
|
||||
* "alarmState": {
|
||||
* "@type": "alarmState",
|
||||
* "value": "ALARM_OFF",
|
||||
* "incidents": [],
|
||||
* "deleted": false
|
||||
* },
|
||||
* "activeConfigurationProfile": {
|
||||
* "@type": "activeConfigurationProfile",
|
||||
* "deleted": false
|
||||
* },
|
||||
* "securityGapState": {
|
||||
* "@type": "securityGapState",
|
||||
* "securityGaps": [],
|
||||
* "deleted": false
|
||||
* },
|
||||
* "deleted": false
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class IntrusionDetectionSystemState extends BoschSHCServiceState {
|
||||
|
||||
public IntrusionDetectionSystemState() {
|
||||
super("systemState");
|
||||
}
|
||||
|
||||
public SystemAvailabilityStateData systemAvailability;
|
||||
|
||||
public ArmingStateData armingState;
|
||||
|
||||
public AlarmStateData alarmState;
|
||||
|
||||
public ActiveConfigurationProfileData activeConfigurationProfile;
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* 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.intrusion.dto;
|
||||
|
||||
import org.openhab.binding.boschshc.internal.services.dto.BoschSHCServiceState;
|
||||
|
||||
/**
|
||||
* A state containing information about intrusion detection events.
|
||||
* <p>
|
||||
* Example data:
|
||||
*
|
||||
* <pre>
|
||||
* {
|
||||
* "@type": "surveillanceAlarmState",
|
||||
* "incidents": [
|
||||
* {
|
||||
* "triggerName": "Motion Detector",
|
||||
* "locationId": "hz_5",
|
||||
* "location": "Living Room",
|
||||
* "id": "hdm:ZigBee:000d6f0012f02342",
|
||||
* "time": 1652615755336,
|
||||
* "type": "INTRUSION"
|
||||
* }
|
||||
* ],
|
||||
* "value": "ALARM_ON"
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* <b>Note:</b> This state is not documented in the official Bosch API docs.
|
||||
* The type of the incidents seems to be very similar to <code>IncidentType</code> documented for
|
||||
* the system state. However, the type enum seems to be slightly different (<code>INTRUSION</code> instead of
|
||||
* <code>INTRUSION_DETECTED</code>).
|
||||
* For this reason incidents are not modeled in this state object for now.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class SurveillanceAlarmState extends BoschSHCServiceState {
|
||||
|
||||
public SurveillanceAlarmState() {
|
||||
super("surveillanceAlarmState");
|
||||
}
|
||||
|
||||
public AlarmState value;
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* 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.intrusion.dto;
|
||||
|
||||
/**
|
||||
* DTO for the availability state of the intrusion detection system.
|
||||
* <p>
|
||||
* Example data:
|
||||
*
|
||||
* <pre>
|
||||
* {
|
||||
* "@type": "systemAvailabilityState",
|
||||
* "available": true,
|
||||
* "deleted": false
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
public class SystemAvailabilityStateData {
|
||||
|
||||
public boolean available;
|
||||
}
|
@ -189,6 +189,89 @@
|
||||
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="intrusion-detection-system">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="shc"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Intrusion Detection System</label>
|
||||
<description>Allows to retrieve and control the state of the intrusion detection alarm system.</description>
|
||||
|
||||
<channels>
|
||||
<channel id="system-availability" typeId="system-availability"/>
|
||||
<channel id="arming-state" typeId="arming-state"/>
|
||||
<channel id="alarm-state" typeId="alarm-state"/>
|
||||
<channel id="active-configuration-profile" typeId="active-configuration-profile"/>
|
||||
<channel id="arm-action" typeId="arm-action"/>
|
||||
<channel id="disarm-action" typeId="disarm-action"/>
|
||||
<channel id="mute-action" typeId="mute-action"/>
|
||||
</channels>
|
||||
|
||||
</thing-type>
|
||||
|
||||
<channel-type id="system-availability">
|
||||
<item-type>Switch</item-type>
|
||||
<label>System Availability</label>
|
||||
<description>Indicates whether the intrusion detection system is available.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="arming-state">
|
||||
<item-type>String</item-type>
|
||||
<label>Arming State</label>
|
||||
<description>The arming state of the intrusion detection system. Possible values are SYSTEM_ARMING, SYSTEM_ARMED and
|
||||
SYSTEM_DISARMED. This channel is read-only. Use the arm-action and disarm-action channels to arm and disarm the
|
||||
system.</description>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="SYSTEM_ARMING">System is currently arming</option>
|
||||
<option value="SYSTEM_ARMED">System is armed</option>
|
||||
<option value="SYSTEM_DISARMED">System is disarmed</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="alarm-state">
|
||||
<item-type>String</item-type>
|
||||
<label>Alarm State</label>
|
||||
<description>The alarm state of the intrusion detection system. Possible values are ALARM_OFF, PRE_ALARM, ALARM_ON,
|
||||
ALARM_MUTED and UNKNOWN.</description>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="ALARM_OFF">No alarm</option>
|
||||
<option value="PRE_ALARM">Alarm is about to go off</option>
|
||||
<option value="ALARM_ON">Alarm was triggered</option>
|
||||
<option value="ALARM_MUTED">Alarm is muted</option>
|
||||
<option value="UNKNOWN">Alarm status is unknown</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="active-configuration-profile">
|
||||
<item-type>String</item-type>
|
||||
<label>Active Configuration Profile</label>
|
||||
<description>The name of the active configuration profile used for the intrusion detection system.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="arm-action">
|
||||
<item-type>String</item-type>
|
||||
<label>Arm Action</label>
|
||||
<description>Arms the intrusion detection system using the given profile ID.</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="disarm-action">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Disarm Action</label>
|
||||
<description>Disarms the intrusion detection system when an ON command is received.</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="mute-action">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Mute Action</label>
|
||||
<description>Mutes the alarm when an ON command is received.</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="privacy-mode">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Privacy Mode</label>
|
||||
|
@ -0,0 +1,72 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.same;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.api.Request;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.binding.boschshc.internal.services.intrusion.actions.arm.dto.ArmActionRequest;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link BridgeHandler}.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
class BridgeHandlerTest {
|
||||
|
||||
@Nullable
|
||||
private BridgeHandler fixture;
|
||||
|
||||
@Nullable
|
||||
private BoschHttpClient httpClient;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
Bridge bridge = mock(Bridge.class);
|
||||
fixture = new BridgeHandler(bridge);
|
||||
httpClient = mock(BoschHttpClient.class);
|
||||
fixture.httpClient = httpClient;
|
||||
}
|
||||
|
||||
@Test
|
||||
void postAction() throws InterruptedException, TimeoutException, ExecutionException {
|
||||
String endpoint = "/intrusion/actions/arm";
|
||||
String url = "https://127.0.0.1:8444/smarthome/intrusion/actions/arm";
|
||||
when(httpClient.getBoschSmartHomeUrl(endpoint)).thenReturn(url);
|
||||
Request mockRequest = mock(Request.class);
|
||||
when(httpClient.createRequest(anyString(), any(), any())).thenReturn(mockRequest);
|
||||
ArmActionRequest request = new ArmActionRequest();
|
||||
request.profileId = "0";
|
||||
|
||||
fixture.postAction(endpoint, request);
|
||||
verify(httpClient).createRequest(eq(url), same(HttpMethod.POST), same(request));
|
||||
verify(mockRequest).send();
|
||||
}
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
/**
|
||||
* 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.intrusion;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants;
|
||||
import org.openhab.binding.boschshc.internal.devices.bridge.BridgeHandler;
|
||||
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
|
||||
import org.openhab.binding.boschshc.internal.services.intrusion.dto.IntrusionDetectionControlState;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link IntrusionDetectionControlStateService}.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class IntrusionDetectionControlStateServiceTest {
|
||||
|
||||
private IntrusionDetectionControlStateService fixture;
|
||||
|
||||
@Mock
|
||||
private BridgeHandler bridgeHandler;
|
||||
|
||||
@Mock
|
||||
private Consumer<IntrusionDetectionControlState> consumer;
|
||||
|
||||
@Mock
|
||||
private IntrusionDetectionControlState testState;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException {
|
||||
fixture = new IntrusionDetectionControlStateService();
|
||||
fixture.initialize(bridgeHandler, BoschSHCBindingConstants.SERVICE_INTRUSION_DETECTION, consumer);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getServiceName() {
|
||||
assertEquals("IntrusionDetectionControl", fixture.getServiceName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getStateClass() {
|
||||
assertSame(IntrusionDetectionControlState.class, fixture.getStateClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getState() throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException {
|
||||
when(bridgeHandler.getState(anyString(), anyString(), any())).thenReturn(testState);
|
||||
IntrusionDetectionControlState state = fixture.getState();
|
||||
verify(bridgeHandler).getState(BoschSHCBindingConstants.SERVICE_INTRUSION_DETECTION,
|
||||
"IntrusionDetectionControl", IntrusionDetectionControlState.class);
|
||||
assertSame(testState, state);
|
||||
}
|
||||
|
||||
@Test
|
||||
void setState() throws InterruptedException, TimeoutException, ExecutionException {
|
||||
fixture.setState(testState);
|
||||
verify(bridgeHandler).putState(BoschSHCBindingConstants.SERVICE_INTRUSION_DETECTION,
|
||||
"IntrusionDetectionControl", testState);
|
||||
}
|
||||
|
||||
@Test
|
||||
void onStateUpdate() {
|
||||
final String json = "{\n" + "\"@type\": \"intrusionDetectionControlState\",\n" + "\"activeProfile\": \"0\",\n"
|
||||
+ "\"alarmActivationDelayTime\": 30,\n" + "\"actuators\": [\n" + "{\n" + "\"readonly\": false,\n"
|
||||
+ "\"active\": true,\n" + "\"id\": \"intrusion:video\"\n" + "},\n" + "{\n" + "\"readonly\": false,\n"
|
||||
+ "\"active\": false,\n" + "\"id\": \"intrusion:siren\"\n" + "}\n" + "],\n"
|
||||
+ "\"remainingTimeUntilArmed\": 28959,\n" + "\"armActivationDelayTime\": 30,\n" + "\"triggers\": [\n"
|
||||
+ "{\n" + "\"readonly\": false,\n" + "\"active\": true,\n" + "\"id\": \"hdm:ZigBee:000d6f0422f42378\"\n"
|
||||
+ "}\n" + "],\n" + "\"value\": \"SYSTEM_ARMING\"\n" + "}";
|
||||
JsonElement jsonElement = JsonParser.parseString(json);
|
||||
fixture.onStateUpdate(jsonElement);
|
||||
verify(consumer).accept(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void refreshState() throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException {
|
||||
when(bridgeHandler.getState(anyString(), anyString(), any())).thenReturn(testState);
|
||||
fixture.refreshState();
|
||||
verify(consumer).accept(testState);
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/**
|
||||
* 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.intrusion;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants;
|
||||
import org.openhab.binding.boschshc.internal.devices.bridge.BridgeHandler;
|
||||
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
|
||||
import org.openhab.binding.boschshc.internal.services.intrusion.dto.IntrusionDetectionSystemState;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link IntrusionDetectionSystemStateService}.
|
||||
*
|
||||
* @author David Pace - Initial contribution
|
||||
*
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class IntrusionDetectionSystemStateServiceTest {
|
||||
|
||||
private IntrusionDetectionSystemStateService fixture;
|
||||
|
||||
@Mock
|
||||
private BridgeHandler bridgeHandler;
|
||||
|
||||
@Mock
|
||||
private Consumer<IntrusionDetectionSystemState> consumer;
|
||||
|
||||
@Mock
|
||||
private IntrusionDetectionSystemState testState;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
fixture = new IntrusionDetectionSystemStateService();
|
||||
fixture.initialize(bridgeHandler, BoschSHCBindingConstants.SERVICE_INTRUSION_DETECTION, consumer);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getState() throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException {
|
||||
when(bridgeHandler.getState(anyString(), any())).thenReturn(testState);
|
||||
IntrusionDetectionSystemState state = fixture.getState();
|
||||
verify(bridgeHandler).getState("intrusion/states/system", IntrusionDetectionSystemState.class);
|
||||
assertSame(testState, state);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user