React Native is an excellent tool for flexible development. We use it constantly and it allows us to feel confident in the speed of development and respond quickly to changing requirements. For those hearing about React Native for the first time, it’s a cross-platform framework for mobile development founded on Facebook and widely supported by huge developer community.
At Star, we use React Native in many different ways: for catalog apps, for logistic apps with maps, POI features and routing, etc. Since it had proved to be such a reliable, flexible development tool for us in the past, we decided to extend our expertise of working with the tool into the automotive area.
As part of our Automotive and mobility team, we decided to create a PoC for React Native with Bluetooth low energy and OBDII. OBD is an acronym for “on-board diagnostics” and refers to a vehicle’s self-diagnostics and reporting capabilities. Designed originally for internal usage, OBD has been adopted for a wide set of use cases. In this particular case, we wanted to read errors from the connected car app to help drivers be aware of possible problems ahead. This is a common use case, widely used for everything from improving customer support for private car owners to optimizing logistics for fleet management. We are not going to share application code but our observations and important points.
Preparations
First of all, we needed to find proper hardware for testing and developing. We started with a super simple and cheap adapter with ELM327 microcontoller. Why did we need an ELM327? It converts the car diagnostic interface into an AT-compatible set of commands, which dramatically simplifies communication with OBD protocol.
Typically, such adapters are connected to the physical OBD port in the car on one end, and to the client application interface on the other end: Bluetooth, WiFi or USB. In our case, we intentionally decided to use Bluetooth due to the fact that it’s really easy to work with it.
The next step was deciding what we were going to use for testing: an actual vehicle, a hardware emulator or a software emulator. A quick investigation revealed that the price of the hardware emulator was out of our budget for PoC. There are, however, a lot of good choices on the market, and if you work with OBD on a daily basis, a hardware simulator is worth the investment. We then considered using a software simulator, but we couldn’t find a stable open source solution. This left us with the last option: using an actual car. This might seem like total overkill, but as we later found out, using a real car helped us to avoid very dangerous types of errors. So we decided to use a car, but only for the OBD-related part of the testing. We could test communication with a Bluetooth low energy device from the React Native app using local environment.
To simplify this testing phase, we chose an Android app that emulates the Bluetooth low energy interface, BLE Peripheral Simulator.
With all of that in place, it was time to start hacking.
Bluetooth
To work with Bluetooth from the React Native app, we needed a library which took all the internal bluetooth communication on its side and allowed us to quickly implement the connection to the OBD adapter. Some quick research gave us a great candidate – react-native-ble-plx GitHub. It’s a robust library with an active community, which made it the perfect choice for our needs. We were able to easily add it to the project, and the initial results were very positive; everything worked as expected, the simulator connected successfully and transmitted data. The results were impressive and we got from the first vehicle fault.
In React Native development, it’s common to work with both the iOS and Android platforms, just not at the same time. Usually a developer starts with one platform, gets some results and then tests the same functionality on the other platform. We followed the same procedure and started developing for the Android platform. When it came time to start testing on iOS, we discovered something unexpected, but very important: iOS only supports Bluetooth 4.0 and later. This means that if you want to develop a cross-platform application, it’s very important to specify Bluetooth 4.0 as a minimum requirement for the OBD adapter. Unfortunately, this brings about some limitations on the Android side, as older Android devices could be unsupported, depending on the business requirements.
OBDII
At this point, we had finished part related to the communication with the adapter, and it was time to start collecting data from the car.
But before we dive into that phase of the process, here are just a few words about the protocol itself In general, we used a text-based polling protocol, where we send a command and receive a response. Knowing all of the supported commands is very important. Generally speaking vehicle manufacturers don’t have to follow the implementation of OBDII protocol, which means some commands may vary, even between models of the same make. Knowing the supported commands means we can:
- Connect to the adapter via Bluetooth
- Start communication using AT commands
- Get data from the vehicle using PID codes
But the main problem here is that OBDII has nine versions and a car usually only supports one of them. The main difference between versions is the set of commands that are supported. As a developer, to start working with the vehicle, you can use the service command to retrieve the supported OBDII version, but it’s important to keep in mind that this command can be unsupported.
A common approach is to use the library, which unifies access to supported commands. A quick search will lead you to a variety of open source solutions for Java, Objective-C, Python or Javascript. But you still may struggle with their support, correctness and stability. This is because the world of automotive manufacturing is still quite closed for the open source community. It’s way easier and profitable for manufacturers to offer this information as a paid solution; a tactic which is good for their bottom lines, but bad for progress. This will most likely mean that you will have to implement the missing commands yourself. This isn’t something critical, but it must be accounted for in your estimations.
Keeping in mind all the constraints, we tried to retrieve the simplest information possible, the VIN number. To get this number, we used a raw AT command – it’s four numbers “0902”. We set it in a writeable property of the Bluetooth dongle and got a response. By the way, don’t forget to add “\r” at the end of command and encode everything with base64. We received a response in raw format, so omitting technical details, it’s encoded in base64 and contains information about the response length and content itself. We successfully tested all of this on the actual vehicle.
Then we moved on to the next feature we’d like to have: reading errors. In OBD world, an error is called DTC fault or Diagnostic Trouble Code. These are the codes generated and stored by a vehicle’s On-board Diagnostic System indicating that a part or section of the vehicle is malfunctioning. Their main goal is to identify a specific problem area. Technicians can use the codes to diagnose the problem and cause the OBD to report the fault. Each car has a wide range of sensors, which analyze the vehicle’s state and produce a DTC fault if something needs attention. Not all DTC faults require some action, and, generally speaking, there are two categories of codes:
- Pending – needs attention if the condition is repeatedly detected for a certain number of times
- Stored – needs immediate action
Unfortunately, neither pending or stored DTC faults were detected when we tested on the car. We even tried using a car we knew needed repairing, but without any success.
So we decided that the current results were sufficient for our analysis, at least in terms of understanding the main bottlenecks during development.
To finalize the experiment, we created a very basic UI from the standard React Native library to trigger the Bluetooth connection and display the VIN of the test car.
React Native proved to be a good choice for automotive. In a relatively small amount of time, we were able to build a fully functional, cross-platform application. During development, we were never blocked by this framework and, what’s more, with its ability to quickly switch between platforms, we were able to identify a critical blocker for iOS support of Bluetooth.
As for future projects, we’ll keep in mind that working with OBDII protocol might be tricky and it’s a good idea to have a rich stand for testing: hardware simulators and real cars.
To summarize
React Native proved to be a good choice for automotive. In a relatively small amount of time, we were able to build a fully functional, cross-platform application. During development, we were never blocked by this framework and, what’s more, with its ability to quickly switch between platforms, we were able to identify a critical blocker for iOS support of Bluetooth.
As for future projects, we’ll keep in mind that working with OBDII protocol might be tricky and it’s a good idea to have a rich stand for testing: hardware simulators and real cars.