Package org.openhab.binding.homematic.internal.communicator

Source Code of org.openhab.binding.homematic.internal.communicator.StateHolder

/**
* 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.homematic.internal.communicator;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.openhab.binding.homematic.internal.common.HomematicContext;
import org.openhab.binding.homematic.internal.communicator.ProviderItemIterator.ProviderItemIteratorCallback;
import org.openhab.binding.homematic.internal.communicator.client.BaseHomematicClient.HmValueItemIteratorCallback;
import org.openhab.binding.homematic.internal.communicator.client.HomematicClientException;
import org.openhab.binding.homematic.internal.config.binding.DatapointConfig;
import org.openhab.binding.homematic.internal.config.binding.HomematicBindingConfig;
import org.openhab.binding.homematic.internal.converter.state.Converter;
import org.openhab.binding.homematic.internal.model.HmRssiInfo;
import org.openhab.binding.homematic.internal.model.HmValueItem;
import org.openhab.core.items.Item;
import org.openhab.core.types.State;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Class which (re-)loads and holds the cached values from a Homematic server.
*
* @author Gerhard Riegler
* @since 1.5.0
*/

public class StateHolder {
  private static final Logger logger = LoggerFactory.getLogger(StateHolder.class);

  private HomematicContext context;

  private ExecutorService reloadExecutorPool;

  private boolean datapointReloadInProgress = false;
  private Map<HomematicBindingConfig, Object> refreshCache = new HashMap<HomematicBindingConfig, Object>();
  private Map<HomematicBindingConfig, HmValueItem> datapoints = new HashMap<HomematicBindingConfig, HmValueItem>();
  private Map<HomematicBindingConfig, HmValueItem> variables = new HashMap<HomematicBindingConfig, HmValueItem>();

  public StateHolder(HomematicContext context) {
    this.context = context;
  }

  /**
   * If a datapoint reload is currently running, this returns true.
   */
  public boolean isDatapointReloadInProgress() {
    return datapointReloadInProgress;
  }

  /**
   * A datapoint reload takes some seconds, this method is called when a event
   * receives from the Homematic server during the reload.
   */
  public void addToRefreshCache(HomematicBindingConfig bindingConfig, Object value) {
    refreshCache.put(bindingConfig, value);
  }

  /**
   * Returns the cached HmValueItem.
   */
  public HmValueItem getState(HomematicBindingConfig bindingConfig) {
    HmValueItem hmValueItem = datapoints.get(bindingConfig);
    if (hmValueItem == null) {
      hmValueItem = variables.get(bindingConfig);
    }
    return hmValueItem;
  }

  /**
   * Loads all datapoints from the Homematic server, only executed at startup.
   */
  public void loadDatapoints() throws HomematicClientException {
    logger.info("Loading Homematic datapoints");
    context.getHomematicClient().iterateAllDatapoints(new HmValueItemIteratorCallback() {

      @Override
      public void iterate(HomematicBindingConfig bindingConfig, HmValueItem hmValueItem) {
        datapoints.put(bindingConfig, hmValueItem);
      }
    });
    logger.info("Finished loading {} Homematic datapoints", datapoints.size());
  }

  /**
   * Reloads all datapoints from the Homematic server and publishes only
   * changed values to the openHAB bus.
   */
  public void reloadDatapoints() {
    reloadExecutorPool.execute(new Runnable() {

      @Override
      public void run() {

        try {
          logger.debug("Reloading Homematic server datapoints");
          datapointReloadInProgress = true;
          context.getHomematicClient().iterateAllDatapoints(new HmValueItemIteratorCallback() {
            @Override
            public void iterate(HomematicBindingConfig bindingConfig, HmValueItem hmValueItem) {
              if (!datapoints.containsKey(bindingConfig)) {
                logger.info("Adding new {}", bindingConfig);
                datapoints.put(bindingConfig, hmValueItem);
              } else {
                Object cachedValue = refreshCache.get(bindingConfig);
                if (cachedValue != null) {
                  logger.debug("Value changed while refreshing from '{}' to '{}' for binding {}",
                      hmValueItem.getValue(), cachedValue, bindingConfig);
                  hmValueItem.setValue(cachedValue);
                }

                if (hasChanged(bindingConfig, datapoints.get(bindingConfig), hmValueItem)) {
                  datapoints.put(bindingConfig, hmValueItem);
                  publish(bindingConfig, hmValueItem);
                }
              }
            }
          });
          logger.debug("Finished reloading {} Homematic server datapoints", datapoints.size());
        } catch (HomematicClientException ex) {
          logger.error(ex.getMessage(), ex);
        } finally {
          datapointReloadInProgress = false;
          refreshCache.clear();
        }

      }
    });
  }

  /**
   * Reloads all RSSI values from the Homematic server and publishes only
   * changed values to the openHAB bus.
   */
  public void reloadRssi() {
    reloadExecutorPool.execute(new Runnable() {

      @Override
      public void run() {
        try {
          logger.debug("Reloading Homematic server RSSI values");
          Map<String, HmRssiInfo> rssiList = context.getHomematicClient().getRssiInfo();
          for (String address : rssiList.keySet()) {
            HmRssiInfo rssiInfo = rssiList.get(address);
            updateRssiInfo(new DatapointConfig(address, "0", "RSSI_DEVICE"), rssiInfo.getDevice());
            updateRssiInfo(new DatapointConfig(address, "0", "RSSI_PEER"), rssiInfo.getPeer());
          }
          logger.debug("Finished reloading {} Homematic server RSSI values", rssiList.size());
        } catch (HomematicClientException ex) {
          logger.error(ex.getMessage(), ex);
        }
      }
    });
  }

  /**
   * Upates the RSSI datapoint if available.
   */
  private void updateRssiInfo(DatapointConfig bindingConfig, Integer rssiValue) {
    HmValueItem valueItem = datapoints.get(bindingConfig);
    if (valueItem != null) {
      if (!valueItem.getValue().equals(rssiValue)) {
        logger.debug("Value changed from '{}' to '{}' for binding {}",
            valueItem == null ? "null" : valueItem.getValue(), rssiValue, bindingConfig);
        valueItem.setValue(rssiValue);
        publish(bindingConfig, valueItem);
      }
    } else {
      logger.debug("Rssi info not found: {}", bindingConfig);
    }
  }

  /**
   * Loads all variables from the Homematic server, only executed at startup.
   */
  public void loadVariables() throws HomematicClientException {
    if (context.getHomematicClient().supportsVariables()) {
      logger.info("Loading Homematic Server variables");

      context.getHomematicClient().iterateAllVariables(new HmValueItemIteratorCallback() {

        @Override
        public void iterate(HomematicBindingConfig bindingConfig, HmValueItem variable) {
          variables.put(bindingConfig, variable);
        }
      });
      logger.info("Finished loading {} Homematic server variables", variables.size());
    }
  }

  /**
   * Reloads all variables from the Homematic server and publishes only
   * changed values to the openHAB bus.
   */
  public void reloadVariables() {
    if (context.getHomematicClient().supportsVariables()) {

      reloadExecutorPool.execute(new Runnable() {

        @Override
        public void run() {
          logger.debug("Reloading Homematic server variables");

          try {
            context.getHomematicClient().iterateAllVariables(new HmValueItemIteratorCallback() {

              @Override
              public void iterate(HomematicBindingConfig bindingConfig, HmValueItem variable) {
                if (hasChanged(bindingConfig, variables.get(bindingConfig), variable)) {
                  variables.put(bindingConfig, variable);
                  publish(bindingConfig, variable);
                }
              }
            });
            logger.debug("Finished reloading {} Homematic server variables", variables.size());
          } catch (HomematicClientException ex) {
            logger.error(ex.getMessage(), ex);
          }
        }
      });
    }
  }

  /**
   * Initializes the stateholder by creating a new executor pool.
   */
  public void init() {
    reloadExecutorPool = Executors.newCachedThreadPool();
  }

  /**
   * Destroys the cache.
   */
  public void destroy() {
    datapointReloadInProgress = false;
    if (reloadExecutorPool != null) {
      reloadExecutorPool.shutdownNow();
      reloadExecutorPool = null;
    }
    datapoints.clear();
    variables.clear();
  }

  /**
   * Returns true if the cached value is not up to date.
   */
  protected boolean hasChanged(HomematicBindingConfig bindingConfig, HmValueItem parentHmValueItem,
      HmValueItem hmValueItem) {
    if (parentHmValueItem == null
        || (parentHmValueItem != null && !parentHmValueItem.getValue().equals(hmValueItem.getValue()))) {
      logger.debug("Value changed from '{}' to '{}' for binding {}", parentHmValueItem == null ? "null"
          : parentHmValueItem.getValue(), hmValueItem.getValue(), bindingConfig);
      return true;
    }
    return false;
  }

  /**
   * Iterate through all items and publishes the state.
   */
  protected void publish(final HomematicBindingConfig bindingConfig, final HmValueItem hmValueItem) {
    new ProviderItemIterator().iterate(bindingConfig, new ProviderItemIteratorCallback() {

      @Override
      public void next(HomematicBindingConfig providerBindingConfig, Item item, Converter<?> converter) {
        State state = converter.convertFromBinding(hmValueItem);
        context.getEventPublisher().postUpdate(item.getName(), state);
      }
    });
  }
}
TOP

Related Classes of org.openhab.binding.homematic.internal.communicator.StateHolder

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.