2

We have an application, which connects to Google Fit, and we obtain user sessions, such as sleep activity (activity = 72). We have this application running every day, for more than two years, with about 15.000 users, working seamlessly.

We discovered recently one user in our app, who has a Huawei Watch 2 Pro, connected to Google Fit. This user has sleep sessions on his mobile, but does not have these sessions in Google Fit API (in the sessions endpoint).

We have connected the same Googlefit account to a second mobile phone, so we could verify if the sessions were in the cloud or not, and this second mobile phone has been able to load all the sleep sessions; so we believe these sessions are in the cloud, but we can not see them as sleep sessions (through the sessions endpoint).

For further analysis, we have also inserted a manual sleep measurement, from the Google Fit app, and it does appear in the Google Fit API. So we think it has something to do about how the huawei app saves sleep sessions in Google Fit.

So we have tried to look where was Huawei saving data, if it was not in sleep sessions. We looked inside dataSources, raw:com.google.activity.segment:com.huawei.health: and then, dataset aggregate:

https://www.googleapis.com/fitness/v1/users/userId/dataset:aggregate

With a request body, and a range of dates that we know the user has a sleep session:

{
  "aggregateBy": [{
    "dataSourceId": "raw:com.google.activity.segment:com.huawei.health:",
    "dataTypeName": "com.google.activity.segment"
  }],
 
  "bucketByTime": { "durationMillis": 86400000 },
  "startTimeMillis": 1603753199000, //GMT: Monday, 26 October 2020 22:59:59
  "endTimeMillis": 1603782000000   //GMT: Tuesday, 27 October 2020 7:00:00
}

We obtain a series of points, which could be the sleep sessions, for example: Response:

{
    "bucket": [
        {
            "startTimeMillis": "1603753199000",
            "endTimeMillis": "1603782000000",
            "dataset": [
                {
                    "dataSourceId": "derived:com.google.activity.summary:com.google.android.gms:aggregated",
                    "point": [
                        {
                            "startTimeNanos": "1603753380000000000",  //GMT: Monday, 26 October 2020 23:03:00
                            "endTimeNanos": "1603780140000000000", //GMT: Tuesday, 27 October 2020 6:29:00
                            "dataTypeName": "com.google.activity.summary",
                            "originDataSourceId": "raw:com.google.activity.segment:com.huawei.health:",
                            "value": [
                                {
                                    "intVal": 109,
                                    "mapVal": []
                                },
                                {
                                    "intVal": 20160000,
                                    "mapVal": []
                                },
                                {
                                    "intVal": 336,
                                    "mapVal": []
                                }
                            ]
                        },
                        {
                            "startTimeNanos": "1603755240000000000", //GMT: Monday, 26 October 2020 23:34:00
                            "endTimeNanos": "1603779600000000000", //GMT: Tuesday, 27 October 2020 6:20:00
                            "dataTypeName": "com.google.activity.summary",
                            "originDataSourceId": "raw:com.google.activity.segment:com.huawei.health:",
                            "value": [
                                {
                                    "intVal": 110,
                                    "mapVal": []
                                },
                                {
                                    "intVal": 6600000,
                                    "mapVal": []
                                },
                                {
                                    "intVal": 110,
                                    "mapVal": []
                                }
                            ]
                        },
                        {
                            "startTimeNanos": "1603781520000000000", //GMT: Tuesday, 27 October 2020 6:52:00
                            "endTimeNanos": "1603781880000000000", GMT: Tuesday, 27 October 2020 6:58:00
                            "dataTypeName": "com.google.activity.summary",
                            "originDataSourceId": "raw:com.google.activity.segment:com.huawei.health:",
                            "value": [
                                {
                                    "intVal": 7,
                                    "mapVal": []
                                },
                                {
                                    "intVal": 240000,
                                    "mapVal": []
                                },
                                {
                                    "intVal": 4,
                                    "mapVal": []
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    ]
}

We think that these points could be the sleep sessions because:

  • The dataTypeName: "com.google.activity.segment" is the sleep session, and the id data source is huawei "raw: com.google.activity.segment: com.huawei.health"
  • The hours of the first two points are at night, in the example, from 23:03 pm to 6:20 am of the following day, and it is exactly a sleep measurement of the user in the Google Fit app.
  • If we add the large values of the first two points, we obtain as a result 26760000/1000*3600 = 7.43 = 7h26m, which is exactly the measurement that the user has for October 27 in Google Fit app

Then:

Could the sleep sessions be in a dataSource and not being collected in the sleep sessions? Can we differentiate somehow in the Google Fit app, that this is not a session, but a dataset? Why could it be that it is not being collected inside sleep sessions? Is it something from the Huawei app? How can we really know that these datasets are sleep sessions?

Sandra
  • 21
  • 2
  • I've not read your issue in great detail, but the fact your asking about sleep makes me wonder if it is related to recent changes to the way sleep segments are handled: this was communicated to existing developers by email, but the important details are described here also: https://developers.google.com/fit/improvements. – Andy Turner Nov 14 '20 at 13:55
  • Thanks for the reply. I'm afraid we've had this problem since June, so I don't think it has anything to do with the new changes on how sleep segments are handled. But this has given us an idea, we are going to try to connect that user with the new sleep permissions, maybe so we can collect the measurements – Sandra Nov 17 '20 at 12:55

1 Answers1

0

I collect sleep data from my Oppo Watch via Google Fitness API using Python.

I don't access the data using sessions, I only use datasets.

source = "derived:com.google.sleep.segment:com.google.android.gms:sleep_from_activity<-raw:com.google.activity.segment:com.heytap.wearable.health:stream_sleep"

startEnd = "%s-%s" % (START, END)

dataset = fitService().users().dataSources().datasets().get(userId='me', dataSourceId=source, datasetId=startEnd ).execute()

The response then looks like this (snippet):

"minStartTimeNs": "1607990400000000000",
    "maxEndTimeNs": "1608063421000000000",
    "dataSourceId": "derived:com.google.sleep.segment:com.google.android.gms:sleep_from_activity<-raw:com.google.activity.segment:com.heytap.wearable.health:stream_sleep",
    "point": [
        {
            "startTimeNanos": "1607992860000000000",
            "endTimeNanos": "1607994180000000000",
            "dataTypeName": "com.google.sleep.segment",
            "originDataSourceId": "raw:com.google.activity.segment:com.heytap.wearable.health:stream_sleep",
            "value": [
                {
                    "intVal": 4,
                    "mapVal": []
                }
            ],
            "modifiedTimeMillis": "1607996640613"
        },
        {
            "startTimeNanos": "1607994180000000000",
            "endTimeNanos": "1607994360000000000",
            "dataTypeName": "com.google.sleep.segment",
            "originDataSourceId": "raw:com.google.activity.segment:com.heytap.wearable.health:stream_sleep",
            "value": [
                {
                    "intVal": 5,
                    "mapVal": []
                }
            ],
            "modifiedTimeMillis": "1607996640613"
        },

The points contain segments including 'light sleep' (intVal 4) and 'deep sleep' (intVal) 5. I calculate how many light and deep segments there are and the start/end time for each one.

All segments retrieved using this method exactly match what is shown in the Google Fit app and the Oppo app (HeyTap Health). I have so far had no issues.

I am not sure if this helps, but I thought it best to mention that I do not use "sessions" at all.

Mr L
  • 470
  • 6
  • 16
  • Thank you very much for answering. In the end the data that we could not see in the session we have been able to collect with the details of the session, aggregate mode: https://developers.google.com/fit/scenarios/read-sleep-data (section 2) And, in order to read the details of the session, the user had to give authorization to the scope https://www.googleapis.com/auth/fitness.sleep.read of Google Fit Whose answer is like the one you show On the other hand, we cannot query using the dataSourceId because there can be many dataSource from all users. – Sandra Mar 18 '21 at 14:34