fixes from issues from the gitlab

dev-linux
Ivan Maslov 3 years ago
parent e361775027
commit 103483a20b

@ -36,9 +36,9 @@ Now you can use the following docs:
- ENG Guide PDF [|OPEN GITLAB|](Wiki/ENG_Guide/pdf/pyOpenRPA_Guide_ENG.pdf) - ENG Guide PDF [|OPEN GITLAB|](Wiki/ENG_Guide/pdf/pyOpenRPA_Guide_ENG.pdf)
- RUS Article: Less cost - no paid RPA [|OPEN HABR|](https://habr.com/ru/post/506766/) - RUS Article: Less cost - no paid RPA [|OPEN HABR|](https://habr.com/ru/post/506766/)
- RUS Tutorial Desktop UI [|OPEN HABR|](https://habr.com/ru/post/509644/); [|OPEN GITLAB|](Wiki/RUS_Tutorial/DesktopGUI_Habr/index.md) - RUS Tutorial Desktop UI [|OPEN HABR|](https://habr.com/ru/post/509644/); [|OPEN GITLAB|](Wiki/RUS_Tutorial/DesktopGUI_Habr/README.md)
- RUS Tutorial Web UI [|OPEN HABR|](https://habr.com/ru/post/515310/); [|OPEN GITLAB|](Wiki/RUS_Tutorial/WebGUI_Habr/3.%20WebGUI_Habr.md) - RUS Tutorial Web UI [|OPEN HABR|](https://habr.com/ru/post/515310/); [|OPEN GITLAB|](Wiki/RUS_Tutorial/WebGUI_Habr/3.%20WebGUI_Habr.md)
- RUS Leaflet pyOpenRPA v4.pdf [|OPEN GITLAB|](Wiki/RUS_Leaflet/RUS%20Leaflet%20pyOpenRPA%20v4.pdf) - RUS Leaflet pyOpenRPA v5.pdf [|OPEN GITLAB|](Wiki/RUS_Leaflet/RUS%20Leaflet%20pyOpenRPA%20v5.pdf)
## Copyrights & Contacts ## Copyrights & Contacts
pyOpenRPA is created by Ivan Maslov (Russia). Use it for free (MIT)! pyOpenRPA is created by Ivan Maslov (Russia). Use it for free (MIT)!
@ -47,7 +47,7 @@ If you need IT help feel free to contact me.
My contacts: My contacts:
- E-mail: Ivan.Maslov@UnicodeLabs.ru - E-mail: I.Maslov@mail.ru
- Skype: MegaFinder - Skype: MegaFinder
- Facebook: https://www.facebook.com/RU.IT4Business - Facebook: https://www.facebook.com/RU.IT4Business
- LinkedIn: https://www.linkedin.com/in/RU-IvanMaslov/ - LinkedIn: https://www.linkedin.com/in/RU-IvanMaslov/

@ -32,12 +32,18 @@ def O2A_Loop(inGSettings):
time.sleep(inGSettings["O2ADict"]["RetryTimeoutSecFloat"]) time.sleep(inGSettings["O2ADict"]["RetryTimeoutSecFloat"])
else: else:
lRequestBody = lResponse.text lRequestBody = lResponse.text
if len(lRequestBody) != 0: # CHeck if not empty result when close the connection from orch lBodyLenInt = len(lRequestBody)
if lBodyLenInt != 0: # CHeck if not empty result when close the connection from orch
lQueueItem = lResponse.json() # Try to get JSON lQueueItem = lResponse.json() # Try to get JSON
# Append QUEUE item in ProcessorDict > ActivityList # Append QUEUE item in ProcessorDict > ActivityList
lActivityLastGUIDStr = lQueueItem["GUIDStr"] lActivityLastGUIDStr = lQueueItem["GUIDStr"]
inGSettings["ProcessorDict"]["ActivityList"].append(lQueueItem) inGSettings["ProcessorDict"]["ActivityList"].append(lQueueItem)
if lL: lL.debug(f"ActivityItem was received from orchestrator: {lQueueItem}"); # Log full version if bytes size is less than limit . else short
lAgentLimitLogSizeBytesInt = 500
if lBodyLenInt <= lAgentLimitLogSizeBytesInt:
if lL: lL.info(f"ActivityItem was received from orchestrator: {lQueueItem}");
else:
if lL: lL.info(f"ActivityItem was received from orchestrator: Was supressed because of big size. Max is {lAgentLimitLogSizeBytesInt} bytes");
else: else:
if lL: lL.debug(f"Empty response from the orchestrator - loop when refresh the connection between Orc and Agent"); if lL: lL.debug(f"Empty response from the orchestrator - loop when refresh the connection between Orc and Agent");
except requests.exceptions.ConnectionError as e: except requests.exceptions.ConnectionError as e:

@ -480,4 +480,12 @@ def Update(inGSettings):
if "AgentFileChunkCheckIntervalSecFloat" not in inGSettings["ServerDict"]: if "AgentFileChunkCheckIntervalSecFloat" not in inGSettings["ServerDict"]:
inGSettings["ServerDict"]["AgentFileChunkCheckIntervalSecFloat"]= 0.2 inGSettings["ServerDict"]["AgentFileChunkCheckIntervalSecFloat"]= 0.2
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.3 to v1.2.4): Add new key ServerDict > AgentFileChunkCheckIntervalSecFloat") # Log about compatibility f"Backward compatibility (v1.2.3 to v1.2.4): Add new key ServerDict > AgentFileChunkCheckIntervalSecFloat") # Log about compatibility
if "ServerThread" not in inGSettings["ServerDict"]:
inGSettings["ServerDict"]["ServerThread"]= None
if lL: lL.warning(
f"Backward compatibility (v1.2.3 to v1.2.4): Add new key ServerDict > ServerThread") # Log about compatibility
if "AgentLimitLogSizeBytesInt" not in inGSettings["ServerDict"]:
inGSettings["ServerDict"]["AgentLimitLogSizeBytesInt"] = 300
if lL: lL.warning(
f"Backward compatibility (v1.2.3 to v1.2.4): Add new key ServerDict > AgentLimitLogSizeBytesInt") # Log about compatibility

@ -397,8 +397,16 @@ def pyOpenRPA_Agent_O2A(inRequest, inGSettings):
lReturnActivityItemDict = copy.deepcopy(lReturnActivityItemDict) lReturnActivityItemDict = copy.deepcopy(lReturnActivityItemDict)
if "CreatedByDatetime" in lReturnActivityItemDict: if "CreatedByDatetime" in lReturnActivityItemDict:
del lReturnActivityItemDict["CreatedByDatetime"] del lReturnActivityItemDict["CreatedByDatetime"]
if lL: lL.info(f"Activity item to agent Hostname {lInput['HostNameUpperStr']}, User {lInput['UserUpperStr']}. Activity item: {lReturnActivityItemDict}")
inRequest.OpenRPAResponseDict["Body"] = bytes(json.dumps(lReturnActivityItemDict), "utf8") inRequest.OpenRPAResponseDict["Body"] = bytes(json.dumps(lReturnActivityItemDict), "utf8")
# Log full version if bytes size is less than limit . else short
lBodyLenInt = len(inRequest.OpenRPAResponseDict["Body"])
lAgentLimitLogSizeBytesInt = inGSettings["ServerDict"]["AgentLimitLogSizeBytesInt"]
if lBodyLenInt <= lAgentLimitLogSizeBytesInt:
if lL: lL.info(f"Activity item to agent Hostname {lInput['HostNameUpperStr']}, User {lInput['UserUpperStr']}. Activity item: {lReturnActivityItemDict}")
else:
if lL: lL.info(
f"Activity item to agent Hostname {lInput['HostNameUpperStr']}, User {lInput['UserUpperStr']}. "
f"Activity item: Was suppressed because of body size of {lBodyLenInt} bytes. Max is {lAgentLimitLogSizeBytesInt}")
lDoLoopBool = False # CLose the connection lDoLoopBool = False # CLose the connection
else: # Nothing to send - sleep for the next iteration else: # Nothing to send - sleep for the next iteration
time.sleep(lAgentLoopSleepSecFloat) time.sleep(lAgentLoopSleepSecFloat)

@ -39,6 +39,8 @@ def __Create__():
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
}, },
"ServerDict": { "ServerDict": {
"AgentLimitLogSizeBytesInt": 300, # Don't show body if json body of transmition is more than
"ServerThread": None, # Server thread is there
"AgentActivityLifetimeSecFloat": 1200.0, # Time in seconds to life for activity for the agent "AgentActivityLifetimeSecFloat": 1200.0, # Time in seconds to life for activity for the agent
"AgentConnectionLifetimeSecFloat": 300.0, # Time in seconds to handle the open connection to the Agent "AgentConnectionLifetimeSecFloat": 300.0, # Time in seconds to handle the open connection to the Agent
"AgentLoopSleepSecFloat": 2.0, # Time in seconds to sleep between loops when check to send some activity to the agent "AgentLoopSleepSecFloat": 2.0, # Time in seconds to sleep between loops when check to send some activity to the agent

@ -75,7 +75,6 @@ def AgentActivityItemExists(inGSettings, inHostNameStr, inUserStr, inGUIDStr):
lAgentDictItemKeyTurple = (inHostNameStr.upper(),inUserStr.upper()) lAgentDictItemKeyTurple = (inHostNameStr.upper(),inUserStr.upper())
lResultBool = False lResultBool = False
if lAgentDictItemKeyTurple in inGSettings["AgentDict"]: if lAgentDictItemKeyTurple in inGSettings["AgentDict"]:
inGSettings["AgentDict"][lAgentDictItemKeyTurple] = SettingsTemplate.__AgentDictItemCreate__()
for lActivityItem in inGSettings["AgentDict"][lAgentDictItemKeyTurple]["ActivityList"]: for lActivityItem in inGSettings["AgentDict"][lAgentDictItemKeyTurple]["ActivityList"]:
if inGUIDStr == lActivityItem.get("GUIDStr",None): if inGUIDStr == lActivityItem.get("GUIDStr",None):
lResultBool = True lResultBool = True
@ -144,6 +143,7 @@ def AgentOSFileSend(inGSettings, inHostNameStr, inUserStr, inOrchestratorFilePat
""" """
Send the file from the Orchestrator to Agent (synchroniously) pyOpenRPA.Agent daemon process (safe for JSON transmition). Send the file from the Orchestrator to Agent (synchroniously) pyOpenRPA.Agent daemon process (safe for JSON transmition).
Work safety with big files Work safety with big files
Thread safe - you can call def even if you dont init the orchestrator - def will be executed later
:param inGSettings: Global settings dict (singleton) :param inGSettings: Global settings dict (singleton)
:param inHostNameStr: :param inHostNameStr:
@ -152,41 +152,58 @@ def AgentOSFileSend(inGSettings, inHostNameStr, inUserStr, inOrchestratorFilePat
:param inFileDataBytes: :param inFileDataBytes:
:return: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! :return: GUID String of the ActivityItem - you can wait (sync or async) result by this guid!
""" """
lActivityItemCheckIntervalSecFloat = inGSettings["ServerDict"]["AgentFileChunkCheckIntervalSecFloat"]
# Get the chunk limit
lChunkByteSizeInt = inGSettings["ServerDict"]["AgentFileChunkBytesSizeInt"]
lL = inGSettings.get("Logger",None)
# Open the file and get the size (in bytes) # Check thread
lFile = open(inOrchestratorFilePathStr,"rb") if inGSettings["ServerDict"]["ServerThread"] is None:
lFileSizeBytesInt = lFile.seek(0,2) if inGSettings["Logger"]: inGSettings["Logger"].warning(f"AgentOSFileSend run before server init - activity will be append in the processor queue.")
lFile.seek(0) lResult = {
"Def": AgentOSFileSend, # def link or def alias (look gSettings["Processor"]["AliasDefDict"])
lChunkCountInt = math.ceil(lFileSizeBytesInt/lChunkByteSizeInt) "ArgList": [], # Args list
if lL: lL.info(f"O2A: Start to send binary file via chunks. Chunk count: {lChunkCountInt}, From (Orch side): {inOrchestratorFilePathStr}, To (Agent side): {inAgentFilePathStr}") "ArgDict": {"inHostNameStr":inHostNameStr, "inUserStr":inUserStr, "inOrchestratorFilePathStr":inOrchestratorFilePathStr, "inAgentFilePathStr": inAgentFilePathStr}, # Args dictionary
for lChunkNumberInt in range(lChunkCountInt): "ArgGSettings": "inGSettings", # Name of GSettings attribute: str (ArgDict) or index (for ArgList)
# Read chunk "ArgLogger": None # Name of GSettings attribute: str (ArgDict) or index (for ArgList)
lFileChunkBytes = lFile.read(lChunkByteSizeInt) }
# Convert to base64 inGSettings["ProcessorDict"]["ActivityList"].append(lResult)
lFileChunkBase64Str = base64.b64encode(lFileChunkBytes).decode("utf-8") else: # In processor - do execution
# Send chunk lActivityItemCheckIntervalSecFloat = inGSettings["ServerDict"]["AgentFileChunkCheckIntervalSecFloat"]
if lChunkNumberInt == 0:
lActivityItemGUIDStr = AgentOSFileBinaryDataBase64StrCreate(inGSettings=inGSettings,inHostNameStr=inHostNameStr, # Get the chunk limit
inUserStr=inUserStr,inFilePathStr=inAgentFilePathStr, lChunkByteSizeInt = inGSettings["ServerDict"]["AgentFileChunkBytesSizeInt"]
inFileDataBase64Str=lFileChunkBase64Str)
else: lL = inGSettings.get("Logger",None)
lActivityItemGUIDStr = AgentOSFileBinaryDataBase64StrAppend(inGSettings=inGSettings, inHostNameStr=inHostNameStr,
inUserStr=inUserStr, inFilePathStr=inAgentFilePathStr, # Open the file and get the size (in bytes)
inFileDataBase64Str=lFileChunkBase64Str) lFile = open(inOrchestratorFilePathStr,"rb")
# Wait for the activity will be deleted lFileSizeBytesInt = lFile.seek(0,2)
while AgentActivityItemExists(inGSettings=inGSettings,inHostNameStr=inHostNameStr,inUserStr=inUserStr,inGUIDStr=lActivityItemGUIDStr): lFile.seek(0)
time.sleep(lActivityItemCheckIntervalSecFloat) #import pdb
if lL: lL.debug( #pdb.set_trace()
f"O2A: BINARY SEND: Current chunk index: {lChunkNumberInt}") lChunkCountInt = math.ceil(lFileSizeBytesInt/lChunkByteSizeInt)
# Close the file if lL: lL.info(f"O2A: Start to send binary file via chunks. Chunk count: {lChunkCountInt}, From (Orch side): {inOrchestratorFilePathStr}, To (Agent side): {inAgentFilePathStr}")
lFile.close() for lChunkNumberInt in range(lChunkCountInt):
# Read chunk
lFileChunkBytes = lFile.read(lChunkByteSizeInt)
# Convert to base64
lFileChunkBase64Str = base64.b64encode(lFileChunkBytes).decode("utf-8")
# Send chunk
if lChunkNumberInt == 0:
lActivityItemGUIDStr = AgentOSFileBinaryDataBase64StrCreate(inGSettings=inGSettings,inHostNameStr=inHostNameStr,
inUserStr=inUserStr,inFilePathStr=inAgentFilePathStr,
inFileDataBase64Str=lFileChunkBase64Str)
else:
lActivityItemGUIDStr = AgentOSFileBinaryDataBase64StrAppend(inGSettings=inGSettings, inHostNameStr=inHostNameStr,
inUserStr=inUserStr, inFilePathStr=inAgentFilePathStr,
inFileDataBase64Str=lFileChunkBase64Str)
# Wait for the activity will be deleted
while AgentActivityItemExists(inGSettings=inGSettings,inHostNameStr=inHostNameStr,inUserStr=inUserStr,inGUIDStr=lActivityItemGUIDStr):
time.sleep(lActivityItemCheckIntervalSecFloat)
if lL: lL.debug(
f"O2A: BINARY SEND: Current chunk index: {lChunkNumberInt}")
if lL: lL.info(
f"O2A: BINARY SEND: Transmition has been complete")
# Close the file
lFile.close()
def AgentOSFileBinaryDataBytesCreate(inGSettings, inHostNameStr, inUserStr, inFilePathStr, inFileDataBytes): def AgentOSFileBinaryDataBytesCreate(inGSettings, inHostNameStr, inUserStr, inFilePathStr, inFileDataBytes):
""" """
@ -2131,6 +2148,7 @@ def Orchestrator(inGSettings, inDumpRestoreBool = True, inRunAsAdministratorBool
lItemDict = lListenDict[lItemKeyStr] lItemDict = lListenDict[lItemKeyStr]
lThreadServer = Server.RobotDaemonServer(lItemKeyStr, gSettingsDict) lThreadServer = Server.RobotDaemonServer(lItemKeyStr, gSettingsDict)
lThreadServer.start() lThreadServer.start()
gSettingsDict["ServerDict"]["ServerThread"] = lThreadServer
lItemDict["ServerInstance"] = lThreadServer lItemDict["ServerInstance"] = lThreadServer
# Init the RobotScreenActive in another thread # Init the RobotScreenActive in another thread

@ -53,7 +53,7 @@ setup(name='pyOpenRPA',
install_requires=[ install_requires=[
'pywinauto>=0.6.8;platform_system=="win32" and python_version>="3.0"', 'pywinauto>=0.6.8;platform_system=="win32" and python_version>="3.0"',
'WMI>=1.4.9;platform_system=="win32" and python_version>="3.0"', 'WMI>=1.4.9;platform_system=="win32" and python_version>="3.0"',
'pillow>=6.0.0','keyboard>=0.13.3','pyautogui>=0.9.44', 'pillow>=6.0.0','keyboard>=0.13.3','pyautogui>=0.9.44 and pyautogui<=0.9.52',
'pywin32>=224;platform_system=="win32" and python_version>="3.0"', 'crypto>=1.4.1' 'pywin32>=224;platform_system=="win32" and python_version>="3.0"', 'crypto>=1.4.1'
#'pywin32>=224;platform_system=="Linux" and python_version>="3.0"', 'crypto>=1.4.1' #'pywin32>=224;platform_system=="Linux" and python_version>="3.0"', 'crypto>=1.4.1'
], ],

Loading…
Cancel
Save