# Справочник API

Справочник публичного интерфейса SDK `artex-robot` версии 0.1.1.

## Класс `Robot`

```python
from artex_robot import Robot
robot = Robot(conf: dict = {})
```

Создаёт робота, загружает конфигурацию из `params.json` и словаря `conf` (приоритет у `conf`), инициализирует журнал и Vault. Соединение с сервером **не** устанавливается — для этого вызовите `init_connector()`. Параметры — на странице [Конфигурация](https://docs.mephi-ai.ru/books/po-dlia-robota/page/konfiguraciia).

## Декораторы

### `@robot.com_handler`

Регистрирует обработчик команд. **Обязателен** — должен быть объявлен до вызова `init_connector()`.

```python
@robot.com_handler
def on_command(type_command: str, command, author=None):
    ...
```

| Аргумент | Описание |
|---|---|
| `type_command` | Тип команды: `com`, `force_com`, `sys_com` и др. (см. [Обработка команд](https://docs.mephi-ai.ru/books/po-dlia-robota/page/obrabotka-komand)) |
| `command` | Сама команда — строка или структура, которую отправил оператор/модель |
| `author` | Идентификатор автора команды (оператор или модель ИИ) |

Обработчик вызывается в потоке Socket.IO-клиента, а не в основном цикле. Долгие действия выполняйте асинхронно (см. пример колёсного робота на странице [Примеры роботов](https://docs.mephi-ai.ru/books/po-dlia-robota/page/primery-robotov)).

### `@robot.telemetry(key)`

Помечает функцию как источник телеметрии. При каждом вызове функции её результат записывается в Vault под ключом `key`.

```python
@robot.telemetry("battery")
def read_battery():
    return adc.read_voltage()
```

- Результат должен сериализоваться в JSON-совместимый вид: число, строка, bool, список, словарь.
- На сервер отправляется **весь** словарь телеметрии, например `{"battery": 11.8, "speed": 0.4}`.
- Несколько функций с разными ключами дополняют общий словарь.
- Функция-обёртка ничего не возвращает — чтобы использовать значение ещё и локально, прочитайте датчик отдельно.

### `@robot.video(cam_id)`

Помечает функцию как источник видео для камеры `cam_id`. Результат функции — кадр OpenCV (numpy-массив BGR) — сжимается в JPEG (качество 80) и записывается в Vault.

```python
@robot.video("front")
def send_front(frame):
    return frame
```

- Функция **не должна** возвращать `None` — это вызовет ошибку OpenCV.
- Несколько камер — несколько функций с разными `cam_id`; на сервер уходит словарь `{"front": <jpeg>, "rear": <jpeg>}`.
- Если `cam_id` содержит `led` или `rgb_strip`, значение **не** кодируется в JPEG и передаётся как есть. Так LED-устройства передают своё текущее состояние (например, массив цветов светодиодной ленты).

### `@robot.mainloop`

Регистрирует функцию основного цикла. **Обязателен.**

```python
@robot.mainloop
def main_loop(context: dict):
    ...
```

Функция вызывается бесконечно с паузой `max_main_freq` секунд. Аргумент `context` — словарь контекста робота (см. ниже). Исключения внутри функции не перехватываются SDK и завершают программу — обрабатывайте их сами.

## Методы

| Метод | Описание |
|---|---|
| `robot.init_connector()` | Подключается к серверу `server:port`, namespace `/robot`, передаёт паспорт устройства. Включено авто-переподключение: 5 попыток, задержка 1–5 с. Если сервер недоступен при первом подключении — выбрасывает исключение `socketio.exceptions.ConnectionError` |
| `robot.start()` | Запускает основной цикл. Блокирует выполнение. По Ctrl+C корректно останавливает потоки и отключается |
| `robot.stop()` | Останавливает отправку телеметрии и видео и отключается от сервера |
| `robot.set_context(key, value)` | Кладёт объект в контекст робота |
| `robot[key] = value`, `robot[key]`, `del robot[key]`, `key in robot` | То же через синтаксис словаря |

## Контекст

Контекст — словарь для объектов, которые нужны основному циклу и обработчикам: камеры, драйверы моторов, последние команды, состояние автомата.

```python
robot["cam"] = cv2.VideoCapture(0)
robot["motors"] = MotorDriver()

@robot.mainloop
def loop(ctx):
    ok, frame = ctx["cam"].read()
```

## Журнал `robot.log`

```python
robot.log("INFO", "Моторы инициализированы")
robot.log("WARN", "Низкий заряд")
robot.log("ERROR", "Нет ответа от контроллера")
robot.log.set_level("skip_TODO")   # скрыть служебные TODO-сообщения
robot.log.set_type("file")         # писать в all.log / error.log
```

| Уровень | Использование |
|---|---|
| `INFO` | Штатные события |
| `WARN` | Предупреждения |
| `ERROR` | Ошибки — при `logger_type = file` дублируются в `error.log` |
| `TODO` | Служебные сообщения SDK (выводятся на каждой итерации цикла, скрываются уровнем `skip_TODO`) |

Файлы журнала создаются в текущем рабочем каталоге. Сервер может запросить их удалённо (см. [Протокол обмена с сервером](https://docs.mephi-ai.ru/books/po-dlia-robota/page/protokol-obmena-s-serverom)).

## Внутренние объекты (для продвинутого использования)

| Атрибут | Назначение |
|---|---|
| `robot.vault` | Хранилище: `set_telem(key, val)`, `set_video(cam_id, frame)`, `get_smeta()`, `get_dmeta(key)` |
| `robot.sio` | Коннектор; `robot.sio.sio` — клиент `socketio.Client`, `robot.sio.emit(event, data)` — отправка произвольного события в namespace `/robot` |

Пример прямой записи телеметрии без декоратора: `robot.vault.set_telem("temp", 36.6)`.