# Socket.IO для старого Artex-robot Адаптер подключает старый `core/com/Connector` из Artex-robot к текущим `SessionManager`, `Session` и `Router`. Код ядра, TCP и `main.py` не изменяется. Все файлы адаптера, его зависимости и тесты находятся в этой папке. ## Подключение Из папки `server` установите зависимости: ```powershell & 'D:\_Programs\anaconda\envs\sites\python.exe' -m pip install -r src/transport/sio_legacy/requirements.txt ``` Интерфейс совпадает с TCP: ```python from transport.sio_legacy import SIO # sessions — тот же менеджер, который используется TCP. sio = SIO("0.0.0.0", 9001, sessions) await sio.run() ``` TCP и Socket.IO могут работать одновременно с одним менеджером и роутером: `await asyncio.gather(tcp.run(), sio.run())`. Им нужны разные порты. Отмена задачи `run()` закрывает listener и активные соединения Socket.IO. Для порта `0` выбранный порт доступен в `sio.bound_port` после `await sio.started.wait()`. Сервер использует [python-socketio с aiohttp](https://python-socketio.readthedocs.io/en/stable/server.html), поддерживает polling и WebSocket, namespace `/robot` и обычный путь `/socket.io`. Это Socket.IO, не отдельный WebSocket-протокол. ## Соответствие протоколов | Старый робот | Пакет для ядра / действие адаптера | | --- | --- | | Метаданные в `auth` при соединении | `connection`, диалект `v1` | | Ответ ACK на `token_ask` | `token_answer` без старого token/upf | | ACK на `heartbeat(["Ready", "d_meta"])`, `Ready == "ok"` | Успешный `handshake_answer` | | ACK на `heartbeat(["d_meta"])` | `heartbeat_ask`, обновление срока в ядре | | `telem` / `video` / другой event с `{"payload": value}` | `{"command": event, "payload": value}` | | Отправка ядром `command` | Event `command` с тем же `payload` | | Отправка ядром `com` / `force_com` / `sys_com` | Event `command`, `payload` содержит выбранную категорию | | Остальные отправки ядра | Event с именем `command` пакета и `{"payload": value}` | `Ready` отправляется один раз при успешном handshake: старый клиент запускает по этому запросу потоки телеметрии и видео. Последующие heartbeat запрашивают только `d_meta`. Данные, отправленные этими потоками до ACK handshake, ждут завершения handshake и затем поступают в ядро. Первый `Ready` задерживается на `heartbeat_interval`, чтобы исходный Connector успел завершить инициализацию после `socketio.Client.connect()`. По умолчанию `heartbeat_interval=1.0`, `ack_timeout=3.0` секунды. Интервал вместе с ожиданием ACK должен быть меньше пяти секунд. У ядра остаются прежние сроки: 60 секунд до первого heartbeat, 5 секунд после heartbeat, 60 секунд хранения отключённой сессии. Истечение ACK также закрывает соединение; удаление сессии и маршрутов выполняет менеджер. `video.payload`, включая JPEG `bytes`, сохраняется в `Session.last_data` без преобразования. Отправка через Socket.IO передаёт тот же бинарный payload. Текущий JSON-транспорт TCP не кодирует bytes; преобразование для других транспортов здесь не добавлено. Исходные `telem_can`, `video_can` и другие поля `auth` доступны в `Connection.metadata`; последнее `d_meta` — в `Connection.dynamic_meta`. Они не превращаются в `in/out`, активные порты или маршруты автоматически. Маршруты задаются существующими средствами Router. `legacy` пока нужен: у старого робота метаданные передаются через `auth`, управляющие ответы приходят как Socket.IO ACK, а heartbeat инициирует сервер. Это отличается от пакетов `v1`. Старый клиент возвращает только `sid`, без `upf`, и в просмотренной реализации не сохраняет новый token. Адаптер сохраняет ответ в `Connection.legacy_sid`, но каждое соединение создаёт новую сессию. Маршруты и данные прежней сессии не восстанавливаются по одному sid или имени робота. Ошибки приёма, отправки и heartbeat записываются в лог с sid/uid и закрывают только соответствующее соединение. `Session.send()` продолжает работать через фоновые задачи. Отправки одному SID упорядочены, чтобы бинарные вложения разных пакетов не перемешивались. ## Проверки Из `server`, после установки зависимостей: ```powershell $env:PYTHONDONTWRITEBYTECODE = '1' & 'D:\_Programs\anaconda\envs\sites\python.exe' -B -m pytest -q -p no:cacheprovider tests src/transport/sio_legacy/tests ``` Тесты используют настоящий сервер, ядро и сетевые клиенты. Проверяются polling/WebSocket, handshake, периодический heartbeat, ранние данные потоков, bytes, команды, общая маршрутизация TCP/Socket.IO, ошибки фоновой отправки, таймаут ACK, watcher ядра, повторное закрытие и остановка listener. Серверные cleanup-таймеры отменяются только при завершении теста. Дополнительный `test_original_robot_connector` загружает исходные Connector, handlers, parsers и метаданные из `E:/robot_src`, запускает его настоящие сетевые обработчики и потоки. Только оборудование заменено источником тестовых кадров и приёмником команд. Другой путь задаётся через `$env:ARTEX_ROBOT_SRC = 'путь/к/artex-robot'`. При отсутствии исходников этот дополнительный тест пропускается; остальные тесты воспроизводимы без них. Ключ `-B` предотвращает запись pyc в каталог внешнего проекта. Не проверяются физическое оборудование робота, восстановление сессии без upf, авторизация и доставка бинарных данных через TCP. API/GUI маршрутов, автоматическое создание маршрутов и сохранение состояния после перезапуска не реализуются этим адаптером.