]> git.basschouten.com Git - openhab-addons.git/blob
a6e072b4f9583eb29f8d8f98169e1168893d6242
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 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;
14
15 import static org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants.*;
16
17 import java.util.HashMap;
18 import java.util.Map;
19 import java.util.concurrent.ConcurrentHashMap;
20
21 import org.openhab.binding.digitalstrom.internal.discovery.DiscoveryServiceManager;
22 import org.openhab.binding.digitalstrom.internal.handler.BridgeHandler;
23 import org.openhab.binding.digitalstrom.internal.handler.CircuitHandler;
24 import org.openhab.binding.digitalstrom.internal.handler.DeviceHandler;
25 import org.openhab.binding.digitalstrom.internal.handler.SceneHandler;
26 import org.openhab.binding.digitalstrom.internal.handler.ZoneTemperatureControlHandler;
27 import org.openhab.binding.digitalstrom.internal.lib.manager.ConnectionManager;
28 import org.openhab.binding.digitalstrom.internal.lib.manager.impl.ConnectionManagerImpl;
29 import org.openhab.binding.digitalstrom.internal.lib.serverconnection.constants.JSONApiResponseKeysEnum;
30 import org.openhab.core.config.core.Configuration;
31 import org.openhab.core.thing.Bridge;
32 import org.openhab.core.thing.Thing;
33 import org.openhab.core.thing.ThingTypeUID;
34 import org.openhab.core.thing.ThingUID;
35 import org.openhab.core.thing.binding.BaseThingHandlerFactory;
36 import org.openhab.core.thing.binding.ThingHandler;
37 import org.openhab.core.thing.binding.ThingHandlerFactory;
38 import org.osgi.service.component.annotations.Component;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 /**
43  * The {@link DigitalSTROMHandlerFactory} is responsible for creating things and thing
44  * handlers.
45  *
46  * @author Michael Ochel - Initial contribution
47  * @author Mathias Siegele - Initial contribution
48  */
49 @Component(service = ThingHandlerFactory.class, configurationPid = "binding.digitalstrom")
50 public class DigitalSTROMHandlerFactory extends BaseThingHandlerFactory {
51
52     private final Logger logger = LoggerFactory.getLogger(DigitalSTROMHandlerFactory.class);
53     private final Map<String, DiscoveryServiceManager> discoveryServiceManagers = new ConcurrentHashMap<>();
54
55     private Map<ThingUID, BridgeHandler> bridgeHandlers;
56
57     @Override
58     public boolean supportsThingType(ThingTypeUID thingTypeUID) {
59         return BridgeHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)
60                 || SceneHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)
61                 || DeviceHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)
62                 || ZoneTemperatureControlHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)
63                 || CircuitHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID);
64     }
65
66     @Override
67     public Thing createThing(ThingTypeUID thingTypeUID, Configuration configuration, ThingUID thingUID,
68             ThingUID bridgeUID) {
69         if (BridgeHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
70             ThingUID dSSUID = getBridgeThingUID(thingTypeUID, thingUID, configuration);
71             if (dSSUID != null) {
72                 return super.createThing(thingTypeUID, configuration, dSSUID, null);
73             } else {
74                 logger.error("Can't generate thing UID for thing type {}"
75                         + ", because digitalSTROM-Server is not reachable. Please check these points:\n"
76                         + "Are the server address and portnumber correct?\n" + "Is the server turned on?\n"
77                         + "Is the network configured correctly?", thingTypeUID);
78                 return null;
79             }
80         }
81
82         if (DeviceHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
83             ThingUID dsDeviceUID = getDeviceUID(thingTypeUID, thingUID, configuration, bridgeUID);
84             return super.createThing(thingTypeUID, configuration, dsDeviceUID, bridgeUID);
85         }
86
87         if (CircuitHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
88             ThingUID dsDeviceUID = getDeviceUID(thingTypeUID, thingUID, configuration, bridgeUID);
89             return super.createThing(thingTypeUID, configuration, dsDeviceUID, bridgeUID);
90         }
91
92         if (ZoneTemperatureControlHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
93             ThingUID zoneTempConUID = getZoneTemperatureControlUID(thingTypeUID, thingUID, configuration, bridgeUID);
94             return super.createThing(thingTypeUID, configuration, zoneTempConUID, bridgeUID);
95         }
96
97         if (SceneHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
98             ThingUID dsSceneUID = getSceneUID(thingTypeUID, thingUID, configuration, bridgeUID);
99             return super.createThing(thingTypeUID, configuration, dsSceneUID, bridgeUID);
100         }
101         throw new IllegalArgumentException(
102                 "The thing type " + thingTypeUID + " is not supported by the digitalSTROM binding.");
103     }
104
105     @Override
106     protected ThingHandler createHandler(Thing thing) {
107         ThingTypeUID thingTypeUID = thing.getThingTypeUID();
108
109         if (BridgeHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
110             BridgeHandler handler = new BridgeHandler((Bridge) thing);
111             if (bridgeHandlers == null) {
112                 bridgeHandlers = new HashMap<>();
113             }
114             bridgeHandlers.put(thing.getUID(), handler);
115             DiscoveryServiceManager discoveryServiceManager = new DiscoveryServiceManager(handler);
116             discoveryServiceManager.registerDiscoveryServices(bundleContext);
117             discoveryServiceManagers.put(handler.getThing().getUID().getAsString(), discoveryServiceManager);
118             return handler;
119         }
120
121         if (DeviceHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
122             return new DeviceHandler(thing);
123         }
124
125         if (CircuitHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
126             return new CircuitHandler(thing);
127         }
128
129         if (ZoneTemperatureControlHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
130             return new ZoneTemperatureControlHandler(thing);
131         }
132
133         if (SceneHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
134             return new SceneHandler(thing);
135         }
136         return null;
137     }
138
139     private ThingUID getDeviceUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Configuration configuration,
140             ThingUID bridgeUID) {
141         String id = (String) configuration.get(DEVICE_DSID);
142         if (thingUID == null && id != null && !id.isBlank()) {
143             return new ThingUID(thingTypeUID, bridgeUID, id);
144         }
145         return thingUID;
146     }
147
148     private ThingUID getZoneTemperatureControlUID(ThingTypeUID thingTypeUID, ThingUID thingUID,
149             Configuration configuration, ThingUID bridgeUID) {
150         if (thingUID == null) {
151             Integer zoneID = ZoneTemperatureControlHandler.getZoneID(configuration, bridgeHandlers.get(bridgeUID));
152             if (zoneID > ZoneTemperatureControlHandler.ZONE_ID_NOT_EXISTS) {
153                 return new ThingUID(thingTypeUID, bridgeUID, zoneID.toString());
154             } else {
155                 switch (zoneID) {
156                     case ZoneTemperatureControlHandler.ZONE_ID_NOT_EXISTS:
157                         logger.error("Configured zone '{}' does not exist, please check your configuration.",
158                                 configuration.get(DigitalSTROMBindingConstants.ZONE_ID));
159                         break;
160                     case ZoneTemperatureControlHandler.ZONE_ID_NOT_SET:
161                         logger.error("ZoneID is missing at your configuration.");
162                         break;
163                     case ZoneTemperatureControlHandler.BRIDGE_IS_NULL:
164                         logger.error("Bridge is missing, can not check the zoneID.");
165                         break;
166                 }
167             }
168         }
169         return thingUID;
170     }
171
172     private ThingUID getSceneUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Configuration configuration,
173             ThingUID bridgeUID) {
174         if (thingUID != null) {
175             return thingUID;
176         }
177         String sceneID = SceneHandler.getSceneID(configuration, bridgeHandlers.get(bridgeUID));
178         switch (sceneID) {
179             case SceneHandler.SCENE_WRONG:
180                 logger.error(
181                         "Configured scene '{}' does not exist or can not be used, please check your configuration.",
182                         configuration.get(DigitalSTROMBindingConstants.SCENE_ID));
183                 break;
184             case SceneHandler.ZONE_WRONG:
185                 logger.error("Configured zone '{}' does not exist, please check your configuration.",
186                         configuration.get(DigitalSTROMBindingConstants.ZONE_ID));
187                 break;
188             case SceneHandler.GROUP_WRONG:
189                 logger.error("Configured group '{}' does not exist, please check your configuration.",
190                         configuration.get(DigitalSTROMBindingConstants.GROUP_ID));
191                 break;
192             case SceneHandler.NO_STRUC_MAN:
193                 logger.error("Waiting for building digitalSTROM model.");
194                 break;
195             case SceneHandler.NO_SCENE:
196                 logger.error("No Scene-ID is set!");
197                 break;
198             case SceneHandler.NO_BRIDGE:
199                 logger.error("No related bridge found!");
200             default:
201                 return new ThingUID(thingTypeUID, bridgeUID, sceneID);
202         }
203         return thingUID;
204     }
205
206     private ThingUID getBridgeThingUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Configuration configuration) {
207         if (thingUID != null) {
208             return thingUID;
209         }
210         String dSID;
211         String configValue = (String) configuration.get(DS_ID);
212         if (configValue == null || configValue.isBlank()) {
213             dSID = getDSSid(configuration);
214             if (dSID != null) {
215                 configuration.put(DS_ID, dSID);
216             }
217         } else {
218             dSID = configuration.get(DS_ID).toString();
219         }
220         if (dSID != null) {
221             return new ThingUID(thingTypeUID, dSID);
222         } else {
223             return null;
224         }
225     }
226
227     private String getDSSid(Configuration configuration) {
228         String dSID = null;
229         String hostConfigValue = (String) configuration.get(HOST);
230         if (hostConfigValue != null && !hostConfigValue.isBlank()) {
231             String host = hostConfigValue;
232             String applicationToken = null;
233             String user = null;
234             String pw = null;
235
236             String atConfigValue = (String) configuration.get(APPLICATION_TOKEN);
237             if (atConfigValue != null && !atConfigValue.isBlank()) {
238                 applicationToken = configuration.get(APPLICATION_TOKEN).toString();
239             }
240
241             if (checkUserPassword(configuration)) {
242                 user = configuration.get(USER_NAME).toString();
243                 pw = configuration.get(PASSWORD).toString();
244             }
245             ConnectionManager connMan = new ConnectionManagerImpl(host, user, pw, applicationToken, false, true);
246             Map<String, String> dsidMap = connMan.getDigitalSTROMAPI().getDSID(connMan.getSessionToken());
247             if (dsidMap != null) {
248                 dSID = dsidMap.get(JSONApiResponseKeysEnum.DSID.getKey());
249             }
250         }
251         return dSID;
252     }
253
254     private boolean checkUserPassword(Configuration configuration) {
255         String userName = (String) configuration.get(USER_NAME);
256         String password = (String) configuration.get(PASSWORD);
257         return userName != null && !userName.isBlank() && password != null && !password.isBlank();
258     }
259
260     @Override
261     protected synchronized void removeHandler(ThingHandler thingHandler) {
262         if (thingHandler instanceof BridgeHandler) {
263             String uid = thingHandler.getThing().getUID().getAsString();
264             DiscoveryServiceManager discoveryServiceManager = discoveryServiceManagers.remove(uid);
265             if (discoveryServiceManager != null) {
266                 discoveryServiceManager.unregisterDiscoveryServices(bundleContext);
267             }
268         }
269     }
270 }