Table of Contents
📚 Документация API проекта: Excavators AI
Базовый URL:
https://ex.neimarker.ru/api/Формат дат: ISO 8601 (например,2026-04-20T15:30:00Z)
Аутентификация (Для интеграций): ЗаголовокAuthorization: Api-Key <токен>
Аутентификация (Web): ЗаголовокAuthorization: Bearer <jwt_access_token>
📑 Оглавление
- Аутентификация и интеграция
- Экскаваторы (Базовый CRUD)
- Настройки графика и работы экскаватора
- Аналитика и Цифровой двойник
- Видеоархив, Карты и Очистка данных
- Подробные примеры использования API (с ответами и их интерпретацией)
1. Аутентификация и интеграция
В системе предусмотрено два типа доступа: для живых пользователей (через веб-интерфейс с логином/паролем) и для сторонних систем (интеграция по статичному API-ключу).
🔑 Доступ для сторонних систем (Интеграция)
Для работы внешних скриптов, 1С, Telegram-ботов и других систем (M2M) капча и временные токены не используются.
⚠️ Важно: Для получения ключа интеграции (
Api-Key) вашей организации необходимо обратиться в службу технической поддержки или к менеджеру.
💻 Пример на Python: Интеграция по Api-Key
import requests
BASE_URL = "https://ex.neimarker.ru/api/"
# Токен, выданный для вашей организации
API_KEY = "ВАШ_УНИКАЛЬНЫЙ_ТОКЕН_ИНТЕГРАЦИИ"
headers = {
"Authorization": f"Api-Key {API_KEY}"
}
# Пример 1: Запрашиваем список всех доступных экскаваторов вашей организации
devices_res = requests.get(f"{BASE_URL}/devices/", headers=headers)
print("Доступная техника:", devices_res.json())
# Пример 2: Запрашиваем аналитику по одному экскаватору
analytics_res = requests.get(
f"{BASE_URL}/analytics/?device_id=1&start_date=2026-04-20T00:00:00Z&end_date=2026-04-20T23:59:59Z",
headers=headers
)
print("Аналитика:", analytics_res.json())
2. Экскаваторы (Базовый CRUD)
Автоматически ограничивает выдачу только устройствами, принадлежащими организации, чей токен совершает запрос.
| Метод | Эндпоинт | Описание |
|---|---|---|
GET |
/devices/ |
Список всех устройств организации. |
POST |
/devices/ |
Создание устройства. Ожидает: name, bucket_volume. MAC и API-токен генерируются автоматически. |
GET |
/devices/<id>/ |
Данные одного устройства. |
PATCH |
/devices/<id>/ |
Изменение параметров (объем ковша, смены, часовой пояс timezone_offset и т.д.). |
DELETE |
/devices/<id>/ |
Удаление. (Можно удалять только устройства с MAC "OFFLINE-..."). |
3. Настройки графика и работы экскаватора
Вложенные справочники для конкретного device_id. Поддерживают создание, чтение списка и удаление по pk (ID записи).
| Метод | Эндпоинт | Описание |
|---|---|---|
GET, POST |
/devices/<device_id>/materials/ |
Типы грунта (плотность, коэффициенты) на заданный период. |
DELETE |
/devices/<device_id>/materials/<pk>/ |
Удалить настройку материала. |
GET, POST |
/devices/<device_id>/schedule-exceptions/ |
Исключения графика: ТО, ремонты, выходные, спец-смены. |
DELETE |
/devices/<device_id>/schedule-exceptions/<pk>/ |
Удалить исключение. |
GET, POST |
/devices/<device_id>/breaks/ |
Ежедневные перерывы (например, Обед 12:00 - 13:00). |
DELETE |
/devices/<device_id>/breaks/<pk>/ |
Удалить перерыв. |
GET, POST |
/devices/<device_id>/shifts/ |
Настройка смен (при has_multiple_shifts=True у устройства). |
DELETE |
/devices/<device_id>/shifts/<pk>/ |
Удалить смену. |
💻 Пример на Python: Настройка расписания
device_id = 1
headers = {"Authorization": f"Api-Key {API_KEY}"}
# 1. Добавляем обед
requests.post(f"{BASE_URL}/devices/{device_id}/breaks/", headers=headers, json={
"start_time": "12:00:00",
"end_time": "13:00:00",
"description": "Обеденный перерыв"
})
# 2. Добавляем исключение (выходной / праздник)
requests.post(f"{BASE_URL}/devices/{device_id}/schedule-exceptions/", headers=headers, json={
"date": "2026-05-01",
"end_date": "2026-05-01",
"is_working": False,
"is_maintenance": False,
"description": "День Труда"
})
4. Аналитика и Цифровой двойник
Тяжелые вычислительные эндпоинты для получения отчетов и метрик.
| Метод | Эндпоинт | Описание |
|---|---|---|
GET |
/analytics/ |
Сводная аналитика. Требует параметры ?device_id=...&start_date=...&end_date=.... Возвращает объемы, массу, таймлайн, циклы, телеметрию (JSON). |
POST |
/analytics/recalculate/ |
Полный пересчет аналитики (сборка циклов и простоев). Ожидает JSON: device_id, start_date. Запускается в фоне. |
5. Видеоархив, Карты и Очистка данных
Все, что связано с видео, треками и управлением сырыми данными устройства.
| Метод | Эндпоинт | Описание |
|---|---|---|
GET |
/devices/<device_id>/available-dates/ |
Массив дат (YYYY-MM-DD), за которые есть загруженные данные. |
GET |
/devices/<device_id>/folders/ |
Список папок архива (кусков видео по 1 часу). |
GET |
/devices/<device_id>/folders/<folder_id>/detections/ |
Координаты рамок (Bounding Boxes) для рисования поверх видеоплеера. |
GET |
/devices/<device_id>/video-frame/?timestamp=... |
Поиск видеофайла и секунды для перемотки по точному времени. |
GET |
/devices/<device_id>/trajectory/?start_date=...&end_date=... |
Координаты GPS для отрисовки линии маршрута на карте. |
POST |
/devices/<device_id>/upload-archive/ |
Ручная загрузка оффлайн .zip архива. Возвращает Streaming HTTP с логами распаковки. |
GET |
/devices/<device_id>/alerts/ |
Список последних экстренных событий (Алертов) от устройства. |
POST |
/devices/<device_id>/clear-data/ |
Опасная операция. Очистка данных устройства. JSON: {"mode": "all"} или {"mode": "date", "date": "..."}. |
6. Подробные примеры использования API (с ответами и их интерпретацией)
Ниже приведены расширенные примеры того, как обращаться к эндпоинтам и как правильно читать возвращаемые данные.
Пример 6.1: Получение информации об устройстве и его настройках
Запрос (Python):
# Получаем базовую информацию об экскаваторе
response = requests.get(f"{BASE_URL}/devices/43/", headers=headers)
device_data = response.json()
# Получаем настроенные для него материалы
mat_response = requests.get(f"{BASE_URL}/devices/43/materials/", headers=headers)
materials_data = mat_response.json()
Ответ API (Устройство):
{
"id": 43,
"name": "Excavator fd7f",
"mac_address": "24f40acefd7f",
"last_seen": "2026-04-23T15:18:35.744056+03:00",
"is_active": true,
"bucket_volume": 2.5,
"max_cycle_time_sec": 60,
"downtime_threshold_sec": 300,
"organization_name": "Дзержинск карьер",
"has_multiple_shifts": true
}
Ответ API (Материалы):
[
{
"id": 3,
"name": "Грунт",
"is_default": true,
"bulk_density": 1650.0,
"true_density": 2600.0,
"loosening_factor": 1.58
}
]
Интерпретация:
- Устройство
Excavator fd7fактивно работает в организации «Дзержинск карьер». Связь с ним была совсем недавно (last_seen). - Физический объем ковша (
bucket_volume) — 2.5 кубометра. - Если экскаватор не двигается более 300 секунд (
downtime_threshold_sec), система засчитывает это как простой. - У машины включен режим работы по сменам (
has_multiple_shifts: true). - По умолчанию машина работает с материалом «Грунт» (
is_default: true). При расчете массы ИИ будет использовать объемный вес 1650 кг/м³ и коэффициент разрыхления 1.58 (loosening_factor).
Пример 6.2: Запрос суточной аналитики (Цифровой двойник)
Запрос (Python):
params = {
"device_id": 43,
"start_date": "2026-04-23T00:00:00Z",
"end_date": "2026-04-23T23:59:59Z"
}
response = requests.get(f"{BASE_URL}/analytics/", headers=headers, params=params)
analytics_data = response.json()
Ответ API (Аналитика, сокращенно):
{
"total_mileage_km": 1.95756,
"total_duration_sec": 68399.0,
"cycle_count_total": 675,
"cycle_count_vehicle": 266,
"cycle_count_ground": 409,
"estimated_volume_total": 1687.5,
"estimated_mass_total": 2784375.0,
"shift_stats": {
"Дневная": {
"cycles_total": 675,
"actual_downtime": 5233.1,
"volume_vehicle": 665.0
},
"Ночная": {
"cycles_total": 0,
"actual_downtime": 0,
"volume_vehicle": 0.0
}
},
"averages": {
"vehicle": {"empty_sec": 5.1, "full_sec": 10.6, "unload_sec": 6.5, "total_sec": 22.1},
"ground": {"empty_sec": 8.3, "full_sec": 4.5, "unload_sec": 5.4, "total_sec": 18.3}
},
"durations_by_class_sec": {
"full_bucket": 4019.7,
"unloading_vehicle": 2036.9,
"unloading_ground": 4897.2,
"empty_bucket": 9006.3,
"actual_downtime": 5233.1,
"no_data": 43205.6
}
}
Интерпретация: Данный эндпоинт отдает готовую сводку за запрошенный период:
- Экскаватор проехал почти 2 км (
total_mileage_km). - За день сделано 675 рабочих циклов (
cycle_count_total). Из них полезная работа — загрузка в транспорт/самосвал (cycle_count_vehicle) составила 266 ковшей, а перекидка в отвал/на землю (cycle_count_ground) — 409 ковшей. - Перемещено около 1687 кубометров или ~2784 тонн породы.
- В блоке
shift_statsвидно, что вся работа пришлась исключительно на смену «Дневная». В «Ночную» машину не заводили (0 циклов). - Блок
averagesпоказывает, что средний цикл загрузки в транспорт занимает 22.1 секунды, где 10.6 сек уходит на поворот с полным ковшом, а 6.5 сек — на выгрузку. - Блок
durations_by_class_secдетально расписывает хронометраж.actual_downtime(фактический простой с включенным двигателем) составил ~1.45 часа (5233 сек). Параметрno_data(экскаватор выключен или нет связи) составил около 12 часов.
Пример 6.3: Работа с видеоархивом (Синхронизация видео и графика)
Частый сценарий — оператор кликает на событие в графике аналитики, и плеер должен перемотать видео точно на этот момент.
Шаг 1: Запрос доступных папок за день (Python):
response = requests.get(f"{BASE_URL}/devices/43/folders/", headers=headers)
folders = response.json()
Ответ:
[
{
"id": 5495,
"received_at": "2026-04-23T15:18:28.541403+03:00",
"video_file": "/media/devices/43/2026/04/23/15/video_...mp4",
"file_count": 4350,
"original_width": 480,
"original_height": 640
}
]
Интерпретация: Видео на сервере нарезается часовыми кусками (папками). Внутри этого часа ИИ обработал 4350 кадров (поле file_count).
Шаг 2: Поиск точного кадра по Timestamp (Python):
params = {"timestamp": "2026-04-23T15:03:02Z"}
response = requests.get(f"{BASE_URL}/devices/43/video-frame/", headers=headers, params=params)
frame_data = response.json()
Ответ:
{
"video_url": "http://ex.neimarker.ru/media/devices/43/2026/04/23/15/video_7d4b6624.mp4",
"seek_seconds": 182.875,
"folder_id": 5495,
"frame_index": 4389
}
Интерпретация: API нашел, в каком видеофайле находится запрошенное время (timestamp). Фронтенду/приложению нужно загрузить video_url и перемотать плеер на 182.875 секунды (seek_seconds), чтобы показать нужный момент работы или нарушения.
Пример 6.4: Получение трека (маршрута) для карты
Запрос (Python):
params = {
"start_date": "2026-04-23T03:17:00Z",
"end_date": "2026-04-23T03:30:00Z"
}
response = requests.get(f"{BASE_URL}/devices/43/trajectory/", headers=headers, params=params)
trajectory = response.json()
Ответ API:
[
{
"ts": "2026-04-23T03:17:00.796000Z",
"lat": 56.23502833333334,
"lon": 43.63613999999999
},
{
"ts": "2026-04-23T03:18:00.997000Z",
"lat": 56.23502833333334,
"lon": 43.63613999999999
}
]
Интерпретация:
Массив точек с широтой (lat) и долготой (lon), привязанных к меткам времени (ts). Эти данные идеально подходят для отрисовки полилинии (Polyline) маршрута движения экскаватора в гео-информационных системах, 1С (через интеграцию карт) или на веб-картах (Yandex Maps, Leaflet). Точки отдаются с фильтрацией погрешностей GPS (выбросов).