#Upgrade python/s

dev-linux v1.0.34
Ivan Maslov 5 years ago
parent f6a364518e
commit 90f2b6a568

@ -1,4 +1,4 @@
cd %~dp0\..\Sources
copy /Y ..\Resources\WPy64-3720\python-3.7.2.amd64\python.exe ..\Resources\WPy64-3720\python-3.7.2.amd64\OpenRPA_Orchestrator.exe
.\..\Resources\WPy64-3720\python-3.7.2.amd64\OpenRPA_Orchestrator.exe -m pyOpenRPA.Orchestrator "..\Orchestrator\Settings\Settings.py"
.\..\Resources\WPy64-3720\python-3.7.2.amd64\OpenRPA_Orchestrator.exe -m pyOpenRPA.Orchestrator "..\Orchestrator\Settings\SettingsOrchestratorExample.py"
pause >nul

@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: pyOpenRPA
Version: 1.0.32
Version: 1.0.34
Summary: First open source RPA platform for business
Home-page: https://gitlab.com/UnicodeLabs/OpenRPA
Author: Ivan Maslov

@ -1,14 +1,14 @@
pyOpenRPA-1.0.32.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pyOpenRPA-1.0.32.dist-info/METADATA,sha256=hwB02rO7bJ84-CJNqzZfm4jVgnNbuBkKuAr8SsRwZq0,3510
pyOpenRPA-1.0.32.dist-info/RECORD,,
pyOpenRPA-1.0.32.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97
pyOpenRPA-1.0.32.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10
pyOpenRPA/Orchestrator/Orchestrator.py,sha256=iM-DZ7TU7o51pzIJYEkNIlVG_GzzaVUESi7Tu0Ppw8g,6717
pyOpenRPA/Orchestrator/Processor.py,sha256=GHXwC1B2py4mAtk9oZa-FVSJhx3no9oD2bvkj20uhNA,9051
pyOpenRPA/Orchestrator/Server.py,sha256=TgKkqgMivzvh4cM4zpbDUdv9AXbUiPPy9uLjR1lTiJU,20229
pyOpenRPA/Orchestrator/ServerSettings.py,sha256=ZrNEt_UoHYGOeAKN5X5jQHz-XNl1lBW47ttKUF8_cmM,4948
pyOpenRPA-1.0.34.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pyOpenRPA-1.0.34.dist-info/METADATA,sha256=WakfkUg30wJGLxsmqvPERvkd2agMGOzXa84qcPG5f5Q,3510
pyOpenRPA-1.0.34.dist-info/RECORD,,
pyOpenRPA-1.0.34.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97
pyOpenRPA-1.0.34.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10
pyOpenRPA/Orchestrator/Orchestrator.py,sha256=UKp7eqvWDM91kYLwl2mo0UB8Pw-qu8eJCsR9NEXD1aU,6436
pyOpenRPA/Orchestrator/Processor.py,sha256=HQQyOVX-d5vPO-YULyTxVOtXtUMfvpAaSVO4xXxaKVI,9107
pyOpenRPA/Orchestrator/Server.py,sha256=5tjhfU0QVEfg4zjT2jWOuOADWeHXMBxX2Fe8lj1bnCA,20839
pyOpenRPA/Orchestrator/ServerSettings.py,sha256=jOXJTLwg8cJx6D-rN8J4dn5RCb2nepAhCH4F9hYVUdM,4912
pyOpenRPA/Orchestrator/Timer.py,sha256=FQZ3y6G9d47Ybx7RewzePKQV77H4gCkx5SaeFVlsuhc,2095
pyOpenRPA/Orchestrator/Web/Index.xhtml,sha256=wWDxguk0q4ylePllPzZvTdaOzlpolqYiBXIGp_a5udI,31744
pyOpenRPA/Orchestrator/Web/Index.xhtml,sha256=7wwEJ8lEI_2AElITUk9yyX91Sq6pNccqPsuAVlm7enQ,32322
pyOpenRPA/Orchestrator/Web/favicon.ico,sha256=jO3pjFWbmJEPQ2KroXSKYtXIesBq46PCBlKSouewODU,5430
pyOpenRPA/Orchestrator/__init__.py,sha256=qVH8fEPgXk54rmy-ol0PnT8GF5OlGE0a8mExwJ4tFqY,124
pyOpenRPA/Orchestrator/__main__.py,sha256=cOd8WU77VGgzTZUB0WmWpPmdYyMZY1zVyuU9yx26MKs,144
@ -192,52 +192,56 @@ pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/fonts/outli
pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/images/flags.png,sha256=lNXH8WYTAcSm3Ekdct1VmgYgzZF6gm8N8bAju5bqnd0,28123
pyOpenRPA/Resources/Web/jQuery/jquery-3.1.1.min.js,sha256=HPMOWdIdSuVgr3FD9ZE-_MgiK8qk_MdQjrgCtfqp6U4,86713
pyOpenRPA/Robot/Clipboard.py,sha256=q76X8L21zJwcwdoJJNPeCEwAV30xS6ylHP1WwvtxoWI,722
pyOpenRPA/Robot/IntegrationOrchestrator.py,sha256=T1g1jJM7_JMTSVP50DTM5WHrMh1w8wovvcBXl1nEokU,2656
pyOpenRPA/Robot/JSONNormalize.py,sha256=aIuVzuZDazhxkCOzoOjfhHVz66mp2FWdfPv5E7KWF5Y,3890
pyOpenRPA/Robot/ProcessCommunicator.py,sha256=Mpo2WoCrEUmY6aCSbQEXkT4qVKtN1N5NcVvG_UZxGVo,8245
pyOpenRPA/Robot/Robot.py,sha256=AVR8jzO-e_ZkW5DrLY_W9ta0eHSul997Y3U6uNVU8WE,9442
pyOpenRPA/Robot/UIDesktop.py,sha256=ehqMQmKLbkwW6iqA9bkw9tvDRni5QriLkG9P3AP_TMs,78377
pyOpenRPA/Robot/OrchestratorConnector.py,sha256=Fihxz-jH9M4VakXEE0SZ0Vo9tLEQk8Tcg_C4HoH45gI,20037
pyOpenRPA/Robot/SettingsTemplate.py,sha256=Rp5XPeV2I4tCS2uf4Zkqm_ERJ6pZMg4-e5_lMqGJYLk,1453
pyOpenRPA/Robot/Test.py,sha256=qXr990nXiFZX5SNv6QN9GLb_U4HZRmJnbZR2qSnwilY,2878
pyOpenRPA/Robot/UIDesktop.py,sha256=MWdWr0dZpk1PL1rsD91q6_8v687CSDBx1_T7IuHd3-E,77473
pyOpenRPA/Robot/Utils/JSONNormalize.py,sha256=aIuVzuZDazhxkCOzoOjfhHVz66mp2FWdfPv5E7KWF5Y,3890
pyOpenRPA/Robot/Utils/ProcessBitness.py,sha256=WlKL-DklGaoTnchtapOTM_ydxSB4yOeo9lcG3zr2VME,4524
pyOpenRPA/Robot/Utils/ProcessCommunicator.py,sha256=8GfmLnOvAdosmt7YNT86uEV9cjhKippssCX62wOMJwM,8039
pyOpenRPA/Robot/Utils/TimerRepeat.py,sha256=_kTct3X9SIEvS3DKM5bGNnjRBVJasmMFZntQaVbPX_E,961
pyOpenRPA/Robot/Utils/ValueVerify.py,sha256=ObskxU4fOMoCGw74_nzYt6-a5jjrAckb3sdBLYyhYxY,777
pyOpenRPA/Robot/Utils/__init__.py,sha256=pHlSQGRFKmn5RCTHIf-3a2ooA9T2xNOWridckynP7W4,28
pyOpenRPA/Robot/Utils/__pycache__/JSONNormalize.cpython-37.pyc,,
pyOpenRPA/Robot/Utils/__pycache__/ProcessBitness.cpython-37.pyc,,
pyOpenRPA/Robot/Utils/__pycache__/ProcessCommunicator.cpython-37.pyc,,
pyOpenRPA/Robot/Utils/__pycache__/TimerRepeat.cpython-37.pyc,,
pyOpenRPA/Robot/Utils/__pycache__/ValueVerify.cpython-37.pyc,,
pyOpenRPA/Robot/Utils/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Robot/ValueVerify.py,sha256=ObskxU4fOMoCGw74_nzYt6-a5jjrAckb3sdBLYyhYxY,777
pyOpenRPA/Robot/Window.py,sha256=UJl-sg4RvvJ35aG9jZOzqGVwE15XK7qPHqoOBD13xFk,431
pyOpenRPA/Robot/__init__.py,sha256=iEW3SGBJf3kYa1zocGH5vEK0woejzJpnQfOmQtIA3P0,324
pyOpenRPA/Robot/__main__.py,sha256=NlwxAG68mwoWNB4YIX15Fc2gWlL1RQ5HN8i1NyjGFdo,1965
pyOpenRPA/Robot/__init__.py,sha256=L-5tPm6evytGWOzlqIq-2oiIhmQnruaxwIstyyaMkVI,253
pyOpenRPA/Robot/__main__.py,sha256=l6II8JuXCsnVOcfs6-2jvogKYTVhbfj3Jl2ld3OIP7s,1992
pyOpenRPA/Robot/__pycache__/Clipboard.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/IntegrationOrchestrator.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/JSONNormalize.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/ProcessCommunicator.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/Robot.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/OrchestratorConnector.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/SettingsTemplate.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/Test.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/UIDesktop.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/ValueVerify.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/Window.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Studio/JSONNormalize.py,sha256=g0Z8G2wojCgTAdZtyRiCfe0_FHSeAi72Va7R7mk27gg,3347
pyOpenRPA/Studio/ProcessCommunicator.py,sha256=5hXDMa4ONBgeJBoDIfDCAW9MoiRO8cq-DdfqQSAysgk,8080
pyOpenRPA/Studio/Studio.py,sha256=7X46k0l33sgQoG6sxFFJmI5G0KKxgDggvEnzux8aonw,7014
pyOpenRPA/Studio/ProcessCommunicator.py,sha256=HD3XASJae31_HV3OznFe8E2MgZFXnwt7YveVN82M8nU,7912
pyOpenRPA/Studio/RobotConnector.py,sha256=tQVC8X0k1HMHAAwAtkhtmeNA0cLMY3wuO-RCbgshdMk,5036
pyOpenRPA/Studio/Studio.py,sha256=wiVGWZZx-yC8jp-Wjz-B5GC1cqTcftDulZfYe-4hU8w,8125
pyOpenRPA/Studio/ValueVerify.py,sha256=ObskxU4fOMoCGw74_nzYt6-a5jjrAckb3sdBLYyhYxY,777
pyOpenRPA/Studio/Web/Index.xhtml,sha256=74z3eWlmB6Yedbp91xgGtDjymUSlBcduAQ09ZxQ67f8,44241
pyOpenRPA/Studio/Web/Index.xhtml,sha256=RqFW3qC1pFRr-qWEEDlCEhL9l3PwANyRbll3KZJnLvo,47927
pyOpenRPA/Studio/Web/favicon.ico,sha256=0vdsnwKGh6pgB0FDB5mOKO7RwbxQ9F13Zg16F1pkvXs,5430
pyOpenRPA/Studio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Studio/__main__.py,sha256=_57Rnq9DKbmmlpGFqIwVrWn_LRcU8jjmMTOny4_zlP8,308
pyOpenRPA/Studio/__pycache__/JSONNormalize.cpython-37.pyc,,
pyOpenRPA/Studio/__pycache__/ProcessCommunicator.cpython-37.pyc,,
pyOpenRPA/Studio/__pycache__/RobotConnector.cpython-37.pyc,,
pyOpenRPA/Studio/__pycache__/Studio.cpython-37.pyc,,
pyOpenRPA/Studio/__pycache__/ValueVerify.cpython-37.pyc,,
pyOpenRPA/Studio/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Studio/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Tools/RobotRDPActive/Connector.py,sha256=vpXFO1irhLTHgIwWn5PCsTq-6E3Sx3sYOweIBNyiYEw,6164
pyOpenRPA/Tools/RobotRDPActive/Monitor.py,sha256=INkiX4Gi4KjvWRoe4jWV_NJGKgjDId6zEyqBHpegUxw,760
pyOpenRPA/Tools/RobotRDPActive/SettingsExample.py,sha256=5eEhjk7NDXf9Q4yvkeRICE7x9npiMkazuMITQX24Ooc,857
pyOpenRPA/Tools/RobotRDPActive/Connector.py,sha256=9Y9zA92Zw9QF6dadW53NLekV_1r2STISFn5RzI08GDo,7272
pyOpenRPA/Tools/RobotRDPActive/Monitor.py,sha256=X8ZhJFdDnA88OHlgRuinPvhZ_eS4R7y0xRchbo7LPCc,1525
pyOpenRPA/Tools/RobotRDPActive/Template.rdp,sha256=qPCLkjzTdYKURK7nRApkPUjRuS4K20vDPj9DIUNSSkE,2392
pyOpenRPA/Tools/RobotRDPActive/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Tools/RobotRDPActive/__main__.py,sha256=qC_LyXI2MjJkidTRpV3abyyPO0qASGTvNkeAkfnA7J0,2108
pyOpenRPA/Tools/RobotRDPActive/__main__.py,sha256=mVk8zVqcBrzAwwn7tbZPXFWTQbWUkgU6w89nbY6GN-8,2340
pyOpenRPA/Tools/RobotRDPActive/__pycache__/Connector.cpython-37.pyc,,
pyOpenRPA/Tools/RobotRDPActive/__pycache__/Monitor.cpython-37.pyc,,
pyOpenRPA/Tools/RobotRDPActive/__pycache__/SettingsExample.cpython-37.pyc,,
pyOpenRPA/Tools/RobotRDPActive/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Tools/RobotRDPActive/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Tools/RobotScreenActive/ConsoleStart.bat,sha256=_HNadUKHOYI5y6foG3srh8wjSzhX33xaKNylFtDjOJk,114
@ -251,5 +255,5 @@ pyOpenRPA/Tools/RobotScreenActive/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Tools/RobotScreenActive/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Tools/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/__init__.py,sha256=mqY50pRbV4Tk-vj2-Z2CiY8u2qSB0HRfKNcduM36Zdo,175
pyOpenRPA/__init__.py,sha256=6g2t0dHUhbsJm87H07rs_6y5XDub0C_nWd2B-w-0XGg,175
pyOpenRPA/__pycache__/__init__.cpython-37.pyc,,

@ -15,11 +15,6 @@ import copy
#from .Settings import Settings
import importlib
from importlib import util
#Создать файл логирования
# add filemode="w" to overwrite
if not os.path.exists("Reports"):
os.makedirs("Reports")
logging.basicConfig(filename="Reports\ReportRun_"+datetime.datetime.now().strftime("%Y_%m_%d__%H_%M_%S")+".log", level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
#Единый глобальный словарь (За основу взять из Settings.py)
global mGlobalDict
@ -51,6 +46,8 @@ lDaemonStartDateTime=datetime.datetime.now()
#Инициализация сервера
lThreadServer = Server.RobotDaemonServer("ServerThread", mGlobalDict)
lThreadServer.start()
#Logging
mGlobalDict["Logger"].info("Scheduler loop init")
#Вечный цикл
while True:
lCurrentDateTime = datetime.datetime.now()

@ -104,28 +104,31 @@ def Activity(inActivity):
#Обработка команды GlobalDictKeyListValueSet
###########################################################
if lItem["Type"]=="GlobalDictKeyListValueSet":
lDict = mGlobalDict
for lItem2 in lItem["KeyList"][:-1]:
#Check if key - value exists
if lItem2 in mGlobalDict:
if lItem2 in lDict:
pass
else:
mGlobalDict[lItem2]={}
mGlobalDict=mGlobalDict[lItem2]
lDict[lItem2]={}
lDict=lDict[lItem2]
#Set value
mGlobalDict[lItem["KeyList"][-1]]=lItem["value"]
lDict[lItem["KeyList"][-1]]=lItem["Value"]
lItem["Result"] = True
###########################################################
#Обработка команды GlobalDictKeyListValueGet
###########################################################
if lItem["Type"]=="GlobalDictKeyListValueGet":
lDict = mGlobalDict
for lItem2 in lItem["KeyList"][:-1]:
#Check if key - value exists
if lItem2 in mGlobalDict:
if lItem2 in lDict:
pass
else:
mGlobalDict[lItem2]={}
mGlobalDict=mGlobalDict[lItem2]
lDict[lItem2]={}
lDict=lDict[lItem2]
#Return value
lItem["Result"]==mGlobalDict.get(lItem["KeyList"][-1],None)
lItem["Result"]=lDict.get(lItem["KeyList"][-1],None)
#Определить вид активности
lActivityDateTime=inActivity["DateTimeUTCStringStart"]
#####################################
@ -193,6 +196,7 @@ def Activity(inActivity):
##################
#Trace activity
##################
#print(mGlobalDict)
if mGlobalDict["Processor"].get(f"LogType_{lItem['Type']}",True):
#Add activity in TransactionList if it is applicable
mGlobalDict["Processor"]["LogList"].append(copy.deepcopy(lItem))

@ -22,12 +22,14 @@ class RobotDaemonServer(Thread):
def run(self):
inServerAddress="";
inPort = mGlobalDict["Server"]["ListenPort"];
print('starting server..., port:'+str(inPort)+" inAddress:"+inServerAddress)
# Server settings
# Choose port 8080, for port 80, which is normally used for a http server, you need root access
server_address = (inServerAddress, inPort)
httpd = HTTPServer(server_address, testHTTPServer_RequestHandler)
print('running server...')
# Logging
mGlobalDict["Logger"].info(f"Server init. Listen URL: {inServerAddress}, Listen port: {inPort}")
# Запуск адреса в браузере
os.system("explorer http://127.0.0.1:8081")
httpd.serve_forever()
#Authenticate function ()
@ -86,6 +88,7 @@ def AuthenticateVerify(inRequest):
mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken] = {}
mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["Domain"] = lResult["Domain"]
mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["User"] = lResult["User"]
mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["FlagDoNotExpire"] = False
mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["TokenDatetime"] = datetime.datetime.now()
#Set-cookie
inRequest.OpenRPA["AuthToken"] = lAuthToken
@ -110,6 +113,7 @@ def AuthenticateBlock(inRequest):
#return bool True - go execute, False - dont execute
def UserAccessCheckBefore(inMethod, inRequest):
# Help def - Get access flag from dict
#pdb.set_trace()
def HelpGetFlag(inAccessRuleItem, inRequest, inGlobalDict, inAuthenticateDict):
if "FlagAccess" in inAccessRuleItem:
return inAccessRuleItem["FlagAccess"]
@ -300,6 +304,8 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
lAuthenticateDict = AuthenticateVerify(self)
if not lAuthenticateDict["User"]:
lFlagAccessUserBlock=True
# Logging
mGlobalDict["Logger"].info(f"HTTP request /. Domain: {lAuthenticateDict['Domain']}, User: {lAuthenticateDict['User']}")
if lFlagAccessUserBlock:
AuthenticateBlock(self)
#####################################
@ -321,7 +327,6 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
lFlagURLIsApplied=False
lFlagURLIsApplied=self.URLItemCheckDo(lURLItem, "GET")
if lFlagURLIsApplied:
#print("New engine")
self.ResponseDictSend()
return
#Monitor
@ -350,6 +355,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# POST
def do_POST(self):
# Prepare result dict
#pdb.set_trace()
lResponseDict = {"Headers": {}, "SetCookies":{}, "Body": "", "StatusCode": None}
self.OpenRPAResponseDict = lResponseDict
#####################################
@ -371,7 +377,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
lFlagUserAccess = True
#If need user authentication
if mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False):
lFlagUserAccess = UserAccessCheckBefore("GET", self)
lFlagUserAccess = UserAccessCheckBefore("POST", self)
######################################
if lFlagUserAccess:
#Централизованная функция получения запросов/отправки
@ -393,3 +399,10 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# Write content as utf-8 data
self.wfile.write(bytes(message, "utf8"))
return
else:
#Set access denied code
# Send response status code
self.send_response(403)
# Send headers
self.end_headers()
return

@ -16,7 +16,6 @@ def Monitor_ControlPanelDictGet(inRequest,inGlobalDict):
# Send message back to client
message = json.dumps(lResultJSON)
# Write content as utf-8 data
#print(bytes(message, "utf8"))
inResponseDict["Body"] = bytes(message, "utf8")
def GetScreenshot(inRequest,inGlobalDict):

@ -275,8 +275,8 @@
});
}
///
mGlobal.Monitor.mControlPanelAutoUpdateSeconds=5;
mGlobal.Monitor.mControlPanelAutoUpdateSecondsCurrent=5;
mGlobal.Monitor.mControlPanelAutoUpdateSeconds=3;
mGlobal.Monitor.mControlPanelAutoUpdateSecondsCurrent=3;
mGlobal.Monitor.fControlPanelAutoUpdateRun=function(inRefreshSeconds) {
mGlobal.Monitor.mControlPanelAutoUpdateSeconds=inRefreshSeconds;
//Функция обновления текста кнопки обновления
@ -291,7 +291,7 @@
mGlobal.Monitor.mControlPanelAutoUpdateTimerId=setInterval(lControlPanelUpdate,1000)
}
mGlobal.Monitor.fControlPanelRefresh()
mGlobal.Monitor.fControlPanelAutoUpdateRun(5);
mGlobal.Monitor.fControlPanelAutoUpdateRun(3);
mGlobal.Test=function() {
///Обнулить таблицу
@ -355,6 +355,29 @@
///////////////////////////////
mGlobal.Processor = {}
mGlobal.Processor.ServerValueSet = function(inKeyList,inValue) {
lData = [
{
"Type":"GlobalDictKeyListValueSet",
"KeyList": inKeyList,
"Value": inValue
}
]
///Обнулить таблицу
$('.ui.modal.basic .content').html("");
$.ajax({
type: "POST",
url: 'Utils/Processor',
data: JSON.stringify(lData),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
///TODO Show error if exist error
},
dataType: "text"
});
}
mGlobal.Processor.LogListShow = function() {
lData = [
{
@ -633,7 +656,7 @@
<div class="ui basic {{Color}} button" onclick="{{OnClick}}">{{{Text}}}</div>
{{/FooterButtonX2List}}
</div>
<div class="ui horizontal divider">Доп. управление</div>
<div class="ui horizontal divider">Add. controls</div>
<div class="ui one buttons">
{{#FooterButtonX1List}}
<div class="ui basic {{Color}} button" onclick="{{OnClick}}">{{{Text}}}</div>

@ -1,46 +0,0 @@
import requests
import grequests
#from requests import async
import json
###################################
##Orchestrator integration module (safe use when orchestrator is turned off)
###################################
################################################################################
#Send data to orchestrator (asynchronyous)
#Example: t=IntegrationOrchestrator.DataSend(["Storage","Robot_R01"],{"RunDateTimeString":"Test1","StepCurrentName":"Test2","StepCurrentDuration":"Test333","SafeStopSignal":True},"localhost",8081)
def DataSend(inKeyList,inValue,inOrchestratorHost="localhost",inOrchestratorPort=80):
lURL = f'http://{inOrchestratorHost}:{inOrchestratorPort}/ProcessingRun'
lDataJSON = {"actionList":[{"type":"AdministrationGlobalDictSetKeyListValue","key_list":inKeyList,"value":inValue}]}
#lAsyncList = []
lResultItem = [grequests.post(lURL, json=lDataJSON)]
return grequests.map(lResultItem)
#lAsyncList.append(lResultItem)
#return async.map(lAsyncList)
################################################################################
#recieve Data from orchestrator
#t=IntegrationOrchestrator.DataRecieve(["Storage","Robot_R01"],"localhost",8081)
def DataRecieve(inKeyList,inOrchestratorHost="localhost",inOrchestratorPort=80):
lURL = f'http://{inOrchestratorHost}:{inOrchestratorPort}/ProcessingRun'
lDataJSON = {"actionList":[{"type":"AdministrationGlobalDictGetKeyListValue","key_list":inKeyList}]}
try:
lResult = requests.post(lURL, json=lDataJSON)
lResultJSON = json.loads(lResult.text)
return lResultJSON["actionListResult"][0]["value"]
except Exception:
return None
################################################################################
#Check if orchestrator has safe stop signal
#Example: IntegrationOrchestrator.SafeStopSignalIs(["Storage","Robot_R01","SafeStopSignal"],"localhost",8081)
def SafeStopSignalIs(inKeyList,inOrchestratorHost="localhost",inOrchestratorPort=80):
lResult=False
lResponse=DataRecieve(inKeyList,inOrchestratorHost,inOrchestratorPort)
if lResponse is not None:
lResult = lResponse
return lResult
################################################################################
#Reset SafeStop signal in orchestrator
#Example: t=IntegrationOrchestrator.SafeStopSignalReset(["Storage","Robot_R01","SafeStopSignal"],"localhost",8081)
def SafeStopSignalReset(inKeyList,inOrchestratorHost="localhost",inOrchestratorPort=80):
lResponse=DataSend(inKeyList,False,inOrchestratorHost,inOrchestratorPort)
return lResponse

@ -0,0 +1,401 @@
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"]
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

@ -1,159 +0,0 @@
import pdb
import json
import subprocess
import zlib
import os
from . import ProcessCommunicator
import importlib
import traceback
import logging
import sys
import datetime
import struct
import shutil
#Создать файл логирования
# add filemode="w" to overwrite
if not os.path.exists("Reports"):
os.makedirs("Reports")
logging.basicConfig(filename="Reports\ReportRobotRun_"+datetime.datetime.now().strftime("%Y_%m_%d")+".log", level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
####################################
#Info: Main module of the Robot app (OpenRPA - Robot)
####################################
#Usage:
#Here you can run some activity or list of activities
#After import this module you can use the folowing functions:
#ActivityRun(inActivitySpecificationDict): outActivityResultDict - function - run activity (function or procedure)
#ActivityRunJSON(inActivitySpecificationDictJSON): outActivityResultDictJSON
#ActivityListRun(inActivitySpecificationDictList): outActivityResultDictList - function - run list of activities (function or procedure)
#ActivityListRunJSON(inActivitySpecificationDictListJSON): outActivityResultDictListJSON
#Naming:
#Activity - some action/list of actions
#Module - Any *.py file, which consist of area specific functions
#Argument
#inActivitySpecificationDict:
#{
# ModuleName: <"GUI"|..., str>,
# ActivityName: <Function or procedure name in module, str>,
# ArgumentList: [<Argument 1, any type>, ...] - optional,
# ArgumentDict: {<Argument 1 name, str>:<Argument 1 value, any type>, ...} - optional
#}
#outActivityResultDict:
#{
# ActivitySpecificationDict: {
# ModuleName: <"GUI"|..., str>,
# ActivityName: <Function or procedure name in module, str>,
# ArgumentList: [<Argument 1, any type>, ...] - optional,
# ArgumentDict: {<Argument 1 name, str>: <Argument 1 value, any type>, ...} - optional
# },
# ErrorFlag: <Boolean flag - Activity result has error (true) or not (false), boolean>,
# ErrorMessage: <Error message, str> - required if ErrorFlag is true,
# ErrorTraceback: <Error traceback log, str> - required if ErrorFlag is true,
# Result: <Result, returned from the Activity, int, str, boolean, list, dict> - required if ErrorFlag is false
#}
####################
#Section: Module initialization
####################
#Start childprocess - GUI Module 32 bit
#pdb.set_trace()
if not os.path.isfile("..\\Resources\\WPy32-3720\\python-3.7.2\\OpenRPARobotGUIx32.exe"):
shutil.copyfile('..\\Resources\\WPy32-3720\\python-3.7.2\\python.exe',"..\\Resources\\WPy32-3720\\python-3.7.2\\OpenRPARobotGUIx32.exe")
mProcessGUI_x32 = subprocess.Popen(['..\\Resources\\WPy32-3720\\python-3.7.2\\OpenRPARobotGUIx32.exe',"-m",'pyOpenRPA.Robot'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
#Start childprocess - GUI Module 64 bit - uncomment after WPy64 installation
ProcessCommunicator.ProcessChildSendObject(mProcessGUI_x32,{"ModuleName":"UIDesktop","ActivityName":"Get_OSBitnessInt","ArgumentList":[],"ArgumentDict":{}})
lOSBitness = ProcessCommunicator.ProcessChildReadWaitObject(mProcessGUI_x32)["Result"]
lProcessBitnessStr = str(struct.calcsize("P") * 8)
#start 64 if system support 64
mProcessGUI_x64 = None
if lOSBitness == 64:
if not os.path.isfile("..\\Resources\\WPy64-3720\\python-3.7.2.amd64\\OpenRPARobotGUIx64.exe"):
shutil.copyfile('..\\Resources\\WPy64-3720\\python-3.7.2.amd64\\python.exe',"..\\Resources\\WPy64-3720\\python-3.7.2.amd64\\OpenRPARobotGUIx64.exe")
mProcessGUI_x64 = subprocess.Popen(['..\\Resources\\WPy64-3720\\python-3.7.2.amd64\\OpenRPARobotGUIx64.exe',"-m",'pyOpenRPA.Robot'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
####################
#Section: Activity
####################
def ActivityRun(inActivitySpecificationDict):
#Выполнить отправку в модуль UIDesktop, если ModuleName == "UIDesktop"
#pdb.set_trace()
if inActivitySpecificationDict["ModuleName"] == "UIDesktop":
if "ArgumentList" not in inActivitySpecificationDict:
inActivitySpecificationDict["ArgumentList"]=[]
if "ArgumentDict" not in inActivitySpecificationDict:
inActivitySpecificationDict["ArgumentDict"]={}
#Если mProcessGUI_x64 не инициализирован
lFlagRun64=True
if mProcessGUI_x64 is None:
lFlagRun64=False
else:
if inActivitySpecificationDict["ActivityName"]=="UIOSelectorsSecs_WaitAppear_List":
#Функция ожидания появления элементов (тк элементы могут быть недоступны, неизвестно в каком фреймворке каждый из них может появиться)
lFlagRun64=True
elif inActivitySpecificationDict["ActivityName"].startswith("UIOSelector") or inActivitySpecificationDict["ActivityName"].startswith("PWASpecification"):
if len(inActivitySpecificationDict["ArgumentList"])>0:
if len(inActivitySpecificationDict["ArgumentList"][0])>0:
#Определение разрядности (32 и 64) для тех функций, где это необходимо
######################################################
#Выполнить проверку разрядности через UIOSelector_Get_BitnessInt
#Отправить запрос в дочерний процесс, который отвечает за работу с Windows окнами
#pdb.set_trace()
#Внимание! Проверка разрядности специально делается на процессе 64 бита, тк процесс 32 бита зависает на 35 итерации проверки
ProcessCommunicator.ProcessChildSendObject(mProcessGUI_x64,{"ModuleName":"UIDesktop","ActivityName":"UIOSelector_Get_BitnessInt","ArgumentList":[inActivitySpecificationDict["ArgumentList"][0]],"ArgumentDict":inActivitySpecificationDict["ArgumentDict"]})
#Получить ответ от дочернего процесса
lResponseObject=ProcessCommunicator.ProcessChildReadWaitObject(mProcessGUI_x64)
#pdb.set_trace()
if lResponseObject["Result"]==32:
lFlagRun64=False
#Запуск 64
#pdb.set_trace()
if lFlagRun64:
#Отправить запрос в дочерний процесс, который отвечает за работу с Windows окнами
ProcessCommunicator.ProcessChildSendObject(mProcessGUI_x64,inActivitySpecificationDict)
#Получить ответ от дочернего процесса
lResponseObject=ProcessCommunicator.ProcessChildReadWaitObject(mProcessGUI_x64)
else:
#Запуск 32
#Отправить запрос в дочерний процесс, который отвечает за работу с Windows окнами
ProcessCommunicator.ProcessChildSendObject(mProcessGUI_x32,inActivitySpecificationDict)
#Получить ответ от дочернего процесса
lResponseObject=ProcessCommunicator.ProcessChildReadWaitObject(mProcessGUI_x32)
#Остальные модули подключать и выполнять здесь
else:
lArgumentList=[]
if "ArgumentList" in inActivitySpecificationDict:
lArgumentList=inActivitySpecificationDict["ArgumentList"]
lArgumentDict={}
if "ArgumentDict" in inActivitySpecificationDict:
lArgumentDict=inActivitySpecificationDict["ArgumentDict"]
#Подготовить результирующую структуру
lResponseObject={"ActivitySpecificationDict":inActivitySpecificationDict,"ErrorFlag":False}
try:
#Подключить модуль для вызова
lModule=importlib.import_module(inActivitySpecificationDict["ModuleName"])
#Найти функцию
lFunction=getattr(lModule,inActivitySpecificationDict["ActivityName"])
#Выполнить вызов и записать результат
lResponseObject["Result"]=lFunction(*lArgumentList,**lArgumentDict)
except Exception as e:
#Установить флаг ошибки и передать тело ошибки
lResponseObject["ErrorFlag"]=True
lResponseObject["ErrorMessage"]=str(e)
lResponseObject["ErrorTraceback"]=traceback.format_exc()
return lResponseObject
#########################################################
#Run list of activities
#########################################################
def ActivityListRun(inActivitySpecificationDictList):
lResult=[]
for lItem in inActivitySpecificationDictList:
lResult.append(ActivityRun(lItem))
return lResult

@ -0,0 +1,34 @@
import logging
import datetime
#Robot settings
def Settings():
import os
mDict = {
"Logger": logging.getLogger("Robot"),
"Storage": {
"Robot_R01_help": "Robot data storage in orchestrator env",
"Robot_R01": {}
},
"ProcessBitness": {
"Python32FullPath": None, #Set from user: "..\\Resources\\WPy32-3720\\python-3.7.2\\OpenRPARobotGUIx32.exe"
"Python64FullPath": None, #Set from user
"Python32ProcessName": "OpenRPAUIDesktopX32.exe", #Config set once
"Python64ProcessName": "OpenRPAUIDesktopX64.exe" #Config set once
}
}
#Создать файл логирования
# add filemode="w" to overwrite
if not os.path.exists("Reports"):
os.makedirs("Reports")
##########################
#Подготовка логгера Robot
#########################
mRobotLogger=mDict["Logger"]
mRobotLogger.setLevel(logging.INFO)
# create the logging file handler
mRobotLoggerFH = logging.FileHandler("Reports\ReportRobot_"+datetime.datetime.now().strftime("%Y_%m_%d")+".log")
mRobotLoggerFormatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
mRobotLoggerFH.setFormatter(mRobotLoggerFormatter)
# add handler to logger object
mRobotLogger.addHandler(mRobotLoggerFH)
############################################

@ -0,0 +1,65 @@
import unittest
from threading import Timer
import sys
lFolderPath = "/".join(__file__.split("\\")[:-3])
sys.path.insert(0, lFolderPath)
from pyOpenRPA.Robot import OrchestratorConnector
from pyOpenRPA.Robot import Utils
class MyTestCase(unittest.TestCase):
def test_something(self):
#self.assertEqual(True, False)
mGlobal={"Storage":{"R01_OrchestratorToRobot":{"Test":"Test2"}}}
# t=OrchestratorConnector.IntervalDataSendAsync(
# Interval=1,
# RobotStorage=mGlobal["Storage"],
# RobotStorageKey="R01_OrchestratorToRobot",
# OrchestratorKeyList=["Storage", "R01_OrchestratorToRobot"],
# OrchestratorProtocol="http",
# OrchestratorHost="localhost",
# OrchestratorPort=8081,
# OrchestratorAuthToken="1992-04-03-0643-ru-b4ff-openrpa52zzz"
# )
# t=OrchestratorConnector.DataSendSync(
# RobotValue="Test",
# OrchestratorKeyList=["Storage", "R01_OrchestratorToRobot"],
# OrchestratorProtocol="http",
# OrchestratorHost="localhost",
# OrchestratorPort=8081,
# OrchestratorAuthToken="1992-04-03-0643-ru-b4ff-openrpa52zzz"
# )
import time
#def Func(lT,inl):
# print(lT)
# return True
#lTimer= Utils.TimerRepeat.TimerRepeat(1, Func, ["dddd"],{"inl":9})
#lTimer.start()
OrchestratorConnector.ConfigurationInit({
"IntervalDataSendResetAsync": [
{
"Interval": 2,
"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"
}
]
})
while True:
print(mGlobal["Storage"]["R01_OrchestratorToRobot"])
# t = OrchestratorConnector.DataSendResetAsync(
# 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"
# )
time.sleep(0.5)
if __name__ == '__main__':
unittest.main()

@ -1,44 +1,18 @@
from pywinauto import win32defines, win32structures, win32functions
import pdb
import pywinauto
import json
import sys
import ctypes
import struct
import os
import select
import zlib
import win32api
import win32clipboard
import time
import traceback
from . import ProcessCommunicator
from . import JSONNormalize
from .Utils import ProcessCommunicator
from . import Utils #For ProcessBitness
from threading import Timer
import datetime
import logging
import re
import copy
#Создать файл логирования
# add filemode="w" to overwrite
if not os.path.exists("Reports"):
os.makedirs("Reports")
##########################
#Подготовка логгера Robot
#########################
mRobotLogger=logging.getLogger("RobotLogger")
mRobotLogger.setLevel(logging.INFO)
# create the logging file handler
mRobotLoggerFH = logging.FileHandler("Reports\ReportRobotGUIRun_"+datetime.datetime.now().strftime("%Y_%m_%d")+".log")
mRobotLoggerFormatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
mRobotLoggerFH.setFormatter(mRobotLoggerFormatter)
# add handler to logger object
mRobotLogger.addHandler(mRobotLoggerFH)
############################################
# When import UIDesktop init the other bitness python
#For this type UIDesktop.Utils.ProcessBitness.SettingsInit(inSettingsDict)
# For this type
# UIDesktop.Utils.ProcessBitness.SettingsInit(inSettingsDict)
# inSettingsDict = {
# "Python32FullPath": None, #Set from user: "..\\Resources\\WPy32-3720\\python-3.7.2\\OpenRPARobotGUIx32.exe"
# "Python64FullPath": None, #Set from user

@ -1,10 +1,9 @@
import json
import subprocess
import zlib
import sys
import os
from . import JSONNormalize
import pdb
############################################
####Межпроцессное взаимодействие
############################################
@ -41,7 +40,6 @@ def ProcessParentWriteString(lString):
#Вернуть \f
lByteString = lByteString.replace(b'\f',b'{{{f}}}')
############################
#print(b"Result: "+lByteString)
#lByteString= b'x\x9c\xdd\x95]O\xc20\x14\x86\xffJ\xb3[5\xa1Cqz\x07\xc4\xe8\x8d\x1fQ\x13.\x0cYJw\xb6U\xbav\xe9\xce"\x84\xf0\xdfm\'"\xb8\xa0L%Q\xb3\x9b\xf6=\xdfO\x9a\xb3\x99\x17\x97\x8a\xa3\xd0\xea\x8ae\xe0\x9d\x12\xaf[\xa2\xce\x98S\xee\x80\x19\x9e^\xea\xb2\x803\t\x19(\xbc\x10`\x9c6\xf5\xf6\x89\xc7LRt\x8daS\x1b\xf5\xf00\xf3\xd4"\xc1u\x0e\xea\xf6\xa6K\x0e\xc8\xb9\xd6\x89\x04\xd2O\x8d\xb6&\x1bb\x04OC\x84\t~\xe2\x97\x1b\xcd\xa1(B\x11YG\xdaj\xfb\xc1\x9b\xb8\xa2\xa4LE\xd2\xd5\xa4\xf6\xdenY\x85Kf\xc3^;yI\x18\x0eD\x94\x00\x0e\x84{{n}}\xa9K\xce\xb5B\xa3e\x88\xd3\xbc\xf2Z\xd5\xaa\x82\xaa\x94\xd25\x0b\x1c\x99J\xaa\x023OB\xec\xbavEP\xe7\x8b\x93\x11I\xeaTz\xe2\xbb\xebH\xa3eW5\xe8\xb7\xe6\xce^*\x14\xb6\x83e\xda\xf9phe]b^\xe2\xf5\xe8\xd1Vp\xf0\xfe.\xbb\x1b\xa6`\x87\xfc8\x1a\x9bSE0q\xa2\x15\xeer\xe0"\x16\xbcz\x9f\xfdT\xc8h\x9d\xdf\xc7\xd4\xbe\xcdj1\xd9:\xa9\x1f\xe1B7\x81\xa1\xef\xc0\xd0:\x98\xc3-\xc0\xd4X\xfc\xda\xf1i\xbb\xe9\xfc\xdb<\x8c\xff2\x7f\'\xa8\x8d\xdf\xdab\xfc\x9e\xd6\xe3\x8c\x99qQ\xe3\xb0f\xd9\x19\x90{\xade\x8f\x99/3\xa1AC(\xfe\x16P\x06F \x90\xb3\t\x07Iba\x17\x83P\xa4\xbf\xb7G\x9e\x04\xa6vE\x13\xb6\xfc\x13\xd6\xa85\x0b\xdd\x19\xd6^i\x11\xa8FT;G\xfe\x06\xac\xc1q\xb0N\x956\xd84\xae\xe4p\xbe\xfa=\x03\x01\xce\x95\x9a'
#lByteString = b"x\x9c\xb5\x91\xcfO\xc3 \x14\xc7\xff\x95\xa6\xd7uI\xf9Q\x8a\xde\xd4\x93\x07\xbdx\xf00\x97\x05)[I(\x90\x8ef3\xcb\xfew\x81M\xbb\xd9M]\x8c!y\xd0\xf7}\xbc\xef\xe3\xd3\xc9&\xd5\xac\x11\xe9u\x92j\xb1J@2N\x1e\x8d\x13\x96U\xa3Q\x9a%i+y=sb\xed\xceV\xd8\xd6p\xb1\\\xced\xe5K{{n}}\x80`\x9f\xeb\x135\xd3\x95{{n}}.\x08RR\xe4>\xc3\x15\xf3\x97>\xbc\x8f:r\xa3]k\xd4\xcc\xbd\xd9(>K]\x99\xd5\xa1\x12\xbd\x00\xc6\xb0\xcc\xcb0\xa4\xe0\x8e\xe9E4\xd8\xa4J\xcc\xc3\xb44\x07^r\xc6\xfa3\x04(\xbeeQ\x07\x05P\x1a\xa4W\xe3\x9ci\xfc\xf7\x15(\xb6A\xee\xb4\x93\x8d\xd85\x9f`?\xf6n\xd8i0v\xadw\xd5\x95X\x87n>\xf1d\x05\x97s\xc9\x99\x93F\xdf\xd5R\xc5K=\xcc\x1bk\xd5^\x1d`\xfc\xa2]\x06PwJ\r\xf0\x9d\xa2\xf6 tw\xcb\xda\x01\xb6}\x83\xd3\xcc\x00\xec\x99\x15\xf4\x88Y\x99\x1f2\x83\xb4\xfc\x8e\x99\xdf\xb3d\x0c\x01.1E\x04\x93l\xff\x8e\xcf\x7f6\xa4Z\xfc\x82\xeaK\x97c BD\xf3\x101\x89g\xba\x8b\x03\xd0?\x97\xff#\xfb{'\x9a\x8b\xe0\x03H\xc89\xfa\x08\x15\x7f\xa2\x0f >\x80_\x0e\xe0\x93\xb3\xf0\xc3\xc4\xd3m\\\xef\xf8\x958\xa0"
#lt=open("logSendByteStringWithoutN.log","wb")
@ -71,7 +69,6 @@ def ProcessChildSendString(lProcess,lString):
lByteString = lByteString.replace(b'\n',b'{{n}}')
#Отправить сообщение в дочерний процесс
lProcess.stdin.write(lByteString+bytes('\n',"utf-8"))
#print(str(lByteString+bytes('\n',"utf-8")))
lProcess.stdin.flush()
#Вернуть результат
return
@ -82,7 +79,6 @@ def ProcessChildReadWaitString(lProcess):
#pdb.set_trace()
lResult = lProcess.stdout.readline()
#Обработка спец символов
#print(b'NewLine: '+lResult)
#Вернуть потенциальные \n
lResult = lResult.replace(b'{{{n}}}',b'\n')
#Вернуть \r
@ -99,8 +95,6 @@ def ProcessChildReadWaitString(lProcess):
lResult = lResult.replace(b'{{{v}}}',b'\v')
#Вернуть \f
lResult = lResult.replace(b'{{{f}}}',b'\f')
#print("check")
#print(str(lResult))
try:
lResult = zlib.decompress(lResult[0:-1])
lResult = lResult.decode("utf-8")

@ -0,0 +1,28 @@
from threading import Timer
import datetime
# lTimer = RepeatedTimer(3, def, [], {}) # it auto-starts, no need of rt.start()
# if def return None = timer stops
# lTimer.start()
class TimerRepeat(object):
def __init__(self, interval, function, args, kwargs):
self._timer = None
self.interval = interval
self.function = function
self.args = args
self.kwargs = kwargs
self.is_running = False
self.start()
def _run(self):
self.is_running = False
lResult = self.function(*self.args, **self.kwargs)
if lResult is not None:
if lResult:
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

@ -4,10 +4,9 @@ The OpenRPA package (from UnicodeLabs)
"""
__all__ = [
'UIDesktop', 'Clipboard', 'IntegrationOrchestrator', 'Window', 'ProcessCommunicator'
'Clipboard', 'OrchestratorConnector.py', 'Window'
]
__author__ = 'Ivan Maslov <ivan.maslov@unicodelabs.ru>'
#from . import UIDesktop
from . import Clipboard
from . import Window
from . import ProcessCommunicator

@ -8,8 +8,8 @@ lFolderPath = "\\".join(__file__.split("\\")[:-2])
sys.path.append(lFolderPath)
################################
import traceback
from Robot import ProcessCommunicator
from Robot import JSONNormalize
from Robot.Utils import ProcessCommunicator
from Robot.Utils import JSONNormalize
from Robot import UIDesktop
##########################################
#Run UIDesktop from new process. Communication with paren process by PIPE channel

@ -40,7 +40,6 @@ def ProcessParentWriteString(lString):
#Вернуть \f
lByteString = lByteString.replace(b'\f',b'{{{f}}}')
############################
#print(b"Result: "+lByteString)
#lByteString= b'x\x9c\xdd\x95]O\xc20\x14\x86\xffJ\xb3[5\xa1Cqz\x07\xc4\xe8\x8d\x1fQ\x13.\x0cYJw\xb6U\xbav\xe9\xce"\x84\xf0\xdfm\'"\xb8\xa0L%Q\xb3\x9b\xf6=\xdfO\x9a\xb3\x99\x17\x97\x8a\xa3\xd0\xea\x8ae\xe0\x9d\x12\xaf[\xa2\xce\x98S\xee\x80\x19\x9e^\xea\xb2\x803\t\x19(\xbc\x10`\x9c6\xf5\xf6\x89\xc7LRt\x8daS\x1b\xf5\xf00\xf3\xd4"\xc1u\x0e\xea\xf6\xa6K\x0e\xc8\xb9\xd6\x89\x04\xd2O\x8d\xb6&\x1bb\x04OC\x84\t~\xe2\x97\x1b\xcd\xa1(B\x11YG\xdaj\xfb\xc1\x9b\xb8\xa2\xa4LE\xd2\xd5\xa4\xf6\xdenY\x85Kf\xc3^;yI\x18\x0eD\x94\x00\x0e\x84{{n}}\xa9K\xce\xb5B\xa3e\x88\xd3\xbc\xf2Z\xd5\xaa\x82\xaa\x94\xd25\x0b\x1c\x99J\xaa\x023OB\xec\xbavEP\xe7\x8b\x93\x11I\xeaTz\xe2\xbb\xebH\xa3eW5\xe8\xb7\xe6\xce^*\x14\xb6\x83e\xda\xf9phe]b^\xe2\xf5\xe8\xd1Vp\xf0\xfe.\xbb\x1b\xa6`\x87\xfc8\x1a\x9bSE0q\xa2\x15\xeer\xe0"\x16\xbcz\x9f\xfdT\xc8h\x9d\xdf\xc7\xd4\xbe\xcdj1\xd9:\xa9\x1f\xe1B7\x81\xa1\xef\xc0\xd0:\x98\xc3-\xc0\xd4X\xfc\xda\xf1i\xbb\xe9\xfc\xdb<\x8c\xff2\x7f\'\xa8\x8d\xdf\xdab\xfc\x9e\xd6\xe3\x8c\x99qQ\xe3\xb0f\xd9\x19\x90{\xade\x8f\x99/3\xa1AC(\xfe\x16P\x06F \x90\xb3\t\x07Iba\x17\x83P\xa4\xbf\xb7G\x9e\x04\xa6vE\x13\xb6\xfc\x13\xd6\xa85\x0b\xdd\x19\xd6^i\x11\xa8FT;G\xfe\x06\xac\xc1q\xb0N\x956\xd84\xae\xe4p\xbe\xfa=\x03\x01\xce\x95\x9a'
#lByteString = b"x\x9c\xb5\x91\xcfO\xc3 \x14\xc7\xff\x95\xa6\xd7uI\xf9Q\x8a\xde\xd4\x93\x07\xbdx\xf00\x97\x05)[I(\x90\x8ef3\xcb\xfew\x81M\xbb\xd9M]\x8c!y\xd0\xf7}\xbc\xef\xe3\xd3\xc9&\xd5\xac\x11\xe9u\x92j\xb1J@2N\x1e\x8d\x13\x96U\xa3Q\x9a%i+y=sb\xed\xceV\xd8\xd6p\xb1\\\xced\xe5K{{n}}\x80`\x9f\xeb\x135\xd3\x95{{n}}.\x08RR\xe4>\xc3\x15\xf3\x97>\xbc\x8f:r\xa3]k\xd4\xcc\xbd\xd9(>K]\x99\xd5\xa1\x12\xbd\x00\xc6\xb0\xcc\xcb0\xa4\xe0\x8e\xe9E4\xd8\xa4J\xcc\xc3\xb44\x07^r\xc6\xfa3\x04(\xbeeQ\x07\x05P\x1a\xa4W\xe3\x9ci\xfc\xf7\x15(\xb6A\xee\xb4\x93\x8d\xd85\x9f`?\xf6n\xd8i0v\xadw\xd5\x95X\x87n>\xf1d\x05\x97s\xc9\x99\x93F\xdf\xd5R\xc5K=\xcc\x1bk\xd5^\x1d`\xfc\xa2]\x06PwJ\r\xf0\x9d\xa2\xf6 tw\xcb\xda\x01\xb6}\x83\xd3\xcc\x00\xec\x99\x15\xf4\x88Y\x99\x1f2\x83\xb4\xfc\x8e\x99\xdf\xb3d\x0c\x01.1E\x04\x93l\xff\x8e\xcf\x7f6\xa4Z\xfc\x82\xeaK\x97c BD\xf3\x101\x89g\xba\x8b\x03\xd0?\x97\xff#\xfb{'\x9a\x8b\xe0\x03H\xc89\xfa\x08\x15\x7f\xa2\x0f >\x80_\x0e\xe0\x93\xb3\xf0\xc3\xc4\xd3m\\\xef\xf8\x958\xa0"
#lt=open("logSendByteStringWithoutN.log","wb")
@ -70,7 +69,6 @@ def ProcessChildSendString(lProcess,lString):
lByteString = lByteString.replace(b'\n',b'{{n}}')
#Отправить сообщение в дочерний процесс
lProcess.stdin.write(lByteString+bytes('\n',"utf-8"))
#print(str(lByteString+bytes('\n',"utf-8")))
lProcess.stdin.flush()
#Вернуть результат
return
@ -80,7 +78,6 @@ def ProcessChildReadWaitString(lProcess):
#Ожидаем ответ от процесса
lResult = lProcess.stdout.readline()
#Обработка спец символов
#print(b'NewLine: '+lResult)
#Вернуть потенциальные \n
lResult = lResult.replace(b'{{{n}}}',b'\n')
#Вернуть \r
@ -97,8 +94,6 @@ def ProcessChildReadWaitString(lProcess):
lResult = lResult.replace(b'{{{v}}}',b'\v')
#Вернуть \f
lResult = lResult.replace(b'{{{f}}}',b'\f')
#print("check")
#print(str(lResult))
lResult = zlib.decompress(lResult[0:-1])
lResult = lResult.decode("utf-8")
#Вернуть результат

@ -0,0 +1,108 @@
import pdb
import json
import subprocess
import zlib
import os
from . import ProcessCommunicator
import importlib
import traceback
import logging
import sys
import datetime
import struct
import shutil
from pyOpenRPA.Robot import UIDesktop
global mGlobalDict
####################################
#Info: Main module of the Robot app (OpenRPA - Robot)
####################################
#Usage:
#Here you can run some activity or list of activities
#After import this module you can use the folowing functions:
#ActivityRun(inActivitySpecificationDict): outActivityResultDict - function - run activity (function or procedure)
#ActivityRunJSON(inActivitySpecificationDictJSON): outActivityResultDictJSON
#ActivityListRun(inActivitySpecificationDictList): outActivityResultDictList - function - run list of activities (function or procedure)
#ActivityListRunJSON(inActivitySpecificationDictListJSON): outActivityResultDictListJSON
#Naming:
#Activity - some action/list of actions
#Module - Any *.py file, which consist of area specific functions
#Argument
#inActivitySpecificationDict:
#{
# ModuleName: <"GUI"|..., str>,
# ActivityName: <Function or procedure name in module, str>,
# ArgumentList: [<Argument 1, any type>, ...] - optional,
# ArgumentDict: {<Argument 1 name, str>:<Argument 1 value, any type>, ...} - optional
#}
#outActivityResultDict:
#{
# ActivitySpecificationDict: {
# ModuleName: <"GUI"|..., str>,
# ActivityName: <Function or procedure name in module, str>,
# ArgumentList: [<Argument 1, any type>, ...] - optional,
# ArgumentDict: {<Argument 1 name, str>: <Argument 1 value, any type>, ...} - optional
# },
# ErrorFlag: <Boolean flag - Activity result has error (true) or not (false), boolean>,
# ErrorMessage: <Error message, str> - required if ErrorFlag is true,
# ErrorTraceback: <Error traceback log, str> - required if ErrorFlag is true,
# Result: <Result, returned from the Activity, int, str, boolean, list, dict> - required if ErrorFlag is false
#}
####################
#Section: Activity
####################
def ActivityRun(inActivitySpecificationDict):
lResponseObject = {}
#Выполнить отправку в модуль UIDesktop, если ModuleName == "UIDesktop"
if inActivitySpecificationDict["ModuleName"] == "UIDesktop":
if "ArgumentList" not in inActivitySpecificationDict:
inActivitySpecificationDict["ArgumentList"]=[]
if "ArgumentDict" not in inActivitySpecificationDict:
inActivitySpecificationDict["ArgumentDict"]={}
#Run the activity
try:
#Найти функцию
lFunction=getattr(UIDesktop,inActivitySpecificationDict["ActivityName"])
#Выполнить вызов и записать результат
lResponseObject["Result"]=lFunction(*inActivitySpecificationDict["ArgumentList"],**inActivitySpecificationDict["ArgumentDict"])
except Exception as e:
#Установить флаг ошибки и передать тело ошибки
lResponseObject["ErrorFlag"]=True
lResponseObject["ErrorMessage"]=str(e)
lResponseObject["ErrorTraceback"]=traceback.format_exc()
#Остальные модули подключать и выполнять здесь
else:
lArgumentList=[]
if "ArgumentList" in inActivitySpecificationDict:
lArgumentList=inActivitySpecificationDict["ArgumentList"]
lArgumentDict={}
if "ArgumentDict" in inActivitySpecificationDict:
lArgumentDict=inActivitySpecificationDict["ArgumentDict"]
#Подготовить результирующую структуру
lResponseObject={"ActivitySpecificationDict":inActivitySpecificationDict,"ErrorFlag":False}
try:
#Подключить модуль для вызова
lModule=importlib.import_module(inActivitySpecificationDict["ModuleName"])
#Найти функцию
lFunction=getattr(lModule,inActivitySpecificationDict["ActivityName"])
#Выполнить вызов и записать результат
lResponseObject["Result"]=lFunction(*lArgumentList,**lArgumentDict)
except Exception as e:
#Установить флаг ошибки и передать тело ошибки
lResponseObject["ErrorFlag"]=True
lResponseObject["ErrorMessage"]=str(e)
lResponseObject["ErrorTraceback"]=traceback.format_exc()
return lResponseObject
#########################################################
#Run list of activities
#########################################################
def ActivityListRun(inActivitySpecificationDictList):
lResult=[]
for lItem in inActivitySpecificationDictList:
lResult.append(ActivityRun(lItem))
return lResult

@ -5,12 +5,30 @@ import json
import subprocess
import zlib
import os
from . import ProcessCommunicator
import sys
import traceback
from pyOpenRPA.Robot import Robot
from . import RobotConnector
import importlib
#Единый глобальный словарь (За основу взять из Settings.py)
global mGlobalDict
#Call Settings function from argv[1] file
################################################
lSubmoduleFunctionName = "Settings"
lFileFullPath = sys.argv[1]
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)
mGlobalDict = None
if lSubmoduleFunctionName in dir(lTechModuleFromSpec):
# Run SettingUpdate function in submodule
mGlobalDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)()
#################################################
RobotConnector.mGlobalDict = mGlobalDict
#Init the robot
RobotConnector.UIDesktop.Utils.ProcessBitness.SettingsInit(mGlobalDict["ProcessBitness"])
# HTTPRequestHandler class
# HTTP Studio web server class
class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
#ResponseContentTypeFile
def SendResponseContentTypeFile(self,inContentType,inFilePath):
@ -82,7 +100,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
#pdb.set_trace()
lRequestObject=lInputObject
#Отправить команду роботу
lResponseObject=Robot.ActivityRun(lRequestObject)
lResponseObject=RobotConnector.ActivityRun(lRequestObject)
message = json.dumps(lResponseObject)
except Exception as e:
#Установить флаг ошибки
@ -113,7 +131,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
lRequestObject=lInputObject
lOutputObject=[]
#pdb.set_trace()
lResponseObject=Robot.ActivityListRun(lRequestObject)
lResponseObject=RobotConnector.ActivityListRun(lRequestObject)
#Сформировать текстовый ответ
message = json.dumps(lResponseObject)
# Write content as utf-8 data
@ -121,14 +139,15 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
return
def run():
print('starting server...')
inServerAddress = "";
inPort = mGlobalDict["Server"]["ListenPort"];
# Server settings
# Choose port 8080, for port 80, which is normally used for a http server, you need root access
server_address = ('127.0.0.1', 8081)
server_address = (inServerAddress, inPort)
httpd = HTTPServer(server_address, testHTTPServer_RequestHandler)
print('running server...')
# Logging
mGlobalDict["Logger"].info(f"Server init. Listen URL: {inServerAddress}, Listen port: {inPort}")
# Запуск адреса в браузере
os.system("explorer http://127.0.0.1:8081")
os.system(f"explorer http://127.0.0.1:{str(inPort)}")
httpd.serve_forever()
#print(ChildProcessReadWaitString(p))
run()

@ -9,6 +9,115 @@
crossorigin="anonymous"></script>
<script src="3rdParty/Semantic-UI-CSS-master/semantic.min.js"></script>
<script>
// Production steps of ECMA-262, Edition 6, 22.1.2.1
if (!Array.from) {
Array.from = (function () {
var toStr = Object.prototype.toString;
var isCallable = function (fn) {
return typeof fn === 'function' || toStr.call(fn) === '[object Function]';
};
var toInteger = function (value) {
var number = Number(value);
if (isNaN(number)) { return 0; }
if (number === 0 || !isFinite(number)) { return number; }
return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
};
var maxSafeInteger = Math.pow(2, 53) - 1;
var toLength = function (value) {
var len = toInteger(value);
return Math.min(Math.max(len, 0), maxSafeInteger);
};
// The length property of the from method is 1.
return function from(arrayLike/*, mapFn, thisArg */) {
// 1. Let C be the this value.
var C = this;
// 2. Let items be ToObject(arrayLike).
var items = Object(arrayLike);
// 3. ReturnIfAbrupt(items).
if (arrayLike == null) {
throw new TypeError('Array.from requires an array-like object - not null or undefined');
}
// 4. If mapfn is undefined, then let mapping be false.
var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
var T;
if (typeof mapFn !== 'undefined') {
// 5. else
// 5. a If IsCallable(mapfn) is false, throw a TypeError exception.
if (!isCallable(mapFn)) {
throw new TypeError('Array.from: when provided, the second argument must be a function');
}
// 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (arguments.length > 2) {
T = arguments[2];
}
}
// 10. Let lenValue be Get(items, "length").
// 11. Let len be ToLength(lenValue).
var len = toLength(items.length);
// 13. If IsConstructor(C) is true, then
// 13. a. Let A be the result of calling the [[Construct]] internal method
// of C with an argument list containing the single item len.
// 14. a. Else, Let A be ArrayCreate(len).
var A = isCallable(C) ? Object(new C(len)) : new Array(len);
// 16. Let k be 0.
var k = 0;
// 17. Repeat, while k < len (also steps a - h)
var kValue;
while (k < len) {
kValue = items[k];
if (mapFn) {
A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);
} else {
A[k] = kValue;
}
k += 1;
}
// 18. Let putStatus be Put(A, "length", len, true).
A.length = len;
// 20. Return A.
return A;
};
}());
}
if (!Object.assign) {
Object.defineProperty(Object, 'assign', {
enumerable: false,
configurable: true,
writable: true,
value: function(target, firstSource) {
'use strict';
if (target === undefined || target === null) {
throw new TypeError('Cannot convert first argument to object');
}
var to = Object(target);
for (var i = 1; i < arguments.length; i++) {
var nextSource = arguments[i];
if (nextSource === undefined || nextSource === null) {
continue;
}
var keysArray = Object.keys(Object(nextSource));
for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
var nextKey = keysArray[nextIndex];
var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
if (desc !== undefined && desc.enumerable) {
to[nextKey] = nextSource[nextKey];
}
}
}
return to;
}
});
}
var mGlobal={}
$(document)
.ready(function() {
@ -17,11 +126,8 @@
/////////////////////////////////////////////////////////////////
mGlobal.Settings={}
mGlobal.Settings.mUIOTreeHeight=450
mGlobal.GUIElement={}
mGlobal.GenerateUniqueID=function(inPrefix="ID") {
mGlobal.GenerateUniqueID=function(inPrefix) {
return inPrefix+Math.round(Math.random()*1000)+"-"+Math.round(Math.random()*10000)+"-"+Math.round(Math.random()*1000)
}
///Инициализация
@ -158,7 +264,7 @@
}
///Функция визуализации дерева
mGlobal.ElementTree.fRender = function(inElementsTreeDataArray,inBackendString="-")
mGlobal.ElementTree.fRender = function(inElementsTreeDataArray,inBackendString)
{
var lHTMLList=
'<b style="font-size:10px;" >Backend: '+inBackendString+'</b>\
@ -166,7 +272,7 @@
///Циклический обход списка
for (var i = 0; i< inElementsTreeDataArray.length;i++) {
///Добавить HTML код позиции
lHTMLList+=mGlobal.ElementTree.fItemGenerateHTML_JS(inElementsTreeDataArray[i])
lHTMLList+=mGlobal.ElementTree.fItemGenerateHTML_JS(inElementsTreeDataArray[i],[])
}
///Закрывающая список HTML
lHTMLList+="</div>"
@ -176,9 +282,9 @@
}
///Функция визуализации дерева
///Вызов создания вложенного листа, если имеется атрибут SpecificationChild
mGlobal.ElementTree.fItemGenerateHTML_JS = function(inItem,inParentSpecification=[]){
mGlobal.ElementTree.fItemGenerateHTML_JS = function(inItem,inParentSpecification){
///Генерация уникального кода для элемента
var lElementId = mGlobal.GenerateUniqueID()
var lElementId = mGlobal.GenerateUniqueID("ID")
//Добавить информацию об элементе в словарь JS
///Урезанная часть селектора (сделать, чтобы была без SpecificationChild)
var lSelectorLocal={};
@ -245,7 +351,7 @@
var lHTMLTree='<div class="ui list">'
var lResponseJSON=JSON.parse(lData)
for (i=0;i<lResponseJSON.Result.length;i++) {
var lElementId = mGlobal.GenerateUniqueID()
var lElementId = mGlobal.GenerateUniqueID("ID")
var lSubItemHandleId=lResponseJSON.Result[i].handle;
var lSubItemActionOnClick=' onclick="mGlobal.TreeLoadSubTree(\''+lElementId+'\');" '
var lSubItemActionOnRightClick=' onclick="mGlobal.ElementHighlightNew(\''+lElementId+'\');" '
@ -293,7 +399,7 @@
var lSpecificationArrayNew=[]
for (i=0;i<lSpecificationArray.length;i++) {
lSpecificationArrayNew.push(lSpecificationArray[i])
var lElementId = mGlobal.GenerateUniqueID()
var lElementId = mGlobal.GenerateUniqueID("ID")
var lOnClickSelect= ' onclick="mGlobal.ElementPropertyListLoad(\''+lElementId+'\');" '
lHTMLList+='\
<div class="item" id="'+lElementId+'" '+lOnClickSelect+'>\
@ -679,7 +785,7 @@
///Очистить дерево
mGlobal.ElementTree.fClear();
///Прогрузить новое дерево
mGlobal.ElementTree.fRender(lResponseJSON.Result,$(".openrpa-value-backend")[0].value);
mGlobal.ElementTree.fRender(lResponseJSON.Result,$(".openrpa-value-backend")[0].value,"-");
///Показать ошибку, если таковая возникла
if (lResponseJSON["ErrorFlag"]) {
mGlobal.ShowModal("GUI Error",lResponseJSON.ErrorMessage+" \nTraceback: "+lResponseJSON.ErrorTraceback);

@ -78,12 +78,15 @@ def SessionRDPStart(inRDPFilePath):
[
[{"title": "Подключение к удаленному рабочему столу", "class_name": "#32770", "backend": "win32"},
{"title": "Боль&ше не выводить запрос о подключениях к этому компьютеру", "friendly_class_name": "CheckBox"}],
[{"title": "Remote Desktop Connection", "class_name": "#32770", "backend": "win32"},
{"title": "D&on't ask me again for connections to this computer",
"friendly_class_name": "CheckBox"}],
[{"title_re": f"{lRDPFileName} — .*",
"class_name": "TscShellContainerClass", "backend": "win32"}]
],
60
30
)
#Click if 0 is appear
#Click if 0 is appear (RUS)
if 0 in lWaitResult:
#Check the box do not retry
UIDesktop.UIOSelector_Get_UIO([{"title": "Подключение к удаленному рабочему столу", "backend": "win32"},
@ -96,7 +99,23 @@ def SessionRDPStart(inRDPFilePath):
[{"title_re": f"{lRDPFileName} — .*",
"class_name": "TscShellContainerClass", "backend": "win32"}]
],
60
30
)
# Click if 1 is appear (ENG)
if 1 in lWaitResult:
# Check the box do not retry
UIDesktop.UIOSelector_Get_UIO([{"title": "Remote Desktop Connection", "class_name": "#32770", "backend": "win32"},
{"title": "D&on't ask me again for connections to this computer",
"friendly_class_name": "CheckBox"}]).check()
# Go to connection
UIDesktop.UIOSelector_Get_UIO([{"title": "Remote Desktop Connection", "class_name": "#32770", "backend": "win32"},
{"title": "Co&nnect", "class_name": "Button"}]).click()
lWaitResult = UIDesktop.UIOSelectorsSecs_WaitAppear_List(
[
[{"title_re": f"{lRDPFileName} — .*",
"class_name": "TscShellContainerClass", "backend": "win32"}]
],
30
)
#Prepare little window
SessionScreen100x550(lRDPFileName)

@ -1,17 +1,34 @@
from pyOpenRPA.Robot import UIDesktop
from . import Connector
import os
import pdb
#Check for session is closed. Reopen if detected. Always keep session is active
def Monitor(inGlobalDict, inListUpdateTimeout):
while True:
lFlagWhile = True
while lFlagWhile:
# UIOSelector list init
lUIOSelectorList = []
for lItem in inGlobalDict["RDPList"]:
lUIOSelectorList.append([{"title_re": f"{lItem['SessionHex']} — .*", "backend": "win32"}])
#Run wait command
lRDPDissappearList = UIDesktop.UIOSelectorsSecs_WaitDisappear_List(lUIOSelectorList, inListUpdateTimeout)
#Analyze if flag safeturn off is activated
if inGlobalDict.get("OrchestratorToRobotResetStorage",{}).get("SafeTurnOff",False):
lFlagWhile=False
#Set status disconnected for all RDP List
for lItem in inGlobalDict["RDPList"]:
lItem["FlagSessionIsActive"]=False
#Kill all RDP sessions
os.system('taskkill /F /im mstsc.exe')
#Return from function
return
for lItem in lRDPDissappearList:
inGlobalDict["RDPList"][lItem]["FlagSessionIsActive"] = False # Set flag that session is disconnected
#pdb.set_trace()
#Session start
try:
Connector.Session(inGlobalDict["RDPList"][lItem])
except Exception:
pass
return None
#TODO Def garbage window cleaner (if connection was lost)

@ -1,22 +0,0 @@
#Robot RDPActive settings
def Settings():
mDict = {
"RDPList":
[
{
"Host": "77.77.22.22", # Host address
"Port": "7777", # RDP Port
"Login": "test", # Login
"Password": "test", # Password
"Screen": {
"Width": 1680, #Width of the remote desktop in pixels
"Height": 1050, #Height of the remote desktop in pixels
# "640x480" or "1680x1050" or "FullScreen". If Resolution not exists set full screen
"FlagUseAllMonitors": False, # True or False
"DepthBit": "32" # "32" or "24" or "16" or "15"
},
"SessionHex":"" # Hex is created when robot runs
}
]
}
return mDict

@ -35,9 +35,15 @@ lCMDString = 'reg add "HKEY_CURRENT_USER\\Software\\Microsoft\\Terminal Server C
os.system(lCMDString)
#time.sleep()
for lConfigurationItem in mGlobalDict["RDPList"]:
try:
Connector.Session(lConfigurationItem)
lConfigurationItem["FlagSessionIsActive"]=True #Flag that session is started
except Exception:
pass
#Run monitor
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'
os.system(lCMDString)
#Close all thread from OrchestratorConnection
mGlobalDict["OrchestratorConnectorTerminateAll"]()

@ -3,7 +3,7 @@ r"""
The OpenRPA package (from UnicodeLabs)
"""
__version__ = 'v1.0.32'
__version__ = 'v1.0.34'
__all__ = []
__author__ = 'Ivan Maslov <ivan.maslov@unicodelabs.ru>'
#from .Core import Robot

@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: pyOpenRPA
Version: 1.0.32
Version: 1.0.34
Summary: First open source RPA platform for business
Home-page: https://gitlab.com/UnicodeLabs/OpenRPA
Author: Ivan Maslov

@ -1,14 +1,14 @@
pyOpenRPA-1.0.32.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pyOpenRPA-1.0.32.dist-info/METADATA,sha256=hwB02rO7bJ84-CJNqzZfm4jVgnNbuBkKuAr8SsRwZq0,3510
pyOpenRPA-1.0.32.dist-info/RECORD,,
pyOpenRPA-1.0.32.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97
pyOpenRPA-1.0.32.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10
pyOpenRPA/Orchestrator/Orchestrator.py,sha256=iM-DZ7TU7o51pzIJYEkNIlVG_GzzaVUESi7Tu0Ppw8g,6717
pyOpenRPA/Orchestrator/Processor.py,sha256=GHXwC1B2py4mAtk9oZa-FVSJhx3no9oD2bvkj20uhNA,9051
pyOpenRPA/Orchestrator/Server.py,sha256=TgKkqgMivzvh4cM4zpbDUdv9AXbUiPPy9uLjR1lTiJU,20229
pyOpenRPA/Orchestrator/ServerSettings.py,sha256=ZrNEt_UoHYGOeAKN5X5jQHz-XNl1lBW47ttKUF8_cmM,4948
pyOpenRPA-1.0.34.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pyOpenRPA-1.0.34.dist-info/METADATA,sha256=WakfkUg30wJGLxsmqvPERvkd2agMGOzXa84qcPG5f5Q,3510
pyOpenRPA-1.0.34.dist-info/RECORD,,
pyOpenRPA-1.0.34.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97
pyOpenRPA-1.0.34.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10
pyOpenRPA/Orchestrator/Orchestrator.py,sha256=UKp7eqvWDM91kYLwl2mo0UB8Pw-qu8eJCsR9NEXD1aU,6436
pyOpenRPA/Orchestrator/Processor.py,sha256=HQQyOVX-d5vPO-YULyTxVOtXtUMfvpAaSVO4xXxaKVI,9107
pyOpenRPA/Orchestrator/Server.py,sha256=5tjhfU0QVEfg4zjT2jWOuOADWeHXMBxX2Fe8lj1bnCA,20839
pyOpenRPA/Orchestrator/ServerSettings.py,sha256=jOXJTLwg8cJx6D-rN8J4dn5RCb2nepAhCH4F9hYVUdM,4912
pyOpenRPA/Orchestrator/Timer.py,sha256=FQZ3y6G9d47Ybx7RewzePKQV77H4gCkx5SaeFVlsuhc,2095
pyOpenRPA/Orchestrator/Web/Index.xhtml,sha256=wWDxguk0q4ylePllPzZvTdaOzlpolqYiBXIGp_a5udI,31744
pyOpenRPA/Orchestrator/Web/Index.xhtml,sha256=7wwEJ8lEI_2AElITUk9yyX91Sq6pNccqPsuAVlm7enQ,32322
pyOpenRPA/Orchestrator/Web/favicon.ico,sha256=jO3pjFWbmJEPQ2KroXSKYtXIesBq46PCBlKSouewODU,5430
pyOpenRPA/Orchestrator/__init__.py,sha256=qVH8fEPgXk54rmy-ol0PnT8GF5OlGE0a8mExwJ4tFqY,124
pyOpenRPA/Orchestrator/__main__.py,sha256=cOd8WU77VGgzTZUB0WmWpPmdYyMZY1zVyuU9yx26MKs,144
@ -192,52 +192,56 @@ pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/fonts/outli
pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/images/flags.png,sha256=lNXH8WYTAcSm3Ekdct1VmgYgzZF6gm8N8bAju5bqnd0,28123
pyOpenRPA/Resources/Web/jQuery/jquery-3.1.1.min.js,sha256=HPMOWdIdSuVgr3FD9ZE-_MgiK8qk_MdQjrgCtfqp6U4,86713
pyOpenRPA/Robot/Clipboard.py,sha256=q76X8L21zJwcwdoJJNPeCEwAV30xS6ylHP1WwvtxoWI,722
pyOpenRPA/Robot/IntegrationOrchestrator.py,sha256=T1g1jJM7_JMTSVP50DTM5WHrMh1w8wovvcBXl1nEokU,2656
pyOpenRPA/Robot/JSONNormalize.py,sha256=aIuVzuZDazhxkCOzoOjfhHVz66mp2FWdfPv5E7KWF5Y,3890
pyOpenRPA/Robot/ProcessCommunicator.py,sha256=Mpo2WoCrEUmY6aCSbQEXkT4qVKtN1N5NcVvG_UZxGVo,8245
pyOpenRPA/Robot/Robot.py,sha256=AVR8jzO-e_ZkW5DrLY_W9ta0eHSul997Y3U6uNVU8WE,9442
pyOpenRPA/Robot/UIDesktop.py,sha256=ehqMQmKLbkwW6iqA9bkw9tvDRni5QriLkG9P3AP_TMs,78377
pyOpenRPA/Robot/OrchestratorConnector.py,sha256=Fihxz-jH9M4VakXEE0SZ0Vo9tLEQk8Tcg_C4HoH45gI,20037
pyOpenRPA/Robot/SettingsTemplate.py,sha256=Rp5XPeV2I4tCS2uf4Zkqm_ERJ6pZMg4-e5_lMqGJYLk,1453
pyOpenRPA/Robot/Test.py,sha256=qXr990nXiFZX5SNv6QN9GLb_U4HZRmJnbZR2qSnwilY,2878
pyOpenRPA/Robot/UIDesktop.py,sha256=MWdWr0dZpk1PL1rsD91q6_8v687CSDBx1_T7IuHd3-E,77473
pyOpenRPA/Robot/Utils/JSONNormalize.py,sha256=aIuVzuZDazhxkCOzoOjfhHVz66mp2FWdfPv5E7KWF5Y,3890
pyOpenRPA/Robot/Utils/ProcessBitness.py,sha256=WlKL-DklGaoTnchtapOTM_ydxSB4yOeo9lcG3zr2VME,4524
pyOpenRPA/Robot/Utils/ProcessCommunicator.py,sha256=8GfmLnOvAdosmt7YNT86uEV9cjhKippssCX62wOMJwM,8039
pyOpenRPA/Robot/Utils/TimerRepeat.py,sha256=_kTct3X9SIEvS3DKM5bGNnjRBVJasmMFZntQaVbPX_E,961
pyOpenRPA/Robot/Utils/ValueVerify.py,sha256=ObskxU4fOMoCGw74_nzYt6-a5jjrAckb3sdBLYyhYxY,777
pyOpenRPA/Robot/Utils/__init__.py,sha256=pHlSQGRFKmn5RCTHIf-3a2ooA9T2xNOWridckynP7W4,28
pyOpenRPA/Robot/Utils/__pycache__/JSONNormalize.cpython-37.pyc,,
pyOpenRPA/Robot/Utils/__pycache__/ProcessBitness.cpython-37.pyc,,
pyOpenRPA/Robot/Utils/__pycache__/ProcessCommunicator.cpython-37.pyc,,
pyOpenRPA/Robot/Utils/__pycache__/TimerRepeat.cpython-37.pyc,,
pyOpenRPA/Robot/Utils/__pycache__/ValueVerify.cpython-37.pyc,,
pyOpenRPA/Robot/Utils/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Robot/ValueVerify.py,sha256=ObskxU4fOMoCGw74_nzYt6-a5jjrAckb3sdBLYyhYxY,777
pyOpenRPA/Robot/Window.py,sha256=UJl-sg4RvvJ35aG9jZOzqGVwE15XK7qPHqoOBD13xFk,431
pyOpenRPA/Robot/__init__.py,sha256=iEW3SGBJf3kYa1zocGH5vEK0woejzJpnQfOmQtIA3P0,324
pyOpenRPA/Robot/__main__.py,sha256=NlwxAG68mwoWNB4YIX15Fc2gWlL1RQ5HN8i1NyjGFdo,1965
pyOpenRPA/Robot/__init__.py,sha256=L-5tPm6evytGWOzlqIq-2oiIhmQnruaxwIstyyaMkVI,253
pyOpenRPA/Robot/__main__.py,sha256=l6II8JuXCsnVOcfs6-2jvogKYTVhbfj3Jl2ld3OIP7s,1992
pyOpenRPA/Robot/__pycache__/Clipboard.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/IntegrationOrchestrator.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/JSONNormalize.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/ProcessCommunicator.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/Robot.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/OrchestratorConnector.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/SettingsTemplate.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/Test.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/UIDesktop.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/ValueVerify.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/Window.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Studio/JSONNormalize.py,sha256=g0Z8G2wojCgTAdZtyRiCfe0_FHSeAi72Va7R7mk27gg,3347
pyOpenRPA/Studio/ProcessCommunicator.py,sha256=5hXDMa4ONBgeJBoDIfDCAW9MoiRO8cq-DdfqQSAysgk,8080
pyOpenRPA/Studio/Studio.py,sha256=7X46k0l33sgQoG6sxFFJmI5G0KKxgDggvEnzux8aonw,7014
pyOpenRPA/Studio/ProcessCommunicator.py,sha256=HD3XASJae31_HV3OznFe8E2MgZFXnwt7YveVN82M8nU,7912
pyOpenRPA/Studio/RobotConnector.py,sha256=tQVC8X0k1HMHAAwAtkhtmeNA0cLMY3wuO-RCbgshdMk,5036
pyOpenRPA/Studio/Studio.py,sha256=wiVGWZZx-yC8jp-Wjz-B5GC1cqTcftDulZfYe-4hU8w,8125
pyOpenRPA/Studio/ValueVerify.py,sha256=ObskxU4fOMoCGw74_nzYt6-a5jjrAckb3sdBLYyhYxY,777
pyOpenRPA/Studio/Web/Index.xhtml,sha256=74z3eWlmB6Yedbp91xgGtDjymUSlBcduAQ09ZxQ67f8,44241
pyOpenRPA/Studio/Web/Index.xhtml,sha256=RqFW3qC1pFRr-qWEEDlCEhL9l3PwANyRbll3KZJnLvo,47927
pyOpenRPA/Studio/Web/favicon.ico,sha256=0vdsnwKGh6pgB0FDB5mOKO7RwbxQ9F13Zg16F1pkvXs,5430
pyOpenRPA/Studio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Studio/__main__.py,sha256=_57Rnq9DKbmmlpGFqIwVrWn_LRcU8jjmMTOny4_zlP8,308
pyOpenRPA/Studio/__pycache__/JSONNormalize.cpython-37.pyc,,
pyOpenRPA/Studio/__pycache__/ProcessCommunicator.cpython-37.pyc,,
pyOpenRPA/Studio/__pycache__/RobotConnector.cpython-37.pyc,,
pyOpenRPA/Studio/__pycache__/Studio.cpython-37.pyc,,
pyOpenRPA/Studio/__pycache__/ValueVerify.cpython-37.pyc,,
pyOpenRPA/Studio/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Studio/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Tools/RobotRDPActive/Connector.py,sha256=vpXFO1irhLTHgIwWn5PCsTq-6E3Sx3sYOweIBNyiYEw,6164
pyOpenRPA/Tools/RobotRDPActive/Monitor.py,sha256=INkiX4Gi4KjvWRoe4jWV_NJGKgjDId6zEyqBHpegUxw,760
pyOpenRPA/Tools/RobotRDPActive/SettingsExample.py,sha256=5eEhjk7NDXf9Q4yvkeRICE7x9npiMkazuMITQX24Ooc,857
pyOpenRPA/Tools/RobotRDPActive/Connector.py,sha256=9Y9zA92Zw9QF6dadW53NLekV_1r2STISFn5RzI08GDo,7272
pyOpenRPA/Tools/RobotRDPActive/Monitor.py,sha256=X8ZhJFdDnA88OHlgRuinPvhZ_eS4R7y0xRchbo7LPCc,1525
pyOpenRPA/Tools/RobotRDPActive/Template.rdp,sha256=qPCLkjzTdYKURK7nRApkPUjRuS4K20vDPj9DIUNSSkE,2392
pyOpenRPA/Tools/RobotRDPActive/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Tools/RobotRDPActive/__main__.py,sha256=qC_LyXI2MjJkidTRpV3abyyPO0qASGTvNkeAkfnA7J0,2108
pyOpenRPA/Tools/RobotRDPActive/__main__.py,sha256=mVk8zVqcBrzAwwn7tbZPXFWTQbWUkgU6w89nbY6GN-8,2340
pyOpenRPA/Tools/RobotRDPActive/__pycache__/Connector.cpython-37.pyc,,
pyOpenRPA/Tools/RobotRDPActive/__pycache__/Monitor.cpython-37.pyc,,
pyOpenRPA/Tools/RobotRDPActive/__pycache__/SettingsExample.cpython-37.pyc,,
pyOpenRPA/Tools/RobotRDPActive/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Tools/RobotRDPActive/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Tools/RobotScreenActive/ConsoleStart.bat,sha256=_HNadUKHOYI5y6foG3srh8wjSzhX33xaKNylFtDjOJk,114
@ -251,5 +255,5 @@ pyOpenRPA/Tools/RobotScreenActive/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Tools/RobotScreenActive/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Tools/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/__init__.py,sha256=mqY50pRbV4Tk-vj2-Z2CiY8u2qSB0HRfKNcduM36Zdo,175
pyOpenRPA/__init__.py,sha256=6g2t0dHUhbsJm87H07rs_6y5XDub0C_nWd2B-w-0XGg,175
pyOpenRPA/__pycache__/__init__.cpython-37.pyc,,

@ -15,11 +15,6 @@ import copy
#from .Settings import Settings
import importlib
from importlib import util
#Создать файл логирования
# add filemode="w" to overwrite
if not os.path.exists("Reports"):
os.makedirs("Reports")
logging.basicConfig(filename="Reports\ReportRun_"+datetime.datetime.now().strftime("%Y_%m_%d__%H_%M_%S")+".log", level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
#Единый глобальный словарь (За основу взять из Settings.py)
global mGlobalDict
@ -51,6 +46,8 @@ lDaemonStartDateTime=datetime.datetime.now()
#Инициализация сервера
lThreadServer = Server.RobotDaemonServer("ServerThread", mGlobalDict)
lThreadServer.start()
#Logging
mGlobalDict["Logger"].info("Scheduler loop init")
#Вечный цикл
while True:
lCurrentDateTime = datetime.datetime.now()

@ -104,28 +104,31 @@ def Activity(inActivity):
#Обработка команды GlobalDictKeyListValueSet
###########################################################
if lItem["Type"]=="GlobalDictKeyListValueSet":
lDict = mGlobalDict
for lItem2 in lItem["KeyList"][:-1]:
#Check if key - value exists
if lItem2 in mGlobalDict:
if lItem2 in lDict:
pass
else:
mGlobalDict[lItem2]={}
mGlobalDict=mGlobalDict[lItem2]
lDict[lItem2]={}
lDict=lDict[lItem2]
#Set value
mGlobalDict[lItem["KeyList"][-1]]=lItem["value"]
lDict[lItem["KeyList"][-1]]=lItem["Value"]
lItem["Result"] = True
###########################################################
#Обработка команды GlobalDictKeyListValueGet
###########################################################
if lItem["Type"]=="GlobalDictKeyListValueGet":
lDict = mGlobalDict
for lItem2 in lItem["KeyList"][:-1]:
#Check if key - value exists
if lItem2 in mGlobalDict:
if lItem2 in lDict:
pass
else:
mGlobalDict[lItem2]={}
mGlobalDict=mGlobalDict[lItem2]
lDict[lItem2]={}
lDict=lDict[lItem2]
#Return value
lItem["Result"]==mGlobalDict.get(lItem["KeyList"][-1],None)
lItem["Result"]=lDict.get(lItem["KeyList"][-1],None)
#Определить вид активности
lActivityDateTime=inActivity["DateTimeUTCStringStart"]
#####################################
@ -193,6 +196,7 @@ def Activity(inActivity):
##################
#Trace activity
##################
#print(mGlobalDict)
if mGlobalDict["Processor"].get(f"LogType_{lItem['Type']}",True):
#Add activity in TransactionList if it is applicable
mGlobalDict["Processor"]["LogList"].append(copy.deepcopy(lItem))

@ -22,12 +22,14 @@ class RobotDaemonServer(Thread):
def run(self):
inServerAddress="";
inPort = mGlobalDict["Server"]["ListenPort"];
print('starting server..., port:'+str(inPort)+" inAddress:"+inServerAddress)
# Server settings
# Choose port 8080, for port 80, which is normally used for a http server, you need root access
server_address = (inServerAddress, inPort)
httpd = HTTPServer(server_address, testHTTPServer_RequestHandler)
print('running server...')
# Logging
mGlobalDict["Logger"].info(f"Server init. Listen URL: {inServerAddress}, Listen port: {inPort}")
# Запуск адреса в браузере
os.system("explorer http://127.0.0.1:8081")
httpd.serve_forever()
#Authenticate function ()
@ -86,6 +88,7 @@ def AuthenticateVerify(inRequest):
mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken] = {}
mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["Domain"] = lResult["Domain"]
mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["User"] = lResult["User"]
mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["FlagDoNotExpire"] = False
mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["TokenDatetime"] = datetime.datetime.now()
#Set-cookie
inRequest.OpenRPA["AuthToken"] = lAuthToken
@ -110,6 +113,7 @@ def AuthenticateBlock(inRequest):
#return bool True - go execute, False - dont execute
def UserAccessCheckBefore(inMethod, inRequest):
# Help def - Get access flag from dict
#pdb.set_trace()
def HelpGetFlag(inAccessRuleItem, inRequest, inGlobalDict, inAuthenticateDict):
if "FlagAccess" in inAccessRuleItem:
return inAccessRuleItem["FlagAccess"]
@ -300,6 +304,8 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
lAuthenticateDict = AuthenticateVerify(self)
if not lAuthenticateDict["User"]:
lFlagAccessUserBlock=True
# Logging
mGlobalDict["Logger"].info(f"HTTP request /. Domain: {lAuthenticateDict['Domain']}, User: {lAuthenticateDict['User']}")
if lFlagAccessUserBlock:
AuthenticateBlock(self)
#####################################
@ -321,7 +327,6 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
lFlagURLIsApplied=False
lFlagURLIsApplied=self.URLItemCheckDo(lURLItem, "GET")
if lFlagURLIsApplied:
#print("New engine")
self.ResponseDictSend()
return
#Monitor
@ -350,6 +355,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# POST
def do_POST(self):
# Prepare result dict
#pdb.set_trace()
lResponseDict = {"Headers": {}, "SetCookies":{}, "Body": "", "StatusCode": None}
self.OpenRPAResponseDict = lResponseDict
#####################################
@ -371,7 +377,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
lFlagUserAccess = True
#If need user authentication
if mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False):
lFlagUserAccess = UserAccessCheckBefore("GET", self)
lFlagUserAccess = UserAccessCheckBefore("POST", self)
######################################
if lFlagUserAccess:
#Централизованная функция получения запросов/отправки
@ -393,3 +399,10 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# Write content as utf-8 data
self.wfile.write(bytes(message, "utf8"))
return
else:
#Set access denied code
# Send response status code
self.send_response(403)
# Send headers
self.end_headers()
return

@ -16,7 +16,6 @@ def Monitor_ControlPanelDictGet(inRequest,inGlobalDict):
# Send message back to client
message = json.dumps(lResultJSON)
# Write content as utf-8 data
#print(bytes(message, "utf8"))
inResponseDict["Body"] = bytes(message, "utf8")
def GetScreenshot(inRequest,inGlobalDict):

@ -275,8 +275,8 @@
});
}
///
mGlobal.Monitor.mControlPanelAutoUpdateSeconds=5;
mGlobal.Monitor.mControlPanelAutoUpdateSecondsCurrent=5;
mGlobal.Monitor.mControlPanelAutoUpdateSeconds=3;
mGlobal.Monitor.mControlPanelAutoUpdateSecondsCurrent=3;
mGlobal.Monitor.fControlPanelAutoUpdateRun=function(inRefreshSeconds) {
mGlobal.Monitor.mControlPanelAutoUpdateSeconds=inRefreshSeconds;
//Функция обновления текста кнопки обновления
@ -291,7 +291,7 @@
mGlobal.Monitor.mControlPanelAutoUpdateTimerId=setInterval(lControlPanelUpdate,1000)
}
mGlobal.Monitor.fControlPanelRefresh()
mGlobal.Monitor.fControlPanelAutoUpdateRun(5);
mGlobal.Monitor.fControlPanelAutoUpdateRun(3);
mGlobal.Test=function() {
///Обнулить таблицу
@ -355,6 +355,29 @@
///////////////////////////////
mGlobal.Processor = {}
mGlobal.Processor.ServerValueSet = function(inKeyList,inValue) {
lData = [
{
"Type":"GlobalDictKeyListValueSet",
"KeyList": inKeyList,
"Value": inValue
}
]
///Обнулить таблицу
$('.ui.modal.basic .content').html("");
$.ajax({
type: "POST",
url: 'Utils/Processor',
data: JSON.stringify(lData),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
///TODO Show error if exist error
},
dataType: "text"
});
}
mGlobal.Processor.LogListShow = function() {
lData = [
{
@ -633,7 +656,7 @@
<div class="ui basic {{Color}} button" onclick="{{OnClick}}">{{{Text}}}</div>
{{/FooterButtonX2List}}
</div>
<div class="ui horizontal divider">Доп. управление</div>
<div class="ui horizontal divider">Add. controls</div>
<div class="ui one buttons">
{{#FooterButtonX1List}}
<div class="ui basic {{Color}} button" onclick="{{OnClick}}">{{{Text}}}</div>

@ -1,46 +0,0 @@
import requests
import grequests
#from requests import async
import json
###################################
##Orchestrator integration module (safe use when orchestrator is turned off)
###################################
################################################################################
#Send data to orchestrator (asynchronyous)
#Example: t=IntegrationOrchestrator.DataSend(["Storage","Robot_R01"],{"RunDateTimeString":"Test1","StepCurrentName":"Test2","StepCurrentDuration":"Test333","SafeStopSignal":True},"localhost",8081)
def DataSend(inKeyList,inValue,inOrchestratorHost="localhost",inOrchestratorPort=80):
lURL = f'http://{inOrchestratorHost}:{inOrchestratorPort}/ProcessingRun'
lDataJSON = {"actionList":[{"type":"AdministrationGlobalDictSetKeyListValue","key_list":inKeyList,"value":inValue}]}
#lAsyncList = []
lResultItem = [grequests.post(lURL, json=lDataJSON)]
return grequests.map(lResultItem)
#lAsyncList.append(lResultItem)
#return async.map(lAsyncList)
################################################################################
#recieve Data from orchestrator
#t=IntegrationOrchestrator.DataRecieve(["Storage","Robot_R01"],"localhost",8081)
def DataRecieve(inKeyList,inOrchestratorHost="localhost",inOrchestratorPort=80):
lURL = f'http://{inOrchestratorHost}:{inOrchestratorPort}/ProcessingRun'
lDataJSON = {"actionList":[{"type":"AdministrationGlobalDictGetKeyListValue","key_list":inKeyList}]}
try:
lResult = requests.post(lURL, json=lDataJSON)
lResultJSON = json.loads(lResult.text)
return lResultJSON["actionListResult"][0]["value"]
except Exception:
return None
################################################################################
#Check if orchestrator has safe stop signal
#Example: IntegrationOrchestrator.SafeStopSignalIs(["Storage","Robot_R01","SafeStopSignal"],"localhost",8081)
def SafeStopSignalIs(inKeyList,inOrchestratorHost="localhost",inOrchestratorPort=80):
lResult=False
lResponse=DataRecieve(inKeyList,inOrchestratorHost,inOrchestratorPort)
if lResponse is not None:
lResult = lResponse
return lResult
################################################################################
#Reset SafeStop signal in orchestrator
#Example: t=IntegrationOrchestrator.SafeStopSignalReset(["Storage","Robot_R01","SafeStopSignal"],"localhost",8081)
def SafeStopSignalReset(inKeyList,inOrchestratorHost="localhost",inOrchestratorPort=80):
lResponse=DataSend(inKeyList,False,inOrchestratorHost,inOrchestratorPort)
return lResponse

@ -0,0 +1,401 @@
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"]
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

@ -1,159 +0,0 @@
import pdb
import json
import subprocess
import zlib
import os
from . import ProcessCommunicator
import importlib
import traceback
import logging
import sys
import datetime
import struct
import shutil
#Создать файл логирования
# add filemode="w" to overwrite
if not os.path.exists("Reports"):
os.makedirs("Reports")
logging.basicConfig(filename="Reports\ReportRobotRun_"+datetime.datetime.now().strftime("%Y_%m_%d")+".log", level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
####################################
#Info: Main module of the Robot app (OpenRPA - Robot)
####################################
#Usage:
#Here you can run some activity or list of activities
#After import this module you can use the folowing functions:
#ActivityRun(inActivitySpecificationDict): outActivityResultDict - function - run activity (function or procedure)
#ActivityRunJSON(inActivitySpecificationDictJSON): outActivityResultDictJSON
#ActivityListRun(inActivitySpecificationDictList): outActivityResultDictList - function - run list of activities (function or procedure)
#ActivityListRunJSON(inActivitySpecificationDictListJSON): outActivityResultDictListJSON
#Naming:
#Activity - some action/list of actions
#Module - Any *.py file, which consist of area specific functions
#Argument
#inActivitySpecificationDict:
#{
# ModuleName: <"GUI"|..., str>,
# ActivityName: <Function or procedure name in module, str>,
# ArgumentList: [<Argument 1, any type>, ...] - optional,
# ArgumentDict: {<Argument 1 name, str>:<Argument 1 value, any type>, ...} - optional
#}
#outActivityResultDict:
#{
# ActivitySpecificationDict: {
# ModuleName: <"GUI"|..., str>,
# ActivityName: <Function or procedure name in module, str>,
# ArgumentList: [<Argument 1, any type>, ...] - optional,
# ArgumentDict: {<Argument 1 name, str>: <Argument 1 value, any type>, ...} - optional
# },
# ErrorFlag: <Boolean flag - Activity result has error (true) or not (false), boolean>,
# ErrorMessage: <Error message, str> - required if ErrorFlag is true,
# ErrorTraceback: <Error traceback log, str> - required if ErrorFlag is true,
# Result: <Result, returned from the Activity, int, str, boolean, list, dict> - required if ErrorFlag is false
#}
####################
#Section: Module initialization
####################
#Start childprocess - GUI Module 32 bit
#pdb.set_trace()
if not os.path.isfile("..\\Resources\\WPy32-3720\\python-3.7.2\\OpenRPARobotGUIx32.exe"):
shutil.copyfile('..\\Resources\\WPy32-3720\\python-3.7.2\\python.exe',"..\\Resources\\WPy32-3720\\python-3.7.2\\OpenRPARobotGUIx32.exe")
mProcessGUI_x32 = subprocess.Popen(['..\\Resources\\WPy32-3720\\python-3.7.2\\OpenRPARobotGUIx32.exe',"-m",'pyOpenRPA.Robot'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
#Start childprocess - GUI Module 64 bit - uncomment after WPy64 installation
ProcessCommunicator.ProcessChildSendObject(mProcessGUI_x32,{"ModuleName":"UIDesktop","ActivityName":"Get_OSBitnessInt","ArgumentList":[],"ArgumentDict":{}})
lOSBitness = ProcessCommunicator.ProcessChildReadWaitObject(mProcessGUI_x32)["Result"]
lProcessBitnessStr = str(struct.calcsize("P") * 8)
#start 64 if system support 64
mProcessGUI_x64 = None
if lOSBitness == 64:
if not os.path.isfile("..\\Resources\\WPy64-3720\\python-3.7.2.amd64\\OpenRPARobotGUIx64.exe"):
shutil.copyfile('..\\Resources\\WPy64-3720\\python-3.7.2.amd64\\python.exe',"..\\Resources\\WPy64-3720\\python-3.7.2.amd64\\OpenRPARobotGUIx64.exe")
mProcessGUI_x64 = subprocess.Popen(['..\\Resources\\WPy64-3720\\python-3.7.2.amd64\\OpenRPARobotGUIx64.exe',"-m",'pyOpenRPA.Robot'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
####################
#Section: Activity
####################
def ActivityRun(inActivitySpecificationDict):
#Выполнить отправку в модуль UIDesktop, если ModuleName == "UIDesktop"
#pdb.set_trace()
if inActivitySpecificationDict["ModuleName"] == "UIDesktop":
if "ArgumentList" not in inActivitySpecificationDict:
inActivitySpecificationDict["ArgumentList"]=[]
if "ArgumentDict" not in inActivitySpecificationDict:
inActivitySpecificationDict["ArgumentDict"]={}
#Если mProcessGUI_x64 не инициализирован
lFlagRun64=True
if mProcessGUI_x64 is None:
lFlagRun64=False
else:
if inActivitySpecificationDict["ActivityName"]=="UIOSelectorsSecs_WaitAppear_List":
#Функция ожидания появления элементов (тк элементы могут быть недоступны, неизвестно в каком фреймворке каждый из них может появиться)
lFlagRun64=True
elif inActivitySpecificationDict["ActivityName"].startswith("UIOSelector") or inActivitySpecificationDict["ActivityName"].startswith("PWASpecification"):
if len(inActivitySpecificationDict["ArgumentList"])>0:
if len(inActivitySpecificationDict["ArgumentList"][0])>0:
#Определение разрядности (32 и 64) для тех функций, где это необходимо
######################################################
#Выполнить проверку разрядности через UIOSelector_Get_BitnessInt
#Отправить запрос в дочерний процесс, который отвечает за работу с Windows окнами
#pdb.set_trace()
#Внимание! Проверка разрядности специально делается на процессе 64 бита, тк процесс 32 бита зависает на 35 итерации проверки
ProcessCommunicator.ProcessChildSendObject(mProcessGUI_x64,{"ModuleName":"UIDesktop","ActivityName":"UIOSelector_Get_BitnessInt","ArgumentList":[inActivitySpecificationDict["ArgumentList"][0]],"ArgumentDict":inActivitySpecificationDict["ArgumentDict"]})
#Получить ответ от дочернего процесса
lResponseObject=ProcessCommunicator.ProcessChildReadWaitObject(mProcessGUI_x64)
#pdb.set_trace()
if lResponseObject["Result"]==32:
lFlagRun64=False
#Запуск 64
#pdb.set_trace()
if lFlagRun64:
#Отправить запрос в дочерний процесс, который отвечает за работу с Windows окнами
ProcessCommunicator.ProcessChildSendObject(mProcessGUI_x64,inActivitySpecificationDict)
#Получить ответ от дочернего процесса
lResponseObject=ProcessCommunicator.ProcessChildReadWaitObject(mProcessGUI_x64)
else:
#Запуск 32
#Отправить запрос в дочерний процесс, который отвечает за работу с Windows окнами
ProcessCommunicator.ProcessChildSendObject(mProcessGUI_x32,inActivitySpecificationDict)
#Получить ответ от дочернего процесса
lResponseObject=ProcessCommunicator.ProcessChildReadWaitObject(mProcessGUI_x32)
#Остальные модули подключать и выполнять здесь
else:
lArgumentList=[]
if "ArgumentList" in inActivitySpecificationDict:
lArgumentList=inActivitySpecificationDict["ArgumentList"]
lArgumentDict={}
if "ArgumentDict" in inActivitySpecificationDict:
lArgumentDict=inActivitySpecificationDict["ArgumentDict"]
#Подготовить результирующую структуру
lResponseObject={"ActivitySpecificationDict":inActivitySpecificationDict,"ErrorFlag":False}
try:
#Подключить модуль для вызова
lModule=importlib.import_module(inActivitySpecificationDict["ModuleName"])
#Найти функцию
lFunction=getattr(lModule,inActivitySpecificationDict["ActivityName"])
#Выполнить вызов и записать результат
lResponseObject["Result"]=lFunction(*lArgumentList,**lArgumentDict)
except Exception as e:
#Установить флаг ошибки и передать тело ошибки
lResponseObject["ErrorFlag"]=True
lResponseObject["ErrorMessage"]=str(e)
lResponseObject["ErrorTraceback"]=traceback.format_exc()
return lResponseObject
#########################################################
#Run list of activities
#########################################################
def ActivityListRun(inActivitySpecificationDictList):
lResult=[]
for lItem in inActivitySpecificationDictList:
lResult.append(ActivityRun(lItem))
return lResult

@ -0,0 +1,34 @@
import logging
import datetime
#Robot settings
def Settings():
import os
mDict = {
"Logger": logging.getLogger("Robot"),
"Storage": {
"Robot_R01_help": "Robot data storage in orchestrator env",
"Robot_R01": {}
},
"ProcessBitness": {
"Python32FullPath": None, #Set from user: "..\\Resources\\WPy32-3720\\python-3.7.2\\OpenRPARobotGUIx32.exe"
"Python64FullPath": None, #Set from user
"Python32ProcessName": "OpenRPAUIDesktopX32.exe", #Config set once
"Python64ProcessName": "OpenRPAUIDesktopX64.exe" #Config set once
}
}
#Создать файл логирования
# add filemode="w" to overwrite
if not os.path.exists("Reports"):
os.makedirs("Reports")
##########################
#Подготовка логгера Robot
#########################
mRobotLogger=mDict["Logger"]
mRobotLogger.setLevel(logging.INFO)
# create the logging file handler
mRobotLoggerFH = logging.FileHandler("Reports\ReportRobot_"+datetime.datetime.now().strftime("%Y_%m_%d")+".log")
mRobotLoggerFormatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
mRobotLoggerFH.setFormatter(mRobotLoggerFormatter)
# add handler to logger object
mRobotLogger.addHandler(mRobotLoggerFH)
############################################

@ -0,0 +1,65 @@
import unittest
from threading import Timer
import sys
lFolderPath = "/".join(__file__.split("\\")[:-3])
sys.path.insert(0, lFolderPath)
from pyOpenRPA.Robot import OrchestratorConnector
from pyOpenRPA.Robot import Utils
class MyTestCase(unittest.TestCase):
def test_something(self):
#self.assertEqual(True, False)
mGlobal={"Storage":{"R01_OrchestratorToRobot":{"Test":"Test2"}}}
# t=OrchestratorConnector.IntervalDataSendAsync(
# Interval=1,
# RobotStorage=mGlobal["Storage"],
# RobotStorageKey="R01_OrchestratorToRobot",
# OrchestratorKeyList=["Storage", "R01_OrchestratorToRobot"],
# OrchestratorProtocol="http",
# OrchestratorHost="localhost",
# OrchestratorPort=8081,
# OrchestratorAuthToken="1992-04-03-0643-ru-b4ff-openrpa52zzz"
# )
# t=OrchestratorConnector.DataSendSync(
# RobotValue="Test",
# OrchestratorKeyList=["Storage", "R01_OrchestratorToRobot"],
# OrchestratorProtocol="http",
# OrchestratorHost="localhost",
# OrchestratorPort=8081,
# OrchestratorAuthToken="1992-04-03-0643-ru-b4ff-openrpa52zzz"
# )
import time
#def Func(lT,inl):
# print(lT)
# return True
#lTimer= Utils.TimerRepeat.TimerRepeat(1, Func, ["dddd"],{"inl":9})
#lTimer.start()
OrchestratorConnector.ConfigurationInit({
"IntervalDataSendResetAsync": [
{
"Interval": 2,
"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"
}
]
})
while True:
print(mGlobal["Storage"]["R01_OrchestratorToRobot"])
# t = OrchestratorConnector.DataSendResetAsync(
# 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"
# )
time.sleep(0.5)
if __name__ == '__main__':
unittest.main()

@ -1,44 +1,18 @@
from pywinauto import win32defines, win32structures, win32functions
import pdb
import pywinauto
import json
import sys
import ctypes
import struct
import os
import select
import zlib
import win32api
import win32clipboard
import time
import traceback
from . import ProcessCommunicator
from . import JSONNormalize
from .Utils import ProcessCommunicator
from . import Utils #For ProcessBitness
from threading import Timer
import datetime
import logging
import re
import copy
#Создать файл логирования
# add filemode="w" to overwrite
if not os.path.exists("Reports"):
os.makedirs("Reports")
##########################
#Подготовка логгера Robot
#########################
mRobotLogger=logging.getLogger("RobotLogger")
mRobotLogger.setLevel(logging.INFO)
# create the logging file handler
mRobotLoggerFH = logging.FileHandler("Reports\ReportRobotGUIRun_"+datetime.datetime.now().strftime("%Y_%m_%d")+".log")
mRobotLoggerFormatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
mRobotLoggerFH.setFormatter(mRobotLoggerFormatter)
# add handler to logger object
mRobotLogger.addHandler(mRobotLoggerFH)
############################################
# When import UIDesktop init the other bitness python
#For this type UIDesktop.Utils.ProcessBitness.SettingsInit(inSettingsDict)
# For this type
# UIDesktop.Utils.ProcessBitness.SettingsInit(inSettingsDict)
# inSettingsDict = {
# "Python32FullPath": None, #Set from user: "..\\Resources\\WPy32-3720\\python-3.7.2\\OpenRPARobotGUIx32.exe"
# "Python64FullPath": None, #Set from user

@ -1,10 +1,9 @@
import json
import subprocess
import zlib
import sys
import os
from . import JSONNormalize
import pdb
############################################
####Межпроцессное взаимодействие
############################################
@ -41,7 +40,6 @@ def ProcessParentWriteString(lString):
#Вернуть \f
lByteString = lByteString.replace(b'\f',b'{{{f}}}')
############################
#print(b"Result: "+lByteString)
#lByteString= b'x\x9c\xdd\x95]O\xc20\x14\x86\xffJ\xb3[5\xa1Cqz\x07\xc4\xe8\x8d\x1fQ\x13.\x0cYJw\xb6U\xbav\xe9\xce"\x84\xf0\xdfm\'"\xb8\xa0L%Q\xb3\x9b\xf6=\xdfO\x9a\xb3\x99\x17\x97\x8a\xa3\xd0\xea\x8ae\xe0\x9d\x12\xaf[\xa2\xce\x98S\xee\x80\x19\x9e^\xea\xb2\x803\t\x19(\xbc\x10`\x9c6\xf5\xf6\x89\xc7LRt\x8daS\x1b\xf5\xf00\xf3\xd4"\xc1u\x0e\xea\xf6\xa6K\x0e\xc8\xb9\xd6\x89\x04\xd2O\x8d\xb6&\x1bb\x04OC\x84\t~\xe2\x97\x1b\xcd\xa1(B\x11YG\xdaj\xfb\xc1\x9b\xb8\xa2\xa4LE\xd2\xd5\xa4\xf6\xdenY\x85Kf\xc3^;yI\x18\x0eD\x94\x00\x0e\x84{{n}}\xa9K\xce\xb5B\xa3e\x88\xd3\xbc\xf2Z\xd5\xaa\x82\xaa\x94\xd25\x0b\x1c\x99J\xaa\x023OB\xec\xbavEP\xe7\x8b\x93\x11I\xeaTz\xe2\xbb\xebH\xa3eW5\xe8\xb7\xe6\xce^*\x14\xb6\x83e\xda\xf9phe]b^\xe2\xf5\xe8\xd1Vp\xf0\xfe.\xbb\x1b\xa6`\x87\xfc8\x1a\x9bSE0q\xa2\x15\xeer\xe0"\x16\xbcz\x9f\xfdT\xc8h\x9d\xdf\xc7\xd4\xbe\xcdj1\xd9:\xa9\x1f\xe1B7\x81\xa1\xef\xc0\xd0:\x98\xc3-\xc0\xd4X\xfc\xda\xf1i\xbb\xe9\xfc\xdb<\x8c\xff2\x7f\'\xa8\x8d\xdf\xdab\xfc\x9e\xd6\xe3\x8c\x99qQ\xe3\xb0f\xd9\x19\x90{\xade\x8f\x99/3\xa1AC(\xfe\x16P\x06F \x90\xb3\t\x07Iba\x17\x83P\xa4\xbf\xb7G\x9e\x04\xa6vE\x13\xb6\xfc\x13\xd6\xa85\x0b\xdd\x19\xd6^i\x11\xa8FT;G\xfe\x06\xac\xc1q\xb0N\x956\xd84\xae\xe4p\xbe\xfa=\x03\x01\xce\x95\x9a'
#lByteString = b"x\x9c\xb5\x91\xcfO\xc3 \x14\xc7\xff\x95\xa6\xd7uI\xf9Q\x8a\xde\xd4\x93\x07\xbdx\xf00\x97\x05)[I(\x90\x8ef3\xcb\xfew\x81M\xbb\xd9M]\x8c!y\xd0\xf7}\xbc\xef\xe3\xd3\xc9&\xd5\xac\x11\xe9u\x92j\xb1J@2N\x1e\x8d\x13\x96U\xa3Q\x9a%i+y=sb\xed\xceV\xd8\xd6p\xb1\\\xced\xe5K{{n}}\x80`\x9f\xeb\x135\xd3\x95{{n}}.\x08RR\xe4>\xc3\x15\xf3\x97>\xbc\x8f:r\xa3]k\xd4\xcc\xbd\xd9(>K]\x99\xd5\xa1\x12\xbd\x00\xc6\xb0\xcc\xcb0\xa4\xe0\x8e\xe9E4\xd8\xa4J\xcc\xc3\xb44\x07^r\xc6\xfa3\x04(\xbeeQ\x07\x05P\x1a\xa4W\xe3\x9ci\xfc\xf7\x15(\xb6A\xee\xb4\x93\x8d\xd85\x9f`?\xf6n\xd8i0v\xadw\xd5\x95X\x87n>\xf1d\x05\x97s\xc9\x99\x93F\xdf\xd5R\xc5K=\xcc\x1bk\xd5^\x1d`\xfc\xa2]\x06PwJ\r\xf0\x9d\xa2\xf6 tw\xcb\xda\x01\xb6}\x83\xd3\xcc\x00\xec\x99\x15\xf4\x88Y\x99\x1f2\x83\xb4\xfc\x8e\x99\xdf\xb3d\x0c\x01.1E\x04\x93l\xff\x8e\xcf\x7f6\xa4Z\xfc\x82\xeaK\x97c BD\xf3\x101\x89g\xba\x8b\x03\xd0?\x97\xff#\xfb{'\x9a\x8b\xe0\x03H\xc89\xfa\x08\x15\x7f\xa2\x0f >\x80_\x0e\xe0\x93\xb3\xf0\xc3\xc4\xd3m\\\xef\xf8\x958\xa0"
#lt=open("logSendByteStringWithoutN.log","wb")
@ -71,7 +69,6 @@ def ProcessChildSendString(lProcess,lString):
lByteString = lByteString.replace(b'\n',b'{{n}}')
#Отправить сообщение в дочерний процесс
lProcess.stdin.write(lByteString+bytes('\n',"utf-8"))
#print(str(lByteString+bytes('\n',"utf-8")))
lProcess.stdin.flush()
#Вернуть результат
return
@ -82,7 +79,6 @@ def ProcessChildReadWaitString(lProcess):
#pdb.set_trace()
lResult = lProcess.stdout.readline()
#Обработка спец символов
#print(b'NewLine: '+lResult)
#Вернуть потенциальные \n
lResult = lResult.replace(b'{{{n}}}',b'\n')
#Вернуть \r
@ -99,8 +95,6 @@ def ProcessChildReadWaitString(lProcess):
lResult = lResult.replace(b'{{{v}}}',b'\v')
#Вернуть \f
lResult = lResult.replace(b'{{{f}}}',b'\f')
#print("check")
#print(str(lResult))
try:
lResult = zlib.decompress(lResult[0:-1])
lResult = lResult.decode("utf-8")

@ -0,0 +1,28 @@
from threading import Timer
import datetime
# lTimer = RepeatedTimer(3, def, [], {}) # it auto-starts, no need of rt.start()
# if def return None = timer stops
# lTimer.start()
class TimerRepeat(object):
def __init__(self, interval, function, args, kwargs):
self._timer = None
self.interval = interval
self.function = function
self.args = args
self.kwargs = kwargs
self.is_running = False
self.start()
def _run(self):
self.is_running = False
lResult = self.function(*self.args, **self.kwargs)
if lResult is not None:
if lResult:
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

@ -4,10 +4,9 @@ The OpenRPA package (from UnicodeLabs)
"""
__all__ = [
'UIDesktop', 'Clipboard', 'IntegrationOrchestrator', 'Window', 'ProcessCommunicator'
'Clipboard', 'OrchestratorConnector.py', 'Window'
]
__author__ = 'Ivan Maslov <ivan.maslov@unicodelabs.ru>'
#from . import UIDesktop
from . import Clipboard
from . import Window
from . import ProcessCommunicator

@ -8,8 +8,8 @@ lFolderPath = "\\".join(__file__.split("\\")[:-2])
sys.path.append(lFolderPath)
################################
import traceback
from Robot import ProcessCommunicator
from Robot import JSONNormalize
from Robot.Utils import ProcessCommunicator
from Robot.Utils import JSONNormalize
from Robot import UIDesktop
##########################################
#Run UIDesktop from new process. Communication with paren process by PIPE channel

@ -40,7 +40,6 @@ def ProcessParentWriteString(lString):
#Вернуть \f
lByteString = lByteString.replace(b'\f',b'{{{f}}}')
############################
#print(b"Result: "+lByteString)
#lByteString= b'x\x9c\xdd\x95]O\xc20\x14\x86\xffJ\xb3[5\xa1Cqz\x07\xc4\xe8\x8d\x1fQ\x13.\x0cYJw\xb6U\xbav\xe9\xce"\x84\xf0\xdfm\'"\xb8\xa0L%Q\xb3\x9b\xf6=\xdfO\x9a\xb3\x99\x17\x97\x8a\xa3\xd0\xea\x8ae\xe0\x9d\x12\xaf[\xa2\xce\x98S\xee\x80\x19\x9e^\xea\xb2\x803\t\x19(\xbc\x10`\x9c6\xf5\xf6\x89\xc7LRt\x8daS\x1b\xf5\xf00\xf3\xd4"\xc1u\x0e\xea\xf6\xa6K\x0e\xc8\xb9\xd6\x89\x04\xd2O\x8d\xb6&\x1bb\x04OC\x84\t~\xe2\x97\x1b\xcd\xa1(B\x11YG\xdaj\xfb\xc1\x9b\xb8\xa2\xa4LE\xd2\xd5\xa4\xf6\xdenY\x85Kf\xc3^;yI\x18\x0eD\x94\x00\x0e\x84{{n}}\xa9K\xce\xb5B\xa3e\x88\xd3\xbc\xf2Z\xd5\xaa\x82\xaa\x94\xd25\x0b\x1c\x99J\xaa\x023OB\xec\xbavEP\xe7\x8b\x93\x11I\xeaTz\xe2\xbb\xebH\xa3eW5\xe8\xb7\xe6\xce^*\x14\xb6\x83e\xda\xf9phe]b^\xe2\xf5\xe8\xd1Vp\xf0\xfe.\xbb\x1b\xa6`\x87\xfc8\x1a\x9bSE0q\xa2\x15\xeer\xe0"\x16\xbcz\x9f\xfdT\xc8h\x9d\xdf\xc7\xd4\xbe\xcdj1\xd9:\xa9\x1f\xe1B7\x81\xa1\xef\xc0\xd0:\x98\xc3-\xc0\xd4X\xfc\xda\xf1i\xbb\xe9\xfc\xdb<\x8c\xff2\x7f\'\xa8\x8d\xdf\xdab\xfc\x9e\xd6\xe3\x8c\x99qQ\xe3\xb0f\xd9\x19\x90{\xade\x8f\x99/3\xa1AC(\xfe\x16P\x06F \x90\xb3\t\x07Iba\x17\x83P\xa4\xbf\xb7G\x9e\x04\xa6vE\x13\xb6\xfc\x13\xd6\xa85\x0b\xdd\x19\xd6^i\x11\xa8FT;G\xfe\x06\xac\xc1q\xb0N\x956\xd84\xae\xe4p\xbe\xfa=\x03\x01\xce\x95\x9a'
#lByteString = b"x\x9c\xb5\x91\xcfO\xc3 \x14\xc7\xff\x95\xa6\xd7uI\xf9Q\x8a\xde\xd4\x93\x07\xbdx\xf00\x97\x05)[I(\x90\x8ef3\xcb\xfew\x81M\xbb\xd9M]\x8c!y\xd0\xf7}\xbc\xef\xe3\xd3\xc9&\xd5\xac\x11\xe9u\x92j\xb1J@2N\x1e\x8d\x13\x96U\xa3Q\x9a%i+y=sb\xed\xceV\xd8\xd6p\xb1\\\xced\xe5K{{n}}\x80`\x9f\xeb\x135\xd3\x95{{n}}.\x08RR\xe4>\xc3\x15\xf3\x97>\xbc\x8f:r\xa3]k\xd4\xcc\xbd\xd9(>K]\x99\xd5\xa1\x12\xbd\x00\xc6\xb0\xcc\xcb0\xa4\xe0\x8e\xe9E4\xd8\xa4J\xcc\xc3\xb44\x07^r\xc6\xfa3\x04(\xbeeQ\x07\x05P\x1a\xa4W\xe3\x9ci\xfc\xf7\x15(\xb6A\xee\xb4\x93\x8d\xd85\x9f`?\xf6n\xd8i0v\xadw\xd5\x95X\x87n>\xf1d\x05\x97s\xc9\x99\x93F\xdf\xd5R\xc5K=\xcc\x1bk\xd5^\x1d`\xfc\xa2]\x06PwJ\r\xf0\x9d\xa2\xf6 tw\xcb\xda\x01\xb6}\x83\xd3\xcc\x00\xec\x99\x15\xf4\x88Y\x99\x1f2\x83\xb4\xfc\x8e\x99\xdf\xb3d\x0c\x01.1E\x04\x93l\xff\x8e\xcf\x7f6\xa4Z\xfc\x82\xeaK\x97c BD\xf3\x101\x89g\xba\x8b\x03\xd0?\x97\xff#\xfb{'\x9a\x8b\xe0\x03H\xc89\xfa\x08\x15\x7f\xa2\x0f >\x80_\x0e\xe0\x93\xb3\xf0\xc3\xc4\xd3m\\\xef\xf8\x958\xa0"
#lt=open("logSendByteStringWithoutN.log","wb")
@ -70,7 +69,6 @@ def ProcessChildSendString(lProcess,lString):
lByteString = lByteString.replace(b'\n',b'{{n}}')
#Отправить сообщение в дочерний процесс
lProcess.stdin.write(lByteString+bytes('\n',"utf-8"))
#print(str(lByteString+bytes('\n',"utf-8")))
lProcess.stdin.flush()
#Вернуть результат
return
@ -80,7 +78,6 @@ def ProcessChildReadWaitString(lProcess):
#Ожидаем ответ от процесса
lResult = lProcess.stdout.readline()
#Обработка спец символов
#print(b'NewLine: '+lResult)
#Вернуть потенциальные \n
lResult = lResult.replace(b'{{{n}}}',b'\n')
#Вернуть \r
@ -97,8 +94,6 @@ def ProcessChildReadWaitString(lProcess):
lResult = lResult.replace(b'{{{v}}}',b'\v')
#Вернуть \f
lResult = lResult.replace(b'{{{f}}}',b'\f')
#print("check")
#print(str(lResult))
lResult = zlib.decompress(lResult[0:-1])
lResult = lResult.decode("utf-8")
#Вернуть результат

@ -0,0 +1,108 @@
import pdb
import json
import subprocess
import zlib
import os
from . import ProcessCommunicator
import importlib
import traceback
import logging
import sys
import datetime
import struct
import shutil
from pyOpenRPA.Robot import UIDesktop
global mGlobalDict
####################################
#Info: Main module of the Robot app (OpenRPA - Robot)
####################################
#Usage:
#Here you can run some activity or list of activities
#After import this module you can use the folowing functions:
#ActivityRun(inActivitySpecificationDict): outActivityResultDict - function - run activity (function or procedure)
#ActivityRunJSON(inActivitySpecificationDictJSON): outActivityResultDictJSON
#ActivityListRun(inActivitySpecificationDictList): outActivityResultDictList - function - run list of activities (function or procedure)
#ActivityListRunJSON(inActivitySpecificationDictListJSON): outActivityResultDictListJSON
#Naming:
#Activity - some action/list of actions
#Module - Any *.py file, which consist of area specific functions
#Argument
#inActivitySpecificationDict:
#{
# ModuleName: <"GUI"|..., str>,
# ActivityName: <Function or procedure name in module, str>,
# ArgumentList: [<Argument 1, any type>, ...] - optional,
# ArgumentDict: {<Argument 1 name, str>:<Argument 1 value, any type>, ...} - optional
#}
#outActivityResultDict:
#{
# ActivitySpecificationDict: {
# ModuleName: <"GUI"|..., str>,
# ActivityName: <Function or procedure name in module, str>,
# ArgumentList: [<Argument 1, any type>, ...] - optional,
# ArgumentDict: {<Argument 1 name, str>: <Argument 1 value, any type>, ...} - optional
# },
# ErrorFlag: <Boolean flag - Activity result has error (true) or not (false), boolean>,
# ErrorMessage: <Error message, str> - required if ErrorFlag is true,
# ErrorTraceback: <Error traceback log, str> - required if ErrorFlag is true,
# Result: <Result, returned from the Activity, int, str, boolean, list, dict> - required if ErrorFlag is false
#}
####################
#Section: Activity
####################
def ActivityRun(inActivitySpecificationDict):
lResponseObject = {}
#Выполнить отправку в модуль UIDesktop, если ModuleName == "UIDesktop"
if inActivitySpecificationDict["ModuleName"] == "UIDesktop":
if "ArgumentList" not in inActivitySpecificationDict:
inActivitySpecificationDict["ArgumentList"]=[]
if "ArgumentDict" not in inActivitySpecificationDict:
inActivitySpecificationDict["ArgumentDict"]={}
#Run the activity
try:
#Найти функцию
lFunction=getattr(UIDesktop,inActivitySpecificationDict["ActivityName"])
#Выполнить вызов и записать результат
lResponseObject["Result"]=lFunction(*inActivitySpecificationDict["ArgumentList"],**inActivitySpecificationDict["ArgumentDict"])
except Exception as e:
#Установить флаг ошибки и передать тело ошибки
lResponseObject["ErrorFlag"]=True
lResponseObject["ErrorMessage"]=str(e)
lResponseObject["ErrorTraceback"]=traceback.format_exc()
#Остальные модули подключать и выполнять здесь
else:
lArgumentList=[]
if "ArgumentList" in inActivitySpecificationDict:
lArgumentList=inActivitySpecificationDict["ArgumentList"]
lArgumentDict={}
if "ArgumentDict" in inActivitySpecificationDict:
lArgumentDict=inActivitySpecificationDict["ArgumentDict"]
#Подготовить результирующую структуру
lResponseObject={"ActivitySpecificationDict":inActivitySpecificationDict,"ErrorFlag":False}
try:
#Подключить модуль для вызова
lModule=importlib.import_module(inActivitySpecificationDict["ModuleName"])
#Найти функцию
lFunction=getattr(lModule,inActivitySpecificationDict["ActivityName"])
#Выполнить вызов и записать результат
lResponseObject["Result"]=lFunction(*lArgumentList,**lArgumentDict)
except Exception as e:
#Установить флаг ошибки и передать тело ошибки
lResponseObject["ErrorFlag"]=True
lResponseObject["ErrorMessage"]=str(e)
lResponseObject["ErrorTraceback"]=traceback.format_exc()
return lResponseObject
#########################################################
#Run list of activities
#########################################################
def ActivityListRun(inActivitySpecificationDictList):
lResult=[]
for lItem in inActivitySpecificationDictList:
lResult.append(ActivityRun(lItem))
return lResult

@ -5,12 +5,30 @@ import json
import subprocess
import zlib
import os
from . import ProcessCommunicator
import sys
import traceback
from pyOpenRPA.Robot import Robot
from . import RobotConnector
import importlib
#Единый глобальный словарь (За основу взять из Settings.py)
global mGlobalDict
#Call Settings function from argv[1] file
################################################
lSubmoduleFunctionName = "Settings"
lFileFullPath = sys.argv[1]
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)
mGlobalDict = None
if lSubmoduleFunctionName in dir(lTechModuleFromSpec):
# Run SettingUpdate function in submodule
mGlobalDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)()
#################################################
RobotConnector.mGlobalDict = mGlobalDict
#Init the robot
RobotConnector.UIDesktop.Utils.ProcessBitness.SettingsInit(mGlobalDict["ProcessBitness"])
# HTTPRequestHandler class
# HTTP Studio web server class
class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
#ResponseContentTypeFile
def SendResponseContentTypeFile(self,inContentType,inFilePath):
@ -82,7 +100,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
#pdb.set_trace()
lRequestObject=lInputObject
#Отправить команду роботу
lResponseObject=Robot.ActivityRun(lRequestObject)
lResponseObject=RobotConnector.ActivityRun(lRequestObject)
message = json.dumps(lResponseObject)
except Exception as e:
#Установить флаг ошибки
@ -113,7 +131,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
lRequestObject=lInputObject
lOutputObject=[]
#pdb.set_trace()
lResponseObject=Robot.ActivityListRun(lRequestObject)
lResponseObject=RobotConnector.ActivityListRun(lRequestObject)
#Сформировать текстовый ответ
message = json.dumps(lResponseObject)
# Write content as utf-8 data
@ -121,14 +139,15 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
return
def run():
print('starting server...')
inServerAddress = "";
inPort = mGlobalDict["Server"]["ListenPort"];
# Server settings
# Choose port 8080, for port 80, which is normally used for a http server, you need root access
server_address = ('127.0.0.1', 8081)
server_address = (inServerAddress, inPort)
httpd = HTTPServer(server_address, testHTTPServer_RequestHandler)
print('running server...')
# Logging
mGlobalDict["Logger"].info(f"Server init. Listen URL: {inServerAddress}, Listen port: {inPort}")
# Запуск адреса в браузере
os.system("explorer http://127.0.0.1:8081")
os.system(f"explorer http://127.0.0.1:{str(inPort)}")
httpd.serve_forever()
#print(ChildProcessReadWaitString(p))
run()

@ -9,6 +9,115 @@
crossorigin="anonymous"></script>
<script src="3rdParty/Semantic-UI-CSS-master/semantic.min.js"></script>
<script>
// Production steps of ECMA-262, Edition 6, 22.1.2.1
if (!Array.from) {
Array.from = (function () {
var toStr = Object.prototype.toString;
var isCallable = function (fn) {
return typeof fn === 'function' || toStr.call(fn) === '[object Function]';
};
var toInteger = function (value) {
var number = Number(value);
if (isNaN(number)) { return 0; }
if (number === 0 || !isFinite(number)) { return number; }
return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
};
var maxSafeInteger = Math.pow(2, 53) - 1;
var toLength = function (value) {
var len = toInteger(value);
return Math.min(Math.max(len, 0), maxSafeInteger);
};
// The length property of the from method is 1.
return function from(arrayLike/*, mapFn, thisArg */) {
// 1. Let C be the this value.
var C = this;
// 2. Let items be ToObject(arrayLike).
var items = Object(arrayLike);
// 3. ReturnIfAbrupt(items).
if (arrayLike == null) {
throw new TypeError('Array.from requires an array-like object - not null or undefined');
}
// 4. If mapfn is undefined, then let mapping be false.
var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
var T;
if (typeof mapFn !== 'undefined') {
// 5. else
// 5. a If IsCallable(mapfn) is false, throw a TypeError exception.
if (!isCallable(mapFn)) {
throw new TypeError('Array.from: when provided, the second argument must be a function');
}
// 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (arguments.length > 2) {
T = arguments[2];
}
}
// 10. Let lenValue be Get(items, "length").
// 11. Let len be ToLength(lenValue).
var len = toLength(items.length);
// 13. If IsConstructor(C) is true, then
// 13. a. Let A be the result of calling the [[Construct]] internal method
// of C with an argument list containing the single item len.
// 14. a. Else, Let A be ArrayCreate(len).
var A = isCallable(C) ? Object(new C(len)) : new Array(len);
// 16. Let k be 0.
var k = 0;
// 17. Repeat, while k < len (also steps a - h)
var kValue;
while (k < len) {
kValue = items[k];
if (mapFn) {
A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);
} else {
A[k] = kValue;
}
k += 1;
}
// 18. Let putStatus be Put(A, "length", len, true).
A.length = len;
// 20. Return A.
return A;
};
}());
}
if (!Object.assign) {
Object.defineProperty(Object, 'assign', {
enumerable: false,
configurable: true,
writable: true,
value: function(target, firstSource) {
'use strict';
if (target === undefined || target === null) {
throw new TypeError('Cannot convert first argument to object');
}
var to = Object(target);
for (var i = 1; i < arguments.length; i++) {
var nextSource = arguments[i];
if (nextSource === undefined || nextSource === null) {
continue;
}
var keysArray = Object.keys(Object(nextSource));
for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
var nextKey = keysArray[nextIndex];
var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
if (desc !== undefined && desc.enumerable) {
to[nextKey] = nextSource[nextKey];
}
}
}
return to;
}
});
}
var mGlobal={}
$(document)
.ready(function() {
@ -17,11 +126,8 @@
/////////////////////////////////////////////////////////////////
mGlobal.Settings={}
mGlobal.Settings.mUIOTreeHeight=450
mGlobal.GUIElement={}
mGlobal.GenerateUniqueID=function(inPrefix="ID") {
mGlobal.GenerateUniqueID=function(inPrefix) {
return inPrefix+Math.round(Math.random()*1000)+"-"+Math.round(Math.random()*10000)+"-"+Math.round(Math.random()*1000)
}
///Инициализация
@ -158,7 +264,7 @@
}
///Функция визуализации дерева
mGlobal.ElementTree.fRender = function(inElementsTreeDataArray,inBackendString="-")
mGlobal.ElementTree.fRender = function(inElementsTreeDataArray,inBackendString)
{
var lHTMLList=
'<b style="font-size:10px;" >Backend: '+inBackendString+'</b>\
@ -166,7 +272,7 @@
///Циклический обход списка
for (var i = 0; i< inElementsTreeDataArray.length;i++) {
///Добавить HTML код позиции
lHTMLList+=mGlobal.ElementTree.fItemGenerateHTML_JS(inElementsTreeDataArray[i])
lHTMLList+=mGlobal.ElementTree.fItemGenerateHTML_JS(inElementsTreeDataArray[i],[])
}
///Закрывающая список HTML
lHTMLList+="</div>"
@ -176,9 +282,9 @@
}
///Функция визуализации дерева
///Вызов создания вложенного листа, если имеется атрибут SpecificationChild
mGlobal.ElementTree.fItemGenerateHTML_JS = function(inItem,inParentSpecification=[]){
mGlobal.ElementTree.fItemGenerateHTML_JS = function(inItem,inParentSpecification){
///Генерация уникального кода для элемента
var lElementId = mGlobal.GenerateUniqueID()
var lElementId = mGlobal.GenerateUniqueID("ID")
//Добавить информацию об элементе в словарь JS
///Урезанная часть селектора (сделать, чтобы была без SpecificationChild)
var lSelectorLocal={};
@ -245,7 +351,7 @@
var lHTMLTree='<div class="ui list">'
var lResponseJSON=JSON.parse(lData)
for (i=0;i<lResponseJSON.Result.length;i++) {
var lElementId = mGlobal.GenerateUniqueID()
var lElementId = mGlobal.GenerateUniqueID("ID")
var lSubItemHandleId=lResponseJSON.Result[i].handle;
var lSubItemActionOnClick=' onclick="mGlobal.TreeLoadSubTree(\''+lElementId+'\');" '
var lSubItemActionOnRightClick=' onclick="mGlobal.ElementHighlightNew(\''+lElementId+'\');" '
@ -293,7 +399,7 @@
var lSpecificationArrayNew=[]
for (i=0;i<lSpecificationArray.length;i++) {
lSpecificationArrayNew.push(lSpecificationArray[i])
var lElementId = mGlobal.GenerateUniqueID()
var lElementId = mGlobal.GenerateUniqueID("ID")
var lOnClickSelect= ' onclick="mGlobal.ElementPropertyListLoad(\''+lElementId+'\');" '
lHTMLList+='\
<div class="item" id="'+lElementId+'" '+lOnClickSelect+'>\
@ -679,7 +785,7 @@
///Очистить дерево
mGlobal.ElementTree.fClear();
///Прогрузить новое дерево
mGlobal.ElementTree.fRender(lResponseJSON.Result,$(".openrpa-value-backend")[0].value);
mGlobal.ElementTree.fRender(lResponseJSON.Result,$(".openrpa-value-backend")[0].value,"-");
///Показать ошибку, если таковая возникла
if (lResponseJSON["ErrorFlag"]) {
mGlobal.ShowModal("GUI Error",lResponseJSON.ErrorMessage+" \nTraceback: "+lResponseJSON.ErrorTraceback);

@ -78,12 +78,15 @@ def SessionRDPStart(inRDPFilePath):
[
[{"title": "Подключение к удаленному рабочему столу", "class_name": "#32770", "backend": "win32"},
{"title": "Боль&ше не выводить запрос о подключениях к этому компьютеру", "friendly_class_name": "CheckBox"}],
[{"title": "Remote Desktop Connection", "class_name": "#32770", "backend": "win32"},
{"title": "D&on't ask me again for connections to this computer",
"friendly_class_name": "CheckBox"}],
[{"title_re": f"{lRDPFileName} — .*",
"class_name": "TscShellContainerClass", "backend": "win32"}]
],
60
30
)
#Click if 0 is appear
#Click if 0 is appear (RUS)
if 0 in lWaitResult:
#Check the box do not retry
UIDesktop.UIOSelector_Get_UIO([{"title": "Подключение к удаленному рабочему столу", "backend": "win32"},
@ -96,7 +99,23 @@ def SessionRDPStart(inRDPFilePath):
[{"title_re": f"{lRDPFileName} — .*",
"class_name": "TscShellContainerClass", "backend": "win32"}]
],
60
30
)
# Click if 1 is appear (ENG)
if 1 in lWaitResult:
# Check the box do not retry
UIDesktop.UIOSelector_Get_UIO([{"title": "Remote Desktop Connection", "class_name": "#32770", "backend": "win32"},
{"title": "D&on't ask me again for connections to this computer",
"friendly_class_name": "CheckBox"}]).check()
# Go to connection
UIDesktop.UIOSelector_Get_UIO([{"title": "Remote Desktop Connection", "class_name": "#32770", "backend": "win32"},
{"title": "Co&nnect", "class_name": "Button"}]).click()
lWaitResult = UIDesktop.UIOSelectorsSecs_WaitAppear_List(
[
[{"title_re": f"{lRDPFileName} — .*",
"class_name": "TscShellContainerClass", "backend": "win32"}]
],
30
)
#Prepare little window
SessionScreen100x550(lRDPFileName)

@ -1,17 +1,34 @@
from pyOpenRPA.Robot import UIDesktop
from . import Connector
import os
import pdb
#Check for session is closed. Reopen if detected. Always keep session is active
def Monitor(inGlobalDict, inListUpdateTimeout):
while True:
lFlagWhile = True
while lFlagWhile:
# UIOSelector list init
lUIOSelectorList = []
for lItem in inGlobalDict["RDPList"]:
lUIOSelectorList.append([{"title_re": f"{lItem['SessionHex']} — .*", "backend": "win32"}])
#Run wait command
lRDPDissappearList = UIDesktop.UIOSelectorsSecs_WaitDisappear_List(lUIOSelectorList, inListUpdateTimeout)
#Analyze if flag safeturn off is activated
if inGlobalDict.get("OrchestratorToRobotResetStorage",{}).get("SafeTurnOff",False):
lFlagWhile=False
#Set status disconnected for all RDP List
for lItem in inGlobalDict["RDPList"]:
lItem["FlagSessionIsActive"]=False
#Kill all RDP sessions
os.system('taskkill /F /im mstsc.exe')
#Return from function
return
for lItem in lRDPDissappearList:
inGlobalDict["RDPList"][lItem]["FlagSessionIsActive"] = False # Set flag that session is disconnected
#pdb.set_trace()
#Session start
try:
Connector.Session(inGlobalDict["RDPList"][lItem])
except Exception:
pass
return None
#TODO Def garbage window cleaner (if connection was lost)

@ -1,22 +0,0 @@
#Robot RDPActive settings
def Settings():
mDict = {
"RDPList":
[
{
"Host": "77.77.22.22", # Host address
"Port": "7777", # RDP Port
"Login": "test", # Login
"Password": "test", # Password
"Screen": {
"Width": 1680, #Width of the remote desktop in pixels
"Height": 1050, #Height of the remote desktop in pixels
# "640x480" or "1680x1050" or "FullScreen". If Resolution not exists set full screen
"FlagUseAllMonitors": False, # True or False
"DepthBit": "32" # "32" or "24" or "16" or "15"
},
"SessionHex":"" # Hex is created when robot runs
}
]
}
return mDict

@ -35,9 +35,15 @@ lCMDString = 'reg add "HKEY_CURRENT_USER\\Software\\Microsoft\\Terminal Server C
os.system(lCMDString)
#time.sleep()
for lConfigurationItem in mGlobalDict["RDPList"]:
try:
Connector.Session(lConfigurationItem)
lConfigurationItem["FlagSessionIsActive"]=True #Flag that session is started
except Exception:
pass
#Run monitor
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'
os.system(lCMDString)
#Close all thread from OrchestratorConnection
mGlobalDict["OrchestratorConnectorTerminateAll"]()

@ -3,7 +3,7 @@ r"""
The OpenRPA package (from UnicodeLabs)
"""
__version__ = 'v1.0.32'
__version__ = 'v1.0.34'
__all__ = []
__author__ = 'Ivan Maslov <ivan.maslov@unicodelabs.ru>'
#from .Core import Robot

@ -1,24 +1,35 @@
import logging
import datetime
#Robot settings
from pyOpenRPA.Robot import OrchestratorConnector
import os
import logging
import datetime
#Definitions
lOrchestratorHost="localhost"
lOrchestratorPort=8081
lOrchestratorProtocol="http"
lOrchestratorAuthToken="1992-04-03-0643-ru-b4ff-openrpa52zzz"
#Robot settings
def Settings():
import os
mDict = {
"Logger": logging.getLogger("Robot"),
"Storage": {
"Robot_R01_help": "Robot data storage in orchestrator env",
"Robot_R01": {}
},
"ProcessBitness": {
"Python32FullPath": None, #Set from user: "..\\Resources\\WPy32-3720\\python-3.7.2\\OpenRPARobotGUIx32.exe"
"Python64FullPath": None, #Set from user
"Python32ProcessName": "OpenRPAUIDesktopX32.exe", #Config set once
"Python64ProcessName": "OpenRPAUIDesktopX64.exe" #Config set once
},
"Logger": logging.getLogger("Robot"),
"OrchestratorToRobotStorage": {
},
"OrchestratorToRobotResetStorage": {
"SafeTurnOff":False #Control from orchestrator to safety turn off robot
},
"OrchestratorConnector": {
#Fill below
}
},
"OrchestratorConnectorTerminateAll":OrchestratorConnector.IntervalTermimateAll #Call this function when program must be shutted down (to kill threads from OrchestratorConnector)
}
######################
#OrchestratorConnector
@ -31,10 +42,10 @@ def Settings():
"RobotStorageKey": "R01_OrchestratorToRobot",
"RobotResetValue": {"Test": "Test"},
"OrchestratorKeyList": ["Storage", "R01_OrchestratorToRobot"],
"OrchestratorProtocol": "http",
"OrchestratorHost": "localhost",
"OrchestratorPort": 8081,
"OrchestratorAuthToken": "1992-04-03-0643-ru-b4ff-openrpa52zzz"
"OrchestratorProtocol": lOrchestratorProtocol,
"OrchestratorHost": lOrchestratorHost,
"OrchestratorPort": lOrchestratorPort,
"OrchestratorAuthToken": lOrchestratorAuthToken
}
]
}

@ -1,4 +1,5 @@
cd %~dp0
RD /S /Q "__pycache__"
RD /S /Q "build"
RD /S /Q "dist"
.\..\Resources\WPy64-3720\python-3.7.2.amd64\python.exe setup.py sdist bdist_wheel

@ -0,0 +1,5 @@
recursive-include pyOpenRPA\Resources *
recursive-include pyOpenRPA\Orchestrator\Web *
recursive-include pyOpenRPA\Studio\Web *
include pyOpenRPA\Tools\RobotRDPActive\Template.rdp
include pyOpenRPA\Tools\RobotScreenActive\ConsoleStart.bat

@ -1,3 +1,6 @@
cd %~dp0
RD /S /Q "__pycache__"
RD /S /Q "build"
RD /S /Q "dist"
.\..\Resources\WPy64-3720\python-3.7.2.amd64\python.exe setup.py sdist bdist_wheel
pause >nul

@ -3,7 +3,7 @@ r"""
The OpenRPA package (from UnicodeLabs)
"""
__version__ = 'v1.0.32'
__version__ = 'v1.0.34'
__all__ = []
__author__ = 'Ivan Maslov <ivan.maslov@unicodelabs.ru>'
#from .Core import Robot

@ -46,5 +46,5 @@ setup(name='pyOpenRPA',
],
include_package_data=True,
#data_files = datafiles,
#package_data = {"": datafiles},
#package_data = {"pyOpenRPA": datafiles},
zip_safe=False)

@ -1,4 +1,4 @@
cd %~dp0\..\Sources
copy /Y ..\Resources\WPy64-3720\python-3.7.2.amd64\python.exe ..\Resources\WPy64-3720\python-3.7.2.amd64\OpenRPA_Studio.exe
.\..\Resources\WPy64-3720\python-3.7.2.amd64\OpenRPA_Studio.exe -m pyOpenRPA.Studio "..\Studio\Settings.py"
.\..\Resources\WPy64-3720\python-3.7.2.amd64\OpenRPA_Studio.exe -m pyOpenRPA.Studio "..\Studio\SettingsStudioExample.py"
pause >nul

@ -38,7 +38,7 @@ def Settings():
"OrchestratorConnector": {
#Fill below
},
"OrchestratorConnectorTerminateAll":OrchestratorConnector.IntervalTermimateAll
"OrchestratorConnectorTerminateAll":OrchestratorConnector.IntervalTermimateAll #Call this function when program must be shutted down (to kill threads from OrchestratorConnector)
}
######################
#OrchestratorConnector

@ -1,4 +1,4 @@
cd %~dp0..\..\Sources
copy /Y ..\Resources\WPy64-3720\python-3.7.2.amd64\python.exe ..\Resources\WPy64-3720\python-3.7.2.amd64\OpenRPA_RobotRDPActive.exe
..\Resources\WPy64-3720\python-3.7.2.amd64\OpenRPA_RobotRDPActive.exe -m pyOpenRPA.Tools.RobotRDPActive "C:\Abs\Archive\scopeSrcUL\OpenRPA_Creds\RobotRDPActive\SettingsVSK.py"
..\Resources\WPy64-3720\python-3.7.2.amd64\OpenRPA_RobotRDPActive.exe -m pyOpenRPA.Tools.RobotRDPActive "..\Utils\RobotRDPActive\SettingsRobotRDPActiveExample.py"
pause >nul

@ -1,4 +1,6 @@
Beta before 1.0.1 (new way of OpenRPA with improovments. Sorry, but no backward compatibility)/ Backward compatibility will start from 1.0.1
Beta before 1.1.0 (new way of OpenRPA with improovments. Sorry, but no backward compatibility)/ Backward compatibility will start from 1.0.1
[1.0.33]
Manu changes - look git
[1.0.31]
Orchestrator new engine - test 2 is ready. Go to PIP
[1.0.30]

Loading…
Cancel
Save