blob: b970b2309cf7f1a3ab718a7a6a09d6486838e575 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.car.hardware;
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.car.annotation.FutureFeature;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.SparseArray;
import android.util.SparseIntArray;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
/**
* A CarDiagnosticEvent object corresponds to a single diagnostic event frame coming from the car.
*
* @hide
*/
@FutureFeature
public class CarDiagnosticEvent implements Parcelable {
/** Whether this frame represents a live or a freeze frame */
public final int frameType;
/**
* When this data was acquired in car or received from car. It is elapsed real-time of data
* reception from car in nanoseconds since system boot.
*/
public final long timestamp;
/**
* Sparse array that contains the mapping of OBD2 diagnostic properties to their values for
* integer valued properties
*/
private final SparseIntArray intValues;
/**
* Sparse array that contains the mapping of OBD2 diagnostic properties to their values for
* float valued properties
*/
private final SparseArray<Float> floatValues;
/**
* Diagnostic Troubleshooting Code (DTC) that was detected and caused this frame to be stored
* (if a freeze frame). Always null for a live frame.
*/
public final String dtc;
public CarDiagnosticEvent(Parcel in) {
frameType = in.readInt();
timestamp = in.readLong();
int len = in.readInt();
floatValues = new SparseArray<>(len);
for (int i = 0; i < len; ++i) {
int key = in.readInt();
float value = in.readFloat();
floatValues.put(key, value);
}
len = in.readInt();
intValues = new SparseIntArray(len);
for (int i = 0; i < len; ++i) {
int key = in.readInt();
int value = in.readInt();
intValues.put(key, value);
}
dtc = (String)in.readValue(String.class.getClassLoader());
// version 1 up to here
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(frameType);
dest.writeLong(timestamp);
dest.writeInt(floatValues.size());
for (int i = 0; i < floatValues.size(); ++i) {
int key = floatValues.keyAt(i);
dest.writeInt(key);
dest.writeFloat(floatValues.get(key));
}
dest.writeInt(intValues.size());
for (int i = 0; i < intValues.size(); ++i) {
int key = intValues.keyAt(i);
dest.writeInt(key);
dest.writeInt(intValues.get(key));
}
dest.writeValue(dtc);
}
public static final Parcelable.Creator<CarDiagnosticEvent> CREATOR =
new Parcelable.Creator<CarDiagnosticEvent>() {
public CarDiagnosticEvent createFromParcel(Parcel in) {
return new CarDiagnosticEvent(in);
}
public CarDiagnosticEvent[] newArray(int size) {
return new CarDiagnosticEvent[size];
}
};
private CarDiagnosticEvent(
int frameType,
long timestamp,
SparseArray<Float> floatValues,
SparseIntArray intValues,
String dtc) {
this.frameType = frameType;
this.timestamp = timestamp;
this.floatValues = floatValues;
this.intValues = intValues;
this.dtc = dtc;
}
public static class Builder {
private int mType = CarDiagnosticManager.FRAME_TYPE_FLAG_LIVE;
private long mTimestamp = 0;
private SparseArray<Float> mFloatValues = new SparseArray<>();
private SparseIntArray mIntValues = new SparseIntArray();
private String mDtc = null;
private Builder(int type) {
mType = type;
}
public static Builder newLiveFrameBuilder() {
return new Builder(CarDiagnosticManager.FRAME_TYPE_FLAG_LIVE);
}
public static Builder newFreezeFrameBuilder() {
return new Builder(CarDiagnosticManager.FRAME_TYPE_FLAG_FREEZE);
}
public Builder atTimestamp(long timestamp) {
mTimestamp = timestamp;
return this;
}
public Builder withIntValue(int key, int value) {
mIntValues.put(key, value);
return this;
}
public Builder withFloatValue(int key, float value) {
mFloatValues.put(key, value);
return this;
}
public Builder withDTC(String dtc) {
mDtc = dtc;
return this;
}
public CarDiagnosticEvent build() {
return new CarDiagnosticEvent(mType, mTimestamp, mFloatValues, mIntValues, mDtc);
}
}
/**
* Returns a copy of this CarDiagnosticEvent with all vendor-specific sensors removed.
* @hide
*/
public CarDiagnosticEvent withVendorSensorsRemoved() {
SparseIntArray newIntValues = intValues.clone();
SparseArray<Float> newFloatValues = floatValues.clone();
for(int i = 0; i < intValues.size(); ++i) {
int key = intValues.keyAt(i);
if (key >= CarDiagnosticSensorIndices.Obd2IntegerSensorIndex.LAST_SYSTEM) {
newIntValues.delete(key);
}
}
for(int i = 0; i < floatValues.size(); ++i) {
int key = floatValues.keyAt(i);
if (key >= CarDiagnosticSensorIndices.Obd2FloatSensorIndex.LAST_SYSTEM) {
newFloatValues.delete(key);
}
}
return new CarDiagnosticEvent(frameType, timestamp, newFloatValues, newIntValues, dtc);
}
public boolean isLiveFrame() {
return CarDiagnosticManager.FRAME_TYPE_FLAG_LIVE == frameType;
}
public boolean isFreezeFrame() {
return CarDiagnosticManager.FRAME_TYPE_FLAG_FREEZE == frameType;
}
public boolean isEmptyFrame() {
boolean empty = (0 == intValues.size());
empty &= (0 == floatValues.size());
if (isFreezeFrame()) empty &= dtc.isEmpty();
return empty;
}
/** @hide */
public CarDiagnosticEvent checkLiveFrame() {
if (!isLiveFrame()) throw new IllegalStateException("frame is not a live frame");
return this;
}
/** @hide */
public CarDiagnosticEvent checkFreezeFrame() {
if (!isFreezeFrame()) throw new IllegalStateException("frame is not a freeze frame");
return this;
}
/** @hide */
public boolean isEarlierThan(CarDiagnosticEvent otherEvent) {
otherEvent = Objects.requireNonNull(otherEvent);
return (timestamp < otherEvent.timestamp);
}
@Override
public String toString() {
return String.format(
"%s diagnostic frame {\n"
+ "\ttimestamp: %d, "
+ "DTC: %s\n"
+ "\tintValues: %s\n"
+ "\tfloatValues: %s\n}",
isLiveFrame() ? "live" : "freeze",
timestamp,
dtc,
intValues.toString(),
floatValues.toString());
}
public int getSystemIntegerSensor(@CarDiagnosticSensorIndices.IntegerSensorIndex int sensor, int defaultValue) {
return intValues.get(sensor, defaultValue);
}
public float getSystemFloatSensor(@CarDiagnosticSensorIndices.FloatSensorIndex int sensor, float defaultValue) {
return floatValues.get(sensor, defaultValue);
}
public int getVendorIntegerSensor(int sensor, int defaultValue) {
return intValues.get(sensor, defaultValue);
}
public float getVendorFloatSensor(int sensor, float defaultValue) {
return floatValues.get(sensor, defaultValue);
}
public @Nullable Integer getSystemIntegerSensor(@CarDiagnosticSensorIndices.IntegerSensorIndex int sensor) {
int index = intValues.indexOfKey(sensor);
if(index < 0) return null;
return intValues.valueAt(index);
}
public @Nullable Float getSystemFloatSensor(@CarDiagnosticSensorIndices.FloatSensorIndex int sensor) {
int index = floatValues.indexOfKey(sensor);
if(index < 0) return null;
return floatValues.valueAt(index);
}
public @Nullable Integer getVendorIntegerSensor(int sensor) {
int index = intValues.indexOfKey(sensor);
if(index < 0) return null;
return intValues.valueAt(index);
}
public @Nullable Float getVendorFloatSensor(int sensor) {
int index = floatValues.indexOfKey(sensor);
if(index < 0) return null;
return floatValues.valueAt(index);
}
/**
* Represents possible states of the fuel system;
* see {@link CarDiagnosticSensorIndices.Obd2IntegerSensorIndex#FUEL_SYSTEM_STATUS}
*/
public static final class FuelSystemStatus {
private FuelSystemStatus() {}
public static final int OPEN_INSUFFICIENT_ENGINE_TEMPERATURE = 1;
public static final int CLOSED_LOOP = 2;
public static final int OPEN_ENGINE_LOAD_OR_DECELERATION = 4;
public static final int OPEN_SYSTEM_FAILURE = 8;
public static final int CLOSED_LOOP_BUT_FEEDBACK_FAULT = 16;
@Retention(RetentionPolicy.SOURCE)
@IntDef({
OPEN_INSUFFICIENT_ENGINE_TEMPERATURE,
CLOSED_LOOP,
OPEN_ENGINE_LOAD_OR_DECELERATION,
OPEN_SYSTEM_FAILURE,
CLOSED_LOOP_BUT_FEEDBACK_FAULT
})
public @interface Status {}
}
/**
* Represents possible states of the secondary air system;
* see {@link CarDiagnosticSensorIndices.Obd2IntegerSensorIndex#COMMANDED_SECONDARY_AIR_STATUS}
*/
public static final class SecondaryAirStatus {
private SecondaryAirStatus() {}
public static final int UPSTREAM = 1;
public static final int DOWNSTREAM_OF_CATALYCIC_CONVERTER = 2;
public static final int FROM_OUTSIDE_OR_OFF = 4;
public static final int PUMP_ON_FOR_DIAGNOSTICS = 8;
@Retention(RetentionPolicy.SOURCE)
@IntDef({
UPSTREAM,
DOWNSTREAM_OF_CATALYCIC_CONVERTER,
FROM_OUTSIDE_OR_OFF,
PUMP_ON_FOR_DIAGNOSTICS
})
public @interface Status {}
}
/**
* Represents possible types of fuel;
* see {@link CarDiagnosticSensorIndices.Obd2IntegerSensorIndex#FUEL_TYPE}
*/
public static final class FuelType {
private FuelType() {}
public static final int NOT_AVAILABLE = 0;
public static final int GASOLINE = 1;
public static final int METHANOL = 2;
public static final int ETHANOL = 3;
public static final int DIESEL = 4;
public static final int LPG = 5;
public static final int CNG = 6;
public static final int PROPANE = 7;
public static final int ELECTRIC = 8;
public static final int BIFUEL_RUNNING_GASOLINE = 9;
public static final int BIFUEL_RUNNING_METHANOL = 10;
public static final int BIFUEL_RUNNING_ETHANOL = 11;
public static final int BIFUEL_RUNNING_LPG = 12;
public static final int BIFUEL_RUNNING_CNG = 13;
public static final int BIFUEL_RUNNING_PROPANE = 14;
public static final int BIFUEL_RUNNING_ELECTRIC = 15;
public static final int BIFUEL_RUNNING_ELECTRIC_AND_COMBUSTION = 16;
public static final int HYBRID_GASOLINE = 17;
public static final int HYBRID_ETHANOL = 18;
public static final int HYBRID_DIESEL = 19;
public static final int HYBRID_ELECTRIC = 20;
public static final int HYBRID_RUNNING_ELECTRIC_AND_COMBUSTION = 21;
public static final int HYBRID_REGENERATIVE = 22;
public static final int BIFUEL_RUNNING_DIESEL = 23;
@Retention(RetentionPolicy.SOURCE)
@IntDef({
NOT_AVAILABLE,
GASOLINE,
METHANOL,
ETHANOL,
DIESEL,
LPG,
CNG,
PROPANE,
ELECTRIC,
BIFUEL_RUNNING_GASOLINE,
BIFUEL_RUNNING_METHANOL,
BIFUEL_RUNNING_ETHANOL,
BIFUEL_RUNNING_LPG,
BIFUEL_RUNNING_CNG,
BIFUEL_RUNNING_PROPANE,
BIFUEL_RUNNING_ELECTRIC,
BIFUEL_RUNNING_ELECTRIC_AND_COMBUSTION,
HYBRID_GASOLINE,
HYBRID_ETHANOL,
HYBRID_DIESEL,
HYBRID_ELECTRIC,
HYBRID_RUNNING_ELECTRIC_AND_COMBUSTION,
HYBRID_REGENERATIVE,
BIFUEL_RUNNING_DIESEL
})
public @interface Type {}
}
/**
* Represents possible states of the ignition monitors on the vehicle;
* see {@link CarDiagnosticSensorIndices.Obd2IntegerSensorIndex#IGNITION_MONITORS_SUPPORTED}
* see {@link CarDiagnosticSensorIndices.Obd2IntegerSensorIndex#IGNITION_SPECIFIC_MONITORS}
*/
public static final class IgnitionMonitors {
public static final class IgnitionMonitor {
public final boolean available;
public final boolean incomplete;
IgnitionMonitor(boolean available, boolean incomplete) {
this.available = available;
this.incomplete = incomplete;
}
public static final class Builder {
private int mAvailableBitmask;
private int mIncompleteBitmask;
Builder() {
mAvailableBitmask = 0;
mIncompleteBitmask = 0;
}
public Builder withAvailableBitmask(int bitmask) {
mAvailableBitmask = bitmask;
return this;
}
public Builder withIncompleteBitmask(int bitmask) {
mIncompleteBitmask = bitmask;
return this;
}
public IgnitionMonitor buildForValue(int value) {
boolean available = (0 != (value & mAvailableBitmask));
boolean incomplete = (0 != (value & mIncompleteBitmask));
return new IgnitionMonitor(available, incomplete);
}
}
}
public static class CommonIgnitionMonitors {
public final IgnitionMonitor components;
public final IgnitionMonitor fuelSystem;
public final IgnitionMonitor misfire;
static final int COMPONENTS_AVAILABLE = 0x1 << 0;
static final int COMPONENTS_INCOMPLETE = 0x1 << 1;
static final int FUEL_SYSTEM_AVAILABLE = 0x1 << 2;
static final int FUEL_SYSTEM_INCOMPLETE = 0x1 << 3;
static final int MISFIRE_AVAILABLE = 0x1 << 4;
static final int MISFIRE_INCOMPLETE = 0x1 << 5;
static final IgnitionMonitor.Builder COMPONENTS_BUILDER =
new IgnitionMonitor.Builder()
.withAvailableBitmask(COMPONENTS_AVAILABLE)
.withIncompleteBitmask(COMPONENTS_INCOMPLETE);
static final IgnitionMonitor.Builder FUEL_SYSTEM_BUILDER =
new IgnitionMonitor.Builder()
.withAvailableBitmask(FUEL_SYSTEM_AVAILABLE)
.withIncompleteBitmask(FUEL_SYSTEM_INCOMPLETE);
static final IgnitionMonitor.Builder MISFIRE_BUILDER =
new IgnitionMonitor.Builder()
.withAvailableBitmask(MISFIRE_AVAILABLE)
.withIncompleteBitmask(MISFIRE_INCOMPLETE);
CommonIgnitionMonitors(int bitmask) {
components = COMPONENTS_BUILDER.buildForValue(bitmask);
fuelSystem = FUEL_SYSTEM_BUILDER.buildForValue(bitmask);
misfire = MISFIRE_BUILDER.buildForValue(bitmask);
}
public @Nullable SparkIgnitionMonitors asSparkIgnitionMonitors() {
if (this instanceof SparkIgnitionMonitors)
return (SparkIgnitionMonitors)this;
return null;
}
public @Nullable CompressionIgnitionMonitors asCompressionIgnitionMonitors() {
if (this instanceof CompressionIgnitionMonitors)
return (CompressionIgnitionMonitors)this;
return null;
}
}
public static final class SparkIgnitionMonitors extends CommonIgnitionMonitors {
public final IgnitionMonitor EGR;
public final IgnitionMonitor oxygenSensorHeater;
public final IgnitionMonitor oxygenSensor;
public final IgnitionMonitor ACRefrigerant;
public final IgnitionMonitor secondaryAirSystem;
public final IgnitionMonitor evaporativeSystem;
public final IgnitionMonitor heatedCatalyst;
public final IgnitionMonitor catalyst;
static final int EGR_AVAILABLE = 0x1 << 6;
static final int EGR_INCOMPLETE = 0x1 << 7;
static final int OXYGEN_SENSOR_HEATER_AVAILABLE = 0x1 << 8;
static final int OXYGEN_SENSOR_HEATER_INCOMPLETE = 0x1 << 9;
static final int OXYGEN_SENSOR_AVAILABLE = 0x1 << 10;
static final int OXYGEN_SENSOR_INCOMPLETE = 0x1 << 11;
static final int AC_REFRIGERANT_AVAILABLE = 0x1 << 12;
static final int AC_REFRIGERANT_INCOMPLETE = 0x1 << 13;
static final int SECONDARY_AIR_SYSTEM_AVAILABLE = 0x1 << 14;
static final int SECONDARY_AIR_SYSTEM_INCOMPLETE = 0x1 << 15;
static final int EVAPORATIVE_SYSTEM_AVAILABLE = 0x1 << 16;
static final int EVAPORATIVE_SYSTEM_INCOMPLETE = 0x1 << 17;
static final int HEATED_CATALYST_AVAILABLE = 0x1 << 18;
static final int HEATED_CATALYST_INCOMPLETE = 0x1 << 19;
static final int CATALYST_AVAILABLE = 0x1 << 20;
static final int CATALYST_INCOMPLETE = 0x1 << 21;
static final IgnitionMonitor.Builder EGR_BUILDER =
new IgnitionMonitor.Builder()
.withAvailableBitmask(EGR_AVAILABLE)
.withIncompleteBitmask(EGR_INCOMPLETE);
static final IgnitionMonitor.Builder OXYGEN_SENSOR_HEATER_BUILDER =
new IgnitionMonitor.Builder()
.withAvailableBitmask(OXYGEN_SENSOR_HEATER_AVAILABLE)
.withIncompleteBitmask(OXYGEN_SENSOR_HEATER_INCOMPLETE);
static final IgnitionMonitor.Builder OXYGEN_SENSOR_BUILDER =
new IgnitionMonitor.Builder()
.withAvailableBitmask(OXYGEN_SENSOR_AVAILABLE)
.withIncompleteBitmask(OXYGEN_SENSOR_INCOMPLETE);
static final IgnitionMonitor.Builder AC_REFRIGERANT_BUILDER =
new IgnitionMonitor.Builder()
.withAvailableBitmask(AC_REFRIGERANT_AVAILABLE)
.withIncompleteBitmask(AC_REFRIGERANT_INCOMPLETE);
static final IgnitionMonitor.Builder SECONDARY_AIR_SYSTEM_BUILDER =
new IgnitionMonitor.Builder()
.withAvailableBitmask(SECONDARY_AIR_SYSTEM_AVAILABLE)
.withIncompleteBitmask(SECONDARY_AIR_SYSTEM_INCOMPLETE);
static final IgnitionMonitor.Builder EVAPORATIVE_SYSTEM_BUILDER =
new IgnitionMonitor.Builder()
.withAvailableBitmask(EVAPORATIVE_SYSTEM_AVAILABLE)
.withIncompleteBitmask(EVAPORATIVE_SYSTEM_INCOMPLETE);
static final IgnitionMonitor.Builder HEATED_CATALYST_BUILDER =
new IgnitionMonitor.Builder()
.withAvailableBitmask(HEATED_CATALYST_AVAILABLE)
.withIncompleteBitmask(HEATED_CATALYST_INCOMPLETE);
static final IgnitionMonitor.Builder CATALYST_BUILDER =
new IgnitionMonitor.Builder()
.withAvailableBitmask(CATALYST_AVAILABLE)
.withIncompleteBitmask(CATALYST_INCOMPLETE);
SparkIgnitionMonitors(int bitmask) {
super(bitmask);
EGR = EGR_BUILDER.buildForValue(bitmask);
oxygenSensorHeater = OXYGEN_SENSOR_HEATER_BUILDER.buildForValue(bitmask);
oxygenSensor = OXYGEN_SENSOR_BUILDER.buildForValue(bitmask);
ACRefrigerant = AC_REFRIGERANT_BUILDER.buildForValue(bitmask);
secondaryAirSystem = SECONDARY_AIR_SYSTEM_BUILDER.buildForValue(bitmask);
evaporativeSystem = EVAPORATIVE_SYSTEM_BUILDER.buildForValue(bitmask);
heatedCatalyst = HEATED_CATALYST_BUILDER.buildForValue(bitmask);
catalyst = CATALYST_BUILDER.buildForValue(bitmask);
}
}
public static final class CompressionIgnitionMonitors extends CommonIgnitionMonitors {
public final IgnitionMonitor EGROrVVT;
public final IgnitionMonitor PMFilter;
public final IgnitionMonitor exhaustGasSensor;
public final IgnitionMonitor boostPressure;
public final IgnitionMonitor NOxSCR;
public final IgnitionMonitor NMHCCatalyst;
static final int EGR_OR_VVT_AVAILABLE = 0x1 << 6;
static final int EGR_OR_VVT_INCOMPLETE = 0x1 << 7;
static final int PM_FILTER_AVAILABLE = 0x1 << 8;
static final int PM_FILTER_INCOMPLETE = 0x1 << 9;
static final int EXHAUST_GAS_SENSOR_AVAILABLE = 0x1 << 10;
static final int EXHAUST_GAS_SENSOR_INCOMPLETE = 0x1 << 11;
static final int BOOST_PRESSURE_AVAILABLE = 0x1 << 12;
static final int BOOST_PRESSURE_INCOMPLETE = 0x1 << 13;
static final int NOx_SCR_AVAILABLE = 0x1 << 14;
static final int NOx_SCR_INCOMPLETE = 0x1 << 15;
static final int NMHC_CATALYST_AVAILABLE = 0x1 << 16;
static final int NMHC_CATALYST_INCOMPLETE = 0x1 << 17;
static final IgnitionMonitor.Builder EGR_OR_VVT_BUILDER =
new IgnitionMonitor.Builder()
.withAvailableBitmask(EGR_OR_VVT_AVAILABLE)
.withIncompleteBitmask(EGR_OR_VVT_INCOMPLETE);
static final IgnitionMonitor.Builder PM_FILTER_BUILDER =
new IgnitionMonitor.Builder()
.withAvailableBitmask(PM_FILTER_AVAILABLE)
.withIncompleteBitmask(PM_FILTER_INCOMPLETE);
static final IgnitionMonitor.Builder EXHAUST_GAS_SENSOR_BUILDER =
new IgnitionMonitor.Builder()
.withAvailableBitmask(EXHAUST_GAS_SENSOR_AVAILABLE)
.withIncompleteBitmask(EXHAUST_GAS_SENSOR_INCOMPLETE);
static final IgnitionMonitor.Builder BOOST_PRESSURE_BUILDER =
new IgnitionMonitor.Builder()
.withAvailableBitmask(BOOST_PRESSURE_AVAILABLE)
.withIncompleteBitmask(BOOST_PRESSURE_INCOMPLETE);
static final IgnitionMonitor.Builder NOx_SCR_BUILDER =
new IgnitionMonitor.Builder()
.withAvailableBitmask(NOx_SCR_AVAILABLE)
.withIncompleteBitmask(NOx_SCR_INCOMPLETE);
static final IgnitionMonitor.Builder NMHC_CATALYST_BUILDER =
new IgnitionMonitor.Builder()
.withAvailableBitmask(NMHC_CATALYST_AVAILABLE)
.withIncompleteBitmask(NMHC_CATALYST_INCOMPLETE);
CompressionIgnitionMonitors(int bitmask) {
super(bitmask);
EGROrVVT = EGR_OR_VVT_BUILDER.buildForValue(bitmask);
PMFilter = PM_FILTER_BUILDER.buildForValue(bitmask);
exhaustGasSensor = EXHAUST_GAS_SENSOR_BUILDER.buildForValue(bitmask);
boostPressure = BOOST_PRESSURE_BUILDER.buildForValue(bitmask);
NOxSCR = NOx_SCR_BUILDER.buildForValue(bitmask);
NMHCCatalyst = NMHC_CATALYST_BUILDER.buildForValue(bitmask);
}
}
}
public @Nullable @FuelSystemStatus.Status Integer getFuelSystemStatus() {
return getSystemIntegerSensor(CarDiagnosticSensorIndices.Obd2IntegerSensorIndex.FUEL_SYSTEM_STATUS);
}
public @Nullable @SecondaryAirStatus.Status Integer getSecondaryAirStatus() {
return getSystemIntegerSensor(CarDiagnosticSensorIndices.Obd2IntegerSensorIndex.COMMANDED_SECONDARY_AIR_STATUS);
}
public @Nullable IgnitionMonitors.CommonIgnitionMonitors getIgnitionMonitors() {
Integer ignitionMonitorsType = getSystemIntegerSensor(
CarDiagnosticSensorIndices.Obd2IntegerSensorIndex.IGNITION_MONITORS_SUPPORTED);
Integer ignitionMonitorsBitmask = getSystemIntegerSensor(
CarDiagnosticSensorIndices.Obd2IntegerSensorIndex.IGNITION_SPECIFIC_MONITORS);
if (null == ignitionMonitorsType) return null;
if (null == ignitionMonitorsBitmask) return null;
switch (ignitionMonitorsType) {
case 0: return new IgnitionMonitors.SparkIgnitionMonitors(
ignitionMonitorsBitmask);
case 1: return new IgnitionMonitors.CompressionIgnitionMonitors(
ignitionMonitorsBitmask);
default: return null;
}
}
public @Nullable @FuelType.Type Integer getFuelType() {
return getSystemIntegerSensor(CarDiagnosticSensorIndices.Obd2IntegerSensorIndex.FUEL_TYPE);
}
}