Загрузка данных


сценарий имитат плс маск замена
async def imitate_sensor_signal(
    ws_client, http_client, cfg: SmokeSuiteConfig, test_data: CaseData, imitator_start_time
):
    """
    Проверка имитации сигнала датчика.
    """
    # Распаковка данных для теста
    sensor_address = test_data.params.get("sensor_address")
    sensor_val, sensor_quality, imitation_event, unimitation_event = test_data.expected_result
    # Получение актуального id датчика
    sensor_id = TestConst.SENSOR_IDS_BY_ADDRESS.get(sensor_address)
    with allure.step(f"Http запрос и обработка ответа об имитации сигнала датчика с id: {sensor_id}"):
        request_body = {
            'id': sensor_id,
            'tuId': cfg.tu_id,
            'imitateInfo': {'value': str(sensor_val), 'quality': sensor_quality},
        }
        response = http_client.post_request(HttpConst.IMITATE_SIGNAL_URL_PATH, request_body)
        sensor_imitate_reply_status = response.status_code

        StepCheck("Проверка кода ответа на запрос об имитации", "replyStatus").actual(
            sensor_imitate_reply_status
        ).expected(ReplyStatus.OK.value).equal_to()

    with allure.step("Подключение по ws и http, получение и обработка данных сообщений для проверки имитации"):
        with allure.step(
            "Получение данных для проверки имитации. Тип сообщения: InputSignalsContent. ЭФ Диагностика Сигналов."
        ):
            parsed_payload, imitate_elapsed = await t_utils.poll_input_signal_state(
                ws_client,
                [sensor_id],
                "isImitated",
                True,
                {'signalIds': [sensor_id], 'tuId': cfg.tu_id, 'additionalProperties': None},
            )
            with allure.step(f"Имитация установилась за {imitate_elapsed:.0f} сек"):
                pass

        with allure.step(
            "Подготовка данных для проверки имитации. Тип сообщения: InputSignalsContent. ЭФ Диагностика Сигналов."
        ):
            sensor_data = getattr(parsed_payload.replyContent, 'inputSignals', [])
            diagnostics_sensor_imitate_data = t_utils.find_object_by_field(sensor_data, "id", sensor_id)
            value_diagnostics_sensor_imitate = getattr(
                getattr(diagnostics_sensor_imitate_data, 'imitation', []), 'value', []
            )
            is_imitated_diagnostics_sensor_imitate = getattr(diagnostics_sensor_imitate_data, 'isImitated', [])
            quality_diagnostics_sensor_imitate = getattr(diagnostics_sensor_imitate_data, 'quality', [])

        with allure.step("Получение данных для проверки имитации. Тип сообщения: SchemeSignalsStateContent. ЭФ Схема."):
            payload = await t_utils.connect_and_poll_subscribed_msg(
                ws_client,
                "SchemeSignalsStateContent",
                "SubscribeSchemeSignalsStateRequest",
                {'tuId': cfg.tu_id},
            )
            parsed_payload = parser.parse_scheme_signals_state_msg(payload)
            journal_signal_state_list = parsed_payload.replyContent.signalsStates
            scheme_sensor_imitate_data = t_utils.find_object_by_field(journal_signal_state_list, "id", sensor_id)
            is_imitated_scheme_sensor_imitate = getattr(scheme_sensor_imitate_data, 'isImitated', [])

    with allure.step(f"Http запрос и обработка ответа о снятии имитации датчика с id: {sensor_id}"):
        request_body = {'id': sensor_id, 'tuId': cfg.tu_id}
        response = http_client.post_request(HttpConst.UNIMITATE_SIGNAL_URL_PATH, request_body)
        sensor_unimitate_reply_status = response.status_code

        StepCheck("Проверка кода ответа на запрос о снятии имитации", "replyStatus").actual(
            sensor_unimitate_reply_status
        ).expected(ReplyStatus.OK.value).equal_to()

    with allure.step("Подключение по ws и http, получение и обработка данных сообщений для проверки снятия имитации"):
        with allure.step(
            "Получение данных для проверки снятия имитации. InputSignalsContent. ЭФ Диагностика Сигналов."
        ):
            parsed_payload, unimitate_elapsed = await t_utils.poll_input_signal_state(
                ws_client,
                [sensor_id],
                "isImitated",
                False,
                {'signalIds': [sensor_id], 'tuId': cfg.tu_id, 'additionalProperties': None},
            )
            with allure.step(f"Имитация снялась за {unimitate_elapsed:.0f} сек"):
                pass

        with allure.step("Извлечение и подготовка данных для проверки снятия имитации"):
            sensor_data = getattr(parsed_payload.replyContent, 'inputSignals', [])
            diagnostics_sensor_unimitate_data = t_utils.find_object_by_field(sensor_data, 'id', sensor_id)
            is_unimitated_diagnostics_sensor_unimitate = getattr(diagnostics_sensor_unimitate_data, 'isImitated', [])

        with allure.step(
            "Получение данных для проверки снятия имитации. Тип сообщения: SchemeSignalsStateContent. ЭФ Схема"
        ):
            payload = await t_utils.connect_and_poll_subscribed_msg(
                ws_client,
                "SchemeSignalsStateContent",
                "SubscribeSchemeSignalsStateRequest",
                {'tuId': cfg.tu_id},
            )
            parsed_payload = parser.parse_scheme_signals_state_msg(payload)
            journal_signal_state_list = parsed_payload.replyContent.signalsStates
            scheme_sensor_unimitate = t_utils.find_object_by_field(journal_signal_state_list, "id", sensor_id)
            is_unimitated_scheme_sensor_unimitate = getattr(scheme_sensor_unimitate, 'isImitated', [])

        with allure.step("Http запрос сообщений журнала с фильтром userActions"):
            # Запрос сообщений по типу действий пользователя маскирование и имитация сигналов
            request_body = t_utils.create_journal_req_body(
                pagination=Pagination(limit=TestConst.JOURNAL_PAGINATION_LIMIT, direction=Direction.FIRST.value),
                filtering=Filtering(
                    userActions=int(UserActions.SIGNAL_MASK_SIM), objects=FilteringObjects(tuId=cfg.tu_id)
                ),
            )
            response = http_client.post_request(HttpConst.GET_MESSAGES_URL_PATH, request_body)
            payload = t_utils.get_json_from_http_response(response)
            parsed_payload = parser.parse_journal_msg(payload)
            messages_info = getattr(parsed_payload.replyContent, 'messagesInfo', [])

            # Фильтр полученных сообщений по времени
            end_time = datetime.now()
            filter_start_msk = t_utils.localize_as_moscow(imitator_start_time)
            filter_end_msk = t_utils.localize_as_moscow(end_time)
            filter_time_messages = [
                msg
                for msg in messages_info
                if filter_start_msk <= t_utils.ensure_moscow_timezone(msg.time) <= filter_end_msk
            ]
            filter_by_imitation_messages = [
                msg
                for msg in filter_time_messages
                if getattr(msg, "event", None) == imitation_event and getattr(msg, "tag", None) == sensor_address
            ]
            filter_by_unimitation_messages = [
                msg
                for msg in filter_time_messages
                if getattr(msg, "event", None) == unimitation_event and getattr(msg, "tag", None) == sensor_address
            ]

    with SoftAssertions() as soft_failures:
        StepCheck(
            f"Проверка имитации датчика с id: {sensor_id}. ЭФ Диагностика Сигналов.", "isImitated", soft_failures
        ).actual(is_imitated_diagnostics_sensor_imitate).expected(True).equal_to()
        StepCheck(f"Проверка имитации датчика с id: {sensor_id}. ЭФ Схема.", "isImitated", soft_failures).actual(
            is_imitated_scheme_sensor_imitate
        ).expected(True).equal_to()
        StepCheck(
            f"Проверка показаний датчика с id: {sensor_id}. ЭФ Диагностика Сигналов.", "value", soft_failures
        ).actual(value_diagnostics_sensor_imitate).expected(sensor_val).equal_to()
        StepCheck(
            f"Проверка качества сигнала датчика с id: {sensor_id}. ЭФ Диагностика Сигналов.", "quality", soft_failures
        ).actual(quality_diagnostics_sensor_imitate).expected(sensor_quality).equal_to()
        StepCheck(
            f"Проверка наличия сообщения с событием {imitation_event} и тегом {sensor_address}. ЭФ Журнал.",
            "event",
            soft_failures,
        ).actual(filter_by_imitation_messages).is_not_empty()
        StepCheck(
            f"Проверка снятия имитации датчика с id: {sensor_id}. ЭФ Диагностика Сигналов.", "isImitated", soft_failures
        ).actual(is_unimitated_diagnostics_sensor_unimitate).expected(False).equal_to()
        StepCheck(f"Проверка снятия имитации датчика с id: {sensor_id}. ЭФ Схема.", "isImitated", soft_failures).actual(
            is_unimitated_scheme_sensor_unimitate
        ).expected(False).equal_to()
        StepCheck(
            f" Проверка наличия сообщения с событием {unimitation_event} и тегом {sensor_address}. ЭФ Журнал.",
            "event",
            soft_failures,
        ).actual(filter_by_unimitation_messages).is_not_empty()


async def mask_signal_test(ws_client, http_client, cfg: SmokeSuiteConfig, test_data: CaseData):
    """
    Проверка маскирования датчиков.
    """

    if not test_data:
        pytest.fail("Данные датчиков отсутствуют")
    pressure_sensor_address = test_data.params.get("pressure_sensor_address")
    flowmeter_address = test_data.params.get("flowmeter_address")
    # Получение актуальных id датчиков
    pressure_sensor_id = TestConst.SENSOR_IDS_BY_ADDRESS.get(pressure_sensor_address)
    flowmeter_id = TestConst.SENSOR_IDS_BY_ADDRESS.get(flowmeter_address)
    with allure.step("Маскирование датчиков"):
        with allure.step(f"Http запрос и обработка ответа о маскировании датчика давления с id: {pressure_sensor_id}"):
            request_body = {'id': pressure_sensor_id, 'tuId': cfg.tu_id}
            response = http_client.post_request(HttpConst.MASK_SIGNAL_URL_PATH, request_body)
            pressure_sensor_mask_reply_status = response.status_code

            StepCheck("Проверка кода ответа на запрос о маскировании", "replyStatus").actual(
                pressure_sensor_mask_reply_status
            ).expected(ReplyStatus.OK.value).equal_to()

        with allure.step(f"Http запрос и обработка ответа о маскировании расходомера с id: {flowmeter_id}"):
            request_body = {'id': flowmeter_id, 'tuId': cfg.tu_id}
            response = http_client.post_request(HttpConst.MASK_SIGNAL_URL_PATH, request_body)
            flowmeter_mask_reply_status = response.status_code

            StepCheck("Проверка кода ответа на запрос о маскировании", "replyStatus").actual(
                flowmeter_mask_reply_status
            ).expected(ReplyStatus.OK.value).equal_to()

    with allure.step(
        "Подключение по ws, получение и обработка данных о статусе датчиков из сообщения типа: InputSignalsContent"
    ):
        parsed_payload, mask_elapsed = await t_utils.poll_input_signal_state(
            ws_client,
            [pressure_sensor_id, flowmeter_id],
            "isMasked",
            True,
            {
                'signalIds': [pressure_sensor_id, flowmeter_id],
                'tuId': cfg.tu_id,
                'additionalProperties': None,
            },
        )
        with allure.step(f"Маскирование установилось за {mask_elapsed:.0f} сек"):
            pass

    with allure.step("Извлечение и подготовка данных для проверки маскирования"):
        sensor_data = getattr(parsed_payload.replyContent, 'inputSignals', [])
        pressure_sensor_mask_data = t_utils.find_object_by_field(sensor_data, "id", pressure_sensor_id)
        flowmeter_mask_data = t_utils.find_object_by_field(sensor_data, "id", flowmeter_id)
        with SoftAssertions() as soft_failures:
            StepCheck("Проверка наличия данных о маскировании датчика давления", "inputSignals", soft_failures).actual(
                pressure_sensor_mask_data
            ).is_not_none()
            StepCheck("Проверка наличия данных о маскировании расходомера", "inputSignals", soft_failures).actual(
                flowmeter_mask_data
            ).is_not_none()

    with allure.step("Снятие маскирования датчиков"):
        with allure.step(f"Http запрос о снятии маскирования датчика давления с id: {pressure_sensor_id}"):
            request_body = {'id': pressure_sensor_id, 'tuId': cfg.tu_id}
            response = http_client.post_request(HttpConst.UNMASK_SIGNAL_URL_PATH, request_body)
            pressure_sensor_unmask_reply_status = response.status_code
            StepCheck("Проверка кода ответа на запрос о снятии маскирования", "replyStatus").actual(
                pressure_sensor_unmask_reply_status
            ).expected(ReplyStatus.OK.value).equal_to()

        with allure.step(f"Http запрос о снятии маскирования расходомера с id: {flowmeter_id}"):
            request_body = {'id': flowmeter_id, 'tuId': cfg.tu_id}
            response = http_client.post_request(HttpConst.UNMASK_SIGNAL_URL_PATH, request_body)
            flowmeter_unmask_reply_status = response.status_code
            StepCheck("Проверка кода ответа на запрос о снятии маскирования", "replyStatus").actual(
                flowmeter_unmask_reply_status
            ).expected(ReplyStatus.OK.value).equal_to()

    with allure.step(
        "Подключение по ws, получение и обработка данных о статусе датчиков из сообщения типа: InputSignalsContent"
    ):
        parsed_payload, unmask_elapsed = await t_utils.poll_input_signal_state(
            ws_client,
            [pressure_sensor_id, flowmeter_id],
            "isMasked",
            False,
            {
                'signalIds': [pressure_sensor_id, flowmeter_id],
                'tuId': cfg.tu_id,
                'additionalProperties': None,
            },
        )
        with allure.step(f"Маскирование снялось за {unmask_elapsed:.0f} сек"):
            pass

    with allure.step("Извлечение и подготовка данных для проверки снятия маскирования"):
        sensor_data = getattr(parsed_payload.replyContent, 'inputSignals', [])
        pressure_sensor_unmask_data = t_utils.find_object_by_field(sensor_data, "id", pressure_sensor_id)
        flowmeter_unmask_data = t_utils.find_object_by_field(sensor_data, "id", flowmeter_id)
        with SoftAssertions() as soft_failures:
            StepCheck(
                "Проверка наличия данных о снятии маскировании датчика давления", "inputSignals", soft_failures
            ).actual(pressure_sensor_unmask_data).is_not_none()
            StepCheck(
                "Проверка наличия данных о снятии маскировании расходомера", "inputSignals", soft_failures
            ).actual(flowmeter_unmask_data).is_not_none()

    with SoftAssertions() as soft_failures:
        StepCheck(
            f"Проверка маскирования датчика давления с id: {pressure_sensor_id}", "isMasked", soft_failures
        ).actual(pressure_sensor_mask_data.isMasked).expected(True).equal_to()
        StepCheck(f"Проверка маскирования расходомера с id: {flowmeter_id}", "isMasked", soft_failures).actual(
            flowmeter_mask_data.isMasked
        ).expected(True).equal_to()
        StepCheck(
            f"Проверка снятия маскирования датчика давления с id: {pressure_sensor_id}", "isMasked", soft_failures
        ).actual(pressure_sensor_unmask_data.isMasked).expected(False).equal_to()
        StepCheck(f"Проверка снятия маскирования расходомера с id: {flowmeter_id}", "isMasked", soft_failures).actual(
            flowmeter_unmask_data.isMasked
        ).expected(False).equal_to()

















вс тетс утил
        ws_client.suppress_recv_logging = False


async def poll_input_signal_state(
    ws_client: WebSocketClient,
    sensor_ids: list[int],
    flag_field: str,
    expected_value: bool,
    ws_invoke_params: Any,
    *,
    attempts: int = TestConst.SIGNAL_STATE_POLL_ATTEMPTS,
    per_attempt_timeout: float = TestConst.POLL_BY_TIMEOUT_SECONDS,
) -> tuple[Any, float]:
    """Опрашивает InputSignalsContent, пока у всех sensor_ids поле flag_field не станет expected_value.

    Возвращает подтверждающий parsed_payload и затраченное время (сек).
    При недостижении состояния за attempts попыток завершается fail(...).
    """
    start = time.monotonic()
    async for payload in _receive_subscribed_messages(
        ws_client,
        "InputSignalsContent",
        "SubscribeInputSignalsRequest",
        ws_invoke_params,
        attempts=attempts,
        per_attempt_timeout=per_attempt_timeout,
    ):
        parsed = ws_message_parser.parse_input_signals_info_msg(payload)
        signals = getattr(parsed.replyContent, "inputSignals", []) or []
        signals_by_id = {signal.id: signal for signal in signals if getattr(signal, "id", None) is not None}
        if all(
            sensor_id in signals_by_id
            and bool(getattr(signals_by_id[sensor_id], flag_field, False)) == bool(expected_value)
            for sensor_id in sensor_ids
        ):
            return parsed, time.monotonic() - start

    fail(
        f"Сигналы id={sensor_ids} не перешли в состояние {flag_field}={expected_value} "
        f"за {attempts} попыток (лимит ~{attempts * per_attempt_timeout} сек)"
    )


async def connect_and_poll_subscribed_signal(
























конст
    POLL_BY_TIMEOUT_SECONDS = 10.0  # Таймаут ожидания сообщения в секундах
    SIGNAL_STATE_POLL_ATTEMPTS = 12  # Число опросов состояния датчика