Cannot set custom descriptors

Posted on
  • So I'm new to bluetooth and from what I've seen reading up on conventions I want to be able to customize the sampling rate on my bangle as well as provide additional metadata about a characteristic. There doesn't seem to be a way to create a custom descriptor that holds a specific value that I would specify, it's in neither NRF.setServices or NRF.updateServices. I want to use this instead of having many characteristics, however from what I see theres no other way.

  • Please can you explain a bit more about what you want? What additional metadata do you want to include? Apart from the text description (which is implemented, but it seems nobody really uses) I wasn't aware of much other metadata that could stored for characteristics.

    What sample rate do you want to change? Is there a problem with just sending a command over the Nordic UART characteristics?

    There doesn't seem to be a way to create a custom descriptor that holds a specific value that I would specify, it's in neither NRF.setServices or NRF.updateServices

    Is the problem that you want to use your own UUID in setServices, not one of the 16 bit pre-defined ones? If so, https://www.espruino.com/About+Bluetooth­+LE might help, but you can just make a random number like c28bef9ab6ea685a3c742eb46418eb9e

    Then change the second set of 4 digits:

    
    NRF.setServices({
      "c28b0001-b6ea-685a-3c74-2eb46418eb9e" : {
        "c28b0002-b6ea-685a-3c74-2eb46418eb9e" : {
          value : "My custom data",
          readable : true
        }
      }
    });
    
  • Lets say I have a service that sends me stored accelerometery data, I want to store additional information like whats the sampling rate configured for this accelerometer. Right now the only way I think we could implement this is one characteristic that is for reading accelerometery data and one characteristic for the sampling rate to be read from and written too however from what I've understood about ble this sampling rate should be configured as a descriptor and not as a characteristic. I don't see anyway to configure a custom descriptor to achieve such functionality in espruino

  • If you want sample rate to be written/changed, then I think it should be another characteristics in same service, why not?
    Can you point to some standard BLE service that is using the way you describe?

  • I'm looking at how xiaomi is handling their weighing scales, they've set their weigh unit as a descriptor which you can set/get to configure whether the data is recorded in LBs or KG. I don't have a problem with creating a characteristic but I thought I'd implement it how standards assume it to be.

  • I thought I'd implement it how standards assume it to be.

    check gatt supplement here https://www.bluetooth.com/specifications­/assigned-numbers/
    there is only single descriptor documented there, for other services this is typically done by characteristics, weight/scales are there too

    EDIT: also the first document with IDs has UUIDs of all standard descriptors on page 81
    https://btprodspecificationrefs.blob.cor­e.windows.net/assigned-numbers/Assigned%­20Number%20Types/Assigned%20Numbers.pdf#­page=81

  • I see for weight they do this thing even directly in the characteristics data, it is a structure and first byte Flags has metric/imperial flag
    EDIT: was googling Xiaomi and here it looks the same https://stackoverflow.com/questions/6857­1527/xiaomi-mi-scale-v1-weight-data

  • Thank you, I'll just use a characteristic. I apologize for asking an unrelated question on this thread but I'd appreciate if you could guide me.

    I am recording accelerometry data and would like to be able to read that data on request from the host device that is connected. This is important that I am able to get data in a pull based approach rather than a push based approach as is the case with Bluetooth.write and Bluetooth.println. With the push based approach the device is informed about the disconnect with a delay which leads to data loss. Also since Bluetooth.write is on serial I get some random console strings coming in through too randomly which is not good.

    The approach I'm thinking of is to make data available in a characteristics value and the host to read from it and write to it to request the next data to be available on the characteristic. Currently I don't see anyway to update the value of a characteristic without using NRF.updateServices which requires that the device is no longer connected to any host. If there's another way I can approach this which would fulfill my requirement or maybe get the way I'm planning to work.

    Also is there a maximum length for the value of a characteristic, in bytes.

  • Currently I don't see anyway to update the value of a characteristic without using NRF.updateServices which requires that the device is no longer connected to any host

    This isn't the case - you can call this just fine when you're connected. It's what it is designed for.

    What you're hitting is that you're calling 'setServices' to set up the services, but Espruino can't set them up while you're connected. Once the characteristics are set up though, updateServices will work fine

    Also is there a maximum length for the value of a characteristic, in bytes.

    It depends on the device, but on Bangle.js the MTU is 131 - I can't remember exactly but I think that means maybe 128 bytes?

  • Currently I don't see anyway to update the value of a characteristic without using NRF.updateServices which requires that the device is no longer connected to any host. If there's another way I can approach this which would fulfill my requirement or maybe get the way I'm planning to work.

    Also is there a maximum length for the value of a characteristic, in bytes.

    Here is my small test of something that works like the nordic uart - you can write to it to run javascript code and get output back. the maxlen on first line is hardcoded, should be MTU-3.

    https://gist.github.com/fanoush/04d0777f­99bb4d153aa1a40aa218db55
    you write to 0x0001 and get output from 0x0002 via notifications

    Default MTU in BLE is 23 so 20 is typical value without larger MTU negotiation.

    The example is cut from larger one https://gist.github.com/fanoush/e8db2729­844972ef1a0ae31719f31537 which does emulation of AT commands for fitness trackers described here https://github.com/fanoush/ds-d6/wiki/Br­acelet-commands

    EDIT:
    and BTW the MTU is 131 for bangle and 53 for 52832 devices https://github.com/espruino/Espruino/blo­b/master/boards/PUCKJS.py#L48
    so the maxlength is 50 or 128 unless the other device refuses MTU increase, then it is 20

  • I am testing now the example and it doesnt work very well. Longer output is incomplete.
    @Gordon can I call NRF.updateServices like that in a busy loop? without interpreter being idle
    https://gist.github.com/fanoush/04d0777f­99bb4d153aa1a40aa218db55#file-desay-jsev­al-js-L39
    Could some update overwrite/cancel previous update without the data being sent?

    Even with maxlen 20 to rule out MTU issues I get something like this

    Connecting to Bangle.js 09cf.
    Found 4 services:
    #00: 0x1800 (GenericAccess)
    #01: 0x1801 (GenericAttribute)
    #02: 6e400001-b5a3-f393-e0a9-e50e24dcca9e
    #03: 0x190A (6410)
    BLE: set #03
    Selected service 0x190A (6410).
    #00: 0x2 (2)      N
    #01: 0x1 (1)     W
    BLE: subs #00
    BLE: write #01 process.env\n
    Value changed for 00000002-0000-1000-8000-00805f9b34fb: {"VERSION":"2v16.21"
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: ,"GIT_COMMIT":"77922
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: SION":2,"STORAGE":83
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: e,heatshrink,crypto,
    BLE: BLE: write #01 process.env\n
    Value changed for 00000002-0000-1000-8000-00805f9b34fb: {"VERSION":"2v16.21"
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: ,"GIT_COMMIT":"77922
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: FLASH":1048576,"SPIF
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: OLE":"Bluetooth","MO
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: AM_BASE":536882880}
    BLE: BLE: write #01 process.env\n
    Value changed for 00000002-0000-1000-8000-00805f9b34fb: {"VERSION":"2v16.21"
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: ,"GIT_COMMIT":"77922
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: FLASH":1048576,"SPIF
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: 88608,"SERIAL":"d3c2
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: OLE":"Bluetooth","MO
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: tensorflow,locale","
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: AM_BASE":536882880}
    BLE: BLE: write #01 process.env\n
    Value changed for 00000002-0000-1000-8000-00805f9b34fb: {"VERSION":"2v16.21"
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: ,"GIT_COMMIT":"77922
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: FLASH":1048576,"SPIF
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: 88608,"SERIAL":"d3c2
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: OLE":"Bluetooth","MO
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: tensorflow,locale","
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: AM_BASE":536882880}
    BLE: BLE: write #01 process.env\n
    Value changed for 00000002-0000-1000-8000-00805f9b34fb: {"VERSION":"2v16.21"
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: ,"GIT_COMMIT":"77922
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: SION":2,"STORAGE":83
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: e,heatshrink,crypto,
    BLE:
    

    This is bleconsole on Windows 10 which can be buggy but I get same thing in nrfconnect on Android phone. I receive only some random subset of splitted array. What is also strange is that sometimes I don't get last part of the output so later calls do not overwrite previous ones. Also at least first two or mostly three are OK, it breaks later.

    Will retest with some other device without lot of stuff running on the background

  • Interesting. I tested newer 2v16 build on 52832, just bare Espruino and the example works fine - get all parts in order. I have updated Bangle to 2.17 release, updated all apps and it still does this. Good for verifying this is also Serial Bluetooth Terminal app for Android, one can select custom characteristics for input/ouput when connecting to device (hold on the name, there is menu). I'll test 52840 dongle too.

    EDIT:
    The 52840 dongle does it too so it is maybe related to SDK12 vs SDK15. With the dongle I can connect console over USB and keep it there while connecting over bluetooth so I have added print(i,E.toString(Uint8Array(val,i,(l>l­en)?len:l))); to the while loop and I can see it printed on console just fine while I get just a subset of those lines over BLE. Also the nordic uart is not used so there are no extra notifications due to the console and still it does not work

    Connecting to Dongle c56e.
    Found 4 services:
    #00: 0x1800 (GenericAccess)
    #01: 0x1801 (GenericAttribute)
    #02: 6e400001-b5a3-f393-e0a9-e50e24dcca9e
    #03: 0x190A (6410)
    BLE: set #03
    Selected service 0x190A (6410).
    #00: 0x2 (2)      N
    #01: 0x1 (1)     W
    BLE: subs #00
    BLE: write #01 process.env\n
    Value changed for 00000002-0000-1000-8000-00805f9b34fb: "STORAGE":393216,"SE
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: torage,heatshrink","
    BLE: BLE: write #01 process.env\n
    Value changed for 00000002-0000-1000-8000-00805f9b34fb: {"VERSION":"2v15.54"
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: ,"GIT_COMMIT":"5345b
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: 840Dongle","RAM":262
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: 10a7","CONSOLE":"USB
    BLE: Value changed for 00000002-0000-1000-8000-00805f9b34fb: AM_BASE":536882880}
    

    in the console I see twice this

    0 {"VERSION":"2v15.54"
    20 ,"GIT_COMMIT":"5345b
    40 5f71","BOARD":"NRF52
    60 840Dongle","RAM":262
    80 144,"FLASH":1048576,
    100 "STORAGE":393216,"SE
    120 RIAL":"05950628-5644
    140 10a7","CONSOLE":"USB
    160 ","MODULES":"Flash,S
    180 torage,heatshrink","
    200 EXPTR":406704,"APP_R
    220 AM_BASE":536882880}
    
  • seems to be related to this line https://github.com/espruino/Espruino/blo­b/master/libs/bluetooth/jswrap_bluetooth­.c#L1604
    I don't see any errors in the console but maybe the call fails with some error, like getting NRF_ERROR_RESOURCES which gets ignored in SDK15, will remove that ignoring line and retest when I have some time

  • so I have commented out all the ignored error codes to let it throw exception and I rewrote the loop to retry

        try {
          NRF.updateServices(s);
          i+=len;l-=len;
        } catch (e) {
          print(e);
        }
    

    and now it works well, I get everything sent and the error is 0x13 = NRF_ERROR_RESOURCES
    the output to console looks like

    0 {"VERSION":"2v16.294
    20 ","GIT_COMMIT":"2522
    40 6e526","BOARD":"NRF5
    Error: Error: ERR 0x13 (:1604)
    40 6e526","BOARD":"NRF5
    60 2840Dongle","RAM":26
    80 2144,"FLASH":1048576
    Error: Error: ERR 0x13 (:1604)
    80 2144,"FLASH":1048576
    100 ,"STORAGE":393216,"S
    120 ERIAL":"05950628-564
    Error: Error: ERR 0x13 (:1604)
    120 ERIAL":"05950628-564
    140 410a7","CONSOLE":"US
    160 B","MODULES":"Flash,
    180 Storage,heatshrink",
    Error: Error: ERR 0x13 (:1604)
    180 Storage,heatshrink",
    200 "EXPTR":415444,"APP_
    220 RAM_BASE":536882880}
    Error: Error: ERR 0x13 (:1604)
    220 RAM_BASE":536882880}
    

    I wonder what is the reason for ignoring errors when trying to send notifications? Isn't it better to throw exception so it can be handled. I'd remove all those ignored errors starting here https://github.com/espruino/Espruino/blo­b/master/libs/bluetooth/jswrap_bluetooth­.c#L1606

    EDIT: I retested with 52832/SDK12 and I see it too. It mostly does not happen when maxchars is 20 so I did not notice before but when I set it to 50 I see something very similar

  • Do I have to be worried about whats happening here? Because I honestly don't understand whats happening.

  • Because I honestly don't understand whats happening.

    NRF.updateServices does not work reliably to send notifications, sometimes nothing is sent.

  • I don't think this will probably affect me because I plan on polling the characteristic anyway but getting notifications would be much better so data can be sent automatically. Is this related to how fast you call updateServices?

    @Gordon have you experienced this problem

  • Is this related to how fast you call updateServices?

    Yes but with more testing I've seen it failing even with first call. It looks random, probably depends on timing in bluetooth stack -whether it is currently possible to send data or not.

    It is also discussed here (there may be some queue size to tune)
    https://devzone.nordicsemi.com/f/nordic-­q-a/66265/ble_nus_data_send-is-returning­-nrf_error_resources but still, with or without tuning, we should not ignore errors there

  • @Gordon have you experienced this problem

    No, I haven't - but I do tend to just use the built-in Nordic UART for sending large amounts of data from devices.

    NRF.updateServices does not work reliably to send notifications, sometimes nothing is sent.

    I could understand it maybe failing if you're calling it repeatedly, but are you saying it fails on the first call sometimes? Maybe you're also sending a bunch of stuff on the Nordic UART at the same time?

    But as you say it seems like we probably shouldn't be ignoring errors from that function - that code looks to be very old (6+ years) so I'm not entirely sure the reasoning behind it being there in the first place.

    @fanoush maybe you could do a PR?

  • could understand it maybe failing if you're calling it repeatedly, but are you saying it fails on the first call sometimes? Maybe you're also sending a bunch of stuff on the Nordic UART at the same time?

    yes, that is what I've seen in post #12 with 52840 dongle, first line is "STORAGE":393216,"SE and I think I had console over internal USB at that time. But could be in theory that the PC lost it even if it was sent. I had no changes there yet so it did not threw exception on Espruino side so I can't say for sure. will try again if I see it again.

    But as you say it seems like we probably shouldn't be ignoring errors from that function - that code looks to be very old (6+ years) so I'm not entirely sure the reasoning behind it being there in the first place.

    Maybe if you are updating more stuff at once, not just one value, then it would not continue with another value but still I'd better throw exception, caller can do more granular approach.

  • I'm getting a weird error too when I use NRF.updateServices,

    Execution Interrupted during event processing.
    Execution Interrupted during event processing.
    

    I've set an interval of 40 seconds, to update the characteristic, it's not like it's updating a few times a second. Is there any reason for this?

  • Does that error happen exactly once every 40 seconds? Maybe you could add a print before and after updateServices to see if it is that which is causing the problem?

    Because generally that error happens if you Ctrl-C out of something that was taking a long time to execute (or some event handler causes the device to run out of memory) but not much else

  • We're adding logs to findout where the problem is stemming from. It probably is related to running out of memory but we changed all of our allocations to be static so not sure why thats happening

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Cannot set custom descriptors

Posted by Avatar for Espruino🥵Espressif🥵 @Espruino🥵Espressif🥵

Actions