forked from openhab/openhab-addons
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[boschshc] Add support for Dimmer (openhab#16501)
Adds support for Bosch Smart Home Dimmer devices. Signed-off-by: David Pace <dev@davidpace.de> Signed-off-by: Patrik Gfeller <patrik.gfeller@proton.me>
- Loading branch information
1 parent
09e93a6
commit df0bd2e
Showing
8 changed files
with
291 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
98 changes: 98 additions & 0 deletions
98
...c/main/java/org/openhab/binding/boschshc/internal/devices/lightcontrol/DimmerHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
/** | ||
* 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.lightcontrol; | ||
|
||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_BRIGHTNESS; | ||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_CHILD_PROTECTION; | ||
import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_SIGNAL_STRENGTH; | ||
|
||
import java.util.List; | ||
|
||
import org.eclipse.jdt.annotation.NonNullByDefault; | ||
import org.openhab.binding.boschshc.internal.devices.AbstractPowerSwitchHandler; | ||
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException; | ||
import org.openhab.binding.boschshc.internal.services.childprotection.ChildProtectionService; | ||
import org.openhab.binding.boschshc.internal.services.childprotection.dto.ChildProtectionServiceState; | ||
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.multilevelswitch.MultiLevelSwitchService; | ||
import org.openhab.binding.boschshc.internal.services.multilevelswitch.dto.MultiLevelSwitchServiceState; | ||
import org.openhab.core.library.types.OnOffType; | ||
import org.openhab.core.library.types.PercentType; | ||
import org.openhab.core.thing.ChannelUID; | ||
import org.openhab.core.thing.Thing; | ||
import org.openhab.core.types.Command; | ||
|
||
/** | ||
* Handler for Bosch Smart Home dimmers. | ||
* | ||
* @author David Pace - Initial contribution | ||
* | ||
*/ | ||
@NonNullByDefault | ||
public class DimmerHandler extends AbstractPowerSwitchHandler { | ||
|
||
private MultiLevelSwitchService multiLevelSwitchService; | ||
private ChildProtectionService childProtectionService; | ||
|
||
public DimmerHandler(Thing thing) { | ||
super(thing); | ||
|
||
this.multiLevelSwitchService = new MultiLevelSwitchService(); | ||
this.childProtectionService = new ChildProtectionService(); | ||
} | ||
|
||
@Override | ||
protected void initializeServices() throws BoschSHCException { | ||
super.initializeServices(); | ||
|
||
createService(CommunicationQualityService::new, this::updateChannels, List.of(CHANNEL_SIGNAL_STRENGTH), true); | ||
registerService(multiLevelSwitchService, this::updateChannels, List.of(CHANNEL_BRIGHTNESS), true); | ||
registerService(childProtectionService, this::updateChannels, List.of(CHANNEL_CHILD_PROTECTION), true); | ||
} | ||
|
||
private void updateChannels(MultiLevelSwitchServiceState serviceState) { | ||
super.updateState(CHANNEL_BRIGHTNESS, serviceState.toPercentType()); | ||
} | ||
|
||
private void updateChannels(CommunicationQualityServiceState communicationQualityServiceState) { | ||
updateState(CHANNEL_SIGNAL_STRENGTH, communicationQualityServiceState.quality.toSystemSignalStrength()); | ||
} | ||
|
||
private void updateChannels(ChildProtectionServiceState childProtectionServiceState) { | ||
super.updateState(CHANNEL_CHILD_PROTECTION, OnOffType.from(childProtectionServiceState.childLockActive)); | ||
} | ||
|
||
@Override | ||
public void handleCommand(ChannelUID channelUID, Command command) { | ||
super.handleCommand(channelUID, command); | ||
|
||
if (CHANNEL_CHILD_PROTECTION.equals(channelUID.getId()) && (command instanceof OnOffType onOffCommand)) { | ||
updateChildProtectionState(onOffCommand); | ||
} else if (CHANNEL_BRIGHTNESS.equals(channelUID.getId()) && command instanceof PercentType percentCommand) { | ||
updateMultiLevelSwitchState(percentCommand); | ||
} | ||
} | ||
|
||
private void updateChildProtectionState(OnOffType onOffCommand) { | ||
ChildProtectionServiceState childProtectionServiceState = new ChildProtectionServiceState(); | ||
childProtectionServiceState.childLockActive = onOffCommand == OnOffType.ON; | ||
updateServiceState(childProtectionService, childProtectionServiceState); | ||
} | ||
|
||
private void updateMultiLevelSwitchState(PercentType percentCommand) { | ||
MultiLevelSwitchServiceState serviceState = new MultiLevelSwitchServiceState(); | ||
serviceState.level = percentCommand.intValue(); | ||
this.updateServiceState(multiLevelSwitchService, serviceState); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
153 changes: 153 additions & 0 deletions
153
...st/java/org/openhab/binding/boschshc/internal/devices/lightcontrol/DimmerHandlerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
/** | ||
* 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.lightcontrol; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.junit.jupiter.api.Assertions.assertTrue; | ||
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.AbstractPowerSwitchHandlerTest; | ||
import org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants; | ||
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException; | ||
import org.openhab.binding.boschshc.internal.services.childprotection.dto.ChildProtectionServiceState; | ||
import org.openhab.binding.boschshc.internal.services.multilevelswitch.dto.MultiLevelSwitchServiceState; | ||
import org.openhab.core.library.types.DecimalType; | ||
import org.openhab.core.library.types.OnOffType; | ||
import org.openhab.core.library.types.PercentType; | ||
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 DimmerHandler}. | ||
* | ||
* @author David Pace - Initial contribution | ||
* | ||
*/ | ||
@NonNullByDefault | ||
class DimmerHandlerTest extends AbstractPowerSwitchHandlerTest<DimmerHandler> { | ||
|
||
private @Captor @NonNullByDefault({}) ArgumentCaptor<MultiLevelSwitchServiceState> multiLevelSwitchServiceStateCaptor; | ||
|
||
private @Captor @NonNullByDefault({}) ArgumentCaptor<ChildProtectionServiceState> childProtectionServiceStateCaptor; | ||
|
||
@Override | ||
protected DimmerHandler createFixture() { | ||
return new DimmerHandler(getThing()); | ||
} | ||
|
||
@Override | ||
protected ThingTypeUID getThingTypeUID() { | ||
return BoschSHCBindingConstants.THING_TYPE_DIMMER; | ||
} | ||
|
||
@Override | ||
protected String getDeviceID() { | ||
return "hdm:ZigBee:60b647fffec5a9d8"; | ||
} | ||
|
||
@Test | ||
void testUpdateChannelMultiLevelSwitchState() { | ||
JsonElement jsonObject = JsonParser.parseString("{\"@type\":\"multiLevelSwitchState\",\"level\":16}"); | ||
getFixture().processUpdate("MultiLevelSwitch", jsonObject); | ||
verify(getCallback()).stateUpdated( | ||
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_BRIGHTNESS), new PercentType(16)); | ||
} | ||
|
||
@Test | ||
void testUpdateChannelsChildProtectionService() { | ||
String json = """ | ||
{ | ||
"@type": "ChildProtectionState", | ||
"childLockActive": true | ||
} | ||
"""; | ||
JsonElement jsonObject = JsonParser.parseString(json); | ||
|
||
getFixture().processUpdate("ChildProtection", jsonObject); | ||
verify(getCallback()).stateUpdated( | ||
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_CHILD_PROTECTION), OnOffType.ON); | ||
} | ||
|
||
@Test | ||
void testHandleCommandMultiLevelSwitch() | ||
throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException { | ||
getFixture().handleCommand(new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_BRIGHTNESS), | ||
new PercentType(42)); | ||
verify(getBridgeHandler()).putState(eq(getDeviceID()), eq("MultiLevelSwitch"), | ||
multiLevelSwitchServiceStateCaptor.capture()); | ||
MultiLevelSwitchServiceState state = multiLevelSwitchServiceStateCaptor.getValue(); | ||
assertEquals(42, state.level); | ||
} | ||
|
||
@Test | ||
void testUpdateChannelCommunicationQualityService() { | ||
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 testHandleCommandChildProtection() | ||
throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException { | ||
getFixture().handleCommand( | ||
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_CHILD_PROTECTION), OnOffType.ON); | ||
verify(getBridgeHandler()).putState(eq(getDeviceID()), eq("ChildProtection"), | ||
childProtectionServiceStateCaptor.capture()); | ||
ChildProtectionServiceState state = childProtectionServiceStateCaptor.getValue(); | ||
assertTrue(state.childLockActive); | ||
} | ||
|
||
@Test | ||
void testHandleCommandChildProtectionInvalidCommand() | ||
throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException { | ||
getFixture().handleCommand( | ||
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_CHILD_PROTECTION), | ||
DecimalType.ZERO); | ||
verify(getBridgeHandler(), times(0)).putState(eq(getDeviceID()), eq("ChildProtection"), | ||
childProtectionServiceStateCaptor.capture()); | ||
} | ||
} |