Package org.ulti.dev.powermeter

Source Code of org.ulti.dev.powermeter.PowerMeterActions

package org.ulti.dev.powermeter;

import java.io.File;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.Vector;

import org.apache.log4j.Logger;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.output.XMLOutputter;
import org.ulti.dev.powermeter.parse.EventParser;
import org.ulti.dev.powermeter.util.Client;
import org.ulti.dev.powermeter.util.RFC3339DateFormat;

public class PowerMeterActions {

  static public enum VariableType {
    CUMULATIVE, DURATIONAL;
  }

  private final static String BASE_URL = "https://www.google.com/powermeter/feeds/";
  private String _authToken = null;
  PowerMeterConfig _config = new PowerMeterConfig();

  private Logger _log = Logger.getLogger(this.getClass());

  private String _userId = null;

  private String _variable = null;

  public PowerMeterActions() {
    _authToken = _config.getToken(); // getProperties().getProperty("token");
    _userId = _config.getUser();// getProperties().getProperty("user");
    _variable = _config.getVariable(); // getProperties().getProperty("variable");
  }

  public void createNewVariable(String varId, String description, String title, String location, VariableType varKind) {
    String url = makeUserUrl() + "/variable";
    _log.info("URL:" + url);

    Client http = new Client();

    http.addHeader("Authorization", "AuthSub token=\"" + _authToken + "\"");
    http.setContentType("application/atom+xml");

    String uploadString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
        + "  <entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:meter=\"http://schemas.google.com/meter/2008\">" + "    <meter:variableId>"
        + varId + "</meter:variableId>" + "    <title>" + title + "</title>" + "    <content type=\"text\">" + description + "</content>"
        + "    <meter:location>" + location + "</meter:location> " + "    <meter:type>electricity_consumption</meter:type>"
        + "    <meter:unit>kW h</meter:unit>";

    if (varKind.name().equals(VariableType.CUMULATIVE.name())) {
      uploadString += "<meter:cumulative/>";
    } else if (varKind.name().equals(VariableType.DURATIONAL.name())) {
      uploadString += "<meter:durational/>";
    } else {
      throw new IllegalArgumentException("Unknown kind: " + varKind);
    }

    uploadString += "</entry>";

    String res = http.postToString(url, uploadString);

    if (http.getResult() < 200 || http.getResult() > 210) {
      _log.error("Error POST: code=" + http.getResult() + "\n" + res);

      _log.error("POST error");
      _log.error("url=" + url);
      _log.error("data:\n" + uploadString);
    } else {
      _log.info("POST Success; you might want to check the results to be certain though.");
    }

    System.out.println("res: " + res);
  }

  /**
   * Get a list of the variable for this account from the server.
   */
  public void getList() {
    _log.info("PowerMeterActions::getList()");
    Client http = new Client();

    String url = makeUserUrl() + "/variable";
    _log.info("URL:" + url);

    http.addHeader("Authorization", "AuthSub token=\"" + _authToken + "\"");
    http.setContentType("application/atom+xml");
    String res = http.getToString(url);

    if (http.getResult() < 200 || http.getResult() > 210) {
      System.err.println("ERROR POST: code=" + http.getResult() + "\n" + res);

      _log.error("POST request error !");
      _log.error("url=" + url);
    }

    System.out.println("result: " + res);

    // List<String> variableIds=Regex.regexFindAll( res, "<meter:variableId>([^<]*)</meter:variableId>");
    // for( String varId : variableIds ) {
    // log.info( "variable: '"+varId+"'");
    // }
  }

  private String makeUserUrl() {
    return BASE_URL + "user/" + _userId + "/" + _userId;
  }

  private boolean post(String url, String data) {
    Client http = new Client();

    _log.info("PowerMeterActions::post( " + url + ", ... )");

    http.addHeader("Authorization", "AuthSub token=\"" + _authToken + "\"");
    http.setContentType("application/atom+xml");

    _log.trace("POSTing data: " + data);

    Document res = http.postToXML(url, data);

    if (http.getResult() < 200 || http.getResult() > 210) {
      _log.error("POST Error - code=" + http.getResult() + ", " + res);

      _log.error("POST error");
      _log.error("url=" + url);
      _log.error("data:\n" + data);
      return false;
    } else {

      String titleText = "";
      boolean hasError = true;

      try {
        // Check for an error message; may fire an exception looking for the error title (if the document
        // doesn't have an error)

        Namespace atomNS = res.getRootElement().getNamespace();
        Element entryElement = res.getRootElement().getChild("entry", res.getRootElement().getNamespace());
        Element root = res.getRootElement();
        titleText = entryElement.getChild("title", atomNS).getText();
        if ("Error".equals(titleText)) {
          XMLOutputter xmlo = new XMLOutputter();
          _log.error("POST was successful; ERROR returned from Google PowerMeter: " + xmlo.outputString(res));
          return false;
        }
      } catch (Exception e) {
        // exception probably means error parsing for error (aka no error found)
        hasError = false;
      }
      if (!hasError) {
        _log.info("POST Success");
        return true;
      }

    }

    _log.debug("POST result: " + res);
    return true;
  }

  /**
   * Uploads a set of power events to the server 1000 at a time.
   *
   * @param events
   */
  public void uploadDurationData(Vector<PowerEvent> events) {
    _log.info("PowerMeterActions::uploadDurationData( .. )");

    String preamble = "<feed xmlns=\"http://www.w3.org/2005/Atom\" xmlns:meter=\"http://schemas.google.com/meter/2008\" xmlns:batch=\"http://schemas.google.com/gdata/batch\">";
    String post = "</feed>";

    String uploadString = "";

    // uploadString += preamble;

    // https://www.google.com/powermeter/feeds/user/01266859867152863645/01266859867152863645/variable/currentcost.envi.MyEnvi.d1

    String subject = makeUserUrl() + "/variable/" + _variable;
    String url = BASE_URL + "event";

    RFC3339DateFormat idf = new RFC3339DateFormat();

    int counter = 0;
    for (PowerEvent event : events) {

      String eventString = "";

      Namespace meterNS = Namespace.getNamespace("meter", "http://schemas.google.com/meter/2008");
      Element meterElement = new Element("entry");
      meterElement.addNamespaceDeclaration(meterNS);

      Element categoryElement = new Element("category");
      categoryElement.setAttribute("scheme", "http://schemas.google.com/g/2005#kind");
      categoryElement.setAttribute("term", "http://schemas.google.com/meter/2008#durMeasurement");

      Element subjectElement = new Element("subject", meterNS);
      subjectElement.setText(subject);

      Element startElement = new Element("startTime", meterNS);
      startElement.setAttribute("uncertainty", "1.0");
      startElement.setText(idf.format(event.getStart()));

      Element endElement = new Element("endTime", meterNS);
      endElement.setAttribute("uncertainty", "1.0");
      endElement.setText(idf.format(event.getEnd()));

      Element quantityElement = new Element("quantity", meterNS);
      quantityElement.setAttribute("uncertainty", "0.001");
      quantityElement.setAttribute("unit", "kW h");
      quantityElement.setText(event.getQuantity() + "");

      meterElement.addContent(categoryElement);
      meterElement.addContent(subjectElement);
      meterElement.addContent(startElement);
      meterElement.addContent(endElement);
      meterElement.addContent(quantityElement);

      XMLOutputter xmlo = new XMLOutputter();
      eventString = xmlo.outputString(meterElement);

      uploadString += eventString;

      counter++;

      if (counter >= 500) {
        uploadString = preamble + uploadString;
        uploadString += post;
        boolean success = post(url, uploadString);

        if (success) {
          // _config.setLastUploadDate(event.getStart());
          if (events.lastElement().getStart().after(_newestUpload)) {
            _newestUpload = events.lastElement().getStart();
          }
        }

        uploadString = "";
        counter = 0;
      }

    }

    if (events.size() > 0 && uploadString.length() > 0) {
      uploadString += post;
      boolean success = post(url, uploadString);
      if (success) {
        if (events.lastElement().getStart().after(_newestUpload)) {
          _newestUpload = events.lastElement().getStart();
        }
      }
    }

    _log.info("PowerMeterActions::uploadDurrationalData( .. ) - complete.");
  }

  @SuppressWarnings("deprecation")
  private Date _newestUpload = new Date(0, 0, 0);

  public void uploadInstanceData(Vector<PowerEvent> events) {
    _log.info("PowerMeterActions::uploadInstanceData( .. )");

    String preamble = "<feed xmlns=\"http://www.w3.org/2005/Atom\" xmlns:meter=\"http://schemas.google.com/meter/2008\" xmlns:batch=\"http://schemas.google.com/gdata/batch\">";
    String post = "</feed>";

    String url = BASE_URL + "event";

    String uploadString = "";

    String subject = makeUserUrl() + "/variable/" + _variable;

    int counter = 0;
    for (PowerEvent event : events) {
      String eventString = "";

      Namespace meterNS = Namespace.getNamespace("meter", "http://schemas.google.com/meter/2008");
      Element meterElement = new Element("entry");
      meterElement.addNamespaceDeclaration(meterNS);

      Element categoryElement = new Element("category");
      categoryElement.setAttribute("scheme", "http://schemas.google.com/g/2005#kind");
      categoryElement.setAttribute("term", "http://schemas.google.com/meter/2008#instMeasurement");

      Element subjectElement = new Element("subject", meterNS);
      subjectElement.setText(subject);

      Element occurElement = new Element("occurTime", meterNS);
      occurElement.setAttribute("uncertainty", "1.0");
      occurElement.setText(new RFC3339DateFormat().format(event.getStart()));

      Element quantityElement = new Element("quantity", meterNS);
      quantityElement.setAttribute("uncertainty", "0.001");
      quantityElement.setAttribute("unit", "kW h");
      quantityElement.setText(event.getQuantity() + "");

      meterElement.addContent(categoryElement);
      meterElement.addContent(subjectElement);
      meterElement.addContent(occurElement);
      meterElement.addContent(quantityElement);

      XMLOutputter xmlo = new XMLOutputter();
      eventString = xmlo.outputString(meterElement);

      uploadString += eventString;

      counter++;

      if (counter >= 500) {
        uploadString = preamble + uploadString;
        uploadString += post;
        boolean success = post(url, uploadString);

        if (success) {
          // _config.setLastUploadDate(event.getStart());
          if (events.lastElement().getStart().after(_newestUpload)) {
            _newestUpload = events.lastElement().getStart();
          }
        }

        uploadString = "";
        counter = 0;
      }
    }

    if (events.size() > 0 && uploadString.length() > 0) {
      uploadString += post;
      boolean success = post(url, uploadString);
      if (success) {
        if (events.lastElement().getStart().after(_newestUpload)) {
          _newestUpload = events.lastElement().getStart();
        }
      }
    }

    _log.info("PowerMeterActions::uploadInstanceData( .. ) - complete.");
  }

  public void saveConfig() {
    _config.setLastUploadDate(_newestUpload);
    _config.saveConfig();
  }

  PowerMeterConfig getConfig() {
    return _config;
  }

  Vector<PowerEvent> parse(String fName) {
    _log.info("PowerMeterActions::parse( " + fName + " )");

    if (!new File(fName).exists()) {
      throw new RuntimeException("Cannot parse: " + new File(fName).getAbsolutePath() + ", file does not exist");
    }

    String parserName = _config.getParser();
    EventParser parser = null;
    try {
      @SuppressWarnings("unchecked")
      Class<EventParser> classDefinition = (Class<EventParser>) Class.forName(parserName);
      parser = classDefinition.newInstance();
    } catch (ClassCastException cce) {
      _log.error(cce);
    } catch (InstantiationException ie) {
      _log.error(ie);
    } catch (IllegalAccessException iae) {
      _log.error(iae);
    } catch (ClassNotFoundException cnfe) {
      _log.error(cnfe);
    }

    if (parser == null) {
      String msg = "Could not instantiate parser; please add eventParser property to config.properties";
      _log.fatal(msg);
      throw new RuntimeException(msg);
    }

    Vector<PowerEvent> events = parser.read(fName);

    Collections.sort(events, new Comparator<PowerEvent>() {
      @Override
      public int compare(PowerEvent arg0, PowerEvent arg1) {
        return arg0.getStart().compareTo(arg1.getStart());
      }
    });

    // purge events listed before the last upload
    Date lastUpload = _config.getLastUploadDate();

    _log.info("# events: " + events.size() + " lastUpload date: " + lastUpload);
    Iterator<PowerEvent> eventIterator = events.iterator();
    while (eventIterator.hasNext()) {
      PowerEvent event = eventIterator.next();

      _log.trace(event.toString());

      if (event.getStart().before(lastUpload)) {
        eventIterator.remove();
      }
    }

    _log.info("# events after pruning with last upload date: " + events.size());

    return events;
  }
}
TOP

Related Classes of org.ulti.dev.powermeter.PowerMeterActions

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.