Skip to content

Commit

Permalink
[boschshc] Provide alarm channel for smoke detectors (#18194)
Browse files Browse the repository at this point in the history
Signed-off-by: David Pace <[email protected]>
  • Loading branch information
david-pace authored Feb 6, 2025
1 parent 28ce3c2 commit ea978fe
Show file tree
Hide file tree
Showing 19 changed files with 448 additions and 51 deletions.
34 changes: 19 additions & 15 deletions bundles/org.openhab.binding.boschshc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -284,34 +284,38 @@ A smart bulb connected to the bridge via Zigbee such as a Ledvance Smart+ bulb.

**Thing Type ID**: `smart-bulb`

| Channel Type ID | Item Type | Writable | Description |
| ----------------| --------- | :------: | -------------------------------------------------------------- |
| power-switch | Switch | &#9745; | Switches the light on or off. |
| brightness | Dimmer | &#9745; | Regulates the brightness on a percentage scale from 0 to 100%. |
| color | Color | &#9745; | The color of the emitted light. |
| Channel Type ID | Item Type | Writable | Description |
| ---------------- | --------- | :------: | -------------------------------------------------------------- |
| power-switch | Switch | &#9745; | Switches the light on or off. |
| brightness | Dimmer | &#9745; | Regulates the brightness on a percentage scale from 0 to 100%. |
| color | Color | &#9745; | The color of the emitted light. |

### Smoke Detector

The smoke detector warns you in case of fire.

**Thing Type ID**: `smoke-detector`

| Channel Type ID | Item Type | Writable | Description |
| ------------------ | -------------------- | :------: | ------------------------------------------------------------------------------------------------- |
| smoke-check | String | &#9745; | State of the smoke check. Also used to request a new smoke check. |
| Channel Type ID | Item Type | Writable | Description |
| ---------------- | --------- | :------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| alarm | String | &#9745; | Alarm state of the smoke detector. Possible values to read are: `IDLE_OFF`, `PRIMARY_ALARM`, `SECONDARY_ALARM` and `INTRUSION_ALARM`. Possible values to write are: `INTRUSION_ALARM_ON_REQUESTED` and `INTRUSION_ALARM_OFF_REQUESTED`. |
| smoke-check | String | &#9745; | State of the smoke check. Also used to request a new smoke check. |
| 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`). |

### Smoke Detector II

The smoke detector warns you in case of fire.

**Thing Type ID**: `smoke-detector`
**Thing Type ID**: `smoke-detector-2`

| Channel Type ID | Item Type | Writable | Description |
|-------------------|-------------| :------: |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| smoke-check | String | &#9745; | State of the smoke check. Also used to request a new smoke check. |
| 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). |
| Channel Type ID | Item Type | Writable | Description |
| --------------- | --------- | :------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| alarm | String | &#9745; | Alarm state of the smoke detector. Possible values to read are: `IDLE_OFF`, `PRIMARY_ALARM`, `SECONDARY_ALARM` and `INTRUSION_ALARM`. Possible values to write are: `INTRUSION_ALARM_ON_REQUESTED` and `INTRUSION_ALARM_OFF_REQUESTED`. |
| smoke-check | String | &#9745; | State of the smoke check. Also used to request a new smoke check. |
| 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). |

### User-defined States

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@ public BoschShcCommandExtension(final @Reference ThingRegistry thingRegistry) {
* <code>src/main/java/org/openhab/binding/boschshc/internal/services</code>.
*/
List<String> 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");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,8 @@ protected void initializeServices() throws BoschSHCException {
public void handleCommand(ChannelUID channelUID, Command command) {
super.handleCommand(channelUID, command);

switch (channelUID.getId()) {
case CHANNEL_SMOKE_CHECK:
this.handleServiceCommand(this.smokeDetectorCheckService, command);
break;
if (CHANNEL_SMOKE_CHECK.equals(channelUID.getId())) {
this.handleServiceCommand(this.smokeDetectorCheckService, command);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ private 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
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* 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.devices.smokedetector;

import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_ALARM;

import java.util.List;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.boschshc.internal.devices.AbstractSmokeDetectorHandler;
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.core.library.types.StringType;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.types.Command;

/**
* Abstract handler for smoke detectors that have an <code>Alarm</code> service.
* <p>
* Note that this includes Smoke Detector and Smoke Detector II, but not Twinguard.
*
* @author David Pace - Initial contribution
*
*/
@NonNullByDefault
public abstract class AbstractSmokeDetectorHandlerWithAlarmService extends AbstractSmokeDetectorHandler {

private AlarmService alarmService;

protected AbstractSmokeDetectorHandlerWithAlarmService(Thing thing) {
super(thing);
this.alarmService = new AlarmService();
}

@Override
protected void initializeServices() throws BoschSHCException {
super.initializeServices();

this.registerService(alarmService, this::updateChannels, List.of(CHANNEL_ALARM));
}

private void updateChannels(AlarmServiceState state) {
updateState(CHANNEL_ALARM, new StringType(state.value.toString()));
}

@Override
public void handleCommand(ChannelUID channelUID, Command command) {
super.handleCommand(channelUID, command);

if (CHANNEL_ALARM.equals(channelUID.getId())) {
this.handleServiceCommand(this.alarmService, command);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import java.util.List;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.boschshc.internal.devices.AbstractSmokeDetectorHandler;
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;
Expand All @@ -29,7 +28,7 @@
* @author Patrick Gell - Initial contribution
*/
@NonNullByDefault
public class SmokeDetector2Handler extends AbstractSmokeDetectorHandler {
public class SmokeDetector2Handler extends AbstractSmokeDetectorHandlerWithAlarmService {

public SmokeDetector2Handler(Thing thing) {
super(thing);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
package org.openhab.binding.boschshc.internal.devices.smokedetector;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.boschshc.internal.devices.AbstractSmokeDetectorHandler;
import org.openhab.core.thing.Thing;

/**
Expand All @@ -23,7 +22,7 @@
* @author Gerd Zanker - AbstractSmokeDetectorHandler refactoring for reuse
*/
@NonNullByDefault
public class SmokeDetectorHandler extends AbstractSmokeDetectorHandler {
public class SmokeDetectorHandler extends AbstractSmokeDetectorHandlerWithAlarmService {

public SmokeDetectorHandler(Thing thing) {
super(thing);
Expand Down
Original file line number Diff line number Diff line change
@@ -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<AlarmServiceState> {
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);
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* 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,
INTRUSION_ALARM_ON_REQUESTED,
INTRUSION_ALARM_OFF_REQUESTED;

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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@ 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.alarm.state.option.INTRUSION_ALARM_ON_REQUESTED = Intrusion alarm on requested
channel-type.boschshc.alarm.state.option.INTRUSION_ALARM_OFF_REQUESTED = Intrusion alarm off requested
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -344,11 +344,16 @@
<description>The smoke detector warns you in case of fire.</description>

<channels>
<channel id="alarm" typeId="alarm"/>
<channel id="smoke-check" typeId="smoke-check"/>
<channel id="battery-level" typeId="system.battery-level"/>
<channel id="low-battery" typeId="system.low-battery"/>
</channels>

<properties>
<property name="thingTypeVersion">1</property>
</properties>

<config-description-ref uri="thing-type:boschshc:device"/>
</thing-type>

Expand Down Expand Up @@ -412,12 +417,17 @@
<description>The smoke detector warns you in case of fire.</description>

<channels>
<channel id="alarm" typeId="alarm"/>
<channel id="smoke-check" typeId="smoke-check"/>
<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>

<properties>
<property name="thingTypeVersion">1</property>
</properties>

<config-description-ref uri="thing-type:boschshc:device"/>
</thing-type>

Expand Down Expand Up @@ -887,4 +897,21 @@
<state readOnly="true"/>
</channel-type>

<channel-type id="alarm">
<item-type>String</item-type>
<label>Alarm</label>
<description>Alarm state of the smoke detector.</description>
<category>Alarm</category>
<state readOnly="false">
<options>
<option value="IDLE_OFF">Alarm off</option>
<option value="PRIMARY_ALARM">Primary alarm</option>
<option value="SECONDARY_ALARM">Secondary alarm</option>
<option value="INTRUSION_ALARM">Intrusion alarm</option>
<option value="INTRUSION_ALARM_ON_REQUESTED">Intrusion alarm on requested</option>
<option value="INTRUSION_ALARM_OFF_REQUESTED">Intrusion alarm off requested</option>
</options>
</state>
</channel-type>

</thing:thing-descriptions>
Loading

0 comments on commit ea978fe

Please sign in to comment.