Електросамокати та електровелосипеди з контролером — це не просто пристрої з BLE-чипом. Типовий стек: контролер BLDC-мотора (Sabvoton, Kelly, Votol) спілкується з дисплеєм або BMS за протоколом UART/RS485 (часто пропрієтарний), BLE-модуль (Nordic nRF52840, ESP32) слухає шину і транслює дані в мобільний додаток. Розробка додатку без розуміння цього ланцюжка закінчується тим, що додаток «підключився», але не знає, що робити з потоком байт. Наша команда має 5+ років досвіду в цій ніші та понад 30 успішно запущених проєктів. Ми гарантуємо стабільне BLE-з'єднання та коректну обробку даних з будь-яких контролерів.
Як ми вирішуємо проблему відсутності документації на контролер?
Більшість виробників контролерів (особливо китайських) не публікують протоколи. Процес: зняти рідний дисплей, підключити USB-UART аналізатор (FTDI232, CP2102) паралельно шині та записати трафік в логи. Інструмент — PulseView + декодер UART, або просто запис у файл через minicom/CoolTerm.
Типовий фрейм протоколу Xiaomi M365 (як приклад відкритого):
[0x55][0xAA][len][addr][cmd][data...][crc_lo][crc_hi]
Фрейм починається з 0x55 0xAA, потім довжина корисного навантаження, адреса отримувача (0x20 — контролер, 0x21 — BMS, 0x3E — дисплей), команда, дані, CRC16. Для менш популярних брендів CRC рахується по-різному — XOR, Modbus CRC, іноді просто сума байт з маскою.
class ScooterFrameParser {
private val buffer = ByteArrayOutputStream()
fun feed(byte: Byte): ScooterFrame? {
buffer.write(byte.toInt())
val bytes = buffer.toByteArray()
// Шукаємо початок фрейму
val start = findStart(bytes) ?: return null
if (bytes.size - start < 4) return null
val len = bytes[start + 2].toInt() and 0xFF
val totalLen = len + 6 // header(2) + len(1) + addr(1) + cmd(1) + crc(2) - 1
if (bytes.size - start < totalLen) return null
val frame = bytes.copyOfRange(start, start + totalLen)
buffer.reset()
if (start + totalLen < bytes.size) {
buffer.write(bytes, start + totalLen, bytes.size - start - totalLen)
}
return if (verifyCRC(frame)) parseFrame(frame) else null
}
}
Чому стабільність BLE-з'єднання критична для поїздок?
На Android BLE працює через BluetoothGatt. Головний біль — onConnectionStateChange з status = 133 (GATT_ERROR) при підключенні, особливо на Android 12+ з увімкненим Bluetooth Permission. Лікування: retry з затримкою 500-1000 мс, максимум 3 спроби, після — показуємо користувачеві інструкцію перепідключити Bluetooth.
class ScooterBLEManager(private val context: Context) {
private var gatt: BluetoothGatt? = null
private var retryCount = 0
fun connect(device: BluetoothDevice) {
gatt = device.connectGatt(context, false, object : BluetoothGattCallback() {
override fun onConnectionStateChange(g: BluetoothGatt, status: Int, newState: Int) {
when {
newState == BluetoothProfile.STATE_CONNECTED -> {
retryCount = 0
g.discoverServices()
}
status == 133 && retryCount < 3 -> {
retryCount++
g.close()
Handler(Looper.getMainLooper()).postDelayed({ connect(device) }, 800)
}
else -> notifyConnectionFailed()
}
}
override fun onCharacteristicChanged(g: BluetoothGatt,
characteristic: BluetoothGattCharacteristic, value: ByteArray) {
frameParser.feed(value)
}
}, BluetoothDevice.TRANSPORT_LE)
}
}
На iOS CBPeripheral стабільніше, але сесія CoreBluetooth не виживає після перезапуску додатку — зберігаємо peripheral.identifier (UUID) в UserDefaults і відновлюємо через retrievePeripherals(withIdentifiers:). Порівняння платформ показує, що Android BLE вимагає більше retry-механізмів, що збільшує час розробки на 10-15% відносно iOS.
| Характеристика | Android | iOS |
|---|---|---|
| Стабільність підключення | Нижча (status 133) | Висока |
| Retry-логіка | 3 спроби | Не потрібна |
| Час розробки BLE-шару | ~2 тижні | ~1 тиждень |
| Робота в фоні | Обмежена (Background limits) | Хороша |
Дашборд: що показуємо
Стандартний набір даних з контролера самоката/велосипеда:
- Швидкість (км/год) — реальна, з датчика колеса або розрахована з RPM + довжина кола
- Заряд батареї (%) — з BMS, рідше — розрахунковий за напругою
- Напруга/струм батареї — важливо для моніторингу рекуперації
- Температура контролера та мотора — критично для важких підйомів
- Пробіг — одометр, сумарний та за поїздку
- Режим їзди — Eco/Normal/Sport або D1-D5
- Стан гальм (якщо датчики підключені до контролера)
Виділимо швидкість, заряд батареї та температуру як ключові показники — їх оновлення має бути максимально швидким. Швидкісний графік за поїздку — обов'язковий елемент. Рендеримо через MPAndroidChart (Android) або Swift Charts (iOS 16+). Дані пишемо в Room/Core Data кожні 500 мс — поїздка на 30 км при такому інтервалі = ~3600 точок, це не проблема.
Деталі протоколів контролерів
Окрім Xiaomi, зустрічаються протоколи з фреймом довжиною 10-20 байт, де CRC рахується як XOR всіх байт, або Modbus RTU. Ми розбирали контролери Votol (EM-30, EM-100) — там фрейм починається з 0xAA, команда 0xB1 для даних, CRC16 Modbus. Алгоритм парсингу універсальний: шукаємо преамбулу, читаємо довжину, перевіряємо CRC.Управління режимами та налаштування контролера
Ряд контролерів дозволяє перепрограмувати параметри: максимальний струм, обмеження швидкості, потужність рекуперації. Відправляємо write-команду в Notify Characteristic. Важливо: зміни параметрів контролера вимагають попередження користувача та підтвердження — неправильний струм може вивести мотор з ладу або розрядити батарею за поїздку.
Для шерингових сервісів (флот самокатів) додається серверна частина: MQTT або WebSocket, історія поїздок на бекенді, геофенсинг, віддалене блокування. Це окремий рівень складності.
Процес роботи
- Аналіз протоколу контролера та специфікації BLE-модуля (1-2 тижні).
- Прототип підключення: прийом та відправка команд, верифікація (1 тиждень).
- Розробка UI/UX: дашборд, екран поїздки, налаштування (2-3 тижні).
- Реалізація BLE-шару, парсера, запису даних (2 тижні).
- Тестування на реальних поїздках (1-2 тижні).
- Публікація в App Store та Google Play, проходження рев'ю (1 тиждень).
Терміни: 6-8 тижнів на одну платформу, 3-4 місяці на крос-платформне рішення (Flutter) з підтримкою кількох протоколів. Вартість розраховується індивідуально після аналізу конкретної моделі пристрою та наявності документації на протокол. Зв'яжіться з нами для оцінки вашого проєкту.
Що входить в роботу
Після завершення проєкту ви отримуєте:
- Вихідний код додатку (native або Flutter) з документацією.
- Інструкцію зі збірки та деплою.
- Документацію протоколу контролера (якщо проводився реверс-інжиніринг).
- Доступ до репозиторію та засобів CI/CD.
- Підтримку при публікації в магазини додатків.
- Навчання адміністраторів флоту (якщо проєкт шеринговий).
Ми даємо гарантію на стабільну роботу BLE-з'єднання та коректний парсинг даних. Постійно оновлюємо додаток під нові версії iOS та Android.
Оцініть економію часу: замовте розробку додатку під ключ і отримайте готовий продукт, протестований на реальних пристроях. Пишіть — ми допоможемо.







