HTTP API¶
Веб-панель использует HTTP API того же сервера. Он подходит для скриптов, которым не нужен ROS: получения списка камер, изменения настроек, работы с моделями и архивом.
Откройте http://127.0.0.1:8000/docs на работающем сервере. Это интерактивный
справочник OpenAPI: у каждого запроса указаны параметры, схема тела и ответы.
Страница /docs сервера — справочник API, а этот сайт MkDocs — руководство пользователя.
Проверить доступность¶
BASE=http://127.0.0.1:8000
curl --fail "$BASE/healthz"
curl --fail "$BASE/api/v1/cameras" | python3 -m json.tool
На другом компьютере замените адрес. Сервер по умолчанию принимает соединения только с локальной машины. Порядок запуска для локальной сети описан в первом запуске.
Камеры¶
| Запрос | Назначение |
|---|---|
GET /api/v1/cameras |
Конфигурация, ревизия и состояние камер |
GET /api/v1/cameras/devices |
Обнаруженные V4L2-устройства и режимы |
GET /api/v1/ros/topics |
Список ROS-топиков и типов |
POST /api/v1/cameras |
Добавление камеры |
PUT /api/v1/cameras/{id} |
Полная новая конфигурация выбранной камеры |
DELETE /api/v1/cameras/{id} |
Удаление |
GET /api/v1/cameras/{id}/stream.mjpeg |
Предпросмотр |
Изменение конфигурации требует If-Match из предыдущего чтения. Иначе два клиента
могли бы незаметно перезаписать настройки друг друга. Здесь ревизия — хеш всей
конфигурации камер, а не счётчик отдельной камеры.
Следующий пример выключает только одну камеру, сохраняя остальные её поля.
Для него нужен пакет requests в Python-окружении клиента.
import requests
base = "http://127.0.0.1:8000"
camera_id = "workbench"
response = requests.get(f"{base}/api/v1/cameras", timeout=10)
response.raise_for_status()
camera = next(c for c in response.json()["cameras"] if c["id"] == camera_id)
camera.pop("runtime", None) # runtime относится к ответу, а не к конфигурации
camera["enabled"] = False
updated = requests.put(
f"{base}/api/v1/cameras/{camera_id}",
headers={"If-Match": response.headers["ETag"]},
json=camera,
timeout=90,
)
updated.raise_for_status()
print(updated.json())
Отключение V4L2/RealSense применяется к драйверу. У внешнего ROS-источника SmartCamera прекращает подписку, а издатель другой программы продолжает работать. При неудачном применении конфигурация восстанавливается; прочитайте ответ и повторно получите список камер, прежде чем отправлять следующую правку.
Модели и запуски¶
| Запрос | Назначение |
|---|---|
GET /api/v1/models |
Библиотека Ultralytics |
GET /api/v1/models/capabilities |
Интерпретатор ML, пакеты, доступность вычислителей |
GET /api/v1/inference |
Запуски моделей |
POST /api/v1/inference |
Подключение модели к камере |
PATCH /api/v1/inference/{id} |
Изменение запуска с If-Match |
DELETE /api/v1/inference/{id} |
Удаление запуска с If-Match |
GET /api/v1/inference/{id}/result |
Последний доступный результат |
GET /api/v1/jobs |
Фоновые задания |
POST /api/v1/jobs |
Загрузка, обучение, валидация или экспорт |
В отличие от камер, ревизия запуска — целое число. Пример создания выключенного запуска, проверки ответа и включения:
import requests
base = "http://127.0.0.1:8000/api/v1"
response = requests.post(f"{base}/inference", json={
"camera_id": "workbench",
"model_id": "ЗАМЕНИТЕ_ID_МОДЕЛИ",
"enabled": False,
"fps": 5,
"device": "cpu",
"parameters": {"conf": 0.4, "iou": 0.6},
}, timeout=15)
response.raise_for_status()
run = response.json()
response = requests.patch(
f"{base}/inference/{run['id']}",
headers={"If-Match": str(run["revision"])},
json={"enabled": True},
timeout=15,
)
response.raise_for_status()
print(response.json())
Получение успешного ответа означает, что настройки приняты. Загрузка весов
и обработка идут в отдельном процессе; последующую ошибку модели нужно читать
в состоянии запуска. Списки parameters и prompts заменяются целиком, поэтому
для изменения одного вложенного значения сначала сохраните остальные настройки.
Произвольная загрузка файла весов через POST /models или /models/upload
в текущей версии отключена и возвращает 410. Для добавления стандартной модели
используется задание загрузки; работа через интерфейс описана
в библиотеке моделей.
Запись и материалы¶
Фото создаётся запросом POST /api/v1/recordings/photos, видео —
POST /api/v1/recordings/videos, bag — POST /api/v1/recordings/bags.
Параметры отличаются: сначала выберите нужную схему в OpenAPI. Для остановки
активной записи используется POST /api/v1/recordings/active/stop.
GET /api/v1/recordings возвращает материалы; отдельная запись доступна по
GET /api/v1/recordings/{id}. ZIP скачивается через
GET /api/v1/recordings/{id}/download.zip. Идентификаторы файлов берите из
manifest, не формируйте пути к файлам вручную.
Как обрабатывать ошибки¶
| Код HTTP | Что проверить |
|---|---|
| 404 | Существуют ли камера, запуск, материал или ещё не истёк ли временный ресурс |
| 409 | Ревизия устарела либо ресурс занят другой операцией |
| 410 | Эта операция больше не поддерживается текущим API |
| 422 | Типы, диапазоны и обязательные поля запроса |
| 428 | Не передан требуемый If-Match |
| 503 | Доступен ли ROS-узел, кадр или запись конфигурации |
Не повторяйте изменяющий запрос бесконечно после сетевого тайм-аута: он мог
успеть выполниться. Перечитайте состояние. Для ROS-команд есть отдельный механизм
повторов по request_id, описанный в контракте команд.