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-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/build.gradle b/sensorhub-android-obd2/build.gradle new file mode 100644 index 00000000..5b11c387 --- /dev/null +++ b/sensorhub-android-obd2/build.gradle @@ -0,0 +1,17 @@ +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 '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') +} + +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..d25cc1a5 --- /dev/null +++ b/sensorhub-android-obd2/src/main/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + + + + \ 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/Obd2Connect.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Connect.java new file mode 100644 index 00000000..864e07eb --- /dev/null +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Connect.java @@ -0,0 +1,79 @@ +package org.sensorhub.impl.sensor.obd2; + +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; +import java.util.Set; + +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 Obd2Connect(BluetoothAdapter adapter, BluetoothDevice btDevice) throws SensorException { + btAdapter = adapter; + BluetoothSocket tmpSocket = null; + + try { + 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); + } + + btSocket = tmpSocket; + } + + public BluetoothSocket getBtSocket() { + return btSocket; + } + + public void run() { + btAdapter.cancelDiscovery(); + + try { + btSocket.connect(); + } catch (IOException connectException) { + try { + btSocket.close(); + } catch (IOException closeException) { + // TODO + } + } + + +// while (active) { +// btAdapter.cancelDiscovery(); +// +// // connect to the bluetooth device +// try { +// btSocket.connect(); +// } catch (IOException connectException) { +// System.out.println("*** CONNECTION ERROR: " + connectException); +// try { +// btSocket.close(); +// } catch (IOException e) { +// // TODO What should I do if I can't close the socket? +// } +// } +// } + } + + public void cancel() { + try { + btSocket.close(); + } catch (IOException e) { + // TODO What should I do if I can't close the socket? + } + } + + 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/Obd2Control.java b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Control.java new file mode 100644 index 00000000..2dfcbc0a --- /dev/null +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Control.java @@ -0,0 +1,115 @@ +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; +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.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; + +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; + Obd2Commands 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); + // TODO Is this ok? + 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.getCommandName()); + 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 + } + } catch (Exception e) { + throw new RuntimeException(e); + } + + return true; + } + + public void init() { + commands = Obd2Commands.getInstance(); + SWEHelper swe = new SWEHelper(); + + 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() { + // 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/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..f636d161 --- /dev/null +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Output.java @@ -0,0 +1,89 @@ +package org.sensorhub.impl.sensor.obd2; + +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.io.FileNotFoundException; +import java.lang.reflect.Array; +import java.net.URISyntaxException; +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(SENSOR_OUTPUT_NAME, parentSensor); + } + + public void doInit() { + SWEHelper sweHelper = new SWEHelper(); + + Obd2Commands commands = Obd2Commands.getInstance(); + DataRecord distanceMILOn = commands.get("DistanceMILOn").getRecord(); + DataRecord DistanceSinceCC = commands.get("DistanceSinceCC").getRecord(); + + dataStruct = 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 ? dataStruct.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 + 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..be5fe8c6 --- /dev/null +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/Obd2Sensor.java @@ -0,0 +1,125 @@ +package org.sensorhub.impl.sensor.obd2; + +import android.app.Activity; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothManager; +import android.bluetooth.BluetoothSocket; +import android.content.Context; +import android.os.Build; + +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; +import java.util.UUID; + +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 Obd2Connect connectionThread; + private BluetoothAdapter btAdapter; + private Obd2Output output; + private Obd2Control control; + private boolean btConnected = false; + + public Obd2Sensor() {} + + public BluetoothSocket getBtSocket() { + return connectionThread.getBtSocket(); + } + + @Override + public void doInit() throws SensorHubException { + // TODO Do I to call super.doInit()? + super.doInit(); + + // set IDs + this.xmlID = "OBD2_" + Build.SERIAL; + this.uniqueID = Obd2Config.getUid(); + + // get the android's 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."); + } + + BluetoothDevice device = null; + Set devices = btAdapter.getBondedDevices(); + + // find the bluetooth device + for (BluetoothDevice d : devices) { + // TODO Get device name from config + if (d.getName().equals("VEEPEAK")) { + device = d; + } + } + + if (device == null) { + throw new SensorException("Could not find bluetooth device, unable to start."); + } + + // create a bluetooth socket via a thread + connectionThread = new Obd2Connect(btAdapter, device); +// connectionThread.start(); + + // TODO Do I need to use location data? + + // init osh output(s) + output = new Obd2Output(this); + output.doInit(); + addOutput(output, false); + + control = new Obd2Control(this); + addControlInput(control); + control.init(); + } + + @Override + protected void doStart() throws SensorHubException { + // TODO Do I need to call super.doStart()? + super.doStart(); + + // connect to the bluetooth device via a thread + 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? + } + + @Override + protected void doStop() { + connectionThread.cancel(); + } + + @Override + public void cleanup() throws SensorHubException {} + + @Override + protected void updateSensorDescription() { + synchronized (sensorDescLock) + { + super.updateSensorDescription(); + + if (!sensorDescription.isSetDescription()) { + sensorDescription.setDescription("Driver for OBD2 sensors conected via BLE"); + } + } + } + + @Override + 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 new file mode 100644 index 00000000..bee4d8e5 --- /dev/null +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Command.java @@ -0,0 +1,58 @@ +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; + +import java.io.InputStream; +import java.io.OutputStream; + +public class Obd2Command extends Thread { + private DataRecord record; + private int index; + private String classRef; + private String name; + + 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) + .updatable(true) + .label(name) + .description(description) + .definition(SWEHelper.getPropertyUri(name)) + .build(); + + this.index = index; + this.classRef = classRef; + this.name = name; // TODO Is this necessary or can i get it from the record? + } + + public DataRecord getRecord() { + return record; + } + + public int getIndex() { + return index; + } + + 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 new file mode 100644 index 00000000..09b0e017 --- /dev/null +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2CommandTask.java @@ -0,0 +1,46 @@ +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) { + System.out.println("*** ERROR: " + 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..d3a32e76 --- /dev/null +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/Obd2Commands.java @@ -0,0 +1,55 @@ +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() { + String fileName = "commands.json"; + + InputStream inputStream = getClass().getClassLoader().getResourceAsStream(fileName); + if (inputStream == null) { + throw new RuntimeException("File not found: " + fileName); + } + + ObjectMapper objectMapper = new ObjectMapper(); + try { + commands = objectMapper.readValue(inputStream, new TypeReference>() {}); + } catch (IOException e) { + // TODO + System.out.println("*** ERROR READING FILE OBJECT: " + e); + } + } + + 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 new file mode 100644 index 00000000..255daceb --- /dev/null +++ b/sensorhub-android-obd2/src/main/java/org/sensorhub/impl/sensor/obd2/commands/commands.json @@ -0,0 +1,16 @@ +{ + "DistanceMILOn": { + "name": "DistanceMILOn", + "description": "Distance traveled (km) with the malfunction indicator lamp (MIL) on", + "units": "km", + "index": 1, + "classRef": "com.github.pires.obd.commands.control.DistanceMILOnCommand" + }, + "DistanceSinceCC": { + "name": "DistanceSinceCC", + "description": "Distance traveled (km) since codes cleared-up", + "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/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 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 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");