EN

BLE Device Gateway

Фокус
Backend / Edge / IoT
Год
2026
Стек
Go · gRPC · Protocol Buffers · BLE · BlueZ / D-Bus · Concurrency · Docker · CI
Репозиторий на GitHub

Инженерная задача

Не выпускать vendor-specific GATT UUID, packet layouts и command bytes наружу и дать остальным сервисам стабильный domain-oriented API.

Моя роль

Go / Systems Engineer. Я спроектировал service boundary, protobuf contracts, BLE adapters, обработку бинарного протокола, concurrency model, streaming path, retry lifecycle, tests и container setup.

Путь телеметрии

BLE notification → frame assembler → checksum / protocol parser → thread-safe battery state → gRPC unary snapshot или server stream

Результат

Рабочий gateway с проверенной на реальном JBD BMS телеметрией, покрытым тестами JDY relay command path, mock mode, Docker, integration tests и CI.

BLE Device Gateway — hardware-facing сервис внутри RV Monitor. Он работает на Linux / Raspberry Pi и превращает device-specific BLE-коммуникацию в небольшой типизированный gRPC boundary. Текущая реализация читает JBD BMS, отдаёт текущее состояние и live server stream, а также реализует управление JDY-33 relay. Основная инженерная работа здесь не CRUD, а реальные edge-условия: фрагментированные бинарные пакеты, общий Bluetooth-адаптер, конкурентные consumers, cancellation, устаревшее состояние и переподключения.

Архитектура gateway

Оборудование за типизированным API

Потребители работают с GetSnapshot, StreamSnapshots и SetChannel вместо ReadCharacteristic или WriteCharacteristic. BLE UUID, vendor packet layouts и command encoding остаются внутри gateway, а внутренняя battery model не зависит от сгенерированных protobuf types. Так hardware-specific детали не протекают в application layer.

От фрагментов BLE к domain state

Ответ JBD может приходить несколькими BLE notifications. Frame assembler накапливает фрагменты до полного ответа, после чего gateway проверяет framing и checksum и разбирает напряжение, signed current, state of charge, напряжения ячеек, температуры, protection flags и другие параметры аккумулятора. Telemetry path проверен на физическом BMS, установленном в автодоме.

Streaming без блокировки device I/O

API поддерживает и unary snapshot текущего состояния, и server-streaming telemetry. Каждый subscriber получает небольшой buffered channel, а публикация не блокирует BLE processing: если клиент отстаёт, старое ожидающее значение заменяется самым свежим, потому что для этого сценария актуальное состояние важнее воспроизведения каждой промежуточной точки. Shared state защищён синхронизацией, а BLE discovery сериализован, поскольку оба устройства используют один физический Bluetooth controller.

Восстановление после ошибок и тестируемость

Долгоживущие hardware clients работают через context-aware retry loop с exponential backoff, а при потере BMS telemetry становится unavailable вместо выдачи старого snapshot как актуального. Shutdown прокидывается через context cancellation и bounded gRPC graceful stop. Mock source без железа, Docker / Compose, gRPC integration tests через bufconn, race-detector checks и GitHub Actions позволяют запускать и проверять тот же public API без автодома.