This commit is contained in:
parent
a781083e20
commit
0ff662a8b5
13 changed files with 1534 additions and 0 deletions
7
python/README.txt
Normal file
7
python/README.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
Start with currcost.py
|
||||
|
||||
You will need to modify YOURCOMPORT before running it.
|
||||
|
||||
Note that this is provided to help get you started, but it lacks careful error-handling or proper documentation.
|
||||
|
||||
If you have any questions about it, or even just find it useful, please do let me know - dale.lane@gmail.com
|
91
python/currcost.py
Normal file
91
python/currcost.py
Normal file
|
@ -0,0 +1,91 @@
|
|||
import xml.parsers.expat
|
||||
import serial
|
||||
|
||||
# Parses data from a CurrentCost meter
|
||||
#
|
||||
# Note that this is provided to help get you started, but it lacks careful
|
||||
# error-handling or proper documentation.
|
||||
#
|
||||
# If you have any questions about it, or even just find it useful, please do
|
||||
# let me know - dale.lane@gmail.com
|
||||
#
|
||||
#
|
||||
# Dale Lane (http://dalelane.co.uk/blog)
|
||||
#
|
||||
|
||||
YOURCOMPORT = "COM21"
|
||||
|
||||
|
||||
# this class lets you store the CurrentCost XML data as a Python object
|
||||
from currentcostdata import CurrentCostUpdate
|
||||
|
||||
# this class lets you translate the CurrentCost data into values and their timestamps
|
||||
from currentcostdatafunctions import CurrentCostDataFunctions
|
||||
|
||||
# this class lets you store your CurrentCost data
|
||||
from currentcostdatastore import CurrentCostDataStore
|
||||
|
||||
|
||||
# XML parsing functions
|
||||
def start_element(name, attrs):
|
||||
global currentelement
|
||||
currentelement = name
|
||||
def end_element(name):
|
||||
global currentelement
|
||||
currentelement = "none"
|
||||
def char_data(data):
|
||||
global currentelement, newupd
|
||||
newupd.UpdateProperty(currentelement, data)
|
||||
|
||||
currentelement = "none"
|
||||
|
||||
# object to represent the CurrentCost data received
|
||||
newupd = CurrentCostUpdate ()
|
||||
|
||||
# objects to parse and store the data
|
||||
ccfuncs = CurrentCostDataFunctions()
|
||||
ccdb = CurrentCostDataStore()
|
||||
|
||||
ser = None
|
||||
|
||||
try:
|
||||
# connect to the CurrentCost meter
|
||||
ser = serial.Serial(port=YOURCOMPORT, timeout=3)
|
||||
except serial.SerialException, msg:
|
||||
print("Failed to connect to CurrentCost meter :: " + str(msg))
|
||||
exit(1)
|
||||
|
||||
# we keep trying to get an update from the CurrentCost meter
|
||||
# until we successfully populate the CurrentCost data object
|
||||
|
||||
while newupd.WattsDay01 == -1:
|
||||
|
||||
# read a line of XML from the CurrentCost meter
|
||||
line = ser.readline()
|
||||
|
||||
print "> " + line
|
||||
|
||||
try:
|
||||
# parse it
|
||||
p = xml.parsers.expat.ParserCreate()
|
||||
p.StartElementHandler = start_element
|
||||
p.EndElementHandler = end_element
|
||||
p.CharacterDataHandler = char_data
|
||||
p.Parse(line, 1)
|
||||
|
||||
except xml.parsers.expat.ExpatError:
|
||||
print("Received incomplete data from CurrentCost meter. Will try and get a new reading")
|
||||
|
||||
except serial.SerialException, err:
|
||||
print("Failed to receive data from CurrentCost meter :: " + str(err))
|
||||
ser.close()
|
||||
exit(1)
|
||||
|
||||
# finished with serial port - close it
|
||||
ser.close()
|
||||
|
||||
# store it
|
||||
ccfuncs.ParseCurrentCostXML(ccdb, newupd)
|
||||
|
||||
|
||||
exit(0)
|
182
python/currentcostdata.py
Normal file
182
python/currentcostdata.py
Normal file
|
@ -0,0 +1,182 @@
|
|||
from string import atoi, atof
|
||||
|
||||
# Represents the data contained in a single update from a CurrentCost meter
|
||||
#
|
||||
# It's a Python object representation of the XML - as described here:
|
||||
# http://cumbers.wordpress.com/2008/05/07/breakdown-of-currentcost-xml-output/
|
||||
#
|
||||
# Dale Lane (http://dalelane.co.uk/blog)
|
||||
|
||||
class CurrentCostUpdate():
|
||||
kWattsHour02 = -1.1
|
||||
kWattsHour04 = -1.1
|
||||
kWattsHour06 = -1.1
|
||||
kWattsHour08 = -1.1
|
||||
kWattsHour10 = -1.1
|
||||
kWattsHour12 = -1.1
|
||||
kWattsHour14 = -1.1
|
||||
kWattsHour16 = -1.1
|
||||
kWattsHour18 = -1.1
|
||||
kWattsHour20 = -1.1
|
||||
kWattsHour22 = -1.1
|
||||
kWattsHour24 = -1.1
|
||||
kWattsHour26 = -1.1
|
||||
WattsDay01 = -1
|
||||
WattsDay02 = -1
|
||||
WattsDay03 = -1
|
||||
WattsDay04 = -1
|
||||
WattsDay05 = -1
|
||||
WattsDay06 = -1
|
||||
WattsDay07 = -1
|
||||
WattsDay08 = -1
|
||||
WattsDay09 = -1
|
||||
WattsDay10 = -1
|
||||
WattsDay11 = -1
|
||||
WattsDay12 = -1
|
||||
WattsDay13 = -1
|
||||
WattsDay14 = -1
|
||||
WattsDay15 = -1
|
||||
WattsDay16 = -1
|
||||
WattsDay17 = -1
|
||||
WattsDay18 = -1
|
||||
WattsDay19 = -1
|
||||
WattsDay20 = -1
|
||||
WattsDay21 = -1
|
||||
WattsDay22 = -1
|
||||
WattsDay23 = -1
|
||||
WattsDay24 = -1
|
||||
WattsDay25 = -1
|
||||
WattsDay26 = -1
|
||||
WattsDay27 = -1
|
||||
WattsDay28 = -1
|
||||
WattsDay29 = -1
|
||||
WattsDay30 = -1
|
||||
WattsDay31 = -1
|
||||
WattsMonth01 = -1
|
||||
WattsMonth02 = -1
|
||||
WattsMonth03 = -1
|
||||
WattsMonth04 = -1
|
||||
WattsMonth05 = -1
|
||||
WattsMonth06 = -1
|
||||
WattsMonth07 = -1
|
||||
WattsMonth08 = -1
|
||||
WattsMonth09 = -1
|
||||
WattsMonth10 = -1
|
||||
WattsMonth11 = -1
|
||||
WattsMonth12 = -1
|
||||
|
||||
|
||||
def UpdateProperty (self, key, value):
|
||||
if (key == "h02"):
|
||||
self.kWattsHour02 = atof(value)
|
||||
elif (key == "h04"):
|
||||
self.kWattsHour04 = atof(value)
|
||||
elif (key == "h06"):
|
||||
self.kWattsHour06 = atof(value)
|
||||
elif (key == "h08"):
|
||||
self.kWattsHour08 = atof(value)
|
||||
elif (key == "h10"):
|
||||
self.kWattsHour10 = atof(value)
|
||||
elif (key == "h12"):
|
||||
self.kWattsHour12 = atof(value)
|
||||
elif (key == "h14"):
|
||||
self.kWattsHour14 = atof(value)
|
||||
elif (key == "h16"):
|
||||
self.kWattsHour16 = atof(value)
|
||||
elif (key == "h18"):
|
||||
self.kWattsHour18 = atof(value)
|
||||
elif (key == "h20"):
|
||||
self.kWattsHour20 = atof(value)
|
||||
elif (key == "h22"):
|
||||
self.kWattsHour22 = atof(value)
|
||||
elif (key == "h24"):
|
||||
self.kWattsHour24 = atof(value)
|
||||
elif (key == "h26"):
|
||||
self.kWattsHour26 = atof(value)
|
||||
elif (key == "d01"):
|
||||
self.WattsDay01 = atoi(value)
|
||||
elif (key == "d02"):
|
||||
self.WattsDay02 = atoi(value)
|
||||
elif (key == "d03"):
|
||||
self.WattsDay03 = atoi(value)
|
||||
elif (key == "d04"):
|
||||
self.WattsDay04 = atoi(value)
|
||||
elif (key == "d05"):
|
||||
self.WattsDay05 = atoi(value)
|
||||
elif (key == "d06"):
|
||||
self.WattsDay06 = atoi(value)
|
||||
elif (key == "d07"):
|
||||
self.WattsDay07 = atoi(value)
|
||||
elif (key == "d08"):
|
||||
self.WattsDay08 = atoi(value)
|
||||
elif (key == "d09"):
|
||||
self.WattsDay09 = atoi(value)
|
||||
elif (key == "d10"):
|
||||
self.WattsDay10 = atoi(value)
|
||||
elif (key == "d11"):
|
||||
self.WattsDay11 = atoi(value)
|
||||
elif (key == "d12"):
|
||||
self.WattsDay12 = atoi(value)
|
||||
elif (key == "d13"):
|
||||
self.WattsDay13 = atoi(value)
|
||||
elif (key == "d14"):
|
||||
self.WattsDay14 = atoi(value)
|
||||
elif (key == "d15"):
|
||||
self.WattsDay15 = atoi(value)
|
||||
elif (key == "d16"):
|
||||
self.WattsDay16 = atoi(value)
|
||||
elif (key == "d17"):
|
||||
self.WattsDay17 = atoi(value)
|
||||
elif (key == "d18"):
|
||||
self.WattsDay18 = atoi(value)
|
||||
elif (key == "d19"):
|
||||
self.WattsDay19 = atoi(value)
|
||||
elif (key == "d20"):
|
||||
self.WattsDay20 = atoi(value)
|
||||
elif (key == "d21"):
|
||||
self.WattsDay21 = atoi(value)
|
||||
elif (key == "d22"):
|
||||
self.WattsDay22 = atoi(value)
|
||||
elif (key == "d23"):
|
||||
self.WattsDay23 = atoi(value)
|
||||
elif (key == "d24"):
|
||||
self.WattsDay24 = atoi(value)
|
||||
elif (key == "d25"):
|
||||
self.WattsDay25 = atoi(value)
|
||||
elif (key == "d26"):
|
||||
self.WattsDay26 = atoi(value)
|
||||
elif (key == "d27"):
|
||||
self.WattsDay27 = atoi(value)
|
||||
elif (key == "d28"):
|
||||
self.WattsDay28 = atoi(value)
|
||||
elif (key == "d29"):
|
||||
self.WattsDay29 = atoi(value)
|
||||
elif (key == "d30"):
|
||||
self.WattsDay30 = atoi(value)
|
||||
elif (key == "d31"):
|
||||
self.WattsDay31 = atoi(value)
|
||||
elif (key == "m01"):
|
||||
self.WattsMonth01 = atoi(value)
|
||||
elif (key == "m02"):
|
||||
self.WattsMonth02 = atoi(value)
|
||||
elif (key == "m03"):
|
||||
self.WattsMonth03 = atoi(value)
|
||||
elif (key == "m04"):
|
||||
self.WattsMonth04 = atoi(value)
|
||||
elif (key == "m05"):
|
||||
self.WattsMonth05 = atoi(value)
|
||||
elif (key == "m06"):
|
||||
self.WattsMonth06 = atoi(value)
|
||||
elif (key == "m07"):
|
||||
self.WattsMonth07 = atoi(value)
|
||||
elif (key == "m08"):
|
||||
self.WattsMonth08 = atoi(value)
|
||||
elif (key == "m09"):
|
||||
self.WattsMonth09 = atoi(value)
|
||||
elif (key == "m10"):
|
||||
self.WattsMonth10 = atoi(value)
|
||||
elif (key == "m11"):
|
||||
self.WattsMonth11 = atoi(value)
|
||||
elif (key == "m12"):
|
||||
self.WattsMonth12 = atoi(value)
|
||||
|
140
python/currentcostdatafunctions.py
Normal file
140
python/currentcostdatafunctions.py
Normal file
|
@ -0,0 +1,140 @@
|
|||
import datetime
|
||||
|
||||
from currentcostdatastore import CurrentCostDataStore
|
||||
|
||||
# A CurrentCost update (as described in currentcostdata.py) is a relative
|
||||
# description of your electricity usage.
|
||||
#
|
||||
# E.g. you used this much electricity 2 hours ago
|
||||
#
|
||||
# This class converts this into an absolute description of your electricity
|
||||
# usage.
|
||||
#
|
||||
# E.g. you used this much electricity at 1pm
|
||||
#
|
||||
#
|
||||
# Dale Lane (http://dalelane.co.uk/blog)
|
||||
|
||||
|
||||
class CurrentCostDataFunctions():
|
||||
|
||||
def ParseCurrentCostXML(self, ccdb, newupd):
|
||||
today = datetime.date.today()
|
||||
#
|
||||
ccdb.StoreMonthData(self.GetOldMonth(today, 1), newupd.WattsMonth01)
|
||||
ccdb.StoreMonthData(self.GetOldMonth(today, 2), newupd.WattsMonth02)
|
||||
ccdb.StoreMonthData(self.GetOldMonth(today, 3), newupd.WattsMonth03)
|
||||
ccdb.StoreMonthData(self.GetOldMonth(today, 4), newupd.WattsMonth04)
|
||||
ccdb.StoreMonthData(self.GetOldMonth(today, 5), newupd.WattsMonth05)
|
||||
ccdb.StoreMonthData(self.GetOldMonth(today, 6), newupd.WattsMonth06)
|
||||
ccdb.StoreMonthData(self.GetOldMonth(today, 7), newupd.WattsMonth07)
|
||||
ccdb.StoreMonthData(self.GetOldMonth(today, 8), newupd.WattsMonth08)
|
||||
ccdb.StoreMonthData(self.GetOldMonth(today, 9), newupd.WattsMonth09)
|
||||
ccdb.StoreMonthData(self.GetOldMonth(today, 10), newupd.WattsMonth10)
|
||||
ccdb.StoreMonthData(self.GetOldMonth(today, 11), newupd.WattsMonth11)
|
||||
ccdb.StoreMonthData(self.GetOldMonth(today, 12), newupd.WattsMonth12)
|
||||
#
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 1), newupd.WattsDay01)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 2), newupd.WattsDay02)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 3), newupd.WattsDay03)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 4), newupd.WattsDay04)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 5), newupd.WattsDay05)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 6), newupd.WattsDay06)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 7), newupd.WattsDay07)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 8), newupd.WattsDay08)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 9), newupd.WattsDay09)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 10), newupd.WattsDay10)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 11), newupd.WattsDay11)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 12), newupd.WattsDay12)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 13), newupd.WattsDay13)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 14), newupd.WattsDay14)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 15), newupd.WattsDay15)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 16), newupd.WattsDay16)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 17), newupd.WattsDay17)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 18), newupd.WattsDay18)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 19), newupd.WattsDay19)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 20), newupd.WattsDay20)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 21), newupd.WattsDay21)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 22), newupd.WattsDay22)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 23), newupd.WattsDay23)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 24), newupd.WattsDay24)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 25), newupd.WattsDay25)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 26), newupd.WattsDay26)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 27), newupd.WattsDay27)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 28), newupd.WattsDay28)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 29), newupd.WattsDay29)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 30), newupd.WattsDay30)
|
||||
ccdb.StoreDayData(self.GetOldDay(today, 31), newupd.WattsDay31)
|
||||
#
|
||||
currtime = datetime.datetime.now()
|
||||
#
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 0), newupd.kWattsHour02)
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 2), newupd.kWattsHour04)
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 4), newupd.kWattsHour06)
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 6), newupd.kWattsHour08)
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 8), newupd.kWattsHour10)
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 10), newupd.kWattsHour12)
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 12), newupd.kWattsHour14)
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 14), newupd.kWattsHour16)
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 16), newupd.kWattsHour18)
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 18), newupd.kWattsHour20)
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 20), newupd.kWattsHour22)
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 22), newupd.kWattsHour24)
|
||||
ccdb.StoreHourData(self.GetOldHour(currtime, 24), newupd.kWattsHour26)
|
||||
|
||||
|
||||
def GetOldMonth(self, referenceDate, monthsago):
|
||||
newmonth = referenceDate.month - monthsago
|
||||
newyear = referenceDate.year
|
||||
|
||||
if newmonth <= 0:
|
||||
newmonth += 12
|
||||
newyear -= 1
|
||||
|
||||
return datetime.date(newyear, newmonth, 1)
|
||||
|
||||
|
||||
def GetOldDay(self, referenceDate, daysago):
|
||||
newday = referenceDate.day - daysago
|
||||
newmonth = referenceDate.month
|
||||
newyear = referenceDate.year
|
||||
|
||||
if newday <= 0:
|
||||
d = datetime.timedelta(days=daysago)
|
||||
sub = referenceDate - d
|
||||
newday = sub.day
|
||||
newmonth = sub.month
|
||||
newyear = sub.year
|
||||
|
||||
return datetime.date(newyear, newmonth, newday)
|
||||
|
||||
|
||||
|
||||
def GetOldHour(self, referenceDate, hoursago):
|
||||
if referenceDate.hour % 2 == 0:
|
||||
hoursago = hoursago + 1
|
||||
|
||||
newhour = referenceDate.hour - hoursago
|
||||
newday = referenceDate.day
|
||||
newmonth = referenceDate.month
|
||||
newyear = referenceDate.year
|
||||
|
||||
if newhour < -24:
|
||||
newhour += 48
|
||||
d = datetime.timedelta(hours=hoursago)
|
||||
sub = referenceDate - d
|
||||
newday = sub.day
|
||||
newmonth = sub.month
|
||||
newyear = sub.year
|
||||
elif newhour < 0:
|
||||
newhour += 24
|
||||
d = datetime.timedelta(hours=hoursago)
|
||||
sub = referenceDate - d
|
||||
newday = sub.day
|
||||
newmonth = sub.month
|
||||
newyear = sub.year
|
||||
|
||||
return datetime.datetime(newyear, newmonth, newday, newhour, 0, 0)
|
||||
|
||||
|
||||
|
21
python/currentcostdatastore.py
Normal file
21
python/currentcostdatastore.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
# Stores your CurrentCost data
|
||||
#
|
||||
# Okay, so this doesn't really store data.
|
||||
#
|
||||
# These are really just stubs, replace them functions which store the data
|
||||
# the way you like
|
||||
# I'm a big fan of pysqlite, but you can use anything you like.
|
||||
#
|
||||
# Dale Lane (http://dalelane.co.uk/blog)
|
||||
#
|
||||
|
||||
class CurrentCostDataStore():
|
||||
|
||||
def StoreHourData (self, updatetimestamp, ccvalue):
|
||||
print "2-HOUR :: " + str(updatetimestamp) + " = " + str(ccvalue) + "kWh"
|
||||
|
||||
def StoreDayData (self, updatetimestamp, ccvalue):
|
||||
print "DAY :: " + str(updatetimestamp) + " = " + str(ccvalue) + "kWh"
|
||||
|
||||
def StoreMonthData (self, updatetimestamp, ccvalue):
|
||||
print "MONTH :: " + str(updatetimestamp) + " = " + str(ccvalue) + "kWh"
|
Loading…
Add table
Add a link
Reference in a new issue