Beispiel #1
0
def get_whdata(avgwatt, sensorhistories, sensorhistory, save_log=False):
    '''return deltawatthours'''
    currminute = (int(time.time())/60) % 10
    if (((time.time() - sensorhistory.fiveminutetimer) >= 60.0)
        and (currminute % 5 == 0)
        ):
        sensorhistory.reset5mintimer()
    for history in sensorhistories.sensorhistories:
        wattsused += history.avgwattover5min()
        whused += history.dayswatthr
    # 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.addwatthr(dwatthr)
    sensorhistory.lasttime = time.time()
    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()
    print wattsused
    return dwatthr
Beispiel #2
0
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)
Beispiel #3
0
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()
Beispiel #4
0
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()
Beispiel #5
0
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)
Beispiel #6
0
                                           
                                           # 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 (True): #((time.time() - twittertimer) >= 3660.0) and (currhour % 8 == 0)):
        print "twittertime!"
        twittertimer = time.time();
        # sum up all the sensors' data
        wattsused = 0
        whused = 0
        for history in sensorhistories.sensorhistories:
            wattsused += history.avgwattover5min()
            whused += history.dayswatthr
Beispiel #7
0
			s.close()
		except socket.error, e:
			s.close()
			s = None
		if s is None:
			print "Socket Error: %s" % (e)
			logger.error("Socket Error %d : %s" % (e.args[0],e.args[1]) )

        if LOGTOFILE and not LOGFILENAME:
        # Or, send it to the app engine
        #if not LOGFILENAME:
            appengineauth.sendreport(xb.address_16, avgwattsused)
        
        
        # Reset our 5 minute timer
        sensorhistory.reset5mintimer()
        

	if ENABLETWITTER:
		# 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 (((time.time() - twittertimer) >= 3660.0) and (currhour % 8 == 0)):
		    print "twittertime!"
		    twittertimer = time.time();
		    if not LOGFILENAME:
		        message = appengineauth.gettweetreport()
		    else:
		        # sum up all the sensors' data
		        wattsused = 0
Beispiel #8
0
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()
Beispiel #9
0
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)
Beispiel #10
0
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
    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()
    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 (((time.time() - twittertimer) >= 3660.0) and (currhour % 8 == 0)):
        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"
            # write something 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)