onConnectedStateChanged not being called

hi, 

i am trying to create a datafield which connects to a indoor rowing controller. 

i am able to scan devices, and try to pair to the controller. however onConnectedStateChanged is never called. 

so far i am using a modified version of Thingy52CoinCollector. my watch is a 645M, and i am building using the sdk 4.1.1

this is what the connectiq log looks like

registerProfiles
scanning
onScanStateChange
onProfileRegister
found device: null
found device: FS-ABFEBE
found FL by Company ID
trying to pair device, rssi -45
onScanStateChange

i have also installed BleScan app, https://apps.garmin.com/en-US/apps/9bcc8b66-8385-4afb-b93e-f69e01422284

and i observed the same behaviour: the controller will be found, but if i try to pair to it, the process will timeout after 14 seconds. 

i read here in the forum that sometimes onConnectedStateChanged() is not always called, and a workaround for it would be to just check if the device is connected. unfortunately if i try 

var device = BluetoothLowEnergy.pairDevice(scanResult); then, the following returns false: 
device.isConnected() ; 
given that BleScan is presenting the same behaviour, i am beginning to think that this might be some kind of issue with the bluetooth stack of the controller (the controller is provided with a topiom rower, and it is compatible by using fitshow protocol in apps like the very same fitshow or kinomap. 
nrf connect does manage to pair the device, the callback after the pairing it is called very fast as shown in the log file
can you guys figure out what my be the problem here, or some workaround to make this work? 
  • hi @

    I couldn't connect with my device. Basically, I managed to get onConnectedStateChanged to be called only once, and unpair didn't work.

    I was able to reproduce this behavior with blescan: I could find the device. Apparently, I could also call unpair, which seemingly unpaired the device in the app. But I concluded that blescan does not wait for the unpair callback to show the device as unpaired. The next attempt to pair with blescan also failed.

    I haven't tested with 7.2.0. I see that blescan hasn't been updated recently. When a version compiled with 7.2.0 is released, I will try to see if I can perform successive pairings and unpairings. However, I doubt the problem can be solved at the SDK level without changing the firmware of the watch (but I don't have knowledge of how Garmin's BLE stack works, so I might be wrong).

    My device exhibits exactly the symptoms described in this ticket that is 3 years old and which Garmin never closed: https://forums.garmin.com/developer/connect-iq/i/bug-reports/connect-iq-ble-advertising-layer-parsing-bug-prevent-many-devices-to-function-properly-paired-or-not-paired-toybox-bluetoothlowenergy-scanresult-getrawdata-getservicedata-getserviceuuids-are-broken

    I can connect to the device from Android using nRF Connect without having to use bonding or any other special feature. And that's where I was able to verify that the device's advertising is exactly as described in the ticket above.

    On the manufacturer's side, I tried to contact them, but they ignored me as well. So, I am afraid that is where my journey ends.

  • I cannot start my program in sim even. Only on a real device lol

  • If you are using bonding, that only works on real devices, not the sim.  You get a error in the sim that doesn't really tell you what the issue is.

  • This line would cause crash in sim
    (_profileManager as ProfileManager).registerProfiles();
    But the registration is quite simple.
    //
    // Copyright 2019-2021 by Garmin Ltd. or its subsidiaries.
    // Subject to Garmin SDK License Agreement and Wearables
    // Application Developer Agreement.
    //

    import Toybox.BluetoothLowEnergy;
    import Toybox.System;

    class ProfileManager {
    public const BROADCAST_SERVICE = BluetoothLowEnergy.stringToUuid(
    "0000190A-0000-1000-8000-00805F9B34FB"
    );

    public const DATA_SENDING_SERVICE = BluetoothLowEnergy.stringToUuid(
    "6E400001-B5A3-F393-E0A9-E50E24DCCA00"
    );

    public const DATA_SENDING_CHARACTERISTIC = BluetoothLowEnergy.stringToUuid(
    "6E400002-B5A3-F393-E0A9-E50E24DCCA00"
    );

    public const DATA_RECEIVING_CHARACTERISTIC = BluetoothLowEnergy.stringToUuid(
    "6E400003-B5A3-F393-E0A9-E50E24DCCA00"
    );

    private const _dataSendingProfileDef = {
    :uuid => DATA_SENDING_SERVICE,
    :characteristics => [
    {
    :uuid => DATA_SENDING_CHARACTERISTIC,
    :descriptors => [BluetoothLowEnergy.cccdUuid()],
    },
    {
    :uuid => DATA_RECEIVING_CHARACTERISTIC,
    :descriptors => [BluetoothLowEnergy.cccdUuid()],
    },
    ],
    };

    //! Register the bluetooth profile
    public function registerProfiles() as Void {
    BluetoothLowEnergy.registerProfile(_dataSendingProfileDef);
    }
    }
  • what is the crash?

  • "vmSummary" : "ReadOnly portion of Libraries: Total=1.3G resident=0K(0%) swapped_out_or_unallocated=1.3G(100%)\nWritable regions: Total=1.2G written=642K(0%) resident=642K(0%) swapped_out=0K(0%) unallocated=1.2G(100%)\n\n VIRTUAL REGION \nREGION TYPE SIZE COUNT (non-coalesced) \n=========== ======= ======= \nAccelerate framework 128K 1 \nActivity Tracing 256K 1 \nCG image 2976K 17 \nCG raster data 2512K 2 \nColorSync 656K 30 \nCoreAnimation 1440K 81 \nCoreGraphics 48K 3 \nCoreServices 624K 2 \nCoreUI image data 400K 5 \nDispatch continuations 64.0M 1 \nFoundation 16K 1 \nKernel Alloc Once 32K 1 \nMALLOC 1.1G 64 \nMALLOC guard page 288K 18 \nSTACK GUARD 56.5M 31 \nStack 24.0M 34 \nVM_ALLOCATE 192K 12 \n__AUTH 3214K 431 \n__AUTH_CONST 47.5M 632 \n__CTF 824 1 \n__DATA 16.6M 611 \n__DATA_CONST 19.6M 638 \n__DATA_DIRTY 1795K 218 \n__FONT_DATA 2352 1 \n__LINKEDIT 586.0M 4 \n__OBJC_RW 2353K 1 \n__TEXT 744.4M 655 \n__TPRO_CONST 272K 2 \nmapped file 238.9M 29 \nowned unmapped memory 976K 1 \npage table in kernel 642K 1 \nshared memory 912K 16 \n=========== ======= ======= \nTOTAL 2.9G 3545 \n",
    "legacyInfo" : {
    "threadTriggered" : {
    "name" : "ant_main"
    }
    },

    The sim crashed.

    I downgraded  my sdk to 6.4.1 the crash dispeared.

  • Here is a demo code for NOT CALLED onConnectedStateChanged https://github.com/Likenttt/demo-ble

    Once the _device gets assigned, it would never be null which means 

    if (_device != null && device.isConnected()) {// this condition is never reached
    //! Process a new device connection
    //! @param device The device that was connected
    public function procConnection(device as Device) as Void {
    if (_device != null && device.isConnected()) {
    _device = device;
    _connected = true;
    // startSoundControl();
    } else {
    _device = null;
    _connected = false;
    BluetoothLowEnergy.setScanState(BluetoothLowEnergy.SCAN_STATE_SCANNING);
    }
    }
    I printed the result on the screen.
    //
    // Copyright 2019-2021 by Garmin Ltd. or its subsidiaries.
    // Subject to Garmin SDK License Agreement and Wearables
    // Application Developer Agreement.
    //

    import Toybox.Activity;
    import Toybox.Lang;
    import Toybox.Time;
    import Toybox.WatchUi;

    class ABSView extends WatchUi.SimpleDataField {
    private var _deviceManager as DeviceManager;

    //! Set the label of the data field here
    //! @param deviceManager The device manager
    public function initialize(deviceManager as DeviceManager) {
    SimpleDataField.initialize();
    label = "Status";
    _deviceManager = deviceManager;
    }

    //! Play the sample every two seconds
    //! @param info The updated Activity.Info object
    //! @return Value to display in the data field
    public function compute(
    info as Info
    ) as Numeric or Duration or String or Null {
    // See Activity.Info in the documentation for available information.
    return _deviceManager.connected() ? "Connected" : "Disconnected";
    }
    }
  • Oh, Make sure you aren't already paired to your device in the watch firmware and the sensor isn't paired to something like you phone

    Oh this line solved my problem.