Bluetooth Low Energy disconnect/reconnect failed invoking symbol

Have a bug in our app using Genric BLE channel.


Device is connected to garmin and characteristics are being written to device, we are merrily going through scenarios where connection is lost and regained (noisy env, obstructions).
Each time we get a reconnection we "freshen" service and chracteristics and 99% of time things keep on working fine.

Just occasionally that black spot where connection is blocked seems to be a little longer and on this occasion while trying to do that "freshen", I see "Error:Unexpected Type Error Details: Failed invoking symbol.

Char written 3F4E1401-D5C9-46C3-A2A5-090606023D85 status 0
Location Characteristic written 0
Char written 3F4E1401-D5C9-46C3-A2A5-090606023D85 status 0
Location Characteristic written 0
Char written 3F4E1401-D5C9-46C3-A2A5-090606023D85 status 0
Location Characteristic written 0
Char written 3F4E1401-D5C9-46C3-A2A5-090606023D85 status 0
Location Characteristic written 0
Char written 3F4E1401-D5C9-46C3-A2A5-090606023D85 status 0
Location Characteristic written 0
procConnection Obj: 218 status 0
procConnection Obj: 218 status 1

Error: Unexpected Type Error
Details: Failed invoking <symbol>
Stack: 
  - freshenServiceAndChracteristics() at C:\NordicSemi\garmin\NovaThingy\source\NovaProfileModel.mc:40 0x1000012d 
  - procDeviceConnected() at C:\NordicSemi\garmin\NovaThingy\source\DeviceDataModel.mc:98 0x10000eb0 
  - procConnection() at C:\NordicSemi\garmin\NovaThingy\source\DeviceDataModel.mc:35 0x10000caa 
  - onConnectedStateChanged() at C:\NordicSemi\garmin\NovaThingy\source\ThingyDelegate.mc:30 0x1000096d 

The procConnection Obj, status is the device and status from the BleDelegte.onConnectedStateChange().

function freshenServiceAndChracteristics()
    {	
        
        _service = _device.get().getService(
            _profileManager.NOVA_SERVICE );

        _pendingNotifies = [];

        _locationCharacteristic = _service.getCharacteristic(
            _profileManager.LOCATION_CHARACTERISTIC);
            
         _commandCharacteristic = _service.getCharacteristic(
            _profileManager.COMMAND_CHARACTERISTIC);
            
         _statusCharacteristic = _service.getCharacteristic(
            _profileManager.STATUS_CHARACTERISTIC);
               
               
         if( null != _statusCharacteristic ) {
            _pendingNotifies = _pendingNotifies.add( _statusCharacteristic );
         }

         activateNextNotification();
    }

And stack trace seems to indicate its on that first _service.getCharacteristic() it fails; but it seems to have done the _device.get().getService() ok.

I am at a loss to know why this logic seems to work 99% of times then just occasionaly fail. Has something in the background been timed out (garbage collected?) and is now nolonger valid? Why would the getService() work, but get this type of error on the getCharacteristic(). 

Any hints greatfuly accepted.

  • Sim or real device?  Which device?

    When you lost a connection, you're just pairing using the same scan result, correct?

    When you're in this process, you've reset the connection status, device, etc before you try to pair?

    This kind of sounds like a timing issue to me, where you might be trying to do something before the connection is fully established.

    I have seen an issue where getServiceUuids get lost after a period of time, but that's it.

  • Hi Jim,
    this is related to one we have discussed a while back.

    When I say disconnect/reconnect; I really mean we have paired and the central and peripheral are connected.
    Are session proceeds we have periods where we loose connectivity (onConnectedStateChange()); but underlying stack informs us when connection is available or not; we only do the pairDevice() once at startup.

    Connection has been merrily working we have been sending data from central to peripheral; connection has been dropping and coming back; proceeding ok; then just occasionally on the reconnenction I get that error.

    I have seen back traces from real devices where this happened.

    I assume the above example is the same as stack trace looks same; was using simulator; placing our peripheral in microwave (not turning on :-)) and opening and shutting the door to force that connection loss, regain.....

  • I have a timer that is periodically writing to a characteristic.
    I also have a user command that writes to a characteristic.

    What if any of these happens at the same time a reconnection is happening and goes to freshen the services.
    Currently on the disconnect the handles to the service and characteristics are not invalidated.

    So a race condition here. I can invalidate the handles on seeing the disconnect; but it is still a race; I assume a characteristic could be somewhere down the pipe of being written when the disconnect event pipes up? Invalidating the handles just closes the window a little.

    This raises the question; what primatives do I have available for mutual exclusion to place locks around such code?
    I searched in forum for "lock", "semaphore" etc; am no wiser.

  • By invalidate, I assume you mean something like setting them to null.  When you go to use them, check for null.  Set them again upon a connection.

  • yes i meant set to null.

    what about the question of mutex/semas in connectiq? Is there an api?

  • CIQ is single threaded.  No wait, semaphores, etc.

  • Do we not have the concept of the GOD task of the OS; So BLE device disconnects; causes interrupt; OS BLE stack processes interrupt; shedules call of onConnectedStateChange() of my APP.

    Or is Interrupt processed in background and event queued; my APP running in running in loop; either processing APP code and then processing event code in a loop.  Appcode, Appevent code, Appcode, Appevent code....until APP dies?

    Is model of execution documented anywhere?

  • Finally returned to this problem.

    Looks as if the garmin tells me it has "re"-connected to our device; but when I do the Device.getService() it returns null once in a bluemoon.

    Any idea what a reasonable workaround/fix is for this? I could inject a delay; might work 99% of the time? Or set a timer to try again?

    You must have seen similar issues.

  • I am seeing device.getService() inexplicably returning null once in a blue moon too. It's rare so I have yet to work out when/why but was thinking I'd perform another reconnect when I detect this.

  • I think I "fixed" this.
    I added a timer to retry the getting of services. A retry of up to 5 times at 2 seconds separation.

    I have seen sessions of more than 1.5 hours now with no problems; previously I never got beyond 30 minutes.
    I suspect "real" issue is race in ble service code in libraries/design issue; but out of our control.