Первых вещей первыми: работаю OSX 10.10.4, IOS 4, Xcode 6.3.2, iPhone 6, SwiftПодписавшись на уведомления от в CBCharacteristic не работают
Краткая история: У меня есть определенный Bluetooth LE устройство здесь с который я хочу получать уведомления, когда значения изменения характеристик, например по пользовательскому вводу. Пытаясь подписаться на него не удастся, а дает погрешность Error Domain=CBATTErrorDomain Code=10 "The attribute could not be found."
Длинная история: Так, у меня есть класс BluetoothManager, в котором я начала сканирования для периферийных устройств, как только мой $CBCentralManager.state
является .PoweredOn
. Это легко, я даже хороший гражданин и отсканировать специально для тех, кто с Услугой Я хочу
centralManager.scanForPeripheralsWithServices([ServiceUUID], options: nil)
Надеясь это удастся, я реализован следующий метод делегата:
func centralManager(central: CBCentralManager!, didDiscoverPeripheral peripheral: CBPeripheral!, advertisementData: [NSObject : AnyObject]!, RSSI: NSNumber!) {
if *this is a known device* {
connectToPeripheral(peripheral)
return
}
[...] // various stuff to make something a known device, this works
}
Так движущуюся вдоль, мы получаем:
func connectToPeripheral(peripheral: CBPeripheral) {
println("connecting to \(peripheral.identifier)")
[...] // saving the peripheral in an array along the way so it is being retained
centralManager.connectPeripheral(peripheral, options: nil)
}
ЮПП, это удастся, так что я получаю подтверждение и начать открыть службу:
func centralManager(central: CBCentralManager!, didConnectPeripheral peripheral: CBPeripheral!) {
println("Connected \(peripheral.name)")
peripheral.delegate = self
println("connected to \(peripheral)")
peripheral.discoverServices([BluetoothConstants.MY_SERVICE_UUID])
}
Который также работает, так как этот метод делегата вызывается так:
func peripheral(peripheral: CBPeripheral!, didDiscoverServices error: NSError!) {
if peripheral.services != nil {
for service in peripheral.services {
println("discovered service \(service)")
let serviceObject = service as! CBService
[...] // Discover the Characteristic to send controls to, this works
peripheral.discoverCharacteristics([BluetoothConstants.MY_CHARACTERISTIC_NOTIFICATION_UUID], forService: serviceObject)
[...] // Some unneccessary stuff about command caches
}
}
}
А что вы знаете: характерный получает обнаружил!
func peripheral(peripheral: CBPeripheral!, didDiscoverCharacteristicsForService service: CBService!, error: NSError!) {
for characteristic in service.characteristics {
let castCharacteristic = characteristic as! CBCharacteristic
characteristics.append(castCharacteristic) // Retaining the characteristic in an Array as well, not sure if I need to do this
println("discovered characteristic \(castCharacteristic)")
if *this is the control characteristic* {
println("control")
} else if castCharacteristic.UUID.UUIDString == BluetoothConstants.MY_CHARACTERISTIC_NOTIFICATION_UUID.UUIDString {
println("notification")
peripheral.setNotifyValue(true, forCharacteristic: castCharacteristic)
} else {
println(castCharacteristic.UUID.UUIDString) // Just in case
}
println("following properties:")
// Just to see what we are dealing with
if (castCharacteristic.properties & CBCharacteristicProperties.Broadcast) != nil {
println("broadcast")
}
if (castCharacteristic.properties & CBCharacteristicProperties.Read) != nil {
println("read")
}
if (castCharacteristic.properties & CBCharacteristicProperties.WriteWithoutResponse) != nil {
println("write without response")
}
if (castCharacteristic.properties & CBCharacteristicProperties.Write) != nil {
println("write")
}
if (castCharacteristic.properties & CBCharacteristicProperties.Notify) != nil {
println("notify")
}
if (castCharacteristic.properties & CBCharacteristicProperties.Indicate) != nil {
println("indicate")
}
if (castCharacteristic.properties & CBCharacteristicProperties.AuthenticatedSignedWrites) != nil {
println("authenticated signed writes ")
}
if (castCharacteristic.properties & CBCharacteristicProperties.ExtendedProperties) != nil {
println("indicate")
}
if (castCharacteristic.properties & CBCharacteristicProperties.NotifyEncryptionRequired) != nil {
println("notify encryption required")
}
if (castCharacteristic.properties & CBCharacteristicProperties.IndicateEncryptionRequired) != nil {
println("indicate encryption required")
}
peripheral.discoverDescriptorsForCharacteristic(castCharacteristic) // Do I need this?
}
}
Теперь вывод на консоль вплоть до здесь выглядит следующим образом:
connected to <CBPeripheral: 0x1740fc780, identifier = $FOO, name = $SomeName, state = connected>
discovered service <CBService: 0x170272c80, isPrimary = YES, UUID = $BAR>
[...]
discovered characteristic <CBCharacteristic: 0x17009f220, UUID = $BARBAR properties = 0xA, value = (null), notifying = NO>
control
following properties:
read
write
[...]
discovered characteristic <CBCharacteristic: 0x17409d0b0, UUID = $BAZBAZ, properties = 0x1A, value = (null), notifying = NO>
notification
following properties:
read
write
notify
[...]
discovered DescriptorsForCharacteristic
[]
updateNotification: false
Эй! В нем говорится, что updateNotification
- false
. Откуда это? Почему это мой обратный вызов для setNotify...
:
func peripheral(peripheral: CBPeripheral!, didUpdateNotificationStateForCharacteristic characteristic: CBCharacteristic!, error: NSError!) {
println("updateNotification: \(characteristic.isNotifying)")
}
Что это дает? Я сказал, чтобы он уведомлялся! Почему он не уведомляет? Давайте установить контрольную точку в соответствии с Println и проверить объект ошибки:
(lldb) po error
Error Domain=CBATTErrorDomain Code=10 "The attribute could not be found." UserInfo=0x17026eac0 {NSLocalizedDescription=The attribute could not be found.}
ОК, так что это оставляет меня из идей. Я не смог найти соответствующие подсказки относительно этого кода ошибки. Само описание, которое я не могу понять, поскольку я пытался настроить уведомление для характеристики, которую я обнаружил ранее, следовательно, это должно существует, правда? Кроме того, на Android, возможно, подписаться на уведомления, поэтому, я думаю, я могу исключить проблемы с устройством ... или я могу? Любые подсказки по этому поводу действительно оценены!
Похоже, что вы не можете сохранить ссылку на периферию. Paulw11 имеет отличный ответ для этого http://stackoverflow.com/questions/26377470/ios-corebluetooth-centralmanagerdidconnectperipheral-didfailtoconnectperiph –
Нет, я делаю это; Я оставил это для краткости: у меня есть Массивы для Периферийных устройств в обнаруженном, подключающемся и подключенном состоянии и не забудьте сохранить периферийное устройство в соответствующем режиме во время настройки. – mss
Ваш код выглядит хорошо, и он может быть большим на вашем устройстве или на iOS. Мой инструмент для тестирования - это приложение LightBlue. Вы можете использовать это, чтобы узнать свое периферийное устройство и службы и посмотреть, может ли он установить уведомление по вашему признаку. – Paulw11