/** * Copyright (c) 2010-2016 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.openhab.binding.gc100ir.internal; import java.util.Dictionary; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import org.openhab.binding.gc100ir.GC100IRBindingProvider; import org.openhab.binding.gc100ir.util.GC100ItemBean; import org.openhab.binding.gc100ir.util.GC100ItemUtility; import org.openhab.core.binding.AbstractBinding; import org.openhab.core.binding.BindingProvider; import org.openhab.core.types.Command; import org.osgi.service.cm.ConfigurationException; import org.osgi.service.cm.ManagedService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This refresh service for the GC100 binding is used to periodically check to * ensure all GC100 sockets are still open and alive. * * All item commands are sent via the tcp socket * * @author Parikshit Thakur & Team * @since 1.9.0 * */ public class GC100IRBinding extends AbstractBinding<GC100IRBindingProvider>implements ManagedService { private static final Logger logger = LoggerFactory.getLogger(GC100IRBinding.class); private Map<String, GC100IRConnector> connectors = new HashMap<String, GC100IRConnector>(); private Map<String, GC100IRHost> nameHostMapper = null; /** * @{inheritDoc} */ @Override public void bindingChanged(BindingProvider provider, String itemName) { if (provider instanceof GC100IRBindingProvider) { GC100IRBindingProvider gc100Provider = (GC100IRBindingProvider) provider; registerWatch(gc100Provider, itemName); } } /** * {@inheritDoc} */ @Override public void allBindingsChanged(BindingProvider provider) { if (provider instanceof GC100IRBindingProvider) { GC100IRBindingProvider gc100Provider = (GC100IRBindingProvider) provider; for (String itemName : gc100Provider.getItemNames()) { registerWatch(gc100Provider, itemName); } } } /** * Registers all items and GC100IRConnector. */ private void registerAllWatches() { for (BindingProvider provider : providers) { if (provider instanceof GC100IRBindingProvider) { GC100IRBindingProvider gc100Provider = (GC100IRBindingProvider) provider; for (String itemName : gc100Provider.getItemNames()) { registerWatch(gc100Provider, itemName); } } } } /** * Register each item and adds them in GC100ItemUtility list. * * @param gc100Provider * @param itemName */ private void registerWatch(GC100IRBindingProvider gc100Provider, String itemName) { if (!gc100Provider.providesBindingFor(itemName)) { return; } String gc100Instance = gc100Provider.getGC100InstanceName(itemName); int module = gc100Provider.getGC100Module(itemName); int connector = gc100Provider.getGC100Connector(itemName); String code = gc100Provider.getCode(itemName); GC100ItemBean itemBean = new GC100ItemBean(); itemBean.setGC100Instance(gc100Instance); itemBean.setModule(module); itemBean.setConnector(connector); itemBean.setCode(code); GC100ItemUtility GC100ItemUtility = org.openhab.binding.gc100ir.util.GC100ItemUtility.getInstance(); GC100ItemUtility.addItem(itemName, itemBean); GC100IRConnector gc100Connector = getGC100Connector(gc100Instance); if (gc100Connector == null) { logger.error("Connection failed with " + gc100Instance); } } /** * Gets the GC100Instance according to item name. * * @param itemName * @return a String value of GC100 instance. */ private String getGC100InstanceName(String itemName) { for (BindingProvider provider : providers) { if (provider instanceof GC100IRBindingProvider) { GC100IRBindingProvider gc100Provider = (GC100IRBindingProvider) provider; if (gc100Provider.getItemNames().contains(itemName)) { return gc100Provider.getGC100InstanceName(itemName); } } } return null; } /** * Gets the GC100 connector object from connector list. * * @param gc100InstanceName * @return GC100IRConnector instance. */ private GC100IRConnector getGC100Connector(String gc100InstanceName) { // sanity check if (gc100InstanceName == null) { return null; } // check if the connector for this instance already exists GC100IRConnector connector = connectors.get(gc100InstanceName); if (connector != null) { return connector; } GC100IRHost gc100Host; if (gc100InstanceName.startsWith("#")) { // trim off the '#' identifier String instance = gc100InstanceName.substring(1); // check if we have been initialised yet - can't process // named instances until we have read the binding config if (nameHostMapper == null) { logger.trace("Attempting to access the named instance '{}' before the binding config has been loaded", instance); return null; } // check this instance name exists in our config if (!nameHostMapper.containsKey(instance)) { logger.error("Named instance '{}' does not exist in the binding config", instance); return null; } gc100Host = nameHostMapper.get(instance); } else { gc100Host = new GC100IRHost(); gc100Host.setHostname(gc100InstanceName); } // create a new connection handler logger.debug("Creating new GC100IRConnector for '{}' on {}", gc100InstanceName, gc100Host.getHostname()); connector = new GC100IRConnector(gc100Host); connectors.put(gc100InstanceName, connector); // attempt to open the connection straight away try { connector.open(); } catch (Exception e) { logger.error("Connection failed for '{}' on {}", gc100InstanceName, gc100Host.getHostname()); } return connector; } /** * {@inheritDoc} */ @Override protected void internalReceiveCommand(String itemName, Command command) { try { // lookup the GC100 instance name and property for this item String gc100Instance = getGC100InstanceName(itemName); GC100IRConnector connector = getGC100Connector(gc100Instance); if (connector == null) { logger.warn("Received command ({}) for item {} but no GC100 connector found for {}, ignoring", command.toString(), itemName, gc100Instance); return; } if (!connector.isConnected()) { logger.warn( "Received command ({}) for item {} but the connection to the GC100 instance {} is down, ignoring", command.toString(), itemName, gc100Instance); return; } connector.invokeCommand(itemName); } catch (Exception e) { logger.error("Error handling command", e); } } /** * {@inheritDoc} */ @Override public void updated(Dictionary<String, ?> config) throws ConfigurationException { // Nothing to do if there is no config if (config == null) { return; } Map<String, GC100IRHost> hosts = new HashMap<String, GC100IRHost>(); Enumeration<String> keys = config.keys(); while (keys.hasMoreElements()) { String key = keys.nextElement(); if ("service.pid".equals(key)) { continue; } String[] parts = key.split("\\."); String hostname = parts[0]; GC100IRHost host = hosts.get(hostname); if (host == null) { host = new GC100IRHost(); } String value = ((String) config.get(key)).trim(); if ("host".equals(parts[1])) { host.setHostname(value); } hosts.put(hostname, host); } nameHostMapper = hosts; registerAllWatches(); } protected void addBindingProvider(GC100IRBindingProvider bindingProvider) { super.addBindingProvider(bindingProvider); } protected void removeBindingProvider(GC100IRBindingProvider bindingProvider) { super.removeBindingProvider(bindingProvider); } }