package org.ulti.dev.powermeter.parse;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringReader;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Vector;
import org.apache.log4j.Logger;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.ulti.dev.powermeter.PowerEvent;
public class UWParse implements EventParser {
Logger _log = Logger.getLogger(this.getClass());
public Vector<PowerEvent> read(String fName) {
Vector<PowerEvent> events = new Vector<PowerEvent>();
// SAXBuilder builder = new SAXBuilder(false);
Document doc = null;
try {
File dataFile = new File(fName);
if (!dataFile.exists()) {
_log.error("File does not exist: " + dataFile.getAbsolutePath());
return null;
}
doc = parseFile(dataFile);
// doc = builder.build(dataFile);
@SuppressWarnings("unchecked")
List<Element> children = doc.getRootElement().getChildren();
// format of XML being parsed; note: timestamp is not embedded in the record (although it should be)
// <timestamp>2011-01-11 00:00:04.837241</timestamp>
// <msg>
// <src>CC128-v0.15</src>
// <dsb>00003</dsb>
// <time>23:58:01</time>
// <tmprF>63.0</tmprF>
// <sensor>0</sensor>
// <id>00077</id>
// <type>1</type>
// <ch1><watts>00464</watts></ch1>
// <ch2><watts>00090</watts></ch2>
// </msg>
Date lastDate = null;
int histCount = 0;
for (int i = 0; i < children.size() - 1;) {
Element timeElement = children.get(i);
Element msgElement = children.get(i + 1);
if (!timeElement.getName().equals("timestamp")) {
throw new RuntimeException("Malformed event file");
}
if (!msgElement.getName().equals("msg")) {
throw new RuntimeException("Malformed event file");
}
i = i + 2;
String format = "yyyy-MM-dd' 'HH:mm:ss";
SimpleDateFormat sdf = new SimpleDateFormat(format);
String dateString = timeElement.getText();
// chop off miliseconds; these were screwing up the date parsing
dateString = dateString.substring(0, dateString.indexOf('.'));
String dateStringBack = sdf.format(sdf.parse(dateString));
if (!dateString.equals(dateStringBack)) {
throw new RuntimeException("Error parsing date string: " + dateString + " != " + dateStringBack);
}
Date recordedDate = sdf.parse(dateString);
if (msgElement.getChild("hist") == null) {
try {
int ch1 = Integer.parseInt(msgElement.getChild("ch1").getChild("watts").getText());
int ch2 = Integer.parseInt(msgElement.getChild("ch2").getChild("watts").getText());
int watts = ch1 + ch2;
if (lastDate != null) {
// drop the first measurement (just makes things simpler although it costs data point)
double kw = (double) watts / (double) 1000;
long seconds = (recordedDate.getTime() - lastDate.getTime()) / 1000;
double hourFraction = (double) seconds / (double) 3600;
double kwh = kw * hourFraction;
_log.trace("watts: " + watts + " seconds: " + seconds + " hour fraction: " + hourFraction + " kwh: " + kwh);
_log.debug("Date: " + dateString + " Watts: " + watts + " kwh: " + kwh);
PowerEvent event = new PowerEvent(lastDate, recordedDate, kwh);
events.add(event);
}
lastDate = recordedDate;
} catch (Exception e) {
_log.warn("Parse error in: " + fName + " - " + e);
}
} else {
// drop these hist events
histCount++;
}
}
_log.info("UWParse::read( " + fName + " ) - good parse; event size: " + events.size() + " hist size: " + histCount);
} catch (ParseException pe) {
_log.error(pe);
}
return events;
}
private Document parseFile(File dataFile) {
SAXBuilder builder = new SAXBuilder(false);
Document doc = null;
try {
doc = builder.build(dataFile);
} catch (JDOMException e) {
_log.info("Failed to parse; take one more chance");
doc = parseFileWithoutRoot(dataFile);
} catch (IOException ioe) {
_log.error("UWParse::parseFile( " + dataFile.getAbsolutePath() + " ) - " + ioe);
}
return doc;
}
private Document parseFileWithoutRoot(File dataFile) {
_log.info("UWParse::parseDocWitoutRoot( " + dataFile.getAbsolutePath() + " )");
Document doc = null;
try {
StringBuffer fileData = new StringBuffer(1000);
BufferedReader reader = new BufferedReader(new FileReader(dataFile));
char[] buf = new char[1024];
int numRead = 0;
while ((numRead = reader.read(buf)) != -1) {
fileData.append(buf, 0, numRead);
}
reader.close();
fileData.insert(0, "<root>");
fileData.append("</root>");
SAXBuilder builder = new SAXBuilder(false);
doc = builder.build(new StringReader(fileData.toString()));
if (doc != null) {
_log.info("UWParse::parseDocWitoutRoot( .. ) - good parse!");
} else {
_log.info("UWParse::parseDocWitoutRoot( .. ) - not successful");
}
} catch (JDOMException jdome) {
_log.error("UWParse::parseFileWithoutRoot( " + dataFile.getAbsolutePath() + " ) - " + jdome);
} catch (IOException ioe) {
_log.error("UWParse::parseFileWithoutRoot( " + dataFile.getAbsolutePath() + " ) - " + ioe);
}
return doc;
}
}