Package org.openhab.binding.tellstick.internal

Source Code of org.openhab.binding.tellstick.internal.TellstickBinding$TellstickDeviceEventHandler

/**
* Copyright (c) 2013-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.tellstick.internal;

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

import org.openhab.binding.tellstick.TellstickBindingConfig;
import org.openhab.binding.tellstick.TellstickBindingProvider;
import org.openhab.binding.tellstick.TellstickValueSelector;
import org.openhab.binding.tellstick.internal.JNA.DataType;
import org.openhab.binding.tellstick.internal.JNA.Method;
import org.openhab.binding.tellstick.internal.device.SupportedMethodsException;
import org.openhab.binding.tellstick.internal.device.TellstickDevice;
import org.openhab.binding.tellstick.internal.device.TellstickDeviceEvent;
import org.openhab.binding.tellstick.internal.device.TellstickSensorEvent;
import org.openhab.binding.tellstick.internal.device.iface.DeviceChangeListener;
import org.openhab.binding.tellstick.internal.device.iface.SensorListener;
import org.openhab.core.binding.AbstractActiveBinding;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.PercentType;
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 class coordinates between the events in openHAB and the Tellstick
* device. It uses a JNA bridge to talk to the C api of the tellstick.
*
* @author jarlebh
* @since 1.5.0
*/
public class TellstickBinding extends AbstractActiveBinding<TellstickBindingProvider> implements ManagedService {

  private static final Logger logger = LoggerFactory.getLogger(TellstickBinding.class);
  /**
   * Default update interval from tellstick
   */
  private static final int UPDATE_FROM_TELLSTICK_INTERVAL = 600000;

  /**
   * Max time without receiving any events.
   */
  private static final int MAX_IDLE_BEFORE_RESTART = 600000;

  private int restartTimeout;

  private int updateFromTellstickInterval;

  private long lastRefresh = 0;

  /**
   * the refresh interval which is used to poll values from the Tellstick
   * server (optional, defaults to 60000ms)
   */
  private long refreshInterval = 60000;

  private TellstickController controller = new TellstickController();

  public TellstickBinding() {
  }

  public void activate() {
    logger.info("Activate " + Thread.currentThread());
  }

  public void deactivate() {
    logger.info("Deactivate " + this);
    try {
      deRegisterListeners();
    } catch (Exception e) {
      logger.error("Failed to deactivate", e);
    }
  }

  private void registerListeners() {
    for (TellstickBindingProvider prov : providers) {
      prov.addListener(new TellstickDeviceEventHandler());
      prov.addListener(new TellstickSensorEventHandler());
    }
  }

  private void deRegisterListeners() throws SupportedMethodsException {
    for (TellstickBindingProvider prov : providers) {
      prov.removeTellstickListener();
    }
  }

  private void resetTelldusProvider() throws SupportedMethodsException {
    for (TellstickBindingProvider prov : providers) {
      prov.resetTellstickListener();
    }
  }

  /**
   * @{inheritDoc
   */
  @Override
  protected void internalReceiveCommand(String itemName, Command command) {
    // the code being executed when a command was sent on the openHAB
    // event bus goes here. This method is only called if one of the
    // BindingProviders provide a binding for the given 'itemName'.
    logger.debug("internalReceiveCommand() is called! for " + itemName + " with " + command);
    TellstickBindingConfig config = findTellstickBindingConfig(itemName);
    if (config != null) {
      try {
        TellstickDevice dev = findDevice(config);
        controller.handleSendEvent(config, dev, command);
      } catch (Exception e) {
        logger.error("Failed to send msg to " + config, e);
      }
    }
  }

  private TellstickDevice findDevice(TellstickBindingConfig config) {
    TellstickDevice dev = null;
    for (TellstickBindingProvider prov : providers) {
      dev = ((TellstickBindingProvider) prov).getDevice(config.getItemName());
      if (dev != null) {
        break;
      }
    }
    return dev;
  }

  /**
   * @{inheritDoc
   */
  @Override
  public void updated(Dictionary<String, ?> config) throws ConfigurationException {

    this.updateFromTellstickInterval = UPDATE_FROM_TELLSTICK_INTERVAL;
    this.restartTimeout = MAX_IDLE_BEFORE_RESTART;

    logger.info("Called with config " + config);
    if (config != null) {
      String maxIdle = (String) config.get("max_idle");
      String updateInterval = (String) config.get("update_interval");
      if (maxIdle != null) {
        this.restartTimeout = Integer.valueOf(maxIdle);
      }
      if (updateInterval != null) {
        this.updateFromTellstickInterval = Integer.valueOf(updateInterval);
      }
    }
    resetTellstick();
    setProperlyConfigured(true);
  }

  private TellstickBindingConfig findTellstickBindingConfig(int itemId, TellstickValueSelector valueSel) {

    TellstickBindingConfig matchingConfig = null;
    for (TellstickBindingProvider provider : this.providers) {
      TellstickBindingConfig config = provider.getTellstickBindingConfig(itemId, valueSel);
      if (config != null) {
        matchingConfig = config;
        break;
      }
    }
    return matchingConfig;
  }

  private TellstickBindingConfig findTellstickBindingConfig(String itemName) {
    TellstickBindingConfig matchingConfig = null;
    for (TellstickBindingProvider provider : this.providers) {
      TellstickBindingConfig config = provider.getTellstickBindingConfig(itemName);
      if (config != null) {
        matchingConfig = config;
        break;
      }
    }
    return matchingConfig;
  }

  class TellstickDeviceEventHandler implements DeviceChangeListener {
    @Override
    public void onRequest(TellstickDeviceEvent newDevices) {
      handleDeviceEvent(newDevices);
    }
  }

  private void handleDeviceEvent(TellstickDeviceEvent event) {
    TellstickDevice device = event.getDevice();
    controller.setLastSend(System.currentTimeMillis());
    logger.debug("Got deviceEvent for " + device + " name:" + device + " method" + event.getMethod());
    if (device != null) {
      State cmd = resolveCommand(event.getMethod(), event.getData());
      TellstickBindingConfig conf = findTellstickBindingConfig(device.getId(), null);
      if (conf != null) {
        sendToOpenHab(conf.getItemName(), cmd);
      } else {
        logger.info("Could not find config for " + device);
      }
    }
  }

  private State resolveCommand(Method method, String data) {
    State cmd = null;
    if (method == Method.TURNON) {
      cmd = OnOffType.ON;
    } else if (method == Method.TURNOFF) {
      cmd = OnOffType.OFF;
    } else if (method == Method.DIM) {
      double value = ((Double.valueOf(data)) / 255);
      cmd = new PercentType((int) (value * 100));
    }
    return cmd;
  }

  private void sendToOpenHab(String itemName, State cmd) {
    eventPublisher.postUpdate(itemName, cmd);
  }

  class TellstickSensorEventHandler implements SensorListener {
    private Map<DataType, String> prevMessages = new HashMap<DataType, String>();

    private void handleSensorEvent(TellstickSensorEvent event, TellstickBindingConfig device) {

      double dValue = Double.valueOf(event.getData());
      TellstickValueSelector selector = device.getUsageSelector();
      if (selector == null) {
        selector = device.getValueSelector();
      }
      State cmd = getCommand(event, dValue, selector);
      sendToOpenHab(device.getItemName(), cmd);
    }

    private State getCommand(TellstickSensorEvent event, double dValue, TellstickValueSelector selector) {
      State cmd = null;
      if (event.getDataType() == DataType.TEMPERATURE) {
        switch (selector) {
        case MOTION:
          cmd = OnOffType.ON;
          break;
        default:
          cmd = new DecimalType(dValue);
        }
      } else if (event.getDataType() == DataType.HUMIDITY) {
        switch (selector) {
        case BATTERY_LEVEL:
          cmd = new DecimalType(dValue);
          break;
        case HUMIDITY:
        default:
          double val = Math.min(100, dValue);
          cmd = new PercentType((int) val);

        }
      }
      return cmd;
    }

    private TellstickValueSelector getSensorBindingType(DataType dataType) {
      TellstickValueSelector result = null;
      switch (dataType) {
      case TEMPERATURE:
        result = TellstickValueSelector.TEMPERATURE;
        break;
      case HUMIDITY:
        result = TellstickValueSelector.HUMIDITY;
        break;
      default:
        logger.warn("Sensor of type " + dataType + " not supported");
      }
      return result;
    }

    @Override
    public void onRequest(TellstickSensorEvent sensorEvent) {
      controller.setLastSend(System.currentTimeMillis());

      String thisMsg = sensorEvent.getProtocol() + sensorEvent.getModel() + sensorEvent.getSensorId()
          + sensorEvent.getData();
      String prevMessage = prevMessages.get(sensorEvent.getDataType());
      if (!thisMsg.equals(prevMessage)) {
        prevMessages.put(sensorEvent.getDataType(), thisMsg);
        TellstickBindingConfig device = findTellstickBindingConfig(sensorEvent.getSensorId(),
            getSensorBindingType(sensorEvent.getDataType()));
        logger.debug("Got sensorEvent for " + sensorEvent.getSensorId() + " name:" + device + " value:"
            + sensorEvent.getData());
        if (device != null) {
          handleSensorEvent(sensorEvent, device);
        }
      } else {
        logger.debug("Ignored message for " + sensorEvent.getSensorId() + " value:" + sensorEvent.getData());
      }
    }

  }

  @Override
  protected void execute() {
    long lastSend = controller.getLastSend();
    logger.trace("Check thread current idle ms " + (System.currentTimeMillis() - lastSend));
    if ((System.currentTimeMillis() - lastSend) > restartTimeout) {
      // RE-INIT
      resetTellstick();

    }
    if ((System.currentTimeMillis() - lastRefresh) > updateFromTellstickInterval) {
      refreshFromTellstick();
    }
  }

  private void refreshFromTellstick() {
    logger.trace("Update with telldus state");
    for (TellstickBindingProvider prov : providers) {
      for (String name : prov.getItemNames()) {
        TellstickDevice dev = prov.getDevice(name);
        if (dev != null) {
          Method method = Method.getMethodById(dev.getStatus());
          sendToOpenHab(name, resolveCommand(method, dev.getData()));
        }

      }
    }
    lastRefresh = System.currentTimeMillis();
  }

  private void resetTellstick() {
    logger.warn("Will do a reinit of listeners, no message received for " + restartTimeout / 1000 + " seconds");
    try {
      deRegisterListeners();
      logger.info("Listeners removed");
      resetTelldusProvider();
      logger.info("Telldus reset");
      registerListeners();
      logger.info("Listeners restarted");
    } catch (Exception e) {
      logger.error("Failed to reset listener", e);
    }
  }

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

  @Override
  protected String getName() {
    return "Telldus Sync Service";
  }
}
TOP

Related Classes of org.openhab.binding.tellstick.internal.TellstickBinding$TellstickDeviceEventHandler

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.