236 lines
7.6 KiB
Markdown
236 lines
7.6 KiB
Markdown
# Withings
|
|
|
|
This module provides interfaces used to communicate with the Withings Public API.
|
|
|
|
## Smart Devices Used
|
|
|
|
We use the following devices for vitals data measurement:
|
|
|
|
* [Withings Scanwatch](https://www.withings.com/de/en/scanwatch)
|
|
* Heart Rate, SPO2
|
|
* [Withings Thermo](https://www.withings.com/de/en/thermo)
|
|
* Body Surface Temperature
|
|
* [WIthings BPM Core](https://www.withings.com/de/en/bpm-core)
|
|
* Blood Pressure
|
|
|
|
## API Access
|
|
|
|
Data is gathered by taking measurements using the devices, either actively (BP sleeve, thermometer) or passively (smartwatch).
|
|
The devices are connected to the Withings mobile app.
|
|
The mobile app then regularly pushes gathered data to the Withings cloud.
|
|
|
|
The Withings Dev Free plan allows for 120 API requests per minute.
|
|
Access to vitals data is available through the [Withings API](https://developer.withings.com/).
|
|
|
|
A detailed [API integration guide](https://developer.withings.com/developer-guide/v3/integration-guide/public-health-data-api/public-health-data-api-overview/),
|
|
as well as an [API reference guide](https://developer.withings.com/api-reference) are available online.
|
|
|
|
### Token expiry
|
|
|
|
When the access token expires, HTTP status `200 OK` is returned, but the response body is as follows:
|
|
|
|
```json
|
|
{
|
|
"status": 401,
|
|
"body": {},
|
|
"error": "XRequestID: Not provided invalid_token: The access token provided is invalid"
|
|
}
|
|
```
|
|
|
|
### Fetching health data
|
|
|
|
Health records can be fetched via GET request as follows:
|
|
|
|
```http
|
|
https://wbsapi.withings.net/measure?action=getmeas&meastypes=9,10,54,71,11
|
|
```
|
|
|
|
The type of vitals measurement is mapped as follows:
|
|
|
|
| Code | Type | Unit |
|
|
|------|--------------------------|------|
|
|
| 9 | Diastolic Blood Pressure | mmHg |
|
|
| 10 | Systolic Blood Pressure | mmHg |
|
|
| 11 | Heart Rate | bpm |
|
|
| 54 | SP02 | % |
|
|
| 71 | Body Temperature | °C |
|
|
|
|
Note the `unit`-field in the response.
|
|
For body temperature, the `unit`-field has the value `-3`.
|
|
This means that to get the body temperature in °C, you must multiply the `value` by `10^(-3)`.
|
|
|
|
The time of measurement can be parsed from the `measuregrps`'s `date` field.
|
|
|
|
A successful response looks like so:
|
|
|
|
```json
|
|
{
|
|
"status": 0,
|
|
"body": {
|
|
"updatetime": 1690491663,
|
|
"timezone": "Europe/Berlin",
|
|
"measuregrps": [
|
|
{
|
|
"grpid": 4716596696,
|
|
"attrib": 0,
|
|
"date": 1690491576,
|
|
"created": 1690491663,
|
|
"modified": 1690491663,
|
|
"category": 1,
|
|
"deviceid": "c405eb8e0e053f6601e151c7e43c04e29aad6956",
|
|
"hash_deviceid": "c405eb8e0e053f6601e151c7e43c04e29aad6956",
|
|
"measures": [
|
|
{
|
|
"value": 89,
|
|
"type": 9,
|
|
"unit": 0,
|
|
"algo": 0,
|
|
"fm": 3
|
|
},
|
|
{
|
|
"value": 109,
|
|
"type": 10,
|
|
"unit": 0,
|
|
"algo": 0,
|
|
"fm": 3
|
|
},
|
|
{
|
|
"value": 88,
|
|
"type": 11,
|
|
"unit": 0,
|
|
"algo": 0,
|
|
"fm": 3
|
|
}
|
|
],
|
|
"modelid": 44,
|
|
"model": "BPM Core",
|
|
"comment": null
|
|
},
|
|
{
|
|
"grpid": 4716596681,
|
|
"attrib": 0,
|
|
"date": 1690491236,
|
|
"created": 1690491662,
|
|
"modified": 1690491662,
|
|
"category": 1,
|
|
"deviceid": "c405eb8e0e053f6601e151c7e43c04e29aad6956",
|
|
"hash_deviceid": "c405eb8e0e053f6601e151c7e43c04e29aad6956",
|
|
"measures": [
|
|
{
|
|
"value": 65,
|
|
"type": 9,
|
|
"unit": 0,
|
|
"algo": 0,
|
|
"fm": 3
|
|
},
|
|
{
|
|
"value": 92,
|
|
"type": 10,
|
|
"unit": 0,
|
|
"algo": 0,
|
|
"fm": 3
|
|
},
|
|
{
|
|
"value": 88,
|
|
"type": 11,
|
|
"unit": 0,
|
|
"algo": 0,
|
|
"fm": 3
|
|
}
|
|
],
|
|
"modelid": 44,
|
|
"model": "BPM Core",
|
|
"comment": null
|
|
},
|
|
{
|
|
"grpid": 4712963495,
|
|
"attrib": 0,
|
|
"date": 1690375238,
|
|
"created": 1690375243,
|
|
"modified": 1690375243,
|
|
"category": 1,
|
|
"deviceid": "dbf7f61809d5fb350a16a50f6af6e826f0746082",
|
|
"hash_deviceid": "dbf7f61809d5fb350a16a50f6af6e826f0746082",
|
|
"measures": [
|
|
{
|
|
"value": 99,
|
|
"type": 54,
|
|
"unit": 0,
|
|
"algo": 33619971,
|
|
"fm": 3,
|
|
"apppfmid": 9,
|
|
"appliver": 2741,
|
|
"algo_params": {
|
|
"1": 0,
|
|
"2": 15
|
|
}
|
|
}
|
|
],
|
|
"modelid": null,
|
|
"model": null,
|
|
"comment": null,
|
|
"is_inconclusive": false
|
|
},
|
|
{
|
|
"grpid": 4712927310,
|
|
"attrib": 1,
|
|
"date": 1690374434,
|
|
"created": 1690374456,
|
|
"modified": 1690374486,
|
|
"category": 1,
|
|
"deviceid": "1d453daf947378fac40677e7a085eea73750b061",
|
|
"hash_deviceid": "1d453daf947378fac40677e7a085eea73750b061",
|
|
"measures": [
|
|
{
|
|
"value": 37370,
|
|
"type": 71,
|
|
"unit": -3,
|
|
"algo": 0,
|
|
"fm": 0
|
|
}
|
|
],
|
|
"modelid": null,
|
|
"model": null,
|
|
"comment": null
|
|
},
|
|
{
|
|
"grpid": 4712911433,
|
|
"attrib": 0,
|
|
"date": 1690373994,
|
|
"created": 1690374078,
|
|
"modified": 1690374078,
|
|
"category": 1,
|
|
"deviceid": "c405eb8e0e053f6601e151c7e43c04e29aad6956",
|
|
"hash_deviceid": "c405eb8e0e053f6601e151c7e43c04e29aad6956",
|
|
"measures": [
|
|
{
|
|
"value": 88,
|
|
"type": 9,
|
|
"unit": 0,
|
|
"algo": 0,
|
|
"fm": 3
|
|
},
|
|
{
|
|
"value": 124,
|
|
"type": 10,
|
|
"unit": 0,
|
|
"algo": 0,
|
|
"fm": 3
|
|
},
|
|
{
|
|
"value": 70,
|
|
"type": 11,
|
|
"unit": 0,
|
|
"algo": 0,
|
|
"fm": 3
|
|
}
|
|
],
|
|
"modelid": null,
|
|
"model": null,
|
|
"comment": null
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|