Simple Datafield crashes on edge device

Hi,

I designed a very simple datafield which works very well on my F6X pro. Nevertheless, the datafield is designed for the edge devices as well. A user complaint about a crash at the very beginning. He told me that the device has no Bluetooth connection yet and then the datafield crashes. If the BT connection is established, the datafield works as well stable. 

The only time I am asking for an info field is in this code area:

	function compute(info) {
    	if (info has :currentSpeed) { // The current speed in meters per second (mps).
        	if (info.currentSpeed != null) {
           		speedValue = info.currentSpeed;
        	}
    	}    	
    	//speedValue = null;
		if (speedValue == null) {
	        speedValue = "---";	
		} else {
			if (splitDecimalPlaces) {
				speedWithFraction = getSplitSpeed(speedValue);
			} else {
				speedValue = getSpeed(speedValue);
			}
		}
	}

Even if I decomment the speedValue = null line the datafield works in my sim. Is there any other means I have to do for edge devices?

  • Hi Travis, yep  the Datafield crashes in the getSpeed method. For me  the problem is fixed with this line:

    if (!(speedValue instanceof Toybox.Lang.Float)) {

    But if you need the real root cause I could rewrite the code again and ask the user for help  

  • Okay, after reading the posts above again, I see the issue... You are re-using the speedValue variable.

    hidden var speedValue;
    
    function initialize() {
        SimpleDataField.initialize();
        speedValue = null;
    }
    
    function compute(info) {
        // speedValue only gets set if info.currentSpeed is non-null
    	if (info has :currentSpeed) {
        	if (info.currentSpeed != null) {
           		speedValue = info.currentSpeed;
        	}
    	}
    	
    	// speedValue will be
    	//  - Float if info.currentSpeed is non-null
    	//  - null if info.currentSpeed is null and speedValue has never been set
    	//  - String if info.currentSpeed is null and speedValue has been set to
    	//      a String by the below code
    
    	if (speedValue == null) {
            speedValue = "---";	// <-- assign speedValue to a String
    	} else {
    		if (splitDecimalPlaces) {
    		    // what happens if speedValue is a String?
    			speedWithFraction = getSplitSpeed(speedValue);
    		} else {
    		    // what happens if speedValue is a String?
    			speedValue = getSpeed(speedValue); // <-- assign speedValue to a String?
    		}
    	}
    	
    	// ...
    }

    It looks to me like getSplitSpeed() and getSpeed() expect a Float parameter, which will happen if you give the value from info.currentSpeed. Unfortunately, you are passing in speedValue which will be a String after compute() has been called once.

    I think it might be best to re-organize your code a bit to avoid this entirely, the instanceof check will work, but it isn't really doing the right thing.

    hidden var speedValue;
    
    function initialize() {
        SimpleDataField.initialize();
        speedValue = null;
    }
    
    function compute(info) {
        var currentSpeed = null;
        
    	if (info has :currentSpeed) {
        	if (info.currentSpeed != null) {
           		currentSpeed = info.currentSpeed;
        	}
    	}
    
    	if (currentSpeedValue == null) {
            speedValue = "---";
    	} else {
    		if (splitDecimalPlaces) {
    			speedWithFraction = getSplitSpeed(currentSpeedValue);
    		} else {
    			speedValue = getSpeed(currentSpeedValue);
    		}
    	}
    	
    	// ...
    }

  • Damn, you nailed it down. Now I can see it clearly what's happening and my code is anything else but solid.

    Thanks Travis for pointing me in the right direction.