Package org.openhab.binding.xbmc.internal

Source Code of org.openhab.binding.xbmc.internal.XbmcActiveBinding

/**
* Copyright (c) 2010-2014, openHAB.org and others.
*
* 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.xbmc.internal;

import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import org.openhab.binding.xbmc.XbmcBindingProvider;
import org.openhab.binding.xbmc.rpc.XbmcConnector;
import org.openhab.core.binding.AbstractActiveBinding;
import org.openhab.core.binding.BindingProvider;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
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 XBMC binding is used to periodically
* check to ensure all XBMC web sockets are still open and alive.
*
* All item updates are received asynchronously via the web socket
* All item commands are sent via the web socket
*
* @author tlan, Ben Jones
* @since 1.5.0
*/
public class XbmcActiveBinding extends AbstractActiveBinding<XbmcBindingProvider> implements ManagedService {

  private static final Logger logger = LoggerFactory.getLogger(XbmcActiveBinding.class);

  private Map<String, XbmcConnector> connectors = new HashMap<String, XbmcConnector>();
  private Map<String, XbmcHost> nameHostMapper = null;

  /**
   * the refresh interval which is used to check for lost connections
   * (optional, defaults to 60000ms)
   */
  private long refreshInterval = 60000;

  public void activate() {
    logger.debug(getName() + " activate()");
    setProperlyConfigured(true);
  }

  public void deactivate() {
    logger.debug(getName() + " deactivate()");

    // close any open connections
    for (XbmcConnector connector : connectors.values()) {
      if (connector.isConnected()) {
        connector.close();
      }
    }
  }

  /**
   * {@inheritDoc}
   */
  @Override
  protected long getRefreshInterval() {
    return refreshInterval;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  protected String getName() {
    return "XBMC Refresh Service";
  }

  /**
   * @{inheritDoc}
   */ 
  @Override
  public void bindingChanged(BindingProvider provider, String itemName) {
    if (provider instanceof XbmcBindingProvider) {
      XbmcBindingProvider xbmcProvider = (XbmcBindingProvider) provider;
      registerWatch(xbmcProvider, itemName);
    }   
  }
 
  /**
   * {@inheritDoc}
   */
  @Override
  public void allBindingsChanged(BindingProvider provider) {
    if (provider instanceof XbmcBindingProvider) {
      XbmcBindingProvider xbmcProvider = (XbmcBindingProvider) provider;   
      for (String itemName : xbmcProvider.getItemNames()) {
        registerWatch(xbmcProvider, itemName);
      }
    }
  }
 
  private void registerAllWatches() {
    for (BindingProvider provider : providers) {
      if (provider instanceof XbmcBindingProvider) {
        XbmcBindingProvider xbmcProvider = (XbmcBindingProvider) provider; 
        for (String itemName : xbmcProvider.getItemNames()) {
          registerWatch(xbmcProvider, itemName);
        }
      }
    }
  }
   
  private void registerWatch(XbmcBindingProvider xbmcProvider, String itemName) {
        // only interested in watching 'inbound' items
    if (!xbmcProvider.isInBound(itemName))
      return;

    String xbmcInstance = xbmcProvider.getXbmcInstance(itemName);
    String property = xbmcProvider.getProperty(itemName);

    XbmcConnector connector = getXbmcConnector(xbmcInstance);
    if (connector != null) {
      // add the new 'watch'
      connector.addItem(itemName, property);
     
      // update the player status so any current value is initialised
      if (connector.isConnected()) {
        connector.updatePlayerStatus();
      }
     
      if (property.startsWith("Application")) {
        connector.requestApplicationUpdate();
      } else if (property.equals("System.State")) {
        connector.updateSystemStatus();
      }
    }
  }
 
  private String getXbmcInstance(String itemName) {
    for (BindingProvider provider : providers) {
      if (provider instanceof XbmcBindingProvider) {
        XbmcBindingProvider xbmcProvider = (XbmcBindingProvider) provider;
        if (xbmcProvider.getItemNames().contains(itemName)) {
          return xbmcProvider.getXbmcInstance(itemName);
        }
      }
    }
    return null;
  }
 
  private String getProperty(String itemName) {
    for (BindingProvider provider : providers) {
      if (provider instanceof XbmcBindingProvider) {
        XbmcBindingProvider xbmcProvider = (XbmcBindingProvider) provider;
        if (xbmcProvider.getItemNames().contains(itemName)) {
          return xbmcProvider.getProperty(itemName);
        }
      }
    }
    return null;
  }

  private boolean isInBound(String itemName) {
    for (BindingProvider provider : providers) {
      if (provider instanceof XbmcBindingProvider) {
        XbmcBindingProvider xbmcProvider = (XbmcBindingProvider) provider;
        if (xbmcProvider.getItemNames().contains(itemName)) {
          return xbmcProvider.isInBound(itemName);
        }
      }
    }
    return false;
  }

  private boolean isOutBound(String itemName) {
    for (BindingProvider provider : providers) {
      if (provider instanceof XbmcBindingProvider) {
        XbmcBindingProvider xbmcProvider = (XbmcBindingProvider) provider;
        if (xbmcProvider.getItemNames().contains(itemName)) {
          return xbmcProvider.isOutBound(itemName);
        }
      }
    }
    return false;
  }

  private XbmcConnector getXbmcConnector(String xbmcInstance) {
    // sanity check
    if (xbmcInstance == null)
      return null;
   
    // check if the connector for this instance already exists
    XbmcConnector connector = connectors.get(xbmcInstance);
    if (connector != null)
      return connector;
   
    XbmcHost xbmcHost;
    if (xbmcInstance.startsWith("#")) {
      // trim off the '#' identifier
      String instance = xbmcInstance.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;
      }

      xbmcHost = nameHostMapper.get(instance);
    } else {
      xbmcHost = new XbmcHost();
      xbmcHost.setHostname(xbmcInstance);
    }   

    // create a new connection handler
    logger.debug("Creating new XbmcConnector for '{}' on {}", xbmcInstance, xbmcHost.getHostname());
    connector = new XbmcConnector(xbmcHost, eventPublisher);
    connectors.put(xbmcInstance, connector);
   
    // attempt to open the connection straight away
    try {
      connector.open();
    } catch (Exception e) {
      logger.error("Connection failed for '{}' on {}", xbmcInstance, xbmcHost.getHostname());
    }

    return connector;
  }
   
  /**
   * {@inheritDoc}
   */
  @Override
  protected void execute() {
    for (Map.Entry<String, XbmcConnector> entry : connectors.entrySet()) {
      XbmcConnector connector = entry.getValue();
      if (connector.isConnected()) {
        // we are still connected but send a ping to make sure
        connector.ping();
        // refresh all players
        connector.updatePlayerStatus(true);
      } else {
        // broken connection so attempt to reconnect
        logger.debug("Broken connection found for '{}', attempting to reconnect...", entry.getKey());
        try {
          connector.open();
        } catch (Exception e) {
          logger.debug("Reconnect failed for '{}', will retry in {}s", entry.getKey(), refreshInterval / 1000);
        }
      }
    }
  }

  /**
   * {@inheritDoc}
   */
  @Override
  protected void internalReceiveCommand(String itemName, Command command) {
        // only interested in 'outbound' items
    if (!isOutBound(itemName)) {
      logger.warn("Received command ({}) for item {} which is configured as 'in-bound', ignoring", command.toString(), itemName);
      return;
    }
   
    try {
      // lookup the XBMC instance name and property for this item
      String xbmcInstance = getXbmcInstance(itemName);
      String property = getProperty(itemName);
     
      XbmcConnector connector = getXbmcConnector(xbmcInstance);
      if (connector == null) {
        logger.warn("Received command ({}) for item {} but no XBMC connector found for {}, ignoring", command.toString(), itemName, xbmcInstance);
        return;
      }
      if (!connector.isConnected()) {
        logger.warn("Received command ({}) for item {} but the connection to the XBMC instance {} is down, ignoring", command.toString(), itemName, xbmcInstance);
        return;
      }
     
      // TODO: handle other commands
      if (property.equals("Player.PlayPause"))
        connector.playerPlayPause();
      else if (property.equals("Player.Open"))
        connector.playerOpen(command.toString());
      else if (property.equals("Player.Stop"))     
        connector.playerStop();
      else if (property.equals("GUI.ShowNotification"))
        connector.showNotification("openHAB", command.toString());
      else if (property.equals("System.Shutdown") && command == OnOffType.OFF)
        connector.systemShutdown();
      else if (property.equals("System.Suspend") && command == OnOffType.OFF)
        connector.systemSuspend();
      else if (property.equals("System.Hibernate") && command == OnOffType.OFF)
        connector.systemHibernate();
      else if (property.equals("System.Reboot") && command == OnOffType.OFF)
        connector.systemReboot();
      else if (property.equals("Application.Volume"))
        connector.applicationSetVolume(command.toString());
    } catch (Exception e) {
      logger.error("Error handling command", e);
    }
  }

  /**
   * {@inheritDoc}
   */
  @Override
  protected void internalReceiveUpdate(String itemName, State newState) {
    try {
      String property = getProperty(itemName);

      String xbmcInstance = getXbmcInstance(itemName);
      XbmcConnector connector = getXbmcConnector(xbmcInstance);

      if (connector == null) {
        logger.warn("Received update ({}) for item {} but no XBMC connector found for {}, ignoring", newState.toString(), itemName, xbmcInstance);
        return;
      }
      if (!connector.isConnected()) {
        logger.warn("Received update ({}) for item {} but the connection to the XBMC instance {} is down, ignoring", newState.toString(), itemName, xbmcInstance);
        return;
      }

      // TODO: handle other updates
      if (property.equals("GUI.ShowNotification")) {
        connector.showNotification("openHAB", newState.toString());     
      } else if (property.equals("Player.Open")) {
        connector.playerOpen(newState.toString());
      } else if (property.equals("Application.SetVolume")) {
        connector.applicationSetVolume(newState.toString());
      }

    } catch (Exception e) {
      logger.error("Error handling update", e);
    }
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public void updated(Dictionary<String, ?> config) throws ConfigurationException {
    logger.debug(getName() + " updated()");

    Map<String, XbmcHost> hosts = new HashMap<String, XbmcHost>();

    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];

      XbmcHost host = hosts.get(hostname);
      if (host == null) {
        host = new XbmcHost();
      }

      String value = ((String) config.get(key)).trim();

      if ("host".equals(parts[1])) {
        host.setHostname(value);
      }
      if ("rsPort".equals(parts[1])) {
        host.setRsPort(Integer.valueOf(value));
      }
      if ("wsPort".equals(parts[1])) {
        host.setWsPort(Integer.valueOf(value));
      }
      if ("username".equals(parts[1])) {
        host.setUsername(value);
      }
      if ("password".equals(parts[1])) {
        host.setPassword(value);
      }

      hosts.put(hostname, host);
    }
   
    nameHostMapper = hosts;   
    registerAllWatches();
  }
}
TOP

Related Classes of org.openhab.binding.xbmc.internal.XbmcActiveBinding

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.