From 0ff662a8b558e1d0cdfa3ed362e8c9c525f14b11 Mon Sep 17 00:00:00 2001 From: Dale Lane Date: Mon, 17 Nov 2008 00:35:33 +0000 Subject: [PATCH] --- .../currentcost/CurrentCostHistory.java | 258 +++++++++++++ .../currentcost/CurrentCostParser.java | 355 ++++++++++++++++++ .../currentcost/CurrentCostSample.java | 143 +++++++ .../currentcost/CurrentCostUpdate.java | 88 +++++ .../currentcost/calendar/DayData.java | 63 ++++ .../currentcost/calendar/HourData.java | 89 +++++ .../currentcost/calendar/MonthData.java | 55 +++ .../currentcost/calendar/YearData.java | 42 +++ python/README.txt | 7 + python/currcost.py | 91 +++++ python/currentcostdata.py | 182 +++++++++ python/currentcostdatafunctions.py | 140 +++++++ python/currentcostdatastore.py | 21 ++ 13 files changed, 1534 insertions(+) create mode 100644 java/dalelane/currentcost/CurrentCostHistory.java create mode 100644 java/dalelane/currentcost/CurrentCostParser.java create mode 100644 java/dalelane/currentcost/CurrentCostSample.java create mode 100644 java/dalelane/currentcost/CurrentCostUpdate.java create mode 100644 java/dalelane/currentcost/calendar/DayData.java create mode 100644 java/dalelane/currentcost/calendar/HourData.java create mode 100644 java/dalelane/currentcost/calendar/MonthData.java create mode 100644 java/dalelane/currentcost/calendar/YearData.java create mode 100644 python/README.txt create mode 100644 python/currcost.py create mode 100644 python/currentcostdata.py create mode 100644 python/currentcostdatafunctions.py create mode 100644 python/currentcostdatastore.py diff --git a/java/dalelane/currentcost/CurrentCostHistory.java b/java/dalelane/currentcost/CurrentCostHistory.java new file mode 100644 index 0000000..5b3a460 --- /dev/null +++ b/java/dalelane/currentcost/CurrentCostHistory.java @@ -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 yearDataCollection = new Hashtable(); + public Hashtable monthDataCollection = new Hashtable(); + public Hashtable dayDataCollection = new Hashtable(); + public Hashtable hourDataCollection = new Hashtable(); + + + 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 enHr = hourDataCollection.keys(); + while(enHr.hasMoreElements()) + { + HourData tm = enHr.nextElement(); + sb.append(tm.toString() + " = " + hourDataCollection.get(tm) + System.getProperty("line.separator")); + } + + Enumeration enDay = dayDataCollection.keys(); + while(enDay.hasMoreElements()) + { + DayData tm = enDay.nextElement(); + sb.append(tm.toString() + " = " + dayDataCollection.get(tm) + System.getProperty("line.separator")); + } + + Enumeration enMth = monthDataCollection.keys(); + while(enMth.hasMoreElements()) + { + MonthData tm = enMth.nextElement(); + sb.append(tm.toString() + " = " + monthDataCollection.get(tm) + System.getProperty("line.separator")); + } + + Enumeration enYr = yearDataCollection.keys(); + while(enYr.hasMoreElements()) + { + YearData tm = enYr.nextElement(); + sb.append(tm.toString() + " = " + yearDataCollection.get(tm) + System.getProperty("line.separator")); + } + + return sb.toString(); + } +} \ No newline at end of file diff --git a/java/dalelane/currentcost/CurrentCostParser.java b/java/dalelane/currentcost/CurrentCostParser.java new file mode 100644 index 0000000..d05388d --- /dev/null +++ b/java/dalelane/currentcost/CurrentCostParser.java @@ -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")) + { + /* is inside , or + * so we need to check what was the last element we started, to know + * which 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; + } + } + } +} \ No newline at end of file diff --git a/java/dalelane/currentcost/CurrentCostSample.java b/java/dalelane/currentcost/CurrentCostSample.java new file mode 100644 index 0000000..72fc91f --- /dev/null +++ b/java/dalelane/currentcost/CurrentCostSample.java @@ -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); + } + +} diff --git a/java/dalelane/currentcost/CurrentCostUpdate.java b/java/dalelane/currentcost/CurrentCostUpdate.java new file mode 100644 index 0000000..782a2ed --- /dev/null +++ b/java/dalelane/currentcost/CurrentCostUpdate.java @@ -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; +} \ No newline at end of file diff --git a/java/dalelane/currentcost/calendar/DayData.java b/java/dalelane/currentcost/calendar/DayData.java new file mode 100644 index 0000000..7c04f12 --- /dev/null +++ b/java/dalelane/currentcost/calendar/DayData.java @@ -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; + } +} \ No newline at end of file diff --git a/java/dalelane/currentcost/calendar/HourData.java b/java/dalelane/currentcost/calendar/HourData.java new file mode 100644 index 0000000..67c8a53 --- /dev/null +++ b/java/dalelane/currentcost/calendar/HourData.java @@ -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; + } +} \ No newline at end of file diff --git a/java/dalelane/currentcost/calendar/MonthData.java b/java/dalelane/currentcost/calendar/MonthData.java new file mode 100644 index 0000000..559178a --- /dev/null +++ b/java/dalelane/currentcost/calendar/MonthData.java @@ -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; + } +} \ No newline at end of file diff --git a/java/dalelane/currentcost/calendar/YearData.java b/java/dalelane/currentcost/calendar/YearData.java new file mode 100644 index 0000000..642c3fb --- /dev/null +++ b/java/dalelane/currentcost/calendar/YearData.java @@ -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; + } +} \ No newline at end of file diff --git a/python/README.txt b/python/README.txt new file mode 100644 index 0000000..207b3a4 --- /dev/null +++ b/python/README.txt @@ -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 \ No newline at end of file diff --git a/python/currcost.py b/python/currcost.py new file mode 100644 index 0000000..44944ff --- /dev/null +++ b/python/currcost.py @@ -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) diff --git a/python/currentcostdata.py b/python/currentcostdata.py new file mode 100644 index 0000000..951225d --- /dev/null +++ b/python/currentcostdata.py @@ -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) + diff --git a/python/currentcostdatafunctions.py b/python/currentcostdatafunctions.py new file mode 100644 index 0000000..a5797fb --- /dev/null +++ b/python/currentcostdatafunctions.py @@ -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) + + + diff --git a/python/currentcostdatastore.py b/python/currentcostdatastore.py new file mode 100644 index 0000000..e166935 --- /dev/null +++ b/python/currentcostdatastore.py @@ -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"