AndroidManifest.xml 에 다음 permission 추가
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
OBDAccess.java
package com.urrecliner.blackbox; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.content.SharedPreferences; import android.view.View; import android.widget.Toast; import com.github.pires.obd.commands.ObdCommand; import com.github.pires.obd.commands.SpeedCommand; import com.github.pires.obd.commands.control.DistanceSinceCCCommand; 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.SelectProtocolCommand; import com.github.pires.obd.commands.protocol.SpacesOffCommand; import com.github.pires.obd.enums.ObdProtocols; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Locale; import java.util.Set; import java.util.Timer; import java.util.TimerTask; import java.util.UUID; import static com.urrecliner.blackbox.Vars.ChronoLog; import static com.urrecliner.blackbox.Vars.OBDConnected; import static com.urrecliner.blackbox.Vars.chronoLogs; import static com.urrecliner.blackbox.Vars.chronoKiloMeter; import static com.urrecliner.blackbox.Vars.lNewsLine; import static com.urrecliner.blackbox.Vars.mActivity; import static com.urrecliner.blackbox.Vars.mContext; import static com.urrecliner.blackbox.Vars.sharedPref; import static com.urrecliner.blackbox.Vars.speedInt; import static com.urrecliner.blackbox.Vars.chronoNowDate; import static com.urrecliner.blackbox.Vars.todayKiloMeter; import static com.urrecliner.blackbox.Vars.utils; import static com.urrecliner.blackbox.Vars.vTextKilo; import static com.urrecliner.blackbox.Vars.vTextSpeed; import static com.urrecliner.blackbox.Vars.vPreviewView; import static com.urrecliner.blackbox.Vars.viewFinder; class OBDAccess { final static int ASK_SPEED_INTERVAL = 1500; String logID = "OBD"; private BluetoothSocket bSocket; private BluetoothDevice bluetoothDevice; private String chosenDeviceName = null; UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); // private ObdCommand engineRpmCommand = new EngineRpmCommand(); private ObdCommand speedCommand = null; // private ObdCommand distanceSinceCCCommand = null; // private ObdCommand loadCommand = new LoadCommand(); void start() { BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter(); if(btAdapter == null){ Toast.makeText(Vars.mContext, "Device doesn't support Bluetooth", Toast.LENGTH_LONG).show(); return; } // final ArrayList<String> pairedDevicesNames = new ArrayList<>(); // final ArrayList<String> pairedDevicesAddresses = new ArrayList<>(); Set<BluetoothDevice> pairedDevices = btAdapter.getBondedDevices(); if (pairedDevices.size() > 0) { for (BluetoothDevice device : pairedDevices) { // utils.log(logID, "pairedDevices ="+device.getName()+" type:"+device.getType()); if (device.getName().contains("OBD")) { bluetoothDevice = device; // chosenDeviceAddress = device.getAddress(); chosenDeviceName = device.getName(); btAdapter.cancelDiscovery(); new Timer().schedule(new TimerTask() { // autoStart public void run() { if (connectOBD() && bSocket.isConnected()) { OBDConnected = true; resetTodayKm(Integer.parseInt(askOBDDistance())); showDistance(); loopAskOBDSpeed(); // new ShowKmLogs().show(chronoLogs); } } }, 100); } } } else{ Toast.makeText(mContext, "\nNo paired devices found\n", Toast.LENGTH_LONG).show(); } } private boolean connectOBD() { // utils.logBoth(logID, "connect OBD"); if (!step1_BuildSocket(bluetoothDevice, uuid)) return false; if (!step2_ResetOBD()) return false; return step3_Initialize(); } private boolean step1_BuildSocket(BluetoothDevice bluetoothDevice, UUID uuid) { try { bSocket = bluetoothDevice.createRfcommSocketToServiceRecord(uuid); bSocket.connect(); if (bSocket.isConnected()) { utils.logBoth("socket", chosenDeviceName + " connected"); return true; } } catch (IllegalArgumentException e) { utils.logE("socket", "IllegalArgumentException ", e); // Toast.makeText(mContext, "Please choose Bluetooth device first", Toast.LENGTH_LONG).show(); } catch (IOException e) { utils.logBoth("socket", "*** OBD NOT FOUND ***"); return true; } catch (Exception e){ utils.logE("socket", "Exception ", e); } return false; } final private int sleepTime = 100; private boolean step2_ResetOBD() { ObdResetCommand obdResetCommand = new ObdResetCommand(); try { for (int i = 0; i < 3; i++) { obdResetCommand.run(bSocket.getInputStream(), bSocket.getOutputStream()); // utils.logBoth("OBD Reset", obdResetCommand.getFormattedResult()); Thread.sleep(sleepTime); // SystemClock.sleep(100); } return true; } catch (IllegalArgumentException e) { // utils.logE("resetOBD", "IllegalArgumentException ", e); } catch (IOException e) { // utils.logBoth("resetOBD", "*** OBD not READY ***"); } catch (Exception e){ // utils.logE("resetOBD", "General Exception ", e); } return false; } private boolean step3_Initialize() { try { EchoOffCommand echoOffCommand = new EchoOffCommand(); echoOffCommand.run(bSocket.getInputStream(), bSocket.getOutputStream()); Thread.sleep(sleepTime); LineFeedOffCommand lineFeedOffCommand = new LineFeedOffCommand(); lineFeedOffCommand.run(bSocket.getInputStream(), bSocket.getOutputStream()); Thread.sleep(sleepTime); SelectProtocolCommand selectProtocolCommand = new SelectProtocolCommand(ObdProtocols.AUTO); selectProtocolCommand.run(bSocket.getInputStream(), bSocket.getOutputStream()); Thread.sleep(sleepTime); SpacesOffCommand spacesOffCommand = new SpacesOffCommand(); spacesOffCommand.run(bSocket.getInputStream(), bSocket.getOutputStream()); return true; } catch (IllegalArgumentException e) { utils.logE(logID, "IllegalArgumentException", e); } catch (IOException e) { utils.logE(logID, "IOException obdCommand", e); } catch (Exception e){ utils.logE(logID, "General Exception", e); } return false; } private void resetTodayKm(int kilo) { String tuDay = new SimpleDateFormat("yy/MM/dd(EEE)", Locale.getDefault()).format(System.currentTimeMillis()); if (!chronoNowDate.equals(tuDay)) { chronoNowDate = tuDay; chronoKiloMeter = kilo; todayKiloMeter = 0; SharedPreferences.Editor editor = sharedPref.edit(); editor.putString("today", chronoNowDate); editor.putInt("kilo", chronoKiloMeter); editor.apply(); } else { todayKiloMeter = kilo - chronoKiloMeter; } } private Timer speedTimer = null; private boolean noPreview = false; private int distCount = 0; private String speedString = "speed", speedOld = "old", distOld = "old"; private void loopAskOBDSpeed() { // switch (SUFFIX) { // case "8": // Galaxy 8 sometimes disconnected so reconnect // try { // bSocket = bluetoothDevice.createRfcommSocketToServiceRecord(uuid); // bSocket.connect(); // } catch (Exception e) { // utils.logBoth("loopAskOBDSpeed connect Exception", e.toString()); // } // break; // case "P": // case "S": // break; // } speedCommand = new SpeedCommand(); speedTimer = new Timer(); final TimerTask speedTask = new TimerTask() { @Override public void run() { speedString = askSpeed(); if (!speedString.equals(speedOld) ) { mActivity.runOnUiThread(() -> { vTextSpeed.setText(speedString); speedInt = Integer.parseInt(speedString); boolean offPrevView = speedInt > 30; // hide video if over 30 Kms if (viewFinder && offPrevView != noPreview) { noPreview = offPrevView; vPreviewView.setVisibility((noPreview) ? View.INVISIBLE : View.VISIBLE); } if (speedOld.equals("old")) { lNewsLine.setVisibility(View.VISIBLE); } speedOld = speedString; }); if (distCount++ > 30) { distCount = 0; showDistance(); } } } }; speedTimer.schedule(speedTask, 200, ASK_SPEED_INTERVAL); } private void showDistance() { String ss = askOBDDistance(); if (ss.equals(distOld)) return; distOld = ss; todayKiloMeter = Integer.parseInt(ss) - chronoKiloMeter; mActivity.runOnUiThread(() -> { String s = ""+todayKiloMeter; vTextKilo.setText(s); }); } private String askSpeed() { try { speedCommand.run(bSocket.getInputStream(), bSocket.getOutputStream()); return speedCommand.getCalculatedResult(); } catch (IllegalArgumentException e) { utils.logE("speed", "IllegalArgumentException", e); } catch (IOException e) { utils.logE("speed", "IOException obdCommand", e); } catch (Exception e){ utils.logE("speed", "General Exception", e); } return "0"; } private String askOBDDistance() { try { DistanceSinceCCCommand distanceSinceCCCommand = new DistanceSinceCCCommand(); distanceSinceCCCommand.run(bSocket.getInputStream(), bSocket.getOutputStream()); return distanceSinceCCCommand.getCalculatedResult(); } catch (Exception e){ utils.logE("distance", "General Exception", e); } return "0"; } void stop() { if (speedTimer != null) speedTimer.cancel(); speedTimer = null; } }
MainActivity.java 내에
OBDAccess obdAccess = new OBDAccess();
obdAccess.start();
OBDAccess.java 에 ASK_SPEED_INTERVAL 마다 OBDII에 speed를 물어 보고 이를 화면에 표시하는 로직 있음
Related logics to keep cumurative distance (OBDII로 부터 받은 거리 정보를 이용)
static ArrayList<ChronoLog> chronoLogs = null;
public static class ChronoLog {
String chroDate;
int chroKilo;
int todayKilo;
}
class ShowKmLogs {
void show(ArrayList<ChronoLog> logs){
if (logs.size() == 0)
return;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < logs.size(); i++) {
Vars.ChronoLog log = logs.get(i);
sb.append((i%2 == 0) ? "\n":", ");
sb.append(log.chroDate).append(" = ")
.append((log.todayKilo>9)?log.todayKilo:"0"+log.todayKilo).append("Km");
}
utils.logShow("Kilo Log", sb.toString());
}
}
OBDII distance sharedPref save & load using json API
private void updateKiloChronology() {
if (chronoNowDate == null)
return;
if (chronoLogs.size() == 0) {
addTodayKilo();
} else {
if (chronoLogs.size() > 10)
chronoLogs.remove(0);
ChronoLog chronoLatest = chronoLogs.get(chronoLogs.size() - 1);
if (chronoLatest.chroDate.equals(chronoNowDate) && chronoLatest.todayKilo < todayKiloMeter) {
chronoLatest.chroKilo = chronoKiloMeter;
chronoLatest.todayKilo = todayKiloMeter;
chronoLogs.set(chronoLogs.size() - 1, chronoLatest);
} else {
addTodayKilo();
}
}
SharedPreferences.Editor prefsEditor = sharedPref.edit();
Gson gson = new Gson();
String json = gson.toJson(chronoLogs);
prefsEditor.putString("chrono", json);
prefsEditor.apply();
}
private void addTodayKilo() {
if (todayKiloMeter != -1) {
ChronoLog chronoLog = new ChronoLog();
chronoLog.chroDate = chronoNowDate;
chronoLog.chroKilo = chronoKiloMeter;
chronoLog.todayKilo = todayKiloMeter;
chronoLogs.add(chronoLog);
}
}
ArrayList<ChronoLog> getTodayTable() {
ArrayList<ChronoLog> list;
Gson gson = new Gson();
String json = sharedPref.getString("chrono", "");
if (json.isEmpty()) {
list = new ArrayList<>();
} else {
Type type = new TypeToken<List<ChronoLog>>() {
}.getType();
list = gson.fromJson(json, type);
}
return list;
}
'android source ' 카테고리의 다른 글
Background Handler 준비해 두기 (0) | 2022.05.15 |
---|---|
Direction Sensor (0) | 2022.05.15 |
Media data Retrieve (0) | 2020.12.23 |
media update after write file (0) | 2020.02.02 |
Chronometer (0) | 2020.02.01 |