matin / garth Goto Github PK
View Code? Open in Web Editor NEWGarmin SSO auth + Connect Python client
License: MIT License
Garmin SSO auth + Connect Python client
License: MIT License
Thank you, @matin for your work on the this lib. I used your code as a basis for refactoring the garmin-connect
which is a typescript lib for garmin connect Pythe1337N/garmin-connect#56
When the account has a phone number, the library works fine. However, if the account doesn't have a phone number, the POST request during the sign-in step returns an HTML page with the title "Update Phone Number", which causes the login to fail. If everything goes well, the title should be "Success".
Does anyone know how to add a phone number to a Garmin account? I tried adding a phone number on the MFA page, but I still can't see the phone number on the https://www.garmin.com/en-US/account/profile/ page.
https://www.garmin.com/en-US/account/profile/
They are useful to interact with other services, i.e. workout-service among others
In the https://github.com/matin/garth#attempt-to-resume-session section of the readme, this line seems to be incorrect. The client part is not needed:
garth.client.username
I want to implement -a much needed and requested- MFA functionality to my Home-Assistant integration home-assistant-garmin_connect
Garth handles this perfectly from cli/python-garminconnect's example.py code but for this to work from GUI code I think I need some small changes to or extra methods added to garth to handle MFA.
I think about this approach (by looking at the current code briefly due to time shortage) :
What do you think? If you have suggestions or a better approach (which you often have), please let me know.
While Garth will support some endpoints natively, it's impractical and slow to add all endpoints.
The faster method is to create a wiki with all known endpoints. The most popular can then be added directly into the library. Others can simply use garth.connectapi(path)
.
Hi nice day!
Looks the lib not working for China domain anymore..
I have tested with 2 CN accounts, even tried reset the password.
All no luck TT
Thanks for your repo~
For some repos like https://github.com/yihong0618/running_page
we use GitHub Actions secret to daily sync the data, so maybe we can make this token something like base64
it to a string, and save it in the secret, we can load them from method like garth.resume_from_string(str)
I can open a PR to support it
Thank you for writing and maintaining Garth!
I just wanted to let you know that - unsurprisingly - Garmin does not allow uploading structured workout files to the upload service. It seems to be only intended for Activities.
I created a custom structured workout FIT file, exactly like the cookbook example from the FIT sdk, so a workout for a 10h endurance ride in zone 2, saved as test.FIT
.
When I use
with open("test.FIT", "rb") as f:
uploaded = garth.client.upload(f)
It confronts me with this error message:
Traceback (most recent call last):
File "C:\Users\joskw\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\garth\http.py", line 127, in request
self.last_resp.raise_for_status()
File "C:\Users\joskw\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\requests\models.py", line 1021, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 406 Client Error: Not Acceptable for url: https://connectapi.garmin.com/upload-service/upload
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "c:\Users\joskw\GitNoOneDrive\FIT-Garth\try-garth.py", line 33, in <module>
uploaded = garth.client.upload(f)
File "C:\Users\joskw\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\garth\http.py", line 173, in upload
resp = self.post(
File "C:\Users\joskw\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\garth\http.py", line 139, in post
return self.request("POST", *args, **kwargs)
File "C:\Users\joskw\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\garth\http.py", line 129, in request
raise GarthHTTPError(
garth.exc.GarthHTTPError: Error in request: 406 Client Error: Not Acceptable for url: https://connectapi.garmin.com/upload-service/upload
I know there is no way for you to fix this. I just wanted to suggest that it would be helpful for others to mention this limitation in the documentation here: https://github.com/matin/garth#upload
MacOS Sonoma 14.2.1, using latest python 3.12.1
make install looks good all the way until the step for numpy 1.24.4, that fails and then pandas cannot install:
ERRORS:
add numpy failed:
Traceback (most recent call last):
File "/opt/homebrew/Cellar/[email protected]/3.12.1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/pdm/2.11.2/libexec/lib/python3.12/site-packages/pdm/installers/synchronizers.py", line 286, in install_candidate
self.manager.install(can)
File "/opt/homebrew/Cellar/pdm/2.11.2/libexec/lib/python3.12/site-packages/pdm/installers/manager.py", line 34, in install
dist_info = installer(str(prepared.build()), self.environment, prepared.direct_url())
^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/pdm/2.11.2/libexec/lib/python3.12/site-packages/pdm/models/candidates.py", line 418, in build
self.wheel = Path(builder.build(build_dir, metadata_directory=self._metadata_dir))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/pdm/2.11.2/libexec/lib/python3.12/site-packages/pdm/builders/wheel.py", line 26, in build
requires = self._hook.get_requires_for_build_wheel(config_settings)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pdm-install-qifi5at5.log
In jaroslawhartman/withings-sync#132 I implemented the upload of *.fit
files. Any interest to move this code to garth?
When I do in provided colab notebook
garth.SleepData.get("2023-10-03")
ValidationError Traceback (most recent call last)
in <cell line: 1>()
----> 1 garth.SleepData.get("2023-10-03")
2 frames
/usr/local/lib/python3.10/dist-packages/pydantic/dataclasses.cpython-310-x86_64-linux-gnu.so in pydantic.dataclasses._dataclass_validate_values()
ValidationError: 1 validation error for SleepData
daily_sleep_dto
DailySleepDTO.init() missing 2 required positional arguments: 'sleep_from_device' and 'sleep_version' (type=type_error)
I am trying to get the previous capability to link/unlink gears to a specific activity. Previous using the Web Based authentication and style, doing a
PUT https://connect.garmin.com/gear-service/gear/link/(gearUUID)/activity/(garminActId)
will work. Now with the new Connect based api, it's not working anymore and I'm getting 403 forbidden using the Bearer Token.
Ref:
Pythe1337N/garmin-connect#56 (comment)
Ref:
cyberjunky/python-garminconnect#171
TX!
First of all I wanted to express my appreciation for your work – your library is fantastic and has been incredibly useful.
I'm currently developing a custom integration for HomeAssistant, which relies on pydantic version 1.10.12 as part of its core dependencies. Would it be feasible for you to adjust the minimum required version of your library to be compatible with pydantic 1.10.12?
Hi,
Nice work on this! I was considering using Garth for an interactive application. It would require making the http requests asynchronous. There are of course ways to achieve this at a higher level. But since this project is relatively small, and we have httpx now, I'd figured I'd get your thoughts on asyncio.
I'd of course be willing to contribute this. Browsing the code, it looks like it could be possible to abstract some stuff out of http.Client and provide 2 clients, one that is sync and one that is async. sso.py would be a little annoying to duplicate, I might have to look into how other libraries handle providing both.
Of course this is assuming you are interested in an async interface at all. I figure it's better than an entire different project or fork. What do you think?
I printed the error text
its a html
<!doctype html>
<html lang="en">
<head>
<title>HTTP Status 401 – Unauthorized</title>
<style type="text/css">
body {
font-family: Tahoma, Arial, sans-serif;
}
h1,
h2,
h3,
b {
color: white;
background-color: #525d76;
}
h1 {
font-size: 22px;
}
h2 {
font-size: 16px;
}
h3 {
font-size: 14px;
}
p {
font-size: 12px;
}
a {
color: bl ack;
}
.line {
height: 1px;
background-color: #525d76;
border: none;
}
</style>
</head>
<body>
<h1>HTTP Status 401 – Unauthorized</h1>
<hr class="line" />
<p><b>Type</b> Status Report</p>
<p><b>Message</b> OAuthToken is invalid</p>
<p>
<b>Description</b> The request has not been applied to the target resource
because it lacks valid authentication credentials for that resource.
</p>
<hr class="line" />
<h3>Garmin Connect API Server</h3>
<script
defer
src="https://static.cloudflareinsights.com/beacon.min.js/v8b253dfea2ab4077af8c6f58422dfbfd1689876627854"
integrity="sha512-bjgnUKX4azu3dLTVtie9u6TKqgx29RBwfj3QXYt5EKfWM/9hPSAI/4qcV5NACjwAo8UtTeWefx6Zq5PHcMm7Tg=="
data-cf-beacon='{"rayId":"8109fdc18c3a15a0","version":"2023.8.0","b":1,"token":"dfcba71ff1d44ca3956104d931b99217","si":100}'
crossorigin="anonymous"
></script>
</body>
</html>
Sleep example in documentation....
spelling error
sleep = garth.connectapi(
f"/wellness-service/wellness/dailySleepData/{garth.client.username}",
params={"date": "2023-07-05", "nonSleepBufferMinutes": 60),
)
maybe?
sleep = garth.connectapi(
f"/wellness-service/wellness/dailySleepData/{garth.client.username}",
params={"date": "2023-07-05", "nonSleepBufferMinutes": 60}
)
Been mulling over this issue looking for a workaround for like 2 weeks now. Tried fresh install and multiple devices. I'm very new to programming so the issue could be painfully obvious.
Followed directions in the README and got up to the point of Connect API, at which point I input the sleep API request and get hit with an AssertionError.
Occurs on garth/http.py at line 127 with "assert self.oauth1_token".
Storing my login info and password seems to have worked. The oauth1 & ouath2 tokens also seem to be created.
I believe the tokens have been created because after inputting my username and password, a .garth folder is created in my user directory, and the JSON files pertaining to the tokens reside in there. Maybe that has something to do with it?
Adding the domain to the OAuth1 token will simplify saving and restoring the token.
This had to be backwards compatible for people that've already stored their tokens.
See #21 (comment)
cc/ @yihong0618
Hi @matin there are a few users of my Garmin Connect home-assistant integration who have reported 'Connection pool is full errors' in their logs, I haven't run into them myself yet, but looking at other issues reported with same error in the Home Assistant repository a possible solution is to limit these from within the requests adapter.
Can you have a look if you can implement this in Garth?
Some references:
Ticket in my integration page
cyberjunky/home-assistant-garmin_connect#85
Similar issues and fixes in the code:
https://github.com/tuya/tuya-iot-python-sdk/pull/63/files
https://github.com/kbr/fritzconnection/pull/114/files
If you need any information, let me know, and thanks for your help in advance!
I'm not sure if this is the place to put this so I apologize in advance if this belongs somewhere else!
Q: Hi everyone, I was wondering if anyone knows how to access the garmin golf data through garth?
Previously I was using the garmin_golf repo to get golf data via json file. However as of a couple months ago it no longer works. From what I can tell it appears to be a change in the API (I could be way off) and I can't figure out how to make it work again.
Garth seems like the better option to access my garmin data so I was hoping someone could point me in the right direction for accessing the golf data. I've tried a few ways but I'm still very new to APIs so I'm not sure what exactly to put in the garth.connectapi()
call.
TIA
On Debian Bookworm i could not install garth as described in the docu.
on Stackoverflow i found a solution.
Maybe we should give a hint in the documentation.
this steps solved it for me:
sudo apt install python3-pip
sudo mv /usr/lib/python3.11/EXTERNALLY-MANAGED /usr/lib/python3.11/EXTERNALLY-MANAGED.OFF
python3 -m pip install garth
# python -m pip install garth
Collecting garth
Could not find a version that satisfies the requirement garth (from versions: )
No matching distribution found for garth
Hello @matin
Is there a way to add the capacity to get and set the hydration please ?
The Garmin connect app and the watch are not really ergonomic for this and that would allow an easy click a button integration to log a glass of water.
Thanks for the project.
I have some days in my Garmin Sleep data where I have no restless moments sleeping this results in an error:
daily_sleep_dto.awake_sleep_seconds
Input should be a valid integer [type=int_type, input_value=None, input_type=NoneType]
@yihong0618 I have a favor to ask ... Can you add a test (along with the VCR cassette) for login from China?
I spent a bunch of time to make sure it can work from China by allowing for a custom domain, but it hasn't been tested.
Using garth.configure(domain="garmin.cn")
before the login should be sufficient 🤞
Let me know if you run into any issues (along with the error) for me to fix it. I want to make sure everyone is able to use Garth.
Garth currently requires Pydantic 2, but the requirement creating a dependency conflict:
cyberjunky/python-garminconnect#162
iirc, some of the functionality Garth uses is unique to Pydantic 2. There should be a way to adapt and support Pydantic 1.8 as well.
I'll investigate whether it's possible.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.