Create ORC CP SIMPLE_01

dev-fastapi
Иван Маслов 2 years ago
parent f3d3bcce98
commit 095e6feb94

@ -2,72 +2,122 @@ from pyOpenRPA.Tools import CrossOS
import os import os
import sys import sys
import time import time
import json import threading
from pyOpenRPA import Orchestrator from pyOpenRPA import Orchestrator
from datetime import date
from pyOpenRPA.Orchestrator.Server import app from pyOpenRPA.Orchestrator.Server import app
import threading
from fastapi import Depends, Body from fastapi import Depends, Body
from fastapi.responses import PlainTextResponse from fastapi.responses import PlainTextResponse
from fastapi.responses import FileResponse from fastapi.responses import FileResponse
time.sleep(1.5) # Определить очередность в панели управления
from fastapi.staticfiles import StaticFiles from fastapi.staticfiles import StaticFiles
# путь к папке, в которой расположена панель управления (используется для формирования других путей) time.sleep(1.5) # Определить очередность в панели управления
cp_path_str = CrossOS.PathJoinList(CrossOS.PathSplitList(__file__)[:-1]) cp_path_str = CrossOS.PathJoinList(CrossOS.PathSplitList(__file__)[:-1]) # ПАПКА ПАНЕЛИ УПРАВЛЕНИЯ (АВТОИДЕНТИФИКАЦИЯ ПО ТЕКУЩЕМУ ФАЙЛУ)
# # # # # # # # # # # # # # БЛОК # # # # # ПАРАМЕТРОВ # # # # # НАЧАЛО # # # # # # # # # # #
#AGENT SETTINGS # ПАРАМЕТРЫ АГЕНТА
agent_hostname_str = "" agent_hostname_str = "OPENRPA-00001" # ЕСЛИ НЕ УКАЗЫВАТЬ - ОРКЕСТРАТОР БУДЕТ ЗАПУСКАТЬ ПРОЦЕСС НА СВОЕЙ УЗ
agent_username_str = "" 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") # ПУТЬ К ИНСТРУКЦИИ НА ДИСКЕ
# # # # # # # # # # # # # # БЛОК # # # # # ПАРАМЕТРОВ # # # # # КОНЕЦ # # # # # # # # # # #
# ROBOT SETTINGS # ПОДКЛЮЧЕНИЕ ПАПКИ С ПАНЕЛЬЮ УПРАВЛЕНИЯ. ДОСТУПНА БУДЕТ ПО URL f"/{robot_key_str}/folder"
robot_logs_path_str = f"{cp_path_str}" app.mount(f"/{robot_key_str}/folder", StaticFiles(directory=os.path.abspath(cp_path_str)), name=f"{robot_key_str}_folder")
# ПОДКЛЮЧЕНИЕ ИНСТРУКЦИИ ПОЛЬЗОВАТЕЛЯ
@app.get(path=howto_url_str,tags=[f"{robot_key_str}"])
def get_howto():
return FileResponse(os.path.abspath(howto_path_str))
gSettings = Orchestrator.GSettingsGet() # ПОДКЛЮЧЕНИЕ ПАПКИ С ЛОГАМИ
app.mount(f"/{robot_key_str}/logs", StaticFiles(directory=os.path.abspath(robot_logs_path_str)), name=f"{robot_key_str}-logs")
# ПОДКЛЮЧЕНИЕ ПАПКИ С ДОП. ДОКУМЕНТАМИ
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]
# календарь # ПРОВЕРКА ПРОЦЕССА (ЗАПУЩЕН ИЛИ ОСТАНОВЛЕН) ВНИМАНИЕ! АСИНХРОННАЯ ПРОВЕРКА, ЧТОБЫ НЕ ЗАВИСАЛ ПОТОК ОБРАБОТКИ (СЕТЕВОЕ ВЗАИМОДЕЙСТВИЕ)
robot_key_str = "SIMPLE_01" 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 # ИНТЕРВАЛ ПРОВЕРКИ АКТИВНОСТИ ПРОЦЕССА РОБОТА
#app.mount(f"/{robot_key_str}/calendar", StaticFiles(directory=os.path.join(os.path.abspath(cpPathStr), "calendar")), name=f"{robot_key_str}_calendar") 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)
threading.Thread(target=loop_robot_is_started).start()
# пути для ... # ФУНКЦИЯ ЗАПУСКА ФАЙЛА
htmlPath = os.path.join(cp_path_str, "index.html") @app.post(path=f"/{robot_key_str}/action/start",tags=[f"{robot_key_str}"])
scriptPath = os.path.join(cp_path_str, f"scripts.js") 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)
# вывод папки логов # ФУНКЦИЯ ОСТАНОВКИ ПРОЦЕССА
def check_folder(folder): @app.post(path=f"/{robot_key_str}/action/stop",tags=[f"{robot_key_str}"])
files = os.listdir(folder) def robot_stop():
return files[::-1] cmd_str = f"taskkill /f /FI \"USERNAME eq %username%\" /im {robot_process_wo_exe_str}.exe"
app.mount(f"/{robot_key_str}/logs", StaticFiles(directory=robot_logs_path_str), name=f"{robot_key_str}-logs") 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(): cp_manager = Orchestrator.Managers.ControlPanel(inControlPanelNameStr=robot_key_str,
return FileResponse(os.path.abspath(scriptPath)) 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))
#проверка процесса # HOTFIX Orchestrator.AgentProcessWOExeUpperUserListGet
def process_is_started(): def HOTFIX_01(inHostNameStr, inUserStr, inGSettings = None):
return Orchestrator.ProcessIsStarted(inProcessNameWOExeStr = robot_key_str) """L-,W+: Получить список процессов, которые выполняется на сессии Агента. Все процессы фиксируются без постфикса .exe, а также в верхнем регистре.
# функции для запуска процессов ПРИМЕР РЕЗУЛЬТАТА, КОТОРЫЙ МОЖНО ПОЛУЧИТЬ ПО ГУИД ЧЕРЕЗ ФУНКЦИЮ AgentActivityItemReturnGet: ["ORCHESTRATOR", "AGENT", "CHROME", "EXPLORER", ...]
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()
# инициализация панели :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон)
lCPManager = Orchestrator.Managers.ControlPanel(inControlPanelNameStr=robot_key_str, :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления
inRefreshHTMLJinja2TemplatePathStr=htmlPath, inJinja2TemplateRefreshBool = True) :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления
contextDict = {"config": sys.modules[__name__]} :return: ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet
lCPManager.Jinja2DataUpdateDictSet(inJinja2DataUpdateDict=contextDict) """
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

@ -6,25 +6,28 @@
<div class="header">Применение:</div> <div class="header">Применение:</div>
<p>Текст панели управления.</p> <p>Текст панели управления.</p>
<div class="header">Сотрудник:</div> <div class="header">Сотрудник:</div>
{% if UserInfoDict['UserNameUpperStr'] %}
<p>{{UserInfoDict['UserNameUpperStr']}}</p> <p>{{UserInfoDict['UserNameUpperStr']}}</p>
{% else %}
<p>Авторизация отключена в настройках оркестратора</p>
{% endif %}
</div> </div>
<div class="ui segment" id="{{config.robot_key_str}}-segment"> <div class="ui segment" id="{{config.robot_key_str}}-segment">
<div class="ui two column very relaxed grid"> <div class="ui two column very relaxed grid">
<div class="column"> <div class="column">
<h3 class="ui center aligned icon header">СОСТОЯНИЕ</h3> <h3 class="ui center aligned icon header">СОСТОЯНИЕ</h3>
{% if config.process_is_started() %} {% if config.robot_is_started_bool %}
<h2 class="ui center aligned icon header green"> <h2 class="ui center aligned icon header green">
<i class="circular play icon"></i> <i class="circular play icon"></i>
Включен Включен
</h2> </h2>
<script>start_block(1);</script>
{% else %} {% else %}
<h2 class="ui center aligned icon header red"> <h2 class="ui center aligned icon header red">
<i class="circular stop icon"></i> <i class="circular stop icon"></i>
Выключен Выключен
</h2> </h2>
<script>start_block(1);</script>
{% endif %} {% endif %}
</div> </div>
@ -32,24 +35,94 @@
<h3 class="ui center aligned icon header">ДЕЙСТВИЯ</h3> <h3 class="ui center aligned icon header">ДЕЙСТВИЯ</h3>
<p class="ui center aligned"><button class="ui right labeled icon button" id="{{config.robot_key_str}}-log-btn" onclick="{{config.robot_key_str}}_logs()"><i class="right file alternate icon"></i> Скачать лог </button></p> <p class="ui center aligned"><button class="ui right labeled icon button" id="{{config.robot_key_str}}-log-btn" onclick="{{config.robot_key_str}}_logs()"><i class="right file alternate icon"></i> Скачать лог </button></p>
<p class="ui center aligned"><button class="ui right labeled icon button" id="{{config.robot_key_str}}-info-btn" onclick="{{config.robot_key_str}}_info()"><i class="right info icon"></i> Скачать инструкцию </button></p> <p class="ui center aligned"><button class="ui right labeled icon button" id="{{config.robot_key_str}}-info-btn" onclick="{{config.robot_key_str}}_info()"><i class="right info icon"></i> Скачать инструкцию </button></p>
<p class="ui center aligned"><button class="ui right labeled icon button"><i class="right book icon"></i> Скачать документацию </button></p>
<p class="ui center aligned"><button class="ui right labeled icon button green"><i class="right book icon"></i> Запустить </button></p>
<p class="ui center aligned"><button class="ui right labeled icon button red"><i class="right book icon"></i> Остановить </button></p>
</div> </div>
</div> </div>
<div class="ui vertical divider"> <div class="ui vertical divider">
</div> </div>
</div> </div>
{% if config.robot_is_started_bool %}
<p class="ui center aligned"><button onclick="{{config.robot_key_str}}_action_stop()" id="{{config.robot_key_str}}-action-stop" class="ui fluid right labeled icon button red"><i class="right stop icon"></i> Выключить робота </button></p>
{% else %}
<p class="ui center aligned"><button onclick="{{config.robot_key_str}}_action_start()" id="{{config.robot_key_str}}-action-start" class="ui fluid right labeled icon button green"><i class="right play icon"></i> Включить робота </button></p>
{% endif %}
<h3 class="ui center aligned icon header">ДОПОЛНИТЕЛЬНЫЕ МАТЕРИАЛЫ</h3>
<div class="ui raised segment" id="{{config.robot_key_str}}-raised-segment">
{% set additional_files = config.additional_files() %}
{% if additional_files|count > 0 %}
{% for item in additional_files %}
<div class="ui label teal">
<i class="file icon"></i> <a href="/{{config.robot_key_str}}/additional/{{item}}" download>{{item}}</a>
</div>
{% endfor %}
{% else %}
<h3>Нет доступных файлов</h3>
{% endif %}
</div>
</div> </div>
</div> </div>
<script src="/{{config.robot_key_str}}/scripts.js"></script>
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function() { $(document).ready(function() {
// JS CODE GOES HERE // JS CODE GOES HERE
{{config.robot_key_str}}_logs = function () {
var l_now = new Date();
l_month_str = String(l_now.getMonth()+1)
if (l_month_str.length == 1){
l_month_str = "0"+l_month_str
}
l_day_str = String(l_now.getDate())
if (l_day_str.length == 1){
l_day_str = "0"+l_day_str
}
l_log_date_str = String(l_now.getFullYear())+"_"+l_month_str+"_"+l_day_str
l_log_date_str = window.prompt("Укажите дату лог файла для скачивания (формат: гггг_мм_дд)", l_log_date_str);
if (l_log_date_str != null) {
l_url_str = "/{{config.robot_key_str}}/logs/"+l_log_date_str+".log"
var link = document.createElement('a');
link.setAttribute('href', l_url_str);
link.setAttribute('download', l_log_date_str+".log");
link.click();
}
}
{{config.robot_key_str}}_info = function () {
l_url_str = "{{config.howto_url_str}}"
var link = document.createElement('a');
link.setAttribute('href', l_url_str);
link.click();
}
{{config.robot_key_str}}_action_start = function () {
$("#{{config.robot_key_str}}-action-start")[0].disabled=true
$.ajax({
type: "POST",
url: "/{{config.robot_key_str}}/action/start",
success:
function(in_settings)
{},
dataType:'json'
});
}
{{config.robot_key_str}}_action_stop = function () {
$("#{{config.robot_key_str}}-action-stop")[0].disabled=true
$.ajax({
type: "POST",
url: "/{{config.robot_key_str}}/action/stop",
success:
function(in_settings)
{},
dataType:'json'
});
}
}); });

@ -60,7 +60,7 @@ else:
Orchestrator.OrchestratorSessionRestore(inGSettings=gSettings) Orchestrator.OrchestratorSessionRestore(inGSettings=gSettings)
# Autoinit control panels starts with CP_ # Autoinit control panels starts with CP_
lPyModules = Orchestrator.OrchestratorPySearchInit(inGlobPatternStr="Demo\\*\\config.py", inAsyncInitBool=True, inPackageLevelInt=1) lPyModules = Orchestrator.OrchestratorPySearchInit(inGlobPatternStr="Demo\\*\\config.py", inAsyncInitBool=True, inPackageLevelInt=1)
lPyModules2 = Orchestrator.OrchestratorPySearchInit(inGlobPatternStr="..\\..\\KPI_Effect\\packages\\*_control_panel\\config.py", inAsyncInitBool=True, inPackageLevelInt=1) #lPyModules2 = Orchestrator.OrchestratorPySearchInit(inGlobPatternStr="..\\..\\KPI_Effect\\packages\\*_control_panel\\config.py", inAsyncInitBool=True, inPackageLevelInt=1)
# Call the orchestrator def # Call the orchestrator def
Orchestrator.Orchestrator(inGSettings=gSettings, inDumpRestoreBool=False) Orchestrator.Orchestrator(inGSettings=gSettings, inDumpRestoreBool=False)

@ -123,6 +123,7 @@ def AgentActivityItemReturnGet(inGUIDStr, inCheckIntervalSecFloat = 0.5, inGSett
:param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон)
:param inGUIDStr: ГУИД (GUID) активности (ActivityItem) :param inGUIDStr: ГУИД (GUID) активности (ActivityItem)
:param inCheckIntervalSecFloat: Интервал в секундах, с какой частотой выполнять проверку результата. По умолчанию 0.5 :param inCheckIntervalSecFloat: Интервал в секундах, с какой частотой выполнять проверку результата. По умолчанию 0.5
:param inTimeoutSecFloat: Время ожидания ответа. Если ответ не поступил, генерация исключения Exception.
:return: Результат выполнения активности. !ВНИМАНИЕ! Возвращаются только то результаты, которые могут быть интерпретированы в JSON формате. :return: Результат выполнения активности. !ВНИМАНИЕ! Возвращаются только то результаты, которые могут быть интерпретированы в JSON формате.
""" """
inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings
@ -439,7 +440,7 @@ def AgentProcessWOExeUpperUserListGet(inHostNameStr, inUserStr, inGSettings = No
"Def":"ProcessWOExeUpperUserListGet", # def alias (look pyOpeRPA.Agent gSettings["ProcessorDict"]["AliasDefDict"]) "Def":"ProcessWOExeUpperUserListGet", # def alias (look pyOpeRPA.Agent gSettings["ProcessorDict"]["AliasDefDict"])
"ArgList":[], # Args list "ArgList":[], # Args list
"ArgDict":{}, # Args dictionary "ArgDict":{}, # Args dictionary
"ArgGSettings": "inGSettings", # Name of GSettings attribute: str (ArgDict) or index (for ArgList) "ArgGSettings": None, # Name of GSettings attribute: str (ArgDict) or index (for ArgList)
"ArgLogger": 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 #Send item in AgentDict for the futher data transmition

Loading…
Cancel
Save