Files
Button/docs/rest-api.md
T
2026-11-02 16:46:20 +03:00

10 KiB
Raw Blame History

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 400 invalid_limit.
  • since — необязательный Unix timestamp, остаются точки с ts >= since. Нечисло — HTTP 400 invalid_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 }