예제 #1
0
def detailsLog(chan, voltage, amperage, power, energy, frequency, powerFactor,
               alarmStatus):
    hdr = 'Chan,Volts,Amps,Watts,Energy (Wh),Freq (Hz),PF,Status'
    s = "{:.0f},{:.1f},{:.1f},{:.1f},{:.1f},{:.1f},{:.1f},{:.0f}".format(
        chan, voltage, amperage, power, energy, frequency, powerFactor,
        alarmStatus)
    topic = "sumpMaster/logDetails_" + chanNames[chan]
    pubScribe.pubRecord(pubScribe.CSV_FILE, topic, s, hdr)
예제 #2
0
def sendStatus() :
    s = time.strftime("\n%a, %d %b %Y %H:%M:%S ", last_us_t)
    s = s + "US: {: 6.2f}\n".format(last_us_result)

    s = s + time.strftime("%a, %d %b %Y %H:%M:%S ", last_abp_t)
    s = s + "ABP: {: 6.2f}\n".format(last_abp_result)

    topic = "basinMaster/Status"
    pubScribe.pubRecord(pubScribe.EMAIL_SMS, topic, s)
예제 #3
0
def energyLog():
    hdr = ""
    for name in chanNames:
        hdr += name + " cycles" + "," + name + " (Wh)" + ","
    hdr = hdr[:-1]

    s = ""
    for chan in range(0, len(chanNames)):
        s += str(round(cycles[chan])) + "," + str(round(
            powerConsumed[chan], 2)) + ","
    s = s[:-1]

    topic = "sumpMaster/logEnergy"
    pubScribe.pubRecord(pubScribe.CSV_FILE, topic, s, hdr)
예제 #4
0
def sendStatus():
    printRowCol(messageRow, 0, "")
    clearDown()
    statusMsg = "Yesterday summary: \n"
    for chan in range(0, len(chanNames)):
        statusMsg += chanNames[chan] + " Cycles: {:<5.0f} \n".format(
            cyclesYesterday[chan])
        statusMsg += "MinRunTime: " + formatTime(
            minRunTimeYesterday[chan]) + '\n'
        statusMsg += "MaxRunTime: " + formatTime(
            maxRunTimeYesterday[chan]) + '\n'
        statusMsg += "TotalRunTime: " + formatTime(
            runTimeYesterday[chan]) + '\n'
        statusMsg += "Power (Wh): {:<8.2f} \n\n".format(
            powerConsumedYesterday[chan])
    topic = "sumpMaster/Status"
    pubScribe.pubRecord(pubScribe.EMAIL_SMS, topic, statusMsg)
예제 #5
0
def readAirthings() :
    global msgOnce

    results = ""
    alert = 0

    if not SerialNumber :
        if msgOnce :
            msgonce = 0
            print("Wave not found! Trying manually entering serial number into code instead of scanning.")
        return

    try:
        waveplus = read_waveplus2c.WavePlus(SerialNumber)
        waveplus.connect()
        sensors = waveplus.read()
        waveplus.disconnect()

        data, wavePlusString, alert = sensor2StringUnits(sensors)

        if MCP4725_ENABLED :
            fanValue = round(dac.alg(data),3)
            # print("FanValue: ", fanValue)
            data.append(fanValue)
            wavePlusString.append('Fan value   : {0:7.2f}    '.format(fanValue))

        if LOGGING_ENABLED :
            topic = "RadonMaster/WavePlus"
            pubScribe.pubRecord(pubScribe.CSV_FILE, topic, data, hdrRow)
        
        results = ""
        for item in wavePlusString :
            results += item + "\n"

    except :
        print("readAirthings() Exception!")
        waveplus.disconnect()

    return results, alert
예제 #6
0
def myTimer():
    global timer, count, sensorSum, lastReadTime, statusIntervalCntDn, lastAlertTime
    global firstTimeAirthings
    global lastPressMsg, lastWaveMsg

    t = datetime.datetime.now()

    # Measure vacuum
    status, result = abp.readAbpStatus()
    if status == 0:
        sensorSum = sensorSum + abp.pres2inwc(
            -result)  # change sign to convert pressure to vacuum
        count = count + 1

    # Calculate average vacuum over interval, log data, and check for alert conditions
    if (count >= (tAverage * 0.8) and t.second == 0):
        sensorAvg = sensorSum / count
        sensorSum = 0
        count = 0

        # Append interval data to CSV file
        topic = "RadonMaster/PresSensor"
        pubScribe.pubRecord(pubScribe.CSV_FILE, topic,
                            str(round(sensorAvg, 2)), "Inches w.c.")
        """ MS-Excel UNIX seconds to date and time
        date from seconds : =FLOOR(A2/86400,1)+DATE(1970,1,1)
        HH:MM from seconds: =MOD(A2,86400)/86400
        """

        sAlg = radonAlg(sensorAvg)

        lastPressMsg = '{0:s} Vacuum: {1:7.2f} in.wc'.format(
            formatLocalTime(), round(sensorAvg, 2))
        print(lastPressMsg + " " + sAlg)

        if not (sAlg == "" or sAlg[:3] == "Cal"):
            alertMsg = "Alert " + lastPressMsg

            if pressAlertsEnabled:
                tsec = time.time()
                if ((tsec - lastAlertTime) > minIntervalBtwAlerts):
                    lastAlertTime = tsec
                    topic = "RadonMaster/Alert"
                    pubScribe.pubRecord(pubScribe.EMAIL_SMS, topic, alertMsg)

                # pubScribe.pubRecord(pubScribe.BUZZER, 'Buzzer', {'Frequency': 700, 'Dutycycle': 10, 'Duration': 10})

            else:
                print(alertMsg)

    #
    if AIRTHINGS and (not (t.minute % 15)) and (t.second == 30):
        if firstTimeAirthings:
            firstTimeAirthings = 0
            wave.writeHeaders()

        try:
            lastWaveMsg, alert = wave.readAirthings()

            if alert and waveAlertsEnabled:
                topic = "RadonMaster/Alert"
                pubScribe.pubRecord(pubScribe.EMAIL_SMS, topic, lastWaveMsg)
            else:
                print(lastWaveMsg)

            lastWaveMsg = time.strftime("%a, %d %b %Y %H:%M:%S \n",
                                        time.localtime()) + lastWaveMsg

        except:
            print("Exception with Bluepy Airthings Wave...")

    # Send status message
    if (statusMsgEnabled and t.hour == statusMsgHHMM[0]
            and t.minute == statusMsgHHMM[1] and t.second == 0):
        sendStatus = 0

        # Send status message every n days, after sending first status message
        if statusInterval:
            statusIntervalCntDn = statusIntervalCntDn - 1
            if statusIntervalCntDn <= 0:
                statusIntervalCntDn = statusInterval
                sendStatus = 1

        # Send status message on a day of the month
        elif statusDOM:
            if t.day == statusDOM:
                sendStatus = 1

        # Send status message on a day of the week
        elif t.weekday() == statusDOW:
            sendStatus = 1

        if sendStatus:
            s = "Reporting at " + time.strftime("%a, %d %b %Y %H:%M:%S \n",
                                                time.localtime())
            s = s + lastPressMsg + "\n" + lastWaveMsg
            topic = "RadonMaster/Status"
            pubScribe.pubRecord(pubScribe.EMAIL_SMS, topic, s)

    if not stopFlag:
        t = datetime.datetime.now()
        Timer(tInterval - t.microsecond / 1000000.,
              myTimer).start()  # every tInterval seconds
예제 #7
0
    paramCheck()

    # Display sensor results on program startup
    status, result, tempC = abp.readAbpStatusTemp()

    # change sign of result to convert pressure to vacuum
    s = 'Status: {0:d}  Vacuum: {1:7.3f} {2:s} {3:7.2f} in.wc {4:5.1f} degF\n'.format(
        status, round(-result, 3), abp.PRES_UNITS,
        round(abp.pres2inwc(-result), 2), round(abp.c2f(tempC), 1))
    print(s)

    pubScribe.connectPubScribe()

    if statusMsgEnabled:
        topic = "RadonMaster/Status"
        pubScribe.pubRecord(pubScribe.EMAIL_SMS, topic, "Program start\n" + s)

    startTimer()

    print(
        "First averaged set of measurement will display in a few minutes...\n"
    )  # chg 2020-12-03

    try:
        while True:
            time.sleep(1)

    except KeyboardInterrupt:
        #timer.cancel()
        stopFlag = 1
        time.sleep(tInterval + 1)
예제 #8
0
def sendAlert(subj, alertMsg) :
    topic = "basinMaster/Alert"
    pubScribe.pubRecord(pubScribe.EMAIL_SMS, topic, alertMsg)
예제 #9
0
def gaugeRead(tInterval) :
    global last_us_result, last_us_t, last_abp_result, last_abp_t
    global measCnt, us_meas
    global last_us_log, last_abp_log

    us_result = -99
    abp_result = -99

    csv_str = ""
    deltaLogResult = 0

    if measCnt :
        # Pump cycle on-off logic prior to measurement
        if ENABLE_HNY_ABP and (measCnt <= pumpOnCnt) :
            if (measCnt > pumpOffCnt) : 
                hc_sr04_range.pump(PUMP_ON)    # Low-cost aquarium bubbler pump to pressurize depth tube
            else :
                hc_sr04_range.pump(not PUMP_ON)

        if ENABLE_HC_SR04 and (measCnt <= US_MEAS_AVERAGING) :
            # Series of range measures to average
            dist = hc_sr04_range.sensorRead()
            if dist :
                us_meas.append(dist)

        measCnt -= 1

    else :
        measCnt = int(measTime/tInterval) - 1
        t = time.localtime()
        
        if ENABLE_HC_SR04 :
            # Average ultrasonic measurements
            cnt = len(us_meas)
            if cnt > (US_MEAS_AVERAGING // 2) :
                mean = sum(us_meas) / cnt
                # variance = sum([((x - mean) ** 2) for x in us_meas]) / cnt
                # res = variance ** 0.5
                us_result = round(US_WELL_DEPTH - mean, 2)

                if us_result != -99 :
                    last_us_result = us_result
                    last_us_t = t

                    if (abs(us_result - last_us_log) > US_GAUGE_DELTA_LOG) :
                        deltaLogResult = 1
                        last_us_log = us_result

            us_meas = []


        if ENABLE_HNY_ABP :
            # Get pressure reading
            status, result, tempC = abp.readAbpStatusTemp()
            if status == 0 :
                abp_result = round(abp.pres2inwc(result),2)

                if abp_result != -99 :
                    last_abp_result = abp_result
                    last_abp_t = t

                    if (abs(abp_result - last_abp_log) > ABP_GAUGE_DELTA_LOG) :
                        deltaLogResult = 1
                        last_abp_log = abp_result

            else :
               print("Water depth pressure sensor fault...")

        if (depthGaugeLogEnable and (deltaLogResult or depthGaugeLogAll)) :
            topic = "basinMaster/WaterDepth"
            data = {"Ultrasonic (in)": round(us_result,2), "ABP (in)": round(abp_result,2)}
            pubScribe.pubRecord(pubScribe.CSV_FILE, topic, data)

    return us_result, abp_result
예제 #10
0
def sendAlert(subj, alertMsg):
    printRowCol(messageRow, 0, "")
    clearDown()
    topic = "sumpMaster/Alert"
    pubScribe.pubRecord(pubScribe.EMAIL_SMS, topic, alertMsg)
예제 #11
0
def readPower():
    global lastReadTime
    global lastStateOn, onTime
    global voltage, amperage, power, energy, frequency, powerFactor, alarmStatus
    global cycles, runTime, powerConsumed
    global cyclesToday, runTimeToday, powerConsumedToday, minRunTimeToday, maxRunTimeToday
    global maxRuntimeLastEmailTime, messageText

    t = time.time()
    timeDelta = (t - lastReadTime)
    if timeDelta > tInterval * 10:  # Assume first interval is tInterval
        timeDelta = tInterval

    for chan in range(0, len(chanNames)):
        [voltage[chan], amperage[chan], power[chan], energy[chan], frequency[chan], powerFactor[chan], \
                alarmStatus[chan]] = pzem.readAcPZEM(chanPorts[chan], chanAddrs[chan])

        if (power[chan] > chanOnThresholds[chan]):
            detailsLog(chan, voltage[chan], amperage[chan], power[chan], energy[chan], frequency[chan], \
                    powerFactor[chan], alarmStatus[chan])

            algSump.motorStatsAppend(chan, power[chan])

            runTime[chan] = runTime[chan] + timeDelta
            runTimeToday[chan] = runTimeToday[chan] + timeDelta

            if (lastStateOn[chan] == 0):
                cycles[chan] = cycles[chan] + 1
                lastStateOn[chan] = 1
                cyclesToday[chan] = cyclesToday[chan] + 1
                onTime[chan] = t  # time motor turned on

            elif (alertMsgEnabled and (t >
                                       (runTimeAlert[chan] + onTime[chan]))):
                # Motor on time exceeded threshold
                if (t > (minIntervalBtwEmails[chan]) +
                        maxRuntimeLastEmailTime[chan]):
                    # Allowed to send email text message
                    maxRuntimeLastEmailTime[chan] = t
                    s = chanNames[chan] + " on time exceeded!"
                    sendAlert(chanNames[chan], s)

        elif lastStateOn[chan]:
            lastStateOn[chan] = 0

            rt = t - onTime[chan]
            if minRunTimeToday[chan] == 0:
                minRunTimeToday[chan] = rt
            elif rt < minRunTimeToday[chan]:
                minRunTimeToday[chan] = rt

            if rt > maxRunTimeToday[chan]:
                maxRunTimeToday[chan] = rt

            hdr, returnStr, alertMsg = algSump.motorStats(
                chan, chanNames, rt, tInterval)

            timeStr = datetime.datetime.now().strftime(
                '%Y-%m-%d %H:%M:%S.%f')[:-3]
            messageText = "{:.2f},{},{}".format(t, timeStr,
                                                returnStr + "        ")

            if returnStr != "":
                topic = "sumpMaster/logStats_" + chanNames[chan]
                pubScribe.pubRecord(pubScribe.CSV_FILE, topic, returnStr, hdr)

            if alertMsg != "" and alertMsgEnabled and (
                    t > (minIntervalBtwEmails[chan]) + algLastEmailTime[chan]):
                # Allowed to send email text message
                algLastEmailTime[chan] = t
                sendAlert(chanNames[chan], alertMsg)

        if lastReadTime:
            pwr = power[chan] * timeDelta / 3600.
            powerConsumed[chan] = powerConsumed[chan] + pwr
            powerConsumedToday[chan] = powerConsumedToday[chan] + pwr

    # end for

    lastReadTime = t