def get_xml_filenames(self): """ Определить список обрабатываемых XML файлов. @return: Cписок обрабатываемых XML файлов. """ if self.cache_xml_filenames: # Работаем с мгновенным слепком списка файлов return self.cache_xml_filenames if self.xml_filename is None: msg = u'Не определены XML файлы источника данных <%s>' % self.__class__.__name__ log.warning(msg) journal.write_msg(msg) return list() xml_filenames = list() if self.is_filename_pattern(self.xml_filename): # Если это шаблон, то получить список файлов xml_filenames = glob.glob(self.xml_filename) log.info(u'Найдены XML файлы в <%s>:' % self.xml_filename) for xml_filename in xml_filenames: log.info(u'\t%s' % xml_filename) # Это указание конкретного файла if os.path.exists(self.xml_filename): self.cache_xml_filenames = [self.xml_filename] return self.cache_xml_filenames # else: # log.warning(u'Не найден XML файл <%s> источника данных' % self.xml_filename) self.cache_xml_filenames = xml_filenames return self.cache_xml_filenames
def load_xml_content(xml_filename, is_change_keys=True): """ Загрузить содержимое XML файла в словарно списковую структуру. @param xml_filename: Полное имя XML файла. @param is_change_keys: Произвести автоматическую замену ключей на короткие. @return: Словарно-списковая структура содержания XML файла. Или None в случае ошибки. """ if not os.path.exists(xml_filename): log.warning(u'XML файл <%s> не найден' % xml_filename) return None log.info(u'Загрузка содержимого файла <%s>' % xml_filename) xml_file = None try: xml_file = open(xml_filename, 'r') xml_txt = xml_file.read() xml_file.close() except: if xml_file: xml_file.close() log.fatal(u'Ошибка загрузки содержимого XML файла <%s>' % xml_filename) return None if not xml_txt.strip(): log.error(u'Файл <%s> пустой' % xml_filename) return dict() data = xmltodict.parse(xml_txt) if is_change_keys: data = change_keys_doc(data) return data
def create_src(self, **properties): """ Метод создания объекта источника данных с инициализацией его свойств. @param properties: Словарь свойств источника данных. @return: Объект источника данных или None в случае ошибки. """ # Сначала в любом случае определяем тип источника данных if 'type' in properties: src_typename = properties['type'] src_class = src.DATA_SOURCES.get(src_typename, None) if src_class is None: log.error( u'Ошибка создания объекта источника данных. Тип <%s> не зарегистрирован в системе как источник данных' % src_typename) else: try: log.info(u'Создание объекта источника данных <%s>' % properties.get('name', src_class.__name__)) src_obj = src_class(parent=self, **properties) # Регистрируем новый объект в словаре внутренних объектов self.reg_object(src_obj) return src_obj except: log.fatal(u'Ошибка создания объекта источника данных') else: name = properties.get('name', u'') log.error( u'Ошибка создания объекта источника данных. Не определен тип <%s>' % name) return None
def printSettings(self, dSettings): """ Вывод на экран текущих настроек для отладки. """ for section in dSettings.keys(): log.info(section) for name, value in dSettings[section].items(): log.info('\t%s\t:\t%s' % (name, value))
def diagnostic(self): """ Простая процедура проверки доступа к источнику данных. @return: True/False. """ log.info(u'Диагностика <%s>.<%s>' % (self.__class__.__name__, self.name)) return self.write()
def initPage(self, Page): """ Функция инициализации контролов страницы. @param Page: Объект страницы. """ if self.settings and Page.__class__.__name__ in self.settings and hasattr( Page, 'init'): log.info(u'Инициализация страницы <%s> - <%s>' % (Page.__class__.__name__, self.settings[Page.__class__.__name__])) return Page.init(**self.settings[Page.__class__.__name__]) return None
def get_http(self, url): """ Получить содержание по URL. @param url: Адрес запроса. @return: Вовращает содержимое XML файла или None в случае ошибки. """ if not (url.startswith('http://') or url.startswith('https://')): log.warning( u'Указан не абсолютный адрес <%s> при получении содержания по адресу' % url) url = self.utm_url + url log.info(u'Преобразуем адрес к абсолютному виду <%s>' % url) try: output_xml_filename = os.path.join(self.output_dir, DEFAULT_OUTPUT_XML_FILENAME) if os.path.exists(output_xml_filename): try: log.info(u'Удаление файла <%s>' % output_xml_filename) os.remove(output_xml_filename) except: msg = u'Ошибка удаления файла <%s>' % output_xml_filename log.fatal(msg) journal.write_msg(msg) cmd = '"%s" --output "%s" -X GET %s' % (self.curl, output_xml_filename, url) execfunc.exec_shell(cmd) content = None if os.path.exists(output_xml_filename): try: content = xmlfunc.load_xml_content(output_xml_filename) except: msg = u'Ошибка XML файла данных <%s>' % output_xml_filename log.error(msg) journal.write_msg(msg) self._backup_error_file(output_xml_filename) raise else: msg = u'Не найден выходной файл УТМ <%s>' % output_xml_filename log.warning(msg) journal.write_msg(msg) return content except: msg = u'Ошибка получения содержания УТМ по адресу <%s>' % url log.fatal(msg) journal.write_msg(msg) return None
def uninstall(*argv): """ Главноя функция запуска деинсталляции. В качестве ключей могут быть параметры деинсталляции. [Параметры] --debug - включить все сервисы в режиме отладки --log - включить все сервисы в режиме журналирования --dialog - включить режим диалогов pythondialogs --urwid - включить режим диалогов urwid (по умолчанию) --check= - отметить секцию для установки --uncheck= - снять отметку секции для установки """ log.init(config) log.info(config.TITLE_TXT) try: from .ic.cui import install_wizard except Exception: from ic.cui import install_wizard # Разбираем аргументы командной строки try: options, args = getopt.getopt(argv, 'DL', ['debug', 'log', 'dialog', 'urwid', 'check=', 'uncheck=']) except getopt.error as msg: log.error(u'Ошибка параметров коммандной строки %s' % str(msg), bForcePrint=True) log.warning(__doc__, bForcePrint=True) sys.exit(2) programms = copy.deepcopy(config.UNINSTALL_PROGRAMM) for option, arg in options: if option in ('--debug', '-D'): utils.set_var('SERVICES_DEBUG_MODE', True) log.info(u'Деинсталяция. Установка режима отладки') elif option in ('--log', '-L'): utils.set_var('SERVICES_LOG_MODE', True) log.info('Деинсталяция. Установка режима журналирования') elif option in ('--dialog', ): utils.set_var('DIALOG_MODE', 'python-dialog') elif option in ('--urwid', ): utils.set_var('DIALOG_MODE', 'urwid') elif option in ('--check',): section = int(arg) if arg.isdigit() else arg programms = util.check_section(programms, section, True) elif option in ('--uncheck',): section = int(arg) if arg.isdigit() else arg programms = util.check_section(programms, section, False) result = install_wizard.uninstall(dProgramms=programms) log.info(config.TITLE_TXT) return result
def _read(self, *values): """ Чтение данных из источника данных. @param values: Список читаемых переменных. @return: Список прочианных значений. Если переменная не найдена или произошла ошибка чтения, то вместо значения подставляется None с указанием WARNING в журнале сообщений. """ xml_filenames = self.get_xml_filenames() if not values: log.warning(u'Не определены переменные для чтения в <%s>' % self.name) values = self.values log.debug(u'Переменные взяты из описания источника данных: %s' % values) try: result = [list() for i in range(len(values))] for xml_filename in xml_filenames: # Получаем содержимое XML файла xml_content = xmlfunc.load_xml_content(xml_filename) for i, value in enumerate(values): value_path = getattr(self, value) xml_value = xmlfunc.get_xml_content_by_link( xml_content, value_path) result[i].append(xml_value) # Регистрация состояния state = dict([(values[i], val) for i, val in enumerate(result)]) self.reg_state(**state) if self.auto_remove: for xml_filename in xml_filenames: if os.path.exists(xml_filename): try: log.info(u'Удаление файла <%s>' % xml_filename) os.remove(xml_filename) except: msg = u'Ошибка удаления файла <%s>' % xml_filename log.fatal(msg) journal.write_msg(msg) return result except: log.fatal(u'Ошибка чтения данных из файлов %s' % xml_filenames) return None
def diagnostic(self): """ Простая процедура прверки доступа к источнику данных. @return: True/False. """ connection = None log.info(u'UniReader. Диагностика <%s>.<%s>' % (self.__class__.__name__, self.name)) if self.opc_server is None: msg = u'UniReader. Не определен OPC сервер в <%s>' % self.name log.warning(msg) journal.write_msg(msg) return False if self.topic is None: msg = u'UniReader. Не определен топик в <%s>' % self.name log.warning(msg) journal.write_msg(msg) return False try: # Создание клиента OPC connection = self.create_connection(self.uni_host) if connection is None: msg = u'Не возможно создать объект связи с UniReader. Хост <%s>' % self.uni_host log.error(msg) journal.write_msg(msg) return None # Контроль наличия процедуры чтения значений из OPC сервера rpc_methods = connection.system.listMethods() if 'sources.ReadValueAsString' not in rpc_methods: msg = u'UniReader. Процедура чтения значения из OPC сервера не найдена. Хост <%s>' % self.uni_host log.error(msg) journal.write_msg(msg) return None else: log.info(u'UniReader. Список методов удаленного вызова %s' % str(rpc_methods)) return True except: msg = u'UniReader. Ошибка диагностики <%s>' % self.__class__.__name__ log.fatal(msg) journal.write_msg(msg) return False
def doScenario(self, lScenario=None): """ Функция выполнения сценария. @param lScenario: Сценарий-список шагов сценария. Основным элементом визарда является сценарий: Сценарий - это список кортежей: [(Идентификатор, Функция обработки шага сценария, Аргументы, Именованные аргументы), ...] Исполнение сценария запускается по кнопке <OK> на последней странице визарда. """ if lScenario is None: lScenario = self.scenario # Проверить определена ли альтернативная функция обработки сценария if self.do_scenario: return self.do_scenario(lScenario) else: result = True # обработка сценария по шагам for step in lScenario: if step: id = step[0] func = step[1] args = step[2] kwargs = step[3] enable = step[4] if func and enable: try: log.info( u'Выполнение сценария %s args: %s kwargs: %s' % (func.__name__, args, kwargs)) step_result = func(*args, **kwargs) except: log.fatal( u'Ошибка выполнения функции сценария <%s>' % func) step_result = False if config.DEBUG_MODE: raise result = result and step_result return result
def getSettingsPath(self): """ Папка сохраненных параметров программы. Находиться в HOME. Функция сразу провеяет если этой папки нет, то создает ее. """ if self.settings_path is None: home_path = utils.getHomeDir() self.settings_path = os.path.join(home_path, config.DEFAULT_WIZ_INI_DIR) if not os.path.exists(self.settings_path): try: log.info(u'Создание директории <%s>' % self.settings_path) os.makedirs(self.settings_path) except: log.fatal(u'Ошибка саздания папки <%s>' % self.settings_path) return self.settings_path
def del_http(self, url): """ Удалит данные по URL на сервере УТМ. Когда ответ на запрос обработан его необходимо удалить командой вида: curl -X DELETE http://localhost:8080/opt/out/ReplyPartner/407 Регулярное удаление отработанных запросов из списка и сохраненных ответов на эти запросы из списка предотвращает безконтрольный рост размера базы данных УТМ. @param url: Адрес запроса. """ if not (url.startswith('http://') or url.startswith('https://')): log.warning( u'Указан не абсолютный адрес <%s> при получении содержания по адресу' % url) url = self.utm_url + url log.info(u'Преобразуем адрес к абсолютному виду <%s>' % url) try: output_xml_filename = os.path.join(self.output_dir, DEFAULT_OUTPUT_XML_FILENAME) if os.path.exists(output_xml_filename): try: log.info(u'Удаление файла <%s>' % output_xml_filename) os.remove(output_xml_filename) except: msg = u'Ошибка удаления файла <%s>' % output_xml_filename log.fatal(msg) journal.write_msg(msg) cmd = '"%s" --output "%s" -X DELETE %s' % ( self.curl, output_xml_filename, url) execfunc.exec_shell(cmd) content = xmlfunc.load_xml_content(output_xml_filename) if content is not None: # Необходимо проанализировать ошибки content = self.valid_content(content) return content except: msg = u'Ошибка удаления данных УТМ по адресу <%s>' % url log.fatal(msg) journal.write_msg(msg) return None
def saveSettings(self, sINIFileName=None): """ Сохранение настрек в INI файле. @type sINIFileName: C{string} @param sINIFileName: Полное имя конфигурационного файла. Если None, то генерируется. @return: True - запись параметров прошла успешно, False - запись не прошла по какой-либо причине. """ if sINIFileName is None: sINIFileName = self.genINIFileName() settings = dict() # Сохранение настроечных переменных в словаре настроек log.info('SAVE SETTINGS') if utils.isDebugMode(): self.printSettings(settings) return ini.Dict2INI(settings, sINIFileName)
def loadSettings(self, sINIFileName=None): """ Загрузка настроек из INI файла. @type sINIFileName: C{string} @param sINIFileName: Полное имя конфигурационного файла. Если None, то генерируется. @return: True - загрузка параметров прошла успешно, False - загрузка не прошла по какой-либо причине. """ if sINIFileName is None: sINIFileName = self.genINIFileName() if os.path.exists(sINIFileName): settings = ini.INI2Dict(sINIFileName) settings = ini.toUnicodeINIValues(settings) if settings: # Инициализация переменных настроек self.loadSectionList(settings, 'OPTIONS', 'sources', 'SOURCES') self.loadSectionList(settings, 'OPTIONS', 'destinations', 'DESTINATIONS') self.loadSectionList(settings, 'OPTIONS', 'queue', 'QUEUE') if 'run_mode' in settings.get('OPTIONS', dict()): config.set_cfg_var( 'RUN_MODE', settings.get('OPTIONS', dict()).get('run_mode', 'debug')) config.set_cfg_var( 'TICK_PERIOD', settings.get('OPTIONS', dict()).get('tick', 300)) log.info('LOAD SETTINGS') if utils.isDebugMode(): self.printSettings(settings) return True else: log.warning('Don\'t define settings. Ini file name: %s' % sINIFileName) return False
def create_opc_client(self, opc_host=None): """ Создание объекта OPC клиента. @param opc_host: Хост OPC сервера для возможности удаленного подключения (через DCOM) к OPC серверу. Если не определен, то считается что OPC сервер находится локально. @return: Объект OPC сервера. """ if type(opc_host) not in (None.__class__, str, unicode): msg = u'Не корректный тип хоста OPC сервера <%s>' % type(opc_host) log.error(msg) journal.write_msg(msg) return None is_local_opc = (opc_host is None) or (type(opc_host) in (str, unicode) and opc_host.lower().strip() in ('localhost', '127.0.0.1')) if is_local_opc: log.info(u'OPC сервер находится локально') opc = OpenOPC.client() else: log.info(u'OPC сервер находится на <%s>' % opc_host) opc = OpenOPC.open_client(opc_host) return opc
def create_connection(self, host=None): """ Создание объекта связи с UniReader XMLRPC сервером. @param host: Хост OPC сервера для возможности удаленного подключения (через DCOM) к OPC серверу. Если не определен, то считается что OPC сервер находится локально. @return: Объект Uni - сервера. """ if type(host) not in (None.__class__, str, unicode): msg = u'UniReader. Не корректный тип хоста OPC сервера <%s>' % type( host) log.error(msg) journal.write_msg(msg) return None is_local_opc = (host is None) or (type(host) in (str, unicode) and host.lower().strip() in ('localhost', '127.0.0.1')) if is_local_opc: log.info(u'UniReader. OPC сервер находится локально') else: log.info(u'UniReader. OPC сервер находится на <%s>' % host) url = UNI_SERVER_URL_FMT % (host, self.uni_port) log.info(u'UniReader. URL для подключения к Uni-серверу: <%s>' % url) connection = xmlrpclib.ServerProxy(url) return connection
def _read(self, *values): """ Прочитать данные из источника данных. @param values: Список получаемых значений. @return: Список имен файлов. """ if not self.filename_pattern: msg = u'Не определен шаблон поиска файлов' log.warning(msg) journal.write_msg(msg) return list() filenames = glob.glob(self.filename_pattern) log.info(u'Найденные файлы:') for filename in filenames: log.info(u'\t%s' % filename) self.state = dict([(os.path.basename(filename), os.path.abspath(filename)) for filename in filenames]) return filenames
def _create_install_log_file(self, sInstallLogFileName=None): """ Создание файла install.log. """ if sInstallLogFileName is None: sInstallLogFileName = self.get_install_log_file_name() install_log_file = None try: if not os.path.exists(sInstallLogFileName): path = os.path.dirname(sInstallLogFileName) if not os.path.exists(path): os.makedirs(path) install_log_file = open(sInstallLogFileName, 'wt') install_log_file.close() install_log_file = None log.info(u'Создан файл <%s>' % sInstallLogFileName) return True return False except: if install_log_file: install_log_file.close() raise
def _read(self, *values): """ Прочитать данные из источника данных. @param values: Список получаемых значений. @return: Список записей/рекордсет. """ self.recordset = list() if not self.sql: msg = u'Не определено SQL выражение для получения данных в <%s>' % self.name log.warning(msg) journal.write_msg(msg) self.reg_state(recordset=self.recordset) return self.recordset sql = self.gen_sql_code(self.sql) if not sql.strip(): msg = u'Попытка выполнения пустого запроса SQL' log.warning(msg) journal.write_msg(msg) self.reg_state(recordset=self.recordset) return self.recordset try: self.connect() log.info(u'Выполнение SQL: <%s>' % sql) recordset = self.connection.execute(sql) self.disconnect() self.recordset = [dict(rec) for rec in recordset] log.debug(u'Результат запроса: %s' % str(self.recordset)) except: self.disconnect() msg = u'Ошибка получения данных в <%s>' % self.name log.fatal(msg) journal.write_msg(msg) self.recordset = list() self.reg_state(recordset=self.recordset) return self.recordset
def _write(self, *values): """ Записать данные в приемник данных. @param values: Список записываемых значений @return: True/False. """ if not self.sql: msg = u'Не определено SQL выражение для записи данных в <%s>' % self.name log.warning(msg) journal.write_msg(msg) return False sql = self.gen_sql_code(self.sql) if sql is None: msg = u'Ошибка запроса SQL' log.warning(msg) journal.write_msg(msg) return False if not sql.strip(): msg = u'Попытка выполнения пустого запроса SQL' log.warning(msg) journal.write_msg(msg) return False try: self.connect() log.info(u'Выполнение SQL: <%s>' % sql) self.connection.execute(sql) self.disconnect() return True except: self.disconnect() msg = u'Ошибка записи данных в <%s>' % self.name log.fatal(msg) journal.write_msg(msg) return False
def main(*argv): """ Главноя функция запуска инсталляции. В качестве ключей могут быть параметры инсталяции. [Параметры] --debug - включить все сервисы в режиме отладки --log - включить все сервисы в режиме журналирования --dialog - включить режим диалогов pythondialogs --urwid - включить режим диалогов urwid (по умолчанию) --dosemu_dir= - папка инсталляции dosemu --icservices_dir= - папка инсталляции icservices --check= - отметить секцию для установки --uncheck= - снять отметку секции для установки """ log.init(config) log.info(config.TITLE_TXT) # Проверка устанувки библиотеки pythondialog if not util.check_python_library_version('dialog'): from . import packages packages.install_pythondialog() # Проверка на устанвки библиотеки urwid if not util.check_python_library_version('urwid'): from . import packages packages.install_urwid() try: from .ic.cui import install_wizard except Exception: from ic.cui import install_wizard # Разбираем аргументы командной строки try: options, args = getopt.getopt(argv, 'DL', [ 'debug', 'log', 'dialog', 'urwid', 'dosemu_dir=', 'icservices_dir=', 'check=', 'uncheck=' ]) except getopt.error as err: log.error(u'Ошибка параметров коммандной строки %s' % err.msg, bForcePrint=True) log.warning(__doc__, bForcePrint=True) sys.exit(2) for option, arg in options: if option in ('--debug', '-D'): utils.set_var('SERVICES_DEBUG_MODE', True) log.info(u'Инсталяция. Установка режима отладки') elif option in ('--log', '-L'): utils.set_var('SERVICES_LOG_MODE', True) log.info(u'Инсталяция. Установка режима журналирования') elif option in ('--dialog', ): utils.set_var('DIALOG_MODE', 'python-dialog') elif option in ('--urwid', ): utils.set_var('DIALOG_MODE', 'urwid') elif option in ('--dosemu_dir', ): config.PROGRAMM[config.DRIVE_C_SECTION]['dir'] = arg log.info(u'Dosemu директория <%s>' % config.PROGRAMM[config.DRIVE_C_SECTION]['dir']) elif option in ('--icservices_dir', ): config.PROGRAMM[config.ICSERVICES_SECTION]['dir'] = arg log.info(u'icservices директория <%s>' % config.PROGRAMM[config.ICSERVICES_SECTION]['dir']) config.PROGRAMM[config.ICDAEMON_SECTION]['dir'] = arg log.info(u'icdaemon директория <%s>' % config.PROGRAMM[config.ICDAEMON_SECTION]['dir']) elif option in ('--check', ): section = int(arg) if arg.isdigit() else arg config.PROGRAMM = util.check_section(config.PROGRAMM, section, True) elif option in ('--uncheck', ): section = int(arg) if arg.isdigit() else arg config.PROGRAMM = util.check_section(config.PROGRAMM, section, False) result = install_wizard.install(install_script, None, None) log.info(config.TITLE_TXT) return result
def run_tick(self, n_tick=1): """ Запуск всех объектов для выполнения 1 тика. @param n_tick: Номер текущего тика. @return: True/False. """ try: config.set_cfg_var('TICK_DT_START', datetime.datetime.now()) # ВНИМАНИЕ! Необходимо с начале каждого тика надо создавать объекты # чтобы не контролировать актуальность их состояния log.info(u'Создание объектов...') src_objects = list() for properties in config.SOURCES: # Создаем объекты источников данных obj = self.create(**properties) if obj: src_objects.append(obj) dst_objects = list() for properties in config.DESTINATIONS: # Создаем объекты получателей данных obj = self.create(**properties) if obj: dst_objects.append(obj) if not config.QUEUE: log.info(u'Порядок обработки штатный') log.info(u'Начало обработки...') journal.write_msg(u'Начало обработки...') for src_object in src_objects: log.info(u'Чтение данных из <%s>' % src_object.name) journal.write_msg(u'\tЧтение данных из <%s>' % src_object.description) src_object.read_as_dict() for dst_object in dst_objects: log.info(u'Запись данных в <%s>' % dst_object.name) journal.write_msg(u'\tЗапись данных в <%s>' % dst_object.description) dst_object.write_as_dict() log.info(u'...Конец обработки [%d]' % n_tick) journal.write_msg(u'...Конец обработки') else: log.info(u'Порядок обработки задан явно %s' % config.QUEUE) log.info(u'Начало обработки...') journal.write_msg(u'Начало обработки...') for obj_properties in config.QUEUE: obj_name = obj_properties['name'] obj = self.find_object(obj_name) if obj: obj_type = obj_properties['type'] if obj_type in src.DATA_SOURCES.keys(): # Это источник данных log.info(u'Чтение данных из <%s>' % obj.name) journal.write_msg(u'\tЧтение данных из <%s>' % obj.description) obj.read_as_dict() elif obj_type in dst.DATA_DESTINATIONS.keys(): # Это получатель данных log.info(u'Запись данных в <%s>' % obj.name) journal.write_msg(u'\tЗапись данных в <%s>' % obj.description) obj.write_as_dict() else: # Вообще не определенный тип log.warning( u'Не поддерживаемый тип <%s> объекта <%s>' % (obj_type, obj_name)) log.info(u'...Конец обработки [%d]' % n_tick) journal.write_msg(u'...Конец обработки') # Сбросить кеш состояния в конце такта # obj_list = src_objects + dst_objects # self.clear_all_state_chaches(*obj_list) return True except: log.fatal(u'Ошибка выполнения тика [%d]' % n_tick) return False
def run(self, mode=None): """ Основная процедура запуска регистрации. @param mode: Режим запуска регистратора. @return: True/False. """ # Проинициализировать конфигурационные переменные в соответствии с настройками. self.init_settings() if mode is None: mode = config.get_cfg_var('RUN_MODE') if mode == config.RUN_MODE_SINGLE: # Одноразовый запуск self.run_tick() config.set_cfg_var('TICK_DT_STOP', datetime.datetime.now()) elif mode == config.RUN_MODE_LOOP: # Запуск регистратора в цикле # Запуск цикла обработки do_exit = False tick = config.get_cfg_var('TICK_PERIOD') log.info(u'Период цикла обработки: <%d>...' % tick) i_tick = 1 while not do_exit: start_tick = time.time() end_tick = start_tick + tick self.run_tick(i_tick) if tick > 0: log.warning(u'Для выхода нажмите <ESC>') cur_time = time.time() while end_tick > cur_time: ch_key = keyboardfunc.getchAsync() if keyboardfunc.same_key(ch_key, keyboardfunc.ESC_KEY): do_exit = True log.info(u'Выход из цикла обработки') break cur_time = time.time() # log.debug(u'test tick %d : %d' % (cur_time, end_tick)) else: log.warning(u'Для выхода нажмите <Ctrl+C>') config.set_cfg_var('TICK_DT_STOP', datetime.datetime.now()) log.info(u'...Конец периода цикла обработки [%d]' % i_tick) i_tick += 1 elif mode == config.RUN_MODE_SRC_DIAGNOSTIC: # Запуск регистратора в режиме диагностики источников данных self.do_diagnostic(config.SOURCES) elif mode == config.RUN_MODE_DST_DIAGNOSTIC: # Запуск регистратора в режиме диагностики получателя данных self.do_diagnostic(config.DESTINATIONS) elif mode == config.RUN_MODE_DEBUG: # Запуск в режиме отладки for src_properties in config.SOURCES: src_obj = self.create_src(**src_properties) if src_obj: result = src_obj.read_as_dict(*src_obj.values) log.info(u'Результат чтения данных из контроллера %s' % result) else: log.warning( u'Режим запуска регистратра <%s> не поддерживается системой' % mode) return False
def diagnostic(self): """ Простая процедура прверки доступа к источнику данных. @return: True/False. """ opc = None log.info(u'Диагностика <%s>.<%s>' % (self.__class__.__name__, self.name)) if self.opc_server is None: msg = u'Не определен OPC сервер в <%s>' % self.name log.warning(msg) journal.write_msg(msg) return False if self.topic is None: msg = u'Не определен топик в <%s>' % self.name log.warning(msg) journal.write_msg(msg) return False try: # Создание клиента OPC opc = self.create_opc_client(self.opc_host) if opc is None: msg = u'Не возможно создать объект клиента OPC. Хост <%s>' % self.opc_host log.error(msg) journal.write_msg(msg) return None # Список серверов OPC servers = opc.servers() if self.opc_server not in servers: msg = u'Сервер <%s> не найден среди %s' % (self.opc_server, servers) log.warning(msg) journal.write_msg(msg) opc.close() return False server = self.opc_server log.info(u'Диагностика OPC сервера <%s>' % server) # Соедиенение с сервером opc.connect(server) # Вывод состояния сервера log.info(u'Общая информация о OPC сервере') info_list = opc.info() for inf in info_list: log.info(u'\t%s' % str(inf)) # Список интерфейсов servers topics = opc.list() if self.topic not in topics: msg = u'Топик <%s> не найден среди %s' % (self.topic, topics) log.warning(msg) journal.write_msg(msg) opc.close() return False # Режимы одного топика topic = topics[topics.index(self.topic)] log.info(u'Топик/Интерфейс: %s' % topic) modes = opc.list(topic) log.info(u'\tРежимы: %s' % modes) # Переменные for mode in modes: address = topic+u'.'+mode tags = opc.list(address) log.info(u'\t\tТеги <%s>:' % address) for tag in tags: log.info(u'\t\t\t%s' % tag) # Закрытие соединения opc.close() return True except: if opc: opc.close() msg = u'Ошибка диагностики <%s>' % self.__class__.__name__ log.fatal(msg) journal.write_msg(msg) return False