2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.digitalstrom.internal;
15 import static org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants.*;
17 import java.util.HashMap;
19 import java.util.concurrent.ConcurrentHashMap;
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;
43 * The {@link DigitalSTROMHandlerFactory} is responsible for creating things and thing
46 * @author Michael Ochel - Initial contribution
47 * @author Mathias Siegele - Initial contribution
49 @Component(service = ThingHandlerFactory.class, configurationPid = "binding.digitalstrom")
50 public class DigitalSTROMHandlerFactory extends BaseThingHandlerFactory {
52 private final Logger logger = LoggerFactory.getLogger(DigitalSTROMHandlerFactory.class);
53 private final Map<String, DiscoveryServiceManager> discoveryServiceManagers = new ConcurrentHashMap<>();
55 private Map<ThingUID, BridgeHandler> bridgeHandlers;
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);
67 public Thing createThing(ThingTypeUID thingTypeUID, Configuration configuration, ThingUID thingUID,
69 if (BridgeHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
70 ThingUID dSSUID = getBridgeThingUID(thingTypeUID, thingUID, configuration);
72 return super.createThing(thingTypeUID, configuration, dSSUID, null);
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?\
85 if (DeviceHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
86 ThingUID dsDeviceUID = getDeviceUID(thingTypeUID, thingUID, configuration, bridgeUID);
87 return super.createThing(thingTypeUID, configuration, dsDeviceUID, bridgeUID);
90 if (CircuitHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
91 ThingUID dsDeviceUID = getDeviceUID(thingTypeUID, thingUID, configuration, bridgeUID);
92 return super.createThing(thingTypeUID, configuration, dsDeviceUID, bridgeUID);
95 if (ZoneTemperatureControlHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
96 ThingUID zoneTempConUID = getZoneTemperatureControlUID(thingTypeUID, thingUID, configuration, bridgeUID);
97 return super.createThing(thingTypeUID, configuration, zoneTempConUID, bridgeUID);
100 if (SceneHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
101 ThingUID dsSceneUID = getSceneUID(thingTypeUID, thingUID, configuration, bridgeUID);
102 return super.createThing(thingTypeUID, configuration, dsSceneUID, bridgeUID);
104 throw new IllegalArgumentException(
105 "The thing type " + thingTypeUID + " is not supported by the digitalSTROM binding.");
109 protected ThingHandler createHandler(Thing thing) {
110 ThingTypeUID thingTypeUID = thing.getThingTypeUID();
112 if (BridgeHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
113 BridgeHandler handler = new BridgeHandler((Bridge) thing);
114 if (bridgeHandlers == null) {
115 bridgeHandlers = new HashMap<>();
117 bridgeHandlers.put(thing.getUID(), handler);
118 DiscoveryServiceManager discoveryServiceManager = new DiscoveryServiceManager(handler);
119 discoveryServiceManager.registerDiscoveryServices(bundleContext);
120 discoveryServiceManagers.put(handler.getThing().getUID().getAsString(), discoveryServiceManager);
124 if (DeviceHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
125 return new DeviceHandler(thing);
128 if (CircuitHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
129 return new CircuitHandler(thing);
132 if (ZoneTemperatureControlHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
133 return new ZoneTemperatureControlHandler(thing);
136 if (SceneHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
137 return new SceneHandler(thing);
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);
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());
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));
163 case ZoneTemperatureControlHandler.ZONE_ID_NOT_SET:
164 logger.error("ZoneID is missing at your configuration.");
166 case ZoneTemperatureControlHandler.BRIDGE_IS_NULL:
167 logger.error("Bridge is missing, can not check the zoneID.");
175 private ThingUID getSceneUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Configuration configuration,
176 ThingUID bridgeUID) {
177 if (thingUID != null) {
180 String sceneID = SceneHandler.getSceneID(configuration, bridgeHandlers.get(bridgeUID));
182 case SceneHandler.SCENE_WRONG:
184 "Configured scene '{}' does not exist or can not be used, please check your configuration.",
185 configuration.get(DigitalSTROMBindingConstants.SCENE_ID));
187 case SceneHandler.ZONE_WRONG:
188 logger.error("Configured zone '{}' does not exist, please check your configuration.",
189 configuration.get(DigitalSTROMBindingConstants.ZONE_ID));
191 case SceneHandler.GROUP_WRONG:
192 logger.error("Configured group '{}' does not exist, please check your configuration.",
193 configuration.get(DigitalSTROMBindingConstants.GROUP_ID));
195 case SceneHandler.NO_STRUC_MAN:
196 logger.error("Waiting for building digitalSTROM model.");
198 case SceneHandler.NO_SCENE:
199 logger.error("No Scene-ID is set!");
201 case SceneHandler.NO_BRIDGE:
202 logger.error("No related bridge found!");
204 return new ThingUID(thingTypeUID, bridgeUID, sceneID);
209 private ThingUID getBridgeThingUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Configuration configuration) {
210 if (thingUID != null) {
214 String configValue = (String) configuration.get(DS_ID);
215 if (configValue == null || configValue.isBlank()) {
216 dSID = getDSSid(configuration);
218 configuration.put(DS_ID, dSID);
221 dSID = configuration.get(DS_ID).toString();
224 return new ThingUID(thingTypeUID, dSID);
230 private String getDSSid(Configuration configuration) {
232 String hostConfigValue = (String) configuration.get(HOST);
233 if (hostConfigValue != null && !hostConfigValue.isBlank()) {
234 String host = hostConfigValue;
235 String applicationToken = null;
239 String atConfigValue = (String) configuration.get(APPLICATION_TOKEN);
240 if (atConfigValue != null && !atConfigValue.isBlank()) {
241 applicationToken = configuration.get(APPLICATION_TOKEN).toString();
244 if (checkUserPassword(configuration)) {
245 user = configuration.get(USER_NAME).toString();
246 pw = configuration.get(PASSWORD).toString();
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());
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();
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);