Complete
over 3 years ago

WERETECH-10085

Fix has been applied to update for VA4 in FW: 5.63

VivoActive 4: BleDelegate.onProfileRegister returns status value 2 on every 2nd and 3rd registerProfile

Registering Ble profiles works just fine with the simulator, simulating a VivoActive 4, and a Nordic nRF52.
Registering Ble profiles when the app runs on a VivoActive 4 is only successful for the 1st profile registered.
Every 2nd and 3rd register fails or better returns state value 2.

This value is not defined in the enumerators of BlueToothLowEnergy.
As a result any app registering more then 1 profile doesn't work on a VivoActive 4.

Changing the order of registering profiles does not help, always only the 1st is SUCCESSful.

There is no difference in results if you call registerProfile, 3 times, and then Ble.setScanState(Ble.SCAN_STATE_SCANNING) or
first call Ble.setScanState(Ble.SCAN_STATE_SCANNING) and then call registerProfile, 3 times.

Log file of the console with the simulator, see BleProfileTest_OK.TXT
Log file of the VivoActive 4, see BleProfileTest_ERROR.TXT

ble:initialize
bleInitProfiles1 avail:3
bleInitProfiles2 avail:3
bleInitProfiles3 avail:3
bleInitProfiles done:3
ble:setScanState SCAN_STATE_SCANNING
ble:onScanStateChange SCAN_STATE_SCANNING SUCCESS
ble:onProfileRegister 0000180F-0000-1000-8000-00805F9B34FB SUCCESS
ble:onProfileRegister 000018EF-5348-494D-414E-4F5F424C4500 STATE_ERROR ? 2
ble:onProfileRegister 000018FE-1212-EFDE-1523-785FEABCD123 STATE_ERROR ? 2
ble:onScanResults avail:3
ble:onScanResults avail:3
ble:onScanResults avail:3

The watch app, see code, registers 3 profiles and prints the results of the BleDelegate callback functions.

using Toybox.BluetoothLowEnergy as Ble;

class TestBleDelegate extends Ble.BleDelegate
{
	var batteryServiceUuid = Ble.stringToUuid("0000180f-0000-1000-8000-00805f9b34fb");
	var batteryCharacteristicUuid = Ble.stringToUuid("00002a19-0000-1000-8000-00805f9b34fb");
	
	var modeServiceUuid = Ble.stringToUuid("000018ef-5348-494d-414e-4f5f424c4500");		
	var modeCharacteristicUuid = Ble.stringToUuid("00002ac1-5348-494d-414e-4f5f424c4500");
	
	var MACServiceUuid = Ble.stringToUuid("000018fe-1212-efde-1523-785feabcd123");
	var MACCharacteristicUuid = Ble.stringToUuid("00002ae3-1212-efde-1523-785feabcd123");

    //==========================================================

    function bleInitProfiles() {
		var profile1 = { 
			:uuid => batteryServiceUuid,
			:characteristics => [ {
					:uuid => batteryCharacteristicUuid 
					} ]
		};
		var profile2 = {
			:uuid => modeServiceUuid,
			:characteristics => [ {
					:uuid => modeCharacteristicUuid,
					:descriptors => [ Ble.cccdUuid() ]
				} ]
		};
		var profile3 = {
			:uuid => MACServiceUuid,
			:characteristics => [ {
					:uuid => MACCharacteristicUuid
				} ]
		};
		try {
			System.println("bleInitProfiles1 avail:" + Ble.getAvailableConnectionCount() );
    		Ble.registerProfile(profile1);
    		
			System.println("bleInitProfiles2 avail:" + Ble.getAvailableConnectionCount() );
    		Ble.registerProfile(profile2);
    		
			System.println("bleInitProfiles3 avail:" + Ble.getAvailableConnectionCount() );
    		Ble.registerProfile(profile3);
    		System.println("bleInitProfiles   done:" + Ble.getAvailableConnectionCount() );
    		
		} catch (e) {
		    System.println("catch = " + e.getErrorMessage());
		}
    }

    //==========================================================
	
    function initialize() {
		System.println("ble:initialize");
		
        BleDelegate.initialize();
   		bleInitProfiles();
		System.println("ble:setScanState SCAN_STATE_SCANNING");
   	    Ble.setScanState(Ble.SCAN_STATE_SCANNING);    		
    }
    
	function onCharacteristicChanged(characteristic, value) {
		System.println("ble:onCharacteristicChanged "+ characteristic.getUuid().toString() + " " + value);
	}
	
	function onCharacteristicRead(characteristic, status, value) {
		System.println("ble:onCharacteristicRead "+ characteristic.getUuid().toString() + " " + stateToString(status) + " " + value);
	}
	
	function onCharacteristicWrite(characteristic, status) {
	     System.println("ble:onCharacteristicWrite "+ characteristic.getUuid().toString() + " " + stateToString(status));
	}

	function onConnectedStateChanged(device, connectionState) {
		System.println("ble:onConnectedStateChanged " + device + " " + connectionStateToString(connectionState));
	}

    function onDescriptorRead(descriptor, status, value) {
		System.println("ble:onDescriptorRead " + descriptor.getCharacteristic().getUuid().toString() + " " + stateToString(status) + " " + value);
    }

	function onDescriptorWrite(descriptor, status) {
		System.println("ble:onDescriptorWrite " + descriptor.getCharacteristic().getUuid().toString() + " " + stateToString(status));
	}

    function onProfileRegister(uuid, status) {
		System.println("ble:onProfileRegister " + uuid.toString() + " " + stateToString(status));  
	}
    
    function onScanResults(scanResults) {
    	System.println("ble:onScanResults avail:" + Ble.getAvailableConnectionCount() );
    }

    function onScanStateChange(scanState, status) {
    	System.println("ble:onScanStateChange " + scanStateToString(scanState) +" "+ stateToString(status));
    }
        
    //======================================================
    
    private function stateToString(state){
        switch(state){
            case Ble.STATUS_NOT_ENOUGH_RESOURCES: { return "NOT_ENOUGH_RESOURCES"; }
            case Ble.STATUS_READ_FAIL: { return "READ_FAIL"; }
            case Ble.STATUS_SUCCESS: { return "SUCCESS"; }
            case Ble.STATUS_WRITE_FAIL: { return "WRITE_FAIL"; }
        }
        return "STATE_ERROR ? " + state;
    }
    
    private function scanStateToString(state){
        switch(state){
            case Ble.SCAN_STATE_OFF: { return "SCAN_STATE_OFF"; }
            case Ble.SCAN_STATE_SCANNING: { return "SCAN_STATE_SCANNING"; }
        }
        return "SCAN_STATE_ERROR ? " + state;
    }
    
    private function connectionStateToString(state){
        switch(state){
            case Ble.CONNECTION_STATE_CONNECTED: { return "CONNECTED"; }
            case Ble.CONNECTION_STATE_DISCONNECTED: { return "DISCONNECTED"; }
            case Ble.CONNECTION_STATE_NOT_CONNECTED: { return "NOT_CONNECTED"; }
            case Ble.CONNECTION_STATE_NOT_INITIALIZED: { return "NOT_INITIALIZED"; }
        }
        return "CONNECTION_STATE_ERROR ? " + state;
    }
}

using Toybox.Application;
using Toybox.WatchUi;
using Toybox.BluetoothLowEnergy as Ble;

class BleProfileTestApp extends Application.AppBase {

    private var view;

    function initialize() {
        AppBase.initialize();
    }

    // onStart() is called on application start up
    function onStart(state) {
    }

    // onStop() is called when your application is exiting
    function onStop(state) {
    }

    // Return the initial view of your application here
    function getInitialView() {
        view = new BleProfileTestView();
        Ble.setDelegate(new TestBleDelegate());
        return [ view, new BleProfileTestDelegate() ];
    }

}

Parents
  • @Brad.ConnectIQ - fantastic to see there is a fix for this now in 5.63 for VA4. Hopefully it is released soon!

    Couple of questions though:

    1. Will I need to recompile my apps in order for this to apply, or is it just about the new firmware being on the watch?
    2. Will this fix also get applied to the Venu? (I notice the Venu and Vivo 4 are both currently on 5.60 - so maybe the firmware is shared/similar?)
Comment
  • @Brad.ConnectIQ - fantastic to see there is a fix for this now in 5.63 for VA4. Hopefully it is released soon!

    Couple of questions though:

    1. Will I need to recompile my apps in order for this to apply, or is it just about the new firmware being on the watch?
    2. Will this fix also get applied to the Venu? (I notice the Venu and Vivo 4 are both currently on 5.60 - so maybe the firmware is shared/similar?)
Children