Is Sensor.getInfo() blocking? + sensor updates subscription pattern

In my application view (watch app, not a watch face) I want to show current altitude with changes as they happen.

I'm planning to initially call Sensor.getInfo() in onShow() method followed by Sensor.enableSensorEvents(callback) and then call Sensor.enableSensorEvents(null) in onHide():

hidden var _altitude as Float or Null;
function onShow() as Void {
    _altitude = Sensor.getInfo().altitude;
    Sensor.enableSensorEvents(method(:onSensorData));
}

function onHide() as Void {
    Sensor.enableSensorEvents(null);
}

function onSensorData(sensorInfo as Sensor.Info) as Void {
    _altitude = sensorInfo.altitude;
    WatchUi.requestUpdate();
}

function onUpdate(dc as Graphics.Dc) as Void {
    View.onUpdate(dc);

    if (_altitude != null) {
        _labelAltitude.setText(_altitude.format("%.0f"));
    } else {
        _labelAltitude.setText("N/A");
    }
}

A few questions:

  1. Is Sensor.getInfo() considered blocking or not? Does it always instantly return currently known values or would it block until watch receives the data? is it OK to call it in onShow() method?
  2. Do I need to call label.setText() in onUpdate() or I can call it any time (e.g. in onShow or onSensorData) and View.onUpdate(dc) will redraw the view with the newly set value?
  3. Should I call setText() before View.onUpdate(dc) or after?
  4. Do you have any other recommendations to my current approach to make it most fluent and computationally efficient (recommended practice)?
  • If something blocks in CIQ, it will have a callback function.  see makeWebRequest for example.  When you call Sensor.getInfo() it returns the current data. 

    f you are recording a fit, you can just get the altitude info in Activity.Info.  That will also update even if you aren't recording on devices with a baro (except the f5x).

    You also won't see info on devices that don't have a baro unless you enable GPS.  

  • Here is a very simple app that shows the basics of displaying the altitude (in meters) on a device with a baro, and updating every second.  Understand the baro needs to be calibrated on a regular basis, and that's easiest done by enabling GPS.

    Altitude.zip

  • Thank you. In your example, the timer probably needs to be started in onStart and stopped in onHide.

  • Nope.  The example shows just how I've done it for years.  No code at all in onShow() or onHide(). .  With the project, you can build a sideload and run it on any devices with a baro altimeter.

  • Since you use timer only to trigger redraw then you should use onShow()/onHide() to start/stop timer, not initialize().

    When your view goes off of the screen, there's nothing to redraw anymore, so working timer just continues to consume CPU time in background even when already other view on the screen.

    Also apps have a quota on timers (5 as I remember), so if you have more than 5 data screens in your app each screen implemented as a view with own working timer then your app will exhaust quota of timers and crash.

  • It's a max of 3 timer.  This was just a simple example I put together in a few minutes and wanted to keep things in one place

    With the one timer, if you push a second view (a menu2 for example), the timer will keep running, and that could be just what you want in a device app (again using menu2 as an example)

    Don't know if you've done a data field, but in a complex one, onUpdate is called every second, but only if the DF is visible, while compute is called every second, even if the DF isn't visible.

    onShow/onHide come into play if you have multiple views, and not so much when the app starts and exits..  When an app exits, all timers are stopped without you doing anything

    Have a look at the Timer sample in the SDK and maybe experiment a bit with it.

  • I see this is quite old post. But I actually found that Sensor.getInfo() takes about 90ms on Fenix 8. 

    I tried this:

            var startTime = System.getTimer();
            sensors = Sensor.getInfo();
            var elaspedMilliseconds = System.getTimer() - startTime;

    and the elapsedMilliseconds oscillated between 85 and 92 ms. I also assumed as per the documentation that it is just simple getter returning the current sensor data state, but it looks like it is waiting until the measurement is done ....

    I actually did not find any method how to read sensor data faster than this way. Registering callback using registerSensorDataListener() seems to be limited to 1 sec period.