# Протокол обмена с сервером

Описание протокола обмена между SDK `artex-robot` (версия 0.1.1) и сервером ARTEX. Страница полезна тем, кто реализует собственного клиента (на другом языке, для микроконтроллера или симулятора) или серверную часть.

## Транспорт

| Параметр | Значение |
|---|---|
| Протокол | Socket.IO (Engine.IO поверх WebSocket / HTTP long-polling) |
| Адрес | `<server>:<port>`, по умолчанию `http://artex.arcon:80` |
| Namespace | `/robot` |
| Авторизация | Объект `auth` при подключении = паспорт устройства |
| Переподключение | Автоматическое: до 5 попыток, задержка 1 с, максимум 5 с |

## Последовательность обмена

```
Робот (SDK)                                              Сервер (ХАБ)
    │ connect /robot, auth = {name, type, telem_can, video_can} │
    │────────────────────────────────────────────────────────────▶│  регистрация, SID
    │                                                             │
    │◀──────────── heartbeat ["d_meta", "Ready"] (с ответом) ─────│
    │──── ack {"d_meta": {...}, "Ready": "ok"} ───────────────────▶│
    │   запуск потоков telem и video                              │
    │                                                             │
    │──── telem {"payload": {"battery": 11.7, ...}} ─────────────▶│  (каждые max_send_freq с,
    │──── video {"payload": {"rgb": <JPEG bytes>}} ──────────────▶│   только при изменении)
    │                                                             │
    │◀──────────── command {"author": ..., "payload": {...}} ─────│
    │                                                             │
    │◀──────────── command {"payload": {"file": "log"}} ──────────│
    │──── file {"payload": {"type": "log", "content": "..."}} ───▶│
    │                                                             │
    │ disconnect                                                  │
```

## Подключение

При подключении клиент передаёт в `auth` паспорт устройства:

```json
{ "name": "tank-01", "type": "Robot", "telem_can": true, "video_can": true }
```

## События от сервера к роботу

### `heartbeat` (с подтверждением)

Данные — список запросов. Робот возвращает словарь ответов (Socket.IO ack).

| Запрос | Ответ | Побочный эффект |
|---|---|---|
| `"d_meta"` | Состояние: `{"sid": ..., "ready": "init" \| "ok", "telem_run": bool, "video_run": bool}` | — |
| `"Ready"` | `"ok"` | Робот переходит в состояние `ready = ok` и запускает потоки отправки телеметрии и видео |
| другое | — | Предупреждение в журнале |

Пример ответа: `{"d_meta": {"sid": null, "ready": "ok", "telem_run": true, "video_run": true}, "Ready": "ok"}`

### `token_ask` (с подтверждением)

Запрос идентификатора. Робот возвращает значение `sid` из своего состояния.

### `command`

```json
{ "author": "<id автора>", "payload": { "<тип>": <команда> } }
```

Обрабатывается только в состоянии `ready = ok`. Типы `file` и `web_settings` обрабатываются SDK; остальные передаются в `@robot.com_handler`. См. [Обработка команд](https://docs.mephi-ai.ru/books/po-dlia-robota/page/obrabotka-komand).

## События от робота к серверу

### `telem`

```json
{ "payload": { "battery": 11.7, "speed": 0.42, "imu": [0.01, -0.02, 9.81] } }
```

Полный текущий словарь телеметрии. Отправляется, только если с прошлой отправки что-то записывалось в телеметрию.

### `video`

```json
{ "payload": { "rgb": "<bytes: JPEG>", "rear": "<bytes: JPEG>" } }
```

Словарь «камера → кадр». Кадры — JPEG (качество 80) в виде бинарных данных Socket.IO. Для ключей, содержащих `led` или `rgb_strip`, значение передаётся как есть (без JPEG).

### `file`

Ответ на команду `{"file": "log"}` или `{"file": "error"}`:

```json
{ "payload": { "type": "log", "content": "<текст журнала>" } }
```

Команда `{"file": "clear"}` очищает журналы и ответа не отправляет.

## Частоты

- Телеметрия и видео отправляются отдельными потоками с паузой `max_send_freq` секунд (по умолчанию 0,05 с).
- Отправляется только изменённое с момента прошлой отправки, поэтому фактическая частота ограничена частотой основного цикла робота.

## Минимальный тестовый сервер

Для отладки робота без платформы можно запустить имитатор сервера (Python, `pip install "python-socketio" aiohttp`):

```python
import asyncio, socketio
from aiohttp import web

sio = socketio.AsyncServer(async_mode="aiohttp")
app = web.Application(); sio.attach(app)

@sio.on("connect", namespace="/robot")
async def connect(sid, environ, auth):
    print("Подключён:", auth)
    async def handshake():
        await asyncio.sleep(0.5)
        ans = await sio.call("heartbeat", ["d_meta", "Ready"], to=sid, namespace="/robot")
        print("heartbeat:", ans)
        await sio.emit("command", {"author": "tester", "payload": {"com": "forward"}},
                       to=sid, namespace="/robot")
    asyncio.create_task(handshake())

@sio.on("telem", namespace="/robot")
async def telem(sid, data):
    print("telem:", data["payload"])

@sio.on("video", namespace="/robot")
async def video(sid, data):
    print("video:", {cam: len(frame) for cam, frame in data["payload"].items()}, "байт")

web.run_app(app, port=8765)
```

Запустите его и укажите в `params.json` робота `"server": "http://localhost", "port": 8765`.

<p class="callout info">В целевой архитектуре платформы предусмотрены также передача видео по RTSP с преобразованием в WebRTC и подключение IoT-датчиков по MQTT. Описание — в книге «Сервер управления роботами», страница <a href="https://docs.mephi-ai.ru/books/server-upravleniia-robotami/page/protokoly-i-potoki-dannyx">Протоколы и потоки данных</a>.</p>