Here is one problem I am facing when using CoreBluetooth
.
Up to now I always used one service and one characteristic and all worked fine.
But here I must use two characteristics and things do not quite work.
What happens is that only the first characteristic is transmitted, not the second one.
Since there must be a mistake in my program, I try to put below all the relevant code, with some comments. If someone thinks another part of the code is necessary to solve the issue, please let me know.
// Declarations relevant to the following code.
var cbPerifMngr:CBPeripheralManager!, mutaSRVC:CBMutableService!,
myCharacOne,myCharacTwo:CBMutableCharacteristic!
...................
// Code to update the CBMutableCharacteristic objects:
let strBuffOne = "abc123_my-information_1"
let strBuffTwo = "GHK678_my-information_2"
if cbPerifMngr.updateValue(Data(strBuffOne.utf8), for: myCharacOne,
onSubscribedCentrals: nil) {
// All is OK.
if cbPerifMngr.updateValue(Data(strBuffTwo.utf8), for: myCharacTwo,
onSubscribedCentrals: nil) {
// All is OK.
} else {
print("1) For some reason, the CBPeripheralManager update was not performed in \(#function).")
}
} else {
print("2) For some reason, the CBPeripheralManager update was not performed in \(#function).")
}
...................
// Code for the CBPeripheralManagerDelegate protocol:
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
print(#function)
if peripheral.state == .poweredOn {
mutaSRVC = CBMutableService(type: serviceDB_UUID, primary: true)
myCharacOne = CBMutableCharacteristic(type: myChrcOne_UUID,
properties: [.read, .notify],
value: nil, permissions: .readable)
myCharacTwo = CBMutableCharacteristic(type: myChrcTwo_UUID,
properties: [.read, .notify],
value: nil, permissions: .readable)
mutaSRVC.characteristics = [myCharacOne,myCharacTwo]
cbPerifMngr?.add(mutaSRVC)
}
}
...................
// Code for the CBPeripheralDelegate protocol:
func peripheral(_ peripheral: CBPeripheral,
didDiscoverCharacteristicsFor service: CBService,
error: Error?) {
print(#function)
if error != nil {
print("Error in \(#function) :\n\(error!)")
} else {
// Here service.characteristics? contains 2 items.
peripheral.setNotifyValue(true,
for: (service.characteristics?[0])!)
peripheral.setNotifyValue(true,
for: (service.characteristics?[1])!)
}
}
func peripheral(_ peripheral: CBPeripheral,
didUpdateValueFor characteristic: CBCharacteristic,
error: Error?) {
print(#function)
if error != nil {
print("Error in \(#function) :\n\(error!)")
} else {
if let dataStr = String(data: characteristic.value!,
encoding: String.Encoding.utf8) {
print("dataStr:: \(dataStr)")
}
}
}
When running the code I can see in the debugger console that the last function (peripheral:didUpdateValueFor:error) is called for the first characteristic (myCharacOne), but not for the second one (myCharacTwo). That means, only the first part of the information is transmitted.
I hope some CoreBluetooth
expert can see what is wrong in my code and give me some guidance.
The Core Bluetooth transmit queue has limited space. If updateValue
returns false
then there is insufficient space in the transmit queue for the update. Your program must queue further updates until you get a call to the peripheralManagerIsReady(toUpdateSubscribers)
CBPeripheralManagerDelegate
method.