Android Question BLE2 - How to read a Bluetooth characteristic descriptor?

Discussion in 'Android Questions' started by emexes, Feb 9, 2019.

  1. emexes

    emexes Well-Known Member Licensed User

    The 0x2902 descriptor is written to by SetNotify, and that is working beautifully.

    But there are other descriptors (per https://www.bluetooth.com/specifications/gatt/descriptors ) and I cannot work out how to read descriptor 0x2904 aka "Characteristic Presentation Format". The descriptor shows up in a BLE Analyser app, alongside the 0x2902 notify descriptor for the same characteristic.

    The descriptor is of fixed format and length (7 bytes). It describes the value returned by the characteristic, eg: what it is, and the units and scaling ("exponent"). In my case currently, it is a pressure measurement in PSI, ie 0x27a5 per https://www.bluetooth.com/specifications/assigned-numbers/units

    Previously I've just hard-coded this information into my apps, but what's happened now is that the sensor manufacturer has updated the device and my readings with the new sensors are a tenth of what they should be. It turns out the scaling of the pressure reading has been changed. I didn't see that coming but, to be fair to the manufacturer, the new devices are indeed compatible with the old devices, provided that the scaling is read from the device. I have temporarily worked around the issue by identifying old/new sensors using their serial number, but I just know that's going to bite me on future device updates.
     
    Last edited: Feb 9, 2019
  2. DonManfred

    DonManfred Expert Licensed User

  3. emexes

    emexes Well-Known Member Licensed User

    That was an impressively quick response! Sadly: already done, several times. Plenty of discussion about writing descriptor 0x2902 (solved by addition of SetNotify to the library) but nothing about reading other descriptors. Is there a specific post in that thread that explains reading descriptors (not characteristics) that I've missed?

    There was a similar query thread previously:

    https://www.b4x.com/android/forum/t...w-and-read-descriptor-in-charateristic.83690/

    but it seems abandoned, and because it was a multi-pronged query, I thought it would be clearer to begin afresh.
     
  4. f0raster0

    f0raster0 Active Member Licensed User

    Better if you copy here your current code..and longs
    Also it should work if add SetNotify true to that new sensor
     
  5. emexes

    emexes Well-Known Member Licensed User

    My problem is with trying to read a characteristic descriptor, not a characteristic value. A characteristic can have multiple descriptors, and ReadData only returns the characteristic values, not characteristic descriptors.

    It looks like people had a similar problem reading 0x2803, which is now done using BLE2:GetCharacteristicProperties. Likewise writing 0x2902, which is now done using BLE2:SetNotify. I would like to read 0x2904, but I cannot find a function in BLE2 that will do it. I am hoping that there is an internal/unpublished function in BLE2 that is used by GetCharacteristicProperties that I could use, if only I knew its name.

    Once I have this app done, I have to port/rewrite it using B4i, so it would be great if the solution worked similarly there as well.
     
  6. Erel

    Erel Administrator Staff Member Licensed User

    Get the BluetoothGattCharacteristic object:
    Code:
    Dim jo As JavaObject = BleManager1
    Dim ser As JavaObject = jo.RunMethod("getService"Array(ServiceId))
    Dim chrc As JavaObject = jo.RunMethod("getChar"Array (ser, CharacteristicId))
    Read the descriptors:
    Code:
    Dim descriptors As List = chrc.RunMethod("getDescriptors"Null)
    For Each desc As JavaObject in descriptos
      
    Log("UUID: " & desc.RunMethod("getUuid"Null))
      
    Dim value() As Byte = desc.RunMethod("getValue"Null)
     
    'use bc.HexFromBytes to log it  
    Next
     
    emexes and DonManfred like this.
  7. emexes

    emexes Well-Known Member Licensed User

    Bonza! Thanks for that, and I'll get back to you on Tuesday when I have a chance to test it.
     
  8. emexes

    emexes Well-Known Member Licensed User

    The JavaObject code above got me tantalisingly close to the descriptor: I can see its UUID returned by the getUuid method, but the getValue method seems to be coming back empty - accessing the Value byte array generates an "uninitialised array" error dump, and if I log the method result directly, the method appears to be returning "null".

    I think it is something to do with not having done this beforehand:

    https://developer.android.com/refer...or(android.bluetooth.BluetoothGattDescriptor)

    I will dig around the forum and see if I can derive a magical incantation by myself (but am wide open to hints from anybody more fluent in Java than me, ie, most everyone ;-)
     
    Last edited: Feb 12, 2019
  9. Erel

    Erel Administrator Staff Member Licensed User

    Try this:
    Code:
    Dim gatt As JavaObject = BleManager1
    gatt = gatt.GetField(
    "gatt")
    gatt.RunMethod(
    "readDescriptor"Array(desc))
    Sleep(
    500'play here
    Dim value() As Byte = desc.RunMethod("getValue"Null)
     
    emexes likes this.
  10. emexes

    emexes Well-Known Member Licensed User

    Breaking news: I think we may be on the home stretch here, I've just got Value.Length = 7, which is the expected number of bytes.

    gatt = gatt.GetField("gatt") made me laugh... I never would have gatt that by myself, you've just saved me hours of frustration.

    Righto, now to find out if that magical incantation has indeed actually worked.
     
  11. emexes

    emexes Well-Known Member Licensed User

    Super, can read the descriptor now, although admittedly I don't understand half of how that code works (yet). Takes 1 to 3 seconds to read, am using a try..catch in a 100 ms loop until getValue returns something.

    From log:

    DeviceId = D3:CC:CB:F7:AC:09
    ServiceId = cc4a6a80-51e0-11e3-b451-0002a5d5c51b
    CharacteristicId = 835ab4c0-51e4-11e3-a5bd-0002a5d5c51b
    DescriptorId =00002904-0000-1000-8000-00805f9b34fb
    Value.Length = 7
    Value = 0EFFA527010000

    where descriptor 0x2904 aka "Characteristic Presentation Format" describes the sensor's pressure characteristic:

    0E = reading is a signed 16-bit integer
    FF = exponent is -1 = scale/multiply 16-bit reading by 10^-1 (ie, reading is in 0.1 PSI)
    A527 = 0x27A5 = reading is in org.bluetooth.unit.pressure.pound_force_per_square_inch
    010000 = description "unknown"
     
    Last edited: Oct 1, 2019
    f0raster0 and Erel like this.
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice