Permalink
Browse files

v1.0 of the tweetawatt software

  • Loading branch information...
ladyada committed May 8, 2010
1 parent 5eb99af commit 08af778969b5b5ca4ab25392799753eb5d1e4ab6
Showing with 2,018 additions and 0 deletions.
  1. +65 −0 appengineauth.py
  2. +128 −0 sensorhistory.py
  3. +1,524 −0 twitter.py
  4. +301 −0 wattcher.py
View
@@ -0,0 +1,65 @@
+import os
+import urllib
+import urllib2
+import cookielib
+
+users_email_address = "username@gmail.com"
+users_password = "password"
+my_app_name = "wattcher"
+target_authenticated_google_app_engine_uri = 'http://wattcher.appspot.com/report'
+
+
+
+# we use a cookie to authenticate with Google App Engine
+# by registering a cookie handler here, this will automatically store the
+# cookie returned when we use urllib2 to open http://currentcost.appspot.com/_ah/login
+cookiejar = cookielib.LWPCookieJar()
+opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookiejar))
+urllib2.install_opener(opener)
+
+#
+# get an AuthToken from Google accounts
+#
+auth_uri = 'https://www.google.com/accounts/ClientLogin'
+authreq_data = urllib.urlencode({ "Email": users_email_address,
+ "Passwd": users_password,
+ "service": "ah",
+ "source": my_app_name,
+ "accountType": "HOSTED_OR_GOOGLE" })
+auth_req = urllib2.Request(auth_uri, data=authreq_data)
+auth_resp = urllib2.urlopen(auth_req)
+auth_resp_body = auth_resp.read()
+# auth response includes several fields - we're interested in
+# the bit after Auth=
+auth_resp_dict = dict(x.split("=")
+ for x in auth_resp_body.split("\n") if x)
+authtoken = auth_resp_dict["Auth"]
+
+#
+# get a cookie
+#
+# the call to request a cookie will also automatically redirect us to the page
+# that we want to go to
+# the cookie jar will automatically provide the cookie when we reach the
+# redirected location
+
+def sendreport(sensornum, watt):
+ # this is where I actually want to go to
+ serv_uri = target_authenticated_google_app_engine_uri + "?watt="+str(watt)+"&sensornum="+str(sensornum)
+
+ serv_args = {}
+ serv_args['continue'] = serv_uri
+ serv_args['auth'] = authtoken
+
+ full_serv_uri = "http://wattcher.appspot.com/_ah/login?%s" % (urllib.urlencode(serv_args))
+
+ serv_req = urllib2.Request(full_serv_uri)
+ serv_resp = urllib2.urlopen(serv_req)
+ serv_resp_body = serv_resp.read()
+
+ # serv_resp_body should contain the contents of the
+ # target_authenticated_google_app_engine_uri page - as we will have been
+ # redirected to that page automatically
+ #
+ # to prove this, I'm just gonna print it out
+ print serv_resp_body
View
@@ -0,0 +1,128 @@
+import time, datetime
+import sys
+import traceback
+def formatExceptionInfo(maxTBlevel=5):
+ cla, exc, trbk = sys.exc_info()
+ excName = cla.__name__
+ try:
+ excArgs = exc.__dict__["args"]
+ except KeyError:
+ excArgs = "<no args>"
+ excTb = traceback.format_tb(trbk, maxTBlevel)
+ return (excName, excArgs, excTb)
+
+
+class SensorHistories:
+ # array of sensor data
+ sensorhistories = []
+
+ def __init__(self):
+ self.sensorhistories = []
+
+ def __init__(self, f):
+ if f:
+ self.readfromfile(f)
+
+ def find(self, sensornum):
+ for history in self.sensorhistories:
+ if history.sensornum == sensornum:
+ return history
+ # none found, create it!
+ history = SensorHistory(sensornum)
+ self.sensorhistories.append(history)
+ return history
+
+ def readfromfile(self, f):
+ curryear = 0
+ currmonth = 0
+ currdate = 0
+
+ currdailypowerusage = None
+
+ for line in f:
+ try:
+ # chomp() off the new line at the end
+ if line and line[-1] == '\n':
+ line = line[:-1]
+
+ # debug print
+ #print line, '\n'
+ #print line
+ if (line[0] == '#'):
+ continue
+
+ # divide up into [0] date, [1] time, [2] sensornum, [3] Watts used
+ # this parsing isnt very flexible...it would be nice if it was rugged :(
+ foo = line.split(', ')
+ timestamp = foo[1]
+ sensornum = int(foo[2])
+ powerused = float(foo[3])
+ dateset = foo[0].split(' ')
+ year = int(dateset[0])
+ month = int(dateset[1])
+ date = int(dateset[2])
+
+ # debug print out that parsed line
+ #print "#", year, month, date, timestamp, sensornum, powerused
+
+ if not ( datetime.date.today().year == year and datetime.date.today().month == month and datetime.date.today().day == date) :
+ pass # older data, skip it
+
+ # get the 'seconds since epoch' time for the datapoint
+ datapointtime = time.mktime( time.strptime(foo[0]+", "+foo[1], "%Y %m %d, %H:%M") )
+ history = self.find(sensornum)
+ if history.lasttime > datapointtime:
+ # this is the first datapoint for this sensor
+ history.lasttime = datapointtime
+ # the next time we go through, we'll have a delta of time
+ continue
+
+ # figure out how much time has elapsed since last datapoint
+ #print (datapointtime - history.lasttime), " seconds elapsed since last datapoint"
+
+ # calculate how many Watthrs since last datapoint
+ #print powerused * (datapointtime - history.lasttime) / (60.0 * 60.0)
+ # add that to the current sensorhistory dayswatthr
+ history.dayswatthr += powerused * (datapointtime - history.lasttime) / (60.0 * 60.0)
+
+ history.lasttime = datapointtime
+ except:
+ print formatExceptionInfo()
+
+ for history in self.sensorhistories:
+ history.lasttime = time.time()
+
+ def __str__(self):
+ s = ""
+ for history in self.sensorhistories:
+ s += history.__str__()
+ return s
+####### store sensor data and array of histories per sensor
+class SensorHistory:
+ sensornum = 0 # the ID for this set of data
+ cumulative5mwatthr = 0 # data for power collected over last 5 minutes
+ dayswatthr = 0 # power collected over last full day
+ fiveminutetimer = 0
+ lasttime = 0
+
+ def __init__(self, sensornum):
+ self.sensornum = sensornum
+ self.fiveminutetimer = time.time() # track data over 5 minutes
+ self.lasttime = time.time()
+ self.cumulative5mwatthr = 0
+ self.dayswatthr = 0
+
+ def addwatthr(self, deltawatthr):
+ self.cumulative5mwatthr += float(deltawatthr)
+ self.dayswatthr += float(deltawatthr)
+
+ def reset5mintimer(self):
+ self.cumulative5mwatthr = 0
+ self.fiveminutetimer = time.time()
+
+ def avgwattover5min(self):
+ return self.cumulative5mwatthr * (60.0*60.0 / (time.time() - self.fiveminutetimer))
+
+ def __str__(self):
+ return "[ id#: %d, 5mintimer: %f, lasttime; %f, 5minwatthr: %f, daywatthr = %f]" % (self.sensornum, self.fiveminutetimer, self.lasttime, self.cumulative5mwatthr, self.dayswatthr)
+
Oops, something went wrong.

0 comments on commit 08af778

Please sign in to comment.