This commit is contained in:
parent
a781083e20
commit
0ff662a8b5
13 changed files with 1534 additions and 0 deletions
258
java/dalelane/currentcost/CurrentCostHistory.java
Normal file
258
java/dalelane/currentcost/CurrentCostHistory.java
Normal file
|
@ -0,0 +1,258 @@
|
|||
package dalelane.currentcost;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import dalelane.currentcost.calendar.DayData;
|
||||
import dalelane.currentcost.calendar.HourData;
|
||||
import dalelane.currentcost.calendar.MonthData;
|
||||
import dalelane.currentcost.calendar.YearData;
|
||||
|
||||
/*
|
||||
* A CurrentCost update (as described in CurrentCostUpdate) is a relative
|
||||
* description of your electricity usage.
|
||||
*
|
||||
* E.g. you used this much electricity 2 hours ago
|
||||
*
|
||||
* This class converts this into an absolute description of your electricity
|
||||
* usage.
|
||||
*
|
||||
* E.g. you used this much electricity at 1pm
|
||||
*
|
||||
*
|
||||
* Dale Lane (http://dalelane.co.uk/blog)
|
||||
*/
|
||||
|
||||
public class CurrentCostHistory {
|
||||
|
||||
public CurrentCostUpdate update;
|
||||
|
||||
public Hashtable<YearData, Integer> yearDataCollection = new Hashtable<YearData, Integer>();
|
||||
public Hashtable<MonthData, Integer> monthDataCollection = new Hashtable<MonthData, Integer>();
|
||||
public Hashtable<DayData, Integer> dayDataCollection = new Hashtable<DayData, Integer>();
|
||||
public Hashtable<HourData, Float> hourDataCollection = new Hashtable<HourData, Float>();
|
||||
|
||||
|
||||
public void UpdateData(CurrentCostUpdate datasource)
|
||||
{
|
||||
// --- YEARS ----------------------------------
|
||||
YearData y1 = YearData.GetOldDate(datasource.TimeStamp, 1);
|
||||
yearDataCollection.put(y1, datasource.WattsYear1);
|
||||
|
||||
YearData y2 = YearData.GetOldDate(datasource.TimeStamp, 2);
|
||||
yearDataCollection.put(y2, datasource.WattsYear2);
|
||||
|
||||
YearData y3 = YearData.GetOldDate(datasource.TimeStamp, 3);
|
||||
yearDataCollection.put(y3, datasource.WattsYear3);
|
||||
|
||||
YearData y4 = YearData.GetOldDate(datasource.TimeStamp, 4);
|
||||
yearDataCollection.put(y4, datasource.WattsYear4);
|
||||
|
||||
// --- MONTHS ---------------------------------
|
||||
MonthData m1 = MonthData.GetOldDate(datasource.TimeStamp, 1);
|
||||
monthDataCollection.put(m1, datasource.WattsMonth01);
|
||||
|
||||
MonthData m2 = MonthData.GetOldDate(datasource.TimeStamp, 2);
|
||||
monthDataCollection.put(m2, datasource.WattsMonth02);
|
||||
|
||||
MonthData m3 = MonthData.GetOldDate(datasource.TimeStamp, 3);
|
||||
monthDataCollection.put(m3, datasource.WattsMonth03);
|
||||
|
||||
MonthData m4 = MonthData.GetOldDate(datasource.TimeStamp, 4);
|
||||
monthDataCollection.put(m4, datasource.WattsMonth04);
|
||||
|
||||
MonthData m5 = MonthData.GetOldDate(datasource.TimeStamp, 5);
|
||||
monthDataCollection.put(m5, datasource.WattsMonth05);
|
||||
|
||||
MonthData m6 = MonthData.GetOldDate(datasource.TimeStamp, 6);
|
||||
monthDataCollection.put(m6, datasource.WattsMonth06);
|
||||
|
||||
MonthData m7 = MonthData.GetOldDate(datasource.TimeStamp, 7);
|
||||
monthDataCollection.put(m7, datasource.WattsMonth07);
|
||||
|
||||
MonthData m8 = MonthData.GetOldDate(datasource.TimeStamp, 8);
|
||||
monthDataCollection.put(m8, datasource.WattsMonth08);
|
||||
|
||||
MonthData m9 = MonthData.GetOldDate(datasource.TimeStamp, 9);
|
||||
monthDataCollection.put(m9, datasource.WattsMonth09);
|
||||
|
||||
MonthData m10 = MonthData.GetOldDate(datasource.TimeStamp, 10);
|
||||
monthDataCollection.put(m10, datasource.WattsMonth10);
|
||||
|
||||
MonthData m11 = MonthData.GetOldDate(datasource.TimeStamp, 11);
|
||||
monthDataCollection.put(m11, datasource.WattsMonth11);
|
||||
|
||||
MonthData m12 = MonthData.GetOldDate(datasource.TimeStamp, 12);
|
||||
monthDataCollection.put(m12, datasource.WattsMonth12);
|
||||
|
||||
// --- DAYS ------------------------------------
|
||||
DayData d1 = DayData.GetOldDate(datasource.TimeStamp, 1);
|
||||
dayDataCollection.put(d1, datasource.WattsDay01);
|
||||
|
||||
DayData d2 = DayData.GetOldDate(datasource.TimeStamp, 2);
|
||||
dayDataCollection.put(d2, datasource.WattsDay02);
|
||||
|
||||
DayData d3 = DayData.GetOldDate(datasource.TimeStamp, 3);
|
||||
dayDataCollection.put(d3, datasource.WattsDay03);
|
||||
|
||||
DayData d4 = DayData.GetOldDate(datasource.TimeStamp, 4);
|
||||
dayDataCollection.put(d4, datasource.WattsDay04);
|
||||
|
||||
DayData d5 = DayData.GetOldDate(datasource.TimeStamp, 5);
|
||||
dayDataCollection.put(d5, datasource.WattsDay05);
|
||||
|
||||
DayData d6 = DayData.GetOldDate(datasource.TimeStamp, 6);
|
||||
dayDataCollection.put(d6, datasource.WattsDay06);
|
||||
|
||||
DayData d7 = DayData.GetOldDate(datasource.TimeStamp, 7);
|
||||
dayDataCollection.put(d7, datasource.WattsDay07);
|
||||
|
||||
DayData d8 = DayData.GetOldDate(datasource.TimeStamp, 8);
|
||||
dayDataCollection.put(d8, datasource.WattsDay08);
|
||||
|
||||
DayData d9 = DayData.GetOldDate(datasource.TimeStamp, 9);
|
||||
dayDataCollection.put(d9, datasource.WattsDay09);
|
||||
|
||||
DayData d10 = DayData.GetOldDate(datasource.TimeStamp, 10);
|
||||
dayDataCollection.put(d10, datasource.WattsDay10);
|
||||
|
||||
DayData d11 = DayData.GetOldDate(datasource.TimeStamp, 11);
|
||||
dayDataCollection.put(d11, datasource.WattsDay11);
|
||||
|
||||
DayData d12 = DayData.GetOldDate(datasource.TimeStamp, 12);
|
||||
dayDataCollection.put(d12, datasource.WattsDay12);
|
||||
|
||||
DayData d13 = DayData.GetOldDate(datasource.TimeStamp, 13);
|
||||
dayDataCollection.put(d13, datasource.WattsDay13);
|
||||
|
||||
DayData d14 = DayData.GetOldDate(datasource.TimeStamp, 14);
|
||||
dayDataCollection.put(d14, datasource.WattsDay14);
|
||||
|
||||
DayData d15 = DayData.GetOldDate(datasource.TimeStamp, 15);
|
||||
dayDataCollection.put(d15, datasource.WattsDay15);
|
||||
|
||||
DayData d16 = DayData.GetOldDate(datasource.TimeStamp, 16);
|
||||
dayDataCollection.put(d16, datasource.WattsDay16);
|
||||
|
||||
DayData d17 = DayData.GetOldDate(datasource.TimeStamp, 17);
|
||||
dayDataCollection.put(d17, datasource.WattsDay17);
|
||||
|
||||
DayData d18 = DayData.GetOldDate(datasource.TimeStamp, 18);
|
||||
dayDataCollection.put(d18, datasource.WattsDay18);
|
||||
|
||||
DayData d19 = DayData.GetOldDate(datasource.TimeStamp, 19);
|
||||
dayDataCollection.put(d19, datasource.WattsDay19);
|
||||
|
||||
DayData d20 = DayData.GetOldDate(datasource.TimeStamp, 20);
|
||||
dayDataCollection.put(d20, datasource.WattsDay20);
|
||||
|
||||
DayData d21 = DayData.GetOldDate(datasource.TimeStamp, 21);
|
||||
dayDataCollection.put(d21, datasource.WattsDay21);
|
||||
|
||||
DayData d22 = DayData.GetOldDate(datasource.TimeStamp, 22);
|
||||
dayDataCollection.put(d22, datasource.WattsDay22);
|
||||
|
||||
DayData d23 = DayData.GetOldDate(datasource.TimeStamp, 23);
|
||||
dayDataCollection.put(d23, datasource.WattsDay23);
|
||||
|
||||
DayData d24 = DayData.GetOldDate(datasource.TimeStamp, 24);
|
||||
dayDataCollection.put(d24, datasource.WattsDay24);
|
||||
|
||||
DayData d25 = DayData.GetOldDate(datasource.TimeStamp, 25);
|
||||
dayDataCollection.put(d25, datasource.WattsDay25);
|
||||
|
||||
DayData d26 = DayData.GetOldDate(datasource.TimeStamp, 26);
|
||||
dayDataCollection.put(d26, datasource.WattsDay26);
|
||||
|
||||
DayData d27 = DayData.GetOldDate(datasource.TimeStamp, 27);
|
||||
dayDataCollection.put(d27, datasource.WattsDay27);
|
||||
|
||||
DayData d28 = DayData.GetOldDate(datasource.TimeStamp, 28);
|
||||
dayDataCollection.put(d28, datasource.WattsDay28);
|
||||
|
||||
DayData d29 = DayData.GetOldDate(datasource.TimeStamp, 29);
|
||||
dayDataCollection.put(d29, datasource.WattsDay29);
|
||||
|
||||
DayData d30 = DayData.GetOldDate(datasource.TimeStamp, 30);
|
||||
dayDataCollection.put(d30, datasource.WattsDay30);
|
||||
|
||||
DayData d31 = DayData.GetOldDate(datasource.TimeStamp, 31);
|
||||
dayDataCollection.put(d31, datasource.WattsDay31);
|
||||
|
||||
// --- HOURS ----------------------------------
|
||||
HourData h0 = HourData.GetOldDate(datasource.TimeStamp, 0);
|
||||
hourDataCollection.put(h0, datasource.kWattsHour02);
|
||||
|
||||
HourData h2 = HourData.GetOldDate(datasource.TimeStamp, 2);
|
||||
hourDataCollection.put(h2, datasource.kWattsHour04);
|
||||
|
||||
HourData h4 = HourData.GetOldDate(datasource.TimeStamp, 4);
|
||||
hourDataCollection.put(h4, datasource.kWattsHour06);
|
||||
|
||||
HourData h6 = HourData.GetOldDate(datasource.TimeStamp, 6);
|
||||
hourDataCollection.put(h6, datasource.kWattsHour08);
|
||||
|
||||
HourData h8 = HourData.GetOldDate(datasource.TimeStamp, 8);
|
||||
hourDataCollection.put(h8, datasource.kWattsHour10);
|
||||
|
||||
HourData h10 = HourData.GetOldDate(datasource.TimeStamp, 10);
|
||||
hourDataCollection.put(h10, datasource.kWattsHour12);
|
||||
|
||||
HourData h12 = HourData.GetOldDate(datasource.TimeStamp, 12);
|
||||
hourDataCollection.put(h12, datasource.kWattsHour14);
|
||||
|
||||
HourData h14 = HourData.GetOldDate(datasource.TimeStamp, 14);
|
||||
hourDataCollection.put(h14, datasource.kWattsHour16);
|
||||
|
||||
HourData h16 = HourData.GetOldDate(datasource.TimeStamp, 16);
|
||||
hourDataCollection.put(h16, datasource.kWattsHour18);
|
||||
|
||||
HourData h18 = HourData.GetOldDate(datasource.TimeStamp, 18);
|
||||
hourDataCollection.put(h18, datasource.kWattsHour20);
|
||||
|
||||
HourData h20 = HourData.GetOldDate(datasource.TimeStamp, 20);
|
||||
hourDataCollection.put(h20, datasource.kWattsHour22);
|
||||
|
||||
HourData h22 = HourData.GetOldDate(datasource.TimeStamp, 22);
|
||||
hourDataCollection.put(h22, datasource.kWattsHour24);
|
||||
|
||||
HourData h24 = HourData.GetOldDate(datasource.TimeStamp, 24);
|
||||
hourDataCollection.put(h24, datasource.kWattsHour26);
|
||||
}
|
||||
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
Enumeration<HourData> enHr = hourDataCollection.keys();
|
||||
while(enHr.hasMoreElements())
|
||||
{
|
||||
HourData tm = enHr.nextElement();
|
||||
sb.append(tm.toString() + " = " + hourDataCollection.get(tm) + System.getProperty("line.separator"));
|
||||
}
|
||||
|
||||
Enumeration<DayData> enDay = dayDataCollection.keys();
|
||||
while(enDay.hasMoreElements())
|
||||
{
|
||||
DayData tm = enDay.nextElement();
|
||||
sb.append(tm.toString() + " = " + dayDataCollection.get(tm) + System.getProperty("line.separator"));
|
||||
}
|
||||
|
||||
Enumeration<MonthData> enMth = monthDataCollection.keys();
|
||||
while(enMth.hasMoreElements())
|
||||
{
|
||||
MonthData tm = enMth.nextElement();
|
||||
sb.append(tm.toString() + " = " + monthDataCollection.get(tm) + System.getProperty("line.separator"));
|
||||
}
|
||||
|
||||
Enumeration<YearData> enYr = yearDataCollection.keys();
|
||||
while(enYr.hasMoreElements())
|
||||
{
|
||||
YearData tm = enYr.nextElement();
|
||||
sb.append(tm.toString() + " = " + yearDataCollection.get(tm) + System.getProperty("line.separator"));
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
355
java/dalelane/currentcost/CurrentCostParser.java
Normal file
355
java/dalelane/currentcost/CurrentCostParser.java
Normal file
|
@ -0,0 +1,355 @@
|
|||
package dalelane.currentcost;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
|
||||
/*
|
||||
* An SAX helper for XML reading of CurrentCost data.
|
||||
*
|
||||
* It converts a line of XML received from a CurrentCost meter into
|
||||
* a Java object that represents the data.
|
||||
*
|
||||
*
|
||||
* Dale Lane (http://dalelane.co.uk/blog)
|
||||
*/
|
||||
|
||||
public class CurrentCostParser extends DefaultHandler {
|
||||
|
||||
/* this is the CurrentCost data object we are creating */
|
||||
private CurrentCostUpdate cc = new CurrentCostUpdate();;
|
||||
|
||||
/* returns the CurrentCost data object we created from the XML */
|
||||
public CurrentCostUpdate getParsedUpdate()
|
||||
{
|
||||
return cc;
|
||||
}
|
||||
|
||||
|
||||
/* constants which define each element in the CurrentCost XML */
|
||||
public enum CurrentCostXMLElement { DSB, TIMESTAMPHR, TIMESTAMPMIN, TIMESTAMPSEC,
|
||||
METERNAME, METERID, METERTYPE, METERSW, TEMP,
|
||||
CH1Wout, CH1Win, CH2Wout, CH2Win, CH3Wout, CH3Win,
|
||||
HR2, HR4, HR6, HR8, HR10, HR12, HR14,
|
||||
HR16, HR18, HR20, HR22, HR24, HR26,
|
||||
DAY1, DAY2, DAY3, DAY4, DAY5, DAY6, DAY7,
|
||||
DAY8, DAY9, DAY10, DAY11, DAY12, DAY13,
|
||||
DAY14, DAY15, DAY16, DAY17, DAY18, DAY19,
|
||||
DAY20, DAY21, DAY22, DAY23, DAY24, DAY25,
|
||||
DAY26, DAY27, DAY28, DAY29, DAY30, DAY31,
|
||||
MTH1, MTH2, MTH3, MTH4, MTH5, MTH6, MTH7,
|
||||
MTH8, MTH9, MTH10, MTH11, MTH12,
|
||||
YR1, YR2, YR3, YR4 };
|
||||
|
||||
/* internal object which identifies which element
|
||||
* in the XML we are currently looking at */
|
||||
private CurrentCostXMLElement currentElement = null;
|
||||
|
||||
/* the XML stores the time as HR, MIN and SECs. we will return
|
||||
* a Calendar object, so we keep the hour, min and sec internal
|
||||
* until we are ready to create the Calendar object. */
|
||||
private int timestampSubElementHour = 0;
|
||||
private int timestampSubElementMins = 0;
|
||||
private int timestampSubElementSecs = 0;
|
||||
|
||||
|
||||
public void startElement(String namespaceURI,
|
||||
String localName,
|
||||
String qualifiedName,
|
||||
Attributes atts)
|
||||
{
|
||||
if (localName.equals("dsb")) currentElement = CurrentCostXMLElement.DSB;
|
||||
else if (localName.equals("hr")) currentElement = CurrentCostXMLElement.TIMESTAMPHR;
|
||||
else if (localName.equals("min")) currentElement = CurrentCostXMLElement.TIMESTAMPMIN;
|
||||
else if (localName.equals("sec")) currentElement = CurrentCostXMLElement.TIMESTAMPSEC;
|
||||
else if (localName.equals("name")) currentElement = CurrentCostXMLElement.METERNAME;
|
||||
else if (localName.equals("id")) currentElement = CurrentCostXMLElement.METERID;
|
||||
else if (localName.equals("type")) currentElement = CurrentCostXMLElement.METERTYPE;
|
||||
else if (localName.equals("sver")) currentElement = CurrentCostXMLElement.METERSW;
|
||||
else if (localName.equals("ch1")) currentElement = CurrentCostXMLElement.CH1Wout;
|
||||
else if (localName.equals("ch2")) currentElement = CurrentCostXMLElement.CH2Wout;
|
||||
else if (localName.equals("ch3")) currentElement = CurrentCostXMLElement.CH3Wout;
|
||||
else if (localName.equals("tmpr")) currentElement = CurrentCostXMLElement.TEMP;
|
||||
else if (localName.equals("h02")) currentElement = CurrentCostXMLElement.HR2;
|
||||
else if (localName.equals("h04")) currentElement = CurrentCostXMLElement.HR4;
|
||||
else if (localName.equals("h06")) currentElement = CurrentCostXMLElement.HR6;
|
||||
else if (localName.equals("h08")) currentElement = CurrentCostXMLElement.HR8;
|
||||
else if (localName.equals("h10")) currentElement = CurrentCostXMLElement.HR10;
|
||||
else if (localName.equals("h12")) currentElement = CurrentCostXMLElement.HR12;
|
||||
else if (localName.equals("h14")) currentElement = CurrentCostXMLElement.HR14;
|
||||
else if (localName.equals("h16")) currentElement = CurrentCostXMLElement.HR16;
|
||||
else if (localName.equals("h18")) currentElement = CurrentCostXMLElement.HR18;
|
||||
else if (localName.equals("h20")) currentElement = CurrentCostXMLElement.HR20;
|
||||
else if (localName.equals("h22")) currentElement = CurrentCostXMLElement.HR22;
|
||||
else if (localName.equals("h24")) currentElement = CurrentCostXMLElement.HR24;
|
||||
else if (localName.equals("h26")) currentElement = CurrentCostXMLElement.HR26;
|
||||
else if (localName.equals("h20")) currentElement = CurrentCostXMLElement.HR20;
|
||||
else if (localName.equals("d01")) currentElement = CurrentCostXMLElement.DAY1;
|
||||
else if (localName.equals("d02")) currentElement = CurrentCostXMLElement.DAY2;
|
||||
else if (localName.equals("d03")) currentElement = CurrentCostXMLElement.DAY3;
|
||||
else if (localName.equals("d04")) currentElement = CurrentCostXMLElement.DAY4;
|
||||
else if (localName.equals("d05")) currentElement = CurrentCostXMLElement.DAY5;
|
||||
else if (localName.equals("d06")) currentElement = CurrentCostXMLElement.DAY6;
|
||||
else if (localName.equals("d07")) currentElement = CurrentCostXMLElement.DAY7;
|
||||
else if (localName.equals("d08")) currentElement = CurrentCostXMLElement.DAY8;
|
||||
else if (localName.equals("d09")) currentElement = CurrentCostXMLElement.DAY9;
|
||||
else if (localName.equals("d10")) currentElement = CurrentCostXMLElement.DAY10;
|
||||
else if (localName.equals("d11")) currentElement = CurrentCostXMLElement.DAY11;
|
||||
else if (localName.equals("d12")) currentElement = CurrentCostXMLElement.DAY12;
|
||||
else if (localName.equals("d13")) currentElement = CurrentCostXMLElement.DAY13;
|
||||
else if (localName.equals("d14")) currentElement = CurrentCostXMLElement.DAY14;
|
||||
else if (localName.equals("d15")) currentElement = CurrentCostXMLElement.DAY15;
|
||||
else if (localName.equals("d16")) currentElement = CurrentCostXMLElement.DAY16;
|
||||
else if (localName.equals("d17")) currentElement = CurrentCostXMLElement.DAY17;
|
||||
else if (localName.equals("d18")) currentElement = CurrentCostXMLElement.DAY18;
|
||||
else if (localName.equals("d19")) currentElement = CurrentCostXMLElement.DAY19;
|
||||
else if (localName.equals("d20")) currentElement = CurrentCostXMLElement.DAY20;
|
||||
else if (localName.equals("d21")) currentElement = CurrentCostXMLElement.DAY21;
|
||||
else if (localName.equals("d22")) currentElement = CurrentCostXMLElement.DAY22;
|
||||
else if (localName.equals("d23")) currentElement = CurrentCostXMLElement.DAY23;
|
||||
else if (localName.equals("d24")) currentElement = CurrentCostXMLElement.DAY24;
|
||||
else if (localName.equals("d25")) currentElement = CurrentCostXMLElement.DAY25;
|
||||
else if (localName.equals("d26")) currentElement = CurrentCostXMLElement.DAY26;
|
||||
else if (localName.equals("d27")) currentElement = CurrentCostXMLElement.DAY27;
|
||||
else if (localName.equals("d28")) currentElement = CurrentCostXMLElement.DAY28;
|
||||
else if (localName.equals("d29")) currentElement = CurrentCostXMLElement.DAY29;
|
||||
else if (localName.equals("d30")) currentElement = CurrentCostXMLElement.DAY30;
|
||||
else if (localName.equals("d31")) currentElement = CurrentCostXMLElement.DAY31;
|
||||
else if (localName.equals("m01")) currentElement = CurrentCostXMLElement.MTH1;
|
||||
else if (localName.equals("m02")) currentElement = CurrentCostXMLElement.MTH2;
|
||||
else if (localName.equals("m03")) currentElement = CurrentCostXMLElement.MTH3;
|
||||
else if (localName.equals("m04")) currentElement = CurrentCostXMLElement.MTH4;
|
||||
else if (localName.equals("m05")) currentElement = CurrentCostXMLElement.MTH5;
|
||||
else if (localName.equals("m06")) currentElement = CurrentCostXMLElement.MTH6;
|
||||
else if (localName.equals("m07")) currentElement = CurrentCostXMLElement.MTH7;
|
||||
else if (localName.equals("m08")) currentElement = CurrentCostXMLElement.MTH8;
|
||||
else if (localName.equals("m09")) currentElement = CurrentCostXMLElement.MTH9;
|
||||
else if (localName.equals("m10")) currentElement = CurrentCostXMLElement.MTH10;
|
||||
else if (localName.equals("m11")) currentElement = CurrentCostXMLElement.MTH11;
|
||||
else if (localName.equals("m12")) currentElement = CurrentCostXMLElement.MTH12;
|
||||
else if (localName.equals("y1")) currentElement = CurrentCostXMLElement.YR1;
|
||||
else if (localName.equals("y2")) currentElement = CurrentCostXMLElement.YR2;
|
||||
else if (localName.equals("y3")) currentElement = CurrentCostXMLElement.YR3;
|
||||
else if (localName.equals("y4")) currentElement = CurrentCostXMLElement.YR4;
|
||||
else if (localName.equals("watts"))
|
||||
{
|
||||
/* <watts> is inside <CH1>, <CH2> or <CH3>
|
||||
* so we need to check what was the last element we started, to know
|
||||
* which <watts> element we're looking at now */
|
||||
switch(currentElement)
|
||||
{
|
||||
case CH1Wout: currentElement = CurrentCostXMLElement.CH1Win; break;
|
||||
case CH2Wout: currentElement = CurrentCostXMLElement.CH2Win; break;
|
||||
case CH3Wout: currentElement = CurrentCostXMLElement.CH3Win; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* last thing we do once we have completed parsing the CurrentCost XML
|
||||
* is to create a timestamp object based on the hour, minute and second
|
||||
* values that were in the XML */
|
||||
public void endDocument() throws SAXException
|
||||
{
|
||||
cc.TimeStamp = new GregorianCalendar();
|
||||
cc.TimeStamp.set(Calendar.HOUR_OF_DAY, timestampSubElementHour);
|
||||
cc.TimeStamp.set(Calendar.MINUTE, timestampSubElementMins);
|
||||
cc.TimeStamp.set(Calendar.SECOND, timestampSubElementSecs);
|
||||
|
||||
/* mark the parsed object as complete */
|
||||
cc.ValidUpdate = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* read the data from a CurrentCost XML element
|
||||
*/
|
||||
public void characters(char[] ch, int start, int length) throws SAXException
|
||||
{
|
||||
if (currentElement != null)
|
||||
{
|
||||
// read the XML data as a string
|
||||
|
||||
StringBuilder currentElementValue = new StringBuilder(length);
|
||||
|
||||
for (int i = start; i < (start + length); i++)
|
||||
{
|
||||
currentElementValue.append(ch[i]);
|
||||
}
|
||||
|
||||
// cast to required format
|
||||
|
||||
float currentElementFloat = -1;
|
||||
int currentElementInt = -1;
|
||||
|
||||
switch (currentElement)
|
||||
{
|
||||
// string values
|
||||
case METERNAME:
|
||||
case METERSW:
|
||||
// no conversion necessary
|
||||
break;
|
||||
|
||||
// float values
|
||||
case TEMP:
|
||||
case HR2:
|
||||
case HR4:
|
||||
case HR6:
|
||||
case HR8:
|
||||
case HR10:
|
||||
case HR12:
|
||||
case HR14:
|
||||
case HR16:
|
||||
case HR18:
|
||||
case HR20:
|
||||
case HR22:
|
||||
case HR24:
|
||||
case HR26:
|
||||
currentElementFloat = Float.parseFloat(currentElementValue.toString());
|
||||
break;
|
||||
|
||||
// int values
|
||||
case DSB:
|
||||
case TIMESTAMPHR:
|
||||
case TIMESTAMPMIN:
|
||||
case TIMESTAMPSEC:
|
||||
case METERID:
|
||||
case METERTYPE:
|
||||
case CH1Win:
|
||||
case CH2Win:
|
||||
case CH3Win:
|
||||
case DAY1:
|
||||
case DAY2:
|
||||
case DAY3:
|
||||
case DAY4:
|
||||
case DAY5:
|
||||
case DAY6:
|
||||
case DAY7:
|
||||
case DAY8:
|
||||
case DAY9:
|
||||
case DAY10:
|
||||
case DAY11:
|
||||
case DAY12:
|
||||
case DAY13:
|
||||
case DAY14:
|
||||
case DAY15:
|
||||
case DAY16:
|
||||
case DAY17:
|
||||
case DAY18:
|
||||
case DAY19:
|
||||
case DAY20:
|
||||
case DAY21:
|
||||
case DAY22:
|
||||
case DAY23:
|
||||
case DAY24:
|
||||
case DAY25:
|
||||
case DAY26:
|
||||
case DAY27:
|
||||
case DAY28:
|
||||
case DAY29:
|
||||
case DAY30:
|
||||
case DAY31:
|
||||
case MTH1:
|
||||
case MTH2:
|
||||
case MTH3:
|
||||
case MTH4:
|
||||
case MTH5:
|
||||
case MTH6:
|
||||
case MTH7:
|
||||
case MTH8:
|
||||
case MTH9:
|
||||
case MTH10:
|
||||
case MTH11:
|
||||
case MTH12:
|
||||
case YR1:
|
||||
case YR2:
|
||||
case YR3:
|
||||
case YR4:
|
||||
currentElementInt = Integer.parseInt(currentElementValue.toString());
|
||||
break;
|
||||
}
|
||||
|
||||
// store the data in the correct attribute of the object
|
||||
|
||||
switch (currentElement)
|
||||
{
|
||||
case METERNAME: cc.MeterName = currentElementValue.toString(); break;
|
||||
case METERSW: cc.MeterSoftwareVersion = currentElementValue.toString(); break;
|
||||
|
||||
case TEMP: cc.Temperature = currentElementFloat; break;
|
||||
case HR2: cc.kWattsHour02 = currentElementFloat; break;
|
||||
case HR4: cc.kWattsHour04 = currentElementFloat; break;
|
||||
case HR6: cc.kWattsHour06 = currentElementFloat; break;
|
||||
case HR8: cc.kWattsHour08 = currentElementFloat; break;
|
||||
case HR10: cc.kWattsHour10 = currentElementFloat; break;
|
||||
case HR12: cc.kWattsHour12 = currentElementFloat; break;
|
||||
case HR14: cc.kWattsHour14 = currentElementFloat; break;
|
||||
case HR16: cc.kWattsHour16 = currentElementFloat; break;
|
||||
case HR18: cc.kWattsHour18 = currentElementFloat; break;
|
||||
case HR20: cc.kWattsHour20 = currentElementFloat; break;
|
||||
case HR22: cc.kWattsHour22 = currentElementFloat; break;
|
||||
case HR24: cc.kWattsHour24 = currentElementFloat; break;
|
||||
case HR26: cc.kWattsHour26 = currentElementFloat; break;
|
||||
|
||||
case TIMESTAMPHR: timestampSubElementHour = currentElementInt; break;
|
||||
case TIMESTAMPMIN: timestampSubElementMins = currentElementInt; break;
|
||||
case TIMESTAMPSEC: timestampSubElementSecs = currentElementInt; break;
|
||||
case DSB: cc.DaysSinceBirth = currentElementInt; break;
|
||||
case METERID: cc.MeterId = currentElementInt; break;
|
||||
case METERTYPE: cc.MeterType = currentElementInt; break;
|
||||
case CH1Win: cc.Channel1Watts = currentElementInt; break;
|
||||
case CH2Win: cc.Channel2Watts = currentElementInt; break;
|
||||
case CH3Win: cc.Channel3Watts = currentElementInt; break;
|
||||
case DAY1: cc.WattsDay01 = currentElementInt; break;
|
||||
case DAY2: cc.WattsDay02 = currentElementInt; break;
|
||||
case DAY3: cc.WattsDay03 = currentElementInt; break;
|
||||
case DAY4: cc.WattsDay04 = currentElementInt; break;
|
||||
case DAY5: cc.WattsDay05 = currentElementInt; break;
|
||||
case DAY6: cc.WattsDay06 = currentElementInt; break;
|
||||
case DAY7: cc.WattsDay07 = currentElementInt; break;
|
||||
case DAY8: cc.WattsDay08 = currentElementInt; break;
|
||||
case DAY9: cc.WattsDay09 = currentElementInt; break;
|
||||
case DAY10: cc.WattsDay10 = currentElementInt; break;
|
||||
case DAY11: cc.WattsDay11 = currentElementInt; break;
|
||||
case DAY12: cc.WattsDay12 = currentElementInt; break;
|
||||
case DAY13: cc.WattsDay13 = currentElementInt; break;
|
||||
case DAY14: cc.WattsDay14 = currentElementInt; break;
|
||||
case DAY15: cc.WattsDay15 = currentElementInt; break;
|
||||
case DAY16: cc.WattsDay16 = currentElementInt; break;
|
||||
case DAY17: cc.WattsDay17 = currentElementInt; break;
|
||||
case DAY18: cc.WattsDay18 = currentElementInt; break;
|
||||
case DAY19: cc.WattsDay19 = currentElementInt; break;
|
||||
case DAY20: cc.WattsDay20 = currentElementInt; break;
|
||||
case DAY21: cc.WattsDay21 = currentElementInt; break;
|
||||
case DAY22: cc.WattsDay22 = currentElementInt; break;
|
||||
case DAY23: cc.WattsDay23 = currentElementInt; break;
|
||||
case DAY24: cc.WattsDay24 = currentElementInt; break;
|
||||
case DAY25: cc.WattsDay25 = currentElementInt; break;
|
||||
case DAY26: cc.WattsDay26 = currentElementInt; break;
|
||||
case DAY27: cc.WattsDay27 = currentElementInt; break;
|
||||
case DAY28: cc.WattsDay28 = currentElementInt; break;
|
||||
case DAY29: cc.WattsDay29 = currentElementInt; break;
|
||||
case DAY30: cc.WattsDay30 = currentElementInt; break;
|
||||
case DAY31: cc.WattsDay31 = currentElementInt; break;
|
||||
case MTH1: cc.WattsMonth01 = currentElementInt; break;
|
||||
case MTH2: cc.WattsMonth02 = currentElementInt; break;
|
||||
case MTH3: cc.WattsMonth03 = currentElementInt; break;
|
||||
case MTH4: cc.WattsMonth04 = currentElementInt; break;
|
||||
case MTH5: cc.WattsMonth05 = currentElementInt; break;
|
||||
case MTH6: cc.WattsMonth06 = currentElementInt; break;
|
||||
case MTH7: cc.WattsMonth07 = currentElementInt; break;
|
||||
case MTH8: cc.WattsMonth08 = currentElementInt; break;
|
||||
case MTH9: cc.WattsMonth09 = currentElementInt; break;
|
||||
case MTH10: cc.WattsMonth10 = currentElementInt; break;
|
||||
case MTH11: cc.WattsMonth11 = currentElementInt; break;
|
||||
case MTH12: cc.WattsMonth12 = currentElementInt; break;
|
||||
case YR1: cc.WattsYear1 = currentElementInt; break;
|
||||
case YR2: cc.WattsYear2 = currentElementInt; break;
|
||||
case YR3: cc.WattsYear3 = currentElementInt; break;
|
||||
case YR4: cc.WattsYear4 = currentElementInt; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
143
java/dalelane/currentcost/CurrentCostSample.java
Normal file
143
java/dalelane/currentcost/CurrentCostSample.java
Normal file
|
@ -0,0 +1,143 @@
|
|||
package dalelane.currentcost;
|
||||
|
||||
import gnu.io.CommPortIdentifier;
|
||||
import gnu.io.NoSuchPortException;
|
||||
import gnu.io.PortInUseException;
|
||||
import gnu.io.SerialPort;
|
||||
import gnu.io.UnsupportedCommOperationException;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.StringReader;
|
||||
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
/*
|
||||
* Parses data from a CurrentCost meter
|
||||
*
|
||||
* Note that this is provided to help get you started, but it lacks careful
|
||||
* error-handling or proper documentation.
|
||||
*
|
||||
* If you have any questions about it, or even just find it useful, please do
|
||||
* let me know - dale.lane@gmail.com
|
||||
*
|
||||
*
|
||||
* Dale Lane (http://dalelane.co.uk/blog)
|
||||
*/
|
||||
|
||||
public class CurrentCostSample {
|
||||
|
||||
public static String COMPORT = "COM21";
|
||||
public static int BAUDRATE = 9600;
|
||||
|
||||
|
||||
/*
|
||||
* An example implementation that uses the sample classes.
|
||||
*
|
||||
* It connects to
|
||||
*/
|
||||
public static void main(String[] args)
|
||||
{
|
||||
/* represents the COM port we connected the CurrentCost meter to */
|
||||
SerialPort serialport = null;
|
||||
|
||||
/* the XML parser that will read the CurrentCost data */
|
||||
CurrentCostParser handler = new CurrentCostParser();
|
||||
|
||||
try
|
||||
{
|
||||
/* prepare the XML parser */
|
||||
XMLReader parser = XMLReaderFactory.createXMLReader();
|
||||
parser.setContentHandler(handler);
|
||||
|
||||
/* specify the parameters to connect to the CurrentCost meter */
|
||||
CommPortIdentifier comportid = CommPortIdentifier.getPortIdentifier(COMPORT);
|
||||
|
||||
serialport = (SerialPort)comportid.open("CurrentCostJava", 5000);
|
||||
|
||||
serialport.setSerialPortParams(BAUDRATE,
|
||||
SerialPort.DATABITS_8,
|
||||
SerialPort.STOPBITS_1,
|
||||
SerialPort.PARITY_NONE);
|
||||
|
||||
/* specify this to handle issues using USB-to-serial connector */
|
||||
serialport.notifyOnOutputEmpty(true);
|
||||
|
||||
/* read data from CurrentCost meter */
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(serialport.getInputStream()));
|
||||
|
||||
String lineOfXML = "";
|
||||
|
||||
/* we will probably need a few attempts before we get a valid update
|
||||
* as it is not unusual to get a partial line
|
||||
*
|
||||
* the quickest sanity-check on an CurrentCost update, is whether it
|
||||
* is at least as long as it should be */
|
||||
while (lineOfXML.length() < 1200)
|
||||
{
|
||||
try
|
||||
{
|
||||
lineOfXML = br.readLine();
|
||||
}
|
||||
catch (IOException exc)
|
||||
{
|
||||
lineOfXML = "";
|
||||
}
|
||||
}
|
||||
|
||||
/* create an inputsource from the line of XML we have - putting
|
||||
* it in a format that the XML parser can accept */
|
||||
StringReader sr = new StringReader(lineOfXML);
|
||||
InputSource isrc = new InputSource(sr);
|
||||
|
||||
/* parse the CurrentCost update */
|
||||
parser.parse(isrc);
|
||||
|
||||
}
|
||||
catch (NoSuchPortException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (PortInUseException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (UnsupportedCommOperationException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (SAXException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
/* we've finished with the COM port, so we close it now */
|
||||
if (serialport != null)
|
||||
{
|
||||
serialport.close();
|
||||
}
|
||||
|
||||
/* we get the parsed update - a Java object that represents the
|
||||
* data that was in the XML we received from the CurrentCost meter */
|
||||
CurrentCostUpdate ccupd = handler.getParsedUpdate();
|
||||
|
||||
/* we now convert the CurrentCostUpdate object - containing data
|
||||
* with relative time descriptions - into a collection of absolute
|
||||
* time descriptions */
|
||||
CurrentCostHistory cchist = new CurrentCostHistory();
|
||||
cchist.UpdateData(ccupd);
|
||||
|
||||
/* did it work? we print out the data we received as a sanity check */
|
||||
System.out.println(cchist);
|
||||
}
|
||||
|
||||
}
|
88
java/dalelane/currentcost/CurrentCostUpdate.java
Normal file
88
java/dalelane/currentcost/CurrentCostUpdate.java
Normal file
|
@ -0,0 +1,88 @@
|
|||
package dalelane.currentcost;
|
||||
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
/*
|
||||
* Represents the data contained in a single update from a CurrentCost meter
|
||||
*
|
||||
* It's a Java object representation of the XML - as described here:
|
||||
* http://cumbers.wordpress.com/2008/05/07/breakdown-of-currentcost-xml-output/
|
||||
*
|
||||
* Dale Lane (http://dalelane.co.uk/blog)
|
||||
*/
|
||||
|
||||
public class CurrentCostUpdate
|
||||
{
|
||||
public boolean ValidUpdate = false;
|
||||
|
||||
public int DaysSinceBirth;
|
||||
public GregorianCalendar TimeStamp;
|
||||
public String MeterName;
|
||||
public int MeterId;
|
||||
public int MeterType;
|
||||
public String MeterSoftwareVersion;
|
||||
public int Channel1Watts;
|
||||
public int Channel2Watts;
|
||||
public int Channel3Watts;
|
||||
public float Temperature;
|
||||
public float kWattsHour02;
|
||||
public float kWattsHour04;
|
||||
public float kWattsHour06;
|
||||
public float kWattsHour08;
|
||||
public float kWattsHour10;
|
||||
public float kWattsHour12;
|
||||
public float kWattsHour14;
|
||||
public float kWattsHour16;
|
||||
public float kWattsHour18;
|
||||
public float kWattsHour20;
|
||||
public float kWattsHour22;
|
||||
public float kWattsHour24;
|
||||
public float kWattsHour26;
|
||||
public int WattsDay01;
|
||||
public int WattsDay02;
|
||||
public int WattsDay03;
|
||||
public int WattsDay04;
|
||||
public int WattsDay05;
|
||||
public int WattsDay06;
|
||||
public int WattsDay07;
|
||||
public int WattsDay08;
|
||||
public int WattsDay09;
|
||||
public int WattsDay10;
|
||||
public int WattsDay11;
|
||||
public int WattsDay12;
|
||||
public int WattsDay13;
|
||||
public int WattsDay14;
|
||||
public int WattsDay15;
|
||||
public int WattsDay16;
|
||||
public int WattsDay17;
|
||||
public int WattsDay18;
|
||||
public int WattsDay19;
|
||||
public int WattsDay20;
|
||||
public int WattsDay21;
|
||||
public int WattsDay22;
|
||||
public int WattsDay23;
|
||||
public int WattsDay24;
|
||||
public int WattsDay25;
|
||||
public int WattsDay26;
|
||||
public int WattsDay27;
|
||||
public int WattsDay28;
|
||||
public int WattsDay29;
|
||||
public int WattsDay30;
|
||||
public int WattsDay31;
|
||||
public int WattsMonth01;
|
||||
public int WattsMonth02;
|
||||
public int WattsMonth03;
|
||||
public int WattsMonth04;
|
||||
public int WattsMonth05;
|
||||
public int WattsMonth06;
|
||||
public int WattsMonth07;
|
||||
public int WattsMonth08;
|
||||
public int WattsMonth09;
|
||||
public int WattsMonth10;
|
||||
public int WattsMonth11;
|
||||
public int WattsMonth12;
|
||||
public int WattsYear1;
|
||||
public int WattsYear2;
|
||||
public int WattsYear3;
|
||||
public int WattsYear4;
|
||||
}
|
63
java/dalelane/currentcost/calendar/DayData.java
Normal file
63
java/dalelane/currentcost/calendar/DayData.java
Normal file
|
@ -0,0 +1,63 @@
|
|||
package dalelane.currentcost.calendar;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
/*
|
||||
* Internal calendar class for CurrentCost daily totals.
|
||||
*
|
||||
* Dale Lane (http://dalelane.co.uk/blog)
|
||||
*/
|
||||
|
||||
public class DayData {
|
||||
|
||||
public int Date;
|
||||
public int Month;
|
||||
public int Year;
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return Date + "/" + Month + "/" + Year;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (obj instanceof DayData)
|
||||
{
|
||||
if ((Year == ((DayData)obj).Year) &&
|
||||
(Month == ((DayData)obj).Month) &&
|
||||
(Date == ((DayData)obj).Date))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* returns a DayData object that is a specified number of days ago
|
||||
* from the provided reference date */
|
||||
public static DayData GetOldDate(GregorianCalendar refDate, int daysago)
|
||||
{
|
||||
GregorianCalendar referenceDate = (GregorianCalendar) refDate.clone();
|
||||
|
||||
DayData oldDay = new DayData();
|
||||
int newday = referenceDate.get(Calendar.DAY_OF_MONTH) - daysago;
|
||||
int newmonth = referenceDate.get(Calendar.MONTH) + 1;
|
||||
int newyear = referenceDate.get(Calendar.YEAR);
|
||||
|
||||
if (newday <= 0)
|
||||
{
|
||||
referenceDate.add(Calendar.DAY_OF_MONTH, -daysago);
|
||||
newday = referenceDate.get(Calendar.DAY_OF_MONTH);
|
||||
newmonth = referenceDate.get(Calendar.MONTH) + 1;
|
||||
newyear = referenceDate.get(Calendar.YEAR);
|
||||
}
|
||||
|
||||
oldDay.Date = newday;
|
||||
oldDay.Month = newmonth;
|
||||
oldDay.Year = newyear;
|
||||
|
||||
return oldDay;
|
||||
}
|
||||
}
|
89
java/dalelane/currentcost/calendar/HourData.java
Normal file
89
java/dalelane/currentcost/calendar/HourData.java
Normal file
|
@ -0,0 +1,89 @@
|
|||
package dalelane.currentcost.calendar;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
|
||||
/*
|
||||
* Internal calendar class for CurrentCost two-hourly totals.
|
||||
*
|
||||
* Dale Lane (http://dalelane.co.uk/blog)
|
||||
*/
|
||||
|
||||
public class HourData {
|
||||
|
||||
public int TwoHourBlock;
|
||||
public int Date;
|
||||
public int Month;
|
||||
public int Year;
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return Date + "/" + Month + "/" + Year + " " + TwoHourBlock + ":00";
|
||||
}
|
||||
|
||||
public boolean equals(Object compare)
|
||||
{
|
||||
if (compare instanceof HourData)
|
||||
{
|
||||
if ((TwoHourBlock == ((HourData)compare).TwoHourBlock) &&
|
||||
(Year == ((HourData)compare).Year) &&
|
||||
(Month == ((HourData)compare).Month) &&
|
||||
(Date == ((HourData)compare).Date))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* returns a HourData object that is a specified number of hours ago
|
||||
* from the provided reference date */
|
||||
public static HourData GetOldDate(GregorianCalendar refDate, int hoursago)
|
||||
{
|
||||
GregorianCalendar referenceDate = (GregorianCalendar) refDate.clone();
|
||||
|
||||
int start = referenceDate.get(Calendar.HOUR_OF_DAY);
|
||||
|
||||
if ((start % 2) == 0)
|
||||
{
|
||||
hoursago += 1;
|
||||
}
|
||||
|
||||
int newhour = start - hoursago;
|
||||
int newday = referenceDate.get(Calendar.DAY_OF_MONTH);
|
||||
int newmonth = referenceDate.get(Calendar.MONTH) + 1;
|
||||
int newyear = referenceDate.get(Calendar.YEAR);
|
||||
|
||||
if (newhour < -24)
|
||||
{
|
||||
newhour += 48;
|
||||
|
||||
referenceDate.add(Calendar.HOUR_OF_DAY, -(hoursago));
|
||||
|
||||
newday = referenceDate.get(Calendar.DAY_OF_MONTH);
|
||||
newmonth = referenceDate.get(Calendar.MONTH) + 1;
|
||||
newyear = referenceDate.get(Calendar.YEAR);
|
||||
}
|
||||
else if (newhour < 0)
|
||||
{
|
||||
newhour += 24;
|
||||
|
||||
referenceDate.add(Calendar.HOUR_OF_DAY, -(hoursago));
|
||||
|
||||
newday = referenceDate.get(Calendar.DAY_OF_MONTH);
|
||||
newmonth = referenceDate.get(Calendar.MONTH) + 1;
|
||||
newyear = referenceDate.get(Calendar.YEAR);
|
||||
}
|
||||
|
||||
|
||||
HourData oldHour = new HourData();
|
||||
oldHour.TwoHourBlock = newhour;
|
||||
oldHour.Date = newday;
|
||||
oldHour.Month = newmonth;
|
||||
oldHour.Year = newyear;
|
||||
|
||||
return oldHour;
|
||||
}
|
||||
}
|
55
java/dalelane/currentcost/calendar/MonthData.java
Normal file
55
java/dalelane/currentcost/calendar/MonthData.java
Normal file
|
@ -0,0 +1,55 @@
|
|||
package dalelane.currentcost.calendar;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
/*
|
||||
* Internal calendar class for CurrentCost monthly totals.
|
||||
*
|
||||
* Dale Lane (http://dalelane.co.uk/blog)
|
||||
*/
|
||||
|
||||
public class MonthData {
|
||||
|
||||
public int Month;
|
||||
public int Year;
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return Month + "/" + Year;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (obj instanceof MonthData)
|
||||
{
|
||||
if ((Year == ((MonthData)obj).Year) &&
|
||||
(Month == ((MonthData)obj).Month))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* returns a MonthData object that is a specified number of months ago
|
||||
* from the provided reference date */
|
||||
public static MonthData GetOldDate(GregorianCalendar referenceDate, int monthsago)
|
||||
{
|
||||
MonthData oldMonth = new MonthData();
|
||||
int newmonth = (referenceDate.get(Calendar.MONTH) + 1) - monthsago;
|
||||
int newyear = referenceDate.get(Calendar.YEAR);
|
||||
|
||||
if (newmonth <= 0)
|
||||
{
|
||||
newmonth += 12;
|
||||
newyear -= 1;
|
||||
}
|
||||
|
||||
oldMonth.Year = newyear;
|
||||
oldMonth.Month = newmonth;
|
||||
|
||||
return oldMonth;
|
||||
}
|
||||
}
|
42
java/dalelane/currentcost/calendar/YearData.java
Normal file
42
java/dalelane/currentcost/calendar/YearData.java
Normal file
|
@ -0,0 +1,42 @@
|
|||
package dalelane.currentcost.calendar;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
|
||||
/*
|
||||
* Internal calendar class for CurrentCost yearly totals.
|
||||
*
|
||||
* Dale Lane (http://dalelane.co.uk/blog)
|
||||
*/
|
||||
|
||||
public class YearData {
|
||||
|
||||
public int Year;
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return Integer.toString(Year);
|
||||
}
|
||||
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (obj instanceof YearData)
|
||||
{
|
||||
if (Year == ((YearData)obj).Year)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* returns a YearData object that is a specified number of years ago
|
||||
* from the provided reference date */
|
||||
public static YearData GetOldDate(GregorianCalendar referenceDate, int yearsago)
|
||||
{
|
||||
YearData oldYear = new YearData();
|
||||
oldYear.Year = referenceDate.get(Calendar.YEAR) - yearsago;
|
||||
return oldYear;
|
||||
}
|
||||
}
|
7
python/README.txt
Normal file
7
python/README.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
Start with currcost.py
|
||||
|
||||
You will need to modify YOURCOMPORT before running it.
|
||||
|
||||
Note that this is provided to help get you started, but it lacks careful error-handling or proper documentation.
|
||||
|
||||
If you have any questions about it, or even just find it useful, please do let me know - dale.lane@gmail.com
|
91
python/currcost.py
Normal file
91
python/currcost.py
Normal file
|
@ -0,0 +1,91 @@
|
|||
import xml.parsers.expat
|
||||
import serial
|
||||
|
||||
# Parses data from a CurrentCost meter
|
||||
#
|
||||
# Note that this is provided to help get you started, but it lacks careful
|
||||
# error-handling or proper documentation.
|
||||
#
|
||||
# If you have any questions about it, or even just find it useful, please do
|
||||
# let me know - dale.lane@gmail.com
|
||||
#
|
||||
#
|
||||
# Dale Lane (http://dalelane.co.uk/blog)
|
||||
#
|
||||
|
||||
YOURCOMPORT = "COM21"
|
||||
|
||||
|
||||
# this class lets you store the CurrentCost XML data as a Python object
|
||||
from currentcostdata import CurrentCostUpdate
|
||||
|
||||
# this class lets you translate the CurrentCost data into values and their timestamps
|
||||
from currentcostdatafunctions import CurrentCostDataFunctions
|
||||
|
||||
# this class lets you store your CurrentCost data
|
||||
from currentcostdatastore import CurrentCostDataStore
|
||||
|
||||
|
||||
# XML parsing functions
|
||||
def start_element(name, attrs):
|
||||
global currentelement
|
||||
currentelement = name
|
||||
def end_element(name):
|
||||
global currentelement
|
||||
currentelement = "none"
|
||||
def char_data(data):
|
||||
global currentelement, newupd
|
||||
newupd.UpdateProperty(currentelement, data)
|
||||
|
||||
currentelement = "none"
|
||||
|
||||
# object to represent the CurrentCost data received
|
||||
newupd = CurrentCostUpdate ()
|
||||
|
||||
# objects to parse and store the data
|
||||
ccfuncs = CurrentCostDataFunctions()
|
||||
ccdb = CurrentCostDataStore()
|
||||
|
||||
ser = None
|
||||
|
||||
try:
|
||||
# connect to the CurrentCost meter
|
||||
ser = serial.Serial(port=YOURCOMPORT, timeout=3)
|
||||
except serial.SerialException, msg:
|
||||
print("Failed to connect to CurrentCost meter :: " + str(msg))
|
||||
exit(1)
|
||||
|
||||
# we keep trying to get an update from the CurrentCost meter
|
||||
# until we successfully populate the CurrentCost data object
|
||||
|
||||
while newupd.WattsDay01 == -1:
|
||||
|
||||
# read a line of XML from the CurrentCost meter
|
||||
line = ser.readline()
|
||||
|
||||
print "> " + line
|
||||
|
||||
try:
|
||||
# parse it
|
||||
p = xml.parsers.expat.ParserCreate()
|
||||
p.StartElementHandler = start_element
|
||||
p.EndElementHandler = end_element
|
||||
p.CharacterDataHandler = char_data
|
||||
p.Parse(line, 1)
|
||||
|
||||
except xml.parsers.expat.ExpatError:
|
||||
print("Received incomplete data from CurrentCost meter. Will try and get a new reading")
|
||||
|
||||
except serial.SerialException, err:
|
||||
print("Failed to receive data from CurrentCost meter :: " + str(err))
|
||||
ser.close()
|
||||
exit(1)
|
||||
|
||||
# finished with serial port - close it
|
||||
ser.close()
|
||||
|
||||
# store it
|
||||
ccfuncs.ParseCurrentCostXML(ccdb, newupd)
|
||||
|
||||
|
||||
exit(0)
|
182
python/currentcostdata.py
Normal file
182
python/currentcostdata.py
Normal file
|
@ -0,0 +1,182 @@
|
|||
from string import atoi, atof
|
||||
|
||||
# Represents the data contained in a single update from a CurrentCost meter
|
||||
#
|
||||
# It's a Python object representation of the XML - as described here:
|
||||
# http://cumbers.wordpress.com/2008/05/07/breakdown-of-currentcost-xml-output/
|
||||
#
|
||||
# Dale Lane (http://dalelane.co.uk/blog)
|
||||
|
||||
class CurrentCostUpdate():
|
||||
kWattsHour02 = -1.1
|
||||
kWattsHour04 = -1.1
|
||||
kWattsHour06 = -1.1
|
||||
kWattsHour08 = -1.1
|
||||
kWattsHour10 = -1.1
|
||||
kWattsHour12 = -1.1
|
||||
kWattsHour14 = -1.1
|
||||
kWattsHour16 = -1.1
|
||||
kWattsHour18 = -1.1
|
||||
kWattsHour20 = -1.1
|
||||
kWattsHour22 = -1.1
|
||||
kWattsHour24 = -1.1
|
||||
kWattsHour26 = -1.1
|
||||
WattsDay01 = -1
|
||||
WattsDay02 = -1
|
||||
WattsDay03 = -1
|
||||
WattsDay04 = -1
|
||||
WattsDay05 = -1
|
||||
WattsDay06 = -1
|
||||
WattsDay07 = -1
|
||||
WattsDay08 = -1
|
||||
WattsDay09 = -1
|
||||
WattsDay10 = -1
|
||||
WattsDay11 = -1
|
||||
WattsDay12 = -1
|
||||
WattsDay13 = -1
|
||||
WattsDay14 = -1
|
||||
WattsDay15 = -1
|
||||
WattsDay16 = -1
|
||||
WattsDay17 = -1
|
||||
WattsDay18 = -1
|
||||
WattsDay19 = -1
|
||||
WattsDay20 = -1
|
||||
WattsDay21 = -1
|
||||
WattsDay22 = -1
|
||||
WattsDay23 = -1
|
||||
WattsDay24 = -1
|
||||
WattsDay25 = -1
|
||||
WattsDay26 = -1
|
||||
WattsDay27 = -1
|
||||
WattsDay28 = -1
|
||||
WattsDay29 = -1
|
||||
WattsDay30 = -1
|
||||
WattsDay31 = -1
|
||||
WattsMonth01 = -1
|
||||
WattsMonth02 = -1
|
||||
WattsMonth03 = -1
|
||||
WattsMonth04 = -1
|
||||
WattsMonth05 = -1
|
||||
WattsMonth06 = -1
|
||||
WattsMonth07 = -1
|
||||
WattsMonth08 = -1
|
||||
WattsMonth09 = -1
|
||||
WattsMonth10 = -1
|
||||
WattsMonth11 = -1
|
||||
WattsMonth12 = -1
|
||||
|
||||
|
||||
def UpdateProperty (self, key, value):
|
||||
if (key == "h02"):
|
||||
self.kWattsHour02 = atof(value)
|
||||
elif (key == "h04"):
|
||||
self.kWattsHour04 = atof(value)
|
||||
elif (key == "h06"):
|
||||
self.kWattsHour06 = atof(value)
|
||||
elif (key == "h08"):
|
||||
self.kWattsHour08 = atof(value)
|
||||
elif (key == "h10"):
|
||||
self.kWattsHour10 = atof(value)
|
||||
elif (key == "h12"):
|
||||
self.kWattsHour12 = atof(value)
|
||||
elif (key == "h14"):
|
||||
self.kWattsHour14 = atof(value)
|
||||
elif (key == "h16"):
|
||||
self.kWattsHour16 = atof(value)
|
||||
elif (key == "h18"):
|
||||
self.kWattsHour18 = atof(value)
|
||||
elif (key == "h20"):
|
||||
self.kWattsHour20 = atof(value)
|
||||
elif (key == "h22"):
|
||||
self.kWattsHour22 = atof(value)
|
||||
elif (key == "h24"):
|
||||
self.kWattsHour24 = atof(value)
|
||||
elif (key == "h26"):
|
||||
self.kWattsHour26 = atof(value)
|
||||
elif (key == "d01"):
|
||||
self.WattsDay01 = atoi(value)
|
||||
elif (key == "d02"):
|
||||
self.WattsDay02 = atoi(value)
|
||||
elif (key == "d03"):
|
||||
self.WattsDay03 = atoi(value)
|
||||
elif (key == "d04"):
|
||||
self.WattsDay04 = atoi(value)
|
||||
elif (key == "d05"):
|
||||
self.WattsDay05 = atoi(value)
|
||||
elif (key == "d06"):
|
||||
self.WattsDay06 = atoi(value)
|
||||
elif (key == "d07"):
|
||||
self.WattsDay07 = atoi(value)
|
||||
elif (key == "d08"):
|
||||
self.WattsDay08 = atoi(value)
|
||||
elif (key == "d09"):
|
||||
self.WattsDay09 = atoi(value)
|
||||
elif (key == "d10"):
|
||||
self.WattsDay10 = atoi(value)
|
||||
elif (key == "d11"):
|
||||
self.WattsDay11 = atoi(value)
|
||||
elif (key == "d12"):
|
||||
self.WattsDay12 = atoi(value)
|
||||
elif (key == "d13"):
|
||||
self.WattsDay13 = atoi(value)
|
||||
elif (key == "d14"):
|
||||
self.WattsDay14 = atoi(value)
|
||||
elif (key == "d15"):
|
||||
self.WattsDay15 = atoi(value)
|
||||
elif (key == "d16"):
|
||||
self.WattsDay16 = atoi(value)
|
||||
elif (key == "d17"):
|
||||
self.WattsDay17 = atoi(value)
|
||||
elif (key == "d18"):
|
||||
self.WattsDay18 = atoi(value)
|
||||
elif (key == "d19"):
|
||||
self.WattsDay19 = atoi(value)
|
||||
elif (key == "d20"):
|
||||
self.WattsDay20 = atoi(value)
|
||||
elif (key == "d21"):
|
||||
self.WattsDay21 = atoi(value)
|
||||
elif (key == "d22"):
|
||||
self.WattsDay22 = atoi(value)
|
||||
elif (key == "d23"):
|
||||
self.WattsDay23 = atoi(value)
|
||||
elif (key == "d24"):
|
||||
self.WattsDay24 = atoi(value)
|
||||
elif (key == "d25"):
|
||||
self.WattsDay25 = atoi(value)
|
||||
elif (key == "d26"):
|
||||
self.WattsDay26 = atoi(value)
|
||||
elif (key == "d27"):
|
||||
self.WattsDay27 = atoi(value)
|
||||
elif (key == "d28"):
|
||||
self.WattsDay28 = atoi(value)
|
||||
elif (key == "d29"):
|
||||
self.WattsDay29 = atoi(value)
|
||||
elif (key == "d30"):
|
||||
self.WattsDay30 = atoi(value)
|
||||
elif (key == "d31"):
|
||||
self.WattsDay31 = atoi(value)
|
||||
elif (key == "m01"):
|
||||
self.WattsMonth01 = atoi(value)
|
||||
elif (key == "m02"):
|
||||
self.WattsMonth02 = atoi(value)
|
||||
elif (key == "m03"):
|
||||
self.WattsMonth03 = atoi(value)
|
||||
elif (key == "m04"):
|
||||
self.WattsMonth04 = atoi(value)
|
||||
elif (key == "m05"):
|
||||
self.WattsMonth05 = atoi(value)
|
||||
elif (key == "m06"):
|
||||
self.WattsMonth06 = atoi(value)
|
||||
elif (key == "m07"):
|
||||
self.WattsMonth07 = atoi(value)
|
||||
elif (key == "m08"):
|
||||
self.WattsMonth08 = atoi(value)
|
||||
elif (key == "m09"):
|
||||
self.WattsMonth09 = atoi(value)
|
||||
elif (key == "m10"):
|
||||
self.WattsMonth10 = atoi(value)
|
||||
elif (key == "m11"):
|
||||
self.WattsMonth11 = atoi(value)
|
||||
elif (key == "m12"):
|
||||
self.WattsMonth12 = atoi(value)
|
||||
|
140
python/currentcostdatafunctions.py
Normal file
140
python/currentcostdatafunctions.py
Normal file
|
@ -0,0 +1,140 @@
|
|||
import datetime
|
||||
|
||||
from currentcostdatastore import CurrentCostDataStore
|
||||
|
||||
# A CurrentCost update (as described in currentcostdata.py) is a relative
|
||||
# description of your electricity usage.
|
||||
#
|
||||
# E.g. you used this much electricity 2 hours ago
|
||||
#
|
||||
# This class converts this into an absolute description of your electricity
|
||||
# usage.
|
||||
#
|
||||
# E.g. you used this much electricity at 1pm
|
||||
#
|
||||
#
|
||||
# Dale Lane (http://dalelane.co.uk/blog)
|
||||
|
||||
|
||||
class CurrentCostDataFunctions():
|
||||
|
||||
def ParseCurrentCostXML(self, ccdb, newupd):
|
||||
today = datetime.date.today()
|
||||
#
|
||||
ccdb.StoreMonthData(self.GetOldMonth(today, 1), newupd.WattsMonth01)
|
||||
ccdb.StoreMonthData(self.GetOldMonth(today, 2), newupd.WattsMonth02)
|
||||
ccdb.StoreMonthData(self.GetOldMonth(today, 3), newupd.WattsMonth03)
|
||||
ccdb.StoreMonthData(self.GetOldMonth(today, 4), newupd.WattsMonth04)
|
||||
ccdb.StoreMonthData(self.GetOldMonth(today, 5), newupd.WattsMonth05)
|
||||
ccdb.StoreMonthData(self.GetOldMonth(today, 6), newupd.WattsMonth06)
|
||||
ccdb.StoreMonthData(self.GetOldMonth(today, 7), newupd.WattsMonth07)
|
||||
ccdb.StoreMonthData(self.GetOldMonth(today, 8), newupd.WattsMonth08)
|
||||
ccdb.StoreMonthData(self.GetOldMonth(today, 9), newupd.WattsMonth09)
|
||||
ccdb.StoreMonthData(self.GetOldMonth(today, 10), newupd.WattsMonth10)
|
||||
ccdb.StoreMonthData(self.GetOldMonth(today, 11), newupd.WattsMonth11)
|
||||
ccdb.StoreMonthData(self.GetOldMonth(today, 12), newupd.WattsMonth12)
|
||||
#
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 1), newupd.WattsDay01)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 2), newupd.WattsDay02)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 3), newupd.WattsDay03)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 4), newupd.WattsDay04)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 5), newupd.WattsDay05)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 6), newupd.WattsDay06)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 7), newupd.WattsDay07)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 8), newupd.WattsDay08)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 9), newupd.WattsDay09)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 10), newupd.WattsDay10)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 11), newupd.WattsDay11)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 12), newupd.WattsDay12)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 13), newupd.WattsDay13)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 14), newupd.WattsDay14)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 15), newupd.WattsDay15)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 16), newupd.WattsDay16)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 17), newupd.WattsDay17)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 18), newupd.WattsDay18)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 19), newupd.WattsDay19)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 20), newupd.WattsDay20)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 21), newupd.WattsDay21)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 22), newupd.WattsDay22)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 23), newupd.WattsDay23)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 24), newupd.WattsDay24)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 25), newupd.WattsDay25)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 26), newupd.WattsDay26)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 27), newupd.WattsDay27)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 28), newupd.WattsDay28)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 29), newupd.WattsDay29)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 30), newupd.WattsDay30)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 31), newupd.WattsDay31)
|
||||
#
|
||||
currtime = datetime.datetime.now()
|
||||
#
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 0), newupd.kWattsHour02)
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 2), newupd.kWattsHour04)
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 4), newupd.kWattsHour06)
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 6), newupd.kWattsHour08)
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 8), newupd.kWattsHour10)
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 10), newupd.kWattsHour12)
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 12), newupd.kWattsHour14)
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 14), newupd.kWattsHour16)
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 16), newupd.kWattsHour18)
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 18), newupd.kWattsHour20)
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 20), newupd.kWattsHour22)
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 22), newupd.kWattsHour24)
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 24), newupd.kWattsHour26)
|
||||
|
||||
|
||||
def GetOldMonth(self, referenceDate, monthsago):
|
||||
newmonth = referenceDate.month - monthsago
|
||||
newyear = referenceDate.year
|
||||
|
||||
if newmonth <= 0:
|
||||
newmonth += 12
|
||||
newyear -= 1
|
||||
|
||||
return datetime.date(newyear, newmonth, 1)
|
||||
|
||||
|
||||
def GetOldDay(self, referenceDate, daysago):
|
||||
newday = referenceDate.day - daysago
|
||||
newmonth = referenceDate.month
|
||||
newyear = referenceDate.year
|
||||
|
||||
if newday <= 0:
|
||||
d = datetime.timedelta(days=daysago)
|
||||
sub = referenceDate - d
|
||||
newday = sub.day
|
||||
newmonth = sub.month
|
||||
newyear = sub.year
|
||||
|
||||
return datetime.date(newyear, newmonth, newday)
|
||||
|
||||
|
||||
|
||||
def GetOldHour(self, referenceDate, hoursago):
|
||||
if referenceDate.hour % 2 == 0:
|
||||
hoursago = hoursago + 1
|
||||
|
||||
newhour = referenceDate.hour - hoursago
|
||||
newday = referenceDate.day
|
||||
newmonth = referenceDate.month
|
||||
newyear = referenceDate.year
|
||||
|
||||
if newhour < -24:
|
||||
newhour += 48
|
||||
d = datetime.timedelta(hours=hoursago)
|
||||
sub = referenceDate - d
|
||||
newday = sub.day
|
||||
newmonth = sub.month
|
||||
newyear = sub.year
|
||||
elif newhour < 0:
|
||||
newhour += 24
|
||||
d = datetime.timedelta(hours=hoursago)
|
||||
sub = referenceDate - d
|
||||
newday = sub.day
|
||||
newmonth = sub.month
|
||||
newyear = sub.year
|
||||
|
||||
return datetime.datetime(newyear, newmonth, newday, newhour, 0, 0)
|
||||
|
||||
|
||||
|
21
python/currentcostdatastore.py
Normal file
21
python/currentcostdatastore.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
# Stores your CurrentCost data
|
||||
#
|
||||
# Okay, so this doesn't really store data.
|
||||
#
|
||||
# These are really just stubs, replace them functions which store the data
|
||||
# the way you like
|
||||
# I'm a big fan of pysqlite, but you can use anything you like.
|
||||
#
|
||||
# Dale Lane (http://dalelane.co.uk/blog)
|
||||
#
|
||||
|
||||
class CurrentCostDataStore():
|
||||
|
||||
def StoreHourData (self, updatetimestamp, ccvalue):
|
||||
print "2-HOUR :: " + str(updatetimestamp) + " = " + str(ccvalue) + "kWh"
|
||||
|
||||
def StoreDayData (self, updatetimestamp, ccvalue):
|
||||
print "DAY :: " + str(updatetimestamp) + " = " + str(ccvalue) + "kWh"
|
||||
|
||||
def StoreMonthData (self, updatetimestamp, ccvalue):
|
||||
print "MONTH :: " + str(updatetimestamp) + " = " + str(ccvalue) + "kWh"
|
Loading…
Add table
Add a link
Reference in a new issue