├── res ├── drawable-hdpi │ ├── car.png │ ├── mpg.png │ ├── icon.png │ ├── pump.gif │ ├── temp.png │ ├── compass.png │ ├── ic_launcher.png │ ├── accel_gauge.xml │ └── coolant_gauge.xml ├── drawable-ldpi │ └── ic_launcher.png ├── drawable-mdpi │ └── ic_launcher.png ├── values │ └── strings.xml ├── layout │ ├── command.xml │ └── main.xml └── xml │ └── preferences.xml ├── bin └── classes │ └── awis │ └── obd │ ├── activity │ ├── R.class │ ├── R$id.class │ ├── R$attr.class │ ├── R$xml.class │ ├── R$layout.class │ ├── R$string.class │ ├── R$drawable.class │ ├── ObdReaderMainActivity.class │ ├── ObdReaderCommandActivity.class │ ├── ObdReaderConfigActivity.class │ ├── ObdReaderMainActivity$1.class │ ├── ObdReaderMainActivity$2.class │ ├── ObdReaderMainActivity$3.class │ ├── ObdReaderCommandActivity$1.class │ ├── ObdReaderCommandActivity$2.class │ ├── ObdReaderConfigActivity$1.class │ ├── ObdReaderMainActivity$UpdateThread.class │ └── ObdReaderCommandActivity$ObdReaderCommandActivityWorkerThread.class │ ├── command │ ├── ObdCommand.class │ ├── IntObdCommand.class │ ├── ObdMultiCommand.class │ ├── SpeedObdCommand.class │ ├── TempObdCommand.class │ ├── DtcNumberObdCommand.class │ ├── EngineRPMObdCommand.class │ ├── FuelTrimObdCommand.class │ ├── PressureObdCommand.class │ ├── ThrottleObdCommand.class │ ├── FuelEconomyObdCommand.class │ ├── FuelPressureObdCommand.class │ ├── MassAirFlowObdCommand.class │ ├── TroubleCodesObdCommand.class │ ├── AirIntakeTempObdCommand.class │ ├── EngineRunTimeObdCommand.class │ ├── FuelEconomyMAPObdCommand.class │ ├── TimingAdvanceObdCommand.class │ ├── CommandEquivRatioObdCommand.class │ ├── AverageFuelEconomyObdCommand.class │ ├── IntakeManifoldPressureObdCommand.class │ └── FuelEconomyCommandedMAPObdCommand.class │ ├── config │ └── ObdConfig.class │ ├── io │ ├── ObdConnectThread.class │ ├── ObdReaderService.class │ ├── ObdCommandConnectThread.class │ ├── ObdReaderServiceConnection.class │ ├── ObdReaderService$ObdReaderServiceBinder.class │ └── ObdReaderService$ObdReaderServiceWorkerThread.class │ ├── drawable │ ├── AccelGaugeView.class │ ├── CoolantGaugeView.class │ └── GradientGaugeView.class │ └── exception │ └── ConfigException.class ├── README ├── src └── awis │ └── obd │ ├── command │ ├── AirIntakeTempObdCommand.java │ ├── FuelPressureObdCommand.java │ ├── IntakeManifoldPressureObdCommand.java │ ├── SpeedObdCommand.java │ ├── TempObdCommand.java │ ├── ThrottleObdCommand.java │ ├── FuelTrimObdCommand.java │ ├── PressureObdCommand.java │ ├── TimingAdvanceObdCommand.java │ ├── MassAirFlowObdCommand.java │ ├── EngineRPMObdCommand.java │ ├── EngineRunTimeObdCommand.java │ ├── DtcNumberObdCommand.java │ ├── IntObdCommand.java │ ├── CommandEquivRatioObdCommand.java │ ├── ObdMultiCommand.java │ ├── AverageFuelEconomyObdCommand.java │ ├── FuelEconomyObdCommand.java │ ├── TroubleCodesObdCommand.java │ ├── FuelEconomyCommandedMAPObdCommand.java │ ├── FuelEconomyMAPObdCommand.java │ └── ObdCommand.java │ ├── exception │ └── ConfigException.java │ ├── io │ ├── ObdReaderServiceConnection.java │ ├── ObdCommandConnectThread.java │ ├── ObdReaderService.java │ └── ObdConnectThread.java │ ├── drawable │ ├── GradientGaugeView.java │ ├── AccelGaugeView.java │ └── CoolantGaugeView.java │ ├── config │ └── ObdConfig.java │ └── activity │ ├── ObdReaderCommandActivity.java │ ├── ObdReaderConfigActivity.java │ └── ObdReaderMainActivity.java ├── project.properties ├── .classpath ├── .project ├── proguard.cfg └── AndroidManifest.xml /res/drawable-hdpi/car.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/res/drawable-hdpi/car.png -------------------------------------------------------------------------------- /res/drawable-hdpi/mpg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/res/drawable-hdpi/mpg.png -------------------------------------------------------------------------------- /res/drawable-hdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/res/drawable-hdpi/icon.png -------------------------------------------------------------------------------- /res/drawable-hdpi/pump.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/res/drawable-hdpi/pump.gif -------------------------------------------------------------------------------- /res/drawable-hdpi/temp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/res/drawable-hdpi/temp.png -------------------------------------------------------------------------------- /res/drawable-hdpi/compass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/res/drawable-hdpi/compass.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-ldpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/res/drawable-ldpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /bin/classes/awis/obd/activity/R.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/activity/R.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/activity/R$id.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/activity/R$id.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/activity/R$attr.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/activity/R$attr.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/activity/R$xml.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/activity/R$xml.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/activity/R$layout.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/activity/R$layout.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/activity/R$string.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/activity/R$string.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/command/ObdCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/command/ObdCommand.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/config/ObdConfig.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/config/ObdConfig.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/activity/R$drawable.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/activity/R$drawable.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/io/ObdConnectThread.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/io/ObdConnectThread.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/io/ObdReaderService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/io/ObdReaderService.class -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This app is cloned from http://code.google.com/p/android-obd-reader/ 2 | The purpose of this app is to communicate to ELM327 reader using wizard for easier usage. -------------------------------------------------------------------------------- /bin/classes/awis/obd/command/IntObdCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/command/IntObdCommand.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/command/ObdMultiCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/command/ObdMultiCommand.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/command/SpeedObdCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/command/SpeedObdCommand.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/command/TempObdCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/command/TempObdCommand.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/drawable/AccelGaugeView.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/drawable/AccelGaugeView.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/drawable/CoolantGaugeView.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/drawable/CoolantGaugeView.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/exception/ConfigException.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/exception/ConfigException.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/command/DtcNumberObdCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/command/DtcNumberObdCommand.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/command/EngineRPMObdCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/command/EngineRPMObdCommand.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/command/FuelTrimObdCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/command/FuelTrimObdCommand.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/command/PressureObdCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/command/PressureObdCommand.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/command/ThrottleObdCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/command/ThrottleObdCommand.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/drawable/GradientGaugeView.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/drawable/GradientGaugeView.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/io/ObdCommandConnectThread.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/io/ObdCommandConnectThread.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/activity/ObdReaderMainActivity.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/activity/ObdReaderMainActivity.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/command/FuelEconomyObdCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/command/FuelEconomyObdCommand.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/command/FuelPressureObdCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/command/FuelPressureObdCommand.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/command/MassAirFlowObdCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/command/MassAirFlowObdCommand.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/command/TroubleCodesObdCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/command/TroubleCodesObdCommand.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/io/ObdReaderServiceConnection.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/io/ObdReaderServiceConnection.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/activity/ObdReaderCommandActivity.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/activity/ObdReaderCommandActivity.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/activity/ObdReaderConfigActivity.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/activity/ObdReaderConfigActivity.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/activity/ObdReaderMainActivity$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/activity/ObdReaderMainActivity$1.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/activity/ObdReaderMainActivity$2.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/activity/ObdReaderMainActivity$2.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/activity/ObdReaderMainActivity$3.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/activity/ObdReaderMainActivity$3.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/command/AirIntakeTempObdCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/command/AirIntakeTempObdCommand.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/command/EngineRunTimeObdCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/command/EngineRunTimeObdCommand.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/command/FuelEconomyMAPObdCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/command/FuelEconomyMAPObdCommand.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/command/TimingAdvanceObdCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/command/TimingAdvanceObdCommand.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/activity/ObdReaderCommandActivity$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/activity/ObdReaderCommandActivity$1.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/activity/ObdReaderCommandActivity$2.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/activity/ObdReaderCommandActivity$2.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/activity/ObdReaderConfigActivity$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/activity/ObdReaderConfigActivity$1.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/command/CommandEquivRatioObdCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/command/CommandEquivRatioObdCommand.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/command/AverageFuelEconomyObdCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/command/AverageFuelEconomyObdCommand.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/command/IntakeManifoldPressureObdCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/command/IntakeManifoldPressureObdCommand.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/activity/ObdReaderMainActivity$UpdateThread.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/activity/ObdReaderMainActivity$UpdateThread.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/command/FuelEconomyCommandedMAPObdCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/command/FuelEconomyCommandedMAPObdCommand.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/io/ObdReaderService$ObdReaderServiceBinder.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/io/ObdReaderService$ObdReaderServiceBinder.class -------------------------------------------------------------------------------- /bin/classes/awis/obd/io/ObdReaderService$ObdReaderServiceWorkerThread.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/io/ObdReaderService$ObdReaderServiceWorkerThread.class -------------------------------------------------------------------------------- /res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | OBD Test App 4 | Choose a command 5 | 6 | -------------------------------------------------------------------------------- /bin/classes/awis/obd/activity/ObdReaderCommandActivity$ObdReaderCommandActivityWorkerThread.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awisalkarni/OBD-Bluetooth-Reader/HEAD/bin/classes/awis/obd/activity/ObdReaderCommandActivity$ObdReaderCommandActivityWorkerThread.class -------------------------------------------------------------------------------- /res/drawable-hdpi/accel_gauge.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 7 | 8 | -------------------------------------------------------------------------------- /res/drawable-hdpi/coolant_gauge.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 7 | 8 | -------------------------------------------------------------------------------- /src/awis/obd/command/AirIntakeTempObdCommand.java: -------------------------------------------------------------------------------- 1 | package awis.obd.command; 2 | 3 | public class AirIntakeTempObdCommand extends TempObdCommand{ 4 | 5 | public AirIntakeTempObdCommand() { 6 | super("010F","Air Intake Temp","C","F"); 7 | } 8 | public AirIntakeTempObdCommand(AirIntakeTempObdCommand other) { 9 | super(other); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/awis/obd/exception/ConfigException.java: -------------------------------------------------------------------------------- 1 | package awis.obd.exception; 2 | 3 | public class ConfigException extends Exception { 4 | 5 | public ConfigException(String msg) { 6 | // TODO Auto-generated constructor stub 7 | } 8 | 9 | /** 10 | * 11 | */ 12 | private static final long serialVersionUID = -7089923352166624943L; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/awis/obd/command/FuelPressureObdCommand.java: -------------------------------------------------------------------------------- 1 | package awis.obd.command; 2 | 3 | public class FuelPressureObdCommand extends PressureObdCommand{ 4 | 5 | public FuelPressureObdCommand() { 6 | super("010A","Fuel Press","kPa","atm"); 7 | } 8 | public FuelPressureObdCommand(FuelPressureObdCommand other) { 9 | super(other); 10 | } 11 | public int transform(int b) { 12 | return b*3; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/awis/obd/command/IntakeManifoldPressureObdCommand.java: -------------------------------------------------------------------------------- 1 | package awis.obd.command; 2 | 3 | public class IntakeManifoldPressureObdCommand extends PressureObdCommand { 4 | 5 | public IntakeManifoldPressureObdCommand() { 6 | super("010B","Intake Manifold Press","kPa","atm"); 7 | } 8 | public IntakeManifoldPressureObdCommand(IntakeManifoldPressureObdCommand other) { 9 | super(other); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system use, 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | 10 | # Project target. 11 | target=android-15 12 | -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/awis/obd/command/SpeedObdCommand.java: -------------------------------------------------------------------------------- 1 | package awis.obd.command; 2 | 3 | import awis.obd.config.ObdConfig; 4 | 5 | public class SpeedObdCommand extends IntObdCommand { 6 | 7 | public SpeedObdCommand() { 8 | super("010D",ObdConfig.SPEED,"km/h","mph"); 9 | } 10 | public SpeedObdCommand(SpeedObdCommand other) { 11 | super(other); 12 | } 13 | @Override 14 | public int getImperialInt() { 15 | if (intValue <= 0) { 16 | return 0; 17 | } 18 | return (int)(intValue * .625); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/awis/obd/command/TempObdCommand.java: -------------------------------------------------------------------------------- 1 | package awis.obd.command; 2 | 3 | public class TempObdCommand extends IntObdCommand{ 4 | 5 | public TempObdCommand(String cmd, String desc, String resType, String impType) { 6 | super(cmd, desc, resType, impType); 7 | } 8 | public TempObdCommand(TempObdCommand other) { 9 | super(other); 10 | } 11 | protected int transform(int b) { 12 | return b-40; 13 | } 14 | @Override 15 | public int getImperialInt() { 16 | return (intValue*9/5) + 32; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/awis/obd/command/ThrottleObdCommand.java: -------------------------------------------------------------------------------- 1 | package awis.obd.command; 2 | 3 | public class ThrottleObdCommand extends IntObdCommand { 4 | 5 | public ThrottleObdCommand(String cmd, String desc, String resType) { 6 | super(cmd,desc,resType,resType); 7 | } 8 | public ThrottleObdCommand() { 9 | super("0111","Throttle Position","%","%"); 10 | } 11 | public ThrottleObdCommand(ThrottleObdCommand other) { 12 | super(other); 13 | } 14 | protected int transform(int b) { 15 | return (int)((double)(b*100)/255.0); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/awis/obd/command/FuelTrimObdCommand.java: -------------------------------------------------------------------------------- 1 | package awis.obd.command; 2 | 3 | public class FuelTrimObdCommand extends IntObdCommand { 4 | 5 | public FuelTrimObdCommand(String cmd, String desc, String resType) { 6 | super(cmd,desc,resType,resType); 7 | } 8 | public FuelTrimObdCommand(FuelTrimObdCommand other) { 9 | super(other); 10 | } 11 | 12 | public FuelTrimObdCommand() { 13 | super("0107","Long Term Fuel Trim","%","%"); 14 | } 15 | 16 | @Override 17 | public int transform(int b) { 18 | double perc = (b-128)*(100.0/128); 19 | return (int)perc; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/awis/obd/command/PressureObdCommand.java: -------------------------------------------------------------------------------- 1 | package awis.obd.command; 2 | 3 | public class PressureObdCommand extends IntObdCommand { 4 | 5 | public PressureObdCommand(String cmd, String desc, String resType, String impType) { 6 | super(cmd,desc,resType,impType); 7 | } 8 | public PressureObdCommand(PressureObdCommand other) { 9 | super(other); 10 | } 11 | public String formatResult() { 12 | String res = super.formatResult(); 13 | if (!isImperial() || "NODATA".equals(res)) { 14 | return res; 15 | } 16 | double atm = intValue * 1.0 / 101.3; 17 | return String.format("%.2f %s", atm, impType); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/awis/obd/command/TimingAdvanceObdCommand.java: -------------------------------------------------------------------------------- 1 | package awis.obd.command; 2 | 3 | public class TimingAdvanceObdCommand extends ObdCommand { 4 | 5 | public TimingAdvanceObdCommand() { 6 | super("010E","Timing Advance","deg","deg"); 7 | } 8 | public TimingAdvanceObdCommand(TimingAdvanceObdCommand other) { 9 | super(other); 10 | } 11 | public String formatResult() { 12 | String res = super.formatResult(); 13 | if ("NODATA".equals(res)) { 14 | return "NODATA"; 15 | } 16 | String A = res.substring(4,6); 17 | double a = (double)Integer.parseInt(A,16); 18 | double adv = (a/2.0) / 64; 19 | return String.format("%.1f %s", adv, resType); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/awis/obd/io/ObdReaderServiceConnection.java: -------------------------------------------------------------------------------- 1 | package awis.obd.io; 2 | 3 | import android.content.ComponentName; 4 | import android.content.ServiceConnection; 5 | import android.os.IBinder; 6 | 7 | public class ObdReaderServiceConnection implements ServiceConnection { 8 | 9 | private ObdReaderService service = null; 10 | public void onServiceConnected(ComponentName name, IBinder service) { 11 | this.service = ((ObdReaderService.ObdReaderServiceBinder)service).getService(); 12 | } 13 | public void onServiceDisconnected(ComponentName name) { 14 | service = null; 15 | } 16 | public ObdReaderService getService() { 17 | return service; 18 | } 19 | public boolean isRunning() { 20 | if (service == null) { 21 | return false; 22 | } 23 | return service.isRunning(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/awis/obd/command/MassAirFlowObdCommand.java: -------------------------------------------------------------------------------- 1 | package awis.obd.command; 2 | 3 | public class MassAirFlowObdCommand extends ObdCommand { 4 | 5 | /** 6 | * @uml.property name="maf" 7 | */ 8 | private double maf = -9999.0; 9 | public MassAirFlowObdCommand() { 10 | super("0110","Mass Air Flow","g/s","g/s"); 11 | } 12 | public MassAirFlowObdCommand(MassAirFlowObdCommand other) { 13 | super(other); 14 | } 15 | public String formatResult() { 16 | String res = super.formatResult(); 17 | if ("NODATA".equals(res)) { 18 | return "NODATA"; 19 | } 20 | String A = res.substring(4,6); 21 | String B = res.substring(6,8); 22 | int a = Integer.parseInt(A,16); 23 | int b = Integer.parseInt(B,16); 24 | maf = ((256.0*a)+b) / 100.0; 25 | return Double.toString(maf); 26 | } 27 | double getMAF() { 28 | return maf; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/awis/obd/command/EngineRPMObdCommand.java: -------------------------------------------------------------------------------- 1 | package awis.obd.command; 2 | 3 | import awis.obd.config.ObdConfig; 4 | 5 | public class EngineRPMObdCommand extends IntObdCommand{ 6 | 7 | public EngineRPMObdCommand() { 8 | super("010C",ObdConfig.RPM,"RPM","RPM"); 9 | } 10 | public EngineRPMObdCommand(EngineRPMObdCommand other) { 11 | super(other); 12 | } 13 | public String formatResult() { 14 | String res = getResult(); 15 | String[] ress = res.split("\r"); 16 | res = ress[0].replace(" ",""); 17 | if ("NODATA".equals(res)) { 18 | return "NODATA"; 19 | } 20 | String byteStrOne = res.substring(4,6); 21 | String byteStrTwo = res.substring(6,8); 22 | int a = Integer.parseInt(byteStrOne,16); 23 | int b = Integer.parseInt(byteStrTwo,16); 24 | intValue = transform(a,b); 25 | return String.format("%d %s", intValue, resType); 26 | } 27 | protected int transform(int a, int b) { 28 | return (int)((double)(a*256+b)/4.0); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/awis/obd/command/EngineRunTimeObdCommand.java: -------------------------------------------------------------------------------- 1 | package awis.obd.command; 2 | 3 | import awis.obd.config.ObdConfig; 4 | 5 | 6 | 7 | public class EngineRunTimeObdCommand extends ObdCommand { 8 | 9 | public EngineRunTimeObdCommand() { 10 | super("011F",ObdConfig.RUN_TIME,"",""); 11 | } 12 | public EngineRunTimeObdCommand(EngineRunTimeObdCommand other) { 13 | super(other); 14 | } 15 | @Override 16 | public String formatResult() { 17 | String res = super.formatResult(); 18 | if ("NODATA".equals(res)) { 19 | return "NODATA"; 20 | } 21 | String A = res.substring(4,6); 22 | String B = res.substring(6,8); 23 | int a = Integer.parseInt(A,16); 24 | int b = Integer.parseInt(B,16); 25 | int sec = (a*256)+b; 26 | String hh = String.format("%02d", sec/3600); 27 | String mm = String.format("%02d", (sec%3600)/60); 28 | String ss = String.format("%02d", sec%60); 29 | String time = String.format("%s:%s:%s", hh,mm,ss); 30 | return time; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/awis/obd/command/DtcNumberObdCommand.java: -------------------------------------------------------------------------------- 1 | package awis.obd.command; 2 | 3 | public class DtcNumberObdCommand extends ObdCommand { 4 | 5 | /** 6 | * @uml.property name="codeCount" 7 | */ 8 | private int codeCount = -1; 9 | /** 10 | * @uml.property name="milOn" 11 | */ 12 | private boolean milOn = false; 13 | public DtcNumberObdCommand() { 14 | super("0101","DTC Status","",""); 15 | } 16 | public DtcNumberObdCommand(DtcNumberObdCommand other) { 17 | super(other); 18 | } 19 | public String formatResult() { 20 | String res = super.formatResult(); 21 | String byte1 = res.substring(4,6); 22 | int mil = Integer.parseInt(byte1,16); 23 | String result = "MIL is off, "; 24 | if ((mil & 0x80) == 1) { 25 | milOn = true; 26 | result = "MIL is on, "; 27 | } 28 | codeCount = mil & 0x7f; 29 | result += codeCount + " codes"; 30 | return result; 31 | } 32 | /** 33 | * @return 34 | * @uml.property name="codeCount" 35 | */ 36 | public int getCodeCount() { 37 | return codeCount; 38 | } 39 | public boolean getMilOn() { 40 | return milOn; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/awis/obd/command/IntObdCommand.java: -------------------------------------------------------------------------------- 1 | package awis.obd.command; 2 | 3 | public class IntObdCommand extends ObdCommand { 4 | 5 | /** 6 | * @uml.property name="intValue" 7 | */ 8 | protected int intValue = -9999; 9 | public IntObdCommand(String cmd, String desc, String resType, String impType) { 10 | super(cmd, desc, resType, impType); 11 | } 12 | public IntObdCommand(IntObdCommand other) { 13 | super(other); 14 | } 15 | public String formatResult() { 16 | String res = super.formatResult(); 17 | if ("NODATA".equals(res)) { 18 | return "NODATA"; 19 | } 20 | String byteStr = res.substring(4,6); 21 | int b = Integer.parseInt(byteStr,16); 22 | intValue = transform(b); 23 | if (isImperial()) { 24 | return String.format("%s %s", Integer.toString(getImperialInt()), impType); 25 | } else { 26 | return String.format("%s %s", Integer.toString(intValue), resType); 27 | } 28 | } 29 | protected int transform(int b) { 30 | return b; 31 | } 32 | public int getInt() { 33 | return intValue; 34 | } 35 | public int getImperialInt() { 36 | return intValue; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /res/layout/command.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 15 | 19 | 22 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/awis/obd/command/CommandEquivRatioObdCommand.java: -------------------------------------------------------------------------------- 1 | package awis.obd.command; 2 | 3 | public class CommandEquivRatioObdCommand extends ObdCommand { 4 | 5 | /** 6 | * @uml.property name="ratio" 7 | */ 8 | private double ratio = 1.0; 9 | public CommandEquivRatioObdCommand() { 10 | super("0144","Command Equivalence Ratio","",""); 11 | } 12 | public CommandEquivRatioObdCommand(String cmd, String desc, String resType, String impType) { 13 | super(cmd, desc, resType, impType); 14 | } 15 | public CommandEquivRatioObdCommand(CommandEquivRatioObdCommand other) { 16 | super(other); 17 | } 18 | public String formatResult() { 19 | String res = super.formatResult(); 20 | if ("NODATA".equals(res)) { 21 | return "NODATA"; 22 | } 23 | try { 24 | String A = res.substring(4,6); 25 | String B = res.substring(6,8); 26 | int a = Integer.parseInt(A,16); 27 | int b = Integer.parseInt(B,16); 28 | ratio = ((a*256)+b)*0.0000305; 29 | } catch (Exception e) { 30 | setError(e); 31 | } 32 | return String.format("%.2f", ratio); 33 | } 34 | /** 35 | * @return 36 | * @uml.property name="ratio" 37 | */ 38 | double getRatio() { 39 | return ratio; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | OBD Reader 4 | @key 32303037303533312D3130204F4244205265616465722F41776973 5 | 6 | 7 | 8 | 9 | com.android.ide.eclipse.adt.ResourceManagerBuilder 10 | 11 | 12 | 13 | 14 | com.android.ide.eclipse.adt.PreCompilerBuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.jdt.core.javabuilder 20 | 21 | 22 | 23 | 24 | com.android.ide.eclipse.adt.ApkBuilder 25 | 26 | 27 | 28 | 29 | com.soyatec.additional.Builder 30 | 31 | 32 | 33 | 34 | 35 | com.android.ide.eclipse.adt.AndroidNature 36 | org.eclipse.jdt.core.javanature 37 | com.soyatec.additional.Nature 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/awis/obd/command/ObdMultiCommand.java: -------------------------------------------------------------------------------- 1 | package awis.obd.command; 2 | 3 | import java.io.IOException; 4 | 5 | public class ObdMultiCommand extends ObdCommand { 6 | 7 | /** 8 | * @uml.property name="cmds" multiplicity="(0 -1)" dimension="1" 9 | */ 10 | private String[] cmds; 11 | 12 | public ObdMultiCommand(String[] cmds, String desc, String resType, String impType) { 13 | super(null, desc, resType, impType); 14 | this.cmds = cmds; 15 | } 16 | public ObdMultiCommand(ObdMultiCommand other) { 17 | this(other.cmds, other.desc, other.resType, other.impType); 18 | } 19 | public void run() { 20 | buff.clear(); 21 | for (int i = 0; i < cmds.length; i++) { 22 | String cmd = cmds[i]; 23 | sendCmd(cmd); 24 | readResult(); 25 | } 26 | } 27 | protected void readResult() { 28 | byte c = 0; 29 | try { 30 | while ((char)(c = (byte)in.read()) != '>') { 31 | buff.add(c); 32 | } 33 | buff.add((byte)'\n'); 34 | } catch (IOException e) { 35 | } 36 | } 37 | public String getCmd() { 38 | String cmd = ""; 39 | for (int i = 0; i < cmds.length; i++) { 40 | cmd += cmds[i]; 41 | if (i+1 < cmds.length) { 42 | cmd += ","; 43 | } 44 | } 45 | return cmd; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/awis/obd/command/AverageFuelEconomyObdCommand.java: -------------------------------------------------------------------------------- 1 | package awis.obd.command; 2 | 3 | public class AverageFuelEconomyObdCommand extends ObdCommand { 4 | 5 | public static final String FUEL_ECONOMY_KEY = "Fuel Economy"; 6 | public static final String AVG_FUEL_ECONOMY_KEY = "Fuel Economy Average"; 7 | public static final String AVG_FUEL_ECONOMY_COUNT_KEY = "Average Fuel Economy Count"; 8 | 9 | public AverageFuelEconomyObdCommand() { 10 | super("",AVG_FUEL_ECONOMY_KEY,"kmpg","mpg"); 11 | } 12 | public AverageFuelEconomyObdCommand(AverageFuelEconomyObdCommand other) { 13 | super(other); 14 | } 15 | public String formatResult() { 16 | Double ampg = 0.0; 17 | Integer count = 0; 18 | Double mpg = 0.0; 19 | if (data.containsKey(AVG_FUEL_ECONOMY_KEY)) { 20 | ampg = (Double)data.get(AVG_FUEL_ECONOMY_KEY); 21 | count = (Integer)data.get(AVG_FUEL_ECONOMY_COUNT_KEY); 22 | } 23 | if (data.containsKey(FUEL_ECONOMY_KEY)) { 24 | mpg = (Double)data.get(FUEL_ECONOMY_KEY); 25 | } 26 | if (mpg > 0) { 27 | ampg += mpg; 28 | count += 1; 29 | data.put(AVG_FUEL_ECONOMY_KEY, ampg); 30 | data.put(AVG_FUEL_ECONOMY_COUNT_KEY, count); 31 | } 32 | if (count > 0) { 33 | ampg = ampg / (double)count; 34 | } 35 | return String.format("%.1f mpg", ampg); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /proguard.cfg: -------------------------------------------------------------------------------- 1 | -optimizationpasses 5 2 | -dontusemixedcaseclassnames 3 | -dontskipnonpubliclibraryclasses 4 | -dontpreverify 5 | -verbose 6 | -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* 7 | 8 | -keep public class * extends android.app.Activity 9 | -keep public class * extends android.app.Application 10 | -keep public class * extends android.app.Service 11 | -keep public class * extends android.content.BroadcastReceiver 12 | -keep public class * extends android.content.ContentProvider 13 | -keep public class * extends android.app.backup.BackupAgentHelper 14 | -keep public class * extends android.preference.Preference 15 | -keep public class com.android.vending.licensing.ILicensingService 16 | 17 | -keepclasseswithmembernames class * { 18 | native ; 19 | } 20 | 21 | -keepclasseswithmembers class * { 22 | public (android.content.Context, android.util.AttributeSet); 23 | } 24 | 25 | -keepclasseswithmembers class * { 26 | public (android.content.Context, android.util.AttributeSet, int); 27 | } 28 | 29 | -keepclassmembers class * extends android.app.Activity { 30 | public void *(android.view.View); 31 | } 32 | 33 | -keepclassmembers enum * { 34 | public static **[] values(); 35 | public static ** valueOf(java.lang.String); 36 | } 37 | 38 | -keep class * implements android.os.Parcelable { 39 | public static final android.os.Parcelable$Creator *; 40 | } 41 | -------------------------------------------------------------------------------- /src/awis/obd/drawable/GradientGaugeView.java: -------------------------------------------------------------------------------- 1 | package awis.obd.drawable; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Paint; 6 | import android.graphics.drawable.Drawable; 7 | import android.graphics.drawable.ShapeDrawable; 8 | import android.graphics.drawable.shapes.RectShape; 9 | import android.util.AttributeSet; 10 | import android.util.Log; 11 | import android.view.View; 12 | 13 | public abstract class GradientGaugeView extends View { 14 | 15 | /** 16 | * @uml.property name="context" 17 | * @uml.associationEnd multiplicity="(1 1)" 18 | */ 19 | protected Context context = null; 20 | /** 21 | * @uml.property name="paint" 22 | * @uml.associationEnd multiplicity="(1 1)" 23 | */ 24 | protected Paint paint = null; 25 | 26 | public GradientGaugeView(Context context, AttributeSet attrs) { 27 | super(context, attrs); 28 | this.context = context; 29 | paint = new Paint(); 30 | } 31 | 32 | @Override 33 | protected abstract void onDraw(Canvas canvas); 34 | 35 | protected void drawGradient(Canvas canvas, Drawable container, int offset, double value, double range) { 36 | int width = getWidth(); 37 | int height = getHeight(); 38 | int left = getLeft(); 39 | int top = getTop(); 40 | Log.i("width",String.format("%d %d",width,left)); 41 | container.setBounds(left,top+offset,left+width,top+height+offset); 42 | container.draw(canvas); 43 | ShapeDrawable cover = new ShapeDrawable(new RectShape()); 44 | double perc = value / range; 45 | int coverLeft = (int)(width * perc); 46 | cover.setBounds(left+coverLeft, top+offset, left+width, top+height+offset); 47 | cover.draw(canvas); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/awis/obd/drawable/AccelGaugeView.java: -------------------------------------------------------------------------------- 1 | package awis.obd.drawable; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | import android.graphics.Canvas; 6 | import android.graphics.Color; 7 | import android.graphics.Paint; 8 | import android.graphics.Typeface; 9 | import android.graphics.drawable.Drawable; 10 | import android.util.AttributeSet; 11 | import awis.obd.activity.R; 12 | 13 | public class AccelGaugeView extends GradientGaugeView { 14 | 15 | public final static int TEXT_SIZE = 15; 16 | public final static int range = 20; 17 | /** 18 | * @uml.property name="accel" 19 | */ 20 | private double accel = 2; 21 | 22 | public AccelGaugeView(Context context, AttributeSet attrs) { 23 | super(context, attrs); 24 | this.context = context; 25 | paint = new Paint(); 26 | paint.setTextSize(TEXT_SIZE); 27 | Typeface bold = Typeface.defaultFromStyle(Typeface.BOLD); 28 | paint.setTypeface(bold); 29 | paint.setStrokeWidth(3); 30 | paint.setStyle(Paint.Style.FILL); 31 | } 32 | 33 | /** 34 | * @param accel 35 | * @uml.property name="accel" 36 | */ 37 | public void setAccel(double accel) { 38 | this.accel = accel; 39 | } 40 | 41 | @Override 42 | protected void onDraw(Canvas canvas) { 43 | Resources res = context.getResources(); 44 | Drawable container = (Drawable) res.getDrawable(R.drawable.accel_gauge); 45 | int width = getWidth(); 46 | int left = getLeft(); 47 | int top = getTop(); 48 | paint.setColor(Color.GREEN); 49 | canvas.drawText("Soft",left,top+TEXT_SIZE,paint); 50 | paint.setColor(Color.RED); 51 | canvas.drawText("Hard", left+width-TEXT_SIZE*3, top+TEXT_SIZE, paint); 52 | drawGradient(canvas, container, TEXT_SIZE+5, accel, range); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/awis/obd/io/ObdCommandConnectThread.java: -------------------------------------------------------------------------------- 1 | package awis.obd.io; 2 | 3 | import awis.obd.activity.ObdReaderCommandActivity; 4 | import awis.obd.command.ObdCommand; 5 | import awis.obd.config.ObdConfig; 6 | 7 | import android.bluetooth.BluetoothDevice; 8 | 9 | public class ObdCommandConnectThread extends ObdConnectThread { 10 | 11 | /** 12 | * @uml.property name="cmd" 13 | * @uml.associationEnd multiplicity="(1 1)" 14 | */ 15 | private ObdCommand cmd = null; 16 | /** 17 | * @uml.property name="activity" 18 | * @uml.associationEnd multiplicity="(1 1)" 19 | */ 20 | private ObdReaderCommandActivity activity = null; 21 | 22 | public ObdCommandConnectThread(BluetoothDevice dev, ObdReaderCommandActivity activity, ObdCommand cmd, double ed, double ve, boolean imperialUnits) { 23 | super(dev, null, null, null, 0, ed, ve, imperialUnits, false, ObdConfig.getAllCommands()); 24 | this.cmd = cmd; 25 | this.activity = activity; 26 | } 27 | 28 | public void run() { 29 | try { 30 | activity.logMsg("Starting device..."); 31 | startDevice(); 32 | activity.logMsg("Device started, running " + cmd.getCmd() + "..."); 33 | cmd.setConnectThread(this); 34 | String res = runCommand(cmd); 35 | String rawRes = cmd.getResult().replace("\r","\\r").replace("\n","\\n"); 36 | activity.logMsg("Raw result is '" + rawRes + "'"); 37 | results.put(cmd.getDesc(), res); 38 | if (cmd.getError() != null) { 39 | activity.logMsg(cmd.getError().getMessage()); 40 | activity.logMsg(getStackTrace(cmd.getError())); 41 | } 42 | } catch (Exception e) { 43 | activity.logMsg("Error running command: " + e.getMessage() + ", result was: '" + cmd.getResult() + "'"); 44 | activity.logMsg("Error was: " + getStackTrace(e)); 45 | } finally { 46 | close(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/awis/obd/command/FuelEconomyObdCommand.java: -------------------------------------------------------------------------------- 1 | package awis.obd.command; 2 | 3 | import awis.obd.config.ObdConfig; 4 | 5 | public class FuelEconomyObdCommand extends ObdCommand { 6 | 7 | public static final double AIR_FUEL_RATIO = 14.64; 8 | public static final double FUEL_DENSITY_GRAMS_PER_LITER = 720.0; 9 | /** 10 | * @uml.property name="fuelEcon" 11 | */ 12 | protected double fuelEcon = -9999.0; 13 | 14 | public FuelEconomyObdCommand(String cmd, String desc, String resType, String impType) { 15 | super(cmd,desc,resType,impType); 16 | } 17 | public FuelEconomyObdCommand() { 18 | super("",ObdConfig.FUEL_ECON,"kml","mpg"); 19 | } 20 | public FuelEconomyObdCommand(FuelEconomyObdCommand other) { 21 | super(other); 22 | } 23 | public void run() { 24 | try { 25 | MassAirFlowObdCommand maf = new MassAirFlowObdCommand(); 26 | SpeedObdCommand speed = new SpeedObdCommand(); 27 | runCmd(maf); 28 | maf.formatResult(); 29 | double mafV = maf.getMAF(); 30 | if (mafV == -9999.0) { 31 | fuelEcon = -9999.0; 32 | } 33 | runCmd(speed); 34 | speed.formatResult(); 35 | double speedV = (double)speed.getInt(); 36 | fuelEcon = (14.7 * 6.17 * 454.0 * speedV * 0.621371) / (3600.0 * mafV); 37 | } catch (Exception e) { 38 | setError(e); 39 | } 40 | } 41 | public void runCmd(ObdCommand cmd) { 42 | cmd.setInputStream(in); 43 | cmd.setOutputStream(out); 44 | cmd.start(); 45 | try { 46 | cmd.join(); 47 | } catch (InterruptedException e) { 48 | setError(e); 49 | } 50 | } 51 | public String formatResult() { 52 | if (fuelEcon < 0) { 53 | return "NODATA"; 54 | } 55 | if (!isImperial()) { 56 | double kml = fuelEcon * 0.354013; 57 | return String.format("%.1f %s", kml, resType); 58 | } 59 | return String.format("%.1f %s", fuelEcon, impType); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/awis/obd/drawable/CoolantGaugeView.java: -------------------------------------------------------------------------------- 1 | package awis.obd.drawable; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | import android.graphics.Canvas; 6 | import android.graphics.Color; 7 | import android.graphics.Paint; 8 | import android.graphics.Typeface; 9 | import android.graphics.drawable.Drawable; 10 | import android.util.AttributeSet; 11 | import awis.obd.activity.R; 12 | 13 | public class CoolantGaugeView extends GradientGaugeView { 14 | 15 | public final static int min_temp = 35; 16 | public final static int max_temp = 138; 17 | public final static int TEXT_SIZE = 18; 18 | public final static int range = max_temp - min_temp; 19 | /** 20 | * @uml.property name="temp" 21 | */ 22 | private int temp = min_temp; 23 | 24 | public CoolantGaugeView(Context context, AttributeSet attrs) { 25 | super(context, attrs); 26 | this.context = context; 27 | paint = new Paint(); 28 | paint.setTextSize(TEXT_SIZE); 29 | Typeface bold = Typeface.defaultFromStyle(Typeface.BOLD); 30 | paint.setTypeface(bold); 31 | paint.setStrokeWidth(3); 32 | paint.setStyle(Paint.Style.FILL_AND_STROKE); 33 | } 34 | 35 | /** 36 | * @param temp 37 | * @uml.property name="temp" 38 | */ 39 | public void setTemp(int temp) { 40 | this.temp = temp; 41 | if (this.temp < min_temp) { 42 | this.temp = min_temp + 2; 43 | } 44 | if (this.temp > max_temp) { 45 | this.temp = max_temp; 46 | } 47 | invalidate(); 48 | } 49 | 50 | @Override 51 | protected void onDraw(Canvas canvas) { 52 | Resources res = context.getResources(); 53 | Drawable container = (Drawable) res.getDrawable(R.drawable.coolant_gauge); 54 | int width = getWidth(); 55 | int left = getLeft(); 56 | int top = getTop(); 57 | paint.setColor(Color.BLUE); 58 | canvas.drawText("C",left,top+TEXT_SIZE,paint); 59 | paint.setColor(Color.RED); 60 | canvas.drawText("H", left+width-TEXT_SIZE, top+TEXT_SIZE, paint); 61 | drawGradient(canvas, container, TEXT_SIZE+5, temp-min_temp,range); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/awis/obd/command/TroubleCodesObdCommand.java: -------------------------------------------------------------------------------- 1 | package awis.obd.command; 2 | 3 | public class TroubleCodesObdCommand extends ObdCommand { 4 | 5 | protected final static char[] dtcLetters = {'P','C','B','U'}; 6 | /** 7 | * @uml.property name="codes" 8 | */ 9 | private StringBuffer codes = null; 10 | public TroubleCodesObdCommand() { 11 | super("03","Trouble Codes","",""); 12 | codes = new StringBuffer(); 13 | } 14 | public TroubleCodesObdCommand(String cmd, String desc, String resType, String impType) { 15 | super(cmd, desc, resType, impType); 16 | codes = new StringBuffer(); 17 | } 18 | public TroubleCodesObdCommand(TroubleCodesObdCommand other) { 19 | super(other); 20 | codes = new StringBuffer(); 21 | } 22 | public void run() { 23 | DtcNumberObdCommand numCmd = new DtcNumberObdCommand(); 24 | numCmd.setInputStream(in); 25 | numCmd.setOutputStream(out); 26 | numCmd.start(); 27 | try { 28 | numCmd.join(); 29 | } catch (InterruptedException e) { 30 | setError(e); 31 | } 32 | int count = numCmd.getCodeCount(); 33 | int dtcNum = (count+2)/3; 34 | for (int i = 0; i < dtcNum; i++) { 35 | sendCmd(cmd); 36 | String res = getResult(); 37 | for (int j = 0; j < 3; j++) { 38 | String byte1 = res.substring(3+j*6,5+j*6); 39 | String byte2 = res.substring(6+j*6,8+j*6); 40 | int b1 = Integer.parseInt(byte1,16); 41 | int b2 = Integer.parseInt(byte2,16); 42 | int val = (b1 << 8) + b2; 43 | if (val == 0) { 44 | break; 45 | } 46 | String code = "P"; 47 | if ((val&0xC000) > 14) { 48 | code = "C"; 49 | } 50 | code += Integer.toString((val&0x3000)>>12); 51 | code += Integer.toString((val&0x0fff)); 52 | codes.append(code); 53 | codes.append("\n"); 54 | } 55 | } 56 | } 57 | public String formatResult() { 58 | String res = getResult(); 59 | String[] ress = res.split("\r"); 60 | for (String r:ress) { 61 | String k = r.replace("\r",""); 62 | codes.append(k); 63 | codes.append("\n"); 64 | } 65 | return codes.toString(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/awis/obd/command/FuelEconomyCommandedMAPObdCommand.java: -------------------------------------------------------------------------------- 1 | package awis.obd.command; 2 | 3 | 4 | public class FuelEconomyCommandedMAPObdCommand extends FuelEconomyObdCommand { 5 | 6 | public static final double AIR_FUEL_RATIO = 14.64; 7 | public static final double FUEL_DENSITY_GRAMS_PER_LITER = 720.0; 8 | 9 | public FuelEconomyCommandedMAPObdCommand() { 10 | super("","Fuel Economy Cmd. MAP","kml","mpg"); 11 | } 12 | public FuelEconomyCommandedMAPObdCommand(FuelEconomyCommandedMAPObdCommand other) { 13 | super(other); 14 | } 15 | public void run() { 16 | try { 17 | EngineRPMObdCommand rpm = new EngineRPMObdCommand(); 18 | AirIntakeTempObdCommand temp = new AirIntakeTempObdCommand(); 19 | SpeedObdCommand speed = new SpeedObdCommand(); 20 | IntakeManifoldPressureObdCommand press = new IntakeManifoldPressureObdCommand(); 21 | runCmd(rpm); 22 | rpm.formatResult(); 23 | double rpmV = rpm.getInt(); 24 | runCmd(speed); 25 | speed.formatResult(); 26 | double speedV = (double)speed.getInt(); 27 | runCmd(temp); 28 | temp.formatResult(); 29 | double tempV = temp.getInt() + 273.15; //convert to K 30 | runCmd(press); 31 | press.formatResult(); 32 | double pressV = press.getInt(); 33 | double imap = rpmV * pressV / tempV; 34 | double ve = 1.0; 35 | double ed = 1.0; 36 | if (connectThread != null) { 37 | ve = connectThread.getVolumetricEfficiency(); 38 | ed = connectThread.getEngineDisplacement(); 39 | } 40 | double mafV = (imap/120.0) * ve * ed * 28.97 / 8.314; 41 | String res = String.format("%.1f rpm, %.1f speed, %.1f temp, %.1f press, %.1f maf", rpmV, speedV, tempV, pressV, mafV); 42 | for (int i = 0; i < res.length(); i ++) { 43 | buff.add((byte)res.charAt(i)); 44 | } 45 | fuelEcon = (14.7 * 6.17 * 454.0 * speedV * 0.621371) / (3600.0 * mafV); 46 | } catch (Exception e) { 47 | setError(e); 48 | } 49 | } 50 | public void runCmd(ObdCommand cmd) { 51 | cmd.setInputStream(in); 52 | cmd.setOutputStream(out); 53 | cmd.start(); 54 | try { 55 | cmd.join(); 56 | } catch (InterruptedException e) { 57 | setError(e); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 21 | 25 | 26 | 27 | 28 | 29 | 30 | 32 | 33 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/awis/obd/command/FuelEconomyMAPObdCommand.java: -------------------------------------------------------------------------------- 1 | package awis.obd.command; 2 | 3 | import awis.obd.config.ObdConfig; 4 | 5 | 6 | public class FuelEconomyMAPObdCommand extends FuelEconomyObdCommand { 7 | 8 | public static final double AIR_FUEL_RATIO = 14.64; 9 | public static final double FUEL_DENSITY_GRAMS_PER_LITER = 720.0; 10 | 11 | public FuelEconomyMAPObdCommand() { 12 | super("",ObdConfig.FUEL_ECON_MAP,"kml","mpg"); 13 | } 14 | public FuelEconomyMAPObdCommand(FuelEconomyMAPObdCommand other) { 15 | super(other); 16 | } 17 | public void run() { 18 | try { 19 | EngineRPMObdCommand rpm = new EngineRPMObdCommand(); 20 | AirIntakeTempObdCommand temp = new AirIntakeTempObdCommand(); 21 | SpeedObdCommand speed = new SpeedObdCommand(); 22 | CommandEquivRatioObdCommand equiv = new CommandEquivRatioObdCommand(); 23 | IntakeManifoldPressureObdCommand press = new IntakeManifoldPressureObdCommand(); 24 | runCmd(rpm); 25 | rpm.formatResult(); 26 | double rpmV = rpm.getInt(); 27 | runCmd(speed); 28 | speed.formatResult(); 29 | double speedV = (double)speed.getInt(); 30 | runCmd(temp); 31 | temp.formatResult(); 32 | double tempV = temp.getInt() + 273.15; //convert to K 33 | runCmd(press); 34 | press.formatResult(); 35 | double pressV = press.getInt(); 36 | runCmd(equiv); 37 | equiv.formatResult(); 38 | double equivV = equiv.getRatio(); 39 | double imap = rpmV * pressV / tempV; 40 | double ve = 1.0; 41 | double ed = 1.0; 42 | if (connectThread != null) { 43 | ve = connectThread.getVolumetricEfficiency(); 44 | ed = connectThread.getEngineDisplacement(); 45 | } 46 | double mafV = (imap/120.0) * ve * ed * 28.97 / 8.314; 47 | String res = String.format("%.1f rpm, %.1f speed, %.1f temp, %.1f press, %.1f maf", rpmV, speedV, tempV, pressV, mafV); 48 | for (int i = 0; i < res.length(); i ++) { 49 | buff.add((byte)res.charAt(i)); 50 | } 51 | fuelEcon = (14.7 * equivV * 6.17 * 454.0 * speedV * 0.621371) / (3600.0 * mafV); 52 | } catch (Exception e) { 53 | setError(e); 54 | } 55 | } 56 | public void runCmd(ObdCommand cmd) { 57 | cmd.setInputStream(in); 58 | cmd.setOutputStream(out); 59 | cmd.start(); 60 | try { 61 | cmd.join(); 62 | } catch (InterruptedException e) { 63 | setError(e); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /res/xml/preferences.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 11 | 18 | 19 | 26 | 27 | 33 | 34 | 40 | 41 | 47 | 48 | 54 | 55 | 61 | 62 | 63 | 65 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /src/awis/obd/config/ObdConfig.java: -------------------------------------------------------------------------------- 1 | package awis.obd.config; 2 | 3 | import java.util.ArrayList; 4 | 5 | import awis.obd.command.AirIntakeTempObdCommand; 6 | import awis.obd.command.CommandEquivRatioObdCommand; 7 | import awis.obd.command.DtcNumberObdCommand; 8 | import awis.obd.command.EngineRPMObdCommand; 9 | import awis.obd.command.EngineRunTimeObdCommand; 10 | import awis.obd.command.FuelEconomyCommandedMAPObdCommand; 11 | import awis.obd.command.FuelEconomyMAPObdCommand; 12 | import awis.obd.command.FuelEconomyObdCommand; 13 | import awis.obd.command.FuelPressureObdCommand; 14 | import awis.obd.command.FuelTrimObdCommand; 15 | import awis.obd.command.IntakeManifoldPressureObdCommand; 16 | import awis.obd.command.MassAirFlowObdCommand; 17 | import awis.obd.command.ObdCommand; 18 | import awis.obd.command.PressureObdCommand; 19 | import awis.obd.command.SpeedObdCommand; 20 | import awis.obd.command.TempObdCommand; 21 | import awis.obd.command.ThrottleObdCommand; 22 | import awis.obd.command.TimingAdvanceObdCommand; 23 | import awis.obd.command.TroubleCodesObdCommand; 24 | 25 | public class ObdConfig { 26 | 27 | public final static String COOLANT_TEMP = "Coolant Temp"; 28 | public final static String FUEL_ECON = "Fuel Economy"; 29 | public final static String FUEL_ECON_MAP = "Fuel Economy MAP"; 30 | public final static String RPM = "Engine RPM"; 31 | public final static String RUN_TIME = "Engine Runtime"; 32 | public final static String SPEED = "Vehicle Speed"; 33 | public final static String AIR_TEMP = "Ambient Air Temp"; 34 | public final static String INTAKE_TEMP = "Air Intake Temp"; 35 | 36 | public static ArrayList getCommands() { 37 | ArrayList cmds = new ArrayList(); 38 | cmds.add(new AirIntakeTempObdCommand()); 39 | cmds.add(new IntakeManifoldPressureObdCommand()); 40 | cmds.add(new PressureObdCommand("0133","Barometric Press","kPa","atm")); 41 | cmds.add(new TempObdCommand("0146",AIR_TEMP,"C","F")); 42 | cmds.add(new SpeedObdCommand()); 43 | cmds.add(new ThrottleObdCommand()); 44 | cmds.add(new EngineRPMObdCommand()); 45 | cmds.add(new FuelPressureObdCommand()); 46 | cmds.add(new TempObdCommand("0105",COOLANT_TEMP,"C","F")); 47 | cmds.add(new ThrottleObdCommand("0104","Engine Load","%")); 48 | cmds.add(new MassAirFlowObdCommand()); 49 | cmds.add(new FuelEconomyObdCommand()); 50 | cmds.add(new FuelEconomyMAPObdCommand()); 51 | cmds.add(new FuelEconomyCommandedMAPObdCommand()); 52 | cmds.add(new FuelTrimObdCommand()); 53 | cmds.add(new FuelTrimObdCommand("0106","Short Term Fuel Trim","%")); 54 | cmds.add(new EngineRunTimeObdCommand()); 55 | cmds.add(new CommandEquivRatioObdCommand()); 56 | cmds.add(new TimingAdvanceObdCommand()); 57 | cmds.add(new ObdCommand("03","Trouble Codes","","")); 58 | return cmds; 59 | } 60 | public static ArrayList getStaticCommands() { 61 | ArrayList cmds = new ArrayList(); 62 | cmds.add(new DtcNumberObdCommand()); 63 | cmds.add(new TroubleCodesObdCommand("03","Trouble Codes","","")); 64 | cmds.add(new ObdCommand("04","Reset Codes","","")); 65 | cmds.add(new ObdCommand("atz\ratz\ratz\r","Serial Reset atz","","")); 66 | cmds.add(new ObdCommand("atz\ratz\ratz\rate0","Serial Echo Off ate0","","")); 67 | cmds.add(new ObdCommand("ate1","Serial Echo On ate1","","")); 68 | cmds.add(new ObdCommand("atsp0","Reset Protocol astp0","","")); 69 | cmds.add(new ObdCommand("atspa2","Reset Protocol atspa2","","")); 70 | return cmds; 71 | } 72 | public static ArrayList getAllCommands() { 73 | ArrayList cmds = new ArrayList(); 74 | cmds.addAll(getStaticCommands()); 75 | cmds.addAll(getCommands()); 76 | return cmds; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /res/layout/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 12 | 15 | 18 | 23 | 27 | 33 | 34 | 35 | 39 | 42 | 47 | 53 | 58 | 59 | 74 | 75 | 80 | 83 | 86 | 89 | 92 | 95 | 96 | 97 | 101 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /src/awis/obd/command/ObdCommand.java: -------------------------------------------------------------------------------- 1 | package awis.obd.command; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | import java.util.ArrayList; 7 | import java.util.HashMap; 8 | 9 | import awis.obd.io.ObdConnectThread; 10 | 11 | public class ObdCommand extends Thread { 12 | 13 | /** 14 | * @uml.property name="in" 15 | */ 16 | protected InputStream in = null; 17 | /** 18 | * @uml.property name="out" 19 | */ 20 | protected OutputStream out = null; 21 | /** 22 | * @uml.property name="buff" 23 | * @uml.associationEnd multiplicity="(0 -1)" elementType="java.lang.Byte" 24 | */ 25 | protected ArrayList buff = null; 26 | /** 27 | * @uml.property name="cmd" 28 | */ 29 | protected String cmd = null; 30 | /** 31 | * @uml.property name="desc" 32 | */ 33 | protected String desc = null; 34 | /** 35 | * @uml.property name="resType" 36 | */ 37 | protected String resType = null; 38 | /** 39 | * @uml.property name="error" 40 | */ 41 | protected Exception error; 42 | /** 43 | * @uml.property name="rawValue" 44 | */ 45 | protected Object rawValue = null; 46 | /** 47 | * @uml.property name="data" 48 | * @uml.associationEnd qualifier="constant:java.lang.String java.lang.Double" 49 | */ 50 | protected HashMap data = null; 51 | /** 52 | * @uml.property name="connectThread" 53 | * @uml.associationEnd inverse="cmds:awis.obd.io.ObdConnectThread" 54 | */ 55 | protected ObdConnectThread connectThread = null; 56 | /** 57 | * @uml.property name="impType" 58 | */ 59 | protected String impType = null; 60 | 61 | public ObdCommand(String cmd, String desc, String resType, String impType) { 62 | this.cmd = cmd; 63 | this.desc = desc; 64 | this.resType = resType; 65 | this.buff = new ArrayList(); 66 | this.impType = impType; 67 | } 68 | /** 69 | * @param thread 70 | * @uml.property name="connectThread" 71 | */ 72 | public void setConnectThread(ObdConnectThread thread) { 73 | this.connectThread = thread; 74 | } 75 | public boolean isImperial() { 76 | if (connectThread != null && connectThread.getImperialUnits()) { 77 | return true; 78 | } 79 | return false; 80 | } 81 | public ObdCommand(ObdCommand other) { 82 | this(other.cmd, other.desc, other.resType, other.impType); 83 | } 84 | public void setInputStream(InputStream in) { 85 | this.in = in; 86 | } 87 | public void setOutputStream(OutputStream out) { 88 | this.out = out; 89 | } 90 | public void run() { 91 | sendCmd(cmd); 92 | readResult(); 93 | } 94 | public void setDataMap(HashMap data) { 95 | this.data = data; 96 | } 97 | protected void sendCmd(String cmd) { 98 | try { 99 | cmd += "\r\n"; 100 | out.write(cmd.getBytes()); 101 | out.flush(); 102 | } catch (Exception e) { 103 | // TODO: handle exception 104 | } 105 | } 106 | protected void readResult() { 107 | byte c = 0; 108 | this.buff.clear(); 109 | try { 110 | while ((char)(c = (byte)in.read()) != '>') { 111 | buff.add(c); 112 | } 113 | } catch (IOException e) { 114 | } 115 | } 116 | public String getResult() { 117 | return new String(getByteArray()); 118 | } 119 | public byte[] getByteArray() { 120 | byte[] data = new byte[this.buff.size()]; 121 | for (int i = 0; i < this.buff.size(); i++) { 122 | data[i] = this.buff.get(i); 123 | } 124 | return data; 125 | } 126 | public String formatResult() { 127 | String res = getResult(); 128 | String[] ress = res.split("\r"); 129 | res = ress[0].replace(" ",""); 130 | return res; 131 | } 132 | /** 133 | * @return 134 | * @uml.property name="in" 135 | */ 136 | public InputStream getIn() { 137 | return in; 138 | } 139 | /** 140 | * @return 141 | * @uml.property name="out" 142 | */ 143 | public OutputStream getOut() { 144 | return out; 145 | } 146 | public ArrayList getBuff() { 147 | return buff; 148 | } 149 | /** 150 | * @return 151 | * @uml.property name="cmd" 152 | */ 153 | public String getCmd() { 154 | return cmd; 155 | } 156 | /** 157 | * @return 158 | * @uml.property name="desc" 159 | */ 160 | public String getDesc() { 161 | return desc; 162 | } 163 | /** 164 | * @return 165 | * @uml.property name="resType" 166 | */ 167 | public String getResType() { 168 | return resType; 169 | } 170 | /** 171 | * @param e 172 | * @uml.property name="error" 173 | */ 174 | public void setError(Exception e) { 175 | error = e; 176 | } 177 | /** 178 | * @return 179 | * @uml.property name="error" 180 | */ 181 | public Exception getError() { 182 | return error; 183 | } 184 | /** 185 | * @return 186 | * @uml.property name="rawValue" 187 | */ 188 | public Object getRawValue() { 189 | return rawValue; 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /src/awis/obd/activity/ObdReaderCommandActivity.java: -------------------------------------------------------------------------------- 1 | package awis.obd.activity; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | import java.util.UUID; 7 | 8 | import awis.obd.activity.R; 9 | import awis.obd.command.ObdCommand; 10 | import awis.obd.command.ObdMultiCommand; 11 | import awis.obd.config.ObdConfig; 12 | import awis.obd.io.ObdCommandConnectThread; 13 | import awis.obd.io.ObdConnectThread; 14 | import android.app.Activity; 15 | import android.bluetooth.BluetoothAdapter; 16 | import android.bluetooth.BluetoothDevice; 17 | import android.content.SharedPreferences; 18 | import android.os.Bundle; 19 | import android.os.Handler; 20 | import android.preference.PreferenceManager; 21 | import android.view.View; 22 | import android.widget.AdapterView; 23 | import android.widget.ArrayAdapter; 24 | import android.widget.Spinner; 25 | import android.widget.TextView; 26 | import android.widget.Toast; 27 | import android.widget.AdapterView.OnItemSelectedListener; 28 | 29 | public class ObdReaderCommandActivity extends Activity implements 30 | OnItemSelectedListener { 31 | 32 | 33 | final private ArrayList commands = ObdConfig.getAllCommands(); 34 | 35 | private Map cmdMap = null; 36 | protected static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); 37 | private Handler handler = null; 38 | private SharedPreferences prefs = null; 39 | private final static String NO_SELECTION_TXT = "Choose Command to Run..."; 40 | 41 | public void onCreate(Bundle savedInstance) { 42 | super.onCreate(savedInstance); 43 | prefs = PreferenceManager 44 | .getDefaultSharedPreferences(ObdReaderCommandActivity.this); 45 | setContentView(R.layout.command); 46 | Spinner cmdSpin = (Spinner) findViewById(R.id.command_spinner); 47 | cmdSpin.setOnItemSelectedListener(this); 48 | cmdMap = new HashMap(); 49 | ArrayList cmdStrs = new ArrayList(); 50 | cmdStrs.add(NO_SELECTION_TXT); 51 | String[] configCmdStrs = ObdReaderConfigActivity 52 | .getReaderConfigCommands(prefs); 53 | ObdMultiCommand configCmd = new ObdMultiCommand(configCmdStrs, 54 | "Configure Reader", "string", "string"); 55 | cmdMap.put(configCmd.getDesc(), configCmd); 56 | cmdStrs.add(configCmd.getDesc()); 57 | for (ObdCommand cmd : commands) { 58 | cmdMap.put(cmd.getDesc(), cmd); 59 | cmdStrs.add(cmd.getDesc()); 60 | } 61 | ArrayAdapter adapt = new ArrayAdapter(this, 62 | android.R.layout.simple_spinner_item, cmdStrs); 63 | cmdSpin.setAdapter(adapt); 64 | handler = new Handler(); 65 | } 66 | 67 | public void onItemSelected(AdapterView arg0, View arg1, int arg2, 68 | long arg3) { 69 | Spinner cmdSpin = (Spinner) findViewById(R.id.command_spinner); 70 | String cmdDesc = cmdSpin.getSelectedItem().toString(); 71 | if (NO_SELECTION_TXT.equals(cmdDesc)) { 72 | return; 73 | } 74 | ObdCommand cmd = cmdMap.get(cmdDesc); 75 | ObdReaderCommandActivityWorkerThread worker = null; 76 | try { 77 | worker = new ObdReaderCommandActivityWorkerThread( 78 | ObdConnectThread.getCopy(cmd)); 79 | } catch (Exception e) { 80 | Toast.makeText(this, "Error copying command: " + e.getMessage(), 81 | Toast.LENGTH_LONG).show(); 82 | return; 83 | } 84 | worker.start(); 85 | cmdSpin.setSelection(0); 86 | } 87 | 88 | public void onNothingSelected(AdapterView arg0) { 89 | } 90 | 91 | public void showMessage(final String message) { 92 | final Activity act = this; 93 | handler.post(new Runnable() { 94 | public void run() { 95 | Toast.makeText(act, message, Toast.LENGTH_LONG).show(); 96 | } 97 | }); 98 | } 99 | 100 | private void setText(final String value, final boolean clear) { 101 | handler.post(new Runnable() { 102 | public void run() { 103 | TextView txtView = (TextView) findViewById(R.id.command_result_text); 104 | String curr = (String) txtView.getText(); 105 | if (curr == null || clear || "".equals(curr)) { 106 | curr = value; 107 | } else { 108 | curr = curr + "\n" + value; 109 | } 110 | txtView.setText(curr); 111 | } 112 | }); 113 | } 114 | 115 | public void logMsg(final String msg) { 116 | setText(msg, false); 117 | } 118 | 119 | private class ObdReaderCommandActivityWorkerThread extends Thread { 120 | 121 | ObdCommand cmd = null; 122 | 123 | private ObdReaderCommandActivityWorkerThread(ObdCommand cmd) { 124 | this.cmd = cmd; 125 | } 126 | 127 | public void run() { 128 | String devString = prefs.getString( 129 | ObdReaderConfigActivity.BLUETOOTH_LIST_KEY, null); 130 | final BluetoothAdapter mBluetoothAdapter = BluetoothAdapter 131 | .getDefaultAdapter(); 132 | if (mBluetoothAdapter == null) { 133 | showMessage("This device does not support bluetooth"); 134 | return; 135 | } 136 | if (devString == null || "".equals(devString)) { 137 | showMessage("No bluetooth device selected"); 138 | return; 139 | } 140 | BluetoothDevice dev = mBluetoothAdapter.getRemoteDevice(devString); 141 | double ve = ObdReaderConfigActivity.getVolumetricEfficieny(prefs); 142 | double ed = ObdReaderConfigActivity.getEngineDisplacement(prefs); 143 | boolean imperialUnits = prefs.getBoolean( 144 | ObdReaderConfigActivity.IMPERIAL_UNITS_KEY, false); 145 | final ObdCommandConnectThread thread = new ObdCommandConnectThread( 146 | dev, ObdReaderCommandActivity.this, cmd, ed, ve, 147 | imperialUnits); 148 | thread.setVolumetricEfficiency(ve); 149 | thread.setEngineDisplacement(ed); 150 | setText(String.format("Running %s...", cmd.getDesc()), true); 151 | try { 152 | thread.start(); 153 | thread.join(); 154 | } catch (Exception e1) { 155 | showMessage("Error getting connection: " + e1.getMessage()); 156 | } 157 | String res = null; 158 | if (!thread.getResults().containsKey(cmd.getDesc())) { 159 | res = "Didn't get a result."; 160 | } else { 161 | res = thread.getResults().get(cmd.getDesc()); 162 | } 163 | logMsg("Formated result: " + res); 164 | } 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /src/awis/obd/io/ObdReaderService.java: -------------------------------------------------------------------------------- 1 | package awis.obd.io; 2 | 3 | import java.io.PrintWriter; 4 | import java.io.StringWriter; 5 | import java.util.ArrayList; 6 | import java.util.Map; 7 | 8 | import awis.obd.activity.ObdReaderConfigActivity; 9 | import awis.obd.activity.R; 10 | import awis.obd.command.ObdCommand; 11 | 12 | import android.app.Notification; 13 | import android.app.NotificationManager; 14 | import android.app.PendingIntent; 15 | import android.app.Service; 16 | import android.bluetooth.BluetoothAdapter; 17 | import android.bluetooth.BluetoothDevice; 18 | import android.content.Context; 19 | import android.content.Intent; 20 | import android.content.SharedPreferences; 21 | import android.location.LocationManager; 22 | import android.os.Binder; 23 | import android.os.IBinder; 24 | import android.preference.PreferenceManager; 25 | import android.widget.Toast; 26 | 27 | public class ObdReaderService extends Service { 28 | 29 | private ObdConnectThread connectThread = null; 30 | private final IBinder binder = new ObdReaderServiceBinder(); 31 | private NotificationManager notifyMan = null; 32 | private Context context = null; 33 | private Intent notificationIntent = null; 34 | private PendingIntent contentIntent = null; 35 | public static final int COMMAND_ERROR_NOTIFY = 2; 36 | public static final int CONNECT_ERROR_NOTIFY = 3; 37 | public static final int OBD_SERVICE_RUNNING_NOTIFY = 4; 38 | public static final int OBD_SERVICE_ERROR_NOTIFY = 5; 39 | 40 | public void onCreate() { 41 | super.onCreate(); 42 | notifyMan = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 43 | context = getApplicationContext(); 44 | notificationIntent = new Intent(this, ObdReaderService.class); 45 | contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); 46 | } 47 | public void onDestroy() { 48 | super.onDestroy(); 49 | stopService(); 50 | stopSelf(); 51 | } 52 | public boolean isRunning() { 53 | if (connectThread == null) { 54 | return false; 55 | } 56 | return connectThread.isAlive(); 57 | } 58 | public IBinder onBind(Intent intent) { 59 | return binder; 60 | } 61 | public boolean startService() { 62 | if (connectThread != null && connectThread.isAlive()) { 63 | return true; 64 | } 65 | SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); 66 | String devString = prefs.getString(ObdReaderConfigActivity.BLUETOOTH_LIST_KEY, null); 67 | boolean uploadEnabled = prefs.getBoolean(ObdReaderConfigActivity.UPLOAD_DATA_KEY,false); 68 | String uploadUrl = null; 69 | if (uploadEnabled) { 70 | uploadUrl = prefs.getString(ObdReaderConfigActivity.UPLOAD_URL_KEY, null); 71 | } 72 | final BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 73 | if (mBluetoothAdapter == null) { 74 | Toast.makeText(this, "This device does not support bluetooth", Toast.LENGTH_LONG).show(); 75 | stopSelf(); 76 | return false; 77 | } 78 | if (devString == null || "".equals(devString)) { 79 | Toast.makeText(this, "No bluetooth device selected", Toast.LENGTH_LONG).show(); 80 | stopSelf(); 81 | return false; 82 | } 83 | LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); 84 | if (locationManager == null) { 85 | Toast.makeText(this, "This device does not support GPS", Toast.LENGTH_LONG).show(); 86 | stopSelf(); 87 | return false; 88 | } 89 | int period = ObdReaderConfigActivity.getUpdatePeriod(prefs); 90 | double ve = ObdReaderConfigActivity.getVolumetricEfficieny(prefs); 91 | double ed = ObdReaderConfigActivity.getEngineDisplacement(prefs); 92 | boolean imperialUnits = prefs.getBoolean(ObdReaderConfigActivity.IMPERIAL_UNITS_KEY, false); 93 | boolean gps = prefs.getBoolean(ObdReaderConfigActivity.ENABLE_GPS_KEY, false); 94 | ArrayList cmds = ObdReaderConfigActivity.getObdCommands(prefs); 95 | BluetoothDevice dev = mBluetoothAdapter.getRemoteDevice(devString); 96 | connectThread = new ObdConnectThread(dev,locationManager,this,uploadUrl,period,ed,ve,imperialUnits,gps,cmds); 97 | connectThread.setEngineDisplacement(ed); 98 | connectThread.setVolumetricEfficiency(ve); 99 | new ObdReaderServiceWorkerThread(connectThread).start(); 100 | return true; 101 | } 102 | public boolean stopService() { 103 | if (connectThread == null) { 104 | return true; 105 | } 106 | while (connectThread.isAlive()) { 107 | try { 108 | connectThread.cancel(); 109 | connectThread.join(300); 110 | } catch (InterruptedException e) { 111 | StringWriter strw = new StringWriter(); 112 | PrintWriter ptrw = new PrintWriter(strw); 113 | e.printStackTrace(ptrw); 114 | notifyMessage(e.getMessage(),strw.toString(), OBD_SERVICE_ERROR_NOTIFY); 115 | } 116 | } 117 | connectThread.close(); 118 | stopSelf(); 119 | return true; 120 | } 121 | public void notifyMessage(String msg, String longMsg, int notifyId) { 122 | long when = System.currentTimeMillis(); 123 | Notification notification = new Notification(android.R.drawable.stat_notify_error, msg, when); 124 | notification.setLatestEventInfo(context, msg, longMsg, contentIntent); 125 | notifyMan.notify(notifyId, notification); 126 | } 127 | public Map getDataMap() { 128 | if (connectThread != null) { 129 | return connectThread.getResults(); 130 | } 131 | return null; 132 | } 133 | public class ObdReaderServiceBinder extends Binder { 134 | ObdReaderService getService() { 135 | return ObdReaderService.this; 136 | } 137 | } 138 | private class ObdReaderServiceWorkerThread extends Thread { 139 | 140 | ObdConnectThread t = null; 141 | public ObdReaderServiceWorkerThread(ObdConnectThread t) { 142 | this.t = t; 143 | } 144 | public void run() { 145 | try { 146 | t.start(); 147 | long when = System.currentTimeMillis(); 148 | Notification notification = new Notification(R.drawable.car, "OBD Service Running", when); 149 | notification.setLatestEventInfo(context, "OBD Service Running", "", contentIntent); 150 | notification.flags |= Notification.FLAG_NO_CLEAR; 151 | notification.flags |= Notification.FLAG_ONGOING_EVENT; 152 | notifyMan.notify(OBD_SERVICE_RUNNING_NOTIFY, notification); 153 | t.join(); 154 | } catch (Exception e) { 155 | } finally { 156 | notifyMan.cancel(OBD_SERVICE_RUNNING_NOTIFY); 157 | stopSelf(); 158 | } 159 | } 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/awis/obd/activity/ObdReaderConfigActivity.java: -------------------------------------------------------------------------------- 1 | package awis.obd.activity; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Set; 5 | 6 | import awis.obd.activity.R; 7 | import awis.obd.command.ObdCommand; 8 | import awis.obd.config.ObdConfig; 9 | import android.app.Activity; 10 | import android.bluetooth.BluetoothAdapter; 11 | import android.bluetooth.BluetoothDevice; 12 | import android.content.SharedPreferences; 13 | import android.os.Bundle; 14 | import android.preference.CheckBoxPreference; 15 | import android.preference.EditTextPreference; 16 | import android.preference.ListPreference; 17 | import android.preference.Preference; 18 | import android.preference.PreferenceActivity; 19 | import android.preference.PreferenceScreen; 20 | import android.preference.Preference.OnPreferenceChangeListener; 21 | import android.preference.Preference.OnPreferenceClickListener; 22 | import android.widget.Toast; 23 | 24 | public class ObdReaderConfigActivity extends PreferenceActivity implements OnPreferenceChangeListener { 25 | 26 | public static final String BLUETOOTH_LIST_KEY = "bluetooth_list_preference"; 27 | public static final String UPLOAD_URL_KEY = "upload_url_preference"; 28 | public static final String UPLOAD_DATA_KEY = "upload_data_preference"; 29 | public static final String UPDATE_PERIOD_KEY = "update_period_preference"; 30 | public static final String VEHICLE_ID_KEY = "vehicle_id_preference"; 31 | public static final String ENGINE_DISPLACEMENT_KEY = "engine_displacement_preference"; 32 | public static final String VOLUMETRIC_EFFICIENCY_KEY = "volumetric_efficiency_preference"; 33 | public static final String IMPERIAL_UNITS_KEY = "imperial_units_preference"; 34 | public static final String COMMANDS_SCREEN_KEY = "obd_commands_screen"; 35 | public static final String ENABLE_GPS_KEY = "enable_gps_preference"; 36 | public static final String MAX_FUEL_ECON_KEY = "max_fuel_econ_preference"; 37 | public static final String CONFIG_READER_KEY = "reader_config_preference"; 38 | 39 | public void onCreate(Bundle savedInstanceState) { 40 | super.onCreate(savedInstanceState); 41 | addPreferencesFromResource(R.xml.preferences); 42 | ArrayList pairedDeviceStrings = new ArrayList(); 43 | ArrayList vals = new ArrayList(); 44 | ListPreference listPref = (ListPreference) getPreferenceScreen().findPreference(BLUETOOTH_LIST_KEY); 45 | String[] prefKeys = new String[]{ENGINE_DISPLACEMENT_KEY,VOLUMETRIC_EFFICIENCY_KEY,UPDATE_PERIOD_KEY,MAX_FUEL_ECON_KEY}; 46 | for (String prefKey:prefKeys) { 47 | EditTextPreference txtPref = (EditTextPreference) getPreferenceScreen().findPreference(prefKey); 48 | txtPref.setOnPreferenceChangeListener(this); 49 | } 50 | final BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 51 | if (mBluetoothAdapter == null) { 52 | listPref.setEntries(pairedDeviceStrings.toArray(new CharSequence[0])); 53 | listPref.setEntryValues(vals.toArray(new CharSequence[0])); 54 | return; 55 | } 56 | final Activity thisAct = this; 57 | listPref.setOnPreferenceClickListener(new OnPreferenceClickListener() { 58 | @SuppressWarnings("unused") 59 | public boolean onPreferenceClick(Preference preference) { 60 | if (mBluetoothAdapter == null) { 61 | Toast.makeText(thisAct,"This device does not support bluetooth", Toast.LENGTH_LONG); 62 | return false; 63 | } 64 | return true; 65 | } 66 | }); 67 | Set pairedDevices = mBluetoothAdapter.getBondedDevices(); 68 | if (pairedDevices.size() > 0) { 69 | for (BluetoothDevice device : pairedDevices) { 70 | pairedDeviceStrings.add(device.getName() + "\n" + device.getAddress()); 71 | vals.add(device.getAddress()); 72 | } 73 | } 74 | listPref.setEntries(pairedDeviceStrings.toArray(new CharSequence[0])); 75 | listPref.setEntryValues(vals.toArray(new CharSequence[0])); 76 | ArrayList cmds = ObdConfig.getCommands(); 77 | PreferenceScreen cmdScr = (PreferenceScreen) getPreferenceScreen().findPreference(COMMANDS_SCREEN_KEY); 78 | for (int i = 0; i < cmds.size(); i++) { 79 | ObdCommand cmd = cmds.get(i); 80 | CheckBoxPreference cpref = new CheckBoxPreference(this); 81 | cpref.setTitle(cmd.getDesc()); 82 | cpref.setKey(cmd.getDesc()); 83 | cpref.setChecked(true); 84 | cmdScr.addPreference(cpref); 85 | } 86 | } 87 | public boolean onPreferenceChange(Preference preference, Object newValue) { 88 | if (UPDATE_PERIOD_KEY.equals(preference.getKey()) || 89 | VOLUMETRIC_EFFICIENCY_KEY.equals(preference.getKey()) || 90 | ENGINE_DISPLACEMENT_KEY.equals(preference.getKey()) || 91 | MAX_FUEL_ECON_KEY.equals(preference.getKey())) { 92 | try { 93 | Double.parseDouble(newValue.toString()); 94 | return true; 95 | } catch (Exception e) { 96 | Toast.makeText(this,"Couldn't parse '" + newValue.toString() + "' as a number.",Toast.LENGTH_LONG).show(); 97 | } 98 | } 99 | return false; 100 | } 101 | public static int getUpdatePeriod(SharedPreferences prefs) { 102 | String periodString = prefs.getString(ObdReaderConfigActivity.UPDATE_PERIOD_KEY, "4"); 103 | int period = 4000; 104 | try { 105 | period = Integer.parseInt(periodString) * 1000; 106 | } catch (Exception e) { 107 | } 108 | if (period <= 0) { 109 | period = 250; 110 | } 111 | return period; 112 | } 113 | public static double getVolumetricEfficieny(SharedPreferences prefs) { 114 | String veString = prefs.getString(ObdReaderConfigActivity.VOLUMETRIC_EFFICIENCY_KEY, ".85"); 115 | double ve = 0.85; 116 | try { 117 | ve = Double.parseDouble(veString); 118 | } catch (Exception e) { 119 | } 120 | return ve; 121 | } 122 | public static double getEngineDisplacement(SharedPreferences prefs) { 123 | String edString = prefs.getString(ObdReaderConfigActivity.ENGINE_DISPLACEMENT_KEY, "1.6"); 124 | double ed = 1.6; 125 | try { 126 | ed = Double.parseDouble(edString); 127 | } catch (Exception e) { 128 | } 129 | return ed; 130 | } 131 | public static ArrayList getObdCommands(SharedPreferences prefs) { 132 | ArrayList cmds = ObdConfig.getCommands(); 133 | ArrayList ucmds = new ArrayList(); 134 | for (int i = 0; i < cmds.size(); i++) { 135 | ObdCommand cmd = cmds.get(i); 136 | boolean selected = prefs.getBoolean(cmd.getDesc(), true); 137 | if (selected) { 138 | ucmds.add(cmd); 139 | } 140 | } 141 | return ucmds; 142 | } 143 | public static double getMaxFuelEconomy(SharedPreferences prefs) { 144 | String maxStr = prefs.getString(ObdReaderConfigActivity.MAX_FUEL_ECON_KEY, "70"); 145 | double max = 70; 146 | try { 147 | max = Double.parseDouble(maxStr); 148 | } catch (Exception e) { 149 | } 150 | return max; 151 | } 152 | public static String[] getReaderConfigCommands(SharedPreferences prefs) { 153 | String cmdsStr = prefs.getString(CONFIG_READER_KEY, "atsp0\natz"); 154 | String[] cmds = cmdsStr.split("\n"); 155 | return cmds; 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /src/awis/obd/io/ObdConnectThread.java: -------------------------------------------------------------------------------- 1 | package awis.obd.io; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | import java.io.PrintWriter; 7 | import java.io.StringWriter; 8 | import java.lang.reflect.InvocationTargetException; 9 | import java.util.ArrayList; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | import java.util.UUID; 13 | import awis.obd.command.ObdCommand; 14 | import android.bluetooth.BluetoothDevice; 15 | import android.bluetooth.BluetoothSocket; 16 | import android.location.Location; 17 | import android.location.LocationListener; 18 | import android.location.LocationManager; 19 | import android.os.Bundle; 20 | 21 | public class ObdConnectThread extends Thread implements LocationListener { 22 | 23 | /** 24 | * @uml.property name="dev" 25 | * @uml.associationEnd multiplicity="(1 1)" 26 | */ 27 | protected BluetoothDevice dev = null; 28 | /** 29 | * @uml.property name="sock" 30 | * @uml.associationEnd 31 | */ 32 | protected BluetoothSocket sock = null; 33 | /** 34 | * @uml.property name="stop" 35 | */ 36 | protected boolean stop = false; 37 | protected static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); 38 | /** 39 | * @uml.property name="in" 40 | */ 41 | protected InputStream in = null; 42 | /** 43 | * @uml.property name="out" 44 | */ 45 | protected OutputStream out = null; 46 | /** 47 | * @uml.property name="cmds" 48 | * @uml.associationEnd multiplicity="(0 -1)" inverse="connectThread:awis.obd.command.ObdCommand" 49 | */ 50 | protected ArrayList cmds = null; 51 | /** 52 | * @uml.property name="results" 53 | * @uml.associationEnd qualifier="constant:java.lang.String java.lang.String" 54 | */ 55 | protected HashMap results = null; 56 | /** 57 | * @uml.property name="data" 58 | * @uml.associationEnd qualifier="constant:java.lang.String java.lang.Double" 59 | */ 60 | protected HashMap data = null; 61 | /** 62 | * @uml.property name="updateCycle" 63 | */ 64 | protected int updateCycle = 4000; 65 | /** 66 | * @uml.property name="service" 67 | * @uml.associationEnd multiplicity="(1 1)" inverse="connectThread:awis.obd.io.ObdReaderService" 68 | */ 69 | protected ObdReaderService service = null; 70 | /** 71 | * @uml.property name="uploadUrl" 72 | */ 73 | protected String uploadUrl = null; 74 | /** 75 | * @uml.property name="currentLocation" 76 | * @uml.associationEnd 77 | */ 78 | protected Location currentLocation = null; 79 | /** 80 | * @uml.property name="locationManager" 81 | * @uml.associationEnd multiplicity="(1 1)" 82 | */ 83 | protected LocationManager locationManager = null; 84 | /** 85 | * @uml.property name="engineDisplacement" 86 | */ 87 | protected double engineDisplacement = 1.0; 88 | /** 89 | * @uml.property name="volumetricEfficiency" 90 | */ 91 | protected double volumetricEfficiency = 1.0; 92 | /** 93 | * @uml.property name="imperialUnits" 94 | */ 95 | protected boolean imperialUnits = false; 96 | 97 | public ObdConnectThread(BluetoothDevice dev, 98 | LocationManager locationManager, final ObdReaderService service, 99 | String uploadUrl, int updateCycle, double engineDisplacement, 100 | double volumetricEfficiency, boolean imperialUnits, 101 | boolean enableGps, ArrayList cmds) { 102 | this.dev = dev; 103 | this.cmds = cmds; 104 | this.updateCycle = updateCycle; 105 | this.service = service; 106 | this.uploadUrl = uploadUrl; 107 | this.locationManager = locationManager; 108 | if (locationManager != null && enableGps) { 109 | this.locationManager.requestLocationUpdates( 110 | LocationManager.GPS_PROVIDER, 0, 0.0f, this); 111 | } 112 | results = new HashMap(); 113 | data = new HashMap(); 114 | this.volumetricEfficiency = volumetricEfficiency; 115 | this.engineDisplacement = engineDisplacement; 116 | this.imperialUnits = imperialUnits; 117 | } 118 | 119 | protected void startDevice() throws IOException, InterruptedException { 120 | sock = this.dev.createRfcommSocketToServiceRecord(MY_UUID); 121 | sock.connect(); 122 | in = sock.getInputStream(); 123 | out = sock.getOutputStream(); 124 | while (!stop) { 125 | ObdCommand echoOff = new ObdCommand("ate0", "echo off", "string", 126 | "string"); 127 | String result = runCommand(echoOff).replace(" ", ""); 128 | if (result != null && result.contains("OK")) { 129 | break; 130 | } 131 | Thread.sleep(1500); 132 | } 133 | } 134 | 135 | public void run() { 136 | try { 137 | startDevice(); 138 | int cmdSize = cmds.size(); 139 | for (int i = 0; i < cmdSize; i++) { 140 | String desc = cmds.get(i).getDesc(); 141 | results.put(desc, "--"); 142 | data.put(desc, -9999); 143 | } 144 | for (int i = 0; !stop; i = ((i + 1) % cmdSize)) { 145 | if (i == 0) { 146 | long obsTime = System.currentTimeMillis() / 1000; 147 | results.put("Obs Time", Long.toString(obsTime)); 148 | data.put("Obs Time", obsTime); 149 | 150 | Thread.sleep(updateCycle); 151 | } 152 | ObdCommand cmd = cmds.get(i); 153 | try { 154 | cmd = getCopy(cmd); // make a copy because thread can only 155 | // run once 156 | String desc = cmd.getDesc(); 157 | String result = runCommand(cmd); 158 | results.put(desc, result); 159 | data.put(desc, cmd.getRawValue()); 160 | } catch (Exception e) { 161 | results.put(cmd.getDesc(), "--"); 162 | if (!stop) { 163 | service.notifyMessage("Error running " + cmd.getDesc(), 164 | e.getMessage(), 165 | ObdReaderService.COMMAND_ERROR_NOTIFY); 166 | } 167 | } 168 | } 169 | } catch (IOException e) { 170 | service.notifyMessage("Bluetooth Connection Error", e.getMessage(), 171 | ObdReaderService.CONNECT_ERROR_NOTIFY); 172 | } catch (Exception e) { 173 | service.notifyMessage(e.getMessage(), e.toString(), 174 | ObdReaderService.OBD_SERVICE_ERROR_NOTIFY); 175 | } finally { 176 | close(); 177 | } 178 | } 179 | 180 | public static ObdCommand getCopy(ObdCommand cmd) 181 | throws IllegalArgumentException, SecurityException, 182 | InstantiationException, IllegalAccessException, 183 | InvocationTargetException, NoSuchMethodException { 184 | return cmd.getClass().getConstructor(cmd.getClass()).newInstance(cmd); 185 | } 186 | 187 | public String runCommand(ObdCommand cmd) throws InterruptedException { 188 | cmd.setInputStream(in); 189 | cmd.setOutputStream(out); 190 | cmd.setDataMap(data); 191 | cmd.setConnectThread(this); 192 | cmd.start(); 193 | while (!stop) { 194 | cmd.join(300); 195 | if (!cmd.isAlive()) { 196 | break; 197 | } 198 | } 199 | return cmd.formatResult(); 200 | } 201 | 202 | public ArrayList getCmds() { 203 | return cmds; 204 | } 205 | 206 | public synchronized Map getResults() { 207 | if (currentLocation != null) { 208 | double lat = currentLocation.getLatitude(); 209 | double lon = currentLocation.getLongitude(); 210 | int speed = (int) currentLocation.getSpeed(); 211 | long gtime = currentLocation.getTime() / 1000; 212 | results.put("Latitude", String.format("%.5f", lat)); 213 | results.put("Longitude", String.format("%.5f", lon)); 214 | results.put("GPS Speed", String.format("%d m/s", speed)); 215 | results.put("GPS Time", Long.toString(gtime)); 216 | data.put("Latitude", lat); 217 | data.put("Longitude", lon); 218 | data.put("GPS Speed", speed); 219 | data.put("GPS Time", gtime); 220 | } 221 | return results; 222 | } 223 | 224 | public void cancel() { 225 | stop = true; 226 | } 227 | 228 | public void close() { 229 | try { 230 | locationManager.removeUpdates(this); 231 | } catch (Exception e) { 232 | } 233 | try { 234 | stop = true; 235 | sock.close(); 236 | } catch (Exception e) { 237 | } 238 | } 239 | 240 | public String getStackTrace(Exception e) { 241 | StringWriter strw = new StringWriter(); 242 | PrintWriter ptrw = new PrintWriter(strw); 243 | e.printStackTrace(ptrw); 244 | return strw.toString(); 245 | } 246 | 247 | public void onLocationChanged(Location location) { 248 | currentLocation = location; 249 | } 250 | 251 | public void onProviderDisabled(String provider) { 252 | service.notifyMessage("GPS Unavailable", 253 | "GPS_PROVIDER disabled, please enable gps in your settings.", 254 | ObdReaderService.OBD_SERVICE_ERROR_NOTIFY); 255 | } 256 | 257 | public void onProviderEnabled(String provider) { 258 | } 259 | 260 | public void onStatusChanged(String provider, int status, Bundle extras) { 261 | } 262 | 263 | /** 264 | * @param ve 265 | * @uml.property name="volumetricEfficiency" 266 | */ 267 | public void setVolumetricEfficiency(double ve) { 268 | this.volumetricEfficiency = ve; 269 | } 270 | 271 | /** 272 | * @param ed 273 | * @uml.property name="engineDisplacement" 274 | */ 275 | public void setEngineDisplacement(double ed) { 276 | this.engineDisplacement = ed; 277 | } 278 | 279 | /** 280 | * @return 281 | * @uml.property name="volumetricEfficiency" 282 | */ 283 | public double getVolumetricEfficiency() { 284 | return volumetricEfficiency; 285 | } 286 | 287 | /** 288 | * @return 289 | * @uml.property name="engineDisplacement" 290 | */ 291 | public double getEngineDisplacement() { 292 | return engineDisplacement; 293 | } 294 | 295 | public boolean getImperialUnits() { 296 | return imperialUnits; 297 | } 298 | } -------------------------------------------------------------------------------- /src/awis/obd/activity/ObdReaderMainActivity.java: -------------------------------------------------------------------------------- 1 | package awis.obd.activity; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | import java.util.Set; 8 | 9 | import awis.obd.activity.R; 10 | import awis.obd.command.ObdCommand; 11 | import awis.obd.config.ObdConfig; 12 | import awis.obd.drawable.CoolantGaugeView; 13 | import awis.obd.io.ObdReaderService; 14 | import awis.obd.io.ObdReaderServiceConnection; 15 | 16 | import android.app.Activity; 17 | import android.app.AlertDialog; 18 | import android.app.Dialog; 19 | import android.bluetooth.BluetoothAdapter; 20 | import android.content.Context; 21 | import android.content.Intent; 22 | import android.content.SharedPreferences; 23 | import android.graphics.Color; 24 | import android.hardware.Sensor; 25 | import android.hardware.SensorEvent; 26 | import android.hardware.SensorEventListener; 27 | import android.hardware.SensorManager; 28 | import android.location.LocationManager; 29 | import android.os.Bundle; 30 | import android.os.Handler; 31 | import android.os.PowerManager; 32 | import android.preference.PreferenceManager; 33 | import android.view.Gravity; 34 | import android.view.Menu; 35 | import android.view.MenuItem; 36 | import android.view.ViewGroup; 37 | import android.view.ViewGroup.LayoutParams; 38 | import android.view.ViewGroup.MarginLayoutParams; 39 | import android.widget.TableLayout; 40 | import android.widget.TableRow; 41 | import android.widget.TextView; 42 | import android.widget.Toast; 43 | 44 | public class ObdReaderMainActivity extends Activity { 45 | static final int NO_BLUETOOTH_ID = 0; 46 | static final int NO_GPS_ID = 1; 47 | static final int START_LIVE_DATA = 1; 48 | static final int STOP_LIVE_DATA = 2; 49 | static final int SETTINGS = 3; 50 | static final int COMMAND_ACTIVITY = 5; 51 | static final int TABLE_ROW_MARGIN = 6; 52 | 53 | private Handler handler = null; 54 | private Intent serviceIntent = null; 55 | private ObdReaderServiceConnection serviceConn = null; 56 | private UpdateThread updater = null; 57 | private SensorManager sensorManager = null; 58 | private Sensor orientSensor = null; 59 | private double fuelEconAvg = 0; 60 | private int fuelEconi = 0; 61 | private double speedAvg = 0; 62 | private int speedi = 0; 63 | private SharedPreferences prefs = null; 64 | private double maxFuelEcon = 70.0; 65 | private PowerManager powerManager = null; 66 | private PowerManager.WakeLock wakeLock = null; 67 | private final SensorEventListener orientListener = new SensorEventListener() { 68 | public void onSensorChanged(SensorEvent event) { 69 | float x = event.values[0]; 70 | String dir = ""; 71 | if (x >= 337.5 || x < 22.5) { 72 | dir = "N"; 73 | } else if (x >= 22.5 && x < 67.5) { 74 | dir = "NE"; 75 | } else if (x >= 67.5 && x < 112.5) { 76 | dir = "E"; 77 | } else if (x >= 112.5 && x < 157.5) { 78 | dir = "SE"; 79 | } else if (x >= 157.5 && x < 202.5) { 80 | dir = "S"; 81 | } else if (x >= 202.5 && x < 247.5) { 82 | dir = "SW"; 83 | } else if (x >= 247.5 && x < 292.5) { 84 | dir = "W"; 85 | } else if (x >= 292.5 && x < 337.5) { 86 | dir = "NW"; 87 | } 88 | TextView compass = (TextView)findViewById(R.id.compass_text); 89 | updateTextView(compass,dir); 90 | } 91 | 92 | public void onAccuracyChanged(Sensor sensor, int accuracy) { 93 | // TODO Auto-generated method stub 94 | } 95 | }; 96 | 97 | /** Called when the activity is first created. */ 98 | @Override 99 | public void onCreate(Bundle savedInstanceState) { 100 | super.onCreate(savedInstanceState); 101 | // ExceptionHandler.register(this,"http://www.whidbeycleaning.com/droid/server.php"); 102 | setContentView(R.layout.main); 103 | handler = new Handler(); 104 | serviceIntent = new Intent(this, ObdReaderService.class); 105 | serviceConn = new ObdReaderServiceConnection(); 106 | bindService(serviceIntent, serviceConn, Context.BIND_AUTO_CREATE); 107 | LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); 108 | if (locationManager == null) { 109 | showDialog(NO_GPS_ID); 110 | return; 111 | } 112 | final BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 113 | if (mBluetoothAdapter == null) { 114 | showDialog(NO_BLUETOOTH_ID); 115 | return; 116 | } 117 | sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE); 118 | List sens = sensorManager.getSensorList(Sensor.TYPE_ORIENTATION); 119 | if ( sens.size() <= 0) { 120 | Toast.makeText(this, "No orientation available.", Toast.LENGTH_LONG).show(); 121 | } else { 122 | orientSensor = sens.get(0); 123 | } 124 | } 125 | @Override 126 | protected void onDestroy() { 127 | super.onDestroy(); 128 | if (wakeLock.isHeld()) { 129 | wakeLock.release(); 130 | } 131 | } 132 | @Override 133 | protected void onPause() { 134 | super.onPause(); 135 | if (wakeLock.isHeld()) { 136 | wakeLock.release(); 137 | } 138 | } 139 | protected void onResume() { 140 | super.onResume(); 141 | sensorManager.registerListener(orientListener, orientSensor, SensorManager.SENSOR_DELAY_UI); 142 | prefs = PreferenceManager.getDefaultSharedPreferences(this); 143 | maxFuelEcon = ObdReaderConfigActivity.getMaxFuelEconomy(prefs); 144 | powerManager = (PowerManager)getSystemService(Context.POWER_SERVICE); 145 | wakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "ObdReader"); 146 | } 147 | private void updateConfig() { 148 | Intent configIntent = new Intent(this,ObdReaderConfigActivity.class); 149 | startActivity(configIntent); 150 | } 151 | public boolean onCreateOptionsMenu(Menu menu) { 152 | menu.add(0, START_LIVE_DATA, 0, "Start Live Data"); 153 | menu.add(0, SETTINGS, 0, "Settings"); 154 | menu.add(0, COMMAND_ACTIVITY, 0, "Run Command"); 155 | menu.add(0, STOP_LIVE_DATA, 0, "Stop"); 156 | return true; 157 | } 158 | public boolean onOptionsItemSelected(MenuItem item) { 159 | switch (item.getItemId()) { 160 | case START_LIVE_DATA: 161 | liveData(); 162 | return true; 163 | case STOP_LIVE_DATA: 164 | cancel(); 165 | return true; 166 | case SETTINGS: 167 | updateConfig(); 168 | return true; 169 | case COMMAND_ACTIVITY: 170 | staticCommand(); 171 | return true; 172 | } 173 | return false; 174 | } 175 | private void staticCommand() { 176 | Intent commandIntent = new Intent(this, ObdReaderCommandActivity.class); 177 | startActivity(commandIntent); 178 | } 179 | private void liveData() { 180 | if (!serviceConn.isRunning()) { 181 | serviceConn.getService().startService(); 182 | } 183 | updater = new UpdateThread(); 184 | updater.start(); 185 | wakeLock.acquire(); 186 | } 187 | private void cancel() { 188 | stopService(serviceIntent); 189 | if (serviceConn.isRunning()) { 190 | serviceConn.getService().stopService(); 191 | } 192 | if (updater != null) { 193 | updater.stop = true; 194 | } 195 | wakeLock.release(); 196 | } 197 | protected Dialog onCreateDialog(int id) { 198 | AlertDialog.Builder build = new AlertDialog.Builder(this); 199 | switch(id) { 200 | case NO_BLUETOOTH_ID: 201 | build.setMessage("Sorry, your device doesn't support bluetooth"); 202 | return build.create(); 203 | case NO_GPS_ID: 204 | build.setMessage("Sorry, your device doesn't support gps"); 205 | return build.create(); 206 | } 207 | return null; 208 | } 209 | public boolean onPrepareOptionsMenu(Menu menu) { 210 | MenuItem startItem = menu.findItem(START_LIVE_DATA); 211 | MenuItem stopItem = menu.findItem(STOP_LIVE_DATA); 212 | MenuItem settingsItem = menu.findItem(SETTINGS); 213 | MenuItem commandItem = menu.findItem(COMMAND_ACTIVITY); 214 | if (serviceConn.isRunning()) { 215 | startItem.setEnabled(false); 216 | stopItem.setEnabled(true); 217 | settingsItem.setEnabled(false); 218 | commandItem.setEnabled(false); 219 | } else { 220 | stopItem.setEnabled(false); 221 | startItem.setEnabled(true); 222 | settingsItem.setEnabled(true); 223 | commandItem.setEnabled(true); 224 | } 225 | return true; 226 | } 227 | public void updateDataTable(final Map dataMap) { 228 | handler.post(new Runnable() { 229 | public void run() { 230 | setDataTableText(dataMap); 231 | } 232 | }); 233 | } 234 | public void updateTextView(final TextView view, final String txt) { 235 | handler.post(new Runnable() { 236 | public void run() { 237 | view.setText(txt); 238 | } 239 | }); 240 | } 241 | public void setDataTableText(Map dataMap) { 242 | TableLayout tl = (TableLayout) findViewById(R.id.data_table); 243 | tl.removeAllViews(); 244 | Set keySet = dataMap.keySet(); 245 | String[] keys = keySet.toArray(new String[0]); 246 | Arrays.sort(keys); 247 | for (String k:keys) { 248 | addTableRow(tl,k,dataMap.get(k)); 249 | } 250 | String coolant = dataMap.get(ObdConfig.COOLANT_TEMP); 251 | String runTime = dataMap.get(ObdConfig.RUN_TIME); 252 | String rpm = dataMap.get(ObdConfig.RPM); 253 | String fuelEcon = dataMap.get(ObdConfig.FUEL_ECON); 254 | String fuelEconMap = dataMap.get(ObdConfig.FUEL_ECON_MAP); 255 | String speed = dataMap.get(ObdConfig.SPEED); 256 | String temp = dataMap.get(ObdConfig.INTAKE_TEMP); 257 | if (coolant != null) { 258 | setCoolantTemp(coolant); 259 | } 260 | if (isFill(fuelEcon)) { 261 | if (!isFill(fuelEconMap)) { 262 | setFuelEconomy(fuelEconMap); 263 | } 264 | } else { 265 | setFuelEconomy(fuelEcon); 266 | } 267 | setRunTime(runTime); 268 | setRpm(rpm); 269 | setAvgSpeed(speed); 270 | setAirTemp(temp); 271 | } 272 | private void setAirTemp(String temp) { 273 | if (isFill(temp)) { 274 | return; 275 | } 276 | TextView tempView = (TextView)findViewById(R.id.air_temp_text); 277 | tempView.setText(temp); 278 | } 279 | private void setAvgSpeed(String spd) { 280 | try { 281 | String[] spds = spd.split(" "); 282 | int spdv = Integer.parseInt(spds[0]); 283 | if ("km/h".equals(spds[1])) { 284 | spdv = (int)((double)spdv / .625); 285 | } 286 | if (spdv > 0) { 287 | speedAvg = (spdv + (speedi*speedAvg)) / (speedi + 1); 288 | speedi += 1; 289 | } 290 | TextView avgSpeed = (TextView)findViewById(R.id.avg_spd_text); 291 | spdv = (int)speedAvg; 292 | if ("km/h".equals(spds[1])) { 293 | spdv = (int)(speedAvg*.625); 294 | } 295 | avgSpeed.setText(String.format("%d %s", spdv, spds[1])); 296 | } catch (Exception e) { 297 | } 298 | } 299 | private boolean isFill(String data) { 300 | if ("--".equals(data) || "NODATA".equals(data)) { 301 | return true; 302 | } 303 | return false; 304 | } 305 | private void setRpm(String rpm) { 306 | if (isFill(rpm)) { 307 | return; 308 | } 309 | TextView rpmView = (TextView)findViewById(R.id.avg_rpm_text); 310 | rpmView.setText(rpm); 311 | } 312 | private void setRunTime(String runTime) { 313 | if (isFill(runTime)) { 314 | return; 315 | } 316 | TextView runTimeView = (TextView)findViewById(R.id.run_time_text); 317 | runTimeView.setText(runTime); 318 | } 319 | private void setFuelEconomy(String fuelEcon) { 320 | try { 321 | String[] econs = fuelEcon.split(" "); 322 | double econ = Double.parseDouble(econs[0]); 323 | if ("kml".equals(econs[1])) { 324 | econ = econ / 0.354013; 325 | } 326 | if (econ > 0 && econ <= maxFuelEcon) { 327 | fuelEconAvg = (econ + (fuelEconi*fuelEconAvg)) / (fuelEconi + 1); 328 | fuelEconi += 1; 329 | } 330 | TextView instEcon = (TextView)findViewById(R.id.inst_fuel_econ_text); 331 | TextView avgEcon = (TextView)findViewById(R.id.avg_fuel_econ_text); 332 | TextView avgEconlbl = (TextView)findViewById(R.id.avg_fuel_econ_lbl); 333 | instEcon.setText(fuelEcon); 334 | String lbl = "mpg"; 335 | if ("kml".equals(econs[1])) { 336 | econ = fuelEconAvg * 0.354013; 337 | lbl = "kml"; 338 | } 339 | avgEcon.setText(String.format("%d", Math.round(fuelEconAvg))); 340 | avgEconlbl.setText(lbl); 341 | } catch (Exception e) { 342 | // TODO: handle exception 343 | } 344 | } 345 | private void setCoolantTemp(String coolant) { 346 | try { 347 | String[] cools = coolant.split(" "); 348 | int temp = Integer.parseInt(cools[0]); 349 | if ("F".equals(cools[1])) { 350 | temp = (temp - 32) * 5 / 9; 351 | } 352 | CoolantGaugeView gauge = (CoolantGaugeView)findViewById(R.id.coolant_gauge); 353 | gauge.setTemp(temp); 354 | } catch (Exception e) { 355 | } 356 | } 357 | private void addTableRow(TableLayout tl, String key, String val) { 358 | TableRow tr = new TableRow(this); 359 | MarginLayoutParams params = new ViewGroup.MarginLayoutParams( 360 | LayoutParams.WRAP_CONTENT, 361 | LayoutParams.WRAP_CONTENT); 362 | params.setMargins(TABLE_ROW_MARGIN,TABLE_ROW_MARGIN,TABLE_ROW_MARGIN,TABLE_ROW_MARGIN); 363 | tr.setLayoutParams(params); 364 | tr.setBackgroundColor(Color.BLACK); 365 | TextView name = new TextView(this); 366 | name.setGravity(Gravity.RIGHT); 367 | name.setText(key + ": "); 368 | TextView value = new TextView(this); 369 | value.setGravity(Gravity.LEFT); 370 | value.setText(val); 371 | tr.addView(name); 372 | tr.addView(value); 373 | tl.addView(tr,new TableLayout.LayoutParams( 374 | LayoutParams.WRAP_CONTENT, 375 | LayoutParams.WRAP_CONTENT)); 376 | } 377 | private class UpdateThread extends Thread { 378 | boolean stop = false; 379 | public void run() { 380 | String vehicleId = prefs.getString(ObdReaderConfigActivity.VEHICLE_ID_KEY,""); 381 | while (!stop && serviceConn.isRunning()) { 382 | ObdReaderService svc = serviceConn.getService(); 383 | Map dataMap = null; 384 | if (svc == null || svc.getDataMap() == null) { 385 | dataMap = new HashMap(); 386 | for (ObdCommand cmd:ObdConfig.getCommands()) { 387 | dataMap.put(cmd.getDesc(),"--"); 388 | } 389 | } else { 390 | dataMap = svc.getDataMap(); 391 | } 392 | if (vehicleId != null && !"".equals(vehicleId.trim())) { 393 | dataMap.put("Vehicle ID", vehicleId); 394 | } 395 | updateDataTable(dataMap); 396 | try { 397 | Thread.sleep(ObdReaderConfigActivity.getUpdatePeriod(prefs)); 398 | } catch (InterruptedException e) { 399 | e.printStackTrace(); 400 | } 401 | } 402 | } 403 | } 404 | } 405 | --------------------------------------------------------------------------------