Расширить обмен по шинам, CAN-адаптеры и обработку графиков

Добавить очереди операций PBUS/SBUS, общую консоль, настройки Candle и SLCAN, декодеры DSView и обработку плотных графиков. Обновить протокол Бальзам и проверки общих компонентов.
This commit is contained in:
2026-10-17 14:36:14 +03:00
parent 95c8b8ac7d
commit a5e46d4627
69 changed files with 4413 additions and 682 deletions
+30 -7
View File
@@ -120,9 +120,11 @@ def test_read_accepts_address_formats_and_displays_both_values(page, address):
widget, protocol = page
widget.byte_read_address.setText(address)
widget.byte_read_button.click()
QTest.qWait(15) # Доставляем назначенный шаг общей очереди через события Qt без синхронной блокировки GUI.
assert protocol.requests == [(0x1000, None, 7)]
assert not widget.byte_read_button.isEnabled()
assert widget.byte_read_button.isEnabled() # Ручная кнопка принимает новые запросы, пока текущее чтение ожидает ответ.
protocol.reply(True, {"value": 0xABCD})
QTest.qWait(15) # Доставляем назначенный шаг общей очереди через события Qt без синхронной блокировки GUI.
assert widget.byte_read_address.text() == "$1000"
assert widget.byte_read_value.text() == "ABCD"
assert widget.byte_read_binary.text() == "1010 1011 1100 1101"
@@ -144,6 +146,7 @@ def test_invalid_inputs_do_not_send(page, address, value, binary):
widget.byte_write_value.setText(value)
widget.byte_write_binary.setText(binary)
widget.byte_write_button.click()
QTest.qWait(15) # Доставляем назначенный шаг общей очереди через события Qt без синхронной блокировки GUI.
assert protocol.requests == []
assert "Проверьте" in widget.status.text()
@@ -156,11 +159,14 @@ def test_write_is_verified_and_controller_is_captured_for_whole_operation(page,
widget.byte_write_value.setText("0301")
widget.sync_byte_value("0301", 16)
widget.byte_write_button.click()
QTest.qWait(15) # Доставляем назначенный шаг общей очереди через события Qt без синхронной блокировки GUI.
assert protocol.requests == [(0x1000, 0x0301, 13)]
controller[0] = 21
protocol.reply(True, {"raw": b"ack"})
QTest.qWait(15) # Доставляем назначенный шаг общей очереди через события Qt без синхронной блокировки GUI.
assert protocol.requests[-1] == (0x1000, None, 13)
protocol.reply(True, {"value": readback})
QTest.qWait(15) # Доставляем назначенный шаг общей очереди через события Qt без синхронной блокировки GUI.
assert widget.byte_read_value.text() == f"{readback:04X}"
assert ("Запись проверена" in widget.status.text()) == confirmed
if not confirmed:
@@ -171,18 +177,23 @@ def test_write_is_verified_and_controller_is_captured_for_whole_operation(page,
def test_failure_and_cancellation_restore_controls_and_ignore_late_reply(page):
widget, protocol = page
widget.byte_read_button.click()
QTest.qWait(15) # Доставляем назначенный шаг общей очереди через события Qt без синхронной блокировки GUI.
protocol.reply(False, "CRC ответа не совпадает")
QTest.qWait(15) # Доставляем назначенный шаг общей очереди через события Qt без синхронной блокировки GUI.
assert widget.status.text() == "CRC ответа не совпадает"
assert widget.byte_read_button.isEnabled()
widget.byte_read_button.click()
QTest.qWait(15) # Доставляем назначенный шаг общей очереди через события Qt без синхронной блокировки GUI.
late_reply = protocol.callback
widget.stop()
assert protocol.cancelled == 1
widget.byte_read_button.click()
QTest.qWait(15) # Доставляем назначенный шаг общей очереди через события Qt без синхронной блокировки GUI.
late_reply(True, {"value": 0x9999})
assert widget.byte_read_value.text() == ""
assert not widget.byte_read_button.isEnabled()
assert widget.byte_read_button.isEnabled() # Ручная кнопка принимает новые запросы, пока текущее чтение ожидает ответ.
protocol.reply(True, {"value": 0x1234})
QTest.qWait(15) # Доставляем назначенный шаг общей очереди через события Qt без синхронной блокировки GUI.
assert widget.byte_read_value.text() == "1234"
assert widget.byte_read_button.isEnabled()
@@ -193,19 +204,31 @@ def test_controller_provider_is_used_by_bus_raw_memory_and_macros(app, tmp_path)
widget = ByteWorkPanel(protocol, device_address=lambda: controller[0],
macros_file=tmp_path / "address.json")
try:
widget.raw_widget.memory_write()
widget.raw_widget.memory_read()
assert protocol.requests == [(0x2000, 0, 21), (0x2000, None, 21)]
widget.bus_widget.read_from_bus()
assert protocol.requests[-2:] == [(0x200B, 0, 21), (0x200F, None, 21)]
widget.raw_widget.memory_write() # Первая операция сохраняет контроллер до ожидания общей очереди.
widget.raw_widget.memory_read() # Второе нажатие принимается до завершения первой записи.
QTest.qWait(15) # Запись получает владение общим соединением.
protocol.reply(True, {"raw": b"ack"}) # Подтверждаем текущую запись перед следующим чтением.
QTest.qWait(15) # Следующая ручная операция начинает PEEK.
protocol.reply(True, {"value": 0x1234}) # Возвращаем слово ручного чтения памяти.
QTest.qWait(15) # Освобождаем очередь после завершения второго действия.
assert protocol.requests == [(0x2000, 0, 21), (0x2000, None, 21)] # Оба нажатия используют контроллер своего исходного снимка.
widget.bus_widget.read_from_bus() # Последовательное чтение также выполняется асинхронно через общую очередь.
QTest.qWait(15) # Отправляем подготовку SBUS.
protocol.reply(True, {"raw": b"ack"}) # Подтверждение позволяет перейти к буферу SBUS.
QTest.qWait(15) # Отправляем чтение существующего регистра результата.
protocol.reply(True, {"value": 0x1234, "raw_response": {"raw": b"reply"}}) # Возвращаем слово последовательной шины.
QTest.qWait(15) # Завершаем логическую операцию перед явным макросом.
assert protocol.requests[-2:] == [(0x200B, 0, 21), (0x200F, None, 21)] # Адреса и формат существующей SBUS остаются прежними.
widget.bus_widget.execute_macro_commands([{"type": "read", "tetrad": 3, "register": 5}])
controller[0] = 22
QTest.qWait(20)
assert protocol.requests[-1] == (0x200B, 0x35, 21)
protocol.reply(True, {"raw": b"ack"})
QTest.qWait(15) # Доставляем назначенный шаг общей очереди через события Qt без синхронной блокировки GUI.
QTest.qWait(20)
assert protocol.requests[-1] == (0x200F, None, 21)
protocol.reply(True, {"value": 0x4321, "raw_response": {"raw": b"reply"}})
QTest.qWait(15) # Доставляем назначенный шаг общей очереди через события Qt без синхронной блокировки GUI.
QTest.qWait(20)
assert not widget.bus_widget._macro_running
assert widget.bus_widget.bus_read_value_label.text() == "0x4321 (17185)"