You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
8.9 KiB
112 lines
8.9 KiB
from . import Timer # Async thread
|
|
import threading # Create in another thread
|
|
import datetime # Datetime class
|
|
import copy # Copy struct functions
|
|
import time # time functions
|
|
import importlib # import lib functions
|
|
# Scheduler class - init and work by the configuration
|
|
# OOP
|
|
class Scheduler:
|
|
# Class properties
|
|
mSchedulerDict = None
|
|
mGSettings = None
|
|
#########################
|
|
# Init class
|
|
def __init__(self,inSchedulerDict, inGSettings = None):
|
|
self.Init(inSchedulerDict = inSchedulerDict, inGSettings = inGSettings)
|
|
# Init the class instance
|
|
def Init(self,inSchedulerDict, inGSettings):
|
|
self.mGSettings = inGSettings
|
|
self.mSchedulerDict = inSchedulerDict
|
|
# Init the threads
|
|
lTimerMainThread = threading.Thread(target = self.TimerMainThreadRun)
|
|
lTimerMainThread.start() # Start the Timer main thread
|
|
#print (f"Class instance configuration: {self.mSchedulerDict}, Init has been completed")
|
|
########################
|
|
# Main timer thread - run when init class instance
|
|
def TimerMainThreadRun(self):
|
|
lDaemonStartDateTime=datetime.datetime.now()
|
|
lDaemonLoopSeconds=self.mSchedulerDict["ActivityTimeCheckLoopSeconds"]
|
|
lDaemonActivityLogDict={} #Словарь отработанных активностей, ключ - кортеж (<activityType>, <datetime>, <processPath || processName>, <processArgs>)
|
|
#Вечный цикл
|
|
while True:
|
|
lCurrentDateTime = datetime.datetime.now()
|
|
#Циклический обход правил
|
|
lFlagSearchActivityType=True
|
|
for lIndex, lItem in enumerate(self.mSchedulerDict["ActivityTimeList"]):
|
|
#Проверка дней недели, в рамках которых можно запускать активность
|
|
lItemWeekdayList=lItem.get("WeekdayList", [0, 1, 2, 3, 4, 5, 6])
|
|
if lCurrentDateTime.weekday() in lItemWeekdayList:
|
|
if lFlagSearchActivityType:
|
|
#######################################################################
|
|
#Branch 1 - if has TimeHH:MM
|
|
#######################################################################
|
|
if "TimeHH:MM" in lItem:
|
|
#Вид активности - запуск процесса
|
|
#Сформировать временной штамп, относительно которого надо будет проверять время
|
|
#часовой пояс пока не учитываем
|
|
lActivityDateTime=datetime.datetime.strptime(lItem["TimeHH:MM"],"%H:%M")
|
|
lActivityDateTime=lActivityDateTime.replace(year=lCurrentDateTime.year,month=lCurrentDateTime.month,day=lCurrentDateTime.day)
|
|
#Убедиться в том, что время наступило
|
|
if (
|
|
lActivityDateTime>=lDaemonStartDateTime and
|
|
lCurrentDateTime>=lActivityDateTime and
|
|
(lIndex,lActivityDateTime) not in lDaemonActivityLogDict):
|
|
#Выполнить операцию
|
|
#Запись в массив отработанных активностей
|
|
lDaemonActivityLogDict[(lIndex,lActivityDateTime)]={"ActivityStartDateTime":lCurrentDateTime}
|
|
#Запустить процесс - new code
|
|
#################
|
|
#Call function from Activity structure
|
|
################################################
|
|
lSubmoduleFunctionName = lItem["Activity"]["DefName"]
|
|
lFileFullPath = lItem["Activity"]["ModulePath"] # "path\\to\\module.py"
|
|
lModuleName = (lFileFullPath.split("\\")[-1])[0:-3]
|
|
lTechSpecification = importlib.util.spec_from_file_location(lModuleName, lFileFullPath)
|
|
lTechModuleFromSpec = importlib.util.module_from_spec(lTechSpecification)
|
|
lTechSpecificationModuleLoader = lTechSpecification.loader.exec_module(lTechModuleFromSpec)
|
|
# Set gSettings in module
|
|
lTechModuleFromSpec.gSettings = self.mGSettings
|
|
if lSubmoduleFunctionName in dir(lTechModuleFromSpec):
|
|
# Run SettingUpdate function in submodule
|
|
#mGlobalDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)()
|
|
getattr(lTechModuleFromSpec, lSubmoduleFunctionName)(*lItem["Activity"]["ArgList"],**lItem["Activity"]["ArgDict"])
|
|
#################################################
|
|
#######################################################################
|
|
#Branch 2 - if TimeHH:MMStart, TimeHH:MMStop, ActivityIntervalSeconds
|
|
#######################################################################
|
|
if "TimeHH:MMStart" in lItem and "TimeHH:MMStop" in lItem and "ActivityIntervalSeconds" in lItem:
|
|
#Сформировать временной штамп, относительно которого надо будет проверять время
|
|
#часовой пояс пока не учитываем
|
|
lActivityDateTime=datetime.datetime.strptime(lItem["TimeHH:MMStart"],"%H:%M")
|
|
lActivityDateTime=lActivityDateTime.replace(year=lCurrentDateTime.year,month=lCurrentDateTime.month,day=lCurrentDateTime.day)
|
|
lActivityTimeEndDateTime=datetime.datetime.strptime(lItem["TimeHH:MMStop"],"%H:%M")
|
|
lActivityTimeEndDateTime=lActivityTimeEndDateTime.replace(year=lCurrentDateTime.year,month=lCurrentDateTime.month,day=lCurrentDateTime.day)
|
|
#Убедиться в том, что время наступило
|
|
if (
|
|
lCurrentDateTime<lActivityTimeEndDateTime and
|
|
lCurrentDateTime>=lActivityDateTime and
|
|
(lIndex,lActivityDateTime) not in lDaemonActivityLogDict):
|
|
#Запись в массив отработанных активностей
|
|
lDaemonActivityLogDict[(lIndex,lActivityDateTime)]={"ActivityStartDateTime":lCurrentDateTime}
|
|
#Call function from Activity structure
|
|
################################################
|
|
lSubmoduleFunctionName = lItem["Activity"]["DefName"]
|
|
lFileFullPath = lItem["Activity"]["ModulePath"] # "path\\to\\module.py"
|
|
lModuleName = (lFileFullPath.split("\\")[-1])[0:-3]
|
|
lTechSpecification = importlib.util.spec_from_file_location(lModuleName, lFileFullPath)
|
|
lTechModuleFromSpec = importlib.util.module_from_spec(lTechSpecification)
|
|
lTechSpecificationModuleLoader = lTechSpecification.loader.exec_module(lTechModuleFromSpec)
|
|
# Set gSettings in module
|
|
lTechModuleFromSpec.gSettings = self.mGSettings
|
|
if lSubmoduleFunctionName in dir(lTechModuleFromSpec):
|
|
# Run SettingUpdate function in submodule
|
|
#mGlobalDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)()
|
|
lDef = getattr(lTechModuleFromSpec, lSubmoduleFunctionName) #(*lItem["Activity"]["ArgList"],**lItem["Activity"]["ArgDict"])
|
|
#################################################
|
|
#Запуск циклической процедуры
|
|
#Timer.activityLoopStart(lItem["ActivityIntervalSeconds"], lActivityTimeEndDateTime, lItem["Activity"])
|
|
lTimer = Timer.RepeatedTimer(lItem["ActivityIntervalSeconds"], lActivityTimeEndDateTime, lDef, *lItem["Activity"]["ArgList"], **lItem["Activity"]["ArgDict"]) # it auto-starts, no need of rt.start()
|
|
#Уснуть до следующего прогона
|
|
#print (f"Loop has been completed")
|
|
time.sleep(lDaemonLoopSeconds) |