compute return value format

Hi
Got a question because I've got stack (I am still learning :). I am working on some simple data field app and trying to return string (from "function compute(info)") that consists of:

- time (based on calculated value)
- some other string

I have written such a code for trying:
function compute(info) {
var options = { :seconds => (info.elapsedTime / 1000) };
return Time.Gregorian.duration( options );
}



and it works perfectly fine, e.g. for info.elapsedTime = 5000ms I get "0:05" on both simulator and watch (FR230)
now I wanted to add something to output like some text, e.g. "time 0:05" and tried this:

function compute(info) {
var options = { :seconds => (info.elapsedTime / 1000) };
return "time" + Time.Gregorian.duration( options );
}


but got something like this: "time Obj: 30" instead expected "time x:xx"
I expect this is something with casting but cannot find solution.

Would you please give me a hand?
  • Former Member
    Former Member over 9 years ago
    Looking at the code, it should be working. What happens when you add toString() to the end of duration value?

    "time" + Time.Gregorian.duration( options ).toString()

    UPDATE: Nevermind, I'm wrong. It seems Duration doesn't have a nice toString method anyway.

    Where do you use this function value? It seems whatever uses it, converts it from Duration.
  • Ok, first thing to note is that you want to check info.elapsedTime for null before you use it (as with many things in Activity.info it will be null before recording starts).

    Also, I'd just skip the whole duration thing, as it's easy to just turn elapsedTime into a string.

    Here's an example of the call, as well as the helper function I use. (you could make it smarter to not include the hours if the hour is 0)
    function compute(info) {
    var time="--";
    if(info.elapsedTime!=null) {
    time=toHMS(info.elapsedTime/1000);
    }
    return "Time: "+time;
    }



    function toHMS(secs) {
    var hr = secs/3600;
    var min = (secs-(hr*3600))/60;
    var sec = secs%60;
    return hr.format("%02d")+":"+min.format("%02d")+":"+sec.format("%02d");
    }
  • Former Member
    Former Member over 9 years ago
    I think you might need value()
    return "time" + Time.Gregorian.duration( options ).value();
  • Ok so yes I've tried all of these things:

    - .value() gives me e.g. "time 70" instead of expected format of "time 1:10"
    - yes I make sure it is not null at the beginning, just wanted to make it simplier
    - .toString() as expected is also not working "time Obj: 30"
    - I could use toHMS but I was thinking if there is already predefined function to do so why not to use it -it should work right?
  • The problem is that the framework (specifically Ui.SimpleDataField) is formatting the result according to the type of the result. If you return a Time.Duration it will be formatted appropriately, but if you return a Lang.String it will be formatted as a string.

    If you want to display a format that isn't provided automatically based on the return type, you need to build up the string that you want to display (using the technique shown above by Jim), and then return that.

    Travis
  • got it!
    thank you all for exhaustive explanation :)
  • Former Member
    Former Member over 9 years ago
    got it!
    thank you all for exhaustive explanation :)

    Hi, I have a similar problem:
    This code works fine:
    function compute(info) {
    var calc = info.altitude;
    return calc;
    }

    But this one:
    function compute(info) {
    var calc = info.altitude * 2;
    return calc;
    }

    Give me this error at compilation:
    Failed invoking <symbol>
    UnexpectedTypeException: Expected Number/Float/Long/Double, given null/Number
    compute in C:\Users\Jlst\worksEclipse\PendienteTotal\source\PendienteTotalView.mc:20
    Unhandled Exception


    Any suggestion? Thanks.
  • Former Member
    Former Member over 9 years ago
    Hi, I have a similar problem:
    This code works fine:
    function compute(info) {
    var calc = info.altitude;
    return calc;
    }

    But this one:
    function compute(info) {
    var calc = info.altitude * 2;
    return calc;
    }

    Give me this error at compilation:
    Failed invoking <symbol>
    UnexpectedTypeException: Expected Number/Float/Long/Double, given null/Number
    compute in C:\Users\Jlst\worksEclipse\PendienteTotal\source\PendienteTotalView.mc:20
    Unhandled Exception


    Any suggestion? Thanks.


    I have reinstalled SDK (the last one), and the second version works fine also, but now I have another problem:
    if I use info.altitude or info.elapsedTime it works fine, but when I try with info.totalAscent or info.elapsedDistance , I receive this messsage:
    Failed invoking <symbol>
    UnexpectedTypeException: Expected Number/Float/Long/Double, given null/Number
    compute in C:\Users\Jlst\worksEclipse\PendienteTotal\source\PendienteTotalView.mc:17
    Unhandled Exception
  • Former Member
    Former Member over 9 years ago
    OK, so you probably need to know what null means. It means a value is missing, and in some cases this is ok and you need to handle such cases.

    If you check documentation for Sensor.Info, it says:
    The Sensor.Info class contains all information necessary for the Sensor. It can be passed on the update or it can be retrieved on demand. The fields in this class may return null so you should null check a value before using it.


    This means info.* elements might have null values, so first you need to check if it is null or not (you can't do null * 2, i.e nothing*2)

    For a lazy approach, you can use ternary operator to have the check on one line (format is condition? then : else)

    var calc = info.altitude == null? 0 : info.altitude * 2;

    But in this case you set calc = 0, which is not what you might want (i.e if calculation on altitude is 0*2, you'd get same result), so use it however you want.
  • Former Member
    Former Member over 9 years ago
    OK, so you probably need to know what null means. It means a value is missing, and in some cases this is ok and you need to handle such cases.

    If you check documentation for Sensor.Info, it says:


    This means info.* elements might have null values, so first you need to check if it is null or not (you can't do null * 2, i.e nothing*2)

    For a lazy approach, you can use ternary operator to have the check on one line (format is condition? then : else)

    var calc = info.altitude == null? 0 : info.altitude * 2;

    But in this case you set calc = 0, which is not what you might want (i.e if calculation on altitude is 0*2, you'd get same result), so use it however you want.


    Yes, you're right . At last I solved with:

    function compute(info) {
    var trash = "0";
    if (info.totalAscent != null && info.elapsedDistance != null)
    {
    return info.totalAscent * 100 / info.elapsedDistance ;
    }
    else
    {
    return trash;
    }
    }