Дашборд с реальными данными + ручное управление устройствами
device-control-service: HTTP/JSON API (internal/httpapi) рядом с gRPC —
POST /devices/{id}/turn-on|turn-off|set-level, тот же server.Server внутри,
без дублирования логики. Решение вместо gRPC-клиента на PHP: grpc/grpc
через PECL компилируется в Alpine 10-20+ минут и утяжеляет образ, а
диаграмма архитектуры в ТЗ и так допускала HTTP для Laravel→device-control.
Laravel: DeviceShadow (чтение Device Shadow из Redis, MGET одним запросом
для списка устройств), ClickHouseClient (HTTP-интерфейс ClickHouse,
параметризованные {name:Type}-запросы), DeviceControlClient (HTTP-вызовы
к новому Go-эндпоинту). Redis-клиент — predis (чистый PHP), а не phpredis,
по той же причине, что и решение по gRPC — не добавлять ещё одну
C-компиляцию в образ.
DeviceController::show — страница устройства: live-статус/last_seen/
desired-reported state из Redis, история показаний из ClickHouse (для
сенсоров), кнопки ручного управления (для актуаторов, только owner,
с проверкой capability устройства). В devices/index — бейдж online/
offline/unknown. Дашборд дополнен счётчиком онлайн-устройств.
Два реальных бага найдены и исправлены при сквозной проверке:
1. Пустой action_params сериализовался в JSON-массив "[]" (PHP не
различает пустой список и пустой объект), а Go ждёт объект —
rule-engine-service падал на unmarshal. Фикс — JsonObjectCast
(JSON_FORCE_OBJECT) на AutomationRule::action_params.
2. Redis-ключи device shadow — общее пространство имён с Go-сервisами
(сырые ключи без префикса), а Laravel по умолчанию добавляет ко всем
ключам префикс "app-name-database-" — Laravel никогда не видел
реальные данные. Фикс — REDIS_PREFIX="" в окружении контейнера
(важно: пустое значение в docker-compose YAML нужно задавать явно
через "", просто "KEY:" означает "взять из окружения хоста").
Проверено сквозным тестом через docker compose: полный цикл телеметрия →
правило → команда воспроизведён вживую с реальным исправлением на лету;
ручное управление (turn_on/turn_off/set_level) из Laravel UI подтверждено
через браузер — HTTP-вызов к device-control-service, обновление
desired_state (merge-patch), реальная MQTT-команда поймана мониторингом
топика. 38/38 тестов Laravel, все Go-тесты device-control-service зелёные.
This commit is contained in:
@@ -5,8 +5,11 @@
|
||||
Зона ответственности:
|
||||
- Предоставляет gRPC API (см. `proto/device_control/device_control.proto`:
|
||||
`TurnOn`, `TurnOff`, `SetLevel` → `CommandResult`) для отправки команд
|
||||
устройствам — вызывается из Laravel (ручное управление) и из
|
||||
rule-engine-service (действия по срабатыванию правил).
|
||||
устройствам — вызывается из rule-engine-service (действия по срабатыванию
|
||||
правил).
|
||||
- Тот же функционал доступен и по HTTP/JSON (`internal/httpapi`,
|
||||
`POST /devices/{device_id}/turn-on|turn-off|set-level`) — для Laravel
|
||||
(ручное управление из UI), см. «Архитектурные решения» почему не gRPC.
|
||||
- Публикует команду в MQTT-топик устройства (`devices/{device_id}/commands`)
|
||||
и слушает подтверждения (`devices/{device_id}/ack`).
|
||||
- Поддерживает паттерн Device Shadow в Redis: `desired_state` (чего хочет
|
||||
@@ -37,6 +40,14 @@
|
||||
телеметрии/ack, а не выгружается из таблицы `devices`. Это удерживает
|
||||
сервис в границах MQTT+Redis+RabbitMQ+gRPC, как и в диаграмме архитектуры
|
||||
корневого README.
|
||||
- **HTTP рядом с gRPC, а не вместо.** ТЗ подразумевало gRPC-вызов и от
|
||||
Laravel тоже, но `grpc/grpc` под PHP требует PECL-расширение, которое в
|
||||
Alpine компилируется мучительно долго (C-код, 10-20+ минут) и утяжеляет
|
||||
образ. `internal/httpapi` — тонкий транспорт поверх ТОГО ЖЕ
|
||||
`server.Server` (никакой логики не дублируется, просто JSON вместо
|
||||
Protobuf): диаграмма архитектуры в ТЗ и так допускала «HTTP/очередь» для
|
||||
Laravel→device-control. gRPC-контракт между Go-сервисами (rule-engine)
|
||||
не тронут.
|
||||
|
||||
## Запуск
|
||||
|
||||
|
||||
Reference in New Issue
Block a user