From 67edc51b5a4d5005686380764e87978fc67541ea Mon Sep 17 00:00:00 2001 From: Philip Khaisman Date: Tue, 7 Jan 2025 15:05:03 -0500 Subject: [PATCH 1/9] Init new driver template --- sensorhub-android-app/build.gradle | 1 + sensorhub-android-obd2/build.gradle | 15 ++++++ .../src/main/AndroidManifest.xml | 8 +++ .../impl/sensor/obd2/Obd2Config.java | 18 +++++++ .../impl/sensor/obd2/Obd2Descriptor.java | 38 ++++++++++++++ .../impl/sensor/obd2/Obd2Output.java | 38 ++++++++++++++ .../impl/sensor/obd2/Obd2Sensor.java | 52 +++++++++++++++++++ .../org.sensorhub.api.module.IModuleProvider | 1 + 8 files changed, 171 insertions(+) create mode 100644 sensorhub-android-obd2/build.gradle create mode 100644 sensorhub-android-obd2/src/main/AndroidManifest.xml create mode 100644 sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Config.java create mode 100644 sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Descriptor.java create mode 100644 sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Output.java create mode 100644 sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java create mode 100644 sensorhub-android-obd2/src/main/resources/META-INF/services/org.sensorhub.api.module.IModuleProvider diff --git a/sensorhub-android-app/build.gradle b/sensorhub-android-app/build.gradle index b60fc16f..bf752963 100644 --- a/sensorhub-android-app/build.gradle +++ b/sensorhub-android-app/build.gradle @@ -27,6 +27,7 @@ dependencies { implementation project(path: ':sensorhub-datastore-h2') implementation project(path: ':sensorhub-service-sweapi') implementation project(':sensorhub-android-ste') + implementation project(':sensorhub-android-obd2') } android { diff --git a/sensorhub-android-obd2/build.gradle b/sensorhub-android-obd2/build.gradle new file mode 100644 index 00000000..1ae61327 --- /dev/null +++ b/sensorhub-android-obd2/build.gradle @@ -0,0 +1,15 @@ +apply plugin: 'com.android.library' + +description = 'OBD2 Sensor' +ext.details = 'Driver for OBD2 sensors' + +dependencies { + api project(':sensorhub-core') + implementation "com.android.support:appcompat-v7:28.0.0" + implementation project(':sensorhub-android-service') + implementation project(':sensorhub-driver-android') +} + +android { + compileSdk = 28 +} \ No newline at end of file diff --git a/sensorhub-android-obd2/src/main/AndroidManifest.xml b/sensorhub-android-obd2/src/main/AndroidManifest.xml new file mode 100644 index 00000000..19783188 --- /dev/null +++ b/sensorhub-android-obd2/src/main/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Config.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Config.java new file mode 100644 index 00000000..a5e30b99 --- /dev/null +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Config.java @@ -0,0 +1,18 @@ +package org.sensorhub.impl.sensor.obd2; + +import android.content.Context; +import android.provider.Settings; + +import org.sensorhub.android.SensorHubService; +import org.sensorhub.api.sensor.SensorConfig; + +public class Obd2Config extends SensorConfig { + public Obd2Config() { + this.moduleClass = Obd2Sensor.class.getCanonicalName(); + } + + public static String getUid() { + Context context = SensorHubService.getContext(); + return "urn:android:obd2:" + Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); + } +} diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Descriptor.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Descriptor.java new file mode 100644 index 00000000..6b61b17a --- /dev/null +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Descriptor.java @@ -0,0 +1,38 @@ +package org.sensorhub.impl.sensor.obd2; + +import org.sensorhub.api.module.IModule; +import org.sensorhub.api.module.IModuleProvider; +import org.sensorhub.api.module.ModuleConfig; +import org.sensorhub.impl.module.JarModuleProvider; + +public class Obd2Descriptor implements IModuleProvider { + @Override + public String getModuleName() { + return "OBD2 Driver"; + } + + @Override + public String getModuleDescription() { + return "Driver for OBD2 sensors conected via BLE"; + } + + @Override + public String getModuleVersion() { + return "0.1"; + } + + @Override + public String getProviderName() { + return "Botts Innovative Research, Inc."; + } + + @Override + public Class> getModuleClass() { + return Obd2Sensor.class; + } + + @Override + public Class getModuleConfigClass() { + return Obd2Config.class; + } +} diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Output.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Output.java new file mode 100644 index 00000000..b62b8abf --- /dev/null +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Output.java @@ -0,0 +1,38 @@ +package org.sensorhub.impl.sensor.obd2; + +import net.opengis.swe.v20.DataBlock; +import net.opengis.swe.v20.DataComponent; +import net.opengis.swe.v20.DataEncoding; + +import org.sensorhub.impl.sensor.AbstractSensorOutput; + +public class Obd2Output extends AbstractSensorOutput { + DataComponent dataStruct; + DataEncoding dataEnc; + + public Obd2Output(Obd2Sensor parentSensor) + { + super("obd2Data", parentSensor); + } + + protected void init() { + } + + @Override + public double getAverageSamplingPeriod() + { + return 1.0; + } + + @Override + public DataComponent getRecordDescription() + { + return dataStruct; + } + + @Override + public DataEncoding getRecommendedEncoding() + { + return dataEnc; + } +} diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java new file mode 100644 index 00000000..fe36afbe --- /dev/null +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java @@ -0,0 +1,52 @@ +package org.sensorhub.impl.sensor.obd2; + +import android.os.Build; + +import org.sensorhub.impl.sensor.AbstractSensorModule; +import org.sensorhub.api.common.SensorHubException; + +public class Obd2Sensor extends AbstractSensorModule { + public Obd2Sensor() { + } + + @Override + protected void doInit() throws SensorHubException { + super.doInit(); + + // set IDs + this.xmlID = "OBD2_" + Build.SERIAL; + this.uniqueID = Obd2Config.getUid(); + + // init output(s) + } + + + @Override + protected void updateSensorDescription() { + synchronized (sensorDescLock) + { + super.updateSensorDescription(); + + if (!sensorDescription.isSetDescription()) { + sensorDescription.setDescription("Driver for OBD2 sensors conected via BLE"); + } + } + } + + @Override + protected void doStart() throws SensorHubException { + } + + @Override + protected void doStop() throws SensorHubException {} + + @Override + public void cleanup() throws SensorHubException {} + + @Override + public boolean isConnected() { + // return (gattClient != null); + + return true; + } +} \ No newline at end of file diff --git a/sensorhub-android-obd2/src/main/resources/META-INF/services/org.sensorhub.api.module.IModuleProvider b/sensorhub-android-obd2/src/main/resources/META-INF/services/org.sensorhub.api.module.IModuleProvider new file mode 100644 index 00000000..b82900da --- /dev/null +++ b/sensorhub-android-obd2/src/main/resources/META-INF/services/org.sensorhub.api.module.IModuleProvider @@ -0,0 +1 @@ +org.sensorhub.impl.sensor.obd2.Descriptor From c47ee78e3e95e4631525fed523331caa0298629f Mon Sep 17 00:00:00 2001 From: Philip Khaisman Date: Wed, 8 Jan 2025 12:23:58 -0500 Subject: [PATCH 2/9] Handle bluetooth device connection --- .../res/xml/pref_sensors.xml | 14 +++ .../org/sensorhub/android/MainActivity.java | 16 ++++ .../impl/sensor/obd2/Obd2Output.java | 2 +- .../impl/sensor/obd2/Obd2Sensor.java | 92 ++++++++++++++++--- 4 files changed, 108 insertions(+), 16 deletions(-) diff --git a/sensorhub-android-app/res/xml/pref_sensors.xml b/sensorhub-android-app/res/xml/pref_sensors.xml index a49d5a21..7e0dd51a 100644 --- a/sensorhub-android-app/res/xml/pref_sensors.xml +++ b/sensorhub-android-app/res/xml/pref_sensors.xml @@ -232,6 +232,20 @@ android:entryValues="@array/sos_option_values" android:defaultValue="@array/sos_option_defaults" /> + + + + diff --git a/sensorhub-android-app/src/org/sensorhub/android/MainActivity.java b/sensorhub-android-app/src/org/sensorhub/android/MainActivity.java index 8fc29269..598e3fc5 100644 --- a/sensorhub-android-app/src/org/sensorhub/android/MainActivity.java +++ b/sensorhub-android-app/src/org/sensorhub/android/MainActivity.java @@ -81,6 +81,7 @@ import org.sensorhub.impl.service.sweapi.SWEApiServiceConfig; import org.sensorhub.impl.sensor.trupulse.SimulatedDataStream; import org.sensorhub.impl.sensor.ste.STERadPagerConfig; +import org.sensorhub.impl.sensor.obd2.Obd2Config; import java.io.File; import java.net.MalformedURLException; @@ -153,6 +154,7 @@ enum Sensors { ProxySensor, BLELocation, STERadPager, + Obd2Sensor, } @@ -424,6 +426,18 @@ public boolean verify(String arg0, SSLSession arg1) { sensorhubConfig.add(steRadPagerConfig); } + // OBD2 sensor + enabled = prefs.getBoolean("obd2_enabled", false); + if(enabled){ + Obd2Config obd2Config = new Obd2Config(); + obd2Config.id = "OBD2_SENSOR"; + obd2Config.name = "OBD2 [" + deviceName + "]"; + obd2Config.autoStart = true; + obd2Config.lastUpdated = ANDROID_SENSORS_LAST_UPDATED; + + sensorhubConfig.add(obd2Config); + } + // AngelSensor /*enabled = prefs.getBoolean("angel_enabled", false); if (enabled) @@ -971,6 +985,8 @@ private boolean isPushingSensor(Sensors sensor) { return prefs.getBoolean("ble_enable", false) && prefs.getStringSet("ble_options", Collections.emptySet()).contains("PUSH_REMOTE"); } else if(Sensors.STERadPager.equals(sensor)){ return prefs.getBoolean("ste_radpager_enabled", false) && prefs.getStringSet("radpager_options", Collections.emptySet()).contains("PUSH_REMOTE"); + } else if(Sensors.Obd2Sensor.equals(sensor)){ + return prefs.getBoolean("obd2_enabled", false) && prefs.getStringSet("obd2_options", Collections.emptySet()).contains("PUSH_REMOTE"); } return false; diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Output.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Output.java index b62b8abf..1fc76177 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Output.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Output.java @@ -15,7 +15,7 @@ public Obd2Output(Obd2Sensor parentSensor) super("obd2Data", parentSensor); } - protected void init() { + protected void doInit() { } @Override diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java index fe36afbe..0ec6354c 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java @@ -1,52 +1,114 @@ package org.sensorhub.impl.sensor.obd2; +import android.Manifest; +import android.app.Activity; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCallback; +import android.bluetooth.BluetoothManager; +import android.content.Context; +import android.content.pm.PackageManager; import android.os.Build; +import android.support.v4.app.ActivityCompat; +import org.sensorhub.android.SensorHubService; +import org.sensorhub.api.sensor.SensorException; import org.sensorhub.impl.sensor.AbstractSensorModule; import org.sensorhub.api.common.SensorHubException; +import java.util.Set; + public class Obd2Sensor extends AbstractSensorModule { - public Obd2Sensor() { + private String deviceName; + private Context context; + private BluetoothAdapter btAdapter; + private BluetoothGatt btGatt; + Obd2Output output; + private boolean btConnected = false; + + public Obd2Sensor(String deviceName) { + this.deviceName = deviceName; } @Override protected void doInit() throws SensorHubException { - super.doInit(); + // TODO Do I need this + // super.doInit(); // set IDs this.xmlID = "OBD2_" + Build.SERIAL; this.uniqueID = Obd2Config.getUid(); + // set up bluetooth adapter + context = SensorHubService.getContext(); + final BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Activity.BLUETOOTH_SERVICE); + btAdapter = bluetoothManager.getAdapter(); + + if (!btAdapter.isEnabled() || btAdapter == null) { + throw new SensorException("Could not get bluetooth adapter, unable to initiate."); + } + + // TODO The STE sensor uses location data. I need to determine if I need it + // init output(s) + output = new Obd2Output(this); + output.doInit(); + addOutput(output, false); } - @Override - protected void updateSensorDescription() { - synchronized (sensorDescLock) - { - super.updateSensorDescription(); + protected void doStart() throws SensorHubException { + // TODO Do I need to call super.doStart()? - if (!sensorDescription.isSetDescription()) { - sensorDescription.setDescription("Driver for OBD2 sensors conected via BLE"); + Set devices = btAdapter.getBondedDevices(); + BluetoothDevice device = null; + + // find the device + for (BluetoothDevice d : devices) { + if (d.getName().equals(deviceName)) { + device = d; } } + + if (device == null) { + throw new SensorException("Could not find bluetooth device, unable to start."); + } + + // request bluetooth permissions + if (context.checkSelfPermission(Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_DENIED) { + ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.BLUETOOTH}, 1); + } + + // connect to the device + btGatt = device.connectGatt(context, true, gattCallback); } @Override - protected void doStart() throws SensorHubException { + protected void doStop() throws SensorHubException { + btGatt.disconnect(); + btGatt.close(); } @Override - protected void doStop() throws SensorHubException {} + public void cleanup() throws SensorHubException {} @Override - public void cleanup() throws SensorHubException {} + protected void updateSensorDescription() { + synchronized (sensorDescLock) + { + super.updateSensorDescription(); + + if (!sensorDescription.isSetDescription()) { + sensorDescription.setDescription("Driver for OBD2 sensors conected via BLE"); + } + } + } @Override public boolean isConnected() { - // return (gattClient != null); - - return true; + return btConnected; } + + private BluetoothGattCallback gattCallback = new BluetoothGattCallback() {}; } \ No newline at end of file From 2cf44f35b7568013b88a44be1c02f65f78df1bda Mon Sep 17 00:00:00 2001 From: Philip Khaisman Date: Wed, 8 Jan 2025 14:21:27 -0500 Subject: [PATCH 3/9] Implement connection for bluetooth classic instead of ble --- .../src/main/AndroidManifest.xml | 1 + .../impl/sensor/obd2/Obd2Sensor.java | 89 +++++++++++++------ 2 files changed, 64 insertions(+), 26 deletions(-) diff --git a/sensorhub-android-obd2/src/main/AndroidManifest.xml b/sensorhub-android-obd2/src/main/AndroidManifest.xml index 19783188..d25cc1a5 100644 --- a/sensorhub-android-obd2/src/main/AndroidManifest.xml +++ b/sensorhub-android-obd2/src/main/AndroidManifest.xml @@ -4,5 +4,6 @@ + \ No newline at end of file diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java index 0ec6354c..fc3a390a 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java @@ -7,6 +7,8 @@ import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCallback; import android.bluetooth.BluetoothManager; +import android.bluetooth.BluetoothProfile; +import android.bluetooth.BluetoothSocket; import android.content.Context; import android.content.pm.PackageManager; import android.os.Build; @@ -18,12 +20,19 @@ import org.sensorhub.api.common.SensorHubException; import java.util.Set; +import java.util.UUID; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; public class Obd2Sensor extends AbstractSensorModule { + private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); + private String deviceName; private Context context; private BluetoothAdapter btAdapter; - private BluetoothGatt btGatt; + private BluetoothSocket btSocket; // TODO Should this be an attribute? + // private BluetoothGatt btGatt; Obd2Output output; private boolean btConnected = false; @@ -33,14 +42,13 @@ public Obd2Sensor(String deviceName) { @Override protected void doInit() throws SensorHubException { - // TODO Do I need this - // super.doInit(); + // TODO Do I to call super.doInit()? // set IDs this.xmlID = "OBD2_" + Build.SERIAL; this.uniqueID = Obd2Config.getUid(); - // set up bluetooth adapter + // get the android's bluetooth adapter context = SensorHubService.getContext(); final BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Activity.BLUETOOTH_SERVICE); btAdapter = bluetoothManager.getAdapter(); @@ -49,22 +57,10 @@ protected void doInit() throws SensorHubException { throw new SensorException("Could not get bluetooth adapter, unable to initiate."); } - // TODO The STE sensor uses location data. I need to determine if I need it - - // init output(s) - output = new Obd2Output(this); - output.doInit(); - addOutput(output, false); - } - - @Override - protected void doStart() throws SensorHubException { - // TODO Do I need to call super.doStart()? - - Set devices = btAdapter.getBondedDevices(); BluetoothDevice device = null; + Set devices = btAdapter.getBondedDevices(); - // find the device + // find the bluetooth device for (BluetoothDevice d : devices) { if (d.getName().equals(deviceName)) { device = d; @@ -75,19 +71,44 @@ protected void doStart() throws SensorHubException { throw new SensorException("Could not find bluetooth device, unable to start."); } - // request bluetooth permissions - if (context.checkSelfPermission(Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_DENIED) { - ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.BLUETOOTH}, 1); + // create a bluetooth socket + try { + btSocket = device.createRfcommSocketToServiceRecord(SPP_UUID); + } catch (IOException e) { + // TODO Is this what I want to happen if creating the socket fails? + throw new SensorException("Could not create client socket", e); } - // connect to the device - btGatt = device.connectGatt(context, true, gattCallback); + // TODO Do I need to use location data? + + // init osh output(s) + output = new Obd2Output(this); + output.doInit(); + addOutput(output, false); + } + + @Override + protected void doStart() throws SensorHubException { + // TODO Do I need to call super.doStart()? + + btAdapter.cancelDiscovery(); + + // connect to the bluetooth device + try { + btSocket.connect(); + } catch (IOException connectException) { + try { + btSocket.close(); + } catch (IOException e) { + // TODO Is this what I want to happen if connecting to the socket fails? + throw new SensorException("Could not close the client socket", e); + } + } } @Override protected void doStop() throws SensorHubException { - btGatt.disconnect(); - btGatt.close(); + // TODO Close the socket. Here and/or elsewhere too? } @Override @@ -110,5 +131,21 @@ public boolean isConnected() { return btConnected; } - private BluetoothGattCallback gattCallback = new BluetoothGattCallback() {}; + private BluetoothGattCallback gattCallback = new BluetoothGattCallback() { + @Override + public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { + if (newState == BluetoothProfile.STATE_CONNECTED) { + btConnected = true; + gatt.discoverServices(); + } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { + btConnected = false; + // TODO What should I do if connection is lost? + } + } + + @Override + public void onServicesDiscovered(BluetoothGatt gatt, int status) { + + } + }; } \ No newline at end of file From 708ea1f13ce466ecdaeb4d89d00dccc3ee498dc0 Mon Sep 17 00:00:00 2001 From: Philip Khaisman Date: Wed, 8 Jan 2025 15:18:16 -0500 Subject: [PATCH 4/9] Implement connection logic in a thread --- .../impl/sensor/obd2/Obd2Sensor.java | 61 ++++--------------- .../sensor/obd2/utils/ConnectionThread.java | 58 ++++++++++++++++++ .../sensor/obd2/utils/ReadWriteThread.java | 0 3 files changed, 69 insertions(+), 50 deletions(-) create mode 100644 sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/utils/ConnectionThread.java create mode 100644 sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/utils/ReadWriteThread.java diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java index fc3a390a..9bcd3e70 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java @@ -1,38 +1,30 @@ package org.sensorhub.impl.sensor.obd2; -import android.Manifest; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothGatt; -import android.bluetooth.BluetoothGattCallback; import android.bluetooth.BluetoothManager; -import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothSocket; import android.content.Context; -import android.content.pm.PackageManager; import android.os.Build; -import android.support.v4.app.ActivityCompat; import org.sensorhub.android.SensorHubService; import org.sensorhub.api.sensor.SensorException; import org.sensorhub.impl.sensor.AbstractSensorModule; import org.sensorhub.api.common.SensorHubException; +import org.sensorhub.impl.sensor.obd2.utils.ConnectionThread; import java.util.Set; import java.util.UUID; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; public class Obd2Sensor extends AbstractSensorModule { private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); private String deviceName; private Context context; + + private ConnectionThread connectionThread; private BluetoothAdapter btAdapter; - private BluetoothSocket btSocket; // TODO Should this be an attribute? - // private BluetoothGatt btGatt; Obd2Output output; private boolean btConnected = false; @@ -58,8 +50,10 @@ protected void doInit() throws SensorHubException { } BluetoothDevice device = null; + // TODO What if the device isn't bonded? Do I need to make calls to discover it? Sounds like I might. Set devices = btAdapter.getBondedDevices(); + // find the bluetooth device for (BluetoothDevice d : devices) { if (d.getName().equals(deviceName)) { @@ -71,13 +65,8 @@ protected void doInit() throws SensorHubException { throw new SensorException("Could not find bluetooth device, unable to start."); } - // create a bluetooth socket - try { - btSocket = device.createRfcommSocketToServiceRecord(SPP_UUID); - } catch (IOException e) { - // TODO Is this what I want to happen if creating the socket fails? - throw new SensorException("Could not create client socket", e); - } + // create a bluetooth socket via a thread + connectionThread = new ConnectionThread(btAdapter, device); // TODO Do I need to use location data? @@ -91,19 +80,9 @@ protected void doInit() throws SensorHubException { protected void doStart() throws SensorHubException { // TODO Do I need to call super.doStart()? - btAdapter.cancelDiscovery(); - - // connect to the bluetooth device - try { - btSocket.connect(); - } catch (IOException connectException) { - try { - btSocket.close(); - } catch (IOException e) { - // TODO Is this what I want to happen if connecting to the socket fails? - throw new SensorException("Could not close the client socket", e); - } - } + // connect to the bluetooth device via a thread + // TODO How/when should I close the thread? + connectionThread.start(); } @Override @@ -128,24 +107,6 @@ protected void updateSensorDescription() { @Override public boolean isConnected() { - return btConnected; + return connectionThread.isConnected(); } - - private BluetoothGattCallback gattCallback = new BluetoothGattCallback() { - @Override - public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { - if (newState == BluetoothProfile.STATE_CONNECTED) { - btConnected = true; - gatt.discoverServices(); - } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { - btConnected = false; - // TODO What should I do if connection is lost? - } - } - - @Override - public void onServicesDiscovered(BluetoothGatt gatt, int status) { - - } - }; } \ No newline at end of file diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/utils/ConnectionThread.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/utils/ConnectionThread.java new file mode 100644 index 00000000..4a9c581d --- /dev/null +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/utils/ConnectionThread.java @@ -0,0 +1,58 @@ +package org.sensorhub.impl.sensor.obd2.utils; + +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothSocket; + +import org.sensorhub.api.sensor.SensorException; + +import java.util.UUID; +import java.io.IOException; + +public class ConnectionThread extends Thread { + private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); + private final BluetoothSocket btSocket; + private final BluetoothDevice btDevice; + private final BluetoothAdapter btAdapter; + volatile boolean active = true; + + public ConnectionThread(BluetoothAdapter adapter, BluetoothDevice device) throws SensorException { + btAdapter = adapter; + btDevice = device; + BluetoothSocket tmpSocket = null; + + try { + tmpSocket = device.createRfcommSocketToServiceRecord(SPP_UUID); + } catch (IOException e) { + // TODO Is this what I want to happen if creating the socket fails? + throw new SensorException("Could not create client socket", e); + } + + btSocket = tmpSocket; + } + + public void run() { + while (active) { + btAdapter.cancelDiscovery(); + + // connect to the bluetooth device + try { + btSocket.connect(); + } catch (IOException connectException) { + try { + btSocket.close(); + } catch (IOException e) { + // TODO What should I do if I can't close the socket? + } + } + } + } + + public void stopThread() { + active = false; + } + + public boolean isConnected() { + return btSocket.isConnected(); + } +} \ No newline at end of file diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/utils/ReadWriteThread.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/utils/ReadWriteThread.java new file mode 100644 index 00000000..e69de29b From 8d9d274dfe0473f2414bc9261f35f1552b1b5585 Mon Sep 17 00:00:00 2001 From: Philip Khaisman Date: Fri, 10 Jan 2025 13:51:38 -0500 Subject: [PATCH 5/9] Make small tweaks --- .../sensorhub/impl/sensor/obd2/Obd2Sensor.java | 10 +++++----- .../impl/sensor/obd2/utils/ConnectionThread.java | 15 +++++++++------ 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java index 9bcd3e70..e8486d0c 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java @@ -22,10 +22,9 @@ public class Obd2Sensor extends AbstractSensorModule { private String deviceName; private Context context; - private ConnectionThread connectionThread; private BluetoothAdapter btAdapter; - Obd2Output output; + private Obd2Output output; private boolean btConnected = false; public Obd2Sensor(String deviceName) { @@ -81,13 +80,14 @@ protected void doStart() throws SensorHubException { // TODO Do I need to call super.doStart()? // connect to the bluetooth device via a thread - // TODO How/when should I close the thread? connectionThread.start(); + + // and then what? i think we'll need a command class to send commands to read data. where do we interface with the driver? android? computer? api? } @Override - protected void doStop() throws SensorHubException { - // TODO Close the socket. Here and/or elsewhere too? + protected void doStop() { + connectionThread.cancel(); } @Override diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/utils/ConnectionThread.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/utils/ConnectionThread.java index 4a9c581d..a4b1876a 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/utils/ConnectionThread.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/utils/ConnectionThread.java @@ -12,17 +12,15 @@ public class ConnectionThread extends Thread { private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); private final BluetoothSocket btSocket; - private final BluetoothDevice btDevice; private final BluetoothAdapter btAdapter; volatile boolean active = true; - public ConnectionThread(BluetoothAdapter adapter, BluetoothDevice device) throws SensorException { + public ConnectionThread(BluetoothAdapter adapter, BluetoothDevice btDevice) throws SensorException { btAdapter = adapter; - btDevice = device; BluetoothSocket tmpSocket = null; try { - tmpSocket = device.createRfcommSocketToServiceRecord(SPP_UUID); + tmpSocket = btDevice.createRfcommSocketToServiceRecord(SPP_UUID); } catch (IOException e) { // TODO Is this what I want to happen if creating the socket fails? throw new SensorException("Could not create client socket", e); @@ -48,8 +46,13 @@ public void run() { } } - public void stopThread() { - active = false; + public void cancel() { + try { + active = false; + btSocket.close(); + } catch (IOException e) { + // TODO What should I do if I can't close the socket? + } } public boolean isConnected() { From 24d5355570dee946aa14ab0fad62c6561ce59886 Mon Sep 17 00:00:00 2001 From: Philip Khaisman Date: Fri, 17 Jan 2025 21:57:29 -0500 Subject: [PATCH 6/9] OBD2 commands save point --- sensorhub-android-obd2/build.gradle | 2 + .../impl/sensor/obd2/Obd2Control.java | 82 +++++++++++++++++++ .../impl/sensor/obd2/Obd2Sensor.java | 6 +- .../sensor/obd2/commands/Obd2Command.java | 27 ++++++ .../impl/sensor/obd2/commands/commands.json | 12 +++ .../sensor/obd2/utils/ConnectionThread.java | 4 + 6 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Control.java create mode 100644 sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Command.java create mode 100644 sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/commands.json diff --git a/sensorhub-android-obd2/build.gradle b/sensorhub-android-obd2/build.gradle index 1ae61327..5b11c387 100644 --- a/sensorhub-android-obd2/build.gradle +++ b/sensorhub-android-obd2/build.gradle @@ -6,6 +6,8 @@ ext.details = 'Driver for OBD2 sensors' dependencies { api project(':sensorhub-core') implementation "com.android.support:appcompat-v7:28.0.0" + implementation 'com.github.pires:obd-java-api:1.0' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.18.2' implementation project(':sensorhub-android-service') implementation project(':sensorhub-driver-android') } diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Control.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Control.java new file mode 100644 index 00000000..76011b9a --- /dev/null +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Control.java @@ -0,0 +1,82 @@ +package org.sensorhub.impl.sensor.obd2; + +import net.opengis.swe.v20.DataBlock; +import net.opengis.swe.v20.DataChoice; +import net.opengis.swe.v20.DataRecord; +import net.opengis.swe.v20.DataComponent; +import org.sensorhub.impl.sensor.AbstractSensorControl; +import org.sensorhub.impl.sensor.obd2.commands.Obd2Command; +import org.sensorhub.api.command.CommandException; +import org.vast.swe.SWEHelper; +import com.github.pires.obd.commands.control.DistanceMILOnCommand; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.File; +import java.io.IOException; + +import java.util.HashMap; + +public class Obd2Control extends AbstractSensorControl { + DataChoice commandData; + DataRecord commandStruct; + HashMap commands; + + public Obd2Control(Obd2Sensor parentSensor) { + super("control", parentSensor); + } + + @Override + public DataComponent getCommandDescription() { + return commandStruct; + } + + @Override + protected boolean execCommand(DataBlock commandBlock) throws CommandException { + try { + DataRecord commandData = commandStruct.copy(); + commandData.setData(commandBlock); + DataComponent component = commandData.getField("Command"); + String commandName = component.getData().getStringValue(); + Obd2Command command = commands.get(commandName); + + try { + command.run(); + // TODO How do I get the data back and what do I do with it? + } catch (Exception e) { + // TODO Handle errors + } + } catch (Exception e) { + throw new RuntimeException(e); + } + + return true; + } + + public void init() { + File file = new File("./commands/commands.json"); + ObjectMapper objectMapper = new ObjectMapper(); + + try { + commands = objectMapper.readValue(file, HashMap.class); + } catch (IOException e) { + e.printStackTrace(); + } + + SWEHelper swe = new SWEHelper(); + DataChoice command = swe.createChoice() + .name("Command") + .label("Command") + .description("Commands accepted by the platform") + .definition(SWEHelper.getPropertyUri("Command")) + .addItem() + .build(); + + for (Obd2Command cmd : commands.values()) { + command.addItem(cmd.getCommandRecord().getName(), cmd.getCommandRecord()); + } + + } + + public void stop() { + // TODO Auto-generated method stub + } +} \ No newline at end of file diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java index e8486d0c..e06bda80 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java @@ -31,6 +31,10 @@ public Obd2Sensor(String deviceName) { this.deviceName = deviceName; } + public BluetoothSocket getBtSocket() { + return connectionThread.getBtSocket(); + } + @Override protected void doInit() throws SensorHubException { // TODO Do I to call super.doInit()? @@ -82,7 +86,7 @@ protected void doStart() throws SensorHubException { // connect to the bluetooth device via a thread connectionThread.start(); - // and then what? i think we'll need a command class to send commands to read data. where do we interface with the driver? android? computer? api? + // TODO and then what? i think we'll need a command class to send commands to read data. where do we interface with the driver? android? computer? api? } @Override diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Command.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Command.java new file mode 100644 index 00000000..8f666763 --- /dev/null +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Command.java @@ -0,0 +1,27 @@ +package org.sensorhub.impl.sensor.obd2.commands; + +import net.opengis.swe.v20.DataRecord; + +import org.vast.swe.SWEHelper; + +public class Obd2Command { + private DataRecord commandRecord; + private String function; + + public Obd2Command(String name, String description, String function) { + SWEHelper swe = new SWEHelper(); + + this.function = function; + this.commandRecord = swe.createRecord() + .name(name) + .updatable(true) + .label(name) + .description(description) + .definition(SWEHelper.getPropertyUri(name)) + .build(); + } + + public DataRecord getCommandRecord() { + return commandRecord; + } +} \ No newline at end of file diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/commands.json b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/commands.json new file mode 100644 index 00000000..d02271fd --- /dev/null +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/commands.json @@ -0,0 +1,12 @@ +{ + "DistanceMILOn": { + "name": "DistanceMILOn", + "description": "Distance traveled (km) with the malfunction indicator lamp (MIL) on", + "function": "DistanceMILOnCommand" + }, + "DistanceSinceCC": { + "name": "DistanceSinceCC", + "description": "Distance traveled (km) since codes cleared-up", + "function": "DistanceSinceCCCommand" + } +} \ No newline at end of file diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/utils/ConnectionThread.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/utils/ConnectionThread.java index a4b1876a..ecc7cda9 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/utils/ConnectionThread.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/utils/ConnectionThread.java @@ -29,6 +29,10 @@ public ConnectionThread(BluetoothAdapter adapter, BluetoothDevice btDevice) thro btSocket = tmpSocket; } + public BluetoothSocket getBtSocket() { + return btSocket; + } + public void run() { while (active) { btAdapter.cancelDiscovery(); From a32eb5a7e1e8dcef806a62435b4ec884b15b20a9 Mon Sep 17 00:00:00 2001 From: Philip Khaisman Date: Mon, 20 Jan 2025 16:40:13 -0500 Subject: [PATCH 7/9] Implement control class --- ...ConnectionThread.java => Obd2Connect.java} | 6 +- .../impl/sensor/obd2/Obd2Control.java | 83 ++++++++++++------- .../impl/sensor/obd2/Obd2Output.java | 61 ++++++++++++-- .../impl/sensor/obd2/Obd2Sensor.java | 10 ++- .../sensor/obd2/commands/Obd2Command.java | 34 ++++++-- .../sensor/obd2/commands/Obd2CommandTask.java | 45 ++++++++++ .../sensor/obd2/commands/Obd2Commands.java | 45 ++++++++++ .../impl/sensor/obd2/commands/commands.json | 8 +- .../sensor/obd2/utils/ReadWriteThread.java | 0 9 files changed, 241 insertions(+), 51 deletions(-) rename sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/{utils/ConnectionThread.java => Obd2Connect.java} (89%) create mode 100644 sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2CommandTask.java create mode 100644 sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Commands.java delete mode 100644 sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/utils/ReadWriteThread.java diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/utils/ConnectionThread.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Connect.java similarity index 89% rename from sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/utils/ConnectionThread.java rename to sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Connect.java index ecc7cda9..0e828ada 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/utils/ConnectionThread.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Connect.java @@ -1,4 +1,4 @@ -package org.sensorhub.impl.sensor.obd2.utils; +package org.sensorhub.impl.sensor.obd2; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; @@ -9,13 +9,13 @@ import java.util.UUID; import java.io.IOException; -public class ConnectionThread extends Thread { +public class Obd2Connect extends Thread { private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); private final BluetoothSocket btSocket; private final BluetoothAdapter btAdapter; volatile boolean active = true; - public ConnectionThread(BluetoothAdapter adapter, BluetoothDevice btDevice) throws SensorException { + public Obd2Connect(BluetoothAdapter adapter, BluetoothDevice btDevice) throws SensorException { btAdapter = adapter; BluetoothSocket tmpSocket = null; diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Control.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Control.java index 76011b9a..80b09dc3 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Control.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Control.java @@ -4,21 +4,34 @@ import net.opengis.swe.v20.DataChoice; import net.opengis.swe.v20.DataRecord; import net.opengis.swe.v20.DataComponent; + +import org.checkerframework.checker.units.qual.A; import org.sensorhub.impl.sensor.AbstractSensorControl; import org.sensorhub.impl.sensor.obd2.commands.Obd2Command; import org.sensorhub.api.command.CommandException; +import org.sensorhub.impl.sensor.obd2.commands.Obd2CommandTask; +import org.sensorhub.impl.sensor.obd2.commands.Obd2Commands; import org.vast.swe.SWEHelper; import com.github.pires.obd.commands.control.DistanceMILOnCommand; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.File; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; import java.util.HashMap; +import java.util.Map; + +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; public class Obd2Control extends AbstractSensorControl { - DataChoice commandData; - DataRecord commandStruct; - HashMap commands; + DataChoice commandData; DataRecord commandStruct; + Obd2Commands commands; public Obd2Control(Obd2Sensor parentSensor) { super("control", parentSensor); @@ -34,13 +47,33 @@ protected boolean execCommand(DataBlock commandBlock) throws CommandException { try { DataRecord commandData = commandStruct.copy(); commandData.setData(commandBlock); - DataComponent component = commandData.getField("Command"); - String commandName = component.getData().getStringValue(); - Obd2Command command = commands.get(commandName); +// DataComponent component = commandData.getField("Command"); +// String commandName = component.getData().getStringValue(); +// Obd2Command command = commands.get(commandName); + // TODO Is this ok? + InputStream in = parentSensor.getBtSocket().getInputStream(); + OutputStream out = parentSensor.getBtSocket().getOutputStream(); try { - command.run(); - // TODO How do I get the data back and what do I do with it? + ArrayList> results = new ArrayList<>(); + ExecutorService executor = Executors.newFixedThreadPool(commands.getCommands().size()); + + for (Obd2Command command: commands.getCommands().values()) { + Obd2Command obd2Command = commands.get(command.getName()); + Callable> task = new Obd2CommandTask(obd2Command, in, out); + Future> future = executor.submit(task); + + HashMap result = null; + try { + result = future.get(); + } catch (InterruptedException | ExecutionException e) { + // TODO + } + + results.add(result); + } + executor.shutdown(); + parentSensor.getOutput().setData(results); } catch (Exception e) { // TODO Handle errors } @@ -52,28 +85,22 @@ protected boolean execCommand(DataBlock commandBlock) throws CommandException { } public void init() { - File file = new File("./commands/commands.json"); - ObjectMapper objectMapper = new ObjectMapper(); - - try { - commands = objectMapper.readValue(file, HashMap.class); - } catch (IOException e) { - e.printStackTrace(); - } - + commands = Obd2Commands.getInstance(); SWEHelper swe = new SWEHelper(); - DataChoice command = swe.createChoice() - .name("Command") - .label("Command") - .description("Commands accepted by the platform") - .definition(SWEHelper.getPropertyUri("Command")) - .addItem() - .build(); - - for (Obd2Command cmd : commands.values()) { - command.addItem(cmd.getCommandRecord().getName(), cmd.getCommandRecord()); - } + commandStruct = swe.createRecord() + .name("xxx") + .updatable(true) + .definition(SWEHelper.getPropertyUri("xxx")) + .label("xxx") + .description("Sends read commands to the OBD-II device") + .addField("Trigger", + swe.createBoolean() + .name("Trigger reading") + .label("Triggers reading") + .definition(SWEHelper.getPropertyUri("TriggerControl")) + .description("Triggers the OBD-II sensor to read all available data")) + .build(); } public void stop() { diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Output.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Output.java index 1fc76177..75e820cf 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Output.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Output.java @@ -1,21 +1,70 @@ package org.sensorhub.impl.sensor.obd2; -import net.opengis.swe.v20.DataBlock; +import net.opengis.swe.v20.DataRecord; import net.opengis.swe.v20.DataComponent; import net.opengis.swe.v20.DataEncoding; - +import net.opengis.swe.v20.DataBlock; +import org.sensorhub.api.data.DataEvent; +import org.sensorhub.impl.sensor.obd2.commands.Obd2Commands; import org.sensorhub.impl.sensor.AbstractSensorOutput; +import org.vast.swe.SWEHelper; + +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.HashMap; public class Obd2Output extends AbstractSensorOutput { + private static final String SENSOR_OUTPUT_NAME = "Obd2Output"; + private static final String SENSOR_OUTPUT_LABEL = "OBD2 Output"; + private static final String SENSOR_OUTPUT_DESCRIPTION = "Output data from the OBD2 Sensors"; DataComponent dataStruct; DataEncoding dataEnc; + DataRecord dataRecord; - public Obd2Output(Obd2Sensor parentSensor) - { - super("obd2Data", parentSensor); + public Obd2Output(Obd2Sensor parentSensor) { + super(SENSOR_OUTPUT_NAME, parentSensor); } - protected void doInit() { + public void doInit() { + SWEHelper sweHelper = new SWEHelper(); + + Obd2Commands commands = Obd2Commands.getInstance(); + DataRecord distanceMILOn = commands.get("DistanceMILOn").getRecord(); + DataRecord DistanceSinceCC = commands.get("DistanceSinceCC").getRecord(); + + dataRecord = sweHelper.createRecord() + .name(SENSOR_OUTPUT_NAME) + .label(SENSOR_OUTPUT_LABEL) + .description(SENSOR_OUTPUT_DESCRIPTION) + .addField("SampleTime", sweHelper.createTime() + .asSamplingTimeIsoUTC() + .label("Sample Time") + .description("Time of data collection")) + .addField(distanceMILOn.getName(), sweHelper.createQuantity() + .label("xxx") + .description(distanceMILOn.getDescription())) + .addField(DistanceSinceCC.getName(), sweHelper.createQuantity() + .label("xxx") + .description(DistanceSinceCC.getDescription())) + .build(); + + dataEnc = sweHelper.newTextEncoding(",", "\n"); + } + + // TODO Order of results is not guaranteed so i can't rely on the index + public void setData(ArrayList> results) { + long timestamp = System.currentTimeMillis(); + + DataBlock dataBlock = latestRecord == null ? dataRecord.createDataBlock() : latestRecord.renew(); + dataBlock.setDoubleValue(0, timestamp / 1000d); + + for (HashMap result: results) { + int key = result.keySet().iterator().next(); + dataBlock.setStringValue(key, result.get(key)); + } + + latestRecord = dataBlock; + eventHandler.publish(new DataEvent(timestamp, Obd2Output.this, dataBlock)); } @Override diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java index e06bda80..71db5de1 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java @@ -12,7 +12,6 @@ import org.sensorhub.api.sensor.SensorException; import org.sensorhub.impl.sensor.AbstractSensorModule; import org.sensorhub.api.common.SensorHubException; -import org.sensorhub.impl.sensor.obd2.utils.ConnectionThread; import java.util.Set; import java.util.UUID; @@ -22,7 +21,7 @@ public class Obd2Sensor extends AbstractSensorModule { private String deviceName; private Context context; - private ConnectionThread connectionThread; + private Obd2Connect connectionThread; private BluetoothAdapter btAdapter; private Obd2Output output; private boolean btConnected = false; @@ -69,7 +68,7 @@ protected void doInit() throws SensorHubException { } // create a bluetooth socket via a thread - connectionThread = new ConnectionThread(btAdapter, device); + connectionThread = new Obd2Connect(btAdapter, device); // TODO Do I need to use location data? @@ -113,4 +112,9 @@ protected void updateSensorDescription() { public boolean isConnected() { return connectionThread.isConnected(); } + + // TODO Is this an ok pattern? + public Obd2Output getOutput() { + return output; + } } \ No newline at end of file diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Command.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Command.java index 8f666763..a792e270 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Command.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Command.java @@ -4,24 +4,40 @@ import org.vast.swe.SWEHelper; -public class Obd2Command { - private DataRecord commandRecord; - private String function; +import java.io.InputStream; +import java.io.OutputStream; - public Obd2Command(String name, String description, String function) { - SWEHelper swe = new SWEHelper(); +public class Obd2Command extends Thread { + private DataRecord record; + private int index; + private String classRef; - this.function = function; - this.commandRecord = swe.createRecord() + public Obd2Command(String name, String description, int index, String classRef) { + SWEHelper swe = new SWEHelper(); + this.record = swe.createRecord() .name(name) .updatable(true) .label(name) .description(description) .definition(SWEHelper.getPropertyUri(name)) .build(); + + this.index = index; + this.classRef = classRef; + } + + public DataRecord getRecord() { + return record; + } + + public int getIndex() { + return index; } - public DataRecord getCommandRecord() { - return commandRecord; + public String getClassRef() { + return classRef; } + + // TODO Does this need a hashcode method since im storing these elsewhere in a Map? + // TODO What about toString()? } \ No newline at end of file diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2CommandTask.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2CommandTask.java new file mode 100644 index 00000000..e3b9201c --- /dev/null +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2CommandTask.java @@ -0,0 +1,45 @@ +package org.sensorhub.impl.sensor.obd2.commands; + +import java.io.InputStream; +import java.io.OutputStream; +import java.util.HashMap; +import java.util.concurrent.Callable; + +public class Obd2CommandTask implements Callable> { + private Obd2Command command; + private InputStream in; + private OutputStream out; + + public Obd2CommandTask(Obd2Command command, InputStream in, OutputStream out) { + this.command = command; + this.in = in; + this.out = out; + } + + @Override + public HashMap call() { + HashMap result = new HashMap<>(); + String classRef = command.getClassRef(); + Object[] args = {in, out}; + + try { + Class clazz = Class.forName(classRef); + Object commandInstance = clazz.getDeclaredConstructor().newInstance(); + // TODO I'm expecting this and the next call to by synchronous + clazz.getMethod("run", InputStream.class, OutputStream.class).invoke(commandInstance, args); + result.put( + command.getIndex(), + (String) clazz.getMethod("getCalculatedResult").invoke(commandInstance) + ); + } catch (ClassNotFoundException e) { + // TODO Is this how I want to handle errors? + System.err.println("Class not found: " + classRef); + } catch (NoSuchMethodException e) { + System.err.println("Method 'run' not found in class: " + classRef); + } catch (Exception e) { + e.printStackTrace(); + } + + return result; + } +} \ No newline at end of file diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Commands.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Commands.java new file mode 100644 index 00000000..9266260c --- /dev/null +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Commands.java @@ -0,0 +1,45 @@ +package org.sensorhub.impl.sensor.obd2.commands; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.File; +import java.io.IOException; +import java.util.Map; + +public final class Obd2Commands { + private static volatile Obd2Commands instance; + private Map commands; + + private Obd2Commands() { + File file = new File("/commands.json"); + ObjectMapper objectMapper = new ObjectMapper(); + + // TODO Test that this works as expected + try { + commands = objectMapper.readValue(file, objectMapper.getTypeFactory().constructMapType(Map.class, String.class, Obd2Command.class)); + } catch (IOException e) { + // TODO + } + } + + public static Obd2Commands getInstance() { + Obd2Commands result = instance; + if (result != null) { + return result; + } + synchronized(Obd2Commands.class) { + if (instance == null) { + instance = new Obd2Commands(); + } + return instance; + } + } + + public Map getCommands() { + return commands; + } + + public Obd2Command get(String name) { + return commands.get(name); + } +} \ No newline at end of file diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/commands.json b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/commands.json index d02271fd..255daceb 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/commands.json +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/commands.json @@ -2,11 +2,15 @@ "DistanceMILOn": { "name": "DistanceMILOn", "description": "Distance traveled (km) with the malfunction indicator lamp (MIL) on", - "function": "DistanceMILOnCommand" + "units": "km", + "index": 1, + "classRef": "com.github.pires.obd.commands.control.DistanceMILOnCommand" }, "DistanceSinceCC": { "name": "DistanceSinceCC", "description": "Distance traveled (km) since codes cleared-up", - "function": "DistanceSinceCCCommand" + "units": "km", + "index": 2, + "classRef": "com.github.pires.obd.commands.control.DistanceSinceCCCommand" } } \ No newline at end of file diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/utils/ReadWriteThread.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/utils/ReadWriteThread.java deleted file mode 100644 index e69de29b..00000000 From 966a316f79fd7b418f73f2e0983f6ea782433082 Mon Sep 17 00:00:00 2001 From: Philip Khaisman Date: Thu, 6 Feb 2025 15:02:08 -0500 Subject: [PATCH 8/9] Save point --- .../impl/sensor/obd2/Obd2Connect.java | 32 +++++++++++-------- .../impl/sensor/obd2/Obd2Control.java | 6 ++++ .../impl/sensor/obd2/Obd2Output.java | 10 ++++-- .../impl/sensor/obd2/Obd2Sensor.java | 26 ++++++++++----- .../sensor/obd2/commands/Obd2Command.java | 13 +++++++- .../sensor/obd2/commands/Obd2Commands.java | 25 ++++++++++++--- .../src/main/resources/commands.json | 14 ++++++++ 7 files changed, 97 insertions(+), 29 deletions(-) create mode 100644 sensorhub-android-obd2/src/main/resources/commands.json diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Connect.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Connect.java index 0e828ada..d7f92a60 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Connect.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Connect.java @@ -16,6 +16,8 @@ public class Obd2Connect extends Thread { volatile boolean active = true; public Obd2Connect(BluetoothAdapter adapter, BluetoothDevice btDevice) throws SensorException { + System.out.println("*** STARTING OBD2CONNECT"); + btAdapter = adapter; BluetoothSocket tmpSocket = null; @@ -27,6 +29,8 @@ public Obd2Connect(BluetoothAdapter adapter, BluetoothDevice btDevice) throws Se } btSocket = tmpSocket; + + System.out.println("*** COMPLETED OBD2CONNECT"); } public BluetoothSocket getBtSocket() { @@ -34,20 +38,22 @@ public BluetoothSocket getBtSocket() { } public void run() { - while (active) { - btAdapter.cancelDiscovery(); + System.out.println("*** RUNNING OBD2CONNECT"); - // connect to the bluetooth device - try { - btSocket.connect(); - } catch (IOException connectException) { - try { - btSocket.close(); - } catch (IOException e) { - // TODO What should I do if I can't close the socket? - } - } - } +// while (active) { +// btAdapter.cancelDiscovery(); +// +// // connect to the bluetooth device +// try { +// btSocket.connect(); +// } catch (IOException connectException) { +// try { +// btSocket.close(); +// } catch (IOException e) { +// // TODO What should I do if I can't close the socket? +// } +// } +// } } public void cancel() { diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Control.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Control.java index 80b09dc3..20ef03a7 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Control.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Control.java @@ -15,10 +15,12 @@ import com.github.pires.obd.commands.control.DistanceMILOnCommand; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.URISyntaxException; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -44,6 +46,7 @@ public DataComponent getCommandDescription() { @Override protected boolean execCommand(DataBlock commandBlock) throws CommandException { + System.out.println("*** EXECUTE COMMAND"); try { DataRecord commandData = commandStruct.copy(); commandData.setData(commandBlock); @@ -85,6 +88,7 @@ protected boolean execCommand(DataBlock commandBlock) throws CommandException { } public void init() { + System.out.println("*** INITIALIZING OBD2 CONTROL"); commands = Obd2Commands.getInstance(); SWEHelper swe = new SWEHelper(); @@ -101,6 +105,8 @@ public void init() { .definition(SWEHelper.getPropertyUri("TriggerControl")) .description("Triggers the OBD-II sensor to read all available data")) .build(); + + System.out.println("*** INITIALIZED OBD2 CONTROL"); } public void stop() { diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Output.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Output.java index 75e820cf..acd8de00 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Output.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Output.java @@ -9,7 +9,9 @@ import org.sensorhub.impl.sensor.AbstractSensorOutput; import org.vast.swe.SWEHelper; +import java.io.FileNotFoundException; import java.lang.reflect.Array; +import java.net.URISyntaxException; import java.util.ArrayList; import java.util.HashMap; @@ -19,7 +21,7 @@ public class Obd2Output extends AbstractSensorOutput { private static final String SENSOR_OUTPUT_DESCRIPTION = "Output data from the OBD2 Sensors"; DataComponent dataStruct; DataEncoding dataEnc; - DataRecord dataRecord; +// DataRecord dataRecord; public Obd2Output(Obd2Sensor parentSensor) { super(SENSOR_OUTPUT_NAME, parentSensor); @@ -32,7 +34,7 @@ public void doInit() { DataRecord distanceMILOn = commands.get("DistanceMILOn").getRecord(); DataRecord DistanceSinceCC = commands.get("DistanceSinceCC").getRecord(); - dataRecord = sweHelper.createRecord() + dataStruct = sweHelper.createRecord() .name(SENSOR_OUTPUT_NAME) .label(SENSOR_OUTPUT_LABEL) .description(SENSOR_OUTPUT_DESCRIPTION) @@ -49,13 +51,15 @@ public void doInit() { .build(); dataEnc = sweHelper.newTextEncoding(",", "\n"); + + System.out.println("*** COMPLETED OBD2 OUTPUT INIT"); } // TODO Order of results is not guaranteed so i can't rely on the index public void setData(ArrayList> results) { long timestamp = System.currentTimeMillis(); - DataBlock dataBlock = latestRecord == null ? dataRecord.createDataBlock() : latestRecord.renew(); + DataBlock dataBlock = latestRecord == null ? dataStruct.createDataBlock() : latestRecord.renew(); dataBlock.setDoubleValue(0, timestamp / 1000d); for (HashMap result: results) { diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java index 71db5de1..6162e4ac 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java @@ -24,19 +24,21 @@ public class Obd2Sensor extends AbstractSensorModule { private Obd2Connect connectionThread; private BluetoothAdapter btAdapter; private Obd2Output output; + private Obd2Control control; private boolean btConnected = false; - public Obd2Sensor(String deviceName) { - this.deviceName = deviceName; - } + public Obd2Sensor() {} public BluetoothSocket getBtSocket() { return connectionThread.getBtSocket(); } @Override - protected void doInit() throws SensorHubException { + public void doInit() throws SensorHubException { + System.out.println("*** INITIALIZING OBD2 SENSOR ***"); + // TODO Do I to call super.doInit()? + super.doInit(); // set IDs this.xmlID = "OBD2_" + Build.SERIAL; @@ -52,13 +54,12 @@ protected void doInit() throws SensorHubException { } BluetoothDevice device = null; - // TODO What if the device isn't bonded? Do I need to make calls to discover it? Sounds like I might. Set devices = btAdapter.getBondedDevices(); - // find the bluetooth device for (BluetoothDevice d : devices) { - if (d.getName().equals(deviceName)) { + // TODO Get device name from config + if (d.getName().equals("VEEPEAK")) { device = d; } } @@ -76,14 +77,23 @@ protected void doInit() throws SensorHubException { output = new Obd2Output(this); output.doInit(); addOutput(output, false); + + control = new Obd2Control(this); + addControlInput(control); + control.init(); + + System.out.println("*** COMPLETED OBD2 SENSOR INIT"); } @Override protected void doStart() throws SensorHubException { // TODO Do I need to call super.doStart()? + System.out.println("*** STARTING OBD2 SENSOR..."); + super.doStart(); // connect to the bluetooth device via a thread - connectionThread.start(); + // TODO I think we're already connected so there's no point in doing this unless i want to connect via osh and not the device + // connectionThread.start(); // TODO and then what? i think we'll need a command class to send commands to read data. where do we interface with the driver? android? computer? api? } diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Command.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Command.java index a792e270..90f1e938 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Command.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Command.java @@ -1,5 +1,8 @@ package org.sensorhub.impl.sensor.obd2.commands; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + import net.opengis.swe.v20.DataRecord; import org.vast.swe.SWEHelper; @@ -12,7 +15,15 @@ public class Obd2Command extends Thread { private int index; private String classRef; - public Obd2Command(String name, String description, int index, String classRef) { + public Obd2Command() {} + + @JsonCreator + public Obd2Command( + @JsonProperty("name") String name, + @JsonProperty("description") String description, + @JsonProperty("index") int index, + @JsonProperty("classRef") String classRef + ) { SWEHelper swe = new SWEHelper(); this.record = swe.createRecord() .name(name) diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Commands.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Commands.java index 9266260c..759b440a 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Commands.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Commands.java @@ -1,25 +1,40 @@ package org.sensorhub.impl.sensor.obd2.commands; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.File; import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; import java.util.Map; +import java.io.InputStream; +import java.io.FileNotFoundException; public final class Obd2Commands { private static volatile Obd2Commands instance; private Map commands; private Obd2Commands() { - File file = new File("/commands.json"); - ObjectMapper objectMapper = new ObjectMapper(); + String fileName = "commands.json"; + + InputStream inputStream = getClass().getClassLoader().getResourceAsStream(fileName); + if (inputStream == null) { + throw new RuntimeException("File not found: " + fileName); + } + + System.out.println("*** RESOURCE: " + inputStream); - // TODO Test that this works as expected + ObjectMapper objectMapper = new ObjectMapper(); try { - commands = objectMapper.readValue(file, objectMapper.getTypeFactory().constructMapType(Map.class, String.class, Obd2Command.class)); + commands = objectMapper.readValue(inputStream, new TypeReference>() {}); } catch (IOException e) { // TODO + System.out.println("*** ERROR READING FILE OBJECT: " + e); } + + System.out.println("*** COMMANDS: " + commands); + } public static Obd2Commands getInstance() { @@ -40,6 +55,8 @@ public Map getCommands() { } public Obd2Command get(String name) { + System.out.println("*** COMMAND NAME: " + name); + System.out.println(commands); return commands.get(name); } } \ No newline at end of file diff --git a/sensorhub-android-obd2/src/main/resources/commands.json b/sensorhub-android-obd2/src/main/resources/commands.json new file mode 100644 index 00000000..2a30871f --- /dev/null +++ b/sensorhub-android-obd2/src/main/resources/commands.json @@ -0,0 +1,14 @@ +{ + "DistanceMILOn": { + "name": "DistanceMILOn", + "description": "Distance traveled (km) with the malfunction indicator lamp (MIL) on", + "index": 1, + "classRef": "com.github.pires.obd.commands.control.DistanceMILOnCommand" + }, + "DistanceSinceCC": { + "name": "DistanceSinceCC", + "description": "Distance traveled (km) since codes cleared-up", + "index": 2, + "classRef": "com.github.pires.obd.commands.control.DistanceSinceCCCommand" + } +} \ No newline at end of file From 56975bf6853e4b48422e70ab61a745ebf16fa91f Mon Sep 17 00:00:00 2001 From: Philip Khaisman Date: Thu, 6 Mar 2025 10:02:59 -0500 Subject: [PATCH 9/9] Debug bt connection and commands --- .../impl/sensor/obd2/Obd2Connect.java | 20 +++++++++++++------ .../impl/sensor/obd2/Obd2Control.java | 12 +++++------ .../impl/sensor/obd2/Obd2Output.java | 2 -- .../impl/sensor/obd2/Obd2Sensor.java | 9 ++------- .../sensor/obd2/commands/Obd2Command.java | 6 +++++- .../sensor/obd2/commands/Obd2CommandTask.java | 1 + .../sensor/obd2/commands/Obd2Commands.java | 7 ------- .../sensorhub/android/SensorHubAndroid.java | 2 ++ 8 files changed, 30 insertions(+), 29 deletions(-) diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Connect.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Connect.java index d7f92a60..864e07eb 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Connect.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Connect.java @@ -8,6 +8,7 @@ import java.util.UUID; import java.io.IOException; +import java.util.Set; public class Obd2Connect extends Thread { private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); @@ -16,8 +17,6 @@ public class Obd2Connect extends Thread { volatile boolean active = true; public Obd2Connect(BluetoothAdapter adapter, BluetoothDevice btDevice) throws SensorException { - System.out.println("*** STARTING OBD2CONNECT"); - btAdapter = adapter; BluetoothSocket tmpSocket = null; @@ -29,8 +28,6 @@ public Obd2Connect(BluetoothAdapter adapter, BluetoothDevice btDevice) throws Se } btSocket = tmpSocket; - - System.out.println("*** COMPLETED OBD2CONNECT"); } public BluetoothSocket getBtSocket() { @@ -38,7 +35,18 @@ public BluetoothSocket getBtSocket() { } public void run() { - System.out.println("*** RUNNING OBD2CONNECT"); + btAdapter.cancelDiscovery(); + + try { + btSocket.connect(); + } catch (IOException connectException) { + try { + btSocket.close(); + } catch (IOException closeException) { + // TODO + } + } + // while (active) { // btAdapter.cancelDiscovery(); @@ -47,6 +55,7 @@ public void run() { // try { // btSocket.connect(); // } catch (IOException connectException) { +// System.out.println("*** CONNECTION ERROR: " + connectException); // try { // btSocket.close(); // } catch (IOException e) { @@ -58,7 +67,6 @@ public void run() { public void cancel() { try { - active = false; btSocket.close(); } catch (IOException e) { // TODO What should I do if I can't close the socket? diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Control.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Control.java index 20ef03a7..2dfcbc0a 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Control.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Control.java @@ -1,5 +1,6 @@ package org.sensorhub.impl.sensor.obd2; +import net.opengis.swe.v20.CategoryOrRange; import net.opengis.swe.v20.DataBlock; import net.opengis.swe.v20.DataChoice; import net.opengis.swe.v20.DataRecord; @@ -32,7 +33,8 @@ import java.util.concurrent.Future; public class Obd2Control extends AbstractSensorControl { - DataChoice commandData; DataRecord commandStruct; + DataChoice commandData; + DataRecord commandStruct; Obd2Commands commands; public Obd2Control(Obd2Sensor parentSensor) { @@ -46,7 +48,6 @@ public DataComponent getCommandDescription() { @Override protected boolean execCommand(DataBlock commandBlock) throws CommandException { - System.out.println("*** EXECUTE COMMAND"); try { DataRecord commandData = commandStruct.copy(); commandData.setData(commandBlock); @@ -57,12 +58,14 @@ protected boolean execCommand(DataBlock commandBlock) throws CommandException { InputStream in = parentSensor.getBtSocket().getInputStream(); OutputStream out = parentSensor.getBtSocket().getOutputStream(); + // TODO check boolean value of the trigger control + try { ArrayList> results = new ArrayList<>(); ExecutorService executor = Executors.newFixedThreadPool(commands.getCommands().size()); for (Obd2Command command: commands.getCommands().values()) { - Obd2Command obd2Command = commands.get(command.getName()); + Obd2Command obd2Command = commands.get(command.getCommandName()); Callable> task = new Obd2CommandTask(obd2Command, in, out); Future> future = executor.submit(task); @@ -88,7 +91,6 @@ protected boolean execCommand(DataBlock commandBlock) throws CommandException { } public void init() { - System.out.println("*** INITIALIZING OBD2 CONTROL"); commands = Obd2Commands.getInstance(); SWEHelper swe = new SWEHelper(); @@ -105,8 +107,6 @@ public void init() { .definition(SWEHelper.getPropertyUri("TriggerControl")) .description("Triggers the OBD-II sensor to read all available data")) .build(); - - System.out.println("*** INITIALIZED OBD2 CONTROL"); } public void stop() { diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Output.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Output.java index acd8de00..f636d161 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Output.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Output.java @@ -51,8 +51,6 @@ public void doInit() { .build(); dataEnc = sweHelper.newTextEncoding(",", "\n"); - - System.out.println("*** COMPLETED OBD2 OUTPUT INIT"); } // TODO Order of results is not guaranteed so i can't rely on the index diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java index 6162e4ac..be5fe8c6 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java @@ -35,8 +35,6 @@ public BluetoothSocket getBtSocket() { @Override public void doInit() throws SensorHubException { - System.out.println("*** INITIALIZING OBD2 SENSOR ***"); - // TODO Do I to call super.doInit()? super.doInit(); @@ -70,6 +68,7 @@ public void doInit() throws SensorHubException { // create a bluetooth socket via a thread connectionThread = new Obd2Connect(btAdapter, device); +// connectionThread.start(); // TODO Do I need to use location data? @@ -81,19 +80,15 @@ public void doInit() throws SensorHubException { control = new Obd2Control(this); addControlInput(control); control.init(); - - System.out.println("*** COMPLETED OBD2 SENSOR INIT"); } @Override protected void doStart() throws SensorHubException { // TODO Do I need to call super.doStart()? - System.out.println("*** STARTING OBD2 SENSOR..."); super.doStart(); // connect to the bluetooth device via a thread - // TODO I think we're already connected so there's no point in doing this unless i want to connect via osh and not the device - // connectionThread.start(); + connectionThread.start(); // TODO and then what? i think we'll need a command class to send commands to read data. where do we interface with the driver? android? computer? api? } diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Command.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Command.java index 90f1e938..bee4d8e5 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Command.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Command.java @@ -10,10 +10,11 @@ import java.io.InputStream; import java.io.OutputStream; -public class Obd2Command extends Thread { +public class Obd2Command extends Thread { private DataRecord record; private int index; private String classRef; + private String name; public Obd2Command() {} @@ -35,6 +36,7 @@ public Obd2Command( this.index = index; this.classRef = classRef; + this.name = name; // TODO Is this necessary or can i get it from the record? } public DataRecord getRecord() { @@ -49,6 +51,8 @@ public String getClassRef() { return classRef; } + public String getCommandName() { return name; } + // TODO Does this need a hashcode method since im storing these elsewhere in a Map? // TODO What about toString()? } \ No newline at end of file diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2CommandTask.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2CommandTask.java index e3b9201c..09b0e017 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2CommandTask.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2CommandTask.java @@ -37,6 +37,7 @@ public HashMap call() { } catch (NoSuchMethodException e) { System.err.println("Method 'run' not found in class: " + classRef); } catch (Exception e) { + System.out.println("*** ERROR: " + e); e.printStackTrace(); } diff --git a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Commands.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Commands.java index 759b440a..d3a32e76 100644 --- a/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Commands.java +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Commands.java @@ -23,8 +23,6 @@ private Obd2Commands() { throw new RuntimeException("File not found: " + fileName); } - System.out.println("*** RESOURCE: " + inputStream); - ObjectMapper objectMapper = new ObjectMapper(); try { commands = objectMapper.readValue(inputStream, new TypeReference>() {}); @@ -32,9 +30,6 @@ private Obd2Commands() { // TODO System.out.println("*** ERROR READING FILE OBJECT: " + e); } - - System.out.println("*** COMMANDS: " + commands); - } public static Obd2Commands getInstance() { @@ -55,8 +50,6 @@ public Map getCommands() { } public Obd2Command get(String name) { - System.out.println("*** COMMAND NAME: " + name); - System.out.println(commands); return commands.get(name); } } \ No newline at end of file diff --git a/sensorhub-android-service/src/org/sensorhub/android/SensorHubAndroid.java b/sensorhub-android-service/src/org/sensorhub/android/SensorHubAndroid.java index 89d4879b..aa9a27a6 100644 --- a/sensorhub-android-service/src/org/sensorhub/android/SensorHubAndroid.java +++ b/sensorhub-android-service/src/org/sensorhub/android/SensorHubAndroid.java @@ -5,6 +5,7 @@ import org.sensorhub.api.module.IModuleConfigRepository; import org.sensorhub.impl.SensorHub; import org.sensorhub.impl.comm.NetworkManagerImpl; +import org.sensorhub.impl.common.IdEncodersDES; import org.sensorhub.impl.database.registry.DefaultDatabaseRegistry; import org.sensorhub.impl.datastore.mem.InMemorySystemStateDbConfig; import org.sensorhub.impl.event.EventBus; @@ -58,6 +59,7 @@ public synchronized void start() throws SensorHubException { this.securityManager = new SecurityManagerImpl(this); this.networkManager = new NetworkManagerImpl(this); this.processingManager = new ProcessingManagerImpl(this); + this.idEncoders = new IdEncodersDES(this); // prepare client authenticator (e.g. for HTTP connections, etc...) ClientAuth.createInstance("keystore");