Перейти к содержанию

API-рецепты (без UI)

Полный набор curl-команд для настройки платы через REST API. Актуально для ESP-01S (API-only сборка, web UI отсутствует), а также для headless-управления любой платой (мобильное приложение, скрипты).

Полный справочник эндпоинтов — ctrl-board/docs/API.md. Здесь — практические сценарии end-to-end.

0. Установить токен

Везде ниже подразумевается переменная $TOK с Bearer-токеном:

TOK=$(curl -s -X POST http://<ip>/api/v1/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"username":"admin","password":"1234"}' \
  | python3 -c 'import sys,json; print(json.load(sys.stdin)["access_token"])')
echo "$TOK"

Токен живёт 1 час (remember=false) или 30 дней ("remember":true).

1. UUID платы

UUID — уникальный идентификатор платы, генерируется из MAC + случайной части на первом boot. Используется для:

  • регистрации в облачном проекте (X-Device-Uuid header);
  • mesh-маршрутизации (from_uuid / to в UDP-событиях);
  • cloud-service идентификации.
curl -s -H "Authorization: Bearer $TOK" http://<ip>/api/v1/system/info
# → {"fw_version":"0.4.64-esp01s","build_ts":...,"uuid":"8caab5045bc0..."}

UUID в device.json на самой плате (/config/device.json).

2. Wi-Fi провижионинг (AP-mode)

После первой прошивки или factory reset плата поднимает AP CtrlBoard-Setup-<суффикс>. Подключиться к этому AP и провизионить через API. В AP-режиме POST /api/v1/settings/wifi bypass'ит auth — пароль не нужен:

# IP платы в AP-mode фиксированный = 192.168.4.1
curl -X POST http://192.168.4.1/api/v1/settings/wifi \
  -H 'Content-Type: application/json' \
  -d '{
    "wifi_networks": [
      {"ssid":"YourSSID","password":"YourPass","retries":3,"timeout_sec":8}
    ]
  }'
# плата перезагрузится и подключится в STA-режиме

IP в STA-режиме найди в роутере, через mDNS (ctrl-<suffix>.local), или сканированием подсети.

3. Сменить пароль admin

Дефолт admin/1234 — пригоден только для первого входа. Меняй сразу:

# get admin user id (обычно 1)
UID=$(curl -s -H "Authorization: Bearer $TOK" http://<ip>/api/v1/users \
  | python3 -c 'import sys,json;u=json.load(sys.stdin)["users"];print(next(x["id"] for x in u if x["username"]=="admin"))')

curl -X PUT http://<ip>/api/v1/users/$UID \
  -H "Authorization: Bearer $TOK" \
  -H 'Content-Type: application/json' \
  -d '{"password":"<новый_пароль>"}'
# → {"status":"ok"}

После смены — текущий токен останется валидным до истечения TTL, новые логины — с новым паролем.

4. Привязать к облаку (cloud-service)

В облачном кабинете создай проект, получи project_api_key. Привяжи плату:

curl -X POST http://<ip>/api/v1/cloud \
  -H "Authorization: Bearer $TOK" \
  -H 'Content-Type: application/json' \
  -d '{
    "enabled": true,
    "url": "http://cloud.kavlev.ru:8081",
    "api_key": "<project_api_key>",
    "interval_sec": 30,
    "mqtt_enabled": true
  }'

# проверить статус через ~10 секунд
curl -s -H "Authorization: Bearer $TOK" http://<ip>/api/v1/cloud/status
# → {"enabled":true,"last_ok":true,"total_ok":1,"total_fail":0,...}

Плата сама зарегистрируется в проекте на cloud-стороне (через HMAC-подписанный heartbeat).

5. Создать устройство (реле)

ESP-01S имеет 2 user-GPIO (0 и 2). Реалистичный сценарий — реле на GPIO2 (там встроенный LED, active-LOW):

curl -X POST http://<ip>/api/v1/devices \
  -H "Authorization: Bearer $TOK" \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Реле LED",
    "type": "relay",
    "pin": 2,
    "inverted": true
  }'
# → {"status":"created","id":1}

Включить/выключить:

# turn ON (с inverted=true → pin LOW → LED горит)
curl -X POST http://<ip>/api/v1/devices/1/state \
  -H "Authorization: Bearer $TOK" \
  -H 'Content-Type: application/json' -d '{"state":true}'

# текущее состояние
curl -s -H "Authorization: Bearer $TOK" http://<ip>/api/v1/devices/1

6. Создать задачу (мигалка интервалом)

Простейший сценарий — каждые N секунд переключать реле:

curl -X POST http://<ip>/api/v1/tasks \
  -H "Authorization: Bearer $TOK" \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Мигай LED",
    "active": true,
    "triggers": [{"type":"interval","interval_sec":60}],
    "actions": [{"type":"relay","device_id":1,"command":"toggle"}]
  }'
# → {"status":"created","id":1}

Cron (каждый день в 7:00):

'triggers':[{"type":"cron","hour":7,"minute":0,"days_mask":127}]

days_mask — битовая маска дней недели (bit0=Пн … bit6=Вс), 127 = 0b1111111 = все дни.

7. Сопряжение между платами (mesh)

Все платы в одной WiFi сети автоматически видят друг друга через UDP multicast (224.0.13.31:13031, подпись HMAC-SHA256 с общим network_secret).

Список соседей:

curl -s -H "Authorization: Bearer $TOK" http://<ip>/api/v1/peers
# → {"self":{"uuid":"...","name":"..."}, "neighbors":[...]}

Получить/установить общий network_secret (должен совпадать на всех платах одной mesh-группы):

curl -s -H "Authorization: Bearer $TOK" http://<ip>/api/v1/settings/network_secret
# → {"network_secret":"<hex32>"}

# на другой плате — установить тот же:
curl -X POST http://<other-ip>/api/v1/settings/network_secret \
  -H "Authorization: Bearer $OTHER_TOK" \
  -H 'Content-Type: application/json' \
  -d '{"network_secret":"<hex32>"}'

После смены network_secret плата перезагружается; mesh-сообщения с другим ключом будут отбракованы (bad sig).

Отправить mesh-событие из задачи (board → board)

Например: на плате A триггер по кнопке шлёт event соседям, на плате B триггер udp_event ловит его и переключает реле.

Плата A (с кнопкой) — task:

curl -X POST http://<ipA>/api/v1/tasks \
  -H "Authorization: Bearer $TOK_A" \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Кнопка → broadcast",
    "active": true,
    "triggers": [{"type":"device_state","device_id":2,"compare":"equals","target_bool":true}],
    "actions": [{"type":"udp_send","target_uuid":"*","event":"button_press"}]
  }'

Плата B (с реле) — task:

curl -X POST http://<ipB>/api/v1/tasks \
  -H "Authorization: Bearer $TOK_B" \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "По UDP toggle реле",
    "active": true,
    "triggers": [{"type":"udp_event","from_uuid":"<UUID_A>","event":"button_press"}],
    "actions": [{"type":"relay","device_id":1,"command":"toggle"}]
  }'

Wildcard event

"event":"*" ловит любое событие от указанного UUID (включая служебные mesh-сообщения). Используй конкретное имя события чтобы избежать ложных срабатываний (см. CB-124, исправлено в v0.4.62).

8. Бэкап и восстановление конфигов

Скачать снимок всех /config/*.json одним JSON-файлом и восстановить на другой плате (или той же после factory reset). Подробности — см. «Бэкап» в UI-документации.

Не на всех платах

GET/POST /api/v1/backup доступны только на ESP32 и ESP-01S. На NodeMCU возвращают 404 (фича отключена через -D BACKUP_DISABLED=1 для экономии ~2.7 KB heap, CB-141). Если донор-плата — NodeMCU, экспортируй через CRUD API (GET /devices, /tasks и т.п.) и собери JSON вручную.

Скачать backup

curl -s -H "Authorization: Bearer $TOK" http://<ip>/api/v1/backup \
  > backup-$(date +%F).json

# проверить структуру
python3 -c "import json,sys; d=json.load(sys.stdin); print(list(d.keys()))" < backup-*.json
# → ['metadata', 'device_config', 'settings', 'auth_settings', 'users',
#    'cloud', 'devices', 'tasks', 'sensors_enabled', ...]

В backup НЕ включены:

  • secrets.jsontoken_secret и password_salt генерируются per-board.
  • users[].password_hash — соль отличается на новой плате → пароль не сработает.
  • cloud.api_key — security (потенциальный leak backup-файла).

Восстановить на другой плате

curl -X POST -H "Authorization: Bearer $TOK_NEW" \
  -F "backup=@backup-2026-05-21.json" \
  http://<new-ip>/api/v1/backup
# → {"status":"applied","reboot_in_ms":2000}
# плата перезагрузится автоматически

После reboot'a:

  1. Логин — admin/1234 (старый password_hash не сохранён).
  2. Cloud — нужно заново вызвать POST /api/v1/cloud с api_key (был замаскирован при export).
  3. Всё остальное (devices, tasks, network_secret, settings) — восстановлено.

9. Прочее

Полный сброс к заводским

curl -X POST -H "Authorization: Bearer $TOK" http://<ip>/api/v1/factory-reset
# плата перезагружается в AP-режиме, admin/1234, все конфиги стёрты

Перезагрузка без сброса

curl -X POST -H "Authorization: Bearer $TOK" http://<ip>/api/v1/system/reboot

Сменить SSID без потери настроек

Создать backup → factory-reset → восстановить backup с обновлённым settings.wifi_networks:

# 1. backup
curl -s -H "Authorization: Bearer $TOK" http://<ip>/api/v1/backup > b.json

# 2. отредактировать b.json локально:
#    "settings": {"wifi_networks":[{"ssid":"NewSSID","password":"NewPass",...}]}
$EDITOR b.json

# 3. восстановить
curl -X POST -H "Authorization: Bearer $TOK" -F "backup=@b.json" \
  http://<ip>/api/v1/backup

Подсказки

  • Authorization: Bearer <token> обязателен везде кроме /api/v1/auth/login, /api/v1/auth/config и POST /api/v1/settings/wifi в AP-mode.
  • Content-Type: application/json для всех POST/PUT с JSON-body.
  • При auth_settings.require_auth = false (домашняя LAN) — токен не нужен вообще.
  • Все timestamps — Unix epoch (uint32).