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 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 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