为什么我的 CBPeripheralManager 有广告但无法被发现?
Why is my CBPeripheralManager advertising but not discoverable?
我正在制作一个核心蓝牙应用程序,使用我的 iPhone 作为外围设备并使用我的 mac 作为中心。我的 iPhone 已打开并播放广告,但在蓝牙浏览器中其他 iPhone 和 Mac 无法发现它。不过我朋友的Androidphone可以发现。这是怎么回事?
iOS 结束:
import UIKit
import CoreBluetooth
class ViewController: UIViewController, CBPeripheralManagerDelegate {
@IBOutlet weak var statusLabel: UILabel!
@IBOutlet weak var connectionInfoLabel: UILabel!
var peripheralManager: CBPeripheralManager!
var accelerometerXCharacteristic: CBMutableCharacteristic!
var phoneDataService: CBMutableService!
var accelerometerXData: Data!
override func viewDidLoad() {
super.viewDidLoad()
connectionInfoLabel.isHidden = true
//Ignore this I was testing the data encoding
let accelerometerVal = "45"
let someData = accelerometerVal.data(using: String.Encoding.utf8)
let revertedString = String(data: someData!, encoding: String.Encoding.utf8)! as String
let integer = Int(revertedString)!
print(integer)
setupBT(delegate: self, intialXData: someData!)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func setupBT(delegate: CBPeripheralManagerDelegate, intialXData: Data) {
peripheralManager = CBPeripheralManager(delegate: delegate, queue: nil)
//print(peripheralManager.state)
let accelerometerXCharacteristicUUID = CBUUID(string: "07B24C73-C35B-45C7-A43D-58240E3DB4DF")
let phoneDataServiceUUID = CBUUID(string: "CAB1B028-2243-4F2C-A2F1-3BE5AD51AD61")
accelerometerXCharacteristic = CBMutableCharacteristic(type: accelerometerXCharacteristicUUID, properties: CBCharacteristicProperties.read, value: intialXData, permissions: CBAttributePermissions.readable)
phoneDataService = CBMutableService(type: phoneDataServiceUUID, primary: true)
phoneDataService.characteristics = [accelerometerXCharacteristic]
}
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
var statusMessage = ""
switch peripheral.state {
case .poweredOn:
statusMessage = "Bluetooth Status: Turned On"
peripheralManager.add(phoneDataService)
peripheralManager.startAdvertising([CBAdvertisementDataServiceUUIDsKey : [phoneDataService.uuid], CBAdvertisementDataLocalNameKey: "DSiPhone"])
case .poweredOff:
statusMessage = "Bluetooth Status: Turned Off"
case .resetting:
statusMessage = "Bluetooth Status: Resetting"
case .unauthorized:
statusMessage = "Bluetooth Status: Not Authorized"
case .unsupported:
statusMessage = "Bluetooth Status: Not Supported"
default:
statusMessage = "Bluetooth Status: Unknown"
}
print(statusMessage)
}
func peripheralManager(_ peripheral: CBPeripheralManager, didAdd service: CBService, error: Error?) {
if ((error) != nil) {
print("Error \(error!.localizedDescription)")
}
}
func peripheralManagerDidStartAdvertising(_ peripheral: CBPeripheralManager, error: Error?) {
print("Advertising")
if ((error) != nil) {
print("Error advertising \(error!.localizedDescription)")
}
}
func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveRead request: CBATTRequest) {
var requestedCharacteristic: CBMutableCharacteristic?
switch request.characteristic.uuid {
case accelerometerXCharacteristic.uuid:
requestedCharacteristic = accelerometerXCharacteristic
default:
requestedCharacteristic = nil
}
if let characteristic = requestedCharacteristic {
if request.offset > characteristic.value!.count {
request.value = characteristic.value?.subdata(in: request.offset..<(characteristic.value!.count - request.offset))
peripheralManager.respond(to: request, withResult: CBATTError.success)
} else {
peripheralManager.respond(to: request, withResult: CBATTError.invalidAttributeValueLength)
}
} else {
peripheralManager.respond(to: request, withResult: CBATTError.attributeNotFound)
}
}
func peripheralManager(_ peripheral: CBPeripheralManager, central: CBCentral, didSubscribeTo characteristic: CBCharacteristic) {
print("Connection Successful")
statusLabel.text = "Successful!"
let didSendValue = peripheralManager.updateValue(accelerometerXData, for: characteristic as! CBMutableCharacteristic, onSubscribedCentrals: nil)
if !didSendValue {
print("Send failed")
}
}
}
正在打印蓝牙状态为打开并通告。在 Mac 端:
import Cocoa
import CoreBluetooth
class ViewController: NSViewController, CBCentralManagerDelegate {
var centralManager: CBCentralManager!
override func viewDidLoad() {
super.viewDidLoad()
centralManager = CBCentralManager(delegate: self, queue: nil)
// Do any additional setup after loading the view.
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
func setupBT() {
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
var statusMessage = ""
switch central.state {
case .poweredOn:
centralManager.scanForPeripherals(withServices: [CBUUID(string: "CAB1B028-2243-4F2C-A2F1-3BE5AD51AD61")], options: nil)
statusMessage = "Bluetooth Status: Turned On"
case .poweredOff:
statusMessage = "Bluetooth Status: Turned Off"
case .resetting:
statusMessage = "Bluetooth Status: Resetting"
case .unauthorized:
statusMessage = "Bluetooth Status: Not Authorized"
case .unsupported:
statusMessage = "Bluetooth Status: Not Supported"
default:
statusMessage = "Bluetooth Status: Unknown"
}
print(statusMessage)
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
print("Discovered")
}
}
打印出蓝牙已打开,但没有发现任何东西。
我首选的外围设备扫描方法是不明确要求任何特别的服务。我发现当 CBCentralManager
有时无法从广告本身指示服务时,走这条路会让人头疼。
相反,发现您感兴趣的外围设备的更可靠方法是不在您的 scanForPeripheral
参数中指定任何服务并扫描 所有内容 ,仅扫描一次.在您的 options
字典中包含 CBCentralManagerScanOptionAllowDuplicatesKey
键值 false
包裹在 NSNumber
.
中
当您收到来自 didDiscover peripheral:
方法的回调时,查看 advertisingData
。它将有一个名为 kCBAdvDataServiceUUIDs
的字段。这将是您放置在外围设备上的一系列服务 UUID。检查这些(通常只有一个)并查看是否有匹配您感兴趣的服务 UUID,如果是,那么这些就是您的外围设备。
扫描
note: Typically I do this on a timed interval basis.
let options: [String: Any] = [CBCentralManagerScanOptionAllowDuplicatesKey: NSNumber(value: false)]
centralManager?.scanForPeripherals(withServices: nil, options: options)
回调
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
if let ids = advertisementData["kCBAdvDataServiceUUIDs"] as? [CBUUID],
let id = ids.first,
id == CBUUID(string: "YourServiceID") {
print("Found Peripheral \(peripheral)")
}
}
仅供参考,重新启动后那里的代码工作得很好,所以很明显这是核心蓝牙的一个小故障。如果其他人有这个问题,一定要试试这个!
我正在制作一个核心蓝牙应用程序,使用我的 iPhone 作为外围设备并使用我的 mac 作为中心。我的 iPhone 已打开并播放广告,但在蓝牙浏览器中其他 iPhone 和 Mac 无法发现它。不过我朋友的Androidphone可以发现。这是怎么回事? iOS 结束:
import UIKit
import CoreBluetooth
class ViewController: UIViewController, CBPeripheralManagerDelegate {
@IBOutlet weak var statusLabel: UILabel!
@IBOutlet weak var connectionInfoLabel: UILabel!
var peripheralManager: CBPeripheralManager!
var accelerometerXCharacteristic: CBMutableCharacteristic!
var phoneDataService: CBMutableService!
var accelerometerXData: Data!
override func viewDidLoad() {
super.viewDidLoad()
connectionInfoLabel.isHidden = true
//Ignore this I was testing the data encoding
let accelerometerVal = "45"
let someData = accelerometerVal.data(using: String.Encoding.utf8)
let revertedString = String(data: someData!, encoding: String.Encoding.utf8)! as String
let integer = Int(revertedString)!
print(integer)
setupBT(delegate: self, intialXData: someData!)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func setupBT(delegate: CBPeripheralManagerDelegate, intialXData: Data) {
peripheralManager = CBPeripheralManager(delegate: delegate, queue: nil)
//print(peripheralManager.state)
let accelerometerXCharacteristicUUID = CBUUID(string: "07B24C73-C35B-45C7-A43D-58240E3DB4DF")
let phoneDataServiceUUID = CBUUID(string: "CAB1B028-2243-4F2C-A2F1-3BE5AD51AD61")
accelerometerXCharacteristic = CBMutableCharacteristic(type: accelerometerXCharacteristicUUID, properties: CBCharacteristicProperties.read, value: intialXData, permissions: CBAttributePermissions.readable)
phoneDataService = CBMutableService(type: phoneDataServiceUUID, primary: true)
phoneDataService.characteristics = [accelerometerXCharacteristic]
}
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
var statusMessage = ""
switch peripheral.state {
case .poweredOn:
statusMessage = "Bluetooth Status: Turned On"
peripheralManager.add(phoneDataService)
peripheralManager.startAdvertising([CBAdvertisementDataServiceUUIDsKey : [phoneDataService.uuid], CBAdvertisementDataLocalNameKey: "DSiPhone"])
case .poweredOff:
statusMessage = "Bluetooth Status: Turned Off"
case .resetting:
statusMessage = "Bluetooth Status: Resetting"
case .unauthorized:
statusMessage = "Bluetooth Status: Not Authorized"
case .unsupported:
statusMessage = "Bluetooth Status: Not Supported"
default:
statusMessage = "Bluetooth Status: Unknown"
}
print(statusMessage)
}
func peripheralManager(_ peripheral: CBPeripheralManager, didAdd service: CBService, error: Error?) {
if ((error) != nil) {
print("Error \(error!.localizedDescription)")
}
}
func peripheralManagerDidStartAdvertising(_ peripheral: CBPeripheralManager, error: Error?) {
print("Advertising")
if ((error) != nil) {
print("Error advertising \(error!.localizedDescription)")
}
}
func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveRead request: CBATTRequest) {
var requestedCharacteristic: CBMutableCharacteristic?
switch request.characteristic.uuid {
case accelerometerXCharacteristic.uuid:
requestedCharacteristic = accelerometerXCharacteristic
default:
requestedCharacteristic = nil
}
if let characteristic = requestedCharacteristic {
if request.offset > characteristic.value!.count {
request.value = characteristic.value?.subdata(in: request.offset..<(characteristic.value!.count - request.offset))
peripheralManager.respond(to: request, withResult: CBATTError.success)
} else {
peripheralManager.respond(to: request, withResult: CBATTError.invalidAttributeValueLength)
}
} else {
peripheralManager.respond(to: request, withResult: CBATTError.attributeNotFound)
}
}
func peripheralManager(_ peripheral: CBPeripheralManager, central: CBCentral, didSubscribeTo characteristic: CBCharacteristic) {
print("Connection Successful")
statusLabel.text = "Successful!"
let didSendValue = peripheralManager.updateValue(accelerometerXData, for: characteristic as! CBMutableCharacteristic, onSubscribedCentrals: nil)
if !didSendValue {
print("Send failed")
}
}
}
正在打印蓝牙状态为打开并通告。在 Mac 端:
import Cocoa
import CoreBluetooth
class ViewController: NSViewController, CBCentralManagerDelegate {
var centralManager: CBCentralManager!
override func viewDidLoad() {
super.viewDidLoad()
centralManager = CBCentralManager(delegate: self, queue: nil)
// Do any additional setup after loading the view.
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
func setupBT() {
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
var statusMessage = ""
switch central.state {
case .poweredOn:
centralManager.scanForPeripherals(withServices: [CBUUID(string: "CAB1B028-2243-4F2C-A2F1-3BE5AD51AD61")], options: nil)
statusMessage = "Bluetooth Status: Turned On"
case .poweredOff:
statusMessage = "Bluetooth Status: Turned Off"
case .resetting:
statusMessage = "Bluetooth Status: Resetting"
case .unauthorized:
statusMessage = "Bluetooth Status: Not Authorized"
case .unsupported:
statusMessage = "Bluetooth Status: Not Supported"
default:
statusMessage = "Bluetooth Status: Unknown"
}
print(statusMessage)
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
print("Discovered")
}
}
打印出蓝牙已打开,但没有发现任何东西。
我首选的外围设备扫描方法是不明确要求任何特别的服务。我发现当 CBCentralManager
有时无法从广告本身指示服务时,走这条路会让人头疼。
相反,发现您感兴趣的外围设备的更可靠方法是不在您的 scanForPeripheral
参数中指定任何服务并扫描 所有内容 ,仅扫描一次.在您的 options
字典中包含 CBCentralManagerScanOptionAllowDuplicatesKey
键值 false
包裹在 NSNumber
.
当您收到来自 didDiscover peripheral:
方法的回调时,查看 advertisingData
。它将有一个名为 kCBAdvDataServiceUUIDs
的字段。这将是您放置在外围设备上的一系列服务 UUID。检查这些(通常只有一个)并查看是否有匹配您感兴趣的服务 UUID,如果是,那么这些就是您的外围设备。
扫描
note: Typically I do this on a timed interval basis.
let options: [String: Any] = [CBCentralManagerScanOptionAllowDuplicatesKey: NSNumber(value: false)]
centralManager?.scanForPeripherals(withServices: nil, options: options)
回调
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
if let ids = advertisementData["kCBAdvDataServiceUUIDs"] as? [CBUUID],
let id = ids.first,
id == CBUUID(string: "YourServiceID") {
print("Found Peripheral \(peripheral)")
}
}
仅供参考,重新启动后那里的代码工作得很好,所以很明显这是核心蓝牙的一个小故障。如果其他人有这个问题,一定要试试这个!