47 lines
6.4 KiB
Python
47 lines
6.4 KiB
Python
"""Три автономных примера общей консоли templates без подключения к аппаратуре.""" # Примеры показывают служебный текст, CAN и двоичный RS485 на одном компоненте.
|
||
import argparse # Ключ --kind выбирает один пример для отдельного запуска.
|
||
import time # Время в модели кадра соответствует обычному источнику пакетов приложения.
|
||
from set_devices.can485_board import BoardFrame # Штатная модель строит RS485-пакет с настоящим CRC.
|
||
from set_devices.can_monitor import decode_protocol # CAN расшифровывается действующим декодером templates.
|
||
from set_devices.can_transport import build_frame # Транспортный кадр не собирается вручную в UI.
|
||
from set_devices.qt_ports.console import ConsoleView # Все примеры используют ту же консоль, что SETGUI.
|
||
try: # Выбираем доступную версию Qt без зависимости от приложения SETGUI.
|
||
from PySide6.QtWidgets import QApplication, QTabWidget # Вкладки позволяют сравнить три независимых журнала.
|
||
except ImportError: # Сохраняем совместимость примера с портом Qt 5.
|
||
from PySide2.QtWidgets import QApplication, QTabWidget # Интерфейс запуска одинаков для обеих версий Qt.
|
||
|
||
|
||
def create_examples(): # Фабрика доступна также тесту и генератору снимков интерфейса.
|
||
service = ConsoleView(limit=4000) # Первый журнал показывает служебные ответы и команды платы.
|
||
service.append_message(">>> V", direction="TX", color="#8fd18f") # Метка отправки демонстрирует независимый фильтр TX.
|
||
service.append_message("#OK driver started", direction="RX", color="#6fa8dc") # Ответ устройства показывает цвет и фильтр RX.
|
||
service.append_message("#ERR transmit failed (no ack / bus busy)", color="#ff7b7b") # Ошибка остаётся видна независимо от фильтров направления.
|
||
can = ConsoleView(limit=4000, payloads=True) # Второй пример добавляет переключение представления настоящих байтов CAN.
|
||
frame = build_frame(0x701, b"\x05", ide=False, rtr=False) # ID 0x701 и байт 05 задают heartbeat CANopen узла 1 в Operational.
|
||
decoded = decode_protocol(frame, "deif") # Подпись события берётся из штатного протокольного декодера.
|
||
can.append_message("RX CAN 0x701 · " + decoded.summary, direction="RX", payload=b"\x05") # Исходный payload позволяет сравнить режимы HEX и ASCII.
|
||
rs485 = ConsoleView(limit=4000, payloads=True) # Третий пример показывает транспортный пакет платы отдельно от прикладного CAN.
|
||
packet = BoardFrame(time.time(), False, 0x701, False, 1, b"\x05", "RS485").rs485_packet() # Пакет AA55 и CRC8 формируются кодеком templates.
|
||
rs485.append_message("RX RS485 · пакет CAN485", direction="RX", payload=packet) # Консоль отображает байты, не повторяя алгоритм разбора пакета.
|
||
for console in (can, rs485): # Двоичные примеры сразу демонстрируют одновременно байты и печатное представление.
|
||
console.display.setCurrentText("HEX + ASCII") # Пользователь может вернуться к исходной подписи или выбрать один формат.
|
||
return (("Служебная консоль", service), ("CAN", can), ("RS485", rs485)) # Каждый журнал владеет своей историей и настройками просмотра.
|
||
|
||
|
||
def main(): # Точка входа запускается обычным Python с установленным Qt-портом templates.
|
||
parser = argparse.ArgumentParser(description=__doc__) # Справка объясняет назначение примеров без отдельного приложения.
|
||
parser.add_argument("--kind", choices=("all", "service", "can", "rs485"), default="all") # Один пример каждого источника доступен отдельной командой.
|
||
args = parser.parse_args() # Пользователь выбирает источник до создания окна.
|
||
app = QApplication.instance() or QApplication([]) # Одно приложение Qt обслуживает все примеры.
|
||
window = QTabWidget() # Общий просмотр не связывает состояния независимых консолей.
|
||
for key, (title, console) in zip(("service", "can", "rs485"), create_examples()): # Стабильные ключи соответствуют значениям --kind.
|
||
if args.kind in ("all", key): window.addTab(console.panel, title) # Выбранные примеры добавляются с общей панелью инструментов.
|
||
window.setWindowTitle("Примеры консоли templates") # Заголовок явно отличает демонстрацию от подключения к плате.
|
||
window.resize(1100, 480) # Начальный размер в логических пикселях позволяет видеть все инструменты.
|
||
window.show() # Окно появляется только при прямом запуске примера.
|
||
return app.exec() # Цикл Qt обрабатывает поиск, паузу, экспорт и изменение масштаба.
|
||
|
||
|
||
if __name__ == "__main__": # Импорт фабрики в тестах не должен открывать окно или запускать цикл событий.
|
||
raise SystemExit(main()) # Код завершения Qt возвращается вызывающему процессу.
|