Я работаю в компании, которая разрабатывает систему электронной очереди. Недавно написал веб-клиент — с SOAP, QR-талонами, веб-интерфейсом. Потом поступила задача: интегрировать физическое табло с вызовом клиентов в веб. Старое десктопное приложение умело зажигать на нём цифры — нужно было повторить это из браузера.
Поиск документации: провал
Обратился к команде, которая делала старое приложение.
День 1: «Да, конечно, поищем». День 3: «Нету, давно было, зайди позже». День 5: «А зачем тебе?» День 7: сеньор, не отрываясь от монитора: «Там где-то в коде зашито, долго искать».
В итоге — только старая утилита от монтажников, под Windows, без исходников. Вместо жалоб — решил разобраться сам. С помощью ИИ.
Анализ трафика через виртуальные COM-порты
Аппаратного анализатора нет, но есть com0com — виртуальная пара COM-портов. Старая утилита пишет в один, RealTerm читает из другого и показывает HEX.
Нажимаю кнопку — в терминал сыплются байты. И сразу бросается в глаза: каждый байт — либо 0x00, либо 0x7F. Никаких промежуточных значений.
Сначала подумал — помехи или битый поток. Потом понял.
BCD4: один бит — один байт
Это аппаратный костыль для устойчивой передачи по длинным линиям с помехами. Один бит данных передаётся как целый байт: 0x7F (семь единиц) — это логическая «1», 0x00 — «0».
Число от 0 до 15 раскладывается по 4 битам, каждый бит превращается в байт. Например:
00 00 00 00→ 07F 00 00 00→ 100 7F 00 00→ 27F 00 7F 00→ 57F 00 00 7F→ 900 00 7F 7F→ 12
Цена — 4 байта на цифру и скорость всего 1200 бод. Зато надёжно.
В Python кодирование выглядит просто:
Структура пакета
Пакет для вывода числа на окно состоит из 33 байт. Например, число 487 на окне 19: D1=7, D2=8, D3=4, W_lo=9, W_hi=1.
Полезные поля — цифры числа и номер окна — нашлись быстро. А вот последние 8 байт вели себя странно.
Контрольная сумма: головоломка с переносом
Простое сложение и XOR не работали. При числах вроде 80 или 90 контрольные байты резко менялись — явно был перенос между полями. На маленьких числах формулы работали, на больших — ломались.
Тогда я обратился к ИИ. Передал около 30 перехваченных пакетов, объяснил структуру, сформулировал гипотезу: «Два поля c1 и c2, судя по поведению, — это младшая и старшая части 8-битного значения с переносом. Найди зависимость от остальных полей».
Ключевым стало именно правильное описание механизма.
Несколько ночей экспериментов: неверные константы, ошибки в переносе, частичные совпадения. Иногда казалось, что логики нет — просто захардкоженная таблица.
Но в итоге удалось. Оказалось: два 4-битных контрольных поля — части одного 8-битного значения. При переполнении младшей части — единица переносится в старшую, как при сложении столбиком.
Перенос возникает не всегда — только при определённых комбинациях числа и номера окна. Поэтому на простых тестах формулы работали, а на реальных — нет.
Режим «все окна» (25 байт, без указания окна) оказался проще — контрольная сумма без переноса.
Режим программирования окна
Установка номера окна — отдельный режим. Другой заголовок, пакет той же длины (33 байта), но без полей числа. Формула сложнее: участвует умножение, магические константы и два независимых переноса для пар контрольных полей.
Когда ИИ вывел точную формулу и проверил её на всех 30 пакетах — это было торжество. Проверил на окнах 1, 19, 30 — всё сошлось до байта.
Сборка пакета
Когда все поля известны, формирование пакета занимает несколько строк:
Алгоритм прост: число и номер окна раскладываются на цифры, каждая кодируется через BCD4, добавляются контрольные поля — и пакет готов к отправке в COM-порт.
Финальная архитектура
Всё завернул в Python-сервер, который работает в трее и принимает HTTP-запросы. Веб-система вызывает клиент — на табло загорается номер. Точно как старое приложение, но без него.
HTTP-интерфейс намеренно простой:
Сервер разбирает запрос, формирует пакет, отправляет в COM-порт. Веб-клиент даже не знает, что где-то работает RS-232 на 1200 бод.
Для отказоустойчивости добавил heartbeat-поток: сервер периодически регистрируется на центральном сервере очереди. При обрыве связи — восстанавливает её автоматически, без перезапуска.
Задача решена за несколько бессонных ночей.
Выводы
Из практического: ИИ отлично ищет математические закономерности, если дать достаточно примеров и правильно сформулировать гипотезу. Важно не «найди формулу», а «вот механизм, который я подозреваю — проверь и уточни». Опишите структуру, предположение — и получите формулу с доказательством.
Из жизненного: иногда проще потратить два вечера на реверс-инжиниринг, чем неделю на переписку в корпоративном чате.