1 Commits
Author SHA1 Message Date
cactoandClaude Sonnet 5 8c5ebe2967 Translate all README files to Russian
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-26 17:06:30 +05:00
6 changed files with 117 additions and 114 deletions
+61 -59
View File
@@ -1,31 +1,32 @@
# Home Automation Platform # Платформа домашней автоматизации
A microservice-based home automation platform, built as a portfolio project Pet-проект на микросервисной архитектуре для портфолио, демонстрирующий Go
demonstrating Go (concurrency, message queues, MQTT), PHP/Laravel (API, (конкурентность, очереди сообщений, MQTT), PHP/Laravel (API, авторизация)
authorization), and polyglot persistence (PostgreSQL, ClickHouse, Redis). и работу с разными БД по назначению (PostgreSQL, ClickHouse, Redis).
**This is not a "growbox project."** A growbox is the first implemented **Это не «проект гроубокса».** Гроубокс — первая реализованная **зона**
**zone** with a first set of **device types** (light, pump, fan, temperature с первым набором **типов устройств** (свет, полив, вентиляция, датчик
sensor). The core system — device management, telemetry, automation rules, температуры). Ядро системы — управление устройствами, телеметрия, правила
users, notifications — operates purely on the abstractions *zone*, *device*, автоматизации, пользователи, уведомления — оперирует исключительно
*device type*, *sensor reading*, *command*, *rule*. Nothing growbox-specific абстракциями *зона*, *устройство*, *тип устройства*, *показание датчика*,
is hardcoded in the core: adding a "living room" zone with a "smart plug" *команда*, *правило*. Ничего специфичного для гроубокса не зашито в ядре:
device type should require zero changes to service code, only new rows in добавление зоны «гостиная» с типом устройства «умная розетка» не должно
требовать изменений в коде сервисов — только новые строки в
`device_types` / `zones` / `devices`. `device_types` / `zones` / `devices`.
## Architecture ## Архитектура
``` ```
ESP32 (or emulator) ESP32 (или эмулятор)
│ MQTT │ MQTT
ingest-service (Go) ──► ClickHouse (raw telemetry) ingest-service (Go) ──► ClickHouse (сырая телеметрия)
▼ RabbitMQ ("new reading" event) ▼ RabbitMQ (событие "новое показание")
rule-engine-service (Go) ──► PostgreSQL (rules, cached) rule-engine-service (Go) ──► PostgreSQL (правила, кэшируются)
│ gRPC (on rule match) │ gRPC (при срабатывании правила)
device-control-service (Go) ──► MQTT (command) ──► device device-control-service (Go) ──► MQTT (команда) ──► устройство
Redis (device shadow: desired/reported state, status, last_seen) Redis (device shadow: desired/reported state, status, last_seen)
@@ -33,68 +34,69 @@ Redis (device shadow: desired/reported state, status, last_seen)
Laravel API (PHP) ──► PostgreSQL / ClickHouse / Redis Laravel API (PHP) ──► PostgreSQL / ClickHouse / Redis
│ gRPC / HTTP │ gRPC / HTTP
device-control-service (manual commands from the UI) device-control-service (ручные команды из UI)
``` ```
## Stack ## Стек
| Concern | Technology | | Назначение | Технология |
|---|---| |---|---|
| Device firmware / emulator | Go (`services/esp32-emulator`) | | Прошивка устройства / эмулятор | Go (`services/esp32-emulator`) |
| Device ↔ server protocol | MQTT (Mosquitto) | | Протокол устройство ↔ сервер | MQTT (Mosquitto) |
| Telemetry / commands / rules backend | Go | | Backend телеметрии / команд / правил | Go |
| Business logic / API / dashboard | PHP (Laravel) | | Бизнес-логика / API / дашборд | PHP (Laravel) |
| Users, zones, devices, rules | PostgreSQL | | Пользователи, зоны, устройства, правила | PostgreSQL |
| Telemetry (time-series) | ClickHouse | | Телеметрия (time-series) | ClickHouse |
| Real-time device state | Redis (Device Shadow pattern) | | Состояние устройств в реальном времени | Redis (паттерн Device Shadow) |
| Inter-service async events | RabbitMQ | | Асинхронные события между сервисами | RabbitMQ |
| Inter-service sync calls | gRPC / Protobuf | | Синхронные вызовы между сервисами | gRPC / Protobuf |
| Metrics (stage 2.5) | Prometheus + Grafana | | Метрики (этап 2.5) | Prometheus + Grafana |
| Containerization | Docker Compose | | Контейнеризация | Docker Compose |
| Web frontend (stage 3) | Vue.js + Inertia.js | | Веб-фронтенд (этап 3) | Vue.js + Inertia.js |
| Mobile app (stage 3) | Flutter | | Мобильное приложение (этап 3) | Flutter |
| Notifications | Telegram Bot (MVP) / Firebase Cloud Messaging (later) | | Уведомления | Telegram-бот (MVP) / Firebase Cloud Messaging (позже) |
## Layout ## Структура репозитория
``` ```
services/ services/
ingest-service/ Go — MQTT → ClickHouse + RabbitMQ ingest-service/ Go — MQTT → ClickHouse + RabbitMQ
device-control-service/ Go — gRPC + MQTT + Redis device shadow device-control-service/ Go — gRPC + MQTT + Redis device shadow
rule-engine-service/ Go — RabbitMQ consumer + rule evaluation rule-engine-service/ Go — консьюмер RabbitMQ + оценка правил
health-check-service/ Go — offline detection ticker health-check-service/ Go — тикер обнаружения офлайн-устройств
esp32-emulator/ Go — fake device for local dev esp32-emulator/ Go — фейковое устройство для локальной разработки
laravel-app/ PHP/Laravel — API, auth, dashboard (stage 2) laravel-app/ PHP/Laravel — API, авторизация, дашборд (этап 2)
proto/ Shared gRPC contracts (device_control.proto) proto/ Общие gRPC-контракты (device_control.proto)
migrations/ migrations/
postgres/ users, zones, devices, device_types, automation_rules postgres/ users, zones, devices, device_types, automation_rules
clickhouse/ telemetry table clickhouse/ таблица telemetry
configs/mosquitto/ MQTT broker config configs/mosquitto/ Конфиг MQTT-брокера
monitoring/ Prometheus + Grafana config (stage 2.5) monitoring/ Конфиги Prometheus + Grafana (этап 2.5)
``` ```
Each `services/*/README.md` describes that service's responsibility and Каждый `services/*/README.md` описывает зону ответственности сервиса и явно
explicit non-responsibilities before any code exists there. то, что в неё не входит, — ещё до того, как там появится код.
## Build stages ## Этапы разработки
1. **Go services** — ingest, rule-engine, device-control, ESP32 emulator. 1. **Go-сервисы** — ingest, rule-engine, device-control, эмулятор ESP32.
2. **Laravel**auth (Sanctum, owner/viewer), CRUD for zones/devices/rules, 2. **Laravel**авторизация (Sanctum, owner/viewer), CRUD для зон/устройств/
Blade dashboard, manual device control. MVP is considered done here. правил, Blade-дашборд, ручное управление устройствами. MVP считается
3. *(optional, high value)* **Observability** — Prometheus metrics from the готовым на этом этапе.
Go services, a Grafana dashboard or two. 3. *(опционально, но сильно повышает ценность)* **Observability** — метрики
4. **Extensions** (no rush) — Telegram notifications, Vue.js/Inertia Prometheus с Go-сервисов, один-два дашборда в Grafana.
frontend, Flutter app, real ESP32 hardware. 4. **Расширения** (не спеша) — Telegram-уведомления, фронтенд на
Vue.js/Inertia, приложение на Flutter, подключение реального ESP32.
## Running locally ## Запуск локально
Infrastructure only for now (app services are added to `docker-compose.yml` Пока только инфраструктура (сервисы добавляются в `docker-compose.yml` по
as they're implemented): мере реализации):
```bash ```bash
cp .env.example .env cp .env.example .env
docker compose up -d docker compose up -d
``` ```
This brings up Mosquitto (`1883`), PostgreSQL (`5432`), ClickHouse (`8123`/`9000`), Поднимутся Mosquitto (`1883`), PostgreSQL (`5432`), ClickHouse (`8123`/`9000`),
Redis (`6379`), and RabbitMQ (`5672`, management UI on `15672`). Redis (`6379`) и RabbitMQ (`5672`, веб-интерфейс управления на `15672`).
+16 -16
View File
@@ -1,20 +1,20 @@
# device-control-service (Go) # device-control-service (Go)
Status: not implemented yet. Статус: пока не реализован.
Responsibility: Зона ответственности:
- Expose a gRPC API (see `proto/device_control.proto`) for issuing commands - Предоставляет gRPC API (см. `proto/device_control.proto`) для отправки
to devices — called by Laravel (manual control) and rule-engine-service команд устройствам — вызывается из Laravel (ручное управление) и из
(rule-triggered actions). rule-engine-service (действия по срабатыванию правил).
- Publish the command to the device's MQTT topic (`devices/{device_id}/commands`) - Публикует команду в MQTT-топик устройства (`devices/{device_id}/commands`)
and listen for acknowledgements (`devices/{device_id}/ack`). и слушает подтверждения (`devices/{device_id}/ack`).
- Maintain the Device Shadow pattern in Redis: `desired_state` (what the user - Поддерживает паттерн Device Shadow в Redis: `desired_state` (чего хочет
wants) vs `reported_state` (what the device confirmed), plus `status` and пользователь) против `reported_state` (что подтвердило устройство), плюс
`last_seen`. `status` и `last_seen`.
- Owns the health-check loop (or delegates to health-check-service): a ticker - Владеет циклом health-check (либо делегирует его health-check-service):
goroutine that flips a device to `offline` when `last_seen` exceeds a горутина-тикер переводит устройство в `offline`, когда `last_seen`
timeout, and emits an event for notification-service. превышает таймаут, и генерирует событие для notification-service.
Not this service's job: deciding *when* to send a command based on sensor Не входит в зону ответственности: решение о том, *когда* отправлять команду
thresholds — that's rule-engine-service's logic. This service only executes на основе показаний датчиков — это логика rule-engine-service. Этот сервис
and tracks state for whatever command it's given. только исполняет команды и отслеживает состояние для той команды, что ему дали.
+8 -8
View File
@@ -1,11 +1,11 @@
# esp32-emulator (Go) # esp32-emulator (Go)
Status: not implemented yet. Статус: пока не реализован.
Responsibility: Зона ответственности:
- Stand in for real ESP32 hardware during MVP development. - Заменяет реальное железо ESP32 на время разработки MVP.
- Publish plausible telemetry (temperature/humidity/etc.) to - Публикует правдоподобную телеметрию (температура/влажность/и т.д.) в
`devices/{device_id}/telemetry` over MQTT on an interval. `devices/{device_id}/telemetry` по MQTT с заданным интервалом.
- Subscribe to `devices/{device_id}/commands` and reply on - Подписывается на `devices/{device_id}/commands` и отвечает в
`devices/{device_id}/ack`, so device-control-service has something real `devices/{device_id}/ack`, чтобы device-control-service было с кем
to talk to. по-настоящему взаимодействовать.
+9 -8
View File
@@ -1,11 +1,12 @@
# health-check-service (Go) # health-check-service (Go)
Status: not implemented yet. May start as a goroutine inside Статус: пока не реализован. Может начаться как горутина внутри
device-control-service and get split out into its own container later — device-control-service и позже выделиться в отдельный контейнер — поэтому
kept as a separate directory from day one so the split is a non-event. с первого дня держим отдельную директорию, чтобы это разделение прошло
безболезненно.
Responsibility: Зона ответственности:
- Periodically (ticker) check `last_seen` for every device in Redis. - Периодически (по тикеру) проверяет `last_seen` каждого устройства в Redis.
- When a device exceeds the offline timeout, flip its `status` to `offline` - Когда устройство превышает таймаут офлайна, переводит его `status` в
and publish an event for notification-service. `offline` и публикует событие для notification-service.
- Good place to demonstrate goroutines + graceful shutdown in Go. - Хороший повод продемонстрировать горутины + graceful shutdown в Go.
+9 -9
View File
@@ -1,13 +1,13 @@
# ingest-service (Go) # ingest-service (Go)
Status: not implemented yet. Статус: пока не реализован.
Responsibility: Зона ответственности:
- Subscribe to MQTT topics `devices/{device_id}/telemetry`. - Подписка на MQTT-топики `devices/{device_id}/telemetry`.
- Validate/parse payload (device_id, sensor_type, value, timestamp). - Валидация/парсинг payload (device_id, sensor_type, value, timestamp).
- Batch-write raw readings into ClickHouse `telemetry` table. - Батч-запись сырых показаний в таблицу ClickHouse `telemetry`.
- Publish a "new reading" event to RabbitMQ for rule-engine-service. - Публикация события «новое показание» в RabbitMQ для rule-engine-service.
Not this service's job: interpreting what a sensor reading *means* (thresholds, Не входит в зону ответственности: интерпретация того, что *означает*
actions) — that belongs to rule-engine-service. This service only ingests and показание датчика (пороги, действия) — это задача rule-engine-service. Этот
stores. сервис только принимает и сохраняет данные.
+14 -14
View File
@@ -1,18 +1,18 @@
# rule-engine-service (Go) # rule-engine-service (Go)
Status: not implemented yet. Статус: пока не реализован.
Responsibility: Зона ответственности:
- Consume "new reading" events from RabbitMQ (async — delivery reliability - Потребляет события «новое показание» из RabbitMQ (асинхронно — здесь
matters more than latency here). надёжность доставки важнее задержки).
- Load active `automation_rules` for the relevant zone/device from PostgreSQL, - Загружает активные `automation_rules` для нужной зоны/устройства из
caching in memory/Redis to avoid a DB round-trip per event. PostgreSQL, кэшируя в памяти/Redis, чтобы не ходить в БД на каждое событие.
- Evaluate rule conditions generically: `sensor_type X operator value` against - Оценивает условия правил обобщённо: `sensor_type X operator value` против
the reading — no hardcoded sensor/device names, everything comes from the показания — никаких зашитых названий датчиков/устройств, всё берётся из
`automation_rules` row. строки `automation_rules`.
- On match: call device-control-service over gRPC (needs a fast pass/fail - При срабатывании: вызывает device-control-service по gRPC (нужен быстрый
result) and publish an event to notification-service over RabbitMQ (not результат успех/неудача) и публикует событие в notification-service через
latency-critical). RabbitMQ (не критично к задержке).
Not this service's job: talking to MQTT or Redis directly — device state Не входит в зону ответственности: прямое взаимодействие с MQTT или Redis
changes always go through device-control-service's gRPC API. изменения состояния устройства всегда идут через gRPC API device-control-service.