import requests #Logging import os import logging import datetime import copy from .Utils import TimerRepeat # Timer which can repeating mLogger=logging.getLogger("OrchestratorConnector") ######################### mTimerList=[] def IntervalTerminateAll(): for lItem in mTimerList: lItem.stop() ######################### # Создать файл логирования # add filemode="w" to overwrite if not os.path.exists("Reports"): os.makedirs("Reports") ########################## # Подготовка логгера Robot ######################### mLogger.setLevel(logging.INFO) # create the logging file handler mLoggerFH = logging.FileHandler("Reports\ReportOrchestratorConnector_" + datetime.datetime.now().strftime("%Y_%m_%d") + ".log") mLoggerFormatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') mLoggerFH.setFormatter(mLoggerFormatter) # add handler to logger object mLogger.addHandler(mLoggerFH) ############################################ #Turn loggin level ERROR def LoggerSetLevelError(): mLogger.setLevel(logging.ERROR) #from requests import async import json ################################### ##Orchestrator integration module (safe use when orchestrator is turned off) ################################### ################################################################################ # Recieve data from orchestrator (synchronyous) # Example: # t=IntegrationOrchestrator.DataRecieveAsync( # RobotStorage=mGlobal["Storage"], # RobotStorageKey="R01_OrchestratorToRobot", # OrchestratorKeyList=["Storage", "R01_OrchestratorToRobot"], # OrchestratorProtocol="http", # OrchestratorHost="localhost", # OrchestratorPort=8081, # OrchestratorAuthToken="1992-04-03-0643-ru-b4ff-openrpa52zzz" # ) def DataReceiveSync( OrchestratorKeyList, OrchestratorProtocol="http", OrchestratorHost="localhost", OrchestratorPort=80, OrchestratorAuthToken=None ): lCookies = {} # Set auth token if authorization is needed if OrchestratorAuthToken: lCookies["AuthToken"] = OrchestratorAuthToken lURL = f'{OrchestratorProtocol}://{OrchestratorHost}:{OrchestratorPort}/Utils/Processor' lDataJSON = [{"Type": "GlobalDictKeyListValueGet", "KeyList": OrchestratorKeyList}] try: lResult = requests.post(lURL, json=lDataJSON, cookies=lCookies) lResultJSON = json.loads(lResult.text) return (True, lResultJSON[0]["Result"]) # (Flag response is ok, Data) except Exception: mLogger.warning( f"Orchestrator not responding. Def DataRecieveSync, OrchestratorKeyList: {str(OrchestratorKeyList)}, OrchestratorProtocol: {str(OrchestratorProtocol)}, OrchestratorHost: {str(OrchestratorHost)}, OrchestratorPort: {str(OrchestratorPort)}") return (False, None) # (Flag response is not ok, Data None) ################################################################################ # Recieve data from orchestrator (asynchronyous) # Example: # t=IntegrationOrchestrator.DataRecieveAsync( # RobotStorage=mGlobal["Storage"], # RobotStorageKey="R01_OrchestratorToRobot", # OrchestratorKeyList=["Storage", "R01_OrchestratorToRobot"], # OrchestratorProtocol="http", # OrchestratorHost="localhost", # OrchestratorPort=8081, # OrchestratorAuthToken="1992-04-03-0643-ru-b4ff-openrpa52zzz" # ) def DataReceiveAsync( RobotStorage, RobotStorageKey, OrchestratorKeyList, OrchestratorProtocol="http", OrchestratorHost="localhost", OrchestratorPort=80, OrchestratorAuthToken=None ): from threading import Thread import uuid global mGlobalDict class ThreadAsync(Thread): def DataRecieveSync(self): lCookies = {} #Set auth token if authorization is needed if OrchestratorAuthToken: lCookies["AuthToken"] = OrchestratorAuthToken lURL = f'{OrchestratorProtocol}://{OrchestratorHost}:{OrchestratorPort}/Utils/Processor' lDataJSON = [{"Type": "GlobalDictKeyListValueGet", "KeyList": OrchestratorKeyList}] try: lResult = requests.post(lURL, json=lDataJSON, cookies = lCookies) lResultJSON = json.loads(lResult.text) return (True,lResultJSON[0]["Result"]) #(Flag response is ok, Data) except Exception: mLogger.warning( f"Orchestrator not responding. Def DataRecieveAsync, OrchestratorKeyList: {str(OrchestratorKeyList)}, OrchestratorProtocol: {str(OrchestratorProtocol)}, OrchestratorHost: {str(OrchestratorHost)}, OrchestratorPort: {str(OrchestratorPort)}") return (False,None) #(Flag response is not ok, Data None) # Thread init def __init__(self, name): Thread.__init__(self) self.name = name #Thread start def run(self): (lFlagResponseOK,lResponseData) = self.DataRecieveSync() if lFlagResponseOK: RobotStorage[RobotStorageKey] = lResponseData ThreadObject = ThreadAsync(f"ThreadAsync{str(uuid.uuid1())}") ThreadObject.start() return True ################################################################################ #IntervalDataRecieveAsync - Periodic recieve data from orchestrator and update storage def IntervalDataReceiveAsync(*args, **kwargs): lInterval=3 #Delete index 0 from args lArgs=copy.copy(args) if len(lArgs)>0: lInterval = lArgs[0] lArgs = lArgs[1:] #Delete Interval from kwargs lKwargs = copy.copy(kwargs) if "Interval" in lKwargs: lInterval = lKwargs["Interval"] del lKwargs["Interval"] lTimer = TimerRepeat.TimerRepeat(lInterval, DataReceiveAsync, lArgs, lKwargs) lTimer.start() #Add timer to general list to stop this when needed mTimerList.append(lTimer) return lTimer ################################################################################ ################################### ################################ ################################### ################################################################################ # Send data from orchestrator (synchronyous) # Example: # t=IntegrationOrchestrator.DataSendSync( # RobotValue="Value", # OrchestratorKeyList=["Storage", "R01_OrchestratorToRobot"], # OrchestratorProtocol="http", # OrchestratorHost="localhost", # OrchestratorPort=8081, # OrchestratorAuthToken="1992-04-03-0643-ru-b4ff-openrpa52zzz" # ) def DataSendSync( RobotValue, OrchestratorKeyList, OrchestratorProtocol="http", OrchestratorHost="localhost", OrchestratorPort=80, OrchestratorAuthToken=None ): lCookies = {} # Set auth token if authorization is needed if OrchestratorAuthToken: lCookies["AuthToken"] = OrchestratorAuthToken lURL = f'{OrchestratorProtocol}://{OrchestratorHost}:{OrchestratorPort}/Utils/Processor' lDataJSON = [{"Type": "GlobalDictKeyListValueSet", "KeyList": OrchestratorKeyList, "Value": RobotValue}] try: lResult = requests.post(lURL, json=lDataJSON, cookies=lCookies) lResultJSON = json.loads(lResult.text) return (True, lResultJSON[0]["Result"]) # (Flag response is ok, Data) except Exception: mLogger.warning( f"Orchestrator not responding. Def: DataSendSync, RobotValue: {str(RobotValue)}, OrchestratorKeyList: {str(OrchestratorKeyList)}, OrchestratorProtocol: {str(OrchestratorProtocol)}, OrchestratorHost: {str(OrchestratorHost)}, OrchestratorPort: {str(OrchestratorPort)}") return (False, None) # (Flag response is not ok, Data None) ################################################################################ # Send data from orchestrator (asynchronyous) # Example: # t=IntegrationOrchestrator.DataSendAsync( # RobotStorage=mGlobal["Storage"], # RobotStorageKey="R01_OrchestratorToRobot", # OrchestratorKeyList=["Storage", "R01_OrchestratorToRobot"], # OrchestratorProtocol="http", # OrchestratorHost="localhost", # OrchestratorPort=8081, # OrchestratorAuthToken="1992-04-03-0643-ru-b4ff-openrpa52zzz" # ) def DataSendAsync( RobotStorage, RobotStorageKey, OrchestratorKeyList, OrchestratorProtocol="http", OrchestratorHost="localhost", OrchestratorPort=80, OrchestratorAuthToken=None ): from threading import Thread import uuid global mGlobalDict class ThreadAsync(Thread): def DataSendSync(self): RobotValue = RobotStorage[RobotStorageKey] lCookies = {} # Set auth token if authorization is needed if OrchestratorAuthToken: lCookies["AuthToken"] = OrchestratorAuthToken lURL = f'{OrchestratorProtocol}://{OrchestratorHost}:{OrchestratorPort}/Utils/Processor' lDataJSON = [{"Type": "GlobalDictKeyListValueSet", "KeyList": OrchestratorKeyList, "Value": RobotValue}] try: lResult = requests.post(lURL, json=lDataJSON, cookies=lCookies) lResultJSON = json.loads(lResult.text) return (True, lResultJSON[0]["Result"]) # (Flag response is ok, Data) except Exception: mLogger.warning( f"Orchestrator not responding. Def: DataSendAsync, RobotValue: {str(RobotValue)}, OrchestratorKeyList: {str(OrchestratorKeyList)}, OrchestratorProtocol: {str(OrchestratorProtocol)}, OrchestratorHost: {str(OrchestratorHost)}, OrchestratorPort: {str(OrchestratorPort)}") return (False, None) # (Flag response is not ok, Data None) # Thread init def __init__(self, name): Thread.__init__(self) self.name = name #Thread start def run(self): self.DataSendSync() ThreadObject = ThreadAsync(f"ThreadAsync{str(uuid.uuid1())}") ThreadObject.start() return True ################################################################################ #IntervalDataSendAsync - Periodic send data from robot to orchestrator def IntervalDataSendAsync(*args,**kwargs): lInterval=3 #Delete index 0 from args lArgs=copy.copy(args) if len(lArgs)>0: lInterval = lArgs[0] lArgs = lArgs[1:] #Delete Interval from kwargs lKwargs = copy.copy(kwargs) if "Interval" in lKwargs: lInterval = lKwargs["Interval"] del lKwargs["Interval"] lTimer = TimerRepeat.TimerRepeat(lInterval, DataSendAsync, lArgs, lKwargs) lTimer.start() #Add timer to general list to stop this when needed mTimerList.append(lTimer) return lTimer ################################################################################ ################################### ################################ ################################### ################################################################################ # Check if RobotStorage[Key] Value has been changed > then send data + reset to orchestrator (asynchronyous) timeout 2 seconds # Example: # t=IntegrationOrchestrator.DataSendResetAsync( # RobotStorage=mGlobal["Storage"], # RobotStorageKey="R01_OrchestratorToRobot", # RobotResetValue="Test", # OrchestratorKeyList=["Storage", "R01_OrchestratorToRobot"], # OrchestratorProtocol="http", # OrchestratorHost="localhost", # OrchestratorPort=8081, # OrchestratorAuthToken="1992-04-03-0643-ru-b4ff-openrpa52zzz" # ) def DataSendResetAsync( RobotStorage, RobotStorageKey, RobotResetValue, OrchestratorKeyList, OrchestratorProtocol="http", OrchestratorHost="localhost", OrchestratorPort=80, OrchestratorAuthToken=None ): #Do operations if data not equal to ResetValue if RobotStorage[RobotStorageKey] != RobotResetValue: #Get value lRobotValue = copy.deepcopy(RobotStorage[RobotStorageKey]) #Reset value RobotStorage[RobotStorageKey] = copy.deepcopy(RobotResetValue) #Send data (retry while data will be transferred completele) from threading import Thread import uuid import time global mGlobalDict class ThreadAsync(Thread): def DataSendSync(self): RobotValue = lRobotValue lCookies = {} # Set auth token if authorization is needed if OrchestratorAuthToken: lCookies["AuthToken"] = OrchestratorAuthToken lURL = f'{OrchestratorProtocol}://{OrchestratorHost}:{OrchestratorPort}/Utils/Processor' lDataJSON = [{"Type": "GlobalDictKeyListValueSet", "KeyList": OrchestratorKeyList, "Value": RobotValue}] lFlagDataTransmit = False while not lFlagDataTransmit: try: lResult = requests.post(lURL, json=lDataJSON, cookies=lCookies) lResultJSON = json.loads(lResult.text) lFlagDataTransmit = True except Exception: mLogger.warning( f"Orchestrator not responding - will retry to send update. Timeout 2 seconds. Def: DataSendResetAsync, RobotValue: {str(RobotValue)}, OrchestratorKeyList: {str(OrchestratorKeyList)}, OrchestratorProtocol: {str(OrchestratorProtocol)}, OrchestratorHost: {str(OrchestratorHost)}, OrchestratorPort: {str(OrchestratorPort)}") time.sleep(2) #Timout for next loop return (True,True) # Only True can be returned # Thread init def __init__(self, name): Thread.__init__(self) self.name = name # Thread start def run(self): self.DataSendSync() ThreadObject = ThreadAsync(f"ThreadAsync{str(uuid.uuid1())}") ThreadObject.start() return True return True ################################################################################ ################################################################################ #IntervalDataSendResetAsync - Periodic check changed and send + reset data from robot to orchestrator def IntervalDataSendResetAsync(*args,**kwargs): lInterval=3 #Delete index 0 from args lArgs=copy.copy(args) if len(lArgs)>0: lInterval = lArgs[0] lArgs = lArgs[1:] #Delete Interval from kwargs lKwargs = copy.copy(kwargs) if "Interval" in lKwargs: lInterval = lKwargs["Interval"] del lKwargs["Interval"] lTimer = TimerRepeat.TimerRepeat(lInterval, DataSendResetAsync, lArgs, lKwargs) lTimer.start() #Add timer to general list to stop this when needed mTimerList.append(lTimer) return lTimer ################################################################################ # Check changes in orchestrator - then replace in RobotStorage if not equeal. Has no timeout because You can use function IntervalDataReceiveResetAsync (asynchronyous) #Next iteration do not rewrite value until new change has come from orchestrator # Example: # t=IntegrationOrchestrator.DataRecieveAsync( # RobotStorage=mGlobal["Storage"], # RobotStorageKey="R01_OrchestratorToRobot", # RobotResetValue={"Test":"Test"}, # OrchestratorKeyList=["Storage", "R01_OrchestratorToRobot"], # OrchestratorProtocol="http", # OrchestratorHost="localhost", # OrchestratorPort=8081, # OrchestratorAuthToken="1992-04-03-0643-ru-b4ff-openrpa52zzz" # ) def DataReceiveResetAsync( RobotStorage, RobotStorageKey, RobotResetValue, OrchestratorKeyList, OrchestratorProtocol="http", OrchestratorHost="localhost", OrchestratorPort=80, OrchestratorAuthToken=None ): from threading import Thread import uuid global mGlobalDict class ThreadAsync(Thread): def DataRecieveSync(self): lCookies = {} #Set auth token if authorization is needed if OrchestratorAuthToken: lCookies["AuthToken"] = OrchestratorAuthToken lURL = f'{OrchestratorProtocol}://{OrchestratorHost}:{OrchestratorPort}/Utils/Processor' lDataJSON = [ {"Type": "GlobalDictKeyListValueGet", "KeyList": OrchestratorKeyList}, {"Type": "GlobalDictKeyListValueSet", "KeyList": OrchestratorKeyList, "Value": RobotResetValue} ] try: lResult = requests.post(lURL, json=lDataJSON, cookies = lCookies) lResultJSON = json.loads(lResult.text) #Change data if it changes with ResetValue if lResultJSON[0]["Result"] != RobotResetValue: return (True,lResultJSON[0]["Result"]) #(Flag data changes is ok, Data) else: return (False, lResultJSON[0]["Result"]) # (Flag data changes is false - dont rewrite in RobotStorage, Data) except Exception: mLogger.warning( f"Orchestrator not responding. Def DataReceiveResetAsync, RobotResetValue: {str(RobotResetValue)}, OrchestratorKeyList: {str(OrchestratorKeyList)}, OrchestratorProtocol: {str(OrchestratorProtocol)}, OrchestratorHost: {str(OrchestratorHost)}, OrchestratorPort: {str(OrchestratorPort)}") return (False,None) #(Flag response is not ok, Data None) # Thread init def __init__(self, name): Thread.__init__(self) self.name = name #Thread start def run(self): (lFlagResponseOK,lResponseData) = self.DataRecieveSync() if lFlagResponseOK: RobotStorage[RobotStorageKey] = lResponseData ThreadObject = ThreadAsync(f"ThreadAsync{str(uuid.uuid1())}") ThreadObject.start() return True ################################################################################ ################################################################################ #IntervalDataReceiveResetAsync - Periodic receive + every time reset and check changed and reset data on robot storage def IntervalDataReceiveResetAsync(*args,**kwargs): lInterval=3 #Delete index 0 from args lArgs=copy.copy(args) if len(lArgs)>0: lInterval = lArgs[0] lArgs = lArgs[1:] #Delete Interval from kwargs lKwargs = copy.copy(kwargs) if "Interval" in lKwargs: lInterval = lKwargs["Interval"] del lKwargs["Interval"] # Reset the storage before start DataSendSync( RobotValue=lKwargs["RobotResetValue"], OrchestratorKeyList=lKwargs["OrchestratorKeyList"], OrchestratorProtocol=lKwargs["OrchestratorProtocol"], OrchestratorHost=lKwargs["OrchestratorHost"], OrchestratorPort=lKwargs["OrchestratorPort"], OrchestratorAuthToken=lKwargs["OrchestratorAuthToken"] ) lTimer = TimerRepeat.TimerRepeat(lInterval, DataReceiveResetAsync, lArgs, lKwargs) lTimer.start() #Add timer to general list to stop this when needed mTimerList.append(lTimer) return lTimer ################################################################################# ################################################################################# ################################################################################ #ConfigurationInit - Get dict configuration and init interval functions def ConfigurationInit(inConfigurationDict): for lItem in inConfigurationDict.keys(): lFunction = globals()[lItem] #Iterate throught the nested list for lFunctionConfigurationDict in inConfigurationDict[lItem]: lFunction(**lFunctionConfigurationDict) return True