I have quickly modified the library to achieve both of these, but I'm not confident it's done correctly. Also I can't figure out how to commit code on here. I'd like an official version to be able to update to the latest version of the library.
I'm writing code to update the firmware on my bluetooth device. I'm trying to send 752 different 154 byte packets. I can't make the packets a different size because that's all they are currently programmed to accept and we have shipped several thousand units. I made a command that called gattServer.requestMtu(request.getMtuSize()) in order to send the larger packets, but it was taking 8.5 minutes to send the packets. After adding a command to call gattServer.requestConnectionPriority(request.getPriority() I was able to get it under 5 minutes. This is still really slow and I don't fully understand why.
I have sent the exact same packets from my previous iOS app developed in swift using coreBluetooth and the packets send in about 1.5 minutes. Neither of these commands needed to be called on iOS so the library should just return success without doing anything.
I'm working off a Lenovo Tab 7 running Android 8.0. I've also tested it on my co-worker's One+ 6T and it took the same amount of time. I'm not sure if the 5 minutes vs 1.5 minutes is a difference in Android vs iOS or if it is overhead in Flutter_Blue
For reference these are the changes I made to the library to get it to work.
Added to bluetooth_device.dart:
Future
var request = protos.RequestMtuRequest.create()
..remoteId = id.toString()
..mtuSize = mtuSize
..success = false;
await FlutterBlue.instance._channel.invokeMethod('requestMtu', request.writeToBuffer());
}
Future
var request = protos.RequestConnectionPriorityRequest.create()
..remoteId = id.toString()
..priority = priority.index
..success = false;
await FlutterBlue.instance._channel.invokeMethod('RequestConnectionPriority', request.writeToBuffer());
}
enum ConnectionPriority { balanced, high, low_power }`
Added to flutterblue.proto
message RequestMtuRequest {
string remote_id = 1;
int32 mtuSize = 2;
bool success = 3;
}
message RequestConnectionPriorityRequest {
string remote_id = 1;
int32 priority = 2;
bool success = 3;
}
Added to flutterblue.pbjson.dart
const RequestMtuRequest$json = const {
'1': 'RequestMtuRequest',
'2': const [
const {'1': 'remote_id', '3': 1, '4': 1, '5': 9, '10': 'remoteId'},
const {'1': 'mtuSize', '3': 2, '4': 1, '5': 5, '10': 'mtuSize'},
const {'1': 'success', '3': 3, '4': 1, '5': 8, '10': 'success'},
],
};
const RequestConnectionPriorityRequest$json = const {
'1': 'RequestConnectionPriority',
'2': const [
const {'1': 'remote_id', '3': 1, '4': 1, '5': 9, '10': 'remoteId'},
const {'1': 'priority', '3': 2, '4': 1, '5': 5, '10': 'mtuSize'},
const {'1': 'success', '3': 3, '4': 1, '5': 8, '10': 'success'},
]
};
Added to flutterblue.pb.dart(I'm fairly sure this is a generated file using the previous file, but I did it manually)
class RequestMtuRequest extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = new $pb.BuilderInfo('RequestMtuRequest')
..aOS(1, 'remoteId')
..a
..aOB(3, 'success')
..hasRequiredFields = false
;
RequestMtuRequest() : super();
RequestMtuRequest.fromBuffer(List
RequestMtuRequest.fromJson(String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromJson(i, r);
RequestMtuRequest clone() => new RequestMtuRequest()..mergeFromMessage(this);
RequestMtuRequest copyWith(void Function(RequestMtuRequest) updates) => super.copyWith((message) => updates(message as RequestMtuRequest));
$pb.BuilderInfo get info_ => _i;
static RequestMtuRequest create() => new RequestMtuRequest();
RequestMtuRequest createEmptyInstance() => create();
static $pb.PbList
static RequestMtuRequest getDefault() => _defaultInstance ??= create()..freeze();
static RequestMtuRequest _defaultInstance;
static void $checkItem(RequestMtuRequest v) {
if (v is! RequestMtuRequest) $pb.checkItemFailed(v, _i.qualifiedMessageName);
}
String get remoteId => $_getS(0, '');
set remoteId(String v) { $_setString(0, v); }
bool hasRemoteId() => $_has(0);
void clearRemoteId() => clearField(1);
int get mtuSize => $_get(1, 0);
set mtuSize(int v) { $_setSignedInt32(1, v); }
bool hasMtuSize() => $_has(1);
void clearMtuSize() => clearField(2);
bool get success => $_get(2, false);
set success(bool v) { $_setBool(2, v); }
bool hasSuccess() => $_has(2);
void clearSuccess() => clearField(3);
}
class RequestConnectionPriorityRequest extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = new $pb.BuilderInfo('RequestConnectionPriority')
..aOS(1, 'remoteId')
..a
..aOB(3, 'success')
..hasRequiredFields = false
;
RequestConnectionPriorityRequest() : super();
RequestConnectionPriorityRequest.fromBuffer(List
RequestConnectionPriorityRequest.fromJson(String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromJson(i, r);
RequestConnectionPriorityRequest clone() => new RequestConnectionPriorityRequest()..mergeFromMessage(this);
RequestConnectionPriorityRequest copyWith(void Function(RequestConnectionPriorityRequest) updates) => super.copyWith((message) => updates(message as RequestConnectionPriorityRequest));
$pb.BuilderInfo get info_ => _i;
static RequestConnectionPriorityRequest create() => new RequestConnectionPriorityRequest();
RequestConnectionPriorityRequest createEmptyInstance() => create();
static $pb.PbList
static RequestConnectionPriorityRequest getDefault() => _defaultInstance ??= create()..freeze();
static RequestConnectionPriorityRequest _defaultInstance;
static void $checkItem(RequestConnectionPriorityRequest v) {
if (v is! RequestConnectionPriorityRequest) $pb.checkItemFailed(v, _i.qualifiedMessageName);
}
String get remoteId => $_getS(0, '');
set remoteId(String v) { $_setString(0, v); }
bool hasRemoteId() => $_has(0);
void clearRemoteId() => clearField(1);
int get priority => $_get(1, 0);
set priority(int v) { $_setSignedInt32(1, v); }
bool hasPriority() => $_has(1);
void clearPriority() => clearField(2);
bool get success => $_get(2, false);
set success(bool v) { $_setBool(2, v); }
bool hasSuccess() => $_has(2);
void clearSuccess() => clearField(3);
}`
Added to FlutterBluePlugin.java:
case "requestMtu":
{
byte[] data = call.arguments();
Protos.RequestMtuRequest request;
try {
request = Protos.RequestMtuRequest.newBuilder().mergeFrom(data).build();
} catch (InvalidProtocolBufferException e) {
result.error("RuntimeException", e.getMessage(), e);
break;
}
BluetoothGatt gattServer;
try {
gattServer = locateGatt(request.getRemoteId());
} catch(Exception e) {
result.error("set_notification_error", e.getMessage(), null);
return;
}
result.success(gattServer.requestMtu(request.getMtuSize()));
break;
}
case "RequestConnectionPriority": {
byte[] data = call.arguments();
Protos.RequestConnectionPriorityRequest request;
try {
request = Protos.RequestConnectionPriorityRequest.newBuilder().mergeFrom(data).build();
} catch (InvalidProtocolBufferException e) {
result.error("RuntimeException", e.getMessage(), e);
break;
}
BluetoothGatt gattServer;
try {
gattServer = locateGatt(request.getRemoteId());
} catch(Exception e) {
result.error("set_notification_error", e.getMessage(), null);
return;
}
result.success(gattServer.requestConnectionPriority(request.getPriority()));
break;
}
Thanks @wabash9000 for your efforts .
I am also facing the same issue . on Android 5.0 , using Flutter_blue , I am getting only 23 bytes MTU but for lower ( Android 4.4.4 ) & higher ( Android 8.1) I am getting >120 bytes .
I will try above & share result .
It will be very helpful if @pauldemarco can add this in official version
Thanks,
Gaurav
@pauldemarco this sounds reasonable. What you think? The connection priority gives a huge speed on data transfers.
Pehaps @wabash9000 could do a pull request?
Hi @wabash9000 @shinayser,
I have added MTU functionality to the latest version 0.6.2. Please try it out and let me know how it goes.
I will have to investigate the influence requestConnectionPriority has on data transfer rates, and will be leaving this issue open until then.
I my case, only the priority will solve my issue.
I am communicating to a hardware piece. When the priority is set to the default one, it takes almost 20 min to transfer the firmware.
When I set it to high priority it goes down to 4 minutes.
@pauldemarco I tested the requestMtu method on iOS 12.4 and it throws a PlatformException PlatformException( requestMtu, IOS does not allow mtu requests to the periperal, null)
any ideas?
requestConnectionPriority does have an important effect. Hope soon, thanks.
same issue here also, interaction with the hardware device.
any solution to this yet ?
This is important to me aswell.
Most helpful comment
Thanks @wabash9000 for your efforts .
I am also facing the same issue . on Android 5.0 , using Flutter_blue , I am getting only 23 bytes MTU but for lower ( Android 4.4.4 ) & higher ( Android 8.1) I am getting >120 bytes .
I will try above & share result .
It will be very helpful if @pauldemarco can add this in official version
Thanks,
Gaurav