]> git.basschouten.com Git - openhab-addons.git/blob
685952bf68831aa4eebb2beddef0506d413eea38
[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;
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("""
75                         Can't generate thing UID for thing type {}\
76                         , because digitalSTROM-Server is not reachable. Please check these points:
77                         Are the server address and portnumber correct?
78                         Is the server turned on?
79                         Is the network configured correctly?\
80                         """, thingTypeUID);
81                 return null;
82             }
83         }
84
85         if (DeviceHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
86             ThingUID dsDeviceUID = getDeviceUID(thingTypeUID, thingUID, configuration, bridgeUID);
87             return super.createThing(thingTypeUID, configuration, dsDeviceUID, bridgeUID);
88         }
89
90         if (CircuitHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
91             ThingUID dsDeviceUID = getDeviceUID(thingTypeUID, thingUID, configuration, bridgeUID);
92             return super.createThing(thingTypeUID, configuration, dsDeviceUID, bridgeUID);
93         }
94
95         if (ZoneTemperatureControlHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
96             ThingUID zoneTempConUID = getZoneTemperatureControlUID(thingTypeUID, thingUID, configuration, bridgeUID);
97             return super.createThing(thingTypeUID, configuration, zoneTempConUID, bridgeUID);
98         }
99
100         if (SceneHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
101             ThingUID dsSceneUID = getSceneUID(thingTypeUID, thingUID, configuration, bridgeUID);
102             return super.createThing(thingTypeUID, configuration, dsSceneUID, bridgeUID);
103         }
104         throw new IllegalArgumentException(
105                 "The thing type " + thingTypeUID + " is not supported by the digitalSTROM binding.");
106     }
107
108     @Override
109     protected ThingHandler createHandler(Thing thing) {
110         ThingTypeUID thingTypeUID = thing.getThingTypeUID();
111
112         if (BridgeHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
113             BridgeHandler handler = new BridgeHandler((Bridge) thing);
114             if (bridgeHandlers == null) {
115                 bridgeHandlers = new HashMap<>();
116             }
117             bridgeHandlers.put(thing.getUID(), handler);
118             DiscoveryServiceManager discoveryServiceManager = new DiscoveryServiceManager(handler);
119             discoveryServiceManager.registerDiscoveryServices(bundleContext);
120             discoveryServiceManagers.put(handler.getThing().getUID().getAsString(), discoveryServiceManager);
121             return handler;
122         }
123
124         if (DeviceHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
125             return new DeviceHandler(thing);
126         }
127
128         if (CircuitHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
129             return new CircuitHandler(thing);
130         }
131
132         if (ZoneTemperatureControlHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
133             return new ZoneTemperatureControlHandler(thing);
134         }
135
136         if (SceneHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
137             return new SceneHandler(thing);
138         }
139         return null;
140     }
141
142     private ThingUID getDeviceUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Configuration configuration,
143             ThingUID bridgeUID) {
144         String id = (String) configuration.get(DEVICE_DSID);
145         if (thingUID == null && id != null && !id.isBlank()) {
146             return new ThingUID(thingTypeUID, bridgeUID, id);
147         }
148         return thingUID;
149     }
150
151     private ThingUID getZoneTemperatureControlUID(ThingTypeUID thingTypeUID, ThingUID thingUID,
152             Configuration configuration, ThingUID bridgeUID) {
153         if (thingUID == null) {
154             Integer zoneID = ZoneTemperatureControlHandler.getZoneID(configuration, bridgeHandlers.get(bridgeUID));
155             if (zoneID > ZoneTemperatureControlHandler.ZONE_ID_NOT_EXISTS) {
156                 return new ThingUID(thingTypeUID, bridgeUID, zoneID.toString());
157             } else {
158                 switch (zoneID) {
159                     case ZoneTemperatureControlHandler.ZONE_ID_NOT_EXISTS:
160                         logger.error("Configured zone '{}' does not exist, please check your configuration.",
161                                 configuration.get(DigitalSTROMBindingConstants.ZONE_ID));
162                         break;
163                     case ZoneTemperatureControlHandler.ZONE_ID_NOT_SET:
164                         logger.error("ZoneID is missing at your configuration.");
165                         break;
166                     case ZoneTemperatureControlHandler.BRIDGE_IS_NULL:
167                         logger.error("Bridge is missing, can not check the zoneID.");
168                         break;
169                 }
170             }
171         }
172         return thingUID;
173     }
174
175     private ThingUID getSceneUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Configuration configuration,
176             ThingUID bridgeUID) {
177         if (thingUID != null) {
178             return thingUID;
179         }
180         String sceneID = SceneHandler.getSceneID(configuration, bridgeHandlers.get(bridgeUID));
181         switch (sceneID) {
182             case SceneHandler.SCENE_WRONG:
183                 logger.error(
184                         "Configured scene '{}' does not exist or can not be used, please check your configuration.",
185                         configuration.get(DigitalSTROMBindingConstants.SCENE_ID));
186                 break;
187             case SceneHandler.ZONE_WRONG:
188                 logger.error("Configured zone '{}' does not exist, please check your configuration.",
189                         configuration.get(DigitalSTROMBindingConstants.ZONE_ID));
190                 break;
191             case SceneHandler.GROUP_WRONG:
192                 logger.error("Configured group '{}' does not exist, please check your configuration.",
193                         configuration.get(DigitalSTROMBindingConstants.GROUP_ID));
194                 break;
195             case SceneHandler.NO_STRUC_MAN:
196                 logger.error("Waiting for building digitalSTROM model.");
197                 break;
198             case SceneHandler.NO_SCENE:
199                 logger.error("No Scene-ID is set!");
200                 break;
201             case SceneHandler.NO_BRIDGE:
202                 logger.error("No related bridge found!");
203             default:
204                 return new ThingUID(thingTypeUID, bridgeUID, sceneID);
205         }
206         return thingUID;
207     }
208
209     private ThingUID getBridgeThingUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Configuration configuration) {
210         if (thingUID != null) {
211             return thingUID;
212         }
213         String dSID;
214         String configValue = (String) configuration.get(DS_ID);
215         if (configValue == null || configValue.isBlank()) {
216             dSID = getDSSid(configuration);
217             if (dSID != null) {
218                 configuration.put(DS_ID, dSID);
219             }
220         } else {
221             dSID = configuration.get(DS_ID).toString();
222         }
223         if (dSID != null) {
224             return new ThingUID(thingTypeUID, dSID);
225         } else {
226             return null;
227         }
228     }
229
230     private String getDSSid(Configuration configuration) {
231         String dSID = null;
232         String hostConfigValue = (String) configuration.get(HOST);
233         if (hostConfigValue != null && !hostConfigValue.isBlank()) {
234             String host = hostConfigValue;
235             String applicationToken = null;
236             String user = null;
237             String pw = null;
238
239             String atConfigValue = (String) configuration.get(APPLICATION_TOKEN);
240             if (atConfigValue != null && !atConfigValue.isBlank()) {
241                 applicationToken = configuration.get(APPLICATION_TOKEN).toString();
242             }
243
244             if (checkUserPassword(configuration)) {
245                 user = configuration.get(USER_NAME).toString();
246                 pw = configuration.get(PASSWORD).toString();
247             }
248             ConnectionManager connMan = new ConnectionManagerImpl(host, user, pw, applicationToken, false, true);
249             Map<String, String> dsidMap = connMan.getDigitalSTROMAPI().getDSID(connMan.getSessionToken());
250             if (dsidMap != null) {
251                 dSID = dsidMap.get(JSONApiResponseKeysEnum.DSID.getKey());
252             }
253         }
254         return dSID;
255     }
256
257     private boolean checkUserPassword(Configuration configuration) {
258         String userName = (String) configuration.get(USER_NAME);
259         String password = (String) configuration.get(PASSWORD);
260         return userName != null && !userName.isBlank() && password != null && !password.isBlank();
261     }
262
263     @Override
264     protected synchronized void removeHandler(ThingHandler thingHandler) {
265         if (thingHandler instanceof BridgeHandler) {
266             String uid = thingHandler.getThing().getUID().getAsString();
267             DiscoveryServiceManager discoveryServiceManager = discoveryServiceManagers.remove(uid);
268             if (discoveryServiceManager != null) {
269                 discoveryServiceManager.unregisterDiscoveryServices(bundleContext);
270             }
271         }
272     }
273 }