- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 core-bluetooth 以 6 Hz 的速率将传感器数据(64-128 字节的数组)传输到 iPad(第 6 代)。它在 ios 12 中运行良好。在我更新到 ios 13 后,蓝牙连接变得非常不可靠。该连接一次只能传输 20 个字节,并且会频繁断开连接(调用 centralManager(_ central: CBCentralManager, didDisconnectPeripheral...
)并出现错误 Code=0 "Unknown error." UserInfo={NSLocalizedDescription=Unknown error.}
。 .
在调试期间查看 iPad 屏幕,我注意到每次中心连接并发现我的服务时,在上述断开连接之前会弹出安全提示“Bluetooth Pairing Request: "<device-name>" would like to pair with your iPad. [Cancel] [Pair]
”半秒钟。
所以似乎出于某种原因,核心蓝牙正在触发安全提示并且(我猜)延迟导致连接失败?奇怪的是这个提示发生了 19/20 次,但偶尔连接会在没有触发提示的情况下通过,并且在断开连接之前会收到几个缓冲区。
有another post关于类似的事情:如何防止 ios 13 中的权限请求,但看起来这更多是由于基于错误消息的外设。
有a post详细说明 CBCentralManager didDiscover peripheral
中的缺失值字典,但无论如何我都没有使用那个值。
我肯定存储了对外围设备的硬引用,所以这不是这里的问题。我还打开了其他应用程序,可以让你浏览bluetooth4.0外设gatt服务器。 LightBlue、BLE Scanner 和 BLE Hero 在我的第 6 代 iPad 上都显示蓝牙连接提示,然后与外围设备断开连接。
这个项目是学校类(class)的一部分。我在 gitlab 上有所有的代码。 The critical ios bluetooth code is below, and the project is on gitlab .
import Foundation
import CoreBluetooth
struct Peripheral {
var uuid: String
var name: String
var rssi: Double
var peripheral: CBPeripheral
}
class SensorsComputer: BLECentral {
// just a rename of below...
}
class BLECentral: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate {
var manager: CBCentralManager!
var availablePeripherals: [String: Peripheral]
var sensorsConnected: Bool
var ref: CBPeripheral?
var sensorServiceUUIDs: [String]
var bleSensorComputerUUID: String
var data: [String:[UInt8]]
var dataNames: [String:[String:String]]
override init() {
data = [:]
availablePeripherals = [:]
sensorsConnected = false
ref = nil
sensorServiceUUIDs = ["5CA4"]
//bleSensorComputerUUID = "096A1CFA-C6BC-A00C-5A68-3227F2C58C06" // builtin is shit
bleSensorComputerUUID = "33548EF4-EDDE-6E6D-002F-DEEFC0A7AF99" // usb dongle
dataNames = [
// service uuids
"5CA4": [
// characteristic uuids
"0000": "LidarRanges",
],
]
super.init()
manager = CBCentralManager(delegate: self, queue: nil)
self.connect(uuid:bleSensorComputerUUID)
}
func scan(){
let services = dataNames.map { CBUUID(string:$0.key) }
manager.scanForPeripherals(withServices: services, options: nil)
}
func connect_internal_(uuid: String) -> Bool{ // TODO known bt device uuids.
if self.sensorsConnected {
// do not try to connect if already connected
return true
} else {
print(self.availablePeripherals.count)
if let found = self.availablePeripherals[uuid] {
manager.stopScan()
manager.connect(found.peripheral, options: nil)
return true
} else {
if availablePeripherals.count == 0 {
scan()
}
print("Error! no peripheral with \(uuid) found!")
return false
}
}
}
func connect(uuid: String){
let queue = OperationQueue()
queue.addOperation() {
// do something in the background
while true {
//usleep(100000)
sleep(1)
OperationQueue.main.addOperation {
self.connect_internal_(uuid: self.bleSensorComputerUUID)
}
}
}
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .poweredOn:
print("The central is powered on!")
scan() // automatically start scanning for BLE devices
default:
print("The centraol is NOT powered on (state is \(central.state))")
}
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
var name = ""
if let name_ = peripheral.name {
name = name_
}
let uuid = peripheral.identifier.uuidString
let rssi = Double(truncating: RSSI)
availablePeripherals[peripheral.identifier.uuidString] = Peripheral(uuid: uuid, name: name, rssi: rssi, peripheral: peripheral)
print(uuid, rssi)
}
func getSorted(uuids:Bool = false) -> [Peripheral] {
let peripherals = Array(availablePeripherals.values)
return peripherals.sorted(by:) {$0.rssi >= $1.rssi}
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
print("Central connected!")
sensorsConnected = true
peripheral.delegate = self
var cbuuids:[CBUUID] = []
for id in sensorServiceUUIDs {
cbuuids.append(CBUUID(string: id))
}
peripheral.discoverServices(cbuuids) // TODO store service uuids somewhere nicer
}
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
if let e = error {
print("Central disconnected because \(e)")
} else {
print("Central disconnected! (no error)")
}
sensorsConnected = false
availablePeripherals = [:]
}
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
print("Central failed to connect...")
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
if let error = error {
print("Peripheral could not discover services! Because: \(error.localizedDescription)")
} else {
peripheral.services?.forEach({(service) in
print("Service discovered \(service)")
// TODO characteristics UUIDs known
peripheral.discoverCharacteristics(nil, for: service)
})
}
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
if let error = error {
print("Could not discover characteristic because error: \(error.localizedDescription)")
} else {
service.characteristics?.forEach({ (characteristic) in
print("Characteristic: \(characteristic)")
if characteristic.properties.contains(.notify){
peripheral.setNotifyValue(true, for: characteristic)
}
if characteristic.properties.contains(.read){
peripheral.readValue(for: characteristic)
}
if characteristic.properties.contains(.write){
peripheral.writeValue(Data([1]), for: characteristic, type: .withResponse)
}
})
}
}
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
if let error = error {
print("error after didUpdateValueFor characteristic \(characteristic): \(error.localizedDescription)")
} else {
let sname = characteristic.service.uuid.uuidString
let cname = characteristic.uuid.uuidString
guard let _dname = dataNames[sname], let dataName = _dname[cname] else {
return
}
//print("value of characteristic \(cname) in service \(sname) was updated.")
if let value = characteristic.value {
let value_arr = Array(value)
//print(" The new data value is \(value_arr.count) bytes long")
//print("dataname is \(dataName)")
self.data[dataName] = value_arr
}
}
}
}
BLE外设代码是一个基于bleno和rosnodejs的传感器数据节点项目。 The peripheral code is also on gitlab .
我已经在 git 中回滚到几个已知的工作项目版本,并且在更新到 ios 13 后似乎没有任何工作。我将尝试在 mac 项目上运行 corebluetooth 代码以测试它是否可以在那里工作。
所以,综上所述,从ios 12.4更新到ios 13后,当连接到BLE外设时,即使通信是蓝牙4.0/BLE,也会打开蓝牙连接提示。随着这个提示,连接一开始就断开,有时给我一些部分数据缓冲区,有时什么都不给我。
BLE 连接未正确启动,如果连接提示正常工作,它会干扰我在没有用户输入的情况下自动连接到设备(机器人传感器)的能力。
如果有人知道 info.plist 中的某些选项可以防止出现此中断连接提示,那就太好了。我在这里不知所措,有没有简单的方法可以回滚 ios 版本?或者有什么方法可以让 Apple INC 发布紧急补丁,防止核心蓝牙低功耗的弹出窗口?或者有什么方法可以绕过弹出窗口并允许用户在不破坏 BLE 协议(protocol)的情况下正确进行身份验证?
感谢任何看过这篇文章的人。
最佳答案
我可能没有完整的解决方案,但这应该有助于指明正确的方向。
我假设代码在 Info.plist 中设置了 NSBluetoothAlwaysUsageDescription,这在 iOS 13 中现在是必需的。NSBluetoothPeripheralUsageDescription 在 iOS 13 之前是必需的。
您在消失前看到的提示是由配对过程引起的,可能由两件事触发:
外设尝试启动配对过程(discouraged by Apple in 25.10 of Accessory Design Guidelines)
该应用已尝试访问已加密但已被拒绝的特征。这会触发配对过程,从而触发弹出的警报。
在您点击“配对”按钮之前,有一些情况可能会导致连接断开。
该应用未保留 CBPeripheral 引用(您表示它保留),如果是这种情况,您会看到一条 API 滥用日志消息。
在您有机会做出响应之前,外围设备正在断开连接。这更有可能,您可以嗅探 BLE 数据包以确定。更多详细信息如下。
可能存在计时问题,即应用程序在配对过程完成之前尝试继续处理请求,这可能会触发断开连接。要测试这种可能性,请在服务和特征发现完成后添加延迟,然后再发出额外的读/写/通知请求。
外围设备很可能正在断开连接,这可能发生在 key 交换过程中,如果 key 不匹配,则在您使用安全特性时会发生这种情况。如果 key 由于某种原因发生变化(我通常会在固件更新时看到它,也许外围设备发生了变化,可能是 iOS 更新到 13),那么这种行为就可能发生。如果您转到蓝牙设置并忘记了设备, key 将被丢弃,因此 key 交换过程可能会再次开始工作。如果是这样,则存在过时的 key ,很可能是在必须重新协商的 iOS 端。
最后的选择是暂时确保服务和特性不 protected 。我没有看到 secure: [...] 在你的代码中,所以我不确定。
如果简单的选项都无法修复它,我的下一步将是嗅探数据包。
关于ios - 如何阻止 ios core-bluetooth CBCentralManagerDelegate 在 ios13 中断开连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58645951/
主要思想是将 EF Core nuget 包添加到 .NET Core 库项目,然后在一堆应用程序(例如 ASP.NET Core、Win 服务、控制台应用程序)中使用该库,而无需在每个应用程序中配置
我想要实现的是编写一个简单的.net核心后台工作程序(.net core 3.1)的代码,在该工作程序作为Windows服务运行时,我在其中将数据写入SQL Server数据库(通过EF Core 3
关于 .Net Core SDK download page 二进制文件有什么用?它与安装程序有何不同? 最佳答案 二进制文件是 .NET Core 的编译代码。它们拥有运行 .NET Core 所需
.NET Core 和 Entity Framework Core 之间的区别?我们可以在 .NET Core 中使用 Entity Framework Core 吗?两者都有什么优势? 最佳答案 E
.NET Core 和 ASP.NET Core 到底有什么区别? 它们是相互排斥的吗?我听说 ASP.NET Core 是基于 .NET Core 构建的,但它也可以基于完整的 .NET 框架构建。
我对 ASP.NET Core 开发完全陌生。我正在尝试使用单个模型和 mysql 创建一个简单的 asp.net core Web api 来存储模型数据,然后我想使用 Swagger 将其作为 R
.NET Core 和 Entity Framework Core 之间的区别?我们可以在 .NET Core 中使用 Entity Framework Core 吗?两者都有什么优势? 最佳答案 E
好吧,作为一个新的 .net 开发生态系统,我有点迷失在核心工具、版本等方面。 有人可以解释我之间的区别吗 VS 2015 核心工具预览版 x - See here .NET Core/SDK 与否
我已阅读有关如何通过信号器核心集线器从后台服务向客户端发送通知的文档。如何从客户端接收到后台服务的通知? 后台服务应该只是一个单例。 public class Startup { public
关闭。这个问题是opinion-based .它目前不接受答案。 想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题. 4年前关闭。 Improve t
非常简单的问题: 我正在尝试创建一个像这样的谓词构建器: var predicate = PredicateBuilder.False(); 但似乎在Net Core和EF Core中不可用。
在 .NET Core 自包含应用程序 中...我们需要在 project.json 中指定运行时 (RID) 我们希望我们的应用程序针对...发布为什么会这样? .NET Core 是跨平台的,与我
如何用 iCloud Core Data 替换我现有的 Core Data?这是我的持久商店协调员: lazy var persistentStoreCoordinator: NSPersistent
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 2 年前。 Improv
今天我正在学习新的 ASP.net 核心 API 3.1,我想将我的旧网站从 MVC4 转移到 Web API。除了一件事,一切都很好。数据库连接。在我的旧网站中,我为每个客户端(10/15 数据库)
我在 Visual Studio 2015 Update 3 和 .NET Core 1.0 中工作。我有一个 .NETCoreApp v1.0 类型的 Web API 项目。当我添加一个 .NET
我一直在尝试遵循 Ben Cull ( http://benjii.me/2016/06/entity-framework-core-migrations-for-class-library-proj
当我打开我的 vs 代码程序时,我收到以下消息: 无法找到 .NET Core SDK。 .NET Core 调试将不会启用。确保 .NET Core SDK 已安装并且在路径上。 如果我安装甚至卸载
我偶然发现了一个非常奇怪的问题。每当 Web 应用程序启动时,dotnet.exe 都会使用相当多的内存(大约 300M)。然而,当它触及某些部分时(我感觉这与 EF Core 使用有关),它会在短时
ASP.NET Core Web (.NET Core) 与 ASP.NET Core Web (.NET Framework) 有什么区别? .NET Framework 是否提供 similar
我是一名优秀的程序员,十分优秀!