• Support
  • BLE Characteristic reads... what did I do?!?!?

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.

    Hey radar777

    I think you can read the value from the characteristic directly. (Apples documentation). I could be wrong here since, as you stated, I mostly was dealing with notified data.

    Also, as you mentioned, a callback to whatever context you’re doing your view manipulation in would definitely make more sense than polling in a loop! I did find some info here in this post on Stack Overflow. Seems like a few techniques you can use to direct your BT data where it needs to go.

      Terms and Conditions | Privacy Policy