I am not able to received complete responses from my BLE device which I am supposed to receive for the commands written to characteristics using flutter_blue. What I am receiving in response is the command itself which I sent for write. The responses received are being decoded properly.
The commands which I'm trying to write are OBDII protocols which are
AT Z
AT H0
AT H0
AT L0
AT S0
01 0C
Surprisingly the command "AT Z" gives response "ELM 327v1.5" which is correct. This is the only command from which I am receiving the correct response. All other commands are returning the command itself which is partially correct because most of the times the actual responses are received along with the command name.
The response reading and decoding is implemented in the following way
await read_CX.setNotifyValue(true);
read_CX.value.listen((response) {
print(utf8.decode(response));
}
Has anyone faced similar issue of receiving incomplete data? Can anyone please help me out?
Thanks!!
Can you include the responses that you get sent back ? Truncated values usually indicate that the ATT MTU is too short.
I've mentioned below the commands (string + encoded) that I am writing to device and their responses (raw + decoded) received.
Written Command = "AT Z"
Written Encoded Value = [65, 84, 32, 90]
Response Received Raw = [13, 13, 69, 76, 77, 51, 50, 55, 32, 118, 49, 46, 53, 13, 13, 62]
Decoded Response = ELM327 v1.5>
Desired Response Raw = [13, 13, 69, 76, 77, 51, 50, 55, 32, 118, 49, 46, 53, 13, 13, 62]
Written Command = "AT H0"
Written Encoded Value = [65, 84, 32, 72, 48]
Response Received Raw = [65, 84, 32, 72, 48]
Decoded Response = "AT H0"
Written Command = "AT L0"
Written Encoded Value = [65, 84, 32, 76, 48]
Response Received Raw = [65, 84, 32, 76, 48]
Decoded Response = "AT L0"
Written Command = "AT S0"
Written Encoded Value = [65, 84, 32, 83, 48]
Response Received Raw = [65, 84, 32, 83, 48]
Decoded Response = "AT S0"
Written Command = "01 0C"
Written Encoded Value = [48, 49, 32, 48, 67]
Response Received Raw = [48, 49, 32, 48, 67]
Decoded Response = "01 0C"
So ATT MTU truncating replies is not the issue. Mind giving more infos about the actual protocol (Seems like a custom one ?), such as what is the separator between a command's name in the reply and the content of the reply, possibly snippets of code about the code on the other end, etc. This seems more like a potential problem with the implementation of whatever protocol is used on top of BLE rather than an issue with the BLE layer/Flutter blue itself.
These are the actual protocols. The "AT Z" protocol is for returning the device type and the rest of the protocols are to perform reset.
White spaces are the separator between a command's name in the response received from BLE device.
Scanning the devices
@override
void initState() {
// TODO: implement initState
widget.flutterBlue.scanResults.listen((List<ScanResult> results) {
for (ScanResult result in results) {
_addDeviceTolist(result.device);
}
});
widget.flutterBlue.startScan();
}
Connecting the Device:-
void _connectDevice() async {
widget.flutterBlue.stopScan();
print(_deviceToConnect);
try {
await _deviceToConnect.connect();
} catch (e) {
if (e.code != 'already_connected') {
throw e;
}
} finally {
_services = await _deviceToConnect.discoverServices();
}
//start discovering services of the device
totalServicesCounter = _services.length;
examineDeviceServicesForConnection();
setState(() {
_connectedDevice = _deviceToConnect;
});
}
Examining services of device
void examineDeviceServicesForConnection(){
if (examinedServicesCounter < totalServicesCounter){
//start examining
var currentExaminingService = _services[examinedServicesCounter];
var arrCurrentExaminingCharacteristics = currentExaminingService.characteristics;
totalExaminingCharacteristicCounter = arrCurrentExaminingCharacteristics.length;
if (arrCurrentExaminingCharacteristics.isNotEmpty){
//characteristics are present in service
setTestReaderWriter(arrCurrentExaminingCharacteristics);
}else{
//characteristics are not present in service
examinedServicesCounter = examinedServicesCounter + 1;
examineDeviceServicesForConnection();
}
}else if (totalServicesCounter > 0 && examinedServicesCounter == totalServicesCounter){
//examining completed
print("all the services are examined and the device is not compatible for communication");
}else{
print("check required");
}
}
Set Read and Write test Characteristics
void setTestReaderWriter(List<BluetoothCharacteristic> arrChars){
for (BluetoothCharacteristic chars in arrChars){
if (chars.properties.notify){
testReader = chars;
}
if (chars.properties.write){
testWriter = chars;
}
}
if (testReader != null && testWriter != null){
//start writing test command
performDeviceConnectionTest();
}else{
examinedServicesCounter = examinedServicesCounter + 1;
examineDeviceServicesForConnection();
}
}
Perform device connection test
void performDeviceConnectionTest() async {
final testCommand = "AT Z\r";
final convertedTestCommand = utf8.encode(testCommand);
await testReader.setNotifyValue(true);
testReader.value.listen((response) {
_parseValueReceived(response, "command");
var responseReceived = _convertedCommandResponseToString;
if (responseReceived.contains("ELM")){
scanningBeginOnce = true;
print("Device is compatible");
//stop the test scanning and continue to actual scan.
testReader.setNotifyValue(false);
_connectedDevice.disconnect();
_rx_Read_Characteristic = testReader;
_rx_Write_Characteristic = testWriter;
_prepareForScanning();
}else{
print("obd device is not found. continuing scanning");
//continue to test scanning.
examinedServicesCounter = examinedServicesCounter + 1;
examineDeviceServicesForConnection();
}
});
await testWriter.write(convertedTestCommand);
}
Prepare for scanning
void _prepareForScanning() async {
//set notifier for reader characteristic and listen to the response.
await _rx_Read_Characteristic.setNotifyValue(true);
_rx_Read_Characteristic.value.transform(utf8.decoder).listen((event) {
print(event);
});
_rx_Read_Characteristic.value.listen((response) {
var responseDecoded = utf8.decode(response);
print(responseDecoded);
if (responseDecoded.isNotEmpty){
_commandsExecutedCounter += 1;
_writeCommandsToDevice();
}else{
print("command response received is empty");
}
});
}
Write commands to device
void _writeCommandsToDevice() async {
//getting commands from the commands list
if (_commandsExecutedCounter < arrTestCommands.length){
_currentCommand = arrTestCommands[_commandsExecutedCounter];
var convertedCommand = utf8.encode(_currentCommand);
await _rx_Write_Characteristic.write(convertedCommand);
}else if (_commandsExecutedCounter == arrTestCommands.length){
print("Scan is completed at ${DateTime.now()}");
_connectedDevice.disconnect();
}else{
print("some other error");
}
}
I agree with you that there is some implementation problem with the rest of the protocols. If I am able to receive the correct response from protocol "AT Z" then the rest of the protocols should also provide the correct responses.
@vaibhiarora03 I'm going to use this plugin to connect with obd2 device, did you face any blocker issue on your project
@deity256 Not a complete blocker issues as of now. I faced issues like duplicate notifications upon each reconnection with device, response receiving issues but was able to resolve them with the help of community and via going through the solutions of existing issues mentioned here.
@vaibhiarora03 can you provide me with some resources you used, cause i couldn't find any usefull links to handle obd2 connection.
another question is how do you test your code without a phisical obd connected to a car?
@deity256 What issues are you facing while handling the responses? I am just following the official documentation of the library.
I actually test via a BLE OBDII device connected with a car. There are simulators too but haven't used them yet.
@vaibhiarora03 like how do you read the protocol response, is there any api or do you handle each response state on its own
I read the responses by subscribing to notifications of the characteristic.
await characteristic.setNotifyValue(true);
characteristic.value.listen((value) {
// do something with new value
});
i mean the response in your case is [13, 13, 69, 76, 77, 51, 50, 55, 32, 118, 49, 46, 53, 13, 13, 62]
how do you understand it
You can convert the response received via
utf8.decode(your_response)
or via
String.fromCharCodes(your_response)
Also, the below mentioned link will help you out.
@vaibhiarora03 thanks for your help, appriciate it ❤