package com.github.pires.obd.reader.activity; import android.app.Activity; import android.app.ProgressDialog; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.preference.PreferenceManager; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.Toast; import com.github.pires.obd.commands.control.TroubleCodesCommand; import com.github.pires.obd.commands.protocol.EchoOffCommand; import com.github.pires.obd.commands.protocol.LineFeedOffCommand; import com.github.pires.obd.commands.protocol.ObdResetCommand; import com.github.pires.obd.commands.protocol.ResetTroubleCodesCommand; import com.github.pires.obd.commands.protocol.SelectProtocolCommand; import com.github.pires.obd.enums.ObdProtocols; import com.github.pires.obd.exceptions.MisunderstoodCommandException; import com.github.pires.obd.exceptions.NoDataException; import com.github.pires.obd.exceptions.UnableToConnectException; import com.github.pires.obd.reader.R; import com.github.pires.obd.reader.io.BluetoothManager; import com.google.inject.Inject; import java.io.IOException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.UUID; public class TroubleCodesActivity extends Activity { private static final String TAG = TroubleCodesActivity.class.getName(); private static final int NO_BLUETOOTH_DEVICE_SELECTED = 0; private static final int CANNOT_CONNECT_TO_DEVICE = 1; private static final int NO_DATA = 3; private static final int DATA_OK = 4; private static final int CLEAR_DTC = 5; private static final int OBD_COMMAND_FAILURE = 10; private static final int OBD_COMMAND_FAILURE_IO = 11; private static final int OBD_COMMAND_FAILURE_UTC = 12; private static final int OBD_COMMAND_FAILURE_IE = 13; private static final int OBD_COMMAND_FAILURE_MIS = 14; private static final int OBD_COMMAND_FAILURE_NODATA = 15; @Inject SharedPreferences prefs; private ProgressDialog progressDialog; private String remoteDevice; private GetTroubleCodesTask gtct; private BluetoothDevice dev = null; private BluetoothSocket sock = null; private Handler mHandler = new Handler(new Handler.Callback() { public boolean handleMessage(Message msg) { Log.d(TAG, "Message received on handler"); switch (msg.what) { case NO_BLUETOOTH_DEVICE_SELECTED: makeToast(getString(R.string.text_bluetooth_nodevice)); finish(); break; case CANNOT_CONNECT_TO_DEVICE: makeToast(getString(R.string.text_bluetooth_error_connecting)); finish(); break; case OBD_COMMAND_FAILURE: makeToast(getString(R.string.text_obd_command_failure)); finish(); break; case OBD_COMMAND_FAILURE_IO: makeToast(getString(R.string.text_obd_command_failure) + " IO"); finish(); break; case OBD_COMMAND_FAILURE_IE: makeToast(getString(R.string.text_obd_command_failure) + " IE"); finish(); break; case OBD_COMMAND_FAILURE_MIS: makeToast(getString(R.string.text_obd_command_failure) + " MIS"); finish(); break; case OBD_COMMAND_FAILURE_UTC: makeToast(getString(R.string.text_obd_command_failure) + " UTC"); finish(); break; case OBD_COMMAND_FAILURE_NODATA: makeToastLong(getString(R.string.text_noerrors)); //finish(); break; case NO_DATA: makeToast(getString(R.string.text_dtc_no_data)); ///finish(); break; case DATA_OK: dataOk((String) msg.obj); break; } return false; } }); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); prefs = PreferenceManager.getDefaultSharedPreferences(this); if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } remoteDevice = prefs.getString(ConfigActivity.BLUETOOTH_LIST_KEY, null); if (remoteDevice == null || "".equals(remoteDevice)) { Log.e(TAG, "No Bluetooth device has been selected."); mHandler.obtainMessage(NO_BLUETOOTH_DEVICE_SELECTED).sendToTarget(); } else { gtct = new GetTroubleCodesTask(); gtct.execute(remoteDevice); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu items for use in the action bar MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.trouble_codes, menu); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle presses on the action bar items switch (item.getItemId()) { case R.id.action_clear_codes: try { sock = BluetoothManager.connect(dev); } catch (Exception e) { Log.e( TAG, "There was an error while establishing connection. -> " + e.getMessage() ); Log.d(TAG, "Message received on handler here"); mHandler.obtainMessage(CANNOT_CONNECT_TO_DEVICE).sendToTarget(); return true; } try { Log.d("TESTRESET", "Trying reset"); //new ObdResetCommand().run(sock.getInputStream(), sock.getOutputStream()); ResetTroubleCodesCommand clear = new ResetTroubleCodesCommand(); clear.run(sock.getInputStream(), sock.getOutputStream()); String result = clear.getFormattedResult(); Log.d("TESTRESET", "Trying reset result: " + result); } catch (Exception e) { Log.e( TAG, "There was an error while establishing connection. -> " + e.getMessage() ); } gtct.closeSocket(sock); // Refresh main activity upon close of dialog box Intent refresh = new Intent(this, TroubleCodesActivity.class); startActivity(refresh); this.finish(); // return true; default: return super.onOptionsItemSelected(item); } } Map<String, String> getDict(int keyId, int valId) { String[] keys = getResources().getStringArray(keyId); String[] vals = getResources().getStringArray(valId); Map<String, String> dict = new HashMap<String, String>(); for (int i = 0, l = keys.length; i < l; i++) { dict.put(keys[i], vals[i]); } return dict; } public void makeToast(String text) { Toast toast = Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT); toast.show(); } public void makeToastLong(String text) { Toast toast = Toast.makeText(getApplicationContext(), text, Toast.LENGTH_LONG); toast.show(); } private void dataOk(String res) { ListView lv = (ListView) findViewById(R.id.listView); Map<String, String> dtcVals = getDict(R.array.dtc_keys, R.array.dtc_values); //TODO replace below codes (res) with aboce dtcVals //String tmpVal = dtcVals.get(res.split("\n")); //String[] dtcCodes = new String[]{}; ArrayList<String> dtcCodes = new ArrayList<String>(); //int i =1; if (res != null) { for (String dtcCode : res.split("\n")) { dtcCodes.add(dtcCode + " : " + dtcVals.get(dtcCode)); Log.d("TEST", dtcCode + " : " + dtcVals.get(dtcCode)); } } else { dtcCodes.add("There are no errors"); } ArrayAdapter<String> myarrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, dtcCodes); lv.setAdapter(myarrayAdapter); lv.setTextFilterEnabled(true); } public class ModifiedTroubleCodesObdCommand extends TroubleCodesCommand { @Override public String getResult() { // remove unwanted response from output since this results in erroneous error codes return rawData.replace("SEARCHING...", "").replace("NODATA", ""); } } public class ClearDTC extends ResetTroubleCodesCommand { @Override public String getResult() { return rawData; } } private class GetTroubleCodesTask extends AsyncTask<String, Integer, String> { @Override protected void onPreExecute() { //Create a new progress dialog progressDialog = new ProgressDialog(TroubleCodesActivity.this); //Set the progress dialog to display a horizontal progress bar progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); //Set the dialog title to 'Loading...' progressDialog.setTitle(getString(R.string.dialog_loading_title)); //Set the dialog message to 'Loading application View, please wait...' progressDialog.setMessage(getString(R.string.dialog_loading_body)); //This dialog can't be canceled by pressing the back key progressDialog.setCancelable(false); //This dialog isn't indeterminate progressDialog.setIndeterminate(false); //The maximum number of items is 100 progressDialog.setMax(5); //Set the current progress to zero progressDialog.setProgress(0); //Display the progress dialog progressDialog.show(); } @Override protected String doInBackground(String... params) { String result = ""; //Get the current thread's token synchronized (this) { Log.d(TAG, "Starting service.."); // get the remote Bluetooth device final BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter(); dev = btAdapter.getRemoteDevice(params[0]); Log.d(TAG, "Stopping Bluetooth discovery."); btAdapter.cancelDiscovery(); Log.d(TAG, "Starting OBD connection.."); // Instantiate a BluetoothSocket for the remote device and connect it. try { sock = BluetoothManager.connect(dev); } catch (Exception e) { Log.e( TAG, "There was an error while establishing connection. -> " + e.getMessage() ); Log.d(TAG, "Message received on handler here"); mHandler.obtainMessage(CANNOT_CONNECT_TO_DEVICE).sendToTarget(); return null; } try { // Let's configure the connection. Log.d(TAG, "Queueing jobs for connection configuration.."); onProgressUpdate(1); new ObdResetCommand().run(sock.getInputStream(), sock.getOutputStream()); onProgressUpdate(2); new EchoOffCommand().run(sock.getInputStream(), sock.getOutputStream()); onProgressUpdate(3); new LineFeedOffCommand().run(sock.getInputStream(), sock.getOutputStream()); onProgressUpdate(4); new SelectProtocolCommand(ObdProtocols.AUTO).run(sock.getInputStream(), sock.getOutputStream()); onProgressUpdate(5); ModifiedTroubleCodesObdCommand tcoc = new ModifiedTroubleCodesObdCommand(); tcoc.run(sock.getInputStream(), sock.getOutputStream()); result = tcoc.getFormattedResult(); onProgressUpdate(6); } catch (IOException e) { e.printStackTrace(); Log.e("DTCERR", e.getMessage()); mHandler.obtainMessage(OBD_COMMAND_FAILURE_IO).sendToTarget(); return null; } catch (InterruptedException e) { e.printStackTrace(); Log.e("DTCERR", e.getMessage()); mHandler.obtainMessage(OBD_COMMAND_FAILURE_IE).sendToTarget(); return null; } catch (UnableToConnectException e) { e.printStackTrace(); Log.e("DTCERR", e.getMessage()); mHandler.obtainMessage(OBD_COMMAND_FAILURE_UTC).sendToTarget(); return null; } catch (MisunderstoodCommandException e) { e.printStackTrace(); Log.e("DTCERR", e.getMessage()); mHandler.obtainMessage(OBD_COMMAND_FAILURE_MIS).sendToTarget(); return null; } catch (NoDataException e) { Log.e("DTCERR", e.getMessage()); mHandler.obtainMessage(OBD_COMMAND_FAILURE_NODATA).sendToTarget(); return null; } catch (Exception e) { Log.e("DTCERR", e.getMessage()); mHandler.obtainMessage(OBD_COMMAND_FAILURE).sendToTarget(); } finally { // close socket closeSocket(sock); } } return result; } public void closeSocket(BluetoothSocket sock) { if (sock != null) // close socket try { sock.close(); } catch (IOException e) { Log.e(TAG, e.getMessage()); } } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); progressDialog.setProgress(values[0]); } @Override protected void onPostExecute(String result) { progressDialog.dismiss(); mHandler.obtainMessage(DATA_OK, result).sendToTarget(); setContentView(R.layout.trouble_codes); } } }