[boschshc] Support for Smart Water Alarm (#16770)

Adds support for Bosch Smart Water Alarm devices.

* add new thing type and new channel types
* add new services for water detector
* refactor CameraNotificationState and PrivacyModeState to a common enum
EnabledDisabledState that can be re-used in the water detector tilt
service states
* implement handler for new device
* register new device in handler factory and discovery
* add unit tests
* add documentation

Signed-off-by: David Pace <dev@davidpace.de>
This commit is contained in:
David Pace 2024-05-29 16:10:48 +02:00 committed by GitHub
parent 706f9ca6b5
commit 170d81b4b1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
30 changed files with 962 additions and 131 deletions

View File

@ -26,6 +26,7 @@ Binding for Bosch Smart Home devices.
- [User-defined States](#user-defined-states) - [User-defined States](#user-defined-states)
- [Universal Switch](#universal-switch) - [Universal Switch](#universal-switch)
- [Universal Switch II](#universal-switch-ii) - [Universal Switch II](#universal-switch-ii)
- [Water Detector](#water-detector)
- [Limitations](#limitations) - [Limitations](#limitations)
- [Discovery](#discovery) - [Discovery](#discovery)
- [Bridge Configuration](#bridge-configuration) - [Bridge Configuration](#bridge-configuration)
@ -333,6 +334,23 @@ A universally configurable switch with four buttons.
| key-event-type | String | &#9744; | Indicates how the key was pressed. Possible values are `PRESS_SHORT`, `PRESS_LONG` and `PRESS_LONG_RELEASED`. | | key-event-type | String | &#9744; | Indicates how the key was pressed. Possible values are `PRESS_SHORT`, `PRESS_LONG` and `PRESS_LONG_RELEASED`. |
| key-event-timestamp | DateTime | &#9744; | Timestamp indicating when the key was pressed. | | key-event-timestamp | DateTime | &#9744; | Timestamp indicating when the key was pressed. |
### Water Detector
Smart water leakage detector.
**Thing Type ID**: `water-detector`
| Channel Type ID | Item Type | Writable | Description |
| -------------------------- | --------- | :------: | ------------------------------------------------- |
| battery-level | Number | &#9744; | Current battery level percentage as integer number. Bosch-specific battery levels are mapped to numbers as follows: `OK`: 100, `LOW_BATTERY`: 10, `CRITICAL_LOW`: 1, `CRITICALLY_LOW_BATTERY`: 1, `NOT_AVAILABLE`: `UNDEF`. |
| low-battery | Switch | &#9744; | Indicates whether the battery is low (`ON`) or OK (`OFF`). |
| signal-strength | Number | &#9744; | Communication quality between the device and the Smart Home Controller. Possible values range between 0 (unknown) and 4 (best signal strength). |
| water-leakage | Switch | &#9744; | Indicates whether a water leakage was detected. |
| push-notifications | Switch | &#9745; | Indicates whether push notifications are enabled. |
| acoustic-signals | Switch | &#9745; | Indicates whether acoustic signals are enabled. |
| water-leakage-sensor-check | String | &#9744; | Provides the result of the last water leakage sensor check. |
| sensor-moved | Trigger | &#9744; | Triggered when the sensor is moved. |
## Limitations ## Limitations
No major limitation known. No major limitation known.

View File

@ -82,7 +82,8 @@ public class BoschShcCommandExtension extends AbstractConsoleCommandExtension im
"childprotection", "communicationquality", "hsbcoloractuator", "humiditylevel", "illuminance", "childprotection", "communicationquality", "hsbcoloractuator", "humiditylevel", "illuminance",
"intrusion", "keypad", "latestmotion", "multilevelswitch", "powermeter", "powerswitch", "privacymode", "intrusion", "keypad", "latestmotion", "multilevelswitch", "powermeter", "powerswitch", "privacymode",
"roomclimatecontrol", "shuttercontact", "shuttercontrol", "silentmode", "smokedetectorcheck", "roomclimatecontrol", "shuttercontact", "shuttercontrol", "silentmode", "smokedetectorcheck",
"temperaturelevel", "userstate", "valvetappet"); "temperaturelevel", "userstate", "valvetappet", "waterleakagesensor", "waterleakagesensorcheck",
"waterleakagesensortilt");
} }
@Override @Override

View File

@ -28,6 +28,10 @@ import org.openhab.core.thing.ThingTypeUID;
@NonNullByDefault @NonNullByDefault
public class BoschSHCBindingConstants { public class BoschSHCBindingConstants {
private BoschSHCBindingConstants() {
// Class containing constants only
}
public static final String BINDING_ID = "boschshc"; public static final String BINDING_ID = "boschshc";
// List of all Thing Type UIDs // List of all Thing Type UIDs
@ -55,6 +59,7 @@ public class BoschSHCBindingConstants {
public static final ThingTypeUID THING_TYPE_SMOKE_DETECTOR_2 = new ThingTypeUID(BINDING_ID, "smoke-detector-2"); public static final ThingTypeUID THING_TYPE_SMOKE_DETECTOR_2 = new ThingTypeUID(BINDING_ID, "smoke-detector-2");
public static final ThingTypeUID THING_TYPE_LIGHT_CONTROL_2 = new ThingTypeUID(BINDING_ID, "light-control-2"); public static final ThingTypeUID THING_TYPE_LIGHT_CONTROL_2 = new ThingTypeUID(BINDING_ID, "light-control-2");
public static final ThingTypeUID THING_TYPE_DIMMER = new ThingTypeUID(BINDING_ID, "dimmer"); public static final ThingTypeUID THING_TYPE_DIMMER = new ThingTypeUID(BINDING_ID, "dimmer");
public static final ThingTypeUID THING_TYPE_WATER_DETECTOR = new ThingTypeUID(BINDING_ID, "water-detector");
public static final ThingTypeUID THING_TYPE_USER_DEFINED_STATE = new ThingTypeUID(BINDING_ID, "user-defined-state"); public static final ThingTypeUID THING_TYPE_USER_DEFINED_STATE = new ThingTypeUID(BINDING_ID, "user-defined-state");
@ -102,6 +107,11 @@ public class BoschSHCBindingConstants {
public static final String CHANNEL_KEY_NAME = "key-name"; public static final String CHANNEL_KEY_NAME = "key-name";
public static final String CHANNEL_KEY_EVENT_TYPE = "key-event-type"; public static final String CHANNEL_KEY_EVENT_TYPE = "key-event-type";
public static final String CHANNEL_KEY_EVENT_TIMESTAMP = "key-event-timestamp"; public static final String CHANNEL_KEY_EVENT_TIMESTAMP = "key-event-timestamp";
public static final String CHANNEL_WATER_LEAKAGE = "water-leakage";
public static final String CHANNEL_PUSH_NOTIFICATIONS_ON_MOVE = "push-notifications-on-move";
public static final String CHANNEL_ACOUSTIC_SIGNALS_ON_MOVE = "acoustic-signals-on-move";
public static final String CHANNEL_WATER_LEAKAGE_SENSOR_CHECK = "water-leakage-sensor-check";
public static final String CHANNEL_SENSOR_MOVED = "sensor-moved";
// numbered channels // numbered channels
// the rationale for introducing numbered channels was discussed in // the rationale for introducing numbered channels was discussed in

View File

@ -23,6 +23,7 @@ import java.util.function.Supplier;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.boschshc.internal.devices.bridge.BridgeHandler; import org.openhab.binding.boschshc.internal.devices.bridge.BridgeHandler;
import org.openhab.binding.boschshc.internal.devices.bridge.dto.Message;
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException; import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
import org.openhab.binding.boschshc.internal.services.AbstractBoschSHCService; import org.openhab.binding.boschshc.internal.services.AbstractBoschSHCService;
import org.openhab.binding.boschshc.internal.services.AbstractStatelessBoschSHCService; import org.openhab.binding.boschshc.internal.services.AbstractStatelessBoschSHCService;
@ -175,6 +176,15 @@ public abstract class BoschSHCHandler extends BaseThingHandler {
// default implementation is empty, subclasses may override // default implementation is empty, subclasses may override
} }
/**
* Processes a device-specific message from the Bosch Smart Home Controller.
*
* @param message the message published by the controller
*/
public void processMessage(Message message) {
// default implementation is empty, subclasses may override
}
/** /**
* Use this method to register all services of the device with * Use this method to register all services of the device with
* {@link #registerService(BoschSHCService, Consumer, Collection, boolean)}. * {@link #registerService(BoschSHCService, Consumer, Collection, boolean)}.

View File

@ -33,6 +33,7 @@ import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConst
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_UNIVERSAL_SWITCH_2; import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_UNIVERSAL_SWITCH_2;
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_USER_DEFINED_STATE; import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_USER_DEFINED_STATE;
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_WALL_THERMOSTAT; import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_WALL_THERMOSTAT;
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_WATER_DETECTOR;
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_WINDOW_CONTACT; import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_WINDOW_CONTACT;
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_WINDOW_CONTACT_2; import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_WINDOW_CONTACT_2;
@ -62,6 +63,7 @@ import org.openhab.binding.boschshc.internal.devices.universalswitch.UniversalSw
import org.openhab.binding.boschshc.internal.devices.universalswitch.UniversalSwitchHandler; import org.openhab.binding.boschshc.internal.devices.universalswitch.UniversalSwitchHandler;
import org.openhab.binding.boschshc.internal.devices.userdefinedstate.UserStateHandler; import org.openhab.binding.boschshc.internal.devices.userdefinedstate.UserStateHandler;
import org.openhab.binding.boschshc.internal.devices.wallthermostat.WallThermostatHandler; import org.openhab.binding.boschshc.internal.devices.wallthermostat.WallThermostatHandler;
import org.openhab.binding.boschshc.internal.devices.waterleakage.WaterLeakageSensorHandler;
import org.openhab.binding.boschshc.internal.devices.windowcontact.WindowContact2Handler; import org.openhab.binding.boschshc.internal.devices.windowcontact.WindowContact2Handler;
import org.openhab.binding.boschshc.internal.devices.windowcontact.WindowContactHandler; import org.openhab.binding.boschshc.internal.devices.windowcontact.WindowContactHandler;
import org.openhab.core.i18n.TimeZoneProvider; import org.openhab.core.i18n.TimeZoneProvider;
@ -132,7 +134,8 @@ public class BoschSHCHandlerFactory extends BaseThingHandlerFactory {
thing -> new UniversalSwitch2Handler(thing, timeZoneProvider)), thing -> new UniversalSwitch2Handler(thing, timeZoneProvider)),
new ThingTypeHandlerMapping(THING_TYPE_SMOKE_DETECTOR_2, SmokeDetector2Handler::new), new ThingTypeHandlerMapping(THING_TYPE_SMOKE_DETECTOR_2, SmokeDetector2Handler::new),
new ThingTypeHandlerMapping(THING_TYPE_LIGHT_CONTROL_2, LightControl2Handler::new), new ThingTypeHandlerMapping(THING_TYPE_LIGHT_CONTROL_2, LightControl2Handler::new),
new ThingTypeHandlerMapping(THING_TYPE_DIMMER, DimmerHandler::new)); new ThingTypeHandlerMapping(THING_TYPE_DIMMER, DimmerHandler::new),
new ThingTypeHandlerMapping(THING_TYPE_WATER_DETECTOR, WaterLeakageSensorHandler::new));
@Override @Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) { public boolean supportsThingType(ThingTypeUID thingTypeUID) {

View File

@ -12,7 +12,9 @@
*/ */
package org.openhab.binding.boschshc.internal.devices.bridge; package org.openhab.binding.boschshc.internal.devices.bridge;
import static org.eclipse.jetty.http.HttpMethod.*; import static org.eclipse.jetty.http.HttpMethod.GET;
import static org.eclipse.jetty.http.HttpMethod.POST;
import static org.eclipse.jetty.http.HttpMethod.PUT;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.ArrayList; import java.util.ArrayList;
@ -40,6 +42,7 @@ import org.openhab.binding.boschshc.internal.devices.BoschSHCHandler;
import org.openhab.binding.boschshc.internal.devices.bridge.dto.Device; import org.openhab.binding.boschshc.internal.devices.bridge.dto.Device;
import org.openhab.binding.boschshc.internal.devices.bridge.dto.DeviceServiceData; import org.openhab.binding.boschshc.internal.devices.bridge.dto.DeviceServiceData;
import org.openhab.binding.boschshc.internal.devices.bridge.dto.LongPollResult; import org.openhab.binding.boschshc.internal.devices.bridge.dto.LongPollResult;
import org.openhab.binding.boschshc.internal.devices.bridge.dto.Message;
import org.openhab.binding.boschshc.internal.devices.bridge.dto.PublicInformation; import org.openhab.binding.boschshc.internal.devices.bridge.dto.PublicInformation;
import org.openhab.binding.boschshc.internal.devices.bridge.dto.Room; import org.openhab.binding.boschshc.internal.devices.bridge.dto.Room;
import org.openhab.binding.boschshc.internal.devices.bridge.dto.Scenario; import org.openhab.binding.boschshc.internal.devices.bridge.dto.Scenario;
@ -488,10 +491,44 @@ public class BridgeHandler extends BaseBridgeHandler {
if (channel != null && isLinked(channel.getUID())) { if (channel != null && isLinked(channel.getUID())) {
updateState(channel.getUID(), new StringType(scenario.name)); updateState(channel.getUID(), new StringType(scenario.name));
} }
} else if (serviceState instanceof Message message) {
handleMessage(message);
} }
} }
} }
private void handleMessage(Message message) {
if (Message.SOURCE_TYPE_DEVICE.equals(message.sourceType) && message.sourceId != null) {
forwardMessageToDevice(message, message.sourceId);
}
}
private void forwardMessageToDevice(Message message, String deviceId) {
BoschSHCHandler deviceHandler = findDeviceHandler(deviceId);
if (deviceHandler == null) {
return;
}
deviceHandler.processMessage(message);
}
@Nullable
private BoschSHCHandler findDeviceHandler(String deviceIdToFind) {
for (Thing childThing : getThing().getThings()) {
@Nullable
ThingHandler baseHandler = childThing.getHandler();
if (baseHandler instanceof BoschSHCHandler handler) {
@Nullable
String deviceId = handler.getBoschID();
if (deviceIdToFind.equals(deviceId)) {
return handler;
}
}
}
return null;
}
/** /**
* Processes a single long poll result. * Processes a single long poll result.
* *

View File

@ -0,0 +1,66 @@
/**
* Copyright (c) 2010-2024 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.boschshc.internal.devices.bridge.dto;
import org.openhab.binding.boschshc.internal.services.dto.BoschSHCServiceState;
/**
* DTO for messages sent by the Smart Home Controller.
* <p>
* JSON Example:
*
* <pre>
* {
* "result": [{
* "sourceId": "hdm:ZigBee:5cc7c1f6fe11fc23",
* "sourceType": "DEVICE",
* "@type": "message",
* "flags": [],
* "messageCode": {
* "name": "TILT_DETECTED",
* "category": "WARNING"
* },
* "location": "Kitchen",
* "arguments": {
* "deviceModel": "WLS"
* },
* "id": "3499a60e-45b5-4c29-ae1a-202c2182970c",
* "sourceName": "Bosch_water_detector_1",
* "timestamp": 1714375556426
* }],
* "jsonrpc": "2.0"
* }
* </pre>
*
* @author David Pace - Initial contribution
*/
public class Message extends BoschSHCServiceState {
/**
* Source type indicating that a message is device-specific
*/
public static final String SOURCE_TYPE_DEVICE = "DEVICE";
public Message() {
super("message");
}
public String id;
public String sourceId;
public String sourceName;
public String sourceType;
public String location;
public long timestamp;
public MessageCode messageCode;
}

View File

@ -0,0 +1,32 @@
/**
* Copyright (c) 2010-2024 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.boschshc.internal.devices.bridge.dto;
/**
* DTO for message codes sent by the Smart Home Controller.
* <p>
* JSON Example:
*
* <pre>
* {
* "name": "TILT_DETECTED",
* "category": "WARNING"
* }
* </pre>
*
* @author David Pace - Initial contribution
*/
public class MessageCode {
public String name;
public String category;
}

View File

@ -12,7 +12,8 @@
*/ */
package org.openhab.binding.boschshc.internal.devices.camera; package org.openhab.binding.boschshc.internal.devices.camera;
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.*; import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_CAMERA_NOTIFICATION;
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_PRIVACY_MODE;
import java.util.List; import java.util.List;
@ -20,10 +21,9 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.boschshc.internal.devices.BoschSHCDeviceHandler; import org.openhab.binding.boschshc.internal.devices.BoschSHCDeviceHandler;
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException; 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.CameraNotificationService;
import org.openhab.binding.boschshc.internal.services.cameranotification.CameraNotificationState;
import org.openhab.binding.boschshc.internal.services.cameranotification.dto.CameraNotificationServiceState; import org.openhab.binding.boschshc.internal.services.cameranotification.dto.CameraNotificationServiceState;
import org.openhab.binding.boschshc.internal.services.dto.EnabledDisabledState;
import org.openhab.binding.boschshc.internal.services.privacymode.PrivacyModeService; import org.openhab.binding.boschshc.internal.services.privacymode.PrivacyModeService;
import org.openhab.binding.boschshc.internal.services.privacymode.PrivacyModeState;
import org.openhab.binding.boschshc.internal.services.privacymode.dto.PrivacyModeServiceState; import org.openhab.binding.boschshc.internal.services.privacymode.dto.PrivacyModeServiceState;
import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.OnOffType;
import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.ChannelUID;
@ -91,13 +91,13 @@ public class CameraHandler extends BoschSHCDeviceHandler {
private void updatePrivacyModeState(OnOffType command) { private void updatePrivacyModeState(OnOffType command) {
PrivacyModeServiceState serviceState = new PrivacyModeServiceState(); PrivacyModeServiceState serviceState = new PrivacyModeServiceState();
serviceState.value = PrivacyModeState.from(command); serviceState.value = EnabledDisabledState.from(command);
this.updateServiceState(this.privacyModeService, serviceState); this.updateServiceState(this.privacyModeService, serviceState);
} }
private void updateCameraNotificationState(OnOffType command) { private void updateCameraNotificationState(OnOffType command) {
CameraNotificationServiceState serviceState = new CameraNotificationServiceState(); CameraNotificationServiceState serviceState = new CameraNotificationServiceState();
serviceState.value = CameraNotificationState.from(command); serviceState.value = EnabledDisabledState.from(command);
this.updateServiceState(this.cameraNotificationService, serviceState); this.updateServiceState(this.cameraNotificationService, serviceState);
} }

View File

@ -0,0 +1,160 @@
/**
* Copyright (c) 2010-2024 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.waterleakage;
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_ACOUSTIC_SIGNALS_ON_MOVE;
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_PUSH_NOTIFICATIONS_ON_MOVE;
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_SENSOR_MOVED;
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_SIGNAL_STRENGTH;
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_WATER_LEAKAGE;
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_WATER_LEAKAGE_SENSOR_CHECK;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.boschshc.internal.devices.AbstractBatteryPoweredDeviceHandler;
import org.openhab.binding.boschshc.internal.devices.bridge.dto.Message;
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
import org.openhab.binding.boschshc.internal.services.communicationquality.CommunicationQualityService;
import org.openhab.binding.boschshc.internal.services.communicationquality.dto.CommunicationQualityServiceState;
import org.openhab.binding.boschshc.internal.services.dto.EnabledDisabledState;
import org.openhab.binding.boschshc.internal.services.waterleakagesensor.WaterLeakageSensorService;
import org.openhab.binding.boschshc.internal.services.waterleakagesensor.dto.WaterLeakageSensorServiceState;
import org.openhab.binding.boschshc.internal.services.waterleakagesensorcheck.WaterLeakageSensorCheckService;
import org.openhab.binding.boschshc.internal.services.waterleakagesensorcheck.dto.WaterLeakageSensorCheckServiceState;
import org.openhab.binding.boschshc.internal.services.waterleakagesensortilt.WaterLeakageSensorTiltService;
import org.openhab.binding.boschshc.internal.services.waterleakagesensortilt.dto.WaterLeakageSensorTiltServiceState;
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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Handler for water leakage sensors.
*
* @author David Pace - Initial contribution
*
*/
@NonNullByDefault
public class WaterLeakageSensorHandler extends AbstractBatteryPoweredDeviceHandler {
private final Logger logger = LoggerFactory.getLogger(WaterLeakageSensorHandler.class);
/**
* Message code indicating that the water leakage sensor was moved
*/
public static final String MESSAGE_CODE_TILT_DETECTED = "TILT_DETECTED";
private WaterLeakageSensorTiltService waterLeakageSensorTiltService;
private WaterLeakageSensorCheckService waterLeakageSensorCheckService;
@Nullable
private WaterLeakageSensorTiltServiceState currentWaterSensorTiltServiceState;
public WaterLeakageSensorHandler(Thing thing) {
super(thing);
this.waterLeakageSensorTiltService = new WaterLeakageSensorTiltService();
this.waterLeakageSensorCheckService = new WaterLeakageSensorCheckService();
}
@Override
protected void initializeServices() throws BoschSHCException {
super.initializeServices();
this.createService(WaterLeakageSensorService::new, this::updateChannels, List.of(CHANNEL_WATER_LEAKAGE), true);
this.registerService(waterLeakageSensorTiltService, this::updateChannels,
List.of(CHANNEL_PUSH_NOTIFICATIONS_ON_MOVE, CHANNEL_ACOUSTIC_SIGNALS_ON_MOVE), true);
this.registerService(waterLeakageSensorCheckService, this::updateChannels, List.of());
this.createService(CommunicationQualityService::new, this::updateChannels, List.of(CHANNEL_SIGNAL_STRENGTH),
true);
}
private void updateChannels(WaterLeakageSensorServiceState waterLeakageSensorServiceState) {
updateState(CHANNEL_WATER_LEAKAGE, waterLeakageSensorServiceState.state.toOnOffType());
}
private void updateChannels(WaterLeakageSensorTiltServiceState waterLeakageSensorTiltServiceState) {
currentWaterSensorTiltServiceState = waterLeakageSensorTiltServiceState;
updateState(CHANNEL_PUSH_NOTIFICATIONS_ON_MOVE,
waterLeakageSensorTiltServiceState.pushNotificationState.toOnOffType());
updateState(CHANNEL_ACOUSTIC_SIGNALS_ON_MOVE,
waterLeakageSensorTiltServiceState.acousticSignalState.toOnOffType());
}
private void updateChannels(WaterLeakageSensorCheckServiceState waterLeakageSensorCheckServiceState) {
updateState(CHANNEL_WATER_LEAKAGE_SENSOR_CHECK, new StringType(waterLeakageSensorCheckServiceState.result));
}
private void updateChannels(CommunicationQualityServiceState communicationQualityServiceState) {
updateState(CHANNEL_SIGNAL_STRENGTH, communicationQualityServiceState.quality.toSystemSignalStrength());
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
super.handleCommand(channelUID, command);
if (CHANNEL_PUSH_NOTIFICATIONS_ON_MOVE.equals(channelUID.getId())
&& command instanceof OnOffType onOffCommand) {
updatePushNotificationState(onOffCommand);
} else if (CHANNEL_ACOUSTIC_SIGNALS_ON_MOVE.equals(channelUID.getId())
&& command instanceof OnOffType onOffCommand) {
updateAcousticSignalState(onOffCommand);
}
}
private void updatePushNotificationState(OnOffType onOffCommand) {
WaterLeakageSensorTiltServiceState newState = cloneCurrentWaterLeakageSensorTiltServiceState();
if (newState != null) {
newState.pushNotificationState = EnabledDisabledState.from(onOffCommand);
this.currentWaterSensorTiltServiceState = newState;
updateServiceState(waterLeakageSensorTiltService, newState);
}
}
private void updateAcousticSignalState(OnOffType onOffCommand) {
WaterLeakageSensorTiltServiceState newState = cloneCurrentWaterLeakageSensorTiltServiceState();
if (newState != null) {
newState.acousticSignalState = EnabledDisabledState.from(onOffCommand);
this.currentWaterSensorTiltServiceState = newState;
updateServiceState(waterLeakageSensorTiltService, newState);
}
}
@Nullable
private WaterLeakageSensorTiltServiceState cloneCurrentWaterLeakageSensorTiltServiceState() {
if (currentWaterSensorTiltServiceState != null) {
WaterLeakageSensorTiltServiceState clonedState = new WaterLeakageSensorTiltServiceState();
clonedState.acousticSignalState = currentWaterSensorTiltServiceState.acousticSignalState;
clonedState.pushNotificationState = currentWaterSensorTiltServiceState.pushNotificationState;
return clonedState;
} else {
logger.warn("Could not obtain current water leakage detector tilt state, command will not be processed.");
}
return null;
}
@Override
public void processMessage(Message message) {
super.processMessage(message);
if (message.messageCode != null && MESSAGE_CODE_TILT_DETECTED.equals(message.messageCode.name)) {
triggerChannel(CHANNEL_SENSOR_MOVED);
}
}
}

View File

@ -98,7 +98,8 @@ public class ThingDiscoveryService extends AbstractThingHandlerDiscoveryService<
new AbstractMap.SimpleEntry<>("MICROMODULE_SHUTTER", BoschSHCBindingConstants.THING_TYPE_SHUTTER_CONTROL_2), new AbstractMap.SimpleEntry<>("MICROMODULE_SHUTTER", BoschSHCBindingConstants.THING_TYPE_SHUTTER_CONTROL_2),
new AbstractMap.SimpleEntry<>("MICROMODULE_AWNING", BoschSHCBindingConstants.THING_TYPE_SHUTTER_CONTROL_2), new AbstractMap.SimpleEntry<>("MICROMODULE_AWNING", BoschSHCBindingConstants.THING_TYPE_SHUTTER_CONTROL_2),
new AbstractMap.SimpleEntry<>("MICROMODULE_LIGHT_CONTROL", BoschSHCBindingConstants.THING_TYPE_LIGHT_CONTROL_2), new AbstractMap.SimpleEntry<>("MICROMODULE_LIGHT_CONTROL", BoschSHCBindingConstants.THING_TYPE_LIGHT_CONTROL_2),
new AbstractMap.SimpleEntry<>("MICROMODULE_DIMMER", BoschSHCBindingConstants.THING_TYPE_DIMMER) new AbstractMap.SimpleEntry<>("MICROMODULE_DIMMER", BoschSHCBindingConstants.THING_TYPE_DIMMER),
new AbstractMap.SimpleEntry<>("WLS", BoschSHCBindingConstants.THING_TYPE_WATER_DETECTOR)
// Future Extension: map deviceModel names to BoschSHC Thing Types when they are supported // Future Extension: map deviceModel names to BoschSHC Thing Types when they are supported
// new AbstractMap.SimpleEntry<>("SMOKE_DETECTION_SYSTEM", BoschSHCBindingConstants.), // new AbstractMap.SimpleEntry<>("SMOKE_DETECTION_SYSTEM", BoschSHCBindingConstants.),
// new AbstractMap.SimpleEntry<>("PRESENCE_SIMULATION_SERVICE", BoschSHCBindingConstants.), // new AbstractMap.SimpleEntry<>("PRESENCE_SIMULATION_SERVICE", BoschSHCBindingConstants.),

View File

@ -17,6 +17,7 @@ import java.lang.reflect.Type;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.boschshc.internal.devices.bridge.dto.DeviceServiceData; import org.openhab.binding.boschshc.internal.devices.bridge.dto.DeviceServiceData;
import org.openhab.binding.boschshc.internal.devices.bridge.dto.Message;
import org.openhab.binding.boschshc.internal.devices.bridge.dto.Scenario; import org.openhab.binding.boschshc.internal.devices.bridge.dto.Scenario;
import org.openhab.binding.boschshc.internal.devices.bridge.dto.UserDefinedState; import org.openhab.binding.boschshc.internal.devices.bridge.dto.UserDefinedState;
import org.openhab.binding.boschshc.internal.services.dto.BoschSHCServiceState; import org.openhab.binding.boschshc.internal.services.dto.BoschSHCServiceState;
@ -65,6 +66,9 @@ public class BoschServiceDataDeserializer implements JsonDeserializer<BoschSHCSe
state.setState(jsonObject.get("state").getAsBoolean()); state.setState(jsonObject.get("state").getAsBoolean());
return state; return state;
} }
case "message" -> {
return GsonUtils.DEFAULT_GSON_INSTANCE.fromJson(jsonElement, Message.class);
}
default -> { default -> {
return new BoschSHCServiceState(dataType.getAsString()); return new BoschSHCServiceState(dataType.getAsString());
} }

View File

@ -12,8 +12,8 @@
*/ */
package org.openhab.binding.boschshc.internal.services.cameranotification.dto; package org.openhab.binding.boschshc.internal.services.cameranotification.dto;
import org.openhab.binding.boschshc.internal.services.cameranotification.CameraNotificationState;
import org.openhab.binding.boschshc.internal.services.dto.BoschSHCServiceState; import org.openhab.binding.boschshc.internal.services.dto.BoschSHCServiceState;
import org.openhab.binding.boschshc.internal.services.dto.EnabledDisabledState;
/** /**
* Represents the state of camera notifications as reported by the Smart Home Controller. * Represents the state of camera notifications as reported by the Smart Home Controller.
@ -35,5 +35,5 @@ public class CameraNotificationServiceState extends BoschSHCServiceState {
* {"@type":"cameraNotificationState","value":"ENABLED"} * {"@type":"cameraNotificationState","value":"ENABLED"}
* </pre> * </pre>
*/ */
public CameraNotificationState value; public EnabledDisabledState value;
} }

View File

@ -10,36 +10,36 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.openhab.binding.boschshc.internal.services.cameranotification; package org.openhab.binding.boschshc.internal.services.dto;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.OnOffType;
/** /**
* Possible states for camera notifications. * State that is serialized as either <code>ENABLED</code> or <code>DISABLED</code>.
* *
* @author David Pace - Initial contribution * @author David Pace - Initial contribution
* *
*/ */
@NonNullByDefault @NonNullByDefault
public enum CameraNotificationState { public enum EnabledDisabledState {
ENABLED, ENABLED,
DISABLED; DISABLED;
/** /**
* Converts an {@link OnOffType} state into a {@link CameraNotificationState}. * Converts an {@link OnOffType} state into a {@link EnabledDisabledState}.
* *
* @param onOff the on/off state * @param onOff the on/off state
* @return the corresponding notification state * @return the corresponding enabled/disabled state
*/ */
public static CameraNotificationState from(OnOffType onOff) { public static EnabledDisabledState from(OnOffType onOff) {
return onOff == OnOffType.ON ? ENABLED : DISABLED; return onOff == OnOffType.ON ? ENABLED : DISABLED;
} }
/** /**
* Converts this {@link CameraNotificationState} into an {@link OnOffType}. * Converts this {@link EnabledDisabledState} into an {@link OnOffType}.
* *
* @return the on/off state corresponding to the notification state of this enumeration literal * @return the on/off state corresponding to the enabled/disabled state of this enumeration literal
*/ */
public OnOffType toOnOffType() { public OnOffType toOnOffType() {
return OnOffType.from(this == ENABLED); return OnOffType.from(this == ENABLED);

View File

@ -1,55 +0,0 @@
/**
* Copyright (c) 2010-2024 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.privacymode;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.library.types.OnOffType;
/**
* Possible privacy mode states of security cameras.
*
* @author David Pace - Initial contribution
*
*/
@NonNullByDefault
public enum PrivacyModeState {
/**
* Privacy mode enabled / camera disabled
*/
ENABLED,
/**
* Privacy mode disabled / camera enabled
*/
DISABLED;
/**
* Converts an {@link OnOffType} state into a {@link PrivacyModeState}.
*
* @param onOff the on/off state
* @return the corresponding privacy mode state
*/
public static PrivacyModeState from(OnOffType onOff) {
return onOff == OnOffType.ON ? ENABLED : DISABLED;
}
/**
* Converts this {@link PrivacyModeState} into an {@link OnOffType}.
*
* @return the on/off state corresponding to the privacy mode state of this enumeration literal
*/
public OnOffType toOnOffType() {
return OnOffType.from(this == ENABLED);
}
}

View File

@ -13,7 +13,7 @@
package org.openhab.binding.boschshc.internal.services.privacymode.dto; package org.openhab.binding.boschshc.internal.services.privacymode.dto;
import org.openhab.binding.boschshc.internal.services.dto.BoschSHCServiceState; import org.openhab.binding.boschshc.internal.services.dto.BoschSHCServiceState;
import org.openhab.binding.boschshc.internal.services.privacymode.PrivacyModeState; import org.openhab.binding.boschshc.internal.services.dto.EnabledDisabledState;
/** /**
* Represents the privacy mode of cameras as reported by the Smart Home Controller. * Represents the privacy mode of cameras as reported by the Smart Home Controller.
@ -35,5 +35,5 @@ public class PrivacyModeServiceState extends BoschSHCServiceState {
* {"@type":"privacyModeState","value":"ENABLED"} * {"@type":"privacyModeState","value":"ENABLED"}
* </pre> * </pre>
*/ */
public PrivacyModeState value; public EnabledDisabledState value;
} }

View File

@ -0,0 +1,31 @@
/**
* Copyright (c) 2010-2024 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.waterleakagesensor;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.boschshc.internal.services.BoschSHCService;
import org.openhab.binding.boschshc.internal.services.waterleakagesensor.dto.WaterLeakageSensorServiceState;
/**
* Service for the water leakage sensor.
*
* @author David Pace - Initial contribution
*
*/
@NonNullByDefault
public class WaterLeakageSensorService extends BoschSHCService<WaterLeakageSensorServiceState> {
public WaterLeakageSensorService() {
super("WaterLeakageSensor", WaterLeakageSensorServiceState.class);
}
}

View File

@ -0,0 +1,30 @@
/**
* Copyright (c) 2010-2024 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.waterleakagesensor.dto;
import org.openhab.binding.boschshc.internal.services.dto.BoschSHCServiceState;
/**
* Water leakage detection state of water detectors.
*
* @author David Pace - Initial contribution
*
*/
public class WaterLeakageSensorServiceState extends BoschSHCServiceState {
public WaterLeakageSensorServiceState() {
super("waterLeakageSensorState");
}
public WaterLeakageState state;
}

View File

@ -0,0 +1,32 @@
/**
* Copyright (c) 2010-2024 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.waterleakagesensor.dto;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.library.types.OnOffType;
/**
* Possible states of the water leakage sensor.
*
* @author David Pace - Initial contribution
*
*/
@NonNullByDefault
public enum WaterLeakageState {
NO_LEAKAGE,
LEAKAGE_DETECTED;
public OnOffType toOnOffType() {
return OnOffType.from(this == LEAKAGE_DETECTED);
}
}

View File

@ -0,0 +1,29 @@
/**
* Copyright (c) 2010-2024 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.waterleakagesensorcheck;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.boschshc.internal.services.BoschSHCService;
import org.openhab.binding.boschshc.internal.services.waterleakagesensorcheck.dto.WaterLeakageSensorCheckServiceState;
/**
*
* @author David Pace - Initial contribution
*
*/
@NonNullByDefault
public class WaterLeakageSensorCheckService extends BoschSHCService<WaterLeakageSensorCheckServiceState> {
public WaterLeakageSensorCheckService() {
super("WaterLeakageSensorCheck", WaterLeakageSensorCheckServiceState.class);
}
}

View File

@ -0,0 +1,30 @@
/**
* Copyright (c) 2010-2024 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.waterleakagesensorcheck.dto;
import org.openhab.binding.boschshc.internal.services.dto.BoschSHCServiceState;
/**
* DTO for the check state of water leakage sensors.
*
* @author David Pace - Initial contribution
*
*/
public class WaterLeakageSensorCheckServiceState extends BoschSHCServiceState {
public WaterLeakageSensorCheckServiceState() {
super("waterLeakageSensorCheckState");
}
public String result;
}

View File

@ -0,0 +1,31 @@
/**
* Copyright (c) 2010-2024 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.waterleakagesensortilt;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.boschshc.internal.services.BoschSHCService;
import org.openhab.binding.boschshc.internal.services.waterleakagesensortilt.dto.WaterLeakageSensorTiltServiceState;
/**
* Service for notifications relating to the water detection sensor.
*
* @author David Pace - Initial contribution
*
*/
@NonNullByDefault
public class WaterLeakageSensorTiltService extends BoschSHCService<WaterLeakageSensorTiltServiceState> {
public WaterLeakageSensorTiltService() {
super("WaterLeakageSensorTilt", WaterLeakageSensorTiltServiceState.class);
}
}

View File

@ -0,0 +1,33 @@
/**
* Copyright (c) 2010-2024 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.waterleakagesensortilt.dto;
import org.openhab.binding.boschshc.internal.services.dto.BoschSHCServiceState;
import org.openhab.binding.boschshc.internal.services.dto.EnabledDisabledState;
/**
* Service for notifications relating to the water detection sensor.
*
* @author David Pace - Initial contribution
*
*/
public class WaterLeakageSensorTiltServiceState extends BoschSHCServiceState {
public WaterLeakageSensorTiltServiceState() {
super("waterLeakageSensorTiltState");
}
public EnabledDisabledState pushNotificationState;
public EnabledDisabledState acousticSignalState;
}

View File

@ -47,6 +47,8 @@ thing-type.boschshc.user-defined-state.label = User-defined State
thing-type.boschshc.user-defined-state.description = A User-defined state. thing-type.boschshc.user-defined-state.description = A User-defined state.
thing-type.boschshc.wall-thermostat.label = Wall Thermostat thing-type.boschshc.wall-thermostat.label = Wall Thermostat
thing-type.boschshc.wall-thermostat.description = Display of the current room temperature as well as the relative humidity in the room. thing-type.boschshc.wall-thermostat.description = Display of the current room temperature as well as the relative humidity in the room.
thing-type.boschshc.water-detector.label = Water Detector
thing-type.boschshc.water-detector.description = Smart sensor to detect water leakage.
thing-type.boschshc.window-contact-2.label = Door/Window Contact II thing-type.boschshc.window-contact-2.label = Door/Window Contact II
thing-type.boschshc.window-contact-2.description = Detects open windows and doors and features an additional button. thing-type.boschshc.window-contact-2.description = Detects open windows and doors and features an additional button.
thing-type.boschshc.window-contact.label = Door/Window Contact thing-type.boschshc.window-contact.label = Door/Window Contact
@ -65,6 +67,10 @@ thing-type.config.boschshc.user-defined-state.id.description = Unique ID of the
# channel types # channel types
channel-type.boschshc.acoustic-signals-on-move.label = Acoustic Signals When Moved
channel-type.boschshc.acoustic-signals-on-move.description = Indicates whether acoustic signals are enabled when the sensor is moved.
channel-type.boschshc.acoustic-signals-on-move.state.option.ON = Enabled
channel-type.boschshc.acoustic-signals-on-move.state.option.OFF = Disabled
channel-type.boschshc.active-configuration-profile.label = Active Configuration Profile channel-type.boschshc.active-configuration-profile.label = Active Configuration Profile
channel-type.boschshc.active-configuration-profile.description = The name of the active configuration profile used for the intrusion detection system. channel-type.boschshc.active-configuration-profile.description = The name of the active configuration profile used for the intrusion detection system.
channel-type.boschshc.air-description.label = Description channel-type.boschshc.air-description.label = Description
@ -148,8 +154,14 @@ channel-type.boschshc.purity-rating.label = Purity Rating
channel-type.boschshc.purity-rating.description = Rating of the air purity. channel-type.boschshc.purity-rating.description = Rating of the air purity.
channel-type.boschshc.purity.label = Purity channel-type.boschshc.purity.label = Purity
channel-type.boschshc.purity.description = Purity of the air. A higher value indicates a higher pollution. channel-type.boschshc.purity.description = Purity of the air. A higher value indicates a higher pollution.
channel-type.boschshc.push-notifications-on-move.label = Push Notifications When Moved
channel-type.boschshc.push-notifications-on-move.description = Indicates whether push notifications are enabled when the sensor is moved.
channel-type.boschshc.push-notifications-on-move.state.option.ON = Enabled
channel-type.boschshc.push-notifications-on-move.state.option.OFF = Disabled
channel-type.boschshc.scenario-triggered.label = Scenario Triggered channel-type.boschshc.scenario-triggered.label = Scenario Triggered
channel-type.boschshc.scenario-triggered.description = Name of the triggered scenario channel-type.boschshc.scenario-triggered.description = Name of the triggered scenario
channel-type.boschshc.sensor-moved.label = Sensor Moved
channel-type.boschshc.sensor-moved.description = Triggered when the sensor is moved.
channel-type.boschshc.setpoint-temperature.label = Setpoint Temperature channel-type.boschshc.setpoint-temperature.label = Setpoint Temperature
channel-type.boschshc.setpoint-temperature.description = Desired temperature. channel-type.boschshc.setpoint-temperature.description = Desired temperature.
channel-type.boschshc.silent-mode.label = Silent Mode channel-type.boschshc.silent-mode.label = Silent Mode
@ -177,6 +189,12 @@ channel-type.boschshc.user-state.label = State
channel-type.boschshc.user-state.description = State of user-defined state channel-type.boschshc.user-state.description = State of user-defined state
channel-type.boschshc.valve-tappet-position.label = Valve Tappet Position channel-type.boschshc.valve-tappet-position.label = Valve Tappet Position
channel-type.boschshc.valve-tappet-position.description = Current open ratio (0 to 100). channel-type.boschshc.valve-tappet-position.description = Current open ratio (0 to 100).
channel-type.boschshc.water-leakage-sensor-check.label = Water Leakage Sensor Check
channel-type.boschshc.water-leakage-sensor-check.description = Provides the result of the last water leakage sensor check.
channel-type.boschshc.water-leakage.label = Water Leakage
channel-type.boschshc.water-leakage.description = Indicates whether a water leakage was detected.
channel-type.boschshc.water-leakage.state.option.ON = Leakage detected
channel-type.boschshc.water-leakage.state.option.OFF = No leakage detected
# thing status offline descriptions # thing status offline descriptions

View File

@ -439,6 +439,28 @@
<config-description-ref uri="thing-type:boschshc:device"/> <config-description-ref uri="thing-type:boschshc:device"/>
</thing-type> </thing-type>
<thing-type id="water-detector">
<supported-bridge-type-refs>
<bridge-type-ref id="shc"/>
</supported-bridge-type-refs>
<label>Water Detector</label>
<description>Smart sensor to detect water leakage.</description>
<channels>
<channel id="water-leakage" typeId="water-leakage"/>
<channel id="push-notifications-on-move" typeId="push-notifications-on-move"/>
<channel id="acoustic-signals-on-move" typeId="acoustic-signals-on-move"/>
<channel id="water-leakage-sensor-check" typeId="water-leakage-sensor-check"/>
<channel id="sensor-moved" typeId="sensor-moved"/>
<channel id="battery-level" typeId="system.battery-level"/>
<channel id="low-battery" typeId="system.low-battery"/>
<channel id="signal-strength" typeId="system.signal-strength"/>
</channels>
<config-description-ref uri="thing-type:boschshc:device"/>
</thing-type>
<!-- Channels --> <!-- Channels -->
<channel-type id="system-availability"> <channel-type id="system-availability">
@ -769,4 +791,58 @@
<description>Enables or disables the child protection on the device.</description> <description>Enables or disables the child protection on the device.</description>
</channel-type> </channel-type>
<channel-type id="water-leakage">
<item-type>Switch</item-type>
<label>Water Leakage</label>
<description>Indicates whether a water leakage was detected.</description>
<state readOnly="true">
<options>
<option value="ON">Leakage detected</option>
<option value="OFF">No leakage detected</option>
</options>
</state>
</channel-type>
<channel-type id="push-notifications-on-move">
<item-type>Switch</item-type>
<label>Push Notifications When Moved</label>
<description>Indicates whether push notifications are enabled when the sensor is moved.</description>
<state>
<options>
<option value="ON">Enabled</option>
<option value="OFF">Disabled</option>
</options>
</state>
</channel-type>
<channel-type id="acoustic-signals-on-move">
<item-type>Switch</item-type>
<label>Acoustic Signals When Moved</label>
<description>Indicates whether acoustic signals are enabled when the sensor is moved.</description>
<state>
<options>
<option value="ON">Enabled</option>
<option value="OFF">Disabled</option>
</options>
</state>
</channel-type>
<channel-type id="water-leakage-sensor-check">
<item-type>String</item-type>
<label>Water Leakage Sensor Check</label>
<description>Provides the result of the last water leakage sensor check.</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="sensor-moved">
<kind>trigger</kind>
<label>Sensor Moved</label>
<description>Triggered when the sensor is moved.</description>
<category>Alarm</category>
<tags>
<tag>Alarm</tag>
<tag>Tilt</tag>
</tags>
</channel-type>
</thing:thing-descriptions> </thing:thing-descriptions>

View File

@ -65,6 +65,7 @@ import org.openhab.binding.boschshc.internal.devices.bridge.dto.DeviceServiceDat
import org.openhab.binding.boschshc.internal.devices.bridge.dto.DeviceTest; import org.openhab.binding.boschshc.internal.devices.bridge.dto.DeviceTest;
import org.openhab.binding.boschshc.internal.devices.bridge.dto.Faults; import org.openhab.binding.boschshc.internal.devices.bridge.dto.Faults;
import org.openhab.binding.boschshc.internal.devices.bridge.dto.LongPollResult; import org.openhab.binding.boschshc.internal.devices.bridge.dto.LongPollResult;
import org.openhab.binding.boschshc.internal.devices.bridge.dto.Message;
import org.openhab.binding.boschshc.internal.devices.bridge.dto.PublicInformation; import org.openhab.binding.boschshc.internal.devices.bridge.dto.PublicInformation;
import org.openhab.binding.boschshc.internal.devices.bridge.dto.Room; import org.openhab.binding.boschshc.internal.devices.bridge.dto.Room;
import org.openhab.binding.boschshc.internal.devices.bridge.dto.Scenario; import org.openhab.binding.boschshc.internal.devices.bridge.dto.Scenario;
@ -738,6 +739,51 @@ class BridgeHandlerTest {
verify(thingHandler).processChildUpdate("hdm:ZigBee:70ac08fffefead2d#3", "PowerSwitch", expectedState); verify(thingHandler).processChildUpdate("hdm:ZigBee:70ac08fffefead2d#3", "PowerSwitch", expectedState);
} }
@Test
void handleLongPollResultHandleMessage() {
List<Thing> things = new ArrayList<Thing>();
when(thing.getThings()).thenReturn(things);
Thing thing = mock(Thing.class);
things.add(thing);
BoschSHCHandler thingHandler = mock(BoschSHCHandler.class);
when(thing.getHandler()).thenReturn(thingHandler);
when(thingHandler.getBoschID()).thenReturn("hdm:ZigBee:5cc7c1fffe1f7967");
String json = """
{
"result": [{
"sourceId": "hdm:ZigBee:5cc7c1fffe1f7967",
"sourceType": "DEVICE",
"@type": "message",
"flags": [],
"messageCode": {
"name": "TILT_DETECTED",
"category": "WARNING"
},
"location": "Kitchen",
"arguments": {
"deviceModel": "WLS"
},
"id": "3499a60e-45b5-4c29-ae1a-202c2182970c",
"sourceName": "Bosch_water_detector_1",
"timestamp": 1714375556426
}],
"jsonrpc": "2.0"
}
""";
LongPollResult longPollResult = GsonUtils.DEFAULT_GSON_INSTANCE.fromJson(json, LongPollResult.class);
assertNotNull(longPollResult);
fixture.handleLongPollResult(longPollResult);
Message expectedMessage = (Message) longPollResult.result.get(0);
verify(thingHandler).processMessage(expectedMessage);
}
@Test @Test
void handleLongPollResultScenarioTriggered() { void handleLongPollResultScenarioTriggered() {
Channel channel = mock(Channel.class); Channel channel = mock(Channel.class);

View File

@ -14,7 +14,8 @@ package org.openhab.binding.boschshc.internal.devices.camera;
import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertSame;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
@ -26,9 +27,8 @@ import org.mockito.Captor;
import org.openhab.binding.boschshc.internal.devices.AbstractBoschSHCDeviceHandlerTest; import org.openhab.binding.boschshc.internal.devices.AbstractBoschSHCDeviceHandlerTest;
import org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants; import org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants;
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException; import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
import org.openhab.binding.boschshc.internal.services.cameranotification.CameraNotificationState;
import org.openhab.binding.boschshc.internal.services.cameranotification.dto.CameraNotificationServiceState; import org.openhab.binding.boschshc.internal.services.cameranotification.dto.CameraNotificationServiceState;
import org.openhab.binding.boschshc.internal.services.privacymode.PrivacyModeState; import org.openhab.binding.boschshc.internal.services.dto.EnabledDisabledState;
import org.openhab.binding.boschshc.internal.services.privacymode.dto.PrivacyModeServiceState; import org.openhab.binding.boschshc.internal.services.privacymode.dto.PrivacyModeServiceState;
import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.OnOffType;
import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.ChannelUID;
@ -73,14 +73,14 @@ class CameraHandlerTest extends AbstractBoschSHCDeviceHandlerTest<CameraHandler>
verify(getBridgeHandler()).putState(eq(getDeviceID()), eq("PrivacyMode"), verify(getBridgeHandler()).putState(eq(getDeviceID()), eq("PrivacyMode"),
privacyModeServiceStateCaptor.capture()); privacyModeServiceStateCaptor.capture());
PrivacyModeServiceState state = privacyModeServiceStateCaptor.getValue(); PrivacyModeServiceState state = privacyModeServiceStateCaptor.getValue();
assertSame(PrivacyModeState.ENABLED, state.value); assertSame(EnabledDisabledState.ENABLED, state.value);
getFixture().handleCommand(new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_PRIVACY_MODE), getFixture().handleCommand(new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_PRIVACY_MODE),
OnOffType.OFF); OnOffType.OFF);
verify(getBridgeHandler(), times(2)).putState(eq(getDeviceID()), eq("PrivacyMode"), verify(getBridgeHandler(), times(2)).putState(eq(getDeviceID()), eq("PrivacyMode"),
privacyModeServiceStateCaptor.capture()); privacyModeServiceStateCaptor.capture());
state = privacyModeServiceStateCaptor.getValue(); state = privacyModeServiceStateCaptor.getValue();
assertSame(PrivacyModeState.DISABLED, state.value); assertSame(EnabledDisabledState.DISABLED, state.value);
} }
@Test @Test
@ -92,7 +92,7 @@ class CameraHandlerTest extends AbstractBoschSHCDeviceHandlerTest<CameraHandler>
verify(getBridgeHandler()).putState(eq(getDeviceID()), eq("CameraNotification"), verify(getBridgeHandler()).putState(eq(getDeviceID()), eq("CameraNotification"),
cameraNotificationServiceStateCaptor.capture()); cameraNotificationServiceStateCaptor.capture());
CameraNotificationServiceState state = cameraNotificationServiceStateCaptor.getValue(); CameraNotificationServiceState state = cameraNotificationServiceStateCaptor.getValue();
assertSame(CameraNotificationState.ENABLED, state.value); assertSame(EnabledDisabledState.ENABLED, state.value);
getFixture().handleCommand( getFixture().handleCommand(
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_CAMERA_NOTIFICATION), new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_CAMERA_NOTIFICATION),
@ -100,7 +100,7 @@ class CameraHandlerTest extends AbstractBoschSHCDeviceHandlerTest<CameraHandler>
verify(getBridgeHandler(), times(2)).putState(eq(getDeviceID()), eq("CameraNotification"), verify(getBridgeHandler(), times(2)).putState(eq(getDeviceID()), eq("CameraNotification"),
cameraNotificationServiceStateCaptor.capture()); cameraNotificationServiceStateCaptor.capture());
state = cameraNotificationServiceStateCaptor.getValue(); state = cameraNotificationServiceStateCaptor.getValue();
assertSame(CameraNotificationState.DISABLED, state.value); assertSame(EnabledDisabledState.DISABLED, state.value);
} }
@Test @Test

View File

@ -0,0 +1,229 @@
/**
* Copyright (c) 2010-2024 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.waterleakage;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.openhab.binding.boschshc.internal.devices.AbstractBatteryPoweredDeviceHandlerTest;
import org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants;
import org.openhab.binding.boschshc.internal.devices.bridge.dto.Message;
import org.openhab.binding.boschshc.internal.devices.bridge.dto.MessageCode;
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
import org.openhab.binding.boschshc.internal.services.dto.EnabledDisabledState;
import org.openhab.binding.boschshc.internal.services.waterleakagesensortilt.dto.WaterLeakageSensorTiltServiceState;
import org.openhab.core.library.types.DecimalType;
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.ThingTypeUID;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
/**
* Unit tests for {@link WaterLeakageSensorHandler}.
*
* @author David Pace - Initial contribution
*
*/
@NonNullByDefault
class WaterLeakageSensorHandlerTest extends AbstractBatteryPoweredDeviceHandlerTest<WaterLeakageSensorHandler> {
private @Captor @NonNullByDefault({}) ArgumentCaptor<WaterLeakageSensorTiltServiceState> waterLeakageTiltServiceStateCaptor;
@Override
protected WaterLeakageSensorHandler createFixture() {
return new WaterLeakageSensorHandler(getThing());
}
@Override
protected ThingTypeUID getThingTypeUID() {
return BoschSHCBindingConstants.THING_TYPE_WATER_DETECTOR;
}
@Override
protected String getDeviceID() {
return "hdm:ZigBee:f0d1b80001d639d5";
}
@Test
void updateChannelsWaterLeakageSensorServiceState() {
JsonElement jsonObject = JsonParser
.parseString("{\"@type\":\"waterLeakageSensorState\",\"state\": \"NO_LEAKAGE\"}");
getFixture().processUpdate("WaterLeakageSensor", jsonObject);
verify(getCallback()).stateUpdated(
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_WATER_LEAKAGE), OnOffType.OFF);
jsonObject = JsonParser.parseString("{\"@type\":\"waterLeakageSensorState\",\"state\": \"LEAKAGE_DETECTED\"}");
getFixture().processUpdate("WaterLeakageSensor", jsonObject);
verify(getCallback()).stateUpdated(
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_WATER_LEAKAGE), OnOffType.ON);
}
@Test
void updateChannelsWaterLeakageSensorTiltServiceState() {
JsonElement jsonObject = JsonParser.parseString(
"{\"@type\":\"waterLeakageSensorTiltState\",\"pushNotificationState\": \"DISABLED\",\"acousticSignalState\": \"DISABLED\"}");
getFixture().processUpdate("WaterLeakageSensorTilt", jsonObject);
verify(getCallback()).stateUpdated(
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_PUSH_NOTIFICATIONS_ON_MOVE),
OnOffType.OFF);
verify(getCallback()).stateUpdated(
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_ACOUSTIC_SIGNALS_ON_MOVE),
OnOffType.OFF);
jsonObject = JsonParser.parseString(
"{\"@type\":\"waterLeakageSensorTiltState\",\"pushNotificationState\": \"ENABLED\",\"acousticSignalState\": \"ENABLED\"}");
getFixture().processUpdate("WaterLeakageSensorTilt", jsonObject);
verify(getCallback()).stateUpdated(
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_PUSH_NOTIFICATIONS_ON_MOVE),
OnOffType.ON);
verify(getCallback()).stateUpdated(
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_ACOUSTIC_SIGNALS_ON_MOVE),
OnOffType.ON);
}
@Test
void testUpdateChannelsCommunicationQualityService() {
String json = """
{
"@type": "communicationQualityState",
"quality": "UNKNOWN"
}
""";
JsonElement jsonObject = JsonParser.parseString(json);
getFixture().processUpdate("CommunicationQuality", jsonObject);
verify(getCallback()).stateUpdated(
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_SIGNAL_STRENGTH),
new DecimalType(0));
json = """
{
"@type": "communicationQualityState",
"quality": "GOOD"
}
""";
jsonObject = JsonParser.parseString(json);
getFixture().processUpdate("CommunicationQuality", jsonObject);
verify(getCallback()).stateUpdated(
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_SIGNAL_STRENGTH),
new DecimalType(4));
}
@Test
void updateChannelsWaterLeakageSensorCheckServiceState() {
JsonElement jsonObject = JsonParser
.parseString("{\"@type\":\"waterLeakageSensorCheckState\",\"result\": \"OK\"}");
getFixture().processUpdate("WaterLeakageSensorCheck", jsonObject);
verify(getCallback()).stateUpdated(
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_WATER_LEAKAGE_SENSOR_CHECK),
new StringType("OK"));
}
@Test
void testHandleCommandPushNotificationsNoPreviousState()
throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException {
getFixture().handleCommand(
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_PUSH_NOTIFICATIONS_ON_MOVE),
OnOffType.ON);
verify(getBridgeHandler(), times(0)).putState(any(), any(), any());
}
@Test
void testHandleCommandPushNotifications()
throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException {
JsonElement jsonObject = JsonParser.parseString(
"{\"@type\":\"waterLeakageSensorTiltState\",\"pushNotificationState\": \"DISABLED\",\"acousticSignalState\": \"DISABLED\"}");
getFixture().processUpdate("WaterLeakageSensorTilt", jsonObject);
getFixture().handleCommand(
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_PUSH_NOTIFICATIONS_ON_MOVE),
OnOffType.ON);
verify(getBridgeHandler()).putState(eq(getDeviceID()), eq("WaterLeakageSensorTilt"),
waterLeakageTiltServiceStateCaptor.capture());
WaterLeakageSensorTiltServiceState state = waterLeakageTiltServiceStateCaptor.getValue();
assertSame(EnabledDisabledState.ENABLED, state.pushNotificationState);
assertSame(EnabledDisabledState.DISABLED, state.acousticSignalState);
}
@Test
void testHandleCommandAcousticSignals()
throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException {
JsonElement jsonObject = JsonParser.parseString(
"{\"@type\":\"waterLeakageSensorTiltState\",\"pushNotificationState\": \"DISABLED\",\"acousticSignalState\": \"DISABLED\"}");
getFixture().processUpdate("WaterLeakageSensorTilt", jsonObject);
getFixture().handleCommand(
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_ACOUSTIC_SIGNALS_ON_MOVE),
OnOffType.ON);
verify(getBridgeHandler()).putState(eq(getDeviceID()), eq("WaterLeakageSensorTilt"),
waterLeakageTiltServiceStateCaptor.capture());
WaterLeakageSensorTiltServiceState state = waterLeakageTiltServiceStateCaptor.getValue();
assertSame(EnabledDisabledState.DISABLED, state.pushNotificationState);
assertSame(EnabledDisabledState.ENABLED, state.acousticSignalState);
}
@Test
void testHandleCommandPushNotificationsInvalidCommandType()
throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException {
getFixture().handleCommand(
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_PUSH_NOTIFICATIONS_ON_MOVE),
new StringType("test"));
verify(getBridgeHandler(), times(0)).putState(any(), any(), any());
}
@Test
void testHandleCommandAcousticSignalsInvalidCommandType()
throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException {
getFixture().handleCommand(
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_ACOUSTIC_SIGNALS_ON_MOVE),
new StringType("test"));
verify(getBridgeHandler(), times(0)).putState(any(), any(), any());
}
@Test
void testHandleCommandPushNotificationsInvalidChannel()
throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException {
getFixture().handleCommand(new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_POWER_SWITCH),
OnOffType.ON);
verify(getBridgeHandler(), times(0)).putState(any(), any(), any());
}
@Test
void processMessageTiltDetected() {
Message message = new Message();
message.sourceType = Message.SOURCE_TYPE_DEVICE;
MessageCode messageCode = new MessageCode();
messageCode.name = WaterLeakageSensorHandler.MESSAGE_CODE_TILT_DETECTED;
messageCode.category = "WARNING";
message.messageCode = messageCode;
getFixture().processMessage(message);
verify(getCallback()).channelTriggered(getThing(),
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_SENSOR_MOVED), "");
}
}

View File

@ -1,41 +0,0 @@
/**
* Copyright (c) 2010-2024 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.cameranotification;
import static org.junit.jupiter.api.Assertions.assertSame;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.Test;
import org.openhab.core.library.types.OnOffType;
/**
* Unit tests for {@link CameraNotificationState}.
*
* @author David Pace - Initial contribution
*
*/
@NonNullByDefault
class CameraNotificationStateTest {
@Test
void testFromOnOffType() {
assertSame(CameraNotificationState.ENABLED, CameraNotificationState.from(OnOffType.ON));
assertSame(CameraNotificationState.DISABLED, CameraNotificationState.from(OnOffType.OFF));
}
@Test
void testToOnOffType() {
assertSame(OnOffType.ON, CameraNotificationState.ENABLED.toOnOffType());
assertSame(OnOffType.OFF, CameraNotificationState.DISABLED.toOnOffType());
}
}

View File

@ -10,7 +10,7 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.openhab.binding.boschshc.internal.services.privacymode; package org.openhab.binding.boschshc.internal.services.dto;
import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertSame;
@ -19,23 +19,23 @@ import org.junit.jupiter.api.Test;
import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.OnOffType;
/** /**
* Unit tests for {@link PrivacyModeState}. * Unit tests for {@link EnabledDisabledState}.
* *
* @author David Pace - Initial contribution * @author David Pace - Initial contribution
* *
*/ */
@NonNullByDefault @NonNullByDefault
class PrivacyModeStateTest { class EnabledDisabledStateTest {
@Test @Test
void testFromOnOffType() { void testFromOnOffType() {
assertSame(PrivacyModeState.ENABLED, PrivacyModeState.from(OnOffType.ON)); assertSame(EnabledDisabledState.ENABLED, EnabledDisabledState.from(OnOffType.ON));
assertSame(PrivacyModeState.DISABLED, PrivacyModeState.from(OnOffType.OFF)); assertSame(EnabledDisabledState.DISABLED, EnabledDisabledState.from(OnOffType.OFF));
} }
@Test @Test
void testToOnOffType() { void testToOnOffType() {
assertSame(OnOffType.ON, PrivacyModeState.ENABLED.toOnOffType()); assertSame(OnOffType.ON, EnabledDisabledState.ENABLED.toOnOffType());
assertSame(OnOffType.OFF, PrivacyModeState.DISABLED.toOnOffType()); assertSame(OnOffType.OFF, EnabledDisabledState.DISABLED.toOnOffType());
} }
} }