10 KiB
REST API ButtonTask /api/v1
Базовый адрес — тот же, что у веб-конфигуратора (по умолчанию порт 8080). Отдельного процесса нет.
Чтение открыто. Запись требует заголовок X-Api-Key. Ключ лежит в settings.apiKey, создаётся сам при первом запуске и показывается на вкладке «Безопасность» конфигуратора. Запроса «отдать ключ» в этом API нет: его увидел бы любой в сети. Неверный или пустой ключ — HTTP 401:
{ "ok": false, "error": "unauthorized" }
Тело ошибок всегда {"ok": false, "error": "<код>"}.
Калибровка в файле хранится как min / max. В API это empty_mm (0%) и full_mm (100%). Уровень: (raw_mm - empty_mm) / (full_mm - empty_mm) * 100, зажим 0…100, один знак после запятой. Нет границ или они равны — level_pct равен null.
Байт питания — десятые вольта. voltage_mv = байт * 100. Байт 255 — нет данных, тогда voltage_mv и charge_pct равны null. charge_pct — оценка остатка двух дешёвых AA по кривой разряда.
stale_timeout_s только для чтения: report_interval_min * 60 * 3. Для 30 минут это 5400.
GET /api/v1/health
Авторизация не требуется.
Сводка коллектора, его аптайм, метрики хоста и счётчики датчиков. ok и status: "healthy" — файл статуса коллектора свежий (не старше 15 секунд). Иначе status: "degraded", HTTP всё равно 200.
{
"ok": true,
"status": "healthy",
"uptime_s": 86400.1,
"version": "1.2.3",
"ts": 1730000000.0,
"collector": {
"available": true,
"sensors_live": 2,
"sensors_stale": 1,
"sensors_total": 3
},
"system": {
"cpu_percent": 12.5,
"memory_used_percent": 41.0,
"load_1m": 0.42
}
}
uptime_s — секунды с старта процесса коллектора. Если метки старта нет, поле null.
GET /api/v1/sensors
Авторизация не требуется.
Интервал отчёта, таймаут устаревания и карточки известных датчиков. Пустых слотов нет.
{
"report_interval_min": 30,
"stale_timeout_s": 5400,
"sensors": [
{
"mac": "AA:BB:CC:DD:EE:FF",
"name": "Резервуар_1",
"raw_mm": 420,
"level_pct": 63.5,
"voltage_mv": 2800,
"charge_pct": 72,
"age_s": 42,
"state": "live",
"rssi": -67,
"last_seen": 1730000000.0
}
]
}
raw_mm равен null, если датчик не видит цель. state — live или stale.
GET /api/v1/sensors/{mac}
Авторизация не требуется.
Карточка одного датчика, тот же объект, что элемент sensors выше. Неизвестный адрес или кривой MAC — HTTP 404 sensor_not_found.
GET /api/v1/sensors/{mac}/history
Авторизация не требуется.
Параметры:
limit— от 1 до 1000, по умолчанию 100. Иначе HTTP 400invalid_limit.since— необязательный Unix timestamp, остаются точки сts >= since. Нечисло — HTTP 400invalid_since.
Кольцо на диске run/sensors-history.json, не больше 1000 точек на датчик. Ответ от новых к старым. Проценты считаются по текущей калибровке, а не по той, что была в момент замера.
Неизвестный датчик — HTTP 404 sensor_not_found. Известный датчик без точек — пустой entries.
{
"mac": "AA:BB:CC:DD:EE:FF",
"entries": [
{
"ts": 1730000000.0,
"raw_mm": 420,
"level_pct": 63.5,
"voltage_mv": 2800,
"charge_pct": 72,
"rssi": -67
}
]
}
PUT /api/v1/sensors/{mac}/name
Заголовок X-Api-Key обязателен.
{ "name": "Резервуар_1" }
Пустая строка сбрасывает имя. name не строка — HTTP 400 invalid_name. Кривой MAC — HTTP 400 invalid_mac.
{ "ok": true, "mac": "AA:BB:CC:DD:EE:FF", "name": "Резервуар_1" }
GET /api/v1/settings
Авторизация не требуется.
{
"report_interval_min": 30,
"stale_timeout_s": 5400
}
PUT /api/v1/settings
Заголовок X-Api-Key обязателен.
Принимается только report_interval_min, целое от 1 до 65535. Иначе HTTP 400 invalid_interval. stale_timeout_s записать нельзя.
Ответ — та же пара полей, что у GET.
GET /api/v1/sensors/{mac}/calibration
Авторизация не требуется.
{ "empty_mm": 1200, "full_mm": 200 }
Границ ещё нет — оба поля null. Кривой MAC — HTTP 404 sensor_not_found.
PUT /api/v1/sensors/{mac}/calibration
Заголовок X-Api-Key обязателен.
{ "empty_mm": 1200, "full_mm": 200 }
Оба значения — целые миллиметры от 0 до 65535 и не равны друг другу. Иначе HTTP 400 invalid_calibration. Кривой MAC — HTTP 400 invalid_mac.
empty_mm — показание 0%, full_mm — показание 100%. Ответ повторяет записанные границы.
GET /api/v1/buttons
Авторизация не требуется.
Только идентификатор и подпись. URL и остальные поля кнопки не отдаются.
[
{ "id": "example-1", "label": "Пример" }
]
GET /api/v1/buttons/{id}
Заголовок X-Api-Key обязателен.
Полная карточка кнопки: подпись, иконка, действие, тексты ответа, удержание и цвет. Неизвестный id — HTTP 404 button_not_found.
{
"id": "example-1",
"label": "Пример",
"iconPath": "cleaner1.png",
"action": {
"type": "http_get",
"url": "http://localhost/btn?bid=01",
"headers": {},
"body": ""
},
"feedback": {
"successText": "Отправлено",
"errorText": "Ошибка",
"pendingText": "...",
"fadeMs": 5000
},
"trigger": { "mode": "hold", "holdMs": 800 },
"color": "#7b007b"
}
POST /api/v1/buttons
Заголовок X-Api-Key обязателен.
Создаёт кнопку. Идентификатор назначается сам. Поля те же, что при правке, плюс плоские имена действия: actionType (http_get или http_post), url, headers, body, timeoutMs (1000…600000), successText, errorText, pendingText, fadeMs, triggerMode (click или hold), holdMs, color, iconPath, latchReset, responseCheck. Некорректное тело — HTTP 400 invalid_button и поле message с причиной. Ответ HTTP 201 — созданная карточка.
{
"label": "Пример",
"actionType": "http_get",
"url": "http://localhost/btn?bid=01",
"triggerMode": "hold",
"holdMs": 800,
"color": "#7b007b"
}
PUT /api/v1/buttons/{id}
Заголовок X-Api-Key обязателен.
Меняет только переданные поля. Имена полей те же, что у создания. Неизвестный id — HTTP 404 button_not_found. Некорректное поле — HTTP 400 invalid_button. Ответ — карточка после записи. Экран подхватывает конфиг сам.
DELETE /api/v1/buttons/{id}
Заголовок X-Api-Key обязателен.
Удаляет кнопку. Неизвестный id — HTTP 404 button_not_found.
{ "ok": true }
POST /api/v1/buttons/reorder
Заголовок X-Api-Key обязателен.
Порядок кнопок на экране. В order — идентификаторы спереди назад. Пропущенные остаются в конце в прежнем порядке. order не массив строк — HTTP 400 invalid_order.
{ "order": ["example-1", "cbd6791cdcb74a58861554b30239c65e"] }
Ответ:
{ "ok": true, "order": ["example-1", "cbd6791cdcb74a58861554b30239c65e"] }
GET /api/v1/background
Авторизация не требуется.
{
"type": "gradient",
"color1": "#00007b",
"color2": "#7b007b",
"animated": true,
"imagePath": ""
}
type: gradient, solid или image.
PUT /api/v1/background
Заголовок X-Api-Key обязателен.
Меняет только переданные поля. Цвет — #rrggbb. animated — логическое. Иначе HTTP 400 invalid_background. Ответ — фон после записи.
{
"type": "gradient",
"color1": "#00007b",
"color2": "#7b007b",
"animated": true
}
POST /api/v1/buttons/{id}/press
Заголовок X-Api-Key обязателен.
То же действие, что нажатие на экране, включая защёлку. Тело не нужно.
Ответ HTTP 202 значит, что команда принята экраном, а не что внешний HTTP-запрос кнопки уже завершился:
{ "ok": true, "id": "example-1" }
Неизвестный id — HTTP 404 button_not_found. Повторная команда, пока экран не забрал предыдущую, заменяет её.
POST /api/v1/system/reboot
Заголовок X-Api-Key обязателен.
Перезагрузка устройства тем же путём, что кнопка в конфигураторе. Ответ уходит до того, как машина погаснет.
{ "ok": true }