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
- Fix connect blocked when bluetooth closed.

View File

@ -26,17 +26,16 @@ dependencies:
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
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
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
- Only support Android for now, iOS will available as soon as possible.
- Only support central APIs for now.
- Not support peripheral APIs for now.

View File

@ -2,7 +2,7 @@ group 'dev.yanshouwang.bluetooth_low_energy'
version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.5.20'
ext.kotlin_version = '1.5.21'
repositories {
google()
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 BLUETOOTH_ADAPTER_STATE_UNKNOWN = -1
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
}
@ -60,28 +50,32 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler
private lateinit var context: Context
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 bluetoothManager by lazy { context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager }
private val bluetoothAdapter by lazy { bluetoothManager.adapter }
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 {
object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val oldState = intent!!.getIntExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, BLUETOOTH_ADAPTER_STATE_UNKNOWN).opened
val newState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BLUETOOTH_ADAPTER_STATE_UNKNOWN).opened
// TODO: clear status when bluetooth closed.
val oldState = intent!!.getIntExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, BLUETOOTH_ADAPTER_STATE_UNKNOWN).messageState
val newState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BLUETOOTH_ADAPTER_STATE_UNKNOWN).messageState
if (newState == oldState) return
val closed = !newState
if (closed && scanning) scanning = false
if (newState != BluetoothState.POWERED_ON && scanning) scanning = false
val event = Message.newBuilder()
.setCategory(BLUETOOTH_STATE)
.setState(newState)
.build()
.toByteArray()
sink?.success(event)
events?.success(event)
}
}
}
@ -93,6 +87,7 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler
private var scanCode = NO_ERROR
private var scanning = false
private val scanCallback by lazy {
object : ScanCallback() {
override fun onScanFailed(errorCode: Int) {
@ -103,122 +98,129 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler
override fun onScanResult(callbackType: Int, result: ScanResult?) {
super.onScanResult(callbackType, result)
if (result == null) return
val address = result.device.address
val rssi = result.rssi
val record = result.scanRecord
val advertisements =
if (record == null) ByteString.EMPTY
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()
.setAddress(address)
.setRssi(rssi)
.setUuid(result.device.uuid)
.setRssi(result.rssi)
.setAdvertisements(advertisements)
.setConnectable(connectable)
val discovery = builder.build()
val event = Message.newBuilder()
.setCategory(CENTRAL_DISCOVERED)
.setDiscovery(discovery)
.build()
.toByteArray()
sink?.success(event)
events?.success(event)
}
override fun onBatchScanResults(results: MutableList<ScanResult>?) {
super.onBatchScanResults(results)
if (results == null) return
for (result in results) {
val address = result.device.address
val rssi = result.rssi
val record = result.scanRecord
val advertisements =
if (record == null) ByteString.EMPTY
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()
.setAddress(address)
.setRssi(rssi)
.setUuid(result.device.uuid)
.setRssi(result.rssi)
.setAdvertisements(advertisements)
.setConnectable(connectable)
val discovery = builder.build()
val event = Message.newBuilder()
.setCategory(CENTRAL_DISCOVERED)
.setDiscovery(discovery)
.build()
.toByteArray()
sink?.success(event)
events?.success(event)
}
}
}
}
private val gatts by lazy { mutableMapOf<String, BluetoothGatt>() }
private val connects by lazy { mutableMapOf<String, Result>() }
private val mtus by lazy { mutableMapOf<String, Int>() }
private val disconnects by lazy { mutableMapOf<String, Result>() }
private val characteristicReads by lazy { mutableMapOf<Int, Result>() }
private val characteristicWrites by lazy { mutableMapOf<Int, Result>() }
private val descriptorReads by lazy { mutableMapOf<Int, Result>() }
private val descriptorWrites by lazy { mutableMapOf<Int, Result>() }
private val nativeGATTs by lazy { mutableMapOf<String, NativeGATT>() }
private val connects by lazy { mutableMapOf<BluetoothGatt, Result>() }
private val maximumWriteLengths by lazy { mutableMapOf<BluetoothGatt, Int>() }
private val disconnects by lazy { mutableMapOf<BluetoothGatt, Result>() }
private val characteristicReads by lazy { mutableMapOf<BluetoothGattCharacteristic, Result>() }
private val characteristicWrites by lazy { mutableMapOf<BluetoothGattCharacteristic, Result>() }
private val descriptorReads by lazy { mutableMapOf<BluetoothGattDescriptor, Result>() }
private val descriptorWrites by lazy { mutableMapOf<BluetoothGattDescriptor, Result>() }
private val bluetoothGattCallback by lazy {
object : BluetoothGattCallback() {
override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
super.onConnectionStateChange(gatt, status, newState)
val address = gatt!!.device.address
when (status) {
BluetoothGatt.GATT_SUCCESS -> {
when (newState) {
BluetoothProfile.STATE_DISCONNECTED -> {
// Maybe disconnect succeed, connect failed, or connection lost when an adaptor closed event triggered.
gatts.remove(address)!!.close()
val disconnect = disconnects.remove(address)
if (disconnect != null) handler.post { disconnect.success() }
gatt!!.close()
val connect = connects.remove(gatt)
if (connect != null) handler.post { connect.error("GATT error with status: $status.", null, null) }
else {
val connect = connects.remove(address)
if (connect != null) handler.post { connect.error(BLUETOOTH_ADAPTER_CLOSED) }
val nativeGATT = nativeGATTs.entries.first { entry -> entry.value.value === gatt }
nativeGATTs.remove(nativeGATT.key)
val disconnect = disconnects.remove(gatt)
if (disconnect != null) handler.post { disconnect.success() }
else {
val id = gatt.hashCode()
val connectionLost = ConnectionLost.newBuilder()
.setId(id)
.setErrorCode(BLUETOOTH_ADAPTER_CLOSED)
val connectionLost = GattConnectionLost.newBuilder()
.setKey(nativeGATT.key)
.setError("GATT error with status: $status")
.build()
val event = Message.newBuilder()
.setCategory(GATT_CONNECTION_LOST)
.setConnectionLost(connectionLost)
.build()
.toByteArray()
handler.post { sink?.success(event) }
handler.post { events?.success(event) }
}
}
}
BluetoothProfile.STATE_CONNECTED -> {
// Must be connect succeed.
val requested = gatt.requestMtu(512)
if (!requested) {
gatts.remove(address)!!.close()
val connect = connects.remove(address)!!
handler.post { connect.error(REQUEST_MTU_FAILED) }
}
val requested = gatt!!.requestMtu(512)
if (!requested) gatt.disconnect()
}
else -> throw NotImplementedError() // should never be called.
}
}
else -> {
// Maybe connect failed, disconnect failed or connection lost when an adaptor closed event triggered.
gatts.remove(address)!!.close()
val connect = connects.remove(address)
if (connect != null) handler.post { connect.error(status) }
// Maybe connect failed, disconnect failed or connection lost.
gatt!!.close()
val connect = connects.remove(gatt)
if (connect != null) handler.post { connect.error("GATT error with status: $status", null, null) }
else {
val disconnect = disconnects.remove(address)
if (disconnect != null) handler.post { disconnect.error(status) }
val nativeGATT = nativeGATTs.entries.first { entry -> entry.value.value === gatt }
nativeGATTs.remove(nativeGATT.key)
val disconnect = disconnects.remove(gatt)
if (disconnect != null) handler.post { disconnect.error("GATT error with status: $status", null, null) }
else {
val id = gatt.hashCode()
val connectionLost = ConnectionLost.newBuilder()
.setId(id)
.setErrorCode(status)
val connectionLost = GattConnectionLost.newBuilder()
.setKey(nativeGATT.key)
.setError("GATT error with status: $status")
.build()
val event = Message.newBuilder()
.setCategory(GATT_CONNECTION_LOST)
.setConnectionLost(connectionLost)
.build()
.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) {
super.onMtuChanged(gatt, mtu, status)
val address = gatt!!.device.address
val code = when (status) {
when (status) {
BluetoothGatt.GATT_SUCCESS -> {
val discovered = gatt.discoverServices()
if (discovered) {
mtus[address] = mtu
NO_ERROR
} else DISCOVER_SERVICES_FAILED
val discovered = gatt!!.discoverServices()
if (discovered) maximumWriteLengths[gatt] = mtu - 3
else gatt.disconnect()
}
else -> status
}
if (code != NO_ERROR) {
gatts.remove(address)!!.close()
val connect = connects.remove(address)!!
handler.post { connect.error(code) }
else -> gatt!!.disconnect()
}
}
override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
super.onServicesDiscovered(gatt, status)
val address = gatt!!.device.address
val connect = connects.remove(address)!!
val mtu = mtus.remove(address)!!
val maximumWriteLength = maximumWriteLengths.remove(gatt)!!
when (status) {
BluetoothGatt.GATT_SUCCESS -> {
val id = gatt.hashCode()
val services = gatt.services.map { service ->
val serviceId = service.hashCode()
val serviceUUID = service.uuid.toString()
val characteristics = service.characteristics.map { characteristic ->
val characteristicId = characteristic.hashCode()
val characteristicUUID = characteristic.uuid.toString()
val properties = characteristic.properties
val canRead = properties and BluetoothGattCharacteristic.PROPERTY_READ != 0
val canWrite = properties and BluetoothGattCharacteristic.PROPERTY_WRITE != 0
val canWriteWithoutResponse = properties and BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE != 0
val canNotify = properties and BluetoothGattCharacteristic.PROPERTY_NOTIFY != 0
val descriptors = characteristic.descriptors.map { descriptor ->
val descriptorId = descriptor.hashCode()
val nativeServices = mutableMapOf<String, NativeGattService>()
val messageServices = mutableListOf<GattService>()
for (service in gatt!!.services) {
val nativeCharacteristics = mutableMapOf<String, NativeGattCharacteristic>()
val messageCharacteristics = mutableListOf<GattCharacteristic>()
for (characteristic in service.characteristics) {
val nativeDescriptors = mutableMapOf<String, NativeGattDescriptor>()
val messageDescriptors = mutableListOf<GattDescriptor>()
for (descriptor in characteristic.descriptors) {
// Add native descriptor.
val nativeDescriptor = NativeGattDescriptor(descriptor)
nativeDescriptors[nativeDescriptor.key] = nativeDescriptor
// Add message descriptor.
val descriptorUUID = descriptor.uuid.toString()
GattDescriptor.newBuilder()
.setId(descriptorId)
val messageDescriptor = GattDescriptor.newBuilder()
.setKey(nativeDescriptor.key)
.setUuid(descriptorUUID)
.build()
messageDescriptors.add(messageDescriptor)
}
GattCharacteristic.newBuilder()
.setId(characteristicId)
// Add native characteristic.
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)
.setCanRead(canRead)
.setCanWrite(canWrite)
.setCanWriteWithoutResponse(canWriteWithoutResponse)
.setCanNotify(canNotify)
.addAllDescriptors(descriptors)
.addAllDescriptors(messageDescriptors)
.build()
messageCharacteristics.add(messageCharacteristic)
}
GattService.newBuilder()
.setId(serviceId)
// Add native service.
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)
.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()
.setId(id)
.setMtu(mtu)
.addAllServices(services)
.setKey(nativeGATT.key)
.setMaximumWriteLength(maximumWriteLength)
.addAllServices(messageServices)
.build()
.toByteArray()
val connect = connects.remove(gatt)!!
handler.post { connect.success(reply) }
}
else -> {
gatts.remove(address)!!.close()
handler.post { connect.error(status) }
}
else -> gatt!!.disconnect()
}
}
override fun onCharacteristicRead(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int) {
super.onCharacteristicRead(gatt, characteristic, status)
val key = characteristic!!.hashCode()
val read = characteristicReads.remove(key)!!
val read = characteristicReads.remove(characteristic)!!
when (status) {
BluetoothGatt.GATT_SUCCESS -> handler.post { read.success(characteristic.value) }
else -> handler.post { read.error(status) }
BluetoothGatt.GATT_SUCCESS -> handler.post { read.success(characteristic!!.value) }
else -> handler.post { read.error("GATT error with status: $status", null, null) }
}
}
override fun onCharacteristicWrite(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int) {
super.onCharacteristicWrite(gatt, characteristic, status)
val key = characteristic!!.hashCode()
val write = characteristicWrites.remove(key)!!
val write = characteristicWrites.remove(characteristic)!!
when (status) {
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?) {
super.onCharacteristicChanged(gatt, characteristic)
val id = characteristic!!.hashCode()
val value = ByteString.copyFrom(characteristic.value)
val nativeGATT = nativeGATTs.values.first { entry -> entry.value === gatt }
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()
.setId(id)
.setGattKey(nativeGATT.key)
.setServiceKey(nativeService.key)
.setKey(nativeCharacteristic.key)
.setValue(value)
.build()
val event = Message.newBuilder()
@ -335,26 +348,24 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler
.setCharacteristicValue(characteristicValue)
.build()
.toByteArray()
handler.post { sink?.success(event) }
handler.post { events?.success(event) }
}
override fun onDescriptorRead(gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int) {
super.onDescriptorRead(gatt, descriptor, status)
val key = descriptor!!.hashCode()
val read = descriptorReads.remove(key)!!
val read = descriptorReads.remove(descriptor)!!
when (status) {
BluetoothGatt.GATT_SUCCESS -> handler.post { read.success(descriptor.value) }
else -> handler.post { read.error(status) }
BluetoothGatt.GATT_SUCCESS -> handler.post { read.success(descriptor!!.value) }
else -> handler.post { read.error("GATT error with status: $status", null, null) }
}
}
override fun onDescriptorWrite(gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int) {
super.onDescriptorWrite(gatt, descriptor, status)
val key = descriptor!!.hashCode()
val write = descriptorWrites.remove(key)!!
val write = descriptorWrites.remove(descriptor)!!
when (status) {
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) {
// Clear connections.
for (gatt in gatts.values) gatt.close()
gatts.clear()
for (nativeGATT in nativeGATTs.values) nativeGATT.value.disconnect()
// Stop scan.
if (scanning) stopScan()
// Unregister bluetooth adapter state receiver.
@ -411,37 +421,30 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler
}
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
val category = call.category
if (category != BLUETOOTH_AVAILABLE && category != BLUETOOTH_STATE && !bluetoothAdapter.state.opened) result.error(BLUETOOTH_ADAPTER_CLOSED)
else when (category) {
BLUETOOTH_AVAILABLE -> result.success(bluetoothAvailable)
BLUETOOTH_STATE -> result.success(bluetoothAdapter.state.opened)
val data = call.arguments<ByteArray>()
val command = Message.parseFrom(data)
when (command.category!!) {
BLUETOOTH_STATE -> result.success(bluetoothState.number)
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 {
requestPermissionsHandler != null -> result.error(INVALID_REQUEST)
hasPermission -> startDiscovery.run()
else -> {
val startDiscovery = Runnable {
val data = call.arguments<ByteArray>()
val arguments = StartDiscoveryArguments.parseFrom(data)
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)
}
requestPermissionsHandler = { granted ->
if (granted) startDiscovery.run()
else result.error("Discovery start failed because `ACCESS_FINE_LOCATION` was denied by user.", null, null)
}
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()
result.success()
}
CENTRAL_DISCOVERED -> result.notImplemented()
CENTRAL_CONNECT -> {
val data = call.arguments<ByteArray>()
val arguments = ConnectArguments.parseFrom(data)
val address = arguments.address
val connect = connects[address]
var gatt = gatts[address]
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
val device = bluetoothAdapter.getRemoteDevice(command.connectArguments.uuid.address)
val 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[gatt] = result
}
GATT_DISCONNECT -> {
val data = call.arguments<ByteArray>()
val arguments = GattDisconnectArguments.parseFrom(data)
val address = arguments.address
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()
}
val nativeGATT = nativeGATTs[command.disconnectArguments.key]!!
disconnects[nativeGATT.value] = result
nativeGATT.value.disconnect()
}
GATT_CONNECTION_LOST -> result.notImplemented()
GATT_CHARACTERISTIC_READ -> {
val data = call.arguments<ByteArray>()
val arguments = GattCharacteristicReadArguments.parseFrom(data)
val gatt = gatts[arguments.address]
if (gatt == null) result.error(INVALID_REQUEST)
else {
val serviceUUID = UUID.fromString(arguments.serviceUuid)
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
}
}
val nativeGATT = nativeGATTs[command.characteristicReadArguments.gattKey]!!
val nativeService = nativeGATT.services[command.characteristicReadArguments.serviceKey]!!
val nativeCharacteristic = nativeService.characteristics[command.characteristicReadArguments.key]!!
val read = nativeGATT.value.readCharacteristic(nativeCharacteristic.value)
if (read) characteristicReads[nativeCharacteristic.value] = result
else result.error("Characteristic read failed.", null, null)
}
GATT_CHARACTERISTIC_WRITE -> {
val data = call.arguments<ByteArray>()
val arguments = GattCharacteristicWriteArguments.parseFrom(data)
val gatt = gatts[arguments.address]
if (gatt == null) result.error(INVALID_REQUEST)
else {
val serviceUUID = UUID.fromString(arguments.serviceUuid)
val service = gatt.getService(serviceUUID)
val uuid = UUID.fromString(arguments.uuid)
val characteristic = service.getCharacteristic(uuid)
val id = characteristic.hashCode()
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
}
}
val nativeGATT = nativeGATTs[command.characteristicWriteArguments.gattKey]!!
val nativeService = nativeGATT.services[command.characteristicWriteArguments.serviceKey]!!
val nativeCharacteristic = nativeService.characteristics[command.characteristicWriteArguments.key]!!
nativeCharacteristic.value.writeType =
if (command.characteristicWriteArguments.withoutResponse) BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE
else BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
nativeCharacteristic.value.value = command.characteristicWriteArguments.value.toByteArray()
val written = nativeGATT.value.writeCharacteristic(nativeCharacteristic.value)
if (written) characteristicWrites[nativeCharacteristic.value] = result
else result.error("Characteristic write failed.", null, null)
}
GATT_CHARACTERISTIC_NOTIFY -> {
val data = call.arguments<ByteArray>()
val arguments = GattCharacteristicNotifyArguments.parseFrom(data)
val gatt = gatts[arguments.address]
if (gatt == null) result.error(INVALID_REQUEST)
else {
val serviceUUID = UUID.fromString(arguments.serviceUuid)
val service = gatt.getService(serviceUUID)
val uuid = UUID.fromString(arguments.uuid)
val characteristic = service.getCharacteristic(uuid)
val id = characteristic.hashCode()
val descriptorUUID = UUID.fromString(CLIENT_CHARACTERISTIC_CONFIG)
val descriptor = characteristic.getDescriptor(descriptorUUID)
val descriptorId = descriptor.hashCode()
val descriptorWrite = descriptorWrites[descriptorId]
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
}
}
}
val nativeGATT = nativeGATTs[command.characteristicNotifyArguments.gattKey]!!
val nativeService = nativeGATT.services[command.characteristicNotifyArguments.serviceKey]!!
val nativeCharacteristic = nativeService.characteristics[command.characteristicNotifyArguments.key]!!
val descriptorUUID = UUID.fromString(CLIENT_CHARACTERISTIC_CONFIG)
val descriptor = nativeCharacteristic.value.getDescriptor(descriptorUUID)
val notified = nativeGATT.value.setCharacteristicNotification(nativeCharacteristic.value, command.characteristicNotifyArguments.state)
if (notified) {
descriptor.value =
if (command.characteristicNotifyArguments.state) BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
else BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE
val written = nativeGATT.value.writeDescriptor(descriptor)
if (written) descriptorWrites[descriptor] = result
else result.error("Client characteristic config descriptor write failed.", null, null)
} else result.error("Characteristic Notify failed.", null, null)
}
GATT_DESCRIPTOR_READ -> {
val data = call.arguments<ByteArray>()
val arguments = GattDescriptorReadArguments.parseFrom(data)
val gatt = gatts[arguments.address]
if (gatt == null) result.error(INVALID_REQUEST)
else {
val serviceUUID = UUID.fromString(arguments.serviceUuid)
val service = gatt.getService(serviceUUID)
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
}
}
val nativeGATT = nativeGATTs[command.descriptorReadArguments.gattKey]!!
val nativeService = nativeGATT.services[command.descriptorReadArguments.serviceKey]!!
val nativeCharacteristic = nativeService.characteristics[command.descriptorReadArguments.characteristicKey]!!
val nativeDescriptor = nativeCharacteristic.descriptors[command.descriptorReadArguments.key]!!
val read = nativeGATT.value.readDescriptor(nativeDescriptor.value)
if (read) descriptorReads[nativeDescriptor.value] = result
else result.error("Descriptor read failed.", null, null)
}
GATT_DESCRIPTOR_WRITE -> {
val data = call.arguments<ByteArray>()
val arguments = GattDescriptorWriteArguments.parseFrom(data)
val gatt = gatts[arguments.address]
if (gatt == null) result.error(INVALID_REQUEST)
else {
val serviceUUID = UUID.fromString(arguments.serviceUuid)
val service = gatt.getService(serviceUUID)
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 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
}
}
val nativeGATT = nativeGATTs[command.descriptorWriteArguments.gattKey]!!
val nativeService = nativeGATT.services[command.descriptorWriteArguments.serviceKey]!!
val nativeCharacteristic = nativeService.characteristics[command.descriptorWriteArguments.characteristicKey]!!
val nativeDescriptor = nativeCharacteristic.descriptors[command.descriptorWriteArguments.key]!!
nativeDescriptor.value.value = command.descriptorWriteArguments.value.toByteArray()
val written = nativeGATT.value.writeDescriptor(nativeDescriptor.value)
if (written) descriptorWrites[nativeDescriptor.value] = result
else result.error("Descriptor write failed.", null, null)
}
UNRECOGNIZED -> result.notImplemented()
else -> result.notImplemented()
}
}
override fun onListen(arguments: Any?, sink: EventSink?) {
override fun onListen(arguments: Any?, events: EventSink?) {
Log.d(TAG, "onListen")
this.sink = sink
this.events = events
}
override fun onCancel(arguments: Any?) {
Log.d(TAG, "onCancel")
// This must be a hot reload for now, clear all status here.
// Clear connections.
for (gatt in gatts.values) gatt.close()
gatts.clear()
for (nativeGATT in nativeGATTs.values) nativeGATT.value.disconnect()
// Stop scan.
if (scanning) stopScan()
sink = null
events = null
}
override fun onAttachedToActivity(binding: ActivityPluginBinding) {
@ -639,11 +558,7 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler
onDetachedFromActivity()
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>?,
grantResults: IntArray?
): Boolean {
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>?, grantResults: IntArray?): Boolean {
return when {
requestCode != REQUEST_CODE || requestPermissionsHandler == null -> false
else -> {
@ -657,25 +572,28 @@ class BluetoothLowEnergyPlugin : FlutterPlugin, MethodCallHandler, StreamHandler
}
}
val Any.TAG: String
get() = this::class.java.simpleName
fun Result.success() {
success(null)
}
fun Result.error(code: Int, message: String? = null, details: String? = null) {
error("$code", message, details)
}
val Any.TAG: String
get() = this::class.java.simpleName
val MethodCall.category: MessageCategory
get() = valueOf(method)
val Int.opened: Boolean
val Int.messageState: BluetoothState
get() = when (this) {
BluetoothAdapter.STATE_OFF -> false
BluetoothAdapter.STATE_TURNING_ON -> false
BluetoothAdapter.STATE_ON -> true
BluetoothAdapter.STATE_TURNING_OFF -> true
else -> false
BluetoothAdapter.STATE_OFF -> BluetoothState.POWERED_OFF
BluetoothAdapter.STATE_TURNING_ON -> BluetoothState.POWERED_OFF
BluetoothAdapter.STATE_ON -> BluetoothState.POWERED_ON
BluetoothAdapter.STATE_TURNING_OFF -> BluetoothState.POWERED_ON
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()
/**
* <code>string address = 1;</code>
* <code>string uuid = 1;</code>
*/
var address: kotlin.String
@JvmName("getAddress")
get() = _builder.getAddress()
@JvmName("setAddress")
var uuid: kotlin.String
@JvmName("getUuid")
get() = _builder.getUuid()
@JvmName("setUuid")
set(value) {
_builder.setAddress(value)
_builder.setUuid(value)
}
/**
* <code>string address = 1;</code>
* <code>string uuid = 1;</code>
*/
fun clearAddress() {
_builder.clearAddress()
fun clearUuid() {
_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()
/**
* <code>string address = 1;</code>
* <code>string uuid = 1;</code>
*/
var address: kotlin.String
@JvmName("getAddress")
get() = _builder.getAddress()
@JvmName("setAddress")
var uuid: kotlin.String
@JvmName("getUuid")
get() = _builder.getUuid()
@JvmName("setUuid")
set(value) {
_builder.setAddress(value)
_builder.setUuid(value)
}
/**
* <code>string address = 1;</code>
* <code>string uuid = 1;</code>
*/
fun clearAddress() {
_builder.clearAddress()
fun clearUuid() {
_builder.clearUuid()
}
/**
@ -72,6 +72,23 @@ object DiscoveryKt {
fun 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

View File

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

View File

@ -23,20 +23,20 @@ object GattCharacteristicKt {
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
@JvmName("getId")
get() = _builder.getId()
@JvmName("setId")
var key: kotlin.String
@JvmName("getKey")
get() = _builder.getKey()
@JvmName("setKey")
set(value) {
_builder.setId(value)
_builder.setKey(value)
}
/**
* <code>int32 id = 1;</code>
* <code>string key = 1;</code>
*/
fun clearId() {
_builder.clearId()
fun clearKey() {
_builder.clearKey()
}
/**
@ -57,70 +57,7 @@ object GattCharacteristicKt {
}
/**
* 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 = 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>
* <code>bool canRead = 3;</code>
*/
var canRead: kotlin.Boolean
@JvmName("getCanRead")
@ -130,14 +67,14 @@ object GattCharacteristicKt {
_builder.setCanRead(value)
}
/**
* <code>bool canRead = 4;</code>
* <code>bool canRead = 3;</code>
*/
fun clearCanRead() {
_builder.clearCanRead()
}
/**
* <code>bool canWrite = 5;</code>
* <code>bool canWrite = 4;</code>
*/
var canWrite: kotlin.Boolean
@JvmName("getCanWrite")
@ -147,14 +84,14 @@ object GattCharacteristicKt {
_builder.setCanWrite(value)
}
/**
* <code>bool canWrite = 5;</code>
* <code>bool canWrite = 4;</code>
*/
fun clearCanWrite() {
_builder.clearCanWrite()
}
/**
* <code>bool canWriteWithoutResponse = 6;</code>
* <code>bool canWriteWithoutResponse = 5;</code>
*/
var canWriteWithoutResponse: kotlin.Boolean
@JvmName("getCanWriteWithoutResponse")
@ -164,14 +101,14 @@ object GattCharacteristicKt {
_builder.setCanWriteWithoutResponse(value)
}
/**
* <code>bool canWriteWithoutResponse = 6;</code>
* <code>bool canWriteWithoutResponse = 5;</code>
*/
fun clearCanWriteWithoutResponse() {
_builder.clearCanWriteWithoutResponse()
}
/**
* <code>bool canNotify = 7;</code>
* <code>bool canNotify = 6;</code>
*/
var canNotify: kotlin.Boolean
@JvmName("getCanNotify")
@ -181,12 +118,75 @@ object GattCharacteristicKt {
_builder.setCanNotify(value)
}
/**
* <code>bool canNotify = 7;</code>
* <code>bool canNotify = 6;</code>
*/
fun 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
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()
/**
* <code>string address = 1;</code>
* <code>string gatt_key = 1;</code>
*/
var address: kotlin.String
@JvmName("getAddress")
get() = _builder.getAddress()
@JvmName("setAddress")
var gattKey: kotlin.String
@JvmName("getGattKey")
get() = _builder.getGattKey()
@JvmName("setGattKey")
set(value) {
_builder.setAddress(value)
_builder.setGattKey(value)
}
/**
* <code>string address = 1;</code>
* <code>string gatt_key = 1;</code>
*/
fun clearAddress() {
_builder.clearAddress()
fun clearGattKey() {
_builder.clearGattKey()
}
/**
* <code>string service_uuid = 2;</code>
* <code>string service_key = 2;</code>
*/
var serviceUuid: kotlin.String
@JvmName("getServiceUuid")
get() = _builder.getServiceUuid()
@JvmName("setServiceUuid")
var serviceKey: kotlin.String
@JvmName("getServiceKey")
get() = _builder.getServiceKey()
@JvmName("setServiceKey")
set(value) {
_builder.setServiceUuid(value)
_builder.setServiceKey(value)
}
/**
* <code>string service_uuid = 2;</code>
* <code>string service_key = 2;</code>
*/
fun clearServiceUuid() {
_builder.clearServiceUuid()
fun clearServiceKey() {
_builder.clearServiceKey()
}
/**
* <code>string uuid = 3;</code>
* <code>string key = 3;</code>
*/
var uuid: kotlin.String
@JvmName("getUuid")
get() = _builder.getUuid()
@JvmName("setUuid")
var key: kotlin.String
@JvmName("getKey")
get() = _builder.getKey()
@JvmName("setKey")
set(value) {
_builder.setUuid(value)
_builder.setKey(value)
}
/**
* <code>string uuid = 3;</code>
* <code>string key = 3;</code>
*/
fun clearUuid() {
_builder.clearUuid()
fun clearKey() {
_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()
}
/**
* <code>bool state = 5;</code>
* <code>bool state = 4;</code>
*/
var state: kotlin.Boolean
@JvmName("getState")
@ -101,7 +84,7 @@ object GattCharacteristicNotifyArgumentsKt {
_builder.setState(value)
}
/**
* <code>bool state = 5;</code>
* <code>bool state = 4;</code>
*/
fun clearState() {
_builder.clearState()

View File

@ -23,71 +23,54 @@ object GattCharacteristicReadArgumentsKt {
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
@JvmName("getAddress")
get() = _builder.getAddress()
@JvmName("setAddress")
var gattKey: kotlin.String
@JvmName("getGattKey")
get() = _builder.getGattKey()
@JvmName("setGattKey")
set(value) {
_builder.setAddress(value)
_builder.setGattKey(value)
}
/**
* <code>string address = 1;</code>
* <code>string gatt_key = 1;</code>
*/
fun clearAddress() {
_builder.clearAddress()
fun clearGattKey() {
_builder.clearGattKey()
}
/**
* <code>string service_uuid = 2;</code>
* <code>string service_key = 2;</code>
*/
var serviceUuid: kotlin.String
@JvmName("getServiceUuid")
get() = _builder.getServiceUuid()
@JvmName("setServiceUuid")
var serviceKey: kotlin.String
@JvmName("getServiceKey")
get() = _builder.getServiceKey()
@JvmName("setServiceKey")
set(value) {
_builder.setServiceUuid(value)
_builder.setServiceKey(value)
}
/**
* <code>string service_uuid = 2;</code>
* <code>string service_key = 2;</code>
*/
fun clearServiceUuid() {
_builder.clearServiceUuid()
fun clearServiceKey() {
_builder.clearServiceKey()
}
/**
* <code>string uuid = 3;</code>
* <code>string key = 3;</code>
*/
var uuid: kotlin.String
@JvmName("getUuid")
get() = _builder.getUuid()
@JvmName("setUuid")
var key: kotlin.String
@JvmName("getKey")
get() = _builder.getKey()
@JvmName("setKey")
set(value) {
_builder.setUuid(value)
_builder.setKey(value)
}
/**
* <code>string uuid = 3;</code>
* <code>string key = 3;</code>
*/
fun clearUuid() {
_builder.clearUuid()
}
/**
* <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()
fun clearKey() {
_builder.clearKey()
}
}
}

View File

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

View File

@ -23,88 +23,71 @@ object GattDescriptorReadArgumentsKt {
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
@JvmName("getAddress")
get() = _builder.getAddress()
@JvmName("setAddress")
var gattKey: kotlin.String
@JvmName("getGattKey")
get() = _builder.getGattKey()
@JvmName("setGattKey")
set(value) {
_builder.setAddress(value)
_builder.setGattKey(value)
}
/**
* <code>string address = 1;</code>
* <code>string gatt_key = 1;</code>
*/
fun clearAddress() {
_builder.clearAddress()
fun clearGattKey() {
_builder.clearGattKey()
}
/**
* <code>string service_uuid = 2;</code>
* <code>string service_key = 2;</code>
*/
var serviceUuid: kotlin.String
@JvmName("getServiceUuid")
get() = _builder.getServiceUuid()
@JvmName("setServiceUuid")
var serviceKey: kotlin.String
@JvmName("getServiceKey")
get() = _builder.getServiceKey()
@JvmName("setServiceKey")
set(value) {
_builder.setServiceUuid(value)
_builder.setServiceKey(value)
}
/**
* <code>string service_uuid = 2;</code>
* <code>string service_key = 2;</code>
*/
fun clearServiceUuid() {
_builder.clearServiceUuid()
fun clearServiceKey() {
_builder.clearServiceKey()
}
/**
* <code>string characteristic_uuid = 3;</code>
* <code>string characteristic_key = 3;</code>
*/
var characteristicUuid: kotlin.String
@JvmName("getCharacteristicUuid")
get() = _builder.getCharacteristicUuid()
@JvmName("setCharacteristicUuid")
var characteristicKey: kotlin.String
@JvmName("getCharacteristicKey")
get() = _builder.getCharacteristicKey()
@JvmName("setCharacteristicKey")
set(value) {
_builder.setCharacteristicUuid(value)
_builder.setCharacteristicKey(value)
}
/**
* <code>string characteristic_uuid = 3;</code>
* <code>string characteristic_key = 3;</code>
*/
fun clearCharacteristicUuid() {
_builder.clearCharacteristicUuid()
fun clearCharacteristicKey() {
_builder.clearCharacteristicKey()
}
/**
* <code>string uuid = 4;</code>
* <code>string key = 4;</code>
*/
var uuid: kotlin.String
@JvmName("getUuid")
get() = _builder.getUuid()
@JvmName("setUuid")
var key: kotlin.String
@JvmName("getKey")
get() = _builder.getKey()
@JvmName("setKey")
set(value) {
_builder.setUuid(value)
_builder.setKey(value)
}
/**
* <code>string uuid = 4;</code>
* <code>string key = 4;</code>
*/
fun clearUuid() {
_builder.clearUuid()
}
/**
* <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()
fun clearKey() {
_builder.clearKey()
}
}
}

View File

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

View File

@ -23,37 +23,20 @@ object GattDisconnectArgumentsKt {
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
@JvmName("getAddress")
get() = _builder.getAddress()
@JvmName("setAddress")
var key: kotlin.String
@JvmName("getKey")
get() = _builder.getKey()
@JvmName("setKey")
set(value) {
_builder.setAddress(value)
_builder.setKey(value)
}
/**
* <code>string address = 1;</code>
* <code>string key = 1;</code>
*/
fun clearAddress() {
_builder.clearAddress()
}
/**
* <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()
fun clearKey() {
_builder.clearKey()
}
}
}

View File

@ -23,20 +23,20 @@ object GattServiceKt {
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
@JvmName("getId")
get() = _builder.getId()
@JvmName("setId")
var key: kotlin.String
@JvmName("getKey")
get() = _builder.getKey()
@JvmName("setKey")
set(value) {
_builder.setId(value)
_builder.setKey(value)
}
/**
* <code>int32 id = 1;</code>
* <code>string key = 1;</code>
*/
fun clearId() {
_builder.clearId()
fun clearKey() {
_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")
get() = _builder.getState()
@JvmName("setState")
@ -50,13 +50,13 @@ object MessageKt {
_builder.setState(value)
}
/**
* <code>bool state = 2;</code>
* <code>.dev.yanshouwang.bluetooth_low_energy.BluetoothState state = 2;</code>
*/
fun 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.
*/
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
@JvmName("getDiscovery")
@ -74,13 +98,13 @@ object MessageKt {
_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() {
_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.
*/
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
@JvmName("getScanning")
get() = _builder.getScanning()
@JvmName("setScanning")
var connectArguments: dev.yanshouwang.bluetooth_low_energy.MessageOuterClass.ConnectArguments
@JvmName("getConnectArguments")
get() = _builder.getConnectArguments()
@JvmName("setConnectArguments")
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() {
_builder.clearScanning()
fun clearConnectArguments() {
_builder.clearConnectArguments()
}
/**
* <code>bool scanning = 4;</code>
* @return Whether the scanning field is set.
* <code>.dev.yanshouwang.bluetooth_low_energy.ConnectArguments connectArguments = 5;</code>
* @return Whether the connectArguments field is set.
*/
fun hasScanning(): kotlin.Boolean {
return _builder.hasScanning()
fun hasConnectArguments(): kotlin.Boolean {
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")
get() = _builder.getConnectionLost()
@JvmName("setConnectionLost")
@ -122,13 +170,13 @@ object MessageKt {
_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() {
_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.
*/
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
@JvmName("getCharacteristicValue")
@ -146,18 +266,66 @@ object MessageKt {
_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() {
_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.
*/
fun hasCharacteristicValue(): kotlin.Boolean {
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
@JvmName("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 {
ext.kotlin_version = '1.5.20'
ext.kotlin_version = '1.5.21'
repositories {
google()
mavenCentral()

View File

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

View File

@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.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;
classes = {
};
objectVersion = 46;
objectVersion = 51;
objects = {
/* Begin PBXBuildFile section */
@ -13,6 +13,7 @@
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
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 */
/* Begin PBXCopyFilesBuildPhase section */
@ -29,8 +30,10 @@
/* End PBXCopyFilesBuildPhase 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>"; };
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>"; };
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>"; };
@ -42,6 +45,8 @@
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>"; };
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 */
/* Begin PBXFrameworksBuildPhase section */
@ -49,6 +54,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
EA280E36114EEC52A66510AF /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -72,6 +78,8 @@
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
A19CF493038BEE74587FB0E8 /* Pods */,
990CDB7BA621E0B7AFA0C6BE /* Frameworks */,
);
sourceTree = "<group>";
};
@ -98,6 +106,24 @@
path = Runner;
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 */
/* Begin PBXNativeTarget section */
@ -105,12 +131,14 @@
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
4DEF012D22BCBC3AF731DE9C /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
EDB3731BEABF1E16CE6A52EB /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@ -183,6 +211,28 @@
shellPath = /bin/sh;
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 */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@ -197,6 +247,23 @@
shellPath = /bin/sh;
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 */
/* Begin PBXSourcesBuildPhase section */
@ -288,9 +355,13 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = JJSB6LL9HD;
ENABLE_BITCODE = NO;
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_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@ -399,7 +470,8 @@
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
@ -412,9 +484,13 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = JJSB6LL9HD;
ENABLE_BITCODE = NO;
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_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@ -431,9 +507,13 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = JJSB6LL9HD;
ENABLE_BITCODE = NO;
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_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";

View File

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

View File

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

View File

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

View File

@ -5,7 +5,7 @@ packages:
dependency: transitive
description:
name: async
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.6.1"
bluetooth_low_energy:
@ -14,68 +14,68 @@ packages:
path: ".."
relative: true
source: path
version: "0.0.2"
version: "0.1.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.15.0"
convert:
dependency: "direct main"
description:
name: convert
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0"
version: "3.0.1"
cupertino_icons:
dependency: "direct main"
description:
name: cupertino_icons
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
fixnum:
dependency: transitive
description:
name: fixnum
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flutter:
@ -87,7 +87,7 @@ packages:
dependency: "direct main"
description:
name: flutter_simple_treeview
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0-nullsafety.1"
flutter_test:
@ -99,35 +99,35 @@ packages:
dependency: transitive
description:
name: matcher
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.10"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
path:
dependency: transitive
description:
name: path
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.0"
pedantic:
dependency: "direct dev"
description:
name: pedantic
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.11.0"
version: "1.11.1"
protobuf:
dependency: transitive
description:
name: protobuf
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
sky_engine:
@ -139,56 +139,56 @@ packages:
dependency: transitive
description:
name: source_span
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.1"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.10.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.0"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
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 UIKit
import CoreBluetooth
public class SwiftBluetoothLowEnergyPlugin: NSObject, FlutterPlugin {
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)
}
let NAMESAPCE = "yanshouwang.dev/bluetooth_low_energy"
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
result("iOS " + UIDevice.current.systemVersion)
}
typealias MessageCategory = Dev_Yanshouwang_BluetoothLowEnergy_MessageCategory
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|
s.name = 'bluetooth_low_energy'
s.version = '0.0.1'
s.summary = 'A new flutter plugin project.'
s.version = '0.1.0'
s.summary = 'A bluetooth low energy plugin for flutter.'
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
s.homepage = 'http://example.com'
s.homepage = 'https://github.com/yanshouwang/bluetooth_low_energy'
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email@example.com' }
s.author = { 'yanshouwang' => 'yanshouwang@outlook.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.dependency 'Flutter'
s.dependency 'SwiftProtobuf', '~> 1.0'
s.platform = :ios, '8.0'
# 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_characteristic.dart';
part 'src/gatt_descriptor.dart';
part 'src/mac.dart';
part 'src/uuid.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.
abstract class Bluetooth {
/// The availability of the bluetooth.
Future<bool> get available;
/// The current state of the bluetooth.
Future<bool> get state;
Future<BluetoothState> get state;
/// The bluetooths state changed.
Stream<bool> get stateChanged;
Stream<BluetoothState> get stateChanged;
}
class _Bluetooth implements Bluetooth {
@override
Future<bool> get available => method
.invokeMethod<bool>(proto.MessageCategory.BLUETOOTH_AVAILABLE.name)
.then((value) => value!);
Future<BluetoothState> get state {
final message = proto.Message(
category: proto.MessageCategory.BLUETOOTH_STATE,
).writeToBuffer();
return method
.invokeMethod<int>('', message)
.then((value) => BluetoothState.values[value!]);
}
@override
Future<bool> get state => method
.invokeMethod<bool>(proto.MessageCategory.BLUETOOTH_STATE.name)
.then((value) => value!);
@override
Stream<bool> get stateChanged => stream
.map((event) => proto.Message.fromBuffer(event))
Stream<BluetoothState> get stateChanged => stream
.where((message) =>
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();
/// Establishes a local connection to a peripheral.
Future<GATT> connect(MAC address);
Future<GATT> connect(UUID uuid);
}
class _Central extends _Bluetooth implements Central {
@override
Stream<Discovery> get discovered => stream
.map((event) => proto.Message.fromBuffer(event))
.where((message) =>
message.category == proto.MessageCategory.CENTRAL_DISCOVERED)
.map((message) => message.discovery.conversion);
.map((message) => message.discovery.toDiscovery());
@override
Future startDiscovery({List<UUID>? services}) {
final name = proto.MessageCategory.CENTRAL_START_DISCOVERY.name;
final arguments = proto.StartDiscoveryArguments(
services: services?.map((uuid) => uuid.name),
final message = proto.Message(
category: proto.MessageCategory.CENTRAL_START_DISCOVERY,
startDiscoveryArguments: proto.StartDiscoveryArguments(
services: services?.map((uuid) => uuid.name),
),
).writeToBuffer();
return method.invokeMethod(name, arguments);
return method.invokeMethod('', message);
}
@override
Future stopDiscovery() {
final name = proto.MessageCategory.CENTRAL_STOP_DISCOVERY.name;
return method.invokeMethod(name);
final message = proto.Message(
category: proto.MessageCategory.CENTRAL_STOP_DISCOVERY,
).writeToBuffer();
return method.invokeMethod('', message);
}
@override
Future<GATT> connect(MAC address) {
final name = proto.MessageCategory.CENTRAL_CONNECT.name;
final arguments =
proto.ConnectArguments(address: address.name).writeToBuffer();
Future<GATT> connect(UUID uuid) {
final message = proto.Message(
category: proto.MessageCategory.CENTRAL_CONNECT,
connectArguments: proto.ConnectArguments(uuid: uuid.name),
).writeToBuffer();
return method
.invokeMethod<List<int>>(name, arguments)
.then((value) => proto.GATT.fromBuffer(value!).convert(address));
.invokeMethod<List<int>>('', message)
.then((value) => proto.GATT.fromBuffer(value!).toGATT());
}
}

View File

@ -3,22 +3,27 @@ part of bluetooth_low_energy;
/// TO BE DONE.
abstract class Discovery {
/// TO BE DONE.
MAC get address;
UUID get uuid;
/// TO BE DONE.
int get rssi;
/// TO BE DONE.
Map<int, List<int>> get advertisements;
/// TO BE DONE.
bool get connectable;
}
class _Discovery implements Discovery {
@override
final MAC address;
final UUID uuid;
@override
final int rssi;
@override
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;
extension on String {
String get nameOfMAC {
final upper = toUpperCase();
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();
String get uuidName {
final lowerCase = toLowerCase();
final exp0 = RegExp(
r'[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$',
multiLine: true,
caseSensitive: true,
r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$',
caseSensitive: false,
);
if (exp0.hasMatch(upper)) {
return upper;
if (exp0.hasMatch(lowerCase)) {
return lowerCase;
}
final exp1 = RegExp(
r'^[0-9A-F]{4}$',
multiLine: true,
caseSensitive: true,
r'^[0-9a-f]{4}$',
caseSensitive: false,
);
if (exp1.hasMatch(upper)) {
return '0000$upper-0000-1000-8000-00805F9B34FB';
if (exp1.hasMatch(lowerCase)) {
return '0000$lowerCase-0000-1000-8000-00805f9b34fb';
}
throw ArgumentError.value(this);
}
List<int> get valueOfUUID {
List<int> get uuidVaue {
final from = RegExp(r'-');
final encoded = replaceAll(from, '');
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 {
Discovery get conversion {
final convertedAdvertisements = <int, List<int>>{};
Discovery toDiscovery() {
final advertisements = <int, List<int>>{};
var start = 0;
while (start < advertisements.length) {
final length = advertisements[start++];
if (length == 0) {
break;
}
while (start < this.advertisements.length) {
final length = this.advertisements[start++];
if (length == 0) break;
final end = start + length;
final key = advertisements[start++];
final value = advertisements.sublist(start, end);
final key = this.advertisements[start++];
final value = this.advertisements.sublist(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 {
GATT convert(MAC address) {
final convertedServices = {
for (var service in services)
service.uuid.conversionOfUUID: service.convert(address)
GATT toGATT() {
final services = {
for (var service in this.services)
service.uuid.uuid: service.toGattService(key)
};
return _GATT(address, id, mtu, convertedServices);
return _GATT(key, maximumWriteLength, services);
}
}
extension on proto.GattService {
GattService convert(MAC address) {
final convertedUUID = uuid.conversionOfUUID;
final convertedCharacteristics = {
for (var characteristic in characteristics)
characteristic.uuid.conversionOfUUID:
characteristic.convert(address, convertedUUID)
GattService toGattService(String gattKey) {
final uuid = this.uuid.uuid;
final characteristics = {
for (var characteristic in this.characteristics)
characteristic.uuid.uuid: characteristic.toGattCharacteristic(
gattKey,
key,
)
};
return _GattService(
address,
id,
convertedUUID,
convertedCharacteristics,
);
return _GattService(gattKey, key, uuid, characteristics);
}
}
extension on proto.GattCharacteristic {
GattCharacteristic convert(MAC address, UUID serviceUUID) {
final convertedUUID = uuid.conversionOfUUID;
final convertedDescriptors = {
for (var descriptor in descriptors)
descriptor.uuid.conversionOfUUID:
descriptor.convert(address, serviceUUID, convertedUUID)
GattCharacteristic toGattCharacteristic(String gattKey, String serviceKey) {
final uuid = this.uuid.uuid;
final descriptors = {
for (var descriptor in this.descriptors)
descriptor.uuid.uuid: descriptor.toGattDescriptor(
gattKey,
serviceKey,
key,
)
};
return _GattCharacteristic(
address,
serviceUUID,
id,
convertedUUID,
convertedDescriptors,
gattKey,
serviceKey,
key,
uuid,
canRead,
canWrite,
canWriteWithoutResponse,
canNotify,
descriptors,
);
}
}
extension on proto.GattDescriptor {
GattDescriptor convert(
MAC address, UUID serviceUUID, UUID characteristicUUID) {
final convertedUUID = uuid.conversionOfUUID;
return _GattDescriptor(
address,
serviceUUID,
characteristicUUID,
id,
convertedUUID,
);
GattDescriptor toGattDescriptor(
String gattKey,
String serviceKey,
String characteristicKey,
) {
final uuid = this.uuid.uuid;
return _GattDescriptor(gattKey, serviceKey, characteristicKey, key, uuid);
}
}

View File

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

View File

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

View File

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

View File

@ -10,10 +10,10 @@ abstract class 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 int id;
final String gattKey;
final String key;
@override
final UUID uuid;
@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;
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._(
1,
0,
const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? ''
: 'BLUETOOTH_STATE');
static const MessageCategory CENTRAL_START_DISCOVERY = MessageCategory._(
2,
1,
const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? ''
: 'CENTRAL_START_DISCOVERY');
static const MessageCategory CENTRAL_STOP_DISCOVERY = MessageCategory._(
3,
2,
const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? ''
: 'CENTRAL_STOP_DISCOVERY');
static const MessageCategory CENTRAL_DISCOVERED = MessageCategory._(
4,
3,
const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? ''
: 'CENTRAL_DISCOVERED');
static const MessageCategory CENTRAL_CONNECT = MessageCategory._(
5,
4,
const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? ''
: 'CENTRAL_CONNECT');
static const MessageCategory GATT_DISCONNECT = MessageCategory._(
6,
5,
const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? ''
: 'GATT_DISCONNECT');
static const MessageCategory GATT_CONNECTION_LOST = MessageCategory._(
7,
6,
const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? ''
: 'GATT_CONNECTION_LOST');
static const MessageCategory GATT_CHARACTERISTIC_READ = MessageCategory._(
8,
7,
const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? ''
: 'GATT_CHARACTERISTIC_READ');
static const MessageCategory GATT_CHARACTERISTIC_WRITE = MessageCategory._(
9,
8,
const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? ''
: 'GATT_CHARACTERISTIC_WRITE');
static const MessageCategory GATT_CHARACTERISTIC_NOTIFY = MessageCategory._(
10,
9,
const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? ''
: 'GATT_CHARACTERISTIC_NOTIFY');
static const MessageCategory GATT_DESCRIPTOR_READ = MessageCategory._(
11,
10,
const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? ''
: 'GATT_DESCRIPTOR_READ');
static const MessageCategory GATT_DESCRIPTOR_WRITE = MessageCategory._(
12,
11,
const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? ''
: 'GATT_DESCRIPTOR_WRITE');
static const $core.List<MessageCategory> values = <MessageCategory>[
BLUETOOTH_AVAILABLE,
BLUETOOTH_STATE,
CENTRAL_START_DISCOVERY,
CENTRAL_STOP_DISCOVERY,
@ -98,3 +92,33 @@ class MessageCategory extends $pb.ProtobufEnum {
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 {
'1': 'MessageCategory',
'2': const [
const {'1': 'BLUETOOTH_AVAILABLE', '2': 0},
const {'1': 'BLUETOOTH_STATE', '2': 1},
const {'1': 'CENTRAL_START_DISCOVERY', '2': 2},
const {'1': 'CENTRAL_STOP_DISCOVERY', '2': 3},
const {'1': 'CENTRAL_DISCOVERED', '2': 4},
const {'1': 'CENTRAL_CONNECT', '2': 5},
const {'1': 'GATT_DISCONNECT', '2': 6},
const {'1': 'GATT_CONNECTION_LOST', '2': 7},
const {'1': 'GATT_CHARACTERISTIC_READ', '2': 8},
const {'1': 'GATT_CHARACTERISTIC_WRITE', '2': 9},
const {'1': 'GATT_CHARACTERISTIC_NOTIFY', '2': 10},
const {'1': 'GATT_DESCRIPTOR_READ', '2': 11},
const {'1': 'GATT_DESCRIPTOR_WRITE', '2': 12},
const {'1': 'BLUETOOTH_STATE', '2': 0},
const {'1': 'CENTRAL_START_DISCOVERY', '2': 1},
const {'1': 'CENTRAL_STOP_DISCOVERY', '2': 2},
const {'1': 'CENTRAL_DISCOVERED', '2': 3},
const {'1': 'CENTRAL_CONNECT', '2': 4},
const {'1': 'GATT_DISCONNECT', '2': 5},
const {'1': 'GATT_CONNECTION_LOST', '2': 6},
const {'1': 'GATT_CHARACTERISTIC_READ', '2': 7},
const {'1': 'GATT_CHARACTERISTIC_WRITE', '2': 8},
const {'1': 'GATT_CHARACTERISTIC_NOTIFY', '2': 9},
const {'1': 'GATT_DESCRIPTOR_READ', '2': 10},
const {'1': 'GATT_DESCRIPTOR_WRITE', '2': 11},
],
};
/// Descriptor for `MessageCategory`. Decode as a `google.protobuf.EnumDescriptorProto`.
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')
const Message$json = const {
'1': 'Message',
@ -44,35 +56,117 @@ const Message$json = const {
'6': '.dev.yanshouwang.bluetooth_low_energy.MessageCategory',
'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 {
'1': 'discovery',
'3': 3,
'3': 4,
'4': 1,
'5': 11,
'6': '.dev.yanshouwang.bluetooth_low_energy.Discovery',
'9': 0,
'10': 'discovery'
},
const {'1': 'scanning', '3': 4, '4': 1, '5': 8, '9': 0, '10': 'scanning'},
const {
'1': 'connectionLost',
'1': 'connectArguments',
'3': 5,
'4': 1,
'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,
'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 {
'1': 'characteristicValue',
'3': 6,
'3': 11,
'4': 1,
'5': 11,
'6': '.dev.yanshouwang.bluetooth_low_energy.GattCharacteristicValue',
'9': 0,
'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 [
const {'1': 'value'},
@ -81,7 +175,7 @@ const Message$json = const {
/// Descriptor for `Message`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List messageDescriptor = $convert.base64Decode(
'CgdNZXNzYWdlElEKCGNhdGVnb3J5GAEgASgOMjUuZGV2LnlhbnNob3V3YW5nLmJsdWV0b290aF9sb3dfZW5lcmd5Lk1lc3NhZ2VDYXRlZ29yeVIIY2F0ZWdvcnkSFgoFc3RhdGUYAiABKAhIAFIFc3RhdGUSTwoJZGlzY292ZXJ5GAMgASgLMi8uZGV2LnlhbnNob3V3YW5nLmJsdWV0b290aF9sb3dfZW5lcmd5LkRpc2NvdmVyeUgAUglkaXNjb3ZlcnkSHAoIc2Nhbm5pbmcYBCABKAhIAFIIc2Nhbm5pbmcSXgoOY29ubmVjdGlvbkxvc3QYBSABKAsyNC5kZXYueWFuc2hvdXdhbmcuYmx1ZXRvb3RoX2xvd19lbmVyZ3kuQ29ubmVjdGlvbkxvc3RIAFIOY29ubmVjdGlvbkxvc3QScQoTY2hhcmFjdGVyaXN0aWNWYWx1ZRgGIAEoCzI9LmRldi55YW5zaG91d2FuZy5ibHVldG9vdGhfbG93X2VuZXJneS5HYXR0Q2hhcmFjdGVyaXN0aWNWYWx1ZUgAUhNjaGFyYWN0ZXJpc3RpY1ZhbHVlQgcKBXZhbHVl');
'CgdNZXNzYWdlElEKCGNhdGVnb3J5GAEgASgOMjUuZGV2LnlhbnNob3V3YW5nLmJsdWV0b290aF9sb3dfZW5lcmd5Lk1lc3NhZ2VDYXRlZ29yeVIIY2F0ZWdvcnkSTAoFc3RhdGUYAiABKA4yNC5kZXYueWFuc2hvdXdhbmcuYmx1ZXRvb3RoX2xvd19lbmVyZ3kuQmx1ZXRvb3RoU3RhdGVIAFIFc3RhdGUSeQoXc3RhcnREaXNjb3ZlcnlBcmd1bWVudHMYAyABKAsyPS5kZXYueWFuc2hvdXdhbmcuYmx1ZXRvb3RoX2xvd19lbmVyZ3kuU3RhcnREaXNjb3ZlcnlBcmd1bWVudHNIAFIXc3RhcnREaXNjb3ZlcnlBcmd1bWVudHMSTwoJZGlzY292ZXJ5GAQgASgLMi8uZGV2LnlhbnNob3V3YW5nLmJsdWV0b290aF9sb3dfZW5lcmd5LkRpc2NvdmVyeUgAUglkaXNjb3ZlcnkSZAoQY29ubmVjdEFyZ3VtZW50cxgFIAEoCzI2LmRldi55YW5zaG91d2FuZy5ibHVldG9vdGhfbG93X2VuZXJneS5Db25uZWN0QXJndW1lbnRzSABSEGNvbm5lY3RBcmd1bWVudHMScQoTZGlzY29ubmVjdEFyZ3VtZW50cxgGIAEoCzI9LmRldi55YW5zaG91d2FuZy5ibHVldG9vdGhfbG93X2VuZXJneS5HYXR0RGlzY29ubmVjdEFyZ3VtZW50c0gAUhNkaXNjb25uZWN0QXJndW1lbnRzEmIKDmNvbm5lY3Rpb25Mb3N0GAcgASgLMjguZGV2LnlhbnNob3V3YW5nLmJsdWV0b290aF9sb3dfZW5lcmd5LkdhdHRDb25uZWN0aW9uTG9zdEgAUg5jb25uZWN0aW9uTG9zdBKJAQobY2hhcmFjdGVyaXN0aWNSZWFkQXJndW1lbnRzGAggASgLMkUuZGV2LnlhbnNob3V3YW5nLmJsdWV0b290aF9sb3dfZW5lcmd5LkdhdHRDaGFyYWN0ZXJpc3RpY1JlYWRBcmd1bWVudHNIAFIbY2hhcmFjdGVyaXN0aWNSZWFkQXJndW1lbnRzEowBChxjaGFyYWN0ZXJpc3RpY1dyaXRlQXJndW1lbnRzGAkgASgLMkYuZGV2LnlhbnNob3V3YW5nLmJsdWV0b290aF9sb3dfZW5lcmd5LkdhdHRDaGFyYWN0ZXJpc3RpY1dyaXRlQXJndW1lbnRzSABSHGNoYXJhY3RlcmlzdGljV3JpdGVBcmd1bWVudHMSjwEKHWNoYXJhY3RlcmlzdGljTm90aWZ5QXJndW1lbnRzGAogASgLMkcuZGV2LnlhbnNob3V3YW5nLmJsdWV0b290aF9sb3dfZW5lcmd5LkdhdHRDaGFyYWN0ZXJpc3RpY05vdGlmeUFyZ3VtZW50c0gAUh1jaGFyYWN0ZXJpc3RpY05vdGlmeUFyZ3VtZW50cxJxChNjaGFyYWN0ZXJpc3RpY1ZhbHVlGAsgASgLMj0uZGV2LnlhbnNob3V3YW5nLmJsdWV0b290aF9sb3dfZW5lcmd5LkdhdHRDaGFyYWN0ZXJpc3RpY1ZhbHVlSABSE2NoYXJhY3RlcmlzdGljVmFsdWUSfQoXZGVzY3JpcHRvclJlYWRBcmd1bWVudHMYDCABKAsyQS5kZXYueWFuc2hvdXdhbmcuYmx1ZXRvb3RoX2xvd19lbmVyZ3kuR2F0dERlc2NyaXB0b3JSZWFkQXJndW1lbnRzSABSF2Rlc2NyaXB0b3JSZWFkQXJndW1lbnRzEoABChhkZXNjcmlwdG9yV3JpdGVBcmd1bWVudHMYDSABKAsyQi5kZXYueWFuc2hvdXdhbmcuYmx1ZXRvb3RoX2xvd19lbmVyZ3kuR2F0dERlc2NyaXB0b3JXcml0ZUFyZ3VtZW50c0gAUhhkZXNjcmlwdG9yV3JpdGVBcmd1bWVudHNCBwoFdmFsdWU=');
@$core.Deprecated('Use startDiscoveryArgumentsDescriptor instead')
const StartDiscoveryArguments$json = const {
'1': 'StartDiscoveryArguments',
@ -98,7 +192,7 @@ final $typed_data.Uint8List startDiscoveryArgumentsDescriptor =
const Discovery$json = const {
'1': 'Discovery',
'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': 'advertisements',
@ -107,29 +201,36 @@ const Discovery$json = const {
'5': 12,
'10': 'advertisements'
},
const {'1': 'connectable', '3': 4, '4': 1, '5': 8, '10': 'connectable'},
],
};
/// Descriptor for `Discovery`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List discoveryDescriptor = $convert.base64Decode(
'CglEaXNjb3ZlcnkSGAoHYWRkcmVzcxgBIAEoCVIHYWRkcmVzcxISCgRyc3NpGAIgASgRUgRyc3NpEiYKDmFkdmVydGlzZW1lbnRzGAMgASgMUg5hZHZlcnRpc2VtZW50cw==');
'CglEaXNjb3ZlcnkSEgoEdXVpZBgBIAEoCVIEdXVpZBISCgRyc3NpGAIgASgRUgRyc3NpEiYKDmFkdmVydGlzZW1lbnRzGAMgASgMUg5hZHZlcnRpc2VtZW50cxIgCgtjb25uZWN0YWJsZRgEIAEoCFILY29ubmVjdGFibGU=');
@$core.Deprecated('Use connectArgumentsDescriptor instead')
const ConnectArguments$json = const {
'1': 'ConnectArguments',
'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`.
final $typed_data.Uint8List connectArgumentsDescriptor = $convert.base64Decode(
'ChBDb25uZWN0QXJndW1lbnRzEhgKB2FkZHJlc3MYASABKAlSB2FkZHJlc3M=');
final $typed_data.Uint8List connectArgumentsDescriptor = $convert
.base64Decode('ChBDb25uZWN0QXJndW1lbnRzEhIKBHV1aWQYASABKAlSBHV1aWQ=');
@$core.Deprecated('Use gATTDescriptor instead')
const GATT$json = const {
'1': 'GATT',
'2': const [
const {'1': 'id', '3': 1, '4': 1, '5': 5, '10': 'id'},
const {'1': 'mtu', '3': 2, '4': 1, '5': 5, '10': 'mtu'},
const {'1': 'key', '3': 1, '4': 1, '5': 9, '10': 'key'},
const {
'1': 'maximumWriteLength',
'3': 2,
'4': 1,
'5': 5,
'10': 'maximumWriteLength'
},
const {
'1': 'services',
'3': 3,
@ -143,25 +244,12 @@ const GATT$json = const {
/// Descriptor for `GATT`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List gATTDescriptor = $convert.base64Decode(
'CgRHQVRUEg4KAmlkGAEgASgFUgJpZBIQCgNtdHUYAiABKAVSA210dRJNCghzZXJ2aWNlcxgDIAMoCzIxLmRldi55YW5zaG91d2FuZy5ibHVldG9vdGhfbG93X2VuZXJneS5HYXR0U2VydmljZVIIc2VydmljZXM=');
@$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==');
'CgRHQVRUEhAKA2tleRgBIAEoCVIDa2V5Ei4KEm1heGltdW1Xcml0ZUxlbmd0aBgCIAEoBVISbWF4aW11bVdyaXRlTGVuZ3RoEk0KCHNlcnZpY2VzGAMgAygLMjEuZGV2LnlhbnNob3V3YW5nLmJsdWV0b290aF9sb3dfZW5lcmd5LkdhdHRTZXJ2aWNlUghzZXJ2aWNlcw==');
@$core.Deprecated('Use gattServiceDescriptor instead')
const GattService$json = const {
'1': 'GattService',
'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': 'characteristics',
@ -176,88 +264,98 @@ const GattService$json = const {
/// Descriptor for `GattService`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List gattServiceDescriptor = $convert.base64Decode(
'CgtHYXR0U2VydmljZRIOCgJpZBgBIAEoBVICaWQSEgoEdXVpZBgCIAEoCVIEdXVpZBJiCg9jaGFyYWN0ZXJpc3RpY3MYAyADKAsyOC5kZXYueWFuc2hvdXdhbmcuYmx1ZXRvb3RoX2xvd19lbmVyZ3kuR2F0dENoYXJhY3RlcmlzdGljUg9jaGFyYWN0ZXJpc3RpY3M=');
'CgtHYXR0U2VydmljZRIQCgNrZXkYASABKAlSA2tleRISCgR1dWlkGAIgASgJUgR1dWlkEmIKD2NoYXJhY3RlcmlzdGljcxgDIAMoCzI4LmRldi55YW5zaG91d2FuZy5ibHVldG9vdGhfbG93X2VuZXJneS5HYXR0Q2hhcmFjdGVyaXN0aWNSD2NoYXJhY3RlcmlzdGljcw==');
@$core.Deprecated('Use gattCharacteristicDescriptor instead')
const GattCharacteristic$json = const {
'1': 'GattCharacteristic',
'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': '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 {
'1': 'descriptors',
'3': 3,
'3': 7,
'4': 3,
'5': 11,
'6': '.dev.yanshouwang.bluetooth_low_energy.GattDescriptor',
'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`.
final $typed_data.Uint8List gattCharacteristicDescriptor = $convert.base64Decode(
'ChJHYXR0Q2hhcmFjdGVyaXN0aWMSDgoCaWQYASABKAVSAmlkEhIKBHV1aWQYAiABKAlSBHV1aWQSVgoLZGVzY3JpcHRvcnMYAyADKAsyNC5kZXYueWFuc2hvdXdhbmcuYmx1ZXRvb3RoX2xvd19lbmVyZ3kuR2F0dERlc2NyaXB0b3JSC2Rlc2NyaXB0b3JzEhgKB2NhblJlYWQYBCABKAhSB2NhblJlYWQSGgoIY2FuV3JpdGUYBSABKAhSCGNhbldyaXRlEjgKF2NhbldyaXRlV2l0aG91dFJlc3BvbnNlGAYgASgIUhdjYW5Xcml0ZVdpdGhvdXRSZXNwb25zZRIcCgljYW5Ob3RpZnkYByABKAhSCWNhbk5vdGlmeQ==');
'ChJHYXR0Q2hhcmFjdGVyaXN0aWMSEAoDa2V5GAEgASgJUgNrZXkSEgoEdXVpZBgCIAEoCVIEdXVpZBIYCgdjYW5SZWFkGAMgASgIUgdjYW5SZWFkEhoKCGNhbldyaXRlGAQgASgIUghjYW5Xcml0ZRI4ChdjYW5Xcml0ZVdpdGhvdXRSZXNwb25zZRgFIAEoCFIXY2FuV3JpdGVXaXRob3V0UmVzcG9uc2USHAoJY2FuTm90aWZ5GAYgASgIUgljYW5Ob3RpZnkSVgoLZGVzY3JpcHRvcnMYByADKAsyNC5kZXYueWFuc2hvdXdhbmcuYmx1ZXRvb3RoX2xvd19lbmVyZ3kuR2F0dERlc2NyaXB0b3JSC2Rlc2NyaXB0b3Jz');
@$core.Deprecated('Use gattDescriptorDescriptor instead')
const GattDescriptor$json = const {
'1': 'GattDescriptor',
'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'},
],
};
/// Descriptor for `GattDescriptor`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List gattDescriptorDescriptor = $convert.base64Decode(
'Cg5HYXR0RGVzY3JpcHRvchIOCgJpZBgBIAEoBVICaWQSEgoEdXVpZBgCIAEoCVIEdXVpZA==');
@$core.Deprecated('Use connectionLostDescriptor instead')
const ConnectionLost$json = const {
'1': 'ConnectionLost',
'Cg5HYXR0RGVzY3JpcHRvchIQCgNrZXkYASABKAlSA2tleRISCgR1dWlkGAIgASgJUgR1dWlk');
@$core.Deprecated('Use gattDisconnectArgumentsDescriptor instead')
const GattDisconnectArguments$json = const {
'1': 'GattDisconnectArguments',
'2': const [
const {'1': 'id', '3': 1, '4': 1, '5': 5, '10': 'id'},
const {'1': 'error_code', '3': 2, '4': 1, '5': 5, '10': 'errorCode'},
const {'1': 'key', '3': 1, '4': 1, '5': 9, '10': 'key'},
],
};
/// Descriptor for `ConnectionLost`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List connectionLostDescriptor = $convert.base64Decode(
'Cg5Db25uZWN0aW9uTG9zdBIOCgJpZBgBIAEoBVICaWQSHQoKZXJyb3JfY29kZRgCIAEoBVIJZXJyb3JDb2Rl');
/// Descriptor for `GattDisconnectArguments`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List gattDisconnectArgumentsDescriptor =
$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')
const GattCharacteristicReadArguments$json = const {
'1': 'GattCharacteristicReadArguments',
'2': const [
const {'1': 'address', '3': 1, '4': 1, '5': 9, '10': 'address'},
const {'1': 'service_uuid', '3': 2, '4': 1, '5': 9, '10': 'serviceUuid'},
const {'1': 'uuid', '3': 3, '4': 1, '5': 9, '10': 'uuid'},
const {'1': 'id', '3': 4, '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'},
],
};
/// Descriptor for `GattCharacteristicReadArguments`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List gattCharacteristicReadArgumentsDescriptor =
$convert.base64Decode(
'Ch9HYXR0Q2hhcmFjdGVyaXN0aWNSZWFkQXJndW1lbnRzEhgKB2FkZHJlc3MYASABKAlSB2FkZHJlc3MSIQoMc2VydmljZV91dWlkGAIgASgJUgtzZXJ2aWNlVXVpZBISCgR1dWlkGAMgASgJUgR1dWlkEg4KAmlkGAQgASgFUgJpZA==');
'Ch9HYXR0Q2hhcmFjdGVyaXN0aWNSZWFkQXJndW1lbnRzEhkKCGdhdHRfa2V5GAEgASgJUgdnYXR0S2V5Eh8KC3NlcnZpY2Vfa2V5GAIgASgJUgpzZXJ2aWNlS2V5EhAKA2tleRgDIAEoCVIDa2V5');
@$core.Deprecated('Use gattCharacteristicWriteArgumentsDescriptor instead')
const GattCharacteristicWriteArguments$json = const {
'1': 'GattCharacteristicWriteArguments',
'2': const [
const {'1': 'address', '3': 1, '4': 1, '5': 9, '10': 'address'},
const {'1': 'service_uuid', '3': 2, '4': 1, '5': 9, '10': 'serviceUuid'},
const {'1': 'uuid', '3': 3, '4': 1, '5': 9, '10': 'uuid'},
const {'1': 'id', '3': 4, '4': 1, '5': 5, '10': 'id'},
const {'1': 'value', '3': 5, '4': 1, '5': 12, '10': 'value'},
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': 'withoutResponse',
'3': 6,
'3': 5,
'4': 1,
'5': 8,
'10': 'withoutResponse'
@ -268,28 +366,29 @@ const GattCharacteristicWriteArguments$json = const {
/// Descriptor for `GattCharacteristicWriteArguments`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List gattCharacteristicWriteArgumentsDescriptor =
$convert.base64Decode(
'CiBHYXR0Q2hhcmFjdGVyaXN0aWNXcml0ZUFyZ3VtZW50cxIYCgdhZGRyZXNzGAEgASgJUgdhZGRyZXNzEiEKDHNlcnZpY2VfdXVpZBgCIAEoCVILc2VydmljZVV1aWQSEgoEdXVpZBgDIAEoCVIEdXVpZBIOCgJpZBgEIAEoBVICaWQSFAoFdmFsdWUYBSABKAxSBXZhbHVlEigKD3dpdGhvdXRSZXNwb25zZRgGIAEoCFIPd2l0aG91dFJlc3BvbnNl');
'CiBHYXR0Q2hhcmFjdGVyaXN0aWNXcml0ZUFyZ3VtZW50cxIZCghnYXR0X2tleRgBIAEoCVIHZ2F0dEtleRIfCgtzZXJ2aWNlX2tleRgCIAEoCVIKc2VydmljZUtleRIQCgNrZXkYAyABKAlSA2tleRIUCgV2YWx1ZRgEIAEoDFIFdmFsdWUSKAoPd2l0aG91dFJlc3BvbnNlGAUgASgIUg93aXRob3V0UmVzcG9uc2U=');
@$core.Deprecated('Use gattCharacteristicNotifyArgumentsDescriptor instead')
const GattCharacteristicNotifyArguments$json = const {
'1': 'GattCharacteristicNotifyArguments',
'2': const [
const {'1': 'address', '3': 1, '4': 1, '5': 9, '10': 'address'},
const {'1': 'service_uuid', '3': 2, '4': 1, '5': 9, '10': 'serviceUuid'},
const {'1': 'uuid', '3': 3, '4': 1, '5': 9, '10': 'uuid'},
const {'1': 'id', '3': 4, '4': 1, '5': 5, '10': 'id'},
const {'1': 'state', '3': 5, '4': 1, '5': 8, '10': 'state'},
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': 'state', '3': 4, '4': 1, '5': 8, '10': 'state'},
],
};
/// Descriptor for `GattCharacteristicNotifyArguments`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List gattCharacteristicNotifyArgumentsDescriptor =
$convert.base64Decode(
'CiFHYXR0Q2hhcmFjdGVyaXN0aWNOb3RpZnlBcmd1bWVudHMSGAoHYWRkcmVzcxgBIAEoCVIHYWRkcmVzcxIhCgxzZXJ2aWNlX3V1aWQYAiABKAlSC3NlcnZpY2VVdWlkEhIKBHV1aWQYAyABKAlSBHV1aWQSDgoCaWQYBCABKAVSAmlkEhQKBXN0YXRlGAUgASgIUgVzdGF0ZQ==');
'CiFHYXR0Q2hhcmFjdGVyaXN0aWNOb3RpZnlBcmd1bWVudHMSGQoIZ2F0dF9rZXkYASABKAlSB2dhdHRLZXkSHwoLc2VydmljZV9rZXkYAiABKAlSCnNlcnZpY2VLZXkSEAoDa2V5GAMgASgJUgNrZXkSFAoFc3RhdGUYBCABKAhSBXN0YXRl');
@$core.Deprecated('Use gattCharacteristicValueDescriptor instead')
const GattCharacteristicValue$json = const {
'1': 'GattCharacteristicValue',
'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'},
],
};
@ -297,49 +396,47 @@ const GattCharacteristicValue$json = const {
/// Descriptor for `GattCharacteristicValue`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List gattCharacteristicValueDescriptor =
$convert.base64Decode(
'ChdHYXR0Q2hhcmFjdGVyaXN0aWNWYWx1ZRIOCgJpZBgDIAEoBVICaWQSFAoFdmFsdWUYBCABKAxSBXZhbHVl');
'ChdHYXR0Q2hhcmFjdGVyaXN0aWNWYWx1ZRIZCghnYXR0X2tleRgBIAEoCVIHZ2F0dEtleRIfCgtzZXJ2aWNlX2tleRgCIAEoCVIKc2VydmljZUtleRIQCgNrZXkYAyABKAlSA2tleRIUCgV2YWx1ZRgEIAEoDFIFdmFsdWU=');
@$core.Deprecated('Use gattDescriptorReadArgumentsDescriptor instead')
const GattDescriptorReadArguments$json = const {
'1': 'GattDescriptorReadArguments',
'2': const [
const {'1': 'address', '3': 1, '4': 1, '5': 9, '10': 'address'},
const {'1': 'service_uuid', '3': 2, '4': 1, '5': 9, '10': 'serviceUuid'},
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': 'characteristic_uuid',
'1': 'characteristic_key',
'3': 3,
'4': 1,
'5': 9,
'10': 'characteristicUuid'
'10': 'characteristicKey'
},
const {'1': 'uuid', '3': 4, '4': 1, '5': 9, '10': 'uuid'},
const {'1': 'id', '3': 5, '4': 1, '5': 5, '10': 'id'},
const {'1': 'key', '3': 4, '4': 1, '5': 9, '10': 'key'},
],
};
/// Descriptor for `GattDescriptorReadArguments`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List gattDescriptorReadArgumentsDescriptor =
$convert.base64Decode(
'ChtHYXR0RGVzY3JpcHRvclJlYWRBcmd1bWVudHMSGAoHYWRkcmVzcxgBIAEoCVIHYWRkcmVzcxIhCgxzZXJ2aWNlX3V1aWQYAiABKAlSC3NlcnZpY2VVdWlkEi8KE2NoYXJhY3RlcmlzdGljX3V1aWQYAyABKAlSEmNoYXJhY3RlcmlzdGljVXVpZBISCgR1dWlkGAQgASgJUgR1dWlkEg4KAmlkGAUgASgFUgJpZA==');
'ChtHYXR0RGVzY3JpcHRvclJlYWRBcmd1bWVudHMSGQoIZ2F0dF9rZXkYASABKAlSB2dhdHRLZXkSHwoLc2VydmljZV9rZXkYAiABKAlSCnNlcnZpY2VLZXkSLQoSY2hhcmFjdGVyaXN0aWNfa2V5GAMgASgJUhFjaGFyYWN0ZXJpc3RpY0tleRIQCgNrZXkYBCABKAlSA2tleQ==');
@$core.Deprecated('Use gattDescriptorWriteArgumentsDescriptor instead')
const GattDescriptorWriteArguments$json = const {
'1': 'GattDescriptorWriteArguments',
'2': const [
const {'1': 'address', '3': 1, '4': 1, '5': 9, '10': 'address'},
const {'1': 'service_uuid', '3': 2, '4': 1, '5': 9, '10': 'serviceUuid'},
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': 'characteristic_uuid',
'1': 'characteristic_key',
'3': 3,
'4': 1,
'5': 9,
'10': 'characteristicUuid'
'10': 'characteristicKey'
},
const {'1': 'uuid', '3': 4, '4': 1, '5': 9, '10': 'uuid'},
const {'1': 'id', '3': 5, '4': 1, '5': 5, '10': 'id'},
const {'1': 'value', '3': 6, '4': 1, '5': 12, '10': 'value'},
const {'1': 'key', '3': 4, '4': 1, '5': 9, '10': 'key'},
const {'1': 'value', '3': 5, '4': 1, '5': 12, '10': 'value'},
],
};
/// Descriptor for `GattDescriptorWriteArguments`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List gattDescriptorWriteArgumentsDescriptor =
$convert.base64Decode(
'ChxHYXR0RGVzY3JpcHRvcldyaXRlQXJndW1lbnRzEhgKB2FkZHJlc3MYASABKAlSB2FkZHJlc3MSIQoMc2VydmljZV91dWlkGAIgASgJUgtzZXJ2aWNlVXVpZBIvChNjaGFyYWN0ZXJpc3RpY191dWlkGAMgASgJUhJjaGFyYWN0ZXJpc3RpY1V1aWQSEgoEdXVpZBgEIAEoCVIEdXVpZBIOCgJpZBgFIAEoBVICaWQSFAoFdmFsdWUYBiABKAxSBXZhbHVl');
'ChxHYXR0RGVzY3JpcHRvcldyaXRlQXJndW1lbnRzEhkKCGdhdHRfa2V5GAEgASgJUgdnYXR0S2V5Eh8KC3NlcnZpY2Vfa2V5GAIgASgJUgpzZXJ2aWNlS2V5Ei0KEmNoYXJhY3RlcmlzdGljX2tleRgDIAEoCVIRY2hhcmFjdGVyaXN0aWNLZXkSEAoDa2V5GAQgASgJUgNrZXkSFAoFdmFsdWUYBSABKAxSBXZhbHVl');

View File

@ -1,9 +1,12 @@
import 'package:collection/collection.dart';
import 'package:flutter/services.dart';
import 'message.pb.dart';
const namespace = 'yanshouwang.dev/bluetooth_low_energy';
const method = MethodChannel('$namespace/method');
const event = EventChannel('$namespace/event');
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
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);

View File

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

View File

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

View File

@ -1,6 +1,6 @@
name: bluetooth_low_energy
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
publish_to: https://pub.dev

View File

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