diff --git a/Orchestrator/Settings/Settings.py b/Orchestrator/Settings/Settings.py new file mode 100644 index 00000000..b31566b9 --- /dev/null +++ b/Orchestrator/Settings/Settings.py @@ -0,0 +1,157 @@ +import psutil +import datetime +def RenderRobotR01(inGlobalConfiguration): + #Subheader Variants + lSubheaderRunTrueText="Состояние: Работает" + lSubheaderRunFalseText="Состояние: Не работает" + #Run button + #Такое большое количество слэшей связано с тем, что этот текст отправляется сначала в браузер, рендерится там, а потом отправляется на процессор оркестратора + lOnClickRunButton="""mGlobal.Controller.CMDRunText("C:\\\\\\\\RPA\\\\\\\\R01_IntegrationOrderOut\\\\\\\\Sources\\\\\\\\R01_IntegrationOrderOut_64_Start.cmd");""" + #Force close button + lOnClickForceCloseButton="""mGlobal.Controller.CMDRunText("taskkill /F /im Robot_R01.exe");""" + #Result template + lResultDict={ + "HeaderLeftText":"Автозагрузка заявок на расход", + "HeaderRightText":"R01", + "SubheaderText":lSubheaderRunFalseText, + "BodyKeyValueList":[ + #Дата запуска: 10:00:09 01.09.2019 + {"Key":"Дата запуска","Value":"Не запущен"}, + {"Key":"Текущий шаг","Value":"Не запущен"}, + {"Key":"Время выполнения шага","Value":"--с."}, + {"Key":"Отчет робота","Value":"Скачать"} + ], + "FooterText":"Дата изменения: 9:38:00 09.10.2019", + "FooterButtonX2List":[ + {"Text":"Ручной запуск", "Color":"green", "Link":"", "OnClick": lOnClickRunButton}, + {"Text":"Безопасная остановка", "Color disabled":"orange", "Link":""} + ], + "FooterButtonX1List":[ + {"Text":"Принудительная остановка", "Color":"red", "Link":"", "OnClick": lOnClickForceCloseButton} + ] + } + #Check if process running + if CheckIfProcessRunning("Robot_R01"): + lResultDict["SubheaderText"]=lSubheaderRunTrueText + #Fill robot info from Storage - R01 + if "Robot_R01" in inGlobalConfiguration.get("Storage",{}): + lItemDict=inGlobalConfiguration["Storage"]["Robot_R01"] + #lResultDict["HeaderLeftText"]=lItemDict["Name"] + #lResultDict["HeaderRightText"]=lItemDict["Code"] + lResultDict["BodyKeyValueList"][0]["Value"]=lItemDict.get("RunDateTimeString","Не запущен") + lResultDict["BodyKeyValueList"][1]["Value"]=lItemDict.get("StepCurrentName","Не запущен") + lResultDict["BodyKeyValueList"][2]["Value"]=lItemDict.get("StepCurrentDuration","--с.") + else: + #Process not running + lResultDict["FooterText"]=f'Дата изменения: {datetime.datetime.now().strftime("%H:%M:%S %d.%m.%Y")}' + else: + #Process not running + lResultDict["FooterText"]=f'Дата изменения: {datetime.datetime.now().strftime("%H:%M:%S %d.%m.%Y")}' + return lResultDict +def CheckIfProcessRunning(processName): + ''' + Check if there is any running process that contains the given name processName. + ''' + #Iterate over the all the running process + for proc in psutil.process_iter(): + try: + # Check if process name contains the given name string. + if processName.lower() in proc.name().lower(): + return True + except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): + pass + return False; + +#Orchestrator settings +mDict = { + "Server":{ + "ListenPort_":"Порт, по которому можно подключиться к демону", + "ListenPort":8081, + "ListenURLList":[ + { + "Description":"Local machine test", + "URL_":"Сетевое расположение сервера демона", + "URL":"http://127.0.0.1:8081" + } + ] + }, + "Scheduler":{ + "ActivityTimeCheckLoopSeconds_":"Количество секунд, между циклами проверки действий", + "ActivityTimeCheckLoopSeconds":5, + "ActivityTimeList":[ + { + "description":"Запуск Python консоли", + "__processCode":"Код процесса в openRPA daemon. Данные код может использоваться в дальнейшем для того, чтобы завершить именно тот процесс, который пораждался этой программой", + "processCode":"PythonDebug", + "__activityType":"processStart/processStop", + "activityType":"processStart", + "__time":"__Время запуска активности", + "time":"22:57", + "__timeZone":"Часовой пояс, в рамках которого указано время. По-умолчанию часовой пояс МСК (GMT+4). Формат UTC offset in the form ±HHMM[SS[.ffffff]] ", + "timeZone":"+0400", + "__processPath":"Полный путь/наименование процесса. Запуск производится через subprocess. Идентификатор процесса в дальнейшем сохраняется и его можно будет закрыть с помощью параметра processCode", + "____processPath":"C:\\Abs\\Archive\\scopeSrcUL\\OpenRPA\\OpenRPA_32.cmd", + "processPath":"C:\\Abs\\Archive\\scopeSrcUL\\OpenRPA\\Orchestrator\\RobotDaemon\\runProcessOpenRPARobotDaemon_x32.cmd", + "__processArgs":"Аргументы, передаваемые при запуске процесса", + "processArgs":"", + "__weekdayNumList":"Список номеров дней недели, по которым выполнять инициализаци активности. Отсчет ведется от 0 до 6", + "weekdayNumList":[1,2,3] + }, + { + "description":"Запуск Python консоли", + "__activityType":"processStart/processStop", + "activityType":"processStart", + "__time":"__Время запуска активности", + "time":"23:24", + "__timeZone":"Часовой пояс, в рамках которого указано время. По-умолчанию часовой пояс МСК (GMT+4). Формат UTC offset in the form ±HHMM[SS[.ffffff]] ", + "timeZone":"+0400", + "__processPath":"Полный путь/наименование процесса. Запуск производится через subprocess. Идентификатор процесса в дальнейшем сохраняется и его можно будет закрыть с помощью параметра processCode", + "processPath":"notepad", + "processArgs":"" + }, + { + "description":"Остановка Python консоли", + "activityType":"processStop", + "time":"19:20", + "timeZone":"4", + "processName":"OpenRPARobotDaemon.exe", + "_flagCloseForce":"Признак, что процесс нужно принудительно закрыть (если флага нет, то на процесс просто посылается команда terminate)", + "flagCloseForce":True, + "_flagCloseOnlyCurrentUser":"Признак, что процесс нужно закрыть только у текущего пользователя", + "flagCloseOnlyCurrentUser":True + }, + { + "activityType":"loopActivity", + "loopSeconds":6, + "loopTimeStart":"21:45", + "loopTimeEnd":"21:46", + "pythonPackageName":"CheckActivity", + "pythonFunctionName":"test_activity", + "pythonFunctionArgList":["TestArg1","TestArg2"], + "processPath":"notepad", + "processArgs":"" + } + + ] + }, + "ControlPanelDict":{ + "RefreshSeconds": 5, + "RobotList": [ + { + "RenderFunctionName":"RenderRobotR01", + "RenderFunctionModuleName":"Settings", + "RenderFunctionModuleSubfolderName":"Settings" + } + ] + }, + "FileManager": { + "FileURLFilePathDict_help":"https://localhost:8081/filemanager/. All FileURL s must be set in lowercase", + "FileURLFilePathDict":{ + "r01/report.xlsx":"C:\\RPA\\R01_IntegrationOrderOut\\Data\\Reestr_otgruzok.xlsx" + } + }, + "Storage":{ + "Robot_R01_help":"Robot data storage in orchestrator env", + "Robot_R01":{} + } +} \ No newline at end of file diff --git a/Orchestrator/Web/Index.xhtml b/Orchestrator/Web/Index.xhtml index 47d53bf6..c477c009 100644 --- a/Orchestrator/Web/Index.xhtml +++ b/Orchestrator/Web/Index.xhtml @@ -64,45 +64,7 @@ mGlobal.Info={}; mGlobal.Info.TableActivityLogScheduleListRefresh=function() { - ///Обнулить таблицу - $(".openrpa-info-table-activitylogschedulelist").html("") - $.ajax({ - type: "POST", - url: 'ProcessingRun', - data: '{"actionList":[{"type":"ActivityLogScheduleListGet"}]}', - success: - function(lData,l2,l3) - { - var lResponseJSON=JSON.parse(lData) - ///Отправить запрос на формирование таблицы - lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-hidden-info-table-activitylogschedulelist",lResponseJSON["actionListResult"][0]) - ///Установить HTML код - $(".openrpa-info-table-activitylogschedulelist").html(lHTMLCode) - }, - dataType: "text" - }); - } - - - mGlobal.Info.TablePlanLogListRefresh=function() { - ///Обнулить таблицу - $(".openrpa-info-table-planloglist").html("") - $.ajax({ - type: "POST", - url: 'ProcessingRun', - data: '{"actionList":[{"type":"PlanLogListGet"}]}', - success: - function(lData,l2,l3) - { - var lResponseJSON=JSON.parse(lData) - lResponseJSON["actionListResult"][0]["result"].forEach(function(lItem){lItem["processPathName"]=("processPath" in lItem ? lItem["processPath"] : lItem["processName"])}) - ///Отправить запрос на формирование таблицы - lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-hidden-info-table-planloglist",lResponseJSON["actionListResult"][0]); - ///Установить HTML код - $(".openrpa-info-table-planloglist").html(lHTMLCode) - }, - dataType: "text" - }); + } ////////////////////////// @@ -285,11 +247,56 @@ }); } - ///////////////////////////////////// - ///Инициализация страницы - //////////////////////////////////// - mGlobal.Info.TableActivityLogScheduleListRefresh(); - mGlobal.Info.TablePlanLogListRefresh(); + /////////////////////////////// + ///Scheduler functions + /////////////////////////////// + + mGlobal.Scheduler = {} + mGlobal.Scheduler.ActivityTimeListShow = function() { + $.ajax({ + type: "POST", + url: 'ProcessingRun', + data: '{"actionList":[{"type":"PlanLogListGet"}]}', + success: + function(lData,l2,l3) + { + var lResponseJSON=JSON.parse(lData) + lResponseJSON["actionListResult"][0]["result"].forEach(function(lItem){lItem["processPathName"]=("processPath" in lItem ? lItem["processPath"] : lItem["processName"])}) + ///Отправить запрос на формирование таблицы + lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-hidden-info-table-planloglist",lResponseJSON["actionListResult"][0]); + ///Установить HTML код + $('.ui.modal.basic .content').html(lHTMLCode); + $('.ui.modal.basic').modal('show'); + }, + dataType: "text" + }); + } + + /////////////////////////////// + ///Processor functions + /////////////////////////////// + + mGlobal.Processor = {} + mGlobal.Processor.LogListShow = function() { + ///Обнулить таблицу + $('.ui.modal.basic .content').html(""); + $.ajax({ + type: "POST", + url: 'ProcessingRun', + data: '{"actionList":[{"type":"ActivityLogScheduleListGet"}]}', + success: + function(lData,l2,l3) + { + var lResponseJSON=JSON.parse(lData) + ///Отправить запрос на формирование таблицы + lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-hidden-info-table-activitylogschedulelist",lResponseJSON["actionListResult"][0]) + ///Установить HTML код + $('.ui.modal.basic .content').html(lHTMLCode); + $('.ui.modal.basic').modal('show'); + }, + dataType: "text" + }); + } }) ; @@ -352,86 +359,10 @@
-
+

- Activity log -

-
- - -
-
-
- -
-

- - Plan log -

-
- -
-
-
- -
-
-
-

- - Robot control panel + Dashboard (Robot control panel)

+ + diff --git a/Orchestrator/orchestratorConfiguration.json b/Orchestrator/orchestratorConfiguration.json deleted file mode 100644 index 0da8b556..00000000 --- a/Orchestrator/orchestratorConfiguration.json +++ /dev/null @@ -1,89 +0,0 @@ -{ - "__webServerPort":"Порт, по которому можно подключиться к демону", - "webServerPort":8081, - "webServerMonitorList":[ - { - "daemonName":"Local machine test", - "__daemonURI":"Сетевое расположение сервера демона", - "daemonURI":"http://127.0.0.1:8081" - } - - ], - - "__loopSeconds":"Количество секунд, между циклами проверки действий", - "loopSeconds":5, - "activityList":[ - { - "description":"Запуск Python консоли", - "__processCode":"Код процесса в openRPA daemon. Данные код может использоваться в дальнейшем для того, чтобы завершить именно тот процесс, который пораждался этой программой", - "processCode":"PythonDebug", - "__activityType":"processStart/processStop", - "activityType":"processStart", - "__time":"__Время запуска активности", - "time":"22:57", - "__timeZone":"Часовой пояс, в рамках которого указано время. По-умолчанию часовой пояс МСК (GMT+4). Формат UTC offset in the form ±HHMM[SS[.ffffff]] ", - "timeZone":"+0400", - "__processPath":"Полный путь/наименование процесса. Запуск производится через subprocess. Идентификатор процесса в дальнейшем сохраняется и его можно будет закрыть с помощью параметра processCode", - "____processPath":"C:\\Abs\\Archive\\scopeSrcUL\\OpenRPA\\OpenRPA_32.cmd", - "processPath":"C:\\Abs\\Archive\\scopeSrcUL\\OpenRPA\\Orchestrator\\RobotDaemon\\runProcessOpenRPARobotDaemon_x32.cmd", - "__processArgs":"Аргументы, передаваемые при запуске процесса", - "processArgs":"", - "__weekdayNumList":"Список номеров дней недели, по которым выполнять инициализаци активности. Отсчет ведется от 0 до 6", - "weekdayNumList":[1,2,3] - }, - { - "description":"Запуск Python консоли", - "__activityType":"processStart/processStop", - "activityType":"processStart", - "__time":"__Время запуска активности", - "time":"23:24", - "__timeZone":"Часовой пояс, в рамках которого указано время. По-умолчанию часовой пояс МСК (GMT+4). Формат UTC offset in the form ±HHMM[SS[.ffffff]] ", - "timeZone":"+0400", - "__processPath":"Полный путь/наименование процесса. Запуск производится через subprocess. Идентификатор процесса в дальнейшем сохраняется и его можно будет закрыть с помощью параметра processCode", - "processPath":"notepad", - "processArgs":"" - }, - { - "description":"Остановка Python консоли", - "activityType":"processStop", - "time":"19:20", - "timeZone":"4", - "processName":"OpenRPARobotDaemon.exe", - "_flagCloseForce":"Признак, что процесс нужно принудительно закрыть (если флага нет, то на процесс просто посылается команда terminate)", - "flagCloseForce":true, - "_flagCloseOnlyCurrentUser":"Признак, что процесс нужно закрыть только у текущего пользователя", - "flagCloseOnlyCurrentUser":true - }, - { - "activityType":"loopActivity", - "loopSeconds":6, - "loopTimeStart":"21:45", - "loopTimeEnd":"21:46", - "pythonPackageName":"CheckActivity", - "pythonFunctionName":"test_activity", - "pythonFunctionArgList":["TestArg1","TestArg2"], - "processPath":"notepad", - "processArgs":"" - } - - ], - "ControlPanelDict":{ - "RefreshSeconds": 5, - "RobotList": [ - { - "RenderFunctionName":"RenderRobotR01", - "RenderFunctionModuleName":"orchestratorConfiguration" - } - ] - }, - "FileManager": { - "FileURLFilePathDict_help":"https://localhost:8081/filemanager/. All FileURL s must be set in lowercase", - "FileURLFilePathDict":{ - "r01/report.xlsx":"C:\\RPA\\R01_IntegrationOrderOut\\Data\\Reestr_otgruzok.xlsx" - } - }, - "Storage":{ - "Robot_R01_help":"Robot data storage in orchestrator env", - "Robot_R01":{} - } -} \ No newline at end of file diff --git a/Orchestrator/orchestratorConfiguration.py b/Orchestrator/orchestratorConfiguration.py deleted file mode 100644 index 0dcce922..00000000 --- a/Orchestrator/orchestratorConfiguration.py +++ /dev/null @@ -1,63 +0,0 @@ -import psutil -import datetime -def RenderRobotR01(inGlobalConfiguration): - #Subheader Variants - lSubheaderRunTrueText="Состояние: Работает" - lSubheaderRunFalseText="Состояние: Не работает" - #Run button - #Такое большое количество слэшей связано с тем, что этот текст отправляется сначала в браузер, рендерится там, а потом отправляется на процессор оркестратора - lOnClickRunButton="""mGlobal.Controller.CMDRunText("C:\\\\\\\\RPA\\\\\\\\R01_IntegrationOrderOut\\\\\\\\Sources\\\\\\\\R01_IntegrationOrderOut_64_Start.cmd");""" - #Force close button - lOnClickForceCloseButton="""mGlobal.Controller.CMDRunText("taskkill /F /im Robot_R01.exe");""" - #Result template - lResultDict={ - "HeaderLeftText":"Автозагрузка заявок на расход", - "HeaderRightText":"R01", - "SubheaderText":lSubheaderRunFalseText, - "BodyKeyValueList":[ - #Дата запуска: 10:00:09 01.09.2019 - {"Key":"Дата запуска","Value":"Не запущен"}, - {"Key":"Текущий шаг","Value":"Не запущен"}, - {"Key":"Время выполнения шага","Value":"--с."}, - {"Key":"Отчет робота","Value":"Скачать"} - ], - "FooterText":"Дата изменения: 9:38:00 09.10.2019", - "FooterButtonX2List":[ - {"Text":"Ручной запуск", "Color":"green", "Link":"", "OnClick": lOnClickRunButton}, - {"Text":"Безопасная остановка", "Color disabled":"orange", "Link":""} - ], - "FooterButtonX1List":[ - {"Text":"Принудительная остановка", "Color":"red", "Link":"", "OnClick": lOnClickForceCloseButton} - ] - } - #Check if process running - if CheckIfProcessRunning("Robot_R01"): - lResultDict["SubheaderText"]=lSubheaderRunTrueText - #Fill robot info from Storage - R01 - if "Robot_R01" in inGlobalConfiguration.get("Storage",{}): - lItemDict=inGlobalConfiguration["Storage"]["Robot_R01"] - #lResultDict["HeaderLeftText"]=lItemDict["Name"] - #lResultDict["HeaderRightText"]=lItemDict["Code"] - lResultDict["BodyKeyValueList"][0]["Value"]=lItemDict.get("RunDateTimeString","Не запущен") - lResultDict["BodyKeyValueList"][1]["Value"]=lItemDict.get("StepCurrentName","Не запущен") - lResultDict["BodyKeyValueList"][2]["Value"]=lItemDict.get("StepCurrentDuration","--с.") - else: - #Process not running - lResultDict["FooterText"]=f'Дата изменения: {datetime.datetime.now().strftime("%H:%M:%S %d.%m.%Y")}' - else: - #Process not running - lResultDict["FooterText"]=f'Дата изменения: {datetime.datetime.now().strftime("%H:%M:%S %d.%m.%Y")}' - return lResultDict -def CheckIfProcessRunning(processName): - ''' - Check if there is any running process that contains the given name processName. - ''' - #Iterate over the all the running process - for proc in psutil.process_iter(): - try: - # Check if process name contains the given name string. - if processName.lower() in proc.name().lower(): - return True - except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): - pass - return False; \ No newline at end of file diff --git a/Orchestrator/orchestratorMain.py b/Orchestrator/orchestratorMain.py index aa8a7aff..1e6cb267 100644 --- a/Orchestrator/orchestratorMain.py +++ b/Orchestrator/orchestratorMain.py @@ -9,6 +9,7 @@ import pdb import orchestratorServer import orchestratorTimer import logging +from Settings import Settings #Создать файл логирования # add filemode="w" to overwrite @@ -21,17 +22,10 @@ lGlobalDict={} #"ActivityLog":[{""}] #"ActivityLogSchedule" -#Чтение конфигурации -lDaemonConfigurationFile = codecs.open("orchestratorConfiguration.json", "r","utf_8_sig") -lDaemonConfigurationJSONString = lDaemonConfigurationFile.read() -#Закрыть файловый объект -lDaemonConfigurationFile.close() -#Преобразование в JSON -lDaemonConfigurationObject=json.loads(lDaemonConfigurationJSONString) - +lDaemonConfigurationObject=Settings.mDict #Инициализация настроечных параметров -lDaemonLoopSeconds=lDaemonConfigurationObject["loopSeconds"] +lDaemonLoopSeconds=lDaemonConfigurationObject["Scheduler"]["ActivityTimeCheckLoopSeconds"] lDaemonActivityLogDict={} #Словарь отработанных активностей, ключ - кортеж (, , , ) lDaemonStartDateTime=datetime.datetime.now() @@ -50,7 +44,7 @@ while True: lCurrentDateTime=datetime.datetime.now() #Циклический обход правил lFlagSearchActivityType=True - for lItem in lDaemonConfigurationObject["activityList"]: + for lItem in lDaemonConfigurationObject["Scheduler"]["ActivityTimeList"]: #Проверка дней недели, в рамках которых можно запускать активность lItemWeekdayList=lItem.get("weekdayNumList",[0,1,2,3,4,5,6]) if lCurrentDateTime.weekday() in lItemWeekdayList: diff --git a/Orchestrator/orchestratorProcessor.py b/Orchestrator/orchestratorProcessor.py index b2d29991..6867a8af 100644 --- a/Orchestrator/orchestratorProcessor.py +++ b/Orchestrator/orchestratorProcessor.py @@ -74,7 +74,7 @@ def ProcessingRun(inConfigurationDict): #Обработка команды PlanLogListGet if lItem["type"]=="PlanLogListGet": #pdb.set_trace() - lResult["actionListResult"][-1] = {**lResult["actionListResult"][-1], **{"result":mGlobalDict["JSONConfigurationDict"]["activityList"]}} + lResult["actionListResult"][-1] = {**lResult["actionListResult"][-1], **{"result":mGlobalDict["JSONConfigurationDict"]["Scheduler"]["ActivityTimeList"]}} #Обработка команды ActivityCMDRun if lItem["type"]=="ActivityCMDRun": lCMDCode="cmd /c "+lItem["code"] diff --git a/Orchestrator/orchestratorServer.py b/Orchestrator/orchestratorServer.py index f8ba8530..a2cadb13 100644 --- a/Orchestrator/orchestratorServer.py +++ b/Orchestrator/orchestratorServer.py @@ -10,6 +10,8 @@ from PIL import ImageGrab from threading import Thread import orchestratorProcessor import importlib +import pdb +import imp def SaveScreenshot(inFilePath): # grab fullscreen @@ -30,9 +32,33 @@ class RobotDaemonServer(Thread): mJSONConfigurationDict=inGlobalDict["JSONConfigurationDict"] #Перенос переменной в orchestratorProcessor orchestratorProcessor.mGlobalDict=inGlobalDict + #Init other functions + #TODO do module init once when run + #lRenderFunctionsRobotList=mJSONConfigurationDict["ControlPanelDict"]["RobotList"] + #for lItem in lRenderFunctionsRobotList: + #lModuleImportName = lItem.get("RenderFunctionModuleSubfolderName","") + #f = None + #filename = None + #description = None + #if lModuleImportName!="": + # lModuleImportName = f'{lItem["RenderFunctionModuleSubfolderName"]}.{lItem["RenderFunctionModuleName"]}' + # f, filename, description = imp.find_module(lModuleImportName) + #else: + # lModuleImportName = lItem["RenderFunctionModuleName"] + # f, filename, description = imp.find_module(lModuleImportName) + #Подключить модуль для вызова + #importlib.import_module(lModuleImportName) + #pdb.set_trace() + #import imp + #f, filename, description = imp.find_module(lModuleImportName) + #example_package = imp.load_module(lModuleImportName, f, filename, description) + #print('Package:', example_package) + #f.close() + #print(globals()) + #print(lModuleImportName) def run(self): inServerAddress=""; - inPort = mJSONConfigurationDict["webServerPort"]; + inPort = mJSONConfigurationDict["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 @@ -45,9 +71,6 @@ class RobotDaemonServer(Thread): # HTTPRequestHandler class class testHTTPServer_RequestHandler(BaseHTTPRequestHandler): #ResponseContentTypeFile - def Config(self,inJSONConfigurationDict): - self.mJSONConfigurationDict=inJSONConfigurationDict - #ResponseContentTypeFile def SendResponseContentTypeFile(self,inContentType,inFilePath): # Send response status code self.send_response(200) @@ -112,7 +135,13 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler): lRenderFunctionsRobotList=mJSONConfigurationDict["ControlPanelDict"]["RobotList"] for lItem in lRenderFunctionsRobotList: #Подключить модуль для вызова - lModule=importlib.import_module(lItem["RenderFunctionModuleName"]) + #print(globals()) + lModuleImportName = lItem.get("RenderFunctionModuleSubfolderName","") + if lModuleImportName!="": + lModuleImportName = f'{lItem["RenderFunctionModuleSubfolderName"]}.{lItem["RenderFunctionModuleName"]}' + else: + lModuleImportName = lItem["RenderFunctionModuleName"] + lModule=importlib.import_module(lModuleImportName) #Найти функцию lFunction=getattr(lModule,lItem["RenderFunctionName"]) #Выполнить вызов и записать результат diff --git a/Orchestrator/todo.txt b/Orchestrator/todo.txt new file mode 100644 index 00000000..6afdd76d --- /dev/null +++ b/Orchestrator/todo.txt @@ -0,0 +1,4 @@ +1. orchestrator Orchestrator/ OrchestratorMain > Orchestrator +2. orchestratorProcessor +3. inConfiguration. - +4. orchestratorProcessor diff --git a/v1.0.4 b/v1.0.4 new file mode 100644 index 00000000..e69de29b