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

Концепции

Общая картина платформы. Из чего она состоит, как куски разговаривают, где хранится состояние.

Архитектура целиком

                    ┌──────────────┐
                    │ голосовой    │
                    │ ассистент    │
                    └──────┬───────┘
                           │ OAuth2 + Smart Home API
  ┌────────────────────────────────────┐
  │   cloud-service (cloud.kavlev.ru)  │
  │   FastAPI + Postgres + MQTT-брокер │
  └─────────────┬────────────┬─────────┘
                │ HTTPS      │ MQTT (Phase Broker)
                │ heartbeat  │ commands
                ▼            ▼
   ┌─────────────────────────────────┐
   │   ctrl-board (ESP8266/ESP32)    │
   │   web-UI + REST API + LittleFS  │
   └───┬─────────────────────┬───────┘
       │ UDP multicast       │ GPIO
       │ (HMAC-SHA256)       │
       ▼                     ▼
   соседние платы      реле и датчики

Главный принцип: каждая плата — отдельная, самодостаточная единица. Облако сверху — слой обмена и удобства, а не зависимость.

Главные понятия платы

Устройство (Device)

«Физическая штука, привязанная к пину». Бывает двух больших классов:

  • Actuator — то, чем плата управляет: реле, MOSFET, симистор. Контролируется командами on/off/toggle.
  • Sensor — то, что плата читает: датчики температуры, влажности, расстояния, аналоговые/цифровые входы, кнопки.

Все устройства живут в /config/devices.json на самой плате. У каждого устройства минимум: id, name, type (плагин), pin (или pin1+pin2 для многоконтактных), плюс плагин-специфичные поля (i2c_address, onewire_address, inverted и т.д.).

Подробнее — Устройства.

Задача (Task)

«Если триггер сработал и условия выполнены — выполнить действия».

Структура задачи:

Часть Сколько Что это
Триггеры до 3, объединены ИЛИ Когда задача может сработать
Условия до 4, all/any Дополнительный фильтр перед действиями
Окно валидности 1 По времени суток (start_min..end_min) и дням недели (days_mask)
Действия до 4, последовательно Что выполнить при срабатывании

Подробнее — Задачи и сценарии.

Плагины

Всё расширяется через плагины. 4 категории:

  • Sensors — поддержка железа (DHT22, BME280, HC-SR04, ваш собственный датчик).
  • Triggers — типы триггеров (interval, cron, sunrise/sunset, device_state, udp_event, ping).
  • Conditions — типы условий (time-window, wifi-rssi, peer-online, task-state, uptime).
  • Actions — типы действий (relay, udp_send, reboot, wait).

Плагин — это одна папка с .cpp и .json. Он включается строчкой в *.enabled.json. Prebuild-скрипт сам пропишет PlatformIO build_src_filter, linker DCE выбросит лишнее из бинарника.

Подробнее — Архитектура плагинов.

Mesh

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

Что даёт mesh:

  • Триггер udp_event — реакция одной платы на событие другой («движение на улице → свет в коридоре»).
  • Действие udp_send — отправка события другим платам.
  • Условие peer_online — проверка что сосед в эфире.

Облако в этом не участвует. Mesh работает на тех же платах в одной локальной сети.

Подробнее — Сеть и mesh.

Главные понятия облака

Проект (Project)

Единица расшаривания. Один человек создаёт проект, добавляет в него платы (по project_api_key), приглашает других людей по email или invite-токену с ролями:

  • owner — всё. Удалить проект тоже может только owner.
  • admin — управление платами, командами, OTA. Не может удалить проект и менять owner'а.
  • viewer — только просмотр состояния плат, без управления.

Группа устройств (Group)

Логическая группировка плат внутри проекта для удобства фильтра на дашборде (например, «улица», «гараж», «дом»). Не влияет на ACL — это чисто UI-фишка.

Heartbeat и Command queue

Каждые ~15 секунд плата шлёт heartbeat на облако: POST /api/v1/devices/{uuid}/heartbeat с подписью HMAC-SHA256. В ответ облако возвращает pending_commands — список команд, которые накопились пока плата отсутствовала. Плата выполняет их, на следующем heartbeat'е возвращает applied_command_ids. У каждой команды есть TTL (1 час) и возможность revoke до доставки.

Это pull-модель: облако не пушит, плата сама ходит — поэтому никакого port-forwarding'а и VPN не надо. Минус — задержка управления равна heartbeat-интервалу.

Подробнее — Облако.

Где хранится состояние

Где Что
Плата → LittleFS /config/*.json Wi-Fi, устройства, задачи, пользователи, секреты, UUID, настройки сети, deep-sleep
Плата → RAM runtime task state, лог-кольцо для UI
Облако → Postgres проекты, участники, плата↔проект, команды, прошивки, heartbeat-метаданные, заметки
Облако → volume firmware_data бинарники прошивок (.bin + .littlefs.bin)

Важно: плата не зависит от облака. Если облако упало — плата продолжает работать, выполнять задачи, отдавать локальный web-UI. Просто временно нельзя дистанционно ей управлять.

Безопасность в двух словах

  • Пользователи на плате — bearer-токен из sha256(payload + token_secret), token_secret генерится на первом запуске.
  • Пароли на платеsha256(password + password_salt), password_salt тоже generated-on-first-boot.
  • MeshHMAC-SHA256(packet, network_secret), общий для всех плат в одной группе.
  • Облако ↔ платаHMAC-SHA256(request, project_api_key) на каждом heartbeat'е.
  • Пользователи в облаке — JWT (HS256), email + одноразовый код для логина.

Нет ни одного зашитого секрета в коде, всё генерируется на старте либо вводится в UI.

Дальше