{"id":280,"date":"2008-06-15T21:33:11","date_gmt":"2008-06-15T21:33:11","guid":{"rendered":"http:\/\/dalelane.co.uk\/blog\/?p=280"},"modified":"2008-10-02T21:46:50","modified_gmt":"2008-10-02T21:46:50","slug":"currentcost-getting-the-history-into-windows","status":"publish","type":"post","link":"https:\/\/dalelane.co.uk\/blog\/?p=280","title":{"rendered":"CurrentCost &#8211; getting the history into Windows"},"content":{"rendered":"<p>The <a href=\"http:\/\/dalelane.co.uk\/blog\/?p=265\">CurrentCost meter<\/a> has been ignored of late as I&#8217;ve <a href=\"http:\/\/dalelane.co.uk\/blog\/?p=278\">been a bit busy with other things<\/a>. Tonight, I started playing with it again. <\/p>\n<p><strong>The plan<\/strong><br \/>\nThe more <a target=\"_blank\" href=\"http:\/\/rooreynolds.com\/2008\/05\/09\/current-cost-charting-fun\">geeky<\/a> <a target=\"_blank\" href=\"http:\/\/knolleary.net\/2008\/05\/05\/power-graphing\/\">amongst<\/a> <a target=\"_blank\" href=\"http:\/\/cumbers.wordpress.com\/2008\/05\/28\/so-now-i-have-a-slug-with-slugos\/\">us<\/a> have connected the CurrentCost to a server of some sort. By connecting it to something that&#8217;s always on, we can collect a history one reading at a time. But what about people without a server? How can they collect history?<\/p>\n<p>As Rich highlighted in his <a target=\"_blank\" href=\"http:\/\/cumbers.wordpress.com\/2008\/05\/07\/breakdown-of-currentcost-xml-output\/\">post on the CurrentCost XML output<\/a>, the CurrentCost meter maintains some running totals in flash memory, and these are included with updates for every reading from the device. <\/p>\n<p>It maintains:<\/p>\n<ul>\n<li>totals for each two-hour block for the last day\n<\/li>\n<li>totals for each day for the last 31 days\n<\/li>\n<li>totals for each month for the last 12 months\n<\/li>\n<li>totals for each year for the last 4 years\n<\/li>\n<\/ul>\n<p>This means that if you store and aggregate these history totals, you can connect the meter to a computer periodically and still get reasonable CurrentCost readings history.<\/p>\n<ul>\n<li>connect at least once every 26 hours to maintain the two-hourly history\n<\/li>\n<li>connect at least once every 31 days to maintain the daily history\n<\/li>\n<li>connect at least once a year to maintain the monthly history\n<\/li>\n<li>connect at least once every four years to maintain the yearly history\n<\/li>\n<\/ul>\n<p>Okay, so the two-hourly history might be a bit much, but the others all seem reasonable, even for non-geeks!<\/p>\n<p>So, the plan is to write a simple Windows application that a user could periodically link to a laptop or computer that will collect CurrentCost readings and aggregate them into history data. And ideally then display them in a pretty way<\/p>\n<p>(<em>Not my plan, incidentally, but rather one that I nicked from <a target=\"_blank\" href=\"http:\/\/twitter.com\/andysc\">Andy<\/a>. Still, if you&#8217;re gonna nick ideas, there are worse places to start&#8230;<\/em> \ud83d\ude42 )<\/p>\n<p>This is what I&#8217;ve got so far&#8230;<\/p>\n<p><a href=\"http:\/\/www.flickr.com\/photos\/dalelane\/2585223088\/\" title=\"the start of a CurrentCost GUI by dalelane, on Flickr\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/farm4.static.flickr.com\/3014\/2585223088_333fb6050d.jpg\" width=\"500\" height=\"375\" alt=\"the start of a CurrentCost GUI\" \/><\/a><\/p>\n<p><!--more--><strong>Step 1 &#8211; Connecting CurrentCost to Windows<\/strong><br \/>\nLike <a href=\"http:\/\/dalelane.co.uk\/blog\/?p=267\">my Slug home server<\/a>, my ThinkPad doesn&#8217;t have a COM port, so I&#8217;m using a <a href=\"http:\/\/www.maplin.co.uk\/module.aspx?ModuleNo=29968&#038;doy=15m6\" target=\"_blank\">USB to Serial adaptor<\/a> cable. When I got it, it came with a CD with Windows drivers. Unfortunately, knowing that I&#8217;d be connecting it to a Linux server, I binned this. Whoops.<\/p>\n<p>I found some <a href=\"http:\/\/www.maplin.co.uk\/media\/ZP43W_Drivers.zip\">Windows drivers on the Maplin website<\/a>, which did sort of work. But they kept crashing. Windows Device Manager showed that the drivers were six or seven years old, so after a few blue-screens-of-death, I searched for a more up-to-date version. I found <a href=\"http:\/\/www.prolific.com.tw\/eng\/downloads.asp?ID=31\" target=\"_blank\">one on the Prolific website<\/a>, and since updating to that, I&#8217;ve had no more BSODs. Yay. \ud83d\ude42<\/p>\n<p><strong>Step 2 &#8211; Getting the data<\/strong><br \/>\nUnlike the Linux app I&#8217;ve been running so far, this app wont be a long-running background task &#8211; all I need is to get a single update from the CurrentCost meter, because that will have the history data that we need. <\/p>\n<p>As <a href=\"http:\/\/cumbers.wordpress.com\/2008\/05\/07\/breakdown-of-currentcost-xml-output\/\" target=\"_blank\">Rich outlined<\/a>, the data from the CurrentCost meter comes down the serial port in XML form. <\/p>\n<p>So I <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.io.ports.serialport.readline.aspx\" target=\"_blank\">read a single line from the serial port<\/a> and try and parse the XML. If I fail (if the update is incomplete, the XML cannot be recognised, or if there are any other problems), I discard it and read another line. <\/p>\n<p><strong>Step 3 &#8211; Recognising the data<\/strong><br \/>\nNothing too elegant here &#8211; for a first quick hack, I use an <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.xml.xmlreader(VS.71).aspx\" target=\"_blank\">XmlReader<\/a> to read through the line and get the values from it. <\/p>\n<p>If anyone wants a copy, the <a href=\"http:\/\/dalelane.co.uk\/blog\/post-images\/080615-CurrentCostUpdate.cs.txt\" target=\"_blank\">class that does this is here<\/a>.<\/p>\n<p>The only slight tweak over just trying to turn XML into a series of text and number fields, is that I&#8217;ve added the ability to discard the timestamp in the XML and replace it with time taken from the computer where the code is running. <\/p>\n<p>I&#8217;ve done this because the clock on my CurrentCost meter keeps losing time, so the computer timestamp is more likely to be accurate. But, as it&#8217;s the CurrentCost meter time that is used to maintain the running totals on the meter, this isn&#8217;t really going to help a great deal for this app. Ah well, I&#8217;ve added it anyway \ud83d\ude42 <\/p>\n<p><strong>Step 4 &#8211; Translating the data<\/strong><br \/>\nAs I said at the start, the CurrentCost data is relative &#8211; it gives the total readings for &#8220;three days ago&#8221; or &#8220;two months ago&#8221;. To store this as a historical reading, I then needed to translate this into an absolute timestamp. <\/p>\n<p>For years, months, and days, this is easy. For example, a reading for four days ago (&#8220;d5&#8221;), is going to the total reading for 11th June. <\/p>\n<p>The history for hours was a bit more confusing. You get thirteen (<i>why thirteen?<\/i>) readings for two hour blocks: h2, h4, h6, h8, h10, h12, h14, h16, h18, h20, h22, h24, h26.<\/p>\n<p>I&#8217;m not sure what this means &#8211; what does &#8220;h2&#8221; mean? A total for midnight &#8211; 2am? A total for the last two hours (e.g. 7.40pm-9.40pm)? A total for the last two complete hours (e.g. 7pm-9pm)? A total since the last &#8216;even&#8217; hour (e.g. 8pm &#8211; 9.40pm)?  Dunno&#8230; I&#8217;ve written a script to capture the hours data for a day &#8211; I&#8217;ll take a look at what it collects by tomorrow and try and reverse-engineer it!<\/p>\n<p>For now, <a href=\"http:\/\/dalelane.co.uk\/blog\/post-images\/080615-CurrentCostHistory.cs.txt\">my code doesn&#8217;t try to calculate hourly totals<\/a>. <\/p>\n<p><em>Update: I&#8217;ve since worked out the hourly totals, see <a href=\"http:\/\/dalelane.co.uk\/blog\/?p=280#comment-99539\">comments below<\/a>.<\/em><\/p>\n<p><strong>Step 5 &#8211; Persisting the data<\/strong><br \/>\nI&#8217;m storing the readings in a collection by date. If there is already a reading for a particular timespan, it is overwritten with the new history reading. And I&#8217;m serializing the collection to XML files of my own.<\/p>\n<p>I&#8217;m separating it out into separate files &#8211; one for yearly totals, one for monthly totals, etc. I mainly did this so that the serialization code doesn&#8217;t break when I finally figure out the two-hour blocks and change the collection.<\/p>\n<p><strong>Step 6 &#8211; Representing the data<\/strong><br \/>\nI&#8217;ve never used <a href=\"http:\/\/en.wikipedia.org\/wiki\/Windows_Presentation_Foundation\" target=\"_blank\">Windows Presentation Foundation (WPF)<\/a> before, but I&#8217;ve read about how it offers developers the chance to create more advanced interfaces than the Windows Forms libraries that I&#8217;m used to. It has better support for binding interface elements to data objects, richer support for pretty text, easier support for graphics&#8230; this seemed like a perfect opportunity to write my first WPF app.<\/p>\n<p>As I <a target=\"_blank\" href=\"http:\/\/twitter.com\/dalelane\/statuses\/835481664\">twittered a little while ago<\/a>, my first impressions on WPF is that it&#8217;s pretty cool, but I&#8217;ve still got a lot to learn &#8211; it&#8217;s quite different from Windows Forms. <\/p>\n<p>Annoyingly, there don&#8217;t appear to be any graph controls already. I&#8217;ve made a stab at writing my own bar graph control &#8211; I basically draw a series of rectangles, and adjust the height based on the CurrentCost reading I&#8217;m representing. <\/p>\n<p><a href=\"http:\/\/www.flickr.com\/photos\/dalelane\/2581143741\/\" title=\"CurrentCost bar graphing by dalelane, on Flickr\"><img loading=\"lazy\" decoding=\"async\" align=\"left\" style=\"border: thin black solid\" hspace=\"10\" vspace=\"10\" src=\"http:\/\/farm4.static.flickr.com\/3062\/2581143741_45b9cd2663_o.png\" width=\"160\" height=\"274\" alt=\"CurrentCost bar graphing\" \/><\/a>The support for events is pretty neat &#8211; which I&#8217;ve played with by adding a line that changes the colour of the bar you have your mouse pointer over, and changes it back when you move away. Pointless, but pretty \ud83d\ude42 <\/p>\n<p>I&#8217;ve not worked out a nice way of adding labels to the graph axes, which is a pain. For the moment, I&#8217;ve reused the event colour-changing code &#8211; when you hover over a bar in the graph, I display the height of the bar in a text box, to give the CurrentCost reading for that bar.<\/p>\n<p>The problem is, as that event only knows of the bar as a graphical Rectangle object, I&#8217;ve only got the height from it. I can&#8217;t say what timespan the reading was from. Hmmm&#8230; annoying. Bit more practice with WPF needed, methinks! Still, for my &#8216;Hello World&#8217; app and the result of an evening&#8217;s work, I&#8217;m pretty happy with it so far.<\/p>\n<p><strong>What&#8217;s next?<\/strong><br \/>\nIt&#8217;s not finished, but it&#8217;s a start&#8230; once I <strike>figure out the daily history data<\/strike> (<em>Update: done!<\/em>), and learn how to draw graphs in WPF properly, it should start getting more useful. <\/p>\n<p>But if anyone wants to <a href=\"http:\/\/dalelane.co.uk\/files\/CurrentCostApp.exe\">play with what I&#8217;ve got working so far<\/a>, please feel free!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The CurrentCost meter has been ignored of late as I&#8217;ve been a bit busy with other things. Tonight, I started playing with it again. The plan The more geeky amongst us have connected the CurrentCost to a server of some sort. By connecting it to something that&#8217;s always on, we can collect a history one [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[194,226,225],"class_list":["post-280","post","type-post","status-publish","format-standard","hentry","category-code","tag-currentcost","tag-serial","tag-wpf"],"_links":{"self":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/280","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=280"}],"version-history":[{"count":0,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/280\/revisions"}],"wp:attachment":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=280"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=280"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=280"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}