From 5f7531c8201a42d9e02f8a3a1dfc08c2fd8c458b Mon Sep 17 00:00:00 2001 From: David Pace Date: Sun, 26 Jan 2025 21:31:47 +0100 Subject: [PATCH] [boschshc] Provide alarm channel for smoke detectors * add new channel definition for alarm channel in thing-types.xml * add alarm channel to Smoke Detector and Smoke Detector II * add update instruction sets in binding.xml * re-generate i18n properties file * add constant for new channel * implement alarm service * register service package in tests * extend abstract smoke detector handler * add unit tests * add documentation Signed-off-by: David Pace --- .../org.openhab.binding.boschshc/README.md | 22 +++--- .../console/BoschShcCommandExtension.java | 8 +-- .../devices/AbstractSmokeDetectorHandler.java | 13 ++++ .../devices/BoschSHCBindingConstants.java | 1 + .../internal/services/alarm/AlarmService.java | 44 ++++++++++++ .../services/alarm/dto/AlarmServiceState.java | 29 ++++++++ .../services/alarm/dto/AlarmState.java | 40 +++++++++++ .../resources/OH-INF/i18n/boschshc.properties | 6 ++ .../resources/OH-INF/thing/thing-types.xml | 17 +++++ .../main/resources/OH-INF/update/binding.xml | 16 +++++ .../AbstractSmokeDetectorHandlerTest.java | 71 +++++++++++++------ .../services/alarm/AlarmServiceTest.java | 54 ++++++++++++++ .../services/alarm/dto/AlarmStateTest.java | 37 ++++++++++ 13 files changed, 325 insertions(+), 33 deletions(-) create mode 100644 bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/services/alarm/AlarmService.java create mode 100644 bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/services/alarm/dto/AlarmServiceState.java create mode 100644 bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/services/alarm/dto/AlarmState.java create mode 100644 bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/services/alarm/AlarmServiceTest.java create mode 100644 bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/services/alarm/dto/AlarmStateTest.java diff --git a/bundles/org.openhab.binding.boschshc/README.md b/bundles/org.openhab.binding.boschshc/README.md index 9ebf88009e3..b3c7e2a1ed1 100644 --- a/bundles/org.openhab.binding.boschshc/README.md +++ b/bundles/org.openhab.binding.boschshc/README.md @@ -296,9 +296,12 @@ The smoke detector warns you in case of fire. **Thing Type ID**: `smoke-detector` -| Channel Type ID | Item Type | Writable | Description | -| ------------------ | -------------------- | :------: | ------------------------------------------------------------------------------------------------- | -| smoke-check | String | ☑ | State of the smoke check. Also used to request a new smoke check. | +| Channel Type ID | Item Type | Writable | Description | +| ----------------| ----------| :------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| alarm | String | ☑ | Alarm state of the smoke detector. Possible values are: `IDLE_OFF`, `PRIMARY_ALARM`, `SECONDARY_ALARM` and `INTRUSION_ALARM`. | +| smoke-check | String | ☑ | State of the smoke check. Also used to request a new smoke check. | +| battery-level | Number | ☐ | Current battery level percentage as integer number. Bosch-specific battery levels are mapped to numbers as follows: `OK`: 100, `LOW_BATTERY`: 10, `CRITICAL_LOW`: 1, `CRITICALLY_LOW_BATTERY`: 1, `NOT_AVAILABLE`: `UNDEF`. | +| low-battery | Switch | ☐ | Indicates whether the battery is low (`ON`) or OK (`OFF`). | ### Smoke Detector II @@ -306,12 +309,13 @@ The smoke detector warns you in case of fire. **Thing Type ID**: `smoke-detector` -| Channel Type ID | Item Type | Writable | Description | -|-------------------|-------------| :------: |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| smoke-check | String | ☑ | State of the smoke check. Also used to request a new smoke check. | -| battery-level | Number | ☐ | Current battery level percentage as integer number. Bosch-specific battery levels are mapped to numbers as follows: `OK`: 100, `LOW_BATTERY`: 10, `CRITICAL_LOW`: 1, `CRITICALLY_LOW_BATTERY`: 1, `NOT_AVAILABLE`: `UNDEF`. | -| low-battery | Switch | ☐ | Indicates whether the battery is low (`ON`) or OK (`OFF`). | -| signal-strength | Number | ☐ | Communication quality between the device and the Smart Home Controller. Possible values range between 0 (unknown) and 4 (best signal strength). | +| Channel Type ID | Item Type | Writable | Description | +|-----------------|-----------| :------: |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| alarm | String | ☑ | Alarm state of the smoke detector. Possible values are: `IDLE_OFF`, `PRIMARY_ALARM`, `SECONDARY_ALARM` and `INTRUSION_ALARM`. | +| smoke-check | String | ☑ | State of the smoke check. Also used to request a new smoke check. | +| battery-level | Number | ☐ | Current battery level percentage as integer number. Bosch-specific battery levels are mapped to numbers as follows: `OK`: 100, `LOW_BATTERY`: 10, `CRITICAL_LOW`: 1, `CRITICALLY_LOW_BATTERY`: 1, `NOT_AVAILABLE`: `UNDEF`. | +| low-battery | Switch | ☐ | Indicates whether the battery is low (`ON`) or OK (`OFF`). | +| signal-strength | Number | ☐ | Communication quality between the device and the Smart Home Controller. Possible values range between 0 (unknown) and 4 (best signal strength). | ### User-defined States diff --git a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/console/BoschShcCommandExtension.java b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/console/BoschShcCommandExtension.java index 9bbc9e43107..9916f45e5ea 100644 --- a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/console/BoschShcCommandExtension.java +++ b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/console/BoschShcCommandExtension.java @@ -81,10 +81,10 @@ public class BoschShcCommandExtension extends AbstractConsoleCommandExtension im * src/main/java/org/openhab/binding/boschshc/internal/services. */ List getAllBoschShcServices() { - return List.of("airqualitylevel", "batterylevel", "binaryswitch", "bypass", "cameranotification", "childlock", - "childprotection", "communicationquality", "hsbcoloractuator", "humiditylevel", "illuminance", - "impulseswitch", "intrusion", "keypad", "latestmotion", "multilevelswitch", "powermeter", "powerswitch", - "privacymode", "roomclimatecontrol", "shuttercontact", "shuttercontrol", "silentmode", + return List.of("airqualitylevel", "alarm", "batterylevel", "binaryswitch", "bypass", "cameranotification", + "childlock", "childprotection", "communicationquality", "hsbcoloractuator", "humiditylevel", + "illuminance", "impulseswitch", "intrusion", "keypad", "latestmotion", "multilevelswitch", "powermeter", + "powerswitch", "privacymode", "roomclimatecontrol", "shuttercontact", "shuttercontrol", "silentmode", "smokedetectorcheck", "temperaturelevel", "userstate", "valvetappet", "waterleakagesensor", "waterleakagesensorcheck", "waterleakagesensortilt"); } diff --git a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/AbstractSmokeDetectorHandler.java b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/AbstractSmokeDetectorHandler.java index 75ee078ad04..91d9ee9a95b 100644 --- a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/AbstractSmokeDetectorHandler.java +++ b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/AbstractSmokeDetectorHandler.java @@ -12,12 +12,15 @@ */ package org.openhab.binding.boschshc.internal.devices; +import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_ALARM; import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_SMOKE_CHECK; import java.util.List; import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException; +import org.openhab.binding.boschshc.internal.services.alarm.AlarmService; +import org.openhab.binding.boschshc.internal.services.alarm.dto.AlarmServiceState; import org.openhab.binding.boschshc.internal.services.smokedetectorcheck.SmokeDetectorCheckService; import org.openhab.binding.boschshc.internal.services.smokedetectorcheck.dto.SmokeDetectorCheckServiceState; import org.openhab.core.library.types.StringType; @@ -34,10 +37,12 @@ import org.openhab.core.types.Command; @NonNullByDefault public abstract class AbstractSmokeDetectorHandler extends AbstractBatteryPoweredDeviceHandler { + private AlarmService alarmService; private SmokeDetectorCheckService smokeDetectorCheckService; protected AbstractSmokeDetectorHandler(Thing thing) { super(thing); + this.alarmService = new AlarmService(); this.smokeDetectorCheckService = new SmokeDetectorCheckService(); } @@ -45,6 +50,7 @@ public abstract class AbstractSmokeDetectorHandler extends AbstractBatteryPowere protected void initializeServices() throws BoschSHCException { super.initializeServices(); + this.registerService(alarmService, this::updateChannels, List.of(CHANNEL_ALARM)); this.registerService(smokeDetectorCheckService, this::updateChannels, List.of(CHANNEL_SMOKE_CHECK)); } @@ -53,12 +59,19 @@ public abstract class AbstractSmokeDetectorHandler extends AbstractBatteryPowere super.handleCommand(channelUID, command); switch (channelUID.getId()) { + case CHANNEL_ALARM: + this.handleServiceCommand(this.alarmService, command); + break; case CHANNEL_SMOKE_CHECK: this.handleServiceCommand(this.smokeDetectorCheckService, command); break; } } + private void updateChannels(AlarmServiceState state) { + updateState(CHANNEL_ALARM, new StringType(state.value.toString())); + } + private void updateChannels(SmokeDetectorCheckServiceState state) { updateState(CHANNEL_SMOKE_CHECK, new StringType(state.value.toString())); } diff --git a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/BoschSHCBindingConstants.java b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/BoschSHCBindingConstants.java index 1f157431d60..4a01184b7cd 100644 --- a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/BoschSHCBindingConstants.java +++ b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/BoschSHCBindingConstants.java @@ -116,6 +116,7 @@ public class BoschSHCBindingConstants { public static final String CHANNEL_IMPULSE_SWITCH = "impulse-switch"; public static final String CHANNEL_IMPULSE_LENGTH = "impulse-length"; public static final String CHANNEL_INSTANT_OF_LAST_IMPULSE = "instant-of-last-impulse"; + public static final String CHANNEL_ALARM = "alarm"; // numbered channels // the rationale for introducing numbered channels was discussed in // https://github.com/openhab/openhab-addons/pull/16400 diff --git a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/services/alarm/AlarmService.java b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/services/alarm/AlarmService.java new file mode 100644 index 00000000000..02ac03048b4 --- /dev/null +++ b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/services/alarm/AlarmService.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2010-2025 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.alarm; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException; +import org.openhab.binding.boschshc.internal.services.BoschSHCService; +import org.openhab.binding.boschshc.internal.services.alarm.dto.AlarmServiceState; +import org.openhab.binding.boschshc.internal.services.alarm.dto.AlarmState; +import org.openhab.core.library.types.StringType; +import org.openhab.core.types.Command; + +/** + * Alarm service for smoke detectors. + * + * @author David Pace - Initial contribution + * + */ +@NonNullByDefault +public class AlarmService extends BoschSHCService { + public AlarmService() { + super("Alarm", AlarmServiceState.class); + } + + @Override + public AlarmServiceState handleCommand(Command command) throws BoschSHCException { + if (command instanceof StringType stringCommand) { + AlarmServiceState state = new AlarmServiceState(); + state.value = AlarmState.from(stringCommand.toFullString()); + return state; + } + return super.handleCommand(command); + } +} diff --git a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/services/alarm/dto/AlarmServiceState.java b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/services/alarm/dto/AlarmServiceState.java new file mode 100644 index 00000000000..fe462c638f6 --- /dev/null +++ b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/services/alarm/dto/AlarmServiceState.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2010-2025 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.alarm.dto; + +import org.openhab.binding.boschshc.internal.services.dto.BoschSHCServiceState; + +/** + * State for alarm services of smoke detectors. + * + * @author David Pace - Initial contribution + * + */ +public class AlarmServiceState extends BoschSHCServiceState { + public AlarmServiceState() { + super("alarmState"); + } + + public AlarmState value; +} diff --git a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/services/alarm/dto/AlarmState.java b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/services/alarm/dto/AlarmState.java new file mode 100644 index 00000000000..bf18cbb17e8 --- /dev/null +++ b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/services/alarm/dto/AlarmState.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2010-2025 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.alarm.dto; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Possible states of smoke detector alarms. + * + * @author David Pace - Initial contribution + * + */ +public enum AlarmState { + IDLE_OFF, + PRIMARY_ALARM, + SECONDARY_ALARM, + INTRUSION_ALARM; + + private static final Logger LOGGER = LoggerFactory.getLogger(AlarmState.class); + + public static AlarmState from(String identifier) { + try { + return valueOf(identifier); + } catch (IllegalArgumentException e) { + LOGGER.warn("Unsupported alarm state: {}", identifier); + return IDLE_OFF; + } + } +} diff --git a/bundles/org.openhab.binding.boschshc/src/main/resources/OH-INF/i18n/boschshc.properties b/bundles/org.openhab.binding.boschshc/src/main/resources/OH-INF/i18n/boschshc.properties index d66c4e8de47..000331a09d4 100644 --- a/bundles/org.openhab.binding.boschshc/src/main/resources/OH-INF/i18n/boschshc.properties +++ b/bundles/org.openhab.binding.boschshc/src/main/resources/OH-INF/i18n/boschshc.properties @@ -84,6 +84,12 @@ channel-type.boschshc.alarm-state.state.option.PRE_ALARM = Alarm is about to go channel-type.boschshc.alarm-state.state.option.ALARM_ON = Alarm was triggered channel-type.boschshc.alarm-state.state.option.ALARM_MUTED = Alarm is muted channel-type.boschshc.alarm-state.state.option.UNKNOWN = Alarm status is unknown +channel-type.boschshc.alarm.label = Alarm +channel-type.boschshc.alarm.description = Alarm state of the smoke detector. +channel-type.boschshc.alarm.state.option.IDLE_OFF = Alarm off +channel-type.boschshc.alarm.state.option.PRIMARY_ALARM = Primary alarm +channel-type.boschshc.alarm.state.option.SECONDARY_ALARM = Secondary alarm +channel-type.boschshc.alarm.state.option.INTRUSION_ALARM = Intrusion alarm channel-type.boschshc.arm-action.label = Arm Action channel-type.boschshc.arm-action.description = Arms the intrusion detection system using the given profile ID. channel-type.boschshc.arming-state.label = Arming State diff --git a/bundles/org.openhab.binding.boschshc/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.boschshc/src/main/resources/OH-INF/thing/thing-types.xml index 1bb020940eb..836f58a128e 100644 --- a/bundles/org.openhab.binding.boschshc/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.boschshc/src/main/resources/OH-INF/thing/thing-types.xml @@ -344,6 +344,7 @@ The smoke detector warns you in case of fire. + @@ -412,6 +413,7 @@ The smoke detector warns you in case of fire. + @@ -887,4 +889,19 @@ + + String + + Alarm state of the smoke detector. + Alarm + + + + + + + + + + diff --git a/bundles/org.openhab.binding.boschshc/src/main/resources/OH-INF/update/binding.xml b/bundles/org.openhab.binding.boschshc/src/main/resources/OH-INF/update/binding.xml index 78bdc3fac3b..5d440641c33 100644 --- a/bundles/org.openhab.binding.boschshc/src/main/resources/OH-INF/update/binding.xml +++ b/bundles/org.openhab.binding.boschshc/src/main/resources/OH-INF/update/binding.xml @@ -22,4 +22,20 @@ + + + + boschshc:alarm + + + + + + + + boschshc:alarm + + + + diff --git a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractSmokeDetectorHandlerTest.java b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractSmokeDetectorHandlerTest.java index 935626f6bde..acfd2913b58 100644 --- a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractSmokeDetectorHandlerTest.java +++ b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractSmokeDetectorHandlerTest.java @@ -14,7 +14,10 @@ package org.openhab.binding.boschshc.internal.devices; import static org.junit.jupiter.api.Assertions.assertSame; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_ALARM; +import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_SMOKE_CHECK; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; @@ -24,7 +27,8 @@ import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.openhab.binding.boschshc.internal.devices.smokedetector.SmokeDetectorHandler; -import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException; +import org.openhab.binding.boschshc.internal.services.alarm.dto.AlarmServiceState; +import org.openhab.binding.boschshc.internal.services.alarm.dto.AlarmState; import org.openhab.binding.boschshc.internal.services.smokedetectorcheck.SmokeDetectorCheckState; import org.openhab.binding.boschshc.internal.services.smokedetectorcheck.dto.SmokeDetectorCheckServiceState; import org.openhab.core.library.types.OnOffType; @@ -52,32 +56,34 @@ public abstract class AbstractSmokeDetectorHandlerTest smokeDetectorCheckStateCaptor; + @Captor + private @NonNullByDefault({}) ArgumentCaptor alarmStateCaptor; + @Test - public void testHandleCommand() - throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException { + public void testHandleCommandSmokeTest() throws InterruptedException, TimeoutException, ExecutionException { // valid commands with valid thing & channel - getFixture().handleCommand(new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_SMOKE_CHECK), + getFixture().handleCommand(new ChannelUID(getThing().getUID(), CHANNEL_SMOKE_CHECK), new StringType(SmokeDetectorCheckState.SMOKE_TEST_REQUESTED.toString())); verify(getBridgeHandler()).putState(eq(getDeviceID()), eq("SmokeDetectorCheck"), smokeDetectorCheckStateCaptor.capture()); SmokeDetectorCheckServiceState state = smokeDetectorCheckStateCaptor.getValue(); assertSame(SmokeDetectorCheckState.SMOKE_TEST_REQUESTED, state.value); - getFixture().handleCommand(new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_SMOKE_CHECK), + getFixture().handleCommand(new ChannelUID(getThing().getUID(), CHANNEL_SMOKE_CHECK), new StringType(SmokeDetectorCheckState.NONE.toString())); verify(getBridgeHandler(), times(2)).putState(eq(getDeviceID()), eq("SmokeDetectorCheck"), smokeDetectorCheckStateCaptor.capture()); state = smokeDetectorCheckStateCaptor.getValue(); assertSame(SmokeDetectorCheckState.NONE, state.value); - getFixture().handleCommand(new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_SMOKE_CHECK), + getFixture().handleCommand(new ChannelUID(getThing().getUID(), CHANNEL_SMOKE_CHECK), new StringType(SmokeDetectorCheckState.SMOKE_TEST_OK.toString())); verify(getBridgeHandler(), times(3)).putState(eq(getDeviceID()), eq("SmokeDetectorCheck"), smokeDetectorCheckStateCaptor.capture()); state = smokeDetectorCheckStateCaptor.getValue(); assertSame(SmokeDetectorCheckState.SMOKE_TEST_OK, state.value); - getFixture().handleCommand(new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_SMOKE_CHECK), + getFixture().handleCommand(new ChannelUID(getThing().getUID(), CHANNEL_SMOKE_CHECK), new StringType(SmokeDetectorCheckState.SMOKE_TEST_FAILED.toString())); verify(getBridgeHandler(), times(4)).putState(eq(getDeviceID()), eq("SmokeDetectorCheck"), smokeDetectorCheckStateCaptor.capture()); @@ -86,10 +92,8 @@ public abstract class AbstractSmokeDetectorHandlerTest fixture.handleCommand(new DecimalType(0))); + } +} diff --git a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/services/alarm/dto/AlarmStateTest.java b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/services/alarm/dto/AlarmStateTest.java new file mode 100644 index 00000000000..a272984e43b --- /dev/null +++ b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/services/alarm/dto/AlarmStateTest.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2010-2025 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.alarm.dto; + +import static org.junit.jupiter.api.Assertions.assertSame; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.jupiter.api.Test; + +/** + * Unit tests for {@link AlarmState}. + * + * @author David Pace - Initial contribution + * + */ +@NonNullByDefault +class AlarmStateTest { + @Test + void testFromValidIdentifier() { + assertSame(AlarmState.PRIMARY_ALARM, AlarmState.from("PRIMARY_ALARM")); + } + + @Test + void testFromInvalidIdentifier() { + assertSame(AlarmState.IDLE_OFF, AlarmState.from("INVALID")); + } +}