Package org.openhab.binding.openenergymonitor.internal

Source Code of org.openhab.binding.openenergymonitor.internal.OpenEnergyMonitorBinding

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

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

import javax.xml.bind.DatatypeConverter;

import net.astesana.javaluator.DoubleEvaluator;

import org.apache.commons.lang.StringUtils;
import org.openhab.binding.openenergymonitor.OpenEnergyMonitorBindingProvider;
import org.openhab.binding.openenergymonitor.protocol.OpenEnergyMonitorConnector;
import org.openhab.binding.openenergymonitor.protocol.OpenEnergyMonitorDataParser;
import org.openhab.binding.openenergymonitor.protocol.OpenEnergyMonitorParserRule;
import org.openhab.binding.openenergymonitor.protocol.OpenEnergyMonitorSerialConnector;
import org.openhab.binding.openenergymonitor.protocol.OpenEnergyMonitorSimulator;
import org.openhab.binding.openenergymonitor.protocol.OpenEnergyMonitorUDPConnector;
import org.openhab.core.binding.AbstractBinding;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.transform.TransformationException;
import org.openhab.core.transform.TransformationHelper;
import org.openhab.core.transform.TransformationService;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
*
* Binding to receive data from Open Energy Monitor devices.
*
* @author Pauli Anttila
* @since 1.4.0
*/
public class OpenEnergyMonitorBinding extends
    AbstractBinding<OpenEnergyMonitorBindingProvider> implements
    ManagedService {

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

  /* configuration variables for communication */
  private int udpPort = 9997;
  private String serialPort = null;
  private boolean simulate = false;

  private OpenEnergyMonitorDataParser dataParser = null;

  /** Thread to handle messages from Open Energy Monitor devices */
  private MessageListener messageListener = null;

  public OpenEnergyMonitorBinding() {
  }

  public void activate() {
    logger.debug("Activate");
  }

  public void deactivate() {
    logger.debug("Deactivate");
    messageListener.setInterrupted(true);
  }

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

    if (config != null) {

      HashMap<String, OpenEnergyMonitorParserRule> parsingRules = new HashMap<String, OpenEnergyMonitorParserRule>();

      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)) {
          continue;
        }

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

        if ("udpPort".equals(key)) {
          if (StringUtils.isNotBlank(value)) {
            udpPort = Integer.parseInt(value);
          }
        } else if ("serialPort".equals(key)) {
          serialPort = value;
        } else if ("simulate".equals(key)) {
          if (StringUtils.isNotBlank(value)) {
            simulate = Boolean.parseBoolean(value);
          }
        } else {

          // process all data parsing rules
          try {
            OpenEnergyMonitorParserRule rule = new OpenEnergyMonitorParserRule(value);
            parsingRules.put(key, rule);
          } catch (OpenEnergyMonitorException e) {
            throw new ConfigurationException(key, "invalid parser rule", e);
          }
        }

      }

      if (parsingRules != null) {

        dataParser = new OpenEnergyMonitorDataParser(parsingRules);
      }
     
      if (messageListener != null) {

        logger.debug("Close previous message listener");

        messageListener.setInterrupted(true);
        try {
          messageListener.join();
        } catch (InterruptedException e) {
          logger.info("Previous message listener closing interrupted", e);
        }
      }
     
      messageListener = new MessageListener();
      messageListener.start();
    }
  }

  /**
   * The MessageListener runs as a separate thread.
   *
   * Thread listening message from Open Energy Monitoring devices and send
   * updates to openHAB bus.
   *
   */
  private class MessageListener extends Thread {

    private boolean interrupted = false;

    MessageListener() {
    }

    public void setInterrupted(boolean interrupted) {
      this.interrupted = interrupted;
      messageListener.interrupt();
    }

    @Override
    public void run() {

      logger.debug("Open Energy Monitor message listener started");

      OpenEnergyMonitorConnector connector;

      if (simulate == true)
        connector = new OpenEnergyMonitorSimulator();
      else if (serialPort != null)
        connector = new OpenEnergyMonitorSerialConnector(serialPort);
      else
        connector = new OpenEnergyMonitorUDPConnector(udpPort);

      try {
        connector.connect();
      } catch (OpenEnergyMonitorException e) {
        logger.error(
            "Error occured when connecting to Open Energy Monitor device",
            e);

        logger.warn("Closing Open Energy Monitor message listener");

        // exit
        interrupted = true;
      }

      // as long as no interrupt is requested, continue running
      while (!interrupted) {

        try {
          // Wait a packet (blocking)
          byte[] data = connector.receiveDatagram();

          logger.trace("Received data (len={}): {}", data.length,
              DatatypeConverter.printHexBinary(data));

          HashMap<String, Number> vals = dataParser.parseData(data);

          for (OpenEnergyMonitorBindingProvider provider : providers) {
            for (String itemName : provider.getItemNames()) {

              for (Entry<String, Number> entry : vals.entrySet()) {
                String key = entry.getKey();
                Number value = entry.getValue();

                if (key != null && value != null) {

                  boolean found = false;

                  org.openhab.core.types.State state = null;

                  String variable = provider.getVariable(itemName);

                  if (variable.equals(key)) {
                    state = new DecimalType(value.doubleValue());
                    found = true;

                  } else if (variable.contains(key) && variable.matches(".*[+-/*^%].*")) {
                    logger.debug("Eval key={}, variable={}", key, variable);

                    String tmp = replaceVariables(vals, variable);
                   
                    try {
                      double result = new DoubleEvaluator().evaluate(tmp);
                      logger.debug("Eval '{}={}={}'", variable, tmp, result);
                      state = new DecimalType(result);
                      found = true;

                    } catch (Exception e) {
                      logger.error(
                          "Error occured during data evaluation",
                          e);
                    }
                  }

                  if (found) {

                    state = transformData(
                        provider.getTransformationType(itemName),
                        provider.getTransformationFunction(itemName),
                        state);

                    if (state != null) {
                      eventPublisher.postUpdate(itemName, state);
                      break;
                    }

                  }

                }
              }
            }

          }

        } catch (OpenEnergyMonitorException e) {

          logger.error(
              "Error occured when received data from Open Energy Monitor device",
              e);
        }
      }

      try {
        connector.disconnect();
      } catch (OpenEnergyMonitorException e) {
        logger.error(
            "Error occured when disconnecting form Open Energy Monitor device",
            e);
      }

    }

  }

  private String replaceVariables(HashMap<String, Number> vals,
      String variable) {
    for (Entry<String, Number> entry : vals.entrySet()) {
      String key = entry.getKey();
      Object value = entry.getValue();

      variable = variable.replace(key, String.valueOf(value));

    }

    return variable;
  }

  /**
   * Transform received data by Transformation service.
   *
   */
  protected org.openhab.core.types.State transformData(
      String transformationType, String transformationFunction,
      org.openhab.core.types.State data) {
   
    if (transformationType != null && transformationFunction != null) {
      String transformedResponse = null;

      try {
        TransformationService transformationService = TransformationHelper
            .getTransformationService(
                OpenEnergyMonitorActivator.getContext(),
                transformationType);
        if (transformationService != null) {
          transformedResponse = transformationService.transform(
              transformationFunction, String.valueOf(data));
        } else {
          logger.warn(
              "couldn't transform response because transformationService of type '{}' is unavailable",
              transformationType);
        }
      } catch (TransformationException te) {
        logger.error(
            "transformation throws exception [transformation type="
                + transformationType
                + ", transformation function="
                + transformationFunction + ", response=" + data
                + "]", te);
      }

      logger.debug("transformed response is '{}'", transformedResponse);

      if (transformedResponse != null) {
        return new DecimalType(transformedResponse);
      }
    }

    return data;
  }
}
TOP

Related Classes of org.openhab.binding.openenergymonitor.internal.OpenEnergyMonitorBinding

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.