-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to develop on the Android platform #13
Comments
Hi, BluetoothConnection in fact is a wrapper on BluetoothSocket, in addition it implements AdapterConnection interface to be able to integrate with the FW. For Android integration purpose you may check ObdGraphs.datalogger module https://github.com/tzebrowski/ObdGraphs/tree/master/datalogger/src/main/java/org/obd/graphs/bl/datalogger |
Thank you. I would like to ask if these programs are currently based on Kotlin architecture. If my application mainly runs on Java, will there be any compatibility issues? |
|
Understood, thank you~ BluetoothDemo.java: public class BluetoothDemo extends Service {
public void test() throws IOException, InterruptedException, ExecutionException {
AdapterConnection connection = BluetoothConnection.connect(getDeviceByName("OBD"));
var collector = new DataCollector();
final Pids pids = Pids
.builder()
.resource(Objects.requireNonNull(Thread.currentThread().getContextClassLoader()).getResource("giulia_2.0_gme.json"))
.resource(Objects.requireNonNull(Thread.currentThread().getContextClassLoader()).getResource("extra.json"))
.resource(Objects.requireNonNull(Thread.currentThread().getContextClassLoader()).getResource("mode01.json"))
.build();
int commandFrequency = 6;
var workflow = Workflow.instance().pids(pids).observer(collector).initialize();
var query = Query.builder().pid(7005l).pid(7006l).pid(7007l).pid(7008l).build();
var optional = Adjustments
.builder()
.vehicleCapabilitiesReadingEnabled(Boolean.TRUE)
.vehicleMetadataReadingEnabled(Boolean.TRUE)
.adaptiveTimeoutPolicy(AdaptiveTimeoutPolicy.builder().enabled(Boolean.TRUE).checkInterval(5000).commandFrequency(commandFrequency).build())
.producerPolicy(ProducerPolicy.builder().priorityQueueEnabled(Boolean.TRUE).build())
.cachePolicy(CachePolicy.builder().resultCacheEnabled(Boolean.FALSE).build())
.batchPolicy(
BatchPolicy.builder().responseLengthEnabled(Boolean.FALSE).enabled(Boolean.FALSE).build())
.build();
var init = Init.builder()
.delayAfterInit(1000)
.header(Header.builder().mode("22").header("DA10F1").build())
.header(Header.builder().mode("01").header("DB33F1").build())
.protocol(Protocol.CAN_29)
.sequence(DefaultCommandGroup.INIT).build();
workflow.start(connection, query, init, optional);
WorkflowFinalizer.finalizeAfter(workflow,25000);
var registry = workflow.getPidRegistry();
var intakePressure = registry.findBy(7005l);
double ratePerSec = workflow.getDiagnostics().rate().findBy(RateType.MEAN, intakePressure).get().getValue();
Assertions.assertThat(ratePerSec).isGreaterThanOrEqualTo(commandFrequency);
}
@SuppressLint("MissingPermission")
private BluetoothDevice getDeviceByName(String name) {
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter != null) {
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
if (pairedDevices != null && !pairedDevices.isEmpty()) {
for (BluetoothDevice device : pairedDevices) {
if (device.getName().equals(name)) {
return device;
}
}
}
}
return null;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
} DataCollector.java: public final class DataCollector extends ReplyObserver<Reply<?>> {
private final MultiValuedMap<Command, Reply<?>> data = new ArrayListValuedHashMap<Command, Reply<?>>();
private final MultiValuedMap<PidDefinition, ObdMetric> metrics = new ArrayListValuedHashMap<PidDefinition, ObdMetric>();
public ObdMetric findSingleMetricBy(PidDefinition pidDefinition) {
List<ObdMetric> list = (List<ObdMetric>) metrics.get(pidDefinition);
if (list.isEmpty()) {
return null;
}
return list.get(0);
}
public List<ObdMetric> findMetricsBy(PidDefinition pidDefinition) {
return (List<ObdMetric>) metrics.get(pidDefinition);
}
@Override
public void onNext(Reply<?> reply) {
Log.i("Receive data: {}", reply.toString());
data.put(reply.getCommand(), reply);
if (reply instanceof ObdMetric) {
metrics.put(((ObdMetric) reply).getCommand().getPid(), (ObdMetric) reply);
}
}
} WorkflowFinalizer.java: public interface WorkflowFinalizer {
int DEFAULT_FINALIZE_TIME = 500;
static void finalizeAfter(final Workflow workflow, long sleepTime) throws InterruptedException {
final Callable<String> end = () -> {
TimeUnit.MILLISECONDS.sleep(sleepTime);
workflow.stop();
return "end";
};
final ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(1);
newFixedThreadPool.invokeAll(Arrays.asList(end));
newFixedThreadPool.shutdown();
}
static void finalizeAfter500ms(final Workflow workflow) throws InterruptedException {
finalizeAfter(workflow, DEFAULT_FINALIZE_TIME);
}
} OBDActivity.java: public class OBDActivity extends AppCompatActivity {
private ActivityObdBinding binding;
@SuppressLint("MissingPermission")
@SuppressWarnings("all")
private final BroadcastReceiver connectionStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (OBDBluetoothService.ACTION_OBD_STATE.equals(intent.getAction())) {
int speed = intent.getIntExtra(OBDBluetoothService.EXTRA_OBD_SPEED, 0);
if (binding != null) {
if (speed != 0 ) {
binding.testSpeed.setText(speed +"Km/h");
}
}
}
}
};
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityObdBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setTheme(R.style.AppTheme);
final Toolbar toolbar = binding.toolbar;
setSupportActionBar(toolbar);
if (getSupportActionBar() != null) {
getSupportActionBar().setTitle(R.string.navigation_obd_II);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
}
@Override
public boolean onSupportNavigateUp() {
finish();
return true;
}
} |
Can you please create simple project on your own, I could clone it and validate it locally? This would speedup problem solving, |
Hello, I have placed the file and the working program on Github, because the program will execute the OBDBluetoothService when specifying automatic connection to find the relevant OBD device. An error occurred and we are currently dealing with the error. If you have some solutions, I can open this Github for editing permissions for you. You can directly modify the file and view the error. Thank you. |
Hi, I managed to run your project, and found few things:
For now, some reason, your bt class is not able to open the connection with the bt device, checking this..
|
Hello, I have modified the program code using the method you suggested and uploaded it to Github. Please re-Clone the project. I am not sure if this modification is correct. There is also a problem about BT connection. There are other methods. Any suggestions? |
Hi, your app does not ask for bluetooth permissions, you might integrate with
|
Hello, I have modified part of the program and added Bluetooth permissions and uploaded it to Github. However, after I actually tested it, I found that the program seems to try to connect to the following device (BA0DED_5), which seems incorrect, my device name is OBDII(Mac Address:CE:5E:89:74:3D:4C)
The following are all the Logcat records displayed in Android Studio. What solutions are there according to the current displayed records?
|
Hi, the reason I had BT errors |
Hello, I found that if I modify this line of code in the var connection = new BluetoothConnection("AA:BB:CC:11:22:33"); I would like to ask how to achieve this connection function if the Mac addresses are different, but the devices are all called OBDII. This way, the OBD-II device can be automatically connected when the program is started. Another question is how to simply receive the data. Is it possible? Is it defined in the Thank you! The following is to directly modify the
|
Correct, mac address need to be changed and refer to the device u are using. Somewhere in the application you need to have mapping between
Correct, U can achieve this by following code (https://github.com/tzebrowski/SimpleOBDJavaTest/blob/main/app/src/main/java/com/example/simpleobdjavatest/OBDBluetoothService.java#L146)
Btw, PIDs like 7005l, 7006l, 7007l are specific for Alfa Romeo, which vehicle you want to test against ? |
Hello @Override
public void onNext(Reply<?> reply) {
Log.i("Receive data: {}", reply.toString());
data.put(reply.getCommand(), reply);
if (reply instanceof ObdMetric) {
metrics.put(((ObdMetric) reply).getCommand().getPid(), (ObdMetric) reply);
}
if (reply instanceof ObdMetric) {
ObdMetric obdMetric = (ObdMetric) reply;
Log.e("PID: ", obdMetric.getCommand().getPid().getId() + ", Value: " + obdMetric.getValue());
metrics.put(obdMetric.getCommand().getPid(), obdMetric);
if (obdMetric.getCommand().getPid().getId().equals("0x0C")) {
double rpm = obdMetric.getValue().doubleValue();
Log.i("Vehicle RPM: ", String.valueOf(rpm));
}
}
} 2.If I only need to send the engine speed, can I define these two lines in the test() function in OBDBluetoothService.java to display them in DataCollector.onNext? var engineSpeedPID = 13L; //https://github.com/tzebrowski/ObdMetrics/blob/main/src/main/resources/mode01.json#L192
var query = Query.builder().pid(engineSpeedPID).build(); 3.So if I want to test multiple data, do I need to write multiple PIDs in the program here? 4.And when querying the vehicle PID, does it directly display the PID of each item in Service 01 on Wikipedia, or can it only be defined from the file you provided? In addition, the car model I want to test is applicable to all car series. I want to make a universal OBD-II connection application that can detect error codes and return various data, etc. |
You need to query multiple PID's, e.g:
You can query just these PIDs which are provided by configuration e.q:
Files likes |
Hello, the program here is modified to look like the file Logcat:
I found that if I print out the Receive data, the following information will be displayed, but the program will not read the judgment formula I wrote (such as obtaining vehicle speed data)
OBDBluetoothService.java: public void test() throws IOException, InterruptedException, ExecutionException {
var connection = new BluetoothConnection(obdMacAddress);
// var connection = new BluetoothConnection("CE:5E:89:74:3D:4C");
// var connection = new BluetoothConnection("BA:0D:ED:5B:E7:35");
var collector = new DataCollector();
final Pids pids = Pids
.builder()
.resource(Objects.requireNonNull(Thread.currentThread().getContextClassLoader()).getResource("giulia_2.0_gme.json"))
.resource(Objects.requireNonNull(Thread.currentThread().getContextClassLoader()).getResource("extra.json"))
.resource(Objects.requireNonNull(Thread.currentThread().getContextClassLoader()).getResource("mode01.json"))
.resource(Objects.requireNonNull(Thread.currentThread().getContextClassLoader()).getResource("mode01_2.json"))
.build();
int commandFrequency = 6;
var workflow = Workflow.instance().pids(pids).observer(collector).initialize();
// var query = Query.builder().pid(7005l).pid(7006l).pid(7007l).pid(7008l).build();
var calculatedEngineLoad = 5L;
var coolant= 6L;
var engineSpeedPID = 13L;
var speed = 14L;
var controlModuleVoltage = 67L;
var query = Query.builder().pid(engineSpeedPID).pid(coolant).pid(calculatedEngineLoad).
pid(speed).pid(controlModuleVoltage).build();
var optional = Adjustments
.builder()
.vehicleCapabilitiesReadingEnabled(Boolean.TRUE)
.vehicleMetadataReadingEnabled(Boolean.TRUE)
.adaptiveTimeoutPolicy(AdaptiveTimeoutPolicy.builder().enabled(Boolean.TRUE).checkInterval(5000).commandFrequency(commandFrequency).build())
.producerPolicy(ProducerPolicy.builder().priorityQueueEnabled(Boolean.TRUE).build())
.cachePolicy(CachePolicy.builder().resultCacheEnabled(Boolean.FALSE).build())
.batchPolicy(
BatchPolicy.builder().responseLengthEnabled(Boolean.FALSE).enabled(Boolean.FALSE).build())
.build();
var init = Init.builder()
.delayAfterInit(1000)
.header(Header.builder().mode("22").header("DA10F1").build())
.header(Header.builder().mode("01").header("DB33F1").build())
.protocol(Protocol.CAN_29)
.sequence(DefaultCommandGroup.INIT).build();
workflow.start(connection, query, init, optional);
} DataCollector.java: @Override
public void onNext(Reply<?> reply) {
Log.e("Receive data: {}", Arrays.toString(reply.getCommand().getData()));
ObdMetric obdMetric = (ObdMetric) reply;
Log.e("DataCollector", String.valueOf(obdMetric));
if (obdMetric.getCommand().getPid().getId() == 5) {
Log.e("DataCollector", "Calculated Engine Load: " + obdMetric.getValue());
} else if (obdMetric.getCommand().getPid().getId() == 6) {
Log.e("DataCollector", "coolant: " + obdMetric.getValue());
} else if (obdMetric.getCommand().getPid().getId() == 13) {
double rpm = obdMetric.getValue().doubleValue();
Log.e("DataCollector", "Vehicle RPM: " + rpm);
} else if (obdMetric.getCommand().getPid().getId() == 14) {
Log.e("DataCollector", "Vehicle Speed: " + obdMetric.getValue());
} else if (obdMetric.getCommand().getPid().getId() == 67) {
Log.e("DataCollector", "Control Module Voltage: " + obdMetric.getValue());
}
data.put(reply.getCommand(), reply);
// if (reply instanceof ObdMetric) {
// metrics.put(((ObdMetric) reply).getCommand().getPid(), (ObdMetric) reply);
// }
} By the way, I modified it so that it will automatically determine the device with the OBD name, and will obtain the Mac address from the device before connecting. Currently, there is no problem connecting the following devices: But realme C51 Android 13 cannot connect normally. What kind of problem could cause this situation?
In addition, I have uploaded all the programs to Github. If you need a test environment to view the content, please download it again. Thank you! |
Hello, any news about the problem? |
Please remove this section from your code https://github.com/Timmy5818/SimpleOBDJavaTest/blob/main/app/src/main/java/com/example/simpleobdjavatest/OBDBluetoothService.java#L160C16-L162C43
Its specific for alfa romeo giulia, |
Hello, I removed the 3 lines of code as you said, but I still did not receive the data normally (such as engine speed data). I only received the following part of the AT command that looks like Bluetooth. That's it. Is there anything else that needs to be modified? Logcat:
By the way, the cars I tested include BMW, TOYOTA, LEXUS, etc., and they all have the same test results. Only the AT commands that look like Bluetooth are displayed. Thank you~~ |
Hi, please enable debug logging and provide logs here,
|
Hello, the following OBD-II Log is the data I currently obtained from Logcat in Android Studio, and I have uploaded the modified program to enable Debug mode to Github. Please check the program modification and the following record files, thank you!
|
Thanks for provided logs.
Can you please do one more tests and enable batch queries and share the logs,
|
Hello, I currently use the following three The first way to modify the program: var optional = Adjustments
.builder()
.debugEnabled(true)
.vehicleCapabilitiesReadingEnabled(Boolean.TRUE)
.vehicleMetadataReadingEnabled(Boolean.TRUE)
.adaptiveTimeoutPolicy(AdaptiveTimeoutPolicy.builder().enabled(Boolean.TRUE).checkInterval(5000).commandFrequency(commandFrequency).build())
.producerPolicy(ProducerPolicy.builder().priorityQueueEnabled(Boolean.TRUE).build())
.cachePolicy(CachePolicy.builder().resultCacheEnabled(Boolean.TRUE).build())
.batchPolicy(BatchPolicy.builder().enabled(Boolean.TRUE).build())
.build(); Logcat:
The second way to modify the program: var optional = Adjustments
.builder()
.debugEnabled(true)
.vehicleCapabilitiesReadingEnabled(Boolean.TRUE)
.vehicleMetadataReadingEnabled(Boolean.TRUE)
.adaptiveTimeoutPolicy(AdaptiveTimeoutPolicy.builder().enabled(Boolean.TRUE).checkInterval(5000).commandFrequency(commandFrequency).build())
.producerPolicy(ProducerPolicy.builder().priorityQueueEnabled(Boolean.TRUE).build())
.cachePolicy(CachePolicy.builder().resultCacheEnabled(Boolean.FALSE).build())
.batchPolicy(BatchPolicy.builder().enabled(Boolean.TRUE).build())
.build(); Logcat:
The third way to modify the program: var optional = Adjustments
.builder()
.debugEnabled(true)
.batchPolicy(BatchPolicy.builder().enabled(Boolean.TRUE).build())
.build(); Logcat:
|
Hi, Thanks for provided input, ECU answers looks better now, however I need to check on my end why it cannot be parsed,
|
May I ask which code of the @SuppressWarnings("all")
public void test(Context context) throws IOException, InterruptedException, ExecutionException {
// Automatically connect OBD devices
var connection = new PcBluetoothConnection(obdMacAddress, context);
// var connection = new PcBluetoothConnection("CE:5E:89:74:3D:4C");
// var connection = new PcBluetoothConnection("BA:0D:ED:5B:E7:35");
var collector = new PcDataCollector();
final Pids pids = Pids
.builder()
.resource(Objects.requireNonNull(Thread.currentThread().getContextClassLoader()).getResource("giulia_2.0_gme.json"))
.resource(Objects.requireNonNull(Thread.currentThread().getContextClassLoader()).getResource("extra.json"))
.resource(Objects.requireNonNull(Thread.currentThread().getContextClassLoader()).getResource("mode01.json"))
.resource(Objects.requireNonNull(Thread.currentThread().getContextClassLoader()).getResource("mode01_2.json"))
.build();
int commandFrequency = 6;
var workflow = Workflow.instance().pids(pids).observer(collector).initialize();
// var query = Query.builder().pid(7005l).pid(7006l).pid(7007l).pid(7008l).build();
// Enter the required OBD-II PID parameters (the PID parameters are defined in this file,
// not as defined in the encyclopedia https://github.com/tzebrowski/ObdMetrics/blob/main/src/main/resources/mode01 )
//Calculated Engine Load
var calculatedEngineLoad = 5L;
// Coolant
var coolant= 6L;
// Engine Speed
var engineSpeedPID = 13L;
//Speed
var speed = 14L;
// Control Module Voltage
var controlModuleVoltage = 67L;
var query = Query.builder().pid(engineSpeedPID).pid(coolant).pid(calculatedEngineLoad).
pid(speed).pid(controlModuleVoltage).build();
// var optional = Adjustments
// .builder()
// .debugEnabled(true)
// .vehicleCapabilitiesReadingEnabled(Boolean.TRUE)
// .vehicleMetadataReadingEnabled(Boolean.TRUE)
// .adaptiveTimeoutPolicy(AdaptiveTimeoutPolicy.builder().enabled(Boolean.TRUE).checkInterval(5000).commandFrequency(commandFrequency).build())
// .producerPolicy(ProducerPolicy.builder().priorityQueueEnabled(Boolean.TRUE).build())
// .cachePolicy(CachePolicy.builder().resultCacheEnabled(Boolean.TRUE).build())
// .batchPolicy(BatchPolicy.builder().responseLengthEnabled(Boolean.FALSE).enabled(Boolean.TRUE).build())
// .build();
var optional = Adjustments
.builder()
.debugEnabled(true)
.vehicleCapabilitiesReadingEnabled(Boolean.TRUE)
.vehicleMetadataReadingEnabled(Boolean.TRUE)
.adaptiveTimeoutPolicy(AdaptiveTimeoutPolicy.builder().enabled(Boolean.TRUE).checkInterval(5000).commandFrequency(commandFrequency).build())
.producerPolicy(ProducerPolicy.builder().priorityQueueEnabled(Boolean.TRUE).build())
.cachePolicy(CachePolicy.builder().resultCacheEnabled(Boolean.FALSE).build())
.batchPolicy(BatchPolicy.builder().enabled(Boolean.TRUE).build())
.build();
var init = Init.builder()
.delayAfterInit(1000)
// .header(Header.builder().mode("22").header("DA10F1").build())
// .header(Header.builder().mode("01").header("DB33F1").build())
// .protocol(Protocol.CAN_29)
.sequence(DefaultCommandGroup.INIT).build();
workflow.start(connection, query, init, optional);
} In addition, I currently set the return data to only have the following PIDs, so I don’t know what PID 42 means.
|
This line refer to
Can you please run the tests once again however without this PID
|
Most probably the reason the received data is not parsed is because of missing right "javascipt evaluating formula" configured . For Android platform u should have something like this:
and in addition in your deps you should have following references:
|
Thank you very much for your help. I have changed it to the following equation according to your suggestion and it can run normally and receive the following data displayed by Logcat.
@SuppressWarnings("all")
public void test(Context context) throws IOException, InterruptedException, ExecutionException {
// Automatically connect OBD devices
var connection = new PcBluetoothConnection(obdMacAddress, context);
var collector = new PcDataCollector();
final Pids pids = Pids
.builder()
// .resource(Objects.requireNonNull(Thread.currentThread().getContextClassLoader()).getResource("giulia_2.0_gme.json"))
.resource(Objects.requireNonNull(Thread.currentThread().getContextClassLoader()).getResource("extra.json"))
.resource(Objects.requireNonNull(Thread.currentThread().getContextClassLoader()).getResource("mode01.json"))
.resource(Objects.requireNonNull(Thread.currentThread().getContextClassLoader()).getResource("mode01_2.json"))
.build();
int commandFrequency = 6;
var workflow = Workflow.instance()
.formulaEvaluatorConfig(FormulaEvaluatorConfig.builder().scriptEngine("rhino").build())
.pids(pids).observer(collector).initialize();
// Enter the required OBD-II PID parameters (the PID parameters are defined in this file,
// not as defined in the encyclopedia https://github.com/tzebrowski/ObdMetrics/blob/main/src/main/resources/mode01 )
// Calculated Engine Load
var calculatedEngineLoad = 5L;
// Coolant
var coolant= 6L;
// Engine Speed
var engineSpeedPID = 13L;
// Speed
var speed = 14L;
// Control Module Voltage
var controlModuleVoltage = 67L;
var query = Query.builder()
.pid(engineSpeedPID)
.pid(coolant)
.pid(calculatedEngineLoad)
.pid(controlModuleVoltage)
.pid(speed)
.build();
var optional = Adjustments
.builder()
.debugEnabled(true)
.vehicleCapabilitiesReadingEnabled(Boolean.TRUE)
.vehicleMetadataReadingEnabled(Boolean.TRUE)
.adaptiveTimeoutPolicy(AdaptiveTimeoutPolicy.builder().enabled(Boolean.TRUE).checkInterval(5000).commandFrequency(commandFrequency).build())
.producerPolicy(ProducerPolicy.builder().priorityQueueEnabled(Boolean.TRUE).build())
.cachePolicy(CachePolicy.builder().resultCacheEnabled(Boolean.FALSE).build())
.batchPolicy(BatchPolicy.builder().enabled(Boolean.TRUE).build())
.build();
var init = Init.builder()
.delayAfterInit(1000)
// .header(Header.builder().mode("22").header("DA10F1").build())
// .header(Header.builder().mode("01").header("DB33F1").build())
// .protocol(Protocol.CAN_29)
.sequence(DefaultCommandGroup.INIT).build();
workflow.start(connection, query, init, optional);
} The following information is from Toyota's actual test Logcat:
|
Great that it works.
You need to enable vehicle capabilities reading and connect Lifecycle listener.
You will receive supported PIDs within
I need raw logs ( |
Hello, I tested a LEXUS vehicle today (4/25) and this problem also occurs. The following is the current recorded content and program. Because there is currently a problem in reading the vehicle speed, it will jump back and forth between 65Km/h and the real vehicle speed. Currently The temporary solution is to use the last read true speed display if 65Km/h is read. In addition, the PID that displays vehicle support will be tested at a later date. Thank you~ OBDBluetoothService.java: @SuppressWarnings("all")
public void test(Context context) throws IOException, InterruptedException, ExecutionException {
// Automatically connect OBD devices
var connection = new PcBluetoothConnection(obdMacAddress, context);
var collector = new PcDataCollector();
final Pids pids = Pids
.builder()
// .resource(Objects.requireNonNull(Thread.currentThread().getContextClassLoader()).getResource("giulia_2.0_gme.json"))
.resource(Objects.requireNonNull(Thread.currentThread().getContextClassLoader()).getResource("extra.json"))
.resource(Objects.requireNonNull(Thread.currentThread().getContextClassLoader()).getResource("mode01.json"))
.resource(Objects.requireNonNull(Thread.currentThread().getContextClassLoader()).getResource("mode01_2.json"))
.build();
int commandFrequency = 6;
var workflow = Workflow.instance()
.formulaEvaluatorConfig(FormulaEvaluatorConfig.builder().scriptEngine("rhino").build())
.pids(pids).observer(collector).initialize();
// Enter the required OBD-II PID parameters (the PID parameters are defined in this file,
// not as defined in the encyclopedia https://github.com/tzebrowski/ObdMetrics/blob/main/src/main/resources/mode01 )
// Calculated Engine Load
var calculatedEngineLoad = 5L;
// Coolant
var coolant= 6L;
// Engine Speed
var engineSpeedPID = 13L;
// Speed
var speed = 14L;
// Control Module Voltage
var controlModuleVoltage = 67L;
var query = Query.builder()
.pid(engineSpeedPID)
.pid(coolant)
.pid(calculatedEngineLoad)
.pid(controlModuleVoltage)
.pid(speed)
.build();
var optional = Adjustments
.builder()
.debugEnabled(true)
.vehicleCapabilitiesReadingEnabled(Boolean.TRUE)
.vehicleMetadataReadingEnabled(Boolean.TRUE)
.adaptiveTimeoutPolicy(AdaptiveTimeoutPolicy.builder().enabled(Boolean.TRUE).checkInterval(5000).commandFrequency(commandFrequency).build())
.producerPolicy(ProducerPolicy.builder().priorityQueueEnabled(Boolean.TRUE).build())
.cachePolicy(CachePolicy.builder().resultCacheEnabled(Boolean.FALSE).build())
.batchPolicy(BatchPolicy.builder().enabled(Boolean.TRUE).build())
.build();
var init = Init.builder()
.delayAfterInit(1000)
// .header(Header.builder().mode("22").header("DA10F1").build())
// .header(Header.builder().mode("01").header("DB33F1").build())
// .protocol(Protocol.CAN_29)
.sequence(DefaultCommandGroup.INIT).build();
workflow.start(connection, query, init, optional);
} DataCollector.java: @Override
public void onNext(Reply<?> reply) {
Log.e("Receive data: {}", Arrays.toString(reply.getCommand().getData()));
// data.put(reply.getCommand(), reply);
if (reply instanceof ObdMetric) {
ObdMetric obdMetric = (ObdMetric) reply;
Log.e("PcDataCollector", String.valueOf(obdMetric));
// Display data
// (defined from this file https://github.com/tzebrowski/ObdMetrics/blob/main/src/main/resources/mode01.json )
// Calculated Engine Load
if (obdMetric.getCommand().getPid().getId() == 5) {
Log.e("PcDataCollector", "Calculated Engine Load: " + obdMetric.getValue());
PcOBDHandler.Companion.calculatedEngineLoadDataUpdate(obdMetric.getValue().toString());
// Coolant
} else if (obdMetric.getCommand().getPid().getId() == 6) {
Log.e("PcDataCollector", "coolant: " + obdMetric.getValue());
PcOBDHandler.Companion.coolantDataUpdate(obdMetric.getValue().toString());
// Engine Speed
} else if (obdMetric.getCommand().getPid().getId() == 13) {
double rpm = obdMetric.getValue().doubleValue();
Log.e("PcDataCollector", "Vehicle RPM: " + rpm);
PcOBDHandler.Companion.engineSpeedDataUpdate(String.valueOf(rpm));
// Speed
} else if (obdMetric.getCommand().getPid().getId() == 14) {
Log.e("PcDataCollector", "Vehicle Speed: " + obdMetric.getValue());
int speed = (int) obdMetric.getValue();
if (speed != 65) {
PcOBDHandler.Companion.speedDataUpdate(obdMetric.getValue().toString());
}
// Control Module Voltage
} else if (obdMetric.getCommand().getPid().getId() == 67) {
Log.e("PcDataCollector", "Control Module Voltage: " + obdMetric.getValue());
PcOBDHandler.Companion.controlModuleVoltageDataUpdate(obdMetric.getValue().toString());
}
metrics.put(((ObdMetric) reply).getCommand().getPid(), (ObdMetric) reply);
}
} Logcat:
|
Thanks,
|
hi Meanwhile I released version that tries to mitigate the problem with incorrect ecu responses,
Through this, messages like |
Hello, we are currently busy with other projects and will select a date to test your suggestions. Thank you~~ |
Hello, I have been testing different devices in the past few days and found a problem. I am using Google Pixel 7 Pro and Samsung S20+, both of which are Android 13 systems. They can communicate with OBD-II devices and receive data normally, but they are both Android The realme C51 of 13 system cannot connect to the OBD-II device normally. Which part of the program needs to be modified or is the problem caused?
|
Hello, I saw someone on the Internet having a similar problem. I modified the Socket connection part as follows and the connection was successful. Thank you for your help! In addition, the following devices can be connected to the mobile phone I tested: Modify part of the connection program: try {
socket.connect();
} catch (IOException ioException) {
Log.e("BluetoothConnection", "Error, Try another connection method" + ioException.getMessage());
try {
Class<?> clazz = socket.getRemoteDevice().getClass();
Class<?>[] paramTypes = new Class<?>[] {Integer.TYPE};
Method m = clazz.getMethod("createRfcommSocket", paramTypes);
Object[] params = new Object[] {1};
socket = (BluetoothSocket) m.invoke(socket.getRemoteDevice(), params);
if (socket != null) {
socket.connect();
} else {
Log.e("BluetoothConnection", "fallback_socket received null....: ");
}
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException | IOException e) {
Log.e("BluetoothConnection", "exception_in_code....: " + e);
e.printStackTrace();
}
} Complete program: @Override
@SuppressWarnings("all")
public void connect() throws IOException {
try {
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice adapter = null;
if (bluetoothAdapter != null) {
for (BluetoothDevice bondedDevice : bluetoothAdapter.getBondedDevices()) {
if (bondedDevice.getName() != null && bondedDevice.getAddress().equals(deviceAddress)) {
adapter = bondedDevice;
Log.e(LOGGER_TAG, "OBD Device found: " + bondedDevice.getName());
deviceName = bondedDevice.getName();
break;
}
}
if (null == adapter) {
throw new IOException("Device not found: " + deviceAddress);
}
final ParcelUuid[] uuids = adapter.getUuids();
final UUID uuid = uuids[0].getUuid();
socket = adapter.createInsecureRfcommSocketToServiceRecord(uuid);
try {
socket.connect();
} catch (IOException ioException) {
Log.e("BluetoothConnection", "Error, Try another connection method" + ioException.getMessage());
try {
Class<?> clazz = socket.getRemoteDevice().getClass();
Class<?>[] paramTypes = new Class<?>[] {Integer.TYPE};
Method m = clazz.getMethod("createRfcommSocket", paramTypes);
Object[] params = new Object[] {1};
socket = (BluetoothSocket) m.invoke(socket.getRemoteDevice(), params);
if (socket != null) {
socket.connect();
} else {
Log.e("BluetoothConnection", "fallback_socket received null....: ");
}
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException | IOException e) {
Log.e("BluetoothConnection", "exception_in_code....: " + e);
e.printStackTrace();
}
}
if (socket.isConnected()) {
input = socket.getInputStream();
output = socket.getOutputStream();
Log.e(LOGGER_TAG, "Successfully connected to the adapter: " + deviceAddress);
} else {
throw new IOException("Failed to connect to the adapter: " + deviceAddress);
}
} else {
throw new IOException("BluetoothAdapter not found");
}
} catch (SecurityException e){
Log.e(LOGGER_TAG,"Failed to connect to BT due to missing permissions.",e);
}
} |
Hello, I recently discovered a strange problem during testing. |
Basically, when engine turn off you should stop the workflow manually. This is something end user should do in the app.
I will see how this use-case works on my end. Do you have by chance some logs ? |
Hello, I am currently writing the relevant program that explains the stop process in your webpage, but it still doesn't work. The following is the record file and program writing status. Thank you for your reply! BluetoothConnection.java, the call stops the workflow when disconnected: @Override
public void close() {
try {
if (input != null) {
input.close();
}
if (output != null) {
output.close();
}
if (socket != null) {
socket.close();
}
Log.e(LOGGER_TAG, "OBD-II Device is disconnect, Socket for the device: " + deviceAddress + " is closed.");
PcOBDBluetoothService.stop();
Application application = (Application) mContext.getApplicationContext();
PcOBDViewModel viewModel = new ViewModelProvider(application).get(PcOBDViewModel.class);
viewModel.updateDeviceName("");
viewModel.updateDeviceMacAddress("");
} catch (IOException e) {
Log.e(LOGGER_TAG, "Error closing the socket: " + deviceAddress, e);
}
} OBDBluetoothService.java, call to stop workflow program: public static void stop() {
if (mContext != null) {
var collector = new PcDataCollector(mContext);
final Pids pids = Pids
.builder()
// .resource(Objects.requireNonNull(Thread.currentThread().getContextClassLoader()).getResource("giulia_2.0_gme.json"))
.resource(Objects.requireNonNull(Thread.currentThread().getContextClassLoader()).getResource("extra.json"))
.resource(Objects.requireNonNull(Thread.currentThread().getContextClassLoader()).getResource("mode01.json"))
.resource(Objects.requireNonNull(Thread.currentThread().getContextClassLoader()).getResource("mode01_2.json"))
.build();
var workflow = Workflow.instance().pids(pids).observer(collector).initialize();
Log.e("OBDBluetoothService","Stop OBD-II Workflow");
workflow.stop();
}
} Open the APP and record the normal connection status:
Directly turn off Bluetooth to simulate leaving the vehicle:
After restarting Bluetooth, the connection cannot be normal. Only by restarting the APP can the connection be normal:
|
From what I see, the workflow was stopped
however there is an issue with submitting new one
will take a look on this, |
Hello, I have quoted your library file according to the steps here. I took a look at the file content. The sample file uses BluetoothConnection. However, I searched on the Internet and found that BluetoothSocket is mainly used on Android. This is different. Function library, if I want to receive data in the background of Android Server and use the BroadcastReceiver method to display the data on the Activity screen, how does the overall process work?
Thanks
The text was updated successfully, but these errors were encountered: