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