def activateactuator(target, value): # return true in case the state change: activation is >0 or a different position from prevoius position. # check the actuator isok=False actuatortype=hardwaremod.searchdata(hardwaremod.HW_INFO_NAME,target,hardwaremod.HW_CTRL_CMD) actuatortypelist=actuatortype.split("/") if actuatortypelist: actuatortype=actuatortypelist[0] print (" Automation Actuator " + actuatortype + " target " + target) supportedactuators=["pulse","servo","stepper"] # stepper motor if actuatortype=="stepper": out, isok = hardwaremod.GO_stepper_position(target,value) if isok: actuatordbmod.insertdataintable(target,value) # hbridge motor if actuatortype=="hbridge": out, isok = hardwaremod.GO_hbridge_position(target,value) if isok: actuatordbmod.insertdataintable(target,value) # pulse if actuatortype=="pulse": duration=hardwaremod.toint(value,0) # check the fertilizer doser flag before activating the pulse doseron=autofertilizermod.checkactivate(target,duration) # start pulse pulseok=hardwaremod.makepulse(target,duration) # salva su database if "Started" in pulseok: actuatordbmod.insertdataintable(target,duration) isok=True # servo motor if actuatortype=="servo": out, isok = hardwaremod.servoangle(target,value,0.5) if isok: actuatordbmod.insertdataintable(target,value) # photo if actuatortype=="photo": duration=hardwaremod.toint(value,0) if duration>0: isok=hardwaremod.takephoto(True) # save action in database if isok: actuatordbmod.insertdataintable(target,1) # mail if (actuatortype=="mail+info+link")or(actuatortype=="mail+info"): if value>0: mailtext=str(value) isok=emailmod.sendmail(target,"info","Automation Value:" + mailtext) # save action in database if isok: actuatordbmod.insertdataintable(target,1) return isok
def activateactuator(target, value): # return true in case the state change: activation is >0 or a different position from prevoius position. # check the actuator isok=False actuatortype=hardwaremod.searchdata(hardwaremod.HW_INFO_NAME,target,hardwaremod.HW_CTRL_CMD) supportedactuators=["pulse","servo","stepper"] # stepper motor if actuatortype=="stepper": out, isok = hardwaremod.GO_stepper_position(target,value,priority=ACTIONPRIORITYLEVEL) if isok: actuatordbmod.insertdataintable(target,value) # hbridge motor if actuatortype=="hbridge": out, isok = hardwaremod.GO_hbridge_position(target,value) if isok: actuatordbmod.insertdataintable(target,value) # pulse if actuatortype=="pulse": duration=hardwaremod.toint(value,0) if duration>0: # check the fertilizer doser flag before activating the pulse doseron=autofertilizermod.checkactivate(target,duration) # start pulse pulseok=hardwaremod.makepulse(target,duration,priority=ACTIONPRIORITYLEVEL) # salva su database if "Started" in pulseok: actuatordbmod.insertdataintable(target,duration) isok=True else: pulseok=hardwaremod.stoppulse(target) # servo motor if actuatortype=="servo": out, isok = hardwaremod.servoangle(target,value,0.5,priority=ACTIONPRIORITYLEVEL) if isok: actuatordbmod.insertdataintable(target,value) # photo if actuatortype=="photo": duration=hardwaremod.toint(value,0) if duration>0: isok=hardwaremod.takephoto(True) # True override the daily activation # save action in database if isok: actuatordbmod.insertdataintable(target,1) # mail if (actuatortype=="mail+info+link")or(actuatortype=="mail+info"): if value>0: mailtext=str(value) isok=emailmod.sendmail(target,"info","Interrupt Value:" + mailtext) # save action in database if isok: actuatordbmod.insertdataintable(target,1) return isok
def activateactuator( target, value ): # return true in case the state change: activation is >0 or a different position from prevoius position. # check the actuator isok = False actuatortype = hardwaremod.searchdata(hardwaremod.HW_INFO_NAME, target, hardwaremod.HW_CTRL_CMD) supportedactuators = ["pulse", "servo", "stepper"] # stepper motor if actuatortype == "stepper": out, isok = hardwaremod.GO_stepper_position(target, value) if isok: actuatordbmod.insertdataintable(target, value) # pulse if actuatortype == "pulse": duration = 1000 * hardwaremod.toint(value, 0) # check the fertilizer doser flag before activating the pulse doseron = autofertilizermod.checkactivate(element, duration) # start pulse pulseok = hardwaremod.makepulse(target, duration) # salva su database if "Started" in pulseok: actuatordbmod.insertdataintable(target, duration) isok = True # servo motor if actuatortype == "servo": out, isok = hardwaremod.servoangle(target, value, 0.5) if isok: actuatordbmod.insertdataintable(target, value) return isok
def activateactuator(target, value): # return true in case the state change: activation is >0 or a different position from prevoius position. # check the actuator isok=False actuatortype=hardwaremod.searchdata(hardwaremod.HW_INFO_NAME,target,hardwaremod.HW_CTRL_CMD) supportedactuators=["pulse","servo","stepper"] # stepper motor if actuatortype=="stepper": out, isok = hardwaremod.GO_stepper_position(target,value) if isok: actuatordbmod.insertdataintable(target,value) # pulse if actuatortype=="pulse": duration=1000*hardwaremod.toint(value,0) # check the fertilizer doser flag before activating the pulse doseron=autofertilizermod.checkactivate(target,duration) # start pulse pulseok=hardwaremod.makepulse(target,duration) # salva su database if "Started" in pulseok: actuatordbmod.insertdataintable(target,duration) isok=True # servo motor if actuatortype=="servo": out, isok = hardwaremod.servoangle(target,value,0.5) if isok: actuatordbmod.insertdataintable(target,value) return isok
def checkactivate(elementwater, durationwater): elementlist = fertilizerdbmod.getelementlist() waterok = False for doserelement in elementlist: # provided the waterelement, search for corresponding doserelement linkedwaterelement = autofertilizerdbmod.searchdata( "element", doserelement, "waterZone") if linkedwaterelement == elementwater: waterok = True element = doserelement break if waterok: # there is a corresponding doser element minwaterduration = hardwaremod.toint( autofertilizerdbmod.searchdata("element", element, "minactivationsec"), 0) if not isschedulermode(element): #setup is not for scheduled time print " Fertilizer ", element, " set to autowater" print " Check Water duration ", durationwater, ">", minwaterduration if durationwater > minwaterduration: # watering time above the set threshold print " OK Water duration " if AUTO_data[element]["tobeactivated"]: #if flag is ON print " Activate ", element durationfer = AUTO_data[element]["duration"] activatedoser(element, durationfer) time.sleep( durationfer ) #this blocks the system (and watering activation) for n seconds ... not best practice else: print " No pending request to activate ", element
def pulsenutrient(target, activationseconds): duration = 1000 * hardwaremod.toint(activationseconds, 0) print target, " ", duration, " ", datetime.now() logger.info('Doser Pulse, pulse time for ms = %s', duration) pulseok = hardwaremod.makepulse(target, duration) # salva su database actuatordbmod.insertdataintable(target, duration) return pulseok
def pulsenutrient(target,activationseconds): #scheduled doser activity for fertilizer duration=hardwaremod.toint(activationseconds,0) if autofertilizermod.isschedulermode(target): autofertilizermod.activatedoser(target, duration) else: logger.info('Book the %s activation', target) autofertilizermod.setActivationDurationDate(target,True,duration,datetime.now()) return True
def cyclereset(element): global AUTO_data waitingtime=hardwaremod.toint(automationdbmod.searchdata("element",element,"pausebetweenwtstepsmin"),0) statusdataDBmod.write_status_data(AUTO_data,element,"lastactiontime",datetime.utcnow() - timedelta(minutes=waitingtime)) statusdataDBmod.write_status_data(AUTO_data,element,"status","ok") statusdataDBmod.write_status_data(AUTO_data,element,"actionvalue",0) statusdataDBmod.write_status_data(AUTO_data,element,"alertcounter",0) statusdataDBmod.write_status_data(AUTO_data,element,"infocounter",0)
def pulsenutrient(target,activationseconds): #scheduled doser activity for fertilizer duration=1000*hardwaremod.toint(activationseconds,0) if autofertilizermod.isschedulermode(target): autofertilizermod.activatedoser(target, duration) else: autofertilizermod.AUTO_data[target]["tobeactivated"]=True autofertilizermod.AUTO_data[target]["duration"]=duration autofertilizermod.AUTO_data[target]["triggerdate"]=datetime.now() return True
def cyclereset(element): #AUTO_data["default"]={"lasteventtime":datetime.utcnow()- timedelta(minutes=waitingtime),"lastinterrupttime":datetime.utcnow(), #"validinterruptcount":0,"eventactivated":False,"lastactiontime":datetime.utcnow()- timedelta(minutes=waitingtime), #"actionvalue":0, "alertcounter":0, "infocounter":0, "status":"ok" , "threadID":None , "blockingstate":False} #SENSOR_data["default"]={"Startcounttime":datetime.utcnow(),"InterruptCount":0} # this is for the actual frequency sensor #PIN_attributes["default"]={"logic":"pos","refsensor":"","bouncetimeSec":0.001} # this is relebant to the PINs #BLOCKING_data["default"]={"BlockingNumbers":0,"BlockingNumbersThreadID":None} # tihs is relenat to the Interrupt trigger global AUTO_data waitingtime = hardwaremod.toint( interruptdbmod.searchdata("element", element, "preemptive_period"), 0) statusdataDBmod.write_status_data( AUTO_data, element, "lastactiontime", datetime.utcnow() - timedelta(minutes=waitingtime)) statusdataDBmod.write_status_data( AUTO_data, element, "lasteventtime", datetime.utcnow() - timedelta(minutes=waitingtime)) statusdataDBmod.write_status_data(AUTO_data, element, "status", "ok") statusdataDBmod.write_status_data(AUTO_data, element, "actionvalue", 0) statusdataDBmod.write_status_data(AUTO_data, element, "alertcounter", 0) statusdataDBmod.write_status_data(AUTO_data, element, "infocounter", 0) statusdataDBmod.write_status_data(AUTO_data, element, "validinterruptcount", 0) # start procedure to stop blocking on this element endblocking(element) # reassess all the interrupt sensor related shit elementlist = interruptdbmod.getelementlist() sensorblockingcounter = {} #print "elementlist" , elementlist #print elementlist for element in elementlist: #print " ELEMENT " , element workmode = checkworkmode(element) if (workmode != "None") and (workmode != ""): sensor = interruptdbmod.searchdata("element", element, "sensor") #print " SENSOR " , sensor if sensor != "": #print "Blocking starte " , statusdataDBmod.read_status_data(AUTO_data,element,"blockingstate") if statusdataDBmod.read_status_data( AUTO_data, element, "blockingstate"): # blocking state is TRUE #print " TRUE ------------------------------------------------------- " , element if sensor in sensorblockingcounter: sensorblockingcounter[ sensor] = sensorblockingcounter[sensor] + 1 else: sensorblockingcounter[sensor] = 1 print(sensorblockingcounter) global BLOCKING_data for sensor in sensorblockingcounter: statusdataDBmod.write_status_data(BLOCKING_data, sensor, "BlockingNumbers", sensorblockingcounter[sensor])
def pulsenutrient(target, activationseconds): #scheduled doser activity for fertilizer duration = 1000 * hardwaremod.toint(activationseconds, 0) if autofertilizermod.isschedulermode(target): autofertilizermod.activatedoser(target, duration) else: autofertilizermod.AUTO_data[target]["tobeactivated"] = True autofertilizermod.AUTO_data[target]["duration"] = duration autofertilizermod.AUTO_data[target]["triggerdate"] = datetime.now() return True
def activateandregister(target,activationseconds): # function to activate the actuators duration=hardwaremod.toint(activationseconds,0) print(target, " ",duration, " " , datetime.now()) logger.info('Pulse time for sec = %s', duration) # start pulse pulseok=hardwaremod.makepulse(target,duration) # salva su database if "Started" in pulseok: actuatordbmod.insertdataintable(target,duration) return pulseok
def activateandregister(target,activationseconds): # function to activate the actuators duration=1000*hardwaremod.toint(activationseconds,0) print target, " ",duration, " " , datetime.now() logger.info('Doser Pulse, pulse time for ms = %s', duration) # start pulse pulseok=hardwaremod.makepulse(target,duration) # salva su database if "Started" in pulseok: actuatordbmod.insertdataintable(target,duration) return pulseok
def cyclereset(element): global AUTO_data waitingtime = hardwaremod.toint( automationdbmod.searchdata("element", element, "pausebetweenwtstepsmin"), 0) AUTO_data[element] = { "lastactiontime": datetime.utcnow() - timedelta(minutes=waitingtime), "status": "ok", "actionvalue": 0, "alertcounter": 0, "infocounter": 0 }
def cyclereset(element): global AUTO_data waitingtime = hardwaremod.toint( autowateringdbmod.searchdata("element", element, "pausebetweenwtstepsmin"), 0) AUTO_data[element] = { "cyclestartdate": datetime.now(), "lastwateringtime": datetime.now() - timedelta(minutes=waitingtime), "cyclestatus": "done", "checkcounter": 0, "alertcounter": 0, "watercounter": 0 }
def cyclereset(element): global AUTO_data waitingtime = hardwaremod.toint( interruptdbmod.searchdata("element", element, "preemptive_period"), 0) statusdataDBmod.write_status_data( AUTO_data, element, "lastactiontime", datetime.utcnow() - timedelta(minutes=waitingtime)) statusdataDBmod.write_status_data( AUTO_data, element, "lasteventtime", datetime.utcnow() - timedelta(minutes=waitingtime)) statusdataDBmod.write_status_data(AUTO_data, element, "status", "ok") statusdataDBmod.write_status_data(AUTO_data, element, "actionvalue", 0) statusdataDBmod.write_status_data(AUTO_data, element, "alertcounter", 0) statusdataDBmod.write_status_data(AUTO_data, element, "infocounter", 0) statusdataDBmod.write_status_data(AUTO_data, element, "validinterruptcount", 0)
def cyclereset(element): global AUTO_data waitingtime = hardwaremod.toint( interruptdbmod.searchdata("element", element, "preemptive_period"), 0) AUTO_data[element] = { "lastactiontime": datetime.utcnow() - timedelta(minutes=waitingtime), "status": "ok", "actionvalue": 0, "alertcounter": 0, "infocounter": 0 } AUTO_data[element] = { "lasteventtime": datetime.utcnow() - timedelta(minutes=waitingtime), "status": "ok", "actionvalue": 0, "alertcounter": 0, "infocounter": 0 }
def endblocking(element, saveend=True): sensor = interruptdbmod.searchdata("element", element, "sensor") if checkstopcondition(element): global AUTO_data #save data if saveend: saveblockingdiff(sensor) #-- threadID = statusdataDBmod.read_status_data(AUTO_data, element, "threadID") if threadID != None and threadID != "": #print "cancel the Thread of element=",element threadID.cancel() global BLOCKING_data # change blocking counter BlockingNumbers = statusdataDBmod.read_status_data( BLOCKING_data, sensor, "BlockingNumbers") BlockingNumbers = BlockingNumbers - 1 statusdataDBmod.write_status_data(BLOCKING_data, sensor, "BlockingNumbers", BlockingNumbers) #-- #save data saveblockingdiff(sensor) #-- #print "Start removing blocking status" statusdataDBmod.write_status_data( hardwaremod.Blocking_Status, element, "priority", NONBLOCKINGPRIORITY) #put the priority to lower levels statusdataDBmod.write_status_data(AUTO_data, element, "threadID", None) statusdataDBmod.write_status_data(AUTO_data, element, "blockingstate", False) else: # renew the blocking status print("Interrupt LEVEL High, Do not stop blocking period, Extend it") # reload the period in case this is chnaged preemptiontimemin = hardwaremod.toint( interruptdbmod.searchdata("element", element, "preemptive_period"), 0) period = preemptiontimemin * 60 if period > 0: startblockingstate(element, period)
def setinterruptevents(): hardwaremod.removeallinterruptevents() print "load interrupt list " interruptlist = interruptdbmod.sensorlist() print "len interrupt list ", len(interruptlist) for item in interruptlist: print "got into the loop " # get PIN number recordkey = hardwaremod.HW_INFO_NAME recordvalue = item keytosearch = hardwaremod.HW_CTRL_PIN PINstr = hardwaremod.searchdata(recordkey, recordvalue, keytosearch) print "set event for the PIN ", PINstr PIN = hardwaremod.toint(PINstr, -1) if PIN > -1: keytosearch = hardwaremod.HW_CTRL_LOGIC logic = hardwaremod.searchdata(recordkey, recordvalue, keytosearch) # set Sw pull up / down mode if logic == "pos": hardwaremod.GPIO_setup(PIN, "in", "pull_down") evenslopetype = "both" else: hardwaremod.GPIO_setup(PIN, "in", "pull_up") evenslopetype = "both" #GPIO.RISING, GPIO.FALLING or GPIO.BOTH. # ignoring further edges for 200ms for switch bounce handling # link to the callback function hardwaremod.GPIO_add_event_detect(PIN, evenslopetype, eventcallback) return ""
def interruptexecute(refsensor, element): sensor = refsensor #logger.info('interrupt Pairing OK ---> Actuator: %s , Sensor: %s', element, sensor) workmode = checkworkmode(element) if (workmode == "None"): # None case print("No Action required, workmode set to None, element: ", element) logger.info("No Action required, workmode set to None, element: %s ", element) return if (workmode == ""): logger.info("Not able to get the workmode: %s ", element) return #logger.info('Interrupt, Get all the parameters') interrupt_validinterval = hardwaremod.tonumber( interruptdbmod.searchdata("element", element, "interrupt_validinterval"), 0) #"Counter Only" if workmode == "Counter Only": CounterOnlyNew(element, sensor, interrupt_validinterval) return interrupt_triggernumber = hardwaremod.tonumber( interruptdbmod.searchdata("element", element, "interrupt_triggernumber"), 1) actuatoroutput = hardwaremod.tonumber( interruptdbmod.searchdata("element", element, "actuator_output"), 0) actuatoroutputfollowup = hardwaremod.tonumber( interruptdbmod.searchdata("element", element, "folloup_output"), 0) # evaluate variables for operational period check starttime = datetime.strptime( interruptdbmod.searchdata("element", element, "allowedperiod")[0], '%H:%M').time() endtime = datetime.strptime( interruptdbmod.searchdata("element", element, "allowedperiod")[1], '%H:%M').time() # get other parameters seonsormode = interruptdbmod.searchdata("element", element, "sensor_mode") triggermode = interruptdbmod.searchdata("element", element, "trigger_mode") preemptiontimemin = hardwaremod.toint( interruptdbmod.searchdata("element", element, "preemptive_period"), 0) if preemptiontimemin == 0: # if relay, meaning cmd = pulse actuatortype = hardwaremod.searchdata(hardwaremod.HW_INFO_NAME, element, hardwaremod.HW_CTRL_CMD) if actuatortype == "pulse": preemptiontime = actuatoroutput # if set to zero then get the time as the actuator (in case of relay) else: preemptiontime = 0 else: preemptiontime = preemptiontimemin * 60 mailtype = interruptdbmod.searchdata("element", element, "mailalerttype") actionmodeafterfirst = interruptdbmod.searchdata("element", element, "actionmode_afterfirst") # time check # ------------------------ interrupt alghoritm if workmode == "Pre-emptive Blocking": # check if inside the allowed time period #print "Pre-emptive Blocking Mode" #logger.info('Pre-emptive Blocking mode --> %s', element) timeok = isNowInTimePeriod( starttime, endtime, datetime.now().time()) # don't use UTC here! #print "inside allowed time ", timeok , " starttime ", starttime , " endtime ", endtime if timeok: CheckActivateNotify(element, sensor, preemptiontime, actuatoroutput, actionmodeafterfirst, actuatoroutputfollowup, mailtype, interrupt_triggernumber, interrupt_validinterval, triggermode) else: logger.info('out of allowed operational time') # implment Critical alert message in case the sensor value is one interval more than Max_threshold return
def setinterruptevents(): hardwaremod.removeallinterruptevents() print("load interrupt list ") interruptlist = interruptdbmod.sensorlist() print("len interrupt list ", len(interruptlist)) for item in interruptlist: print("got into the loop ") # get PIN number recordkey = hardwaremod.HW_INFO_NAME recordvalue = item keytosearch = hardwaremod.HW_CTRL_PIN PINstr = hardwaremod.searchdata(recordkey, recordvalue, keytosearch) print("set event for the PIN ", PINstr) if not PINstr == "": keytosearch = hardwaremod.HW_CTRL_LOGIC logic = hardwaremod.searchdata(recordkey, recordvalue, keytosearch) # set Sw pull up / down mode if logic == "pos": hardwaremod.GPIO_setup(PINstr, "in", "pull_down") evenslopetype = "both" else: hardwaremod.GPIO_setup(PINstr, "in", "pull_up") evenslopetype = "both" #GPIO.RISING, GPIO.FALLING or GPIO.BOTH. # link to the callback function # the bouncetime is set by the frequency parameter, if this parameter is empty, the default bouncetime would be 200 keytosearch = hardwaremod.HW_CTRL_FREQ frequency = hardwaremod.searchdata(recordkey, recordvalue, keytosearch) if frequency == "": bouncetimeINT = 200 else: frequencyINT = hardwaremod.toint(frequency, 5) bouncetimeINT = old_div( 1000, frequencyINT ) # in ms. this is ok to be trunk of the int. For frequencies higher than 1000 the bouncetime is exactly zero # RPI.GPIO library does not accept bouncetime=0, it gives runtime error if bouncetimeINT <= 0: bouncetimeINT = 1 #ms hardwaremod.GPIO_add_event_detect(PINstr, evenslopetype, eventcallback, bouncetimeINT) # set fast reference call indexed with the PIN number which is the variable used when interrupt is called: # search now to avoid searching later global PIN_attributes PIN = hardwaremod.toint(PINstr, 0) statusdataDBmod.write_status_data(PIN_attributes, PIN, "logic", logic) recordkey = hardwaremod.HW_CTRL_PIN recordvalue = PINstr keytosearch = hardwaremod.HW_INFO_NAME refsensor = hardwaremod.searchdata( recordkey, recordvalue, keytosearch) # return first occurence statusdataDBmod.write_status_data(PIN_attributes, PIN, "refsensor", refsensor) statusdataDBmod.write_status_data( PIN_attributes, PIN, "bouncetimeSec", 0.4 * float(bouncetimeINT) / 1000) # code below to enable blocking for N sec, it is necessary to trigger the bloccking status in case of levels already present when starting. elementlist = interruptdbmod.getelementlist() #print elementlist for element in elementlist: workmode = checkworkmode(element) if (workmode != "None") and (workmode != ""): sensor = interruptdbmod.searchdata("element", element, "sensor") #saveblockingdiff(sensor) print(" what a sensor ", sensor) if sensor != "": startblockingstate(element, 10, False) t.sleep(0.02) return ""
def cycleresetall(): elementlist= automationdbmod.getelementlist() for element in elementlist: waitingtime=hardwaremod.toint(automationdbmod.searchdata("element",element,"pausebetweenwtstepsmin"),0) #print("Cycle reset all ------------------------------------_>", waitingtime , " ", element) cyclereset(element)
def startpump(target, activationseconds, MinAveragetemp, MaxAverageHumid): duration = 1000 * hardwaremod.toint(activationseconds, 0) print target, " ", duration, " ", datetime.now() logger.info('Startpump evaluation') # evaluate parameters #MinAverageLight=500 not used now MinutesOfAverage = 120 #minutes in which the average data is calculated from sensor sampling print "waterpump check" logger.info('execute water pump check %s', datetime.now().strftime("%Y-%m-%d %H:%M:%S")) # then check the temperature and Humidity print "Check Humidity and Temperature" hsensornamelist = hardwaremod.getsensornamebymeasure( hardwaremod.MEASURELIST[1]) if hsensornamelist: sensordata = [] hsensorname = hsensornamelist[0] # get first found sensor in the list sensordbmod.getsensordbdata(hsensorname, sensordata) starttimecalc = datetime.now() - timedelta( minutes=int(MinutesOfAverage)) humquantity = sensordbmod.EvaluateDataPeriod(sensordata, starttimecalc, datetime.now())["average"] logger.info( 'Waterpump Check parameter if humquantity=%s < MaxAverageHumid=%s ', str(humquantity), str(MaxAverageHumid)) print 'Waterpump Check parameter if humquantity=', humquantity, ' < MaxAverageHumid=', MaxAverageHumid tsensornamelist = hardwaremod.getsensornamebymeasure( hardwaremod.MEASURELIST[0]) if tsensornamelist: sensordata = [] tsensorname = tsensornamelist[0] # get first found sensor in the list sensordbmod.getsensordbdata(tsensorname, sensordata) starttimecalc = datetime.now() - timedelta( minutes=int(MinutesOfAverage)) tempquantity = sensordbmod.EvaluateDataPeriod( sensordata, starttimecalc, datetime.now())["average"] logger.info( 'Waterpump Check parameter if tempquantity=%s > MinAveragetemp=%s ', str(tempquantity), str(MinAveragetemp)) print 'Waterpump Check parameter if tempquantity=', tempquantity, ' > MinAveragetemp=', MinAveragetemp MinAveragetempnum = hardwaremod.tonumber(MinAveragetemp, "NA") MaxAverageHumidnum = hardwaremod.tonumber(MaxAverageHumid, "NA") # all the below conditions should be verified to start the PUMP pumpit = True if (MinAveragetempnum != "NA"): if (tempquantity > MinAveragetempnum): logger.info( 'Temperature check PASSED, tempquantity=%s > MinAveragetemp=%s ', str(tempquantity), str(MinAveragetemp)) else: logger.info('Temperature check FAILED') print 'Temperature check FAILED' pumpit = False if (MaxAverageHumidnum != "NA"): if (humquantity < MaxAverageHumidnum): logger.info( 'Humidity check PASSED, humquantity=%s < MaxAverageHumid=%s ', str(humquantity), str(MaxAverageHumid)) else: logger.info('Humidity check FAILED') print 'Humidity check FAILED' pumpit = False if pumpit: hardwaremod.makepulse(target, duration) # salva su database logger.info('Pump ON, optional time for sec = %s', duration) print 'Pump ON, optional time for sec =', duration actuatordbmod.insertdataintable(target, duration)
def setinterruptevents(): hardwaremod.removeallinterruptevents() print "load interrupt list " interruptlist = interruptdbmod.sensorlist() print "len interrupt list ", len(interruptlist) for item in interruptlist: print "got into the loop " # get PIN number recordkey = hardwaremod.HW_INFO_NAME recordvalue = item keytosearch = hardwaremod.HW_CTRL_PIN PINstr = hardwaremod.searchdata(recordkey, recordvalue, keytosearch) print "set event for the PIN ", PINstr if not PINstr == "": keytosearch = hardwaremod.HW_CTRL_LOGIC logic = hardwaremod.searchdata(recordkey, recordvalue, keytosearch) # set Sw pull up / down mode if logic == "pos": hardwaremod.GPIO_setup(PINstr, "in", "pull_down") evenslopetype = "both" else: hardwaremod.GPIO_setup(PINstr, "in", "pull_up") evenslopetype = "both" #GPIO.RISING, GPIO.FALLING or GPIO.BOTH. # link to the callback function # the bouncetime is set by the frequency parameter, if this parameter is empty, the default bouncetime would be 200 keytosearch = hardwaremod.HW_CTRL_FREQ frequency = hardwaremod.searchdata(recordkey, recordvalue, keytosearch) if frequency == "": bouncetimeINT = 200 else: frequencyINT = hardwaremod.toint(frequency, 5) bouncetimeINT = 1000 / frequencyINT # this is ok to be trunk of the int. For frequencies higher than 1000 the bouncetime is exactly zero # RPI.GPIO library does not accept bouncetime=0, it gives runtime error if bouncetimeINT <= 0: bouncetimeINT = 1 hardwaremod.GPIO_add_event_detect(PINstr, evenslopetype, eventcallback, bouncetimeINT) # set fast reference call indexed with the PIN number which is the variable used when interrupt is called: # search now to avoid searching later global PIN_attributes PIN = hardwaremod.toint(PINstr, 0) statusdataDBmod.write_status_data(PIN_attributes, PIN, "logic", logic) recordkey = hardwaremod.HW_CTRL_PIN recordvalue = PINstr keytosearch = hardwaremod.HW_INFO_NAME refsensor = hardwaremod.searchdata( recordkey, recordvalue, keytosearch) # return first occurence statusdataDBmod.write_status_data(PIN_attributes, PIN, "refsensor", refsensor) return ""
def mastercallback(): # clean old data of the database (pastdays) pastdays = 364 sensordbmod.RemoveSensorDataPeriod(pastdays) actuatordbmod.RemoveActuatorDataPeriod(pastdays) hardwaremod.removephotodataperiod(364) # remove all jobs except masterscheduler for job in SchedulerMod.sched.get_jobs(): if job.name != "master": try: job.remove() except: logger.error('Not able to remove Job %s', job.name) # set the individual callback of the day # info file dedicate call-back --------------------------------------------- (heartbeat) #this callback is used only for system status periodic check calltype = "periodic" global HEARTBEATINTERVAL interval = HEARTBEATINTERVAL timelist = [0, interval, 900] # 900 indicates to start after 15 minutes callback = "heartbeat" argument = [] setschedulercallback(calltype, timelist, argument, callback, callback) # info file dedicate call-back --------------------------------------------- (sensor) hwnamelist = sensordbmod.gettablelist() callback = "sensor" timeshift = 300 shiftstep = 2 #seconds for hwname in hwnamelist: calltype = hardwaremod.searchdata(hardwaremod.HW_INFO_NAME, hwname, hardwaremod.HW_FUNC_SCHEDTYPE) timelist = hardwaremod.gettimedata(hwname) timelist[2] = timelist[ 2] + timeshift # avoid all the sensor thread to be called in the same time argument = [] argument.append(hwname) setschedulercallback(calltype, timelist, argument, callback, hwname) timeshift = timeshift + shiftstep #<------> # info file dedicate quinto call-back ----------------------------------(takephoto) usedfor = "photocontrol" callback = "photo" hwnamelist = hardwaremod.searchdatalist(hardwaremod.HW_FUNC_USEDFOR, usedfor, hardwaremod.HW_INFO_NAME) for hwname in hwnamelist: calltype = hardwaremod.searchdata(hardwaremod.HW_INFO_NAME, hwname, hardwaremod.HW_FUNC_SCHEDTYPE) timelist = hardwaremod.gettimedata(hwname) argument = [] argument.append(hwname) setschedulercallback(calltype, timelist, argument, callback, hwname) # info ne file dedicate quarto call-back ---------------------------------------(sendmail) usedfor = "mailcontrol" callback = "mail" hwnamelist = hardwaremod.searchdatalist(hardwaremod.HW_FUNC_USEDFOR, usedfor, hardwaremod.HW_INFO_NAME) for hwname in hwnamelist: calltype = hardwaremod.searchdata(hardwaremod.HW_INFO_NAME, hwname, hardwaremod.HW_FUNC_SCHEDTYPE) timelist = hardwaremod.gettimedata(hwname) argument = [] argument.append(hwname) setschedulercallback(calltype, timelist, argument, callback, hwname) # info ne file dedicate quinto call-back ---------------------------------------(lightcheck) # empty #<----> # info file dedicate call-back ------------------------------------------------ (waterpump) callback = "waterpump" #water schedule table paramlist = wateringdbmod.getparamlist() # name of the months ordered elementlist = wateringdbmod.getelementlist( ) # pump ordered (based on "watercontrol" field) table = wateringdbmod.gettable( 1 ) # table, each row is a pump, each column is a month, value is watering time multiplieer table1 = wateringdbmod.gettable( 0 ) # table, each row is a pump, each column is a month, value is watering scheme table2 = wateringdbmod.gettable( 2 ) # table, each row is a pump, each column is a month, value is time delay #print paramlist #print elementlistly #print table paramlistdrop = advancedmod.getparamlist() # day of the week elementlistdrop = advancedmod.getelementlist() # drops ordered tabledrop = advancedmod.gettable( ) # table, each row is a schema number (drop number), each column is a weekday for pumpnumber in range(len(elementlist)): #print "number =",pumpnumber pumpname = elementlist[pumpnumber] todaydate = date.today() # Monday is 0 and Sunday is 6 weekday = todaydate.weekday() month = todaydate.month try: waterschemanumber = table1[pumpnumber][month - 1] waterdropnumber = hardwaremod.toint(table[pumpnumber][month - 1], 0) watertimedelaysec = hardwaremod.toint( table2[pumpnumber][month - 1], 0) except IndexError: print "EXCEPTION: index out of range" waterdropnumber = 0 watertimedelaysec = 0 if waterdropnumber > 0: #print " month " , month, " drop " , waterdropnumber calltype = hardwaremod.searchdata(hardwaremod.HW_INFO_NAME, pumpname, hardwaremod.HW_FUNC_SCHEDTYPE) for todayevent in tabledrop[waterschemanumber - 1][weekday]: timelist = hardwaremod.separatetimestringint(todayevent[0]) timelist[2] = timelist[2] + watertimedelaysec argument = [] argument.append(pumpname) durationinseconds = hardwaremod.toint(todayevent[1], 0) * waterdropnumber argument.append(durationinseconds) for i in range(2, len(todayevent)): argument.append(todayevent[i]) if durationinseconds > 0: #check if the duration in second is >0 setschedulercallback(calltype, timelist, argument, callback, pumpname) # info file dedicate call-back ------------------------------------------------ (pulsenutrient) callback = "doser" #fertilizer schedule table paramlist = fertilizerdbmod.getparamlist() # name of the months ordered elementlist = fertilizerdbmod.getelementlist( ) # element with "fertilizercontrol field" ordered table = fertilizerdbmod.gettable( 1 ) # table, each row is a doser, each column is a month, value is number of times in a month table1 = fertilizerdbmod.gettable( 0 ) # table, each row is a doser, each column is a month, value is pulse seconds for dosernumber in range(len(elementlist)): #print "number =",dosernumber dosername = elementlist[dosernumber] calltype = hardwaremod.searchdata(hardwaremod.HW_INFO_NAME, dosername, hardwaremod.HW_FUNC_SCHEDTYPE) todaydate = date.today() # Monday is 0 and Sunday is 6 year = todaydate.year month = todaydate.month day = todaydate.day fertilizerpulsenumber = hardwaremod.toint( table[dosernumber][month - 1], 0) fertilizerpulsesecond = hardwaremod.toint( table1[dosernumber][month - 1], 0) if (fertilizerpulsenumber > 0) and (fertilizerpulsesecond > 0): themonthdays = 30 #approximate number of days in a month dayinterval = themonthdays / fertilizerpulsenumber halfinterval = (dayinterval + 1) / 2 print "day=", day, " dayinterval=", dayinterval, " half=", halfinterval if ((day + int(halfinterval)) % int(dayinterval)) == 0: timelist = hardwaremod.gettimedata("06:00:00") argument = [] argument.append(dosername) argument.append(fertilizerpulsesecond) if (fertilizerpulsesecond ) > 0: #check if the duration in second is >0 setschedulercallback(calltype, timelist, argument, callback, dosername)
def cycleresetall(): global AUTO_data elementlist= automationdbmod.getelementlist() for element in elementlist: waitingtime=hardwaremod.toint(automationdbmod.searchdata("element",element,"pausebetweenwtstepsmin"),0) AUTO_data[element]={"lastactiontime":datetime.now() - timedelta(minutes=waitingtime),"status":"ok","actionvalue":0, "alertcounter":0, "infocounter":0}
def autowateringexecute(refsensor, element): global AUTO_data sensor = autowateringdbmod.searchdata("element", element, "sensor") # check the sensor if refsensor == sensor: print "auto watering check -----------------------------------------> ", element logger.info('auto watering check --------------------------> %s', element) # check the watering mode modelist = ["None", "Full Auto", "Emergency Activation", "Alert Only"] workmode = checkworkmode(element) if not (sensor in sensordbmod.gettablelist()): print "Sensor does not exist ", sensor, ", element: ", element logger.error("Sensor does not exist %s , element: %s ", sensor, element) return "sensor not Exist" maxthreshold = hardwaremod.tonumber( autowateringdbmod.searchdata("element", element, "threshold")[1], 0) minthreshold = hardwaremod.tonumber( autowateringdbmod.searchdata("element", element, "threshold")[0], maxthreshold) # exit condition in case of data inconsistency if minthreshold >= maxthreshold: print "Data inconsistency , element: ", element logger.error("Data inconsistency , element: %s ", element) return "data inconsistency" now = datetime.now() nowtime = now.time() starttimeh = hardwaremod.toint( autowateringdbmod.searchdata("element", element, "allowedperiod")[0].split(":")[0], 0) starttimem = hardwaremod.toint( autowateringdbmod.searchdata("element", element, "allowedperiod")[0].split(":")[1], 0) endtimeh = hardwaremod.toint( autowateringdbmod.searchdata("element", element, "allowedperiod")[1].split(":")[0], 1) endtimem = hardwaremod.toint( autowateringdbmod.searchdata("element", element, "allowedperiod")[1].split(":")[1], 0) starttime = time(starttimeh, starttimem) endtime = time(endtimeh, endtimem) duration = 1000 * hardwaremod.toint( autowateringdbmod.searchdata("element", element, "wtstepsec"), 0) maxstepnumber = hardwaremod.toint( autowateringdbmod.searchdata("element", element, "maxstepnumber"), 0) maxdays = hardwaremod.toint( autowateringdbmod.searchdata("element", element, "maxdaysbetweencycles"), 0) waitingtime = hardwaremod.toint( autowateringdbmod.searchdata("element", element, "pausebetweenwtstepsmin"), 0) mailtype = autowateringdbmod.searchdata("element", element, "mailalerttype") minaccepted = hardwaremod.tonumber( autowateringdbmod.searchdata("element", element, "sensorminacceptedvalue"), 0.1) # ------------------------ Workmode split if workmode == "Full Auto": # block the wateringplan activation as by definition of "Full Auto" allowwateringplan[element] = False # check if inside the allowed time period print "full Auto Mode" logger.info('full auto mode --> %s', element) timeok = isNowInTimePeriod(starttime, endtime, nowtime) print "inside allowed time ", timeok, " starttime ", starttime, " endtime ", endtime logger.info('full auto mode') if timeok: logger.info('inside allowed time') belowthr, valid = checkminthreshold(sensor, minthreshold, minaccepted) if valid: if belowthr: status = "lowthreshold" logger.info('below threshold') # wait to seek a more stable reading of hygrometer # check if time between watering events is larger that the waiting time (minutes) lastwateringtime = statusdataDBmod.read_status_data( AUTO_data, element, "lastwateringtime") print ' Previous watering: ', lastwateringtime, ' Now: ', datetime.now( ) timedifference = sensordbmod.timediffinminutes( lastwateringtime, datetime.now()) print 'Time interval between watering steps', timedifference, '. threshold', waitingtime logger.info( 'Time interval between watering steps %d threshold %d', timedifference, waitingtime) if timedifference > waitingtime: print " Sufficient waiting time" logger.info('Sufficient waiting time') # activate watering in case the maxstepnumber is not exceeded watercounter = statusdataDBmod.read_status_data( AUTO_data, element, "watercounter") if maxstepnumber > watercounter: #activate pump activatewater(element, duration) # invia mail, considered as info, not as alert if mailtype != "warningonly": textmessage = "INFO: " + sensor + " value below the minimum threshold " + str( minthreshold ) + ", activating the watering :" + element emailmod.sendallmail("alert", textmessage) statusdataDBmod.write_status_data( AUTO_data, element, "watercounter", watercounter + 1) statusdataDBmod.write_status_data( AUTO_data, element, "lastwateringtime", datetime.now()) else: # critical, sensor below minimum after all watering activations are done logger.info( 'Number of watering time per cycle has been exceeeded' ) # read hystory data and calculate the slope timelist = hardwaremod.gettimedata(sensor) cyclestartdate = statusdataDBmod.read_status_data( AUTO_data, element, "cyclestartdate") lastwateringtime = statusdataDBmod.read_status_data( AUTO_data, element, "lastwateringtime") startdate = cyclestartdate - timedelta( minutes=timelist[1]) enddate = lastwateringtime + timedelta( minutes=waitingtime) isslopeok = checkinclination( sensor, startdate, enddate ) # still to decide if use the enddate if isslopeok: # invia mail if couner alert is lower than 1 alertcounter = statusdataDBmod.read_status_data( AUTO_data, element, "alertcounter") if alertcounter < 1: textmessage = "WARNING: Please consider to increase the amount of water per cycle, the " + sensor + " value below the MINIMUM threshold " + str( minthreshold ) + " still after activating the watering :" + element + " for " + str( maxstepnumber ) + " times. System will automatically reset the watering cycle to allow more water" print textmessage #send alert mail notification emailmod.sendallmail( "alert", textmessage) logger.error(textmessage) statusdataDBmod.write_status_data( AUTO_data, element, "alertcounter", alertcounter + 1) # reset watering cycle status = "done" statusdataDBmod.write_status_data( AUTO_data, element, "watercounter", 0) statusdataDBmod.write_status_data( AUTO_data, element, "checkcounter", -1) statusdataDBmod.write_status_data( AUTO_data, element, "alertcounter", 0) statusdataDBmod.write_status_data( AUTO_data, element, "cyclestartdate", datetime.now()) else: # slope not OK, probable hardware problem alertcounter = statusdataDBmod.read_status_data( AUTO_data, element, "alertcounter") if alertcounter < 3: textmessage = "CRITICAL: Possible hardware problem, " + sensor + " value below the MINIMUM threshold " + str( minthreshold ) + " still after activating the watering :" + element + " for " + str( maxstepnumber) + " times" print textmessage #send alert mail notification emailmod.sendallmail( "alert", textmessage) logger.error(textmessage) statusdataDBmod.write_status_data( AUTO_data, element, "alertcounter", alertcounter + 1) # update the status checkcounter = statusdataDBmod.read_status_data( AUTO_data, element, "checkcounter") statusdataDBmod.write_status_data( AUTO_data, element, "cyclestatus", status) statusdataDBmod.write_status_data( AUTO_data, element, "checkcounter", checkcounter + 1) # RAMPUP case above threshold but below maxthreshold elif sensorreading( sensor ) < maxthreshold: # intermediate state where the sensor is above the minthreshold but lower than the max threshold # check the status of the automatic cycle cyclestatus = statusdataDBmod.read_status_data( AUTO_data, element, "cyclestatus") if cyclestatus != "done": status = "rampup" # wait to seek a more stable reading of hygrometer # check if time between watering events is larger that the waiting time (minutes) lastwateringtime = statusdataDBmod.read_status_data( AUTO_data, element, "lastwateringtime") if sensordbmod.timediffinminutes( lastwateringtime, datetime.now()) > waitingtime: watercounter = statusdataDBmod.read_status_data( AUTO_data, element, "watercounter") if maxstepnumber > watercounter: #activate pump activatewater(element, duration) # invia mail, considered as info, not as alert if mailtype != "warningonly": textmessage = "INFO: " + sensor + " value below the Maximum threshold " + str( maxthreshold ) + ", activating the watering :" + element emailmod.sendallmail( "alert", textmessage) statusdataDBmod.write_status_data( AUTO_data, element, "watercounter", watercounter + 1) statusdataDBmod.write_status_data( AUTO_data, element, "lastwateringtime", datetime.now()) else: # give up to reache the maximum threshold, proceed as done, send alert logger.info( 'Number of watering time per cycle has been exceeeded' ) # invia mail if couner alert is lower than 1 -------------- # only if the info is activated if mailtype != "warningonly": alertcounter = statusdataDBmod.read_status_data( AUTO_data, element, "alertcounter") if alertcounter < 2: textmessage = "INFO " + sensor + " value below the Maximum threshold " + str( maxthreshold ) + " still after activating the watering :" + element + " for " + str( maxstepnumber) + " times" print textmessage #send alert mail notification emailmod.sendallmail( "alert", textmessage) logger.error(textmessage) statusdataDBmod.write_status_data( AUTO_data, element, "alertcounter", alertcounter + 1) # reset watering cycle status = "done" statusdataDBmod.write_status_data( AUTO_data, element, "watercounter", 0) statusdataDBmod.write_status_data( AUTO_data, element, "checkcounter", -1) statusdataDBmod.write_status_data( AUTO_data, element, "alertcounter", 0) statusdataDBmod.write_status_data( AUTO_data, element, "cyclestartdate", datetime.now()) # update the status checkcounter = statusdataDBmod.read_status_data( AUTO_data, element, "checkcounter") statusdataDBmod.write_status_data( AUTO_data, element, "cyclestatus", status) statusdataDBmod.write_status_data( AUTO_data, element, "checkcounter", checkcounter + 1) else: # update the status, reset cycle statusdataDBmod.write_status_data( AUTO_data, element, "cyclestatus", "done") statusdataDBmod.write_status_data( AUTO_data, element, "checkcounter", 0) statusdataDBmod.write_status_data( AUTO_data, element, "watercounter", 0) statusdataDBmod.write_status_data( AUTO_data, element, "alertcounter", 0) elif workmode == "Emergency Activation": # check if inside the allow time period logger.info('Emergency Mode') timeok = isNowInTimePeriod(starttime, endtime, nowtime) print "inside allowed time ", timeok, " starttime ", starttime, " endtime ", endtime if timeok: belowthr, valid = checkminthreshold(sensor, minthreshold, minaccepted) if valid: if belowthr: # wait to seek a more stable reading of hygrometer # check if time between watering events is larger that the waiting time (minutes) lastwateringtime = statusdataDBmod.read_status_data( AUTO_data, element, "lastwateringtime") if sensordbmod.timediffinminutes( lastwateringtime, datetime.now()) > waitingtime: # activate watering in case the maxstepnumber is not exceeded watercounter = statusdataDBmod.read_status_data( AUTO_data, element, "watercounter") if maxstepnumber > watercounter: #activate pump activatewater(element, duration) # invia mail, considered as info, not as alert if mailtype != "warningonly": textmessage = "INFO: " + sensor + " value below the minimum threshold " + str( minthreshold ) + ", activating the watering :" + element emailmod.sendallmail("alert", textmessage) statusdataDBmod.write_status_data( AUTO_data, element, "watercounter", watercounter + 1) statusdataDBmod.write_status_data( AUTO_data, element, "lastwateringtime", datetime.now()) else: logger.info( 'Number of watering time per cycle has been exceeeded' ) # read hystory data and calculate the slope timelist = hardwaremod.gettimedata(sensor) cyclestartdate = statusdataDBmod.read_status_data( AUTO_data, element, "cyclestartdate") lastwateringtime = statusdataDBmod.read_status_data( AUTO_data, element, "lastwateringtime") startdate = cyclestartdate - timedelta( minutes=timelist[1]) enddate = lastwateringtime + timedelta( minutes=waitingtime) isslopeok = checkinclination( sensor, startdate, enddate) if isslopeok: # invia mail if couner alert is lower than 1 alertcounter = statusdataDBmod.read_status_data( AUTO_data, element, "alertcounter") if alertcounter < 1: textmessage = "WARNING: Please consider to increase the amount of water per cycle, the " + sensor + " value below the MINIMUM threshold " + str( minthreshold ) + " still after activating the watering :" + element + " for " + str( maxstepnumber ) + " times. System will automatically reset the watering cycle to allow more water" print textmessage #send alert mail notification alertcounter emailmod.sendallmail( "alert", textmessage) logger.error(textmessage) statusdataDBmod.write_status_data( AUTO_data, element, "alertcounter", alertcounter + 1) # reset watering cycle status = "done" statusdataDBmod.write_status_data( AUTO_data, element, "watercounter", 0) statusdataDBmod.write_status_data( AUTO_data, element, "checkcounter", -1) statusdataDBmod.write_status_data( AUTO_data, element, "alertcounter", 0) statusdataDBmod.write_status_data( AUTO_data, element, "cyclestartdate", datetime.now()) else: # slope not OK, probable hardware problem alertcounter = statusdataDBmod.read_status_data( AUTO_data, element, "alertcounter") if alertcounter < 3: textmessage = "CRITICAL: Possible hardware problem, " + sensor + " value below the MINIMUM threshold " + str( minthreshold ) + " still after activating the watering :" + element + " for " + str( maxstepnumber) + " times" print textmessage #send alert mail notification emailmod.sendallmail( "alert", textmessage) logger.error(textmessage) statusdataDBmod.write_status_data( AUTO_data, element, "alertcounter", alertcounter + 1) # update the status checkcounter = statusdataDBmod.read_status_data( AUTO_data, element, "checkcounter") statusdataDBmod.write_status_data( AUTO_data, element, "cyclestatus", "lowthreshold") statusdataDBmod.write_status_data( AUTO_data, element, "checkcounter", checkcounter + 1) else: # update the status statusdataDBmod.write_status_data( AUTO_data, element, "cyclestatus", "done") statusdataDBmod.write_status_data( AUTO_data, element, "checkcounter", 0) statusdataDBmod.write_status_data( AUTO_data, element, "watercounter", 0) statusdataDBmod.write_status_data( AUTO_data, element, "alertcounter", 0) elif workmode == "under MIN over MAX": logger.info('under MIN over MAX') # normally watering plan is allowed unless over MAX threshold allowwateringplan[element] = True # check if inside the allow time period timeok = isNowInTimePeriod(starttime, endtime, nowtime) print "inside allowed time ", timeok, " starttime ", starttime, " endtime ", endtime if timeok: logger.info('Insede operative time') belowthr, valid = checkminthreshold(sensor, minthreshold, minaccepted) if valid: logger.info('valid sensor reading') if belowthr: logger.info('sensor reading below threshold') # wait to seek a more stable reading of hygrometer # check if time between watering events is larger that the waiting time (minutes) lastwateringtime = statusdataDBmod.read_status_data( AUTO_data, element, "lastwateringtime") if sensordbmod.timediffinminutes( lastwateringtime, datetime.now()) > waitingtime: # activate watering in case the maxstepnumber is not exceeded watercounter = statusdataDBmod.read_status_data( AUTO_data, element, "watercounter") if maxstepnumber > watercounter: logger.info('water Count not exceeded') #activate pump activatewater(element, duration) # invia mail, considered as info, not as alert if mailtype != "warningonly": textmessage = "INFO: " + sensor + " value below the minimum threshold " + str( minthreshold ) + ", activating the watering :" + element emailmod.sendallmail("alert", textmessage) statusdataDBmod.write_status_data( AUTO_data, element, "watercounter", watercounter + 1) statusdataDBmod.write_status_data( AUTO_data, element, "lastwateringtime", datetime.now()) else: logger.info( 'Number of watering time per cycle has been exceeeded' ) # read hystory data and calculate the slope timelist = hardwaremod.gettimedata(sensor) cyclestartdate = statusdataDBmod.read_status_data( AUTO_data, element, "cyclestartdate") lastwateringtime = statusdataDBmod.read_status_data( AUTO_data, element, "lastwateringtime") startdate = cyclestartdate - timedelta( minutes=timelist[1]) enddate = lastwateringtime + timedelta( minutes=waitingtime) isslopeok = checkinclination( sensor, startdate, enddate) if isslopeok: # invia mail if couner alert is lower than 1 alertcounter = statusdataDBmod.read_status_data( AUTO_data, element, "alertcounter") if alertcounter < 1: textmessage = "WARNING: Please consider to increase the amount of water per cycle, the " + sensor + " value below the MINIMUM threshold " + str( minthreshold ) + " still after activating the watering :" + element + " for " + str( maxstepnumber ) + " times. System will automatically reset the watering cycle to allow more water" print textmessage #send alert mail notification emailmod.sendallmail( "alert", textmessage) logger.error(textmessage) statusdataDBmod.write_status_data( AUTO_data, element, "alertcounter", alertcounter + 1) # reset watering cycle status = "done" statusdataDBmod.write_status_data( AUTO_data, element, "watercounter", 0) statusdataDBmod.write_status_data( AUTO_data, element, "checkcounter", -1) statusdataDBmod.write_status_data( AUTO_data, element, "alertcounter", 0) statusdataDBmod.write_status_data( AUTO_data, element, "cyclestartdate", datetime.now()) else: # slope not OK, probable hardware problem alertcounter = statusdataDBmod.read_status_data( AUTO_data, element, "alertcounter") if alertcounter < 3: textmessage = "CRITICAL: Possible hardware problem, " + sensor + " value below the MINIMUM threshold " + str( minthreshold ) + " still after activating the watering :" + element + " for " + str( maxstepnumber) + " times" print textmessage #send alert mail notification emailmod.sendallmail( "alert", textmessage) logger.error(textmessage) statusdataDBmod.write_status_data( AUTO_data, element, "alertcounter", alertcounter + 1) # update the status checkcounter = statusdataDBmod.read_status_data( AUTO_data, element, "checkcounter") statusdataDBmod.write_status_data( AUTO_data, element, "cyclestatus", "lowthreshold") statusdataDBmod.write_status_data( AUTO_data, element, "checkcounter", checkcounter + 1) else: # above minimum threshold logger.info('sensor reading above min threshold') # update the status statusdataDBmod.write_status_data( AUTO_data, element, "cyclestatus", "done") statusdataDBmod.write_status_data( AUTO_data, element, "checkcounter", 0) statusdataDBmod.write_status_data( AUTO_data, element, "watercounter", 0) statusdataDBmod.write_status_data( AUTO_data, element, "alertcounter", 0) if sensorreading(sensor) > maxthreshold: logger.info( 'sensor reading above MAX threshold, deactivate scheduled irrigation' ) # do not activate the irrigation scheduled in the time plan allowwateringplan[element] = False elif workmode == "Alert Only": belowthr, valid = checkminthreshold(sensor, minthreshold, minaccepted) if valid: if belowthr: # invia mail if couter alert is lower than alertcounter = statusdataDBmod.read_status_data( AUTO_data, element, "alertcounter") if alertcounter < 2: textmessage = "WARNING " + sensor + " value below the minimum threshold " + str( minthreshold) + " watering system: " + element print textmessage #send alert mail notification emailmod.sendallmail("alert", textmessage) logger.error(textmessage) statusdataDBmod.write_status_data( AUTO_data, element, "alertcounter", alertcounter + 1) # update the status checkcounter = statusdataDBmod.read_status_data( AUTO_data, element, "checkcounter") statusdataDBmod.write_status_data(AUTO_data, element, "cyclestatus", "lowthreshold") statusdataDBmod.write_status_data(AUTO_data, element, "checkcounter", checkcounter + 1) else: # update the status statusdataDBmod.write_status_data(AUTO_data, element, "cyclestatus", "done") statusdataDBmod.write_status_data(AUTO_data, element, "checkcounter", 0) statusdataDBmod.write_status_data(AUTO_data, element, "watercounter", 0) statusdataDBmod.write_status_data(AUTO_data, element, "alertcounter", 0) else: # None case print "No Action required, workmode set to None, element: ", element logger.info( "No Action required, workmode set to None, element: %s ", element) cyclestatus = statusdataDBmod.read_status_data(AUTO_data, element, "cyclestatus") if cyclestatus == "lowthreshold": checkcounter = statusdataDBmod.read_status_data( AUTO_data, element, "checkcounter") if checkcounter == 1: statusdataDBmod.write_status_data(AUTO_data, element, "cyclestartdate", datetime.now()) # implment alert message for the cycle exceeding days, and reset the cycle if workmode != "None": cyclestartdate = statusdataDBmod.read_status_data( AUTO_data, element, "cyclestartdate") timedeltadays = sensordbmod.timediffdays(datetime.now(), cyclestartdate) if (timedeltadays > maxdays ): #the upper limit is set in case of abrupt time change textmessage = "WARNING " + sensor + " watering cycle is taking too many days, watering system: " + element + ". Reset watering cycle" print textmessage # in case of full Auto, activate pump for minimum pulse period if workmode == "Full Auto": if ( timedeltadays < maxdays + 2 ): #the upper limit is set in case of abrupt time change textmessage = "WARNING " + sensor + " watering cycle is taking too many days, watering system: " + element + ". Activate Min pulse + Reset watering cycle" activatewater(element, duration) #send alert mail notification if mailtype != "warningonly": emailmod.sendallmail("alert", textmessage) logger.error(textmessage) logger.error("Cycle started %s, Now is %s ", cyclestartdate.strftime("%Y-%m-%d %H:%M:%S"), datetime.now().strftime("%Y-%m-%d %H:%M:%S")) # reset cycle statusdataDBmod.write_status_data(AUTO_data, element, "cyclestatus", "done") statusdataDBmod.write_status_data(AUTO_data, element, "checkcounter", 0) statusdataDBmod.write_status_data(AUTO_data, element, "watercounter", 0) statusdataDBmod.write_status_data(AUTO_data, element, "alertcounter", 0) statusdataDBmod.write_status_data(AUTO_data, element, "cyclestartdate", datetime.now()) # implment Critical alert message in case the threshold is below the 0.5 of the minimum if workmode != "None": belowthr, valid = checkminthreshold(sensor, minthreshold * 0.5, minaccepted) if valid: if belowthr: logger.info( 'sensor %s below half of the actual set threshold', sensor) textmessage = "CRITICAL: Plant is dying, " + sensor + " reading below half of the minimum threshold, need to check the " + element print textmessage #send alert mail notification alertcounter = statusdataDBmod.read_status_data( AUTO_data, element, "alertcounter") if alertcounter < 5: emailmod.sendallmail("alert", textmessage) logger.error(textmessage) statusdataDBmod.write_status_data( AUTO_data, element, "alertcounter", alertcounter + 1) else: logger.info('sensor %s below valid data', sensor) textmessage = "WARNING: " + sensor + " below valid data range, need to check sensor" print textmessage #send alert mail notification alertcounter = statusdataDBmod.read_status_data( AUTO_data, element, "alertcounter") if alertcounter < 3: emailmod.sendallmail("alert", textmessage) logger.error(textmessage) statusdataDBmod.write_status_data(AUTO_data, element, "alertcounter", alertcounter + 1) return
def startpump(target, activationseconds, MinAveragetemp, MaxAverageHumid): logger.info('WateringPlan Startpump evaluation: %s', target) #workmode=autowateringmod.checkworkmode(target) #if workmode=="Full Auto": if target in autowateringmod.allowwateringplan: if not autowateringmod.allowwateringplan[target]: logger.info( 'WateringPlan: %s pump activation blocked by automation', target) pumpit = False return False duration = hardwaremod.toint(activationseconds, 0) print target, " ", duration, " ", datetime.now() # evaluate parameters #MinAverageLight=500 not used now MinutesOfAverage = 120 #minutes in which the average data is calculated from sensor sampling print "waterpump check" logger.info('execute water pump check %s', datetime.now().strftime("%Y-%m-%d %H:%M:%S")) # then check the temperature and Humidity print "Check Humidity and Temperature" MinAveragetempnum = hardwaremod.tonumber(MinAveragetemp, "NA") MaxAverageHumidnum = hardwaremod.tonumber(MaxAverageHumid, "NA") # all the below conditions should be verified to start the PUMP pumpit = True hsensornamelist = hardwaremod.getsensornamebymeasure( hardwaremod.MEASURELIST[1]) if hsensornamelist: sensordata = [] hsensorname = hsensornamelist[0] # get first found sensor in the list sensordbmod.getsensordbdata(hsensorname, sensordata) starttimecalc = datetime.now() - timedelta( minutes=int(MinutesOfAverage)) isok, quantitylist = sensordbmod.EvaluateDataPeriod( sensordata, starttimecalc, datetime.now()) humquantity = quantitylist["average"] logger.info( 'Waterpump Check parameter if humquantity=%s < MaxAverageHumid=%s ', str(humquantity), str(MaxAverageHumid)) print 'Waterpump Check parameter if humquantity=', humquantity, ' < MaxAverageHumid=', MaxAverageHumid if (MaxAverageHumidnum != "NA"): if (humquantity < MaxAverageHumidnum): logger.info( 'Humidity check PASSED, humquantity=%s < MaxAverageHumid=%s ', str(humquantity), str(MaxAverageHumid)) else: logger.info('Humidity check FAILED') print 'Humidity check FAILED' pumpit = False tsensornamelist = hardwaremod.getsensornamebymeasure( hardwaremod.MEASURELIST[0]) if tsensornamelist: sensordata = [] tsensorname = tsensornamelist[0] # get first found sensor in the list sensordbmod.getsensordbdata(tsensorname, sensordata) starttimecalc = datetime.now() - timedelta( minutes=int(MinutesOfAverage)) isok, quantitylist = sensordbmod.EvaluateDataPeriod( sensordata, starttimecalc, datetime.now()) tempquantity = quantitylist["average"] logger.info( 'Waterpump Check parameter if tempquantity=%s > MinAveragetemp=%s ', str(tempquantity), str(MinAveragetemp)) print 'Waterpump Check parameter if tempquantity=', tempquantity, ' > MinAveragetemp=', MinAveragetemp if (MinAveragetempnum != "NA"): if (tempquantity > MinAveragetempnum): logger.info( 'Temperature check PASSED, tempquantity=%s > MinAveragetemp=%s ', str(tempquantity), str(MinAveragetemp)) else: logger.info('Temperature check FAILED') print 'Temperature check FAILED' pumpit = False if pumpit: # activation of the doser before the pump doseron = autofertilizermod.checkactivate(target, duration) # watering hardwaremod.makepulse(target, duration) # salva su database logger.info('Switch Pump %s ON, optional time for sec = %s', target, duration) print 'Pump ON, optional time for sec =', duration actuatordbmod.insertdataintable(target, duration) return True
def startpump(target,activationseconds,MinAveragetemp,MaxAverageHumid): logger.info('WateringPlan Startpump evaluation: %s', target) #workmode=autowateringmod.checkworkmode(target) #if workmode=="Full Auto": if target in autowateringmod.allowwateringplan: if not autowateringmod.allowwateringplan[target]: logger.info('WateringPlan: %s pump activation blocked by automation', target) pumpit=False return False duration=1000*hardwaremod.toint(activationseconds,0) print target, " ",duration, " " , datetime.now() # evaluate parameters #MinAverageLight=500 not used now MinutesOfAverage=120 #minutes in which the average data is calculated from sensor sampling print "waterpump check" logger.info('execute water pump check %s', datetime.now().strftime("%Y-%m-%d %H:%M:%S")) # then check the temperature and Humidity print "Check Humidity and Temperature" MinAveragetempnum=hardwaremod.tonumber(MinAveragetemp,"NA") MaxAverageHumidnum=hardwaremod.tonumber(MaxAverageHumid,"NA") # all the below conditions should be verified to start the PUMP pumpit=True hsensornamelist=hardwaremod.getsensornamebymeasure(hardwaremod.MEASURELIST[1]) if hsensornamelist: sensordata=[] hsensorname=hsensornamelist[0] # get first found sensor in the list sensordbmod.getsensordbdata(hsensorname,sensordata) starttimecalc=datetime.now()-timedelta(minutes=int(MinutesOfAverage)) humquantity=sensordbmod.EvaluateDataPeriod(sensordata,starttimecalc,datetime.now())["average"] logger.info('Waterpump Check parameter if humquantity=%s < MaxAverageHumid=%s ', str(humquantity), str(MaxAverageHumid)) print 'Waterpump Check parameter if humquantity=',humquantity,' < MaxAverageHumid=' ,MaxAverageHumid if (MaxAverageHumidnum!="NA"): if (humquantity<MaxAverageHumidnum): logger.info('Humidity check PASSED, humquantity=%s < MaxAverageHumid=%s ', str(humquantity), str(MaxAverageHumid)) else: logger.info('Humidity check FAILED') print 'Humidity check FAILED' pumpit=False tsensornamelist=hardwaremod.getsensornamebymeasure(hardwaremod.MEASURELIST[0]) if tsensornamelist: sensordata=[] tsensorname=tsensornamelist[0] # get first found sensor in the list sensordbmod.getsensordbdata(tsensorname,sensordata) starttimecalc=datetime.now()-timedelta(minutes=int(MinutesOfAverage)) tempquantity=sensordbmod.EvaluateDataPeriod(sensordata,starttimecalc,datetime.now())["average"] logger.info('Waterpump Check parameter if tempquantity=%s > MinAveragetemp=%s ', str(tempquantity), str(MinAveragetemp)) print 'Waterpump Check parameter if tempquantity=',tempquantity,' > MinAveragetemp=' ,MinAveragetemp if (MinAveragetempnum!="NA"): if (tempquantity>MinAveragetempnum): logger.info('Temperature check PASSED, tempquantity=%s > MinAveragetemp=%s ', str(tempquantity), str(MinAveragetemp)) else: logger.info('Temperature check FAILED') print 'Temperature check FAILED' pumpit=False if pumpit: # activation of the doser before the pump doseron=autofertilizermod.checkactivate(target,duration) # watering hardwaremod.makepulse(target,duration) # salva su database logger.info('Switch Pump %s ON, optional time for sec = %s', target, duration) print 'Pump ON, optional time for sec =', duration actuatordbmod.insertdataintable(target,duration) return True
def automationexecute(refsensor,element): sensor=automationdbmod.searchdata("element",element,"sensor") # check the sensor if refsensor==sensor: logger.info('automation Pairing OK ---> Actuator: %s , Sensor: %s', element, sensor) # check the watering mode modelist=["None", "Full Auto" , "Emergency Activation" , "Alert Only"] workmode=checkworkmode(element) if (workmode=="None"): # None case print "No Action required, workmode set to None, element: " , element logger.info("No Action required, workmode set to None, element: %s " , element) return if (workmode==""): logger.info("Not able to get the workmode: %s " , element) return logger.info('Automantion, Get all the parameters') sensormaxthreshold=hardwaremod.tonumber(automationdbmod.searchdata("element",element,"sensor_threshold")[1],0) sensorminthreshold=hardwaremod.tonumber(automationdbmod.searchdata("element",element,"sensor_threshold")[0],sensormaxthreshold) actuatormaxthreshold=hardwaremod.tonumber(automationdbmod.searchdata("element",element,"actuator_threshold")[1],0) actuatorminthreshold=hardwaremod.tonumber(automationdbmod.searchdata("element",element,"actuator_threshold")[0],actuatormaxthreshold) # evaluate variables for operational period check now = datetime.now() nowtime = now.time() starttimeh=hardwaremod.toint(automationdbmod.searchdata("element",element,"allowedperiod")[0].split(":")[0],0) starttimem=hardwaremod.toint(automationdbmod.searchdata("element",element,"allowedperiod")[0].split(":")[1],0) endtimeh=hardwaremod.toint(automationdbmod.searchdata("element",element,"allowedperiod")[1].split(":")[0],1) endtimem=hardwaremod.toint(automationdbmod.searchdata("element",element,"allowedperiod")[1].split(":")[1],0) starttime=time(starttimeh,starttimem) endtime=time(endtimeh,endtimem) # get other parameters maxstepnumber=hardwaremod.toint(automationdbmod.searchdata("element",element,"stepnumber"),1) waitingtime=hardwaremod.toint(automationdbmod.searchdata("element",element,"pausebetweenwtstepsmin"),1) mailtype=automationdbmod.searchdata("element",element,"mailalerttype") averageminutes=hardwaremod.tonumber(automationdbmod.searchdata("element",element,"averagesample"),1) mathoperation=automationdbmod.searchdata("element",element,"mathoperation") # check sensor timetrigger sensorcontrolcommand=hardwaremod.searchdata(hardwaremod.HW_INFO_NAME,refsensor,hardwaremod.HW_CTRL_CMD) logger.info('Sensor control command: %s , Sensor: %s', sensorcontrolcommand, sensor) if sensorcontrolcommand=="returnzero": logger.info('Modify parameter for the timetrigger') #adjust the parameters in the way the activation condition is always obtained sensormaxthreshold=1 sensorminthreshold=-1 maxstepnumber=1 averageminutes=0 # Calculated Variables if maxstepnumber<1: # not possible to proceed print "No Action required, maxstepnumber <1, element: " , element logger.info("No Action required, maxstepnumber <1, element: %s " , element) return interval=(sensormaxthreshold-sensorminthreshold)/maxstepnumber actuatorinterval=(actuatormaxthreshold-actuatorminthreshold)/maxstepnumber P=[] for I in range(0, maxstepnumber+1): P.append(actuatorminthreshold+I*actuatorinterval) # ------------------------ Automation alghoritm if workmode=="Full Auto": # check if inside the allowed time period print "full Auto Mode" logger.info('full auto mode --> %s', element) timeok=isNowInTimePeriod(starttime, endtime, nowtime) print "inside allowed time ", timeok , " starttime ", starttime , " endtime ", endtime if timeok: logger.info('inside allowed time') isok,sensorvalue=sensorreading(sensor,averageminutes,mathoperation) # operation of sensor readings for a number of sample if isok: print "Sensor Value ", sensorvalue if sensorminthreshold<=sensormaxthreshold: print "Algorithm , element: " , element logger.info("Forward algorithm , element: %s " , element) Inde=0 maxs=sensorminthreshold+Inde*interval if sensorvalue<=maxs: status="belowthreshold" logger.info('below Minthreshold') value=P[Inde] # do relevant stuff CheckActivateNotify(element,waitingtime,value,mailtype,sensor,sensorvalue) Inde=1 for I in range(Inde, maxstepnumber): mins=sensorminthreshold+(I-1)*interval maxs=sensorminthreshold+I*interval if mins<sensorvalue<=maxs: value=P[I] logger.info('inside Range') # do relevant stuff CheckActivateNotify(element,waitingtime,value,mailtype,sensor,sensorvalue) Inde=maxstepnumber mins=sensorminthreshold+(Inde-1)*interval if mins<sensorvalue: print "INDE:",Inde value=P[Inde] logger.info('beyond Range') # do relevant stuff CheckActivateNotify(element,waitingtime,value,mailtype,sensor,sensorvalue) # END MAIN ALGORITHM else: # to be added case of inverse sensor condition, where the sensorminthreshold is higher than the sensormaxthreshold print "Reverse Algorithm , element: " , element logger.info("Reverse Algorithm , element: %s " , element) Inde=0 maxs=sensorminthreshold+Inde*interval if sensorvalue>=maxs: status="belowthreshold" logger.info('Above MAXthreshold') value=P[Inde] # do relevant stuff CheckActivateNotify(element,waitingtime,value,mailtype,sensor,sensorvalue) Inde=Inde+1 for I in range(Inde, maxstepnumber): mins=sensorminthreshold+(I-1)*interval maxs=sensorminthreshold+I*interval if mins>sensorvalue>=maxs: value=P[I] # do relevant stuff CheckActivateNotify(element,waitingtime,value,mailtype,sensor,sensorvalue) Inde=maxstepnumber mins=sensorminthreshold+(Inde-1)*interval if mins>sensorvalue: print "INDE:",Inde value=P[Inde] # do relevant stuff CheckActivateNotify(element,waitingtime,value,mailtype,sensor,sensorvalue) # END MAIN ALGORITHM - Reverse else: logger.info('No valid calculation operation on the stored sensor data') elif workmode=="Emergency Activation": print "Emergency Activation" elif workmode=="Alert Only": print "Alert Only" # implment Critical alert message in case the sensor value is one interval more than Max_threshold isok,sensorvalue=sensorreading(sensor,averageminutes,mathoperation) # operation of sensor readings for a number of sample if isok: if sensorminthreshold<=sensormaxthreshold: if sensorvalue>sensormaxthreshold+interval: logger.info('sensor %s exceeding limits', sensor) textmessage="CRITICAL: "+ sensor + " reading " + str(sensorvalue) + " exceeding threshold limits, need to check the " + element print textmessage #send alert mail notification alertcounter=statusdataDBmod.read_status_data(AUTO_data,element,"alertcounter") if alertcounter<2: emailmod.sendallmail("alert", textmessage) logger.error(textmessage) statusdataDBmod.write_status_data(AUTO_data,element,"alertcounter",alertcounter+1) else: if sensorvalue<sensormaxthreshold+interval: logger.info('sensor %s exceeding limits', sensor) textmessage="CRITICAL: "+ sensor + " reading " + str(sensorvalue) + " exceeding threshold limits, need to check the " + element print textmessage #send alert mail notification alertcounter=statusdataDBmod.read_status_data(AUTO_data,element,"alertcounter") if alertcounter<2: emailmod.sendallmail("alert", textmessage) logger.error(textmessage) statusdataDBmod.write_status_data(AUTO_data,element,"alertcounter",alertcounter+1) return
def startpump(target, activationseconds, MinAveragetemp, MaxAverageHumid): logger.info('WateringPlan Startpump evaluation: %s', target) #workmode=autowateringmod.checkworkmode(target) #if workmode=="Full Auto": if target in autowateringmod.allowwateringplan: if not autowateringmod.allowwateringplan[target]: logger.info( 'WateringPlan: %s pump activation blocked by automation', target) pumpit = False return False duration = hardwaremod.toint(activationseconds, 0) print(target, " ", duration, " ", datetime.now()) # evaluate parameters #MinAverageLight=500 not used now MinutesOfAverage = 120 #minutes in which the average data is calculated from sensor sampling print("waterpump check") logger.info('execute water pump check %s', datetime.now().strftime("%Y-%m-%d %H:%M:%S")) # then check the temperature and Humidity print("Check Humidity and Temperature") MinAveragetempnum = hardwaremod.tonumber(MinAveragetemp, "NA") MaxAverageHumidnum = hardwaremod.tonumber(MaxAverageHumid, "NA") # all the below conditions should be verified to start the PUMP pumpit = True hsensornamelist = hardwaremod.getsensornamebymeasure( hardwaremod.MEASURELIST[1]) if hsensornamelist: sensordata = [] hsensorname = hsensornamelist[0] # get first found sensor in the list sensordbmod.getsensordbdata(hsensorname, sensordata) starttimecalc = datetime.now() - timedelta( minutes=int(MinutesOfAverage)) isok, quantitylist = sensordbmod.EvaluateDataPeriod( sensordata, starttimecalc, datetime.now()) humquantity = quantitylist["average"] logger.info( 'Waterpump Check parameter if humquantity=%s < MaxAverageHumid=%s ', str(humquantity), str(MaxAverageHumid)) print('Waterpump Check parameter if humquantity=', humquantity, ' < MaxAverageHumid=', MaxAverageHumid) if (MaxAverageHumidnum != "NA"): if (humquantity < MaxAverageHumidnum): logger.info( 'Humidity check PASSED, humquantity=%s < MaxAverageHumid=%s ', str(humquantity), str(MaxAverageHumid)) else: logger.info('Humidity check FAILED') print('Humidity check FAILED') pumpit = False tsensornamelist = hardwaremod.getsensornamebymeasure( hardwaremod.MEASURELIST[0]) if tsensornamelist: sensordata = [] tsensorname = tsensornamelist[0] # get first found sensor in the list sensordbmod.getsensordbdata(tsensorname, sensordata) starttimecalc = datetime.now() - timedelta( minutes=int(MinutesOfAverage)) isok, quantitylist = sensordbmod.EvaluateDataPeriod( sensordata, starttimecalc, datetime.now()) tempquantity = quantitylist["average"] logger.info( 'Waterpump Check parameter if tempquantity=%s > MinAveragetemp=%s ', str(tempquantity), str(MinAveragetemp)) print('Waterpump Check parameter if tempquantity=', tempquantity, ' > MinAveragetemp=', MinAveragetemp) if (MinAveragetempnum != "NA"): if (tempquantity > MinAveragetempnum): logger.info( 'Temperature check PASSED, tempquantity=%s > MinAveragetemp=%s ', str(tempquantity), str(MinAveragetemp)) else: logger.info('Temperature check FAILED') print('Temperature check FAILED') pumpit = False # weather Forecast sensorname = weatherAPImod.DefaultCounterName() sensorlist = sensordbmod.gettablelist() if sensorname in sensorlist: ActiveActuatorList = weatherAPImod.ActiveActuatorList() if target in ActiveActuatorList: sensordata = [] samplesnumber = 1 sensordbmod.getsensordbdatasamplesN(sensorname, sensordata, samplesnumber) MaxPastMinutes = 1200 starttimecalc = datetime.now() - timedelta(minutes=MaxPastMinutes) isok, quantitylist = sensordbmod.EvaluateDataPeriod( sensordata, starttimecalc, datetime.now()) if isok: RainMultipier = quantitylist["average"] logger.info('Waterpump weather multiplier =%s ', str(RainMultipier)) else: logger.warning( 'Waterpump weather multiplier NOT found within 20 Hours apply 100 ' ) RainMultipier = 100 duration = int(duration * RainMultipier / 100) else: logger.warning('Weather Sensor not found, no multpilier applied ') if pumpit: # activation of the doser before the pump doseron = autofertilizermod.checkactivate(target, duration) # watering #hardwaremod.makepulse(target,duration) activateandregister(target, duration) # salva su database #logger.info('Switch Pump %s ON, optional time for sec = %s', target, duration) #print 'Pump ON, optional time for sec =', duration #actuatordbmod.insertdataintable(target,duration) return True
def mastercallback(fromscheduledtime=False): print("master callback") if fromscheduledtime: # check if the time this function is called is the same as the expected time it should be called (solar/legal time might mess with it) logger.info( 'Master scheduler call at scheduled local time, expected time %s', MASTERSCHEDULERTIME) thedateloc = datetime.now() timelist = hardwaremod.separatetimestringint(MASTERSCHEDULERTIME) masterschedtime = thedateloc.replace(hour=timelist[0], minute=timelist[1], second=timelist[2]) secondsdifference = abs((thedateloc - masterschedtime).total_seconds()) logger.info( 'Master scheduler, difference between expected time and local time %d', secondsdifference) if secondsdifference > 300: # more than 5 minutes logger.warning( 'Master scheduler, difference between expected time and local time greater than 5 minutes, RESET MASTER SCHEDULER' ) resetmastercallback() return # clean old data of the database (pastdays) logger.info('Remove data exceeding one year') pastdays = hardwaremod.toint(STOREPASTDAYS, 364) logger.info('Sensor Remove data exceeding one year') sensordbmod.RemoveSensorDataPeriod(pastdays) logger.info('Actuator Remove data exceeding one year') actuatordbmod.RemoveActuatorDataPeriod(pastdays) logger.info('Photo Remove data exceeding one year') hardwaremod.removephotodataperiod(pastdays) else: logger.info('Master scheduler call not coming from scheduler') logger.info('Scheduling main activities') # remove all jobs except masterscheduler #for job in SchedulerMod.sched.get_jobs(): # if job.name != "master": # try: # job.remove() # except: # logger.error('Not able to remove Job %s', job.name) # set the individual callback of the day logger.info('Start other scheduler activities - heartbeat') # info file dedicate call-back --------------------------------------------- (heartbeat) #this callback is used only for system status periodic check calltype = "periodic" global HEARTBEATINTERVAL interval = HEARTBEATINTERVAL timelist = [0, interval, 900] # 20 indicates to start after 15 minutes callback = "heartbeat" argument = [] setschedulercallback(calltype, timelist, argument, callback, callback) logger.info('Start other scheduler activities - sensor') # info file dedicate call-back --------------------------------------------- (sensor) hwnamelist = hardwaremod.searchdatalist(hardwaremod.HW_INFO_IOTYPE, "input", hardwaremod.HW_INFO_NAME) # GPIO input can be considered at all the aspects a binary input, therefor their stat collection are possible as any other input # the input should be time periodic and time should be more than one minute callback = "sensor" timeshift = 300 # after wifi activation because of possible clock adjustment shiftstep = 7 #seconds # IMPORTANT # the shiftstep is necessary to avoid thread collision which brings to sqlite3 db failure "database is locked" # this number is giving a limit to the sensor reading that should be higher than 1min for hwname in hwnamelist: calltype = hardwaremod.searchdata(hardwaremod.HW_INFO_NAME, hwname, hardwaremod.HW_FUNC_SCHEDTYPE) if calltype == "periodic": #check the input to be periodic timelist = hardwaremod.gettimedata(hwname) timelist[ 2] = timeshift # avoid all the sensor thread to be called in the same time argument = [] argument.append(hwname) setschedulercallback(calltype, timelist, argument, callback, hwname) timeshift = timeshift + shiftstep else: logger.warning( 'The scheduler for the input %s is not set to PERIODIC, no log record of this input will be taken', hwname) logger.info('Start other scheduler activities - photo') #<------> # info file dedicate quinto call-back ----------------------------------(takephoto) usedfor = "photocontrol" callback = "photo" hwnamelist = hardwaremod.searchdatalist(hardwaremod.HW_FUNC_USEDFOR, usedfor, hardwaremod.HW_INFO_NAME) for hwname in hwnamelist: calltype = hardwaremod.searchdata(hardwaremod.HW_INFO_NAME, hwname, hardwaremod.HW_FUNC_SCHEDTYPE) timelist = hardwaremod.gettimedata(hwname) argument = [] argument.append(hwname) setschedulercallback(calltype, timelist, argument, callback, hwname) logger.info('Start other scheduler activities - mail') # info ne file dedicate quarto call-back ---------------------------------------(sendmail) usedfor = "mailcontrol" callback = "mail" hwnamelist = hardwaremod.searchdatalist(hardwaremod.HW_FUNC_USEDFOR, usedfor, hardwaremod.HW_INFO_NAME) for hwname in hwnamelist: calltype = hardwaremod.searchdata(hardwaremod.HW_INFO_NAME, hwname, hardwaremod.HW_FUNC_SCHEDTYPE) timelist = hardwaremod.gettimedata(hwname) argument = [] argument.append(hwname) setschedulercallback(calltype, timelist, argument, callback, hwname) # info ne file dedicate quinto call-back ---------------------------------------(lightcheck) # empty #<----> logger.info('Start other scheduler activities - pump') # info file dedicate call-back ------------------------------------------------ (waterpump) callback = "waterpump" #water schedule table paramlist = wateringdbmod.getparamlist() # name of the months ordered elementlist = wateringdbmod.getelementlist( ) # pump ordered (based on "watercontrol" field) table = wateringdbmod.gettable( 1 ) # table, each row is a pump, each column is a month, value is watering time multiplieer table1 = wateringdbmod.gettable( 0 ) # table, each row is a pump, each column is a month, value is watering scheme table2 = wateringdbmod.gettable( 2 ) # table, each row is a pump, each column is a month, value is time delay #print paramlist #print elementlistly #print table paramlistdrop = advancedmod.getparamlist() # day of the week elementlistdrop = advancedmod.getelementlist() # drops ordered tabledrop = advancedmod.gettable( ) # table, each row is a schema number (drop number), each column is a weekday for pumpnumber in range(len(elementlist)): #print "number =",pumpnumber pumpname = elementlist[pumpnumber] todaydate = date.today() # Monday is 0 and Sunday is 6 weekday = todaydate.weekday() month = todaydate.month try: waterschemanumber = table1[pumpnumber][month - 1] waterdropnumber = hardwaremod.toint(table[pumpnumber][month - 1], 0) watertimedelaysec = hardwaremod.toint( table2[pumpnumber][month - 1], 0) except IndexError: print("EXCEPTION: index out of range") waterdropnumber = 0 watertimedelaysec = 0 if waterdropnumber > 0: #print " month " , month, " drop " , waterdropnumber calltype = hardwaremod.searchdata(hardwaremod.HW_INFO_NAME, pumpname, hardwaremod.HW_FUNC_SCHEDTYPE) for todayevent in tabledrop[waterschemanumber - 1][weekday]: timelist = hardwaremod.separatetimestringint(todayevent[0]) timelist[2] = timelist[2] + watertimedelaysec argument = [] argument.append(pumpname) durationinseconds = hardwaremod.toint(todayevent[1], 0) * waterdropnumber argument.append(durationinseconds) for i in range(2, len(todayevent)): argument.append(todayevent[i]) if durationinseconds > 0: #check if the duration in second is >0 setschedulercallback(calltype, timelist, argument, callback, pumpname) logger.info('Start other scheduler activities - doser') # info file dedicate call-back ------------------------------------------------ (pulsenutrient) callback = "doser" #fertilizer schedule table paramlist = fertilizerdbmod.getparamlist() # name of the months ordered elementlist = fertilizerdbmod.getelementlist( ) # element with "fertilizercontrol field" ordered table = fertilizerdbmod.gettable( 1 ) # table, each row is a doser, each column is a month, value is number of times in a month table1 = fertilizerdbmod.gettable( 0 ) # table, each row is a doser, each column is a month, value is pulse seconds for dosernumber in range(len(elementlist)): #print "number =",dosernumber dosername = elementlist[dosernumber] calltype = hardwaremod.searchdata(hardwaremod.HW_INFO_NAME, dosername, hardwaremod.HW_FUNC_SCHEDTYPE) todaydate = date.today() # Monday is 0 and Sunday is 6 year = todaydate.year month = todaydate.month day = todaydate.day fertilizerpulsenumber = hardwaremod.toint( table[dosernumber][month - 1], 0) fertilizerpulsesecond = hardwaremod.toint( table1[dosernumber][month - 1], 0) if (fertilizerpulsenumber > 0) and (fertilizerpulsesecond > 0): themonthdays = 30 #approximate number of days in a month dayinterval = old_div(themonthdays, fertilizerpulsenumber) halfinterval = old_div((dayinterval + 1), 2) print("day=", day, " dayinterval=", dayinterval, " half=", halfinterval) if ((day + int(halfinterval)) % int(dayinterval)) == 0: #timelist=hardwaremod.gettimedata("06:00:00") timelist = autofertilizermod.timelist(dosername) argument = [] argument.append(dosername) argument.append(fertilizerpulsesecond) if (fertilizerpulsesecond ) > 0: #check if the duration in second is >0 setschedulercallback(calltype, timelist, argument, callback, dosername) logger.info('Start other scheduler activities - finish') return True
def autowateringexecute(refsensor,element): global AUTO_data sensor=autowateringdbmod.searchdata("element",element,"sensor") # check the sensor if refsensor==sensor: print "auto watering check -----------------------------------------> ", element logger.info('auto watering check --------------------------> %s', element) # check the watering mode modelist=["None", "Full Auto" , "Emergency Activation" , "Alert Only"] workmode=checkworkmode(element) if not(sensor in sensordbmod.gettablelist()): print "Sensor does not exist " ,sensor , ", element: " , element logger.error("Sensor does not exist %s , element: %s " ,sensor, element) return "sensor not Exist" maxthreshold=hardwaremod.tonumber(autowateringdbmod.searchdata("element",element,"threshold")[1],0) minthreshold=hardwaremod.tonumber(autowateringdbmod.searchdata("element",element,"threshold")[0],maxthreshold) # exit condition in case of data inconsistency if minthreshold>=maxthreshold: print "Data inconsistency , element: " , element logger.error("Data inconsistency , element: %s " , element) return "data inconsistency" now = datetime.now() nowtime = now.time() starttimeh=hardwaremod.toint(autowateringdbmod.searchdata("element",element,"allowedperiod")[0].split(":")[0],0) starttimem=hardwaremod.toint(autowateringdbmod.searchdata("element",element,"allowedperiod")[0].split(":")[1],0) endtimeh=hardwaremod.toint(autowateringdbmod.searchdata("element",element,"allowedperiod")[1].split(":")[0],1) endtimem=hardwaremod.toint(autowateringdbmod.searchdata("element",element,"allowedperiod")[1].split(":")[1],0) starttime=time(starttimeh,starttimem) endtime=time(endtimeh,endtimem) duration=1000*hardwaremod.toint(autowateringdbmod.searchdata("element",element,"wtstepsec"),0) maxstepnumber=hardwaremod.toint(autowateringdbmod.searchdata("element",element,"maxstepnumber"),0) maxdays=hardwaremod.toint(autowateringdbmod.searchdata("element",element,"maxdaysbetweencycles"),0) waitingtime=hardwaremod.toint(autowateringdbmod.searchdata("element",element,"pausebetweenwtstepsmin"),0) mailtype=autowateringdbmod.searchdata("element",element,"mailalerttype") minaccepted=hardwaremod.tonumber(autowateringdbmod.searchdata("element",element,"sensorminacceptedvalue"),0.1) # ------------------------ Workmode split if workmode=="Full Auto": # block the wateringplan activation as by definition of "Full Auto" allowwateringplan[element]=False # check if inside the allowed time period print "full Auto Mode" logger.info('full auto mode --> %s', element) timeok=isNowInTimePeriod(starttime, endtime, nowtime) print "inside allowed time ", timeok , " starttime ", starttime , " endtime ", endtime logger.info('full auto mode') if timeok: logger.info('inside allowed time') belowthr,valid=checkminthreshold(sensor,minthreshold,minaccepted) if valid: if belowthr: status="lowthreshold" logger.info('below threshold') # wait to seek a more stable reading of hygrometer # check if time between watering events is larger that the waiting time (minutes) lastwateringtime=statusdataDBmod.read_status_data(AUTO_data,element,"lastwateringtime") print ' Previous watering: ' , lastwateringtime , ' Now: ', datetime.now() timedifference=sensordbmod.timediffinminutes(lastwateringtime,datetime.now()) print 'Time interval between watering steps', timedifference ,'. threshold', waitingtime logger.info('Time interval between watering steps %d threshold %d', timedifference,waitingtime) if timedifference>waitingtime: print " Sufficient waiting time" logger.info('Sufficient waiting time') # activate watering in case the maxstepnumber is not exceeded watercounter=statusdataDBmod.read_status_data(AUTO_data,element,"watercounter") if maxstepnumber>watercounter: #activate pump activatewater(element, duration) # invia mail, considered as info, not as alert if mailtype!="warningonly": textmessage="INFO: " + sensor + " value below the minimum threshold " + str(minthreshold) + ", activating the watering :" + element emailmod.sendallmail("alert", textmessage) statusdataDBmod.write_status_data(AUTO_data,element,"watercounter",watercounter+1) statusdataDBmod.write_status_data(AUTO_data,element,"lastwateringtime",datetime.now()) else: # critical, sensor below minimum after all watering activations are done logger.info('Number of watering time per cycle has been exceeeded') # read hystory data and calculate the slope timelist=hardwaremod.gettimedata(sensor) cyclestartdate=statusdataDBmod.read_status_data(AUTO_data,element,"cyclestartdate") lastwateringtime=statusdataDBmod.read_status_data(AUTO_data,element,"lastwateringtime") startdate=cyclestartdate - timedelta(minutes=timelist[1]) enddate=lastwateringtime + timedelta(minutes=waitingtime) isslopeok=checkinclination(sensor,startdate,enddate) # still to decide if use the enddate if isslopeok: # invia mail if couner alert is lower than 1 alertcounter=statusdataDBmod.read_status_data(AUTO_data,element,"alertcounter") if alertcounter<1: textmessage="WARNING: Please consider to increase the amount of water per cycle, the "+ sensor + " value below the MINIMUM threshold " + str(minthreshold) + " still after activating the watering :" + element + " for " + str(maxstepnumber) + " times. System will automatically reset the watering cycle to allow more water" print textmessage #send alert mail notification emailmod.sendallmail("alert", textmessage) logger.error(textmessage) statusdataDBmod.write_status_data(AUTO_data,element,"alertcounter",alertcounter+1) # reset watering cycle status="done" statusdataDBmod.write_status_data(AUTO_data,element,"watercounter",0) statusdataDBmod.write_status_data(AUTO_data,element,"checkcounter",-1) statusdataDBmod.write_status_data(AUTO_data,element,"alertcounter",0) statusdataDBmod.write_status_data(AUTO_data,element,"cyclestartdate",datetime.now()) else: # slope not OK, probable hardware problem alertcounter=statusdataDBmod.read_status_data(AUTO_data,element,"alertcounter") if alertcounter<3: textmessage="CRITICAL: Possible hardware problem, "+ sensor + " value below the MINIMUM threshold " + str(minthreshold) + " still after activating the watering :" + element + " for " + str(maxstepnumber) + " times" print textmessage #send alert mail notification emailmod.sendallmail("alert", textmessage) logger.error(textmessage) statusdataDBmod.write_status_data(AUTO_data,element,"alertcounter",alertcounter+1) # update the status checkcounter=statusdataDBmod.read_status_data(AUTO_data,element,"checkcounter") statusdataDBmod.write_status_data(AUTO_data,element,"cyclestatus",status) statusdataDBmod.write_status_data(AUTO_data,element,"checkcounter",checkcounter+1) # RAMPUP case above threshold but below maxthreshold elif sensorreading(sensor)<maxthreshold: # intermediate state where the sensor is above the minthreshold but lower than the max threshold # check the status of the automatic cycle cyclestatus=statusdataDBmod.read_status_data(AUTO_data,element,"cyclestatus") if cyclestatus!="done": status="rampup" # wait to seek a more stable reading of hygrometer # check if time between watering events is larger that the waiting time (minutes) lastwateringtime=statusdataDBmod.read_status_data(AUTO_data,element,"lastwateringtime") if sensordbmod.timediffinminutes(lastwateringtime,datetime.now())>waitingtime: watercounter=statusdataDBmod.read_status_data(AUTO_data,element,"watercounter") if maxstepnumber>watercounter: #activate pump activatewater(element, duration) # invia mail, considered as info, not as alert if mailtype!="warningonly": textmessage="INFO: " + sensor + " value below the Maximum threshold " + str(maxthreshold) + ", activating the watering :" + element emailmod.sendallmail("alert", textmessage) statusdataDBmod.write_status_data(AUTO_data,element,"watercounter",watercounter+1) statusdataDBmod.write_status_data(AUTO_data,element,"lastwateringtime",datetime.now()) else: # give up to reache the maximum threshold, proceed as done, send alert logger.info('Number of watering time per cycle has been exceeeded') # invia mail if couner alert is lower than 1 -------------- # only if the info is activated if mailtype!="warningonly": alertcounter=statusdataDBmod.read_status_data(AUTO_data,element,"alertcounter") if alertcounter<2: textmessage="INFO "+ sensor + " value below the Maximum threshold " + str(maxthreshold) + " still after activating the watering :" + element + " for " + str(maxstepnumber) + " times" print textmessage #send alert mail notification emailmod.sendallmail("alert", textmessage) logger.error(textmessage) statusdataDBmod.write_status_data(AUTO_data,element,"alertcounter",alertcounter+1) # reset watering cycle status="done" statusdataDBmod.write_status_data(AUTO_data,element,"watercounter",0) statusdataDBmod.write_status_data(AUTO_data,element,"checkcounter",-1) statusdataDBmod.write_status_data(AUTO_data,element,"alertcounter",0) statusdataDBmod.write_status_data(AUTO_data,element,"cyclestartdate",datetime.now()) # update the status checkcounter=statusdataDBmod.read_status_data(AUTO_data,element,"checkcounter") statusdataDBmod.write_status_data(AUTO_data,element,"cyclestatus",status) statusdataDBmod.write_status_data(AUTO_data,element,"checkcounter",checkcounter+1) else: # update the status, reset cycle statusdataDBmod.write_status_data(AUTO_data,element,"cyclestatus","done") statusdataDBmod.write_status_data(AUTO_data,element,"checkcounter",0) statusdataDBmod.write_status_data(AUTO_data,element,"watercounter",0) statusdataDBmod.write_status_data(AUTO_data,element,"alertcounter",0) elif workmode=="Emergency Activation": # check if inside the allow time period logger.info('Emergency Mode') timeok=isNowInTimePeriod(starttime, endtime, nowtime) print "inside allowed time ", timeok , " starttime ", starttime , " endtime ", endtime if timeok: belowthr,valid=checkminthreshold(sensor,minthreshold,minaccepted) if valid: if belowthr: # wait to seek a more stable reading of hygrometer # check if time between watering events is larger that the waiting time (minutes) lastwateringtime=statusdataDBmod.read_status_data(AUTO_data,element,"lastwateringtime") if sensordbmod.timediffinminutes(lastwateringtime,datetime.now())>waitingtime: # activate watering in case the maxstepnumber is not exceeded watercounter=statusdataDBmod.read_status_data(AUTO_data,element,"watercounter") if maxstepnumber>watercounter: #activate pump activatewater(element, duration) # invia mail, considered as info, not as alert if mailtype!="warningonly": textmessage="INFO: " + sensor + " value below the minimum threshold " + str(minthreshold) + ", activating the watering :" + element emailmod.sendallmail("alert", textmessage) statusdataDBmod.write_status_data(AUTO_data,element,"watercounter",watercounter+1) statusdataDBmod.write_status_data(AUTO_data,element,"lastwateringtime",datetime.now()) else: logger.info('Number of watering time per cycle has been exceeeded') # read hystory data and calculate the slope timelist=hardwaremod.gettimedata(sensor) cyclestartdate=statusdataDBmod.read_status_data(AUTO_data,element,"cyclestartdate") lastwateringtime=statusdataDBmod.read_status_data(AUTO_data,element,"lastwateringtime") startdate=cyclestartdate - timedelta(minutes=timelist[1]) enddate=lastwateringtime + timedelta(minutes=waitingtime) isslopeok=checkinclination(sensor,startdate,enddate) if isslopeok: # invia mail if couner alert is lower than 1 alertcounter=statusdataDBmod.read_status_data(AUTO_data,element,"alertcounter") if alertcounter<1: textmessage="WARNING: Please consider to increase the amount of water per cycle, the "+ sensor + " value below the MINIMUM threshold " + str(minthreshold) + " still after activating the watering :" + element + " for " + str(maxstepnumber) + " times. System will automatically reset the watering cycle to allow more water" print textmessage #send alert mail notification alertcounter emailmod.sendallmail("alert", textmessage) logger.error(textmessage) statusdataDBmod.write_status_data(AUTO_data,element,"alertcounter",alertcounter+1) # reset watering cycle status="done" statusdataDBmod.write_status_data(AUTO_data,element,"watercounter",0) statusdataDBmod.write_status_data(AUTO_data,element,"checkcounter",-1) statusdataDBmod.write_status_data(AUTO_data,element,"alertcounter",0) statusdataDBmod.write_status_data(AUTO_data,element,"cyclestartdate",datetime.now()) else: # slope not OK, probable hardware problem alertcounter=statusdataDBmod.read_status_data(AUTO_data,element,"alertcounter") if alertcounter<3: textmessage="CRITICAL: Possible hardware problem, "+ sensor + " value below the MINIMUM threshold " + str(minthreshold) + " still after activating the watering :" + element + " for " + str(maxstepnumber) + " times" print textmessage #send alert mail notification emailmod.sendallmail("alert", textmessage) logger.error(textmessage) statusdataDBmod.write_status_data(AUTO_data,element,"alertcounter",alertcounter+1) # update the status checkcounter=statusdataDBmod.read_status_data(AUTO_data,element,"checkcounter") statusdataDBmod.write_status_data(AUTO_data,element,"cyclestatus","lowthreshold") statusdataDBmod.write_status_data(AUTO_data,element,"checkcounter",checkcounter+1) else: # update the status statusdataDBmod.write_status_data(AUTO_data,element,"cyclestatus","done") statusdataDBmod.write_status_data(AUTO_data,element,"checkcounter",0) statusdataDBmod.write_status_data(AUTO_data,element,"watercounter",0) statusdataDBmod.write_status_data(AUTO_data,element,"alertcounter",0) elif workmode=="under MIN over MAX": logger.info('under MIN over MAX') # normally watering plan is allowed unless over MAX threshold allowwateringplan[element]=True # check if inside the allow time period timeok=isNowInTimePeriod(starttime, endtime, nowtime) print "inside allowed time ", timeok , " starttime ", starttime , " endtime ", endtime if timeok: logger.info('Insede operative time') belowthr,valid=checkminthreshold(sensor,minthreshold,minaccepted) if valid: logger.info('valid sensor reading') if belowthr: logger.info('sensor reading below threshold') # wait to seek a more stable reading of hygrometer # check if time between watering events is larger that the waiting time (minutes) lastwateringtime=statusdataDBmod.read_status_data(AUTO_data,element,"lastwateringtime") if sensordbmod.timediffinminutes(lastwateringtime,datetime.now())>waitingtime: # activate watering in case the maxstepnumber is not exceeded watercounter=statusdataDBmod.read_status_data(AUTO_data,element,"watercounter") if maxstepnumber>watercounter: logger.info('water Count not exceeded') #activate pump activatewater(element, duration) # invia mail, considered as info, not as alert if mailtype!="warningonly": textmessage="INFO: " + sensor + " value below the minimum threshold " + str(minthreshold) + ", activating the watering :" + element emailmod.sendallmail("alert", textmessage) statusdataDBmod.write_status_data(AUTO_data,element,"watercounter",watercounter+1) statusdataDBmod.write_status_data(AUTO_data,element,"lastwateringtime",datetime.now()) else: logger.info('Number of watering time per cycle has been exceeeded') # read hystory data and calculate the slope timelist=hardwaremod.gettimedata(sensor) cyclestartdate=statusdataDBmod.read_status_data(AUTO_data,element,"cyclestartdate") lastwateringtime=statusdataDBmod.read_status_data(AUTO_data,element,"lastwateringtime") startdate=cyclestartdate - timedelta(minutes=timelist[1]) enddate=lastwateringtime + timedelta(minutes=waitingtime) isslopeok=checkinclination(sensor,startdate,enddate) if isslopeok: # invia mail if couner alert is lower than 1 alertcounter=statusdataDBmod.read_status_data(AUTO_data,element,"alertcounter") if alertcounter<1: textmessage="WARNING: Please consider to increase the amount of water per cycle, the "+ sensor + " value below the MINIMUM threshold " + str(minthreshold) + " still after activating the watering :" + element + " for " + str(maxstepnumber) + " times. System will automatically reset the watering cycle to allow more water" print textmessage #send alert mail notification emailmod.sendallmail("alert", textmessage) logger.error(textmessage) statusdataDBmod.write_status_data(AUTO_data,element,"alertcounter",alertcounter+1) # reset watering cycle status="done" statusdataDBmod.write_status_data(AUTO_data,element,"watercounter",0) statusdataDBmod.write_status_data(AUTO_data,element,"checkcounter",-1) statusdataDBmod.write_status_data(AUTO_data,element,"alertcounter",0) statusdataDBmod.write_status_data(AUTO_data,element,"cyclestartdate",datetime.now()) else: # slope not OK, probable hardware problem alertcounter=statusdataDBmod.read_status_data(AUTO_data,element,"alertcounter") if alertcounter<3: textmessage="CRITICAL: Possible hardware problem, "+ sensor + " value below the MINIMUM threshold " + str(minthreshold) + " still after activating the watering :" + element + " for " + str(maxstepnumber) + " times" print textmessage #send alert mail notification emailmod.sendallmail("alert", textmessage) logger.error(textmessage) statusdataDBmod.write_status_data(AUTO_data,element,"alertcounter",alertcounter+1) # update the status checkcounter=statusdataDBmod.read_status_data(AUTO_data,element,"checkcounter") statusdataDBmod.write_status_data(AUTO_data,element,"cyclestatus","lowthreshold") statusdataDBmod.write_status_data(AUTO_data,element,"checkcounter",checkcounter+1) else: # above minimum threshold logger.info('sensor reading above min threshold') # update the status statusdataDBmod.write_status_data(AUTO_data,element,"cyclestatus","done") statusdataDBmod.write_status_data(AUTO_data,element,"checkcounter",0) statusdataDBmod.write_status_data(AUTO_data,element,"watercounter",0) statusdataDBmod.write_status_data(AUTO_data,element,"alertcounter",0) if sensorreading(sensor)>maxthreshold: logger.info('sensor reading above MAX threshold, deactivate scheduled irrigation') # do not activate the irrigation scheduled in the time plan allowwateringplan[element]=False elif workmode=="Alert Only": belowthr,valid=checkminthreshold(sensor,minthreshold,minaccepted) if valid: if belowthr: # invia mail if couter alert is lower than alertcounter=statusdataDBmod.read_status_data(AUTO_data,element,"alertcounter") if alertcounter<2: textmessage="WARNING "+ sensor + " value below the minimum threshold " + str(minthreshold) + " watering system: " + element print textmessage #send alert mail notification emailmod.sendallmail("alert", textmessage) logger.error(textmessage) statusdataDBmod.write_status_data(AUTO_data,element,"alertcounter",alertcounter+1) # update the status checkcounter=statusdataDBmod.read_status_data(AUTO_data,element,"checkcounter") statusdataDBmod.write_status_data(AUTO_data,element,"cyclestatus","lowthreshold") statusdataDBmod.write_status_data(AUTO_data,element,"checkcounter",checkcounter+1) else: # update the status statusdataDBmod.write_status_data(AUTO_data,element,"cyclestatus","done") statusdataDBmod.write_status_data(AUTO_data,element,"checkcounter",0) statusdataDBmod.write_status_data(AUTO_data,element,"watercounter",0) statusdataDBmod.write_status_data(AUTO_data,element,"alertcounter",0) else: # None case print "No Action required, workmode set to None, element: " , element logger.info("No Action required, workmode set to None, element: %s " , element) cyclestatus=statusdataDBmod.read_status_data(AUTO_data,element,"cyclestatus") if cyclestatus=="lowthreshold": checkcounter=statusdataDBmod.read_status_data(AUTO_data,element,"checkcounter") if checkcounter==1: statusdataDBmod.write_status_data(AUTO_data,element,"cyclestartdate",datetime.now()) # implment alert message for the cycle exceeding days, and reset the cycle if workmode!="None": cyclestartdate=statusdataDBmod.read_status_data(AUTO_data,element,"cyclestartdate") timedeltadays=sensordbmod.timediffdays(datetime.now(),cyclestartdate) if (timedeltadays > maxdays): #the upper limit is set in case of abrupt time change textmessage="WARNING "+ sensor + " watering cycle is taking too many days, watering system: " + element + ". Reset watering cycle" print textmessage # in case of full Auto, activate pump for minimum pulse period if workmode=="Full Auto": if (timedeltadays < maxdays+2): #the upper limit is set in case of abrupt time change textmessage="WARNING "+ sensor + " watering cycle is taking too many days, watering system: " + element + ". Activate Min pulse + Reset watering cycle" activatewater(element, duration) #send alert mail notification if mailtype!="warningonly": emailmod.sendallmail("alert", textmessage) logger.error(textmessage) logger.error("Cycle started %s, Now is %s ", cyclestartdate.strftime("%Y-%m-%d %H:%M:%S"), datetime.now().strftime("%Y-%m-%d %H:%M:%S")) # reset cycle statusdataDBmod.write_status_data(AUTO_data,element,"cyclestatus","done") statusdataDBmod.write_status_data(AUTO_data,element,"checkcounter",0) statusdataDBmod.write_status_data(AUTO_data,element,"watercounter",0) statusdataDBmod.write_status_data(AUTO_data,element,"alertcounter",0) statusdataDBmod.write_status_data(AUTO_data,element,"cyclestartdate",datetime.now()) # implment Critical alert message in case the threshold is below the 0.5 of the minimum if workmode!="None": belowthr,valid=checkminthreshold(sensor,minthreshold*0.5,minaccepted) if valid: if belowthr: logger.info('sensor %s below half of the actual set threshold', sensor) textmessage="CRITICAL: Plant is dying, "+ sensor + " reading below half of the minimum threshold, need to check the " + element print textmessage #send alert mail notification alertcounter=statusdataDBmod.read_status_data(AUTO_data,element,"alertcounter") if alertcounter<5: emailmod.sendallmail("alert", textmessage) logger.error(textmessage) statusdataDBmod.write_status_data(AUTO_data,element,"alertcounter",alertcounter+1) else: logger.info('sensor %s below valid data', sensor) textmessage="WARNING: "+ sensor + " below valid data range, need to check sensor" print textmessage #send alert mail notification alertcounter=statusdataDBmod.read_status_data(AUTO_data,element,"alertcounter") if alertcounter<3: emailmod.sendallmail("alert", textmessage) logger.error(textmessage) statusdataDBmod.write_status_data(AUTO_data,element,"alertcounter",alertcounter+1) return
def mastercallback(): # clean old data of the database (pastdays) logger.info('Remove data in exceed of one year') pastdays=364 #sensordbmod.RemoveSensorDataPeriod(pastdays) logger.info('Sensor Remove data in exceed of one year') #actuatordbmod.RemoveActuatorDataPeriod(pastdays) logger.info('Actuator Remove data in exceed of one year') #hardwaremod.removephotodataperiod(364) logger.info('Photo Remove data in exceed of one year') logger.info('Start other scheduler activities') # remove all jobs except masterscheduler #for job in SchedulerMod.sched.get_jobs(): # if job.name != "master": # try: # job.remove() # except: # logger.error('Not able to remove Job %s', job.name) # set the individual callback of the day # info file dedicate call-back --------------------------------------------- (heartbeat) #this callback is used only for system status periodic check calltype="periodic" global HEARTBEATINTERVAL interval=HEARTBEATINTERVAL timelist=[0,interval,900] # 900 indicates to start after 15 minutes callback="heartbeat" argument=[] setschedulercallback(calltype,timelist,argument,callback,callback) logger.info('Start other scheduler activities - sensor') # info file dedicate call-back --------------------------------------------- (sensor) hwnamelist=sensordbmod.gettablelist() callback="sensor" timeshift=300 shiftstep=5 #seconds # IMPORTANT # the shiftstep is necessary to avoid thread collision which brings to sqlite3 db failure "database is locked" # this number is giving a limit to the sensor reading that should be higher than 1min for hwname in hwnamelist: calltype=hardwaremod.searchdata(hardwaremod.HW_INFO_NAME,hwname,hardwaremod.HW_FUNC_SCHEDTYPE) timelist=hardwaremod.gettimedata(hwname) timelist[2]=timeshift # avoid all the sensor thread to be called in the same time argument=[] argument.append(hwname) setschedulercallback(calltype,timelist,argument,callback,hwname) timeshift=timeshift+shiftstep logger.info('Start other scheduler activities - photo') #<------> # info file dedicate quinto call-back ----------------------------------(takephoto) usedfor="photocontrol" callback="photo" hwnamelist=hardwaremod.searchdatalist(hardwaremod.HW_FUNC_USEDFOR,usedfor,hardwaremod.HW_INFO_NAME) for hwname in hwnamelist: calltype=hardwaremod.searchdata(hardwaremod.HW_INFO_NAME,hwname,hardwaremod.HW_FUNC_SCHEDTYPE) timelist=hardwaremod.gettimedata(hwname) argument=[] argument.append(hwname) setschedulercallback(calltype,timelist,argument,callback,hwname) logger.info('Start other scheduler activities - mail') # info ne file dedicate quarto call-back ---------------------------------------(sendmail) usedfor="mailcontrol" callback="mail" hwnamelist=hardwaremod.searchdatalist(hardwaremod.HW_FUNC_USEDFOR,usedfor,hardwaremod.HW_INFO_NAME) for hwname in hwnamelist: calltype=hardwaremod.searchdata(hardwaremod.HW_INFO_NAME,hwname,hardwaremod.HW_FUNC_SCHEDTYPE) timelist=hardwaremod.gettimedata(hwname) argument=[] argument.append(hwname) setschedulercallback(calltype,timelist,argument,callback,hwname) # info ne file dedicate quinto call-back ---------------------------------------(lightcheck) # empty #<----> logger.info('Start other scheduler activities - pump') # info file dedicate call-back ------------------------------------------------ (waterpump) callback="waterpump" #water schedule table paramlist= wateringdbmod.getparamlist() # name of the months ordered elementlist= wateringdbmod.getelementlist() # pump ordered (based on "watercontrol" field) table=wateringdbmod.gettable(1)# table, each row is a pump, each column is a month, value is watering time multiplieer table1=wateringdbmod.gettable(0)# table, each row is a pump, each column is a month, value is watering scheme table2=wateringdbmod.gettable(2)# table, each row is a pump, each column is a month, value is time delay #print paramlist #print elementlistly #print table paramlistdrop= advancedmod.getparamlist() # day of the week elementlistdrop= advancedmod.getelementlist() # drops ordered tabledrop=advancedmod.gettable() # table, each row is a schema number (drop number), each column is a weekday for pumpnumber in range(len(elementlist)): #print "number =",pumpnumber pumpname=elementlist[pumpnumber] todaydate = date.today() # Monday is 0 and Sunday is 6 weekday = todaydate.weekday() month = todaydate.month try: waterschemanumber=table1[pumpnumber][month-1] waterdropnumber=hardwaremod.toint(table[pumpnumber][month-1],0) watertimedelaysec=hardwaremod.toint(table2[pumpnumber][month-1],0) except IndexError: print "EXCEPTION: index out of range" waterdropnumber=0 watertimedelaysec=0 if waterdropnumber>0: #print " month " , month, " drop " , waterdropnumber calltype=hardwaremod.searchdata(hardwaremod.HW_INFO_NAME,pumpname,hardwaremod.HW_FUNC_SCHEDTYPE) for todayevent in tabledrop[waterschemanumber-1][weekday]: timelist=hardwaremod.separatetimestringint(todayevent[0]) timelist[2]=timelist[2]+watertimedelaysec argument=[] argument.append(pumpname) durationinseconds=hardwaremod.toint(todayevent[1],0)*waterdropnumber argument.append(durationinseconds) for i in range(2,len(todayevent)): argument.append(todayevent[i]) if durationinseconds>0: #check if the duration in second is >0 setschedulercallback(calltype,timelist,argument,callback,pumpname) logger.info('Start other scheduler activities - doser') # info file dedicate call-back ------------------------------------------------ (pulsenutrient) callback="doser" #fertilizer schedule table paramlist= fertilizerdbmod.getparamlist() # name of the months ordered elementlist= fertilizerdbmod.getelementlist() # element with "fertilizercontrol field" ordered table=fertilizerdbmod.gettable(1)# table, each row is a doser, each column is a month, value is number of times in a month table1=fertilizerdbmod.gettable(0)# table, each row is a doser, each column is a month, value is pulse seconds for dosernumber in range(len(elementlist)): #print "number =",dosernumber dosername=elementlist[dosernumber] calltype=hardwaremod.searchdata(hardwaremod.HW_INFO_NAME,dosername,hardwaremod.HW_FUNC_SCHEDTYPE) todaydate = date.today() # Monday is 0 and Sunday is 6 year = todaydate.year month = todaydate.month day = todaydate.day fertilizerpulsenumber=hardwaremod.toint(table[dosernumber][month-1],0) fertilizerpulsesecond=hardwaremod.toint(table1[dosernumber][month-1],0) if (fertilizerpulsenumber>0) and (fertilizerpulsesecond>0): themonthdays=30 #approximate number of days in a month dayinterval=themonthdays/fertilizerpulsenumber halfinterval=(dayinterval+1)/2 print "day=" , day , " dayinterval=", dayinterval, " half=", halfinterval if ((day+int(halfinterval)) % int(dayinterval)) == 0: #timelist=hardwaremod.gettimedata("06:00:00") timelist=autofertilizermod.timelist(dosername) argument=[] argument.append(dosername) argument.append(fertilizerpulsesecond) if (fertilizerpulsesecond)>0: #check if the duration in second is >0 setschedulercallback(calltype,timelist,argument,callback,dosername) logger.info('Start other scheduler activities - finish') return True
def startpump(target,activationseconds,ThesholdOFFON,ThesholdONOFF): logger.info('WateringPlan Startpump evaluation: %s', target) #workmode=autowateringmod.checkworkmode(target) #if workmode=="Full Auto": if target in autowateringmod.allowwateringplan: if not autowateringmod.allowwateringplan[target]: logger.info('WateringPlan: %s pump activation blocked by automation', target) pumpit=False return False duration=hardwaremod.toint(activationseconds,0) print(target, " ",duration, " " , datetime.now()) print("waterpump check") logger.info('execute water pump check %s', datetime.now().strftime("%Y-%m-%d %H:%M:%S")) # evaluate parameters MinutesOfAverage=hardwaremod.toint(wateringplansensordbmod.getselduration(),120) #minutes in which the average data is calculated from sensor sampling tsensornamelist, hsensornamelist=wateringplansensordbmod.getactivesensor() valid1, passed1 = checksensorcondition(tsensornamelist,ThesholdOFFON, MinutesOfAverage, False) valid2, passed2 = checksensorcondition(hsensornamelist,ThesholdONOFF, MinutesOfAverage, True) # apply AND or OR condition condition=wateringplansensordbmod.getselcondition() # "AND" , "OR" pumpit=True if valid1 and valid2: if condition=="AND": pumpit=passed1 and passed2 elif condition=="OR": pumpit=passed1 or passed2 else: if valid1: pumpit=passed1 if valid2: pumpit=passed2 print('valid1= ' , valid1 , 'valid2= ' , valid2) print('passed1= ' , passed1 , 'passed2= ' , passed2) print('pumpit= ' , pumpit, 'condition= ' , condition) logger.info('Condition for activation =%s ', pumpit) # weather Forecast sensorname=weatherAPImod.DefaultCounterName() sensorlist=sensordbmod.gettablelist() if sensorname in sensorlist: ActiveActuatorList=weatherAPImod.ActiveActuatorList() if target in ActiveActuatorList: sensordata=[] samplesnumber=1 sensordbmod.getsensordbdatasamplesN(sensorname,sensordata,samplesnumber) MaxPastMinutes=1200 starttimecalc=datetime.now()-timedelta(minutes=MaxPastMinutes) isok , quantitylist=sensordbmod.EvaluateDataPeriod(sensordata,starttimecalc,datetime.now()) if isok: RainMultipier=quantitylist["average"] logger.info('Waterpump weather multiplier =%s ', str(RainMultipier)) else: logger.warning('Waterpump weather multiplier NOT found within 20 Hours apply 100 ') RainMultipier=100 duration=int(duration*RainMultipier/100) else: logger.warning('Weather Sensor not found, no multpilier applied ') if pumpit: # activation of the doser before the pump doseron=autofertilizermod.checkactivate(target,duration) # watering #hardwaremod.makepulse(target,duration) activateandregister(target,duration) # salva su database #logger.info('Switch Pump %s ON, optional time for sec = %s', target, duration) #print 'Pump ON, optional time for sec =', duration #actuatordbmod.insertdataintable(target,duration) return True
def automationexecute(refsensor, element): sensor = automationdbmod.searchdata("element", element, "sensor") # check the sensor if refsensor == sensor: logger.info('automation Pairing OK ---> Actuator: %s , Sensor: %s', element, sensor) # check the watering mode modelist = ["None", "Full Auto", "Emergency Activation", "Alert Only"] workmode = checkworkmode(element) if (workmode == "None"): # None case print "No Action required, workmode set to None, element: ", element logger.info( "No Action required, workmode set to None, element: %s ", element) return if (workmode == ""): logger.info("Not able to get the workmode: %s ", element) return logger.info('Automantion, Get all the parameters') sensormaxthreshold = hardwaremod.tonumber( automationdbmod.searchdata("element", element, "sensor_threshold")[1], 0) sensorminthreshold = hardwaremod.tonumber( automationdbmod.searchdata("element", element, "sensor_threshold")[0], sensormaxthreshold) actuatormaxthreshold = hardwaremod.tonumber( automationdbmod.searchdata("element", element, "actuator_threshold")[1], 0) actuatorminthreshold = hardwaremod.tonumber( automationdbmod.searchdata("element", element, "actuator_threshold")[0], actuatormaxthreshold) # evaluate variables for operational period check starttime = datetime.strptime( automationdbmod.searchdata("element", element, "allowedperiod")[0], '%H:%M').time() endtime = datetime.strptime( automationdbmod.searchdata("element", element, "allowedperiod")[1], '%H:%M').time() # get other parameters maxstepnumber = hardwaremod.toint( automationdbmod.searchdata("element", element, "stepnumber"), 1) waitingtime = hardwaremod.toint( automationdbmod.searchdata("element", element, "pausebetweenwtstepsmin"), 1) mailtype = automationdbmod.searchdata("element", element, "mailalerttype") averageminutes = hardwaremod.tonumber( automationdbmod.searchdata("element", element, "averagesample"), 1) mathoperation = automationdbmod.searchdata("element", element, "mathoperation") # check sensor timetrigger sensorcontrolcommand = hardwaremod.searchdata(hardwaremod.HW_INFO_NAME, refsensor, hardwaremod.HW_CTRL_CMD) logger.info('Sensor control command: %s , Sensor: %s', sensorcontrolcommand, sensor) if sensorcontrolcommand == "returnzero": logger.info('Modify parameter for the timetrigger') #adjust the parameters in the way the activation condition is always obtained sensormaxthreshold = 1 sensorminthreshold = -1 maxstepnumber = 1 averageminutes = 0 # Calculated Variables if maxstepnumber < 1: # not possible to proceed print "No Action required, maxstepnumber <1, element: ", element logger.info("No Action required, maxstepnumber <1, element: %s ", element) return interval = (sensormaxthreshold - sensorminthreshold) / maxstepnumber actuatorinterval = (actuatormaxthreshold - actuatorminthreshold) / maxstepnumber P = [] for I in range(0, maxstepnumber + 1): P.append(actuatorminthreshold + I * actuatorinterval) # ------------------------ Automation alghoritm if workmode == "Full Auto": # check if inside the allowed time period print "full Auto Mode" logger.info('full auto mode --> %s', element) timeok = isNowInTimePeriod( starttime, endtime, datetime.now().time()) # don't use UTC here! print "inside allowed time ", timeok, " starttime ", starttime, " endtime ", endtime if timeok: logger.info('inside allowed time') isok, sensorvalue = sensorreading( sensor, averageminutes, mathoperation ) # operation of sensor readings for a number of sample if isok: print "Sensor Value ", sensorvalue if sensorminthreshold <= sensormaxthreshold: print "Algorithm , element: ", element logger.info("Forward algorithm , element: %s ", element) Inde = 0 maxs = sensorminthreshold + Inde * interval if sensorvalue <= maxs: status = "belowthreshold" logger.info('below Minthreshold') value = P[Inde] # do relevant stuff CheckActivateNotify(element, waitingtime, value, mailtype, sensor, sensorvalue) Inde = 1 for I in range(Inde, maxstepnumber): mins = sensorminthreshold + (I - 1) * interval maxs = sensorminthreshold + I * interval if mins < sensorvalue <= maxs: value = P[I] logger.info('inside Range') # do relevant stuff CheckActivateNotify(element, waitingtime, value, mailtype, sensor, sensorvalue) Inde = maxstepnumber mins = sensorminthreshold + (Inde - 1) * interval if mins < sensorvalue: print "INDE:", Inde value = P[Inde] logger.info('beyond Range') # do relevant stuff CheckActivateNotify(element, waitingtime, value, mailtype, sensor, sensorvalue) # END MAIN ALGORITHM else: # to be added case of inverse sensor condition, where the sensorminthreshold is higher than the sensormaxthreshold print "Reverse Algorithm , element: ", element logger.info("Reverse Algorithm , element: %s ", element) Inde = 0 maxs = sensorminthreshold + Inde * interval if sensorvalue >= maxs: status = "belowthreshold" logger.info('Above MAXthreshold') value = P[Inde] # do relevant stuff CheckActivateNotify(element, waitingtime, value, mailtype, sensor, sensorvalue) Inde = Inde + 1 for I in range(Inde, maxstepnumber): mins = sensorminthreshold + (I - 1) * interval maxs = sensorminthreshold + I * interval if mins > sensorvalue >= maxs: value = P[I] # do relevant stuff CheckActivateNotify(element, waitingtime, value, mailtype, sensor, sensorvalue) Inde = maxstepnumber mins = sensorminthreshold + (Inde - 1) * interval if mins > sensorvalue: print "INDE:", Inde value = P[Inde] # do relevant stuff CheckActivateNotify(element, waitingtime, value, mailtype, sensor, sensorvalue) # END MAIN ALGORITHM - Reverse else: logger.error( 'No valid calculation operation on the stored sensor data' ) else: logger.info('Outside allowed Time, Stop') elif workmode == "Emergency Activation": print "Emergency Activation" elif workmode == "Alert Only": print "Alert Only" # implment Critical alert message in case the sensor value is one interval more than Max_threshold isok, sensorvalue = sensorreading( sensor, averageminutes, mathoperation ) # operation of sensor readings for a number of sample if isok: if sensorminthreshold <= sensormaxthreshold: if sensorvalue > sensormaxthreshold + interval: logger.info('sensor %s exceeding limits', sensor) textmessage = "CRITICAL: " + sensor + " reading " + str( sensorvalue ) + " exceeding threshold limits, need to check the " + element print textmessage #send alert mail notification alertcounter = statusdataDBmod.read_status_data( AUTO_data, element, "alertcounter") if alertcounter < 2: if (mailtype != "none"): emailmod.sendallmail("alert", textmessage) logger.error(textmessage) statusdataDBmod.write_status_data( AUTO_data, element, "alertcounter", alertcounter + 1) else: if sensorvalue < sensormaxthreshold + interval: logger.info('sensor %s exceeding limits', sensor) textmessage = "CRITICAL: " + sensor + " reading " + str( sensorvalue ) + " exceeding threshold limits, need to check the " + element print textmessage #send alert mail notification alertcounter = statusdataDBmod.read_status_data( AUTO_data, element, "alertcounter") if alertcounter < 2: if (mailtype != "none"): emailmod.sendallmail("alert", textmessage) logger.error(textmessage) statusdataDBmod.write_status_data( AUTO_data, element, "alertcounter", alertcounter + 1) return
def cyclereset(element): global AUTO_data waitingtime=hardwaremod.toint(autowateringdbmod.searchdata("element",element,"pausebetweenwtstepsmin"),0) AUTO_data[element]={"cyclestartdate":datetime.now(),"lastwateringtime":datetime.now() - timedelta(minutes=waitingtime),"cyclestatus":"done", "checkcounter":0, "alertcounter":0, "watercounter":0}