diff --git a/bundles/org.openhab.binding.boschshc/README.md b/bundles/org.openhab.binding.boschshc/README.md index 9331afa9f..979f54659 100644 --- a/bundles/org.openhab.binding.boschshc/README.md +++ b/bundles/org.openhab.binding.boschshc/README.md @@ -4,9 +4,10 @@ Binding for the Bosch Smart Home. - [Bosch Smart Home Binding](#bosch-smart-home-binding) - [Supported Things](#supported-things) - - [In-Wall switches & Smart Plugs](#in-wall-switches-smart-plugs) - - [TwinGuard smoke detector](#twinguard-smoke-detector) - - [Door/Window contact](#door-window-contact) + - [In-Wall Switch](#in-wall-switch) + - [Compact Smart Plug](#compact-smart-plug) + - [Twinguard Smoke Detector](#twinguard-smoke-detector) + - [Door/Window Contact](#door-window-contact) - [Motion Detector](#motion-detector) - [Shutter Control](#shutter-control) - [Thermostat](#thermostat) @@ -24,19 +25,31 @@ Binding for the Bosch Smart Home. ## Supported Things -### In-Wall switches & Smart Plugs +### In-Wall Switch A simple light control. **Thing Type ID**: `in-wall-switch` -| Channel Type ID | Item Type | Writable | Description | -| ------------------ | ------------- | :------: | -------------------------------------------- | -| power-switch | Switch | ☑ | Current state of the switch. | -| power-consumption | Number:Power | ☐ | Current power consumption (W) of the device. | -| energy-consumption | Number:Energy | ☐ | Energy consumption of the device. | +| Channel Type ID | Item Type | Writable | Description | +| ------------------ | ------------- | :------: | ------------------------------------------------ | +| power-switch | Switch | ☑ | Current state of the switch. | +| power-consumption | Number:Power | ☐ | Current power consumption (W) of the device. | +| energy-consumption | Number:Energy | ☐ | Cumulated energy consumption (Wh) of the device. | -### TwinGuard smoke detector +### Compact Smart Plug + +A compact smart plug with energy monitoring capabilities. + +**Thing Type ID**: `smart-plug-compact` + +| Channel Type ID | Item Type | Writable | Description | +| ------------------ | ------------- | :------: | ------------------------------------------------ | +| power-switch | Switch | ☑ | Current state of the switch. | +| power-consumption | Number:Power | ☐ | Current power consumption (W) of the device. | +| energy-consumption | Number:Energy | ☐ | Cumulated energy consumption (Wh) of the device. | + +### Twinguard smoke detector The Twinguard smoke detector warns you in case of fire and constantly monitors the air. @@ -53,7 +66,7 @@ The Twinguard smoke detector warns you in case of fire and constantly monitors t | air-description | String | ☐ | Overall description of the air quality. | | combined-rating | String | ☐ | Combined rating of the air quality. | -### Door/Window contact +### Door/Window Contact Detects open windows and doors. diff --git a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/AbstractPowerSwitchHandler.java b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/AbstractPowerSwitchHandler.java new file mode 100644 index 000000000..21503db05 --- /dev/null +++ b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/AbstractPowerSwitchHandler.java @@ -0,0 +1,110 @@ +/** + * Copyright (c) 2010-2022 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; + +import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.*; + +import java.util.List; + +import javax.measure.quantity.Energy; +import javax.measure.quantity.Power; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException; +import org.openhab.binding.boschshc.internal.services.powermeter.PowerMeterService; +import org.openhab.binding.boschshc.internal.services.powermeter.dto.PowerMeterServiceState; +import org.openhab.binding.boschshc.internal.services.powerswitch.PowerSwitchService; +import org.openhab.binding.boschshc.internal.services.powerswitch.PowerSwitchState; +import org.openhab.binding.boschshc.internal.services.powerswitch.dto.PowerSwitchServiceState; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.library.types.QuantityType; +import org.openhab.core.library.unit.Units; +import org.openhab.core.thing.ChannelUID; +import org.openhab.core.thing.Thing; +import org.openhab.core.types.Command; +import org.openhab.core.types.State; + +/** + * Abstract handler implementation for devices with power switches and energy monitoring. + *

+ * This implementation provides the functionality to + *

+ * + * @author David Pace - Initial contribution (extracted from LightControlHandler) + */ +@NonNullByDefault +public abstract class AbstractPowerSwitchHandler extends BoschSHCDeviceHandler { + + /** + * Service for switching the device on and off + */ + private final PowerSwitchService powerSwitchService; + + protected AbstractPowerSwitchHandler(Thing thing) { + super(thing); + this.powerSwitchService = new PowerSwitchService(); + } + + @Override + protected void initializeServices() throws BoschSHCException { + super.initializeServices(); + + this.registerService(this.powerSwitchService, this::updateChannels, List.of(CHANNEL_POWER_SWITCH), true); + this.createService(PowerMeterService::new, this::updateChannels, + List.of(CHANNEL_POWER_CONSUMPTION, CHANNEL_ENERGY_CONSUMPTION), true); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + super.handleCommand(channelUID, command); + + switch (channelUID.getId()) { + case CHANNEL_POWER_SWITCH: + if (command instanceof OnOffType) { + updatePowerSwitchState((OnOffType) command); + } + break; + } + } + + /** + * Updates the channels which are linked to the {@link PowerMeterService} of the device. + * + * @param state Current state of {@link PowerMeterService}. + */ + private void updateChannels(PowerMeterServiceState state) { + super.updateState(CHANNEL_POWER_CONSUMPTION, new QuantityType(state.powerConsumption, Units.WATT)); + super.updateState(CHANNEL_ENERGY_CONSUMPTION, + new QuantityType(state.energyConsumption, Units.WATT_HOUR)); + } + + /** + * Updates the channels which are linked to the {@link PowerSwitchService} of the device. + * + * @param state Current state of {@link PowerSwitchService}. + */ + private void updateChannels(PowerSwitchServiceState state) { + State powerState = OnOffType.from(state.switchState.toString()); + super.updateState(CHANNEL_POWER_SWITCH, powerState); + } + + private void updatePowerSwitchState(OnOffType command) { + PowerSwitchServiceState state = new PowerSwitchServiceState(); + state.switchState = PowerSwitchState.valueOf(command.toFullString()); + this.updateServiceState(this.powerSwitchService, state); + } +} 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 6b3cf4e3e..7097deba8 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 @@ -44,6 +44,7 @@ public class BoschSHCBindingConstants { public static final ThingTypeUID THING_TYPE_CAMERA_EYES = new ThingTypeUID(BINDING_ID, "security-camera-eyes"); public static final ThingTypeUID THING_TYPE_INTRUSION_DETECTION_SYSTEM = new ThingTypeUID(BINDING_ID, "intrusion-detection-system"); + public static final ThingTypeUID THING_TYPE_SMART_PLUG_COMPACT = new ThingTypeUID(BINDING_ID, "smart-plug-compact"); // List of all Channel IDs // Auto-generated from thing-types.xml via script, don't modify diff --git a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/BoschSHCDeviceHandler.java b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/BoschSHCDeviceHandler.java index a7e1fc88f..7479efd09 100644 --- a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/BoschSHCDeviceHandler.java +++ b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/BoschSHCDeviceHandler.java @@ -28,19 +28,19 @@ import org.openhab.core.thing.ThingStatusDetail; * The device ID of physical devices has to be configured in the thing configuration. *

* Examples for physical device IDs are: - * + * *

  * hdm:Cameras:d20354de-44b5-3acc-924c-24c98d59da42
  * hdm:ZigBee:000d6f0016d1cdae
  * 
- * + * * @author Stefan Kästle - Initial contribution * @author Christian Oeing - refactorings of e.g. server registration * @author David Pace - Handler abstraction * */ @NonNullByDefault -public class BoschSHCDeviceHandler extends BoschSHCHandler { +public abstract class BoschSHCDeviceHandler extends BoschSHCHandler { /** * Bosch SHC configuration loaded from openHAB configuration. @@ -85,6 +85,7 @@ public class BoschSHCDeviceHandler extends BoschSHCHandler { * * @return Unique id of the Bosch device. */ + @Override public @Nullable String getBoschID() { if (config != null) { return config.id; diff --git a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/BoschSHCHandler.java b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/BoschSHCHandler.java index 5fbbe50a6..9e3d79836 100644 --- a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/BoschSHCHandler.java +++ b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/BoschSHCHandler.java @@ -100,14 +100,14 @@ public abstract class BoschSHCHandler extends BaseThingHandler { * Returns the unique id of the Bosch device or service. *

* For physical devices, the ID looks like - * + * *

      * hdm:Cameras:d20354de-44b5-3acc-924c-24c98d59da42
      * hdm:ZigBee:000d6f0016d1c087
      * 
- * + * * For virtual devices / services, static IDs like the following are used: - * + * *
      * ventilationService
      * smokeDetectionSystem
@@ -241,8 +241,29 @@ public abstract class BoschSHCHandler extends BaseThingHandler {
     protected , TState extends BoschSHCServiceState> TService createService(
             Supplier newService, Consumer stateUpdateListener, Collection affectedChannels)
             throws BoschSHCException {
+        return createService(newService, stateUpdateListener, affectedChannels, false);
+    }
+
+    /**
+     * Creates and registers a new service for this device.
+     *
+     * @param  Type of service.
+     * @param  Type of service state.
+     * @param newService Supplier function to create a new instance of the service.
+     * @param stateUpdateListener Function to call when a state update was received
+     *            from the device.
+     * @param affectedChannels Channels which are affected by the state of this
+     *            service.
+     * @param shouldFetchInitialState indicates whether the initial state should be actively requested from the device
+     *            or service. Useful if state updates are not included in long poll results.
+     * @return Instance of registered service.
+     * @throws BoschSHCException
+     */
+    protected , TState extends BoschSHCServiceState> TService createService(
+            Supplier newService, Consumer stateUpdateListener, Collection affectedChannels,
+            boolean shouldFetchInitialState) throws BoschSHCException {
         TService service = newService.get();
-        this.registerService(service, stateUpdateListener, affectedChannels);
+        this.registerService(service, stateUpdateListener, affectedChannels, shouldFetchInitialState);
         return service;
     }
 
@@ -296,7 +317,7 @@ public abstract class BoschSHCHandler extends BaseThingHandler {
     /**
      * Actively requests the initial state for the given service. This is required if long poll results do not contain
      * status updates for the given service.
-     * 
+     *
      * @param  Type of the service for which the state should be obtained
      * @param  Type of the objects to serialize and deserialize the service state
      * @param service Service for which the state should be requested
@@ -325,7 +346,7 @@ public abstract class BoschSHCHandler extends BaseThingHandler {
      * Registers a write-only service that does not receive states from the bridge.
      * 

* Examples for such services are the actions of the intrusion detection service. - * + * * @param Type of service. * @param service Service to register. * @throws BoschSHCException If no device ID is set. @@ -340,7 +361,7 @@ public abstract class BoschSHCHandler extends BaseThingHandler { /** * Verifies that a Bosch device or service ID is set and throws an exception if this is not the case. - * + * * @return the Bosch ID, if present * @throws BoschSHCException if no Bosch ID is set */ @@ -404,7 +425,7 @@ public abstract class BoschSHCHandler extends BaseThingHandler { /** * Requests a service to refresh its state. * Sets the device offline if request fails. - * + * * @param Type of service. * @param Type of service state. * @param service Service to refresh state for. @@ -438,7 +459,7 @@ public abstract class BoschSHCHandler extends BaseThingHandler { /** * Sends a HTTP POST request with empty body. - * + * * @param Type of service. * @param service Service implementing the action */ @@ -457,7 +478,7 @@ public abstract class BoschSHCHandler extends BaseThingHandler { /** * Sends a HTTP POST request with the given request body. - * + * * @param Type of service. * @param Type of the request to be sent. * @param service Service implementing the action diff --git a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/BoschSHCHandlerFactory.java b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/BoschSHCHandlerFactory.java index b686acb51..81dffc59f 100644 --- a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/BoschSHCHandlerFactory.java +++ b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/BoschSHCHandlerFactory.java @@ -26,6 +26,7 @@ import org.openhab.binding.boschshc.internal.devices.climatecontrol.ClimateContr import org.openhab.binding.boschshc.internal.devices.intrusion.IntrusionDetectionHandler; import org.openhab.binding.boschshc.internal.devices.lightcontrol.LightControlHandler; import org.openhab.binding.boschshc.internal.devices.motiondetector.MotionDetectorHandler; +import org.openhab.binding.boschshc.internal.devices.plug.PlugHandler; import org.openhab.binding.boschshc.internal.devices.shuttercontrol.ShutterControlHandler; import org.openhab.binding.boschshc.internal.devices.thermostat.ThermostatHandler; import org.openhab.binding.boschshc.internal.devices.twinguard.TwinguardHandler; @@ -47,7 +48,7 @@ import org.osgi.service.component.annotations.Component; * @author Stefan Kästle - Initial contribution * @author Christian Oeing - Added Shutter Control and ThermostatHandler; refactored handler mapping * @author Christian Oeing - Added WallThermostatHandler - * @author David Pace - Added cameras and intrusion detection system + * @author David Pace - Added cameras, intrusion detection system and smart plugs */ @NonNullByDefault @Component(configurationPid = "binding.boschshc", service = ThingHandlerFactory.class) @@ -75,7 +76,8 @@ public class BoschSHCHandlerFactory extends BaseThingHandlerFactory { new ThingTypeHandlerMapping(THING_TYPE_WALL_THERMOSTAT, WallThermostatHandler::new), new ThingTypeHandlerMapping(THING_TYPE_CAMERA_360, CameraHandler::new), new ThingTypeHandlerMapping(THING_TYPE_CAMERA_EYES, CameraHandler::new), - new ThingTypeHandlerMapping(THING_TYPE_INTRUSION_DETECTION_SYSTEM, IntrusionDetectionHandler::new)); + new ThingTypeHandlerMapping(THING_TYPE_INTRUSION_DETECTION_SYSTEM, IntrusionDetectionHandler::new), + new ThingTypeHandlerMapping(THING_TYPE_SMART_PLUG_COMPACT, PlugHandler::new)); @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { diff --git a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/lightcontrol/LightControlHandler.java b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/lightcontrol/LightControlHandler.java index 2dde138ce..7c651baba 100644 --- a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/lightcontrol/LightControlHandler.java +++ b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/lightcontrol/LightControlHandler.java @@ -12,28 +12,9 @@ */ package org.openhab.binding.boschshc.internal.devices.lightcontrol; -import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.*; - -import java.util.List; - -import javax.measure.quantity.Energy; -import javax.measure.quantity.Power; - import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.boschshc.internal.devices.BoschSHCDeviceHandler; -import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException; -import org.openhab.binding.boschshc.internal.services.powermeter.PowerMeterService; -import org.openhab.binding.boschshc.internal.services.powermeter.dto.PowerMeterServiceState; -import org.openhab.binding.boschshc.internal.services.powerswitch.PowerSwitchService; -import org.openhab.binding.boschshc.internal.services.powerswitch.PowerSwitchState; -import org.openhab.binding.boschshc.internal.services.powerswitch.dto.PowerSwitchServiceState; -import org.openhab.core.library.types.OnOffType; -import org.openhab.core.library.types.QuantityType; -import org.openhab.core.library.unit.Units; -import org.openhab.core.thing.ChannelUID; +import org.openhab.binding.boschshc.internal.devices.AbstractPowerSwitchHandler; import org.openhab.core.thing.Thing; -import org.openhab.core.types.Command; -import org.openhab.core.types.State; /** * A simple light control. @@ -41,61 +22,9 @@ import org.openhab.core.types.State; * @author Stefan Kästle - Initial contribution */ @NonNullByDefault -public class LightControlHandler extends BoschSHCDeviceHandler { - - private final PowerSwitchService powerSwitchService; +public class LightControlHandler extends AbstractPowerSwitchHandler { public LightControlHandler(Thing thing) { super(thing); - this.powerSwitchService = new PowerSwitchService(); - } - - @Override - protected void initializeServices() throws BoschSHCException { - super.initializeServices(); - - this.registerService(this.powerSwitchService, this::updateChannels, List.of(CHANNEL_POWER_SWITCH)); - this.createService(PowerMeterService::new, this::updateChannels, - List.of(CHANNEL_POWER_CONSUMPTION, CHANNEL_ENERGY_CONSUMPTION)); - } - - @Override - public void handleCommand(ChannelUID channelUID, Command command) { - super.handleCommand(channelUID, command); - - switch (channelUID.getId()) { - case CHANNEL_POWER_SWITCH: - if (command instanceof OnOffType) { - updatePowerSwitchState((OnOffType) command); - } - break; - } - } - - /** - * Updates the channels which are linked to the {@link PowerMeterService} of the device. - * - * @param state Current state of {@link PowerMeterService}. - */ - private void updateChannels(PowerMeterServiceState state) { - super.updateState(CHANNEL_POWER_CONSUMPTION, new QuantityType(state.powerConsumption, Units.WATT)); - super.updateState(CHANNEL_ENERGY_CONSUMPTION, - new QuantityType(state.energyConsumption, Units.WATT_HOUR)); - } - - /** - * Updates the channels which are linked to the {@link PowerSwitchService} of the device. - * - * @param state Current state of {@link PowerSwitchService}. - */ - private void updateChannels(PowerSwitchServiceState state) { - State powerState = OnOffType.from(state.switchState.toString()); - super.updateState(CHANNEL_POWER_SWITCH, powerState); - } - - private void updatePowerSwitchState(OnOffType command) { - PowerSwitchServiceState state = new PowerSwitchServiceState(); - state.switchState = PowerSwitchState.valueOf(command.toFullString()); - this.updateServiceState(this.powerSwitchService, state); } } diff --git a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/plug/PlugHandler.java b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/plug/PlugHandler.java new file mode 100644 index 000000000..927e6789c --- /dev/null +++ b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/plug/PlugHandler.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2010-2022 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.plug; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.boschshc.internal.devices.AbstractPowerSwitchHandler; +import org.openhab.core.thing.Thing; + +/** + * A handler for compact smart plugs. + * + * @author David Pace - Initial contribution + */ +@NonNullByDefault +public class PlugHandler extends AbstractPowerSwitchHandler { + + public PlugHandler(Thing thing) { + super(thing); + } +} 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 34c55fc80..12c1dda89 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 @@ -30,6 +30,24 @@ + + + + + + + A compact smart plug with energy monitoring capabilities. + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractBoschSHCDeviceHandlerTest.java b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractBoschSHCDeviceHandlerTest.java new file mode 100644 index 000000000..f5f9608c2 --- /dev/null +++ b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractBoschSHCDeviceHandlerTest.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2010-2022 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; + +import org.openhab.core.config.core.Configuration; + +/** + * Abstract unit test implementation for device handlers. + * + * @author David Pace - Initial contribution + * + * @param type of the device handler to be tested + */ +public abstract class AbstractBoschSHCDeviceHandlerTest + extends AbstractSHCHandlerTest { + + @Override + protected Configuration getConfiguration() { + Configuration configuration = super.getConfiguration(); + configuration.put("id", getDeviceID()); + return configuration; + } + + protected abstract String getDeviceID(); +} diff --git a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractPowerSwitchHandlerTest.java b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractPowerSwitchHandlerTest.java new file mode 100644 index 000000000..38432d552 --- /dev/null +++ b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractPowerSwitchHandlerTest.java @@ -0,0 +1,118 @@ +/** + * Copyright (c) 2010-2022 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; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +import javax.measure.quantity.Energy; +import javax.measure.quantity.Power; + +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException; +import org.openhab.binding.boschshc.internal.services.powerswitch.PowerSwitchState; +import org.openhab.binding.boschshc.internal.services.powerswitch.dto.PowerSwitchServiceState; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.library.types.QuantityType; +import org.openhab.core.thing.ChannelUID; +import org.openhab.core.thing.ThingTypeUID; +import org.openhab.core.thing.ThingUID; + +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; + +/** + * Abstract unit test implementation for devices with power switches and energy monitoring. + * + * @author David Pace - Initial contribution + * + * @param type of the handler to be tested + */ +public abstract class AbstractPowerSwitchHandlerTest + extends AbstractBoschSHCDeviceHandlerTest { + + @Captor + private ArgumentCaptor serviceStateCaptor; + + @Captor + private ArgumentCaptor> powerCaptor; + + @Captor + private ArgumentCaptor> energyCaptor; + + @Test + public void testHandleCommand() + throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException { + + when(getThing().getUID()).thenReturn(new ThingUID("boschshc", "abcdef")); + + getFixture().handleCommand(new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_POWER_SWITCH), + OnOffType.ON); + verify(getBridgeHandler()).putState(eq(getDeviceID()), eq("PowerSwitch"), serviceStateCaptor.capture()); + PowerSwitchServiceState state = serviceStateCaptor.getValue(); + assertSame(PowerSwitchState.ON, state.switchState); + + getFixture().handleCommand(new ChannelUID(new ThingUID(getThingTypeUID(), "abcdef"), + BoschSHCBindingConstants.CHANNEL_POWER_SWITCH), OnOffType.OFF); + verify(getBridgeHandler(), times(2)).putState(eq(getDeviceID()), eq("PowerSwitch"), + serviceStateCaptor.capture()); + state = serviceStateCaptor.getValue(); + assertSame(PowerSwitchState.OFF, state.switchState); + } + + protected abstract ThingTypeUID getThingTypeUID(); + + @Test + public void testUpdateChannel_PowerSwitchState() { + when(getThing().getUID()).thenReturn(new ThingUID("boschshc", "abcdef")); + + JsonElement jsonObject = JsonParser + .parseString("{\n" + " \"@type\": \"powerSwitchState\",\n" + " \"switchState\": \"ON\"\n" + "}"); + getFixture().processUpdate("PowerSwitch", jsonObject); + verify(getCallback()).stateUpdated( + new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_POWER_SWITCH), OnOffType.ON); + + jsonObject = JsonParser + .parseString("{\n" + " \"@type\": \"powerSwitchState\",\n" + " \"switchState\": \"OFF\"\n" + "}"); + getFixture().processUpdate("PowerSwitch", jsonObject); + verify(getCallback()).stateUpdated( + new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_POWER_SWITCH), OnOffType.OFF); + } + + @Test + public void testUpdateChannel_PowerMeterServiceState() { + when(getThing().getUID()).thenReturn(new ThingUID("boschshc", "abcdef")); + + JsonElement jsonObject = JsonParser.parseString("{\n" + " \"@type\": \"powerMeterState\",\n" + + " \"powerConsumption\": \"23\",\n" + " \"energyConsumption\": 42\n" + "}"); + getFixture().processUpdate("PowerMeter", jsonObject); + + verify(getCallback()).stateUpdated( + eq(new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_POWER_CONSUMPTION)), + powerCaptor.capture()); + QuantityType powerValue = powerCaptor.getValue(); + assertEquals(23, powerValue.intValue()); + + verify(getCallback()).stateUpdated( + eq(new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_ENERGY_CONSUMPTION)), + energyCaptor.capture()); + QuantityType energyValue = energyCaptor.getValue(); + assertEquals(42, energyValue.intValue()); + } +} diff --git a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractSHCHandlerTest.java b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractSHCHandlerTest.java new file mode 100644 index 000000000..872ca5336 --- /dev/null +++ b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractSHCHandlerTest.java @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2010-2022 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; + +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.openhab.binding.boschshc.internal.devices.bridge.BridgeHandler; +import org.openhab.core.config.core.Configuration; +import org.openhab.core.thing.Bridge; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingStatus; +import org.openhab.core.thing.ThingStatusDetail; +import org.openhab.core.thing.ThingStatusInfo; +import org.openhab.core.thing.ThingUID; +import org.openhab.core.thing.binding.ThingHandlerCallback; + +/** + * Abstract unit test implementation for all types of handlers. + * + * @author David Pace - Initial contribution + * + * @param type of the handler to be tested + */ +@ExtendWith(MockitoExtension.class) +public abstract class AbstractSHCHandlerTest { + + private T fixture; + + @Mock + private Thing thing; + + @Mock + private Bridge bridge; + + @Mock + private BridgeHandler bridgeHandler; + + @Mock + private ThingHandlerCallback callback; + + @BeforeEach + public void beforeEach() { + fixture = createFixture(); + when(thing.getBridgeUID()).thenReturn(new ThingUID("boschshc", "shc", "myBridgeUID")); + when(callback.getBridge(any())).thenReturn(bridge); + fixture.setCallback(callback); + when(bridge.getHandler()).thenReturn(bridgeHandler); + when(thing.getConfiguration()).thenReturn(getConfiguration()); + + fixture.initialize(); + } + + protected abstract T createFixture(); + + protected T getFixture() { + return fixture; + } + + protected Configuration getConfiguration() { + return new Configuration(); + } + + protected Thing getThing() { + return thing; + } + + public BridgeHandler getBridgeHandler() { + return bridgeHandler; + } + + public ThingHandlerCallback getCallback() { + return callback; + } + + @Test + public void testInitialize() { + ThingStatusInfo expectedStatusInfo = new ThingStatusInfo(ThingStatus.ONLINE, ThingStatusDetail.NONE, null); + verify(callback).statusUpdated(same(thing), eq(expectedStatusInfo)); + } +} diff --git a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/lightcontrol/LightControlHandlerTest.java b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/lightcontrol/LightControlHandlerTest.java new file mode 100644 index 000000000..94ae904ad --- /dev/null +++ b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/lightcontrol/LightControlHandlerTest.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2010-2022 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 org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.boschshc.internal.devices.AbstractPowerSwitchHandlerTest; +import org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants; +import org.openhab.core.thing.ThingTypeUID; + +/** + * Unit tests for {@link LightControlHandler}. + * + * @author David Pace - Initial contribution + * + */ +@NonNullByDefault +public class LightControlHandlerTest extends AbstractPowerSwitchHandlerTest { + + @Override + protected ThingTypeUID getThingTypeUID() { + return BoschSHCBindingConstants.THING_TYPE_INWALL_SWITCH; + } + + @Override + protected String getDeviceID() { + return "hdm:ZigBee:50325ffffe61d7b9c6e"; + } + + @Override + protected LightControlHandler createFixture() { + return new LightControlHandler(getThing()); + } +} diff --git a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/plug/PlugHandlerTest.java b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/plug/PlugHandlerTest.java new file mode 100644 index 000000000..0c285912a --- /dev/null +++ b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/plug/PlugHandlerTest.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2010-2022 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.plug; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.boschshc.internal.devices.AbstractPowerSwitchHandlerTest; +import org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants; +import org.openhab.core.thing.ThingTypeUID; + +/** + * Unit tests for {@link PlugHandler}. + * + * @author David Pace - Initial contribution + * + */ +@NonNullByDefault +public class PlugHandlerTest extends AbstractPowerSwitchHandlerTest { + + @Override + protected PlugHandler createFixture() { + return new PlugHandler(getThing()); + } + + @Override + protected String getDeviceID() { + return "hdm:ZigBee:50325ffffe61d7b9c6e"; + } + + @Override + protected ThingTypeUID getThingTypeUID() { + return BoschSHCBindingConstants.THING_TYPE_SMART_PLUG_COMPACT; + } +}