cyberjunky / python-garminconnect

Python 3 API wrapper for Garmin Connect to get activity statistics
MIT License
964 stars 149 forks source link

Add, get, and delete weigh-ins #132

Closed dpfrakes closed 1 year ago

dpfrakes commented 1 year ago

@cyberjunky hope you don't mind but I saw https://github.com/cyberjunky/python-garminconnect/issues/130 and figured I'd give it a shot!

I didn't add these to your example script (running out of keys!), but I've documented sample usage here. Weight is returned by Garmin API in grams (g).

New methods

>>> api.add_weigh_in(152, 'lbs', '2023-03-30')
<Response [204]>
>>> api.add_weigh_in(175, 'lbs', '2023-03-31')
<Response [204]>
>>> api.add_weigh_in(200, 'lbs')
<Response [204]>
>>> api.add_weigh_in(80)
<Response [204]>
>>> api.get_weigh_ins('2023-03-30', '2023-04-01')
{'dailyWeightSummaries': [{'summaryDate': '2023-03-31', 'numOfWeightEntries': 3, 'minWeight': 79378.66475, 'maxWeight': 90718.474, 'latestWeight': {'samplePk': 1680318229590, 'date': 1680303829053, 'calendarDate': '2023-03-31', 'weight': 80000.0, 'bmi': None, 'bodyFat': None, 'bodyWater': None, 'boneMass': None, 'muscleMass': None, 'physiqueRating': None, 'visceralFat': None, 'metabolicAge': None, 'sourceType': 'MANUAL', 'timestampGMT': 1680318229053, 'weightDelta': 11067.653828000002}, 'allWeightMetrics': [{'samplePk': 1680318229590, 'date': 1680303829053, 'calendarDate': '2023-03-31', 'weight': 80000.0, 'bmi': None, 'bodyFat': None, 'bodyWater': None, 'boneMass': None, 'muscleMass': None, 'physiqueRating': None, 'visceralFat': None, 'metabolicAge': None, 'sourceType': 'MANUAL', 'timestampGMT': 1680318229053, 'weightDelta': -10704.779931999998}, {'samplePk': 1680318224735, 'date': 1680303824066, 'calendarDate': '2023-03-31', 'weight': 90718.474, 'bmi': None, 'bodyFat': None, 'bodyWater': None, 'boneMass': None, 'muscleMass': None, 'physiqueRating': None, 'visceralFat': None, 'metabolicAge': None, 'sourceType': 'MANUAL', 'timestampGMT': 1680318224066, 'weightDelta': 11339.80925}, {'samplePk': 1680318219255, 'date': 1680220800000, 'calendarDate': '2023-03-31', 'weight': 79378.66475, 'bmi': None, 'bodyFat': None, 'bodyWater': None, 'boneMass': None, 'muscleMass': None, 'physiqueRating': None, 'visceralFat': None, 'metabolicAge': None, 'sourceType': 'MANUAL', 'timestampGMT': 1680235200000, 'weightDelta': 10432.62451}]}, {'summaryDate': '2023-03-30', 'numOfWeightEntries': 1, 'minWeight': 68946.04024, 'maxWeight': 68946.04024, 'latestWeight': {'samplePk': 1680318212328, 'date': 1680134400000, 'calendarDate': '2023-03-30', 'weight': 68946.04024, 'bmi': None, 'bodyFat': None, 'bodyWater': None, 'boneMass': None, 'muscleMass': None, 'physiqueRating': None, 'visceralFat': None, 'metabolicAge': None, 'sourceType': 'MANUAL', 'timestampGMT': 1680148800000, 'weightDelta': 3175.1465900000003}, 'allWeightMetrics': [{'samplePk': 1680318212328, 'date': 1680134400000, 'calendarDate': '2023-03-30', 'weight': 68946.04024, 'bmi': None, 'bodyFat': None, 'bodyWater': None, 'boneMass': None, 'muscleMass': None, 'physiqueRating': None, 'visceralFat': None, 'metabolicAge': None, 'sourceType': 'MANUAL', 'timestampGMT': 1680148800000, 'weightDelta': 3175.1465900000003}]}], 'totalAverage': {'from': 1680134400000, 'until': 1680393599999, 'weight': 74473.02012, 'bmi': None, 'bodyFat': None, 'bodyWater': None, 'boneMass': None, 'muscleMass': None, 'physiqueRating': None, 'visceralFat': None, 'metabolicAge': None}, 'previousDateWeight': {'samplePk': 1679337307105, 'date': 1679322900000, 'calendarDate': '2023-03-20', 'weight': 65770.89365, 'bmi': None, 'bodyFat': None, 'bodyWater': None, 'boneMass': None, 'muscleMass': None, 'physiqueRating': None, 'visceralFat': None, 'metabolicAge': None, 'sourceType': 'MANUAL', 'timestampGMT': 1679337300000, 'weightDelta': None}, 'nextDateWeight': {'samplePk': None, 'date': None, 'calendarDate': None, 'weight': None, 'bmi': None, 'bodyFat': None, 'bodyWater': None, 'boneMass': None, 'muscleMass': None, 'physiqueRating': None, 'visceralFat': None, 'metabolicAge': None, 'sourceType': None, 'timestampGMT': None, 'weightDelta': None}}
>>> api.delete_weigh_ins('2023-03-31')
Multiple weigh-ins found for 2023-03-31
Set delete_all to True to delete all 3 weigh-ins
>>> api.delete_weigh_ins('2023-03-31', True)
Multiple weigh-ins found for 2023-03-31
3
>>> api.get_weigh_ins('2023-03-30', '2023-04-01')
{'dailyWeightSummaries': [{'summaryDate': '2023-03-30', 'numOfWeightEntries': 1, 'minWeight': 68946.04024, 'maxWeight': 68946.04024, 'latestWeight': {'samplePk': 1680318212328, 'date': 1680134400000, 'calendarDate': '2023-03-30', 'weight': 68946.04024, 'bmi': None, 'bodyFat': None, 'bodyWater': None, 'boneMass': None, 'muscleMass': None, 'physiqueRating': None, 'visceralFat': None, 'metabolicAge': None, 'sourceType': 'MANUAL', 'timestampGMT': 1680148800000, 'weightDelta': 3175.1465900000003}, 'allWeightMetrics': [{'samplePk': 1680318212328, 'date': 1680134400000, 'calendarDate': '2023-03-30', 'weight': 68946.04024, 'bmi': None, 'bodyFat': None, 'bodyWater': None, 'boneMass': None, 'muscleMass': None, 'physiqueRating': None, 'visceralFat': None, 'metabolicAge': None, 'sourceType': 'MANUAL', 'timestampGMT': 1680148800000, 'weightDelta': 3175.1465900000003}]}], 'totalAverage': {'from': 1680134400000, 'until': 1680393599999, 'weight': 68946.04024, 'bmi': None, 'bodyFat': None, 'bodyWater': None, 'boneMass': None, 'muscleMass': None, 'physiqueRating': None, 'visceralFat': None, 'metabolicAge': None}, 'previousDateWeight': {'samplePk': 1679337307105, 'date': 1679322900000, 'calendarDate': '2023-03-20', 'weight': 65770.89365, 'bmi': None, 'bodyFat': None, 'bodyWater': None, 'boneMass': None, 'muscleMass': None, 'physiqueRating': None, 'visceralFat': None, 'metabolicAge': None, 'sourceType': 'MANUAL', 'timestampGMT': 1679337300000, 'weightDelta': None}, 'nextDateWeight': {'samplePk': None, 'date': None, 'calendarDate': None, 'weight': None, 'bmi': None, 'bodyFat': None, 'bodyWater': None, 'boneMass': None, 'muscleMass': None, 'physiqueRating': None, 'visceralFat': None, 'metabolicAge': None, 'sourceType': None, 'timestampGMT': None, 'weightDelta': None}}
>>> api.get_daily_weigh_ins('2023-03-30')
{'startDate': '2023-03-30', 'endDate': '2023-03-30', 'dateWeightList': [{'samplePk': 1680318212328, 'date': 1680134400000, 'calendarDate': '2023-03-30', 'weight': 68946.04024, 'bmi': None, 'bodyFat': None, 'bodyWater': None, 'boneMass': None, 'muscleMass': None, 'physiqueRating': None, 'visceralFat': None, 'metabolicAge': None, 'sourceType': 'MANUAL', 'timestampGMT': 1680148800000, 'weightDelta': 3175.1465900000003}], 'totalAverage': {'from': 1680134400000, 'until': 1680220799999, 'weight': 68946.04024, 'bmi': None, 'bodyFat': None, 'bodyWater': None, 'boneMass': None, 'muscleMass': None, 'physiqueRating': None, 'visceralFat': None, 'metabolicAge': None}}
cyberjunky commented 1 year ago

Thanks man, merging it now, well solving the conflicts, since I always merge in the wrong order lol, and you forgot all about the free upper characters in example.py menu B-Z ;-)

cyberjunky commented 1 year ago

I have all working, except for the delete_weigh_ins, it gives an error, seems the POST overrride with DELETE doesn't work, we don't use our own request code any more, need some investigation (option D in example.py) and maybe a garth delete method...

Executing: Delete all weigh-ins for '2023-09-14'

WARNING:garminconnect:Multiple weigh-ins found for 2023-09-14
Traceback (most recent call last):
  File "/home/ron/.local/lib/python3.11/site-packages/garth/http.py", line 123, in request
    self.last_resp.raise_for_status()
  File "/usr/lib/python3/dist-packages/requests/models.py", line 1021, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 405 Client Error: Method Not Allowed for url: https://connectapi.garmin.com/weight-service/weight/2023-09-14/byversion/1694695073182

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/ron/development/python-garminconnect/./example.py", line 628, in <module>
    switch(api, option)
  File "/home/ron/development/python-garminconnect/./example.py", line 575, in switch
    api.delete_weigh_ins(today.isoformat(), delete_all=True)
  File "/home/ron/development/python-garminconnect/garminconnect/__init__.py", line 327, in delete_weigh_ins
    self.delete_weigh_in(w['samplePk'], cdate)
  File "/home/ron/development/python-garminconnect/garminconnect/__init__.py", line 306, in delete_weigh_in
    return self.garth.post(
           ^^^^^^^^^^^^^^^^
  File "/home/ron/.local/lib/python3.11/site-packages/garth/http.py", line 135, in post
    return self.request("POST", *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ron/.local/lib/python3.11/site-packages/garth/http.py", line 125, in request
    raise GarthHTTPError(
garth.exc.GarthHTTPError: Error in request: 405 Client Error: Method Not Allowed for url: https://connectapi.garmin.com/weight-service/weight/2023-09-14/byversion/1694695073182
matin commented 1 year ago

Here's how you perform a DELETE using Garth:

garth.request(
    "DELETE",
    "connectapi",
    path,
    api=True,
)

A correct response will be of type requests.Response with status 204 No Content.

cyberjunky commented 1 year ago
garth.request(
    "DELETE",
    "connectapi",
    path,
    api=True,
)

Yes this works, thanks a lot again!