Example #1
0
    def gen_sql_code(self, code):
        """
        Дополнение кода информацией из контекста описания объекта.
        ВНИМАНИЕ! Т.к. одинарные кавычки не должны присутствовать,
        то необходимо сделать дополнительную предобработку контекста.
        @param code: Строка блока кода.
        @return: Полностью заполненная и готовая к выполнению строка блока кода.
        """
        if not code:
            return None

        if self.cache_state is None:
            self.cache_state = self.fill_state()
        context = self.get_context(self.cache_state)

        # ВНИМАНИЕ! Т.к. одинарные кавычки не должны присутствовать,
        # то необходимо сделать дополнительную предобработку контекста.
        for name, value in context.items():
            # context[name] = str(value).replace('\'', '"')
            if type(value) in (str, unicode):
                try:
                    context[name] = value.replace('\'', '"')
                except UnicodeEncodeError:
                    msg = u'Ошибка замены кавычек в значении <%s>' % value
                    log.fatal(msg)
                    journal.write_msg(msg)
        result = self.gen_code(code, context)
        return result
Example #2
0
 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
Example #3
0
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
Example #4
0
    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
Example #5
0
    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
Example #6
0
    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 parse_key(self, key_txt):
     """
     Распарсить ключ элемента.
     @param key_txt: Ключ элемента.
     @return: Имя тега, его атрибуты.
     """
     key_line = re.split(' |\n', key_txt)
     name = key_line[0]
     try:
         attrs = dict([
             tuple([re.sub(r'^"|"$', '', s) for s in attr_txt.split('=')])
             for attr_txt in key_line[1:] if attr_txt.strip()
         ])
     except:
         log.fatal(u'Ошибка определения атрибутов XML тега <%s>' % name)
         attrs = dict()
     return name, attrs
Example #8
0
    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
Example #9
0
    def get_value_by_link(self, link):
        """
        Получить значение внутренней переменной по ссылке.
        @param link: Строковая ссылка в формате:
            ИМЯ_ОБЪЕКТА.имя_переменной или
            ИМЯ_ОБЪЕКТА.имя_функции(аргументы функции).
        @return: Значение внутренней переменной или None если по этой ссылке переменная или объект не найдены.
        """
        if link.startswith(LINK_SIGNATURE):
            # Убрать сигнатуру из обработки
            link = link[len(LINK_SIGNATURE):].strip()

        try:
            # Разделяем ссылку на имя объекта и имя переменной
            obj_name, val_name = link.split(LINK_DELIMETER)

            # Определение объекта
            obj = self.objects.get(obj_name, None)
            if obj is None:
                log.warning(u'Не найден объект <%s> среди зарегистрированных' %
                            obj_name)
                return None

            if not self.is_link_func(link):
                # Определение значения переменной
                value = obj.state.get(val_name, None)
                if value is None:
                    log.warning(u'Не найдена переменная <%s> в объекте <%s>' %
                                (val_name, obj_name))
                    return None
            else:
                # Это вызов функции
                value = None
                try:
                    value = eval(u'obj.%s' % val_name)
                except:
                    log.fatal(u'Ошибка вызова метода <%s.%s>' %
                              (obj_name, val_name))
            return value
        except:
            log.fatal(
                u'Ошибка получения значения внутренней переменной по ссылке <%s>'
                % link)
        return None
Example #10
0
    def _read_value(self, address):
        """
        Прочитать значение по адресу из RSLinx.
        @param address: Адрес. Адрес задается явно.
        @return: Прочитанное значение либо None в случае ошибки.
        """
        opc = None
        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 None

            # Соедиенение с сервером
            server = self.opc_server
            opc.connect(server)

            # Прочитать из OPC сервера
            val = opc.read(address)
            result = self.recode(val[0]) if val and val[1] == 'Good' else None

            opc.close()

            log.debug(u'Адрес <%s>. Результат чтения данных %s' % (address, result))
            return result
        except:
            if opc:
                opc.close()
            msg = u'Ошибка чтения значения по адресу <%s> в <%s>' % (address, self.__class__.__name__)
            log.fatal(msg)
            journal.write_msg(msg)
        return None
Example #11
0
    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
Example #12
0
    def clear_all_state_chaches(self, *objects):
        """
        Сбросить все кеши в объектах
        @param objects: Список обрабатываемых объектов.
        @return: True/False.
        """
        if not objects:
            log.warning(u'Не определены объекты для сброса кеша состояния')
            return False

        result = True
        for obj in objects:
            try:
                obj.clear_state_cache()
                result = result and True
            except:
                log.fatal(u'Ошибка сброса кеша в объекте <%s>' % obj)
                result = False
        return result
Example #13
0
def save_xml_content(xml_filename, data, is_rewrite=True):
    """
    Записать словарно списковую структуру в XML файл.
    @param xml_filename: Полное имя XML файла.
    @param data: Словарно-списковая структура содержания XML файла.
    @param is_rewrite: Перезаписать результирующий файл, если необходимо?
    @return: True/False.
    """
    if os.path.exists(xml_filename) and not is_rewrite:
        log.warning(u'Запрет на перезапись. Файл <%s> уже существует.' %
                    xml_filename)
        return False

    # Сама конвертация словаря в текст
    if isinstance(data, list):
        xml_txt = dicttoxml.dicttoxml(data,
                                      root=True,
                                      custom_root='root',
                                      ids=False,
                                      attr_type=False)
    elif isinstance(data, dict):
        root_key = data[data.keys()[0]]
        xml_txt = dicttoxml.dicttoxml(data,
                                      root=False,
                                      custom_root=root_key,
                                      ids=False,
                                      attr_type=False)
    else:
        log.warning(u'Не корректный тип данных <%s> для записи в XML файл' %
                    type(data))
        return False

    xml_file = None
    try:
        xml_file = open(xml_filename, 'w')
        xml_file.write(xml_txt)
        xml_file.close()
        return True
    except:
        if xml_file:
            xml_file.close()
        log.fatal(u'Ошибка записи в файл <%s>' % xml_filename)
    return False
 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
Example #15
0
    def connect(self, db_url=None):
        """
        Соединение с БД.
        @param db_url: Конекшн стринг подключения к БД.
        @return: Объект sqlalchemy движка.
        """
        if db_url is None:
            db_url = self.get_db_url()

        if self.connection:
            self.disconnect()
            self.connection = None
        try:
            # Отображение в консоли выполняемых SQL выражений---------+
            #                                                         V
            self.connection = sqlalchemy.create_engine(db_url, echo=False)
        except:
            msg = u'Ошибка соединения с БД <%s>' % db_url
            log.fatal(msg)
            journal.write_msg(msg)
            self.connection = None
        return self.connection
Example #16
0
    def _read(self, *values):
        """
        Чтение данных из источника данных.
        @param values: Список читаемых переменных.
        @return: Список прочианных значений.
            Если переменная не найдена или произошла ошибка чтения, то
            вместо значения подставляется None с указанием WARNING в журнале сообщений.
        """
        if not values:
            log.warning(u'Не определены переменные для чтения в <%s>' %
                        self.name)
            values = self.values
            log.debug(u'Переменные взяты из описания источника данных: %s' %
                      values)

        try:
            # Прочитать все документы
            inbox_docs = self.get_inbox_documents()
            if inbox_docs is None:
                return False

            # Регистрация состояния
            if not self.cache_state:
                inbox = dict([(doc.get('uuid', str(uuid.uuid4())), doc)
                              for doc in inbox_docs])
                state = dict([(val, self.gen_code(getattr(self, val)))
                              for val in values])
                # state = self.get_values_as_dict(values)
                state[INBOX_STATE_NAME] = inbox
                self.reg_state(**state)

                self.cache_state = self.state

            return inbox_docs
        except:
            msg = u'Ошибка чтения входящих документов УТМ'
            log.fatal(msg)
            journal.write_msg(msg)
        return None
Example #17
0
 def _backup_error_file(self, src_filename, err_filename=None):
     """
     Сохранить ошибочный файл в папке.
     @param src_filename: Имя исходного ошибочного файла.
     @param err_filename: Имя нового файла.
         Если не определено, то имя генерируется по времени.
     @return: True/False.
     """
     if err_filename is None:
         err_filename = os.path.join(
             str(self.output_dir),
             datetime.datetime.now().strftime('%Y_%m_%d_%H_%M_%S.err'))
     try:
         if os.path.exists(err_filename):
             os.remove(err_filename)
         shutil.copyfile(src_filename, err_filename)
         return True
     except:
         msg = u'Ошибка сохранения ошибочного файла'
         log.fatal(msg)
         journal.write_msg(msg)
     return False
Example #18
0
    def _read_value(self, address):
        """
        Прочитать значение по адресу из OPC сервера.
        @param address: Адрес. Адрес задается явно.
        @return: Прочитанное значение либо None в случае ошибки.
        """
        connection = None
        try:
            # Создание связи
            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

            # Прочитать из OPC сервера
            val = connection.sources.ReadValueAsString('OPC_SERVER_NODE',
                                                       self.opc_server,
                                                       address)
            result = self.recode(val[0]) if val else None

            log.debug(u'UniReader. Адрес <%s>. Результат чтения данных %s' %
                      (address, result))
            return result
        except:
            msg = u'UniReader. Ошибка чтения значения по адресу <%s> в <%s>' % (
                address, self.__class__.__name__)
            log.fatal(msg)
            journal.write_msg(msg)
        return None
Example #19
0
def save_simple_xml_content(xml_filename,
                            data,
                            is_rewrite=True,
                            tag_filter=None):
    """
    Записать словарно списковую структуру в XML файл.
    Самая простая реализация.
    @param xml_filename: Полное имя XML файла.
    @param data: Словарно-списковая структура содержания XML файла.
    @param is_rewrite: Перезаписать результирующий файл, если необходимо?
    @param tag_filter: Словарь фильтра тегов,
        определяющий список и порядок дочерних тегов для
        каждого тега.
        Порядок тегов важен для XML, поэтому введен этот фильтр.
    @return: True/False.
    """
    if os.path.exists(xml_filename) and not is_rewrite:
        log.warning(u'Запрет на перезапись. Файл <%s> уже существует.' %
                    xml_filename)
        return False

    xml_file = None
    try:
        # Начать запись
        xml_file = open(xml_filename, 'wt')
        xml_writer = simple_dict2xml.icSimpleDict2XmlWriter(data, xml_file)
        xml_writer.startDocument()
        xml_writer.startWrite(tag_filter=tag_filter)

        # Закончить запись
        xml_writer.endDocument()
        xml_file.close()
        return True
    except:
        if xml_file:
            xml_file.close()
        log.fatal(u'Ошибка записи в файл <%s>' % xml_filename)
    return False
Example #20
0
    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
Example #21
0
    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
Example #22
0
    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
Example #23
0
    def _read(self, *values):
        """
        Чтение данных из источника данных.
        @param values: Список читаемых переменных.
        @return: Список прочитанных значений.
            Если переменная не найдена или произошла ошибка чтения, то
            вместо значения подставляется None с указанием WARNING в журнале сообщений.
        """
        connection = None

        if not values:
            log.warning(
                u'UniReader. Не определены переменные для чтения в <%s>' %
                self.name)
            values = self.addresses
            log.debug(
                u'UniReader. Переменные взяты из описания источника данных: %s'
                % values)

        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

            # Подготовка переменных для чтения
            # Адреса всегда задаются строками
            addresses = self._gen_addresses(*values)
            log.debug(u'UniReader. Чтение адресов %s' % addresses)

            # Прочитать из OPC сервера
            result = list()
            for address in addresses:
                value = connection.sources.ReadValueAsString(
                    'OPC_SERVER_NODE', self.opc_server, address)
                result.append(self.recode(value) if value else None)

            # Регистрация состояния
            state = dict([(values[i], val) for i, val in enumerate(result)])
            self.reg_state(**state)

            log.debug(u'UniReader. Результат чтения данных:')
            for i, value in enumerate(result):
                log.debug(u'\t%s\t=\t%s' % (addresses[i], value))

            return result
        except:
            msg = u'UniReader. Ошибка чтения данных <%s>' % self.__class__.__name__
            log.fatal(msg)
            journal.write_msg(msg)
        return None
Example #24
0
ВНИМАНИЕ! В переменной values в INI файле настроек задаются только адреса читаемые из OPC сервера
Другие внутренние переменные могут учавствовать в генерации адресов, но не указываются как values.
В противном случае будет exception при чтении данных из OPC сервера.
"""

from ic.utils import log
from ic.utils import journal
from ic.utils import txtgen
from ic.utils import execfunc
from ic import config

try:
    import xmlrpclib
except ImportError:
    log.fatal(u'UniReader OPC Data Source. Import error <xmlrpclib>')

from ic import datasrc_proto

__version__ = (0, 0, 0, 1)

UNI_SERVER_URL_FMT = 'http://%s:%d'

DEFAULT_PORT = 8080


class icUniReaderOPCDataSource(datasrc_proto.icDataSourceProto):
    """
    Источник данных UniReader.
    UniReader используется как шлюз для доступа к OPC серверу.
    """
Example #25
0
ВНИМАНИЕ! В переменной values в INI файле настроек задаются только адреса читаемые из OPC сервера
Другие внутренние переменные могут учавствовать в генерации адресов, но не указываются как values.
В противном случае будет exception при чтении данных из OPC сервера.
"""

from ic.utils import log
from ic.utils import journal
from ic.utils import txtgen
from ic.utils import execfunc
from ic import config

try:
    import OpenOPC
except ImportError:
    log.fatal(u'RSLinx Data Source. Import error <OpenOPC>')

from ic import datasrc_proto

__version__ = (0, 0, 5, 1)


class icRSLinxDataSource(datasrc_proto.icDataSourceProto):
    """
    Источник данных OPC сервер RSLinx.
    """
    def __init__(self, *args, **kwargs):
        """
        Конструктор.
        """
        datasrc_proto.icDataSourceProto.__init__(self, *args, **kwargs)
Example #26
0
    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
Example #27
0
    def _read(self, *values):
        """
        Чтение данных из источника данных.
        @param values: Список читаемых переменных.
        @return: Список прочитанных значений.
            Если переменная не найдена или произошла ошибка чтения, то
            вместо значения подставляется None с указанием WARNING в журнале сообщений.
        """
        opc = None

        if not values:
            log.warning(u'Не определены переменные для чтения в <%s>' % self.name)
            values = self.addresses
            log.debug(u'Переменные взяты из описания источника данных: %s' % values)

        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 None

            # Соедиенение с сервером
            server = self.opc_server
            opc.connect(server)

            # Подготовка переменных для чтения
            # Адреса всегда задаются строками
            addresses = self._gen_addresses(*values)
            log.debug(u'Чтение адресов %s' % addresses)
            # Прочитать из OPC сервера
            result = [self.recode(val[1]) if val and val[2] == 'Good' else None for val in opc.read(addresses)]

            # result = [val.encode('') if isinstance(val, unicode) else val for val in result]
            # result = [val for val in opc.read(addresses)]

            opc.close()

            # Регистрация состояния
            state = dict([(values[i], val) for i, val in enumerate(result)])
            self.reg_state(**state)

            log.debug(u'Результат чтения данных %s' % result)
            return result
        except:
            if opc:
                opc.close()
            msg = u'Ошибка чтения данных <%s>' % self.__class__.__name__
            log.fatal(msg)
            journal.write_msg(msg)
        return None