-
-
Notifications
You must be signed in to change notification settings - Fork 2
uk Architecture
- Огляд
- Архітектура високого рівня
- Послідовність завантаження
- Система модулів
- EventBus
- Module Bus
- Система інтентів
- Реєстр пристроїв
- Рівень API
- Хмарна синхронізація
- Конфігурація
- Інтернаціоналізація
- Агент цілісності
- Розгортання
- Послідовність завершення роботи
- Додаткові матеріали
SelenaCore — це локальний хаб розумного дому, побудований на FastAPI, розроблений для роботи на маломіцному обладнанні, такому як Raspberry Pi. Вся логіка автоматизації, управління пристроями та обробка голосу виконуються на локальній машині. Хмарне з'єднання є необов'язковим і обмежується синхронізацією heartbeat та прийомом віддалених команд.
Основний технологічний стек:
| Компонент | Технологія |
|---|---|
| Веб-фреймворк | FastAPI (порт 80) |
| База даних | SQLite через SQLAlchemy 2.0 async |
| Асинхронний драйвер | aiosqlite |
| Цикл подій | Один цикл asyncio |
| Точка входу |
core/main.py (FastAPI lifespan) |
| Мова | Python 3.11 |
+------------------------------------------------------------------+
| SelenaCore Process |
| port 80 (FastAPI) |
| |
| +------------------+ +------------------+ +--------------+ |
| | 21 SYSTEM | | EventBus | | Device | |
| | modules |<->| (asyncio.Queue) |<->| Registry | |
| | (in-process) | | | | (SQLite) | |
| +------------------+ +--------+---------+ +--------------+ |
| | |
| +--------+---------+ |
| | Module Bus | |
| | (WebSocket) | |
| +--------+---------+ |
| | |
+----------------------------------+-------------------------------+
|
+--------------+--------------+
| | |
+----+----+ +----+----+ +------+------+
| Docker | | Docker | | Docker |
| Module | | Module | | Module |
| (user) | | (user) | | (user) |
+---------+ +---------+ +-------------+
Окремий процес:
+----------------------------+
| Integrity Agent |
| SHA256 hash check / 30s |
| Safe mode enforcement |
+----------------------------+
Процедура запуску визначена в обробнику lifespan FastAPI у core/main.py. Кроки виконуються у строгому порядку:
1. _setup_logging()
| Читання logging.yaml або перехід на базову конфігурацію
v
2. Create SQLAlchemy async engine + tables
| Ініціалізація бази даних SQLite
v
3. Inject session factory into sandbox
| Системні модулі отримують доступ до бази даних
v
4. EventBus.start()
| Споживач asyncio.Queue починає роботу
v
5. Publish core.startup event
| Слухачі повідомлені
v
6. CloudSync.start()
| Цикл heartbeat починається (необов'язково)
v
7. Scan system_modules/ -> load in-process -> mount routers
| 21 вбудовані модулі активовано
v
8. Scan modules/ -> start user modules
| Docker-контейнери запущено, bus-з'єднання прийнято
v
9. "SelenaCore ready on port 80"
SelenaCore підтримує два різних типи модулів, які використовують спільний EventBus, але принципово відрізняються способом виконання.
| Властивість | Значення |
|---|---|
| Кількість | 21 вбудованих |
| Базовий клас |
SystemModule (core/module_loader/system_module.py) |
| Виконання | In-process через Python importlib
|
| Ізоляція | Відсутня (спільний процес) |
| Витрати RAM | ~0 МБ (без контейнера) |
| Доступ до EventBus | Прямі async-колбеки (DirectSubscription) |
| Доступ до БД | Пряма сесія SQLAlchemy |
| API | Необов'язковий FastAPI роутер на /api/ui/modules/{name}/
|
| Розташування | Каталог system_modules/
|
Вбудовані системні модулі:
voice_core llm_engine ui_core
user_manager automation_engine scheduler
device_watchdog protocol_bridge notification_router
media_player presence_detection hw_monitor
backup_manager remote_access network_scanner
device_control energy_monitor update_manager
notify_push secrets_vault weather_service
| Властивість | Значення |
|---|---|
| Базовий клас |
SmartHomeModule (sdk/base_module.py) |
| Виконання | Окремі Docker-контейнери |
| Комунікація | WebSocket Module Bus |
| Bus endpoint | ws://core/api/v1/bus?token=TOKEN |
| Окремі порти | Немає — весь трафік через єдиний bus |
Типи користувацьких модулів:
| Тип | Призначення |
|---|---|
| UI | Панелі користувацького інтерфейсу |
| INTEGRATION | Конектори до сторонніх сервісів |
| DRIVER | Драйвери пристроїв та протоколів |
| AUTOMATION | Логіка користувацької автоматизації |
| IMPORT_SOURCE | Імпортери зовнішніх даних |
[Discovered]
|
v
[Installed] --module.installed-->
|
v
[Started] --module.started---> (підписка EventBus активна)
|
v
[Running] <-- нормальна робота -->
|
v
[Stopped] --module.stopped--->
|
v
[Removed] --module.removed--->
Джерело: core/eventbus/bus.py
EventBus — це центральна нервова система SelenaCore. Це система публікації/підписки на основі asyncio.Queue з максимальним розміром черги 10 000 повідомлень та політикою видалення найстаріших при переповненні.
Publisher
|
v
+---+-----------+
| EventBus |
| (Queue: 10K) |
+---+-------+---+
| |
v v
Direct Module Bus
Subscr. WebSocket
(system) (user modules)
- DirectSubscription — in-process async-колбеки, які використовуються системними модулями. Нульова вартість серіалізації, доставка за мікросекунди.
- Module Bus WebSocket — події серіалізуються в JSON і доставляються через WebSocket-з'єднання до користувацьких модулів, які працюють у Docker-контейнерах.
Усі типи подій визначені у core/eventbus/types.py:
| Простір імен | Події |
|---|---|
core.* |
startup, shutdown, integrity_violation, safe_mode_entered, safe_mode_exited |
device.* |
state_changed, registered, removed, offline, online, discovered |
module.* |
installed, started, stopped, error, removed |
sync.* |
command_received, command_ack, connection_lost, connection_restored |
voice.* |
wake_word, recognized, intent, response, privacy_on, privacy_off |
Правило захисту: Події у просторі імен core.* можуть публікуватися лише основним процесом. Модулі не можуть створювати події core.
Джерело: core/module_bus.py
Module Bus — це комунікаційний рівень, натхненний CAN-bus, який мультиплексує весь трафік користувацьких модулів через єдиний WebSocket endpoint.
- Core є головним вузлом. Модулі підключаються ДО core, ніколи навпаки.
-
Єдиний endpoint:
/api/v1/bus— без окремих портів для модулів. - Подвійні черги повідомлень на кожне з'єднання для розділення критичного та некритичного трафіку.
| Повідомлення | Напрямок | Призначення |
|---|---|---|
announce |
module -> core | Модуль реєструється при підключенні |
re_announce |
module -> core | Модуль перереєструється після перепідключення |
announce_ack |
core -> module | Реєстрацію підтверджено |
intent |
core -> module | Інтент маршрутизовано до обробника |
intent_response |
module -> core | Обробник повертає результат |
event |
двонаправлений | Пересилання подій EventBus |
ping / pong
|
двонаправлений | Keepalive |
api_request |
module -> core | Модуль викликає API core |
api_response |
core -> module | Core повертає результат API |
shutdown |
core -> module | Сигнал коректного завершення |
Кожне WebSocket-з'єднання підтримує дві незалежні черги:
Module Connection
+---------------------------------------+
| |
| Critical Queue (backpressure) |
| - Max size: 100 |
| - Used for: intent, api_request, |
| api_response, intent_response |
| - Blocks sender when full |
| |
| Event Queue (drop-oldest) |
| - Max size: 1000 |
| - Used for: event messages |
| - Drops oldest when full |
| |
+---------------------------------------+
Така архітектура гарантує, що потік некритичних подій ніколи не блокує обробку інтентів або API-викликів.
Якщо модуль не відповідає протягом 30 секунд, bus активує circuit breaker для цього модуля. Модуль тимчасово виключається з маршрутизації інтентів до відновлення.
Кожен тип модуля має попередньо визначений набір дозволених типів повідомлень та підписок на події. Bus перевіряє ці дозволи для кожного повідомлення.
Джерело: core/api/sync_manager.py, core/api/routes/ui.py
Синхронізація стану UI (тема, мова, розташування віджетів) у реальному часі між усіма підключеними клієнтами через WebSocket /api/ui/sync.
| Властивість | Значення |
|---|---|
| Ендпоінт | ws://host/api/ui/sync?v=<version> |
| Протокол | JSON-повідомлення з монотонним версіонуванням |
| Стан | Налаштування (тема, мова) + розташування віджетів |
| При підключенні | Повний знімок (hello) або дельта-повтор (replay) |
| Health check | Серверний ping кожні 5с, клієнт pong протягом 15с |
| Бекенд |
SyncManager синглтон з deque(256) логом подій |
| Фронтенд | Zustand store connectSyncStream() з exponential backoff |
| Безпека кіоску |
useConnectionHealth хук — примусове перезавантаження після 60с мовчання |
SPA (React) та всі API-ендпоінти обслуговуються одним процесом на порту 80. HTTPS на порту 443 обслуговується легким TLS-проксі (~5 МБ RAM).
Дивіться Архітектура синхронізації UI для повного опису протоколу та нотаток міграції.
Джерело: system_modules/llm_engine/intent_router.py
Маршрутизатор інтентів використовує 5-рівневий каскад. Кожен рівень перевіряється по порядку; перший збіг виграє. Уся pipeline працює англійською внутрішньо — починаючи з v0.4 переклад виконується Argos Translate на краях пайплайну (після Vosk STT, перед Piper TTS), а не LLM. Українських / російських / німецьких FastMatcher-патернів немає за дизайном.
Голосова команда (будь-якою мовою)
│
▼
┌──────────────────────────────────────────────────────────────┐
│ Tier 1 FastMatcher (regex з БД, тільки English) ~0 мс │
│ Tier 2 Module Bus (модулі користувача, WS) ~мс │
│ Cache IntentCache (SQLite, попередні LLM hits) ~10 мс │
│ Tier 3 Local LLM (Ollama, один виклик) 300-800 │
│ Tier 4 Cloud LLM (OpenAI-сумісний, опціонально) 1-3 сек │
│ Fallback "не зрозумів" (i18n) │
└──────────────────────────────────────────────────────────────┘
│
▼ EventBus: voice.intent { intent, params, source }
Модуль-власник інтенту виконує
│
▼
Відповідь (LLM rephrase для варіативності) → TTS
Деталі рівнів:
| Рівень | Джерело | Затримка | Механізм | Примітки |
|---|---|---|---|---|
| 1 | FastMatcher (IntentCompiler) |
~0 мс | Regex з БД з пріоритетом + specificity-сортуванням + verb-bucket pre-filter | Тільки англійська |
| 2 | Module Bus | ~мс | WebSocket запит до user-installed модулів | Per-module circuit breaker |
| Cache |
IntentCache (SQLite) |
~10 мс | Lookup за (text, lang) ключем для попередніх LLM hits |
Усі мови |
| 3 | Local LLM (Ollama) | 300-800 мс | Один виклик класифікації з динамічним registry-aware промптом | Потребує ~3-5 ГБ RAM |
| 4 | Cloud LLM | 1-3 сек | OpenAI / Anthropic / Groq класифікація | Опційно |
| — | Fallback | ~0 мс | i18n повідомлення "не зрозумів" | — |
Жорсткі інтенти приходять з модулів, не зі seed-скриптів. Кожен системний модуль декларує свої OWNED_INTENTS і _OWNED_INTENT_META та inserts/claims рядки в intent_definitions на start() через _claim_intent_ownership(). Центрального seed-файлу немає.
Composite-патерни пристроїв масштабуються O(1) у DB рядках. PatternGenerator.rebuild_composite_device_patterns() створює максимум 5 рядків на весь реєстр пристроїв — по одному на дієслово (device.on, device.off, device.set_temperature, device.lock, device.unlock) — кожен з (?P<name>...) alternation усіх відомих імен пристроїв. Захоплене ім'я резолвиться у device_id через in-memory індекс за O(1).
Verb-bucket pre-filter скорочує типову довжину FastMatcher scan з O(всі-патерни) до ~3-15 кандидатів. _VERB_BUCKETS мапа маршрутизує перше слово вводу (turn, set, play, what, lock, …) до малого набору кандидатних інтентів.
Динамічний LLM-промпт з registry context. Tier 3 промпт перебудовується при кожному device CRUD і містить: зареєстровані інтенти (з описами), підключені модулі з їх інтентами, пристрої згруповані за meta.location_en, і список відомих індор-кімнат. Дві константи cap'лять розмір: _DEVICES_PER_ROOM_LIMIT=10 і _ROOMS_LIMIT=30. Це те, що дозволяє LLM розрізнити "what is the temperature in the living room" (→ device.query_temperature) і "what is the temperature outside" (→ weather.temperature) без жодного хардкодного мапу.
IntentCache промоція. Гарячі фрази, які hit'нули кеш >=5 разів, промотуються у FastMatcher-патерни раз на годину з core/main.py lifespan. Promoted рядки використовують source='auto_learned' відокремлений namespace від auto_entity. Тільки англійською за дизайном.
LLM Rephrase відповідей: Після виконання голосової команди модулем voice-core відправляє структурований action context до rephrase LLM (temperature=0.9). Це дає природні TTS-відповіді замість шаблонних рядків. Сесія діалогу (останні 20 повідомлень, таймаут 5 хв) забезпечує контекст для зв'язного спілкування.
Повні деталі імплементації — pattern specificity scoring, composite resolver, дисамбігуація ambiguous імен, структура промпту, межі масштабування — у intent-routing.md.
Джерело: core/registry/
Реєстр пристроїв — це постійне сховище для всіх відомих пристроїв, їхнього поточного стану та історичних даних.
Таблиця Device:
| Стовпець | Тип | Опис |
|---|---|---|
| device_id | UUID | Первинний ключ, автогенерований |
| name | String | Зручна для людини назва пристрою |
| type | String | Категорія пристрою (light, sensor тощо) |
| protocol | String | Протокол зв'язку (zigbee, mqtt...) |
| state | JSON | Поточний стан пристрою |
| capabilities | JSON | Підтримувані функції та діапазони значень |
| last_seen | DateTime | Часова мітка останнього зв'язку |
| module_id | String | Ідентифікатор модуля-власника |
| meta | JSON | Довільні метадані |
Таблиця StateHistory:
- Зберігає останні 1 000 змін стану для кожного пристрою.
- Кожен запис містить попередній стан, новий стан та часову мітку.
- Старіші записи видаляються автоматично.
Таблиця AuditLog:
- Зберігає до 10 000 записів з автоматичною ротацією.
- Логує адміністративні дії: реєстрацію пристроїв, видалення, зміни конфігурації.
Запити проходять через middleware у такому порядку:
Incoming request
|
v
RequestIdMiddleware -- Присвоює унікальний заголовок X-Request-ID
|
v
RateLimitMiddleware -- 120 запитів за 60 секунд
|
v
CORSMiddleware -- Політика крос-доменних запитів
|
v
Route handler
- Аутентифікація за допомогою Bearer token для доступу модулів та зовнішнього API.
- Токени зберігаються у
/secure/module_tokens/. - Маршрути UI (
/api/ui/*) не потребують аутентифікації, але доступні лише з localhost.
Core API (/api/v1/*) — з аутентифікацією:
| Маршрут | Призначення |
|---|---|
/system |
Інформація про систему, стан здоров'я |
/devices |
CRUD пристроїв та запити стану |
/events |
Інспекція та публікація подій EventBus |
/integrity |
Статус та звіти перевірки цілісності |
/modules |
Управління життєвим циклом модулів |
/secrets |
Доступ до сховища секретів |
/intents |
Маршрутизація та тестування інтентів |
/bus |
WebSocket endpoint Module Bus |
UI API (/api/ui/*) — лише localhost, без аутентифікації:
| Маршрут | Призначення |
|---|---|
/ui |
Обслуговування панелі UI |
/setup |
Майстер початкового налаштування |
/voice_engines |
Конфігурація голосових рушіїв |
Доступна за адресою /docs лише коли DEBUG=true у змінних середовища.
Джерело: core/cloud_sync/sync.py
Хмарне з'єднання є необов'язковим і спроєктоване як мінімальне. Core ніколи не залежить від доступності хмари для локальної роботи.
| Параметр | Значення |
|---|---|
| Віддалений сервер | selenehome.tech |
| Інтервал heartbeat | 60 секунд |
| Підпис запитів | HMAC-SHA256 |
| Тайм-аут опитування команд | 55 секунд (long-poll) |
| Відступ (початковий) | 5 секунд |
| Відступ (максимальний) | 300 секунд |
| Стратегія відступу | Експоненційна |
SelenaCore selenehome.tech
| |
|--- heartbeat (HMAC-SHA256) --------->|
|<-- 200 OK ---------------------------|
| |
|--- long-poll /commands ------------->|
| (55s timeout) |
|<-- command payload ------------------|
| |
|--- command ack --------------------->|
| |
При збої мережі клієнт синхронізації відступає експоненційно від 5 до 300 секунд перед повторною спробою.
SelenaCore використовує модель конфігурації з двох джерел.
Керуються через Pydantic BaseSettings у core/config.py за допомогою класу CoreSettings. Усі поля типізовані та валідуються при запуску.
Основні налаштування:
| Змінна | Значення за замовчуванням | Опис |
|---|---|---|
CORE_PORT |
80 | Порт прослуховування FastAPI |
CORE_DATA_DIR |
/var/lib/selena | Каталог постійних даних |
CORE_SECURE_DIR |
/secure | Сховище токенів та секретів |
DEBUG |
false | Увімкнення режиму налагодження та /docs |
Використовується для структурованої конфігурації, яка погано вписується у плоскі змінні середовища (налаштування модулів, пресети логування, правила автоматизації).
Пріоритет: Змінні середовища перевизначають значення YAML, де обидва джерела визначають однакове налаштування.
Фронтенд: src/i18n/locales/{en,uk}.ts через i18next + react-i18next.
Голосові відповіді: Генеруються LLM в реальному часі через _generate_via_llm() у VoiceCoreModule. Voice handler'и повертають структуровані dict'и з контекстом дії; LLM генерує природну відповідь мовою TTS. Без попередньо написаних перекладів чи кешування — кожна відповідь генерується заново.
HTML-віджети: Вбудовані словники var L = {en:{…}, uk:{…}} з атрибутами data-i18n.
Джерело: agent/
Агент цілісності працює як окремий процес поряд із core. Це сторожовий модуль, який забезпечує, що кодова база core не була змінена.
every 30 seconds:
|
v
Compute SHA256 hashes of core files
|
v
Compare against known-good manifest
|
+-- match -----> OK, sleep 30s
|
+-- mismatch --> VIOLATION DETECTED
|
v
Stop all modules
|
v
Notify (core.integrity_violation event)
|
v
Attempt rollback
|
v
Enter SAFE MODE
|
v
Publish core.safe_mode_entered
У безпечному режимі залишаються активними лише основні функції core. Усі користувацькі модулі зупиняються і не можуть бути перезапущені, доки проблему цілісності не буде вирішено.
docker-compose.yml
+--------------------------------------------------+
| |
| +------------------+ +-------------------+ |
| | core | | agent | |
| | Dockerfile.core | | Integrity Agent | |
| | Host networking | | Separate process | |
| | Privileged mode | | | |
| +------------------+ +-------------------+ |
| | | |
| v v |
| +-------------+ +------------------+ |
| | selena_data | | selena_secure | |
| | (volume) | | (volume) | |
| +-------------+ +------------------+ |
| |
+--------------------------------------------------+
| Властивість | Значення |
|---|---|
| Базовий образ | python:3.11-slim |
| Режим мережі | host |
| Привілеї | privileged (доступ до обладнання) |
| Системні пакети | ffmpeg, portaudio, VLC, ALSA libs, PulseAudio |
Мережа host та привілейований режим необхідні для:
- Прямого доступу до аудіообладнання (мікрофон, динаміки) для обробки голосу.
- Доступу до USB-пристроїв та GPIO-пінів для мостів протоколів (Zigbee, Z-Wave dongles).
- Multicast/broadcast для протоколів виявлення пристроїв.
| Том | Призначення |
|---|---|
| selena_data | База даних, дані модулів, логи, резервні копії |
| selena_secure | Токени, секрети, сертифікати |
Коректне завершення роботи дзеркально відображає послідовність завантаження у зворотному порядку, гарантуючи відсутність втрати даних:
1. CloudSync.stop()
| Зупинка heartbeat та опитування команд
v
2. Publish core.shutdown event
| Усі слухачі повідомлені
v
3. Module Bus shutdown_all(drain_ms=5000)
| Надсилання shutdown усім користувацьким модулям
| Очікування до 5 секунд для дренажу черг
v
4. Shutdown in-process system modules
| Виклик stop() кожного системного модуля
v
5. EventBus.stop()
| Споживач черги зупинено
v
6. Database engine dispose
| Усі з'єднання закриті, WAL checkpoint
v
Process exit
5-секундне вікно дренажу для Module Bus гарантує, що користувацькі модулі мають час зберегти свій стан та підтвердити завершення роботи до того, як їхні WebSocket-з'єднання будуть розірвані.
| Тема | Документ |
|---|---|
| Аутентифікація користувачів та QR-процес | user-manager-auth.md |
| Протокол модулів (токени, HMAC, webhooks) | module-core-protocol.md |
| Дротовий протокол Module Bus | module-bus-protocol.md |
| Розробка модулів (SDK, маніфест) | module-development.md |
| Розробка віджетів (widget.html, i18n) | widget-development.md |
| Довідник конфігурації | configuration.md |
| Розгортання та systemd | deployment.md |
🤖 This wiki is auto-synced from docs/ in the main repo. Hand-edits on the wiki UI get overwritten on the next push. Open a PR against the main repo instead.
MIT License · Sponsor · Ko-fi
SelenaCore
🇬🇧 English
Getting started
Architecture
Voice & translation
Hardware integration
Development
- Modules overview
- Module development
- System module development
- Module API guide
- Module bus protocol
- Widget development
- User manager / auth
Reference
🇺🇦 Українська
Початок
Архітектура
Голос і переклад
Інтеграція заліза
Розробка
- Розробка модулів
- Розробка системних модулів
- Module API
- Module bus
- Widget development
- User manager / auth
Довідник