/** * Copyright (c) 2014-2017 by the respective copyright holders. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.eclipse.smarthome.binding.digitalstrom.internal; import static org.eclipse.smarthome.binding.digitalstrom.DigitalSTROMBindingConstants.*; import java.util.HashMap; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.eclipse.smarthome.binding.digitalstrom.DigitalSTROMBindingConstants; import org.eclipse.smarthome.binding.digitalstrom.handler.BridgeHandler; import org.eclipse.smarthome.binding.digitalstrom.handler.DeviceHandler; import org.eclipse.smarthome.binding.digitalstrom.handler.SceneHandler; import org.eclipse.smarthome.binding.digitalstrom.internal.discovery.DiscoveryServiceManager; import org.eclipse.smarthome.binding.digitalstrom.internal.lib.manager.ConnectionManager; import org.eclipse.smarthome.binding.digitalstrom.internal.lib.manager.impl.ConnectionManagerImpl; import org.eclipse.smarthome.config.core.Configuration; import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.ThingUID; import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.collect.Sets; /** * The {@link DigitalSTROMHandlerFactory} is responsible for creating things and thing * handlers. * * @author Michael Ochel - Initial contribution * @author Mathias Siegele - Initial contribution */ public class DigitalSTROMHandlerFactory extends BaseThingHandlerFactory { private Logger logger = LoggerFactory.getLogger(DigitalSTROMHandlerFactory.class); private HashMap<String, DiscoveryServiceManager> discoveryServiceManagers = new HashMap<String, DiscoveryServiceManager>(); public final static Set<ThingTypeUID> SUPPORTED_THING_TYPES = Sets.union(SceneHandler.SUPPORTED_THING_TYPES, Sets.union(BridgeHandler.SUPPORTED_THING_TYPES, DeviceHandler.SUPPORTED_THING_TYPES)); private HashMap<ThingUID, BridgeHandler> bridgeHandlers = null; @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { return SUPPORTED_THING_TYPES.contains(thingTypeUID); } @Override public Thing createThing(ThingTypeUID thingTypeUID, Configuration configuration, ThingUID thingUID, ThingUID bridgeUID) { if (BridgeHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) { ThingUID dSSUID = getBridgeThingUID(thingTypeUID, thingUID, configuration); if (dSSUID != null) { logger.info(dSSUID.toString()); return super.createThing(thingTypeUID, configuration, dSSUID, null); } else { logger.error("Can't generate thing UID for thing type " + thingTypeUID + ", because digitalSTROM-Server is not reachable. Please check these points:\n" + "Are the server address and portnumber correct?\n" + "Is the server turned on?\n" + "Is the network configured correctly?"); return null; } } if (DeviceHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) { ThingUID dsDeviceUID = getDeviceUID(thingTypeUID, thingUID, configuration, bridgeUID); return super.createThing(thingTypeUID, configuration, dsDeviceUID, bridgeUID); } if (SceneHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) { ThingUID dsSceneUID = getSceneUID(thingTypeUID, thingUID, configuration, bridgeUID); return super.createThing(thingTypeUID, configuration, dsSceneUID, bridgeUID); } throw new IllegalArgumentException( "The thing type " + thingTypeUID + " is not supported by the digitalSTROM binding."); } @Override protected ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (thingTypeUID == null) { return null; } if (BridgeHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) { BridgeHandler handler = new BridgeHandler((Bridge) thing); if (bridgeHandlers == null) { bridgeHandlers = new HashMap<ThingUID, BridgeHandler>(); } bridgeHandlers.put(thing.getUID(), handler); DiscoveryServiceManager discoveryServiceManager = new DiscoveryServiceManager(handler); discoveryServiceManager.registerDiscoveryServices(bundleContext); discoveryServiceManagers.put(handler.getThing().getUID().getAsString(), discoveryServiceManager); return handler; } if (DeviceHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) { return new DeviceHandler(thing); } if (SceneHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) { return new SceneHandler(thing); } return null; } private ThingUID getDeviceUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Configuration configuration, ThingUID bridgeUID) { if (StringUtils.isNotBlank((String) configuration.get(DEVICE_DSID))) { thingUID = new ThingUID(thingTypeUID, bridgeUID, configuration.get(DEVICE_DSID).toString()); } return thingUID; } private ThingUID getSceneUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Configuration configuration, ThingUID bridgeUID) { if (thingUID.getId().split("-").length == 3) { return thingUID; } String sceneID = SceneHandler.getSceneID(configuration, bridgeHandlers.get(bridgeUID)); switch (sceneID) { case SceneHandler.SCENE_WRONG: logger.error("Configured scene '" + configuration.get(DigitalSTROMBindingConstants.SCENE_ID) + "' does not exist or can not be used, please check your configuration."); break; case SceneHandler.ZONE_WRONG: logger.error("Configured zone '" + configuration.get(DigitalSTROMBindingConstants.SCENE_ZONE_ID) + "' does not exist, please check your configuration."); break; case SceneHandler.GROUP_WRONG: logger.error("Configured group '" + configuration.get(DigitalSTROMBindingConstants.SCENE_GROUP_ID) + "' does not exist, please check your configuration."); break; case SceneHandler.NO_STRUC_MAN: logger.error("Waiting for building digitalSTROM model."); break; case SceneHandler.NO_SCENE: logger.error("No Scene-ID is set!"); break; case SceneHandler.NO_BRIDGE: logger.error("No related bridge found!"); default: return new ThingUID(thingTypeUID, bridgeUID, sceneID); } return null; } private ThingUID getBridgeThingUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Configuration configuration) { String dSID; if (StringUtils.isBlank((String) configuration.get(DS_ID))) { dSID = getDSSid(configuration); if (dSID != null) { configuration.put(DS_ID, dSID); } } else { dSID = configuration.get(DS_ID).toString(); } if (dSID != null) { return new ThingUID(thingTypeUID, dSID); } else { return null; } } private String getDSSid(Configuration configuration) { String dsID = null; if (StringUtils.isNotBlank((String) configuration.get(HOST))) { String host = configuration.get(HOST).toString(); String applicationToken = null; String user = null; String pw = null; if (StringUtils.isNotBlank((String) configuration.get(APPLICATION_TOKEN))) { applicationToken = configuration.get(APPLICATION_TOKEN).toString(); } if (checkUserPassword(configuration)) { user = configuration.get(USER_NAME).toString(); pw = configuration.get(PASSWORD).toString(); } ConnectionManager connMan = new ConnectionManagerImpl(host, user, pw, applicationToken, false, true); // Only to get sessionToken for server versions which returns the dSID of the server only, if a user is // logged in connMan.checkConnection(); dsID = connMan.getDigitalSTROMAPI().getDSID(connMan.getSessionToken()); } return dsID; } private boolean checkUserPassword(Configuration configuration) { return StringUtils.isNotBlank((String) configuration.get(USER_NAME)) && StringUtils.isNotBlank((String) configuration.get(PASSWORD)); } @Override protected synchronized void removeHandler(ThingHandler thingHandler) { if (thingHandler instanceof BridgeHandler) { String uid = thingHandler.getThing().getUID().getAsString(); if (discoveryServiceManagers.get(uid) != null) { discoveryServiceManagers.get(uid).unregisterDiscoveryServices(bundleContext); discoveryServiceManagers.remove(uid); } } } }