From 6e4410c1a7118cf8c8d5970b7e4ab71148142303 Mon Sep 17 00:00:00 2001 From: Paul DeMarco Date: Tue, 10 Sep 2019 23:21:43 -0400 Subject: [PATCH] MTU (Maximum Transmission Unit) (#363) * Update protobuf * Add MtuSizeRequest MtuSizeResponse proto messages * Add BluetoothDeviceCache. Implement requestMtu and mtu. (Android) The BluetoothDeviceCache class is used to augment the underlying Bluetooth API cache for missing information, such as mtu size. * Add quick ListTile to test MTU features. * Add requestMtu and mtu to BluetoothDevice. * Doc updates. Run dartfmt on example. * Update readme. * Add mtu and requestMtu to iOS. * Add comment about which type to use for iOS mtu size. * Update generated iOS project file. --- README.md | 16 +- android/build.gradle | 4 +- .../flutterblue/FlutterBluePlugin.java | 135 ++++++++--- example/lib/main.dart | 186 +++++++-------- ios/Classes/FlutterBluePlugin.m | 25 +++ ios/gen/Flutterblue.pbobjc.h | 30 +++ ios/gen/Flutterblue.pbobjc.m | 212 +++++++++++++++--- lib/gen/flutterblue.pb.dart | 171 +++++++++----- lib/gen/flutterblue.pbenum.dart | 7 +- lib/gen/flutterblue.pbjson.dart | 21 +- lib/gen/flutterblue.pbserver.dart | 5 +- lib/src/bluetooth_device.dart | 26 +++ lib/src/flutter_blue.dart | 1 + protos/flutterblue.proto | 10 + pubspec.yaml | 2 +- 15 files changed, 639 insertions(+), 212 deletions(-) diff --git a/README.md b/README.md index 431f3fa6..46cee25c 100644 --- a/README.md +++ b/README.md @@ -95,13 +95,20 @@ characteristic.value.listen((value) { }); ``` +### Read the MTU and request larger size +```dart +final mtu = await device.mtu.first; +await device.requestMtu(512); +``` + ## Reference ### FlutterBlue API | | Android | iOS | Description | | :--------------- | :----------------: | :------------------: | :-------------------------------- | | scan | :white_check_mark: | :white_check_mark: | Starts a scan for Bluetooth Low Energy devices. | -| state | :white_check_mark: | :white_check_mark: | Gets the current state of the Bluetooth Adapter. | -| onStateChanged | :white_check_mark: | :white_check_mark: | Stream of state changes for the Bluetooth Adapter. | +| state | :white_check_mark: | :white_check_mark: | Stream of state changes for the Bluetooth Adapter. | +| isAvailable | :white_check_mark: | :white_check_mark: | Checks whether the device supports Bluetooth. | +| isOn | :white_check_mark: | :white_check_mark: | Checks if Bluetooth functionality is turned on. | ### BluetoothDevice API | | Android | iOS | Description | @@ -110,8 +117,9 @@ characteristic.value.listen((value) { | disconnect | :white_check_mark: | :white_check_mark: | Cancels an active or pending connection to the device. | | discoverServices | :white_check_mark: | :white_check_mark: | Discovers services offered by the remote device as well as their characteristics and descriptors. | | services | :white_check_mark: | :white_check_mark: | Gets a list of services. Requires that discoverServices() has completed. | -| state | :white_check_mark: | :white_check_mark: | Gets the current state of the device. | -| onStateChanged | :white_check_mark: | :white_check_mark: | Notifies of state changes for the device. | +| state | :white_check_mark: | :white_check_mark: | Stream of state changes for the Bluetooth Device. | +| mtu | :white_check_mark: | | Stream of mtu size changes. | +| requestMtu | :white_check_mark: | | Request to change the MTU for the device. | ### BluetoothCharacteristic API | | Android | iOS | Description | diff --git a/android/build.gradle b/android/build.gradle index 98d9ebcf..6c5609ec 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -23,7 +23,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.3.0' - classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.8' + classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.10' } } @@ -66,7 +66,7 @@ protobuf { // Configure the protoc executable protoc { // Download from repositories - artifact = 'com.google.protobuf:protoc:3.7.0' + artifact = 'com.google.protobuf:protoc:3.9.1' } plugins { javalite { diff --git a/android/src/main/java/com/pauldemarco/flutterblue/FlutterBluePlugin.java b/android/src/main/java/com/pauldemarco/flutterblue/FlutterBluePlugin.java index 51157d3f..5dd56a2e 100644 --- a/android/src/main/java/com/pauldemarco/flutterblue/FlutterBluePlugin.java +++ b/android/src/main/java/com/pauldemarco/flutterblue/FlutterBluePlugin.java @@ -13,6 +13,7 @@ import android.bluetooth.BluetoothGattCallback; import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattDescriptor; +import android.bluetooth.BluetoothGattServer; import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothProfile; @@ -66,7 +67,7 @@ public class FlutterBluePlugin implements MethodCallHandler, RequestPermissionsR private final EventChannel stateChannel; private final BluetoothManager mBluetoothManager; private BluetoothAdapter mBluetoothAdapter; - private final Map mGattServers = new HashMap<>(); + private final Map mDevices = new HashMap<>(); private LogLevel logLevel = LogLevel.EMERGENCY; // Pending call and result for startScan, in the case where permissions are needed @@ -181,7 +182,7 @@ public void onMethodCall(MethodCall call, Result result) { p.addDevices(ProtoMaker.from(d)); } result.success(p.build().toByteArray()); - log(LogLevel.EMERGENCY, "mGattServers size: " + mGattServers.size()); + log(LogLevel.EMERGENCY, "mDevices size: " + mDevices.size()); break; } @@ -200,14 +201,14 @@ public void onMethodCall(MethodCall call, Result result) { boolean isConnected = mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT).contains(device); // If device is already connected, return error - if(mGattServers.containsKey(deviceId) && isConnected) { + if(mDevices.containsKey(deviceId) && isConnected) { result.error("already_connected", "connection with device already exists", null); return; } // If device was connected to previously but is now disconnected, attempt a reconnect - if(mGattServers.containsKey(deviceId) && !isConnected) { - if(mGattServers.get(deviceId).connect()){ + if(mDevices.containsKey(deviceId) && !isConnected) { + if(mDevices.get(deviceId).gatt.connect()){ result.success(null); } else { result.error("reconnect_error", "error when reconnecting to device", null); @@ -222,7 +223,7 @@ public void onMethodCall(MethodCall call, Result result) { } else { gattServer = device.connectGatt(activity, options.getAndroidAutoConnect(), mGattCallback); } - mGattServers.put(deviceId, gattServer); + mDevices.put(deviceId, new BluetoothDeviceCache(gattServer)); result.success(null); break; } @@ -232,8 +233,9 @@ public void onMethodCall(MethodCall call, Result result) { String deviceId = (String)call.arguments; BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(deviceId); int state = mBluetoothManager.getConnectionState(device, BluetoothProfile.GATT); - BluetoothGatt gattServer = mGattServers.remove(deviceId); - if(gattServer != null) { + BluetoothDeviceCache cache = mDevices.remove(deviceId); + if(cache != null) { + BluetoothGatt gattServer = cache.gatt; gattServer.disconnect(); if(state == BluetoothProfile.STATE_DISCONNECTED) { gattServer.close(); @@ -251,7 +253,7 @@ public void onMethodCall(MethodCall call, Result result) { try { result.success(ProtoMaker.from(device, state).toByteArray()); } catch(Exception e) { - result.error("device_state_error", e.getMessage(), null); + result.error("device_state_error", e.getMessage(), e); } break; } @@ -259,15 +261,15 @@ public void onMethodCall(MethodCall call, Result result) { case "discoverServices": { String deviceId = (String)call.arguments; - BluetoothGatt gattServer = mGattServers.get(deviceId); - if(gattServer == null) { - result.error("discover_services_error", "no instance of BluetoothGatt, have you connected first?", null); - return; - } - if(gattServer.discoverServices()) { - result.success(null); - } else { - result.error("discover_services_error", "unknown reason", null); + try { + BluetoothGatt gatt = locateGatt(deviceId); + if(gatt.discoverServices()) { + result.success(null); + } else { + result.error("discover_services_error", "unknown reason", null); + } + } catch(Exception e) { + result.error("discover_services_error", e.getMessage(), e); } break; } @@ -275,17 +277,17 @@ public void onMethodCall(MethodCall call, Result result) { case "services": { String deviceId = (String)call.arguments; - BluetoothGatt gattServer = mGattServers.get(deviceId); - if(gattServer == null) { - result.error("get_services_error", "no instance of BluetoothGatt, have you connected first?", null); - return; - } - Protos.DiscoverServicesResult.Builder p = Protos.DiscoverServicesResult.newBuilder(); - p.setRemoteId(deviceId); - for(BluetoothGattService s : gattServer.getServices()){ - p.addServices(ProtoMaker.from(gattServer.getDevice(), s, gattServer)); + try { + BluetoothGatt gatt = locateGatt(deviceId); + Protos.DiscoverServicesResult.Builder p = Protos.DiscoverServicesResult.newBuilder(); + p.setRemoteId(deviceId); + for(BluetoothGattService s : gatt.getServices()){ + p.addServices(ProtoMaker.from(gatt.getDevice(), s, gatt)); + } + result.success(p.build().toByteArray()); + } catch(Exception e) { + result.error("get_services_error", e.getMessage(), e); } - result.success(p.build().toByteArray()); break; } @@ -492,6 +494,52 @@ public void onMethodCall(MethodCall call, Result result) { break; } + case "mtu": + { + String deviceId = (String)call.arguments; + BluetoothDeviceCache cache = mDevices.get(deviceId); + if(cache != null) { + Protos.MtuSizeResponse.Builder p = Protos.MtuSizeResponse.newBuilder(); + p.setRemoteId(deviceId); + p.setMtu(cache.mtu); + result.success(p.build().toByteArray()); + } else { + result.error("mtu", "no instance of BluetoothGatt, have you connected first?", null); + } + break; + } + + case "requestMtu": + { + byte[] data = call.arguments(); + Protos.MtuSizeRequest request; + try { + request = Protos.MtuSizeRequest.newBuilder().mergeFrom(data).build(); + } catch (InvalidProtocolBufferException e) { + result.error("RuntimeException", e.getMessage(), e); + break; + } + + BluetoothGatt gatt; + try { + gatt = locateGatt(request.getRemoteId()); + int mtu = request.getMtu(); + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + if(gatt.requestMtu(mtu)) { + result.success(null); + } else { + result.error("requestMtu", "gatt.requestMtu returned false", null); + } + } else { + result.error("requestMtu", "Only supported on devices >= API 21 (Lollipop). This device == " + Build.VERSION.SDK_INT, null); + } + } catch(Exception e) { + result.error("requestMtu", e.getMessage(), e); + } + + break; + } + default: { result.notImplemented(); @@ -518,11 +566,12 @@ public boolean onRequestPermissionsResult( } private BluetoothGatt locateGatt(String remoteId) throws Exception { - BluetoothGatt gattServer = mGattServers.get(remoteId); - if(gattServer == null) { + BluetoothDeviceCache cache = mDevices.get(remoteId); + if(cache == null || cache.gatt == null) { throw new Exception("no instance of BluetoothGatt, have you connected first?"); + } else { + return cache.gatt; } - return gattServer; } private BluetoothGattCharacteristic locateCharacteristic(BluetoothGatt gattServer, String serviceId, String secondaryServiceId, String characteristicId) throws Exception { @@ -710,7 +759,7 @@ private void stopScan18() { public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { log(LogLevel.DEBUG, "[onConnectionStateChange] status: " + status + " newState: " + newState); if(newState == BluetoothProfile.STATE_DISCONNECTED) { - if(!mGattServers.containsKey(gatt.getDevice().getAddress())) { + if(!mDevices.containsKey(gatt.getDevice().getAddress())) { gatt.close(); } } @@ -822,6 +871,16 @@ public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { @Override public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) { log(LogLevel.DEBUG, "[onMtuChanged] mtu: " + mtu + " status: " + status); + if(status == BluetoothGatt.GATT_SUCCESS) { + if(mDevices.containsKey(gatt.getDevice().getAddress())) { + BluetoothDeviceCache cache = mDevices.get(gatt.getDevice().getAddress()); + cache.mtu = mtu; + Protos.MtuSizeResponse.Builder p = Protos.MtuSizeResponse.newBuilder(); + p.setRemoteId(gatt.getDevice().getAddress()); + p.setMtu(mtu); + invokeMethodUIThread("MtuSize", p.build().toByteArray()); + } + } } }; @@ -847,4 +906,16 @@ public void run() { }); } + // BluetoothDeviceCache contains any other cached information not stored in Android Bluetooth API + // but still needed Dart side. + class BluetoothDeviceCache { + final BluetoothGatt gatt; + int mtu; + + BluetoothDeviceCache(BluetoothGatt gatt) { + this.gatt = gatt; + mtu = 20; + } + } + } \ No newline at end of file diff --git a/example/lib/main.dart b/example/lib/main.dart index e8bfdb49..6fa02814 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -81,49 +81,48 @@ class FindDevicesScreen extends StatelessWidget { .asyncMap((_) => FlutterBlue.instance.connectedDevices), initialData: [], builder: (c, snapshot) => Column( - children: snapshot.data - .map((d) => ListTile( - title: Text(d.name), - subtitle: Text(d.id.toString()), - trailing: StreamBuilder( - stream: d.state, - initialData: - BluetoothDeviceState.disconnected, - builder: (c, snapshot) { - if (snapshot.data == - BluetoothDeviceState.connected) { - return RaisedButton( - child: Text('OPEN'), - onPressed: () => Navigator.of(context) - .push(MaterialPageRoute( - builder: (context) => - DeviceScreen(device: d))), - ); - } - return Text(snapshot.data.toString()); - }, - ), - )) - .toList(), - ), + children: snapshot.data + .map((d) => ListTile( + title: Text(d.name), + subtitle: Text(d.id.toString()), + trailing: StreamBuilder( + stream: d.state, + initialData: BluetoothDeviceState.disconnected, + builder: (c, snapshot) { + if (snapshot.data == + BluetoothDeviceState.connected) { + return RaisedButton( + child: Text('OPEN'), + onPressed: () => Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => + DeviceScreen(device: d))), + ); + } + return Text(snapshot.data.toString()); + }, + ), + )) + .toList(), + ), ), StreamBuilder>( stream: FlutterBlue.instance.scanResults, initialData: [], builder: (c, snapshot) => Column( - children: snapshot.data - .map( - (r) => ScanResultTile( - result: r, - onTap: () => Navigator.of(context).push( - MaterialPageRoute(builder: (context) { - r.device.connect(); - return DeviceScreen(device: r.device); - })), - ), - ) - .toList(), - ), + children: snapshot.data + .map( + (r) => ScanResultTile( + result: r, + onTap: () => Navigator.of(context) + .push(MaterialPageRoute(builder: (context) { + r.device.connect(); + return DeviceScreen(device: r.device); + })), + ), + ) + .toList(), + ), ), ], ), @@ -160,28 +159,28 @@ class DeviceScreen extends StatelessWidget { return services .map( (s) => ServiceTile( - service: s, - characteristicTiles: s.characteristics - .map( - (c) => CharacteristicTile( - characteristic: c, - onReadPressed: () => c.read(), - onWritePressed: () => c.write([13, 24]), - onNotificationPressed: () => - c.setNotifyValue(!c.isNotifying), - descriptorTiles: c.descriptors - .map( - (d) => DescriptorTile( - descriptor: d, - onReadPressed: () => d.read(), - onWritePressed: () => d.write([11, 12]), - ), - ) - .toList(), + service: s, + characteristicTiles: s.characteristics + .map( + (c) => CharacteristicTile( + characteristic: c, + onReadPressed: () => c.read(), + onWritePressed: () => c.write([13, 24]), + onNotificationPressed: () => + c.setNotifyValue(!c.isNotifying), + descriptorTiles: c.descriptors + .map( + (d) => DescriptorTile( + descriptor: d, + onReadPressed: () => d.read(), + onWritePressed: () => d.write([11, 12]), ), - ) - .toList(), - ), + ) + .toList(), + ), + ) + .toList(), + ), ) .toList(); } @@ -232,37 +231,48 @@ class DeviceScreen extends StatelessWidget { stream: device.state, initialData: BluetoothDeviceState.connecting, builder: (c, snapshot) => ListTile( - leading: (snapshot.data == BluetoothDeviceState.connected) - ? Icon(Icons.bluetooth_connected) - : Icon(Icons.bluetooth_disabled), - title: Text( - 'Device is ${snapshot.data.toString().split('.')[1]}.'), - subtitle: Text('${device.id}'), - trailing: StreamBuilder( - stream: device.isDiscoveringServices, - initialData: false, - builder: (c, snapshot) => IndexedStack( - index: snapshot.data ? 1 : 0, - children: [ - IconButton( - icon: Icon(Icons.refresh), - onPressed: () => device.discoverServices(), - ), - IconButton( - icon: SizedBox( - child: CircularProgressIndicator( - valueColor: - AlwaysStoppedAnimation(Colors.grey), - ), - width: 18.0, - height: 18.0, - ), - onPressed: null, - ) - ], + leading: (snapshot.data == BluetoothDeviceState.connected) + ? Icon(Icons.bluetooth_connected) + : Icon(Icons.bluetooth_disabled), + title: Text( + 'Device is ${snapshot.data.toString().split('.')[1]}.'), + subtitle: Text('${device.id}'), + trailing: StreamBuilder( + stream: device.isDiscoveringServices, + initialData: false, + builder: (c, snapshot) => IndexedStack( + index: snapshot.data ? 1 : 0, + children: [ + IconButton( + icon: Icon(Icons.refresh), + onPressed: () => device.discoverServices(), + ), + IconButton( + icon: SizedBox( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(Colors.grey), ), - ), + width: 18.0, + height: 18.0, + ), + onPressed: null, + ) + ], ), + ), + ), + ), + StreamBuilder( + stream: device.mtu, + initialData: 0, + builder: (c, snapshot) => ListTile( + title: Text('MTU Size'), + subtitle: Text('${snapshot.data} bytes'), + trailing: IconButton( + icon: Icon(Icons.edit), + onPressed: () => device.requestMtu(223), + ), + ), ), StreamBuilder>( stream: device.services, diff --git a/ios/Classes/FlutterBluePlugin.m b/ios/Classes/FlutterBluePlugin.m index 354b529f..2f60f7f8 100644 --- a/ios/Classes/FlutterBluePlugin.m +++ b/ios/Classes/FlutterBluePlugin.m @@ -239,6 +239,24 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { } @catch(FlutterError *e) { result(e); } + } else if([@"mtu" isEqualToString:call.method]) { + NSString *remoteId = [call arguments]; + @try { + CBPeripheral *peripheral = [self findPeripheral:remoteId]; + int32_t mtu; + if (@available(iOS 9.0, *)) { + // Which type should we use? (issue #365) + mtu = (int32_t)[peripheral maximumWriteValueLengthForType:CBCharacteristicWriteWithoutResponse]; + } else { + // Fallback to minimum on earlier versions. (issue #364) + mtu = 20; + } + result([self toFlutterData:[self toMtuSizeResponseProto:peripheral mtu:mtu]]); + } @catch(FlutterError *e) { + result(e); + } + } else if([@"requestMtu" isEqualToString:call.method]) { + result([FlutterError errorWithCode:@"requestMtu" message:@"iOS does not allow mtu requests to the peripheral" details:NULL]); } else { result(FlutterMethodNotImplemented); } @@ -707,6 +725,13 @@ - (ProtosCharacteristicProperties*)toCharacteristicPropsProto:(CBCharacteristicP return result; } +- (ProtosMtuSizeResponse*)toMtuSizeResponseProto:(CBPeripheral *)peripheral mtu:(int32_t)mtu { + ProtosMtuSizeResponse *result = [[ProtosMtuSizeResponse alloc] init]; + [result setRemoteId:[[peripheral identifier] UUIDString]]; + [result setMtu:mtu]; + return result; +} + - (void)log:(LogLevel)level format:(NSString *)format, ... { if(level <= _logLevel) { diff --git a/ios/gen/Flutterblue.pbobjc.h b/ios/gen/Flutterblue.pbobjc.h index 8a77322c..abf46403 100644 --- a/ios/gen/Flutterblue.pbobjc.h +++ b/ios/gen/Flutterblue.pbobjc.h @@ -744,6 +744,36 @@ typedef GPB_ENUM(ProtosConnectedDevicesResponse_FieldNumber) { @end +#pragma mark - ProtosMtuSizeRequest + +typedef GPB_ENUM(ProtosMtuSizeRequest_FieldNumber) { + ProtosMtuSizeRequest_FieldNumber_RemoteId = 1, + ProtosMtuSizeRequest_FieldNumber_Mtu = 2, +}; + +@interface ProtosMtuSizeRequest : GPBMessage + +@property(nonatomic, readwrite, copy, null_resettable) NSString *remoteId; + +@property(nonatomic, readwrite) int32_t mtu; + +@end + +#pragma mark - ProtosMtuSizeResponse + +typedef GPB_ENUM(ProtosMtuSizeResponse_FieldNumber) { + ProtosMtuSizeResponse_FieldNumber_RemoteId = 1, + ProtosMtuSizeResponse_FieldNumber_Mtu = 2, +}; + +@interface ProtosMtuSizeResponse : GPBMessage + +@property(nonatomic, readwrite, copy, null_resettable) NSString *remoteId; + +@property(nonatomic, readwrite) int32_t mtu; + +@end + NS_ASSUME_NONNULL_END CF_EXTERN_C_END diff --git a/ios/gen/Flutterblue.pbobjc.m b/ios/gen/Flutterblue.pbobjc.m index 18087084..f9ac8892 100644 --- a/ios/gen/Flutterblue.pbobjc.m +++ b/ios/gen/Flutterblue.pbobjc.m @@ -80,7 +80,9 @@ + (GPBDescriptor *)descriptor { fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(ProtosInt32Value__storage_) flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG descriptor = localDescriptor; } return descriptor; @@ -123,7 +125,9 @@ + (GPBDescriptor *)descriptor { fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(ProtosBluetoothState__storage_) flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG descriptor = localDescriptor; } return descriptor; @@ -278,7 +282,9 @@ + (GPBDescriptor *)descriptor { fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(ProtosAdvertisementData__storage_) flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG descriptor = localDescriptor; } return descriptor; @@ -332,7 +338,9 @@ + (GPBDescriptor *)descriptor { fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(ProtosScanSettings__storage_) flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG descriptor = localDescriptor; } return descriptor; @@ -397,7 +405,9 @@ + (GPBDescriptor *)descriptor { fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(ProtosScanResult__storage_) flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG descriptor = localDescriptor; } return descriptor; @@ -450,7 +460,9 @@ + (GPBDescriptor *)descriptor { fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(ProtosConnectRequest__storage_) flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG descriptor = localDescriptor; } return descriptor; @@ -515,7 +527,9 @@ + (GPBDescriptor *)descriptor { fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(ProtosBluetoothDevice__storage_) flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG descriptor = localDescriptor; } return descriptor; @@ -652,7 +666,9 @@ + (GPBDescriptor *)descriptor { fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(ProtosBluetoothService__storage_) flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG descriptor = localDescriptor; } return descriptor; @@ -766,7 +782,9 @@ + (GPBDescriptor *)descriptor { "\002\003\013\000\004\024\000"; [localDescriptor setupExtraTextInfo:extraTextFormatInfo]; #endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS - NSAssert(descriptor == nil, @"Startup recursed!"); + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG descriptor = localDescriptor; } return descriptor; @@ -858,7 +876,9 @@ + (GPBDescriptor *)descriptor { "\002\003\013\000\004\022\000"; [localDescriptor setupExtraTextInfo:extraTextFormatInfo]; #endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS - NSAssert(descriptor == nil, @"Startup recursed!"); + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG descriptor = localDescriptor; } return descriptor; @@ -990,7 +1010,9 @@ + (GPBDescriptor *)descriptor { fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(ProtosCharacteristicProperties__storage_) flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG descriptor = localDescriptor; } return descriptor; @@ -1044,7 +1066,9 @@ + (GPBDescriptor *)descriptor { fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(ProtosDiscoverServicesResult__storage_) flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG descriptor = localDescriptor; } return descriptor; @@ -1120,7 +1144,9 @@ + (GPBDescriptor *)descriptor { fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(ProtosReadCharacteristicRequest__storage_) flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG descriptor = localDescriptor; } return descriptor; @@ -1174,7 +1200,9 @@ + (GPBDescriptor *)descriptor { fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(ProtosReadCharacteristicResponse__storage_) flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG descriptor = localDescriptor; } return descriptor; @@ -1261,7 +1289,9 @@ + (GPBDescriptor *)descriptor { fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(ProtosReadDescriptorRequest__storage_) flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG descriptor = localDescriptor; } return descriptor; @@ -1315,7 +1345,9 @@ + (GPBDescriptor *)descriptor { fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(ProtosReadDescriptorResponse__storage_) flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG descriptor = localDescriptor; } return descriptor; @@ -1413,7 +1445,9 @@ + (GPBDescriptor *)descriptor { fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(ProtosWriteCharacteristicRequest__storage_) flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG descriptor = localDescriptor; } return descriptor; @@ -1513,7 +1547,9 @@ + (GPBDescriptor *)descriptor { fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(ProtosWriteCharacteristicResponse__storage_) flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG descriptor = localDescriptor; } return descriptor; @@ -1611,7 +1647,9 @@ + (GPBDescriptor *)descriptor { fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(ProtosWriteDescriptorRequest__storage_) flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG descriptor = localDescriptor; } return descriptor; @@ -1664,7 +1702,9 @@ + (GPBDescriptor *)descriptor { fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(ProtosWriteDescriptorResponse__storage_) flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG descriptor = localDescriptor; } return descriptor; @@ -1750,7 +1790,9 @@ + (GPBDescriptor *)descriptor { fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(ProtosSetNotificationRequest__storage_) flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG descriptor = localDescriptor; } return descriptor; @@ -1814,7 +1856,9 @@ + (GPBDescriptor *)descriptor { fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(ProtosSetNotificationResponse__storage_) flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG descriptor = localDescriptor; } return descriptor; @@ -1868,7 +1912,9 @@ + (GPBDescriptor *)descriptor { fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(ProtosOnCharacteristicChanged__storage_) flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG descriptor = localDescriptor; } return descriptor; @@ -1922,7 +1968,9 @@ + (GPBDescriptor *)descriptor { fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(ProtosDeviceStateResponse__storage_) flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG descriptor = localDescriptor; } return descriptor; @@ -2017,7 +2065,121 @@ + (GPBDescriptor *)descriptor { fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(ProtosConnectedDevicesResponse__storage_) flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - ProtosMtuSizeRequest + +@implementation ProtosMtuSizeRequest + +@dynamic remoteId; +@dynamic mtu; + +typedef struct ProtosMtuSizeRequest__storage_ { + uint32_t _has_storage_[1]; + int32_t mtu; + NSString *remoteId; +} ProtosMtuSizeRequest__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "remoteId", + .dataTypeSpecific.className = NULL, + .number = ProtosMtuSizeRequest_FieldNumber_RemoteId, + .hasIndex = 0, + .offset = (uint32_t)offsetof(ProtosMtuSizeRequest__storage_, remoteId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "mtu", + .dataTypeSpecific.className = NULL, + .number = ProtosMtuSizeRequest_FieldNumber_Mtu, + .hasIndex = 1, + .offset = (uint32_t)offsetof(ProtosMtuSizeRequest__storage_, mtu), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[ProtosMtuSizeRequest class] + rootClass:[ProtosFlutterblueRoot class] + file:ProtosFlutterblueRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(ProtosMtuSizeRequest__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - ProtosMtuSizeResponse + +@implementation ProtosMtuSizeResponse + +@dynamic remoteId; +@dynamic mtu; + +typedef struct ProtosMtuSizeResponse__storage_ { + uint32_t _has_storage_[1]; + int32_t mtu; + NSString *remoteId; +} ProtosMtuSizeResponse__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "remoteId", + .dataTypeSpecific.className = NULL, + .number = ProtosMtuSizeResponse_FieldNumber_RemoteId, + .hasIndex = 0, + .offset = (uint32_t)offsetof(ProtosMtuSizeResponse__storage_, remoteId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "mtu", + .dataTypeSpecific.className = NULL, + .number = ProtosMtuSizeResponse_FieldNumber_Mtu, + .hasIndex = 1, + .offset = (uint32_t)offsetof(ProtosMtuSizeResponse__storage_, mtu), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[ProtosMtuSizeResponse class] + rootClass:[ProtosFlutterblueRoot class] + file:ProtosFlutterblueRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(ProtosMtuSizeResponse__storage_) + flags:GPBDescriptorInitializationFlag_None]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG descriptor = localDescriptor; } return descriptor; diff --git a/lib/gen/flutterblue.pb.dart b/lib/gen/flutterblue.pb.dart index 0feb434a..5fc5f0c3 100644 --- a/lib/gen/flutterblue.pb.dart +++ b/lib/gen/flutterblue.pb.dart @@ -1,10 +1,11 @@ /// // Generated code. Do not modify. // source: flutterblue.proto -/// -// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type -import 'dart:core' as $core show bool, Deprecated, double, int, List, Map, override, pragma, String; +import 'dart:core' as $core; import 'package:protobuf/protobuf.dart' as $pb; @@ -13,7 +14,7 @@ import 'flutterblue.pbenum.dart'; export 'flutterblue.pbenum.dart'; class Int32Value extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('Int32Value') + static final $pb.BuilderInfo _i = $pb.BuilderInfo('Int32Value', createEmptyInstance: create) ..a<$core.int>(1, 'value', $pb.PbFieldType.O3) ..hasRequiredFields = false ; @@ -39,8 +40,8 @@ class Int32Value extends $pb.GeneratedMessage { } class BluetoothState extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('BluetoothState') - ..e(1, 'state', $pb.PbFieldType.OE, BluetoothState_State.UNKNOWN, BluetoothState_State.valueOf, BluetoothState_State.values) + static final $pb.BuilderInfo _i = $pb.BuilderInfo('BluetoothState', createEmptyInstance: create) + ..e(1, 'state', $pb.PbFieldType.OE, defaultOrMaker: BluetoothState_State.UNKNOWN, valueOf: BluetoothState_State.valueOf, enumValues: BluetoothState_State.values) ..hasRequiredFields = false ; @@ -65,12 +66,12 @@ class BluetoothState extends $pb.GeneratedMessage { } class AdvertisementData extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('AdvertisementData') + static final $pb.BuilderInfo _i = $pb.BuilderInfo('AdvertisementData', createEmptyInstance: create) ..aOS(1, 'localName') - ..a(2, 'txPowerLevel', $pb.PbFieldType.OM, Int32Value.getDefault, Int32Value.create) + ..a(2, 'txPowerLevel', $pb.PbFieldType.OM, defaultOrMaker: Int32Value.getDefault, subBuilder: Int32Value.create) ..aOB(3, 'connectable') - ..m<$core.int, $core.List<$core.int>>(4, 'manufacturerData', 'AdvertisementData.ManufacturerDataEntry',$pb.PbFieldType.O3, $pb.PbFieldType.OY, null, null, null ) - ..m<$core.String, $core.List<$core.int>>(5, 'serviceData', 'AdvertisementData.ServiceDataEntry',$pb.PbFieldType.OS, $pb.PbFieldType.OY, null, null, null ) + ..m<$core.int, $core.List<$core.int>>(4, 'manufacturerData', entryClassName: 'AdvertisementData.ManufacturerDataEntry', keyFieldType: $pb.PbFieldType.O3, valueFieldType: $pb.PbFieldType.OY) + ..m<$core.String, $core.List<$core.int>>(5, 'serviceData', entryClassName: 'AdvertisementData.ServiceDataEntry', keyFieldType: $pb.PbFieldType.OS, valueFieldType: $pb.PbFieldType.OY) ..pPS(6, 'serviceUuids') ..hasRequiredFields = false ; @@ -112,7 +113,7 @@ class AdvertisementData extends $pb.GeneratedMessage { } class ScanSettings extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('ScanSettings') + static final $pb.BuilderInfo _i = $pb.BuilderInfo('ScanSettings', createEmptyInstance: create) ..a<$core.int>(1, 'androidScanMode', $pb.PbFieldType.O3) ..pPS(2, 'serviceUuids') ..hasRequiredFields = false @@ -141,9 +142,9 @@ class ScanSettings extends $pb.GeneratedMessage { } class ScanResult extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('ScanResult') - ..a(1, 'device', $pb.PbFieldType.OM, BluetoothDevice.getDefault, BluetoothDevice.create) - ..a(2, 'advertisementData', $pb.PbFieldType.OM, AdvertisementData.getDefault, AdvertisementData.create) + static final $pb.BuilderInfo _i = $pb.BuilderInfo('ScanResult', createEmptyInstance: create) + ..a(1, 'device', $pb.PbFieldType.OM, defaultOrMaker: BluetoothDevice.getDefault, subBuilder: BluetoothDevice.create) + ..a(2, 'advertisementData', $pb.PbFieldType.OM, defaultOrMaker: AdvertisementData.getDefault, subBuilder: AdvertisementData.create) ..a<$core.int>(3, 'rssi', $pb.PbFieldType.O3) ..hasRequiredFields = false ; @@ -179,7 +180,7 @@ class ScanResult extends $pb.GeneratedMessage { } class ConnectRequest extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('ConnectRequest') + static final $pb.BuilderInfo _i = $pb.BuilderInfo('ConnectRequest', createEmptyInstance: create) ..aOS(1, 'remoteId') ..aOB(2, 'androidAutoConnect') ..hasRequiredFields = false @@ -211,10 +212,10 @@ class ConnectRequest extends $pb.GeneratedMessage { } class BluetoothDevice extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('BluetoothDevice') + static final $pb.BuilderInfo _i = $pb.BuilderInfo('BluetoothDevice', createEmptyInstance: create) ..aOS(1, 'remoteId') ..aOS(2, 'name') - ..e(3, 'type', $pb.PbFieldType.OE, BluetoothDevice_Type.UNKNOWN, BluetoothDevice_Type.valueOf, BluetoothDevice_Type.values) + ..e(3, 'type', $pb.PbFieldType.OE, defaultOrMaker: BluetoothDevice_Type.UNKNOWN, valueOf: BluetoothDevice_Type.valueOf, enumValues: BluetoothDevice_Type.values) ..hasRequiredFields = false ; @@ -249,12 +250,12 @@ class BluetoothDevice extends $pb.GeneratedMessage { } class BluetoothService extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('BluetoothService') + static final $pb.BuilderInfo _i = $pb.BuilderInfo('BluetoothService', createEmptyInstance: create) ..aOS(1, 'uuid') ..aOS(2, 'remoteId') ..aOB(3, 'isPrimary') - ..pc(4, 'characteristics', $pb.PbFieldType.PM,BluetoothCharacteristic.create) - ..pc(5, 'includedServices', $pb.PbFieldType.PM,BluetoothService.create) + ..pc(4, 'characteristics', $pb.PbFieldType.PM, subBuilder: BluetoothCharacteristic.create) + ..pc(5, 'includedServices', $pb.PbFieldType.PM, subBuilder: BluetoothService.create) ..hasRequiredFields = false ; @@ -293,13 +294,13 @@ class BluetoothService extends $pb.GeneratedMessage { } class BluetoothCharacteristic extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('BluetoothCharacteristic') + static final $pb.BuilderInfo _i = $pb.BuilderInfo('BluetoothCharacteristic', createEmptyInstance: create) ..aOS(1, 'uuid') ..aOS(2, 'remoteId') - ..aOS(3, 'serviceUuid') - ..aOS(4, 'secondaryServiceUuid') - ..pc(5, 'descriptors', $pb.PbFieldType.PM,BluetoothDescriptor.create) - ..a(6, 'properties', $pb.PbFieldType.OM, CharacteristicProperties.getDefault, CharacteristicProperties.create) + ..aOS(3, 'serviceUuid', protoName: 'serviceUuid') + ..aOS(4, 'secondaryServiceUuid', protoName: 'secondaryServiceUuid') + ..pc(5, 'descriptors', $pb.PbFieldType.PM, subBuilder: BluetoothDescriptor.create) + ..a(6, 'properties', $pb.PbFieldType.OM, defaultOrMaker: CharacteristicProperties.getDefault, subBuilder: CharacteristicProperties.create) ..a<$core.List<$core.int>>(7, 'value', $pb.PbFieldType.OY) ..hasRequiredFields = false ; @@ -352,11 +353,11 @@ class BluetoothCharacteristic extends $pb.GeneratedMessage { } class BluetoothDescriptor extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('BluetoothDescriptor') + static final $pb.BuilderInfo _i = $pb.BuilderInfo('BluetoothDescriptor', createEmptyInstance: create) ..aOS(1, 'uuid') ..aOS(2, 'remoteId') - ..aOS(3, 'serviceUuid') - ..aOS(4, 'characteristicUuid') + ..aOS(3, 'serviceUuid', protoName: 'serviceUuid') + ..aOS(4, 'characteristicUuid', protoName: 'characteristicUuid') ..a<$core.List<$core.int>>(5, 'value', $pb.PbFieldType.OY) ..hasRequiredFields = false ; @@ -402,7 +403,7 @@ class BluetoothDescriptor extends $pb.GeneratedMessage { } class CharacteristicProperties extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('CharacteristicProperties') + static final $pb.BuilderInfo _i = $pb.BuilderInfo('CharacteristicProperties', createEmptyInstance: create) ..aOB(1, 'broadcast') ..aOB(2, 'read') ..aOB(3, 'writeWithoutResponse') @@ -482,9 +483,9 @@ class CharacteristicProperties extends $pb.GeneratedMessage { } class DiscoverServicesResult extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('DiscoverServicesResult') + static final $pb.BuilderInfo _i = $pb.BuilderInfo('DiscoverServicesResult', createEmptyInstance: create) ..aOS(1, 'remoteId') - ..pc(2, 'services', $pb.PbFieldType.PM,BluetoothService.create) + ..pc(2, 'services', $pb.PbFieldType.PM, subBuilder: BluetoothService.create) ..hasRequiredFields = false ; @@ -511,7 +512,7 @@ class DiscoverServicesResult extends $pb.GeneratedMessage { } class ReadCharacteristicRequest extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('ReadCharacteristicRequest') + static final $pb.BuilderInfo _i = $pb.BuilderInfo('ReadCharacteristicRequest', createEmptyInstance: create) ..aOS(1, 'remoteId') ..aOS(2, 'characteristicUuid') ..aOS(3, 'serviceUuid') @@ -555,9 +556,9 @@ class ReadCharacteristicRequest extends $pb.GeneratedMessage { } class ReadCharacteristicResponse extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('ReadCharacteristicResponse') + static final $pb.BuilderInfo _i = $pb.BuilderInfo('ReadCharacteristicResponse', createEmptyInstance: create) ..aOS(1, 'remoteId') - ..a(2, 'characteristic', $pb.PbFieldType.OM, BluetoothCharacteristic.getDefault, BluetoothCharacteristic.create) + ..a(2, 'characteristic', $pb.PbFieldType.OM, defaultOrMaker: BluetoothCharacteristic.getDefault, subBuilder: BluetoothCharacteristic.create) ..hasRequiredFields = false ; @@ -587,7 +588,7 @@ class ReadCharacteristicResponse extends $pb.GeneratedMessage { } class ReadDescriptorRequest extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('ReadDescriptorRequest') + static final $pb.BuilderInfo _i = $pb.BuilderInfo('ReadDescriptorRequest', createEmptyInstance: create) ..aOS(1, 'remoteId') ..aOS(2, 'descriptorUuid') ..aOS(3, 'serviceUuid') @@ -637,8 +638,8 @@ class ReadDescriptorRequest extends $pb.GeneratedMessage { } class ReadDescriptorResponse extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('ReadDescriptorResponse') - ..a(1, 'request', $pb.PbFieldType.OM, ReadDescriptorRequest.getDefault, ReadDescriptorRequest.create) + static final $pb.BuilderInfo _i = $pb.BuilderInfo('ReadDescriptorResponse', createEmptyInstance: create) + ..a(1, 'request', $pb.PbFieldType.OM, defaultOrMaker: ReadDescriptorRequest.getDefault, subBuilder: ReadDescriptorRequest.create) ..a<$core.List<$core.int>>(2, 'value', $pb.PbFieldType.OY) ..hasRequiredFields = false ; @@ -669,12 +670,12 @@ class ReadDescriptorResponse extends $pb.GeneratedMessage { } class WriteCharacteristicRequest extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('WriteCharacteristicRequest') + static final $pb.BuilderInfo _i = $pb.BuilderInfo('WriteCharacteristicRequest', createEmptyInstance: create) ..aOS(1, 'remoteId') ..aOS(2, 'characteristicUuid') ..aOS(3, 'serviceUuid') ..aOS(4, 'secondaryServiceUuid') - ..e(5, 'writeType', $pb.PbFieldType.OE, WriteCharacteristicRequest_WriteType.WITH_RESPONSE, WriteCharacteristicRequest_WriteType.valueOf, WriteCharacteristicRequest_WriteType.values) + ..e(5, 'writeType', $pb.PbFieldType.OE, defaultOrMaker: WriteCharacteristicRequest_WriteType.WITH_RESPONSE, valueOf: WriteCharacteristicRequest_WriteType.valueOf, enumValues: WriteCharacteristicRequest_WriteType.values) ..a<$core.List<$core.int>>(6, 'value', $pb.PbFieldType.OY) ..hasRequiredFields = false ; @@ -725,8 +726,8 @@ class WriteCharacteristicRequest extends $pb.GeneratedMessage { } class WriteCharacteristicResponse extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('WriteCharacteristicResponse') - ..a(1, 'request', $pb.PbFieldType.OM, WriteCharacteristicRequest.getDefault, WriteCharacteristicRequest.create) + static final $pb.BuilderInfo _i = $pb.BuilderInfo('WriteCharacteristicResponse', createEmptyInstance: create) + ..a(1, 'request', $pb.PbFieldType.OM, defaultOrMaker: WriteCharacteristicRequest.getDefault, subBuilder: WriteCharacteristicRequest.create) ..aOB(2, 'success') ..hasRequiredFields = false ; @@ -757,7 +758,7 @@ class WriteCharacteristicResponse extends $pb.GeneratedMessage { } class WriteDescriptorRequest extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('WriteDescriptorRequest') + static final $pb.BuilderInfo _i = $pb.BuilderInfo('WriteDescriptorRequest', createEmptyInstance: create) ..aOS(1, 'remoteId') ..aOS(2, 'descriptorUuid') ..aOS(3, 'serviceUuid') @@ -813,8 +814,8 @@ class WriteDescriptorRequest extends $pb.GeneratedMessage { } class WriteDescriptorResponse extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('WriteDescriptorResponse') - ..a(1, 'request', $pb.PbFieldType.OM, WriteDescriptorRequest.getDefault, WriteDescriptorRequest.create) + static final $pb.BuilderInfo _i = $pb.BuilderInfo('WriteDescriptorResponse', createEmptyInstance: create) + ..a(1, 'request', $pb.PbFieldType.OM, defaultOrMaker: WriteDescriptorRequest.getDefault, subBuilder: WriteDescriptorRequest.create) ..aOB(2, 'success') ..hasRequiredFields = false ; @@ -845,7 +846,7 @@ class WriteDescriptorResponse extends $pb.GeneratedMessage { } class SetNotificationRequest extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('SetNotificationRequest') + static final $pb.BuilderInfo _i = $pb.BuilderInfo('SetNotificationRequest', createEmptyInstance: create) ..aOS(1, 'remoteId') ..aOS(2, 'serviceUuid') ..aOS(3, 'secondaryServiceUuid') @@ -895,9 +896,9 @@ class SetNotificationRequest extends $pb.GeneratedMessage { } class SetNotificationResponse extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('SetNotificationResponse') + static final $pb.BuilderInfo _i = $pb.BuilderInfo('SetNotificationResponse', createEmptyInstance: create) ..aOS(1, 'remoteId') - ..a(2, 'characteristic', $pb.PbFieldType.OM, BluetoothCharacteristic.getDefault, BluetoothCharacteristic.create) + ..a(2, 'characteristic', $pb.PbFieldType.OM, defaultOrMaker: BluetoothCharacteristic.getDefault, subBuilder: BluetoothCharacteristic.create) ..aOB(3, 'success') ..hasRequiredFields = false ; @@ -933,9 +934,9 @@ class SetNotificationResponse extends $pb.GeneratedMessage { } class OnCharacteristicChanged extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('OnCharacteristicChanged') + static final $pb.BuilderInfo _i = $pb.BuilderInfo('OnCharacteristicChanged', createEmptyInstance: create) ..aOS(1, 'remoteId') - ..a(2, 'characteristic', $pb.PbFieldType.OM, BluetoothCharacteristic.getDefault, BluetoothCharacteristic.create) + ..a(2, 'characteristic', $pb.PbFieldType.OM, defaultOrMaker: BluetoothCharacteristic.getDefault, subBuilder: BluetoothCharacteristic.create) ..hasRequiredFields = false ; @@ -965,9 +966,9 @@ class OnCharacteristicChanged extends $pb.GeneratedMessage { } class DeviceStateResponse extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('DeviceStateResponse') + static final $pb.BuilderInfo _i = $pb.BuilderInfo('DeviceStateResponse', createEmptyInstance: create) ..aOS(1, 'remoteId') - ..e(2, 'state', $pb.PbFieldType.OE, DeviceStateResponse_BluetoothDeviceState.DISCONNECTED, DeviceStateResponse_BluetoothDeviceState.valueOf, DeviceStateResponse_BluetoothDeviceState.values) + ..e(2, 'state', $pb.PbFieldType.OE, defaultOrMaker: DeviceStateResponse_BluetoothDeviceState.DISCONNECTED, valueOf: DeviceStateResponse_BluetoothDeviceState.valueOf, enumValues: DeviceStateResponse_BluetoothDeviceState.values) ..hasRequiredFields = false ; @@ -997,8 +998,8 @@ class DeviceStateResponse extends $pb.GeneratedMessage { } class ConnectedDevicesResponse extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('ConnectedDevicesResponse') - ..pc(1, 'devices', $pb.PbFieldType.PM,BluetoothDevice.create) + static final $pb.BuilderInfo _i = $pb.BuilderInfo('ConnectedDevicesResponse', createEmptyInstance: create) + ..pc(1, 'devices', $pb.PbFieldType.PM, subBuilder: BluetoothDevice.create) ..hasRequiredFields = false ; @@ -1019,3 +1020,67 @@ class ConnectedDevicesResponse extends $pb.GeneratedMessage { $core.List get devices => $_getList(0); } +class MtuSizeRequest extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('MtuSizeRequest', createEmptyInstance: create) + ..aOS(1, 'remoteId') + ..a<$core.int>(2, 'mtu', $pb.PbFieldType.O3) + ..hasRequiredFields = false + ; + + MtuSizeRequest._() : super(); + factory MtuSizeRequest() => create(); + factory MtuSizeRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory MtuSizeRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + MtuSizeRequest clone() => MtuSizeRequest()..mergeFromMessage(this); + MtuSizeRequest copyWith(void Function(MtuSizeRequest) updates) => super.copyWith((message) => updates(message as MtuSizeRequest)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static MtuSizeRequest create() => MtuSizeRequest._(); + MtuSizeRequest createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static MtuSizeRequest getDefault() => _defaultInstance ??= create()..freeze(); + static MtuSizeRequest _defaultInstance; + + $core.String get remoteId => $_getS(0, ''); + set remoteId($core.String v) { $_setString(0, v); } + $core.bool hasRemoteId() => $_has(0); + void clearRemoteId() => clearField(1); + + $core.int get mtu => $_get(1, 0); + set mtu($core.int v) { $_setSignedInt32(1, v); } + $core.bool hasMtu() => $_has(1); + void clearMtu() => clearField(2); +} + +class MtuSizeResponse extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('MtuSizeResponse', createEmptyInstance: create) + ..aOS(1, 'remoteId') + ..a<$core.int>(2, 'mtu', $pb.PbFieldType.O3) + ..hasRequiredFields = false + ; + + MtuSizeResponse._() : super(); + factory MtuSizeResponse() => create(); + factory MtuSizeResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory MtuSizeResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + MtuSizeResponse clone() => MtuSizeResponse()..mergeFromMessage(this); + MtuSizeResponse copyWith(void Function(MtuSizeResponse) updates) => super.copyWith((message) => updates(message as MtuSizeResponse)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static MtuSizeResponse create() => MtuSizeResponse._(); + MtuSizeResponse createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static MtuSizeResponse getDefault() => _defaultInstance ??= create()..freeze(); + static MtuSizeResponse _defaultInstance; + + $core.String get remoteId => $_getS(0, ''); + set remoteId($core.String v) { $_setString(0, v); } + $core.bool hasRemoteId() => $_has(0); + void clearRemoteId() => clearField(1); + + $core.int get mtu => $_get(1, 0); + set mtu($core.int v) { $_setSignedInt32(1, v); } + $core.bool hasMtu() => $_has(1); + void clearMtu() => clearField(2); +} + diff --git a/lib/gen/flutterblue.pbenum.dart b/lib/gen/flutterblue.pbenum.dart index 64b4fa5f..f8879fdd 100644 --- a/lib/gen/flutterblue.pbenum.dart +++ b/lib/gen/flutterblue.pbenum.dart @@ -1,11 +1,12 @@ /// // Generated code. Do not modify. // source: flutterblue.proto -/// -// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type // ignore_for_file: UNDEFINED_SHOWN_NAME,UNUSED_SHOWN_NAME -import 'dart:core' as $core show int, dynamic, String, List, Map; +import 'dart:core' as $core; import 'package:protobuf/protobuf.dart' as $pb; class BluetoothState_State extends $pb.ProtobufEnum { diff --git a/lib/gen/flutterblue.pbjson.dart b/lib/gen/flutterblue.pbjson.dart index 9878f52b..e17a8799 100644 --- a/lib/gen/flutterblue.pbjson.dart +++ b/lib/gen/flutterblue.pbjson.dart @@ -1,8 +1,9 @@ /// // Generated code. Do not modify. // source: flutterblue.proto -/// -// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type const Int32Value$json = const { '1': 'Int32Value', @@ -307,3 +308,19 @@ const ConnectedDevicesResponse$json = const { ], }; +const MtuSizeRequest$json = const { + '1': 'MtuSizeRequest', + '2': const [ + const {'1': 'remote_id', '3': 1, '4': 1, '5': 9, '10': 'remoteId'}, + const {'1': 'mtu', '3': 2, '4': 1, '5': 5, '10': 'mtu'}, + ], +}; + +const MtuSizeResponse$json = const { + '1': 'MtuSizeResponse', + '2': const [ + const {'1': 'remote_id', '3': 1, '4': 1, '5': 9, '10': 'remoteId'}, + const {'1': 'mtu', '3': 2, '4': 1, '5': 5, '10': 'mtu'}, + ], +}; + diff --git a/lib/gen/flutterblue.pbserver.dart b/lib/gen/flutterblue.pbserver.dart index c9e5666b..fb7833fd 100644 --- a/lib/gen/flutterblue.pbserver.dart +++ b/lib/gen/flutterblue.pbserver.dart @@ -1,8 +1,9 @@ /// // Generated code. Do not modify. // source: flutterblue.proto -/// -// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type export 'flutterblue.pb.dart'; diff --git a/lib/src/bluetooth_device.dart b/lib/src/bluetooth_device.dart index db27ead6..ddb3edd4 100644 --- a/lib/src/bluetooth_device.dart +++ b/lib/src/bluetooth_device.dart @@ -101,6 +101,32 @@ class BluetoothDevice { .map((p) => BluetoothDeviceState.values[p.state.value]); } + /// The MTU size in bytes + Stream get mtu async* { + yield await FlutterBlue.instance._channel + .invokeMethod('mtu', id.toString()) + .then((buffer) => new protos.MtuSizeResponse.fromBuffer(buffer)) + .then((p) => p.mtu); + + yield* FlutterBlue.instance._methodStream + .where((m) => m.method == "MtuSize") + .map((m) => m.arguments) + .map((buffer) => new protos.MtuSizeResponse.fromBuffer(buffer)) + .where((p) => p.remoteId == id.toString()) + .map((p) => p.mtu); + } + + /// Request to change the MTU Size + /// Throws error if request did not complete successfully + Future requestMtu(int desiredMtu) async { + var request = protos.MtuSizeRequest.create() + ..remoteId = id.toString() + ..mtu = desiredMtu; + + return FlutterBlue.instance._channel + .invokeMethod('requestMtu', request.writeToBuffer()); + } + /// Indicates whether the Bluetooth Device can send a write without response Future get canSendWriteWithoutResponse => new Future.error(new UnimplementedError()); diff --git a/lib/src/flutter_blue.dart b/lib/src/flutter_blue.dart index bc547150..a2f36845 100644 --- a/lib/src/flutter_blue.dart +++ b/lib/src/flutter_blue.dart @@ -56,6 +56,7 @@ class FlutterBlue { .map((s) => BluetoothState.values[s.state.value]); } + /// Retrieve a list of connected devices Future> get connectedDevices { return _channel .invokeMethod('getConnectedDevices') diff --git a/protos/flutterblue.proto b/protos/flutterblue.proto index fc9bf8e5..6bd6db0e 100644 --- a/protos/flutterblue.proto +++ b/protos/flutterblue.proto @@ -200,4 +200,14 @@ message DeviceStateResponse { message ConnectedDevicesResponse { repeated BluetoothDevice devices = 1; +} + +message MtuSizeRequest { + string remote_id = 1; + int32 mtu = 2; +} + +message MtuSizeResponse { + string remote_id = 1; + int32 mtu = 2; } \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index 6069810e..851c7bad 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -13,7 +13,7 @@ dependencies: flutter: sdk: flutter convert: "^2.1.1" - protobuf: "^0.13.12" + protobuf: "^0.14.1" rxdart: "^0.22.0" flutter: