feat: Implement Garmin sync, login improvements, and utility scripts

This commit is contained in:
2025-10-11 11:56:25 -07:00
parent 56a93cd8df
commit 3819e4f5e2
921 changed files with 2058 additions and 371 deletions

View File

@@ -0,0 +1,46 @@
import logging
import asyncio # Import asyncio for sleep
from typing import Optional
from garminconnect import Garmin
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
from ..schemas import GarminCredentials
# Configure debug logging for garminconnect
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
# Define a retry strategy for Garmin login
GARMIN_LOGIN_RETRY_STRATEGY = retry(
stop=stop_after_attempt(10), # Increased attempts
wait=wait_exponential(multiplier=1, min=10, max=60), # Increased min and max wait times
retry=retry_if_exception_type(Exception), # Retry on any exception for now
reraise=True
)
class GarminAuthService:
def __init__(self):
pass
@GARMIN_LOGIN_RETRY_STRATEGY # Apply retry strategy here
async def _perform_login(self, username: str, password: str) -> Garmin:
"""Helper to perform the actual garminconnect login with retry."""
client = Garmin(username, password)
client.login()
return client
async def initial_login(self, username: str, password: str) -> Optional[GarminCredentials]:
"""Performs initial login to Garmin Connect and returns GarminCredentials."""
try:
client = await self._perform_login(username, password) # Use the retried login helper
logger.info(f"Successful Garmin login for {username}")
return GarminCredentials(
garmin_username=username,
garmin_password_plaintext=password, # Storing plaintext as per user requirement
)
except Exception as e:
logger.error(f"Garmin initial login failed for {username}: {e}")
return None