Page 1 of 1

Accessing health data

Posted: Wed Feb 17, 2021 8:13 am
by lubomir.moric
I am familiarising myself how to write a watch face for TicWatch Pro 3 GPS. I have working watch face and now I am trying to get some sensor data: Heart rate, SPO2, SDNN, Steps.
Getting steps is quite nicely described in development page, registering an observer to "content://com.mobvoi.ticwear.steps": https://developer.chumenwenwen.com/en/d ... l#doc/5/20.

Accessing other data is now for me only possible by subscribing a listener to a sensor. However, whenever such subscription exists, sensors continuously monitors that requested asset, which means continuous measurement of Heart rate, SPO2, SDNN, causing heavy battery drain.
I created a workaround: when data from sensor are received, I unsubscribe for next N minutes (e.g. 60 minutes) and only after that interval I subscribe again and measure fresh data.

However I do not like this approach, as I do my own measurements only for the purpose of watch faces.
I would prefer to be able to access data collected by TicHealth app or even sensor's "last readings" cache, as it is displayed using command "adb shell dumpsys sensorservice ".

Is there any other "content://" I can register to and get these data? Without a proper documentation, I can just guess, but no luck so far.

Re: Accessing health data

Posted: Wed Mar 10, 2021 1:32 am
by bryson
I want to know the same thing. Were you able to subscribe listeners to sensors for SPO2 and SDNN? I am unable to find documentation on getting even that far.

Re: Accessing health data

Posted: Thu Mar 11, 2021 5:38 am
by taylor.odishoo
I'm facing the same issue - battery life is draining way too quickly with continuous monitoring. It would be great if there was a feature to enable interval subscriptions.



I have been able to monitor the SP02 sensor via the following:

Code: Select all

private static final int TYPE_SP02 = 69640;
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
Sensor sp02Sensor = sensorManager.getDefaultSensor(TYPE_SP02);
sensorManager.registerListener(this, sp02Sensor, SensorManager.SENSOR_DELAY_NORMAL);
However I have noticed that the Ticwatch Pro 3 sometimes fails to record sensor oxygen sensor data... Still not sure what causes this but it has been mentioned in other threads.

I've also been successful in receiving SDNN events using code 69641, however I do not seem to get any actual data on this. Any help would be appreciated!

Re: Accessing health data

Posted: Thu Mar 11, 2021 8:27 am
by lubomir.moric
This is very brief "Stub" of the code, just to give an idea of Sensor Listeners. I tried to minimise the code, otherwise you need to implement more overriding methods and other code around, however this is not important for this example:

Code: Select all

// Check for codes and full list of sensors using "adb shell dumpsys sensorservice"
private const val BG_PPG_HEART = 69644
private const val BG_PPG_SPO2 = 69645
private const val BG_PPG_SDNN = 69646

inner class Engine : CanvasWatchFaceService.Engine(), SensorEventListener {
    ...
    private val mSensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
    private val sensorListener = SensorListener(this, mSensorManager)
    private val sensorEventProcessor = SensorEventProcessor(this, sensorListener)
    ...
    Sensor sdnnVal        // Here sensore values will be updated any time "onSensorChanged" is invoked by the Engine
    sensorListener.registerSensorListeners(BG_PPG_SDNN, sdnnVal)
    ...
    // This method is invoked automatically whenever new sensor data are available
    override fun onSensorChanged(event: SensorEvent) {
        val ticSensor = event.sensor.type
        sensorEventProcessor.processEvent(ticSensor, event)
    }
}

...

class SensorListener(
    private val engine: WatchFace.Engine,
    private val mSensorManager: SensorManager
) {
    private fun registerSensorListener(id: Int, sensorVal: Sensor) {
        ticSensor.sensor = mSensorManager.getDefaultSensor(id)
        ticSensor.registered = mSensorManager.registerListener(
            engine,
            sensorVal,
            SensorManager.SENSOR_DELAY_NORMAL,
            MAX_REPORT_LATENCY
        )
    }
}
Idea is, that SensorEventListener calls "onSensorChanged" whenever there is sensor data available for those sensors you registered using "mSensorManager.registerListener( ...". During registration you already provide "Sensor" object to be automatically and asynchronously filled with actual data.

Unfortunately this is good for some constantly tracking fitness app, because as long sensor is registered, it measures data. You need to unregister it to make it stop:

Code: Select all

mSensorManager.unregisterListener(engine, sensorVal)
For Watch this is not best approach, way better will be just reusing already existing and collected data from some API, which I don't know which to use and how.