Champs, hoping someone here has made the same stupid mistake I must have at some point; has to be pilot error but I feel like I’ve tried everything. So I have a BLE device, with a few characteristics that are notifiable and a few readable. For testing purposes, I modified the notifiable ones to be readable as well. So what I THINK I am supposed to be doing is; I make a copy of the characteristic into a variable on discovery so I can read it later. I gathered that the ‘making a copy’ step was necessary because the BLE delegate doesn’t leave things lying around. I then updated my didTapView function to ‘force ’ a read just for testing this out. I consistently get this error:
n DidTapView- trying to read this:
<CBCharacteristic: 0×281579320, UUID = FFF1, properties = 0×12, value = {length = 4, bytes = 0xffffffff}, notifying = YES>
only to be greeted by this:
ERROR didUpdateValue Error Domain=CBATTErrorDomain Code=2 “Reading is not permitted.” UserInfo={NSLocalizedDescription=Reading is not permitted.}
in didUpdateValue: This is what it thought it was doing; which looks both correct and readable to me
<CBCharacteristic: 0×281579320, UUID = FFF1, properties = 0×12, value = {length = 4, bytes = 0xffffffff}, notifying = YES>
So… what’s the deal? That characteristic has properties 0×12; which is most certainly readable. LightBlue confirms the same, I can read it ad nauseum; and it reports the correct Read and Notify properties. I’m particularly intrigued by the fact that I can also print the characteristic from within the didUpdateValue function, which has EXACTLY the right data in it (I can change it on the peripheral from 0xFFFFFFFF, and I see it reflected in what didUpdateValue sees); so I’m thinking this has to just be some stupid permission thing I skipped.
So apologies in advance for not sharing everything; but it’s a little messy right now, but here’s the critical things I think I did:
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
if let characteristics = service.characteristics {
for characteristic in characteristics {
if characteristic.uuid == BargeTender.Sensor0CharacteristicUUID {
FwdPortChar = characteristic // copy this, so I can read it later on
print("Sensor0 found")
and then my didTapView handler:
@objc func didTapView(){
self.view.endEditing(true)
// and then I'd like to force a read of characteristics, IF we're still connected
print("In DidTapView- trying to read this:")
print(FwdPortChar!)
peripheral.readValue(for: FwdPortChar!)
}
and then in didUpdateValue:
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
if let e = error {
print("ERROR didUpdateValue \(e)")
// so what's super awesome here... the rads aren't permitted, and yet they complete... so let's just
// grab the data anyhow
print("in didUpdateValue: This is what it thought it was doing; which looks both correct and readable to me")
print(characteristic)
return
}
so if anyone can show me how to read characteristic and the proper callback flow, that’s really what I think I need. Notifiable ones work great (because I blatantly copied Jarod’s code no doubt…). For the moment I’ve reverted to making EVERYTHING notifiable and I just have a timing loop in my peripheral FW that updates everything every few seconds to the app still works, but it’s super annoying and not so great for power consumption, and I have to believe that other’s wiser than me have figured out a way to read things… I know PunchThrough did! Send any good ideas; I don’t mind the ‘you ninny’ feedback.