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 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

@ -6,25 +6,28 @@
<div class="header">Применение:</div>
<p>Текст панели управления.</p>
<div class="header">Сотрудник:</div>
{% if UserInfoDict['UserNameUpperStr'] %}
<p>{{UserInfoDict['UserNameUpperStr']}}</p>
{% else %}
<p>Авторизация отключена в настройках оркестратора</p>
{% endif %}
</div>
<div class="ui segment" id="{{config.robot_key_str}}-segment">
<div class="ui two column very relaxed grid">
<div class="column">
<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">
<i class="circular play icon"></i>
Включен
</h2>
<script>start_block(1);</script>
{% else %}
<h2 class="ui center aligned icon header red">
<i class="circular stop icon"></i>
Выключен
</h2>
<script>start_block(1);</script>
{% endif %}
</div>
@ -32,24 +35,94 @@
<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}}-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 class="ui vertical divider">
</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>
<script src="/{{config.robot_key_str}}/scripts.js"></script>
<script type="text/javascript">
$(document).ready(function() {
// 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)
# Autoinit control panels starts with CP_
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
Orchestrator.Orchestrator(inGSettings=gSettings, inDumpRestoreBool=False)

@ -123,6 +123,7 @@ def AgentActivityItemReturnGet(inGUIDStr, inCheckIntervalSecFloat = 0.5, inGSett
:param inGSettings: Глобальный словарь настроек Оркестратора (синглтон)
:param inGUIDStr: ГУИД (GUID) активности (ActivityItem)
:param inCheckIntervalSecFloat: Интервал в секундах, с какой частотой выполнять проверку результата. По умолчанию 0.5
:param inTimeoutSecFloat: Время ожидания ответа. Если ответ не поступил, генерация исключения Exception.
:return: Результат выполнения активности. !ВНИМАНИЕ! Возвращаются только то результаты, которые могут быть интерпретированы в JSON формате.
"""
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"])
"ArgList":[], # Args list
"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)
}
#Send item in AgentDict for the futher data transmition

Loading…
Cancel
Save