From 095e6feb94f6dab0b411fad5a73bda6be1bb627d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=B2=D0=B0=D0=BD=20=D0=9C=D0=B0=D1=81=D0=BB=D0=BE?= =?UTF-8?q?=D0=B2?= Date: Wed, 7 Dec 2022 15:00:17 +0300 Subject: [PATCH] Create ORC CP SIMPLE_01 --- Orchestrator/Demo/SIMPLE_01/config.py | 150 ++++++++++++------ Orchestrator/Demo/SIMPLE_01/index.html | 89 ++++++++++- Orchestrator/Demo/SIMPLE_01/scripts.js | 1 - Orchestrator/config.py | 2 +- .../Orchestrator/__Orchestrator__.py | 3 +- 5 files changed, 184 insertions(+), 61 deletions(-) delete mode 100644 Orchestrator/Demo/SIMPLE_01/scripts.js diff --git a/Orchestrator/Demo/SIMPLE_01/config.py b/Orchestrator/Demo/SIMPLE_01/config.py index 4c30004a..8cde756a 100644 --- a/Orchestrator/Demo/SIMPLE_01/config.py +++ b/Orchestrator/Demo/SIMPLE_01/config.py @@ -2,72 +2,122 @@ from pyOpenRPA.Tools import CrossOS import os import sys import time -import json +import threading from pyOpenRPA import Orchestrator -from datetime import date from pyOpenRPA.Orchestrator.Server import app -import threading from fastapi import Depends, Body from fastapi.responses import PlainTextResponse from fastapi.responses import FileResponse -time.sleep(1.5) # Определить очередность в панели управления from fastapi.staticfiles import StaticFiles -# путь к папке, в которой расположена панель управления (используется для формирования других путей) -cp_path_str = CrossOS.PathJoinList(CrossOS.PathSplitList(__file__)[:-1]) - -#AGENT SETTINGS -agent_hostname_str = "" -agent_username_str = "" - -# ROBOT SETTINGS -robot_logs_path_str = f"{cp_path_str}" +time.sleep(1.5) # Определить очередность в панели управления +cp_path_str = CrossOS.PathJoinList(CrossOS.PathSplitList(__file__)[:-1]) # ПАПКА ПАНЕЛИ УПРАВЛЕНИЯ (АВТОИДЕНТИФИКАЦИЯ ПО ТЕКУЩЕМУ ФАЙЛУ) +# # # # # # # # # # # # # # БЛОК # # # # # ПАРАМЕТРОВ # # # # # НАЧАЛО # # # # # # # # # # # +# ПАРАМЕТРЫ АГЕНТА +agent_hostname_str = "OPENRPA-00001" # ЕСЛИ НЕ УКАЗЫВАТЬ - ОРКЕСТРАТОР БУДЕТ ЗАПУСКАТЬ ПРОЦЕСС НА СВОЕЙ УЗ +agent_username_str = "IMASL" +# ПАРАМЕТРЫ РОБОТА +robot_logs_path_str = os.path.join(cp_path_str, "..", "..", "Logs") # ПУТЬ К ПАПКЕ С ЛОГАМИ ВИДА гггг_мм_дд.log +robot_key_str = "SIMPLE_01" # КОД РОБОТА (ТЕКСТОВЫЙ ИДЕНТИФИКАТОР В ОБЩЕМ ПРОСТРАНСТВЕ ОРКЕСТРАТОРА) +robot_start_path_str = "notepad" # ПУТЬ К ФАЙЛУ ЗАПУСКА ПРОЦЕССА +robot_process_wo_exe_str = "notepad" # НАИМЕНОВАНИЕ ПРОЦЕССА РОБОТА !БЕЗ УПОМИНАНИЯ РАСШИРЕНИЯ .EXE! +# ПАРАМЕТРЫ ДОПОЛНИТЕЛЬНЫЕ +additional_folder_path_str = os.path.join(cp_path_str, "..", "..", "Readme") # ПУТЬ К ПАПКЕ С ДОПОЛНИТЕЛЬНЫМИ ДОКУМЕНТАМИ - ОТОБРАЖАЮТСЯ НА ПАНЕЛИ ЗАДАЧ +howto_url_str = f"/{robot_key_str}/howto.docx" # URL ССЫЛКА НА ИНСТРУКЦИЮ. НАЧИНАТЬ ОБЯЗАТЕЛЬНО С / +howto_path_str = os.path.join(cp_path_str, "how_to.docx") # ПУТЬ К ИНСТРУКЦИИ НА ДИСКЕ +# # # # # # # # # # # # # # БЛОК # # # # # ПАРАМЕТРОВ # # # # # КОНЕЦ # # # # # # # # # # # +# ПОДКЛЮЧЕНИЕ ПАПКИ С ПАНЕЛЬЮ УПРАВЛЕНИЯ. ДОСТУПНА БУДЕТ ПО URL f"/{robot_key_str}/folder" +app.mount(f"/{robot_key_str}/folder", StaticFiles(directory=os.path.abspath(cp_path_str)), name=f"{robot_key_str}_folder") -gSettings = Orchestrator.GSettingsGet() +# ПОДКЛЮЧЕНИЕ ИНСТРУКЦИИ ПОЛЬЗОВАТЕЛЯ +@app.get(path=howto_url_str,tags=[f"{robot_key_str}"]) +def get_howto(): + return FileResponse(os.path.abspath(howto_path_str)) +# ПОДКЛЮЧЕНИЕ ПАПКИ С ЛОГАМИ +app.mount(f"/{robot_key_str}/logs", StaticFiles(directory=os.path.abspath(robot_logs_path_str)), name=f"{robot_key_str}-logs") -# календарь -robot_key_str = "SIMPLE_01" +# ПОДКЛЮЧЕНИЕ ПАПКИ С ДОП. ДОКУМЕНТАМИ +app.mount(f"/{robot_key_str}/additional", StaticFiles(directory=os.path.abspath(additional_folder_path_str)), name=f"{robot_key_str}-additional") +def additional_files(): + files = os.listdir(additional_folder_path_str) + return files[::-1] -# Подключить папку -#app.mount(f"/{robot_key_str}/calendar", StaticFiles(directory=os.path.join(os.path.abspath(cpPathStr), "calendar")), name=f"{robot_key_str}_calendar") +# ПРОВЕРКА ПРОЦЕССА (ЗАПУЩЕН ИЛИ ОСТАНОВЛЕН) ВНИМАНИЕ! АСИНХРОННАЯ ПРОВЕРКА, ЧТОБЫ НЕ ЗАВИСАЛ ПОТОК ОБРАБОТКИ (СЕТЕВОЕ ВЗАИМОДЕЙСТВИЕ) +robot_is_started_bool = False +def robot_is_started(): + global robot_is_started_bool + if agent_hostname_str: + process_list_guid_str = Orchestrator.AgentProcessWOExeUpperUserListGet( + inHostNameStr=agent_hostname_str, inUserStr=agent_username_str) + process_list = Orchestrator.AgentActivityItemReturnGet(inGUIDStr=process_list_guid_str, inTimeoutSecFloat=60.0) + if robot_process_wo_exe_str.upper() in process_list: robot_is_started_bool=True + else: robot_is_started_bool=False + else: + if robot_process_wo_exe_str.upper() in Orchestrator.ProcessListGet()['ProcessWOExeUpperList']: robot_is_started_bool=True + else: robot_is_started_bool=False +robot_status_interval_sec_float = 3.0 # ИНТЕРВАЛ ПРОВЕРКИ АКТИВНОСТИ ПРОЦЕССА РОБОТА +def loop_robot_is_started(): + global robot_status_interval_sec_float + while True: + try: + robot_is_started() + except Exception as e: + pass + time.sleep(robot_status_interval_sec_float) -# пути для ... -htmlPath = os.path.join(cp_path_str, "index.html") -scriptPath = os.path.join(cp_path_str, f"scripts.js") +threading.Thread(target=loop_robot_is_started).start() -# вывод папки логов -def check_folder(folder): - files = os.listdir(folder) - return files[::-1] -app.mount(f"/{robot_key_str}/logs", StaticFiles(directory=robot_logs_path_str), name=f"{robot_key_str}-logs") +# ФУНКЦИЯ ЗАПУСКА ФАЙЛА +@app.post(path=f"/{robot_key_str}/action/start",tags=[f"{robot_key_str}"]) +def robot_start(): + cmd_str = robot_start_path_str + global robot_is_started_bool + if agent_hostname_str: + Orchestrator.AgentOSCMD(inHostNameStr=agent_hostname_str, inUserStr=agent_username_str, + inCMDStr=cmd_str, inRunAsyncBool=True, + inSendOutputToOrchestratorLogsBool=False, inCaptureBool=False) + else: + Orchestrator.OSCMD(inCMDStr=cmd_str,inRunAsyncBool=True) -@app.get(path=f"/{robot_key_str}/scripts.js",tags=[f"{robot_key_str}"]) -def get_file2(): - return FileResponse(os.path.abspath(scriptPath)) +# ФУНКЦИЯ ОСТАНОВКИ ПРОЦЕССА +@app.post(path=f"/{robot_key_str}/action/stop",tags=[f"{robot_key_str}"]) +def robot_stop(): + cmd_str = f"taskkill /f /FI \"USERNAME eq %username%\" /im {robot_process_wo_exe_str}.exe" + global robot_is_started_bool + if agent_hostname_str: + Orchestrator.AgentOSCMD(inHostNameStr=agent_hostname_str, inUserStr=agent_username_str, + inCMDStr=cmd_str, inRunAsyncBool=True, + inSendOutputToOrchestratorLogsBool=False, inCaptureBool=False) + else: + Orchestrator.OSCMD(inCMDStr=cmd_str,inRunAsyncBool=True) + +# ИНИЦИАЛИЗАЦИЯ ПАНЕЛИ УПРАВЛЕНИЯ РОБОТОМ +cp_manager = Orchestrator.Managers.ControlPanel(inControlPanelNameStr=robot_key_str, + inRefreshHTMLJinja2TemplatePathStr=os.path.join(cp_path_str, "index.html"), inJinja2TemplateRefreshBool = True) +cp_manager.Jinja2DataUpdateDictSet(inJinja2DataUpdateDict={"config": sys.modules[__name__]} ) -# сторонние файлы -infoPath = os.path.join(cp_path_str, "how_to.docx") -@app.get(path=f"/{robot_key_str}/how_to.docx",tags=[f"{robot_key_str}"]) -def get_file(): - return FileResponse(os.path.abspath(infoPath)) -#проверка процесса -def process_is_started(): - return Orchestrator.ProcessIsStarted(inProcessNameWOExeStr = robot_key_str) +# HOTFIX Orchestrator.AgentProcessWOExeUpperUserListGet +def HOTFIX_01(inHostNameStr, inUserStr, inGSettings = None): + """L-,W+: Получить список процессов, которые выполняется на сессии Агента. Все процессы фиксируются без постфикса .exe, а также в верхнем регистре. -# функции для запуска процессов -buildPathStr = CrossOS.PathJoinList(CrossOS.PathSplitList(__file__)[:-3]+["builds"]) -startHandPathStr = os.path.join(buildPathStr, "startHand.cmd") -def startHand(): - Orchestrator.AgentOSCMD(inHostNameStr=agent_hostname_str, inUserStr=agent_username_str, inCMDStr=startHandPathStr, inRunAsyncBool=True, inSendOutputToOrchestratorLogsBool=False, inCaptureBool=False) -@app.get(path=f"/{robot_key_str}/startHand",tags=[f"{robot_key_str}"]) -def start_app(): - startHand() + ПРИМЕР РЕЗУЛЬТАТА, КОТОРЫЙ МОЖНО ПОЛУЧИТЬ ПО ГУИД ЧЕРЕЗ ФУНКЦИЮ AgentActivityItemReturnGet: ["ORCHESTRATOR", "AGENT", "CHROME", "EXPLORER", ...] -# инициализация панели -lCPManager = Orchestrator.Managers.ControlPanel(inControlPanelNameStr=robot_key_str, - inRefreshHTMLJinja2TemplatePathStr=htmlPath, inJinja2TemplateRefreshBool = True) -contextDict = {"config": sys.modules[__name__]} -lCPManager.Jinja2DataUpdateDictSet(inJinja2DataUpdateDict=contextDict) + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :return: ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet + """ + inGSettings = Orchestrator.GSettingsGet(inGSettings=inGSettings) # Set the global settings + lActivityItemDict = { + "Def":"ProcessWOExeUpperUserListGet", # def alias (look pyOpeRPA.Agent gSettings["ProcessorDict"]["AliasDefDict"]) + "ArgList":[], # Args list + "ArgDict":{}, # Args dictionary + "ArgGSettings": None, # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + "ArgLogger": None # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + } + #Send item in AgentDict for the futher data transmition + return Orchestrator.AgentActivityItemAdd(inGSettings=inGSettings, inHostNameStr=inHostNameStr, inUserStr=inUserStr, inActivityItemDict=lActivityItemDict) +Orchestrator.AgentProcessWOExeUpperUserListGet = HOTFIX_01 \ No newline at end of file diff --git a/Orchestrator/Demo/SIMPLE_01/index.html b/Orchestrator/Demo/SIMPLE_01/index.html index f1a1b6c5..648f5966 100644 --- a/Orchestrator/Demo/SIMPLE_01/index.html +++ b/Orchestrator/Demo/SIMPLE_01/index.html @@ -6,25 +6,28 @@
Применение:

Текст панели управления.

Сотрудник:
+ + {% if UserInfoDict['UserNameUpperStr'] %}

{{UserInfoDict['UserNameUpperStr']}}

+ {% else %} +

Авторизация отключена в настройках оркестратора

+ {% endif %}

СОСТОЯНИЕ

- {% if config.process_is_started() %} + {% if config.robot_is_started_bool %}

Включен

- {% else %}

Выключен

- {% endif %}
@@ -32,24 +35,94 @@

ДЕЙСТВИЯ

-

-

-

+ {% if config.robot_is_started_bool %} +

+ {% else %} +

+ {% endif %} + + + + +

ДОПОЛНИТЕЛЬНЫЕ МАТЕРИАЛЫ

+
+ {% set additional_files = config.additional_files() %} + {% if additional_files|count > 0 %} + {% for item in additional_files %} +
+ {{item}} +
+ {% endfor %} + {% else %} +

Нет доступных файлов

+ {% endif %} +
- -