type assignment works in simulator, crashes on watch, need advice

I'm developing a relatively simple app, sideloading for my own use only.

I'm getting a crash caused by a type mismatch when I try to do a text format to display a number on the watch face.

I'm getting temperature information from Sensor.getInfo(), which is a floating point value.

If I just assign the local tempC variable a value like 10.0, then it works, but when I use the following code to do the assignment with the sensor info it works in the simulation, but crashes on the watch.

 info = Sensor.getInfo();
 tempC = info.temperature;

string = Lang.format("$1$", [tempC.format("%5.1f")]);

the debug file error says "unexpected type error" in the string = statement above.

Its driving me crazy because I had a similar app running normally before, but accidentally overwrote it on the watch and can't figure out where I stored the source files in the eclipse directory to see how I did it the first time.

its a Fenix 6 watch, thanks for any help.

  • On some devices, and I think the f6 is one of them, the temperature in Sensor will be null if there isn't a Tempe sensor paired/connected.

    Add a null check on the value and you may want to look at using  SensorHistory.getTemperatureHistory)_ or Weather.getCurrentCondiditions()

  • thanks Jim, you're right, its returning null on the watch.

    I tried getTemperatureHistory and that didn't work.  Garmin claims it applies to Fenix 5, not 6.

    I know I've reported the temperature on an app before, so there has to be a way.

  • I tried again with getTemperatureHistory and the runtime screen displays the following:

    info Obj : 154

    info Obj: 155

    info Obj: 155

    I'm using "info" as the target for the getTemperatureHistory call, but I don't know what the 154/155 means.  I tried using it as an array index and that didn't work, it errored out with "expected symbol, given number".

    Now I'm getting a deja-vu that I may have asked you this a couple years ago when I got the first one working.

  • If you change your type checking level to informative [2] or strict [3]), the compiler will give you warning or error for this kind of problem - trying to inappropriately access a field/function [format] on a value [tempC] that might be null. The default type checking level is gradual [1].

  • I tried again with getTemperatureHistory and the runtime screen displays the following:

    info Obj : 154

    info Obj: 155

    info Obj: 155

    I'm using "info" as the target for the getTemperatureHistory call, but I don't know what the 154/155 means.  I tried using it as an array index and that didn't work, it errored out with "expected symbol, given number".

    It means that you're trying to print out an object (like an instance of the Toybox.SensorHistory.SensorSample class), rather than a "primitive" type like Number, Float, Long, Double, String, or Null, or a container like Array / Dictionary.

    The "primitive" types are automatically converted to useful strings when you print them, but in general, other objects are not. 

    I'm going to guess that your code looks something like this:

    If so, what you need to do is to print out the *data* from the SensorSample, which is a Float, Number, or Null, as per the docs

    btw it would really help if you showed us your actual code instead of saying vague stuff like "I tried again with getTemperatureHistory" and "I'm using "info" as the target for the getTemperatureHistory call"

    People who read that literally have to guess what your code is.

  • Its driving me crazy because I had a similar app running normally before, but accidentally overwrote it on the watch and can't figure out where I stored the source files in the eclipse directory to see how I did it the first time.
    Now I'm getting a deja-vu that I may have asked you this a couple years ago when I got the first one working.

    This is why source control is useful even for personal projects.

    If you don't want to use github, you can always set up your own local git server. It would be a decent learning experience imo.

  • thanks for the help, that solved my issue.

  • I remember now that even in the simulator the temperature info request originally returned null.

    I'm familiar with that happening before in testing, and I've used the pulldown "Simulation/Fit Data/SimulateData" from the device simulator window to generate debug data in the past.  So I did that here. In previous projects I was fetching data from GetActivityInfo() rather than Sensor.GetInfo().  I'd get null data until turning on "simulate data" with the activity info as well, but when I put the code on the watch it found the data OK.

    I don't write much code on the watch, so I learn something new every time.  

    So now I'm a bit confused about the Fit Data simulation feature.  Will the watch throw null on any Sensor.GetInfo requests, but not GetActivityInfo() requests?  Its not obvious which data needs to be simulated on Eclipse to debug code, but will work OK on the watch itself.  Are there any guidelines on how to know which data is readily available on the watch, and which data needs to be fetched from sensor history or any other repository? 

    thanks again.

  • In this case when you simulate data, that includes Tempe data which is why you were seeing temperature in the sim.

    With things in Activity.Info and Sensor.Info you want to include null checks.

  • Will the watch throw null on any Sensor.GetInfo requests, but not GetActivityInfo() requests? 

    In general [*], you don't have to worry about how the simulator and watch behave with regard to returning nulls as long as you either:

    - set type checking to informative or strict as mentioned above. The compiler knows whether a given API function can return null, and if it can, then it will prevent you from writing code like you posted in the OP which may inappropriately access a field on a null value

    and/or

    - look at the type info in relevant API documentation and follow what it says. It's the same as using informative/strict type checking, except it's a manual process

    The compiler type definitions / type info in API documentation represent a contract where Connect IQ promises you that if you call a certain function, you are guaranteed to get a return value of a given type or types. If the watch or sim break that contract, that's a bug on Garmin's end and technically not a problem with your app.

    In other words, the API documentation should have the answer to every question of yours which looks like "Does this API function return null?" or "Can this API field have a null value?" You don't have to try for yourself or ask anybody else, unless there's a problem with the docs [*].

    [1/2]