Have you ever considered accessing and displaying your vehicle’s real-time parameters directly within your custom Android application? If this idea excites you, you’ve landed in the right spot. We’re going to explore the essential steps in developing your very own OBDII reader application, leveraging the power of the Obd2 Bluetooth Api.
CHECK OUT: Developing Basic Features for Your Fleet Management Application
Let’s start with a brief overview of the diagnostic protocols employed in modern vehicles.
OBD, short for “on-board diagnostics,” is the system vehicles use for self-monitoring and reporting. Initially designed to assist mechanics with quick vehicle assessments, early OBD versions primarily focused on engine-related issues. Today, OBD systems, especially OBD-II, have evolved significantly. Beyond basic diagnostics, they now empower vehicle owners to monitor a wide array of parameters, including real-time fuel consumption, transmission status, and even GPS data. For a deep dive into the workings and history of OBD, the Wikipedia article “On-board diagnostics” offers comprehensive information.
Necessary Materials
To begin, you’ll need an OBDII adapter to interface with your vehicle’s OBDII port. The market offers a variety of adapters from different manufacturers, featuring interfaces like COM, USB, and Bluetooth. While technically any adapter could be used with an Android application, a Bluetooth adapter is generally the most practical choice for wireless communication. It’s also important to note that adapters can differ in terms of supported OBDII protocols, affecting vehicle compatibility. Ideally, having a car and a compatible OBDII adapter readily available is perfect for development.
However, what if you don’t have immediate access to a vehicle? For initial development and testing, a simulator can be incredibly useful. OBDSim is a recommended open-source simulator compatible with various platforms. Keep in mind that Bluetooth support on Windows might be limited, potentially requiring a Linux environment and source code modifications to adjust the RFCOMM channel for Bluetooth communication.
Alternatively, a hardware emulator can replace a physical car during development. We’ve successfully used the ECUsim 2000 standard with the ISO 15765 (CAN) protocol enabled. For the OBDII adapter, the ELM327 v.1.5 adapter proved to be a reliable option.
Developing the Application
Let’s delve into the communication protocol that facilitates data exchange between your Android device and the OBDII adapter or vehicle. It’s a text-based, polling-type protocol. This means communication is driven by sending commands and receiving responses, making understanding the command set crucial.
We will establish a connection to the adapter via Bluetooth. While Bluetooth Low Energy (BLE) API might seem like a modern choice, its limited device support currently makes it less practical for broad application compatibility. Therefore, classic Bluetooth remains the more reliable option for now when working with the obd2 bluetooth api.
The protocol includes AT commands for basic adapter control, such as toggling echo and line feed. Beyond these, the core is the OBDII control protocol itself, which defines commands to request specific vehicle parameters.
DISCOVER MORE: Embedded Engineering Services at Lemberg Solutions
The general application workflow involves these steps:
-
Establish a Bluetooth connection with the OBDII adapter.
-
Initialize the OBDII adapter using AT commands.
-
Continuously request vehicle data by sending corresponding PID (Parameter ID) codes.
Connecting to the OBDII adapter via Bluetooth is relatively straightforward. The initial step is to allow the user to select the Bluetooth device. A user-friendly approach is to display an alert dialog listing paired Bluetooth devices:
ArrayList<String> deviceStrs = new ArrayList<>();
final ArrayList<String> devices = new ArrayList<>();
BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
Set<BluetoothDevice> pairedDevices = btAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
deviceStrs.add(device.getName() + "n" + device.getAddress());
devices.add(device.getAddress());
}
}
// show list
final AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.select_dialog_singlechoice, deviceStrs.toArray(new String[0]));
alertDialog.setSingleChoiceItems(adapter, -1, (dialog, which) -> {
dialog.dismiss();
int position = ((AlertDialog) dialog).getListView().getCheckedItemPosition();
String deviceAddress = devices.get(position);
// TODO save deviceAddress
});
alertDialog.setTitle("Choose Bluetooth device");
alertDialog.show();
Remember to store the selected deviceAddress
for subsequent connection attempts. Now, you can establish the Bluetooth socket connection to the chosen device:
BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice device = btAdapter.getRemoteDevice(deviceAddress);
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
BluetoothSocket socket = device.createInsecureRfcommSocketToServiceRecord(uuid);
socket.connect();
The UUID specified (“00001101-0000-1000-8000-00805F9B34FB”) is the standard UUID for serial port profile (SPP) over Bluetooth. Crucially, execute this connection code within a background thread to prevent blocking the user interface. For troubleshooting potential connection issues, especially on Android 4.3 and later, refer to this Stack Overflow article addressing a known Bluetooth socket bug: IOException: Read failed, socket might closed Bluetooth on Android 4.3.
With the Bluetooth connection established, we can proceed to data exchange. The OBD-Java-API library simplifies interaction with OBDII. This library offers classes representing various OBD commands, making implementation easier. First, initialize the OBDII adapter with configuration commands:
new EchoOffObdCommand().run(socket.getInputStream(), socket.getOutputStream());
new LineFeedOffObdCommand().run(socket.getInputStream(), socket.getOutputStream());
new TimeoutObdCommand().run(socket.getInputStream(), socket.getOutputStream());
new SelectProtocolObdCommand(ObdProtocols.AUTO).run(socket.getInputStream(), socket.getOutputStream());
Now, you are ready to send OBDII data requests:
EngineRPMObdCommand engineRpmCommand = new EngineRPMObdCommand();
SpeedObdCommand speedCommand = new SpeedObdCommand();
while (!Thread.currentThread().isInterrupted()) {
engineRpmCommand.run(sock.getInputStream(), sock.getOutputStream());
speedCommand.run(sock.getInputStream(), sock.getOutputStream());
// TODO handle commands result
Log.d(TAG, "RPM: " + engineRpmCommand.getFormattedResult());
Log.d(TAG, "Speed: " + speedCommand.getFormattedResult());
}
It’s important to note that the OBD-Java-API library, while helpful, has some limitations. Specifically, its response parsing and error handling can be improved. A common issue is in the performCalculations
method within command classes. Implementing checks for buffer size before accessing data would enhance robustness, as OBDII adapter responses can sometimes be shorter than expected. While the root cause of short responses might be on the adapter or vehicle side, a robust library should gracefully handle such scenarios.
Despite these points, the OBD-Java-API library serves as a valuable starting point and reference for developing your obd2 bluetooth api application.
The retrieved vehicle data can be stored for further analysis, for instance, using Elasticsearch.
Currently, at obd-de.com, we are actively developing a Hours of Service application for commercial vehicle drivers and plan to continue sharing our insights and experiences with OBDII development in future blog posts.