def update_graph(idleevent): global avgwattdataidx, sensorhistories, twittertimer, DEBUG # grab one packet from the xbee, or timeout packet = xbee.find_packet(ser) if not packet: return # we timedout xb = xbee(packet) # parse the packet print xb.address_16 if DEBUG: # for debugging sometimes we only want one print xb # we'll only store n-1 samples since the first one is usually messed up voltagedata = [-1] * (len(xb.analog_samples) - 1) ampdata = [-1] * (len(xb.analog_samples ) -1) # grab 1 thru n of the ADC readings, referencing the ADC constants # and store them in nice little arrays for i in range(len(voltagedata)): voltagedata[i] = xb.analog_samples[i+1][VOLTSENSE] ampdata[i] = xb.analog_samples[i+1][CURRENTSENSE] if DEBUG: print "ampdata: "+str(ampdata) print "voltdata: "+str(voltagedata) # get max and min voltage and normalize the curve to '0' # to make the graph 'AC coupled' / signed min_v = 1024 # XBee ADC is 10 bits, so max value is 1023 max_v = 0 for i in range(len(voltagedata)): if (min_v > voltagedata[i]): min_v = voltagedata[i] if (max_v < voltagedata[i]): max_v = voltagedata[i]
def do_watch(self, p): if not self.serial.isOpen(): print "You must set a serial port first." else: while 1: packet = xbee.find_packet(self.serial) if packet: xb = xbee(packet) print xb
def do_stuff(nothing): packet = xbee.find_packet(ser) if not packet: return xb = xbee(packet) if xb.packet_id == xbee.IO_DATA: print xb.addr_16 if xb.addr_16 == TEMPLOGGER1_ADDR_16: temp =temp_logger_parse(xb,f) xb.send_cmd_local(ser,"DB") print "STFFF" + str(xb.analog[0]) print "OUTSIDE RSSI" + str(xb.rssi)
def mainloop(idleevent): global sensorhistories, twittertimer, DEBUG, COSM_KEY # grab one packet from the xbee, or timeout try: packet = xbee.find_packet(ser) if not packet: # print " no serial packet found... "+ time.strftime("%Y %m %d, %H:%M") # syslog.syslog("TLSM.mainloop exception: no serial packet found..." ) return except Exception, e: print "TLSM.mainloop exception: Serial packet: " + str(e) syslog.syslog("TLSM.mainloop exception: Serial packet: " + str(e)) return
def grab_packet(): # grab one packet from the xbee, or timeout trial = 0 max_trials = 100 while trial < max_trials: packet = xbee.find_packet(ser) if not packet: trial = trial + 1 else: break if trial == max_trials: # We couldn't get any data... return None,False else: return xbee(packet),True
def mainloop(idleevent): global sensorhistories, twittertimer, DEBUG, PACHUBE_KEY # grab one packet from the xbee, or timeout try: packet = xbee.find_packet(ser) if not packet: # print " no serial packet found... "+ time.strftime("%Y %m %d, %H:%M") # syslog.syslog("TLSM.mainloop exception: no serial packet found..." ) return except Exception, e: print "TLSM.mainloop exception: Serial packet: "+str(e) syslog.syslog("TLSM.mainloop exception: Serial packet: "+str(e)) return
def read_data(port): packet = xbee.find_packet(port) if not packet: raise RuntimeError xb = xbee(packet) voltage_samples = [] amperage_samples = [] for sample in xb.analog_samples[1:]: voltage_samples.append(sample[VOLTSENSE]) amperage_samples.append(sample[CURRENTSENSE]) # get max and min voltage and normalize the curve to '0' # to make the graph 'AC coupled' / signed min_v = min(voltage_samples) max_v = max(voltage_samples) # figure out the 'average' of the max and min readings avgv = (max_v + min_v) / 2.0 # also calculate the peak to peak measurements vpp = max_v-min_v for i in range(len(voltage_samples)): #remove 'dc bias', which we call the average read voltage_samples[i] -= avgv # We know that the mains voltage is 120Vrms = +-170Vpp voltage_samples[i] = (voltage_samples[i] * MAINSVPP) / vpp # normalize current readings to amperes for i in range(len(amperage_samples)): # VREF is the hardcoded 'DC bias' value, its # about 492 but would be nice if we could somehow # get this data once in a while maybe using xbeeAPI if vrefcalibration[xb.address_16]: amperage_samples[i] -= vrefcalibration[xb.address_16] else: amperage_samples[i] -= vrefcalibration[0] # the CURRENTNORM is our normalizing constant # that converts the ADC reading to Amperes amperage_samples[i] /= CURRENTNORM wattage_data = [v * a for v, a in zip(voltage_samples, amperage_samples)] amperage = sum(map(abs, amperage_samples)) / float(len(amperage_samples)) wattage = sum(map(abs, wattage_data)) / float(len(wattage_data)) return datetime.datetime.now(), amperage, wattage
def update_log(): global maxVolts, minVolts, maxAmps, minAmps, maxWatts, minWatts, DEBUG, height, width, counter, longAvgVolts, longAvgAmps, longAvgWatts, longMaxVolts, longMinVolts, longMaxAmps, longMinAmps, xb # grab one packet from the xbee, or timeout packet = xbee.find_packet(ser) if not packet: return # we timedout xb = xbee(packet) # parse the packet #print xb.address_16 if DEBUG: # for debugging sometimes we only want one print xb # we'll only store n-1 samples since the first one is usually messed up #voltagedata = [-1] * (len(xb.analog_samples) - 1) #ampdata = [-1] * (len(xb.analog_samples ) -1) voltagedata = [-1] * (len(xb.analog_samples)) ampdata = [-1] * (len(xb.analog_samples )) # grab 1 thru n of the ADC readings, referencing the ADC constants # and store them in nice little arrays for i in range(len(voltagedata)): voltagedata[i] = xb.analog_samples[i][VOLTSENSE] ampdata[i] = xb.analog_samples[i][CURRENTSENSE] # get max and min voltage and normalize the curve to '0' # to make the graph 'AC coupled' / signed max_v=max(voltagedata) min_v=min(voltagedata) # figure out the 'average' of the max and min readings avgv = (max_v + min_v) / 2 # also calculate the peak to peak measurements vpp = max_v-min_v if DEBUG: print "min_v="+str(min_v) print "max_v="+str(max_v) print "avgv="+str(avgv) print "vpp="+str(vpp) for i in range(len(voltagedata)): #remove 'dc bias', which we call the average read voltagedata[i] -= avgv # We know that the mains voltage is 120Vrms = +-170Vpp voltagedata[i] = (voltagedata[i] * MAINSVPP) / vpp # normalize current readings to amperes for i in range(len(ampdata)): # VREF is the hardcoded 'DC bias' value, its # about 492 but would be nice if we could somehow # get this data once in a while maybe using xbeeAPI #if vrefcalibration[xb.address_16]: # ampdata[i] -= vrefcalibration[xb.address_16] #else: # ampdata[i] -= vrefcalibration[0] ampdata[i] -= avgv # the CURRENTNORM is our normalizing constant # that converts the ADC reading to Amperes ampdata[i] /= CURRENTNORM ampdata[i] = abs(ampdata[i]) # calculate instant. watts, by multiplying V*I for each sample point wattdata = [0] * len(voltagedata) for i in range(len(wattdata)): wattdata[i] = voltagedata[i] * ampdata[i] if DEBUG: print "voltdata: "+str(voltagedata) print "ampdata: "+str(ampdata) print "wattdata: "+str(wattdata) avgvolts = 0 #for i in range(len(voltagedata)): for i in range(cycleLength): avgvolts += abs(voltagedata[i]) #avgvolts /= float(len(voltagedata)) avgvolts /= float(cycleLength) avgamps = 0 #for i in range(len(ampdata)): for i in range(cycleLength): #avgamps += abs(ampdata[i]) avgamps += ampdata[i] #avgamps /= float(len(ampdata)) avgamps /= float(cycleLength) avgwatts=avgvolts*avgamps avgwatts2 = 0 #for i in range(len(wattdata)): for i in range(cycleLength): avgwatts2 += abs(wattdata[i]) #avgwatts2 /= float(len(wattdata)) avgwatts2 /= float(cycleLength) if avgvolts>maxVolts: maxVolts=avgvolts if avgvolts<minVolts: minVolts=avgvolts if avgamps>maxAmps: maxAmps=avgamps if avgamps<minAmps: minAmps=avgamps if avgwatts>maxWatts: maxWatts=avgwatts if avgwatts<minWatts: minWatts=avgwatts if avgvolts>longMaxVolts: longMaxVolts=avgvolts if avgvolts<longMinVolts: longMinVolts=avgvolts if avgamps>longMaxAmps: longMaxAmps=avgamps if avgamps<longMinAmps: longMinAmps=avgamps longAvgVolts+=avgvolts longAvgAmps+=avgamps longAvgWatts+=avgwatts # Print out our most recent measurements if DEBUG: print str(xb.address_16) print "\tAverage Voltage: "+str(avgvolts) print "\tAverage Amperage: "+str(avgamps) print "\tAverage Watt draw: "+str(avgwatts) print "\tAverage Watt instantaneous draw: "+str(avgwatts2) print "\tVolts Min: "+str(minVolts) print "\tVolts Max: "+str(maxVolts) print "\tAmps Min: "+str(minAmps) print "\tAmps Max: "+str(maxAmps) print "\tWatts Min: "+str(minWatts) print "\tWatts Max: "+str(maxWatts) else: scr.clear() # Draw pretty box frame for data for y in range(height): for x in range(width): if (x==0 or x==width-1): scr.addch(y,x,curses.ACS_VLINE) if (x==0): if (y==0): scr.addch(y,x,curses.ACS_ULCORNER) elif (y==height-1): scr.addch(y,x,curses.ACS_LLCORNER) elif (x==width): if (y==0): scr.addch(y,x,curses.ACS_URCORNER) elif (y==height-1): scr.addch(y,x,curses.ACS_LRCORNER) elif (y==0 or y==height-1): scr.addch(y,x,curses.ACS_HLINE) #scr.addstr(height-2,5,"height="+str(height)+", width="+str(width)) # console is 25x79 # Show data scr.addstr(1,5,"Log Data for Sensor "+str(xb.address_16)) scr.addstr(2,5,time.strftime("%m/%d/%Y %H:%M:%S")) scr.addstr(4,10,"Average Voltage: "+str(avgvolts)) scr.addstr(5,10,"Average Amperage: "+str(avgamps)) scr.addstr(6,10,"Average Wattage: "+str(avgwatts)) scr.addstr(7,10,"Average Instantaneous Wattage: "+str(avgwatts2)) scr.addstr(9,10,"Volts Min: "+str(minVolts)) scr.addstr(9,40,"Volts Max: "+str(maxVolts)) scr.addstr(10,10,"Amps Min: "+str(minAmps)) scr.addstr(10,40,"Amps Max: "+str(maxAmps)) scr.addstr(11,10,"Watts Min: "+str(minWatts)) scr.addstr(11,40,"Watts Max: "+str(maxWatts)) # voltagedata, ampdata, wattdata # using 10 vertical lines for sinewave # 19 samples horizontal for each # Draw labels scr.addstr(height-1,9,"Voltage Graph") scr.addstr(height-1,32,"Amperage Graph") scr.addstr(height-1,57,"Wattage Graph") # Draw boxes for graphs for x in range(11): if (x==0): linetype1=curses.ACS_ULCORNER linetype2=curses.ACS_LLCORNER elif (x==11): linetype1=curses.ACS_URCORNER linetype2=curses.ACS_LRCORNER else: linetype1=curses.ACS_VLINE linetype2=curses.ACS_VLINE scr.addch(12+x,5,linetype1) scr.addch(12+x,25,linetype2) scr.addch(12+x,29,linetype1) scr.addch(12+x,49,linetype2) scr.addch(12+x,53,linetype1) scr.addch(12+x,73,linetype2) for x in range(19): if (x==cycleLength-1): linetype=curses.ACS_VLINE else: linetype=curses.ACS_HLINE scr.addch(12,6+x,linetype) scr.addch(23,6+x,linetype) scr.addch(12,30+x,linetype) scr.addch(23,30+x,linetype) scr.addch(12,54+x,linetype) scr.addch(23,54+x,linetype) for x in range(len(voltagedata)): y=voltagedata[x] if (y>148): scr.addstr(13,x+6,'*') elif (y>111): scr.addstr(14,x+6,'*') elif (y>74): scr.addstr(15,x+6,'*') elif (y>37): scr.addstr(16,x+6,'*') elif (y>0): scr.addstr(17,x+6,'*') elif (y>-37): scr.addstr(18,x+6,'*') elif (y>-74): scr.addstr(19,x+6,'*') elif (y>-111): scr.addstr(20,x+6,'*') elif (y>-148): scr.addstr(21,x+6,'*') else: scr.addstr(22,x+6,'*') for x in range(len(ampdata)): y=ampdata[x] if (y>13.5): scr.addstr(13,x+30,'*') elif (y>12): scr.addstr(14,x+30,'*') elif (y>10.5): scr.addstr(15,x+30,'*') elif (y>9): scr.addstr(16,x+30,'*') elif (y>7.5): scr.addstr(17,x+30,'*') elif (y>6): scr.addstr(18,x+30,'*') elif (y>4.5): scr.addstr(19,x+30,'*') elif (y>3): scr.addstr(20,x+30,'*') elif (y>1.5): scr.addstr(21,x+30,'*') else: scr.addstr(22,x+30,'*') for x in range(len(wattdata)): y=abs(wattdata[x]) if (y>1687.5): scr.addstr(13,x+54,'*') elif (y>1500): scr.addstr(14,x+54,'*') elif (y>1312.5): scr.addstr(15,x+54,'*') elif (y>1125): scr.addstr(16,x+54,'*') elif (y>937.5): scr.addstr(17,x+54,'*') elif (y>750): scr.addstr(18,x+54,'*') elif (y>562.5): scr.addstr(19,x+54,'*') elif (y>375): scr.addstr(20,x+54,'*') elif (y>187.5): scr.addstr(21,x+54,'*') else: scr.addstr(22,x+54,'*') # Lets log it! Seek to the end of our log file if logfile: # save on disk writes (for ssd) if (counter>=60): write_to_log() if not DEBUG: scr.addstr(1,42,"Log file flushed.") else: if DEBUG: print "\tNext log file flush in "+str((60-counter)*2)+" seconds." else: scr.addstr(1,42,"Next log file flush in "+str((60-counter)*2)+" seconds") if not DEBUG: scr.refresh() counter+=1
def update_graph(idleevent): global avgwattdataidx, sensorhistories, twittertimer, DEBUG # grab one packet from the xbee, or timeout packet = xbee.find_packet(ser) if not packet: return # we timedout xb = xbee(packet) # parse the packet #print xb.address_16 if DEBUG: # for debugging sometimes we only want one print xb # we'll only store n-1 samples since the first one is usually messed up voltagedata = [-1] * (len(xb.analog_samples) - 1) ampdata = [-1] * (len(xb.analog_samples ) -1) # grab 1 thru n of the ADC readings, referencing the ADC constants # and store them in nice little arrays for i in range(len(voltagedata)): voltagedata[i] = xb.analog_samples[i+1][VOLTSENSE] ampdata[i] = xb.analog_samples[i+1][CURRENTSENSE] if DEBUG: print "ampdata: "+str(ampdata) print "voltdata: "+str(voltagedata) # get max and min voltage and normalize the curve to '0' # to make the graph 'AC coupled' / signed min_v = 1024 # XBee ADC is 10 bits, so max value is 1023 max_v = 0 for i in range(len(voltagedata)): if (min_v > voltagedata[i]): min_v = voltagedata[i] if (max_v < voltagedata[i]): max_v = voltagedata[i] # figure out the 'average' of the max and min readings avgv = (max_v + min_v) / 2 # also calculate the peak to peak measurements vpp = max_v-min_v for i in range(len(voltagedata)): #remove 'dc bias', which we call the average read voltagedata[i] -= avgv # We know that the mains voltage is 120Vrms = +-170Vpp voltagedata[i] = (voltagedata[i] * MAINSVPP) / vpp # normalize current readings to amperes for i in range(len(ampdata)): # VREF is the hardcoded 'DC bias' value, its # about 492 but would be nice if we could somehow # get this data once in a while maybe using xbeeAPI if vrefcalibration[xb.address_16]: ampdata[i] -= vrefcalibration[xb.address_16] else: ampdata[i] -= vrefcalibration[0] # the CURRENTNORM is our normalizing constant # that converts the ADC reading to Amperes ampdata[i] /= CURRENTNORM #print "Voltage, in volts: ", voltagedata #print "Current, in amps: ", ampdata # calculate instant. watts, by multiplying V*I for each sample point wattdata = [0] * len(voltagedata) for i in range(len(wattdata)): wattdata[i] = voltagedata[i] * ampdata[i] # sum up the current drawn over one 1/60hz cycle avgamp = 0 # 16.6 samples per second, one cycle = ~17 samples # close enough for govt work :( for i in range(17): avgamp += abs(ampdata[i]) avgamp /= 17.0 # sum up power drawn over one 1/60hz cycle avgwatt = 0 # 16.6 samples per second, one cycle = ~17 samples for i in range(17): avgwatt += abs(wattdata[i]) avgwatt /= 17.0 # Print out our most recent measurements if not QUIET: print str(xb.address_16)+"\tCurrent draw, in amperes: "+str(avgamp) print "\tWatt draw, in VA: "+str(avgwatt) if (avgamp > 13): return # hmm, bad data if GRAPHIT: # Add the current watt usage to our graph history avgwattdata[avgwattdataidx] = avgwatt avgwattdataidx += 1 if (avgwattdataidx >= len(avgwattdata)): # If we're running out of space, shift the first 10% out tenpercent = int(len(avgwattdata)*0.1) for i in range(len(avgwattdata) - tenpercent): avgwattdata[i] = avgwattdata[i+tenpercent] for i in range(len(avgwattdata) - tenpercent, len(avgwattdata)): avgwattdata[i] = 0 avgwattdataidx = len(avgwattdata) - tenpercent # retreive the history for this sensor sensorhistory = sensorhistories.find(xb.address_16) #print sensorhistory # add up the delta-watthr used since last reading # Figure out how many watt hours were used since last reading elapsedseconds = time.time() - sensorhistory.lasttime dwatthr = (avgwatt * elapsedseconds) / (60.0 * 60.0) # 60 seconds in 60 minutes = 1 hr sensorhistory.lasttime = time.time() if not QUIET: print "\t\tWh used in last ",elapsedseconds," seconds: ",dwatthr sensorhistory.addwatthr(dwatthr) # Determine the minute of the hour (ie 6:42 -> '42') currminute = (int(time.time())/60) % 10 # Figure out if its been five minutes since our last save if (((time.time() - sensorhistory.fiveminutetimer) >= 60.0) and (currminute % 5 == 0) ): currPowerMeter_Update_Time = time.time() # Print out debug data, Wh used in last 5 minutes avgwattsused = sensorhistory.avgwattover5min() print time.strftime("%Y %m %d, %H:%M")+", "+str(sensorhistory.sensornum)+", "+str(sensorhistory.avgwattover5min())+"\n" # Lets log it! Seek to the end of our log file if logfile: logfile.seek(0, 2) # 2 == SEEK_END. ie, go to the end of the file logfile.write(time.strftime("%Y %m %d, %H:%M")+", "+ str(sensorhistory.sensornum)+", "+ str(sensorhistory.avgwattover5min())+"\n") logfile.flush() # Or, send it to the app engine if not LOGFILENAME: appengineauth.sendreport(xb.address_16, avgwattsused) #Send it to GooglePowerMeter: #Power meter can take readings in Joules (W*sec) #Multiply the average Watts used in the last 300 sec by 300 seconds try: powerMeter.PostIntervalReading( sensorhistory.avgwattover5min() * (currPowerMeter_Update_Time - powerMeter.last_read_time) * powerMeterUnit, powerMeterUncertainty * powerMeterUnit, powerMeter.last_read_time, currPowerMeter_Update_Time ) except (IOError, socket.error), e: print '-- %s: %s' % (e.__class__.__name__, e) # Reset our 5 minute timer sensorhistory.reset5mintimer()
def update_graph(idleevent): global avgwattdataidx, sensorhistories, twittertimer, DEBUG # grab one packet from the xbee, or timeout packet = xbee.find_packet(ser) if not packet: return # we timedout xb = xbee(packet) # parse the packet #print xb.address_16 if DEBUG: # for debugging sometimes we only want one print xb # we'll only store n-1 samples since the first one is usually messed up voltagedata = [-1] * (len(xb.analog_samples) - 1) ampdata = [-1] * (len(xb.analog_samples) - 1) # grab 1 thru n of the ADC readings, referencing the ADC constants # and store them in nice little arrays for i in range(len(voltagedata)): voltagedata[i] = xb.analog_samples[i + 1][VOLTSENSE] ampdata[i] = xb.analog_samples[i + 1][CURRENTSENSE] if DEBUG: print "ampdata: " + str(ampdata) print "voltdata: " + str(voltagedata) # get max and min voltage and normalize the curve to '0' # to make the graph 'AC coupled' / signed min_v = 1024 # XBee ADC is 10 bits, so max value is 1023 max_v = 0 for i in range(len(voltagedata)): if (min_v > voltagedata[i]): min_v = voltagedata[i] if (max_v < voltagedata[i]): max_v = voltagedata[i] # figure out the 'average' of the max and min readings avgv = (max_v + min_v) / 2 # also calculate the peak to peak measurements vpp = max_v - min_v for i in range(len(voltagedata)): #remove 'dc bias', which we call the average read voltagedata[i] -= avgv # We know that the mains voltage is 120Vrms = +-170Vpp voltagedata[i] = (voltagedata[i] * MAINSVPP) / vpp # normalize current readings to amperes for i in range(len(ampdata)): # VREF is the hardcoded 'DC bias' value, its # about 492 but would be nice if we could somehow # get this data once in a while maybe using xbeeAPI if vrefcalibration[xb.address_16]: ampdata[i] -= vrefcalibration[xb.address_16] else: ampdata[i] -= vrefcalibration[0] # the CURRENTNORM is our normalizing constant # that converts the ADC reading to Amperes ampdata[i] /= CURRENTNORM #print "Voltage, in volts: ", voltagedata #print "Current, in amps: ", ampdata # calculate instant. watts, by multiplying V*I for each sample point wattdata = [0] * len(voltagedata) for i in range(len(wattdata)): wattdata[i] = voltagedata[i] * ampdata[i] # sum up the current drawn over one 1/60hz cycle avgamp = 0 # 16.6 samples per second, one cycle = ~17 samples # close enough for govt work :( for i in range(17): avgamp += abs(ampdata[i]) avgamp /= 17.0 # sum up power drawn over one 1/60hz cycle avgwatt = 0 # 16.6 samples per second, one cycle = ~17 samples for i in range(17): avgwatt += abs(wattdata[i]) avgwatt /= 17.0 # Print out our most recent measurements if not QUIET: print str(xb.address_16) + "\tCurrent draw, in amperes: " + str(avgamp) print "\tWatt draw, in VA: " + str(avgwatt) if (avgamp > 13): return # hmm, bad data if GRAPHIT: # Add the current watt usage to our graph history avgwattdata[avgwattdataidx] = avgwatt avgwattdataidx += 1 if (avgwattdataidx >= len(avgwattdata)): # If we're running out of space, shift the first 10% out tenpercent = int(len(avgwattdata) * 0.1) for i in range(len(avgwattdata) - tenpercent): avgwattdata[i] = avgwattdata[i + tenpercent] for i in range(len(avgwattdata) - tenpercent, len(avgwattdata)): avgwattdata[i] = 0 avgwattdataidx = len(avgwattdata) - tenpercent # retreive the history for this sensor sensorhistory = sensorhistories.find(xb.address_16) #print sensorhistory # add up the delta-watthr used since last reading # Figure out how many watt hours were used since last reading elapsedseconds = time.time() - sensorhistory.lasttime dwatthr = (avgwatt * elapsedseconds) / ( 60.0 * 60.0) # 60 seconds in 60 minutes = 1 hr sensorhistory.lasttime = time.time() if not QUIET: print "\t\tWh used in last ", elapsedseconds, " seconds: ", dwatthr sensorhistory.addwatthr(dwatthr) # Determine the minute of the hour (ie 6:42 -> '42') currminute = (int(time.time()) / 60) % 10 # Figure out if its been five minutes since our last save if (((time.time() - sensorhistory.fiveminutetimer) >= 60.0) and (currminute % 5 == 0)): currPowerMeter_Update_Time = time.time() # Print out debug data, Wh used in last 5 minutes avgwattsused = sensorhistory.avgwattover5min() print time.strftime("%Y %m %d, %H:%M") + ", " + str( sensorhistory.sensornum) + ", " + str( sensorhistory.avgwattover5min()) + "\n" # Lets log it! Seek to the end of our log file if logfile: logfile.seek(0, 2) # 2 == SEEK_END. ie, go to the end of the file logfile.write( time.strftime("%Y %m %d, %H:%M") + ", " + str(sensorhistory.sensornum) + ", " + str(sensorhistory.avgwattover5min()) + "\n") logfile.flush() # Or, send it to the app engine if not LOGFILENAME: appengineauth.sendreport(xb.address_16, avgwattsused) #Send it to GooglePowerMeter: #Power meter can take readings in Joules (W*sec) #Multiply the average Watts used in the last 300 sec by 300 seconds try: powerMeter.PostIntervalReading( sensorhistory.avgwattover5min() * (currPowerMeter_Update_Time - powerMeter.last_read_time) * powerMeterUnit, powerMeterUncertainty * powerMeterUnit, powerMeter.last_read_time, currPowerMeter_Update_Time) except (IOError, socket.error), e: print '-- %s: %s' % (e.__class__.__name__, e) # Reset our 5 minute timer sensorhistory.reset5mintimer()
def update_graph(idleevent): global avgwattdataidx, sensorhistories, twittertimer, DEBUG, incoffee, coffeecutoff shouldtweet = False # grab one packet from the xbee, or timeout packet = xbee.find_packet(ser) if not packet: return # we timedout xb = xbee(packet) # parse the packet #print xb.address_16 if DEBUG: # for debugging sometimes we only want one print xb # we'll only store n-1 samples since the first one is usually messed up voltagedata = [-1] * (len(xb.analog_samples) - 1) ampdata = [-1] * (len(xb.analog_samples ) -1) # grab 1 thru n of the ADC readings, referencing the ADC constants # and store them in nice little arrays for i in range(len(voltagedata)): voltagedata[i] = xb.analog_samples[i+1][VOLTSENSE] ampdata[i] = xb.analog_samples[i+1][CURRENTSENSE] if DEBUG: print "ampdata: "+str(ampdata) print "voltdata: "+str(voltagedata) # get max and min voltage and normalize the curve to '0' # to make the graph 'AC coupled' / signed min_v = 1024 # XBee ADC is 10 bits, so max value is 1023 max_v = 0 for i in range(len(voltagedata)): if (min_v > voltagedata[i]): min_v = voltagedata[i] if (max_v < voltagedata[i]): max_v = voltagedata[i] # figure out the 'average' of the max and min readings avgv = (max_v + min_v) / 2 # also calculate the peak to peak measurements vpp = max_v-min_v for i in range(len(voltagedata)): #remove 'dc bias', which we call the average read voltagedata[i] -= avgv # We know that the mains voltage is 120Vrms = +-170Vpp voltagedata[i] = (voltagedata[i] * MAINSVPP) / vpp # normalize current readings to amperes for i in range(len(ampdata)): # VREF is the hardcoded 'DC bias' value, its # about 492 but would be nice if we could somehow # get this data once in a while maybe using xbeeAPI if vrefcalibration[xb.address_16]: ampdata[i] -= vrefcalibration[xb.address_16] else: ampdata[i] -= vrefcalibration[0] # the CURRENTNORM is our normalizing constant # that converts the ADC reading to Amperes ampdata[i] /= CURRENTNORM print "Voltage, in volts: ", voltagedata print "Current, in amps: ", ampdata # calculate instant. watts, by multiplying V*I for each sample point wattdata = [0] * len(voltagedata) for i in range(len(wattdata)): wattdata[i] = voltagedata[i] * ampdata[i] # sum up the current drawn over one 1/60hz cycle avgamp = 0 # 16.6 samples per second, one cycle = ~17 samples # close enough for govt work :( for i in range(17): avgamp += abs(ampdata[i]) avgamp /= 17.0 # sum up power drawn over one 1/60hz cycle avgwatt = 0 # 16.6 samples per second, one cycle = ~17 samples for i in range(17): avgwatt += abs(wattdata[i]) avgwatt /= 17.0 if (avgamp > 13): return # hmm, bad data # Print out our most recent measurements print str(xb.address_16)+"\tCurrent draw, in amperes: "+str(avgamp) print "\tWatt draw, in VA: "+str(avgwatt) if(avgwatt > coffeecutoff and incoffee == False): print "MAKING COFFEE!!!\n" incoffee = True shouldtweet = True elif(avgwatt < coffeecutoff and incoffee == True): print "NO MORE COFFEE :(\n" incoffee = False shouldtweet = True if GRAPHIT: # Add the current watt usage to our graph history avgwattdata[avgwattdataidx] = avgwatt avgwattdataidx += 1 if (avgwattdataidx >= len(avgwattdata)): # If we're running out of space, shift the first 10% out tenpercent = int(len(avgwattdata)*0.1) for i in range(len(avgwattdata) - tenpercent): avgwattdata[i] = avgwattdata[i+tenpercent] for i in range(len(avgwattdata) - tenpercent, len(avgwattdata)): avgwattdata[i] = 0 avgwattdataidx = len(avgwattdata) - tenpercent # retreive the history for this sensor sensorhistory = sensorhistories.find(xb.address_16) print sensorhistory # add up the delta-watthr used since last reading # Figure out how many watt hours were used since last reading elapsedseconds = time.time() - sensorhistory.lasttime dwatthr = (avgwatt * elapsedseconds) / (60.0 * 60.0) # 60 seconds in 60 minutes = 1 hr sensorhistory.lasttime = time.time() print "\t\tWh used in last ",elapsedseconds," seconds: ",dwatthr sensorhistory.addwatthr(dwatthr) # Determine the minute of the hour (ie 6:42 -> '42') currminute = (int(time.time())/60) % 10 # Figure out if its been five minutes since our last save if (((time.time() - sensorhistory.fiveminutetimer) >= 60.0) and (currminute % 5 == 0) ): # Print out debug data, Wh used in last 5 minutes avgwattsused = sensorhistory.avgwattover5min() print time.strftime("%Y %m %d, %H:%M")+", "+str(sensorhistory.sensornum)+", "+str(sensorhistory.avgwattover5min())+"\n" # Lets log it! Seek to the end of our log file if logfile: logfile.seek(0, 2) # 2 == SEEK_END. ie, go to the end of the file logfile.write(time.strftime("%Y %m %d, %H:%M")+", "+ str(sensorhistory.sensornum)+", "+ str(sensorhistory.avgwattover5min())+"\n") logfile.flush() # Or, send it to the app engine if not LOGFILENAME: appengineauth.sendreport(xb.address_16, avgwattsused) # Reset our 5 minute timer sensorhistory.reset5mintimer() # We're going to twitter at midnight, 8am and 4pm # Determine the hour of the day (ie 6:42 -> '6') currhour = datetime.datetime.now().hour # twitter every 8 hours if (shouldtweet): #((time.time() - twittertimer) >= 3660.0) and (currhour % 8 == 0)): shouldtweet = False print "twittertime!" twittertimer = time.time(); if not LOGFILENAME: message = appengineauth.gettweetreport() else: # sum up all the sensors' data wattsused = 0 whused = 0 for history in sensorhistories.sensorhistories: wattsused += history.avgwattover5min() whused += history.dayswatthr message = "Currently using "+str(int(wattsused))+" Watts, "+str(int(whused))+" Wh today so far #tweetawatt" if(incoffee): message = "Made coffee!!! %s #happyday" % (datetime.datetime.now()) else: message = "No more coffee %s #sadface" % (datetime.datetime.now()) # write sometdatetime.datetime.now() hindatetime.datetime.now() g ourselves if message: print message TwitterIt(twitterusername, twitterpassword, message) if GRAPHIT: # Redraw our pretty picture fig.canvas.draw_idle() # Update with latest data wattusageline.set_ydata(avgwattdata) voltagewatchline.set_ydata(voltagedata) ampwatchline.set_ydata(ampdata) # Update our graphing range so that we always see all the data maxamp = max(ampdata) minamp = min(ampdata) maxamp = max(maxamp, -minamp) mainsampwatcher.set_ylim(maxamp * -1.2, maxamp * 1.2) wattusage.set_ylim(0, max(avgwattdata) * 1.2)
#!/usr/bin/env python import serial from xbee import xbee SERIALPORT = "/dev/tts/0" # the com/serial port the XBee is connected to BAUDRATE = 9600 # the baud rate we talk to the xbee # open up the FTDI serial port to get data transmitted to xbee ser = serial.Serial(SERIALPORT, BAUDRATE) ser.open() while True: # grab one packet from the xbee, or timeout packet = xbee.find_packet(ser) if packet: xb = xbee(packet) print ">>> " print xb
def update_graph(idleevent): global avgwattdataidx, sensorhistories, twittertimer, onlywatchfor # grab one packet from the xbee, or timeout packet = xbee.find_packet(ser) if packet: xb = xbee(packet) print xb.address_16 if (onlywatchfor != 0): if (xb.address_16 != onlywatchfor): return print xb # we'll only store n-1 samples since the first one is usually messed up voltagedata = [-1] * (len(xb.analog_samples) - 1) ampdata = [-1] * (len(xb.analog_samples ) -1) # grab 1 thru n of the ADC readings, referencing the ADC constants # and store them in nice little arrays for i in range(len(voltagedata)): voltagedata[i] = xb.analog_samples[i+1][VOLTSENSE] ampdata[i] = xb.analog_samples[i+1][CURRENTSENSE] #print ampdata # get max and min voltage and normalize the curve to '0' # to make the graph 'AC coupled' / signed min_v = 1024 # XBee ADC is 10 bits, so max value is 1023 max_v = 0 for i in range(len(voltagedata)): if (min_v > voltagedata[i]): min_v = voltagedata[i] if (max_v < voltagedata[i]): max_v = voltagedata[i] # figure out the 'average' of the max and min readings avgv = (max_v + min_v) / 2 # also calculate the peak to peak measurements vpp = max_v-min_v for i in range(len(voltagedata)): #remove 'dc bias', which we call the average read voltagedata[i] -= avgv # We know that the mains voltage is 120Vrms = +-170Vpp voltagedata[i] = (voltagedata[i] * MAINSVPP) / vpp # normalize current readings to amperes for i in range(len(ampdata)): # VREF is the hardcoded 'DC bias' value, its # about 492 but would be nice if we could somehow # get this data once in a while maybe using xbeeAPI if vrefs[xb.address_16]: ampdata[i] -= vrefs[xb.address_16] else: ampdata[i] -= vrefs[0] # the CURRENTNORM is our normalizing constant # that converts the ADC reading to Amperes ampdata[i] /= CURRENTNORM #print "Voltage, in volts: ", voltagedata #print "Current, in amps: ", ampdata # calculate instant. watts, by multiplying V*I for each sample point wattdata = [0] * len(voltagedata) for i in range(len(wattdata)): wattdata[i] = voltagedata[i] * ampdata[i] # sum up the current drawn over one 1/60hz cycle avgamp = 0 # 16.6 samples per second, one cycle = ~17 samples # close enough for govt work :( for i in range(17): avgamp += abs(ampdata[i]) avgamp /= 17.0 # sum up power drawn over one 1/60hz cycle avgwatt = 0 # 16.6 samples per second, one cycle = ~17 samples for i in range(17): avgwatt += abs(wattdata[i]) avgwatt /= 17.0 # Print out our most recent measurements print str(xb.address_16)+"\tCurrent draw, in amperes: "+str(avgamp) print "\tWatt draw, in VA: "+str(avgwatt) # Add the current watt usage to our graph history avgwattdata[avgwattdataidx] = avgwatt avgwattdataidx += 1 if (avgwattdataidx >= len(avgwattdata)): # If we're running out of space, shift the first 10% out tenpercent = int(len(avgwattdata)*0.1) for i in range(len(avgwattdata) - tenpercent): avgwattdata[i] = avgwattdata[i+tenpercent] for i in range(len(avgwattdata) - tenpercent, len(avgwattdata)): avgwattdata[i] = 0 avgwattdataidx = len(avgwattdata) - tenpercent # retreive the history for this sensor sensorhistory = findsensorhistory(xb.address_16) #print sensorhistory # add up the delta-watthr used since last reading # Figure out how many watt hours were used since last reading elapsedseconds = time.time() - sensorhistory.lasttime dwatthr = (avgwatt * elapsedseconds) / (60.0 * 60.0) # 60 seconds in 60 minutes = 1 hr sensorhistory.lasttime = time.time() print "\t\tWh used in last ",elapsedseconds," seconds: ",dwatthr sensorhistory.addwatthr(dwatthr) # Determine the minute of the hour (ie 6:42 -> '42') currminute = (int(time.time())/60) % 10 # Figure out if its been five minutes since our last save if (((time.time() - sensorhistory.fiveminutetimer) >= 60.0) and (currminute % 5 == 0)): # Print out debug data, Wh used in last 5 minutes avgwattsused = sensorhistory.avgwattover5min() print time.strftime("%Y %m %d, %H:%M"),", ",sensorhistory.cumulativewatthr,"Wh = ",avgwattsused," W average" # Also, send it to the app engine appengineauth.sendreport(xb.address_16, avgwattsused) # Reset our 5 minute timer sensorhistory.reset5mintimer() # We're going to twitter at midnight, 8am and 4pm # Determine the hour of the day (ie 6:42 -> '6') currhour = datetime.datetime.now().hour if (((time.time() - twittertimer) >= 3660.0) and (currhour % 8 == 0)): print "twittertime!" twittertimer = time.time(); TwitterIt(twitterusername, twitterpassword, appengineauth.gettweetreport()) # Redraw our pretty picture fig.canvas.draw_idle() # Update with latest data wattusageline.set_ydata(avgwattdata) voltagewatchline.set_ydata(voltagedata) ampwatchline.set_ydata(ampdata) # Update our graphing range so that we always see all the data maxamp = max(ampdata) minamp = min(ampdata) maxamp = max(maxamp, -minamp) mainsampwatcher.set_ylim(maxamp * -1.2, maxamp * 1.2) wattusage.set_ylim(0, max(avgwattdata) * 1.2)
def update_graph(idleevent): global avgwattdataidx, sensorhistories, DEBUG #get one packet from the xbee or timeout packet = xbee.find_packet(ser) if not packet: return #timeout xb = xbee(packet) #parse print xb.address_16 #n-1 samples as first one is not correct voltagedata = [-1] * (len(xb.analog_samples) - 1) ampdata = [-1] * (len(xb.analog_samples) -1) #store in arrays for i in range(len(voltagedata)): voltagedata[i] = xb.analog_samples[i+1][VOLTSENSE] ampdata[i] = xb.analog_samples[i+1][CURRENTSENSE] #normalising data min_v = 1024 #xbee adc is 10 bits so max = 1023 max_v = 0 for i in range(len(voltagedata)): if (min_v > voltagedata[i]): min_v = voltagedata[i] if (max_v < voltagedata[i]): max_v = voltagedata[i] #average of min & max voltage avg_v = (max_v + min_v) / 2 vpp = max_v-min_v #vpp for i in range(len(voltagedata)): #remove dc bias voltagedata[i] -= avg_v voltagedata[i] = (voltagedata[i] * MAINSVPP) / vpp #normailse current for i in range(len(ampdata)): if vrefcalibration[xb.address_16]: ampdata[i] -= vrefcalibration[xb.address_16] else: ampdata[i] -= vrefcalibration[0] ampdata[i] /= CURRENTNORM print "Voltage: ", voltagedata print "Current: ", ampdata #calculate power wattdata = [0] * len(voltagedata) for i in range(len(wattdata)): wattdata[i] = voltagedata[i] * ampdata[i] #sum current over 1/50Hz avgamp = 0 #17 cycles per seccond for i in range(17): avgamp += abs(ampdata[i]) avgamp /= 17.0 #sum power over 1/50Hz avgwatt = 0 #17 cycles per seccond for i in range(17): avgwatt += abs(wattdata[i]) avgwatt /= 17.0 sensorhistory = sensorhistories.find(xb.address_16) print sensorhistory elapsedseconds = time.time() - sensorhistory.lasttime dwatthr = (avgwatt * elapsedseconds) / (60.0 * 60.0) # 60 seconds in 60 minutes = 1 hr sensorhistory.lasttime = time.time() print "\t\tWh used in last ",elapsedseconds," seconds: ",dwatthr sensorhistory.addwatthr(dwatthr) # Determine the minute of the hour (ie 6:42 -> '42') currminute = (int(time.time())/60) % 10 # Figure out if its been five minutes since our last save if (((time.time() - sensorhistory.fiveminutetimer) >= 60.0) and (currminute % 2 == 0) ): wattsused = 0 whused = 0 for history in sensorhistories.sensorhistories: wattsused += history.avgwattover5min() whused += history.dayswatthr kwhused = whused/1000 avgwatt = sensorhistory.avgwattover5min() cost = kwhused * ENERGY_PRICE cost = "%.2f" % cost params = urllib.urlencode({'field1': avgwatt, 'field2': kwhused, 'field3': cost, 'key': API_KEY}) headers = {"content-type": "application/x-www-form-urlencoded","Accept": "text/plain"} conn = httplib.HTTPConnection(API_URL) try: conn.request("POST", "/update", params, headers) response = conn.getresponse() print response.status, response.reason data = response.read() conn.close() except: print "connection failed" # Print out debug data, Wh used in last 5 minutes avgwattsused = sensorhistory.avgwattover5min() print time.strftime("%Y %m %d, %H:%M")+", "+str(sensorhistory.sensornum)+", "+str(sensorhistory.avgwattover5min())+"\n" # Lets log it! Seek to the end of our log file if logfile: logfile.seek(0, 2) # 2 == SEEK_END. ie, go to the end of the file logfile.write(time.strftime("%Y %m %d, %H:%M")+", "+ str(sensorhistory.sensornum)+", "+ str(sensorhistory.avgwattover5min())+"\n") logfile.flush() if __name__ == "__main__": while True: update_graph(None)
def update_graph(idleevent): global avgwattdataidx, twittertimer, DEBUG, tempdata, samplenum, dbsample1, dbsample2, dbsample3, dbsample4, db #,sensorhistories # grab one packet from the xbee, or timeout packet = xbee.find_packet(ser) if not packet: return # we timedout xb = xbee(packet) # parse the packet ###################################### Sensor 1 ########################################################### if xb.address_16 == KILLAWATT1: # we'll only store n-1 samples since the first one is usually messed up voltagedata = [-1] * (len(xb.analog_samples) - 1) ampdata = [-1] * (len(xb.analog_samples ) -1) # grab 1 thru n of the ADC readings, referencing the ADC constants # and store them in nice little arrays for i in range(len(voltagedata)): voltagedata[i] = xb.analog_samples[i+1][VOLTSENSE] ampdata[i] = xb.analog_samples[i+1][CURRENTSENSE] # get max and min voltage and normalize the curve to '0' # to make the graph 'AC coupled' / signed min_v = 1024 # XBee ADC is 10 bits, so max value is 1023 max_v = 0 for i in range(len(voltagedata)): if (min_v > voltagedata[i]): min_v = voltagedata[i] if (max_v < voltagedata[i]): max_v = voltagedata[i] # figure out the 'average' of the max and min readings avgv = (max_v + min_v) / 2 # also calculate the peak to peak measurements vpp = max_v-min_v for i in range(len(voltagedata)): #remove 'dc bias', which we call the average read voltagedata[i] -= avgv # We know that the mains voltage is 120Vrms = +-170Vpp voltagedata[i] = (voltagedata[i] * MAINSVPP) / vpp # normalize current readings to amperes for i in range(len(ampdata)): # VREF is the hardcoded 'DC bias' value, its # about 492 but would be nice if we could somehow # get this data once in a while maybe using xbeeAPI if vrefcalibration[xb.address_16]: ampdata[i] -= vrefcalibration[xb.address_16] else: ampdata[i] -= vrefcalibration[0] # the CURRENTNORM is our normalizing constant # that converts the ADC reading to Amperes ampdata[i] /= CURRENTNORM # calculate instant. watts, by multiplying V*I for each sample point wattdata = [0] * len(voltagedata) for i in range(len(wattdata)): wattdata[i] = voltagedata[i] * ampdata[i] # sum up the current drawn over one 1/60hz cycle avgamp = 0 # 16.6 samples per second, one cycle = ~17 samples # close enough for govt work :( for i in range(len(ampdata)): avgamp += abs(ampdata[i]) avgamp /= float(len(ampdata)) # sum up power drawn over one 1/60hz cycle avgwatt = 0 # 16.6 samples per second, one cycle = ~17 samples for i in range(len(wattdata)): avgwatt += abs(wattdata[i]) avgwatt /= float(len(wattdata)) # Print out our most recent measurements message = "" message = message + "Sensor #: "+str(xb.address_16)+ " (Tweetawatt) Sample # " + str(samplenum) + ". Signal RSSI is : " + str(xb.rssi) message = message + " Current draw, in amperes: "+str(avgamp) message = message + " Watt draw, in VA: "+str(avgwatt) #print message if dbsample1 >15: sql = "INSERT into databasename.sensordata(xbeeid, sensorname0, sensortime, sensorvalue0, sensortype0, sensorname1, sensorvalue1, sensortype1, samplecount, sensorRSSI) VALUES ('1','Pump Amps','" sql = sql + strftime("%Y-%m-%d %H:%M:%S") + "','" + str(avgamp) + "', 'Amps','Pump Watts','" + str(avgwatt) + "','Watts','" + str(samplenum) + "','" + str(xb.rssi) + "')" #print sql if db == 0: # check if connection is there... and open it if it isnt db = MySQLdb.connect(host="website",user="******",passwd="password",db="dbn") try: curs = db.cursor() # Get a db cursor curs.execute(sql) # execute the SQL db.commit # commit the changes to the DB #print "successfull query : " + sql # debug info dbsample1 = 0 # reset the couter except StandardError, err: # may have lost host #print "- lost host trying to reopen db - retrying" + str(err) db = MySQLdb.connect(host="website.com",user="******",passwd="pw",db="dbn") curs = db.cursor() curs.execute(sql) db.commit dbsample1 = 0 #print "I think it worked... " + sql dbsample1 +=1
def update_graph(idleevent): global avgwattdataidx, sensorhistories, twittertimer, DEBUG, currday # DAW - 5/18/11 - wrap the whole xbee packet inspection code in an exception handler try: # grab one packet from the xbee, or timeout packet = xbee.find_packet(ser) if not packet: return # we timedout xb = xbee(packet) # parse the packet #print xb.address_16 if DEBUG: # for debugging sometimes we only want one print xb # DAW - 5/18/11 - prevent exception that was caused by invalid xbee packet address if xb.address_16 < 0 or xb.address_16 > len(vrefcalibration): LogMsg("ERROR - invalid packet address: " + xb.address_16) return # we'll only store n-1 samples since the first one is usually messed up voltagedata = [-1] * (len(xb.analog_samples) - 1) ampdata = [-1] * (len(xb.analog_samples) - 1) # grab 1 thru n of the ADC readings, referencing the ADC constants # and store them in nice little arrays for i in range(len(voltagedata)): voltagedata[i] = xb.analog_samples[i + 1][VOLTSENSE] ampdata[i] = xb.analog_samples[i + 1][CURRENTSENSE] if DEBUG: print "ampdata: " + str(ampdata) print "voltdata: " + str(voltagedata) # get max and min voltage and normalize the curve to '0' # to make the graph 'AC coupled' / signed min_v = 1024 # XBee ADC is 10 bits, so max value is 1023 max_v = 0 for i in range(len(voltagedata)): if (min_v > voltagedata[i]): min_v = voltagedata[i] if (max_v < voltagedata[i]): max_v = voltagedata[i] # figure out the 'average' of the max and min readings avgv = (max_v + min_v) / 2 # also calculate the peak to peak measurements vpp = max_v - min_v for i in range(len(voltagedata)): #remove 'dc bias', which we call the average read voltagedata[i] -= avgv # We know that the mains voltage is 120Vrms = +-170Vpp voltagedata[i] = (voltagedata[i] * MAINSVPP) / vpp # normalize current readings to amperes for i in range(len(ampdata)): # VREF is the hardcoded 'DC bias' value, its # about 492 but would be nice if we could somehow # get this data once in a while maybe using xbeeAPI if vrefcalibration[xb.address_16]: ampdata[i] -= vrefcalibration[xb.address_16] else: ampdata[i] -= vrefcalibration[0] # the CURRENTNORM is our normalizing constant # that converts the ADC reading to Amperes ampdata[i] /= CURRENTNORM #print "Voltage, in volts: ", voltagedata #print "Current, in amps: ", ampdata # calculate instant. watts, by multiplying V*I for each sample point wattdata = [0] * len(voltagedata) for i in range(len(wattdata)): wattdata[i] = voltagedata[i] * ampdata[i] # sum up the current drawn over one 1/60hz cycle avgamp = 0 # DAW - 2/26/11 - check for less than 17 samples - would sometimes cause index out of range exception if (len(ampdata) < 17): return # 16.6 samples per second, one cycle = ~17 samples # close enough for govt work :( for i in range(17): avgamp += abs(ampdata[i]) avgamp /= 17.0 # DAW - average of all 18 amp readings avgamp2 = 0 for i in range(len(ampdata)): avgamp2 += abs(ampdata[i]) avgamp2 /= len(ampdata) # DAW - average of all 18 volt readings avgvolt = 0 for i in range(len(voltagedata)): avgvolt += abs(voltagedata[i]) avgvolt /= len(voltagedata) # sum up power drawn over one 1/60hz cycle avgwatt = 0 # DAW - 2/26/11 - check for less than 17 samples - would sometimes cause index out of range exception if len(wattdata) < 17: return # 16.6 samples per second, one cycle = ~17 samples for i in range(17): avgwatt += abs(wattdata[i]) avgwatt /= 17.0 # DAW - average of all 18 watt readings avgwatt2 = 0 for i in range(len(wattdata)): avgwatt2 += abs(wattdata[i]) avgwatt2 /= len(wattdata) except: LogMsg("Error in packet handling, ignoring") return # Print out our most recent measurements print str(xb.address_16) + "\tCurrent draw, in amperes: " + str(avgamp) print "\tWatt draw, in VA: " + str(avgwatt) # DAW print out extra data print "\t RSSI: " + str(xb.rssi) + " Volt: " + str( avgvolt) + " Amps: " + str(avgamp2) + " Watts: " + str(avgwatt2) if (avgamp > 13): return # hmm, bad data if GRAPHIT: # Add the current watt usage to our graph history avgwattdata[avgwattdataidx] = avgwatt avgwattdataidx += 1 if (avgwattdataidx >= len(avgwattdata)): # If we're running out of space, shift the first 10% out tenpercent = int(len(avgwattdata) * 0.1) for i in range(len(avgwattdata) - tenpercent): avgwattdata[i] = avgwattdata[i + tenpercent] for i in range(len(avgwattdata) - tenpercent, len(avgwattdata)): avgwattdata[i] = 0 avgwattdataidx = len(avgwattdata) - tenpercent # retreive the history for this sensor sensorhistory = sensorhistories.find(xb.address_16) #print sensorhistory # add up the delta-watthr used since last reading # Figure out how many watt hours were used since last reading elapsedseconds = time.time() - sensorhistory.lasttime dwatthr = (avgwatt * elapsedseconds) / ( 60.0 * 60.0) # 60 seconds in 60 minutes = 1 hr sensorhistory.lasttime = time.time() print "\t\tWh used in last ", elapsedseconds, " seconds: ", dwatthr sensorhistory.addwatthr(dwatthr) if DEBUG: print "sensorhistory.avgwattover5min is " + str( sensorhistory.avgwattover5min()) print time.strftime("%Y %m %d, %H:%M") + ", " + str( sensorhistory.sensornum) + ", " + str( sensorhistory.avgwattover5min()) + "\n" # Determine the minute of the hour (ie 6:42 -> '42') currminute = (int(time.time()) / 60) % 10 # Figure out if its been five minutes since our last save if (((time.time() - sensorhistory.fiveminutetimer) >= 60.0) and (currminute % 5 == 0)): # Print out debug data, Wh used in last 5 minutes avgwattsused = sensorhistory.avgwattover5min() print time.strftime("%Y %m %d, %H:%M") + ", " + str( sensorhistory.sensornum) + ", " + str( sensorhistory.avgwattover5min()) + "\n" # Lets log it! Seek to the end of our log file if logfile: logfile.seek(0, 2) # 2 == SEEK_END. ie, go to the end of the file logfile.write( time.strftime("%Y %m %d, %H:%M") + ", " + str(sensorhistory.sensornum) + ", " + str(sensorhistory.avgwattover5min()) + "\n") logfile.flush() # Or, send it to the app engine if not LOGFILENAME: appengineauth.sendreport(xb.address_16, avgwattsused) # DAW - 1/18/11 - log avg watts used to nimbits # avgwattstosend = "%.2f" % avgwattsused if NIMBITS_ID: try: urllib.urlopen( "http://gigamega-beta.appspot.com/service/currentvalue?value=" + str(avgwattsused) + "&point=" + NIMBITS_ID + "&[email protected]&secret=e90d9c41-6529-4cf8-b248-92335c577cc7" ) except IOError: print 'Error sending to nimbits' # DAW - 2/7/11 - log avg watts used to Pachube if PACHUBE_ID: try: pac.update([ eeml.Data(int(PACHUBE_ID), avgwattsused, unit=eeml.Watt()) ]) # unit=eeml.Unit('Volt', type='basicSI', symbol='V'))]) pac.put() except: print 'Error sending to Pachube' # DAW - 8/7/10 - moved here from below - otherwise, reset5mintimer can cause watts to be 0 when tweet occurs # We're going to twitter at midnight, 8am and 4pm # Determine the hour of the day (ie 6:42 -> '6') currhour = datetime.datetime.now().hour # twitter every 8 hours # DAW - if debugging, twitter (actually just log to file) every minute #if ((((time.time() - twittertimer) >= 3660.0) and (currhour % 8 == 0)) or (DEBUG and ((time.time() - twittertimer) >= 60.0))): # DAW - twitter every 4 hours if (((time.time() - twittertimer) >= 3660.0) and (currhour % 4 == 0)): print "twittertime!" twittertimer = time.time() if not LOGFILENAME: message = appengineauth.gettweetreport() else: # sum up all the sensors' data wattsused = 0 whused = 0 if DEBUG: print "num sensor histories", len( sensorhistories.sensorhistories) newday = False thisday = datetime.datetime.now().day if currday != thisday: newday = True if DEBUG: message = "New day, clearing dayswatthr " + str( currday) + " to " + str(thisday) LogMsg(message) currday = thisday for history in sensorhistories.sensorhistories: if DEBUG: print "in twitter loop, found history", history.sensornum, history.cumulative5mwatthr wattsused += history.avgwattover5min() whused += history.dayswatthr # DAW - 8/7/10 - clear day's count when day changes if newday: history.dayswatthr = 0 message = "Currently using " + str( int(wattsused)) + " Watts, " + str( int(whused)) + " Wh today so far #tweetawatt" # DAW - 8/7/10 - if it's midnight, clear the day's count # write something ourselves if message: print message # DAW - if debugging, write to CSV file for debug purposes rather than twittering if DEBUG: LogMsg(message) else: #TwitterIt(twitterusername, twitterpassword, message) TwitterIt(message) # Reset our 5 minute timer sensorhistory.reset5mintimer() if GRAPHIT: # Redraw our pretty picture fig.canvas.draw_idle() # Update with latest data wattusageline.set_ydata(avgwattdata) voltagewatchline.set_ydata(voltagedata) ampwatchline.set_ydata(ampdata) # Update our graphing range so that we always see all the data maxamp = max(ampdata) minamp = min(ampdata) maxamp = max(maxamp, -minamp) mainsampwatcher.set_ylim(maxamp * -1.2, maxamp * 1.2) wattusage.set_ylim(0, max(avgwattdata) * 1.2)
def update_graph(idleevent): global avgwattdataidx, sensorhistories, twittertimer, onlywatchfor # grab one packet from the xbee, or timeout packet = xbee.find_packet(ser) if packet: xb = xbee(packet) print xb.address_16 if (onlywatchfor != 0): if (xb.address_16 != onlywatchfor): return print xb # we'll only store n-1 samples since the first one is usually messed up voltagedata = [-1] * (len(xb.analog_samples) - 1) ampdata = [-1] * (len(xb.analog_samples) - 1) # grab 1 thru n of the ADC readings, referencing the ADC constants # and store them in nice little arrays for i in range(len(voltagedata)): voltagedata[i] = xb.analog_samples[i + 1][VOLTSENSE] ampdata[i] = xb.analog_samples[i + 1][CURRENTSENSE] #print ampdata # get max and min voltage and normalize the curve to '0' # to make the graph 'AC coupled' / signed min_v = 1024 # XBee ADC is 10 bits, so max value is 1023 max_v = 0 for i in range(len(voltagedata)): if (min_v > voltagedata[i]): min_v = voltagedata[i] if (max_v < voltagedata[i]): max_v = voltagedata[i] # figure out the 'average' of the max and min readings avgv = (max_v + min_v) / 2 # also calculate the peak to peak measurements vpp = max_v - min_v for i in range(len(voltagedata)): #remove 'dc bias', which we call the average read voltagedata[i] -= avgv # We know that the mains voltage is 120Vrms = +-170Vpp voltagedata[i] = (voltagedata[i] * MAINSVPP) / vpp # normalize current readings to amperes for i in range(len(ampdata)): # VREF is the hardcoded 'DC bias' value, its # about 492 but would be nice if we could somehow # get this data once in a while maybe using xbeeAPI if vrefs[xb.address_16]: ampdata[i] -= vrefs[xb.address_16] else: ampdata[i] -= vrefs[0] # the CURRENTNORM is our normalizing constant # that converts the ADC reading to Amperes ampdata[i] /= CURRENTNORM #print "Voltage, in volts: ", voltagedata #print "Current, in amps: ", ampdata # calculate instant. watts, by multiplying V*I for each sample point wattdata = [0] * len(voltagedata) for i in range(len(wattdata)): wattdata[i] = voltagedata[i] * ampdata[i] # sum up the current drawn over one 1/60hz cycle avgamp = 0 # 16.6 samples per second, one cycle = ~17 samples # close enough for govt work :( for i in range(17): avgamp += abs(ampdata[i]) avgamp /= 17.0 # sum up power drawn over one 1/60hz cycle avgwatt = 0 # 16.6 samples per second, one cycle = ~17 samples for i in range(17): avgwatt += abs(wattdata[i]) avgwatt /= 17.0 # Print out our most recent measurements print str(xb.address_16) + "\tCurrent draw, in amperes: " + str(avgamp) print "\tWatt draw, in VA: " + str(avgwatt) # Add the current watt usage to our graph history avgwattdata[avgwattdataidx] = avgwatt avgwattdataidx += 1 if (avgwattdataidx >= len(avgwattdata)): # If we're running out of space, shift the first 10% out tenpercent = int(len(avgwattdata) * 0.1) for i in range(len(avgwattdata) - tenpercent): avgwattdata[i] = avgwattdata[i + tenpercent] for i in range(len(avgwattdata) - tenpercent, len(avgwattdata)): avgwattdata[i] = 0 avgwattdataidx = len(avgwattdata) - tenpercent # retreive the history for this sensor sensorhistory = findsensorhistory(xb.address_16) #print sensorhistory # add up the delta-watthr used since last reading # Figure out how many watt hours were used since last reading elapsedseconds = time.time() - sensorhistory.lasttime dwatthr = (avgwatt * elapsedseconds) / ( 60.0 * 60.0) # 60 seconds in 60 minutes = 1 hr sensorhistory.lasttime = time.time() print "\t\tWh used in last ", elapsedseconds, " seconds: ", dwatthr sensorhistory.addwatthr(dwatthr) # Determine the minute of the hour (ie 6:42 -> '42') currminute = (int(time.time()) / 60) % 10 # Figure out if its been five minutes since our last save if (((time.time() - sensorhistory.fiveminutetimer) >= 60.0) and (currminute % 5 == 0)): # Print out debug data, Wh used in last 5 minutes avgwattsused = sensorhistory.avgwattover5min() print time.strftime( "%Y %m %d, %H:%M" ), ", ", sensorhistory.cumulativewatthr, "Wh = ", avgwattsused, " W average" # Also, send it to the app engine appengineauth.sendreport(xb.address_16, avgwattsused) # Reset our 5 minute timer sensorhistory.reset5mintimer() # We're going to twitter at midnight, 8am and 4pm # Determine the hour of the day (ie 6:42 -> '6') currhour = datetime.datetime.now().hour if (((time.time() - twittertimer) >= 3660.0) and (currhour % 8 == 0)): print "twittertime!" twittertimer = time.time() TwitterIt(twitterusername, twitterpassword, appengineauth.gettweetreport()) # Redraw our pretty picture fig.canvas.draw_idle() # Update with latest data wattusageline.set_ydata(avgwattdata) voltagewatchline.set_ydata(voltagedata) ampwatchline.set_ydata(ampdata) # Update our graphing range so that we always see all the data maxamp = max(ampdata) minamp = min(ampdata) maxamp = max(maxamp, -minamp) mainsampwatcher.set_ylim(maxamp * -1.2, maxamp * 1.2) wattusage.set_ylim(0, max(avgwattdata) * 1.2)
def update_graph(idleevent): global DEBUG # grab one packet from the xbee, or timeout packet = xbee.find_packet(ser) if not packet: return # we timedout xb = xbee(packet) # parse the packet if DEBUG: # for debugging sometimes we only want one print xb # we'll only store n-1 samples since the first one is usually messed up voltagedata = [-1] * (len(xb.analog_samples) - 1) ampdata = [-1] * (len(xb.analog_samples ) -1) # grab 1 thru n of the ADC readings, referencing the ADC constants # and store them in nice little arrays for i in range(len(voltagedata)): voltagedata[i] = xb.analog_samples[i+1][VOLTSENSE] ampdata[i] = xb.analog_samples[i+1][CURRENTSENSE] # get max and min voltage and normalize the curve to '0' # to make the graph 'AC coupled' / signed min_v = 1024 # XBee ADC is 10 bits, so max value is 1023 max_v = 0 for i in range(len(voltagedata)): if (min_v > voltagedata[i]): min_v = voltagedata[i] if (max_v < voltagedata[i]): max_v = voltagedata[i] # figure out the 'average' of the max and min readings avgv = (max_v + min_v) / 2 # also calculate the peak to peak measurements vpp = max_v-min_v for i in range(len(voltagedata)): #remove 'dc bias', which we call the average read voltagedata[i] -= avgv # We know that the mains voltage is 120Vrms = +-170Vpp voltagedata[i] = (voltagedata[i] * MAINSVPP) / vpp # normalize current readings to amperes for i in range(len(ampdata)): # VREF is the hardcoded 'DC bias' value, its # about 492 but would be nice if we could somehow # get this data once in a while maybe using xbeeAPI if vrefcalibration[xb.address_16]: ampdata[i] -= vrefcalibration[xb.address_16] else: ampdata[i] -= vrefcalibration[0] # the CURRENTNORM is our normalizing constant # that converts the ADC reading to Amperes ampdata[i] /= CURRENTNORM # calculate instant. watts, by multiplying V*I for each sample point wattdata = [0] * len(voltagedata) for i in range(len(wattdata)): wattdata[i] = voltagedata[i] * ampdata[i] # sum up the current drawn over one 1/60hz cycle avgamp = 0 # 16.6 samples per second, one cycle = ~17 samples # close enough for govt work :( for i in range(17): avgamp += abs(ampdata[i]) avgamp /= 17.0 # sum up power drawn over one 1/60hz cycle avgwatt = 0 # 16.6 samples per second, one cycle = ~17 samples for i in range(17): avgwatt += abs(wattdata[i]) avgwatt /= 17.0 # Log results meter_id = xb.address_16 # Print out our most recent measurements print "Meter:", str(meter_id) print "\tCurrent in amperes: "+str(avgamp) print "\tWatts in VA: "+str(avgwatt) if (avgamp > 13): return # hmm, bad data # Figure out how many watt hours were used since last reading meter = meters[meter_id] elapsedseconds = time.time() - meter.lasttime watthr = (avgwatt * elapsedseconds) / (60.0 * 60.0) # 60 seconds in 60 minutes = 1 hr meter.lasttime = time.time() print "\tWatt hours: "+str(watthr) meter.addReading(watthr) TidalLog(avgwatt, watthr, meter_id, True) # determine the minute of the hour (ie 6:42 -> '42') currminute = (int(time.time()) / 60) % 10 if (((time.time() - meter.timer) >= 60.0) and (currminute % 5 == 0)): print "Five Minute Log" avgwatt = meter.getAvgWatts() TidalLog(avgwatt, meter.watthr, meter_id, False) meter.resetTimer()
def update_graph(idleevent): global avgwattdataidx, sensorhistories, datarecieved, currentmonth if ((datetime.today().month) != currentmonth): new_logfile #get one packet from the xbee or timeout packet = xbee.find_packet(ser) if not packet: return #timeout xb = xbee(packet) #parse #print xb.address_16 #n-1 samples as first one is not correct voltagedata = [-1] * (len(xb.analog_samples) - 1) ampdata = [-1] * (len(xb.analog_samples) - 1) #store in arrays for i in range(len(voltagedata)): voltagedata[i] = xb.analog_samples[i + 1][VOLTSENSE] ampdata[i] = xb.analog_samples[i + 1][CURRENTSENSE] min_v = 1024 max_v = 0 #normalising data for i in range(len(voltagedata)): if (min_v > voltagedata[i]): min_v = voltagedata[i] if (max_v < voltagedata[i]): max_v = voltagedata[i] #average of min & max voltage avgv = (max_v + min_v) / 2 vpp = max_v - min_v for i in range(len(voltagedata)): voltagedata[i] -= avgv #remove DC Bias voltagedata[i] = (voltagedata[i] * MAINSVPP) / vpp #normailse current for i in range(len(ampdata)): if vrefcalibration[xb.address_16]: ampdata[i] -= vrefcalibration[xb.address_16] else: ampdata[i] -= vrefcalibration[0] ampdata[i] /= CURRENTNORM #print "Voltage: ", voltagedata #print "Current: ", ampdata #calculate power wattdata = [0] * len(voltagedata) for i in range(len(wattdata)): wattdata[i] = voltagedata[i] * ampdata[i] #sum current over 1/50Hz avgamp = 0 #17 cycles per seccond for i in range(17): avgamp += abs(ampdata[i]) avgamp /= 17.0 #sum power over 1/50Hz avgwatt = 0 #17 cycles per seccond for i in range(17): avgwatt += abs(wattdata[i]) avgwatt /= 17.0 print str(xb.address_16) + "\tCurrent draw, in amperes: " + str(avgamp) print "\tWatt draw, in VA: " + str(avgwatt) if (avgamp > 13): return sensorhistory = sensorhistories.find(xb.address_16) #print sensorhistory elapsedseconds = time.time() - sensorhistory.lasttime dwatthr = (avgwatt * elapsedseconds) / ( 60.0 * 60.0) # 60 seconds in 60 minutes = 1 hr sensorhistory.lasttime = time.time() print "\t\tWh used in last ", elapsedseconds, " seconds: ", dwatthr sensorhistory.addwatthr(dwatthr) datarecieved += 1 # Determine the minute of the hour (ie 6:42 -> '42') currminute = (int(time.time()) / 60) % 10 currentSecond = datetime.now().second if (datarecieved == 15): #send to thingspeak every 15 data recieved wattsused = 0 whused = 0 datarecieved = 0 for history in sensorhistories.sensorhistories: wattsused += history.avgwattover5min() whused += history.dayswatthr kwhused = whused / 1000 avgwatt = (sensorhistory.avgwattover5min()) / 1000 cost = kwhused * ENERGY_PRICE cost = "%.2f" % cost if (avgwatt > 500): return params = urllib.urlencode({ 'field1': kwhused, 'field2': cost, 'field3': avgwatt, 'key': API_KEY }) headers = { "content-type": "application/x-www-form-urlencoded", "Accept": "text/plain" } conn = httplib.HTTPConnection(API_URL) try: conn.request("POST", "/update", params, headers) response = conn.getresponse() print response.status, response.reason data = response.read() conn.close() except: print "connection failed" # Print out debug data, Wh used in last 5 minutes avgwattsused = sensorhistory.avgwattover5min() print time.strftime("%Y %m %d, %H:%M") + ", " + str( sensorhistory.sensornum) + ", " + str( sensorhistory.avgwattover5min()) + "\n" # Lets log it! Seek to the end of our log file if logfile: logfile.seek(0, 2) # 2 == SEEK_END. ie, go to the end of the file logfile.write( time.strftime("%Y %m %d, %H:%M") + ", " + str(sensorhistory.sensornum) + ", " + str(sensorhistory.avgwattover5min()) + "\n") logfile.flush() sensorhistory.reset5mintimer()
def update_graph(idleevent): global avgwattdataidx, sensorhistories, twittertimer, DEBUG, currday # DAW - 5/18/11 - wrap the whole xbee packet inspection code in an exception handler try: # grab one packet from the xbee, or timeout packet = xbee.find_packet(ser) if not packet: return # we timedout xb = xbee(packet) # parse the packet #print xb.address_16 if DEBUG: # for debugging sometimes we only want one print xb # DAW - 5/18/11 - prevent exception that was caused by invalid xbee packet address if xb.address_16 < 0 or xb.address_16 > len(vrefcalibration): LogMsg("ERROR - invalid packet address: " + xb.address_16) return # we'll only store n-1 samples since the first one is usually messed up voltagedata = [-1] * (len(xb.analog_samples) - 1) ampdata = [-1] * (len(xb.analog_samples ) -1) # grab 1 thru n of the ADC readings, referencing the ADC constants # and store them in nice little arrays for i in range(len(voltagedata)): voltagedata[i] = xb.analog_samples[i+1][VOLTSENSE] ampdata[i] = xb.analog_samples[i+1][CURRENTSENSE] if DEBUG: print "ampdata: "+str(ampdata) print "voltdata: "+str(voltagedata) # get max and min voltage and normalize the curve to '0' # to make the graph 'AC coupled' / signed min_v = 1024 # XBee ADC is 10 bits, so max value is 1023 max_v = 0 for i in range(len(voltagedata)): if (min_v > voltagedata[i]): min_v = voltagedata[i] if (max_v < voltagedata[i]): max_v = voltagedata[i] # figure out the 'average' of the max and min readings avgv = (max_v + min_v) / 2 # also calculate the peak to peak measurements vpp = max_v-min_v for i in range(len(voltagedata)): #remove 'dc bias', which we call the average read voltagedata[i] -= avgv # We know that the mains voltage is 120Vrms = +-170Vpp voltagedata[i] = (voltagedata[i] * MAINSVPP) / vpp # normalize current readings to amperes for i in range(len(ampdata)): # VREF is the hardcoded 'DC bias' value, its # about 492 but would be nice if we could somehow # get this data once in a while maybe using xbeeAPI if vrefcalibration[xb.address_16]: ampdata[i] -= vrefcalibration[xb.address_16] else: ampdata[i] -= vrefcalibration[0] # the CURRENTNORM is our normalizing constant # that converts the ADC reading to Amperes ampdata[i] /= CURRENTNORM #print "Voltage, in volts: ", voltagedata #print "Current, in amps: ", ampdata # calculate instant. watts, by multiplying V*I for each sample point wattdata = [0] * len(voltagedata) for i in range(len(wattdata)): wattdata[i] = voltagedata[i] * ampdata[i] # sum up the current drawn over one 1/60hz cycle avgamp = 0 # DAW - 2/26/11 - check for less than 17 samples - would sometimes cause index out of range exception if (len(ampdata) < 17): return # 16.6 samples per second, one cycle = ~17 samples # close enough for govt work :( for i in range(17): avgamp += abs(ampdata[i]) avgamp /= 17.0 # DAW - average of all 18 amp readings avgamp2 = 0 for i in range(len(ampdata)): avgamp2 += abs(ampdata[i]) avgamp2 /= len(ampdata) # DAW - average of all 18 volt readings avgvolt = 0 for i in range(len(voltagedata)): avgvolt += abs(voltagedata[i]) avgvolt /= len(voltagedata) # sum up power drawn over one 1/60hz cycle avgwatt = 0 # DAW - 2/26/11 - check for less than 17 samples - would sometimes cause index out of range exception if len(wattdata) < 17: return # 16.6 samples per second, one cycle = ~17 samples for i in range(17): avgwatt += abs(wattdata[i]) avgwatt /= 17.0 # DAW - average of all 18 watt readings avgwatt2 = 0 for i in range(len(wattdata)): avgwatt2 += abs(wattdata[i]) avgwatt2 /= len(wattdata) except: LogMsg("Error in packet handling, ignoring") return # Print out our most recent measurements print str(xb.address_16)+"\tCurrent draw, in amperes: "+str(avgamp) print "\tWatt draw, in VA: "+str(avgwatt) # DAW print out extra data print "\t RSSI: " + str(xb.rssi) + " Volt: " + str(avgvolt) + " Amps: " + str(avgamp2) + " Watts: " + str(avgwatt2) if (avgamp > 13): return # hmm, bad data if GRAPHIT: # Add the current watt usage to our graph history avgwattdata[avgwattdataidx] = avgwatt avgwattdataidx += 1 if (avgwattdataidx >= len(avgwattdata)): # If we're running out of space, shift the first 10% out tenpercent = int(len(avgwattdata)*0.1) for i in range(len(avgwattdata) - tenpercent): avgwattdata[i] = avgwattdata[i+tenpercent] for i in range(len(avgwattdata) - tenpercent, len(avgwattdata)): avgwattdata[i] = 0 avgwattdataidx = len(avgwattdata) - tenpercent # retreive the history for this sensor sensorhistory = sensorhistories.find(xb.address_16) #print sensorhistory # add up the delta-watthr used since last reading # Figure out how many watt hours were used since last reading elapsedseconds = time.time() - sensorhistory.lasttime dwatthr = (avgwatt * elapsedseconds) / (60.0 * 60.0) # 60 seconds in 60 minutes = 1 hr sensorhistory.lasttime = time.time() print "\t\tWh used in last ",elapsedseconds," seconds: ",dwatthr sensorhistory.addwatthr(dwatthr) if DEBUG: print "sensorhistory.avgwattover5min is " + str(sensorhistory.avgwattover5min()) print time.strftime("%Y %m %d, %H:%M")+", "+str(sensorhistory.sensornum)+", "+str(sensorhistory.avgwattover5min())+"\n" # Determine the minute of the hour (ie 6:42 -> '42') currminute = (int(time.time())/60) % 10 # Figure out if its been five minutes since our last save if (((time.time() - sensorhistory.fiveminutetimer) >= 60.0) and (currminute % 5 == 0) ): # Print out debug data, Wh used in last 5 minutes avgwattsused = sensorhistory.avgwattover5min() print time.strftime("%Y %m %d, %H:%M")+", "+str(sensorhistory.sensornum)+", "+str(sensorhistory.avgwattover5min())+"\n" # Lets log it! Seek to the end of our log file if logfile: logfile.seek(0, 2) # 2 == SEEK_END. ie, go to the end of the file logfile.write(time.strftime("%Y %m %d, %H:%M")+", "+ str(sensorhistory.sensornum)+", "+ str(sensorhistory.avgwattover5min())+"\n") logfile.flush() # Or, send it to the app engine if not LOGFILENAME: appengineauth.sendreport(xb.address_16, avgwattsused) # DAW - 1/18/11 - log avg watts used to nimbits # avgwattstosend = "%.2f" % avgwattsused if NIMBITS_ID: try: urllib.urlopen("http://gigamega-beta.appspot.com/service/currentvalue?value=" + str(avgwattsused) + "&point=" + NIMBITS_ID + "&[email protected]&secret=e90d9c41-6529-4cf8-b248-92335c577cc7") except IOError: print 'Error sending to nimbits' # DAW - 2/7/11 - log avg watts used to Pachube if PACHUBE_ID: try: pac.update([eeml.Data(int(PACHUBE_ID), avgwattsused, unit=eeml.Watt())]) # unit=eeml.Unit('Volt', type='basicSI', symbol='V'))]) pac.put() except: print 'Error sending to Pachube' # DAW - 8/7/10 - moved here from below - otherwise, reset5mintimer can cause watts to be 0 when tweet occurs # We're going to twitter at midnight, 8am and 4pm # Determine the hour of the day (ie 6:42 -> '6') currhour = datetime.datetime.now().hour # twitter every 8 hours # DAW - if debugging, twitter (actually just log to file) every minute #if ((((time.time() - twittertimer) >= 3660.0) and (currhour % 8 == 0)) or (DEBUG and ((time.time() - twittertimer) >= 60.0))): # DAW - twitter every 4 hours if (((time.time() - twittertimer) >= 3660.0) and (currhour % 4 == 0)): print "twittertime!" twittertimer = time.time(); if not LOGFILENAME: message = appengineauth.gettweetreport() else: # sum up all the sensors' data wattsused = 0 whused = 0 if DEBUG: print "num sensor histories", len(sensorhistories.sensorhistories) newday = False thisday = datetime.datetime.now().day if currday != thisday: newday = True if DEBUG: message = "New day, clearing dayswatthr " + str(currday) + " to " + str(thisday) LogMsg(message) currday = thisday for history in sensorhistories.sensorhistories: if DEBUG: print "in twitter loop, found history", history.sensornum, history.cumulative5mwatthr wattsused += history.avgwattover5min() whused += history.dayswatthr # DAW - 8/7/10 - clear day's count when day changes if newday: history.dayswatthr = 0 message = "Currently using "+str(int(wattsused))+" Watts, "+str(int(whused))+" Wh today so far #tweetawatt" # DAW - 8/7/10 - if it's midnight, clear the day's count # write something ourselves if message: print message # DAW - if debugging, write to CSV file for debug purposes rather than twittering if DEBUG: LogMsg(message) else: #TwitterIt(twitterusername, twitterpassword, message) TwitterIt(message) # Reset our 5 minute timer sensorhistory.reset5mintimer() if GRAPHIT: # Redraw our pretty picture fig.canvas.draw_idle() # Update with latest data wattusageline.set_ydata(avgwattdata) voltagewatchline.set_ydata(voltagedata) ampwatchline.set_ydata(ampdata) # Update our graphing range so that we always see all the data maxamp = max(ampdata) minamp = min(ampdata) maxamp = max(maxamp, -minamp) mainsampwatcher.set_ylim(maxamp * -1.2, maxamp * 1.2) wattusage.set_ylim(0, max(avgwattdata) * 1.2)
def update_log(): global maxVolts, minVolts, maxAmps, minAmps, maxWatts, minWatts, DEBUG, height, width, counter # grab one packet from the xbee, or timeout packet = xbee.find_packet(ser) if not packet: return # we timedout xb = xbee(packet) # parse the packet #print xb.address_16 #if DEBUG: # for debugging sometimes we only want one #print xb # we'll only store n-1 samples since the first one is usually messed up #voltagedata = [-1] * (len(xb.analog_samples) - 1) #ampdata = [-1] * (len(xb.analog_samples ) -1) voltagedata = [-1] * (len(xb.analog_samples)) ampdata = [-1] * (len(xb.analog_samples )) # grab 1 thru n of the ADC readings, referencing the ADC constants # and store them in nice little arrays for i in range(len(voltagedata)): voltagedata[i] = xb.analog_samples[i][VOLTSENSE] ampdata[i] = xb.analog_samples[i][CURRENTSENSE] #if DEBUG: #print "ampdata: "+str(ampdata) print "voltdata: "+str(voltagedata) # get max and min voltage and normalize the curve to '0' # to make the graph 'AC coupled' / signed max_v=max(voltagedata) min_v=min(voltagedata) # figure out the 'average' of the max and min readings avgv = (max_v + min_v) / 2 # also calculate the peak to peak measurements vpp = max_v-min_v for i in range(len(voltagedata)): #remove 'dc bias', which we call the average read voltagedata[i] -= avgv # We know that the mains voltage is 120Vrms = +-170Vpp voltagedata[i] = (voltagedata[i] * MAINSVPP) / vpp if DEBUG: print "min_v="+str(min_v) print "max_v="+str(max_v) print "avgv="+str(avgv) print "vpp="+str(vpp) print "voltdata: "+str(voltagedata) # normalize current readings to amperes for i in range(len(ampdata)): # VREF is the hardcoded 'DC bias' value, its # about 492 but would be nice if we could somehow # get this data once in a while maybe using xbeeAPI #if vrefcalibration[xb.address_16]: # ampdata[i] -= vrefcalibration[xb.address_16] #else: # ampdata[i] -= vrefcalibration[0] ampdata[i] -= avgv # the CURRENTNORM is our normalizing constant # that converts the ADC reading to Amperes ampdata[i] /= CURRENTNORM # calculate instant. watts, by multiplying V*I for each sample point wattdata = [0] * len(voltagedata) for i in range(len(wattdata)): wattdata[i] = voltagedata[i] * ampdata[i] avgvolts = 0 #for i in range(len(voltagedata)): for i in range(cycleLength): avgvolts += abs(voltagedata[i]) #avgvolts /= float(len(voltagedata)) avgvolts /= float(cycleLength) avgamps = 0 #for i in range(len(ampdata)): for i in range(cycleLength): avgamps += abs(ampdata[i]) #avgamps /= float(len(ampdata)) avgamps /= float(cycleLength) avgwatts=avgvolts*avgamps avgwatts2 = 0 #for i in range(len(wattdata)): for i in range(cycleLength): avgwatts2 += abs(wattdata[i]) #avgwatts2 /= float(len(wattdata)) avgwatts2 /= float(cycleLength) if avgvolts>maxVolts: maxVolts=avgvolts if avgvolts<minVolts: minVolts=avgvolts if avgamps>maxAmps: maxAmps=avgamps if avgamps<minAmps: minAmps=avgamps if avgwatts>maxWatts: maxWatts=avgwatts if avgwatts<minWatts: minWatts=avgwatts # Print out our most recent measurements if DEBUG: print str(xb.address_16) print "\tAverage Voltage: "+str(avgvolts) print "\tAverage Amperage: "+str(avgamps) print "\tAverage Watt draw: "+str(avgwatts) print "\tAverage Watt instantaneous draw: "+str(avgwatts2) print "\tVolts Min: "+str(minVolts) print "\tVolts Max: "+str(maxVolts) print "\tAmps Min: "+str(minAmps) print "\tAmps Max: "+str(maxAmps) print "\tWatts Min: "+str(minWatts) print "\tWatts Max: "+str(maxWatts) counter+=1
def update_graph(): global avgwattdataidx, sensorhistories, twittertimer, onlywatchfor # grab one packet from the xbee, or timeout packet = xbee.find_packet(ser) logging.debug('Se ha leido un nuevo paquete del xbee') if packet: xb = xbee(packet) if (onlywatchfor != 0): if (xb.address_16 != onlywatchfor): return logging.debug('llego un paquete del killwatt numero : %s' , str(xb.address_16)) # we'll only store n-1 samples since the first one is usually messed up voltagedata = [-1] * (len(xb.analog_samples) - 1) ampdata = [-1] * (len(xb.analog_samples ) -1) # grab 1 thru n of the ADC readings, referencing the ADC constants # and store them in nice little arrays for i in range(len(voltagedata)): voltagedata[i] = xb.analog_samples[i+1][VOLTSENSE] ampdata[i] = xb.analog_samples[i+1][CURRENTSENSE] # get max and min voltage and normalize the curve to '0' # to make the graph 'AC coupled' / signed min_v = 1024 # XBee ADC is 10 bits, so max value is 1023 max_v = 0 voltagedataPablo = voltagedata[:] max_v_p = max(voltagedataPablo) min_v_p = min(voltagedataPablo) valor_int_p = ((max_v_p - min_v_p) / 2) + min_v_p for i in range(len(voltagedataPablo)): #en la siguiente linea aparece el factor de ajuste proporcionado por expertos de la uaz voltagedataPablo[i] = (voltagedataPablo[i] - valor_int_p) * 0.581 corrientedataPablo = ampdata[:] max_c_p = max(corrientedataPablo) min_c_p = min(corrientedataPablo) valor_intCorriente_p = ((max_c_p - min_c_p) / 2) + min_c_p for i in range(len(corrientedataPablo)): #en la siguiente linea aparece el factor de ajuste proporcionado por expertos de la uaz corrientedataPablo[i] = (corrientedataPablo[i] - valor_intCorriente_p) * 0.062 for i in range(len(voltagedata)): if (min_v > voltagedata[i]): min_v = voltagedata[i] if (max_v < voltagedata[i]): max_v = voltagedata[i] # figure out the 'average' of the max and min readings avgv = (max_v + min_v) / 2 # also calculate the peak to peak measurements vpp = max_v-min_v for i in range(len(voltagedata)): #remove 'dc bias', which we call the average read voltagedata[i] -= avgv # We know that the mains voltage is 120Vrms = +-170Vpp voltagedata[i] = (voltagedata[i] * MAINSVPP) / vpp # normalize current readings to amperes for i in range(len(ampdata)): # VREF is the hardcoded 'DC bias' value, its # about 492 but would be nice if we could somehow # get this data once in a while maybe using xbeeAPI if vrefs[xb.address_16]: ampdata[i] -= vrefs[xb.address_16] else: ampdata[i] -= vrefs[0] # the CURRENTNORM is our normalizing constant # that converts the ADC reading to Amperes ampdata[i] /= CURRENTNORM # calculate instant. watts, by multiplying V*I for each sample point wattdata = [0] * len(voltagedata) for i in range(len(wattdata)): wattdata[i] = voltagedataPablo[i] * corrientedataPablo[i] # sum up the current drawn over one 1/60hz cycle avgamp = 0 # 16.6 samples per second, one cycle = ~17 samples # close enough for govt work :( for i in range(17): avgamp += corrientedataPablo[i] avgamp /= 17.0 # sum up power drawn over one 1/60hz cycle avgwatt = 0 # 16.6 samples per second, one cycle = ~17 samples for i in range(17): avgwatt += (wattdata[i]) avgwatt /= 17.0 # Add the current watt usage to our graph history avgwattdata[avgwattdataidx] = avgwatt avgwattdataidx += 1 if (avgwattdataidx >= len(avgwattdata)): # If we're running out of space, shift the first 10% out tenpercent = int(len(avgwattdata)*0.1) for i in range(len(avgwattdata) - tenpercent): avgwattdata[i] = avgwattdata[i+tenpercent] for i in range(len(avgwattdata) - tenpercent, len(avgwattdata)): avgwattdata[i] = 0 avgwattdataidx = len(avgwattdata) - tenpercent logging.debug('fin del procesamiento de paquete del killwatt numero : %s' , str(xb.address_16)) # retreive the history for this sensor sensorhistory = findsensorhistory(xb.address_16) #print sensorhistory # add up the delta-watthr used since last reading # Figure out how many watt hours were used since last reading elapsedseconds = time.time() - sensorhistory.lasttime # logging.debug("Antiguo segundos entre envio de xbee = %s" , str(elapsedseconds)) dwatthr = (avgwatt * elapsedseconds) / (60.0 * 60.0) # 60 seconds in 60 minutes = 1 hr # logging.debug("Antiguo watts hora = %s" , str(dwatthr)) sensorhistory.lasttime = time.time() logging.debug('%s ***** valores killawatt 2 segundos' , "killawatt id = " +str(xb.address_16)) logging.debug ('watt hora = %s' , str(dwatthr)) logging.debug ('amp = %s' , str(avgamp)) logging.debug ('vol = %s' , str(120)) logging.debug ('watt = %s' , str(avgwatt)) logging.debug ("---------------------------------") sensorhistory.addwatthr(dwatthr) sensorhistory.addamp(avgamp) sensorhistory.addvol(120) sensorhistory.addwat(avgwatt) currminute = (int(time.time())/60) % 10 if ((time.time() - sensorhistory.fiveminutetimer) >= timeToMeasure): # Print out debug data, Wh used in last 5 minutes avgwattsused = sensorhistory.avgwattover5min() logging.debug('%s !!!!!! valores listos para enviarse al servidor' , "killawatt id = " +str(xb.address_16)) logging.debug ('avg watt hora = %s' , str(avgwattsused)) logging.debug ('avg amp = %s' , str(sensorhistory.avgwat())) logging.debug ('avg vol = %s' , str(sensorhistory.avgvol())) logging.debug ('avg watt = %s' , str(sensorhistory.avgwat())) logging.debug ("---------------------------------") api = apiElectro(urlDevices,urlUser,urlRecords) api.postElectroRegistry(sensorhistory.avgwat(),sensorhistory.avgamp(),sensorhistory.avgvol(),str(xb.address_16),avgwattsused,str(xb.address_16)) print time.strftime("%Y %m %d, %H:%M"),", ",sensorhistory.cumulativewatthr,"Wh = ",avgwattsused," W average" print xb.address_16," , ",sensorhistory.cumulativewatthr,"Wh = ",avgwattsused," W average" # Reset our 5 minute timer sensorhistory.reset5mintimer()
def main_loop(): global mousetraps global KEEP_RUNNING try: # grab one packet from the xbee, or timeout packet = xbee.find_packet(ser) except KeyboardInterrupt: KEEP_RUNNING = False except: logger.debug("Error reading packet.") return if packet == True: # received data but not sync'd return elif packet == None: # Did not receive data, timed out. for mouseTrap in mouseTraps.itervalues(): mouseTrap.check_update() # for debugging if logger.isEnabledFor(logging.DEBUG): logger.debug("Serial port Timedout waiting for data.") else: try: xb = xbee(packet) # parse the packet # no op but by parsing to string it forces AttributeError if bad packet nop = str(xb) greenOn = False redOn = False greenCount = 0 redCount = 0 # check the samples to determine if either of the LEDs are "ON" for sample in xb.digital_samples: greenCount += sample[GRNLEDPIN] redCount += sample[REDLEDPIN] if greenCount > 0: greenOn = True if redCount > 0: redOn = True if logger.isEnabledFor(logging.DEBUG): green = "" red = "" for sample in xb.digital_samples: green += str(sample[GRNLEDPIN]) red += str(sample[REDLEDPIN]) logger.debug("Address: %s, RSSI: %s, Sample Count: %s Green LED: %s, Red LED: %s" \ % (xb.address_16, xb.rssi, len(xb.digital_samples), green, red)) #logger.debug("Address: %s, RSSI: %s" % (xb.address_16, xb.rssi)) # if the trap has not yet been added to the dictionary if not mouseTraps.has_key(xb.address_16): mouseTrap = MouseTrap(xb.address_16) mouseTraps[xb.address_16] = mouseTrap # update the trap witht the LED values mouseTraps[xb.address_16].update(greenOn, redOn) except AttributeError as attrError: logger.debug(attrError) # check for traps last update and set offline if past deltatime for mouseTrap in mouseTraps.itervalues(): mouseTrap.check_update()