# 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
            }
        ]
    }
}
```
