* add thing definition with ID "smart-plug-compact" * add constant for thing type UID * extract abstract implementation for devices with power switch and energy monitoring * let in-wall switch handler and smart plug handler extend the abstract implementation * register new handler * add method with boolean parameter to fetch initial state actively * make BoschSHCDeviceHandler abstract * add documentation * add unit tests closes #13528 Signed-off-by: David Pace <dev@davidpace.de>
This commit is contained in:
@@ -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.
|
||||
* <p>
|
||||
* This implementation provides the functionality to
|
||||
* <ul>
|
||||
* <li>Switch the device on and off using the <code>PowerSwitch</code> service</li>
|
||||
* <li>Measuring the current power consumption and the overall energy consumption using the <code>PowerMeter</code>
|
||||
* service</li>
|
||||
* </ul>
|
||||
*
|
||||
* @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<Power>(state.powerConsumption, Units.WATT));
|
||||
super.updateState(CHANNEL_ENERGY_CONSUMPTION,
|
||||
new QuantityType<Energy>(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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -28,19 +28,19 @@ import org.openhab.core.thing.ThingStatusDetail;
|
||||
* The device ID of physical devices has to be configured in the thing configuration.
|
||||
* <p>
|
||||
* Examples for physical device IDs are:
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* hdm:Cameras:d20354de-44b5-3acc-924c-24c98d59da42
|
||||
* hdm:ZigBee:000d6f0016d1cdae
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @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;
|
||||
|
||||
@@ -100,14 +100,14 @@ public abstract class BoschSHCHandler extends BaseThingHandler {
|
||||
* Returns the unique id of the Bosch device or service.
|
||||
* <p>
|
||||
* For physical devices, the ID looks like
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* hdm:Cameras:d20354de-44b5-3acc-924c-24c98d59da42
|
||||
* hdm:ZigBee:000d6f0016d1c087
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* For virtual devices / services, static IDs like the following are used:
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* ventilationService
|
||||
* smokeDetectionSystem
|
||||
@@ -241,8 +241,29 @@ public abstract class BoschSHCHandler extends BaseThingHandler {
|
||||
protected <TService extends BoschSHCService<TState>, TState extends BoschSHCServiceState> TService createService(
|
||||
Supplier<TService> newService, Consumer<TState> stateUpdateListener, Collection<String> affectedChannels)
|
||||
throws BoschSHCException {
|
||||
return createService(newService, stateUpdateListener, affectedChannels, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and registers a new service for this device.
|
||||
*
|
||||
* @param <TService> Type of service.
|
||||
* @param <TState> 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 <TService extends BoschSHCService<TState>, TState extends BoschSHCServiceState> TService createService(
|
||||
Supplier<TService> newService, Consumer<TState> stateUpdateListener, Collection<String> 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 <TService> Type of the service for which the state should be obtained
|
||||
* @param <TState> 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.
|
||||
* <p>
|
||||
* Examples for such services are the actions of the intrusion detection service.
|
||||
*
|
||||
*
|
||||
* @param <TService> 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 <TService> Type of service.
|
||||
* @param <TState> 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 <TService> 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 <TService> Type of service.
|
||||
* @param <TState> Type of the request to be sent.
|
||||
* @param service Service implementing the action
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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<Power>(state.powerConsumption, Units.WATT));
|
||||
super.updateState(CHANNEL_ENERGY_CONSUMPTION,
|
||||
new QuantityType<Energy>(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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,24 @@
|
||||
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="smart-plug-compact">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="shc"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Compact Smart Plug</label>
|
||||
<description>A compact smart plug with energy monitoring capabilities.</description>
|
||||
|
||||
<channels>
|
||||
<channel id="power-switch" typeId="system.power"/>
|
||||
<channel id="power-consumption" typeId="power-consumption"/>
|
||||
<channel id="energy-consumption" typeId="energy-consumption"/>
|
||||
</channels>
|
||||
|
||||
<config-description-ref uri="thing-type:boschshc:device"/>
|
||||
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="twinguard">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="shc"/>
|
||||
|
||||
Reference in New Issue
Block a user