При розробці мобільного застосунку для OBD-II діагностики ключове завдання — стабільне та швидке зчитування параметрів двигуна через ELM327-адаптер. Неякісні клони ELM327 втрачають з'єднання, повільно відповідають на запити, а протоколи CAN bus різняться у різних виробників. Ми вирішуємо ці проблеми: гарантуємо стабільне опитування до 50+ PID в реальному часі, використовуючи оптимізовані алгоритми та fallback-логіку.
OBD-II адаптер (ELM327-сумісний або професійний) підключається до 16-пінового роз'єму під рулем і спілкується з мобільним застосунком через Bluetooth Classic, Bluetooth LE або Wi-Fi. Протоколи CAN bus за OBD-II — SAE J1979 (стандарт запиту PID), ISO 15765-4 (CAN), ISO 14230 (KWP2000) — залежать від виробника та року випуску автомобіля. Завдання розробника: розпарсити AT-команди ELM327, декодувати відповіді PID, інтерпретувати коди помилок DTC. Наш досвід — багаторічний у мобільній розробці OBD-рішень, ми гарантуємо стабільне підключення та точність даних.
Проблеми, які вирішуємо — obd ii діагностика
Нестабільне підключення. ELM327-клони часто втрачають з'єднання на високих швидкостях. Ми реалізуємо реконнект з експоненціальним відкатом та перевіркою цілісності каналу через AT-команди.
Повільне опитування PID. Послідовний запит десятків параметрів створює лаги. Оптимізуємо: групуємо за пріоритетом, використовуємо багатопотоковість та асинхронні стріми.
Несумісність протоколів. Китайські адаптери не завжди коректно обробляють ATSP. Пишемо fallback-логіку з перебором протоколів та кешуванням успішних конфігів.
Як забезпечити стабільне підключення до ELM327?
ELM327 та AT-команди
ELM327 — міст між CAN-шиною автомобіля та послідовним портом. Ініціалізація та базові запити:
ATZ → скидання адаптера
ATL0 → вимкнути перенесення рядка
ATE0 → вимкнути відлуння
ATH0 → вимкнути заголовки CAN-фреймів
ATSP0 → авто-вибір протоколу
0100 → запит підтримуваних PID (01-20)
Відповідь на 0100: 41 00 BE 3F A8 13 — біти показують які PID підтримує ECU. 41 — відповідь на режим 01, 00 — PID. Наступні 4 байти — бітова маска.
Декодування:
fun parseSupportedPids(response: String): Set<Int> {
val bytes = response.trim().split(" ").map { it.toInt(16) }
if (bytes.size < 6 || bytes[0] != 0x41 || bytes[1] != 0x00) return emptySet()
val supported = mutableSetOf<Int>()
var bitMask = (bytes[2].toLong() shl 24) or (bytes[3].toLong() shl 16) or
(bytes[4].toLong() shl 8) or bytes[5].toLong()
for (bit in 31 downTo 0) {
if ((bitMask and (1L shl bit)) != 0L) {
supported.add(32 - bit)
}
}
return supported
}
Bluetooth Classic vs Bluetooth LE
ELM327-клони працюють по Bluetooth Classic (SPP profile). На Android — BluetoothSocket з UUID 00001101-0000-1000-8000-00805F9B34FB. На iOS Bluetooth Classic недоступний для сторонніх застосунків — тільки через MFi-сертифіковані аксесуари або Wi-Fi адаптер.
Тому для кросплатформи Flutter рекомендуємо Wi-Fi ELM327 адаптери (TCP 192.168.0.10:35000) або BLE-адаптери нового покоління (OBDLink MX+, Veepeak OBDCheck BLE+):
class OBD2WifiConnector {
late Socket _socket;
final StreamController<String> _responseController = StreamController();
Stream<String> get responses => _responseController.stream;
Future<void> connect(String host, int port) async {
_socket = await Socket.connect(host, port,
timeout: const Duration(seconds: 5));
_socket.listen(
(data) {
final response = String.fromCharCodes(data).trim();
if (response.endsWith('>')) {
final clean = response.replaceAll('>', '').trim();
if (clean.isNotEmpty) _responseController.add(clean);
}
},
onError: (error) => _reconnect(),
);
await _initializeAdapter();
}
Future<String> sendCommand(String command) async {
final completer = Completer<String>();
late StreamSubscription sub;
sub = responses.first.asStream().listen((response) {
sub.cancel();
completer.complete(response);
});
_socket.write('$command\r');
return completer.future.timeout(const Duration(seconds: 3));
}
}
Опитування PID в реальному часі
Популярні PID режиму 01 (реальний час):
| PID | Параметр | Формула |
|---|---|---|
| 0C | Оберти двигуна RPM | (A*256+B)/4 |
| 0D | Швидкість км/год | A |
| 05 | Температура охолоджувальної рідини °C | A-40 |
| 0F | Температура впускного повітря °C | A-40 |
| 11 | Положення дросельної заслінки % | A*100/255 |
| 04 | Навантаження двигуна % | A*100/255 |
| 0B | Тиск колектора kPa | A |
Опитування декількох PID послідовно з мінімальною затримкою:
Future<void> startPolling(List<int> pids) async {
while (_isPolling) {
for (final pid in pids) {
final pidHex = pid.toRadixString(16).padLeft(2, '0').toUpperCase();
final response = await sendCommand('01' + pidHex);
_parsePidResponse(pid, response);
await Future.delayed(const Duration(milliseconds: 50));
}
}
}
50 мс між запитами — мінімум для стабільної роботи більшості адаптерів. Швидше — ризик переповнення буфера ELM327.
Чому важлива підтримка багатьох протоколів?
Читання та скидання кодів помилок DTC
Режим 03 — запит активних DTC (Diagnostic Trouble Codes):
fun parseDtcResponse(response: String): List<String> {
val bytes = response.trim().split(" ").map { it.toInt(16) }
val dtcs = mutableListOf<String>()
var i = 2 // пропускаємо режим та кількість
while (i + 1 < bytes.size) {
val byte1 = bytes[i]
val byte2 = bytes[i + 1]
if (byte1 == 0 && byte2 == 0) break
val prefix = when ((byte1 shr 6) and 0x03) {
0 -> "P"; 1 -> "C"; 2 -> "B"; 3 -> "U"; else -> "P"
}
val digit2 = (byte1 shr 4) and 0x03
val digit3 = byte1 and 0x0F
val digits45 = byte2.toString(16).padStart(2, '0').uppercase()
dtcs.add("$prefix$digit2$digit3$digits45")
i += 2
}
return dtcs
}
Типові коди DTC:
| Код | Опис | Можливі причини |
|---|---|---|
| P0300 | Випадкові пропуски запалювання | Свічки, котушки, паливо |
| P0171 | Бідна суміш | Підсмоктування повітря, лямбда-зонд |
| P0420 | Каталізатор банк 1 | Каталізатор, кисневі датчики |
Розшифровка DTC — окрема база даних (SAE J2012 для стандартних, OEM для виробників).
Скидання помилок: режим 04, команда 04. Підтвердження через діалог обов'язкове — скидання видаляє дані готовності (Readiness Monitors), що може призвести до відмови в техогляді.
Докладніше про fallback-логіку протоколів
Якщо автовизначення (ATSP0) не дає відповіді, перебираємо протоколи в порядку: ISO 15765-4 (CAN 11/29 bit), ISO 14230 (KWP2000), ISO 9141-2. Після успішного підключення кешуємо PID протоколу для швидкого старту наступного разу.
Як ми працюємо
- Аналіз вимог та вибір адаптера (BLE, Wi-Fi, Classic).
- Проектування архітектури застосунку (чиста архітектура, DI).
- Розробка прототипу підключення з базовим опитуванням PID.
- Тестування на 5+ моделях авто різних марок.
- Інтеграція розширених функцій (DTC, тренди, декілька профілів).
- Деплой в App Store та Google Play.
Що входить в роботу
- Прототип підключення до ELM327 через BLE/Wi-Fi/Bluetooth Classic з реалізацією реконнекту.
- Реалізація опитування PID (до 50+ параметрів) з налаштовуваною частотою.
- Читання та розшифровка DTC (стандартних та OEM).
- Підтримка багатьох протоколів CAN, fallback-логіка.
- Документація з інтеграції SDK.
- Тестування на 5+ моделях авто різних марок.
- Підтримка після запуску (3 місяці).
Строки та вартість
Розробка застосунку OBD-II діагностики з BLE/Wi-Fi підключенням, опитуванням PID та читанням DTC: 3-5 тижнів. Додавання розшифровки DTC, трендів та підтримки декількох автомобілів: 6-8 тижнів. Вартість розраховується індивідуально після аудиту ваших вимог. Замовте розробку OBD-II застосунку — ми підготуємо прототип за 2 тижні. Отримайте консультацію з реалізації OBD-II діагностики під ключ.







