diff --git a/dotnet/CurrentCostHistory.cs b/dotnet/CurrentCostHistory.cs new file mode 100644 index 0000000..67366a5 --- /dev/null +++ b/dotnet/CurrentCostHistory.cs @@ -0,0 +1,655 @@ +using System; +using System.Collections.Generic; +using System.Text; + +/* + * 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) + */ + +namespace CurrentCost +{ + public class CurrentCostHistory + { + public Dictionary yearDataCollection = new Dictionary(); + public Dictionary monthDataCollection = new Dictionary(); + public Dictionary dayDataCollection = new Dictionary(); + public Dictionary hourDataCollection = new Dictionary(); + + + public void UpdateData(CurrentCostUpdate datasource) + { + // --- YEARS ---------------------------------- + YearData y1 = YearData.GetOldDate(datasource.TimeStamp, 1); + yearDataCollection[y1] = datasource.WattsYear1; + + YearData y2 = YearData.GetOldDate(datasource.TimeStamp, 2); + yearDataCollection[y2] = datasource.WattsYear2; + + YearData y3 = YearData.GetOldDate(datasource.TimeStamp, 3); + yearDataCollection[y3] = datasource.WattsYear3; + + YearData y4 = YearData.GetOldDate(datasource.TimeStamp, 4); + yearDataCollection[y4] = datasource.WattsYear4; + + // --- MONTHS --------------------------------- + MonthData m1 = MonthData.GetOldDate(datasource.TimeStamp, 1); + monthDataCollection[m1] = datasource.WattsMonth01; + + MonthData m2 = MonthData.GetOldDate(datasource.TimeStamp, 2); + monthDataCollection[m2] = datasource.WattsMonth02; + + MonthData m3 = MonthData.GetOldDate(datasource.TimeStamp, 3); + monthDataCollection[m3] = datasource.WattsMonth03; + + MonthData m4 = MonthData.GetOldDate(datasource.TimeStamp, 4); + monthDataCollection[m4] = datasource.WattsMonth04; + + MonthData m5 = MonthData.GetOldDate(datasource.TimeStamp, 5); + monthDataCollection[m5] = datasource.WattsMonth05; + + MonthData m6 = MonthData.GetOldDate(datasource.TimeStamp, 6); + monthDataCollection[m6] = datasource.WattsMonth06; + + MonthData m7 = MonthData.GetOldDate(datasource.TimeStamp, 7); + monthDataCollection[m7] = datasource.WattsMonth07; + + MonthData m8 = MonthData.GetOldDate(datasource.TimeStamp, 8); + monthDataCollection[m8] = datasource.WattsMonth08; + + MonthData m9 = MonthData.GetOldDate(datasource.TimeStamp, 9); + monthDataCollection[m9] = datasource.WattsMonth09; + + MonthData m10 = MonthData.GetOldDate(datasource.TimeStamp, 10); + monthDataCollection[m10] = datasource.WattsMonth10; + + MonthData m11 = MonthData.GetOldDate(datasource.TimeStamp, 11); + monthDataCollection[m11] = datasource.WattsMonth11; + + MonthData m12 = MonthData.GetOldDate(datasource.TimeStamp, 12); + monthDataCollection[m12] = datasource.WattsMonth12; + + // --- DAYS ------------------------------------ + DayData d1 = DayData.GetOldDate(datasource.TimeStamp, 1); + dayDataCollection[d1] = datasource.WattsDay01; + + DayData d2 = DayData.GetOldDate(datasource.TimeStamp, 2); + dayDataCollection[d2] = datasource.WattsDay02; + + DayData d3 = DayData.GetOldDate(datasource.TimeStamp, 3); + dayDataCollection[d3] = datasource.WattsDay03; + + DayData d4 = DayData.GetOldDate(datasource.TimeStamp, 4); + dayDataCollection[d4] = datasource.WattsDay04; + + DayData d5 = DayData.GetOldDate(datasource.TimeStamp, 5); + dayDataCollection[d5] = datasource.WattsDay05; + + DayData d6 = DayData.GetOldDate(datasource.TimeStamp, 6); + dayDataCollection[d6] = datasource.WattsDay06; + + DayData d7 = DayData.GetOldDate(datasource.TimeStamp, 7); + dayDataCollection[d7] = datasource.WattsDay07; + + DayData d8 = DayData.GetOldDate(datasource.TimeStamp, 8); + dayDataCollection[d8] = datasource.WattsDay08; + + DayData d9 = DayData.GetOldDate(datasource.TimeStamp, 9); + dayDataCollection[d9] = datasource.WattsDay09; + + DayData d10 = DayData.GetOldDate(datasource.TimeStamp, 10); + dayDataCollection[d10] = datasource.WattsDay10; + + DayData d11 = DayData.GetOldDate(datasource.TimeStamp, 11); + dayDataCollection[d11] = datasource.WattsDay11; + + DayData d12 = DayData.GetOldDate(datasource.TimeStamp, 12); + dayDataCollection[d12] = datasource.WattsDay12; + + DayData d13 = DayData.GetOldDate(datasource.TimeStamp, 13); + dayDataCollection[d13] = datasource.WattsDay13; + + DayData d14 = DayData.GetOldDate(datasource.TimeStamp, 14); + dayDataCollection[d14] = datasource.WattsDay14; + + DayData d15 = DayData.GetOldDate(datasource.TimeStamp, 15); + dayDataCollection[d15] = datasource.WattsDay15; + + DayData d16 = DayData.GetOldDate(datasource.TimeStamp, 16); + dayDataCollection[d16] = datasource.WattsDay16; + + DayData d17 = DayData.GetOldDate(datasource.TimeStamp, 17); + dayDataCollection[d17] = datasource.WattsDay17; + + DayData d18 = DayData.GetOldDate(datasource.TimeStamp, 18); + dayDataCollection[d18] = datasource.WattsDay18; + + DayData d19 = DayData.GetOldDate(datasource.TimeStamp, 19); + dayDataCollection[d19] = datasource.WattsDay19; + + DayData d20 = DayData.GetOldDate(datasource.TimeStamp, 20); + dayDataCollection[d20] = datasource.WattsDay20; + + DayData d21 = DayData.GetOldDate(datasource.TimeStamp, 21); + dayDataCollection[d21] = datasource.WattsDay21; + + DayData d22 = DayData.GetOldDate(datasource.TimeStamp, 22); + dayDataCollection[d22] = datasource.WattsDay22; + + DayData d23 = DayData.GetOldDate(datasource.TimeStamp, 23); + dayDataCollection[d23] = datasource.WattsDay23; + + DayData d24 = DayData.GetOldDate(datasource.TimeStamp, 24); + dayDataCollection[d24] = datasource.WattsDay24; + + DayData d25 = DayData.GetOldDate(datasource.TimeStamp, 25); + dayDataCollection[d25] = datasource.WattsDay25; + + DayData d26 = DayData.GetOldDate(datasource.TimeStamp, 26); + dayDataCollection[d26] = datasource.WattsDay26; + + DayData d27 = DayData.GetOldDate(datasource.TimeStamp, 27); + dayDataCollection[d27] = datasource.WattsDay27; + + DayData d28 = DayData.GetOldDate(datasource.TimeStamp, 28); + dayDataCollection[d28] = datasource.WattsDay28; + + DayData d29 = DayData.GetOldDate(datasource.TimeStamp, 29); + dayDataCollection[d29] = datasource.WattsDay29; + + DayData d30 = DayData.GetOldDate(datasource.TimeStamp, 30); + dayDataCollection[d30] = datasource.WattsDay30; + + DayData d31 = DayData.GetOldDate(datasource.TimeStamp, 31); + dayDataCollection[d31] = datasource.WattsDay31; + + // --- HOURS ---------------------------------- + HourData h0 = HourData.GetOldDate(datasource.TimeStamp, 0); + hourDataCollection[h0] = datasource.kWattsHour02; + + HourData h2 = HourData.GetOldDate(datasource.TimeStamp, 2); + hourDataCollection[h2] = datasource.kWattsHour04; + + HourData h4 = HourData.GetOldDate(datasource.TimeStamp, 4); + hourDataCollection[h4] = datasource.kWattsHour06; + + HourData h6 = HourData.GetOldDate(datasource.TimeStamp, 6); + hourDataCollection[h6] = datasource.kWattsHour08; + + HourData h8 = HourData.GetOldDate(datasource.TimeStamp, 8); + hourDataCollection[h8] = datasource.kWattsHour10; + + HourData h10 = HourData.GetOldDate(datasource.TimeStamp, 10); + hourDataCollection[h10] = datasource.kWattsHour12; + + HourData h12 = HourData.GetOldDate(datasource.TimeStamp, 12); + hourDataCollection[h12] = datasource.kWattsHour14; + + HourData h14 = HourData.GetOldDate(datasource.TimeStamp, 14); + hourDataCollection[h14] = datasource.kWattsHour16; + + HourData h16 = HourData.GetOldDate(datasource.TimeStamp, 16); + hourDataCollection[h16] = datasource.kWattsHour18; + + HourData h18 = HourData.GetOldDate(datasource.TimeStamp, 18); + hourDataCollection[h18] = datasource.kWattsHour20; + + HourData h20 = HourData.GetOldDate(datasource.TimeStamp, 20); + hourDataCollection[h20] = datasource.kWattsHour22; + + HourData h22 = HourData.GetOldDate(datasource.TimeStamp, 22); + hourDataCollection[h22] = datasource.kWattsHour24; + + HourData h24 = HourData.GetOldDate(datasource.TimeStamp, 24); + hourDataCollection[h24] = datasource.kWattsHour26; + } + + + /***************************************************/ + /* debug */ + /***************************************************/ + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + + foreach (KeyValuePair kvp in hourDataCollection) + { + sb.AppendLine(kvp.Key + " = " + kvp.Value); + } + foreach (KeyValuePair kvp in dayDataCollection) + { + sb.AppendLine(kvp.Key + " = " + kvp.Value); + } + foreach (KeyValuePair kvp in monthDataCollection) + { + sb.AppendLine(kvp.Key + " = " + kvp.Value); + } + foreach (KeyValuePair kvp in yearDataCollection) + { + sb.AppendLine(kvp.Key + " = " + kvp.Value); + } + + return sb.ToString(); + } + + + + + /***********************************************************/ + /* inner classes used to define custom calendar types */ + /***********************************************************/ + + + public abstract class CurrentCostTime + { + } + + + /*****************************************************/ + /* Represents the date for a CurrentCost record of a */ + /* year's electricity usage. */ + /*****************************************************/ + public class YearData : CurrentCostTime, IComparable + { + public int Year; + + public static YearData GetOldDate(DateTime referenceDate, int yearsago) + { + YearData oldYear = new YearData(); + oldYear.Year = referenceDate.Year - yearsago; + + return oldYear; + } + + /**************************************************/ + /* we add the following methods so that we can */ + /* store YearData in Dictionary objects */ + /**************************************************/ + + public int CompareTo(object obj) + { + if (obj is YearData) + { + YearData comp = (YearData)obj; + + return Year.CompareTo(comp.Year); + } + + throw new ArgumentException(); + } + + public override bool Equals(object compare) + { + if (compare is YearData) + { + if (Year == ((YearData)compare).Year) + { + return true; + } + } + return false; + } + + public override int GetHashCode() + { + return Year.GetHashCode(); + } + + /***************************************************/ + /* debug */ + /***************************************************/ + public override string ToString() + { + return Year.ToString(); + } + } + + + /*****************************************************/ + /* Represents the date for a CurrentCost record of a */ + /* month's electricity usage. */ + /*****************************************************/ + public class MonthData : CurrentCostTime, IComparable + { + public int Month; + public int Year; + + + public static MonthData GetOldDate(DateTime referenceDate, int monthsago) + { + MonthData oldMonth = new MonthData(); + int newmonth = referenceDate.Month - monthsago; + int newyear = referenceDate.Year; + + if (newmonth <= 0) + { + newmonth += 12; + newyear -= 1; + } + + oldMonth.Year = newyear; + oldMonth.Month = newmonth; + + return oldMonth; + } + + /**************************************************/ + /* we add the following methods so that we can */ + /* store MonthData in Dictionary objects */ + /**************************************************/ + + public int CompareTo(object obj) + { + if (obj is MonthData) + { + MonthData comp = (MonthData)obj; + + switch (Year.CompareTo(comp.Year)) + { + case -1: + return -1; + case 1: + return 1; + case 0: + return Month.CompareTo(comp.Month); + } + } + + throw new ArgumentException(); + } + + public override bool Equals(object compare) + { + if (compare is MonthData) + { + if ((Year == ((MonthData)compare).Year) && + (Month == ((MonthData)compare).Month)) + { + return true; + } + } + return false; + } + + public override int GetHashCode() + { + return Month.GetHashCode() ^ Year.GetHashCode(); + } + + /***************************************************/ + /* debug */ + /***************************************************/ + + public override string ToString() + { + switch (Month) + { + case 1: + return "Jan " + Year; + case 2: + return "Feb " + Year; + case 3: + return "Mar " + Year; + case 4: + return "Apr " + Year; + case 5: + return "May " + Year; + case 6: + return "Jun " + Year; + case 7: + return "Jul " + Year; + case 8: + return "Aug " + Year; + case 9: + return "Sep " + Year; + case 10: + return "Oct " + Year; + case 11: + return "Nov " + Year; + case 12: + return "Dec " + Year; + default: + return Month + " / " + Year; + } + } + } + + + + /*****************************************************/ + /* Represents the date for a CurrentCost record of a */ + /* days's electricity usage. */ + /*****************************************************/ + public class DayData : CurrentCostTime, IComparable + { + public int Date; + public int Month; + public int Year; + + + public static DayData GetOldDate(DateTime referenceDate, int daysago) + { + DayData oldDay = new DayData(); + int newday = referenceDate.Day - daysago; + int newmonth = referenceDate.Month; + int newyear = referenceDate.Year; + + if (newday <= 0) + { + DateTime sub = referenceDate.Subtract(new TimeSpan(daysago, 0, 0, 0)); + newday = sub.Day; + newmonth = sub.Month; + newyear = sub.Year; + } + + oldDay.Date = newday; + oldDay.Month = newmonth; + oldDay.Year = newyear; + + return oldDay; + } + + /**************************************************/ + /* we add the following methods so that we can */ + /* store DayData in Dictionary objects */ + /**************************************************/ + + public int CompareTo(object obj) + { + if (obj is DayData) + { + DayData comp = (DayData)obj; + + switch (Year.CompareTo(comp.Year)) + { + case -1: + return -1; + case 1: + return 1; + case 0: + switch (Month.CompareTo(comp.Month)) + { + case -1: + return -1; + case 1: + return 1; + case 0: + return Date.CompareTo(comp.Date); + } + break; + } + } + + throw new ArgumentException(); + } + + public override bool Equals(object compare) + { + if (compare is DayData) + { + if ((Year == ((DayData)compare).Year) && + (Month == ((DayData)compare).Month) && + (Date == ((DayData)compare).Date)) + { + return true; + } + } + return false; + } + + public override int GetHashCode() + { + return Date.GetHashCode() ^ Month.GetHashCode() ^ Year.GetHashCode(); + } + + /***************************************************/ + /* debug */ + /***************************************************/ + + public override string ToString() + { + return Date + "/" + Month + "/" + Year; + } + } + + + /******************************************************/ + /* Represents the date for a CurrentCost record of an */ + /* hour's electricity usage. */ + /******************************************************/ + + public class HourData : CurrentCostTime, IComparable + { + public int TwoHourBlock; + public int Date; + public int Month; + public int Year; + + + public static HourData GetOldDate(DateTime referenceDate, int hoursago) + { + int start = referenceDate.Hour; + if ((start % 2) == 0) + { + hoursago += 1; + } + + int newhour = start - hoursago; + int newday = referenceDate.Day; + int newmonth = referenceDate.Month; + int newyear = referenceDate.Year; + + if (newhour < -24) + { + newhour += 48; + + DateTime sub = referenceDate.Subtract(new TimeSpan(1, 0, 0, 0)); + newday = sub.Day; + newmonth = sub.Month; + newyear = sub.Year; + } + else if (newhour < 0) + { + newhour += 24; + + DateTime sub = referenceDate.Subtract(new TimeSpan(1, 0, 0, 0)); + newday = sub.Day; + newmonth = sub.Month; + newyear = sub.Year; + } + + HourData oldHour = new HourData(); + oldHour.TwoHourBlock = newhour; + oldHour.Date = newday; + oldHour.Month = newmonth; + oldHour.Year = newyear; + + return oldHour; + } + + + /**************************************************/ + /* we add the following methods so that we can */ + /* store DayData in Dictionary objects */ + /**************************************************/ + + public int CompareTo(object obj) + { + if (obj is HourData) + { + HourData comp = (HourData)obj; + + switch (Year.CompareTo(comp.Year)) + { + case -1: + return -1; + case 1: + return 1; + case 0: + switch (Month.CompareTo(comp.Month)) + { + case -1: + return -1; + case 1: + return 1; + case 0: + switch (Date.CompareTo(comp.Date)) + { + case -1: + return -1; + case 1: + return 1; + case 0: + return TwoHourBlock.CompareTo(comp.TwoHourBlock); + } + break; + } + break; + } + } + + throw new ArgumentException(); + } + + public override bool Equals(object compare) + { + if (compare is HourData) + { + if ((TwoHourBlock == ((HourData)compare).TwoHourBlock) && + (Year == ((HourData)compare).Year) && + (Month == ((HourData)compare).Month) && + (Date == ((HourData)compare).Date)) + { + return true; + } + } + return false; + } + + public override int GetHashCode() + { + return TwoHourBlock.GetHashCode() ^ Date.GetHashCode() ^ Month.GetHashCode() ^ Year.GetHashCode(); + } + + /***************************************************/ + /* debug */ + /***************************************************/ + + public override string ToString() + { + return TwoHourBlock + ":00 " + Date + "/" + Month + "/" + Year; + } + } + } +} diff --git a/dotnet/CurrentCostProgram.cs b/dotnet/CurrentCostProgram.cs new file mode 100644 index 0000000..c45f000 --- /dev/null +++ b/dotnet/CurrentCostProgram.cs @@ -0,0 +1,44 @@ +using System; +using System.Text; + + +/* + * 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) + */ + +namespace CurrentCost +{ + class CurrentCostProgram + { + static void Main(string[] args) + { + /* define the connection to the CurrentCost meter */ + SerialPortAccess meter = new SerialPortAccess(); + meter.ComPort = "COM21"; + + /* get a single update from the CurrentCost meter */ + CurrentCostUpdate ccUpdate = meter.GetSingleUpdate(); + + /* create somewhere to store the CurrentCost data */ + /* this contains Dictionary objects that, in a real application, */ + /* you will want to persist between running the app, rather than*/ + /* creating an empty collection like this every time */ + CurrentCostHistory historyStore = new CurrentCostHistory(); + + /* store the update in the history collection */ + historyStore.UpdateData(ccUpdate); + + /* print out the contents to check it worked */ + Console.WriteLine(historyStore); + } + } +} diff --git a/dotnet/CurrentCostUpdate.cs b/dotnet/CurrentCostUpdate.cs new file mode 100644 index 0000000..5ff0391 --- /dev/null +++ b/dotnet/CurrentCostUpdate.cs @@ -0,0 +1,424 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; + +/* + * 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/ + * + * Class includes a constructor to create an update object from a line of + * CurrentCost XML. + * + * Dale Lane (http://dalelane.co.uk/blog) + */ + +namespace CurrentCost +{ + public class CurrentCostUpdate + { + public bool ValidUpdate = false; + + public int DaysSinceBirth; + public DateTime TimeStamp; + public string MeterName; + public int MeterId; + public int MeterType; + public string MeterSoftwareVersion; + public int Channel1Watts; + public int Channel2Watts; + public int Channel3Watts; + public string 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; + + + public CurrentCostUpdate() + { + // invalid by default + ValidUpdate = false; + } + + public CurrentCostUpdate(string xmloutput) + : this(xmloutput, false) + { + + } + + public CurrentCostUpdate(string xmloutput, bool UseLocalTime) + { + XmlReaderSettings settings = new XmlReaderSettings(); + settings.ConformanceLevel = ConformanceLevel.Fragment; + settings.IgnoreComments = true; + settings.IgnoreWhitespace = true; + + XmlReader reader = XmlReader.Create(new System.IO.StringReader(xmloutput)); + + try + { + reader.Read(); + reader.ReadStartElement("msg"); + + reader.ReadStartElement("date"); + + reader.ReadStartElement("dsb"); + DaysSinceBirth = reader.ReadContentAsInt(); + reader.ReadEndElement(); + + reader.ReadStartElement("hr"); + int hrs = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("min"); + int mins = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("sec"); + int secs = reader.ReadContentAsInt(); + reader.ReadEndElement(); + if (UseLocalTime) + { + TimeStamp = DateTime.Now; + } + else + { + TimeStamp = new DateTime(DateTime.Today.Year, + DateTime.Today.Month, + DateTime.Today.Day, + hrs, + mins, + secs); + } + reader.ReadEndElement(); // end of date + + reader.ReadStartElement("src"); + + reader.ReadStartElement("name"); + MeterName = reader.ReadString(); + reader.ReadEndElement(); + + reader.ReadStartElement("id"); + MeterId = reader.ReadContentAsInt(); + reader.ReadEndElement(); + + reader.ReadStartElement("type"); + MeterType = reader.ReadContentAsInt(); + reader.ReadEndElement(); + + reader.ReadStartElement("sver"); + MeterSoftwareVersion = reader.ReadContentAsString(); + reader.ReadEndElement(); + + reader.ReadEndElement(); // end of src + + reader.ReadStartElement("ch1"); + + reader.ReadStartElement("watts"); + Channel1Watts = reader.ReadContentAsInt(); + reader.ReadEndElement(); + + reader.ReadEndElement(); // end of ch1 + + reader.ReadStartElement("ch2"); + + reader.ReadStartElement("watts"); + Channel2Watts = reader.ReadContentAsInt(); + reader.ReadEndElement(); + + reader.ReadEndElement(); // end of ch2 + + reader.ReadStartElement("ch3"); + + reader.ReadStartElement("watts"); + Channel3Watts = reader.ReadContentAsInt(); + reader.ReadEndElement(); + + reader.ReadEndElement(); // end of ch3 + + reader.ReadStartElement("tmpr"); + Temperature = reader.ReadContentAsString(); + reader.ReadEndElement(); + + reader.ReadStartElement("hist"); + + reader.ReadStartElement("hrs"); + + reader.ReadStartElement("h02"); + kWattsHour02 = reader.ReadContentAsFloat(); + reader.ReadEndElement(); + reader.ReadStartElement("h04"); + kWattsHour04 = reader.ReadContentAsFloat(); + reader.ReadEndElement(); + reader.ReadStartElement("h06"); + kWattsHour06 = reader.ReadContentAsFloat(); + reader.ReadEndElement(); + reader.ReadStartElement("h08"); + kWattsHour08 = reader.ReadContentAsFloat(); + reader.ReadEndElement(); + reader.ReadStartElement("h10"); + kWattsHour10 = reader.ReadContentAsFloat(); + reader.ReadEndElement(); + reader.ReadStartElement("h12"); + kWattsHour12 = reader.ReadContentAsFloat(); + reader.ReadEndElement(); + reader.ReadStartElement("h14"); + kWattsHour14 = reader.ReadContentAsFloat(); + reader.ReadEndElement(); + reader.ReadStartElement("h16"); + kWattsHour16 = reader.ReadContentAsFloat(); + reader.ReadEndElement(); + reader.ReadStartElement("h18"); + kWattsHour18 = reader.ReadContentAsFloat(); + reader.ReadEndElement(); + reader.ReadStartElement("h20"); + kWattsHour20 = reader.ReadContentAsFloat(); + reader.ReadEndElement(); + reader.ReadStartElement("h22"); + kWattsHour22 = reader.ReadContentAsFloat(); + reader.ReadEndElement(); + reader.ReadStartElement("h24"); + kWattsHour24 = reader.ReadContentAsFloat(); + reader.ReadEndElement(); + reader.ReadStartElement("h26"); + kWattsHour26 = reader.ReadContentAsFloat(); + reader.ReadEndElement(); + + reader.ReadEndElement(); // end of hrs + + reader.ReadStartElement("days"); + + reader.ReadStartElement("d01"); + WattsDay01 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d02"); + WattsDay02 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d03"); + WattsDay03 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d04"); + WattsDay04 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d05"); + WattsDay05 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d06"); + WattsDay06 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d07"); + WattsDay07 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d08"); + WattsDay08 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d09"); + WattsDay09 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d10"); + WattsDay10 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d11"); + WattsDay11 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d12"); + WattsDay12 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d13"); + WattsDay13 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d14"); + WattsDay14 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d15"); + WattsDay15 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d16"); + WattsDay16 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d17"); + WattsDay17 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d18"); + WattsDay18 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d19"); + WattsDay19 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d20"); + WattsDay20 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d21"); + WattsDay21 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d22"); + WattsDay22 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d23"); + WattsDay23 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d24"); + WattsDay24 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d25"); + WattsDay25 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d26"); + WattsDay26 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d27"); + WattsDay27 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d28"); + WattsDay28 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d29"); + WattsDay29 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d30"); + WattsDay30 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("d31"); + WattsDay31 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + + reader.ReadEndElement(); // end of days + + reader.ReadStartElement("mths"); + + reader.ReadStartElement("m01"); + WattsMonth01 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("m02"); + WattsMonth02 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("m03"); + WattsMonth03 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("m04"); + WattsMonth04 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("m05"); + WattsMonth05 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("m06"); + WattsMonth06 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("m07"); + WattsMonth07 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("m08"); + WattsMonth08 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("m09"); + WattsMonth09 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("m10"); + WattsMonth10 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("m11"); + WattsMonth11 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("m12"); + WattsMonth12 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + + reader.ReadEndElement(); // end of mths + + reader.ReadStartElement("yrs"); + + reader.ReadStartElement("y1"); + WattsYear1 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("y2"); + WattsYear2 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("y3"); + WattsYear3 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + reader.ReadStartElement("y4"); + WattsYear4 = reader.ReadContentAsInt(); + reader.ReadEndElement(); + + reader.ReadEndElement(); // end of yrs + + + reader.ReadEndElement(); // end of hist + + ValidUpdate = true; + } + catch (XmlException exc) + { + ValidUpdate = false; + + /* partial updates from CurrentCost meters are not uncommon */ + /* so this is unlikely to be a severe error */ + /* the normal solution is just to try again with another */ + /* line of data from the CurrentCost meter */ + /* however, it might be good to count how many times we end */ + /* up in here, and put a limit on how many times we try? */ + } + finally + { + reader.Close(); + } + } + } +} diff --git a/dotnet/SerialPortAccess.cs b/dotnet/SerialPortAccess.cs new file mode 100644 index 0000000..a490e2c --- /dev/null +++ b/dotnet/SerialPortAccess.cs @@ -0,0 +1,85 @@ +using System; +using System.ComponentModel; +using System.Collections.Generic; +using System.IO.Ports; +using System.Text; + + +/* + * Creates a serial connection to a CurrentCost meter, and uses it + * to get a single update. + * + * Uses the CurrentCostUpdate class to parse the data and represent + * it as a .NET object. + * + * Dale Lane (http://dalelane.co.uk/blog) + * + */ + +namespace CurrentCost +{ + public class SerialPortAccess + { + public string ComPort = "COM20"; + public int BaudRate = 9600; + public int Timeout = 12000; + + private SerialPort serialPortObj; + + public CurrentCostUpdate GetSingleUpdate() + { + try + { + serialPortObj = new SerialPort(); + serialPortObj.PortName = ComPort; + serialPortObj.BaudRate = BaudRate; + serialPortObj.ReadTimeout = Timeout; + serialPortObj.DtrEnable = true; + serialPortObj.Open(); + + while (true) + { + CurrentCostUpdate update = new CurrentCostUpdate(serialPortObj.ReadLine()); + + if (update.ValidUpdate) + { + serialPortObj.Close(); + return update; + } + } + } + catch (TimeoutException exc) + { + throw new ConnectTimeoutException(exc); + } + catch (UnauthorizedAccessException exc) + { + throw new ConnectFailException(exc); + } + catch (Exception exc) + { + throw new ConnectFailException(exc); + } + } + + + public class ConnectFailException : Exception + { + public Exception ImplException = null; + + public ConnectFailException(Exception exc) + { + ImplException = exc; + } + } + public class ConnectTimeoutException : Exception + { + public Exception ImplException = null; + + public ConnectTimeoutException(Exception exc) + { + ImplException = exc; + } + } + } +} \ No newline at end of file