From e4863d89ca2c7070df93c16ee171785bdf627d80 Mon Sep 17 00:00:00 2001 From: Ivan Maslov Date: Wed, 11 Mar 2020 17:03:40 +0300 Subject: [PATCH] # Prefinal RobotRDPActive OpenRPA test --- .../pyOpenRPA/Tools/RobotRDPActive/CMDStr.py | 12 ++ .../Tools/RobotRDPActive/Connector.py | 73 ++++++++---- .../GlobalDictSessionIndex_Defs.py | 17 +++ .../pyOpenRPA/Tools/RobotRDPActive/Monitor.py | 22 +++- .../Tools/RobotRDPActive/Scheduler.py | 106 ++++++++++++++++++ .../pyOpenRPA/Tools/RobotRDPActive/Timer.py | 31 +++++ .../Tools/RobotRDPActive/__main__.py | 4 +- Sources/test_idle.py | 39 +++++++ .../SettingsRobotRDPActiveExample.py | 47 +++++++- 9 files changed, 321 insertions(+), 30 deletions(-) create mode 100644 Sources/pyOpenRPA/Tools/RobotRDPActive/CMDStr.py create mode 100644 Sources/pyOpenRPA/Tools/RobotRDPActive/GlobalDictSessionIndex_Defs.py create mode 100644 Sources/pyOpenRPA/Tools/RobotRDPActive/Scheduler.py create mode 100644 Sources/pyOpenRPA/Tools/RobotRDPActive/Timer.py create mode 100644 Sources/test_idle.py diff --git a/Sources/pyOpenRPA/Tools/RobotRDPActive/CMDStr.py b/Sources/pyOpenRPA/Tools/RobotRDPActive/CMDStr.py new file mode 100644 index 00000000..77a6a098 --- /dev/null +++ b/Sources/pyOpenRPA/Tools/RobotRDPActive/CMDStr.py @@ -0,0 +1,12 @@ +import os # Get abs path of the file +# Create CMD str to run file if process.exe is not running +def ProcessStartIfNotRunning(inProcessName, inFilePath): + lFileAbsPath = os.abspath(inFilePath) + lResult = f'tasklist /nh /fi "imagename eq {inProcessName}" | find /i "{inProcessName}" > nul || (start {lFileAbsPath})' + return lResult +# Create CMD str to stop process +def ProcessStop(inProcessName, inFlagForceClose) + lResult = f'taskkill /im "{inProcessName}" /fi "username eq %USERNAME%"' + if inFlagForceClose: + lResult+= " /F" + return lResult \ No newline at end of file diff --git a/Sources/pyOpenRPA/Tools/RobotRDPActive/Connector.py b/Sources/pyOpenRPA/Tools/RobotRDPActive/Connector.py index 7f0d4853..f5bbac8c 100644 --- a/Sources/pyOpenRPA/Tools/RobotRDPActive/Connector.py +++ b/Sources/pyOpenRPA/Tools/RobotRDPActive/Connector.py @@ -6,6 +6,10 @@ import tempfile #Temporary location import time import subprocess from . import Clipboard # Clipboard functions get/set +import keyboard +import time +import random # random integers +from win32api import GetSystemMetrics # Get Screen rect #Connect to RDP session """ { @@ -118,40 +122,71 @@ def SessionRDPStart(inRDPFilePath): ], 30 ) + # Raise exception if RDP is not active + if len(lWaitResult) == 0: + raise Exception("Error when initialize the RDP session!") #Prepare little window SessionScreen100x550(lRDPFileName) return None #Set fullscreen for app def SessionScreenFull(inSessionHex): #Prepare little window - lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "uia"}]) #Hotfix uia is needed to set focus in RDP - lRDPWindow.maximize() + lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}]) lRDPWindow.set_focus() + if not SessionIsFullScreen(inSessionHex): + lRDPWindow.type_keys("^%{BREAK}") + time.sleep(0.5) return None #Set Little window of the session def SessionScreen100x550(inSessionHex): #Prepare little window lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}]) - #lRDPWindow.minimize() - #lRDPWindow.restore() - lRDPWindow.maximize() - lRDPWindow.type_keys("^%{BREAK}") # Ctrl + alt + creak to return window from full screen correctly + lRDPWindow.set_focus() + if SessionIsFullScreen(inSessionHex): + lRDPWindow.type_keys("^%{BREAK}") + time.sleep(0.5) + lRDPWindow.restore() + time.sleep(0.5) lRDPWindow.move_window(10,10,550,100) return None -import keyboard -import time #Type command in CMD -def SessionCMDRun(inSessionHex,inCMDCommandStr): +# inFlagDoCrossCheck: True - Do check that CMD is executed (the text response will not be available) +# inModeStr "LISTEN", "CROSSCHECK", "RUN" +# "LISTEN" - Get result of the cmd command in result TODO get home script +# "CROSSCHECK" - Check if the command was successufully sent TODO get home script +# "RUN" - Run without crosscheck and get clipboard +# return ... +# example Connector.SessionCMDRun("4d1e48f3ff6c45cc810ea25d8adbeb50","start notepad", "RUN") +def SessionCMDRun(inSessionHex,inCMDCommandStr, inModeStr="RUN"): + lCMDPostFixStr = "" # Case default "RUN" + if inModeStr == "CROSSCHECK": + lCMDPostFixStr = f"| echo {str(random.randrange(999,9999999))} | clip" + elif inModeStr == "LISTEN": + lCMDPostFixStr = f"| clip" SessionScreenFull(inSessionHex) - time.sleep(2) # High priority - keyboard.press_and_release('win+r') time.sleep(2) - print(Clipboard.InputIsFocused()) - keyboard.write(f"cmd") - keyboard.press_and_release('enter') - time.sleep(2) # Only time wait we can set here :( - print(Clipboard.CMDIsOpen()) - keyboard.write(f"{inCMDCommandStr} && exit") # Run CMD command and close CMD console + UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}]) + keyboard.press_and_release('win+r') + time.sleep(1) + keyboard.write(f"cmd /c {inCMDCommandStr} {lCMDPostFixStr}") + time.sleep(1) + # TODo cross check from clipboard keyboard.press_and_release('enter') - time.sleep(2) - SessionScreen100x550(inSessionHex) \ No newline at end of file + SessionScreen100x550(inSessionHex) +# Check if session is in Full screen mode +# Return True - is in fullscreen +# example print(Connector.SessionIsFullScreen("")) +def SessionIsFullScreen(inSessionHexStr): + #Default resul + lResult = False + lWeight = GetSystemMetrics(0) + lHeight = GetSystemMetrics(1) + #Get window screen + lRectangle = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHexStr}.*", "backend": "win32"}]).rectangle() + # Get Height/Weight + lSessionWeight = lRectangle.right - lRectangle.left + lSessionHeight = lRectangle.bottom - lRectangle.top + #Case fullscreen + if lSessionHeight == lHeight and lSessionWeight == lWeight: + lResult = True + return lResult diff --git a/Sources/pyOpenRPA/Tools/RobotRDPActive/GlobalDictSessionIndex_Defs.py b/Sources/pyOpenRPA/Tools/RobotRDPActive/GlobalDictSessionIndex_Defs.py new file mode 100644 index 00000000..a8297715 --- /dev/null +++ b/Sources/pyOpenRPA/Tools/RobotRDPActive/GlobalDictSessionIndex_Defs.py @@ -0,0 +1,17 @@ +from . import CMDStr # Create CMD Strings +from . import Connector # RDP API +def ProcessStartIfNotRunning(inGlobalDict, inSessionIndex, inProcessName, inFilePath): + lCMDStr = CMDStr.ProcessStartIfNotRunning(inProcessName,inFilePath) + # Calculate the session Hex + lSessionHex = inGlobalDict["RDPList"][inSessionIndex]["SessionHex"] + # Run CMD + Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN") +# Create CMD str to stop process +def ProcessStop(inGlobalDict, inSessionIndex, inProcessName, inFlagForceClose) + lCMDStr = f'taskkill /im "{inProcessName}" /fi "username eq %USERNAME%"' + if inFlagForceClose: + lCMDStr+= " /F" + # Calculate the session Hex + lSessionHex = inGlobalDict["RDPList"][inSessionIndex]["SessionHex"] + # Run CMD + Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN") \ No newline at end of file diff --git a/Sources/pyOpenRPA/Tools/RobotRDPActive/Monitor.py b/Sources/pyOpenRPA/Tools/RobotRDPActive/Monitor.py index 935e5a0a..025cf231 100644 --- a/Sources/pyOpenRPA/Tools/RobotRDPActive/Monitor.py +++ b/Sources/pyOpenRPA/Tools/RobotRDPActive/Monitor.py @@ -3,6 +3,7 @@ from . import Connector import os import time # Time wait operations import pdb +import importlib # from dynamic import module #Check for session is closed. Reopen if detected. Always keep session is active def Monitor(inGlobalDict, inListUpdateTimeout): lFlagWhile = True @@ -55,12 +56,21 @@ def Monitor(inGlobalDict, inListUpdateTimeout): ########################################### # Check ActivityList from orchestrator for lActivityItem in inGlobalDict["OrchestratorToRobotResetStorage"]["ActivityList"]: - # Check case CMDCommand - if lActivityItem["Type"] == "CMDCommand": - pass - # CMD command passed - #Connector.SessionCMDRun(inSessionHex=lActivityItem["SessionHex"], inCMDCommandStr= lActivityItem["CMDValue"]) - # loop interval + ################# + #Call function from Activity structure + ################################################ + lSubmoduleFunctionName = lActivityItem["DefName"] + lFileFullPath = lActivityItem["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) + if lSubmoduleFunctionName in dir(lTechModuleFromSpec): + # Run SettingUpdate function in submodule + #mGlobalDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)() + getattr(lTechModuleFromSpec, lSubmoduleFunctionName)(*lActivityItem["ArgList"],**lActivityItem["ArgDict"]) + ################################################# + inGlobalDict["OrchestratorToRobotResetStorage"]["ActivityList"] = [] # Override the value time.sleep(2) return None #TODO Def garbage window cleaner (if connection was lost) \ No newline at end of file diff --git a/Sources/pyOpenRPA/Tools/RobotRDPActive/Scheduler.py b/Sources/pyOpenRPA/Tools/RobotRDPActive/Scheduler.py new file mode 100644 index 00000000..4eb0e5f0 --- /dev/null +++ b/Sources/pyOpenRPA/Tools/RobotRDPActive/Scheduler.py @@ -0,0 +1,106 @@ +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 + ######################### + # Init class + def __init__(self,inSchedulerDict): + self.Init(inSchedulerDict = inSchedulerDict) + # Init the class instance + def Init(self,inSchedulerDict): + 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={} #Словарь отработанных активностей, ключ - кортеж (, , , ) + #Вечный цикл + 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) + 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=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) + 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) \ No newline at end of file diff --git a/Sources/pyOpenRPA/Tools/RobotRDPActive/Timer.py b/Sources/pyOpenRPA/Tools/RobotRDPActive/Timer.py new file mode 100644 index 00000000..3f1e4fcc --- /dev/null +++ b/Sources/pyOpenRPA/Tools/RobotRDPActive/Timer.py @@ -0,0 +1,31 @@ +from threading import Timer +import datetime +class RepeatedTimer(object): + def __init__(self, interval, inDateTimeEnd, function, *args, **kwargs): + self._timer = None + self.interval = interval + self.function = function + self.args = args + self.kwargs = kwargs + self.is_running = False + self.mDateTimeEnd = inDateTimeEnd # DateTime when stop + self.start() + def _run(self): + self.is_running = False + lResultGoLoop=True + lCurrentDateTime=datetime.datetime.now() + self.function(*self.args, **self.kwargs) + if lCurrentDateTime>=self.mDateTimeEnd: + lResultGoLoop=False + if lResultGoLoop is not None: + if lResultGoLoop: + self.start() + def start(self): + if not self.is_running: + self._timer = Timer(self.interval, self._run) + self._timer.start() + self.is_running = True + + def stop(self): + self._timer.cancel() + self.is_running = False \ No newline at end of file diff --git a/Sources/pyOpenRPA/Tools/RobotRDPActive/__main__.py b/Sources/pyOpenRPA/Tools/RobotRDPActive/__main__.py index 4b7dd76f..06e7b5c3 100644 --- a/Sources/pyOpenRPA/Tools/RobotRDPActive/__main__.py +++ b/Sources/pyOpenRPA/Tools/RobotRDPActive/__main__.py @@ -30,6 +30,7 @@ if lSubmoduleFunctionName in dir(lTechModuleFromSpec): ######################################################### from pyOpenRPA.Tools.RobotRDPActive import Connector from pyOpenRPA.Tools.RobotRDPActive import Monitor +from pyOpenRPA.Tools.RobotRDPActive import Scheduler # Scheduler operations #Disable certificate warning lCMDString = 'reg add "HKEY_CURRENT_USER\\Software\\Microsoft\\Terminal Server Client" /v "AuthenticationLevelOverride" /t "REG_DWORD" /d 0 /f' os.system(lCMDString) @@ -41,7 +42,8 @@ for lConfigurationItem in mGlobalDict["RDPList"]: except Exception: pass #Run monitor -print(mGlobalDict) +#print(mGlobalDict) +Scheduler.Scheduler(mGlobalDict["Scheduler"]) # Init & Run Scheduler Monitor.Monitor(mGlobalDict, 1) #Enable certificate warning lCMDString = 'reg add "HKEY_CURRENT_USER\\Software\\Microsoft\\Terminal Server Client" /v "AuthenticationLevelOverride" /t "REG_DWORD" /d 2 /f' diff --git a/Sources/test_idle.py b/Sources/test_idle.py new file mode 100644 index 00000000..97c1d3b4 --- /dev/null +++ b/Sources/test_idle.py @@ -0,0 +1,39 @@ +from pyOpenRPA.Tools.RobotRDPActive import Scheduler +inConfiguration={ + "ActivityTimeCheckLoopSeconds":5, #Количество секунд, между циклами проверки действий + "ActivityTimeList": [ + { + "TimeHH:MM": "22:23", #Time [HH:MM] to trigger activity + "WeekdayList": [1,2,3,4,5,6,7], #List of the weekday index when activity is applicable, Default [1,2,3,4,5,6,7] + "Activity":{ + "ModulePath": "Session\\SessionDefs.py", # "Session\\SessionDefs.py" + "DefName":"test", # Function name + "ArgList":[1,2,3], # Args list + "ArgDict":{"ttt":1,"222":2,"dsd":3} # Args dictionary + } + }, + { + "TimeHH:MM": "14:17", #Time [HH:MM] to trigger activity + "WeekdayList": [1, 2, 3], #List of the weekday index when activity is applicable, Default [1,2,3,4,5,6,7] + "Activity":{ + "ModulePath": "Session\\SessionDefs.py", # "Session\\SessionDefs.py" + "DefName":"test", # Function name + "ArgList":[1,2,3], # Args list + "ArgDict":{"ttt":1,"222":2,"dsd":3} # Args dictionary + } + }, + { + "TimeHH:MMStart": "12:40", #Time [HH:MM] to trigger activity + "TimeHH:MMStop": "14:36", + "ActivityIntervalSeconds": 2, + "WeekdayList": [1, 2, 3, 4, 5, 6, 7], #List of the weekday index when activity is applicable, Default [1,2,3,4,5,6,7] + "Activity":{ + "ModulePath": "Session\\SessionDefs.py", # "Session\\SessionDefs.py" + "DefName":"test", # Function name + "ArgList":[1,2,3], # Args list + "ArgDict":{"ttt":1,"222":2,"dsd":3} # Args dictionary + } + } + ] + } +lT = Scheduler.Scheduler(inConfiguration) diff --git a/Utils/RobotRDPActive/SettingsRobotRDPActiveExample.py b/Utils/RobotRDPActive/SettingsRobotRDPActiveExample.py index 457fa2be..3df138e7 100644 --- a/Utils/RobotRDPActive/SettingsRobotRDPActiveExample.py +++ b/Utils/RobotRDPActive/SettingsRobotRDPActiveExample.py @@ -1,5 +1,6 @@ #Robot RDPActive settings from pyOpenRPA.Robot import OrchestratorConnector +from pyOpenRPA.Tools import RobotRDPActive # For RobotRDPActive folder purposes import os import logging import datetime @@ -8,6 +9,9 @@ lOrchestratorHost="localhost" lOrchestratorPort=8081 lOrchestratorProtocol="http" lOrchestratorAuthToken="1992-04-03-0643-ru-b4ff-openrpa52zzz" + +lRobotRDPActiveFolderPath = '\\'.join(RobotRDPActive.__file__.split('\\')[:-1]) +print(f"{os.path.join(lRobotRDPActiveFolderPath,'SessionDefs.py')}") def Settings(): mDict = { "RDPList": @@ -35,16 +39,51 @@ def Settings(): "IgnoreIndexList":[] }, "OrchestratorToRobotResetStorage": { - "SafeTurnOff":False #Control from orchestrator to safety turn off robot + "SafeTurnOff":False ,#Control from orchestrator to safety turn off robot "ActivityList":[ - {"Type":"CMDCommand", "CMDValue"}, - {"Type":"CreateFile","FileFullPath": "" ,"FileBytes": None} + #{ + # "ModulePath": f"{os.path.join(lRobotRDPActiveFolderPath,'SessionDefs.py')}", # "Session\\SessionDefs.py" + # "DefName":"test", # Function name + # "ArgList":[1,2,3], # Args list + # "ArgDict":{"ttt":1,"222":2,"dsd":3} # Args dictionary + #} ] }, "OrchestratorConnector": { #Fill below }, - "OrchestratorConnectorTerminateAll":OrchestratorConnector.IntervalTerminateAll #Call this function when program must be shutted down (to kill threads from OrchestratorConnector) + "OrchestratorConnectorTerminateAll":OrchestratorConnector.IntervalTerminateAll, #Call this function when program must be shutted down (to kill threads from OrchestratorConnector) + "Scheduler":None # !!! Will be filled below + } + ############### + # Scheduler operations for RDP + ############### + mDict["Scheduler"]={ + "ActivityTimeCheckLoopSeconds":5, #Количество секунд, между циклами проверки действий + "ActivityTimeList": [ + { + "TimeHH:MM": "22:23", #Time [HH:MM] to trigger activity + "WeekdayList": [1,2,3,4,5,6,7], #List of the weekday index when activity is applicable, Default [1,2,3,4,5,6,7] + "Activity":{ + "ModulePath": f"{os.path.join(lRobotRDPActiveFolderPath,'GlobalDictSessionIndex_Defs.py')}", # "Session\\SessionDefs.py" + "DefName":"ProcessStop", # Function name + "ArgList":[], # Args list + "ArgDict":{"inGlobalDict": mDict, "inSessionIndex": 0, "inProcessName": "notepad.exe", "inFlagForceClose":True} # Args dictionary + } + }, + { + "TimeHH:MMStart": "12:40", #Time [HH:MM] to trigger activity + "TimeHH:MMStop": "17:10", + "ActivityIntervalSeconds": 5, + "WeekdayList": [1, 2, 3, 4, 5, 6, 7], #List of the weekday index when activity is applicable, Default [1,2,3,4,5,6,7] + "Activity":{ + "ModulePath": f"{os.path.join(lRobotRDPActiveFolderPath,'GlobalDictSessionIndex_Defs.py')}", # "RobotRDPActive\\SessionDefs.py" + "DefName":"ProcessStartIfNotRunning", # Function name + "ArgList":[], # Args list + "ArgDict":{"inGlobalDict": mDict, "inSessionIndex": 0, "inProcessName": "notepad.exe", "inFilePath": "notepad"} # Args dictionary + } + } + ] } ###################### #OrchestratorConnector