Skip to content

Commit 778f9f6

Browse files
authored
[boschshc] Add support for Door/Window Contact II Plus (openhab#18201)
Signed-off-by: David Pace <[email protected]>
1 parent bb79656 commit 778f9f6

File tree

14 files changed

+568
-30
lines changed

14 files changed

+568
-30
lines changed

bundles/org.openhab.binding.boschshc/DEVELOPERS.md

+17
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
# For Developers
22

3+
## Typical Workflow for Supporting new Devices / Services / Channels
4+
5+
1. Define new thing types and channel types in `src/main/resources/OH-INF/thing/thing-types.xml`
6+
1. If `thing-types.xml` was modified, re-generate the i18n properties file by running Maven with the goal `i18n:generate-default-translations`
7+
1. Define constants for new thing/channel types in `BoschSHCBindingConstants`
8+
1. Create new packages for services that are not implemented yet and create service classes
9+
1. Create new DTO packages for new services and implement data transfer model classes / enums according to the JSON structure of the service requests
10+
1. Create a new handler or extend existing handlers to update channel states according to what was received, and/or to send new states to the Bosch Smart Home Controller in case of writable channels
11+
1. Register new handlers in `BoschSHCHandlerFactory`, if applicable
12+
1. Register new thing types in `ThingDiscoveryService`, if applicable
13+
1. Implement unit tests for new handlers / services / model classes
14+
15+
1. If channels were added to existing devices/things, add a migration instruction set to `src/main/resources/update/binding.xml`
16+
1. Add documentation for new things/channels to `README.md`
17+
1. Apply automatic code formatting by running a Maven build with goal `spotless:apply`
18+
1. Build the binding by running a Maven build with goals `clean install`
19+
320
## Build
421

522
To only build the Bosch Smart Home binding code execute

bundles/org.openhab.binding.boschshc/README.md

+18-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ Detects open windows and doors.
121121

122122
Detects open windows and doors and features an additional button.
123123

124-
**Thing Type ID**: `window-contact`
124+
**Thing Type ID**: `window-contact-2`
125125

126126
| Channel Type ID | Item Type | Writable | Description |
127127
| ----------------| --------- | :------: | ---------------------------- |
@@ -131,6 +131,23 @@ Detects open windows and doors and features an additional button.
131131
| bypass | Switch | &#9744; | Indicates whether the device is currently bypassed. Possible values are `ON`,`OFF` and `UNDEF` if the bypass state cannot be determined. |
132132
| 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). |
133133

134+
### Door/Window Contact II Plus
135+
136+
Detects open windows and doors, provides a configurable button and a vibration sensor.
137+
138+
**Thing Type ID**: `window-contact-2-plus`
139+
140+
| Channel Type ID | Item Type | Writable | Description |
141+
| -----------------------------| --------- | :------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
142+
| contact | Contact | &#9744; | Contact state of the device. |
143+
| 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`. |
144+
| low-battery | Switch | &#9744; | Indicates whether the battery is low (`ON`) or OK (`OFF`). |
145+
| bypass | Switch | &#9744; | Indicates whether the device is currently bypassed. Possible values are `ON`,`OFF` and `UNDEF` if the bypass state cannot be determined. |
146+
| 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). |
147+
| vibration-sensor-enabled | Switch | &#9745; | Channel to enable or disable the vibration sensor. |
148+
| vibration-sensor-sensitivity | String | &#9745; | The sensitivity of the vibration sensor. Possible values are `VERY_HIGH`, `HIGH`, `MEDIUM`, `LOW` and `VERY_LOW`. |
149+
| vibration-sensor-state | String | &#9744; | Indicates whether vibrations were detected by the sensor. Possible values are `NO_VIBRATION`, `VIBRATION_DETECTED` and `UNKNOWN`. |
150+
134151
### Light Control II
135152

136153
This thing type is used if Light/Shutter Control II devices are configured as light controls.

bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/console/BoschShcCommandExtension.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ List<String> getAllBoschShcServices() {
8585
"childlock", "childprotection", "communicationquality", "hsbcoloractuator", "humiditylevel",
8686
"illuminance", "impulseswitch", "intrusion", "keypad", "latestmotion", "multilevelswitch", "powermeter",
8787
"powerswitch", "privacymode", "roomclimatecontrol", "shuttercontact", "shuttercontrol", "silentmode",
88-
"smokedetectorcheck", "temperaturelevel", "userstate", "valvetappet", "waterleakagesensor",
89-
"waterleakagesensorcheck", "waterleakagesensortilt");
88+
"smokedetectorcheck", "temperaturelevel", "userstate", "valvetappet", "vibrationsensor",
89+
"waterleakagesensor", "waterleakagesensorcheck", "waterleakagesensortilt");
9090
}
9191

9292
@Override

bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/BoschSHCBindingConstants.java

+5
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ private BoschSHCBindingConstants() {
4141
public static final ThingTypeUID THING_TYPE_TWINGUARD = new ThingTypeUID(BINDING_ID, "twinguard");
4242
public static final ThingTypeUID THING_TYPE_WINDOW_CONTACT = new ThingTypeUID(BINDING_ID, "window-contact");
4343
public static final ThingTypeUID THING_TYPE_WINDOW_CONTACT_2 = new ThingTypeUID(BINDING_ID, "window-contact-2");
44+
public static final ThingTypeUID THING_TYPE_WINDOW_CONTACT_2_PLUS = new ThingTypeUID(BINDING_ID,
45+
"window-contact-2-plus");
4446
public static final ThingTypeUID THING_TYPE_MOTION_DETECTOR = new ThingTypeUID(BINDING_ID, "motion-detector");
4547
public static final ThingTypeUID THING_TYPE_SHUTTER_CONTROL = new ThingTypeUID(BINDING_ID, "shutter-control");
4648
public static final ThingTypeUID THING_TYPE_SHUTTER_CONTROL_2 = new ThingTypeUID(BINDING_ID, "shutter-control-2");
@@ -117,6 +119,9 @@ private BoschSHCBindingConstants() {
117119
public static final String CHANNEL_IMPULSE_LENGTH = "impulse-length";
118120
public static final String CHANNEL_INSTANT_OF_LAST_IMPULSE = "instant-of-last-impulse";
119121
public static final String CHANNEL_ALARM = "alarm";
122+
public static final String CHANNEL_VIBRATION_SENSOR_ENABLED = "vibration-sensor-enabled";
123+
public static final String CHANNEL_VIBRATION_SENSOR_SENSITIVITY = "vibration-sensor-sensitivity";
124+
public static final String CHANNEL_VIBRATION_SENSOR_STATE = "vibration-sensor-state";
120125
// numbered channels
121126
// the rationale for introducing numbered channels was discussed in
122127
// https://github.com/openhab/openhab-addons/pull/16400

bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/BoschSHCHandlerFactory.java

+5-27
Original file line numberDiff line numberDiff line change
@@ -12,31 +12,7 @@
1212
*/
1313
package org.openhab.binding.boschshc.internal.devices;
1414

15-
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_CAMERA_360;
16-
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_CAMERA_EYES;
17-
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_CLIMATE_CONTROL;
18-
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_DIMMER;
19-
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_INTRUSION_DETECTION_SYSTEM;
20-
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_INWALL_SWITCH;
21-
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_LIGHT_CONTROL_2;
22-
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_MOTION_DETECTOR;
23-
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_RELAY;
24-
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_SHC;
25-
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_SHUTTER_CONTROL;
26-
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_SHUTTER_CONTROL_2;
27-
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_SMART_BULB;
28-
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_SMART_PLUG_COMPACT;
29-
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_SMOKE_DETECTOR;
30-
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_SMOKE_DETECTOR_2;
31-
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_THERMOSTAT;
32-
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_TWINGUARD;
33-
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_UNIVERSAL_SWITCH;
34-
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_UNIVERSAL_SWITCH_2;
35-
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_USER_DEFINED_STATE;
36-
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_WALL_THERMOSTAT;
37-
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_WATER_DETECTOR;
38-
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_WINDOW_CONTACT;
39-
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.THING_TYPE_WINDOW_CONTACT_2;
15+
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.*;
4016

4117
import java.util.Collection;
4218
import java.util.List;
@@ -67,6 +43,7 @@
6743
import org.openhab.binding.boschshc.internal.devices.wallthermostat.WallThermostatHandler;
6844
import org.openhab.binding.boschshc.internal.devices.waterleakage.WaterLeakageSensorHandler;
6945
import org.openhab.binding.boschshc.internal.devices.windowcontact.WindowContact2Handler;
46+
import org.openhab.binding.boschshc.internal.devices.windowcontact.WindowContact2PlusHandler;
7047
import org.openhab.binding.boschshc.internal.devices.windowcontact.WindowContactHandler;
7148
import org.openhab.core.thing.Bridge;
7249
import org.openhab.core.thing.Thing;
@@ -107,6 +84,7 @@ public ThingTypeHandlerMapping(ThingTypeUID thingTypeUID, Function<Thing, BaseTh
10784
new ThingTypeHandlerMapping(THING_TYPE_TWINGUARD, TwinguardHandler::new),
10885
new ThingTypeHandlerMapping(THING_TYPE_WINDOW_CONTACT, WindowContactHandler::new),
10986
new ThingTypeHandlerMapping(THING_TYPE_WINDOW_CONTACT_2, WindowContact2Handler::new),
87+
new ThingTypeHandlerMapping(THING_TYPE_WINDOW_CONTACT_2_PLUS, WindowContact2PlusHandler::new),
11088
new ThingTypeHandlerMapping(THING_TYPE_MOTION_DETECTOR, MotionDetectorHandler::new),
11189
new ThingTypeHandlerMapping(THING_TYPE_SHUTTER_CONTROL, ShutterControlHandler::new),
11290
new ThingTypeHandlerMapping(THING_TYPE_SHUTTER_CONTROL_2, ShutterControl2Handler::new),
@@ -120,8 +98,8 @@ public ThingTypeHandlerMapping(ThingTypeUID thingTypeUID, Function<Thing, BaseTh
12098
new ThingTypeHandlerMapping(THING_TYPE_SMART_BULB, SmartBulbHandler::new),
12199
new ThingTypeHandlerMapping(THING_TYPE_SMOKE_DETECTOR, SmokeDetectorHandler::new),
122100
new ThingTypeHandlerMapping(THING_TYPE_USER_DEFINED_STATE, UserStateHandler::new),
123-
new ThingTypeHandlerMapping(THING_TYPE_UNIVERSAL_SWITCH, thing -> new UniversalSwitchHandler(thing)),
124-
new ThingTypeHandlerMapping(THING_TYPE_UNIVERSAL_SWITCH_2, thing -> new UniversalSwitch2Handler(thing)),
101+
new ThingTypeHandlerMapping(THING_TYPE_UNIVERSAL_SWITCH, UniversalSwitchHandler::new),
102+
new ThingTypeHandlerMapping(THING_TYPE_UNIVERSAL_SWITCH_2, UniversalSwitch2Handler::new),
125103
new ThingTypeHandlerMapping(THING_TYPE_SMOKE_DETECTOR_2, SmokeDetector2Handler::new),
126104
new ThingTypeHandlerMapping(THING_TYPE_LIGHT_CONTROL_2, LightControl2Handler::new),
127105
new ThingTypeHandlerMapping(THING_TYPE_DIMMER, DimmerHandler::new),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
* Copyright (c) 2010-2025 Contributors to the openHAB project
3+
*
4+
* See the NOTICE file(s) distributed with this work for additional
5+
* information.
6+
*
7+
* This program and the accompanying materials are made available under the
8+
* terms of the Eclipse Public License 2.0 which is available at
9+
* http://www.eclipse.org/legal/epl-2.0
10+
*
11+
* SPDX-License-Identifier: EPL-2.0
12+
*/
13+
package org.openhab.binding.boschshc.internal.devices.windowcontact;
14+
15+
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.*;
16+
17+
import java.util.List;
18+
19+
import org.eclipse.jdt.annotation.NonNullByDefault;
20+
import org.eclipse.jdt.annotation.Nullable;
21+
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
22+
import org.openhab.binding.boschshc.internal.services.vibrationsensor.VibrationSensorService;
23+
import org.openhab.binding.boschshc.internal.services.vibrationsensor.dto.VibrationSensorSensitivity;
24+
import org.openhab.binding.boschshc.internal.services.vibrationsensor.dto.VibrationSensorServiceState;
25+
import org.openhab.core.library.types.OnOffType;
26+
import org.openhab.core.library.types.StringType;
27+
import org.openhab.core.thing.ChannelUID;
28+
import org.openhab.core.thing.Thing;
29+
import org.openhab.core.types.Command;
30+
import org.slf4j.Logger;
31+
import org.slf4j.LoggerFactory;
32+
33+
/**
34+
* Handler for Door/Window Contact II Plus.
35+
*
36+
* @author David Pace - Initial contribution
37+
*
38+
*/
39+
@NonNullByDefault
40+
public class WindowContact2PlusHandler extends WindowContact2Handler {
41+
42+
private final Logger logger = LoggerFactory.getLogger(WindowContact2PlusHandler.class);
43+
44+
private final VibrationSensorService vibrationSensorService;
45+
46+
@Nullable
47+
private VibrationSensorServiceState currentVibrationSensorState;
48+
49+
public WindowContact2PlusHandler(Thing thing) {
50+
super(thing);
51+
this.vibrationSensorService = new VibrationSensorService();
52+
}
53+
54+
@Override
55+
protected void initializeServices() throws BoschSHCException {
56+
super.initializeServices();
57+
58+
this.registerService(vibrationSensorService, this::updateChannels, List.of(CHANNEL_VIBRATION_SENSOR_ENABLED,
59+
CHANNEL_VIBRATION_SENSOR_STATE, CHANNEL_VIBRATION_SENSOR_SENSITIVITY), true);
60+
}
61+
62+
private void updateChannels(VibrationSensorServiceState state) {
63+
this.currentVibrationSensorState = state;
64+
updateState(CHANNEL_VIBRATION_SENSOR_ENABLED, OnOffType.from(state.enabled));
65+
updateState(CHANNEL_VIBRATION_SENSOR_STATE, new StringType(state.value.toString()));
66+
updateState(CHANNEL_VIBRATION_SENSOR_SENSITIVITY, new StringType(state.sensitivity.toString()));
67+
}
68+
69+
@Override
70+
public void handleCommand(ChannelUID channelUID, Command command) {
71+
super.handleCommand(channelUID, command);
72+
73+
switch (channelUID.getId()) {
74+
case CHANNEL_VIBRATION_SENSOR_ENABLED:
75+
if (command instanceof OnOffType onOffCommand) {
76+
updateVibrationSensorEnabled(onOffCommand);
77+
}
78+
break;
79+
case CHANNEL_VIBRATION_SENSOR_SENSITIVITY:
80+
if (command instanceof StringType stringCommand) {
81+
updateVibrationSensorSensitivity(stringCommand.toFullString());
82+
}
83+
break;
84+
}
85+
}
86+
87+
private void updateVibrationSensorSensitivity(String sensitivityValue) {
88+
VibrationSensorSensitivity newSensitivity = VibrationSensorSensitivity.from(sensitivityValue);
89+
90+
if (newSensitivity == null) {
91+
logger.warn("Unsupported vibration sensor sensitivity value: {}", sensitivityValue);
92+
return;
93+
}
94+
95+
VibrationSensorServiceState copy = copyCurrentState();
96+
if (copy == null) {
97+
return;
98+
}
99+
100+
copy.sensitivity = newSensitivity;
101+
102+
this.currentVibrationSensorState = copy;
103+
updateServiceState(vibrationSensorService, copy);
104+
}
105+
106+
private void updateVibrationSensorEnabled(OnOffType enabled) {
107+
VibrationSensorServiceState copy = copyCurrentState();
108+
if (copy == null) {
109+
return;
110+
}
111+
112+
copy.enabled = enabled == OnOffType.ON;
113+
114+
this.currentVibrationSensorState = copy;
115+
updateServiceState(vibrationSensorService, copy);
116+
}
117+
118+
@Nullable
119+
private VibrationSensorServiceState copyCurrentState() {
120+
if (currentVibrationSensorState != null) {
121+
return currentVibrationSensorState.copy();
122+
}
123+
124+
logger.warn("Could not obtain current vibration sensor service state, command will not be processed.");
125+
return null;
126+
}
127+
}

bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/discovery/ThingDiscoveryService.java

+1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ public class ThingDiscoveryService extends AbstractThingHandlerDiscoveryService<
9292
new AbstractMap.SimpleEntry<>("LEDVANCE_LIGHT", BoschSHCBindingConstants.THING_TYPE_SMART_BULB),
9393
new AbstractMap.SimpleEntry<>("SWD", BoschSHCBindingConstants.THING_TYPE_WINDOW_CONTACT),
9494
new AbstractMap.SimpleEntry<>("SWD2", BoschSHCBindingConstants.THING_TYPE_WINDOW_CONTACT_2),
95+
new AbstractMap.SimpleEntry<>("SWD2_PLUS", BoschSHCBindingConstants.THING_TYPE_WINDOW_CONTACT_2_PLUS),
9596
new AbstractMap.SimpleEntry<>("TRV", BoschSHCBindingConstants.THING_TYPE_THERMOSTAT),
9697
new AbstractMap.SimpleEntry<>("WRC2", BoschSHCBindingConstants.THING_TYPE_UNIVERSAL_SWITCH),
9798
new AbstractMap.SimpleEntry<>("SWITCH2", BoschSHCBindingConstants.THING_TYPE_UNIVERSAL_SWITCH_2),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright (c) 2010-2025 Contributors to the openHAB project
3+
*
4+
* See the NOTICE file(s) distributed with this work for additional
5+
* information.
6+
*
7+
* This program and the accompanying materials are made available under the
8+
* terms of the Eclipse Public License 2.0 which is available at
9+
* http://www.eclipse.org/legal/epl-2.0
10+
*
11+
* SPDX-License-Identifier: EPL-2.0
12+
*/
13+
package org.openhab.binding.boschshc.internal.services.vibrationsensor;
14+
15+
import org.eclipse.jdt.annotation.NonNullByDefault;
16+
import org.openhab.binding.boschshc.internal.services.BoschSHCService;
17+
import org.openhab.binding.boschshc.internal.services.vibrationsensor.dto.VibrationSensorServiceState;
18+
19+
/**
20+
* Service implementation for vibration sensors of door/window contacts.
21+
*
22+
* @author David Pace - Initial contribution
23+
*
24+
*/
25+
@NonNullByDefault
26+
public class VibrationSensorService extends BoschSHCService<VibrationSensorServiceState> {
27+
28+
public VibrationSensorService() {
29+
super("VibrationSensor", VibrationSensorServiceState.class);
30+
}
31+
}

0 commit comments

Comments
 (0)