OxygenSaturation SensorHistory always returns 0 on vivoactive 4

I am developing an app for Garmin vivoactive 4/4s/venu/fenix etc series that support PulseOx.

I was trying to implement the SensorHistory module to get the oxygen saturation history for the given period of time. On debugging in the simulator it works fine and returns correct numbers like 95-100%, but when I test it on a real device (in my case that is vivoactive 4) it always returns 0.

Can you please tell me why that is happening and how can I solve that?

Also, I found a similar issue on the developer forum. Here is a link: https://forums.garmin.com/developer/connect-iq/f/discussion/245288/possible-getoxygensaturationhistory-bug?ReplySortBy=CreatedDate&ReplySortOrder=Ascending. But there is no answer.

  • If you look though the bug report you linked, you'll see that SensorHistory.getOxygenSaturation() isn't returning things in the correct order on real devices.  It's always returned as oldest first, with newest last.

    So if you are looking at the first sample, you need to have a number of days of history or you won't have valid data.

  • I just need to get measurements for the last hour. The way it orders data is fine for me. The only problem that every element from SensorHistory on a real device is 0. Is there any way to solve that?

  • Do you have PulseOx turned on? And you need to be wearing the device and be fairly motionless at the time.

    Also, in history, samples for that are only saved every hour or so.  On some devices, there are 192 samples - every hour for 8 days.  Right now you need to walk the iterator and use the very last sample, but that will change when the order issue is fixed.

  • On a simulator, it works fine. On my vivoactive 4 I'm measuring PulseOx 24/7 and that data is present in Garmin Connect after synchronization. But iterator returns empty values all the time in my app.

    Can you please tell me what I'm doing wrong here? Or any possible solution?

    var arr = { "oxygen_values"=>new [0] };

    function getIterator() {

            if ( ( Toybox has :SensorHistory ) && ( Toybox.SensorHistory has :getOxygenSaturationHistory) ) {

                var getMethod = new Lang.Method( Toybox.SensorHistory, :getOxygenSaturationHistory);

                return getMethod.invoke( { :order=>0, :period=>10 } ); // Here I want to get last 10 measures.

            }

            return null;

        }

    function getSensorsData(){

    var gotValidData = false;

    if ( Toybox has :SensorHistory ) {

                var sensorIter = getIterator();           

                if( sensorIter != null ) {

                var sample = sensorIter.next();

                while( null != sample ) {

                if(sample != null && sample.data != null){

                gotValidData = true;

                        var temp_date = Gregorian.utcInfo(sample.when, Time.FORMAT_SHORT);

                        var temp_date_string = Lang.format("$1$-$2$-$3$T$4$:$5$:00.000Z", [

                        temp_date.year.format("%d"),

                            temp_date.month.format("%02d"),

                            temp_date.day.format("%02d"),

                            temp_date.hour.format("%02d"),

                            temp_date.min.format("%02d")

                        ]);

    if (sample.data > 40 && sample.data <= 100) {

      arr["oxygen_values"].add({

      "oxygen"=>sample.data.toNumber().toString(), 

      "oxygen_updated_at"=>temp_date_string

      }).toString();

    }

                    }

                  sample = sensorIter.next();

                }             

                }

            }

            if( gotValidData ) {

    return arr;

    }  else{

    return null;

    }

        }

  • Yes, it works in the sim, but on a real devices, the iterators are backwards and you see the oldest one first.  The newest is the very end.

  • Personally, I'm got using SensorHistory for O2 saturation until this bug is fixed.  Bug reports have been filed. See forums.garmin.com/.../toybox-sensorhistory-getoxygensaturationhistory-strange-samples

  • Thank you for the reply. 

    After a few ineffective tries to get SpO2 history I was thinking about another possible solution.

    Is there any way to manually sync Watch with Garmin connect using BLE or WiFi? (The same process as we do from the Garmin Connect app on smartphones to sync with watch data). After that I can receive data from Garmin Health API.

    In that case, I wouldn't need to use SensorHistory and Garmin would send it directrly to my server.