OBD-II Car Diagnostics Monitoring in Mobile App

NOVASOLUTIONS.TECHNOLOGY is engaged in the development, support and maintenance of iOS, Android, PWA mobile applications. We have extensive experience and expertise in publishing mobile applications in popular markets like Google Play, App Store, Amazon, AppGallery and others.
Development and support of all types of mobile applications:
Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1 servicesAll 1735 services
OBD-II Car Diagnostics Monitoring in Mobile App
Medium
~1-2 weeks
FAQ
Our competencies:
Development stages
Latest works
  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1052
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    445

Implementing OBD-II Diagnostics in Mobile Applications

An OBD-II adapter (ELM327-compatible or professional) connects to the 16-pin port under the steering wheel and communicates with the mobile app via Bluetooth Classic, Bluetooth LE, or Wi-Fi. CAN bus protocols behind OBD-II — SAE J1979 (PID request standard), ISO 15765-4 (CAN), ISO 14230 (KWP2000) — depend on manufacturer and vehicle year. Developer's task: parse ELM327 AT commands, decode PID responses, interpret DTC error codes.

ELM327 and AT Commands

ELM327 is a bridge between the vehicle's CAN bus and serial port. Initialization and basic requests:

ATZ        → adapter reset
ATL0       → disable line feed
ATE0       → disable echo
ATH0       → disable CAN frame headers
ATSP0      → auto-select protocol
0100       → request supported PIDs (01-20)

Response to 0100: 41 00 BE 3F A8 13 — bits show which PIDs ECU supports. 41 is the response to mode 01, 00 is PID. Next 4 bytes are bitmask.

Decoding:

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 clones use Bluetooth Classic (SPP profile). On Android — BluetoothSocket with UUID 00001101-0000-1000-8000-00805F9B34FB. On iOS, Bluetooth Classic is unavailable for third-party apps — only MFi-certified accessories or Wi-Fi adapters.

For cross-platform Flutter, recommend Wi-Fi ELM327 adapters (TCP 192.168.0.10:35000) or next-gen BLE adapters (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));
  }
}

Real-Time PID Polling

Popular mode 01 (real-time) PIDs:

PID Parameter Formula
0C Engine RPM (A*256+B)/4
0D Vehicle Speed km/h A
05 Coolant Temperature °C A-40
0F Intake Air Temperature °C A-40
11 Throttle Position % A*100/255
04 Engine Load % A*100/255
0B Manifold Pressure kPa A

Poll multiple PIDs sequentially with minimal delay:

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 ms between requests is minimum for stable operation of most adapters. Faster risks ELM327 buffer overflow.

Reading and Clearing DTC Error Codes

Mode 03 — request active 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  // skip mode and count
    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
}

P0300 — random misfires, P0171 — lean fuel mixture, P0420 — catalyst bank 1. DTC decoding — separate database (SAE J2012 for standard, OEM for manufacturers).

Clearing errors: mode 04, command 04. Confirmation via dialog is mandatory — clearing deletes Readiness Monitor data, which can cause vehicle inspection failure.

Developing OBD-II diagnostics application with BLE/Wi-Fi connection, PID polling and DTC reading: 3-5 weeks. Adding DTC decoding, trends and multi-vehicle support: 6-8 weeks. Cost calculated individually.