Files
ignis-core/README.md
2026-05-16 11:22:02 +07:00

6.1 KiB

Ignis Core

Локальный FastAPI-сервер для управления лампами WiZ.

Что есть

  • discovery устройств в локальной сети
  • группы устройств
  • команды для device/group
  • one-shot и cron расписания
  • guest/admin/master API-ключи
  • event log и базовая статистика
  • встроенный UI в static/index.html
  • встроенный UI без внешних CDN

Запуск

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
uvicorn main:app --host 0.0.0.0 --port 8000

UI: http://<host>:8000/

Готовые deployment-файлы для systemd: deploy/README.md

Конфигурация

Минимум:

IGNIS_API_KEY=change-me
APP_TIMEZONE=Asia/Novosibirsk
SCAN_NETWORK=
DISCOVERY_INTERVAL_SECONDS=600
DISCOVERY_BACKGROUND_MISSING_THRESHOLD=2
LOG_LEVEL=INFO
EVENT_LOG_RETENTION_DAYS=30

БД:

IGNIS_DATABASE_URL=sqlite+aiosqlite:///./ignis.db
IGNIS_SYNC_DATABASE_URL=sqlite:///./ignis.db

Замечание по discovery:

  • если SCAN_NETWORK не задан, сервер сам выбирает private IPv4-подсети обычных интерфейсов и старается не сканировать VPN / docker / tunnel-интерфейсы
  • если на хосте есть VPN или несколько интерфейсов, всё равно лучше явно задать SCAN_NETWORK
  • формат: 192.168.0.0/24 или список через запятую
  • startup scan выполняется до старта фонового цикла
  • background refresh по умолчанию удаляет устройство только после двух подряд промахов discovery
  • manual POST /devices/rescan удаляет оффлайн-устройства сразу и возвращает summary (found, added, updated, removed_offline, pending_removal, online)

Авторизация

Заголовок: X-API-Key

Роли:

  • master: значение из IGNIS_API_KEY, полный доступ
  • admin: ключ из БД, доступ к группам, расписаниям, stats и rescan
  • guest: обычное управление и чтение

Сервер работает в fail-closed: если IGNIS_API_KEY не задан, защищённые маршруты недоступны.

Встроенный UI:

  • использует только локальные статические ассеты
  • по умолчанию не сохраняет API-ключ между перезагрузками
  • может запомнить ключ только в рамках текущей вкладки браузера

API

Основные маршруты:

  • GET /devices
  • GET /devices/groups
  • GET /devices/scenes
  • POST /devices/groups
  • DELETE /devices/groups/{group_id}
  • POST /devices/rescan
  • POST /control/device/{device_id}
  • POST /control/group/{group_id}
  • POST /control/device/{device_id}/blink
  • GET /control/device/{device_id}/status
  • GET /control/group/{group_id}/status
  • POST /schedules/once
  • POST /schedules/cron
  • GET /schedules/tasks
  • DELETE /schedules/{job_id}
  • GET /api-keys
  • POST /api-keys
  • POST /api-keys/revoke
  • POST /api-keys/activate
  • GET /stats/summary
  • GET /stats/log
  • GET /auth/me

control и schedules принимают JSON body.

Поддерживаемые параметры команд:

  • state
  • brightness
  • scene
  • temp
  • r, g, b

Примеры:

curl -X POST 'http://localhost:8000/control/device/dev-1' \
  -H 'X-API-Key: change-me' \
  -H 'Content-Type: application/json' \
  -d '{"temp": 4200}'
curl -X POST 'http://localhost:8000/schedules/once' \
  -H 'X-API-Key: change-me' \
  -H 'Content-Type: application/json' \
  -d '{"target_id":"bedroom","hours_from_now":2,"is_group":true,"temp":3200}'

Валидация:

  • brightness: 10..100
  • temp: 2200..6500
  • r/g/b: 0..255
  • scene, temp и rgb взаимоисключаемы
  • r, g, b нужно передавать только полной тройкой
  • для schedules/once нужно передать ровно одно из run_at или hours_from_now

API keys

  • список ключей возвращает публичный key / key_id
  • полный секрет возвращается только при создании
  • маршруты /api-keys/* доступны только master

Хранилище

Основные таблицы:

  • groups
  • api_keys
  • event_log
  • schedules
  • apscheduler_jobs

OpenAPI

Актуальная схема лежит в openapi.json.

Перегенерация:

.venv/bin/python -c 'import json, os, pathlib; os.environ.setdefault("IGNIS_API_KEY", "openapi-export"); from main import app; pathlib.Path("openapi.json").write_text(json.dumps(app.openapi(), ensure_ascii=False, indent=2) + "\n", encoding="utf-8")'

Тесты

Проверка синтаксиса:

.venv/bin/python -m compileall app tests main.py

Полный прогон:

timeout 120s .venv/bin/python -m unittest discover -s tests -v

Сейчас есть 27 тестов. Покрыты:

  • auth и роли
  • lifecycle API-ключей
  • control/status ошибки и partial success
  • валидация scene
  • one-shot и cron расписания
  • миграция legacy jobs
  • auto-subnet selection для discovery
  • background offline cleanup threshold
  • manual rescan summary и immediate cleanup
  • security headers и локальные UI-ассеты
  • агрегация stats без двойного счёта *_requested

Ограничения

  • discovery всё ещё основан на переборе IP по подсетям
  • UI остаётся монолитным файлом
  • stats пока простые и не заменяют нормальную аналитику