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