]> git.basschouten.com Git - openhab-addons.git/blob
c19557f3cdc16e2fd530671f737895fe2b51310e
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 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.digitalstrom.internal.discovery;
14
15 import static org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants.*;
16
17 import java.util.Arrays;
18 import java.util.Date;
19 import java.util.HashMap;
20 import java.util.HashSet;
21 import java.util.Map;
22
23 import org.openhab.binding.digitalstrom.internal.handler.BridgeHandler;
24 import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.FuncNameAndColorGroupEnum;
25 import org.openhab.binding.digitalstrom.internal.lib.structure.scene.InternalScene;
26 import org.openhab.binding.digitalstrom.internal.lib.structure.scene.constants.SceneEnum;
27 import org.openhab.core.config.discovery.AbstractDiscoveryService;
28 import org.openhab.core.config.discovery.DiscoveryResult;
29 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
30 import org.openhab.core.thing.ThingTypeUID;
31 import org.openhab.core.thing.ThingUID;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 /**
36  * The {@link SceneDiscoveryService} discovers all digitalSTROM-scene of one supported scene-type. The scene-type has to
37  * be given to the {@link #SceneDiscoveryService(BridgeHandler, ThingTypeUID)} as
38  * {@link ThingTypeUID}. The supported {@link ThingTypeUID} can be found at {@link SceneHandler#SUPPORTED_THING_TYPES}
39  *
40  * @author Michael Ochel - Initial contribution
41  * @author Matthias Siegele - Initial contribution
42  */
43 public class SceneDiscoveryService extends AbstractDiscoveryService {
44
45     private final Logger logger = LoggerFactory.getLogger(SceneDiscoveryService.class);
46     private final BridgeHandler bridgeHandler;
47     private final String sceneType;
48
49     public static final int TIMEOUT = 10;
50
51     /**
52      * Creates a new {@link SceneDiscoveryService} for the given supportedThingType.
53      *
54      * @param bridgeHandler (must not be null)
55      * @param supportedThingType (must not be null)
56      * @throws IllegalArgumentException see {@link AbstractDiscoveryService#AbstractDiscoveryService(int)}
57      */
58     public SceneDiscoveryService(BridgeHandler bridgeHandler, ThingTypeUID supportedThingType)
59             throws IllegalArgumentException {
60         super(new HashSet<>(Arrays.asList(supportedThingType)), TIMEOUT, false);
61         this.sceneType = supportedThingType.getId();
62         this.bridgeHandler = bridgeHandler;
63     }
64
65     /**
66      * Deactivates the {@link SceneDiscoveryService} and removes the {@link DiscoveryResult}s.
67      */
68     @Override
69     public void deactivate() {
70         logger.debug("deactivate discovery service for scene type {} remove thing tyspes {}", sceneType,
71                 super.getSupportedThingTypes());
72         removeOlderResults(new Date().getTime());
73     }
74
75     @Override
76     protected void startScan() {
77         if (bridgeHandler != null) {
78             if (bridgeHandler.getScenes() != null) {
79                 for (InternalScene scene : bridgeHandler.getScenes()) {
80                     onSceneAddedInternal(scene);
81                 }
82             }
83         }
84     }
85
86     @Override
87     protected synchronized void stopScan() {
88         super.stopScan();
89         removeOlderResults(getTimestampOfLastScan());
90     }
91
92     private void onSceneAddedInternal(InternalScene scene) {
93         logger.debug("{}", scene.getSceneType());
94         if (scene.getSceneType().equals(sceneType)) {
95             if (!ignoredScene(scene.getSceneID()) && !ignoreGroup(scene.getGroupID())) {
96                 ThingUID thingUID = getThingUID(scene);
97                 if (thingUID != null) {
98                     ThingUID bridgeUID = bridgeHandler.getThing().getUID();
99                     Map<String, Object> properties = new HashMap<>();
100                     properties.put(ZONE_ID, scene.getZoneID());
101                     properties.put(GROUP_ID, scene.getGroupID());
102                     if (SceneEnum.containsScene(scene.getSceneID())) {
103                         properties.put(SCENE_ID, SceneEnum.getScene(scene.getSceneID()).toString());
104                     } else {
105                         logger.debug("discovered scene: name '{}' with id {} have an invalid scene-ID",
106                                 scene.getSceneName(), scene.getID());
107                     }
108                     DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties)
109                             .withBridge(bridgeUID).withLabel(scene.getSceneName()).build();
110
111                     thingDiscovered(discoveryResult);
112
113                 } else {
114                     logger.debug("discovered unsupported scene: name '{}' with id {}", scene.getSceneName(),
115                             scene.getID());
116                 }
117             }
118         }
119     }
120
121     private boolean ignoreGroup(Short groupID) {
122         if (FuncNameAndColorGroupEnum.getMode(groupID) != null) {
123             switch (FuncNameAndColorGroupEnum.getMode(groupID)) {
124                 case TEMPERATION_CONTROL:
125                     return true;
126                 default:
127                     return false;
128             }
129         }
130         return false;
131     }
132
133     private boolean ignoredScene(short sceneID) {
134         switch (SceneEnum.getScene(sceneID)) {
135             case INCREMENT:
136             case DECREMENT:
137             case STOP:
138             case MINIMUM:
139             case MAXIMUM:
140             case DEVICE_ON:
141             case DEVICE_OFF:
142             case DEVICE_STOP:
143             case AREA_1_INCREMENT:
144             case AREA_1_DECREMENT:
145             case AREA_1_STOP:
146             case AREA_2_INCREMENT:
147             case AREA_2_DECREMENT:
148             case AREA_2_STOP:
149             case AREA_3_INCREMENT:
150             case AREA_3_DECREMENT:
151             case AREA_3_STOP:
152             case AREA_4_INCREMENT:
153             case AREA_4_DECREMENT:
154             case AREA_4_STOP:
155             case AREA_STEPPING_CONTINUE:
156             case ENERGY_OVERLOAD:
157             case ALARM_SIGNAL:
158             case AUTO_STANDBY:
159             case ZONE_ACTIVE:
160                 return true;
161             default:
162                 return false;
163         }
164     }
165
166     private ThingUID getThingUID(InternalScene scene) {
167         ThingUID bridgeUID = bridgeHandler.getThing().getUID();
168         ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, sceneType);
169
170         if (getSupportedThingTypes().contains(thingTypeUID)) {
171             String thingSceneId = scene.getID();
172             ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, thingSceneId);
173             return thingUID;
174         } else {
175             return null;
176         }
177     }
178
179     /**
180      * Returns the ID of this {@link SceneDiscoveryService}.
181      *
182      * @return id of this service
183      */
184     public String getID() {
185         return sceneType;
186     }
187
188     /**
189      * Creates a {@link DiscoveryResult} of the given {@link InternalScene}, if the scene exists, if it is allowed to
190      * use the scene
191      * and if the scene is not one of the following scenes:
192      * <ul>
193      * <li>{@link SceneEnum#INCREMENT}</li>
194      * <li>{@link SceneEnum#DECREMENT}</li>
195      * <li>{@link SceneEnum#STOP}</li>
196      * <li>{@link SceneEnum#MINIMUM}</li>
197      * <li>{@link SceneEnum#MAXIMUM}</li>
198      * <li>{@link SceneEnum#AUTO_OFF}</li>
199      * <li>{@link SceneEnum#DEVICE_ON}</li>
200      * <li>{@link SceneEnum#DEVICE_OFF}</li>
201      * <li>{@link SceneEnum#DEVICE_STOP}</li>
202      * <li>{@link SceneEnum#AREA_1_INCREMENT}</li>
203      * <li>{@link SceneEnum#AREA_1_DECREMENT}</li>
204      * <li>{@link SceneEnum#AREA_1_STOP}</li>
205      * <li>{@link SceneEnum#AREA_2_INCREMENT}</li>
206      * <li>{@link SceneEnum#AREA_2_DECREMENT}</li>
207      * <li>{@link SceneEnum#AREA_2_STOP}</li>
208      * <li>{@link SceneEnum#AREA_3_INCREMENT}</li>
209      * <li>{@link SceneEnum#AREA_3_DECREMENT}</li>
210      * <li>{@link SceneEnum#AREA_3_STOP}</li>
211      * <li>{@link SceneEnum#AREA_4_INCREMENT}</li>
212      * <li>{@link SceneEnum#AREA_4_DECREMENT}</li>
213      * <li>{@link SceneEnum#AREA_4_STOP}</li>
214      * <li>{@link SceneEnum#AREA_STEPPING_CONTINUE}</li>
215      * <li>{@link SceneEnum#ENERGY_OVERLOAD}</li>
216      * <li>{@link SceneEnum#ALARM_SIGNAL}</li>
217      * <li>{@link SceneEnum#AUTO_STANDBY}</li>
218      * <li>{@link SceneEnum#ZONE_ACTIVE}</li>
219      * </ul>
220      *
221      * @param scene (must not be null)
222      */
223     public void onSceneAdded(InternalScene scene) {
224         if (super.isBackgroundDiscoveryEnabled()) {
225             onSceneAddedInternal(scene);
226         }
227     }
228
229     /**
230      * Removes the {@link DiscoveryResult} of the given {@link InternalScene}.
231      *
232      * @param scene (must not be null)
233      */
234     public void onSceneRemoved(InternalScene scene) {
235         ThingUID thingUID = getThingUID(scene);
236         if (thingUID != null) {
237             thingRemoved(thingUID);
238         }
239     }
240 }