iOS 平台实现 (#2)

* 修复 UUID 创建失败的问题

* 移除 scanning 属性

* 临时提交

* CentralManager 开发 & 示例项目开发

* CentralManager 开发 & 示例项目开发

* android 插件生命周期监听

* 修改 API

* 示例程序开发

* 修改字体,添加 API,解决后台问题

* Central#connect API

* 蓝牙连接部分开发

* 蓝牙连接部分开发

* 解决一些问题

* 解决一些问题

* Connect API 优化

* 添加 API

* example 开发

* API 基本完成

* 消息重命名

* API 修改,Android 实现

* 删除多余代码

* 删除多余文件

* 解决 descriptor 自动生成报错的问题

* 还原 Kotlin 版本,广播处理代码迁移至 dart 端

* Kotlin 版本升至 1.5.20

* 解决特征值通知没有在主线程触发的问题,优化代码

* 引入哈希值,避免对象销毁后继续使用

* 使用下拉刷新代替搜索按钮

* 解决由于热重载和蓝牙关闭产生的问题

* 更新插件信息

* 更新 README 和 CHANGELOG

* 更新许可证

* 添加注释

* 添加注释,central 拆分

* dartfmt -w .

* flutter build ios --no-codesign

* API 重构

* 添加 connectable 属性

* Android 8.0 之前无法获取 connectable 属性

* 解决合并错误

* 解决连接时可能引发异常的一个问题,iOS 开发

* API 修改,TODO: iOS 哈希值为 64 位无法用 Int32 表示

* iOS 开发

* iOS 开发完成,使用 UUID 实现对象映射

* 更新版本记录和文档
This commit is contained in:
iAMD
2021-07-15 20:18:49 +08:00
committed by GitHub
parent aaed38e1eb
commit fc35f74488
63 changed files with 10278 additions and 5267 deletions

View File

@ -1,3 +1,10 @@
## 0.1.0
- Add implements on iOS.
- Combine available and state for Bluetooth.
- Add connectable for Discovery.
- Add maximumWriteLength for GATT.
## 0.0.2 ## 0.0.2
- Fix connect blocked when bluetooth closed. - Fix connect blocked when bluetooth closed.

View File

@ -26,17 +26,16 @@ dependencies:
bluetooth_low_energy: ^<latest-version> bluetooth_low_energy: ^<latest-version>
``` ```
*Note*: Bluetooth Low Energy doesn't work on Android emulators, so use physical devices which has bluetooth features for development.
### Android ### Android
Make sure you have a `miniSdkVersion` with 21 or higher in your `android/app/build.gradle` file, now we only support Android 5.0 or above. Make sure you have a `miniSdkVersion` with 21 or higher in your `android/app/build.gradle` file, now we only support Android 5.0 or above.
*Note*: Bluetooth Low Energy doesn't work on Android emulators, so use physical devices which has bluetooth features for development.
### iOS ### iOS
TO BE DONE. Make sure you have a minimum deployment target of 9.0 or above, you can uncomment the first line `platform :ios, '9.0'` in your iOS project's `Podfile`.
## Issues ## Issues
- Only support Android for now, iOS will available as soon as possible. - Not support peripheral APIs for now.
- Only support central APIs for now.

View File

@ -2,7 +2,7 @@ group 'dev.yanshouwang.bluetooth_low_energy'
version '1.0-SNAPSHOT' version '1.0-SNAPSHOT'
buildscript { buildscript {
ext.kotlin_version = '1.5.20' ext.kotlin_version = '1.5.21'
repositories { repositories {
google() google()
mavenCentral() mavenCentral()

View File

@ -42,16 +42,6 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler
private const val CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb" private const val CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb"
private const val BLUETOOTH_ADAPTER_STATE_UNKNOWN = -1 private const val BLUETOOTH_ADAPTER_STATE_UNKNOWN = -1
private const val NO_ERROR = 0 private const val NO_ERROR = 0
private const val INVALID_REQUEST = 1
private const val REQUEST_PERMISSION_FAILED = 2
private const val REQUEST_MTU_FAILED = 3
private const val DISCOVER_SERVICES_FAILED = 4
private const val READ_CHARACTERISTIC_FAILED = 5
private const val WRITE_CHARACTERISTIC_FAILED = 6
private const val NOTIFY_CHARACTERISTIC_FAILED = 7
private const val READ_DESCRIPTOR_FAILED = 8
private const val WRITE_DESCRIPTOR_FAILED = 9
private const val BLUETOOTH_ADAPTER_CLOSED = 10
private const val REQUEST_CODE = 443 private const val REQUEST_CODE = 443
} }
@ -60,28 +50,32 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler
private lateinit var context: Context private lateinit var context: Context
private var binding: ActivityPluginBinding? = null private var binding: ActivityPluginBinding? = null
private var sink: EventSink? = null private var events: EventSink? = null
private val bluetoothAvailable by lazy { context.packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE) } private val bluetoothAvailable by lazy { context.packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE) }
private val bluetoothManager by lazy { context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager } private val bluetoothManager by lazy { context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager }
private val bluetoothAdapter by lazy { bluetoothManager.adapter } private val bluetoothAdapter by lazy { bluetoothManager.adapter }
private val handler by lazy { Handler(context.mainLooper) } private val handler by lazy { Handler(context.mainLooper) }
private val bluetoothState: BluetoothState
get() {
return if (bluetoothAvailable) bluetoothAdapter.state.messageState
else BluetoothState.UNSUPPORTED
}
private val bluetoothStateReceiver by lazy { private val bluetoothStateReceiver by lazy {
object : BroadcastReceiver() { object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) { override fun onReceive(context: Context?, intent: Intent?) {
val oldState = intent!!.getIntExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, BLUETOOTH_ADAPTER_STATE_UNKNOWN).opened val oldState = intent!!.getIntExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, BLUETOOTH_ADAPTER_STATE_UNKNOWN).messageState
val newState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BLUETOOTH_ADAPTER_STATE_UNKNOWN).opened val newState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BLUETOOTH_ADAPTER_STATE_UNKNOWN).messageState
// TODO: clear status when bluetooth closed.
if (newState == oldState) return if (newState == oldState) return
val closed = !newState if (newState != BluetoothState.POWERED_ON && scanning) scanning = false
if (closed && scanning) scanning = false
val event = Message.newBuilder() val event = Message.newBuilder()
.setCategory(BLUETOOTH_STATE) .setCategory(BLUETOOTH_STATE)
.setState(newState) .setState(newState)
.build() .build()
.toByteArray() .toByteArray()
sink?.success(event) events?.success(event)
} }
} }
} }
@ -93,6 +87,7 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler
private var scanCode = NO_ERROR private var scanCode = NO_ERROR
private var scanning = false private var scanning = false
private val scanCallback by lazy { private val scanCallback by lazy {
object : ScanCallback() { object : ScanCallback() {
override fun onScanFailed(errorCode: Int) { override fun onScanFailed(errorCode: Int) {
@ -103,122 +98,129 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler
override fun onScanResult(callbackType: Int, result: ScanResult?) { override fun onScanResult(callbackType: Int, result: ScanResult?) {
super.onScanResult(callbackType, result) super.onScanResult(callbackType, result)
if (result == null) return if (result == null) return
val address = result.device.address
val rssi = result.rssi
val record = result.scanRecord val record = result.scanRecord
val advertisements = val advertisements =
if (record == null) ByteString.EMPTY if (record == null) ByteString.EMPTY
else ByteString.copyFrom(record.bytes) else ByteString.copyFrom(record.bytes)
// TODO: We can't get connectable value before Android 8.0, here we just return true
// remove this useless code after the minSdkVersion set to 26 or later.
val connectable =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) result.isConnectable
else true
val builder = Discovery.newBuilder() val builder = Discovery.newBuilder()
.setAddress(address) .setUuid(result.device.uuid)
.setRssi(rssi) .setRssi(result.rssi)
.setAdvertisements(advertisements) .setAdvertisements(advertisements)
.setConnectable(connectable)
val discovery = builder.build() val discovery = builder.build()
val event = Message.newBuilder() val event = Message.newBuilder()
.setCategory(CENTRAL_DISCOVERED) .setCategory(CENTRAL_DISCOVERED)
.setDiscovery(discovery) .setDiscovery(discovery)
.build() .build()
.toByteArray() .toByteArray()
sink?.success(event) events?.success(event)
} }
override fun onBatchScanResults(results: MutableList<ScanResult>?) { override fun onBatchScanResults(results: MutableList<ScanResult>?) {
super.onBatchScanResults(results) super.onBatchScanResults(results)
if (results == null) return if (results == null) return
for (result in results) { for (result in results) {
val address = result.device.address
val rssi = result.rssi
val record = result.scanRecord val record = result.scanRecord
val advertisements = val advertisements =
if (record == null) ByteString.EMPTY if (record == null) ByteString.EMPTY
else ByteString.copyFrom(record.bytes) else ByteString.copyFrom(record.bytes)
// TODO: We can't get connectable value before Android 8.0, here we just return true
// remove this useless code after the minSdkVersion set to 26 or later.
val connectable =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) result.isConnectable
else true
val builder = Discovery.newBuilder() val builder = Discovery.newBuilder()
.setAddress(address) .setUuid(result.device.uuid)
.setRssi(rssi) .setRssi(result.rssi)
.setAdvertisements(advertisements) .setAdvertisements(advertisements)
.setConnectable(connectable)
val discovery = builder.build() val discovery = builder.build()
val event = Message.newBuilder() val event = Message.newBuilder()
.setCategory(CENTRAL_DISCOVERED) .setCategory(CENTRAL_DISCOVERED)
.setDiscovery(discovery) .setDiscovery(discovery)
.build() .build()
.toByteArray() .toByteArray()
sink?.success(event) events?.success(event)
} }
} }
} }
} }
private val gatts by lazy { mutableMapOf<String, BluetoothGatt>() } private val nativeGATTs by lazy { mutableMapOf<String, NativeGATT>() }
private val connects by lazy { mutableMapOf<String, Result>() }
private val mtus by lazy { mutableMapOf<String, Int>() } private val connects by lazy { mutableMapOf<BluetoothGatt, Result>() }
private val disconnects by lazy { mutableMapOf<String, Result>() } private val maximumWriteLengths by lazy { mutableMapOf<BluetoothGatt, Int>() }
private val characteristicReads by lazy { mutableMapOf<Int, Result>() } private val disconnects by lazy { mutableMapOf<BluetoothGatt, Result>() }
private val characteristicWrites by lazy { mutableMapOf<Int, Result>() } private val characteristicReads by lazy { mutableMapOf<BluetoothGattCharacteristic, Result>() }
private val descriptorReads by lazy { mutableMapOf<Int, Result>() } private val characteristicWrites by lazy { mutableMapOf<BluetoothGattCharacteristic, Result>() }
private val descriptorWrites by lazy { mutableMapOf<Int, Result>() } private val descriptorReads by lazy { mutableMapOf<BluetoothGattDescriptor, Result>() }
private val descriptorWrites by lazy { mutableMapOf<BluetoothGattDescriptor, Result>() }
private val bluetoothGattCallback by lazy { private val bluetoothGattCallback by lazy {
object : BluetoothGattCallback() { object : BluetoothGattCallback() {
override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) { override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
super.onConnectionStateChange(gatt, status, newState) super.onConnectionStateChange(gatt, status, newState)
val address = gatt!!.device.address
when (status) { when (status) {
BluetoothGatt.GATT_SUCCESS -> { BluetoothGatt.GATT_SUCCESS -> {
when (newState) { when (newState) {
BluetoothProfile.STATE_DISCONNECTED -> { BluetoothProfile.STATE_DISCONNECTED -> {
// Maybe disconnect succeed, connect failed, or connection lost when an adaptor closed event triggered. // Maybe disconnect succeed, connect failed, or connection lost when an adaptor closed event triggered.
gatts.remove(address)!!.close() gatt!!.close()
val disconnect = disconnects.remove(address) val connect = connects.remove(gatt)
if (disconnect != null) handler.post { disconnect.success() } if (connect != null) handler.post { connect.error("GATT error with status: $status.", null, null) }
else { else {
val connect = connects.remove(address) val nativeGATT = nativeGATTs.entries.first { entry -> entry.value.value === gatt }
if (connect != null) handler.post { connect.error(BLUETOOTH_ADAPTER_CLOSED) } nativeGATTs.remove(nativeGATT.key)
val disconnect = disconnects.remove(gatt)
if (disconnect != null) handler.post { disconnect.success() }
else { else {
val id = gatt.hashCode() val connectionLost = GattConnectionLost.newBuilder()
val connectionLost = ConnectionLost.newBuilder() .setKey(nativeGATT.key)
.setId(id) .setError("GATT error with status: $status")
.setErrorCode(BLUETOOTH_ADAPTER_CLOSED)
.build() .build()
val event = Message.newBuilder() val event = Message.newBuilder()
.setCategory(GATT_CONNECTION_LOST) .setCategory(GATT_CONNECTION_LOST)
.setConnectionLost(connectionLost) .setConnectionLost(connectionLost)
.build() .build()
.toByteArray() .toByteArray()
handler.post { sink?.success(event) } handler.post { events?.success(event) }
} }
} }
} }
BluetoothProfile.STATE_CONNECTED -> { BluetoothProfile.STATE_CONNECTED -> {
// Must be connect succeed. // Must be connect succeed.
val requested = gatt.requestMtu(512) val requested = gatt!!.requestMtu(512)
if (!requested) { if (!requested) gatt.disconnect()
gatts.remove(address)!!.close()
val connect = connects.remove(address)!!
handler.post { connect.error(REQUEST_MTU_FAILED) }
}
} }
else -> throw NotImplementedError() // should never be called. else -> throw NotImplementedError() // should never be called.
} }
} }
else -> { else -> {
// Maybe connect failed, disconnect failed or connection lost when an adaptor closed event triggered. // Maybe connect failed, disconnect failed or connection lost.
gatts.remove(address)!!.close() gatt!!.close()
val connect = connects.remove(address) val connect = connects.remove(gatt)
if (connect != null) handler.post { connect.error(status) } if (connect != null) handler.post { connect.error("GATT error with status: $status", null, null) }
else { else {
val disconnect = disconnects.remove(address) val nativeGATT = nativeGATTs.entries.first { entry -> entry.value.value === gatt }
if (disconnect != null) handler.post { disconnect.error(status) } nativeGATTs.remove(nativeGATT.key)
val disconnect = disconnects.remove(gatt)
if (disconnect != null) handler.post { disconnect.error("GATT error with status: $status", null, null) }
else { else {
val id = gatt.hashCode() val connectionLost = GattConnectionLost.newBuilder()
val connectionLost = ConnectionLost.newBuilder() .setKey(nativeGATT.key)
.setId(id) .setError("GATT error with status: $status")
.setErrorCode(status)
.build() .build()
val event = Message.newBuilder() val event = Message.newBuilder()
.setCategory(GATT_CONNECTION_LOST) .setCategory(GATT_CONNECTION_LOST)
.setConnectionLost(connectionLost) .setConnectionLost(connectionLost)
.build() .build()
.toByteArray() .toByteArray()
handler.post { sink?.success(event) } handler.post { events?.success(event) }
} }
} }
} }
@ -227,107 +229,118 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler
override fun onMtuChanged(gatt: BluetoothGatt?, mtu: Int, status: Int) { override fun onMtuChanged(gatt: BluetoothGatt?, mtu: Int, status: Int) {
super.onMtuChanged(gatt, mtu, status) super.onMtuChanged(gatt, mtu, status)
val address = gatt!!.device.address when (status) {
val code = when (status) {
BluetoothGatt.GATT_SUCCESS -> { BluetoothGatt.GATT_SUCCESS -> {
val discovered = gatt.discoverServices() val discovered = gatt!!.discoverServices()
if (discovered) { if (discovered) maximumWriteLengths[gatt] = mtu - 3
mtus[address] = mtu else gatt.disconnect()
NO_ERROR
} else DISCOVER_SERVICES_FAILED
} }
else -> status else -> gatt!!.disconnect()
}
if (code != NO_ERROR) {
gatts.remove(address)!!.close()
val connect = connects.remove(address)!!
handler.post { connect.error(code) }
} }
} }
override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) { override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
super.onServicesDiscovered(gatt, status) super.onServicesDiscovered(gatt, status)
val address = gatt!!.device.address val maximumWriteLength = maximumWriteLengths.remove(gatt)!!
val connect = connects.remove(address)!!
val mtu = mtus.remove(address)!!
when (status) { when (status) {
BluetoothGatt.GATT_SUCCESS -> { BluetoothGatt.GATT_SUCCESS -> {
val id = gatt.hashCode() val nativeServices = mutableMapOf<String, NativeGattService>()
val services = gatt.services.map { service -> val messageServices = mutableListOf<GattService>()
val serviceId = service.hashCode() for (service in gatt!!.services) {
val serviceUUID = service.uuid.toString() val nativeCharacteristics = mutableMapOf<String, NativeGattCharacteristic>()
val characteristics = service.characteristics.map { characteristic -> val messageCharacteristics = mutableListOf<GattCharacteristic>()
val characteristicId = characteristic.hashCode() for (characteristic in service.characteristics) {
val characteristicUUID = characteristic.uuid.toString() val nativeDescriptors = mutableMapOf<String, NativeGattDescriptor>()
val properties = characteristic.properties val messageDescriptors = mutableListOf<GattDescriptor>()
val canRead = properties and BluetoothGattCharacteristic.PROPERTY_READ != 0 for (descriptor in characteristic.descriptors) {
val canWrite = properties and BluetoothGattCharacteristic.PROPERTY_WRITE != 0 // Add native descriptor.
val canWriteWithoutResponse = properties and BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE != 0 val nativeDescriptor = NativeGattDescriptor(descriptor)
val canNotify = properties and BluetoothGattCharacteristic.PROPERTY_NOTIFY != 0 nativeDescriptors[nativeDescriptor.key] = nativeDescriptor
val descriptors = characteristic.descriptors.map { descriptor -> // Add message descriptor.
val descriptorId = descriptor.hashCode()
val descriptorUUID = descriptor.uuid.toString() val descriptorUUID = descriptor.uuid.toString()
GattDescriptor.newBuilder() val messageDescriptor = GattDescriptor.newBuilder()
.setId(descriptorId) .setKey(nativeDescriptor.key)
.setUuid(descriptorUUID) .setUuid(descriptorUUID)
.build() .build()
messageDescriptors.add(messageDescriptor)
} }
GattCharacteristic.newBuilder() // Add native characteristic.
.setId(characteristicId) val nativeCharacteristic = NativeGattCharacteristic(characteristic, nativeDescriptors)
nativeCharacteristics[nativeCharacteristic.key] = nativeCharacteristic
// Add message characteristic.
val characteristicUUID = characteristic.uuid.toString()
val canRead = characteristic.properties and BluetoothGattCharacteristic.PROPERTY_READ != 0
val canWrite = characteristic.properties and BluetoothGattCharacteristic.PROPERTY_WRITE != 0
val canWriteWithoutResponse = characteristic.properties and BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE != 0
val canNotify = characteristic.properties and BluetoothGattCharacteristic.PROPERTY_NOTIFY != 0
val messageCharacteristic = GattCharacteristic.newBuilder()
.setKey(nativeCharacteristic.key)
.setUuid(characteristicUUID) .setUuid(characteristicUUID)
.setCanRead(canRead) .setCanRead(canRead)
.setCanWrite(canWrite) .setCanWrite(canWrite)
.setCanWriteWithoutResponse(canWriteWithoutResponse) .setCanWriteWithoutResponse(canWriteWithoutResponse)
.setCanNotify(canNotify) .setCanNotify(canNotify)
.addAllDescriptors(descriptors) .addAllDescriptors(messageDescriptors)
.build() .build()
messageCharacteristics.add(messageCharacteristic)
} }
GattService.newBuilder() // Add native service.
.setId(serviceId) val nativeService = NativeGattService(service, nativeCharacteristics)
nativeServices[nativeService.key] = nativeService
// Add message service.
val serviceUUID = service.uuid.toString()
val messageService = GattService.newBuilder()
.setKey(nativeService.key)
.setUuid(serviceUUID) .setUuid(serviceUUID)
.addAllCharacteristics(characteristics).build() .addAllCharacteristics(messageCharacteristics)
.build()
messageServices.add(messageService)
} }
// Add native gatt.
val nativeGATT = NativeGATT(gatt, nativeServices)
nativeGATTs[nativeGATT.key] = nativeGATT
// Add message gatt.
val reply = GATT.newBuilder() val reply = GATT.newBuilder()
.setId(id) .setKey(nativeGATT.key)
.setMtu(mtu) .setMaximumWriteLength(maximumWriteLength)
.addAllServices(services) .addAllServices(messageServices)
.build() .build()
.toByteArray() .toByteArray()
val connect = connects.remove(gatt)!!
handler.post { connect.success(reply) } handler.post { connect.success(reply) }
} }
else -> { else -> gatt!!.disconnect()
gatts.remove(address)!!.close()
handler.post { connect.error(status) }
}
} }
} }
override fun onCharacteristicRead(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int) { override fun onCharacteristicRead(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int) {
super.onCharacteristicRead(gatt, characteristic, status) super.onCharacteristicRead(gatt, characteristic, status)
val key = characteristic!!.hashCode() val read = characteristicReads.remove(characteristic)!!
val read = characteristicReads.remove(key)!!
when (status) { when (status) {
BluetoothGatt.GATT_SUCCESS -> handler.post { read.success(characteristic.value) } BluetoothGatt.GATT_SUCCESS -> handler.post { read.success(characteristic!!.value) }
else -> handler.post { read.error(status) } else -> handler.post { read.error("GATT error with status: $status", null, null) }
} }
} }
override fun onCharacteristicWrite(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int) { override fun onCharacteristicWrite(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int) {
super.onCharacteristicWrite(gatt, characteristic, status) super.onCharacteristicWrite(gatt, characteristic, status)
val key = characteristic!!.hashCode() val write = characteristicWrites.remove(characteristic)!!
val write = characteristicWrites.remove(key)!!
when (status) { when (status) {
BluetoothGatt.GATT_SUCCESS -> handler.post { write.success() } BluetoothGatt.GATT_SUCCESS -> handler.post { write.success() }
else -> handler.post { write.error(status) } else -> handler.post { write.error("GATT error with status: $status", null, null) }
} }
} }
override fun onCharacteristicChanged(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?) { override fun onCharacteristicChanged(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?) {
super.onCharacteristicChanged(gatt, characteristic) super.onCharacteristicChanged(gatt, characteristic)
val id = characteristic!!.hashCode() val nativeGATT = nativeGATTs.values.first { entry -> entry.value === gatt }
val value = ByteString.copyFrom(characteristic.value) val nativeService = nativeGATT.services.values.first { entry -> entry.value === characteristic!!.service }
val nativeCharacteristic = nativeService.characteristics.values.first { entry -> entry.value === characteristic }
val value = ByteString.copyFrom(characteristic!!.value)
val characteristicValue = GattCharacteristicValue.newBuilder() val characteristicValue = GattCharacteristicValue.newBuilder()
.setId(id) .setGattKey(nativeGATT.key)
.setServiceKey(nativeService.key)
.setKey(nativeCharacteristic.key)
.setValue(value) .setValue(value)
.build() .build()
val event = Message.newBuilder() val event = Message.newBuilder()
@ -335,26 +348,24 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler
.setCharacteristicValue(characteristicValue) .setCharacteristicValue(characteristicValue)
.build() .build()
.toByteArray() .toByteArray()
handler.post { sink?.success(event) } handler.post { events?.success(event) }
} }
override fun onDescriptorRead(gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int) { override fun onDescriptorRead(gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int) {
super.onDescriptorRead(gatt, descriptor, status) super.onDescriptorRead(gatt, descriptor, status)
val key = descriptor!!.hashCode() val read = descriptorReads.remove(descriptor)!!
val read = descriptorReads.remove(key)!!
when (status) { when (status) {
BluetoothGatt.GATT_SUCCESS -> handler.post { read.success(descriptor.value) } BluetoothGatt.GATT_SUCCESS -> handler.post { read.success(descriptor!!.value) }
else -> handler.post { read.error(status) } else -> handler.post { read.error("GATT error with status: $status", null, null) }
} }
} }
override fun onDescriptorWrite(gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int) { override fun onDescriptorWrite(gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int) {
super.onDescriptorWrite(gatt, descriptor, status) super.onDescriptorWrite(gatt, descriptor, status)
val key = descriptor!!.hashCode() val write = descriptorWrites.remove(descriptor)!!
val write = descriptorWrites.remove(key)!!
when (status) { when (status) {
BluetoothGatt.GATT_SUCCESS -> handler.post { write.success() } BluetoothGatt.GATT_SUCCESS -> handler.post { write.success() }
else -> handler.post { write.error(status) } else -> handler.post { write.error("GATT error with status: $status", null, null) }
} }
} }
} }
@ -400,8 +411,7 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
// Clear connections. // Clear connections.
for (gatt in gatts.values) gatt.close() for (nativeGATT in nativeGATTs.values) nativeGATT.value.disconnect()
gatts.clear()
// Stop scan. // Stop scan.
if (scanning) stopScan() if (scanning) stopScan()
// Unregister bluetooth adapter state receiver. // Unregister bluetooth adapter state receiver.
@ -411,37 +421,30 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler
} }
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) { override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
val category = call.category val data = call.arguments<ByteArray>()
if (category != BLUETOOTH_AVAILABLE && category != BLUETOOTH_STATE && !bluetoothAdapter.state.opened) result.error(BLUETOOTH_ADAPTER_CLOSED) val command = Message.parseFrom(data)
else when (category) { when (command.category!!) {
BLUETOOTH_AVAILABLE -> result.success(bluetoothAvailable) BLUETOOTH_STATE -> result.success(bluetoothState.number)
BLUETOOTH_STATE -> result.success(bluetoothAdapter.state.opened)
CENTRAL_START_DISCOVERY -> { CENTRAL_START_DISCOVERY -> {
val startDiscovery = Runnable {
val services = command.startDiscoveryArguments.servicesList
val startScanHandler: StartScanHandler = { code ->
when (code) {
NO_ERROR -> result.success()
else -> result.error("Discovery start failed with code: $code", null, null)
}
}
startScan(services, startScanHandler)
}
when { when {
requestPermissionsHandler != null -> result.error(INVALID_REQUEST) hasPermission -> startDiscovery.run()
else -> { else -> {
val startDiscovery = Runnable { requestPermissionsHandler = { granted ->
val data = call.arguments<ByteArray>() if (granted) startDiscovery.run()
val arguments = StartDiscoveryArguments.parseFrom(data) else result.error("Discovery start failed because `ACCESS_FINE_LOCATION` was denied by user.", null, null)
val startScanHandler: StartScanHandler = { code ->
when (code) {
NO_ERROR -> result.success()
else -> result.error(code)
}
}
startScan(arguments.servicesList, startScanHandler)
}
when {
hasPermission -> startDiscovery.run()
else -> {
requestPermissionsHandler = { granted ->
if (granted) startDiscovery.run()
else result.error(REQUEST_PERMISSION_FAILED)
}
val permissions = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION)
ActivityCompat.requestPermissions(binding!!.activity, permissions, REQUEST_CODE)
}
} }
val permissions = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION)
ActivityCompat.requestPermissions(binding!!.activity, permissions, REQUEST_CODE)
} }
} }
} }
@ -449,176 +452,92 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler
stopScan() stopScan()
result.success() result.success()
} }
CENTRAL_DISCOVERED -> result.notImplemented()
CENTRAL_CONNECT -> { CENTRAL_CONNECT -> {
val data = call.arguments<ByteArray>() val device = bluetoothAdapter.getRemoteDevice(command.connectArguments.uuid.address)
val arguments = ConnectArguments.parseFrom(data) val gatt = when {
val address = arguments.address // Use TRANSPORT_LE to avoid none flag device on Android 23 or later.
val connect = connects[address] Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> device.connectGatt(context, false, bluetoothGattCallback, BluetoothDevice.TRANSPORT_LE)
var gatt = gatts[address] else -> device.connectGatt(context, false, bluetoothGattCallback)
if (connect != null || gatt != null) {
result.error(INVALID_REQUEST)
} else {
val device = bluetoothAdapter.getRemoteDevice(address)
gatt = when {
// Use TRANSPORT_LE to avoid none flag device on Android 23 or later.
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> device.connectGatt(context, false, bluetoothGattCallback, BluetoothDevice.TRANSPORT_LE)
else -> device.connectGatt(context, false, bluetoothGattCallback)
}
connects[address] = result
gatts[address] = gatt
} }
connects[gatt] = result
} }
GATT_DISCONNECT -> { GATT_DISCONNECT -> {
val data = call.arguments<ByteArray>() val nativeGATT = nativeGATTs[command.disconnectArguments.key]!!
val arguments = GattDisconnectArguments.parseFrom(data) disconnects[nativeGATT.value] = result
val address = arguments.address nativeGATT.value.disconnect()
val disconnect = disconnects[address]
val gatt = gatts[address]
if (disconnect != null || gatt == null || gatt.hashCode() != arguments.id) {
result.error(INVALID_REQUEST)
} else {
disconnects[address] = result
gatt.disconnect()
}
} }
GATT_CONNECTION_LOST -> result.notImplemented()
GATT_CHARACTERISTIC_READ -> { GATT_CHARACTERISTIC_READ -> {
val data = call.arguments<ByteArray>() val nativeGATT = nativeGATTs[command.characteristicReadArguments.gattKey]!!
val arguments = GattCharacteristicReadArguments.parseFrom(data) val nativeService = nativeGATT.services[command.characteristicReadArguments.serviceKey]!!
val gatt = gatts[arguments.address] val nativeCharacteristic = nativeService.characteristics[command.characteristicReadArguments.key]!!
if (gatt == null) result.error(INVALID_REQUEST) val read = nativeGATT.value.readCharacteristic(nativeCharacteristic.value)
else { if (read) characteristicReads[nativeCharacteristic.value] = result
val serviceUUID = UUID.fromString(arguments.serviceUuid) else result.error("Characteristic read failed.", null, null)
val service = gatt.getService(serviceUUID)
val uuid = UUID.fromString(arguments.uuid)
val characteristic = service.getCharacteristic(uuid)
val id = characteristic.hashCode()
val characteristicRead = characteristicReads[id]
if (characteristicRead != null || id != arguments.id) result.error(INVALID_REQUEST)
else {
val failed = !gatt.readCharacteristic(characteristic)
if (failed) result.error(READ_CHARACTERISTIC_FAILED)
else characteristicReads[id] = result
}
}
} }
GATT_CHARACTERISTIC_WRITE -> { GATT_CHARACTERISTIC_WRITE -> {
val data = call.arguments<ByteArray>() val nativeGATT = nativeGATTs[command.characteristicWriteArguments.gattKey]!!
val arguments = GattCharacteristicWriteArguments.parseFrom(data) val nativeService = nativeGATT.services[command.characteristicWriteArguments.serviceKey]!!
val gatt = gatts[arguments.address] val nativeCharacteristic = nativeService.characteristics[command.characteristicWriteArguments.key]!!
if (gatt == null) result.error(INVALID_REQUEST) nativeCharacteristic.value.writeType =
else { if (command.characteristicWriteArguments.withoutResponse) BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE
val serviceUUID = UUID.fromString(arguments.serviceUuid) else BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
val service = gatt.getService(serviceUUID) nativeCharacteristic.value.value = command.characteristicWriteArguments.value.toByteArray()
val uuid = UUID.fromString(arguments.uuid) val written = nativeGATT.value.writeCharacteristic(nativeCharacteristic.value)
val characteristic = service.getCharacteristic(uuid) if (written) characteristicWrites[nativeCharacteristic.value] = result
val id = characteristic.hashCode() else result.error("Characteristic write failed.", null, null)
val characteristicWrite = characteristicWrites[id]
if (characteristicWrite != null || id != arguments.id) result.error(INVALID_REQUEST)
else {
characteristic.value = arguments.value.toByteArray()
characteristic.writeType =
if (arguments.withoutResponse) BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE
else BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
val failed = !gatt.writeCharacteristic(characteristic)
if (failed) result.error(WRITE_CHARACTERISTIC_FAILED)
else characteristicWrites[id] = result
}
}
} }
GATT_CHARACTERISTIC_NOTIFY -> { GATT_CHARACTERISTIC_NOTIFY -> {
val data = call.arguments<ByteArray>() val nativeGATT = nativeGATTs[command.characteristicNotifyArguments.gattKey]!!
val arguments = GattCharacteristicNotifyArguments.parseFrom(data) val nativeService = nativeGATT.services[command.characteristicNotifyArguments.serviceKey]!!
val gatt = gatts[arguments.address] val nativeCharacteristic = nativeService.characteristics[command.characteristicNotifyArguments.key]!!
if (gatt == null) result.error(INVALID_REQUEST) val descriptorUUID = UUID.fromString(CLIENT_CHARACTERISTIC_CONFIG)
else { val descriptor = nativeCharacteristic.value.getDescriptor(descriptorUUID)
val serviceUUID = UUID.fromString(arguments.serviceUuid) val notified = nativeGATT.value.setCharacteristicNotification(nativeCharacteristic.value, command.characteristicNotifyArguments.state)
val service = gatt.getService(serviceUUID) if (notified) {
val uuid = UUID.fromString(arguments.uuid) descriptor.value =
val characteristic = service.getCharacteristic(uuid) if (command.characteristicNotifyArguments.state) BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
val id = characteristic.hashCode() else BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE
val descriptorUUID = UUID.fromString(CLIENT_CHARACTERISTIC_CONFIG) val written = nativeGATT.value.writeDescriptor(descriptor)
val descriptor = characteristic.getDescriptor(descriptorUUID) if (written) descriptorWrites[descriptor] = result
val descriptorId = descriptor.hashCode() else result.error("Client characteristic config descriptor write failed.", null, null)
val descriptorWrite = descriptorWrites[descriptorId] } else result.error("Characteristic Notify failed.", null, null)
if (descriptorWrite != null || id != arguments.id) result.error(INVALID_REQUEST)
else {
var failed = !gatt.setCharacteristicNotification(characteristic, arguments.state)
if (failed) result.error(NOTIFY_CHARACTERISTIC_FAILED)
else {
descriptor.value =
if (arguments.state) BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
else BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE
failed = !gatt.writeDescriptor(descriptor)
if (failed) result.error(WRITE_DESCRIPTOR_FAILED)
else descriptorWrites[descriptorId] = result
}
}
}
} }
GATT_DESCRIPTOR_READ -> { GATT_DESCRIPTOR_READ -> {
val data = call.arguments<ByteArray>() val nativeGATT = nativeGATTs[command.descriptorReadArguments.gattKey]!!
val arguments = GattDescriptorReadArguments.parseFrom(data) val nativeService = nativeGATT.services[command.descriptorReadArguments.serviceKey]!!
val gatt = gatts[arguments.address] val nativeCharacteristic = nativeService.characteristics[command.descriptorReadArguments.characteristicKey]!!
if (gatt == null) result.error(INVALID_REQUEST) val nativeDescriptor = nativeCharacteristic.descriptors[command.descriptorReadArguments.key]!!
else { val read = nativeGATT.value.readDescriptor(nativeDescriptor.value)
val serviceUUID = UUID.fromString(arguments.serviceUuid) if (read) descriptorReads[nativeDescriptor.value] = result
val service = gatt.getService(serviceUUID) else result.error("Descriptor read failed.", null, null)
val characteristicUUID = UUID.fromString(arguments.characteristicUuid)
val characteristic = service.getCharacteristic(characteristicUUID)
val uuid = UUID.fromString(arguments.uuid)
val descriptor = characteristic.getDescriptor(uuid)
val id = descriptor.hashCode()
val descriptorRead = descriptorReads[id]
if (descriptorRead != null || id != arguments.id) result.error(INVALID_REQUEST)
else {
val failed = !gatt.readDescriptor(descriptor)
if (failed) result.error(READ_DESCRIPTOR_FAILED)
else descriptorReads[id] = result
}
}
} }
GATT_DESCRIPTOR_WRITE -> { GATT_DESCRIPTOR_WRITE -> {
val data = call.arguments<ByteArray>() val nativeGATT = nativeGATTs[command.descriptorWriteArguments.gattKey]!!
val arguments = GattDescriptorWriteArguments.parseFrom(data) val nativeService = nativeGATT.services[command.descriptorWriteArguments.serviceKey]!!
val gatt = gatts[arguments.address] val nativeCharacteristic = nativeService.characteristics[command.descriptorWriteArguments.characteristicKey]!!
if (gatt == null) result.error(INVALID_REQUEST) val nativeDescriptor = nativeCharacteristic.descriptors[command.descriptorWriteArguments.key]!!
else { nativeDescriptor.value.value = command.descriptorWriteArguments.value.toByteArray()
val serviceUUID = UUID.fromString(arguments.serviceUuid) val written = nativeGATT.value.writeDescriptor(nativeDescriptor.value)
val service = gatt.getService(serviceUUID) if (written) descriptorWrites[nativeDescriptor.value] = result
val characteristicUUID = UUID.fromString(arguments.characteristicUuid) else result.error("Descriptor write failed.", null, null)
val characteristic = service.getCharacteristic(characteristicUUID)
val uuid = UUID.fromString(arguments.uuid)
val descriptor = characteristic.getDescriptor(uuid)
val id = descriptor.hashCode()
val descriptorWrite = descriptorWrites[id]
if (descriptorWrite != null || id != arguments.id) result.error(INVALID_REQUEST)
else {
val failed = !gatt.writeDescriptor(descriptor)
if (failed) result.error(WRITE_DESCRIPTOR_FAILED)
else descriptorWrites[id] = result
}
}
} }
UNRECOGNIZED -> result.notImplemented() else -> result.notImplemented()
} }
} }
override fun onListen(arguments: Any?, sink: EventSink?) { override fun onListen(arguments: Any?, events: EventSink?) {
Log.d(TAG, "onListen") Log.d(TAG, "onListen")
this.sink = sink this.events = events
} }
override fun onCancel(arguments: Any?) { override fun onCancel(arguments: Any?) {
Log.d(TAG, "onCancel") Log.d(TAG, "onCancel")
// This must be a hot reload for now, clear all status here. // This must be a hot reload for now, clear all status here.
// Clear connections. // Clear connections.
for (gatt in gatts.values) gatt.close() for (nativeGATT in nativeGATTs.values) nativeGATT.value.disconnect()
gatts.clear()
// Stop scan. // Stop scan.
if (scanning) stopScan() if (scanning) stopScan()
sink = null events = null
} }
override fun onAttachedToActivity(binding: ActivityPluginBinding) { override fun onAttachedToActivity(binding: ActivityPluginBinding) {
@ -639,11 +558,7 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler
onDetachedFromActivity() onDetachedFromActivity()
} }
override fun onRequestPermissionsResult( override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>?, grantResults: IntArray?): Boolean {
requestCode: Int,
permissions: Array<out String>?,
grantResults: IntArray?
): Boolean {
return when { return when {
requestCode != REQUEST_CODE || requestPermissionsHandler == null -> false requestCode != REQUEST_CODE || requestPermissionsHandler == null -> false
else -> { else -> {
@ -657,25 +572,28 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler
} }
} }
val Any.TAG: String
get() = this::class.java.simpleName
fun Result.success() { fun Result.success() {
success(null) success(null)
} }
fun Result.error(code: Int, message: String? = null, details: String? = null) { val Int.messageState: BluetoothState
error("$code", message, details)
}
val Any.TAG: String
get() = this::class.java.simpleName
val MethodCall.category: MessageCategory
get() = valueOf(method)
val Int.opened: Boolean
get() = when (this) { get() = when (this) {
BluetoothAdapter.STATE_OFF -> false BluetoothAdapter.STATE_OFF -> BluetoothState.POWERED_OFF
BluetoothAdapter.STATE_TURNING_ON -> false BluetoothAdapter.STATE_TURNING_ON -> BluetoothState.POWERED_OFF
BluetoothAdapter.STATE_ON -> true BluetoothAdapter.STATE_ON -> BluetoothState.POWERED_ON
BluetoothAdapter.STATE_TURNING_OFF -> true BluetoothAdapter.STATE_TURNING_OFF -> BluetoothState.POWERED_ON
else -> false else -> BluetoothState.UNRECOGNIZED
} }
val BluetoothDevice.uuid: String
get() {
val node = address.filter { char -> char != ':' }.lowercase()
// We don't known the timestamp of the bluetooth device, use nil UUID as prefix.
return "00000000-0000-0000-0000-$node"
}
val String.address: String
get() = takeLast(12).chunked(2).joinToString(":").uppercase()

View File

@ -23,20 +23,20 @@ object ConnectArgumentsKt {
internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.ConnectArguments = _builder.build() internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.ConnectArguments = _builder.build()
/** /**
* <code>string address = 1;</code> * <code>string uuid = 1;</code>
*/ */
var address: kotlin.String var uuid: kotlin.String
@JvmName("getAddress") @JvmName("getUuid")
get() = _builder.getAddress() get() = _builder.getUuid()
@JvmName("setAddress") @JvmName("setUuid")
set(value) { set(value) {
_builder.setAddress(value) _builder.setUuid(value)
} }
/** /**
* <code>string address = 1;</code> * <code>string uuid = 1;</code>
*/ */
fun clearAddress() { fun clearUuid() {
_builder.clearAddress() _builder.clearUuid()
} }
} }
} }

View File

@ -1,62 +0,0 @@
//Generated by the protocol buffer compiler. DO NOT EDIT!
// source: message.proto
package dev.yanshouwang.bluetooth_low_energy;
@kotlin.jvm.JvmSynthetic
inline fun connectionLost(block: dev.yanshouwang.bluetooth_low_energy.ConnectionLostKt.Dsl.() -> Unit): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.ConnectionLost =
dev.yanshouwang.bluetooth_low_energy.ConnectionLostKt.Dsl._create(dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.ConnectionLost.newBuilder()).apply { block() }._build()
object ConnectionLostKt {
@kotlin.OptIn(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)
@com.google.protobuf.kotlin.ProtoDslMarker
class Dsl private constructor(
@kotlin.jvm.JvmField private val _builder: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.ConnectionLost.Builder
) {
companion object {
@kotlin.jvm.JvmSynthetic
@kotlin.PublishedApi
internal fun _create(builder: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.ConnectionLost.Builder): Dsl = Dsl(builder)
}
@kotlin.jvm.JvmSynthetic
@kotlin.PublishedApi
internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.ConnectionLost = _builder.build()
/**
* <code>int32 id = 1;</code>
*/
var id: kotlin.Int
@JvmName("getId")
get() = _builder.getId()
@JvmName("setId")
set(value) {
_builder.setId(value)
}
/**
* <code>int32 id = 1;</code>
*/
fun clearId() {
_builder.clearId()
}
/**
* <code>int32 error_code = 2;</code>
*/
var errorCode: kotlin.Int
@JvmName("getErrorCode")
get() = _builder.getErrorCode()
@JvmName("setErrorCode")
set(value) {
_builder.setErrorCode(value)
}
/**
* <code>int32 error_code = 2;</code>
*/
fun clearErrorCode() {
_builder.clearErrorCode()
}
}
}
@kotlin.jvm.JvmSynthetic
inline fun dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.ConnectionLost.copy(block: dev.yanshouwang.bluetooth_low_energy.ConnectionLostKt.Dsl.() -> Unit): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.ConnectionLost =
dev.yanshouwang.bluetooth_low_energy.ConnectionLostKt.Dsl._create(this.toBuilder()).apply { block() }._build()

View File

@ -23,20 +23,20 @@ object DiscoveryKt {
internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.Discovery = _builder.build() internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.Discovery = _builder.build()
/** /**
* <code>string address = 1;</code> * <code>string uuid = 1;</code>
*/ */
var address: kotlin.String var uuid: kotlin.String
@JvmName("getAddress") @JvmName("getUuid")
get() = _builder.getAddress() get() = _builder.getUuid()
@JvmName("setAddress") @JvmName("setUuid")
set(value) { set(value) {
_builder.setAddress(value) _builder.setUuid(value)
} }
/** /**
* <code>string address = 1;</code> * <code>string uuid = 1;</code>
*/ */
fun clearAddress() { fun clearUuid() {
_builder.clearAddress() _builder.clearUuid()
} }
/** /**
@ -72,6 +72,23 @@ object DiscoveryKt {
fun clearAdvertisements() { fun clearAdvertisements() {
_builder.clearAdvertisements() _builder.clearAdvertisements()
} }
/**
* <code>bool connectable = 4;</code>
*/
var connectable: kotlin.Boolean
@JvmName("getConnectable")
get() = _builder.getConnectable()
@JvmName("setConnectable")
set(value) {
_builder.setConnectable(value)
}
/**
* <code>bool connectable = 4;</code>
*/
fun clearConnectable() {
_builder.clearConnectable()
}
} }
} }
@kotlin.jvm.JvmSynthetic @kotlin.jvm.JvmSynthetic

View File

@ -23,37 +23,37 @@ object GATTKt {
internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GATT = _builder.build() internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GATT = _builder.build()
/** /**
* <code>int32 id = 1;</code> * <code>string key = 1;</code>
*/ */
var id: kotlin.Int var key: kotlin.String
@JvmName("getId") @JvmName("getKey")
get() = _builder.getId() get() = _builder.getKey()
@JvmName("setId") @JvmName("setKey")
set(value) { set(value) {
_builder.setId(value) _builder.setKey(value)
} }
/** /**
* <code>int32 id = 1;</code> * <code>string key = 1;</code>
*/ */
fun clearId() { fun clearKey() {
_builder.clearId() _builder.clearKey()
} }
/** /**
* <code>int32 mtu = 2;</code> * <code>int32 maximumWriteLength = 2;</code>
*/ */
var mtu: kotlin.Int var maximumWriteLength: kotlin.Int
@JvmName("getMtu") @JvmName("getMaximumWriteLength")
get() = _builder.getMtu() get() = _builder.getMaximumWriteLength()
@JvmName("setMtu") @JvmName("setMaximumWriteLength")
set(value) { set(value) {
_builder.setMtu(value) _builder.setMaximumWriteLength(value)
} }
/** /**
* <code>int32 mtu = 2;</code> * <code>int32 maximumWriteLength = 2;</code>
*/ */
fun clearMtu() { fun clearMaximumWriteLength() {
_builder.clearMtu() _builder.clearMaximumWriteLength()
} }
/** /**

View File

@ -23,20 +23,20 @@ object GattCharacteristicKt {
internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattCharacteristic = _builder.build() internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattCharacteristic = _builder.build()
/** /**
* <code>int32 id = 1;</code> * <code>string key = 1;</code>
*/ */
var id: kotlin.Int var key: kotlin.String
@JvmName("getId") @JvmName("getKey")
get() = _builder.getId() get() = _builder.getKey()
@JvmName("setId") @JvmName("setKey")
set(value) { set(value) {
_builder.setId(value) _builder.setKey(value)
} }
/** /**
* <code>int32 id = 1;</code> * <code>string key = 1;</code>
*/ */
fun clearId() { fun clearKey() {
_builder.clearId() _builder.clearKey()
} }
/** /**
@ -57,70 +57,7 @@ object GattCharacteristicKt {
} }
/** /**
* An uninstantiable, behaviorless type to represent the field in * <code>bool canRead = 3;</code>
* generics.
*/
@kotlin.OptIn(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)
class DescriptorsProxy private constructor() : com.google.protobuf.kotlin.DslProxy()
/**
* <code>repeated .dev.yanshouwang.bluetooth_low_energy.GattDescriptor descriptors = 3;</code>
*/
val descriptors: com.google.protobuf.kotlin.DslList<dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor, DescriptorsProxy>
@kotlin.jvm.JvmSynthetic
get() = com.google.protobuf.kotlin.DslList(
_builder.getDescriptorsList()
)
/**
* <code>repeated .dev.yanshouwang.bluetooth_low_energy.GattDescriptor descriptors = 3;</code>
* @param value The descriptors to add.
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("addDescriptors")
fun com.google.protobuf.kotlin.DslList<dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor, DescriptorsProxy>.add(value: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor) {
_builder.addDescriptors(value)
}/**
* <code>repeated .dev.yanshouwang.bluetooth_low_energy.GattDescriptor descriptors = 3;</code>
* @param value The descriptors to add.
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("plusAssignDescriptors")
inline operator fun com.google.protobuf.kotlin.DslList<dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor, DescriptorsProxy>.plusAssign(value: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor) {
add(value)
}/**
* <code>repeated .dev.yanshouwang.bluetooth_low_energy.GattDescriptor descriptors = 3;</code>
* @param values The descriptors to add.
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("addAllDescriptors")
fun com.google.protobuf.kotlin.DslList<dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor, DescriptorsProxy>.addAll(values: kotlin.collections.Iterable<dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor>) {
_builder.addAllDescriptors(values)
}/**
* <code>repeated .dev.yanshouwang.bluetooth_low_energy.GattDescriptor descriptors = 3;</code>
* @param values The descriptors to add.
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("plusAssignAllDescriptors")
inline operator fun com.google.protobuf.kotlin.DslList<dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor, DescriptorsProxy>.plusAssign(values: kotlin.collections.Iterable<dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor>) {
addAll(values)
}/**
* <code>repeated .dev.yanshouwang.bluetooth_low_energy.GattDescriptor descriptors = 3;</code>
* @param index The index to set the value at.
* @param value The descriptors to set.
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("setDescriptors")
operator fun com.google.protobuf.kotlin.DslList<dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor, DescriptorsProxy>.set(index: kotlin.Int, value: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor) {
_builder.setDescriptors(index, value)
}/**
* <code>repeated .dev.yanshouwang.bluetooth_low_energy.GattDescriptor descriptors = 3;</code>
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("clearDescriptors")
fun com.google.protobuf.kotlin.DslList<dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor, DescriptorsProxy>.clear() {
_builder.clearDescriptors()
}
/**
* <code>bool canRead = 4;</code>
*/ */
var canRead: kotlin.Boolean var canRead: kotlin.Boolean
@JvmName("getCanRead") @JvmName("getCanRead")
@ -130,14 +67,14 @@ object GattCharacteristicKt {
_builder.setCanRead(value) _builder.setCanRead(value)
} }
/** /**
* <code>bool canRead = 4;</code> * <code>bool canRead = 3;</code>
*/ */
fun clearCanRead() { fun clearCanRead() {
_builder.clearCanRead() _builder.clearCanRead()
} }
/** /**
* <code>bool canWrite = 5;</code> * <code>bool canWrite = 4;</code>
*/ */
var canWrite: kotlin.Boolean var canWrite: kotlin.Boolean
@JvmName("getCanWrite") @JvmName("getCanWrite")
@ -147,14 +84,14 @@ object GattCharacteristicKt {
_builder.setCanWrite(value) _builder.setCanWrite(value)
} }
/** /**
* <code>bool canWrite = 5;</code> * <code>bool canWrite = 4;</code>
*/ */
fun clearCanWrite() { fun clearCanWrite() {
_builder.clearCanWrite() _builder.clearCanWrite()
} }
/** /**
* <code>bool canWriteWithoutResponse = 6;</code> * <code>bool canWriteWithoutResponse = 5;</code>
*/ */
var canWriteWithoutResponse: kotlin.Boolean var canWriteWithoutResponse: kotlin.Boolean
@JvmName("getCanWriteWithoutResponse") @JvmName("getCanWriteWithoutResponse")
@ -164,14 +101,14 @@ object GattCharacteristicKt {
_builder.setCanWriteWithoutResponse(value) _builder.setCanWriteWithoutResponse(value)
} }
/** /**
* <code>bool canWriteWithoutResponse = 6;</code> * <code>bool canWriteWithoutResponse = 5;</code>
*/ */
fun clearCanWriteWithoutResponse() { fun clearCanWriteWithoutResponse() {
_builder.clearCanWriteWithoutResponse() _builder.clearCanWriteWithoutResponse()
} }
/** /**
* <code>bool canNotify = 7;</code> * <code>bool canNotify = 6;</code>
*/ */
var canNotify: kotlin.Boolean var canNotify: kotlin.Boolean
@JvmName("getCanNotify") @JvmName("getCanNotify")
@ -181,12 +118,75 @@ object GattCharacteristicKt {
_builder.setCanNotify(value) _builder.setCanNotify(value)
} }
/** /**
* <code>bool canNotify = 7;</code> * <code>bool canNotify = 6;</code>
*/ */
fun clearCanNotify() { fun clearCanNotify() {
_builder.clearCanNotify() _builder.clearCanNotify()
} }
}
/**
* An uninstantiable, behaviorless type to represent the field in
* generics.
*/
@kotlin.OptIn(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)
class DescriptorsProxy private constructor() : com.google.protobuf.kotlin.DslProxy()
/**
* <code>repeated .dev.yanshouwang.bluetooth_low_energy.GattDescriptor descriptors = 7;</code>
*/
val descriptors: com.google.protobuf.kotlin.DslList<dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor, DescriptorsProxy>
@kotlin.jvm.JvmSynthetic
get() = com.google.protobuf.kotlin.DslList(
_builder.getDescriptorsList()
)
/**
* <code>repeated .dev.yanshouwang.bluetooth_low_energy.GattDescriptor descriptors = 7;</code>
* @param value The descriptors to add.
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("addDescriptors")
fun com.google.protobuf.kotlin.DslList<dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor, DescriptorsProxy>.add(value: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor) {
_builder.addDescriptors(value)
}/**
* <code>repeated .dev.yanshouwang.bluetooth_low_energy.GattDescriptor descriptors = 7;</code>
* @param value The descriptors to add.
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("plusAssignDescriptors")
inline operator fun com.google.protobuf.kotlin.DslList<dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor, DescriptorsProxy>.plusAssign(value: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor) {
add(value)
}/**
* <code>repeated .dev.yanshouwang.bluetooth_low_energy.GattDescriptor descriptors = 7;</code>
* @param values The descriptors to add.
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("addAllDescriptors")
fun com.google.protobuf.kotlin.DslList<dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor, DescriptorsProxy>.addAll(values: kotlin.collections.Iterable<dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor>) {
_builder.addAllDescriptors(values)
}/**
* <code>repeated .dev.yanshouwang.bluetooth_low_energy.GattDescriptor descriptors = 7;</code>
* @param values The descriptors to add.
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("plusAssignAllDescriptors")
inline operator fun com.google.protobuf.kotlin.DslList<dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor, DescriptorsProxy>.plusAssign(values: kotlin.collections.Iterable<dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor>) {
addAll(values)
}/**
* <code>repeated .dev.yanshouwang.bluetooth_low_energy.GattDescriptor descriptors = 7;</code>
* @param index The index to set the value at.
* @param value The descriptors to set.
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("setDescriptors")
operator fun com.google.protobuf.kotlin.DslList<dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor, DescriptorsProxy>.set(index: kotlin.Int, value: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor) {
_builder.setDescriptors(index, value)
}/**
* <code>repeated .dev.yanshouwang.bluetooth_low_energy.GattDescriptor descriptors = 7;</code>
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("clearDescriptors")
fun com.google.protobuf.kotlin.DslList<dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor, DescriptorsProxy>.clear() {
_builder.clearDescriptors()
}}
} }
@kotlin.jvm.JvmSynthetic @kotlin.jvm.JvmSynthetic
inline fun dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattCharacteristic.copy(block: dev.yanshouwang.bluetooth_low_energy.GattCharacteristicKt.Dsl.() -> Unit): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattCharacteristic = inline fun dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattCharacteristic.copy(block: dev.yanshouwang.bluetooth_low_energy.GattCharacteristicKt.Dsl.() -> Unit): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattCharacteristic =

View File

@ -23,75 +23,58 @@ object GattCharacteristicNotifyArgumentsKt {
internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattCharacteristicNotifyArguments = _builder.build() internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattCharacteristicNotifyArguments = _builder.build()
/** /**
* <code>string address = 1;</code> * <code>string gatt_key = 1;</code>
*/ */
var address: kotlin.String var gattKey: kotlin.String
@JvmName("getAddress") @JvmName("getGattKey")
get() = _builder.getAddress() get() = _builder.getGattKey()
@JvmName("setAddress") @JvmName("setGattKey")
set(value) { set(value) {
_builder.setAddress(value) _builder.setGattKey(value)
} }
/** /**
* <code>string address = 1;</code> * <code>string gatt_key = 1;</code>
*/ */
fun clearAddress() { fun clearGattKey() {
_builder.clearAddress() _builder.clearGattKey()
} }
/** /**
* <code>string service_uuid = 2;</code> * <code>string service_key = 2;</code>
*/ */
var serviceUuid: kotlin.String var serviceKey: kotlin.String
@JvmName("getServiceUuid") @JvmName("getServiceKey")
get() = _builder.getServiceUuid() get() = _builder.getServiceKey()
@JvmName("setServiceUuid") @JvmName("setServiceKey")
set(value) { set(value) {
_builder.setServiceUuid(value) _builder.setServiceKey(value)
} }
/** /**
* <code>string service_uuid = 2;</code> * <code>string service_key = 2;</code>
*/ */
fun clearServiceUuid() { fun clearServiceKey() {
_builder.clearServiceUuid() _builder.clearServiceKey()
} }
/** /**
* <code>string uuid = 3;</code> * <code>string key = 3;</code>
*/ */
var uuid: kotlin.String var key: kotlin.String
@JvmName("getUuid") @JvmName("getKey")
get() = _builder.getUuid() get() = _builder.getKey()
@JvmName("setUuid") @JvmName("setKey")
set(value) { set(value) {
_builder.setUuid(value) _builder.setKey(value)
} }
/** /**
* <code>string uuid = 3;</code> * <code>string key = 3;</code>
*/ */
fun clearUuid() { fun clearKey() {
_builder.clearUuid() _builder.clearKey()
} }
/** /**
* <code>int32 id = 4;</code> * <code>bool state = 4;</code>
*/
var id: kotlin.Int
@JvmName("getId")
get() = _builder.getId()
@JvmName("setId")
set(value) {
_builder.setId(value)
}
/**
* <code>int32 id = 4;</code>
*/
fun clearId() {
_builder.clearId()
}
/**
* <code>bool state = 5;</code>
*/ */
var state: kotlin.Boolean var state: kotlin.Boolean
@JvmName("getState") @JvmName("getState")
@ -101,7 +84,7 @@ object GattCharacteristicNotifyArgumentsKt {
_builder.setState(value) _builder.setState(value)
} }
/** /**
* <code>bool state = 5;</code> * <code>bool state = 4;</code>
*/ */
fun clearState() { fun clearState() {
_builder.clearState() _builder.clearState()

View File

@ -23,71 +23,54 @@ object GattCharacteristicReadArgumentsKt {
internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattCharacteristicReadArguments = _builder.build() internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattCharacteristicReadArguments = _builder.build()
/** /**
* <code>string address = 1;</code> * <code>string gatt_key = 1;</code>
*/ */
var address: kotlin.String var gattKey: kotlin.String
@JvmName("getAddress") @JvmName("getGattKey")
get() = _builder.getAddress() get() = _builder.getGattKey()
@JvmName("setAddress") @JvmName("setGattKey")
set(value) { set(value) {
_builder.setAddress(value) _builder.setGattKey(value)
} }
/** /**
* <code>string address = 1;</code> * <code>string gatt_key = 1;</code>
*/ */
fun clearAddress() { fun clearGattKey() {
_builder.clearAddress() _builder.clearGattKey()
} }
/** /**
* <code>string service_uuid = 2;</code> * <code>string service_key = 2;</code>
*/ */
var serviceUuid: kotlin.String var serviceKey: kotlin.String
@JvmName("getServiceUuid") @JvmName("getServiceKey")
get() = _builder.getServiceUuid() get() = _builder.getServiceKey()
@JvmName("setServiceUuid") @JvmName("setServiceKey")
set(value) { set(value) {
_builder.setServiceUuid(value) _builder.setServiceKey(value)
} }
/** /**
* <code>string service_uuid = 2;</code> * <code>string service_key = 2;</code>
*/ */
fun clearServiceUuid() { fun clearServiceKey() {
_builder.clearServiceUuid() _builder.clearServiceKey()
} }
/** /**
* <code>string uuid = 3;</code> * <code>string key = 3;</code>
*/ */
var uuid: kotlin.String var key: kotlin.String
@JvmName("getUuid") @JvmName("getKey")
get() = _builder.getUuid() get() = _builder.getKey()
@JvmName("setUuid") @JvmName("setKey")
set(value) { set(value) {
_builder.setUuid(value) _builder.setKey(value)
} }
/** /**
* <code>string uuid = 3;</code> * <code>string key = 3;</code>
*/ */
fun clearUuid() { fun clearKey() {
_builder.clearUuid() _builder.clearKey()
}
/**
* <code>int32 id = 4;</code>
*/
var id: kotlin.Int
@JvmName("getId")
get() = _builder.getId()
@JvmName("setId")
set(value) {
_builder.setId(value)
}
/**
* <code>int32 id = 4;</code>
*/
fun clearId() {
_builder.clearId()
} }
} }
} }

View File

@ -23,20 +23,54 @@ object GattCharacteristicValueKt {
internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattCharacteristicValue = _builder.build() internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattCharacteristicValue = _builder.build()
/** /**
* <code>int32 id = 3;</code> * <code>string gatt_key = 1;</code>
*/ */
var id: kotlin.Int var gattKey: kotlin.String
@JvmName("getId") @JvmName("getGattKey")
get() = _builder.getId() get() = _builder.getGattKey()
@JvmName("setId") @JvmName("setGattKey")
set(value) { set(value) {
_builder.setId(value) _builder.setGattKey(value)
} }
/** /**
* <code>int32 id = 3;</code> * <code>string gatt_key = 1;</code>
*/ */
fun clearId() { fun clearGattKey() {
_builder.clearId() _builder.clearGattKey()
}
/**
* <code>string service_key = 2;</code>
*/
var serviceKey: kotlin.String
@JvmName("getServiceKey")
get() = _builder.getServiceKey()
@JvmName("setServiceKey")
set(value) {
_builder.setServiceKey(value)
}
/**
* <code>string service_key = 2;</code>
*/
fun clearServiceKey() {
_builder.clearServiceKey()
}
/**
* <code>string key = 3;</code>
*/
var key: kotlin.String
@JvmName("getKey")
get() = _builder.getKey()
@JvmName("setKey")
set(value) {
_builder.setKey(value)
}
/**
* <code>string key = 3;</code>
*/
fun clearKey() {
_builder.clearKey()
} }
/** /**

View File

@ -23,75 +23,58 @@ object GattCharacteristicWriteArgumentsKt {
internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattCharacteristicWriteArguments = _builder.build() internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattCharacteristicWriteArguments = _builder.build()
/** /**
* <code>string address = 1;</code> * <code>string gatt_key = 1;</code>
*/ */
var address: kotlin.String var gattKey: kotlin.String
@JvmName("getAddress") @JvmName("getGattKey")
get() = _builder.getAddress() get() = _builder.getGattKey()
@JvmName("setAddress") @JvmName("setGattKey")
set(value) { set(value) {
_builder.setAddress(value) _builder.setGattKey(value)
} }
/** /**
* <code>string address = 1;</code> * <code>string gatt_key = 1;</code>
*/ */
fun clearAddress() { fun clearGattKey() {
_builder.clearAddress() _builder.clearGattKey()
} }
/** /**
* <code>string service_uuid = 2;</code> * <code>string service_key = 2;</code>
*/ */
var serviceUuid: kotlin.String var serviceKey: kotlin.String
@JvmName("getServiceUuid") @JvmName("getServiceKey")
get() = _builder.getServiceUuid() get() = _builder.getServiceKey()
@JvmName("setServiceUuid") @JvmName("setServiceKey")
set(value) { set(value) {
_builder.setServiceUuid(value) _builder.setServiceKey(value)
} }
/** /**
* <code>string service_uuid = 2;</code> * <code>string service_key = 2;</code>
*/ */
fun clearServiceUuid() { fun clearServiceKey() {
_builder.clearServiceUuid() _builder.clearServiceKey()
} }
/** /**
* <code>string uuid = 3;</code> * <code>string key = 3;</code>
*/ */
var uuid: kotlin.String var key: kotlin.String
@JvmName("getUuid") @JvmName("getKey")
get() = _builder.getUuid() get() = _builder.getKey()
@JvmName("setUuid") @JvmName("setKey")
set(value) { set(value) {
_builder.setUuid(value) _builder.setKey(value)
} }
/** /**
* <code>string uuid = 3;</code> * <code>string key = 3;</code>
*/ */
fun clearUuid() { fun clearKey() {
_builder.clearUuid() _builder.clearKey()
} }
/** /**
* <code>int32 id = 4;</code> * <code>bytes value = 4;</code>
*/
var id: kotlin.Int
@JvmName("getId")
get() = _builder.getId()
@JvmName("setId")
set(value) {
_builder.setId(value)
}
/**
* <code>int32 id = 4;</code>
*/
fun clearId() {
_builder.clearId()
}
/**
* <code>bytes value = 5;</code>
*/ */
var value: com.google.protobuf.ByteString var value: com.google.protobuf.ByteString
@JvmName("getValue") @JvmName("getValue")
@ -101,14 +84,14 @@ object GattCharacteristicWriteArgumentsKt {
_builder.setValue(value) _builder.setValue(value)
} }
/** /**
* <code>bytes value = 5;</code> * <code>bytes value = 4;</code>
*/ */
fun clearValue() { fun clearValue() {
_builder.clearValue() _builder.clearValue()
} }
/** /**
* <code>bool withoutResponse = 6;</code> * <code>bool withoutResponse = 5;</code>
*/ */
var withoutResponse: kotlin.Boolean var withoutResponse: kotlin.Boolean
@JvmName("getWithoutResponse") @JvmName("getWithoutResponse")
@ -118,7 +101,7 @@ object GattCharacteristicWriteArgumentsKt {
_builder.setWithoutResponse(value) _builder.setWithoutResponse(value)
} }
/** /**
* <code>bool withoutResponse = 6;</code> * <code>bool withoutResponse = 5;</code>
*/ */
fun clearWithoutResponse() { fun clearWithoutResponse() {
_builder.clearWithoutResponse() _builder.clearWithoutResponse()

View File

@ -0,0 +1,62 @@
//Generated by the protocol buffer compiler. DO NOT EDIT!
// source: message.proto
package dev.yanshouwang.bluetooth_low_energy;
@kotlin.jvm.JvmSynthetic
inline fun gattConnectionLost(block: dev.yanshouwang.bluetooth_low_energy.GattConnectionLostKt.Dsl.() -> Unit): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattConnectionLost =
dev.yanshouwang.bluetooth_low_energy.GattConnectionLostKt.Dsl._create(dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattConnectionLost.newBuilder()).apply { block() }._build()
object GattConnectionLostKt {
@kotlin.OptIn(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)
@com.google.protobuf.kotlin.ProtoDslMarker
class Dsl private constructor(
@kotlin.jvm.JvmField private val _builder: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattConnectionLost.Builder
) {
companion object {
@kotlin.jvm.JvmSynthetic
@kotlin.PublishedApi
internal fun _create(builder: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattConnectionLost.Builder): Dsl = Dsl(builder)
}
@kotlin.jvm.JvmSynthetic
@kotlin.PublishedApi
internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattConnectionLost = _builder.build()
/**
* <code>string key = 1;</code>
*/
var key: kotlin.String
@JvmName("getKey")
get() = _builder.getKey()
@JvmName("setKey")
set(value) {
_builder.setKey(value)
}
/**
* <code>string key = 1;</code>
*/
fun clearKey() {
_builder.clearKey()
}
/**
* <code>string error = 2;</code>
*/
var error: kotlin.String
@JvmName("getError")
get() = _builder.getError()
@JvmName("setError")
set(value) {
_builder.setError(value)
}
/**
* <code>string error = 2;</code>
*/
fun clearError() {
_builder.clearError()
}
}
}
@kotlin.jvm.JvmSynthetic
inline fun dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattConnectionLost.copy(block: dev.yanshouwang.bluetooth_low_energy.GattConnectionLostKt.Dsl.() -> Unit): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattConnectionLost =
dev.yanshouwang.bluetooth_low_energy.GattConnectionLostKt.Dsl._create(this.toBuilder()).apply { block() }._build()

View File

@ -23,20 +23,20 @@ object GattDescriptorKt {
internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor = _builder.build() internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptor = _builder.build()
/** /**
* <code>int32 id = 1;</code> * <code>string key = 1;</code>
*/ */
var id: kotlin.Int var key: kotlin.String
@JvmName("getId") @JvmName("getKey")
get() = _builder.getId() get() = _builder.getKey()
@JvmName("setId") @JvmName("setKey")
set(value) { set(value) {
_builder.setId(value) _builder.setKey(value)
} }
/** /**
* <code>int32 id = 1;</code> * <code>string key = 1;</code>
*/ */
fun clearId() { fun clearKey() {
_builder.clearId() _builder.clearKey()
} }
/** /**

View File

@ -23,88 +23,71 @@ object GattDescriptorReadArgumentsKt {
internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptorReadArguments = _builder.build() internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptorReadArguments = _builder.build()
/** /**
* <code>string address = 1;</code> * <code>string gatt_key = 1;</code>
*/ */
var address: kotlin.String var gattKey: kotlin.String
@JvmName("getAddress") @JvmName("getGattKey")
get() = _builder.getAddress() get() = _builder.getGattKey()
@JvmName("setAddress") @JvmName("setGattKey")
set(value) { set(value) {
_builder.setAddress(value) _builder.setGattKey(value)
} }
/** /**
* <code>string address = 1;</code> * <code>string gatt_key = 1;</code>
*/ */
fun clearAddress() { fun clearGattKey() {
_builder.clearAddress() _builder.clearGattKey()
} }
/** /**
* <code>string service_uuid = 2;</code> * <code>string service_key = 2;</code>
*/ */
var serviceUuid: kotlin.String var serviceKey: kotlin.String
@JvmName("getServiceUuid") @JvmName("getServiceKey")
get() = _builder.getServiceUuid() get() = _builder.getServiceKey()
@JvmName("setServiceUuid") @JvmName("setServiceKey")
set(value) { set(value) {
_builder.setServiceUuid(value) _builder.setServiceKey(value)
} }
/** /**
* <code>string service_uuid = 2;</code> * <code>string service_key = 2;</code>
*/ */
fun clearServiceUuid() { fun clearServiceKey() {
_builder.clearServiceUuid() _builder.clearServiceKey()
} }
/** /**
* <code>string characteristic_uuid = 3;</code> * <code>string characteristic_key = 3;</code>
*/ */
var characteristicUuid: kotlin.String var characteristicKey: kotlin.String
@JvmName("getCharacteristicUuid") @JvmName("getCharacteristicKey")
get() = _builder.getCharacteristicUuid() get() = _builder.getCharacteristicKey()
@JvmName("setCharacteristicUuid") @JvmName("setCharacteristicKey")
set(value) { set(value) {
_builder.setCharacteristicUuid(value) _builder.setCharacteristicKey(value)
} }
/** /**
* <code>string characteristic_uuid = 3;</code> * <code>string characteristic_key = 3;</code>
*/ */
fun clearCharacteristicUuid() { fun clearCharacteristicKey() {
_builder.clearCharacteristicUuid() _builder.clearCharacteristicKey()
} }
/** /**
* <code>string uuid = 4;</code> * <code>string key = 4;</code>
*/ */
var uuid: kotlin.String var key: kotlin.String
@JvmName("getUuid") @JvmName("getKey")
get() = _builder.getUuid() get() = _builder.getKey()
@JvmName("setUuid") @JvmName("setKey")
set(value) { set(value) {
_builder.setUuid(value) _builder.setKey(value)
} }
/** /**
* <code>string uuid = 4;</code> * <code>string key = 4;</code>
*/ */
fun clearUuid() { fun clearKey() {
_builder.clearUuid() _builder.clearKey()
}
/**
* <code>int32 id = 5;</code>
*/
var id: kotlin.Int
@JvmName("getId")
get() = _builder.getId()
@JvmName("setId")
set(value) {
_builder.setId(value)
}
/**
* <code>int32 id = 5;</code>
*/
fun clearId() {
_builder.clearId()
} }
} }
} }

View File

@ -23,92 +23,75 @@ object GattDescriptorWriteArgumentsKt {
internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptorWriteArguments = _builder.build() internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptorWriteArguments = _builder.build()
/** /**
* <code>string address = 1;</code> * <code>string gatt_key = 1;</code>
*/ */
var address: kotlin.String var gattKey: kotlin.String
@JvmName("getAddress") @JvmName("getGattKey")
get() = _builder.getAddress() get() = _builder.getGattKey()
@JvmName("setAddress") @JvmName("setGattKey")
set(value) { set(value) {
_builder.setAddress(value) _builder.setGattKey(value)
} }
/** /**
* <code>string address = 1;</code> * <code>string gatt_key = 1;</code>
*/ */
fun clearAddress() { fun clearGattKey() {
_builder.clearAddress() _builder.clearGattKey()
} }
/** /**
* <code>string service_uuid = 2;</code> * <code>string service_key = 2;</code>
*/ */
var serviceUuid: kotlin.String var serviceKey: kotlin.String
@JvmName("getServiceUuid") @JvmName("getServiceKey")
get() = _builder.getServiceUuid() get() = _builder.getServiceKey()
@JvmName("setServiceUuid") @JvmName("setServiceKey")
set(value) { set(value) {
_builder.setServiceUuid(value) _builder.setServiceKey(value)
} }
/** /**
* <code>string service_uuid = 2;</code> * <code>string service_key = 2;</code>
*/ */
fun clearServiceUuid() { fun clearServiceKey() {
_builder.clearServiceUuid() _builder.clearServiceKey()
} }
/** /**
* <code>string characteristic_uuid = 3;</code> * <code>string characteristic_key = 3;</code>
*/ */
var characteristicUuid: kotlin.String var characteristicKey: kotlin.String
@JvmName("getCharacteristicUuid") @JvmName("getCharacteristicKey")
get() = _builder.getCharacteristicUuid() get() = _builder.getCharacteristicKey()
@JvmName("setCharacteristicUuid") @JvmName("setCharacteristicKey")
set(value) { set(value) {
_builder.setCharacteristicUuid(value) _builder.setCharacteristicKey(value)
} }
/** /**
* <code>string characteristic_uuid = 3;</code> * <code>string characteristic_key = 3;</code>
*/ */
fun clearCharacteristicUuid() { fun clearCharacteristicKey() {
_builder.clearCharacteristicUuid() _builder.clearCharacteristicKey()
} }
/** /**
* <code>string uuid = 4;</code> * <code>string key = 4;</code>
*/ */
var uuid: kotlin.String var key: kotlin.String
@JvmName("getUuid") @JvmName("getKey")
get() = _builder.getUuid() get() = _builder.getKey()
@JvmName("setUuid") @JvmName("setKey")
set(value) { set(value) {
_builder.setUuid(value) _builder.setKey(value)
} }
/** /**
* <code>string uuid = 4;</code> * <code>string key = 4;</code>
*/ */
fun clearUuid() { fun clearKey() {
_builder.clearUuid() _builder.clearKey()
} }
/** /**
* <code>int32 id = 5;</code> * <code>bytes value = 5;</code>
*/
var id: kotlin.Int
@JvmName("getId")
get() = _builder.getId()
@JvmName("setId")
set(value) {
_builder.setId(value)
}
/**
* <code>int32 id = 5;</code>
*/
fun clearId() {
_builder.clearId()
}
/**
* <code>bytes value = 6;</code>
*/ */
var value: com.google.protobuf.ByteString var value: com.google.protobuf.ByteString
@JvmName("getValue") @JvmName("getValue")
@ -118,7 +101,7 @@ object GattDescriptorWriteArgumentsKt {
_builder.setValue(value) _builder.setValue(value)
} }
/** /**
* <code>bytes value = 6;</code> * <code>bytes value = 5;</code>
*/ */
fun clearValue() { fun clearValue() {
_builder.clearValue() _builder.clearValue()

View File

@ -23,37 +23,20 @@ object GattDisconnectArgumentsKt {
internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDisconnectArguments = _builder.build() internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDisconnectArguments = _builder.build()
/** /**
* <code>string address = 1;</code> * <code>string key = 1;</code>
*/ */
var address: kotlin.String var key: kotlin.String
@JvmName("getAddress") @JvmName("getKey")
get() = _builder.getAddress() get() = _builder.getKey()
@JvmName("setAddress") @JvmName("setKey")
set(value) { set(value) {
_builder.setAddress(value) _builder.setKey(value)
} }
/** /**
* <code>string address = 1;</code> * <code>string key = 1;</code>
*/ */
fun clearAddress() { fun clearKey() {
_builder.clearAddress() _builder.clearKey()
}
/**
* <code>int32 id = 2;</code>
*/
var id: kotlin.Int
@JvmName("getId")
get() = _builder.getId()
@JvmName("setId")
set(value) {
_builder.setId(value)
}
/**
* <code>int32 id = 2;</code>
*/
fun clearId() {
_builder.clearId()
} }
} }
} }

View File

@ -23,20 +23,20 @@ object GattServiceKt {
internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattService = _builder.build() internal fun _build(): dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattService = _builder.build()
/** /**
* <code>int32 id = 1;</code> * <code>string key = 1;</code>
*/ */
var id: kotlin.Int var key: kotlin.String
@JvmName("getId") @JvmName("getKey")
get() = _builder.getId() get() = _builder.getKey()
@JvmName("setId") @JvmName("setKey")
set(value) { set(value) {
_builder.setId(value) _builder.setKey(value)
} }
/** /**
* <code>int32 id = 1;</code> * <code>string key = 1;</code>
*/ */
fun clearId() { fun clearKey() {
_builder.clearId() _builder.clearKey()
} }
/** /**

View File

@ -40,9 +40,9 @@ object MessageKt {
} }
/** /**
* <code>bool state = 2;</code> * <code>.dev.yanshouwang.bluetooth_low_energy.BluetoothState state = 2;</code>
*/ */
var state: kotlin.Boolean var state: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.BluetoothState
@JvmName("getState") @JvmName("getState")
get() = _builder.getState() get() = _builder.getState()
@JvmName("setState") @JvmName("setState")
@ -50,13 +50,13 @@ object MessageKt {
_builder.setState(value) _builder.setState(value)
} }
/** /**
* <code>bool state = 2;</code> * <code>.dev.yanshouwang.bluetooth_low_energy.BluetoothState state = 2;</code>
*/ */
fun clearState() { fun clearState() {
_builder.clearState() _builder.clearState()
} }
/** /**
* <code>bool state = 2;</code> * <code>.dev.yanshouwang.bluetooth_low_energy.BluetoothState state = 2;</code>
* @return Whether the state field is set. * @return Whether the state field is set.
*/ */
fun hasState(): kotlin.Boolean { fun hasState(): kotlin.Boolean {
@ -64,7 +64,31 @@ object MessageKt {
} }
/** /**
* <code>.dev.yanshouwang.bluetooth_low_energy.Discovery discovery = 3;</code> * <code>.dev.yanshouwang.bluetooth_low_energy.StartDiscoveryArguments startDiscoveryArguments = 3;</code>
*/
var startDiscoveryArguments: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.StartDiscoveryArguments
@JvmName("getStartDiscoveryArguments")
get() = _builder.getStartDiscoveryArguments()
@JvmName("setStartDiscoveryArguments")
set(value) {
_builder.setStartDiscoveryArguments(value)
}
/**
* <code>.dev.yanshouwang.bluetooth_low_energy.StartDiscoveryArguments startDiscoveryArguments = 3;</code>
*/
fun clearStartDiscoveryArguments() {
_builder.clearStartDiscoveryArguments()
}
/**
* <code>.dev.yanshouwang.bluetooth_low_energy.StartDiscoveryArguments startDiscoveryArguments = 3;</code>
* @return Whether the startDiscoveryArguments field is set.
*/
fun hasStartDiscoveryArguments(): kotlin.Boolean {
return _builder.hasStartDiscoveryArguments()
}
/**
* <code>.dev.yanshouwang.bluetooth_low_energy.Discovery discovery = 4;</code>
*/ */
var discovery: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.Discovery var discovery: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.Discovery
@JvmName("getDiscovery") @JvmName("getDiscovery")
@ -74,13 +98,13 @@ object MessageKt {
_builder.setDiscovery(value) _builder.setDiscovery(value)
} }
/** /**
* <code>.dev.yanshouwang.bluetooth_low_energy.Discovery discovery = 3;</code> * <code>.dev.yanshouwang.bluetooth_low_energy.Discovery discovery = 4;</code>
*/ */
fun clearDiscovery() { fun clearDiscovery() {
_builder.clearDiscovery() _builder.clearDiscovery()
} }
/** /**
* <code>.dev.yanshouwang.bluetooth_low_energy.Discovery discovery = 3;</code> * <code>.dev.yanshouwang.bluetooth_low_energy.Discovery discovery = 4;</code>
* @return Whether the discovery field is set. * @return Whether the discovery field is set.
*/ */
fun hasDiscovery(): kotlin.Boolean { fun hasDiscovery(): kotlin.Boolean {
@ -88,33 +112,57 @@ object MessageKt {
} }
/** /**
* <code>bool scanning = 4;</code> * <code>.dev.yanshouwang.bluetooth_low_energy.ConnectArguments connectArguments = 5;</code>
*/ */
var scanning: kotlin.Boolean var connectArguments: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.ConnectArguments
@JvmName("getScanning") @JvmName("getConnectArguments")
get() = _builder.getScanning() get() = _builder.getConnectArguments()
@JvmName("setScanning") @JvmName("setConnectArguments")
set(value) { set(value) {
_builder.setScanning(value) _builder.setConnectArguments(value)
} }
/** /**
* <code>bool scanning = 4;</code> * <code>.dev.yanshouwang.bluetooth_low_energy.ConnectArguments connectArguments = 5;</code>
*/ */
fun clearScanning() { fun clearConnectArguments() {
_builder.clearScanning() _builder.clearConnectArguments()
} }
/** /**
* <code>bool scanning = 4;</code> * <code>.dev.yanshouwang.bluetooth_low_energy.ConnectArguments connectArguments = 5;</code>
* @return Whether the scanning field is set. * @return Whether the connectArguments field is set.
*/ */
fun hasScanning(): kotlin.Boolean { fun hasConnectArguments(): kotlin.Boolean {
return _builder.hasScanning() return _builder.hasConnectArguments()
} }
/** /**
* <code>.dev.yanshouwang.bluetooth_low_energy.ConnectionLost connectionLost = 5;</code> * <code>.dev.yanshouwang.bluetooth_low_energy.GattDisconnectArguments disconnectArguments = 6;</code>
*/ */
var connectionLost: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.ConnectionLost var disconnectArguments: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDisconnectArguments
@JvmName("getDisconnectArguments")
get() = _builder.getDisconnectArguments()
@JvmName("setDisconnectArguments")
set(value) {
_builder.setDisconnectArguments(value)
}
/**
* <code>.dev.yanshouwang.bluetooth_low_energy.GattDisconnectArguments disconnectArguments = 6;</code>
*/
fun clearDisconnectArguments() {
_builder.clearDisconnectArguments()
}
/**
* <code>.dev.yanshouwang.bluetooth_low_energy.GattDisconnectArguments disconnectArguments = 6;</code>
* @return Whether the disconnectArguments field is set.
*/
fun hasDisconnectArguments(): kotlin.Boolean {
return _builder.hasDisconnectArguments()
}
/**
* <code>.dev.yanshouwang.bluetooth_low_energy.GattConnectionLost connectionLost = 7;</code>
*/
var connectionLost: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattConnectionLost
@JvmName("getConnectionLost") @JvmName("getConnectionLost")
get() = _builder.getConnectionLost() get() = _builder.getConnectionLost()
@JvmName("setConnectionLost") @JvmName("setConnectionLost")
@ -122,13 +170,13 @@ object MessageKt {
_builder.setConnectionLost(value) _builder.setConnectionLost(value)
} }
/** /**
* <code>.dev.yanshouwang.bluetooth_low_energy.ConnectionLost connectionLost = 5;</code> * <code>.dev.yanshouwang.bluetooth_low_energy.GattConnectionLost connectionLost = 7;</code>
*/ */
fun clearConnectionLost() { fun clearConnectionLost() {
_builder.clearConnectionLost() _builder.clearConnectionLost()
} }
/** /**
* <code>.dev.yanshouwang.bluetooth_low_energy.ConnectionLost connectionLost = 5;</code> * <code>.dev.yanshouwang.bluetooth_low_energy.GattConnectionLost connectionLost = 7;</code>
* @return Whether the connectionLost field is set. * @return Whether the connectionLost field is set.
*/ */
fun hasConnectionLost(): kotlin.Boolean { fun hasConnectionLost(): kotlin.Boolean {
@ -136,7 +184,79 @@ object MessageKt {
} }
/** /**
* <code>.dev.yanshouwang.bluetooth_low_energy.GattCharacteristicValue characteristicValue = 6;</code> * <code>.dev.yanshouwang.bluetooth_low_energy.GattCharacteristicReadArguments characteristicReadArguments = 8;</code>
*/
var characteristicReadArguments: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattCharacteristicReadArguments
@JvmName("getCharacteristicReadArguments")
get() = _builder.getCharacteristicReadArguments()
@JvmName("setCharacteristicReadArguments")
set(value) {
_builder.setCharacteristicReadArguments(value)
}
/**
* <code>.dev.yanshouwang.bluetooth_low_energy.GattCharacteristicReadArguments characteristicReadArguments = 8;</code>
*/
fun clearCharacteristicReadArguments() {
_builder.clearCharacteristicReadArguments()
}
/**
* <code>.dev.yanshouwang.bluetooth_low_energy.GattCharacteristicReadArguments characteristicReadArguments = 8;</code>
* @return Whether the characteristicReadArguments field is set.
*/
fun hasCharacteristicReadArguments(): kotlin.Boolean {
return _builder.hasCharacteristicReadArguments()
}
/**
* <code>.dev.yanshouwang.bluetooth_low_energy.GattCharacteristicWriteArguments characteristicWriteArguments = 9;</code>
*/
var characteristicWriteArguments: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattCharacteristicWriteArguments
@JvmName("getCharacteristicWriteArguments")
get() = _builder.getCharacteristicWriteArguments()
@JvmName("setCharacteristicWriteArguments")
set(value) {
_builder.setCharacteristicWriteArguments(value)
}
/**
* <code>.dev.yanshouwang.bluetooth_low_energy.GattCharacteristicWriteArguments characteristicWriteArguments = 9;</code>
*/
fun clearCharacteristicWriteArguments() {
_builder.clearCharacteristicWriteArguments()
}
/**
* <code>.dev.yanshouwang.bluetooth_low_energy.GattCharacteristicWriteArguments characteristicWriteArguments = 9;</code>
* @return Whether the characteristicWriteArguments field is set.
*/
fun hasCharacteristicWriteArguments(): kotlin.Boolean {
return _builder.hasCharacteristicWriteArguments()
}
/**
* <code>.dev.yanshouwang.bluetooth_low_energy.GattCharacteristicNotifyArguments characteristicNotifyArguments = 10;</code>
*/
var characteristicNotifyArguments: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattCharacteristicNotifyArguments
@JvmName("getCharacteristicNotifyArguments")
get() = _builder.getCharacteristicNotifyArguments()
@JvmName("setCharacteristicNotifyArguments")
set(value) {
_builder.setCharacteristicNotifyArguments(value)
}
/**
* <code>.dev.yanshouwang.bluetooth_low_energy.GattCharacteristicNotifyArguments characteristicNotifyArguments = 10;</code>
*/
fun clearCharacteristicNotifyArguments() {
_builder.clearCharacteristicNotifyArguments()
}
/**
* <code>.dev.yanshouwang.bluetooth_low_energy.GattCharacteristicNotifyArguments characteristicNotifyArguments = 10;</code>
* @return Whether the characteristicNotifyArguments field is set.
*/
fun hasCharacteristicNotifyArguments(): kotlin.Boolean {
return _builder.hasCharacteristicNotifyArguments()
}
/**
* <code>.dev.yanshouwang.bluetooth_low_energy.GattCharacteristicValue characteristicValue = 11;</code>
*/ */
var characteristicValue: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattCharacteristicValue var characteristicValue: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattCharacteristicValue
@JvmName("getCharacteristicValue") @JvmName("getCharacteristicValue")
@ -146,18 +266,66 @@ object MessageKt {
_builder.setCharacteristicValue(value) _builder.setCharacteristicValue(value)
} }
/** /**
* <code>.dev.yanshouwang.bluetooth_low_energy.GattCharacteristicValue characteristicValue = 6;</code> * <code>.dev.yanshouwang.bluetooth_low_energy.GattCharacteristicValue characteristicValue = 11;</code>
*/ */
fun clearCharacteristicValue() { fun clearCharacteristicValue() {
_builder.clearCharacteristicValue() _builder.clearCharacteristicValue()
} }
/** /**
* <code>.dev.yanshouwang.bluetooth_low_energy.GattCharacteristicValue characteristicValue = 6;</code> * <code>.dev.yanshouwang.bluetooth_low_energy.GattCharacteristicValue characteristicValue = 11;</code>
* @return Whether the characteristicValue field is set. * @return Whether the characteristicValue field is set.
*/ */
fun hasCharacteristicValue(): kotlin.Boolean { fun hasCharacteristicValue(): kotlin.Boolean {
return _builder.hasCharacteristicValue() return _builder.hasCharacteristicValue()
} }
/**
* <code>.dev.yanshouwang.bluetooth_low_energy.GattDescriptorReadArguments descriptorReadArguments = 12;</code>
*/
var descriptorReadArguments: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptorReadArguments
@JvmName("getDescriptorReadArguments")
get() = _builder.getDescriptorReadArguments()
@JvmName("setDescriptorReadArguments")
set(value) {
_builder.setDescriptorReadArguments(value)
}
/**
* <code>.dev.yanshouwang.bluetooth_low_energy.GattDescriptorReadArguments descriptorReadArguments = 12;</code>
*/
fun clearDescriptorReadArguments() {
_builder.clearDescriptorReadArguments()
}
/**
* <code>.dev.yanshouwang.bluetooth_low_energy.GattDescriptorReadArguments descriptorReadArguments = 12;</code>
* @return Whether the descriptorReadArguments field is set.
*/
fun hasDescriptorReadArguments(): kotlin.Boolean {
return _builder.hasDescriptorReadArguments()
}
/**
* <code>.dev.yanshouwang.bluetooth_low_energy.GattDescriptorWriteArguments descriptorWriteArguments = 13;</code>
*/
var descriptorWriteArguments: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.GattDescriptorWriteArguments
@JvmName("getDescriptorWriteArguments")
get() = _builder.getDescriptorWriteArguments()
@JvmName("setDescriptorWriteArguments")
set(value) {
_builder.setDescriptorWriteArguments(value)
}
/**
* <code>.dev.yanshouwang.bluetooth_low_energy.GattDescriptorWriteArguments descriptorWriteArguments = 13;</code>
*/
fun clearDescriptorWriteArguments() {
_builder.clearDescriptorWriteArguments()
}
/**
* <code>.dev.yanshouwang.bluetooth_low_energy.GattDescriptorWriteArguments descriptorWriteArguments = 13;</code>
* @return Whether the descriptorWriteArguments field is set.
*/
fun hasDescriptorWriteArguments(): kotlin.Boolean {
return _builder.hasDescriptorWriteArguments()
}
val valueCase: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.Message.ValueCase val valueCase: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.Message.ValueCase
@JvmName("getValueCase") @JvmName("getValueCase")
get() = _builder.getValueCase() get() = _builder.getValueCase()

View File

@ -0,0 +1,5 @@
package dev.yanshouwang.bluetooth_low_energy
import android.bluetooth.BluetoothGatt
class NativeGATT(value: BluetoothGatt, val services: Map<String, NativeGattService>) : NativeValue<BluetoothGatt>(value)

View File

@ -0,0 +1,5 @@
package dev.yanshouwang.bluetooth_low_energy
import android.bluetooth.BluetoothGattCharacteristic
class NativeGattCharacteristic(value: BluetoothGattCharacteristic, val descriptors: Map<String, NativeGattDescriptor>) : NativeValue<BluetoothGattCharacteristic>(value)

View File

@ -0,0 +1,5 @@
package dev.yanshouwang.bluetooth_low_energy
import android.bluetooth.BluetoothGattDescriptor
class NativeGattDescriptor(value: BluetoothGattDescriptor) : NativeValue<BluetoothGattDescriptor>(value)

View File

@ -0,0 +1,5 @@
package dev.yanshouwang.bluetooth_low_energy
import android.bluetooth.BluetoothGattService
class NativeGattService(value: BluetoothGattService, val characteristics: Map<String, NativeGattCharacteristic>) : NativeValue<BluetoothGattService>(value)

View File

@ -0,0 +1,7 @@
package dev.yanshouwang.bluetooth_low_energy
import java.util.*
open class NativeValue<T>(val value: T) {
public val key = UUID.randomUUID().toString()
}

View File

@ -1,5 +1,5 @@
buildscript { buildscript {
ext.kotlin_version = '1.5.20' ext.kotlin_version = '1.5.21'
repositories { repositories {
google() google()
mavenCentral() mavenCentral()

View File

@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig" #include "Generated.xcconfig"

View File

@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig" #include "Generated.xcconfig"

41
example/ios/Podfile Normal file
View File

@ -0,0 +1,41 @@
# Uncomment this line to define a global platform for your project
platform :ios, '9.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_ios_podfile_setup
target 'Runner' do
use_frameworks!
use_modular_headers!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end

29
example/ios/Podfile.lock Normal file
View File

@ -0,0 +1,29 @@
PODS:
- bluetooth_low_energy (0.0.1):
- Flutter
- SwiftProtobuf (~> 1.0)
- Flutter (1.0.0)
- SwiftProtobuf (1.17.0)
DEPENDENCIES:
- bluetooth_low_energy (from `.symlinks/plugins/bluetooth_low_energy/ios`)
- Flutter (from `Flutter`)
SPEC REPOS:
trunk:
- SwiftProtobuf
EXTERNAL SOURCES:
bluetooth_low_energy:
:path: ".symlinks/plugins/bluetooth_low_energy/ios"
Flutter:
:path: Flutter
SPEC CHECKSUMS:
bluetooth_low_energy: 9222b99f977897165e6ffaece386bd289ac8c1fb
Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
SwiftProtobuf: 9c85136c6ba74b0a1b84279dbf0f6db8efb714e0
PODFILE CHECKSUM: a75497545d4391e2d394c3668e20cfb1c2bbd4aa
COCOAPODS: 1.10.1

View File

@ -3,7 +3,7 @@
archiveVersion = 1; archiveVersion = 1;
classes = { classes = {
}; };
objectVersion = 46; objectVersion = 51;
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
@ -13,6 +13,7 @@
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
EA280E36114EEC52A66510AF /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F6363DB0F6B8F760A0B70E6 /* Pods_Runner.framework */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */ /* Begin PBXCopyFilesBuildPhase section */
@ -29,8 +30,10 @@
/* End PBXCopyFilesBuildPhase section */ /* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
1173070BE6CFE927D74C0736 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
2F6363DB0F6B8F760A0B70E6 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
@ -42,6 +45,8 @@
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
9E8C4C982EC9200D28D9557C /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
FA6DAFE6FDB9F8D1C4A8AEF3 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -49,6 +54,7 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
EA280E36114EEC52A66510AF /* Pods_Runner.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -72,6 +78,8 @@
9740EEB11CF90186004384FC /* Flutter */, 9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */, 97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */, 97C146EF1CF9000F007C117D /* Products */,
A19CF493038BEE74587FB0E8 /* Pods */,
990CDB7BA621E0B7AFA0C6BE /* Frameworks */,
); );
sourceTree = "<group>"; sourceTree = "<group>";
}; };
@ -98,6 +106,24 @@
path = Runner; path = Runner;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
990CDB7BA621E0B7AFA0C6BE /* Frameworks */ = {
isa = PBXGroup;
children = (
2F6363DB0F6B8F760A0B70E6 /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
A19CF493038BEE74587FB0E8 /* Pods */ = {
isa = PBXGroup;
children = (
FA6DAFE6FDB9F8D1C4A8AEF3 /* Pods-Runner.debug.xcconfig */,
1173070BE6CFE927D74C0736 /* Pods-Runner.release.xcconfig */,
9E8C4C982EC9200D28D9557C /* Pods-Runner.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXNativeTarget section */ /* Begin PBXNativeTarget section */
@ -105,12 +131,14 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = ( buildPhases = (
4DEF012D22BCBC3AF731DE9C /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */, 9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */, 97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */, 97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */, 97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */, 9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
EDB3731BEABF1E16CE6A52EB /* [CP] Embed Pods Frameworks */,
); );
buildRules = ( buildRules = (
); );
@ -183,6 +211,28 @@
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
}; };
4DEF012D22BCBC3AF731DE9C /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
9740EEB61CF901F6004384FC /* Run Script */ = { 9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
@ -197,6 +247,23 @@
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
}; };
EDB3731BEABF1E16CE6A52EB /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */ /* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */
@ -288,9 +355,13 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = JJSB6LL9HD;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = dev.yanshouwang.bluetoothLowEnergyExample; PRODUCT_BUNDLE_IDENTIFIER = dev.yanshouwang.bluetoothLowEnergyExample;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@ -399,7 +470,8 @@
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos; SUPPORTED_PLATFORMS = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES; VALIDATE_PRODUCT = YES;
}; };
@ -412,9 +484,13 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = JJSB6LL9HD;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = dev.yanshouwang.bluetoothLowEnergyExample; PRODUCT_BUNDLE_IDENTIFIER = dev.yanshouwang.bluetoothLowEnergyExample;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@ -431,9 +507,13 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = JJSB6LL9HD;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = dev.yanshouwang.bluetoothLowEnergyExample; PRODUCT_BUNDLE_IDENTIFIER = dev.yanshouwang.bluetoothLowEnergyExample;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";

View File

@ -4,4 +4,7 @@
<FileRef <FileRef
location = "group:Runner.xcodeproj"> location = "group:Runner.xcodeproj">
</FileRef> </FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace> </Workspace>

View File

@ -22,6 +22,8 @@
<string>$(FLUTTER_BUILD_NUMBER)</string> <string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>We need to use your bluetooth to communicate with other BLE devices.</string>
<key>UILaunchStoryboardName</key> <key>UILaunchStoryboardName</key>
<string>LaunchScreen</string> <string>LaunchScreen</string>
<key>UIMainStoryboardFile</key> <key>UIMainStoryboardFile</key>

View File

@ -27,24 +27,33 @@ class HomeView extends StatefulWidget {
} }
class _HomeViewState extends State<HomeView> with WidgetsBindingObserver { class _HomeViewState extends State<HomeView> with WidgetsBindingObserver {
final ValueNotifier<bool> state;
final ValueNotifier<bool> discovering; final ValueNotifier<bool> discovering;
final ValueNotifier<Map<MAC, Discovery>> discoveries; final ValueNotifier<Map<UUID, Discovery>> discoveries;
late StreamSubscription<bool> stateSubscription; late StreamSubscription<BluetoothState> stateSubscription;
late StreamSubscription<Discovery> discoverySubscription; late StreamSubscription<Discovery> discoverySubscription;
_HomeViewState() _HomeViewState()
: discovering = ValueNotifier(false), : state = ValueNotifier(false),
discovering = ValueNotifier(false),
discoveries = ValueNotifier({}); discoveries = ValueNotifier({});
@override @override
void initState() { void initState() {
super.initState(); super.initState();
WidgetsBinding.instance!.addObserver(this); WidgetsBinding.instance!.addObserver(this);
setup();
}
void setup() async {
final state = await central.state;
this.state.value = state == BluetoothState.poweredOn;
stateSubscription = central.stateChanged.listen( stateSubscription = central.stateChanged.listen(
(state) { (state) {
this.state.value = state == BluetoothState.poweredOn;
final invisible = !ModalRoute.of(context)!.isCurrent; final invisible = !ModalRoute.of(context)!.isCurrent;
if (invisible) return; if (invisible) return;
if (state) { if (this.state.value) {
startDiscovery(); startDiscovery();
} else { } else {
discovering.value = false; discovering.value = false;
@ -53,11 +62,13 @@ class _HomeViewState extends State<HomeView> with WidgetsBindingObserver {
); );
discoverySubscription = central.discovered.listen( discoverySubscription = central.discovered.listen(
(discovery) { (discovery) {
discoveries.value[discovery.address] = discovery; discoveries.value[discovery.uuid] = discovery;
discoveries.value = {...discoveries.value}; discoveries.value = {...discoveries.value};
}, },
); );
startDiscovery(); if (this.state.value) {
startDiscovery();
}
} }
@override @override
@ -88,13 +99,13 @@ class _HomeViewState extends State<HomeView> with WidgetsBindingObserver {
} }
void startDiscovery() async { void startDiscovery() async {
if (discovering.value || !await central.state) return; if (discovering.value || !state.value) return;
await central.startDiscovery(); await central.startDiscovery();
discovering.value = true; discovering.value = true;
} }
void stopDiscovery() async { void stopDiscovery() async {
if (!discovering.value || !await central.state) return; if (!discovering.value || !state.value) return;
await central.stopDiscovery(); await central.stopDiscovery();
discoveries.value = {}; discoveries.value = {};
discovering.value = false; discovering.value = false;
@ -113,7 +124,7 @@ class _HomeViewState extends State<HomeView> with WidgetsBindingObserver {
stopDiscovery(); stopDiscovery();
await Navigator.of(context).pushNamed( await Navigator.of(context).pushNamed(
'gatt', 'gatt',
arguments: discovery.address, arguments: discovery.uuid,
); );
startDiscovery(); startDiscovery();
} }
@ -121,16 +132,10 @@ class _HomeViewState extends State<HomeView> with WidgetsBindingObserver {
extension on _HomeViewState { extension on _HomeViewState {
Widget get bodyView { Widget get bodyView {
return FutureBuilder<bool>( return ValueListenableBuilder(
future: central.state, valueListenable: state,
builder: (context, snapshot) => snapshot.hasData builder: (context, bool state, child) =>
? StreamBuilder<bool>( state ? discoveriesView : closedView,
stream: central.stateChanged,
initialData: snapshot.data,
builder: (context, snapshot) =>
snapshot.data! ? discoveriesView : closedView,
)
: closedView,
); );
} }
@ -145,14 +150,14 @@ extension on _HomeViewState {
onRefresh: () async => discoveries.value = {}, onRefresh: () async => discoveries.value = {},
child: ValueListenableBuilder( child: ValueListenableBuilder(
valueListenable: discoveries, valueListenable: discoveries,
builder: (context, Map<MAC, Discovery> discoveries, child) { builder: (context, Map<UUID, Discovery> discoveries, child) {
return ListView.builder( return ListView.builder(
padding: EdgeInsets.all(6.0), padding: EdgeInsets.all(6.0),
itemCount: discoveries.length, itemCount: discoveries.length,
itemBuilder: (context, i) { itemBuilder: (context, i) {
final discovery = discoveries.values.elementAt(i); final discovery = discoveries.values.elementAt(i);
return Card( return Card(
color: Colors.amber, color: discovery.connectable ? Colors.amber : Colors.grey,
clipBehavior: Clip.antiAlias, clipBehavior: Clip.antiAlias,
shape: BeveledRectangleBorder( shape: BeveledRectangleBorder(
borderRadius: BorderRadius.only( borderRadius: BorderRadius.only(
@ -160,24 +165,39 @@ extension on _HomeViewState {
bottomLeft: Radius.circular(12.0)), bottomLeft: Radius.circular(12.0)),
), ),
margin: EdgeInsets.all(6.0), margin: EdgeInsets.all(6.0),
key: Key(discovery.address.name), key: Key(discovery.uuid.name),
child: InkWell( child: InkWell(
splashColor: Colors.purple, splashColor: Colors.purple,
onTap: () => showGattView(discovery), onTap: discovery.connectable
? () => showGattView(discovery)
: null,
onLongPress: () => showAdvertisements(discovery), onLongPress: () => showAdvertisements(discovery),
child: Container( child: Container(
height: 100.0, height: 100.0,
padding: EdgeInsets.all(12.0),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround, mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [ children: [
Column( Expanded(
mainAxisAlignment: MainAxisAlignment.center, flex: 3,
children: [ child: Column(
Text(discovery.name ?? 'NaN'), mainAxisAlignment: MainAxisAlignment.center,
Text(discovery.address.name), children: [
], Text(discovery.name ?? 'NaN'),
Text(
discovery.uuid.name,
softWrap: true,
),
],
),
),
Expanded(
flex: 1,
child: Text(
discovery.rssi.toString(),
textAlign: TextAlign.center,
),
), ),
Text(discovery.rssi.toString()),
], ],
), ),
), ),
@ -265,7 +285,7 @@ class _GattViewState extends State<GattView> {
final ValueNotifier<Map<GattCharacteristic, StreamSubscription>> notifies; final ValueNotifier<Map<GattCharacteristic, StreamSubscription>> notifies;
final ValueNotifier<List<String>> logs; final ValueNotifier<List<String>> logs;
late MAC address; late UUID uuid;
_GattViewState() _GattViewState()
: state = ValueNotifier(ConnectionState.disconnected), : state = ValueNotifier(ConnectionState.disconnected),
@ -282,10 +302,10 @@ class _GattViewState extends State<GattView> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
address = ModalRoute.of(context)!.settings.arguments as MAC; uuid = ModalRoute.of(context)!.settings.arguments as UUID;
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('$address'), title: Text(uuid.name),
actions: [ actions: [
changeStateView, changeStateView,
], ],
@ -336,7 +356,7 @@ class _GattViewState extends State<GattView> {
void connect() async { void connect() async {
try { try {
state.value = ConnectionState.connecting; state.value = ConnectionState.connecting;
gatt = await central.connect(address); gatt = await central.connect(uuid);
state.value = ConnectionState.connected; state.value = ConnectionState.connected;
connectionLostSubscription = gatt!.connectionLost.listen( connectionLostSubscription = gatt!.connectionLost.listen(
(errorCode) async { (errorCode) async {
@ -547,6 +567,7 @@ extension on _GattViewState {
final controllerView = TextField( final controllerView = TextField(
controller: writeController, controller: writeController,
decoration: InputDecoration( decoration: InputDecoration(
hintText: 'MTU: ${gatt!.maximumWriteLength}',
suffixIcon: IconButton( suffixIcon: IconButton(
onPressed: canWrite onPressed: canWrite
? () { ? () {

View File

@ -5,7 +5,7 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: async name: async
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.6.1" version: "2.6.1"
bluetooth_low_energy: bluetooth_low_energy:
@ -14,68 +14,68 @@ packages:
path: ".." path: ".."
relative: true relative: true
source: path source: path
version: "0.0.2" version: "0.1.0"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
description: description:
name: boolean_selector name: boolean_selector
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.0" version: "2.1.0"
characters: characters:
dependency: transitive dependency: transitive
description: description:
name: characters name: characters
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0" version: "1.1.0"
charcode: charcode:
dependency: transitive dependency: transitive
description: description:
name: charcode name: charcode
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "1.2.0"
clock: clock:
dependency: transitive dependency: transitive
description: description:
name: clock name: clock
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0" version: "1.1.0"
collection: collection:
dependency: transitive dependency: transitive
description: description:
name: collection name: collection
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.15.0" version: "1.15.0"
convert: convert:
dependency: "direct main" dependency: "direct main"
description: description:
name: convert name: convert
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.0" version: "3.0.1"
cupertino_icons: cupertino_icons:
dependency: "direct main" dependency: "direct main"
description: description:
name: cupertino_icons name: cupertino_icons
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.3" version: "1.0.3"
fake_async: fake_async:
dependency: transitive dependency: transitive
description: description:
name: fake_async name: fake_async
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "1.2.0"
fixnum: fixnum:
dependency: transitive dependency: transitive
description: description:
name: fixnum name: fixnum
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.0" version: "1.0.0"
flutter: flutter:
@ -87,7 +87,7 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_simple_treeview name: flutter_simple_treeview
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.0-nullsafety.1" version: "3.0.0-nullsafety.1"
flutter_test: flutter_test:
@ -99,35 +99,35 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: matcher name: matcher
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.12.10" version: "0.12.10"
meta: meta:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.0" version: "1.3.0"
path: path:
dependency: transitive dependency: transitive
description: description:
name: path name: path
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.8.0" version: "1.8.0"
pedantic: pedantic:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: pedantic name: pedantic
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.11.0" version: "1.11.1"
protobuf: protobuf:
dependency: transitive dependency: transitive
description: description:
name: protobuf name: protobuf
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.0" version: "2.0.0"
sky_engine: sky_engine:
@ -139,56 +139,56 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: source_span name: source_span
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.8.1" version: "1.8.1"
stack_trace: stack_trace:
dependency: transitive dependency: transitive
description: description:
name: stack_trace name: stack_trace
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.10.0" version: "1.10.0"
stream_channel: stream_channel:
dependency: transitive dependency: transitive
description: description:
name: stream_channel name: stream_channel
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.0" version: "2.1.0"
string_scanner: string_scanner:
dependency: transitive dependency: transitive
description: description:
name: string_scanner name: string_scanner
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0" version: "1.1.0"
term_glyph: term_glyph:
dependency: transitive dependency: transitive
description: description:
name: term_glyph name: term_glyph
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "1.2.0"
test_api: test_api:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.3.0" version: "0.3.0"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
name: typed_data name: typed_data
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.0" version: "1.3.0"
vector_math: vector_math:
dependency: transitive dependency: transitive
description: description:
name: vector_math name: vector_math
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.0" version: "2.1.0"
sdks: sdks:

View File

@ -0,0 +1,18 @@
//
// NativeGATT.swift
// bluetooth_low_energy
//
// Created by on 2021/7/15.
//
import Foundation
import CoreBluetooth
class NativeGATT: NativeValue<CBPeripheral> {
let services: [String: NativeGattService]
init(_ value: CBPeripheral, _ services: [String: NativeGattService]) {
self.services = services
super.init(value)
}
}

View File

@ -0,0 +1,18 @@
//
// NativeGattCharacteristic.swift
// bluetooth_low_energy
//
// Created by on 2021/7/15.
//
import Foundation
import CoreBluetooth
class NativeGattCharacteristic: NativeValue<CBCharacteristic> {
let descriptors: [String: NativeGattDescriptor]
init(_ value: CBCharacteristic, _ descriptors: [String: NativeGattDescriptor]) {
self.descriptors = descriptors
super.init(value)
}
}

View File

@ -0,0 +1,12 @@
//
// NativeGattDescriptor.swift
// bluetooth_low_energy
//
// Created by on 2021/7/15.
//
import Foundation
import CoreBluetooth
class NativeGattDescriptor: NativeValue<CBDescriptor> {
}

View File

@ -0,0 +1,18 @@
//
// NativeGattService.swift
// bluetooth_low_energy
//
// Created by on 2021/7/15.
//
import Foundation
import CoreBluetooth
class NativeGattService: NativeValue<CBService> {
let characteristics: [String: NativeGattCharacteristic]
init(_ value: CBService, _ characteristics: [String: NativeGattCharacteristic]) {
self.characteristics = characteristics
super.init(value)
}
}

View File

@ -0,0 +1,17 @@
//
// NativeValue.swift
// bluetooth_low_energy
//
// Created by on 2021/7/15.
//
import Foundation
class NativeValue<T> {
let key = UUID().uuidString
let value: T
init(_ value: T) {
self.value = value
}
}

View File

@ -1,14 +1,512 @@
import Flutter import Flutter
import UIKit import UIKit
import CoreBluetooth
public class SwiftBluetoothLowEnergyPlugin: NSObject, FlutterPlugin { let NAMESAPCE = "yanshouwang.dev/bluetooth_low_energy"
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: "bluetooth_low_energy", binaryMessenger: registrar.messenger())
let instance = SwiftBluetoothLowEnergyPlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { typealias MessageCategory = Dev_Yanshouwang_BluetoothLowEnergy_MessageCategory
result("iOS " + UIDevice.current.systemVersion) typealias Message = Dev_Yanshouwang_BluetoothLowEnergy_Message
} typealias BluetoothState = Dev_Yanshouwang_BluetoothLowEnergy_BluetoothState
typealias StartDiscoveryArguments = Dev_Yanshouwang_BluetoothLowEnergy_StartDiscoveryArguments
typealias Discovery = Dev_Yanshouwang_BluetoothLowEnergy_Discovery
typealias GATT = Dev_Yanshouwang_BluetoothLowEnergy_GATT
typealias GattService = Dev_Yanshouwang_BluetoothLowEnergy_GattService
typealias GattCharacteristic = Dev_Yanshouwang_BluetoothLowEnergy_GattCharacteristic
typealias GattDescriptor = Dev_Yanshouwang_BluetoothLowEnergy_GattDescriptor
typealias GattConnectionLost = Dev_Yanshouwang_BluetoothLowEnergy_GattConnectionLost
typealias GattCharacteristicValue = Dev_Yanshouwang_BluetoothLowEnergy_GattCharacteristicValue
public class SwiftBluetoothLowEnergyPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, CBCentralManagerDelegate, CBPeripheralDelegate {
let SHORTENED_LOCAL_NAME_TYPE = 0x08
let COMPLETE_LOCAL_NAME_TYPE: UInt8 = 0x09
let MANUFACTURER_SPECIFIC_DATA_TYPE: UInt8 = 0xff
let SERVICE_DATA_16BIT_TYPE: UInt8 = 0x16
let SERVICE_DATA_32BIT_TYPE: UInt8 = 0x20
let SERVICE_DATA_128BIT_TYPE: UInt8 = 0x21
let INCOMPLETE_SERVICE_UUIDS_16BIT_TYPE: UInt8 = 0x02
let INCOMPLETE_SERVICE_UUIDS_32BIT_TYPE: UInt8 = 0x04
let INCOMPLETE_SERVICE_UUIDS_128BIT_TYPE: UInt8 = 0x06
let COMPLETE_SERVICE_UUIDS_16BIT_TYPE: UInt8 = 0x03
let COMPLETE_SERVICE_UUIDS_32BIT_TYPE: UInt8 = 0x05
let COMPLETE_SERVICE_UUIDS_128BIT_TYPE: UInt8 = 0x07
let SOLICITTED_SERVICE_UUIDS_16BIT_TYPE: UInt8 = 0x14
let SOLICITTED_SERVICE_UUIDS_32BIT_TYPE: UInt8 = 0x1f
let SOLICITTED_SERVICE_UUIDS_128BIT_TYPE: UInt8 = 0x15
let TX_POWER_LEVEL_TYPE: UInt8 = 0x0a
var events: FlutterEventSink? = nil
var central: CBCentralManager!
var oldState: BluetoothState? = nil
public override init() {
super.init()
central = CBCentralManager(delegate: self, queue: nil)
}
lazy var nativeGATTs = [String: NativeGATT]()
lazy var connects = [CBPeripheral: FlutterResult]()
lazy var disconnects = [CBPeripheral: FlutterResult]()
lazy var characteristicReads = [CBCharacteristic: FlutterResult]()
lazy var characteristicWrites = [CBCharacteristic: FlutterResult]()
lazy var characteristicNotifies = [CBCharacteristic: FlutterResult]()
lazy var descriptorReads = [CBDescriptor: FlutterResult]()
lazy var descriptorWrites = [CBDescriptor: FlutterResult]()
public static func register(with registrar: FlutterPluginRegistrar) {
debugPrint("SwiftBluetoothLowEnergyPlugin: register")
let instance = SwiftBluetoothLowEnergyPlugin()
let messenger = registrar.messenger()
let method = FlutterMethodChannel(name: "\(NAMESAPCE)/method", binaryMessenger: messenger)
registrar.addMethodCallDelegate(instance, channel: method)
let event = FlutterEventChannel(name: "\(NAMESAPCE)/event", binaryMessenger: messenger)
event.setStreamHandler(instance)
}
public func detachFromEngine(for registrar: FlutterPluginRegistrar) {
debugPrint("SwiftBluetoothLowEnergyPlugin: detachFromEngine")
// Clear connections.
for nativeGATT in nativeGATTs.values {
central.cancelPeripheralConnection(nativeGATT.value)
}
// Stop scan.
if central.isScanning {
central.stopScan()
}
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let arguments = call.arguments as! FlutterStandardTypedData
let command = try! Message(serializedData: arguments.data)
switch command.category {
case .bluetoothState:
result(central.messageState.rawValue)
case .centralStartDiscovery:
let withServices = command.startDiscoveryArguments.services.map { CBUUID(string: $0) }
let options = [CBCentralManagerScanOptionAllowDuplicatesKey: true]
central.scanForPeripherals(withServices: withServices, options: options)
result(nil)
case .centralStopDiscovery:
central.stopScan()
result(nil)
case .centralConnect:
let uuid = UUID(uuidString: command.connectArguments.uuid)!
let peripheral = central.retrievePeripherals(withIdentifiers: [uuid]).first!
connects[peripheral] = result
central.connect(peripheral, options: nil)
case .gattDisconnect:
let nativeGATT = nativeGATTs[command.disconnectArguments.key]!
disconnects[nativeGATT.value] = result
central.cancelPeripheralConnection(nativeGATT.value)
case .gattCharacteristicRead:
let nativeGATT = nativeGATTs[command.characteristicReadArguments.gattKey]!
let nativeService = nativeGATT.services[command.characteristicReadArguments.serviceKey]!
let nativeCharacteristic = nativeService.characteristics[command.characteristicReadArguments.key]!
characteristicReads[nativeCharacteristic.value] = result
nativeGATT.value.readValue(for: nativeCharacteristic.value)
case .gattCharacteristicWrite:
let nativeGATT = nativeGATTs[command.characteristicWriteArguments.gattKey]!
let nativeService = nativeGATT.services[command.characteristicWriteArguments.serviceKey]!
let nativeCharacteristic = nativeService.characteristics[command.characteristicWriteArguments.key]!
let value = command.characteristicWriteArguments.value
let type: CBCharacteristicWriteType = command.characteristicWriteArguments.withoutResponse ? .withoutResponse : .withResponse
characteristicWrites[nativeCharacteristic.value] = result
nativeGATT.value.writeValue(value, for: nativeCharacteristic.value, type: type)
break
case .gattCharacteristicNotify:
let nativeGATT = nativeGATTs[command.characteristicNotifyArguments.gattKey]!
let nativeService = nativeGATT.services[command.characteristicNotifyArguments.serviceKey]!
let nativeCharacteristic = nativeService.characteristics[command.characteristicNotifyArguments.key]!
let state = command.characteristicNotifyArguments.state
characteristicNotifies[nativeCharacteristic.value] = result
nativeGATT.value.setNotifyValue(state, for: nativeCharacteristic.value)
break
case .gattDescriptorRead:
let nativeGATT = nativeGATTs[command.descriptorReadArguments.gattKey]!
let nativeService = nativeGATT.services[command.descriptorReadArguments.serviceKey]!
let nativeCharacteristic = nativeService.characteristics[command.descriptorReadArguments.characteristicKey]!
let nativeDescriptor = nativeCharacteristic.descriptors[command.descriptorReadArguments.key]!
descriptorReads[nativeDescriptor.value] = result
nativeGATT.value.readValue(for: nativeDescriptor.value)
break
case .gattDescriptorWrite:
let nativeGATT = nativeGATTs[command.descriptorReadArguments.gattKey]!
let nativeService = nativeGATT.services[command.descriptorReadArguments.serviceKey]!
let nativeCharacteristic = nativeService.characteristics[command.descriptorReadArguments.characteristicKey]!
let nativeDescriptor = nativeCharacteristic.descriptors[command.descriptorReadArguments.key]!
let value = command.descriptorWriteArguments.value
descriptorWrites[nativeDescriptor.value] = result
nativeGATT.value.writeValue(value, for: nativeDescriptor.value)
break
default:
result(FlutterMethodNotImplemented)
}
}
public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
debugPrint("SwiftBluetoothLowEnergyPlugin: onListen")
self.events = events
return nil
}
public func onCancel(withArguments arguments: Any?) -> FlutterError? {
debugPrint("SwiftBluetoothLowEnergyPlugin: onCancel")
// This must be a hot reload for now, clear all status here.
// Clear connections.
for nativeGATT in nativeGATTs.values {
central.cancelPeripheralConnection(nativeGATT.value)
}
// Stop scan.
if central.isScanning {
central.stopScan()
}
events = nil
return nil
}
public func centralManagerDidUpdateState(_ central: CBCentralManager) {
let newState = central.messageState
if newState == oldState {
return
} else if oldState == nil {
oldState = newState
} else {
oldState = newState
let event = try! Message.with {
$0.category = .bluetoothState
$0.state = newState
}.serializedData()
events?(event)
// Send connection lost event and remove all nativeGATTs after central closed, same behaior with Android.
if newState != .poweredOn {
for nativeGATT in nativeGATTs {
let connectionLost = GattConnectionLost.with {
$0.key = nativeGATT.key
$0.error = "Central closed."
}
let event = try! Message.with {
$0.category = .gattConnectionLost
$0.connectionLost = connectionLost
}.serializedData()
events?(event)
}
nativeGATTs.removeAll()
}
}
}
public func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
// Can't analyze complete raw advertisements on iOS.
var advertisements = Data()
for key in advertisementData.keys {
switch key {
case CBAdvertisementDataLocalNameKey:
let name = advertisementData[key] as! String
let data = name.data(using: .utf8)!
let length = UInt8(data.count) + 1
advertisements.append(length)
// TODO: We don't know is this a SHORTENED_LOCAL_NAME or COMPLETE_LOCAL_NAME
// Just use COMPLETE_LOCAL_NAME as type
advertisements.append(COMPLETE_LOCAL_NAME_TYPE)
advertisements.append(data)
break
case CBAdvertisementDataManufacturerDataKey:
let data = advertisementData[key] as! Data
let length = UInt8(data.count) + 1
advertisements.append(length)
advertisements.append(MANUFACTURER_SPECIFIC_DATA_TYPE)
advertisements.append(data)
break
case CBAdvertisementDataServiceDataKey:
let serviceData = advertisementData[key] as! [CBUUID: Data]
var data = Data()
for item in serviceData {
data.append(item.key.data)
data.append(item.value)
}
let length = UInt8(data.count) + 1
advertisements.append(length)
// TODO: Need to know the real SERVICE_DATA_TYPE
advertisements.append(SERVICE_DATA_128BIT_TYPE)
advertisements.append(data)
break
case CBAdvertisementDataServiceUUIDsKey:
let serviceUUIDs = advertisementData[key] as! [CBUUID]
var data = Data()
for serviceUUID in serviceUUIDs {
data.append(serviceUUID.data)
}
let length = UInt8(data.count) + 1
advertisements.append(length)
// TODO: Need to know the real SERVICE_UUIDS_TYPE
advertisements.append(COMPLETE_SERVICE_UUIDS_128BIT_TYPE)
advertisements.append(data)
break
case CBAdvertisementDataOverflowServiceUUIDsKey:
// TODO: What is an OVERFLOW_SERVICE_UUIDS_TYPE?
// Maybe INCOMPLETE_SERVICE_UUIDS?
break
case CBAdvertisementDataTxPowerLevelKey:
let txPowerLevel = advertisementData[key] as! UInt8
advertisements.append(2)
advertisements.append(TX_POWER_LEVEL_TYPE)
advertisements.append(txPowerLevel)
break
case CBAdvertisementDataIsConnectable:
break
case CBAdvertisementDataSolicitedServiceUUIDsKey:
let serviceUUIDs = advertisementData[key] as! [CBUUID]
var data = Data()
for serviceUUID in serviceUUIDs {
data.append(serviceUUID.data)
}
let length = UInt8(data.count) + 1
advertisements.append(length)
// TODO: Need to know the real SOLICITED_SERVICE_UUIDS_TYPE
advertisements.append(SOLICITTED_SERVICE_UUIDS_128BIT_TYPE)
advertisements.append(data)
break
default:
break
}
}
let connectable = advertisementData[CBAdvertisementDataIsConnectable] as? Bool ?? false
let discovery = Discovery.with {
$0.uuid = peripheral.identifier.uuidString
$0.rssi = RSSI.int32Value
$0.advertisements = advertisements
$0.connectable = connectable
}
let event = try! Message.with {
$0.category = .centralDiscovered
$0.discovery = discovery
}.serializedData()
events?(event)
}
public func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
peripheral.delegate = self
peripheral.discoverServices(nil)
}
public func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
let connect = connects.removeValue(forKey: peripheral)!
let error = FlutterError(code: error!.localizedDescription, message: nil, details: nil)
connect(error)
}
public func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
if connects.keys.contains(peripheral) {
let connect = connects.removeValue(forKey: peripheral)!
let error = FlutterError(code: "GATT disconnected.", message: nil, details: nil)
connect(error)
} else {
let nativeGATT = nativeGATTs.first(where: { $1.value === peripheral })!
nativeGATTs.removeValue(forKey: nativeGATT.key)
if disconnects.keys.contains(peripheral) {
let disconnect = disconnects.removeValue(forKey: peripheral)!
disconnect(nil)
} else {
let connectionLost = GattConnectionLost.with {
$0.key = nativeGATT.key
$0.error = error!.localizedDescription
}
let event = try! Message.with {
$0.category = MessageCategory.gattConnectionLost
$0.connectionLost = connectionLost
}.serializedData()
events?(event)
}
}
}
public func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
if error == nil {
let service = peripheral.services?.first(where: { $0.characteristics == nil })
peripheral.discoverCharacteristics(nil, for: service!)
} else {
central.cancelPeripheralConnection(peripheral)
}
}
public func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
if error == nil {
let characteristic = service.characteristics?.first(where: { $0.descriptors == nil })
if characteristic != nil {
peripheral.discoverDescriptors(for: characteristic!)
}
} else {
central.cancelPeripheralConnection(peripheral)
}
}
public func peripheral(_ peripheral: CBPeripheral, didDiscoverDescriptorsFor characteristic: CBCharacteristic, error: Error?) {
if error == nil {
let nextCharacteristic = characteristic.service.characteristics?.first(where: { $0.descriptors == nil })
if nextCharacteristic == nil {
let nextService = peripheral.services?.first(where: { $0.characteristics == nil })
if nextService == nil {
var nativeServices = [String: NativeGattService]()
var messageServices = [GattService]()
for service in peripheral.services! {
var nativeCharacteristics = [String: NativeGattCharacteristic]()
var messageCharacteristics = [GattCharacteristic]()
for characteristic in service.characteristics! {
var nativeDescriptors = [String: NativeGattDescriptor]()
var messageDescriptors = [GattDescriptor]()
for descriptor in characteristic.descriptors! {
// Add native descriptor.
let nativeDescriptor = NativeGattDescriptor(descriptor)
nativeDescriptors[nativeDescriptor.key] = nativeDescriptor
// Add message descriptor.
let messageDescriptor = GattDescriptor.with {
$0.key = nativeDescriptor.key
$0.uuid = descriptor.uuid.uuidString
}
messageDescriptors.append(messageDescriptor)
}
// Add native characteristic.
let nativeCharacteristic = NativeGattCharacteristic(characteristic, nativeDescriptors)
nativeCharacteristics[nativeCharacteristic.key] = nativeCharacteristic
// Add message characteristic.
let messageCharacteristic = GattCharacteristic.with {
$0.key = nativeCharacteristic.key
$0.uuid = characteristic.uuid.uuidString
$0.canRead = characteristic.properties.contains(.read)
$0.canWrite = characteristic.properties.contains(.write)
$0.canWriteWithoutResponse = characteristic.properties.contains(.writeWithoutResponse)
$0.canNotify = characteristic.properties.contains(.notify)
$0.descriptors = messageDescriptors
}
messageCharacteristics.append(messageCharacteristic)
}
// Add native service.
let nativeService = NativeGattService(service, nativeCharacteristics)
nativeServices[nativeService.key] = nativeService
// Add message service.
let messageService = GattService.with {
$0.key = nativeService.key
$0.uuid = service.uuid.uuidString
$0.characteristics = messageCharacteristics
}
messageServices.append(messageService)
}
// Add native gatt.
let nativeGATT = NativeGATT(peripheral, nativeServices)
nativeGATTs[nativeGATT.key] = nativeGATT
// Add message gatt.
let reply = try! GATT.with {
$0.key = nativeGATT.key
$0.maximumWriteLength = peripheral.maximumWriteLength
$0.services = messageServices
}.serializedData()
let connect = connects.removeValue(forKey: peripheral)!
connect(reply)
} else {
peripheral.discoverCharacteristics(nil, for: nextService!)
}
} else {
peripheral.discoverDescriptors(for: nextCharacteristic!)
}
} else {
central.cancelPeripheralConnection(peripheral)
}
}
public func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
let read = characteristicReads.removeValue(forKey: characteristic)
if read == nil {
let nativeGATT = nativeGATTs.values.first(where: { $0.value === peripheral })!
let nativeService = nativeGATT.services.values.first(where: { $0.value === characteristic.service })!
let nativeCharacteristic = nativeService.characteristics.values.first(where: { $0.value === characteristic })!
let characteristicValue = GattCharacteristicValue.with {
$0.gattKey = nativeGATT.key
$0.serviceKey = nativeService.key
$0.key = nativeCharacteristic.key
$0.value = characteristic.value!
}
let event = try! Message.with {
$0.category = .gattCharacteristicNotify
$0.characteristicValue = characteristicValue
}.serializedData()
events?(event)
} else if error == nil {
read!(characteristic.value!)
} else {
let error = FlutterError(code: error!.localizedDescription, message: nil, details: nil)
read!(error)
}
}
public func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
let write = characteristicWrites.removeValue(forKey: characteristic)!
if error == nil {
write(nil)
} else {
let error = FlutterError(code: error!.localizedDescription, message: nil, details: nil)
write(error)
}
}
public func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
let notify = characteristicNotifies[characteristic]!
if error == nil {
notify(nil)
} else {
let error = FlutterError(code: error!.localizedDescription, message: nil, details: nil)
notify(error)
}
}
public func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor descriptor: CBDescriptor, error: Error?) {
let read = descriptorReads[descriptor]!
if error == nil {
read(descriptor.value!)
} else {
let error = FlutterError(code: error!.localizedDescription, message: nil, details: nil)
read(error)
}
}
public func peripheral(_ peripheral: CBPeripheral, didWriteValueFor descriptor: CBDescriptor, error: Error?) {
let write = descriptorWrites[descriptor]!
if error == nil {
write(nil)
} else {
let error = FlutterError(code: error!.localizedDescription, message: nil, details: nil)
write(error)
}
}
}
extension CBCentralManager {
var messageState: BluetoothState {
switch state {
case .unknown:
return .unsupported
case .resetting:
return .unsupported
case .unsupported:
return .unsupported
case .unauthorized:
return .unsupported
case .poweredOff:
return .poweredOff
case .poweredOn:
return .poweredOn
default:
return .UNRECOGNIZED(-1)
}
}
}
extension CBPeripheral {
var maximumWriteLength: Int32 {
let maximumWriteLengthWithResponse = maximumWriteValueLength(for: .withResponse)
let maximumWriteLengthWithoutResponse = maximumWriteValueLength(for: .withoutResponse)
// TODO: Is this two length the same value?
let maximumWriteLength = min(maximumWriteLengthWithResponse, maximumWriteLengthWithoutResponse)
return Int32(maximumWriteLength)
}
} }

1540
ios/Classes/message.pb.swift Normal file

File diff suppressed because it is too large Load Diff

View File

@ -4,17 +4,18 @@
# #
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'bluetooth_low_energy' s.name = 'bluetooth_low_energy'
s.version = '0.0.1' s.version = '0.1.0'
s.summary = 'A new flutter plugin project.' s.summary = 'A bluetooth low energy plugin for flutter.'
s.description = <<-DESC s.description = <<-DESC
A new flutter plugin project. A bluetooth low energy plugin for flutter, which can be used to develope central role apps.
DESC DESC
s.homepage = 'http://example.com' s.homepage = 'https://github.com/yanshouwang/bluetooth_low_energy'
s.license = { :file => '../LICENSE' } s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email@example.com' } s.author = { 'yanshouwang' => 'yanshouwang@outlook.com' }
s.source = { :path => '.' } s.source = { :path => '.' }
s.source_files = 'Classes/**/*' s.source_files = 'Classes/**/*'
s.dependency 'Flutter' s.dependency 'Flutter'
s.dependency 'SwiftProtobuf', '~> 1.0'
s.platform = :ios, '8.0' s.platform = :ios, '8.0'
# Flutter.framework does not contain a i386 slice. # Flutter.framework does not contain a i386 slice.

View File

@ -15,6 +15,5 @@ part 'src/gatt.dart';
part 'src/gatt_service.dart'; part 'src/gatt_service.dart';
part 'src/gatt_characteristic.dart'; part 'src/gatt_characteristic.dart';
part 'src/gatt_descriptor.dart'; part 'src/gatt_descriptor.dart';
part 'src/mac.dart';
part 'src/uuid.dart'; part 'src/uuid.dart';
part 'src/extension.dart'; part 'src/extension.dart';

View File

@ -2,31 +2,39 @@ part of bluetooth_low_energy;
/// The abstract base class that manages central and peripheral objects. /// The abstract base class that manages central and peripheral objects.
abstract class Bluetooth { abstract class Bluetooth {
/// The availability of the bluetooth.
Future<bool> get available;
/// The current state of the bluetooth. /// The current state of the bluetooth.
Future<bool> get state; Future<BluetoothState> get state;
/// The bluetooths state changed. /// The bluetooths state changed.
Stream<bool> get stateChanged; Stream<BluetoothState> get stateChanged;
} }
class _Bluetooth implements Bluetooth { class _Bluetooth implements Bluetooth {
@override @override
Future<bool> get available => method Future<BluetoothState> get state {
.invokeMethod<bool>(proto.MessageCategory.BLUETOOTH_AVAILABLE.name) final message = proto.Message(
.then((value) => value!); category: proto.MessageCategory.BLUETOOTH_STATE,
).writeToBuffer();
return method
.invokeMethod<int>('', message)
.then((value) => BluetoothState.values[value!]);
}
@override @override
Future<bool> get state => method Stream<BluetoothState> get stateChanged => stream
.invokeMethod<bool>(proto.MessageCategory.BLUETOOTH_STATE.name)
.then((value) => value!);
@override
Stream<bool> get stateChanged => stream
.map((event) => proto.Message.fromBuffer(event))
.where((message) => .where((message) =>
message.category == proto.MessageCategory.BLUETOOTH_STATE) message.category == proto.MessageCategory.BLUETOOTH_STATE)
.map((message) => message.state); .map((message) => message.state.toState());
}
/// TO BE DONE.
enum BluetoothState {
/// TO BE DONE.
unsupported,
/// TO BE DONE.
poweredOff,
/// TO BE DONE.
poweredOn,
} }

View File

@ -14,39 +14,43 @@ abstract class Central extends Bluetooth {
Future stopDiscovery(); Future stopDiscovery();
/// Establishes a local connection to a peripheral. /// Establishes a local connection to a peripheral.
Future<GATT> connect(MAC address); Future<GATT> connect(UUID uuid);
} }
class _Central extends _Bluetooth implements Central { class _Central extends _Bluetooth implements Central {
@override @override
Stream<Discovery> get discovered => stream Stream<Discovery> get discovered => stream
.map((event) => proto.Message.fromBuffer(event))
.where((message) => .where((message) =>
message.category == proto.MessageCategory.CENTRAL_DISCOVERED) message.category == proto.MessageCategory.CENTRAL_DISCOVERED)
.map((message) => message.discovery.conversion); .map((message) => message.discovery.toDiscovery());
@override @override
Future startDiscovery({List<UUID>? services}) { Future startDiscovery({List<UUID>? services}) {
final name = proto.MessageCategory.CENTRAL_START_DISCOVERY.name; final message = proto.Message(
final arguments = proto.StartDiscoveryArguments( category: proto.MessageCategory.CENTRAL_START_DISCOVERY,
services: services?.map((uuid) => uuid.name), startDiscoveryArguments: proto.StartDiscoveryArguments(
services: services?.map((uuid) => uuid.name),
),
).writeToBuffer(); ).writeToBuffer();
return method.invokeMethod(name, arguments); return method.invokeMethod('', message);
} }
@override @override
Future stopDiscovery() { Future stopDiscovery() {
final name = proto.MessageCategory.CENTRAL_STOP_DISCOVERY.name; final message = proto.Message(
return method.invokeMethod(name); category: proto.MessageCategory.CENTRAL_STOP_DISCOVERY,
).writeToBuffer();
return method.invokeMethod('', message);
} }
@override @override
Future<GATT> connect(MAC address) { Future<GATT> connect(UUID uuid) {
final name = proto.MessageCategory.CENTRAL_CONNECT.name; final message = proto.Message(
final arguments = category: proto.MessageCategory.CENTRAL_CONNECT,
proto.ConnectArguments(address: address.name).writeToBuffer(); connectArguments: proto.ConnectArguments(uuid: uuid.name),
).writeToBuffer();
return method return method
.invokeMethod<List<int>>(name, arguments) .invokeMethod<List<int>>('', message)
.then((value) => proto.GATT.fromBuffer(value!).convert(address)); .then((value) => proto.GATT.fromBuffer(value!).toGATT());
} }
} }

View File

@ -3,22 +3,27 @@ part of bluetooth_low_energy;
/// TO BE DONE. /// TO BE DONE.
abstract class Discovery { abstract class Discovery {
/// TO BE DONE. /// TO BE DONE.
MAC get address; UUID get uuid;
/// TO BE DONE. /// TO BE DONE.
int get rssi; int get rssi;
/// TO BE DONE. /// TO BE DONE.
Map<int, List<int>> get advertisements; Map<int, List<int>> get advertisements;
/// TO BE DONE.
bool get connectable;
} }
class _Discovery implements Discovery { class _Discovery implements Discovery {
@override @override
final MAC address; final UUID uuid;
@override @override
final int rssi; final int rssi;
@override @override
final Map<int, List<int>> advertisements; final Map<int, List<int>> advertisements;
@override
final bool connectable;
_Discovery(this.address, this.rssi, this.advertisements); _Discovery(this.uuid, this.rssi, this.advertisements, this.connectable);
} }

View File

@ -1,136 +1,114 @@
part of bluetooth_low_energy; part of bluetooth_low_energy;
extension on String { extension on String {
String get nameOfMAC { String get uuidName {
final upper = toUpperCase(); final lowerCase = toLowerCase();
final exp = RegExp(
r'^[0-9A-F]{2}(:[0-9A-F]{2}){5}$',
multiLine: true,
caseSensitive: true,
);
if (exp.hasMatch(upper)) {
return upper;
}
throw ArgumentError.value(this);
}
List<int> get valueOfMAC {
final from = RegExp(r':');
final encoded = replaceAll(from, '');
return hex.decode(encoded);
}
String get nameOfUUID {
final upper = toUpperCase();
final exp0 = RegExp( final exp0 = RegExp(
r'[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$', r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$',
multiLine: true, caseSensitive: false,
caseSensitive: true,
); );
if (exp0.hasMatch(upper)) { if (exp0.hasMatch(lowerCase)) {
return upper; return lowerCase;
} }
final exp1 = RegExp( final exp1 = RegExp(
r'^[0-9A-F]{4}$', r'^[0-9a-f]{4}$',
multiLine: true, caseSensitive: false,
caseSensitive: true,
); );
if (exp1.hasMatch(upper)) { if (exp1.hasMatch(lowerCase)) {
return '0000$upper-0000-1000-8000-00805F9B34FB'; return '0000$lowerCase-0000-1000-8000-00805f9b34fb';
} }
throw ArgumentError.value(this); throw ArgumentError.value(this);
} }
List<int> get valueOfUUID { List<int> get uuidVaue {
final from = RegExp(r'-'); final from = RegExp(r'-');
final encoded = replaceAll(from, ''); final encoded = replaceAll(from, '');
return hex.decode(encoded); return hex.decode(encoded);
} }
MAC get conversionOfMAC => MAC(this); UUID get uuid => UUID(this);
UUID get conversionOfUUID => UUID(this); Exception get exceptoin => Exception(this);
}
extension on proto.BluetoothState {
BluetoothState toState() => BluetoothState.values[value];
} }
extension on proto.Discovery { extension on proto.Discovery {
Discovery get conversion { Discovery toDiscovery() {
final convertedAdvertisements = <int, List<int>>{}; final advertisements = <int, List<int>>{};
var start = 0; var start = 0;
while (start < advertisements.length) { while (start < this.advertisements.length) {
final length = advertisements[start++]; final length = this.advertisements[start++];
if (length == 0) { if (length == 0) break;
break;
}
final end = start + length; final end = start + length;
final key = advertisements[start++]; final key = this.advertisements[start++];
final value = advertisements.sublist(start, end); final value = this.advertisements.sublist(start, end);
start = end; start = end;
convertedAdvertisements[key] = value; advertisements[key] = value;
} }
return _Discovery(address.conversionOfMAC, rssi, convertedAdvertisements); return _Discovery(uuid.uuid, rssi, advertisements, connectable);
} }
} }
extension on proto.GATT { extension on proto.GATT {
GATT convert(MAC address) { GATT toGATT() {
final convertedServices = { final services = {
for (var service in services) for (var service in this.services)
service.uuid.conversionOfUUID: service.convert(address) service.uuid.uuid: service.toGattService(key)
}; };
return _GATT(address, id, mtu, convertedServices); return _GATT(key, maximumWriteLength, services);
} }
} }
extension on proto.GattService { extension on proto.GattService {
GattService convert(MAC address) { GattService toGattService(String gattKey) {
final convertedUUID = uuid.conversionOfUUID; final uuid = this.uuid.uuid;
final convertedCharacteristics = { final characteristics = {
for (var characteristic in characteristics) for (var characteristic in this.characteristics)
characteristic.uuid.conversionOfUUID: characteristic.uuid.uuid: characteristic.toGattCharacteristic(
characteristic.convert(address, convertedUUID) gattKey,
key,
)
}; };
return _GattService( return _GattService(gattKey, key, uuid, characteristics);
address,
id,
convertedUUID,
convertedCharacteristics,
);
} }
} }
extension on proto.GattCharacteristic { extension on proto.GattCharacteristic {
GattCharacteristic convert(MAC address, UUID serviceUUID) { GattCharacteristic toGattCharacteristic(String gattKey, String serviceKey) {
final convertedUUID = uuid.conversionOfUUID; final uuid = this.uuid.uuid;
final convertedDescriptors = { final descriptors = {
for (var descriptor in descriptors) for (var descriptor in this.descriptors)
descriptor.uuid.conversionOfUUID: descriptor.uuid.uuid: descriptor.toGattDescriptor(
descriptor.convert(address, serviceUUID, convertedUUID) gattKey,
serviceKey,
key,
)
}; };
return _GattCharacteristic( return _GattCharacteristic(
address, gattKey,
serviceUUID, serviceKey,
id, key,
convertedUUID, uuid,
convertedDescriptors,
canRead, canRead,
canWrite, canWrite,
canWriteWithoutResponse, canWriteWithoutResponse,
canNotify, canNotify,
descriptors,
); );
} }
} }
extension on proto.GattDescriptor { extension on proto.GattDescriptor {
GattDescriptor convert( GattDescriptor toGattDescriptor(
MAC address, UUID serviceUUID, UUID characteristicUUID) { String gattKey,
final convertedUUID = uuid.conversionOfUUID; String serviceKey,
return _GattDescriptor( String characteristicKey,
address, ) {
serviceUUID, final uuid = this.uuid.uuid;
characteristicUUID, return _GattDescriptor(gattKey, serviceKey, characteristicKey, key, uuid);
id,
convertedUUID,
);
} }
} }

View File

@ -3,10 +3,10 @@ part of bluetooth_low_energy;
/// TO BE DONE. /// TO BE DONE.
abstract class GATT { abstract class GATT {
/// TO BE DONE. /// TO BE DONE.
int get mtu; int get maximumWriteLength;
/// TO BE DONE. /// TO BE DONE.
Stream<int> get connectionLost; Stream<Exception> get connectionLost;
/// TO BE DONE. /// TO BE DONE.
Map<UUID, GattService> get services; Map<UUID, GattService> get services;
@ -16,29 +16,27 @@ abstract class GATT {
} }
class _GATT implements GATT { class _GATT implements GATT {
_GATT(this.address, this.id, this.mtu, this.services); _GATT(this.key, this.maximumWriteLength, this.services);
final MAC address; final String key;
final int id;
@override @override
final int mtu; final int maximumWriteLength;
@override @override
final Map<UUID, GattService> services; final Map<UUID, GattService> services;
@override @override
Stream<int> get connectionLost => stream Stream<Exception> get connectionLost => stream
.map((event) => proto.Message.fromBuffer(event)) .where((message) =>
.where((event) => message.category == proto.MessageCategory.GATT_CONNECTION_LOST &&
event.category == proto.MessageCategory.GATT_CONNECTION_LOST && message.connectionLost.key == key)
event.connectionLost.id == id) .map((message) => message.connectionLost.error.exceptoin);
.map((event) => event.connectionLost.errorCode);
@override @override
Future disconnect() { Future disconnect() {
final name = proto.MessageCategory.GATT_DISCONNECT.name; final message = proto.Message(
final arguments = category: proto.MessageCategory.GATT_DISCONNECT,
proto.GattDisconnectArguments(address: address.name, id: id) disconnectArguments: proto.GattDisconnectArguments(key: key),
.writeToBuffer(); ).writeToBuffer();
return method.invokeMethod(name, arguments); return method.invokeMethod('', message);
} }
} }

View File

@ -5,9 +5,6 @@ abstract class GattCharacteristic {
/// TO BE DONE. /// TO BE DONE.
UUID get uuid; UUID get uuid;
/// TO BE DONE.
Map<UUID, GattDescriptor> get descriptors;
/// TO BE DONE. /// TO BE DONE.
bool get canRead; bool get canRead;
@ -20,6 +17,9 @@ abstract class GattCharacteristic {
/// TO BE DONE. /// TO BE DONE.
bool get canNotify; bool get canNotify;
/// TO BE DONE.
Map<UUID, GattDescriptor> get descriptors;
/// TO BE DONE. /// TO BE DONE.
Stream<List<int>> get valueChanged; Stream<List<int>> get valueChanged;
@ -35,25 +35,23 @@ abstract class GattCharacteristic {
class _GattCharacteristic implements GattCharacteristic { class _GattCharacteristic implements GattCharacteristic {
_GattCharacteristic( _GattCharacteristic(
this.address, this.gattKey,
this.serviceUUID, this.serviceKey,
this.id, this.key,
this.uuid, this.uuid,
this.descriptors,
this.canRead, this.canRead,
this.canWrite, this.canWrite,
this.canWriteWithoutResponse, this.canWriteWithoutResponse,
this.canNotify, this.canNotify,
this.descriptors,
); );
final MAC address; final String gattKey;
final UUID serviceUUID; final String serviceKey;
final int id; final String key;
@override @override
final UUID uuid; final UUID uuid;
@override @override
final Map<UUID, GattDescriptor> descriptors;
@override
final bool canRead; final bool canRead;
@override @override
final bool canWrite; final bool canWrite;
@ -61,54 +59,58 @@ class _GattCharacteristic implements GattCharacteristic {
final bool canWriteWithoutResponse; final bool canWriteWithoutResponse;
@override @override
final bool canNotify; final bool canNotify;
@override
final Map<UUID, GattDescriptor> descriptors;
@override @override
Stream<List<int>> get valueChanged => stream Stream<List<int>> get valueChanged => stream
.map((event) => proto.Message.fromBuffer(event))
.where((message) => .where((message) =>
message.category == message.category ==
proto.MessageCategory.GATT_CHARACTERISTIC_NOTIFY && proto.MessageCategory.GATT_CHARACTERISTIC_NOTIFY &&
message.characteristicValue.id == id) message.characteristicValue.gattKey == gattKey &&
message.characteristicValue.serviceKey == serviceKey &&
message.characteristicValue.key == key)
.map((message) => message.characteristicValue.value); .map((message) => message.characteristicValue.value);
@override @override
Future<List<int>> read() { Future<List<int>> read() {
final name = proto.MessageCategory.GATT_CHARACTERISTIC_READ.name; final message = proto.Message(
final arguments = proto.GattCharacteristicReadArguments( category: proto.MessageCategory.GATT_CHARACTERISTIC_READ,
address: address.name, characteristicReadArguments: proto.GattCharacteristicReadArguments(
serviceUuid: serviceUUID.name, gattKey: gattKey,
uuid: uuid.name, serviceKey: serviceKey,
id: id, key: key,
),
).writeToBuffer(); ).writeToBuffer();
return method return method.invokeListMethod<int>('', message).then((value) => value!);
.invokeListMethod<int>(name, arguments)
.then((value) => value!);
} }
@override @override
Future write(List<int> value, {bool withoutResponse = false}) { Future write(List<int> value, {bool withoutResponse = false}) {
final name = proto.MessageCategory.GATT_CHARACTERISTIC_WRITE.name; final message = proto.Message(
final arguments = proto.GattCharacteristicWriteArguments( category: proto.MessageCategory.GATT_CHARACTERISTIC_WRITE,
address: address.name, characteristicWriteArguments: proto.GattCharacteristicWriteArguments(
serviceUuid: serviceUUID.name, gattKey: gattKey,
uuid: uuid.name, serviceKey: serviceKey,
id: id, key: key,
value: value, value: value,
withoutResponse: withoutResponse, withoutResponse: withoutResponse,
),
).writeToBuffer(); ).writeToBuffer();
return method.invokeMethod(name, arguments); return method.invokeMethod('', message);
} }
@override @override
Future notify(bool state) { Future notify(bool state) {
final name = proto.MessageCategory.GATT_CHARACTERISTIC_NOTIFY.name; final message = proto.Message(
final arguments = proto.GattCharacteristicNotifyArguments( category: proto.MessageCategory.GATT_CHARACTERISTIC_NOTIFY,
address: address.name, characteristicNotifyArguments: proto.GattCharacteristicNotifyArguments(
serviceUuid: serviceUUID.name, gattKey: gattKey,
uuid: uuid.name, serviceKey: serviceKey,
id: id, key: key,
state: state, state: state,
),
).writeToBuffer(); ).writeToBuffer();
return method.invokeMethod(name, arguments); return method.invokeMethod('', message);
} }
} }

View File

@ -14,46 +14,46 @@ abstract class GattDescriptor {
class _GattDescriptor implements GattDescriptor { class _GattDescriptor implements GattDescriptor {
_GattDescriptor( _GattDescriptor(
this.address, this.gattKey,
this.serviceUUID, this.serviceKey,
this.characteristicUUID, this.characteristicKey,
this.id, this.key,
this.uuid, this.uuid,
); );
final MAC address; final String gattKey;
final UUID serviceUUID; final String serviceKey;
final UUID characteristicUUID; final String characteristicKey;
final int id; final String key;
@override @override
final UUID uuid; final UUID uuid;
@override @override
Future<List<int>> read() { Future<List<int>> read() {
final name = proto.MessageCategory.GATT_DESCRIPTOR_READ.name; final message = proto.Message(
final arguments = proto.GattDescriptorReadArguments( category: proto.MessageCategory.GATT_DESCRIPTOR_READ,
address: address.name, descriptorReadArguments: proto.GattDescriptorReadArguments(
serviceUuid: serviceUUID.name, gattKey: gattKey,
characteristicUuid: characteristicUUID.name, serviceKey: serviceKey,
uuid: uuid.name, characteristicKey: characteristicKey,
id: id, key: key,
),
).writeToBuffer(); ).writeToBuffer();
return method return method.invokeListMethod<int>('', message).then((value) => value!);
.invokeListMethod<int>(name, arguments)
.then((value) => value!);
} }
@override @override
Future write(List<int> value) { Future write(List<int> value) {
final name = proto.MessageCategory.GATT_DESCRIPTOR_WRITE.name; final message = proto.Message(
final arguments = proto.GattDescriptorWriteArguments( category: proto.MessageCategory.GATT_DESCRIPTOR_WRITE,
address: address.name, descriptorWriteArguments: proto.GattDescriptorWriteArguments(
serviceUuid: serviceUUID.name, gattKey: gattKey,
characteristicUuid: characteristicUUID.name, serviceKey: serviceKey,
uuid: uuid.name, characteristicKey: characteristicKey,
id: id, key: key,
value: value, value: value,
),
).writeToBuffer(); ).writeToBuffer();
return method.invokeMethod(name, arguments); return method.invokeMethod('', message);
} }
} }

View File

@ -10,10 +10,10 @@ abstract class GattService {
} }
class _GattService implements GattService { class _GattService implements GattService {
_GattService(this.address, this.id, this.uuid, this.characteristics); _GattService(this.gattKey, this.key, this.uuid, this.characteristics);
final MAC address; final String gattKey;
final int id; final String key;
@override @override
final UUID uuid; final UUID uuid;
@override @override

View File

@ -1,34 +0,0 @@
part of bluetooth_low_energy;
/// TO BE DONE.
abstract class MAC {
/// TO BE DONE.
List<int> get value;
/// TO BE DONE.
String get name;
/// TO BE DONE.
factory MAC(String str) => _MAC(str);
}
class _MAC implements MAC {
@override
final String name;
@override
final List<int> value;
@override
final int hashCode;
_MAC(String str) : this.name(str.nameOfMAC);
_MAC.name(String name) : this.nameValue(name, name.valueOfMAC);
_MAC.nameValue(this.name, this.value) : hashCode = equality.hash(value);
@override
String toString() => name;
@override
bool operator ==(other) => other is MAC && other.hashCode == hashCode;
}

File diff suppressed because it is too large Load Diff

View File

@ -10,74 +10,68 @@ import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb; import 'package:protobuf/protobuf.dart' as $pb;
class MessageCategory extends $pb.ProtobufEnum { class MessageCategory extends $pb.ProtobufEnum {
static const MessageCategory BLUETOOTH_AVAILABLE = MessageCategory._(
0,
const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? ''
: 'BLUETOOTH_AVAILABLE');
static const MessageCategory BLUETOOTH_STATE = MessageCategory._( static const MessageCategory BLUETOOTH_STATE = MessageCategory._(
1, 0,
const $core.bool.fromEnvironment('protobuf.omit_enum_names') const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? '' ? ''
: 'BLUETOOTH_STATE'); : 'BLUETOOTH_STATE');
static const MessageCategory CENTRAL_START_DISCOVERY = MessageCategory._( static const MessageCategory CENTRAL_START_DISCOVERY = MessageCategory._(
2, 1,
const $core.bool.fromEnvironment('protobuf.omit_enum_names') const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? '' ? ''
: 'CENTRAL_START_DISCOVERY'); : 'CENTRAL_START_DISCOVERY');
static const MessageCategory CENTRAL_STOP_DISCOVERY = MessageCategory._( static const MessageCategory CENTRAL_STOP_DISCOVERY = MessageCategory._(
3, 2,
const $core.bool.fromEnvironment('protobuf.omit_enum_names') const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? '' ? ''
: 'CENTRAL_STOP_DISCOVERY'); : 'CENTRAL_STOP_DISCOVERY');
static const MessageCategory CENTRAL_DISCOVERED = MessageCategory._( static const MessageCategory CENTRAL_DISCOVERED = MessageCategory._(
4, 3,
const $core.bool.fromEnvironment('protobuf.omit_enum_names') const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? '' ? ''
: 'CENTRAL_DISCOVERED'); : 'CENTRAL_DISCOVERED');
static const MessageCategory CENTRAL_CONNECT = MessageCategory._( static const MessageCategory CENTRAL_CONNECT = MessageCategory._(
5, 4,
const $core.bool.fromEnvironment('protobuf.omit_enum_names') const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? '' ? ''
: 'CENTRAL_CONNECT'); : 'CENTRAL_CONNECT');
static const MessageCategory GATT_DISCONNECT = MessageCategory._( static const MessageCategory GATT_DISCONNECT = MessageCategory._(
6, 5,
const $core.bool.fromEnvironment('protobuf.omit_enum_names') const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? '' ? ''
: 'GATT_DISCONNECT'); : 'GATT_DISCONNECT');
static const MessageCategory GATT_CONNECTION_LOST = MessageCategory._( static const MessageCategory GATT_CONNECTION_LOST = MessageCategory._(
7, 6,
const $core.bool.fromEnvironment('protobuf.omit_enum_names') const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? '' ? ''
: 'GATT_CONNECTION_LOST'); : 'GATT_CONNECTION_LOST');
static const MessageCategory GATT_CHARACTERISTIC_READ = MessageCategory._( static const MessageCategory GATT_CHARACTERISTIC_READ = MessageCategory._(
8, 7,
const $core.bool.fromEnvironment('protobuf.omit_enum_names') const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? '' ? ''
: 'GATT_CHARACTERISTIC_READ'); : 'GATT_CHARACTERISTIC_READ');
static const MessageCategory GATT_CHARACTERISTIC_WRITE = MessageCategory._( static const MessageCategory GATT_CHARACTERISTIC_WRITE = MessageCategory._(
9, 8,
const $core.bool.fromEnvironment('protobuf.omit_enum_names') const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? '' ? ''
: 'GATT_CHARACTERISTIC_WRITE'); : 'GATT_CHARACTERISTIC_WRITE');
static const MessageCategory GATT_CHARACTERISTIC_NOTIFY = MessageCategory._( static const MessageCategory GATT_CHARACTERISTIC_NOTIFY = MessageCategory._(
10, 9,
const $core.bool.fromEnvironment('protobuf.omit_enum_names') const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? '' ? ''
: 'GATT_CHARACTERISTIC_NOTIFY'); : 'GATT_CHARACTERISTIC_NOTIFY');
static const MessageCategory GATT_DESCRIPTOR_READ = MessageCategory._( static const MessageCategory GATT_DESCRIPTOR_READ = MessageCategory._(
11, 10,
const $core.bool.fromEnvironment('protobuf.omit_enum_names') const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? '' ? ''
: 'GATT_DESCRIPTOR_READ'); : 'GATT_DESCRIPTOR_READ');
static const MessageCategory GATT_DESCRIPTOR_WRITE = MessageCategory._( static const MessageCategory GATT_DESCRIPTOR_WRITE = MessageCategory._(
12, 11,
const $core.bool.fromEnvironment('protobuf.omit_enum_names') const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? '' ? ''
: 'GATT_DESCRIPTOR_WRITE'); : 'GATT_DESCRIPTOR_WRITE');
static const $core.List<MessageCategory> values = <MessageCategory>[ static const $core.List<MessageCategory> values = <MessageCategory>[
BLUETOOTH_AVAILABLE,
BLUETOOTH_STATE, BLUETOOTH_STATE,
CENTRAL_START_DISCOVERY, CENTRAL_START_DISCOVERY,
CENTRAL_STOP_DISCOVERY, CENTRAL_STOP_DISCOVERY,
@ -98,3 +92,33 @@ class MessageCategory extends $pb.ProtobufEnum {
const MessageCategory._($core.int v, $core.String n) : super(v, n); const MessageCategory._($core.int v, $core.String n) : super(v, n);
} }
class BluetoothState extends $pb.ProtobufEnum {
static const BluetoothState UNSUPPORTED = BluetoothState._(
0,
const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? ''
: 'UNSUPPORTED');
static const BluetoothState POWERED_OFF = BluetoothState._(
1,
const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? ''
: 'POWERED_OFF');
static const BluetoothState POWERED_ON = BluetoothState._(
2,
const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? ''
: 'POWERED_ON');
static const $core.List<BluetoothState> values = <BluetoothState>[
UNSUPPORTED,
POWERED_OFF,
POWERED_ON,
];
static final $core.Map<$core.int, BluetoothState> _byValue =
$pb.ProtobufEnum.initByValue(values);
static BluetoothState? valueOf($core.int value) => _byValue[value];
const BluetoothState._($core.int v, $core.String n) : super(v, n);
}

View File

@ -13,25 +13,37 @@ import 'dart:typed_data' as $typed_data;
const MessageCategory$json = const { const MessageCategory$json = const {
'1': 'MessageCategory', '1': 'MessageCategory',
'2': const [ '2': const [
const {'1': 'BLUETOOTH_AVAILABLE', '2': 0}, const {'1': 'BLUETOOTH_STATE', '2': 0},
const {'1': 'BLUETOOTH_STATE', '2': 1}, const {'1': 'CENTRAL_START_DISCOVERY', '2': 1},
const {'1': 'CENTRAL_START_DISCOVERY', '2': 2}, const {'1': 'CENTRAL_STOP_DISCOVERY', '2': 2},
const {'1': 'CENTRAL_STOP_DISCOVERY', '2': 3}, const {'1': 'CENTRAL_DISCOVERED', '2': 3},
const {'1': 'CENTRAL_DISCOVERED', '2': 4}, const {'1': 'CENTRAL_CONNECT', '2': 4},
const {'1': 'CENTRAL_CONNECT', '2': 5}, const {'1': 'GATT_DISCONNECT', '2': 5},
const {'1': 'GATT_DISCONNECT', '2': 6}, const {'1': 'GATT_CONNECTION_LOST', '2': 6},
const {'1': 'GATT_CONNECTION_LOST', '2': 7}, const {'1': 'GATT_CHARACTERISTIC_READ', '2': 7},
const {'1': 'GATT_CHARACTERISTIC_READ', '2': 8}, const {'1': 'GATT_CHARACTERISTIC_WRITE', '2': 8},
const {'1': 'GATT_CHARACTERISTIC_WRITE', '2': 9}, const {'1': 'GATT_CHARACTERISTIC_NOTIFY', '2': 9},
const {'1': 'GATT_CHARACTERISTIC_NOTIFY', '2': 10}, const {'1': 'GATT_DESCRIPTOR_READ', '2': 10},
const {'1': 'GATT_DESCRIPTOR_READ', '2': 11}, const {'1': 'GATT_DESCRIPTOR_WRITE', '2': 11},
const {'1': 'GATT_DESCRIPTOR_WRITE', '2': 12},
], ],
}; };
/// Descriptor for `MessageCategory`. Decode as a `google.protobuf.EnumDescriptorProto`. /// Descriptor for `MessageCategory`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List messageCategoryDescriptor = $convert.base64Decode( final $typed_data.Uint8List messageCategoryDescriptor = $convert.base64Decode(
'Cg9NZXNzYWdlQ2F0ZWdvcnkSFwoTQkxVRVRPT1RIX0FWQUlMQUJMRRAAEhMKD0JMVUVUT09USF9TVEFURRABEhsKF0NFTlRSQUxfU1RBUlRfRElTQ09WRVJZEAISGgoWQ0VOVFJBTF9TVE9QX0RJU0NPVkVSWRADEhYKEkNFTlRSQUxfRElTQ09WRVJFRBAEEhMKD0NFTlRSQUxfQ09OTkVDVBAFEhMKD0dBVFRfRElTQ09OTkVDVBAGEhgKFEdBVFRfQ09OTkVDVElPTl9MT1NUEAcSHAoYR0FUVF9DSEFSQUNURVJJU1RJQ19SRUFEEAgSHQoZR0FUVF9DSEFSQUNURVJJU1RJQ19XUklURRAJEh4KGkdBVFRfQ0hBUkFDVEVSSVNUSUNfTk9USUZZEAoSGAoUR0FUVF9ERVNDUklQVE9SX1JFQUQQCxIZChVHQVRUX0RFU0NSSVBUT1JfV1JJVEUQDA=='); 'Cg9NZXNzYWdlQ2F0ZWdvcnkSEwoPQkxVRVRPT1RIX1NUQVRFEAASGwoXQ0VOVFJBTF9TVEFSVF9ESVNDT1ZFUlkQARIaChZDRU5UUkFMX1NUT1BfRElTQ09WRVJZEAISFgoSQ0VOVFJBTF9ESVNDT1ZFUkVEEAMSEwoPQ0VOVFJBTF9DT05ORUNUEAQSEwoPR0FUVF9ESVNDT05ORUNUEAUSGAoUR0FUVF9DT05ORUNUSU9OX0xPU1QQBhIcChhHQVRUX0NIQVJBQ1RFUklTVElDX1JFQUQQBxIdChlHQVRUX0NIQVJBQ1RFUklTVElDX1dSSVRFEAgSHgoaR0FUVF9DSEFSQUNURVJJU1RJQ19OT1RJRlkQCRIYChRHQVRUX0RFU0NSSVBUT1JfUkVBRBAKEhkKFUdBVFRfREVTQ1JJUFRPUl9XUklURRAL');
@$core.Deprecated('Use bluetoothStateDescriptor instead')
const BluetoothState$json = const {
'1': 'BluetoothState',
'2': const [
const {'1': 'UNSUPPORTED', '2': 0},
const {'1': 'POWERED_OFF', '2': 1},
const {'1': 'POWERED_ON', '2': 2},
],
};
/// Descriptor for `BluetoothState`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List bluetoothStateDescriptor = $convert.base64Decode(
'Cg5CbHVldG9vdGhTdGF0ZRIPCgtVTlNVUFBPUlRFRBAAEg8KC1BPV0VSRURfT0ZGEAESDgoKUE9XRVJFRF9PThAC');
@$core.Deprecated('Use messageDescriptor instead') @$core.Deprecated('Use messageDescriptor instead')
const Message$json = const { const Message$json = const {
'1': 'Message', '1': 'Message',
@ -44,35 +56,117 @@ const Message$json = const {
'6': '.dev.yanshouwang.bluetooth_low_energy.MessageCategory', '6': '.dev.yanshouwang.bluetooth_low_energy.MessageCategory',
'10': 'category' '10': 'category'
}, },
const {'1': 'state', '3': 2, '4': 1, '5': 8, '9': 0, '10': 'state'}, const {
'1': 'state',
'3': 2,
'4': 1,
'5': 14,
'6': '.dev.yanshouwang.bluetooth_low_energy.BluetoothState',
'9': 0,
'10': 'state'
},
const {
'1': 'startDiscoveryArguments',
'3': 3,
'4': 1,
'5': 11,
'6': '.dev.yanshouwang.bluetooth_low_energy.StartDiscoveryArguments',
'9': 0,
'10': 'startDiscoveryArguments'
},
const { const {
'1': 'discovery', '1': 'discovery',
'3': 3, '3': 4,
'4': 1, '4': 1,
'5': 11, '5': 11,
'6': '.dev.yanshouwang.bluetooth_low_energy.Discovery', '6': '.dev.yanshouwang.bluetooth_low_energy.Discovery',
'9': 0, '9': 0,
'10': 'discovery' '10': 'discovery'
}, },
const {'1': 'scanning', '3': 4, '4': 1, '5': 8, '9': 0, '10': 'scanning'},
const { const {
'1': 'connectionLost', '1': 'connectArguments',
'3': 5, '3': 5,
'4': 1, '4': 1,
'5': 11, '5': 11,
'6': '.dev.yanshouwang.bluetooth_low_energy.ConnectionLost', '6': '.dev.yanshouwang.bluetooth_low_energy.ConnectArguments',
'9': 0,
'10': 'connectArguments'
},
const {
'1': 'disconnectArguments',
'3': 6,
'4': 1,
'5': 11,
'6': '.dev.yanshouwang.bluetooth_low_energy.GattDisconnectArguments',
'9': 0,
'10': 'disconnectArguments'
},
const {
'1': 'connectionLost',
'3': 7,
'4': 1,
'5': 11,
'6': '.dev.yanshouwang.bluetooth_low_energy.GattConnectionLost',
'9': 0, '9': 0,
'10': 'connectionLost' '10': 'connectionLost'
}, },
const {
'1': 'characteristicReadArguments',
'3': 8,
'4': 1,
'5': 11,
'6':
'.dev.yanshouwang.bluetooth_low_energy.GattCharacteristicReadArguments',
'9': 0,
'10': 'characteristicReadArguments'
},
const {
'1': 'characteristicWriteArguments',
'3': 9,
'4': 1,
'5': 11,
'6':
'.dev.yanshouwang.bluetooth_low_energy.GattCharacteristicWriteArguments',
'9': 0,
'10': 'characteristicWriteArguments'
},
const {
'1': 'characteristicNotifyArguments',
'3': 10,
'4': 1,
'5': 11,
'6':
'.dev.yanshouwang.bluetooth_low_energy.GattCharacteristicNotifyArguments',
'9': 0,
'10': 'characteristicNotifyArguments'
},
const { const {
'1': 'characteristicValue', '1': 'characteristicValue',
'3': 6, '3': 11,
'4': 1, '4': 1,
'5': 11, '5': 11,
'6': '.dev.yanshouwang.bluetooth_low_energy.GattCharacteristicValue', '6': '.dev.yanshouwang.bluetooth_low_energy.GattCharacteristicValue',
'9': 0, '9': 0,
'10': 'characteristicValue' '10': 'characteristicValue'
}, },
const {
'1': 'descriptorReadArguments',
'3': 12,
'4': 1,
'5': 11,
'6': '.dev.yanshouwang.bluetooth_low_energy.GattDescriptorReadArguments',
'9': 0,
'10': 'descriptorReadArguments'
},
const {
'1': 'descriptorWriteArguments',
'3': 13,
'4': 1,
'5': 11,
'6': '.dev.yanshouwang.bluetooth_low_energy.GattDescriptorWriteArguments',
'9': 0,
'10': 'descriptorWriteArguments'
},
], ],
'8': const [ '8': const [
const {'1': 'value'}, const {'1': 'value'},
@ -81,7 +175,7 @@ const Message$json = const {
/// Descriptor for `Message`. Decode as a `google.protobuf.DescriptorProto`. /// Descriptor for `Message`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List messageDescriptor = $convert.base64Decode( final $typed_data.Uint8List messageDescriptor = $convert.base64Decode(
'CgdNZXNzYWdlElEKCGNhdGVnb3J5GAEgASgOMjUuZGV2LnlhbnNob3V3YW5nLmJsdWV0b290aF9sb3dfZW5lcmd5Lk1lc3NhZ2VDYXRlZ29yeVIIY2F0ZWdvcnkSFgoFc3RhdGUYAiABKAhIAFIFc3RhdGUSTwoJZGlzY292ZXJ5GAMgASgLMi8uZGV2LnlhbnNob3V3YW5nLmJsdWV0b290aF9sb3dfZW5lcmd5LkRpc2NvdmVyeUgAUglkaXNjb3ZlcnkSHAoIc2Nhbm5pbmcYBCABKAhIAFIIc2Nhbm5pbmcSXgoOY29ubmVjdGlvbkxvc3QYBSABKAsyNC5kZXYueWFuc2hvdXdhbmcuYmx1ZXRvb3RoX2xvd19lbmVyZ3kuQ29ubmVjdGlvbkxvc3RIAFIOY29ubmVjdGlvbkxvc3QScQoTY2hhcmFjdGVyaXN0aWNWYWx1ZRgGIAEoCzI9LmRldi55YW5zaG91d2FuZy5ibHVldG9vdGhfbG93X2VuZXJneS5HYXR0Q2hhcmFjdGVyaXN0aWNWYWx1ZUgAUhNjaGFyYWN0ZXJpc3RpY1ZhbHVlQgcKBXZhbHVl'); 'CgdNZXNzYWdlElEKCGNhdGVnb3J5GAEgASgOMjUuZGV2LnlhbnNob3V3YW5nLmJsdWV0b290aF9sb3dfZW5lcmd5Lk1lc3NhZ2VDYXRlZ29yeVIIY2F0ZWdvcnkSTAoFc3RhdGUYAiABKA4yNC5kZXYueWFuc2hvdXdhbmcuYmx1ZXRvb3RoX2xvd19lbmVyZ3kuQmx1ZXRvb3RoU3RhdGVIAFIFc3RhdGUSeQoXc3RhcnREaXNjb3ZlcnlBcmd1bWVudHMYAyABKAsyPS5kZXYueWFuc2hvdXdhbmcuYmx1ZXRvb3RoX2xvd19lbmVyZ3kuU3RhcnREaXNjb3ZlcnlBcmd1bWVudHNIAFIXc3RhcnREaXNjb3ZlcnlBcmd1bWVudHMSTwoJZGlzY292ZXJ5GAQgASgLMi8uZGV2LnlhbnNob3V3YW5nLmJsdWV0b290aF9sb3dfZW5lcmd5LkRpc2NvdmVyeUgAUglkaXNjb3ZlcnkSZAoQY29ubmVjdEFyZ3VtZW50cxgFIAEoCzI2LmRldi55YW5zaG91d2FuZy5ibHVldG9vdGhfbG93X2VuZXJneS5Db25uZWN0QXJndW1lbnRzSABSEGNvbm5lY3RBcmd1bWVudHMScQoTZGlzY29ubmVjdEFyZ3VtZW50cxgGIAEoCzI9LmRldi55YW5zaG91d2FuZy5ibHVldG9vdGhfbG93X2VuZXJneS5HYXR0RGlzY29ubmVjdEFyZ3VtZW50c0gAUhNkaXNjb25uZWN0QXJndW1lbnRzEmIKDmNvbm5lY3Rpb25Mb3N0GAcgASgLMjguZGV2LnlhbnNob3V3YW5nLmJsdWV0b290aF9sb3dfZW5lcmd5LkdhdHRDb25uZWN0aW9uTG9zdEgAUg5jb25uZWN0aW9uTG9zdBKJAQobY2hhcmFjdGVyaXN0aWNSZWFkQXJndW1lbnRzGAggASgLMkUuZGV2LnlhbnNob3V3YW5nLmJsdWV0b290aF9sb3dfZW5lcmd5LkdhdHRDaGFyYWN0ZXJpc3RpY1JlYWRBcmd1bWVudHNIAFIbY2hhcmFjdGVyaXN0aWNSZWFkQXJndW1lbnRzEowBChxjaGFyYWN0ZXJpc3RpY1dyaXRlQXJndW1lbnRzGAkgASgLMkYuZGV2LnlhbnNob3V3YW5nLmJsdWV0b290aF9sb3dfZW5lcmd5LkdhdHRDaGFyYWN0ZXJpc3RpY1dyaXRlQXJndW1lbnRzSABSHGNoYXJhY3RlcmlzdGljV3JpdGVBcmd1bWVudHMSjwEKHWNoYXJhY3RlcmlzdGljTm90aWZ5QXJndW1lbnRzGAogASgLMkcuZGV2LnlhbnNob3V3YW5nLmJsdWV0b290aF9sb3dfZW5lcmd5LkdhdHRDaGFyYWN0ZXJpc3RpY05vdGlmeUFyZ3VtZW50c0gAUh1jaGFyYWN0ZXJpc3RpY05vdGlmeUFyZ3VtZW50cxJxChNjaGFyYWN0ZXJpc3RpY1ZhbHVlGAsgASgLMj0uZGV2LnlhbnNob3V3YW5nLmJsdWV0b290aF9sb3dfZW5lcmd5LkdhdHRDaGFyYWN0ZXJpc3RpY1ZhbHVlSABSE2NoYXJhY3RlcmlzdGljVmFsdWUSfQoXZGVzY3JpcHRvclJlYWRBcmd1bWVudHMYDCABKAsyQS5kZXYueWFuc2hvdXdhbmcuYmx1ZXRvb3RoX2xvd19lbmVyZ3kuR2F0dERlc2NyaXB0b3JSZWFkQXJndW1lbnRzSABSF2Rlc2NyaXB0b3JSZWFkQXJndW1lbnRzEoABChhkZXNjcmlwdG9yV3JpdGVBcmd1bWVudHMYDSABKAsyQi5kZXYueWFuc2hvdXdhbmcuYmx1ZXRvb3RoX2xvd19lbmVyZ3kuR2F0dERlc2NyaXB0b3JXcml0ZUFyZ3VtZW50c0gAUhhkZXNjcmlwdG9yV3JpdGVBcmd1bWVudHNCBwoFdmFsdWU=');
@$core.Deprecated('Use startDiscoveryArgumentsDescriptor instead') @$core.Deprecated('Use startDiscoveryArgumentsDescriptor instead')
const StartDiscoveryArguments$json = const { const StartDiscoveryArguments$json = const {
'1': 'StartDiscoveryArguments', '1': 'StartDiscoveryArguments',
@ -98,7 +192,7 @@ final $typed_data.Uint8List startDiscoveryArgumentsDescriptor =
const Discovery$json = const { const Discovery$json = const {
'1': 'Discovery', '1': 'Discovery',
'2': const [ '2': const [
const {'1': 'address', '3': 1, '4': 1, '5': 9, '10': 'address'}, const {'1': 'uuid', '3': 1, '4': 1, '5': 9, '10': 'uuid'},
const {'1': 'rssi', '3': 2, '4': 1, '5': 17, '10': 'rssi'}, const {'1': 'rssi', '3': 2, '4': 1, '5': 17, '10': 'rssi'},
const { const {
'1': 'advertisements', '1': 'advertisements',
@ -107,29 +201,36 @@ const Discovery$json = const {
'5': 12, '5': 12,
'10': 'advertisements' '10': 'advertisements'
}, },
const {'1': 'connectable', '3': 4, '4': 1, '5': 8, '10': 'connectable'},
], ],
}; };
/// Descriptor for `Discovery`. Decode as a `google.protobuf.DescriptorProto`. /// Descriptor for `Discovery`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List discoveryDescriptor = $convert.base64Decode( final $typed_data.Uint8List discoveryDescriptor = $convert.base64Decode(
'CglEaXNjb3ZlcnkSGAoHYWRkcmVzcxgBIAEoCVIHYWRkcmVzcxISCgRyc3NpGAIgASgRUgRyc3NpEiYKDmFkdmVydGlzZW1lbnRzGAMgASgMUg5hZHZlcnRpc2VtZW50cw=='); 'CglEaXNjb3ZlcnkSEgoEdXVpZBgBIAEoCVIEdXVpZBISCgRyc3NpGAIgASgRUgRyc3NpEiYKDmFkdmVydGlzZW1lbnRzGAMgASgMUg5hZHZlcnRpc2VtZW50cxIgCgtjb25uZWN0YWJsZRgEIAEoCFILY29ubmVjdGFibGU=');
@$core.Deprecated('Use connectArgumentsDescriptor instead') @$core.Deprecated('Use connectArgumentsDescriptor instead')
const ConnectArguments$json = const { const ConnectArguments$json = const {
'1': 'ConnectArguments', '1': 'ConnectArguments',
'2': const [ '2': const [
const {'1': 'address', '3': 1, '4': 1, '5': 9, '10': 'address'}, const {'1': 'uuid', '3': 1, '4': 1, '5': 9, '10': 'uuid'},
], ],
}; };
/// Descriptor for `ConnectArguments`. Decode as a `google.protobuf.DescriptorProto`. /// Descriptor for `ConnectArguments`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List connectArgumentsDescriptor = $convert.base64Decode( final $typed_data.Uint8List connectArgumentsDescriptor = $convert
'ChBDb25uZWN0QXJndW1lbnRzEhgKB2FkZHJlc3MYASABKAlSB2FkZHJlc3M='); .base64Decode('ChBDb25uZWN0QXJndW1lbnRzEhIKBHV1aWQYASABKAlSBHV1aWQ=');
@$core.Deprecated('Use gATTDescriptor instead') @$core.Deprecated('Use gATTDescriptor instead')
const GATT$json = const { const GATT$json = const {
'1': 'GATT', '1': 'GATT',
'2': const [ '2': const [
const {'1': 'id', '3': 1, '4': 1, '5': 5, '10': 'id'}, const {'1': 'key', '3': 1, '4': 1, '5': 9, '10': 'key'},
const {'1': 'mtu', '3': 2, '4': 1, '5': 5, '10': 'mtu'}, const {
'1': 'maximumWriteLength',
'3': 2,
'4': 1,
'5': 5,
'10': 'maximumWriteLength'
},
const { const {
'1': 'services', '1': 'services',
'3': 3, '3': 3,
@ -143,25 +244,12 @@ const GATT$json = const {
/// Descriptor for `GATT`. Decode as a `google.protobuf.DescriptorProto`. /// Descriptor for `GATT`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List gATTDescriptor = $convert.base64Decode( final $typed_data.Uint8List gATTDescriptor = $convert.base64Decode(
'CgRHQVRUEg4KAmlkGAEgASgFUgJpZBIQCgNtdHUYAiABKAVSA210dRJNCghzZXJ2aWNlcxgDIAMoCzIxLmRldi55YW5zaG91d2FuZy5ibHVldG9vdGhfbG93X2VuZXJneS5HYXR0U2VydmljZVIIc2VydmljZXM='); 'CgRHQVRUEhAKA2tleRgBIAEoCVIDa2V5Ei4KEm1heGltdW1Xcml0ZUxlbmd0aBgCIAEoBVISbWF4aW11bVdyaXRlTGVuZ3RoEk0KCHNlcnZpY2VzGAMgAygLMjEuZGV2LnlhbnNob3V3YW5nLmJsdWV0b290aF9sb3dfZW5lcmd5LkdhdHRTZXJ2aWNlUghzZXJ2aWNlcw==');
@$core.Deprecated('Use gattDisconnectArgumentsDescriptor instead')
const GattDisconnectArguments$json = const {
'1': 'GattDisconnectArguments',
'2': const [
const {'1': 'address', '3': 1, '4': 1, '5': 9, '10': 'address'},
const {'1': 'id', '3': 2, '4': 1, '5': 5, '10': 'id'},
],
};
/// Descriptor for `GattDisconnectArguments`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List gattDisconnectArgumentsDescriptor =
$convert.base64Decode(
'ChdHYXR0RGlzY29ubmVjdEFyZ3VtZW50cxIYCgdhZGRyZXNzGAEgASgJUgdhZGRyZXNzEg4KAmlkGAIgASgFUgJpZA==');
@$core.Deprecated('Use gattServiceDescriptor instead') @$core.Deprecated('Use gattServiceDescriptor instead')
const GattService$json = const { const GattService$json = const {
'1': 'GattService', '1': 'GattService',
'2': const [ '2': const [
const {'1': 'id', '3': 1, '4': 1, '5': 5, '10': 'id'}, const {'1': 'key', '3': 1, '4': 1, '5': 9, '10': 'key'},
const {'1': 'uuid', '3': 2, '4': 1, '5': 9, '10': 'uuid'}, const {'1': 'uuid', '3': 2, '4': 1, '5': 9, '10': 'uuid'},
const { const {
'1': 'characteristics', '1': 'characteristics',
@ -176,88 +264,98 @@ const GattService$json = const {
/// Descriptor for `GattService`. Decode as a `google.protobuf.DescriptorProto`. /// Descriptor for `GattService`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List gattServiceDescriptor = $convert.base64Decode( final $typed_data.Uint8List gattServiceDescriptor = $convert.base64Decode(
'CgtHYXR0U2VydmljZRIOCgJpZBgBIAEoBVICaWQSEgoEdXVpZBgCIAEoCVIEdXVpZBJiCg9jaGFyYWN0ZXJpc3RpY3MYAyADKAsyOC5kZXYueWFuc2hvdXdhbmcuYmx1ZXRvb3RoX2xvd19lbmVyZ3kuR2F0dENoYXJhY3RlcmlzdGljUg9jaGFyYWN0ZXJpc3RpY3M='); 'CgtHYXR0U2VydmljZRIQCgNrZXkYASABKAlSA2tleRISCgR1dWlkGAIgASgJUgR1dWlkEmIKD2NoYXJhY3RlcmlzdGljcxgDIAMoCzI4LmRldi55YW5zaG91d2FuZy5ibHVldG9vdGhfbG93X2VuZXJneS5HYXR0Q2hhcmFjdGVyaXN0aWNSD2NoYXJhY3RlcmlzdGljcw==');
@$core.Deprecated('Use gattCharacteristicDescriptor instead') @$core.Deprecated('Use gattCharacteristicDescriptor instead')
const GattCharacteristic$json = const { const GattCharacteristic$json = const {
'1': 'GattCharacteristic', '1': 'GattCharacteristic',
'2': const [ '2': const [
const {'1': 'id', '3': 1, '4': 1, '5': 5, '10': 'id'}, const {'1': 'key', '3': 1, '4': 1, '5': 9, '10': 'key'},
const {'1': 'uuid', '3': 2, '4': 1, '5': 9, '10': 'uuid'}, const {'1': 'uuid', '3': 2, '4': 1, '5': 9, '10': 'uuid'},
const {'1': 'canRead', '3': 3, '4': 1, '5': 8, '10': 'canRead'},
const {'1': 'canWrite', '3': 4, '4': 1, '5': 8, '10': 'canWrite'},
const {
'1': 'canWriteWithoutResponse',
'3': 5,
'4': 1,
'5': 8,
'10': 'canWriteWithoutResponse'
},
const {'1': 'canNotify', '3': 6, '4': 1, '5': 8, '10': 'canNotify'},
const { const {
'1': 'descriptors', '1': 'descriptors',
'3': 3, '3': 7,
'4': 3, '4': 3,
'5': 11, '5': 11,
'6': '.dev.yanshouwang.bluetooth_low_energy.GattDescriptor', '6': '.dev.yanshouwang.bluetooth_low_energy.GattDescriptor',
'10': 'descriptors' '10': 'descriptors'
}, },
const {'1': 'canRead', '3': 4, '4': 1, '5': 8, '10': 'canRead'},
const {'1': 'canWrite', '3': 5, '4': 1, '5': 8, '10': 'canWrite'},
const {
'1': 'canWriteWithoutResponse',
'3': 6,
'4': 1,
'5': 8,
'10': 'canWriteWithoutResponse'
},
const {'1': 'canNotify', '3': 7, '4': 1, '5': 8, '10': 'canNotify'},
], ],
}; };
/// Descriptor for `GattCharacteristic`. Decode as a `google.protobuf.DescriptorProto`. /// Descriptor for `GattCharacteristic`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List gattCharacteristicDescriptor = $convert.base64Decode( final $typed_data.Uint8List gattCharacteristicDescriptor = $convert.base64Decode(
'ChJHYXR0Q2hhcmFjdGVyaXN0aWMSDgoCaWQYASABKAVSAmlkEhIKBHV1aWQYAiABKAlSBHV1aWQSVgoLZGVzY3JpcHRvcnMYAyADKAsyNC5kZXYueWFuc2hvdXdhbmcuYmx1ZXRvb3RoX2xvd19lbmVyZ3kuR2F0dERlc2NyaXB0b3JSC2Rlc2NyaXB0b3JzEhgKB2NhblJlYWQYBCABKAhSB2NhblJlYWQSGgoIY2FuV3JpdGUYBSABKAhSCGNhbldyaXRlEjgKF2NhbldyaXRlV2l0aG91dFJlc3BvbnNlGAYgASgIUhdjYW5Xcml0ZVdpdGhvdXRSZXNwb25zZRIcCgljYW5Ob3RpZnkYByABKAhSCWNhbk5vdGlmeQ=='); 'ChJHYXR0Q2hhcmFjdGVyaXN0aWMSEAoDa2V5GAEgASgJUgNrZXkSEgoEdXVpZBgCIAEoCVIEdXVpZBIYCgdjYW5SZWFkGAMgASgIUgdjYW5SZWFkEhoKCGNhbldyaXRlGAQgASgIUghjYW5Xcml0ZRI4ChdjYW5Xcml0ZVdpdGhvdXRSZXNwb25zZRgFIAEoCFIXY2FuV3JpdGVXaXRob3V0UmVzcG9uc2USHAoJY2FuTm90aWZ5GAYgASgIUgljYW5Ob3RpZnkSVgoLZGVzY3JpcHRvcnMYByADKAsyNC5kZXYueWFuc2hvdXdhbmcuYmx1ZXRvb3RoX2xvd19lbmVyZ3kuR2F0dERlc2NyaXB0b3JSC2Rlc2NyaXB0b3Jz');
@$core.Deprecated('Use gattDescriptorDescriptor instead') @$core.Deprecated('Use gattDescriptorDescriptor instead')
const GattDescriptor$json = const { const GattDescriptor$json = const {
'1': 'GattDescriptor', '1': 'GattDescriptor',
'2': const [ '2': const [
const {'1': 'id', '3': 1, '4': 1, '5': 5, '10': 'id'}, const {'1': 'key', '3': 1, '4': 1, '5': 9, '10': 'key'},
const {'1': 'uuid', '3': 2, '4': 1, '5': 9, '10': 'uuid'}, const {'1': 'uuid', '3': 2, '4': 1, '5': 9, '10': 'uuid'},
], ],
}; };
/// Descriptor for `GattDescriptor`. Decode as a `google.protobuf.DescriptorProto`. /// Descriptor for `GattDescriptor`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List gattDescriptorDescriptor = $convert.base64Decode( final $typed_data.Uint8List gattDescriptorDescriptor = $convert.base64Decode(
'Cg5HYXR0RGVzY3JpcHRvchIOCgJpZBgBIAEoBVICaWQSEgoEdXVpZBgCIAEoCVIEdXVpZA=='); 'Cg5HYXR0RGVzY3JpcHRvchIQCgNrZXkYASABKAlSA2tleRISCgR1dWlkGAIgASgJUgR1dWlk');
@$core.Deprecated('Use connectionLostDescriptor instead') @$core.Deprecated('Use gattDisconnectArgumentsDescriptor instead')
const ConnectionLost$json = const { const GattDisconnectArguments$json = const {
'1': 'ConnectionLost', '1': 'GattDisconnectArguments',
'2': const [ '2': const [
const {'1': 'id', '3': 1, '4': 1, '5': 5, '10': 'id'}, const {'1': 'key', '3': 1, '4': 1, '5': 9, '10': 'key'},
const {'1': 'error_code', '3': 2, '4': 1, '5': 5, '10': 'errorCode'},
], ],
}; };
/// Descriptor for `ConnectionLost`. Decode as a `google.protobuf.DescriptorProto`. /// Descriptor for `GattDisconnectArguments`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List connectionLostDescriptor = $convert.base64Decode( final $typed_data.Uint8List gattDisconnectArgumentsDescriptor =
'Cg5Db25uZWN0aW9uTG9zdBIOCgJpZBgBIAEoBVICaWQSHQoKZXJyb3JfY29kZRgCIAEoBVIJZXJyb3JDb2Rl'); $convert.base64Decode(
'ChdHYXR0RGlzY29ubmVjdEFyZ3VtZW50cxIQCgNrZXkYASABKAlSA2tleQ==');
@$core.Deprecated('Use gattConnectionLostDescriptor instead')
const GattConnectionLost$json = const {
'1': 'GattConnectionLost',
'2': const [
const {'1': 'key', '3': 1, '4': 1, '5': 9, '10': 'key'},
const {'1': 'error', '3': 2, '4': 1, '5': 9, '10': 'error'},
],
};
/// Descriptor for `GattConnectionLost`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List gattConnectionLostDescriptor = $convert.base64Decode(
'ChJHYXR0Q29ubmVjdGlvbkxvc3QSEAoDa2V5GAEgASgJUgNrZXkSFAoFZXJyb3IYAiABKAlSBWVycm9y');
@$core.Deprecated('Use gattCharacteristicReadArgumentsDescriptor instead') @$core.Deprecated('Use gattCharacteristicReadArgumentsDescriptor instead')
const GattCharacteristicReadArguments$json = const { const GattCharacteristicReadArguments$json = const {
'1': 'GattCharacteristicReadArguments', '1': 'GattCharacteristicReadArguments',
'2': const [ '2': const [
const {'1': 'address', '3': 1, '4': 1, '5': 9, '10': 'address'}, const {'1': 'gatt_key', '3': 1, '4': 1, '5': 9, '10': 'gattKey'},
const {'1': 'service_uuid', '3': 2, '4': 1, '5': 9, '10': 'serviceUuid'}, const {'1': 'service_key', '3': 2, '4': 1, '5': 9, '10': 'serviceKey'},
const {'1': 'uuid', '3': 3, '4': 1, '5': 9, '10': 'uuid'}, const {'1': 'key', '3': 3, '4': 1, '5': 9, '10': 'key'},
const {'1': 'id', '3': 4, '4': 1, '5': 5, '10': 'id'},
], ],
}; };
/// Descriptor for `GattCharacteristicReadArguments`. Decode as a `google.protobuf.DescriptorProto`. /// Descriptor for `GattCharacteristicReadArguments`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List gattCharacteristicReadArgumentsDescriptor = final $typed_data.Uint8List gattCharacteristicReadArgumentsDescriptor =
$convert.base64Decode( $convert.base64Decode(
'Ch9HYXR0Q2hhcmFjdGVyaXN0aWNSZWFkQXJndW1lbnRzEhgKB2FkZHJlc3MYASABKAlSB2FkZHJlc3MSIQoMc2VydmljZV91dWlkGAIgASgJUgtzZXJ2aWNlVXVpZBISCgR1dWlkGAMgASgJUgR1dWlkEg4KAmlkGAQgASgFUgJpZA=='); 'Ch9HYXR0Q2hhcmFjdGVyaXN0aWNSZWFkQXJndW1lbnRzEhkKCGdhdHRfa2V5GAEgASgJUgdnYXR0S2V5Eh8KC3NlcnZpY2Vfa2V5GAIgASgJUgpzZXJ2aWNlS2V5EhAKA2tleRgDIAEoCVIDa2V5');
@$core.Deprecated('Use gattCharacteristicWriteArgumentsDescriptor instead') @$core.Deprecated('Use gattCharacteristicWriteArgumentsDescriptor instead')
const GattCharacteristicWriteArguments$json = const { const GattCharacteristicWriteArguments$json = const {
'1': 'GattCharacteristicWriteArguments', '1': 'GattCharacteristicWriteArguments',
'2': const [ '2': const [
const {'1': 'address', '3': 1, '4': 1, '5': 9, '10': 'address'}, const {'1': 'gatt_key', '3': 1, '4': 1, '5': 9, '10': 'gattKey'},
const {'1': 'service_uuid', '3': 2, '4': 1, '5': 9, '10': 'serviceUuid'}, const {'1': 'service_key', '3': 2, '4': 1, '5': 9, '10': 'serviceKey'},
const {'1': 'uuid', '3': 3, '4': 1, '5': 9, '10': 'uuid'}, const {'1': 'key', '3': 3, '4': 1, '5': 9, '10': 'key'},
const {'1': 'id', '3': 4, '4': 1, '5': 5, '10': 'id'}, const {'1': 'value', '3': 4, '4': 1, '5': 12, '10': 'value'},
const {'1': 'value', '3': 5, '4': 1, '5': 12, '10': 'value'},
const { const {
'1': 'withoutResponse', '1': 'withoutResponse',
'3': 6, '3': 5,
'4': 1, '4': 1,
'5': 8, '5': 8,
'10': 'withoutResponse' '10': 'withoutResponse'
@ -268,28 +366,29 @@ const GattCharacteristicWriteArguments$json = const {
/// Descriptor for `GattCharacteristicWriteArguments`. Decode as a `google.protobuf.DescriptorProto`. /// Descriptor for `GattCharacteristicWriteArguments`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List gattCharacteristicWriteArgumentsDescriptor = final $typed_data.Uint8List gattCharacteristicWriteArgumentsDescriptor =
$convert.base64Decode( $convert.base64Decode(
'CiBHYXR0Q2hhcmFjdGVyaXN0aWNXcml0ZUFyZ3VtZW50cxIYCgdhZGRyZXNzGAEgASgJUgdhZGRyZXNzEiEKDHNlcnZpY2VfdXVpZBgCIAEoCVILc2VydmljZVV1aWQSEgoEdXVpZBgDIAEoCVIEdXVpZBIOCgJpZBgEIAEoBVICaWQSFAoFdmFsdWUYBSABKAxSBXZhbHVlEigKD3dpdGhvdXRSZXNwb25zZRgGIAEoCFIPd2l0aG91dFJlc3BvbnNl'); 'CiBHYXR0Q2hhcmFjdGVyaXN0aWNXcml0ZUFyZ3VtZW50cxIZCghnYXR0X2tleRgBIAEoCVIHZ2F0dEtleRIfCgtzZXJ2aWNlX2tleRgCIAEoCVIKc2VydmljZUtleRIQCgNrZXkYAyABKAlSA2tleRIUCgV2YWx1ZRgEIAEoDFIFdmFsdWUSKAoPd2l0aG91dFJlc3BvbnNlGAUgASgIUg93aXRob3V0UmVzcG9uc2U=');
@$core.Deprecated('Use gattCharacteristicNotifyArgumentsDescriptor instead') @$core.Deprecated('Use gattCharacteristicNotifyArgumentsDescriptor instead')
const GattCharacteristicNotifyArguments$json = const { const GattCharacteristicNotifyArguments$json = const {
'1': 'GattCharacteristicNotifyArguments', '1': 'GattCharacteristicNotifyArguments',
'2': const [ '2': const [
const {'1': 'address', '3': 1, '4': 1, '5': 9, '10': 'address'}, const {'1': 'gatt_key', '3': 1, '4': 1, '5': 9, '10': 'gattKey'},
const {'1': 'service_uuid', '3': 2, '4': 1, '5': 9, '10': 'serviceUuid'}, const {'1': 'service_key', '3': 2, '4': 1, '5': 9, '10': 'serviceKey'},
const {'1': 'uuid', '3': 3, '4': 1, '5': 9, '10': 'uuid'}, const {'1': 'key', '3': 3, '4': 1, '5': 9, '10': 'key'},
const {'1': 'id', '3': 4, '4': 1, '5': 5, '10': 'id'}, const {'1': 'state', '3': 4, '4': 1, '5': 8, '10': 'state'},
const {'1': 'state', '3': 5, '4': 1, '5': 8, '10': 'state'},
], ],
}; };
/// Descriptor for `GattCharacteristicNotifyArguments`. Decode as a `google.protobuf.DescriptorProto`. /// Descriptor for `GattCharacteristicNotifyArguments`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List gattCharacteristicNotifyArgumentsDescriptor = final $typed_data.Uint8List gattCharacteristicNotifyArgumentsDescriptor =
$convert.base64Decode( $convert.base64Decode(
'CiFHYXR0Q2hhcmFjdGVyaXN0aWNOb3RpZnlBcmd1bWVudHMSGAoHYWRkcmVzcxgBIAEoCVIHYWRkcmVzcxIhCgxzZXJ2aWNlX3V1aWQYAiABKAlSC3NlcnZpY2VVdWlkEhIKBHV1aWQYAyABKAlSBHV1aWQSDgoCaWQYBCABKAVSAmlkEhQKBXN0YXRlGAUgASgIUgVzdGF0ZQ=='); 'CiFHYXR0Q2hhcmFjdGVyaXN0aWNOb3RpZnlBcmd1bWVudHMSGQoIZ2F0dF9rZXkYASABKAlSB2dhdHRLZXkSHwoLc2VydmljZV9rZXkYAiABKAlSCnNlcnZpY2VLZXkSEAoDa2V5GAMgASgJUgNrZXkSFAoFc3RhdGUYBCABKAhSBXN0YXRl');
@$core.Deprecated('Use gattCharacteristicValueDescriptor instead') @$core.Deprecated('Use gattCharacteristicValueDescriptor instead')
const GattCharacteristicValue$json = const { const GattCharacteristicValue$json = const {
'1': 'GattCharacteristicValue', '1': 'GattCharacteristicValue',
'2': const [ '2': const [
const {'1': 'id', '3': 3, '4': 1, '5': 5, '10': 'id'}, const {'1': 'gatt_key', '3': 1, '4': 1, '5': 9, '10': 'gattKey'},
const {'1': 'service_key', '3': 2, '4': 1, '5': 9, '10': 'serviceKey'},
const {'1': 'key', '3': 3, '4': 1, '5': 9, '10': 'key'},
const {'1': 'value', '3': 4, '4': 1, '5': 12, '10': 'value'}, const {'1': 'value', '3': 4, '4': 1, '5': 12, '10': 'value'},
], ],
}; };
@ -297,49 +396,47 @@ const GattCharacteristicValue$json = const {
/// Descriptor for `GattCharacteristicValue`. Decode as a `google.protobuf.DescriptorProto`. /// Descriptor for `GattCharacteristicValue`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List gattCharacteristicValueDescriptor = final $typed_data.Uint8List gattCharacteristicValueDescriptor =
$convert.base64Decode( $convert.base64Decode(
'ChdHYXR0Q2hhcmFjdGVyaXN0aWNWYWx1ZRIOCgJpZBgDIAEoBVICaWQSFAoFdmFsdWUYBCABKAxSBXZhbHVl'); 'ChdHYXR0Q2hhcmFjdGVyaXN0aWNWYWx1ZRIZCghnYXR0X2tleRgBIAEoCVIHZ2F0dEtleRIfCgtzZXJ2aWNlX2tleRgCIAEoCVIKc2VydmljZUtleRIQCgNrZXkYAyABKAlSA2tleRIUCgV2YWx1ZRgEIAEoDFIFdmFsdWU=');
@$core.Deprecated('Use gattDescriptorReadArgumentsDescriptor instead') @$core.Deprecated('Use gattDescriptorReadArgumentsDescriptor instead')
const GattDescriptorReadArguments$json = const { const GattDescriptorReadArguments$json = const {
'1': 'GattDescriptorReadArguments', '1': 'GattDescriptorReadArguments',
'2': const [ '2': const [
const {'1': 'address', '3': 1, '4': 1, '5': 9, '10': 'address'}, const {'1': 'gatt_key', '3': 1, '4': 1, '5': 9, '10': 'gattKey'},
const {'1': 'service_uuid', '3': 2, '4': 1, '5': 9, '10': 'serviceUuid'}, const {'1': 'service_key', '3': 2, '4': 1, '5': 9, '10': 'serviceKey'},
const { const {
'1': 'characteristic_uuid', '1': 'characteristic_key',
'3': 3, '3': 3,
'4': 1, '4': 1,
'5': 9, '5': 9,
'10': 'characteristicUuid' '10': 'characteristicKey'
}, },
const {'1': 'uuid', '3': 4, '4': 1, '5': 9, '10': 'uuid'}, const {'1': 'key', '3': 4, '4': 1, '5': 9, '10': 'key'},
const {'1': 'id', '3': 5, '4': 1, '5': 5, '10': 'id'},
], ],
}; };
/// Descriptor for `GattDescriptorReadArguments`. Decode as a `google.protobuf.DescriptorProto`. /// Descriptor for `GattDescriptorReadArguments`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List gattDescriptorReadArgumentsDescriptor = final $typed_data.Uint8List gattDescriptorReadArgumentsDescriptor =
$convert.base64Decode( $convert.base64Decode(
'ChtHYXR0RGVzY3JpcHRvclJlYWRBcmd1bWVudHMSGAoHYWRkcmVzcxgBIAEoCVIHYWRkcmVzcxIhCgxzZXJ2aWNlX3V1aWQYAiABKAlSC3NlcnZpY2VVdWlkEi8KE2NoYXJhY3RlcmlzdGljX3V1aWQYAyABKAlSEmNoYXJhY3RlcmlzdGljVXVpZBISCgR1dWlkGAQgASgJUgR1dWlkEg4KAmlkGAUgASgFUgJpZA=='); 'ChtHYXR0RGVzY3JpcHRvclJlYWRBcmd1bWVudHMSGQoIZ2F0dF9rZXkYASABKAlSB2dhdHRLZXkSHwoLc2VydmljZV9rZXkYAiABKAlSCnNlcnZpY2VLZXkSLQoSY2hhcmFjdGVyaXN0aWNfa2V5GAMgASgJUhFjaGFyYWN0ZXJpc3RpY0tleRIQCgNrZXkYBCABKAlSA2tleQ==');
@$core.Deprecated('Use gattDescriptorWriteArgumentsDescriptor instead') @$core.Deprecated('Use gattDescriptorWriteArgumentsDescriptor instead')
const GattDescriptorWriteArguments$json = const { const GattDescriptorWriteArguments$json = const {
'1': 'GattDescriptorWriteArguments', '1': 'GattDescriptorWriteArguments',
'2': const [ '2': const [
const {'1': 'address', '3': 1, '4': 1, '5': 9, '10': 'address'}, const {'1': 'gatt_key', '3': 1, '4': 1, '5': 9, '10': 'gattKey'},
const {'1': 'service_uuid', '3': 2, '4': 1, '5': 9, '10': 'serviceUuid'}, const {'1': 'service_key', '3': 2, '4': 1, '5': 9, '10': 'serviceKey'},
const { const {
'1': 'characteristic_uuid', '1': 'characteristic_key',
'3': 3, '3': 3,
'4': 1, '4': 1,
'5': 9, '5': 9,
'10': 'characteristicUuid' '10': 'characteristicKey'
}, },
const {'1': 'uuid', '3': 4, '4': 1, '5': 9, '10': 'uuid'}, const {'1': 'key', '3': 4, '4': 1, '5': 9, '10': 'key'},
const {'1': 'id', '3': 5, '4': 1, '5': 5, '10': 'id'}, const {'1': 'value', '3': 5, '4': 1, '5': 12, '10': 'value'},
const {'1': 'value', '3': 6, '4': 1, '5': 12, '10': 'value'},
], ],
}; };
/// Descriptor for `GattDescriptorWriteArguments`. Decode as a `google.protobuf.DescriptorProto`. /// Descriptor for `GattDescriptorWriteArguments`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List gattDescriptorWriteArgumentsDescriptor = final $typed_data.Uint8List gattDescriptorWriteArgumentsDescriptor =
$convert.base64Decode( $convert.base64Decode(
'ChxHYXR0RGVzY3JpcHRvcldyaXRlQXJndW1lbnRzEhgKB2FkZHJlc3MYASABKAlSB2FkZHJlc3MSIQoMc2VydmljZV91dWlkGAIgASgJUgtzZXJ2aWNlVXVpZBIvChNjaGFyYWN0ZXJpc3RpY191dWlkGAMgASgJUhJjaGFyYWN0ZXJpc3RpY1V1aWQSEgoEdXVpZBgEIAEoCVIEdXVpZBIOCgJpZBgFIAEoBVICaWQSFAoFdmFsdWUYBiABKAxSBXZhbHVl'); 'ChxHYXR0RGVzY3JpcHRvcldyaXRlQXJndW1lbnRzEhkKCGdhdHRfa2V5GAEgASgJUgdnYXR0S2V5Eh8KC3NlcnZpY2Vfa2V5GAIgASgJUgpzZXJ2aWNlS2V5Ei0KEmNoYXJhY3RlcmlzdGljX2tleRgDIAEoCVIRY2hhcmFjdGVyaXN0aWNLZXkSEAoDa2V5GAQgASgJUgNrZXkSFAoFdmFsdWUYBSABKAxSBXZhbHVl');

View File

@ -1,9 +1,12 @@
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'message.pb.dart';
const namespace = 'yanshouwang.dev/bluetooth_low_energy'; const namespace = 'yanshouwang.dev/bluetooth_low_energy';
const method = MethodChannel('$namespace/method'); const method = MethodChannel('$namespace/method');
const event = EventChannel('$namespace/event'); const event = EventChannel('$namespace/event');
const equality = ListEquality<int>(); const equality = ListEquality<int>();
final stream = event.receiveBroadcastStream(); final stream =
event.receiveBroadcastStream().map((event) => Message.fromBuffer(event));

View File

@ -20,9 +20,9 @@ class _UUID implements UUID {
@override @override
final int hashCode; final int hashCode;
_UUID(String str) : this.name(str.nameOfUUID); _UUID(String str) : this.name(str.uuidName);
_UUID.name(String name) : this.nameValue(name, name.valueOfUUID); _UUID.name(String name) : this.nameValue(name, name.uuidVaue);
_UUID.nameValue(this.name, this.value) : hashCode = equality.hash(value); _UUID.nameValue(this.name, this.value) : hashCode = equality.hash(value);

View File

@ -4,11 +4,18 @@ package dev.yanshouwang.bluetooth_low_energy;
message Message { message Message {
MessageCategory category = 1; MessageCategory category = 1;
oneof value { oneof value {
bool state = 2; BluetoothState state = 2;
Discovery discovery = 3; StartDiscoveryArguments startDiscoveryArguments = 3;
bool scanning = 4; Discovery discovery = 4;
ConnectionLost connectionLost = 5; ConnectArguments connectArguments = 5;
GattCharacteristicValue characteristicValue = 6; GattDisconnectArguments disconnectArguments = 6;
GattConnectionLost connectionLost = 7;
GattCharacteristicReadArguments characteristicReadArguments = 8;
GattCharacteristicWriteArguments characteristicWriteArguments = 9;
GattCharacteristicNotifyArguments characteristicNotifyArguments = 10;
GattCharacteristicValue characteristicValue = 11;
GattDescriptorReadArguments descriptorReadArguments = 12;
GattDescriptorWriteArguments descriptorWriteArguments = 13;
} }
} }
@ -17,110 +24,112 @@ message StartDiscoveryArguments {
} }
message Discovery { message Discovery {
string address = 1; string uuid = 1;
sint32 rssi = 2; sint32 rssi = 2;
bytes advertisements = 3; bytes advertisements = 3;
bool connectable = 4;
} }
message ConnectArguments { message ConnectArguments {
string address = 1; string uuid = 1;
} }
message GATT { message GATT {
int32 id = 1; string key = 1;
int32 mtu = 2; int32 maximumWriteLength = 2;
repeated GattService services = 3; repeated GattService services = 3;
} }
message GattDisconnectArguments{
string address = 1;
int32 id = 2;
}
message GattService { message GattService {
int32 id = 1; string key = 1;
string uuid = 2; string uuid = 2;
repeated GattCharacteristic characteristics = 3; repeated GattCharacteristic characteristics = 3;
} }
message GattCharacteristic { message GattCharacteristic {
int32 id = 1; string key = 1;
string uuid = 2; string uuid = 2;
repeated GattDescriptor descriptors = 3; bool canRead = 3;
bool canRead = 4; bool canWrite = 4;
bool canWrite = 5; bool canWriteWithoutResponse = 5;
bool canWriteWithoutResponse = 6; bool canNotify = 6;
bool canNotify = 7; repeated GattDescriptor descriptors = 7;
} }
message GattDescriptor { message GattDescriptor {
int32 id = 1; string key = 1;
string uuid = 2; string uuid = 2;
} }
message ConnectionLost { message GattDisconnectArguments{
int32 id = 1; string key = 1;
int32 error_code = 2; }
message GattConnectionLost {
string key = 1;
string error = 2;
} }
message GattCharacteristicReadArguments { message GattCharacteristicReadArguments {
string address = 1; string gatt_key = 1;
string service_uuid = 2; string service_key = 2;
string uuid = 3; string key = 3;
int32 id = 4;
} }
message GattCharacteristicWriteArguments { message GattCharacteristicWriteArguments {
string address = 1; string gatt_key = 1;
string service_uuid = 2; string service_key = 2;
string uuid = 3; string key = 3;
int32 id = 4; bytes value = 4;
bytes value = 5; bool withoutResponse = 5;
bool withoutResponse = 6;
} }
message GattCharacteristicNotifyArguments{ message GattCharacteristicNotifyArguments{
string address = 1; string gatt_key = 1;
string service_uuid = 2; string service_key = 2;
string uuid = 3; string key = 3;
int32 id = 4; bool state = 4;
bool state = 5;
} }
message GattCharacteristicValue { message GattCharacteristicValue {
int32 id = 3; string gatt_key = 1;
string service_key = 2;
string key = 3;
bytes value = 4; bytes value = 4;
} }
message GattDescriptorReadArguments { message GattDescriptorReadArguments {
string address = 1; string gatt_key = 1;
string service_uuid = 2; string service_key = 2;
string characteristic_uuid = 3; string characteristic_key = 3;
string uuid = 4; string key = 4;
int32 id = 5;
} }
message GattDescriptorWriteArguments { message GattDescriptorWriteArguments {
string address = 1; string gatt_key = 1;
string service_uuid = 2; string service_key = 2;
string characteristic_uuid = 3; string characteristic_key = 3;
string uuid = 4; string key = 4;
int32 id = 5; bytes value = 5;
bytes value = 6;
} }
enum MessageCategory { enum MessageCategory {
BLUETOOTH_AVAILABLE =0; BLUETOOTH_STATE = 0;
BLUETOOTH_STATE = 1; CENTRAL_START_DISCOVERY = 1;
CENTRAL_START_DISCOVERY = 2; CENTRAL_STOP_DISCOVERY = 2;
CENTRAL_STOP_DISCOVERY = 3; CENTRAL_DISCOVERED = 3;
CENTRAL_DISCOVERED = 4; CENTRAL_CONNECT = 4;
CENTRAL_CONNECT = 5; GATT_DISCONNECT = 5;
GATT_DISCONNECT = 6; GATT_CONNECTION_LOST = 6;
GATT_CONNECTION_LOST = 7; GATT_CHARACTERISTIC_READ = 7;
GATT_CHARACTERISTIC_READ = 8; GATT_CHARACTERISTIC_WRITE = 8;
GATT_CHARACTERISTIC_WRITE = 9; GATT_CHARACTERISTIC_NOTIFY = 9;
GATT_CHARACTERISTIC_NOTIFY = 10; GATT_DESCRIPTOR_READ = 10;
GATT_DESCRIPTOR_READ = 11; GATT_DESCRIPTOR_WRITE = 11;
GATT_DESCRIPTOR_WRITE = 12; }
enum BluetoothState {
UNSUPPORTED = 0;
POWERED_OFF = 1;
POWERED_ON = 2;
} }

View File

@ -5,63 +5,63 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: async name: async
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.6.1" version: "2.6.1"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
description: description:
name: boolean_selector name: boolean_selector
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.0" version: "2.1.0"
characters: characters:
dependency: transitive dependency: transitive
description: description:
name: characters name: characters
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0" version: "1.1.0"
charcode: charcode:
dependency: transitive dependency: transitive
description: description:
name: charcode name: charcode
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "1.2.0"
clock: clock:
dependency: transitive dependency: transitive
description: description:
name: clock name: clock
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0" version: "1.1.0"
collection: collection:
dependency: "direct main" dependency: "direct main"
description: description:
name: collection name: collection
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.15.0" version: "1.15.0"
convert: convert:
dependency: "direct main" dependency: "direct main"
description: description:
name: convert name: convert
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.0" version: "3.0.1"
fake_async: fake_async:
dependency: transitive dependency: transitive
description: description:
name: fake_async name: fake_async
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "1.2.0"
fixnum: fixnum:
dependency: transitive dependency: transitive
description: description:
name: fixnum name: fixnum
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.0" version: "1.0.0"
flutter: flutter:
@ -78,35 +78,35 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: matcher name: matcher
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.12.10" version: "0.12.10"
meta: meta:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.0" version: "1.3.0"
path: path:
dependency: transitive dependency: transitive
description: description:
name: path name: path
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.8.0" version: "1.8.0"
pedantic: pedantic:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: pedantic name: pedantic
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.11.0" version: "1.11.1"
protobuf: protobuf:
dependency: "direct main" dependency: "direct main"
description: description:
name: protobuf name: protobuf
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.0" version: "2.0.0"
sky_engine: sky_engine:
@ -118,56 +118,56 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: source_span name: source_span
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.8.1" version: "1.8.1"
stack_trace: stack_trace:
dependency: transitive dependency: transitive
description: description:
name: stack_trace name: stack_trace
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.10.0" version: "1.10.0"
stream_channel: stream_channel:
dependency: transitive dependency: transitive
description: description:
name: stream_channel name: stream_channel
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.0" version: "2.1.0"
string_scanner: string_scanner:
dependency: transitive dependency: transitive
description: description:
name: string_scanner name: string_scanner
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0" version: "1.1.0"
term_glyph: term_glyph:
dependency: transitive dependency: transitive
description: description:
name: term_glyph name: term_glyph
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "1.2.0"
test_api: test_api:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.3.0" version: "0.3.0"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
name: typed_data name: typed_data
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.0" version: "1.3.0"
vector_math: vector_math:
dependency: transitive dependency: transitive
description: description:
name: vector_math name: vector_math
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.0" version: "2.1.0"
sdks: sdks:

View File

@ -1,6 +1,6 @@
name: bluetooth_low_energy name: bluetooth_low_energy
description: A bluetooth low energy plugin for flutter, which can be used to develope central role apps. description: A bluetooth low energy plugin for flutter, which can be used to develope central role apps.
version: 0.0.2 version: 0.1.0
homepage: https://github.com/yanshouwang/bluetooth_low_energy homepage: https://github.com/yanshouwang/bluetooth_low_energy
publish_to: https://pub.dev publish_to: https://pub.dev

View File

@ -14,66 +14,59 @@ void main() {
calls.clear(); calls.clear();
method.setMockMethodCallHandler((call) async { method.setMockMethodCallHandler((call) async {
calls.add(call); calls.add(call);
if (call.method == proto.MessageCategory.BLUETOOTH_AVAILABLE.name) { final message = proto.Message.fromBuffer(call.arguments);
return true; switch (message.category) {
} else if (call.method == proto.MessageCategory.BLUETOOTH_STATE.name) { case proto.MessageCategory.BLUETOOTH_STATE:
return true; return proto.BluetoothState.POWERED_ON.value;
} else if (call.method == case proto.MessageCategory.CENTRAL_START_DISCOVERY:
proto.MessageCategory.CENTRAL_START_DISCOVERY.name) { return null;
return null; case proto.MessageCategory.CENTRAL_STOP_DISCOVERY:
} else if (call.method == return null;
proto.MessageCategory.CENTRAL_STOP_DISCOVERY.name) { case proto.MessageCategory.CENTRAL_CONNECT:
return null; final descriptors = [
} else if (call.method == proto.MessageCategory.CENTRAL_CONNECT.name) { proto.GattDescriptor(
final descriptors = [ key: '0',
proto.GattDescriptor( uuid: '2900',
id: 4000, ),
uuid: '2900', ];
), final characteristics = [
]; proto.GattCharacteristic(
final characteristics = [ key: '0',
proto.GattCharacteristic( uuid: '2A00',
id: 3000, descriptors: descriptors,
uuid: '2A00', canRead: true,
descriptors: descriptors, canWrite: true,
canRead: true, canWriteWithoutResponse: true,
canWrite: true, canNotify: true,
canWriteWithoutResponse: true, ),
canNotify: true, ];
), final services = [
]; proto.GattService(
final services = [ key: '0',
proto.GattService( uuid: '1800',
id: 2000, characteristics: characteristics,
uuid: '1800', ),
characteristics: characteristics, ];
), final gatt = proto.GATT(
]; key: '0',
final gatt = proto.GATT( maximumWriteLength: 20,
id: 1000, services: services,
mtu: 23, );
services: services, return gatt.writeToBuffer();
); case proto.MessageCategory.GATT_DISCONNECT:
return gatt.writeToBuffer(); return null;
} else if (call.method == proto.MessageCategory.GATT_DISCONNECT.name) { case proto.MessageCategory.GATT_CHARACTERISTIC_READ:
return null; return [0x01, 0x02, 0x03, 0x04, 0x05];
} else if (call.method == case proto.MessageCategory.GATT_CHARACTERISTIC_WRITE:
proto.MessageCategory.GATT_CHARACTERISTIC_READ.name) { return null;
return [0x01, 0x02, 0x03, 0x04, 0x05]; case proto.MessageCategory.GATT_CHARACTERISTIC_NOTIFY:
} else if (call.method == return null;
proto.MessageCategory.GATT_CHARACTERISTIC_WRITE.name) { case proto.MessageCategory.GATT_DESCRIPTOR_READ:
return null; return [0x05, 0x04, 0x03, 0x02, 0x01];
} else if (call.method == case proto.MessageCategory.GATT_DESCRIPTOR_WRITE:
proto.MessageCategory.GATT_CHARACTERISTIC_NOTIFY.name) { return null;
return null; default:
} else if (call.method == throw UnimplementedError();
proto.MessageCategory.GATT_DESCRIPTOR_READ.name) {
return [0x05, 0x04, 0x03, 0x02, 0x01];
} else if (call.method ==
proto.MessageCategory.GATT_DESCRIPTOR_WRITE.name) {
return null;
} else {
throw UnimplementedError();
} }
}); });
event.setMockMethodCallHandler((call) async { event.setMockMethodCallHandler((call) async {
@ -81,7 +74,7 @@ void main() {
case 'listen': case 'listen':
final state = proto.Message( final state = proto.Message(
category: proto.MessageCategory.BLUETOOTH_STATE, category: proto.MessageCategory.BLUETOOTH_STATE,
state: false, state: proto.BluetoothState.POWERED_OFF,
).writeToBuffer(); ).writeToBuffer();
await ServicesBinding.instance!.defaultBinaryMessenger await ServicesBinding.instance!.defaultBinaryMessenger
.handlePlatformMessage( .handlePlatformMessage(
@ -92,7 +85,7 @@ void main() {
final discovery = proto.Message( final discovery = proto.Message(
category: proto.MessageCategory.CENTRAL_DISCOVERED, category: proto.MessageCategory.CENTRAL_DISCOVERED,
discovery: proto.Discovery( discovery: proto.Discovery(
address: 'aa:bb:cc:dd:ee:ff', uuid: 'AABB',
rssi: -50, rssi: -50,
advertisements: [0x07, 0xff, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa], advertisements: [0x07, 0xff, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa],
), ),
@ -105,9 +98,9 @@ void main() {
); );
final connectionLost = proto.Message( final connectionLost = proto.Message(
category: proto.MessageCategory.GATT_CONNECTION_LOST, category: proto.MessageCategory.GATT_CONNECTION_LOST,
connectionLost: proto.ConnectionLost( connectionLost: proto.GattConnectionLost(
id: 1000, key: '0',
errorCode: 19, error: 'Connection lost.',
), ),
).writeToBuffer(); ).writeToBuffer();
await ServicesBinding.instance!.defaultBinaryMessenger await ServicesBinding.instance!.defaultBinaryMessenger
@ -119,7 +112,9 @@ void main() {
final characteristicValue = proto.Message( final characteristicValue = proto.Message(
category: proto.MessageCategory.GATT_CHARACTERISTIC_NOTIFY, category: proto.MessageCategory.GATT_CHARACTERISTIC_NOTIFY,
characteristicValue: proto.GattCharacteristicValue( characteristicValue: proto.GattCharacteristicValue(
id: 3000, gattKey: '0',
serviceKey: '0',
key: '0',
value: [0x0A, 0x0B, 0x0C, 0x0D, 0x0E], value: [0x0A, 0x0B, 0x0C, 0x0D, 0x0E],
), ),
).writeToBuffer(); ).writeToBuffer();
@ -142,33 +137,19 @@ void main() {
event.setMockMethodCallHandler(null); event.setMockMethodCallHandler(null);
}); });
test(
'${proto.MessageCategory.BLUETOOTH_AVAILABLE}',
() async {
final actual = await central.available;
expect(actual, true);
expect(
calls,
[
isMethodCall(
proto.MessageCategory.BLUETOOTH_AVAILABLE.name,
arguments: null,
),
],
);
},
);
test( test(
'${proto.MessageCategory.BLUETOOTH_STATE}', '${proto.MessageCategory.BLUETOOTH_STATE}',
() async { () async {
final actual = await central.state; final actual = await central.state;
expect(actual, true); expect(actual, BluetoothState.poweredOn);
expect( expect(
calls, calls,
[ [
isMethodCall( isMethodCall(
proto.MessageCategory.BLUETOOTH_STATE.name, '',
arguments: null, arguments: proto.Message(
category: proto.MessageCategory.BLUETOOTH_STATE,
).writeToBuffer(),
), ),
], ],
); );
@ -178,7 +159,7 @@ void main() {
'${proto.MessageCategory.BLUETOOTH_STATE} EVENT', '${proto.MessageCategory.BLUETOOTH_STATE} EVENT',
() async { () async {
final actual = await central.stateChanged.first; final actual = await central.stateChanged.first;
expect(actual, false); expect(actual, BluetoothState.poweredOff);
}, },
); );
test( test(
@ -190,9 +171,12 @@ void main() {
calls, calls,
[ [
isMethodCall( isMethodCall(
proto.MessageCategory.CENTRAL_START_DISCOVERY.name, '',
arguments: proto.StartDiscoveryArguments( arguments: proto.Message(
services: services.map((uuid) => uuid.name), category: proto.MessageCategory.CENTRAL_START_DISCOVERY,
startDiscoveryArguments: proto.StartDiscoveryArguments(
services: services.map((uuid) => uuid.name),
),
).writeToBuffer(), ).writeToBuffer(),
), ),
], ],
@ -207,8 +191,10 @@ void main() {
calls, calls,
[ [
isMethodCall( isMethodCall(
proto.MessageCategory.CENTRAL_STOP_DISCOVERY.name, '',
arguments: null, arguments: proto.Message(
category: proto.MessageCategory.CENTRAL_STOP_DISCOVERY,
).writeToBuffer(),
), ),
], ],
); );
@ -218,8 +204,8 @@ void main() {
'${proto.MessageCategory.CENTRAL_DISCOVERED} EVENT', '${proto.MessageCategory.CENTRAL_DISCOVERED} EVENT',
() async { () async {
final actual = await central.discovered.first; final actual = await central.discovered.first;
final address = MAC('aa:bb:cc:dd:ee:ff'); final uuid = UUID('AABB');
expect(actual.address, address); expect(actual.uuid, uuid);
final rssi = -50; final rssi = -50;
expect(actual.rssi, rssi); expect(actual.rssi, rssi);
final advertisements = { final advertisements = {
@ -231,9 +217,9 @@ void main() {
test( test(
'${proto.MessageCategory.CENTRAL_CONNECT}', '${proto.MessageCategory.CENTRAL_CONNECT}',
() async { () async {
final address = MAC('aa:bb:cc:dd:ee:ff'); final uuid = UUID('AABB');
final actual = await central.connect(address); final actual = await central.connect(uuid);
expect(actual.mtu, 23); expect(actual.maximumWriteLength, 20);
expect(actual.services.length, 1); expect(actual.services.length, 1);
final service = actual.services.values.first; final service = actual.services.values.first;
expect(service.uuid, UUID('1800')); expect(service.uuid, UUID('1800'));
@ -251,9 +237,12 @@ void main() {
calls, calls,
[ [
isMethodCall( isMethodCall(
proto.MessageCategory.CENTRAL_CONNECT.name, '',
arguments: proto.ConnectArguments( arguments: proto.Message(
address: address.name, category: proto.MessageCategory.CENTRAL_CONNECT,
connectArguments: proto.ConnectArguments(
uuid: uuid.name,
),
).writeToBuffer(), ).writeToBuffer(),
), ),
], ],
@ -263,23 +252,26 @@ void main() {
test( test(
'${proto.MessageCategory.GATT_DISCONNECT}', '${proto.MessageCategory.GATT_DISCONNECT}',
() async { () async {
final address = MAC('aa:bb:cc:dd:ee:ff'); final uuid = UUID('AABB');
final gatt = await central.connect(address); final gatt = await central.connect(uuid);
await gatt.disconnect(); await gatt.disconnect();
expect( expect(
calls, calls,
[ [
isMethodCall( isMethodCall(
proto.MessageCategory.CENTRAL_CONNECT.name, '',
arguments: proto.ConnectArguments( arguments: proto.Message(
address: address.name, category: proto.MessageCategory.CENTRAL_CONNECT,
connectArguments: proto.ConnectArguments(
uuid: uuid.name,
),
).writeToBuffer(), ).writeToBuffer(),
), ),
isMethodCall( isMethodCall(
proto.MessageCategory.GATT_DISCONNECT.name, '',
arguments: proto.GattDisconnectArguments( arguments: proto.Message(
address: address.name, category: proto.MessageCategory.GATT_DISCONNECT,
id: 1000, disconnectArguments: proto.GattDisconnectArguments(key: '0'),
).writeToBuffer(), ).writeToBuffer(),
), ),
], ],
@ -289,17 +281,32 @@ void main() {
test( test(
'${proto.MessageCategory.GATT_CONNECTION_LOST}', '${proto.MessageCategory.GATT_CONNECTION_LOST}',
() async { () async {
final address = MAC('aa:bb:cc:dd:ee:ff'); final uuid = UUID('AABB');
final gatt = await central.connect(address); final gatt = await central.connect(uuid);
final actual = await gatt.connectionLost.first; final actual = await gatt.connectionLost.first;
expect(actual, 19); final matcher = Exception('Connection lost.');
expect('$actual', '$matcher');
expect(
calls,
[
isMethodCall(
'',
arguments: proto.Message(
category: proto.MessageCategory.CENTRAL_CONNECT,
connectArguments: proto.ConnectArguments(
uuid: uuid.name,
),
).writeToBuffer(),
),
],
);
}, },
); );
test( test(
'${proto.MessageCategory.GATT_CHARACTERISTIC_READ}', '${proto.MessageCategory.GATT_CHARACTERISTIC_READ}',
() async { () async {
final address = MAC('aa:bb:cc:dd:ee:ff'); final uuid = UUID('AABB');
final gatt = await central.connect(address); final gatt = await central.connect(uuid);
final service = gatt.services.values.first; final service = gatt.services.values.first;
final characteristic = service.characteristics.values.first; final characteristic = service.characteristics.values.first;
final actual = await characteristic.read(); final actual = await characteristic.read();
@ -308,18 +315,24 @@ void main() {
calls, calls,
[ [
isMethodCall( isMethodCall(
proto.MessageCategory.CENTRAL_CONNECT.name, '',
arguments: proto.ConnectArguments( arguments: proto.Message(
address: address.name, category: proto.MessageCategory.CENTRAL_CONNECT,
connectArguments: proto.ConnectArguments(
uuid: uuid.name,
),
).writeToBuffer(), ).writeToBuffer(),
), ),
isMethodCall( isMethodCall(
proto.MessageCategory.GATT_CHARACTERISTIC_READ.name, '',
arguments: proto.GattCharacteristicReadArguments( arguments: proto.Message(
address: address.name, category: proto.MessageCategory.GATT_CHARACTERISTIC_READ,
serviceUuid: service.uuid.name, characteristicReadArguments:
uuid: characteristic.uuid.name, proto.GattCharacteristicReadArguments(
id: 3000, gattKey: '0',
serviceKey: '0',
key: '0',
),
).writeToBuffer(), ).writeToBuffer(),
), ),
], ],
@ -329,8 +342,8 @@ void main() {
test( test(
'${proto.MessageCategory.GATT_CHARACTERISTIC_WRITE}', '${proto.MessageCategory.GATT_CHARACTERISTIC_WRITE}',
() async { () async {
final address = MAC('aa:bb:cc:dd:ee:ff'); final uuid = UUID('AABB');
final gatt = await central.connect(address); final gatt = await central.connect(uuid);
final service = gatt.services.values.first; final service = gatt.services.values.first;
final characteristic = service.characteristics.values.first; final characteristic = service.characteristics.values.first;
final value = [0x01, 0x02, 0x03, 0x04, 0x05]; final value = [0x01, 0x02, 0x03, 0x04, 0x05];
@ -339,20 +352,26 @@ void main() {
calls, calls,
[ [
isMethodCall( isMethodCall(
proto.MessageCategory.CENTRAL_CONNECT.name, '',
arguments: proto.ConnectArguments( arguments: proto.Message(
address: address.name, category: proto.MessageCategory.CENTRAL_CONNECT,
connectArguments: proto.ConnectArguments(
uuid: uuid.name,
),
).writeToBuffer(), ).writeToBuffer(),
), ),
isMethodCall( isMethodCall(
proto.MessageCategory.GATT_CHARACTERISTIC_WRITE.name, '',
arguments: proto.GattCharacteristicWriteArguments( arguments: proto.Message(
address: address.name, category: proto.MessageCategory.GATT_CHARACTERISTIC_WRITE,
serviceUuid: service.uuid.name, characteristicWriteArguments:
uuid: characteristic.uuid.name, proto.GattCharacteristicWriteArguments(
id: 3000, gattKey: '0',
value: value, serviceKey: '0',
withoutResponse: true, key: '0',
value: value,
withoutResponse: true,
),
).writeToBuffer(), ).writeToBuffer(),
), ),
], ],
@ -362,8 +381,8 @@ void main() {
test( test(
'${proto.MessageCategory.GATT_CHARACTERISTIC_NOTIFY}', '${proto.MessageCategory.GATT_CHARACTERISTIC_NOTIFY}',
() async { () async {
final address = MAC('aa:bb:cc:dd:ee:ff'); final uuid = UUID('AABB');
final gatt = await central.connect(address); final gatt = await central.connect(uuid);
final service = gatt.services.values.first; final service = gatt.services.values.first;
final characteristic = service.characteristics.values.first; final characteristic = service.characteristics.values.first;
await characteristic.notify(true); await characteristic.notify(true);
@ -371,19 +390,25 @@ void main() {
calls, calls,
[ [
isMethodCall( isMethodCall(
proto.MessageCategory.CENTRAL_CONNECT.name, '',
arguments: proto.ConnectArguments( arguments: proto.Message(
address: address.name, category: proto.MessageCategory.CENTRAL_CONNECT,
connectArguments: proto.ConnectArguments(
uuid: uuid.name,
),
).writeToBuffer(), ).writeToBuffer(),
), ),
isMethodCall( isMethodCall(
proto.MessageCategory.GATT_CHARACTERISTIC_NOTIFY.name, '',
arguments: proto.GattCharacteristicNotifyArguments( arguments: proto.Message(
address: address.name, category: proto.MessageCategory.GATT_CHARACTERISTIC_NOTIFY,
serviceUuid: service.uuid.name, characteristicNotifyArguments:
uuid: characteristic.uuid.name, proto.GattCharacteristicNotifyArguments(
id: 3000, gattKey: '0',
state: true, serviceKey: '0',
key: '0',
state: true,
),
).writeToBuffer(), ).writeToBuffer(),
), ),
], ],
@ -393,19 +418,33 @@ void main() {
test( test(
'${proto.MessageCategory.GATT_CHARACTERISTIC_NOTIFY} EVENT', '${proto.MessageCategory.GATT_CHARACTERISTIC_NOTIFY} EVENT',
() async { () async {
final address = MAC('aa:bb:cc:dd:ee:ff'); final uuid = UUID('AABB');
final gatt = await central.connect(address); final gatt = await central.connect(uuid);
final service = gatt.services.values.first; final service = gatt.services.values.first;
final characteristic = service.characteristics.values.first; final characteristic = service.characteristics.values.first;
final value = await characteristic.valueChanged.first; final value = await characteristic.valueChanged.first;
expect(value, [0x0A, 0x0B, 0x0C, 0x0D, 0x0E]); expect(value, [0x0A, 0x0B, 0x0C, 0x0D, 0x0E]);
expect(
calls,
[
isMethodCall(
'',
arguments: proto.Message(
category: proto.MessageCategory.CENTRAL_CONNECT,
connectArguments: proto.ConnectArguments(
uuid: uuid.name,
),
).writeToBuffer(),
),
],
);
}, },
); );
test( test(
'${proto.MessageCategory.GATT_DESCRIPTOR_READ}', '${proto.MessageCategory.GATT_DESCRIPTOR_READ}',
() async { () async {
final address = MAC('aa:bb:cc:dd:ee:ff'); final uuid = UUID('AABB');
final gatt = await central.connect(address); final gatt = await central.connect(uuid);
final service = gatt.services.values.first; final service = gatt.services.values.first;
final characteristic = service.characteristics.values.first; final characteristic = service.characteristics.values.first;
final descriptor = characteristic.descriptors.values.first; final descriptor = characteristic.descriptors.values.first;
@ -415,19 +454,24 @@ void main() {
calls, calls,
[ [
isMethodCall( isMethodCall(
proto.MessageCategory.CENTRAL_CONNECT.name, '',
arguments: proto.ConnectArguments( arguments: proto.Message(
address: address.name, category: proto.MessageCategory.CENTRAL_CONNECT,
connectArguments: proto.ConnectArguments(
uuid: uuid.name,
),
).writeToBuffer(), ).writeToBuffer(),
), ),
isMethodCall( isMethodCall(
proto.MessageCategory.GATT_DESCRIPTOR_READ.name, '',
arguments: proto.GattDescriptorReadArguments( arguments: proto.Message(
address: address.name, category: proto.MessageCategory.GATT_DESCRIPTOR_READ,
serviceUuid: service.uuid.name, descriptorReadArguments: proto.GattDescriptorReadArguments(
characteristicUuid: characteristic.uuid.name, gattKey: '0',
uuid: descriptor.uuid.name, serviceKey: '0',
id: 4000, characteristicKey: '0',
key: '0',
),
).writeToBuffer(), ).writeToBuffer(),
), ),
], ],
@ -437,8 +481,8 @@ void main() {
test( test(
'${proto.MessageCategory.GATT_DESCRIPTOR_WRITE}', '${proto.MessageCategory.GATT_DESCRIPTOR_WRITE}',
() async { () async {
final address = MAC('aa:bb:cc:dd:ee:ff'); final uuid = UUID('AABB');
final gatt = await central.connect(address); final gatt = await central.connect(uuid);
final service = gatt.services.values.first; final service = gatt.services.values.first;
final characteristic = service.characteristics.values.first; final characteristic = service.characteristics.values.first;
final descriptor = characteristic.descriptors.values.first; final descriptor = characteristic.descriptors.values.first;
@ -448,20 +492,25 @@ void main() {
calls, calls,
[ [
isMethodCall( isMethodCall(
proto.MessageCategory.CENTRAL_CONNECT.name, '',
arguments: proto.ConnectArguments( arguments: proto.Message(
address: address.name, category: proto.MessageCategory.CENTRAL_CONNECT,
connectArguments: proto.ConnectArguments(
uuid: uuid.name,
),
).writeToBuffer(), ).writeToBuffer(),
), ),
isMethodCall( isMethodCall(
proto.MessageCategory.GATT_DESCRIPTOR_WRITE.name, '',
arguments: proto.GattDescriptorWriteArguments( arguments: proto.Message(
address: address.name, category: proto.MessageCategory.GATT_DESCRIPTOR_WRITE,
serviceUuid: service.uuid.name, descriptorWriteArguments: proto.GattDescriptorWriteArguments(
characteristicUuid: characteristic.uuid.name, gattKey: '0',
uuid: descriptor.uuid.name, serviceKey: '0',
id: 4000, characteristicKey: '0',
value: value, key: '0',
value: value,
),
).writeToBuffer(), ).writeToBuffer(),
), ),
], ],