Package org.openhab.binding.iec6205621meter.internal

Source Code of org.openhab.binding.iec6205621meter.internal.Iec6205621MeterBinding

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

import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.openhab.binding.iec6205621meter.Iec6205621MeterBindingProvider;
import org.openhab.core.binding.AbstractActiveBinding;
import org.openhab.core.items.Item;
import org.openhab.core.library.items.NumberItem;
import org.openhab.core.library.items.StringItem;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.openmuc.j62056.DataSet;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* iec 62056-21 meter binding implementation
*
* @author Peter Kreutzer
* @author Günter Speckhofer
* @since 1.5.0
*/
public class Iec6205621MeterBinding extends
    AbstractActiveBinding<Iec6205621MeterBindingProvider> implements
    ManagedService {

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

  // regEx to validate a meter config
  // <code>'^(.*?)\\.(serialPort|baudRateChangeDelay|echoHandling)$'</code>
  private final Pattern METER_CONFIG_PATTERN = Pattern
      .compile("^(.*?)\\.(serialPort|baudRateChangeDelay|echoHandling)$");

  private static final long DEFAULT_REFRESH_INTERVAL = 60000;

  /**
   * the refresh interval which is used to poll values from the IEC 62056-21 Meter
   * server (optional, defaults to 10 minutes)
   */
  private long refreshInterval = DEFAULT_REFRESH_INTERVAL;

  // configured meter devices - keyed by meter device name
  private final Map<String, Meter> meterDeviceConfigurtions = new HashMap<String, Meter>();

  public Iec6205621MeterBinding() {
  }

  public void activate() {

  }

  public void deactivate() {
    meterDeviceConfigurtions.clear();
  }

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

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

  private final Meter createIec6205621MeterConfig(String name,
      MeterConfig config) {

    Meter reader = null;
    reader = new Meter(name, config);
    return reader;
  }

  /**
   * @{inheritDoc
   */
  @Override
  protected void execute() {
    // the frequently executed code (polling) goes here ...
    Map<String, Map<String, DataSet>> cache = new HashMap<String, Map<String,DataSet>>();
    for (Iec6205621MeterBindingProvider provider : providers) {

      for (String itemName : provider.getItemNames()) {
        for (Entry<String, Meter> entry : meterDeviceConfigurtions.entrySet()) {
          Meter reader = entry.getValue();
          String meterName = provider.getMeterName(itemName);
          if(meterName != null && meterName.equals(entry.getKey())) {
            Map<String, DataSet> dataSets;
            if((dataSets = cache.get(meterName)) == null) {
              if(logger.isDebugEnabled())
                logger.debug("Read meter: " + meterName + "; " + reader.getConfig().getSerialPort());
              dataSets = reader.read();
              cache.put(meterName, dataSets);
            }
            String obis = provider.getObis(itemName);
            if (obis != null && dataSets.containsKey(obis)) {
              DataSet dataSet = dataSets.get(obis);
              if(logger.isDebugEnabled())
                logger.debug("Updateing item " + itemName + " with OBIS code " + obis + " and value " + dataSet.getValue());
              Class<? extends Item> itemType = provider
                  .getItemType(itemName);
              if (itemType.isAssignableFrom(NumberItem.class)) {
                eventPublisher.postUpdate(itemName,
                    new DecimalType(dataSet.getValue()));
              }
              if (itemType.isAssignableFrom(StringItem.class)) {
                String value = dataSet.getValue();
                eventPublisher.postUpdate(itemName, new StringType(
                    value));
              }
            }
          }
        }
      }

    }
  }

  /**
   * @{inheritDoc
   */
  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!");
  }

  /**
   * @{inheritDoc
   */
  protected void internalReceiveUpdate(String itemName, State newState) {
    // the code being executed when a state 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!");
  }

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

    if (config == null || config.isEmpty()) {
      logger.warn("Empty or null configuration. Ignoring.");
      return;
    }

    Set<String> names = getNames(config);

    for (String name : names) {

      String value = (String) config.get(name + ".serialPort");
      String serialPort = value != null ? value
          : MeterConfig.DEFAULT_SERIAL_PORT;

      value = (String) config.get(name + ".baudRateChangeDelay");
      int baudRateChangeDelay = value != null ? Integer.valueOf(value)
          : MeterConfig.DEFAULT_BAUD_RATE_CHANGE_DELAY;

      value = (String) config.get(name + ".echoHandling");
      boolean echoHandling = value != null ? Boolean.valueOf(value)
          : MeterConfig.DEFAULT_ECHO_HANDLING;

      Meter meterConfig = createIec6205621MeterConfig(name,
          new MeterConfig(serialPort, baudRateChangeDelay,
              echoHandling));

      if (meterDeviceConfigurtions.put(meterConfig.getName(), meterConfig) != null) {
        logger.info("Recreated reader {} with  {}!", meterConfig.getName(),
            meterConfig.getConfig());
      } else {
        logger.info("Created reader {} with  {}!", meterConfig.getName(),
            meterConfig.getConfig());
      }
    }

    if (config != null) {
      // to override the default refresh interval one has to add a
      // parameter to openhab.cfg like
      // <bindingName>:refresh=<intervalInMs>
      if (StringUtils.isNotBlank((String) config.get("refresh"))) {
        refreshInterval = Long
            .parseLong((String) config.get("refresh"));
      }
      setProperlyConfigured(true);
    }
  }

  /**
   * Analyze configuration to get meter names
   *
   * @return set of String of meter names
   */
  private Set<String> getNames(Dictionary<String, ?> config) {
    Set<String> set = new HashSet<String>();

    Enumeration<String> keys = config.keys();
    while (keys.hasMoreElements()) {

      String key = (String) keys.nextElement();

      // the config-key enumeration contains additional keys that we
      // don't want to process here ...
      if ("service.pid".equals(key) || "refresh".equals(key)) {
        continue;
      }

      Matcher meterMatcher = METER_CONFIG_PATTERN.matcher(key);

      if (!meterMatcher.matches()) {
        logger.debug("given config key '"
            + key
            + "' does not follow the expected pattern '<meterName>.<serialPort|baudRateChangeDelay|echoHandling>'");
        continue;
      }

      meterMatcher.reset();
      meterMatcher.find();

      set.add(meterMatcher.group(1));
    }
    return set;
  }

}
TOP

Related Classes of org.openhab.binding.iec6205621meter.internal.Iec6205621MeterBinding

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.