This document describes the interface for the OpenXC library version 7.0.6.
Vehicle data is accessed through an Android service. Your application binds with the VehicleManager which handles reading fresh data from the vehicle and sending commands.
You must first bind with the VehicleManager before you can receive any vehicle data.
Request to bind with the service in the normal fashion:
This will require you to import the VehicleManager class from OpenXC:
Then, in your onServiceConnected()
grab the service handle and cast it to the
correct type:
Once the service is bound and you have a connection to it in your activity, you can start sending and receiving messages with the vehicle interface.
The VehicleMessage is the parent of all message sent to and from the vehicle interface. You can register to receive asynchronous updates for anything from all receive messages to only those matching a certain key. All of the examples here show how to receive updates for more specific subtypes, but you do have the option of interfacing directly with VehicleMessages.
If the attached VI is sending low-level CAN messages, you can receive them in your Android application.
You can also configure this listener to only receive CAN messages matching a certain message ID:
You can send a diagnostic request and wait for a response:
You can also register a receiver for the response so this function is non-blocking:
You can also send the request without caring about responses:
The commands defined in the OpenXC message
format that are
supported by your VI firmware can be sent using a Command
message type.
To send a command and wait to receive a response:
There is also a non-blocking version of the request
method that takes a
callback argument.
To send a command but return immediately, without waiting for a response:
For commands that don’t require any data in the request you can use this shortcut:
The VehicleManager has a couple of the supported VI commands built into the API - the firmware version and device ID.
A pre-defined set of simple vehicle
messages,
the official OpenXC
signals
is also exposed in the Android library as higher level Measurement
objects.
These work similarly to VehicleMessages but include more metadata and checks to
make sure the data is valid.
To query for a measurement synchronously, e.g. the speed of the vehicle, import the com.openxc.measurements.VehicleSpeed. You’ll also need to import the necessary exceptions:
You can then create a VehicleSpeed object and get the speed from the vehicle object.
If you want to access a different measurement, cast the measurement to any of the available measurement objects in the API.
If you need to be kept up-to-date on any vehicle measurement, you can also register with the service to be notified of updates.
The parent Measurement class provides a standard interface for all measurements, starting with a way to retrieve its value:
Occasionally a measurement will not have been received from the vehicle interface yet - it could be a malfunction, or you’re just checking too early for an infrequently updated measurement:
You can check the age of a measurement to determine how long ago the state was actually reflected in the physical vehicle:
The range of every measurement is defined in the class, and can be queried programmatically if you need to figure out the current value’s relative position:
The Android framework includes built-in support for location information - most devices support determining position based on CellID, GPS and Wi-Fi. OpenXC’s latitude, longitude and vehicle speed are exposed through this interface using a vehicle location provider. This functionality is provided by Android primarily for testing, but it’s also a useful way to inject location data from sources other than the built-in sensors. It works well with Bluetooth GPS receivers, too.
If your app already uses the Android location framework, with a very small change you can increase the accuracy by taking advantage of the GPS receiver built into many vehicles (including the 2012 Ford Focus, even those without a navigation system).
Add the ACCESS_FINE_LOCATION
and ACCESS_MOCK_LOCATION
permission to your
app’s AndroidManifest.xml
:
Open a connection to the VehicleManager as described earlier in “Service
Binding.” Then access user location in the traditional Android fashion -
data from the LocationManager.GPS_PROVIDER
and
VehicleManager.VEHICLE_LOCATION_PROVIDER
providers will be coming from OpenXC.
You may want to continue to use the GPS_PROVIDER
so your app can support
switching from built-in GPS to the vehicle’s receiver.
Data Flow
Vehicle data is first received by a physical interface, e.g. USB (#1 in the figure), in an Android process running the VehicleService. The data processed and encapsulated in Java objects as a part of a DataPipeline (#2) before being propagated to all client applications (#3).
The client applications (in a separate process) receive the data in an instance of the VehicleManager service (#4) which notifies any activities that have previously registered their interest in vehicle data (#5).
There are a few sequence diagrams available in the openxc-android docs directory.
Android exposes many of its system level functions in the form of services. This is a useful paradigm for long-running components of an application and perfect for OpenXC, which needs to maintain a connection to the vehicle to continue receiving new measurements.
Services can run either inside an application’s address space or as an external process; OpenXC uses both.
The core of the system is the VehicleService, which runs in a separate process to any app. Since only one application at a time can connect to a USB device , this service controls access to the USB vehicle interface. From here, new data from the vehicle (or other sources, as you’ll see) is propagated to any applications using the OpenXC library. The benefit is that multiple OpenXC-enabled apps can run on the same system, simultaneously.
Application developers use a second, in-process service - the VehicleManager. This service provides the interface that you’ll use when developing your app. Behind the scenes, it binds to the VehicleService (running in another process) and communicates with it using the Android Interface Definition Language. The benefit of using the VehicleManager in-process is that developers don’t need to care about any of this - it’s all abstracted away.
The VehicleManager uses the concept of a pipeline to funnel data from “sources” to “sinks.” This is a one-way pipeline.
Source
A data source injects new measurements into the OpenXC vehicle service. Sources can be added by the internal vehicle service itself (e.g. the source that connects to a USB device), the Enabler (e.g. a Bluetooth device source) or an app (e.g. the trace source, as in the tutorial).
At whatever level you add the source, its data is made available to all other OpenXC apps in the system. This is because even when a source is added to the VehicleManager, it ferries incoming measurements back to the VehicleService. Client apps can create and add their own custom sources, and when the client app is destroyed by Android the source will no longer send any data.
Besides the VehicleInterface subclasses, there is one built-in source for developers:
Sink
A data sink receives every new measurement put into the pipeline by the sources.
It receives the data in its base form, a VehicleMessage
.
Data sinks handle the core of the library’s asynchronous notification system, too. The VehicleManager always adds an instance of the MessageListenerSink, which keeps tabs on which applications want to be notified of changes in measurements.
The built-in sinks for application developers are:
Remote Service
The remote process VehicleService also uses a pipeline, but it’s not accessible to application developers. The sources for this pipeline are the active vehicle interface (e.g. Bluetooth, USB or Network) and:
The VehicleService only uses two sinks:
Application developers don’t need to worry about these, but it’s good to know how data flow through the system.
Enabler
The OpenXC Enabler app is primarily for convenience, but it also increases the reliability of the system by handling background tasks on behalf of client applications.
The Enabler provides a common location to control which data sources and sinks are active, e.g. if the a trace file should be played back or recorded. It’s preferable to be able to change the data source on the fly, and not have to programmatically load a trace file in any application under test.
With the enabler installed, the VehicleService is also started automatically when the Android device boots up. A simple data sink like a trace file uploader can start immediately without any user interaction. This behavior probably isn’t desirable for a phone-based OpenXC system, but makes more sense when using a tablet or other Android device that is permanently installed in the vehicle.
As a developer, you can also appreciate that because the enabler takes care of
starting the VehicleService, you don’t need to add much to your
application’s AndroidManifest.xml
- just the VehicleManager service.