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-Uuidheader); - 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):
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.json—token_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:
- Логин —
admin/1234(старый password_hash не сохранён). - Cloud — нужно заново вызвать
POST /api/v1/cloudс api_key (был замаскирован при export). - Всё остальное (devices, tasks, network_secret, settings) — восстановлено.
9. Прочее¶
Полный сброс к заводским¶
curl -X POST -H "Authorization: Bearer $TOK" http://<ip>/api/v1/factory-reset
# плата перезагружается в AP-режиме, admin/1234, все конфиги стёрты
Перезагрузка без сброса¶
Сменить 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).