Close

Analyze Sensors and Take Action Code

A project log for The Compost Professor - A Smart Composting System

A set of senors and actuators that make composting simple.

Darian JohnsonDarian Johnson 06/11/2017 at 05:100 Comments

6/11/2017 -

I am still waiting for my LoRa sensors to arrive; in the meantime, I've started writing the logic that will interpret the sensor data. This code will run on the base station. The flow is:

  1. Base station requests sensor data
  2. Satellite station returns sensor values
  3. Base station interprets data and sends commands to satellite station
  4. Satellite station takes requested action (water compost, open vent, etc)
  5. Base station saves sensor data to database
  6. Base station saves UI data (warning colors, messages) to database for easy retrieval

The first pass of the code is below:

from datetime import timedelta, datetime
import json

def main:
    # TODO implement
    #return 'Hello from Lambda'
    
    tempMessageArray = [
        "Your compost is at optimal levels.", #0
        "Your compost is ready for use. At your convenience, move your sensors to a new compost pile/layer.", #1
        "Your compost heating cycle is complete and is in a 'curing stage'.", #2
        "Your compost has reached an unsafe temperature. Immediately turn the compost and add water.", #3
        "Your compost has reached unhealthily temperature. At your convenience, turn compost and add 'brown' (Carbon-rich) materials.", #4
        "Your compost temperature is slightly higher than optimal. You may want to turn the compost and add 'brown' materials.", #5
        "Your compost temperature is slightly higher than optimal, but is staring to cool off. I will let you know if any action is required.", #6
        "Your compost is at optimal temperature.", #7
        "Your compost temperature is slightly lower than optimal, but is staring to warm up. I will let you know if any action is required.", #8
        "Your compost temperature is slightly lower than optimal, and is continuing to cool. At your convenience, turn compost and add 'green' (Nitrogen-rich) materials.", #9
        "Your compost temperature is slightly lower than optimal, and is continuing to cool. The ambient temperature is low, so you should cover your compost to continue aerobic composting." #10
        ]
        
    moistureMessageArray = [
        "Your compost moisture content is too high. Turn your compost and add 'green' (Nitrogen-rich) materials.", #0
        "Your compost moisture content is too high but is starting to dry out. I will let you know if any action is required.", #1
        "Your compost is at optimal moisture levels.", #2
        "Your compost moisture content is too dry, but is starting to reach optimal moisture. I will let you know if any action is required.", #3
        "Your compost  is too dry and requires your attention. You need to turn and water your compost." #4
        ]
    
    #warnings
    success = "alert alert-success"
    info = "alert alert-info"
    warning = "alert alert-warning"
    danger = "alert alert-danger"

    #Limits
    tempDanger = 175
    tempHigh = 160
    tempOK = 140
    tempLow = 90
    moistHigh = 60
    moistLow = 40
    
    #get inputs for analysis
    sensorDataJSON = getSensorData()
    trendDataJSON = getTrendData()
    days = handleDateLogic()
    
    #set variables
    tempF = sensorDataJSON["tempF"]
    tempC = sensorDataJSON["tempC"]
    moisture = sensorDataJSON["moisture"]
    methane = sensorDataJSON["methane"]
    waterLevel = sensorDataJSON["waterLevel"]
    ambientTemp = sensorDataJSON["ambientTemp"]
    
    tempTrend = trendDataJSON['tempTrend']
    moistTrend = trendDataJSON['moistTrend']
        
    tempAlert = info
    moistAlert = info
    methaneAlert = info
    waterLevelAlert = info
    OverallMsg = tempMessageArray[0]
    msgPriority = 3 #1 = trumps all other actions, #2 additive
    
    if days > 35:
        OverallMsg = tempMessageArray[1]
        
    elif days > 25:
        OverallMsg = tempMessageArray[2]
        
    else: # the compost is not ready
    
        ################################################################
        #Handle Temperatures
        if tempF > tempDanger:
            addWater()
            openVent()
            tempAlert = danger
            OverallMsg = tempMessageArray[3]
            msgPriority = 1
            
        elif tempDanger >= tempF > tempHigh:
            addWater()
            openVent()
            tempAlert = danger
            OverallMsg = tempMessageArray[4]
            msgPriority = 1
            
        elif tempHigh >= tempF > tempOK:

            if tempTrend < 1:
                openVent()
                tempAlert = warning
                OverallMsg = tempMessageArray[5]
                msgPriority = 2
            else:
                tempAlert = warning
                OverallMsg = tempMessageArray[6]
                msgPriority = 2
        
        elif tempOK >= tempF > tempLow:
            tempAlert = success
            OverallMsg = tempMessageArray[7]
            msgPriority = 3
        
        else:
            closeVent()
            if tempTrend > 0:
                tempAlert = warning
                OverallMsg = tempMessageArray[8]
                msgPriority = 2
            else:
                if ambientTemp =="low":
                    tempAlert = danger
                    OverallMsg = tempMessageArray[10]
                    msgPriority = 1
                else:
                    tempAlert = warning
                    OverallMsg = tempMessageArray[9]
                    msgPriority = 2
        
        #######################################################################
        #handle Moisture content
        if moisture> moistHigh:
            if moistTrend>=0:
                moistAlert = danger
                if msgPriority > 1: #this message will trump any other message besides temp priority 3
                    OverallMsg = moistureMessageArray[0]
                    openVent()
                    msgPriority = 1
            else:
                moistAlert = warning
                if msgPriority == 2: # this message is appended to any existing P2 messages
                    OverallMsg = OverallMsg + " " + moistureMessageArray[1]
                    openVent()
                    msgPriority = 2
                elif msgPriority == 3:#this message is replaces any P3 messages
                    OverallMsg = moistureMessageArray[1]
                    openVent()
                    msgPriority = 2
        elif moistHigh >=moisture> moistLow:
            moistAlert = success
        else:
            if moistTrend<1:
                moistAlert = danger
                if msgPriority > 1: #this message will trump any other message besides priority 1
                    OverallMsg = moistureMessageArray[4]
                    closeVent()
                    addWater()
                    msgPriority = 1
            else:
                moistAlert = warning
                if msgPriority == 2: # this message is appended to any existing P2 messages
                    OverallMsg = OverallMsg + " " + moistureMessageArray[3]
                    addWater()
                    msgPriority = 2
                elif msgPriority == 3:#this message is replaces any P3 messages
                    OverallMsg = moistureMessageArray[3]
                    addWater()
                    msgPriority = 2
                    
        
        #######################
        #Handle Water Level
        if waterLevel <= 0:
            waterLevelMsg = "Refill"
            waterLevelAlert = danger

        else:
            waterLevelMsg = "Ok"
            waterLevelAlert = success
            
        #######################
        #Handle Methane Level
        if methane > 50000:
            methaneAlert = danger
        elif 50000 >= methane > 10000:
            methaneAlert = warning
        else:
            methaneAlert = success
                    
    writeToDatabase()
    return OverallMsg

#####################################################    
def getSensorData(): #stub to get sensor data
    #read request and recieve data from sensors
    #return data to function
    tempF = 85
    tempC = (tempF - 32) * 5/9
    ambientTempF = 50
    
    if ambientTempF <=40:
        ambientTemp = "low"
    else:
        ambientTemp = "high"

    return {"tempF":tempF, "tempC": tempC, "ambientTemp": ambientTemp, "moisture":30, "methane": 23.1, "waterLevel": -1}
    
def getTrendData(): #stub to get trend data
    #analyze historical data
    #set thresholds for what up/down/and steady
    #return data to function
    return {"tempTrend":1,"moistTrend":1}
    
def handleDateLogic(): #stub to handle date logic
    
    #settings for readiness
    daysWhenReady = 35
    daysAtSafeTempLevel = 25
    today = datetime.today() 
    
    #calculations based on trends - hardcoded for testing
    calcDaysAtSafeTempLevel = 1 #will need to read from database
    dateOfLastTemp = datetime.strptime('2017-06-01', "%Y-%m-%d") #will need to read from database
    
    if calcDaysAtSafeTempLevel >= daysAtSafeTempLevel:
        dateOf25thDay = datetime.strptime('2017-05-25', "%Y-%m-%d")
        daysSince25th = abs((today - dateOf25thDay).days) 
        
        return daysSince25th + daysAtSafeTempLevel       

    else:
        return calcDaysAtSafeTempLevel
            
    
def addWater(): #stub to send command to satellite station to add water
    return 'ok'

def openVent(): #stub to send command to satellite station to open vent
    return 'ok'
    
def closeVent(): #stub to send command to satellite station to close vent
    return 'ok'

def writeToDatabase(): #stub to write values to database
    return 'ok'
    
def persistSensorData(): #stub to write values to database for trend analysis
    return 'ok'
    
    

Discussions