/** * Copyright (c) 2014-2017 by the respective copyright holders. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.eclipse.smarthome.binding.digitalstrom.internal.discovery; import static org.eclipse.smarthome.binding.digitalstrom.DigitalSTROMBindingConstants.*; import java.util.Date; import java.util.HashMap; import java.util.Map; import org.eclipse.smarthome.binding.digitalstrom.handler.BridgeHandler; import org.eclipse.smarthome.binding.digitalstrom.handler.SceneHandler; import org.eclipse.smarthome.binding.digitalstrom.internal.lib.structure.scene.InternalScene; import org.eclipse.smarthome.binding.digitalstrom.internal.lib.structure.scene.constants.SceneEnum; import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService; import org.eclipse.smarthome.config.discovery.DiscoveryResult; import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.ThingUID; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.collect.Sets; /** * The {@link SceneDiscoveryService} discovers all digitalSTROM-scene of one supported scene-type. The scene-type has to * be given to the {@link #SceneDiscoveryService(BridgeHandler, ThingTypeUID)} as * {@link ThingTypeUID}. The supported {@link ThingTypeUID} can be found at {@link SceneHandler#SUPPORTED_THING_TYPES} * * @author Michael Ochel - Initial contribution * @author Matthias Siegele - Initial contribution */ public class SceneDiscoveryService extends AbstractDiscoveryService { private final static Logger logger = LoggerFactory.getLogger(SceneDiscoveryService.class); private final BridgeHandler bridgeHandler; private final String sceneType; /** * Creates a new {@link SceneDiscoveryService} for the given supportedThingType. * * @param bridgeHandler (must not be null) * @param supportedThingType (must not be null) * @throws IllegalArgumentException */ public SceneDiscoveryService(BridgeHandler bridgeHandler, ThingTypeUID supportedThingType) throws IllegalArgumentException { super(Sets.newHashSet(supportedThingType), 10, false); this.sceneType = supportedThingType.getId(); this.bridgeHandler = bridgeHandler; } /** * Deactivates the {@link SceneDiscoveryService} and removes the {@link DiscoveryResult}s. */ @Override public void deactivate() { logger.debug("deactivate discovery service for scene type " + sceneType + " remove thing tyspes " + super.getSupportedThingTypes().toString()); removeOlderResults(new Date().getTime()); } @Override protected void startScan() { if (bridgeHandler != null) { if (bridgeHandler.getScenes() != null) { for (InternalScene scene : bridgeHandler.getScenes()) { onSceneAddedInternal(scene); } } } } @Override protected synchronized void stopScan() { super.stopScan(); removeOlderResults(getTimestampOfLastScan()); } private void onSceneAddedInternal(InternalScene scene) { if (scene != null && scene.getSceneType().equals(sceneType)) { if (!ignoredScene(scene.getSceneID())) { ThingUID thingUID = getThingUID(scene); if (thingUID != null) { ThingUID bridgeUID = bridgeHandler.getThing().getUID(); Map<String, Object> properties = new HashMap<>(5); properties.put(SCENE_NAME, scene.getSceneName()); properties.put(SCENE_ZONE_ID, scene.getZoneID()); properties.put(SCENE_GROUP_ID, scene.getGroupID()); if (SceneEnum.containsScene(scene.getSceneID())) { properties.put(SCENE_ID, SceneEnum.getScene(scene.getSceneID()).toString()); } else { logger.debug("discovered scene: name '{}' with id {} have an invalid scene-ID", scene.getSceneName(), scene.getID()); } DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties) .withBridge(bridgeUID).withLabel(scene.getSceneName()).build(); thingDiscovered(discoveryResult); } else { logger.debug("discovered unsupported scene: name '{}' with id {}", scene.getSceneName(), scene.getID()); } } } } private boolean ignoredScene(short sceneID) { switch (SceneEnum.getScene(sceneID)) { case INCREMENT: case DECREMENT: case STOP: case MINIMUM: case MAXIMUM: case DEVICE_ON: case DEVICE_OFF: case DEVICE_STOP: case AREA_1_INCREMENT: case AREA_1_DECREMENT: case AREA_1_STOP: case AREA_2_INCREMENT: case AREA_2_DECREMENT: case AREA_2_STOP: case AREA_3_INCREMENT: case AREA_3_DECREMENT: case AREA_3_STOP: case AREA_4_INCREMENT: case AREA_4_DECREMENT: case AREA_4_STOP: case AREA_STEPPING_CONTINUE: case ENERGY_OVERLOAD: case ALARM_SIGNAL: case AUTO_STANDBY: case ZONE_ACTIVE: return true; default: return false; } } private ThingUID getThingUID(InternalScene scene) { ThingUID bridgeUID = bridgeHandler.getThing().getUID(); ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, sceneType); if (getSupportedThingTypes().contains(thingTypeUID)) { String thingSceneId = scene.getID(); ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, thingSceneId); return thingUID; } else { return null; } } /** * Returns the ID of this {@link SceneDiscoveryService}. * * @return id of this service */ public String getID() { return sceneType; } /** * Creates a {@link DiscoveryResult} of the given {@link InternalScene}, if the scene exists, if it is allowed to * use the scene * and if the scene is not one of the following scenes: * <li>{@link SceneEnum#INCREMENT}</li> * <li>{@link SceneEnum#DECREMENT}</li> * <li>{@link SceneEnum#STOP}</li> * <li>{@link SceneEnum#MINIMUM}</li> * <li>{@link SceneEnum#MAXIMUM}</li> * <li>{@link SceneEnum#AUTO_OFF}</li> * <li>{@link SceneEnum#DEVICE_ON}</li> * <li>{@link SceneEnum#DEVICE_OFF}</li> * <li>{@link SceneEnum#DEVICE_STOP}</li> * <li>{@link SceneEnum#AREA_1_INCREMENT}</li> * <li>{@link SceneEnum#AREA_1_DECREMENT}</li> * <li>{@link SceneEnum#AREA_1_STOP}</li> * <li>{@link SceneEnum#AREA_2_INCREMENT}</li> * <li>{@link SceneEnum#AREA_2_DECREMENT}</li> * <li>{@link SceneEnum#AREA_2_STOP}</li> * <li>{@link SceneEnum#AREA_3_INCREMENT}</li> * <li>{@link SceneEnum#AREA_3_DECREMENT}</li> * <li>{@link SceneEnum#AREA_3_STOP}</li> * <li>{@link SceneEnum#AREA_4_INCREMENT}</li> * <li>{@link SceneEnum#AREA_4_DECREMENT}</li> * <li>{@link SceneEnum#AREA_4_STOP}</li> * <li>{@link SceneEnum#AREA_STEPPING_CONTINUE}</li> * <li>{@link SceneEnum#ENERGY_OVERLOAD}</li> * <li>{@link SceneEnum#ALARM_SIGNAL}</li> * <li>{@link SceneEnum#AUTO_STANDBY}</li> * <li>{@link SceneEnum#ZONE_ACTIVE}</li><br> * * @param scene (must not be null) */ public void onSceneAdded(InternalScene scene) { if (super.isBackgroundDiscoveryEnabled()) { onSceneAddedInternal(scene); } } /** * Removes the {@link DiscoveryResult} of the given {@link InternalScene}. * * @param scene (must not be null) */ public void onSceneRemoved(InternalScene scene) { ThingUID thingUID = getThingUID(scene); if (thingUID != null) { thingRemoved(thingUID); } } }