我正在尝试使用RxAndroidBle写入Android Kotlin中的外设。应用程序写入外设,然后如果此写入请求成功,外设将做出响应,即根据对发送到外设的信息所做的评估,如果是预期信息,外设将向应用程序发送响应,如果不是预期信息,则外围设备以不同的响应进行响应;总之,这是一个非常类似于通过POST发送HTTP请求的场景,信息被发送,如果信息满足要求,服务器会以状态响应。我已经成功地通过以下方式连接并从外设读取信息:
override fun connectDeviceToGetInfoHardwareByBle(mac: String): Observable<Resource<HardwareInfoResponse>> {
val device: RxBleDevice = bleClient.getBleDevice(mac)
return Observable.defer {
device.bluetoothDevice.createBond()// it is a blocking function
device.establishConnection(false) // return Observable<RxBleConnection>
}
.delay(5, TimeUnit.SECONDS)
.flatMapSingle { connection ->
connection.requestMtu(515)
.flatMap {
Single.just(connection)
}
}
.flatMapSingle {
it.readCharacteristic(UUID.fromString(GET_HARDWARE_INFORMATION_CHARACTERISTIC))
.map { byteArray ->
evaluateHardwareInfoResponse(byteArray = byteArray)
}
}
.map {
Resource.success(data = it)
}
.take(1)
.onErrorReturn {
Timber.i("Rointe Ble* Error getting ble information. {$it}")
Resource.error(data = null, message = it.message.toString())
}
.doOnError {
Timber.i("Rointe Ble*","Error getting ble information."+it)
}
.subscribeOn(ioScheduler)
.observeOn(uiScheduler)
}
如您所见,外设需要MTU,它回答了我的需求。响应后,我关闭BLE连接,应用在网络(HTTP)上执行另一项独立任务。然后,需要再次连接,但这次需要向外设写入JSON信息,设备分析该JSON,并提供一些我需要的答案作为返回;如何实现等待外设响应的写操作?由于我在连接上分配MTU,是否有必要对JSON进行长写操作?我在Kotlin的Repository模式下开发此操作。
发送的JSON如下所示:
{
"data": {
"id_hardware": "[ID_HARDWARE]",
"product_brand": <value>,
"product_type": <value>,
"product_model": <value>,
"nominal_power": <value>,
"industrialization_process_date": <value>,
"platform_api_path": "[Host_API_REST]",
"platform_streaming_path": "[Host_STREAMING]",
"updates_main_path": "[Host_UPDATES]",
"updates_alternative_path": "[Host_ALTERNATIVE_UPDATES]",
"check_updates_time": <value>,
"check_updates_day": <value>,
"auth_main_path": "[Host_AUTHORIZATION]",
"auth_alternative_path": "[Host_BACKUP_AUTHORIZATION]",
"analytics_path": "[Host_ANALYTICS]",
"idToken": "[ID_TOKEN]",
"refreshToken": "[REFRESH_TOKEN]",
"expiresIn": "3600",
"apiKey": "[API_KEY]",
"factory_wifi_ssid": "[FACTORY_WIFI_SSID]",
"factory_wifi_security_type": "[FACTORY_WIFI_TYPE]",
"factory_wifi_passphrase": "[FACTORY_WIFI_PASS]",
"factory_wifi_dhcp": 1,
"factory_wifi_device_ip": "[IPv4]",
"factory_wifi_subnet_mask": "[SubNetMask_IPv4]",
"factory_wifi_gateway": "[IPv4]"
},
"factory_version": 1,
"crc": ""
}
外围设备分析该JSON,并根据发送的JSON给我一些答案。
现在,我尝试编写期望响应的方法是:
private fun setupNotifications(connection: RxBleConnection): Observable<Observable<ByteArray>> =
connection.setupNotification(UUID.fromString(SET_FACTORY_SETTINGS_CHARACTERISTIC))
private fun performWrite(connection: RxBleConnection, notifications: Observable<ByteArray>, data: ByteArray): Observable<ByteArray> {
return connection.writeCharacteristic(UUID.fromString(SET_FACTORY_SETTINGS_CHARACTERISTIC), data).toObservable()
}
override fun connectDeviceToWriteFactorySettingsByBle(mac: String, data: ByteArray): Observable<Resource<HardwareInfoResponse>> {
val device: RxBleDevice = bleClient.getBleDevice(mac)
return Observable.defer {
//device.bluetoothDevice.createBond()// it is a blocking function
device.establishConnection(false) // return Observable<RxBleConnection>
}
.delay(5, TimeUnit.SECONDS)
.flatMapSingle { connection ->
connection.requestMtu(515)
.flatMap {
Single.just(connection)
}
}
.flatMap(
{ connection -> setupNotifications(connection).delay(5, TimeUnit.SECONDS) },
{ connection, deviceCallbacks -> performWrite(connection, deviceCallbacks, data) }
)
.flatMap {
it
}
//.take(1) // after the successful write we are no longer interested in the connection so it will be released
.map {
Timber.i("Rointe Ble: Result write: ok ->{${it.toHex()}}")
Resource.success(data = evaluateHardwareInfoResponse(it))
}
//.take(1)
.onErrorReturn {
Timber.i("Rointe Ble: Result write: failed ->{${it.message.toString()}}")
Resource.error(data = HardwareInfoResponse.NULL_HARDWARE_INFO_RESPONSE, message = "Error write on device.")
}
.doOnError {
Timber.i("Rointe Ble*","Error getting ble information."+it)
}
//.subscribeOn(ioScheduler)
.observeOn(uiScheduler)
}
如图所示,MTU被协商为最大值,并发送单个数据包(显示json文件)。
当我运行我的代码时,它会连接,但显示以下错误:
无法设置特征通知异常:找不到特征UUID为4f4a4554 - 4520 - 4341 - 4c4f-520001000002的客户端特征配置描述符(代码2
Kotlin那边有线索吗
非常感谢!!
1条答案
按热度按时间iszxjhcz1#
当我运行我的代码时,它会连接,但显示以下错误:
无法设置特征通知异常:找不到特征UUID为4f 4a 4554 -4520-4341- 4c 4f-520001000002的客户端特征配置描述符(代码2
您可以通过两种方式解决此问题:
1.更改您的外设代码,以包含有关您要使用通知的特征的客户端特征配置描述符-这是首选方法,因为它将使外设符合蓝牙规范
1.设置根本不设置CCCD值的通知时,使用
COMPAT
模式如何清理UUID的特征缓存?库在缓存中记住的东西可能是最后注册的UUID。我如何清理这个缓存?
可以使用
BluetoothGatt#refresh
清除该高速缓存,然后获取新的服务集,这将允许绕过库UUID
帮助器-您需要使用接受BluetoothGattCharacteristic
而不是UUID
的函数。刷新
BluetoothGatt
的代码:发现绕过库缓存的服务的代码: