Type Check Error: BluetoothLowEnergy.registerProfile

The example code for BluetoothLowEnergey contains the following code:

function registerProfiles() {
    var profile = {                                                  // Set the Profile
       :uuid => Ble.stringToUuid("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"),
       :characteristics => [ {                                      // Define the characteristics
               :uuid => Ble.stringToUuid("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"),     // UUID of the first characteristic
               :descriptors => [                                    // Descriptors of the characteristic
                   Ble.stringToUuid("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"),
                   Ble.stringToUuid("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") ] }, {
               :uuid => Ble.stringToUuid("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") }]   // UUID of the second characteristic
    };

    // Make the registerProfile call
    BluetoothLowEnergy.registerProfile( profile );
}

But with CIQ SDK 4.1.5 the compiler throws the following error:

Invalid '$.Toybox.Lang.Dictionary{:characteristics as $.Toybox.Lang.Array<Any>, :uuid as $.Toybox.BluetoothLowEnergy.Uuid}' passed as parameter 1
of type '$.Toybox.Lang.Dictionary{:characteristics as $.Toybox.Lang.Array<{:uuid as $.Toybox.BluetoothLowEnergy.Uuid, :descriptors as $.Toybox.Lang.Array<$.Toybox.BluetoothLowEnergy.Uuid>}>, :uuid as $.Toybox.BluetoothLowEnergy.Uuid}'.

Adding Type-Annotations to the code:

typedef Ds as Lang.Array<Ble.Uuid>;
typedef Cs as Lang.Array<{:uuid as Ble.Uuid, :descriptors as Ds}>

var chars = [] as Cs
chars.add({:uuid => ...});
chars.add({:uuid => ..., :descriptors => [ ... ]});
Ble.registerProfile({:uuid => ..., :characteristics => chars as Cs})

The error changes to

Invalid '$.Toybox.Lang.Dictionary{:characteristics as $.Toybox.Lang.Array<{:uuid as $.Toybox.BluetoothLowEnergy.Uuid, :descriptors as $.Toybox.Lang.Array<$.Toybox.BluetoothLowEnergy.Uuid>}>, :uuid as $.Toybox.BluetoothLowEnergy.Uuid}' passed as parameter 1
of type '$.Toybox.Lang.Dictionary{:characteristics as $.Toybox.Lang.Array<{:uuid as $.Toybox.BluetoothLowEnergy.Uuid, :descriptors as $.Toybox.Lang.Array<$.Toybox.BluetoothLowEnergy.Uuid>}>, :uuid as $.Toybox.BluetoothLowEnergy.Uuid}'.

Which is even stranger as I can't see the difference in the types...

So - how is one expected to use Ble with type checking on modern compiler?

  • Which SDK?  4.1.5 or the current beta for the new compiler?  Which BLE sample are you using?  The Nordic ones use longToUuid like this

    public const THINGY_ENVIRONMENTAL_SERVICE = BluetoothLowEnergy.longToUuid(0xEF6802009B354933L, 0x9B1052FFA9740042L);

  • As wrote in the post: 4.1.5 and the accoriding code samples. The issue ist not with the Ble.longToUuid/Ble.stringToUuid but with the call to Ble.registerProfile - as written in the post.

  • Jim, first, thank you for all of your help on the BLE... I am trying to figure this all out myself. 

    can you help me with a couple of questions I cannot seem to find an answer to(?):   

    In the Thingy52 example it uses the THINGY_ENVIRONMENTAL_SERVICE and the THINGY_CONFIGURATION_SERVICE.   But what does the Thingy52 (Nordic Dev Board) advertising? 

    Likewise in the Thingy52CoinCollector example it uses the THINGY_CONFIGURATION_SERVICE and the THINGY_SOUND_SERVICE, and what does the dev board advertise?   i am assuming here, since i do not own the dev board, that there is example code on the Nordic side that has these services setup.   Am i correct in assuming this?  

    it seems to me that you have to add these UUID's to the Thingy52 board to get the environmental data or sound, but I cannot seem to identify the need for THINGY_CONFIGURATION_SERVICE in the Thingy52 example, or the need for the THINGY_CONFIGURATION_SERVICE in the Thingy52CC example....

    It seems like you could just use the ENVIRONMENTAL or SOUND services in each, respectively... 

    I tried looking in the Nordic SDK to see if there were examples, but I could not find any that offered insight here.

    I wish that Garmin Documented their examples better with some documentation behind them...  even some better notes could help us beginners.

    Thank you again.... you have been very helpful in all of this adventure.

  • it seems i may have found the answer to this in another post you provided...

    https://nordicsemiconductor.github.io/Nordic-Thingy52-FW/documentation/firmware_architecture.html

    but i am still a bit confused on the need for the THINGY_CONFIGURATION_SERVICE... 

    could you not just scan for the THINGY_ENVIRONMENTIAL/SOUND_SERVICE(S) instead?

  • THINGY_CONFIGURATION_SERVICES is what is advertised, but you can use the other services once you are paired with the thingy.  Do you have a thiny52 ?

  • I think I see now... No I do not have one... I wish I did, I think it would save me a lot of time and headache.

  • Do you have the HW so you can run in the sim?  If not I have an app you can run on a device to see what's advertising around you  BleScan | Garmin Connect IQ

    The main picture shows "Thing17" which is a Thiny52, and you can see the UUID that it advertised.

  • I do not have the board, but I have been using blescan a lot.. thank you!

  • I guess I am still missing some piece of this, and i am sure you have seen this question before.... but:

    what is the code Nordic is using to advertise multiple services?

    for example, they advertise the THINGY_CONFIGURATION_SERVICE and the THINGY_ENVIRONMENTIAL.

    It seems that I can only advertise one service.  Is there a means to add optional services?  I cannot seem to find the Nordic Code for this... 

  • Understand that the advertisement is sent by the thingy52  And for it, it advertises the UUID for the configuration service.  Once you pair to that scan result and you are connected, you can access the other services, like environment, and it's characteristics.

    There is a limit with CIQ, in that you can define at most 3 services