diff --git a/backend/app/services/garmin.py b/backend/app/services/garmin.py index a5130f4..3b6966a 100644 --- a/backend/app/services/garmin.py +++ b/backend/app/services/garmin.py @@ -1,17 +1,22 @@ import os from pathlib import Path -import garth -from garth.exc import GarthException import asyncio +import logging from typing import List, Dict, Any, Optional from datetime import datetime, timedelta + +from garminconnect import ( + Garmin, + GarminConnectAuthenticationError, + GarminConnectConnectionError, + GarminConnectTooManyRequestsError, +) from sqlalchemy.ext.asyncio import AsyncSession -import logging logger = logging.getLogger(__name__) -class GarminService: +class GarminConnectService: """Service for interacting with Garmin Connect API.""" def __init__(self, db: Optional[AsyncSession] = None): @@ -20,58 +25,93 @@ class GarminService: self.password = os.getenv("GARMIN_PASSWORD") self.session_dir = Path("data/sessions") self.session_dir.mkdir(parents=True, exist_ok=True) + self.client: Optional[Garmin] = None + + async def _get_garmin_client(self) -> Garmin: + """Get or create a Garmin client instance.""" + if self.client: + return self.client + + self.client = Garmin() + return self.client async def authenticate(self) -> bool: """Authenticate with Garmin Connect and persist session.""" + client = await self._get_garmin_client() try: - await asyncio.to_thread(garth.resume, self.session_dir) - logger.info("Loaded existing Garmin session") - except (FileNotFoundError, GarthException): - logger.warning("No existing session found. Attempting fresh authentication.") + logger.debug("Attempting to resume existing Garmin session.") + await asyncio.to_thread(client.login, str(self.session_dir)) + logger.info("Successfully loaded existing Garmin session.") + except (FileNotFoundError, GarminConnectAuthenticationError, GarminConnectConnectionError): + logger.debug("No existing Garmin session found or session invalid.") + logger.info("Attempting fresh authentication with Garmin Connect.") if not self.username or not self.password: logger.error("Garmin username or password not set in environment variables.") raise GarminAuthError("Garmin username or password not configured.") try: - await asyncio.to_thread(garth.login, self.username, self.password) - await asyncio.to_thread(garth.save, self.session_dir) - logger.info("Successfully authenticated with Garmin Connect") + logger.debug(f"Attempting to log in with username: {self.username}") + # The login method of python-garminconnect returns (token1, token2) on successful login + # and handles MFA internally if prompt_mfa is provided. + await asyncio.to_thread(client.login, self.username, self.password) + await asyncio.to_thread(client.garth.dump, str(self.session_dir)) # Save tokens using garth.dump + logger.info("Successfully authenticated and saved new Garmin session.") except Exception as e: - logger.error(f"Garmin authentication failed: {str(e)}") - raise GarminAuthError(f"Authentication failed: {str(e)}") + logger.error(f"Garmin fresh authentication failed: {e}", exc_info=True) + raise GarminAuthError(f"Authentication failed: {e}") return True - async def get_activities(self, limit: int = 10, start_date: datetime = None) -> List[Dict[str, Any]]: + async def get_activities(self, limit: int = 10, start_date: Optional[datetime] = None) -> List[Dict[str, Any]]: """Fetch recent activities from Garmin Connect.""" await self.authenticate() + client = await self._get_garmin_client() - if not start_date: - start_date = datetime.now() - timedelta(days=7) + # Convert start_date to YYYY-MM-DD string as required by garminconnect.get_activities_by_date + start_date_str = start_date.strftime("%Y-%m-%d") if start_date else (datetime.now() - timedelta(days=30)).strftime("%Y-%m-%d") + end_date_str = datetime.now().strftime("%Y-%m-%d") try: + logger.debug(f"Fetching Garmin activities with limit={limit}, start_date={start_date_str}.") activities = await asyncio.to_thread( - garth.connectapi, - "/activity-service/activity/activities", - params={"limit": limit, "start": start_date.strftime("%Y-%m-%d")}, + client.get_activities_by_date, + start_date_str, + end_date_str, + limit=limit ) - logger.info(f"Fetched {len(activities)} activities from Garmin") + logger.info(f"Successfully fetched {len(activities)} activities from Garmin.") + logger.debug(f"Garmin activities data: {activities}") return activities or [] + except (GarminConnectConnectionError, GarminConnectTooManyRequestsError) as e: + logger.error(f"Failed to fetch activities from Garmin: {e}", exc_info=True) + raise GarminAPIError(f"Failed to fetch activities: {e}") + except GarminConnectAuthenticationError as e: + logger.error(f"Garmin authentication failed while fetching activities: {e}", exc_info=True) + raise GarminAuthError(f"Authentication failed: {e}") except Exception as e: - logger.error(f"Failed to fetch activities: {str(e)}") - raise GarminAPIError(f"Failed to fetch activities: {str(e)}") + logger.error(f"An unexpected error occurred while fetching activities from Garmin: {e}", exc_info=True) + raise GarminAPIError(f"Unexpected error: {e}") async def get_activity_details(self, activity_id: str) -> Dict[str, Any]: """Get detailed activity data including metrics.""" await self.authenticate() + client = await self._get_garmin_client() try: + logger.debug(f"Fetching detailed data for activity ID: {activity_id}.") details = await asyncio.to_thread( - garth.connectapi, f"/activity-service/activity/{activity_id}" + client.get_activity_details, activity_id ) - logger.info(f"Fetched details for activity {activity_id}") + logger.info(f"Successfully fetched details for activity ID: {activity_id}.") + logger.debug(f"Garmin activity {activity_id} details: {details}") return details + except (GarminConnectConnectionError, GarminConnectTooManyRequestsError) as e: + logger.error(f"Failed to fetch activity details for {activity_id}: {e}", exc_info=True) + raise GarminAPIError(f"Failed to fetch activity details: {e}") + except GarminConnectAuthenticationError as e: + logger.error(f"Garmin authentication failed while fetching activity details: {e}", exc_info=True) + raise GarminAuthError(f"Authentication failed: {e}") except Exception as e: - logger.error(f"Failed to fetch activity details for {activity_id}: {str(e)}") - raise GarminAPIError(f"Failed to fetch activity details: {str(e)}") + logger.error(f"An unexpected error occurred while fetching activity details for {activity_id}: {e}", exc_info=True) + raise GarminAPIError(f"Unexpected error: {e}") class GarminAuthError(Exception): diff --git a/backend/app/services/workout_sync.py b/backend/app/services/workout_sync.py index 273cc81..87a24a9 100644 --- a/backend/app/services/workout_sync.py +++ b/backend/app/services/workout_sync.py @@ -1,6 +1,6 @@ from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select, desc -from backend.app.services.garmin import GarminService, GarminAPIError, GarminAuthError +from backend.app.services.garmin import GarminConnectService as GarminService, GarminAPIError, GarminAuthError from backend.app.models.workout import Workout from backend.app.models.garmin_sync_log import GarminSyncLog, GarminSyncStatus from datetime import datetime, timedelta @@ -20,46 +20,65 @@ class WorkoutSyncService: async def sync_recent_activities(self, days_back: int = 7) -> int: """Sync recent Garmin activities to database.""" + logger.info(f"Starting Garmin activity sync for the last {days_back} days.") + sync_log = None # Initialize sync_log try: # Create sync log entry - sync_log = GarminSyncLog(status="in_progress") + sync_log = GarminSyncLog(status=GarminSyncStatus.IN_PROGRESS) self.db.add(sync_log) await self.db.commit() + await self.db.refresh(sync_log) # Refresh to get the generated ID + + logger.debug(f"Created new GarminSyncLog with ID: {sync_log.id}") # Calculate start date start_date = datetime.now() - timedelta(days=days_back) + logger.debug(f"Fetching activities from Garmin starting from: {start_date}") # Fetch activities from Garmin activities = await self.garmin_service.get_activities( - limit=50, start_date=start_date + limit=50, start_date=start_date, end_date=datetime.now() ) + logger.debug(f"Found {len(activities)} activities from Garmin.") synced_count = 0 for activity in activities: - activity_id = activity['activityId'] + activity_id = str(activity['activityId']) + logger.debug(f"Processing activity ID: {activity_id}") if await self.activity_exists(activity_id): + logger.debug(f"Activity {activity_id} already exists in DB, skipping.") continue # Get full activity details with retry logic max_retries = 3 + details = None for attempt in range(max_retries): try: + logger.debug(f"Attempt {attempt + 1} to fetch details for activity {activity_id}") details = await self.garmin_service.get_activity_details(activity_id) + logger.debug(f"Successfully fetched details for activity {activity_id}.") break except (GarminAPIError, GarminAuthError) as e: + logger.warning(f"Failed to fetch details for {activity_id} (attempt {attempt + 1}/{max_retries}): {e}") if attempt == max_retries - 1: + logger.error(f"Max retries reached for activity {activity_id}. Skipping details fetch.", exc_info=True) raise await asyncio.sleep(2 ** attempt) - logger.warning(f"Retrying activity details fetch for {activity_id}, attempt {attempt + 1}") + + if details is None: + logger.warning(f"Skipping activity {activity_id} due to failure in fetching details.") + continue # Merge basic activity data with detailed metrics full_activity = {**activity, **details} + logger.debug(f"Merged activity data for {activity_id}.") # Parse and create workout workout_data = await self.parse_activity_data(full_activity) workout = Workout(**workout_data) self.db.add(workout) synced_count += 1 + logger.debug(f"Added workout {workout.garmin_activity_id} to session.") # Update sync log sync_log.status = GarminSyncStatus.COMPLETED @@ -67,48 +86,58 @@ class WorkoutSyncService: sync_log.last_sync_time = datetime.now() await self.db.commit() - logger.info(f"Successfully synced {synced_count} activities") + logger.info(f"Successfully synced {synced_count} activities.") return synced_count except GarminAuthError as e: - sync_log.status = GarminSyncStatus.AUTH_FAILED - sync_log.error_message = str(e) - await self.db.commit() - logger.error(f"Garmin authentication failed: {str(e)}") + logger.error(f"Garmin authentication failed during sync: {e}", exc_info=True) + if sync_log: + sync_log.status = GarminSyncStatus.AUTH_FAILED + sync_log.error_message = str(e) + await self.db.commit() raise except GarminAPIError as e: - sync_log.status = GarminSyncStatus.FAILED - sync_log.error_message = str(e) - await self.db.commit() - logger.error(f"Garmin API error during sync: {str(e)}") + logger.error(f"Garmin API error during sync: {e}", exc_info=True) + if sync_log: + sync_log.status = GarminSyncStatus.FAILED + sync_log.error_message = str(e) + await self.db.commit() raise except Exception as e: - sync_log.status = GarminSyncStatus.FAILED - sync_log.error_message = str(e) - await self.db.commit() - logger.error(f"Unexpected error during sync: {str(e)}") + logger.error(f"Unexpected error during Garmin sync: {e}", exc_info=True) + if sync_log: + sync_log.status = GarminSyncStatus.FAILED + sync_log.error_message = str(e) + await self.db.commit() raise async def get_latest_sync_status(self): - """Get the most recent sync log entry""" + """Get the most recent sync log entry.""" + logger.debug("Fetching latest Garmin sync status.") result = await self.db.execute( select(GarminSyncLog) .order_by(desc(GarminSyncLog.created_at)) .limit(1) ) - return await result.scalar_one_or_none() + status = result.scalar_one_or_none() + logger.debug(f"Latest sync status: {status.status if status else 'None'}") + return status async def activity_exists(self, garmin_activity_id: str) -> bool: """Check if activity already exists in database.""" + logger.debug(f"Checking if activity {garmin_activity_id} exists in database.") result = await self.db.execute( select(Workout).where(Workout.garmin_activity_id == garmin_activity_id) ) - return result.scalar_one_or_none() is not None # Remove the await here + exists = result.scalar_one_or_none() is not None + logger.debug(f"Activity {garmin_activity_id} exists: {exists}") + return exists async def parse_activity_data(self, activity: Dict[str, Any]) -> Dict[str, Any]: """Parse Garmin activity data into workout model format.""" + logger.debug(f"Parsing activity data for Garmin activity ID: {activity.get('activityId')}") return { - "garmin_activity_id": activity['activityId'], + "garmin_activity_id": str(activity['activityId']), "activity_type": activity.get('activityType', {}).get('typeKey'), "start_time": datetime.fromisoformat(activity['startTimeLocal'].replace('Z', '+00:00')), "duration_seconds": activity.get('duration'), diff --git a/backend/tests/services/test_garmin.py b/backend/tests/services/test_garmin.py index c24b6ea..ba88be4 100644 --- a/backend/tests/services/test_garmin.py +++ b/backend/tests/services/test_garmin.py @@ -1,7 +1,7 @@ import os from unittest.mock import AsyncMock, MagicMock, patch import pytest -from backend.app.services.garmin import GarminService, GarminAuthError, GarminAPIError +from backend.app.services.garmin import GarminConnectService as GarminService, GarminAuthError, GarminAPIError from backend.app.models.garmin_sync_log import GarminSyncStatus from datetime import datetime, timedelta import garth # Import garth for type hinting @@ -11,13 +11,12 @@ def mock_env_vars(): with patch.dict(os.environ, {"GARMIN_USERNAME": "test_user", "GARMIN_PASSWORD": "test_password"}): yield -def create_garth_client_mock(): - mock_client_instance = MagicMock(spec=garth.Client) - mock_client_instance.login = AsyncMock(return_value=True) +def create_garmin_client_mock(): + mock_client_instance = MagicMock(spec=GarminService) # Use GarminService (which is GarminConnectService) + mock_client_instance.authenticate = AsyncMock(return_value=True) mock_client_instance.get_activities = AsyncMock(return_value=[]) - mock_client_instance.get_activity = AsyncMock(return_value={}) - mock_client_instance.load = AsyncMock(side_effect=FileNotFoundError) - mock_client_instance.save = AsyncMock() + mock_client_instance.get_activity_details = AsyncMock(return_value={}) + mock_client_instance.is_authenticated = MagicMock(return_value=True) return mock_client_instance @pytest.mark.asyncio diff --git a/backend/tests/services/test_garmin_functional.py b/backend/tests/services/test_garmin_functional.py index cea86c8..ab3e712 100644 --- a/backend/tests/services/test_garmin_functional.py +++ b/backend/tests/services/test_garmin_functional.py @@ -9,7 +9,7 @@ from datetime import datetime, timedelta from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select -from backend.app.services.garmin import GarminService, GarminAuthError, GarminAPIError +from backend.app.services.garmin import GarminConnectService as GarminService, GarminAuthError, GarminAPIError from backend.app.services.workout_sync import WorkoutSyncService from backend.app.models.workout import Workout from backend.app.models.garmin_sync_log import GarminSyncLog @@ -36,12 +36,12 @@ class TestGarminAuthentication: 'GARMIN_USERNAME': 'test@example.com', 'GARMIN_PASSWORD': 'testpass123' }) - @patch('garth.Client') + @patch('garminconnect.Garmin') async def test_successful_authentication(self, mock_client_class, garmin_service): """Test successful authentication with valid credentials.""" # Setup mock client mock_client = MagicMock() - mock_client.login = AsyncMock(return_value=True) + mock_client.login = AsyncMock(return_value=(None, None)) mock_client.save = MagicMock() mock_client_class.return_value = mock_client @@ -56,7 +56,7 @@ class TestGarminAuthentication: 'GARMIN_USERNAME': 'invalid@example.com', 'GARMIN_PASSWORD': 'wrongpass' }) - @patch('garth.Client') + @patch('garminconnect.Garmin') async def test_failed_authentication(self, mock_client_class, garmin_service): """Test authentication failure with invalid credentials.""" # Setup mock client to raise exception @@ -72,21 +72,20 @@ class TestGarminAuthentication: 'GARMIN_USERNAME': 'test@example.com', 'GARMIN_PASSWORD': 'testpass123' }) - @patch('garth.Client') + @patch('garminconnect.Garmin') async def test_session_reuse(self, mock_client_class, garmin_service): """Test that existing sessions are reused.""" # Setup mock client with load method mock_client = MagicMock() - mock_client.load = MagicMock(return_value=True) - mock_client.login = AsyncMock() # Should not be called + mock_client.login = AsyncMock(return_value=(None, None)) # Login handles loading from tokenstore mock_client_class.return_value = mock_client # Test authentication result = await garmin_service.authenticate() assert result is True - mock_client.load.assert_called_once() - mock_client.login.assert_not_awaited() + mock_client.login.assert_awaited_once_with(tokenstore=garmin_service.session_dir) + mock_client.save.assert_not_called() class TestWorkoutSyncing: @@ -96,7 +95,7 @@ class TestWorkoutSyncing: 'GARMIN_USERNAME': 'test@example.com', 'GARMIN_PASSWORD': 'testpass123' }) - @patch('garth.Client') + @patch('garminconnect.Garmin') async def test_successful_sync_recent_activities(self, mock_client_class, workout_sync_service, db_session): """Test successful synchronization of recent activities.""" # Setup mock Garmin client @@ -136,8 +135,8 @@ class TestWorkoutSyncing: 'elevationGain': 500.0 } - mock_client.get_activities = MagicMock(return_value=mock_activities) - mock_client.get_activity = MagicMock(return_value=mock_details) + mock_client.get_activities_by_date = MagicMock(return_value=mock_activities) + mock_client.get_activity_details = MagicMock(return_value=mock_details) mock_client_class.return_value = mock_client # Test sync @@ -198,7 +197,7 @@ class TestWorkoutSyncing: } ] - mock_client.get_activities = MagicMock(return_value=mock_activities) + mock_client.get_activities_by_date = MagicMock(return_value=mock_activities) mock_client_class.return_value = mock_client # Test sync @@ -210,7 +209,7 @@ class TestWorkoutSyncing: 'GARMIN_USERNAME': 'invalid@example.com', 'GARMIN_PASSWORD': 'wrongpass' }) - @patch('garth.Client') + @patch('garminconnect.Garmin') async def test_sync_with_auth_failure(self, mock_client_class, workout_sync_service, db_session): """Test sync failure due to authentication error.""" # Setup mock client to fail authentication @@ -234,14 +233,14 @@ class TestWorkoutSyncing: 'GARMIN_USERNAME': 'test@example.com', 'GARMIN_PASSWORD': 'testpass123' }) - @patch('garth.Client') + @patch('garminconnect.Garmin') async def test_sync_with_api_error(self, mock_client_class, workout_sync_service, db_session): """Test sync failure due to API error.""" # Setup mock client mock_client = MagicMock() mock_client.login = AsyncMock(return_value=True) mock_client.save = MagicMock() - mock_client.get_activities = MagicMock(side_effect=Exception("API rate limit exceeded")) + mock_client.get_activities_by_date = MagicMock(side_effect=Exception("API rate limit exceeded")) mock_client_class.return_value = mock_client # Test sync @@ -265,7 +264,7 @@ class TestErrorHandling: 'GARMIN_USERNAME': 'test@example.com', 'GARMIN_PASSWORD': 'testpass123' }) - @patch('garth.Client') + @patch('garminconnect.Garmin') async def test_activity_detail_fetch_retry(self, mock_client_class, workout_sync_service, db_session): """Test retry logic when fetching activity details fails.""" # Setup mock client @@ -283,9 +282,9 @@ class TestErrorHandling: } ] - mock_client.get_activities = MagicMock(return_value=mock_activities) + mock_client.get_activities_by_date = MagicMock(return_value=mock_activities) # First two calls fail, third succeeds - mock_client.get_activity = MagicMock(side_effect=[ + mock_client.get_activity_details = MagicMock(side_effect=[ Exception("Temporary error"), Exception("Temporary error"), { @@ -305,4 +304,4 @@ class TestErrorHandling: assert synced_count == 1 # Verify get_activity was called 3 times (initial + 2 retries) - assert mock_client.get_activity.call_count == 3 \ No newline at end of file + assert mock_client.get_activity_details.call_count == 3 \ No newline at end of file diff --git a/backend/tests/services/test_garmin_sync_functional.py b/backend/tests/services/test_garmin_sync_functional.py index 874134c..885c66b 100644 --- a/backend/tests/services/test_garmin_sync_functional.py +++ b/backend/tests/services/test_garmin_sync_functional.py @@ -5,7 +5,7 @@ from sqlalchemy.pool import StaticPool from sqlalchemy import select from backend.app.database import Base from backend.app.services.workout_sync import WorkoutSyncService -from backend.app.services.garmin import GarminService, GarminAPIError, GarminAuthError +from backend.app.services.garmin import GarminConnectService as GarminService, GarminAPIError, GarminAuthError from backend.app.models.workout import Workout from backend.app.models.garmin_sync_log import GarminSyncLog, GarminSyncStatus from datetime import datetime, timedelta diff --git a/git_scape_python_garminconnect_digest.txt b/git_scape_python_garminconnect_digest.txt new file mode 100755 index 0000000..7c344ea --- /dev/null +++ b/git_scape_python_garminconnect_digest.txt @@ -0,0 +1,31241 @@ +Repository: https://github.com/cyberjunky/python-garminconnect +Files analyzed: 8 + +Directory structure: +└── cyberjunky-python-garminconnect/ + ├── .github + │ ├── workflows + │ │ └── ci.yml + │ ├── dependabot.yml + │ └── FUNDING.yml + ├── docs + │ ├── graphql_queries.txt + │ └── reference.ipynb + ├── garminconnect + │ ├── __init__.py + │ └── fit.py + ├── test_data + │ └── sample_activity.gpx + ├── tests + │ ├── cassettes + │ ├── 12129115726_ACTIVITY.fit + │ ├── conftest.py + │ └── test_garmin.py + ├── .editorconfig + ├── .gitignore + ├── demo.py + ├── example.py + ├── LICENSE + ├── pyproject.toml + └── README.md + + +================================================ +FILE: README.md +================================================ +# Python: Garmin Connect + +The Garmin Connect API library comes with two examples: + +- **`example.py`** - Simple getting-started example showing authentication, token storage, and basic API calls +- **`demo.py`** - Comprehensive demo providing access to **100+ API methods** organized into **11 categories** for easy navigation + +Note: The demo menu is generated dynamically; exact options may change between releases. + +```bash +$ ./demo.py +🏃‍♂️ Full-blown Garmin Connect API Demo - Main Menu +================================================== +Select a category: + + [1] 👤 User & Profile + [2] 📊 Daily Health & Activity + [3] 🔬 Advanced Health Metrics + [4] 📈 Historical Data & Trends + [5] 🏃 Activities & Workouts + [6] ⚖️ Body Composition & Weight + [7] 🏆 Goals & Achievements + [8] ⌚ Device & Technical + [9] 🎽 Gear & Equipment + [0] 💧 Hydration & Wellness + [a] 🔧 System & Export + + [q] Exit program + +Make your selection: +``` + +## API Coverage Statistics + +- **Total API Methods**: 100+ unique endpoints (snapshot) +- **Categories**: 11 organized sections +- **User & Profile**: 4 methods (basic user info, settings) +- **Daily Health & Activity**: 8 methods (today's health data) +- **Advanced Health Metrics**: 10 methods (fitness metrics, HRV, VO2) +- **Historical Data & Trends**: 6 methods (date range queries) +- **Activities & Workouts**: 20 methods (comprehensive activity management) +- **Body Composition & Weight**: 8 methods (weight tracking, body composition) +- **Goals & Achievements**: 15 methods (challenges, badges, goals) +- **Device & Technical**: 7 methods (device info, settings) +- **Gear & Equipment**: 6 methods (gear management, tracking) +- **Hydration & Wellness**: 9 methods (hydration, blood pressure, menstrual) +- **System & Export**: 4 methods (reporting, logout, GraphQL) + +### Interactive Features + +- **Enhanced User Experience**: Categorized navigation with emoji indicators +- **Smart Data Management**: Interactive weigh-in deletion with search capabilities +- **Comprehensive Coverage**: All major Garmin Connect features are accessible +- **Error Handling**: Robust error handling with user-friendly prompts +- **Data Export**: JSON export functionality for all data types + +[![Donate via PayPal](https://img.shields.io/badge/Donate-PayPal-blue.svg?style=for-the-badge&logo=paypal)](https://www.paypal.me/cyberjunkynl/) +[![Sponsor on GitHub](https://img.shields.io/badge/Sponsor-GitHub-red.svg?style=for-the-badge&logo=github)](https://github.com/sponsors/cyberjunky) + +A comprehensive Python3 API wrapper for Garmin Connect, providing access to health, fitness, and device data. + +## 📖 About + +This library enables developers to programmatically access Garmin Connect data including: + +- **Health Metrics**: Heart rate, sleep, stress, body composition, SpO2, HRV +- **Activity Data**: Workouts, exercises, training status, performance metrics +- **Device Information**: Connected devices, settings, alarms, solar data +- **Goals & Achievements**: Personal records, badges, challenges, race predictions +- **Historical Data**: Trends, progress tracking, date range queries + +Compatible with all Garmin Connect accounts. See + +## 📦 Installation + +Install from PyPI: + +```bash +python3 -m pip install --upgrade pip +python3 -m pip install garminconnect +``` + +## Run demo software (recommended) + +```bash +python3 -m venv .venv --copies +source .venv/bin/activate # On Windows: .venv\Scripts\activate +pip install pdm +pdm install --group :example + +# Run the simple example +python3 ./example.py + +# Run the comprehensive demo +python3 ./demo.py +``` + + +## 🛠️ Development + +Set up a development environment for contributing: + +> **Note**: This project uses [PDM](https://pdm.fming.dev/) for modern Python dependency management and task automation. All development tasks are configured as PDM scripts in `pyproject.toml`. The Python interpreter is automatically configured to use `.venv/bin/python` when you create the virtual environment. + +**Environment Setup:** + +> **⚠️ Important**: On externally-managed Python environments (like Debian/Ubuntu), you must create a virtual environment before installing PDM to avoid system package conflicts. + +```bash +# 1. Create and activate a virtual environment +python3 -m venv .venv --copies +source .venv/bin/activate # On Windows: .venv\Scripts\activate + +# 2. Install PDM (Python Dependency Manager) +pip install pdm + +# 3. Install all development dependencies +pdm install --group :all + +# 4. Install optional tools for enhanced development experience +pip install "black[jupyter]" codespell pre-commit + +# 5. Setup pre-commit hooks (optional) +pre-commit install --install-hooks +``` + +**Alternative for System-wide PDM Installation:** +```bash +# Install PDM via pipx (recommended for system-wide tools) +python3 -m pip install --user pipx +pipx install pdm + +# Then proceed with project setup +pdm install --group :all +``` + +**Available Development Commands:** +```bash +pdm run format # Auto-format code (isort, black, ruff --fix) +pdm run lint # Check code quality (isort, ruff, black, mypy) +pdm run codespell # Check spelling errors (install codespell if needed) +pdm run test # Run test suite +pdm run testcov # Run tests with coverage report +pdm run all # Run all checks +pdm run clean # Clean build artifacts and cache files +pdm run build # Build package for distribution +pdm run publish # Build and publish to PyPI +``` + +**View all available commands:** +```bash +pdm run --list # Display all available PDM scripts +``` + +**Code Quality Workflow:** +```bash +# Before making changes +pdm run lint # Check current code quality + +# After making changes +pdm run format # Auto-format your code +pdm run lint # Verify code quality +pdm run codespell # Check spelling +pdm run test # Run tests to ensure nothing broke +``` + +Run these commands before submitting PRs to ensure code quality standards. + +## 🔐 Authentication + +The library uses the same OAuth authentication as the official Garmin Connect app via [Garth](https://github.com/matin/garth). + +**Key Features:** +- Login credentials valid for one year (no repeated logins) +- Secure OAuth token storage +- Same authentication flow as official app + +**Advanced Configuration:** +```python +# Optional: Custom OAuth consumer (before login) +import os +import garth +garth.sso.OAUTH_CONSUMER = { + 'key': os.getenv('GARTH_OAUTH_KEY', ''), + 'secret': os.getenv('GARTH_OAUTH_SECRET', ''), +} +# Note: Set these env vars securely; placeholders are non-sensitive. +``` + +**Token Storage:** +Tokens are automatically saved to `~/.garminconnect` directory for persistent authentication. +For security, ensure restrictive permissions: + +```bash +chmod 700 ~/.garminconnect +chmod 600 ~/.garminconnect/* 2>/dev/null || true +``` + +## 🧪 Testing + +Run the test suite to verify functionality: + +**Prerequisites:** + +Create tokens in ~/.garminconnect by running the example program. + +```bash +# Install development dependencies +pdm install --group :all +``` + +**Run Tests:** +```bash +pdm run test # Run all tests +pdm run testcov # Run tests with coverage report +``` + +Optional: keep test tokens isolated + +```bash +export GARMINTOKENS="$(mktemp -d)" +python3 ./example.py # create fresh tokens for tests +pdm run test +``` + +**Note:** Tests automatically use `~/.garminconnect` as the default token file location. You can override this by setting the `GARMINTOKENS` environment variable. Run `example.py` first to generate authentication tokens for testing. + +**For Developers:** Tests use VCR cassettes to record/replay HTTP interactions. If tests fail with authentication errors, ensure valid tokens exist in `~/.garminconnect` + +## 📦 Publishing + +For package maintainers: + +**Setup PyPI credentials:** +```bash +pip install twine +# Edit with your preferred editor, or create via here-doc: +# cat > ~/.pypirc <<'EOF' +# [pypi] +# username = __token__ +# password = +# EOF +``` +```ini +[pypi] +username = __token__ +password = +``` + +Recommended: use environment variables and restrict file perms + +```bash +chmod 600 ~/.pypirc +export TWINE_USERNAME="__token__" +export TWINE_PASSWORD="" +``` + +**Publish new version:** +```bash +pdm run publish # Build and publish to PyPI +``` + +**Alternative publishing steps:** +```bash +pdm run build # Build package only +pdm publish # Publish pre-built package +``` + +## 🤝 Contributing + +We welcome contributions! Here's how you can help: + +- **Report Issues**: Bug reports and feature requests via GitHub issues +- **Submit PRs**: Code improvements, new features, documentation updates +- **Testing**: Help test new features and report compatibility issues +- **Documentation**: Improve examples, add use cases, fix typos + +**Before Contributing:** +1. Set up development environment (`pdm install --group :all`) +2. Execute code quality checks (`pdm run format && pdm run lint`) +3. Test your changes (`pdm run test`) +4. Follow existing code style and patterns + +**Development Workflow:** +```bash +# 1. Setup environment (with virtual environment) +python3 -m venv .venv --copies +source .venv/bin/activate +pip install pdm +pdm install --group :all + +# 2. Make your changes +# ... edit code ... + +# 3. Quality checks +pdm run format # Auto-format code +pdm run lint # Check code quality +pdm run test # Run tests + +# 4. Submit PR +git commit -m "Your changes" +git push origin your-branch +``` + +### Jupyter Notebook + +Explore the API interactively with our [reference notebook](https://github.com/cyberjunky/python-garminconnect/blob/master/reference.ipynb). + +### Python Code Examples + +```python +from garminconnect import Garmin +import os + +# Initialize and login +client = Garmin( + os.getenv("GARMIN_EMAIL", ""), + os.getenv("GARMIN_PASSWORD", "") +) +client.login() + +# Get today's stats +from datetime import date +_today = date.today().strftime('%Y-%m-%d') +stats = client.get_stats(_today) + +# Get heart rate data +hr_data = client.get_heart_rates(_today) +print(f"Resting HR: {hr_data.get('restingHeartRate', 'n/a')}") +``` + +### Additional Resources +- **Simple Example**: [example.py](https://raw.githubusercontent.com/cyberjunky/python-garminconnect/master/example.py) - Getting started guide +- **Comprehensive Demo**: [demo.py](https://raw.githubusercontent.com/cyberjunky/python-garminconnect/master/demo.py) - All 101 API methods +- **API Documentation**: Comprehensive method documentation in source code +- **Test Cases**: Real-world usage examples in `tests/` directory + +## 🙏 Acknowledgments + +Special thanks to all contributors who have helped improve this project: + +- **Community Contributors**: Bug reports, feature requests, and code improvements +- **Issue Reporters**: Helping identify and resolve compatibility issues +- **Feature Developers**: Adding new API endpoints and functionality +- **Documentation Authors**: Improving examples and user guides + +This project thrives thanks to community involvement and feedback. + +## 💖 Support This Project + +If you find this library useful for your projects, please consider supporting its continued development and maintenance: + +### 🌟 Ways to Support + +- **⭐ Star this repository** - Help others discover the project +- **💰 Financial Support** - Contribute to development and hosting costs +- **🐛 Report Issues** - Help improve stability and compatibility +- **📖 Spread the Word** - Share with other developers + +### 💳 Financial Support Options + +[![Donate via PayPal](https://img.shields.io/badge/Donate-PayPal-blue.svg?style=for-the-badge&logo=paypal)](https://www.paypal.me/cyberjunkynl/) +[![Sponsor on GitHub](https://img.shields.io/badge/Sponsor-GitHub-red.svg?style=for-the-badge&logo=github)](https://github.com/sponsors/cyberjunky) + +**Why Support?** +- Keeps the project actively maintained +- Enables faster bug fixes and new features +- Supports infrastructure costs (testing, AI, CI/CD) +- Shows appreciation for hundreds of hours of development + +Every contribution, no matter the size, makes a difference and is greatly appreciated! 🙏 + + +================================================ +FILE: demo.py +================================================ +#!/usr/bin/env python3 +""" +🏃‍♂️ Comprehensive Garmin Connect API Demo +========================================== + +This is a comprehensive demonstration program showing ALL available API calls +and error handling patterns for python-garminconnect. + +For a simple getting-started example, see example.py + +Dependencies: +pip3 install garth requests readchar + +Environment Variables (optional): +export EMAIL= +export PASSWORD= +export GARMINTOKENS= +""" + +import datetime +import json +import logging +import os +import sys +from contextlib import suppress +from datetime import timedelta +from getpass import getpass +from pathlib import Path +from typing import Any + +import readchar +import requests +from garth.exc import GarthException, GarthHTTPError + +from garminconnect import ( + Garmin, + GarminConnectAuthenticationError, + GarminConnectConnectionError, + GarminConnectTooManyRequestsError, +) + +# Configure logging to reduce verbose error output from garminconnect library +# This prevents double error messages for known API issues +logging.getLogger("garminconnect").setLevel(logging.CRITICAL) + +api: Garmin | None = None + + +class Config: + """Configuration class for the Garmin Connect API demo.""" + + def __init__(self): + # Load environment variables + self.email = os.getenv("EMAIL") + self.password = os.getenv("PASSWORD") + self.tokenstore = os.getenv("GARMINTOKENS") or "~/.garminconnect" + self.tokenstore_base64 = ( + os.getenv("GARMINTOKENS_BASE64") or "~/.garminconnect_base64" + ) + + # Date settings + self.today = datetime.date.today() + self.week_start = self.today - timedelta(days=7) + self.month_start = self.today - timedelta(days=30) + + # API call settings + self.default_limit = 100 + self.start = 0 + self.start_badge = 1 # Badge related calls start counting at 1 + + # Activity settings + self.activitytype = "" # Possible values: cycling, running, swimming, multi_sport, fitness_equipment, hiking, walking, other + self.activityfile = ( + "test_data/sample_activity.gpx" # Supported file types: .fit .gpx .tcx + ) + self.workoutfile = "test_data/sample_workout.json" # Sample workout JSON file + + # Export settings + self.export_dir = Path("your_data") + self.export_dir.mkdir(exist_ok=True) + + +# Initialize configuration +config = Config() + +# Organized menu categories +menu_categories = { + "1": { + "name": "👤 User & Profile", + "options": { + "1": {"desc": "Get full name", "key": "get_full_name"}, + "2": {"desc": "Get unit system", "key": "get_unit_system"}, + "3": {"desc": "Get user profile", "key": "get_user_profile"}, + "4": { + "desc": "Get userprofile settings", + "key": "get_userprofile_settings", + }, + }, + }, + "2": { + "name": "📊 Daily Health & Activity", + "options": { + "1": { + "desc": f"Get activity data for '{config.today.isoformat()}'", + "key": "get_stats", + }, + "2": { + "desc": f"Get user summary for '{config.today.isoformat()}'", + "key": "get_user_summary", + }, + "3": { + "desc": f"Get stats and body composition for '{config.today.isoformat()}'", + "key": "get_stats_and_body", + }, + "4": { + "desc": f"Get steps data for '{config.today.isoformat()}'", + "key": "get_steps_data", + }, + "5": { + "desc": f"Get heart rate data for '{config.today.isoformat()}'", + "key": "get_heart_rates", + }, + "6": { + "desc": f"Get resting heart rate for '{config.today.isoformat()}'", + "key": "get_resting_heart_rate", + }, + "7": { + "desc": f"Get sleep data for '{config.today.isoformat()}'", + "key": "get_sleep_data", + }, + "8": { + "desc": f"Get stress data for '{config.today.isoformat()}'", + "key": "get_all_day_stress", + }, + }, + }, + "3": { + "name": "🔬 Advanced Health Metrics", + "options": { + "1": { + "desc": f"Get training readiness for '{config.today.isoformat()}'", + "key": "get_training_readiness", + }, + "2": { + "desc": f"Get training status for '{config.today.isoformat()}'", + "key": "get_training_status", + }, + "3": { + "desc": f"Get respiration data for '{config.today.isoformat()}'", + "key": "get_respiration_data", + }, + "4": { + "desc": f"Get SpO2 data for '{config.today.isoformat()}'", + "key": "get_spo2_data", + }, + "5": { + "desc": f"Get max metrics (VO2, fitness age) for '{config.today.isoformat()}'", + "key": "get_max_metrics", + }, + "6": { + "desc": f"Get Heart Rate Variability (HRV) for '{config.today.isoformat()}'", + "key": "get_hrv_data", + }, + "7": { + "desc": f"Get Fitness Age data for '{config.today.isoformat()}'", + "key": "get_fitnessage_data", + }, + "8": { + "desc": f"Get stress data for '{config.today.isoformat()}'", + "key": "get_stress_data", + }, + "9": {"desc": "Get lactate threshold data", "key": "get_lactate_threshold"}, + "0": { + "desc": f"Get intensity minutes for '{config.today.isoformat()}'", + "key": "get_intensity_minutes_data", + }, + }, + }, + "4": { + "name": "📈 Historical Data & Trends", + "options": { + "1": { + "desc": f"Get daily steps from '{config.week_start.isoformat()}' to '{config.today.isoformat()}'", + "key": "get_daily_steps", + }, + "2": { + "desc": f"Get body battery from '{config.week_start.isoformat()}' to '{config.today.isoformat()}'", + "key": "get_body_battery", + }, + "3": { + "desc": f"Get floors data for '{config.week_start.isoformat()}'", + "key": "get_floors", + }, + "4": { + "desc": f"Get blood pressure from '{config.week_start.isoformat()}' to '{config.today.isoformat()}'", + "key": "get_blood_pressure", + }, + "5": { + "desc": f"Get progress summary from '{config.week_start.isoformat()}' to '{config.today.isoformat()}'", + "key": "get_progress_summary_between_dates", + }, + "6": { + "desc": f"Get body battery events for '{config.week_start.isoformat()}'", + "key": "get_body_battery_events", + }, + }, + }, + "5": { + "name": "🏃 Activities & Workouts", + "options": { + "1": { + "desc": f"Get recent activities (limit {config.default_limit})", + "key": "get_activities", + }, + "2": {"desc": "Get last activity", "key": "get_last_activity"}, + "3": { + "desc": f"Get activities for today '{config.today.isoformat()}'", + "key": "get_activities_fordate", + }, + "4": { + "desc": f"Download activities by date range '{config.week_start.isoformat()}' to '{config.today.isoformat()}'", + "key": "download_activities", + }, + "5": { + "desc": "Get all activity types and statistics", + "key": "get_activity_types", + }, + "6": { + "desc": f"Upload activity data from {config.activityfile}", + "key": "upload_activity", + }, + "7": {"desc": "Get workouts", "key": "get_workouts"}, + "8": {"desc": "Get activity splits (laps)", "key": "get_activity_splits"}, + "9": { + "desc": "Get activity typed splits", + "key": "get_activity_typed_splits", + }, + "0": { + "desc": "Get activity split summaries", + "key": "get_activity_split_summaries", + }, + "a": {"desc": "Get activity weather data", "key": "get_activity_weather"}, + "b": { + "desc": "Get activity heart rate zones", + "key": "get_activity_hr_in_timezones", + }, + "c": { + "desc": "Get detailed activity information", + "key": "get_activity_details", + }, + "d": {"desc": "Get activity gear information", "key": "get_activity_gear"}, + "e": {"desc": "Get single activity data", "key": "get_activity"}, + "f": { + "desc": "Get strength training exercise sets", + "key": "get_activity_exercise_sets", + }, + "g": {"desc": "Get workout by ID", "key": "get_workout_by_id"}, + "h": {"desc": "Download workout to .FIT file", "key": "download_workout"}, + "i": { + "desc": f"Upload workout from {config.workoutfile}", + "key": "upload_workout", + }, + "j": { + "desc": f"Get activities by date range '{config.today.isoformat()}'", + "key": "get_activities_by_date", + }, + "k": {"desc": "Set activity name", "key": "set_activity_name"}, + "l": {"desc": "Set activity type", "key": "set_activity_type"}, + "m": {"desc": "Create manual activity", "key": "create_manual_activity"}, + "n": {"desc": "Delete activity", "key": "delete_activity"}, + }, + }, + "6": { + "name": "⚖️ Body Composition & Weight", + "options": { + "1": { + "desc": f"Get body composition for '{config.today.isoformat()}'", + "key": "get_body_composition", + }, + "2": { + "desc": f"Get weigh-ins from '{config.week_start.isoformat()}' to '{config.today.isoformat()}'", + "key": "get_weigh_ins", + }, + "3": { + "desc": f"Get daily weigh-ins for '{config.today.isoformat()}'", + "key": "get_daily_weigh_ins", + }, + "4": {"desc": "Add a weigh-in (interactive)", "key": "add_weigh_in"}, + "5": { + "desc": f"Set body composition data for '{config.today.isoformat()}' (interactive)", + "key": "set_body_composition", + }, + "6": { + "desc": f"Add body composition for '{config.today.isoformat()}' (interactive)", + "key": "add_body_composition", + }, + "7": { + "desc": f"Delete all weigh-ins for '{config.today.isoformat()}'", + "key": "delete_weigh_ins", + }, + "8": {"desc": "Delete specific weigh-in", "key": "delete_weigh_in"}, + }, + }, + "7": { + "name": "🏆 Goals & Achievements", + "options": { + "1": {"desc": "Get personal records", "key": "get_personal_records"}, + "2": {"desc": "Get earned badges", "key": "get_earned_badges"}, + "3": {"desc": "Get adhoc challenges", "key": "get_adhoc_challenges"}, + "4": { + "desc": "Get available badge challenges", + "key": "get_available_badge_challenges", + }, + "5": {"desc": "Get active goals", "key": "get_active_goals"}, + "6": {"desc": "Get future goals", "key": "get_future_goals"}, + "7": {"desc": "Get past goals", "key": "get_past_goals"}, + "8": {"desc": "Get badge challenges", "key": "get_badge_challenges"}, + "9": { + "desc": "Get non-completed badge challenges", + "key": "get_non_completed_badge_challenges", + }, + "0": { + "desc": "Get virtual challenges in progress", + "key": "get_inprogress_virtual_challenges", + }, + "a": {"desc": "Get race predictions", "key": "get_race_predictions"}, + "b": { + "desc": f"Get hill score from '{config.week_start.isoformat()}' to '{config.today.isoformat()}'", + "key": "get_hill_score", + }, + "c": { + "desc": f"Get endurance score from '{config.week_start.isoformat()}' to '{config.today.isoformat()}'", + "key": "get_endurance_score", + }, + "d": {"desc": "Get available badges", "key": "get_available_badges"}, + "e": {"desc": "Get badges in progress", "key": "get_in_progress_badges"}, + }, + }, + "8": { + "name": "⌚ Device & Technical", + "options": { + "1": {"desc": "Get all device information", "key": "get_devices"}, + "2": {"desc": "Get device alarms", "key": "get_device_alarms"}, + "3": {"desc": "Get solar data from your devices", "key": "get_solar_data"}, + "4": { + "desc": f"Request data reload (epoch) for '{config.today.isoformat()}'", + "key": "request_reload", + }, + "5": {"desc": "Get device settings", "key": "get_device_settings"}, + "6": {"desc": "Get device last used", "key": "get_device_last_used"}, + "7": { + "desc": "Get primary training device", + "key": "get_primary_training_device", + }, + }, + }, + "9": { + "name": "🎽 Gear & Equipment", + "options": { + "1": {"desc": "Get user gear list", "key": "get_gear"}, + "2": {"desc": "Get gear defaults", "key": "get_gear_defaults"}, + "3": {"desc": "Get gear statistics", "key": "get_gear_stats"}, + "4": {"desc": "Get gear activities", "key": "get_gear_activities"}, + "5": {"desc": "Set gear default", "key": "set_gear_default"}, + "6": { + "desc": "Track gear usage (total time used)", + "key": "track_gear_usage", + }, + }, + }, + "0": { + "name": "💧 Hydration & Wellness", + "options": { + "1": { + "desc": f"Get hydration data for '{config.today.isoformat()}'", + "key": "get_hydration_data", + }, + "2": {"desc": "Add hydration data", "key": "add_hydration_data"}, + "3": { + "desc": "Set blood pressure and pulse (interactive)", + "key": "set_blood_pressure", + }, + "4": {"desc": "Get pregnancy summary data", "key": "get_pregnancy_summary"}, + "5": { + "desc": f"Get all day events for '{config.week_start.isoformat()}'", + "key": "get_all_day_events", + }, + "6": { + "desc": f"Get body battery events for '{config.week_start.isoformat()}'", + "key": "get_body_battery_events", + }, + "7": { + "desc": f"Get menstrual data for '{config.today.isoformat()}'", + "key": "get_menstrual_data_for_date", + }, + "8": { + "desc": f"Get menstrual calendar from '{config.week_start.isoformat()}' to '{config.today.isoformat()}'", + "key": "get_menstrual_calendar_data", + }, + "9": { + "desc": "Delete blood pressure entry", + "key": "delete_blood_pressure", + }, + }, + }, + "a": { + "name": "🔧 System & Export", + "options": { + "1": {"desc": "Create sample health report", "key": "create_health_report"}, + "2": { + "desc": "Remove stored login tokens (logout)", + "key": "remove_tokens", + }, + "3": {"desc": "Disconnect from Garmin Connect", "key": "disconnect"}, + "4": {"desc": "Execute GraphQL query", "key": "query_garmin_graphql"}, + }, + }, +} + +current_category = None + + +def print_main_menu(): + """Print the main category menu.""" + print("\n" + "=" * 50) + print("🚴 Full-blown Garmin Connect API Demo - Main Menu") + print("=" * 50) + print("Select a category:") + print() + + for key, category in menu_categories.items(): + print(f" [{key}] {category['name']}") + + print() + print(" [q] Exit program") + print() + print("Make your selection: ", end="", flush=True) + + +def print_category_menu(category_key: str): + """Print options for a specific category.""" + if category_key not in menu_categories: + return False + + category = menu_categories[category_key] + print(f"\n📋 #{category_key} {category['name']} - Options") + print("-" * 40) + + for key, option in category["options"].items(): + print(f" [{key}] {option['desc']}") + + print() + print(" [q] Back to main menu") + print() + print("Make your selection: ", end="", flush=True) + return True + + +def get_mfa() -> str: + """Get MFA token.""" + return input("MFA one-time code: ") + + +class DataExporter: + """Utilities for exporting data in various formats.""" + + @staticmethod + def save_json(data: Any, filename: str, pretty: bool = True) -> str: + """Save data as JSON file.""" + filepath = config.export_dir / f"{filename}.json" + with open(filepath, "w", encoding="utf-8") as f: + if pretty: + json.dump(data, f, indent=4, default=str, ensure_ascii=False) + else: + json.dump(data, f, default=str, ensure_ascii=False) + return str(filepath) + + @staticmethod + def create_health_report(api_instance: Garmin) -> str: + """Create a comprehensive health report in JSON and HTML formats.""" + report_data = { + "generated_at": datetime.datetime.now().isoformat(), + "user_info": {"full_name": "N/A", "unit_system": "N/A"}, + "today_summary": {}, + "recent_activities": [], + "health_metrics": {}, + "weekly_data": [], + "device_info": [], + } + + try: + # Basic user info + report_data["user_info"]["full_name"] = ( + api_instance.get_full_name() or "N/A" + ) + report_data["user_info"]["unit_system"] = ( + api_instance.get_unit_system() or "N/A" + ) + + # Today's summary + today_str = config.today.isoformat() + report_data["today_summary"] = api_instance.get_user_summary(today_str) + + # Recent activities + recent_activities = api_instance.get_activities(0, 10) + report_data["recent_activities"] = recent_activities or [] + + # Weekly data for trends + for i in range(7): + date = config.today - datetime.timedelta(days=i) + try: + daily_data = api_instance.get_user_summary(date.isoformat()) + if daily_data: + daily_data["date"] = date.isoformat() + report_data["weekly_data"].append(daily_data) + except Exception as e: + print( + f"Skipping data for {date.isoformat()}: {e}" + ) # Skip if data not available + + # Health metrics for today + health_metrics = {} + metrics_to_fetch = [ + ("heart_rate", lambda: api_instance.get_heart_rates(today_str)), + ("steps", lambda: api_instance.get_steps_data(today_str)), + ("sleep", lambda: api_instance.get_sleep_data(today_str)), + ("stress", lambda: api_instance.get_all_day_stress(today_str)), + ( + "body_battery", + lambda: api_instance.get_body_battery( + config.week_start.isoformat(), today_str + ), + ), + ] + + for metric_name, fetch_func in metrics_to_fetch: + try: + health_metrics[metric_name] = fetch_func() + except Exception: + health_metrics[metric_name] = None + + report_data["health_metrics"] = health_metrics + + # Device information + try: + report_data["device_info"] = api_instance.get_devices() + except Exception: + report_data["device_info"] = [] + + except Exception as e: + print(f"Error creating health report: {e}") + + # Create HTML version + html_filepath = DataExporter.create_readable_health_report(report_data) + + print(f"📊 Report created: {html_filepath}") + + return html_filepath + + @staticmethod + def create_readable_health_report(report_data: dict) -> str: + """Create a readable HTML report from comprehensive health data.""" + timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") + html_filename = f"health_report_{timestamp}.html" + + # Extract key information + user_name = report_data.get("user_info", {}).get("full_name", "Unknown User") + generated_at = report_data.get("generated_at", "Unknown") + + # Create HTML content with complete styling + html_content = f""" + + + + + Garmin Health Report - {user_name} + + + +
+
+

🏃 Garmin Health Report

+

{user_name}

+
+ +
+

Generated: {generated_at}

+

Date: {config.today.isoformat()}

+
+""" + + # Today's Summary Section + today_summary = report_data.get("today_summary", {}) + if today_summary: + steps = today_summary.get("totalSteps", 0) + calories = today_summary.get("totalKilocalories", 0) + distance = ( + round(today_summary.get("totalDistanceMeters", 0) / 1000, 2) + if today_summary.get("totalDistanceMeters") + else 0 + ) + active_calories = today_summary.get("activeKilocalories", 0) + + html_content += f""" +
+

📈 Today's Activity Summary

+
+
+

👟 Steps

+
{steps:,} steps
+
+
+

🔥 Calories

+
{calories:,} total
+
{active_calories:,} active
+
+
+

📏 Distance

+
{distance} km
+
+
+
+""" + else: + html_content += """ +
+

📈 Today's Activity Summary

+
No activity data available for today
+
+""" + + # Health Metrics Section + health_metrics = report_data.get("health_metrics", {}) + if health_metrics and any(health_metrics.values()): + html_content += """ +
+

❤️ Health Metrics

+
+""" + + # Heart Rate + heart_rate = health_metrics.get("heart_rate", {}) + if heart_rate and isinstance(heart_rate, dict): + resting_hr = heart_rate.get("restingHeartRate", "N/A") + max_hr = heart_rate.get("maxHeartRate", "N/A") + html_content += f""" +
+

💓 Heart Rate

+
{resting_hr} bpm (resting)
+
Max: {max_hr} bpm
+
+""" + + # Sleep Data + sleep_data = health_metrics.get("sleep", {}) + if ( + sleep_data + and isinstance(sleep_data, dict) + and "dailySleepDTO" in sleep_data + ): + sleep_seconds = sleep_data["dailySleepDTO"].get("sleepTimeSeconds", 0) + sleep_hours = round(sleep_seconds / 3600, 1) if sleep_seconds else 0 + deep_sleep = sleep_data["dailySleepDTO"].get("deepSleepSeconds", 0) + deep_hours = round(deep_sleep / 3600, 1) if deep_sleep else 0 + + html_content += f""" +
+

😴 Sleep

+
{sleep_hours} hours
+
Deep Sleep: {deep_hours} hours
+
+""" + + # Steps + steps_data = health_metrics.get("steps", {}) + if steps_data and isinstance(steps_data, dict): + total_steps = steps_data.get("totalSteps", 0) + goal = steps_data.get("dailyStepGoal", 10000) + html_content += f""" +
+

🎯 Step Goal

+
{total_steps:,} of {goal:,}
+
Goal: {round((total_steps/goal)*100) if goal else 0}%
+
+""" + + # Stress Data + stress_data = health_metrics.get("stress", {}) + if stress_data and isinstance(stress_data, dict): + avg_stress = stress_data.get("avgStressLevel", "N/A") + max_stress = stress_data.get("maxStressLevel", "N/A") + html_content += f""" +
+

😰 Stress Level

+
{avg_stress} avg
+
Max: {max_stress}
+
+""" + + # Body Battery + body_battery = health_metrics.get("body_battery", []) + if body_battery and isinstance(body_battery, list) and body_battery: + latest_bb = body_battery[-1] if body_battery else {} + charged = latest_bb.get("charged", "N/A") + drained = latest_bb.get("drained", "N/A") + html_content += f""" +
+

🔋 Body Battery

+
+{charged} charged
+
-{drained} drained
+
+""" + + html_content += "
\n
\n" + else: + html_content += """ +
+

❤️ Health Metrics

+
No health metrics data available
+
+""" + + # Weekly Trends Section + weekly_data = report_data.get("weekly_data", []) + if weekly_data: + html_content += """ +
+

📊 Weekly Trends (Last 7 Days)

+
+""" + for daily in weekly_data[:7]: # Show last 7 days + date = daily.get("date", "Unknown") + steps = daily.get("totalSteps", 0) + calories = daily.get("totalKilocalories", 0) + distance = ( + round(daily.get("totalDistanceMeters", 0) / 1000, 2) + if daily.get("totalDistanceMeters") + else 0 + ) + + html_content += f""" +
+

📅 {date}

+
{steps:,} steps
+
+
{calories:,} kcal
+
{distance} km
+
+
+""" + html_content += "
\n
\n" + + # Recent Activities Section + activities = report_data.get("recent_activities", []) + if activities: + html_content += """ +
+

🏃 Recent Activities

+""" + for activity in activities[:5]: # Show last 5 activities + name = activity.get("activityName", "Unknown Activity") + activity_type = activity.get("activityType", {}).get( + "typeKey", "Unknown" + ) + date = ( + activity.get("startTimeLocal", "").split("T")[0] + if activity.get("startTimeLocal") + else "Unknown" + ) + duration = activity.get("duration", 0) + duration_min = round(duration / 60, 1) if duration else 0 + distance = ( + round(activity.get("distance", 0) / 1000, 2) + if activity.get("distance") + else 0 + ) + calories = activity.get("calories", 0) + avg_hr = activity.get("avgHR", 0) + + html_content += f""" +
+

{name} ({activity_type})

+
+
Date: {date}
+
Duration: {duration_min} min
+
Distance: {distance} km
+
Calories: {calories}
+
Avg HR: {avg_hr} bpm
+
+
+""" + html_content += "
\n" + else: + html_content += """ +
+

🏃 Recent Activities

+
No recent activities found
+
+""" + + # Device Information + device_info = report_data.get("device_info", []) + if device_info: + html_content += """ +
+

⌚ Device Information

+
+""" + for device in device_info: + device_name = device.get("displayName", "Unknown Device") + model = device.get("productDisplayName", "Unknown Model") + version = device.get("softwareVersion", "Unknown") + + html_content += f""" +
+

{device_name}

+
Model: {model}
+
Software: {version}
+
+""" + html_content += "
\n
\n" + + # Footer + html_content += f""" + +
+ + +""" + + # Save HTML file + html_filepath = config.export_dir / html_filename + with open(html_filepath, "w", encoding="utf-8") as f: + f.write(html_content) + + return str(html_filepath) + + +def safe_api_call(api_method, *args, method_name: str = None, **kwargs): + """ + Centralized API call wrapper with comprehensive error handling. + + This function provides unified error handling for all Garmin Connect API calls. + It handles common HTTP errors (400, 401, 403, 404, 429, 500, 503) with + user-friendly messages and provides consistent error reporting. + + Usage: + success, result, error_msg = safe_api_call(api.get_user_summary) + + Args: + api_method: The API method to call + *args: Positional arguments for the API method + method_name: Human-readable name for the API method (optional) + **kwargs: Keyword arguments for the API method + + Returns: + tuple: (success: bool, result: Any, error_message: str|None) + """ + if method_name is None: + method_name = getattr(api_method, "__name__", str(api_method)) + + try: + result = api_method(*args, **kwargs) + return True, result, None + + except GarthHTTPError as e: + # Handle specific HTTP errors more gracefully + error_str = str(e) + + # Extract status code more reliably + status_code = None + if hasattr(e, "response") and hasattr(e.response, "status_code"): + status_code = e.response.status_code + + # Handle specific status codes + if status_code == 400 or ("400" in error_str and "Bad Request" in error_str): + error_msg = "Endpoint not available (400 Bad Request) - This feature may not be enabled for your account or region" + # Don't print for 400 errors as they're often expected for unavailable features + elif status_code == 401 or "401" in error_str: + error_msg = ( + "Authentication required (401 Unauthorized) - Please re-authenticate" + ) + print(f"⚠️ {method_name} failed: {error_msg}") + elif status_code == 403 or "403" in error_str: + error_msg = "Access denied (403 Forbidden) - Your account may not have permission for this feature" + print(f"⚠️ {method_name} failed: {error_msg}") + elif status_code == 404 or "404" in error_str: + error_msg = ( + "Endpoint not found (404) - This feature may have been moved or removed" + ) + print(f"⚠️ {method_name} failed: {error_msg}") + elif status_code == 429 or "429" in error_str: + error_msg = ( + "Rate limit exceeded (429) - Please wait before making more requests" + ) + print(f"⚠️ {method_name} failed: {error_msg}") + elif status_code == 500 or "500" in error_str: + error_msg = "Server error (500) - Garmin's servers are experiencing issues" + print(f"⚠️ {method_name} failed: {error_msg}") + elif status_code == 503 or "503" in error_str: + error_msg = "Service unavailable (503) - Garmin's servers are temporarily unavailable" + print(f"⚠️ {method_name} failed: {error_msg}") + else: + error_msg = f"HTTP error: {e}" + + print(f"⚠️ {method_name} failed: {error_msg}") + return False, None, error_msg + + except GarminConnectAuthenticationError as e: + error_msg = f"Authentication issue: {e}" + print(f"⚠️ {method_name} failed: {error_msg}") + return False, None, error_msg + + except GarminConnectConnectionError as e: + error_msg = f"Connection issue: {e}" + print(f"⚠️ {method_name} failed: {error_msg}") + return False, None, error_msg + + except Exception as e: + error_msg = f"Unexpected error: {e}" + print(f"⚠️ {method_name} failed: {error_msg}") + return False, None, error_msg + + +def call_and_display( + api_method=None, + *args, + method_name: str = None, + api_call_desc: str = None, + group_name: str = None, + api_responses: list = None, + **kwargs, +): + """ + Unified wrapper that calls API methods safely and displays results. + Can handle both single API calls and grouped API responses. + + For single API calls: + call_and_display(api.get_user_summary, "2024-01-01") + + For grouped responses: + call_and_display(group_name="User Data", api_responses=[("api.get_user", data)]) + + Args: + api_method: The API method to call (for single calls) + *args: Positional arguments for the API method + method_name: Human-readable name for the API method (optional) + api_call_desc: Description for display purposes (optional) + group_name: Name for grouped display (when displaying multiple responses) + api_responses: List of (api_call_desc, result) tuples for grouped display + **kwargs: Keyword arguments for the API method + + Returns: + For single calls: tuple: (success: bool, result: Any) + For grouped calls: None + """ + # Handle grouped display mode + if group_name is not None and api_responses is not None: + return _display_group(group_name, api_responses) + + # Handle single API call mode + if api_method is None: + raise ValueError( + "Either api_method or (group_name + api_responses) must be provided" + ) + + if method_name is None: + method_name = getattr(api_method, "__name__", str(api_method)) + + if api_call_desc is None: + # Try to construct a reasonable description + args_str = ", ".join(str(arg) for arg in args) + kwargs_str = ", ".join(f"{k}={v}" for k, v in kwargs.items()) + all_args = ", ".join(filter(None, [args_str, kwargs_str])) + api_call_desc = f"{method_name}({all_args})" + + success, result, error_msg = safe_api_call( + api_method, *args, method_name=method_name, **kwargs + ) + + if success: + _display_single(api_call_desc, result) + return True, result + else: + # Display error in a consistent format + _display_single(f"{api_call_desc} [ERROR]", {"error": error_msg}) + return False, None + + +def _display_single(api_call: str, output: Any): + """Internal function to display single API response.""" + print(f"\n📡 API Call: {api_call}") + print("-" * 50) + + if output is None: + print("No data returned") + # Save empty JSON to response.json in the export directory + response_file = config.export_dir / "response.json" + with open(response_file, "w", encoding="utf-8") as f: + f.write(f"{'-' * 20} {api_call} {'-' * 20}\n{{}}\n{'-' * 77}\n") + return + + try: + # Format the output + if isinstance(output, int | str | dict | list): + formatted_output = json.dumps(output, indent=2, default=str) + else: + formatted_output = str(output) + + # Save to response.json in the export directory + response_content = ( + f"{'-' * 20} {api_call} {'-' * 20}\n{formatted_output}\n{'-' * 77}\n" + ) + + response_file = config.export_dir / "response.json" + with open(response_file, "w", encoding="utf-8") as f: + f.write(response_content) + + print(formatted_output) + print("-" * 77) + + except Exception as e: + print(f"Error formatting output: {e}") + print(output) + + +def _display_group(group_name: str, api_responses: list[tuple[str, Any]]): + """Internal function to display grouped API responses.""" + print(f"\n📡 API Group: {group_name}") + + # Collect all responses for saving + all_responses = {} + response_content_parts = [] + + for api_call, output in api_responses: + print(f"\n📋 {api_call}") + print("-" * 50) + + if output is None: + print("No data returned") + formatted_output = "{}" + else: + try: + if isinstance(output, int | str | dict | list): + formatted_output = json.dumps(output, indent=2, default=str) + else: + formatted_output = str(output) + print(formatted_output) + except Exception as e: + print(f"Error formatting output: {e}") + formatted_output = str(output) + print(output) + + # Store for grouped response file + all_responses[api_call] = output + response_content_parts.append( + f"{'-' * 20} {api_call} {'-' * 20}\n{formatted_output}" + ) + print("-" * 50) + + # Save grouped responses to file + try: + response_file = config.export_dir / "response.json" + grouped_content = f"""{'=' * 20} {group_name} {'=' * 20} +{chr(10).join(response_content_parts)} +{'=' * 77} +""" + with open(response_file, "w", encoding="utf-8") as f: + f.write(grouped_content) + + print(f"\n✅ Grouped responses saved to: {response_file}") + print("=" * 77) + + except Exception as e: + print(f"Error saving grouped responses: {e}") + + +# Legacy function aliases removed - all calls now use the unified call_and_display function + + +def format_timedelta(td): + minutes, seconds = divmod(td.seconds + td.days * 86400, 60) + hours, minutes = divmod(minutes, 60) + return f"{hours:d}:{minutes:02d}:{seconds:02d}" + + +def safe_call_for_group( + api_method, *args, method_name: str = None, api_call_desc: str = None, **kwargs +): + """ + Safe API call wrapper that returns result suitable for grouped display. + + Args: + api_method: The API method to call + *args: Positional arguments for the API method + method_name: Human-readable name for the API method (optional) + api_call_desc: Description for display purposes (optional) + **kwargs: Keyword arguments for the API method + + Returns: + tuple: (api_call_description: str, result: Any) - suitable for grouped display + """ + if method_name is None: + method_name = getattr(api_method, "__name__", str(api_method)) + + if api_call_desc is None: + # Try to construct a reasonable description + args_str = ", ".join(str(arg) for arg in args) + kwargs_str = ", ".join(f"{k}={v}" for k, v in kwargs.items()) + all_args = ", ".join(filter(None, [args_str, kwargs_str])) + api_call_desc = f"{method_name}({all_args})" + + success, result, error_msg = safe_api_call( + api_method, *args, method_name=method_name, **kwargs + ) + + if success: + return api_call_desc, result + else: + return f"{api_call_desc} [ERROR]", {"error": error_msg} + + +def get_solar_data(api: Garmin) -> None: + """Get solar data from all Garmin devices using centralized error handling.""" + print("☀️ Getting solar data from devices...") + + # Collect all API responses for grouped display + api_responses = [] + + # Get all devices using centralized wrapper + api_responses.append( + safe_call_for_group( + api.get_devices, + method_name="get_devices", + api_call_desc="api.get_devices()", + ) + ) + + # Get device last used using centralized wrapper + api_responses.append( + safe_call_for_group( + api.get_device_last_used, + method_name="get_device_last_used", + api_call_desc="api.get_device_last_used()", + ) + ) + + # Get the device list to process solar data + devices_success, devices, _ = safe_api_call( + api.get_devices, method_name="get_devices" + ) + + # Get solar data for each device + if devices_success and devices: + for device in devices: + device_id = device.get("deviceId") + if device_id: + device_name = device.get("displayName", f"Device {device_id}") + print( + f"\n☀️ Getting solar data for device: {device_name} (ID: {device_id})" + ) + + # Use centralized wrapper for each device's solar data + api_responses.append( + safe_call_for_group( + api.get_device_solar_data, + device_id, + config.today.isoformat(), + method_name="get_device_solar_data", + api_call_desc=f"api.get_device_solar_data({device_id}, '{config.today.isoformat()}')", + ) + ) + else: + print("ℹ️ No devices found or error retrieving devices") + + # Display all responses as a group + call_and_display(group_name="Solar Data Collection", api_responses=api_responses) + + +def upload_activity_file(api: Garmin) -> None: + """Upload activity data from file.""" + try: + # Default activity file from config + print(f"📤 Uploading activity from file: {config.activityfile}") + + # Check if file exists + import os + + if not os.path.exists(config.activityfile): + print(f"❌ File not found: {config.activityfile}") + print( + "ℹ️ Please place your activity file (.fit, .gpx, or .tcx) under the 'test_data' directory or update config.activityfile" + ) + print("ℹ️ Supported formats: FIT, GPX, TCX") + return + + # Upload the activity + result = api.upload_activity(config.activityfile) + + if result: + print("✅ Activity uploaded successfully!") + call_and_display( + api.upload_activity, + config.activityfile, + method_name="upload_activity", + api_call_desc=f"api.upload_activity({config.activityfile})", + ) + else: + print(f"❌ Failed to upload activity from {config.activityfile}") + + except FileNotFoundError: + print(f"❌ File not found: {config.activityfile}") + print("ℹ️ Please ensure the activity file exists in the current directory") + except requests.exceptions.HTTPError as e: + if e.response.status_code == 409: + print( + "⚠️ Activity already exists: This activity has already been uploaded to Garmin Connect" + ) + print("ℹ️ Garmin Connect prevents duplicate activities from being uploaded") + print( + "💡 Try modifying the activity timestamps or creating a new activity file" + ) + elif e.response.status_code == 413: + print( + "❌ File too large: The activity file exceeds Garmin Connect's size limit" + ) + print("💡 Try compressing the file or reducing the number of data points") + elif e.response.status_code == 422: + print( + "❌ Invalid file format: The activity file format is not supported or corrupted" + ) + print("ℹ️ Supported formats: FIT, GPX, TCX") + print("💡 Try converting to a different format or check file integrity") + elif e.response.status_code == 400: + print("❌ Bad request: Invalid activity data or malformed file") + print( + "💡 Check if the activity file contains valid GPS coordinates and timestamps" + ) + elif e.response.status_code == 401: + print("❌ Authentication failed: Please login again") + print("💡 Your session may have expired") + elif e.response.status_code == 429: + print("❌ Rate limit exceeded: Too many upload requests") + print("💡 Please wait a few minutes before trying again") + else: + print(f"❌ HTTP Error {e.response.status_code}: {e}") + except GarminConnectAuthenticationError as e: + print(f"❌ Authentication error: {e}") + print("💡 Please check your login credentials and try again") + except GarminConnectConnectionError as e: + print(f"❌ Connection error: {e}") + print("💡 Please check your internet connection and try again") + except GarminConnectTooManyRequestsError as e: + print(f"❌ Too many requests: {e}") + print("💡 Please wait a few minutes before trying again") + except Exception as e: + # Check if this is a wrapped HTTP error from the Garmin library + error_str = str(e) + if "409 Client Error: Conflict" in error_str: + print( + "⚠️ Activity already exists: This activity has already been uploaded to Garmin Connect" + ) + print("ℹ️ Garmin Connect prevents duplicate activities from being uploaded") + print( + "💡 Try modifying the activity timestamps or creating a new activity file" + ) + elif "413" in error_str and "Request Entity Too Large" in error_str: + print( + "❌ File too large: The activity file exceeds Garmin Connect's size limit" + ) + print("💡 Try compressing the file or reducing the number of data points") + elif "422" in error_str and "Unprocessable Entity" in error_str: + print( + "❌ Invalid file format: The activity file format is not supported or corrupted" + ) + print("ℹ️ Supported formats: FIT, GPX, TCX") + print("💡 Try converting to a different format or check file integrity") + elif "400" in error_str and "Bad Request" in error_str: + print("❌ Bad request: Invalid activity data or malformed file") + print( + "💡 Check if the activity file contains valid GPS coordinates and timestamps" + ) + elif "401" in error_str and "Unauthorized" in error_str: + print("❌ Authentication failed: Please login again") + print("💡 Your session may have expired") + elif "429" in error_str and "Too Many Requests" in error_str: + print("❌ Rate limit exceeded: Too many upload requests") + print("💡 Please wait a few minutes before trying again") + else: + print(f"❌ Unexpected error uploading activity: {e}") + print("💡 Please check the file format and try again") + + +def download_activities_by_date(api: Garmin) -> None: + """Download activities by date range in multiple formats.""" + try: + print( + f"📥 Downloading activities by date range ({config.week_start.isoformat()} to {config.today.isoformat()})..." + ) + + # Get activities for the date range (last 7 days as default) + activities = api.get_activities_by_date( + config.week_start.isoformat(), config.today.isoformat() + ) + + if not activities: + print("ℹ️ No activities found in the specified date range") + return + + print(f"📊 Found {len(activities)} activities to download") + + # Download each activity in multiple formats + for activity in activities: + activity_id = activity.get("activityId") + activity_name = activity.get("activityName", "Unknown") + start_time = activity.get("startTimeLocal", "").replace(":", "-") + + if not activity_id: + continue + + print(f"📥 Downloading: {activity_name} (ID: {activity_id})") + + # Download formats: GPX, TCX, ORIGINAL, CSV + formats = ["GPX", "TCX", "ORIGINAL", "CSV"] + + for fmt in formats: + try: + filename = f"{start_time}_{activity_id}_ACTIVITY.{fmt.lower()}" + if fmt == "ORIGINAL": + filename = f"{start_time}_{activity_id}_ACTIVITY.zip" + + filepath = config.export_dir / filename + + if fmt == "CSV": + # Get activity details for CSV export + activity_details = api.get_activity_details(activity_id) + with open(filepath, "w", encoding="utf-8") as f: + import json + + json.dump(activity_details, f, indent=2, ensure_ascii=False) + print(f" ✅ {fmt}: {filename}") + else: + # Download the file from Garmin using proper enum values + format_mapping = { + "GPX": api.ActivityDownloadFormat.GPX, + "TCX": api.ActivityDownloadFormat.TCX, + "ORIGINAL": api.ActivityDownloadFormat.ORIGINAL, + } + + dl_fmt = format_mapping[fmt] + content = api.download_activity(activity_id, dl_fmt=dl_fmt) + + if content: + with open(filepath, "wb") as f: + f.write(content) + print(f" ✅ {fmt}: {filename}") + else: + print(f" ❌ {fmt}: No content available") + + except Exception as e: + print(f" ❌ {fmt}: Error downloading - {e}") + + print(f"✅ Activity downloads completed! Files saved to: {config.export_dir}") + + except Exception as e: + print(f"❌ Error downloading activities: {e}") + + +def add_weigh_in_data(api: Garmin) -> None: + """Add a weigh-in with timestamps.""" + try: + # Get weight input from user + print("⚖️ Adding weigh-in entry") + print("-" * 30) + + # Weight input with validation + while True: + try: + weight_str = input("Enter weight (30-300, default: 85.1): ").strip() + if not weight_str: + weight = 85.1 + break + weight = float(weight_str) + if 30 <= weight <= 300: + break + else: + print("❌ Weight must be between 30 and 300") + except ValueError: + print("❌ Please enter a valid number") + + # Unit selection + while True: + unit_input = input("Enter unit (kg/lbs, default: kg): ").strip().lower() + if not unit_input: + weight_unit = "kg" + break + elif unit_input in ["kg", "lbs"]: + weight_unit = unit_input + break + else: + print("❌ Please enter 'kg' or 'lbs'") + + print(f"⚖️ Adding weigh-in: {weight} {weight_unit}") + + # Collect all API responses for grouped display + api_responses = [] + + # Add a simple weigh-in + result1 = api.add_weigh_in(weight=weight, unitKey=weight_unit) + api_responses.append( + (f"api.add_weigh_in(weight={weight}, unitKey={weight_unit})", result1) + ) + + # Add a weigh-in with timestamps for yesterday + import datetime + from datetime import timezone + + yesterday = config.today - datetime.timedelta(days=1) # Get yesterday's date + weigh_in_date = datetime.datetime.strptime(yesterday.isoformat(), "%Y-%m-%d") + local_timestamp = weigh_in_date.strftime("%Y-%m-%dT%H:%M:%S") + gmt_timestamp = weigh_in_date.astimezone(timezone.utc).strftime( + "%Y-%m-%dT%H:%M:%S" + ) + + result2 = api.add_weigh_in_with_timestamps( + weight=weight, + unitKey=weight_unit, + dateTimestamp=local_timestamp, + gmtTimestamp=gmt_timestamp, + ) + api_responses.append( + ( + f"api.add_weigh_in_with_timestamps(weight={weight}, unitKey={weight_unit}, dateTimestamp={local_timestamp}, gmtTimestamp={gmt_timestamp})", + result2, + ) + ) + + # Display all responses as a group + call_and_display(group_name="Weigh-in Data Entry", api_responses=api_responses) + + print("✅ Weigh-in data added successfully!") + + except Exception as e: + print(f"❌ Error adding weigh-in: {e}") + + +# Helper functions for the new API methods +def get_lactate_threshold_data(api: Garmin) -> None: + """Get lactate threshold data.""" + try: + # Collect all API responses for grouped display + api_responses = [] + + # Get latest lactate threshold + latest = api.get_lactate_threshold(latest=True) + api_responses.append(("api.get_lactate_threshold(latest=True)", latest)) + + # Get historical lactate threshold for past four weeks + four_weeks_ago = config.today - datetime.timedelta(days=28) + historical = api.get_lactate_threshold( + latest=False, + start_date=four_weeks_ago.isoformat(), + end_date=config.today.isoformat(), + aggregation="daily", + ) + api_responses.append( + ( + f"api.get_lactate_threshold(latest=False, start_date='{four_weeks_ago.isoformat()}', end_date='{config.today.isoformat()}', aggregation='daily')", + historical, + ) + ) + + # Display all responses as a group + call_and_display( + group_name="Lactate Threshold Data", api_responses=api_responses + ) + + except Exception as e: + print(f"❌ Error getting lactate threshold data: {e}") + + +def get_activity_splits_data(api: Garmin) -> None: + """Get activity splits for the last activity.""" + try: + activities = api.get_activities(0, 1) + if activities: + activity_id = activities[0]["activityId"] + call_and_display( + api.get_activity_splits, + activity_id, + method_name="get_activity_splits", + api_call_desc=f"api.get_activity_splits({activity_id})", + ) + else: + print("ℹ️ No activities found") + except Exception as e: + print(f"❌ Error getting activity splits: {e}") + + +def get_activity_typed_splits_data(api: Garmin) -> None: + """Get activity typed splits for the last activity.""" + try: + activities = api.get_activities(0, 1) + if activities: + activity_id = activities[0]["activityId"] + call_and_display( + api.get_activity_typed_splits, + activity_id, + method_name="get_activity_typed_splits", + api_call_desc=f"api.get_activity_typed_splits({activity_id})", + ) + else: + print("ℹ️ No activities found") + except Exception as e: + print(f"❌ Error getting activity typed splits: {e}") + + +def get_activity_split_summaries_data(api: Garmin) -> None: + """Get activity split summaries for the last activity.""" + try: + activities = api.get_activities(0, 1) + if activities: + activity_id = activities[0]["activityId"] + call_and_display( + api.get_activity_split_summaries, + activity_id, + method_name="get_activity_split_summaries", + api_call_desc=f"api.get_activity_split_summaries({activity_id})", + ) + else: + print("ℹ️ No activities found") + except Exception as e: + print(f"❌ Error getting activity split summaries: {e}") + + +def get_activity_weather_data(api: Garmin) -> None: + """Get activity weather data for the last activity.""" + try: + activities = api.get_activities(0, 1) + if activities: + activity_id = activities[0]["activityId"] + call_and_display( + api.get_activity_weather, + activity_id, + method_name="get_activity_weather", + api_call_desc=f"api.get_activity_weather({activity_id})", + ) + else: + print("ℹ️ No activities found") + except Exception as e: + print(f"❌ Error getting activity weather: {e}") + + +def get_activity_hr_timezones_data(api: Garmin) -> None: + """Get activity heart rate timezones for the last activity.""" + try: + activities = api.get_activities(0, 1) + if activities: + activity_id = activities[0]["activityId"] + call_and_display( + api.get_activity_hr_in_timezones, + activity_id, + method_name="get_activity_hr_in_timezones", + api_call_desc=f"api.get_activity_hr_in_timezones({activity_id})", + ) + else: + print("ℹ️ No activities found") + except Exception as e: + print(f"❌ Error getting activity HR timezones: {e}") + + +def get_activity_details_data(api: Garmin) -> None: + """Get detailed activity information for the last activity.""" + try: + activities = api.get_activities(0, 1) + if activities: + activity_id = activities[0]["activityId"] + call_and_display( + api.get_activity_details, + activity_id, + method_name="get_activity_details", + api_call_desc=f"api.get_activity_details({activity_id})", + ) + else: + print("ℹ️ No activities found") + except Exception as e: + print(f"❌ Error getting activity details: {e}") + + +def get_activity_gear_data(api: Garmin) -> None: + """Get activity gear information for the last activity.""" + try: + activities = api.get_activities(0, 1) + if activities: + activity_id = activities[0]["activityId"] + call_and_display( + api.get_activity_gear, + activity_id, + method_name="get_activity_gear", + api_call_desc=f"api.get_activity_gear({activity_id})", + ) + else: + print("ℹ️ No activities found") + except Exception as e: + print(f"❌ Error getting activity gear: {e}") + + +def get_single_activity_data(api: Garmin) -> None: + """Get single activity data for the last activity.""" + try: + activities = api.get_activities(0, 1) + if activities: + activity_id = activities[0]["activityId"] + call_and_display( + api.get_activity, + activity_id, + method_name="get_activity", + api_call_desc=f"api.get_activity({activity_id})", + ) + else: + print("ℹ️ No activities found") + except Exception as e: + print(f"❌ Error getting single activity: {e}") + + +def get_activity_exercise_sets_data(api: Garmin) -> None: + """Get exercise sets for strength training activities.""" + try: + activities = api.get_activities( + 0, 20 + ) # Get more activities to find a strength training one + strength_activity = None + + # Find strength training activities + for activity in activities: + activity_type = activity.get("activityType", {}) + type_key = activity_type.get("typeKey", "") + if "strength" in type_key.lower() or "training" in type_key.lower(): + strength_activity = activity + break + + if strength_activity: + activity_id = strength_activity["activityId"] + call_and_display( + api.get_activity_exercise_sets, + activity_id, + method_name="get_activity_exercise_sets", + api_call_desc=f"api.get_activity_exercise_sets({activity_id})", + ) + else: + # Return empty JSON response + print("ℹ️ No strength training activities found") + except Exception: + print("ℹ️ No activity exercise sets available") + + +def get_workout_by_id_data(api: Garmin) -> None: + """Get workout by ID for the last workout.""" + try: + workouts = api.get_workouts() + if workouts: + workout_id = workouts[-1]["workoutId"] + workout_name = workouts[-1]["workoutName"] + call_and_display( + api.get_workout_by_id, + workout_id, + method_name="get_workout_by_id", + api_call_desc=f"api.get_workout_by_id({workout_id}) - {workout_name}", + ) + else: + print("ℹ️ No workouts found") + except Exception as e: + print(f"❌ Error getting workout by ID: {e}") + + +def download_workout_data(api: Garmin) -> None: + """Download workout to .FIT file.""" + try: + workouts = api.get_workouts() + if workouts: + workout_id = workouts[-1]["workoutId"] + workout_name = workouts[-1]["workoutName"] + + print(f"📥 Downloading workout: {workout_name}") + workout_data = api.download_workout(workout_id) + + if workout_data: + output_file = config.export_dir / f"{workout_name}_{workout_id}.fit" + with open(output_file, "wb") as f: + f.write(workout_data) + print(f"✅ Workout downloaded to: {output_file}") + else: + print("❌ No workout data available") + else: + print("ℹ️ No workouts found") + except Exception as e: + print(f"❌ Error downloading workout: {e}") + + +def upload_workout_data(api: Garmin) -> None: + """Upload workout from JSON file.""" + try: + print(f"📤 Uploading workout from file: {config.workoutfile}") + + # Check if file exists + if not os.path.exists(config.workoutfile): + print(f"❌ File not found: {config.workoutfile}") + print( + "ℹ️ Please ensure the workout JSON file exists in the test_data directory" + ) + return + + # Load the workout JSON data + import json + + with open(config.workoutfile, encoding="utf-8") as f: + workout_data = json.load(f) + + # Get current timestamp in Garmin format + current_time = datetime.datetime.now() + garmin_timestamp = current_time.strftime("%Y-%m-%dT%H:%M:%S.0") + + # Remove IDs that shouldn't be included when uploading a new workout + fields_to_remove = ["workoutId", "ownerId", "updatedDate", "createdDate"] + for field in fields_to_remove: + if field in workout_data: + del workout_data[field] + + # Add current timestamps + workout_data["createdDate"] = garmin_timestamp + workout_data["updatedDate"] = garmin_timestamp + + # Remove step IDs to ensure new ones are generated + def clean_step_ids(workout_segments): + """Recursively remove step IDs from workout structure.""" + if isinstance(workout_segments, list): + for segment in workout_segments: + clean_step_ids(segment) + elif isinstance(workout_segments, dict): + # Remove stepId if present + if "stepId" in workout_segments: + del workout_segments["stepId"] + + # Recursively clean nested structures + if "workoutSteps" in workout_segments: + clean_step_ids(workout_segments["workoutSteps"]) + + # Handle any other nested lists or dicts + for _key, value in workout_segments.items(): + if isinstance(value, list | dict): + clean_step_ids(value) + + # Clean step IDs from workout segments + if "workoutSegments" in workout_data: + clean_step_ids(workout_data["workoutSegments"]) + + # Update workout name to indicate it's uploaded with current timestamp + original_name = workout_data.get("workoutName", "Workout") + workout_data["workoutName"] = ( + f"Uploaded {original_name} - {current_time.strftime('%Y-%m-%d %H:%M:%S')}" + ) + + print(f"📤 Uploading workout: {workout_data['workoutName']}") + + # Upload the workout + result = api.upload_workout(workout_data) + + if result: + print("✅ Workout uploaded successfully!") + call_and_display( + lambda: result, # Use a lambda to pass the result + method_name="upload_workout", + api_call_desc="api.upload_workout(workout_data)", + ) + else: + print(f"❌ Failed to upload workout from {config.workoutfile}") + + except FileNotFoundError: + print(f"❌ File not found: {config.workoutfile}") + print("ℹ️ Please ensure the workout JSON file exists in the test_data directory") + except json.JSONDecodeError as e: + print(f"❌ Invalid JSON format in {config.workoutfile}: {e}") + print("ℹ️ Please check the JSON file format") + except Exception as e: + print(f"❌ Error uploading workout: {e}") + # Check for common upload errors + error_str = str(e) + if "400" in error_str: + print("💡 The workout data may be invalid or malformed") + elif "401" in error_str: + print("💡 Authentication failed - please login again") + elif "403" in error_str: + print("💡 Permission denied - check account permissions") + elif "409" in error_str: + print("💡 Workout may already exist") + elif "422" in error_str: + print("💡 Workout data validation failed") + + +def set_body_composition_data(api: Garmin) -> None: + """Set body composition data.""" + try: + print(f"⚖️ Setting body composition data for {config.today.isoformat()}") + print("-" * 50) + + # Get weight input from user + while True: + try: + weight_str = input( + "Enter weight in kg (30-300, default: 85.1): " + ).strip() + if not weight_str: + weight = 85.1 + break + weight = float(weight_str) + if 30 <= weight <= 300: + break + else: + print("❌ Weight must be between 30 and 300 kg") + except ValueError: + print("❌ Please enter a valid number") + + call_and_display( + api.set_body_composition, + timestamp=config.today.isoformat(), + weight=weight, + percent_fat=15.4, + percent_hydration=54.8, + bone_mass=2.9, + muscle_mass=55.2, + method_name="set_body_composition", + api_call_desc=f"api.set_body_composition({config.today.isoformat()}, weight={weight}, ...)", + ) + print("✅ Body composition data set successfully!") + except Exception as e: + print(f"❌ Error setting body composition: {e}") + + +def add_body_composition_data(api: Garmin) -> None: + """Add body composition data.""" + try: + print(f"⚖️ Adding body composition data for {config.today.isoformat()}") + print("-" * 50) + + # Get weight input from user + while True: + try: + weight_str = input( + "Enter weight in kg (30-300, default: 85.1): " + ).strip() + if not weight_str: + weight = 85.1 + break + weight = float(weight_str) + if 30 <= weight <= 300: + break + else: + print("❌ Weight must be between 30 and 300 kg") + except ValueError: + print("❌ Please enter a valid number") + + call_and_display( + api.add_body_composition, + config.today.isoformat(), + weight=weight, + percent_fat=15.4, + percent_hydration=54.8, + visceral_fat_mass=10.8, + bone_mass=2.9, + muscle_mass=55.2, + basal_met=1454.1, + active_met=None, + physique_rating=None, + metabolic_age=33.0, + visceral_fat_rating=None, + bmi=22.2, + method_name="add_body_composition", + api_call_desc=f"api.add_body_composition({config.today.isoformat()}, weight={weight}, ...)", + ) + print("✅ Body composition data added successfully!") + except Exception as e: + print(f"❌ Error adding body composition: {e}") + + +def delete_weigh_ins_data(api: Garmin) -> None: + """Delete all weigh-ins for today.""" + try: + call_and_display( + api.delete_weigh_ins, + config.today.isoformat(), + delete_all=True, + method_name="delete_weigh_ins", + api_call_desc=f"api.delete_weigh_ins({config.today.isoformat()}, delete_all=True)", + ) + print("✅ Weigh-ins deleted successfully!") + except Exception as e: + print(f"❌ Error deleting weigh-ins: {e}") + + +def delete_weigh_in_data(api: Garmin) -> None: + """Delete a specific weigh-in.""" + try: + all_weigh_ins = [] + + # Find weigh-ins + print(f"🔍 Checking daily weigh-ins for today ({config.today.isoformat()})...") + try: + daily_weigh_ins = api.get_daily_weigh_ins(config.today.isoformat()) + + if daily_weigh_ins and "dateWeightList" in daily_weigh_ins: + weight_list = daily_weigh_ins["dateWeightList"] + for weigh_in in weight_list: + if isinstance(weigh_in, dict): + all_weigh_ins.append(weigh_in) + print(f"📊 Found {len(all_weigh_ins)} weigh-in(s) for today") + else: + print("📊 No weigh-in data found in response") + except Exception as e: + print(f"⚠️ Could not fetch daily weigh-ins: {e}") + + if not all_weigh_ins: + print("ℹ️ No weigh-ins found for today") + print("💡 You can add a test weigh-in using menu option [4]") + return + + print(f"\n⚖️ Found {len(all_weigh_ins)} weigh-in(s) available for deletion:") + print("-" * 70) + + # Display weigh-ins for user selection + for i, weigh_in in enumerate(all_weigh_ins): + # Extract weight data - Garmin API uses different field names + weight = weigh_in.get("weight") + if weight is None: + weight = weigh_in.get("weightValue", "Unknown") + + # Convert weight from grams to kg if it's a number + if isinstance(weight, int | float) and weight > 1000: + weight = weight / 1000 # Convert from grams to kg + weight = round(weight, 1) # Round to 1 decimal place + + unit = weigh_in.get("unitKey", "kg") + date = weigh_in.get("calendarDate", config.today.isoformat()) + + # Try different timestamp fields + timestamp = ( + weigh_in.get("timestampGMT") + or weigh_in.get("timestamp") + or weigh_in.get("date") + ) + + # Format timestamp for display + if timestamp: + try: + import datetime as dt + + if isinstance(timestamp, str): + # Handle ISO format strings + datetime_obj = dt.datetime.fromisoformat( + timestamp.replace("Z", "+00:00") + ) + else: + # Handle millisecond timestamps + datetime_obj = dt.datetime.fromtimestamp(timestamp / 1000) + time_str = datetime_obj.strftime("%H:%M:%S") + except Exception: + time_str = "Unknown time" + else: + time_str = "Unknown time" + + print(f" [{i}] {weight} {unit} on {date} at {time_str}") + + print() + try: + selection = input( + "Enter the index of the weigh-in to delete (or 'q' to cancel): " + ).strip() + + if selection.lower() == "q": + print("❌ Delete cancelled") + return + + weigh_in_index = int(selection) + if 0 <= weigh_in_index < len(all_weigh_ins): + selected_weigh_in = all_weigh_ins[weigh_in_index] + + # Get the weigh-in ID (Garmin uses 'samplePk' as the primary key) + weigh_in_id = ( + selected_weigh_in.get("samplePk") + or selected_weigh_in.get("id") + or selected_weigh_in.get("weightPk") + or selected_weigh_in.get("pk") + or selected_weigh_in.get("weightId") + or selected_weigh_in.get("uuid") + ) + + if weigh_in_id: + weight = selected_weigh_in.get("weight", "Unknown") + + # Convert weight from grams to kg if it's a number + if isinstance(weight, int | float) and weight > 1000: + weight = weight / 1000 # Convert from grams to kg + weight = round(weight, 1) # Round to 1 decimal place + + unit = selected_weigh_in.get("unitKey", "kg") + date = selected_weigh_in.get( + "calendarDate", config.today.isoformat() + ) + + # Confirm deletion + confirm = input( + f"Delete weigh-in {weight} {unit} from {date}? (yes/no): " + ).lower() + if confirm == "yes": + call_and_display( + api.delete_weigh_in, + weigh_in_id, + config.today.isoformat(), + method_name="delete_weigh_in", + api_call_desc=f"api.delete_weigh_in({weigh_in_id}, {config.today.isoformat()})", + ) + print("✅ Weigh-in deleted successfully!") + else: + print("❌ Delete cancelled") + else: + print("❌ No weigh-in ID found for selected entry") + else: + print("❌ Invalid selection") + + except ValueError: + print("❌ Invalid input - please enter a number") + + except Exception as e: + print(f"❌ Error deleting weigh-in: {e}") + + +def get_device_settings_data(api: Garmin) -> None: + """Get device settings for all devices.""" + try: + devices = api.get_devices() + if devices: + for device in devices: + device_id = device["deviceId"] + device_name = device.get("displayName", f"Device {device_id}") + try: + call_and_display( + api.get_device_settings, + device_id, + method_name="get_device_settings", + api_call_desc=f"api.get_device_settings({device_id}) - {device_name}", + ) + except Exception as e: + print(f"❌ Error getting settings for device {device_name}: {e}") + else: + print("ℹ️ No devices found") + except Exception as e: + print(f"❌ Error getting device settings: {e}") + + +def get_gear_data(api: Garmin) -> None: + """Get user gear list.""" + print("🔄 Fetching user gear list...") + + api_responses = [] + + # Get device info first + api_responses.append( + safe_call_for_group( + api.get_device_last_used, + method_name="get_device_last_used", + api_call_desc="api.get_device_last_used()", + ) + ) + + # Get user profile number from the first call + device_success, device_data, _ = safe_api_call( + api.get_device_last_used, method_name="get_device_last_used" + ) + + if device_success and device_data: + user_profile_number = device_data.get("userProfileNumber") + if user_profile_number: + api_responses.append( + safe_call_for_group( + api.get_gear, + user_profile_number, + method_name="get_gear", + api_call_desc=f"api.get_gear({user_profile_number})", + ) + ) + else: + print("❌ Could not get user profile number") + + call_and_display(group_name="User Gear List", api_responses=api_responses) + + +def get_gear_defaults_data(api: Garmin) -> None: + """Get gear defaults.""" + print("🔄 Fetching gear defaults...") + + api_responses = [] + + # Get device info first + api_responses.append( + safe_call_for_group( + api.get_device_last_used, + method_name="get_device_last_used", + api_call_desc="api.get_device_last_used()", + ) + ) + + # Get user profile number from the first call + device_success, device_data, _ = safe_api_call( + api.get_device_last_used, method_name="get_device_last_used" + ) + + if device_success and device_data: + user_profile_number = device_data.get("userProfileNumber") + if user_profile_number: + api_responses.append( + safe_call_for_group( + api.get_gear_defaults, + user_profile_number, + method_name="get_gear_defaults", + api_call_desc=f"api.get_gear_defaults({user_profile_number})", + ) + ) + else: + print("❌ Could not get user profile number") + + call_and_display(group_name="Gear Defaults", api_responses=api_responses) + + +def get_gear_stats_data(api: Garmin) -> None: + """Get gear statistics.""" + print("🔄 Fetching comprehensive gear statistics...") + + api_responses = [] + + # Get device info first + api_responses.append( + safe_call_for_group( + api.get_device_last_used, + method_name="get_device_last_used", + api_call_desc="api.get_device_last_used()", + ) + ) + + # Get user profile number and gear list + device_success, device_data, _ = safe_api_call( + api.get_device_last_used, method_name="get_device_last_used" + ) + + if device_success and device_data: + user_profile_number = device_data.get("userProfileNumber") + if user_profile_number: + # Get gear list + api_responses.append( + safe_call_for_group( + api.get_gear, + user_profile_number, + method_name="get_gear", + api_call_desc=f"api.get_gear({user_profile_number})", + ) + ) + + # Get gear data to extract UUIDs for stats + gear_success, gear_data, _ = safe_api_call( + api.get_gear, user_profile_number, method_name="get_gear" + ) + + if gear_success and gear_data: + # Get stats for each gear item (limit to first 3) + for gear_item in gear_data[:3]: + gear_uuid = gear_item.get("uuid") + gear_name = gear_item.get("displayName", "Unknown") + if gear_uuid: + api_responses.append( + safe_call_for_group( + api.get_gear_stats, + gear_uuid, + method_name="get_gear_stats", + api_call_desc=f"api.get_gear_stats('{gear_uuid}') - {gear_name}", + ) + ) + else: + print("ℹ️ No gear found") + else: + print("❌ Could not get user profile number") + + call_and_display(group_name="Gear Statistics", api_responses=api_responses) + + +def get_gear_activities_data(api: Garmin) -> None: + """Get gear activities.""" + print("🔄 Fetching gear activities...") + + api_responses = [] + + # Get device info first + api_responses.append( + safe_call_for_group( + api.get_device_last_used, + method_name="get_device_last_used", + api_call_desc="api.get_device_last_used()", + ) + ) + + # Get user profile number and gear list + device_success, device_data, _ = safe_api_call( + api.get_device_last_used, method_name="get_device_last_used" + ) + + if device_success and device_data: + user_profile_number = device_data.get("userProfileNumber") + if user_profile_number: + # Get gear list + api_responses.append( + safe_call_for_group( + api.get_gear, + user_profile_number, + method_name="get_gear", + api_call_desc=f"api.get_gear({user_profile_number})", + ) + ) + + # Get gear data to extract UUID for activities + gear_success, gear_data, _ = safe_api_call( + api.get_gear, user_profile_number, method_name="get_gear" + ) + + if gear_success and gear_data and len(gear_data) > 0: + # Get activities for the first gear item + gear_uuid = gear_data[0].get("uuid") + gear_name = gear_data[0].get("displayName", "Unknown") + + if gear_uuid: + api_responses.append( + safe_call_for_group( + api.get_gear_activities, + gear_uuid, + method_name="get_gear_activities", + api_call_desc=f"api.get_gear_activities('{gear_uuid}') - {gear_name}", + ) + ) + else: + print("❌ No gear UUID found") + else: + print("ℹ️ No gear found") + else: + print("❌ Could not get user profile number") + + call_and_display(group_name="Gear Activities", api_responses=api_responses) + + +def set_gear_default_data(api: Garmin) -> None: + """Set gear default.""" + try: + device_last_used = api.get_device_last_used() + user_profile_number = device_last_used.get("userProfileNumber") + if user_profile_number: + gear = api.get_gear(user_profile_number) + if gear: + gear_uuid = gear[0].get("uuid") + gear_name = gear[0].get("displayName", "Unknown") + if gear_uuid: + # Set as default for running (activity type ID 1) + # Correct method signature: set_gear_default(activityType, gearUUID, defaultGear=True) + activity_type = 1 # Running + call_and_display( + api.set_gear_default, + activity_type, + gear_uuid, + True, + method_name="set_gear_default", + api_call_desc=f"api.set_gear_default({activity_type}, '{gear_uuid}', True) - {gear_name} for running", + ) + print("✅ Gear default set successfully!") + else: + print("❌ No gear UUID found") + else: + print("ℹ️ No gear found") + else: + print("❌ Could not get user profile number") + except Exception as e: + print(f"❌ Error setting gear default: {e}") + + +def set_activity_name_data(api: Garmin) -> None: + """Set activity name.""" + try: + activities = api.get_activities(0, 1) + if activities: + activity_id = activities[0]["activityId"] + print(f"Current name of fetched activity: {activities[0]['activityName']}") + new_name = input("Enter new activity name: (or 'q' to cancel): ").strip() + + if new_name.lower() == "q": + print("❌ Rename cancelled") + return + + if new_name: + call_and_display( + api.set_activity_name, + activity_id, + new_name, + method_name="set_activity_name", + api_call_desc=f"api.set_activity_name({activity_id}, '{new_name}')", + ) + print("✅ Activity name updated!") + else: + print("❌ No name provided") + else: + print("❌ No activities found") + except Exception as e: + print(f"❌ Error setting activity name: {e}") + + +def set_activity_type_data(api: Garmin) -> None: + """Set activity type.""" + try: + activities = api.get_activities(0, 1) + if activities: + activity_id = activities[0]["activityId"] + activity_types = api.get_activity_types() + + # Show available types + print("\nAvailable activity types: (limit=10)") + for i, activity_type in enumerate(activity_types[:10]): # Show first 10 + print( + f"{i}: {activity_type.get('typeKey', 'Unknown')} - {activity_type.get('display', 'No description')}" + ) + + try: + print( + f"Current type of fetched activity '{activities[0]['activityName']}': {activities[0]['activityType']['typeKey']}" + ) + type_index = input( + "Enter activity type index: (or 'q' to cancel): " + ).strip() + + if type_index.lower() == "q": + print("❌ Type change cancelled") + return + + type_index = int(type_index) + if 0 <= type_index < len(activity_types): + selected_type = activity_types[type_index] + type_id = selected_type["typeId"] + type_key = selected_type["typeKey"] + parent_type_id = selected_type.get( + "parentTypeId", selected_type["typeId"] + ) + + call_and_display( + api.set_activity_type, + activity_id, + type_id, + type_key, + parent_type_id, + method_name="set_activity_type", + api_call_desc=f"api.set_activity_type({activity_id}, {type_id}, '{type_key}', {parent_type_id})", + ) + print("✅ Activity type updated!") + else: + print("❌ Invalid index") + except ValueError: + print("❌ Invalid input") + else: + print("❌ No activities found") + except Exception as e: + print(f"❌ Error setting activity type: {e}") + + +def create_manual_activity_data(api: Garmin) -> None: + """Create manual activity.""" + try: + print("Creating manual activity...") + print("Enter activity details (press Enter for defaults):") + + activity_name = ( + input("Activity name [Manual Activity]: ").strip() or "Manual Activity" + ) + type_key = input("Activity type key [running]: ").strip() or "running" + duration_min = input("Duration in minutes [60]: ").strip() or "60" + distance_km = input("Distance in kilometers [5]: ").strip() or "5" + timezone = input("Timezone [UTC]: ").strip() or "UTC" + + try: + duration_min = float(duration_min) + distance_km = float(distance_km) + + # Use the current time as start time + import datetime + + start_datetime = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S.00") + + call_and_display( + api.create_manual_activity, + start_datetime=start_datetime, + time_zone=timezone, + type_key=type_key, + distance_km=distance_km, + duration_min=duration_min, + activity_name=activity_name, + method_name="create_manual_activity", + api_call_desc=f"api.create_manual_activity(start_datetime='{start_datetime}', time_zone='{timezone}', type_key='{type_key}', distance_km={distance_km}, duration_min={duration_min}, activity_name='{activity_name}')", + ) + print("✅ Manual activity created!") + except ValueError: + print("❌ Invalid numeric input") + except Exception as e: + print(f"❌ Error creating manual activity: {e}") + + +def delete_activity_data(api: Garmin) -> None: + """Delete activity.""" + try: + activities = api.get_activities(0, 5) + if activities: + print("\nRecent activities:") + for i, activity in enumerate(activities): + activity_name = activity.get("activityName", "Unnamed") + activity_id = activity.get("activityId") + start_time = activity.get("startTimeLocal", "Unknown time") + print(f"{i}: {activity_name} ({activity_id}) - {start_time}") + + try: + activity_index = input( + "Enter activity index to delete: (or 'q' to cancel): " + ).strip() + + if activity_index.lower() == "q": + print("❌ Delete cancelled") + return + activity_index = int(activity_index) + if 0 <= activity_index < len(activities): + activity_id = activities[activity_index]["activityId"] + activity_name = activities[activity_index].get( + "activityName", "Unnamed" + ) + + confirm = input(f"Delete '{activity_name}'? (yes/no): ").lower() + if confirm == "yes": + call_and_display( + api.delete_activity, + activity_id, + method_name="delete_activity", + api_call_desc=f"api.delete_activity({activity_id})", + ) + print("✅ Activity deleted!") + else: + print("❌ Delete cancelled") + else: + print("❌ Invalid index") + except ValueError: + print("❌ Invalid input") + else: + print("❌ No activities found") + except Exception as e: + print(f"❌ Error deleting activity: {e}") + + +def delete_blood_pressure_data(api: Garmin) -> None: + """Delete blood pressure entry.""" + try: + # Get recent blood pressure entries + bp_data = api.get_blood_pressure( + config.week_start.isoformat(), config.today.isoformat() + ) + entry_list = [] + + # Parse the actual blood pressure data structure + if bp_data and bp_data.get("measurementSummaries"): + for summary in bp_data["measurementSummaries"]: + if summary.get("measurements"): + for measurement in summary["measurements"]: + # Use 'version' as the identifier (this is what Garmin uses) + entry_id = measurement.get("version") + systolic = measurement.get("systolic") + diastolic = measurement.get("diastolic") + pulse = measurement.get("pulse") + timestamp = measurement.get("measurementTimestampLocal") + notes = measurement.get("notes", "") + + # Extract date for deletion API (format: YYYY-MM-DD) + measurement_date = None + if timestamp: + try: + measurement_date = timestamp.split("T")[ + 0 + ] # Get just the date part + except Exception: + measurement_date = summary.get( + "startDate" + ) # Fallback to summary date + else: + measurement_date = summary.get( + "startDate" + ) # Fallback to summary date + + if entry_id and systolic and diastolic and measurement_date: + # Format display text with more details + display_parts = [f"{systolic}/{diastolic}"] + if pulse: + display_parts.append(f"pulse {pulse}") + if timestamp: + display_parts.append(f"at {timestamp}") + if notes: + display_parts.append(f"({notes})") + + display_text = " ".join(display_parts) + # Store both entry_id and measurement_date for deletion + entry_list.append( + (entry_id, display_text, measurement_date) + ) + + if entry_list: + print(f"\n📊 Found {len(entry_list)} blood pressure entries:") + print("-" * 70) + for i, (entry_id, display_text, _measurement_date) in enumerate(entry_list): + print(f" [{i}] {display_text} (ID: {entry_id})") + + try: + entry_index = input( + "\nEnter entry index to delete: (or 'q' to cancel): " + ).strip() + + if entry_index.lower() == "q": + print("❌ Entry deletion cancelled") + return + + entry_index = int(entry_index) + if 0 <= entry_index < len(entry_list): + entry_id, display_text, measurement_date = entry_list[entry_index] + confirm = input( + f"Delete entry '{display_text}'? (yes/no): " + ).lower() + if confirm == "yes": + call_and_display( + api.delete_blood_pressure, + entry_id, + measurement_date, + method_name="delete_blood_pressure", + api_call_desc=f"api.delete_blood_pressure('{entry_id}', '{measurement_date}')", + ) + print("✅ Blood pressure entry deleted!") + else: + print("❌ Delete cancelled") + else: + print("❌ Invalid index") + except ValueError: + print("❌ Invalid input") + else: + print("❌ No blood pressure entries found for past week") + print("💡 You can add a test measurement using menu option [3]") + + except Exception as e: + print(f"❌ Error deleting blood pressure: {e}") + + +def query_garmin_graphql_data(api: Garmin) -> None: + """Execute GraphQL query with a menu of available queries.""" + try: + print("Available GraphQL queries:") + print(" [1] Activities (recent activities with details)") + print(" [2] Health Snapshot (comprehensive health data)") + print(" [3] Weight Data (weight measurements)") + print(" [4] Blood Pressure (blood pressure data)") + print(" [5] Sleep Summaries (sleep analysis)") + print(" [6] Heart Rate Variability (HRV data)") + print(" [7] User Daily Summary (comprehensive daily stats)") + print(" [8] Training Readiness (training readiness metrics)") + print(" [9] Training Status (training status data)") + print(" [10] Activity Stats (aggregated activity statistics)") + print(" [11] VO2 Max (VO2 max data)") + print(" [12] Endurance Score (endurance scoring)") + print(" [13] User Goals (current goals)") + print(" [14] Stress Data (epoch chart with stress)") + print(" [15] Badge Challenges (available challenges)") + print(" [16] Adhoc Challenges (adhoc challenges)") + print(" [c] Custom query") + + choice = input("\nEnter choice (1-16, c): ").strip() + + # Use today's date and date range for queries that need them + today = config.today.isoformat() + week_start = config.week_start.isoformat() + start_datetime = f"{today}T00:00:00.00" + end_datetime = f"{today}T23:59:59.999" + + if choice == "1": + query = f'query{{activitiesScalar(displayName:"{api.display_name}", startTimestampLocal:"{start_datetime}", endTimestampLocal:"{end_datetime}", limit:10)}}' + elif choice == "2": + query = f'query{{healthSnapshotScalar(startDate:"{week_start}", endDate:"{today}")}}' + elif choice == "3": + query = ( + f'query{{weightScalar(startDate:"{week_start}", endDate:"{today}")}}' + ) + elif choice == "4": + query = f'query{{bloodPressureScalar(startDate:"{week_start}", endDate:"{today}")}}' + elif choice == "5": + query = f'query{{sleepSummariesScalar(startDate:"{week_start}", endDate:"{today}")}}' + elif choice == "6": + query = f'query{{heartRateVariabilityScalar(startDate:"{week_start}", endDate:"{today}")}}' + elif choice == "7": + query = f'query{{userDailySummaryV2Scalar(startDate:"{week_start}", endDate:"{today}")}}' + elif choice == "8": + query = f'query{{trainingReadinessRangeScalar(startDate:"{week_start}", endDate:"{today}")}}' + elif choice == "9": + query = f'query{{trainingStatusDailyScalar(calendarDate:"{today}")}}' + elif choice == "10": + query = f'query{{activityStatsScalar(aggregation:"daily", startDate:"{week_start}", endDate:"{today}", metrics:["duration", "distance"], groupByParentActivityType:true, standardizedUnits:true)}}' + elif choice == "11": + query = ( + f'query{{vo2MaxScalar(startDate:"{week_start}", endDate:"{today}")}}' + ) + elif choice == "12": + query = f'query{{enduranceScoreScalar(startDate:"{week_start}", endDate:"{today}", aggregation:"weekly")}}' + elif choice == "13": + query = "query{userGoalsScalar}" + elif choice == "14": + query = f'query{{epochChartScalar(date:"{today}", include:["stress"])}}' + elif choice == "15": + query = "query{badgeChallengesScalar}" + elif choice == "16": + query = "query{adhocChallengesScalar}" + elif choice.lower() == "c": + print("\nEnter your custom GraphQL query:") + print("Example: query{userGoalsScalar}") + query = input("Query: ").strip() + else: + print("❌ Invalid choice") + return + + if query: + # GraphQL API expects a dictionary with the query as a string value + graphql_payload = {"query": query} + call_and_display( + api.query_garmin_graphql, + graphql_payload, + method_name="query_garmin_graphql", + api_call_desc=f"api.query_garmin_graphql({graphql_payload})", + ) + else: + print("❌ No query provided") + except Exception as e: + print(f"❌ Error executing GraphQL query: {e}") + + +def get_virtual_challenges_data(api: Garmin) -> None: + """Get virtual challenges data with centralized error handling.""" + print("🏆 Attempting to get virtual challenges data...") + + # Try in-progress virtual challenges - this endpoint often returns 400 for accounts + # that don't have virtual challenges enabled, so handle it quietly + try: + challenges = api.get_inprogress_virtual_challenges( + config.start, config.default_limit + ) + if challenges: + print("✅ Virtual challenges data retrieved successfully") + call_and_display( + api.get_inprogress_virtual_challenges, + config.start, + config.default_limit, + method_name="get_inprogress_virtual_challenges", + api_call_desc=f"api.get_inprogress_virtual_challenges({config.start}, {config.default_limit})", + ) + return + else: + print("ℹ️ No in-progress virtual challenges found") + return + except GarminConnectConnectionError as e: + # Handle the common 400 error case quietly - this is expected for many accounts + error_str = str(e) + if "400" in error_str and ( + "Bad Request" in error_str or "API client error" in error_str + ): + print("ℹ️ Virtual challenges are not available for your account") + else: + # For unexpected connection errors, show them + print(f"⚠️ Connection error accessing virtual challenges: {error_str}") + except Exception as e: + print(f"⚠️ Unexpected error accessing virtual challenges: {e}") + + # Since virtual challenges failed or returned no data, suggest alternatives + print("💡 You can try other challenge-related endpoints instead:") + print(" - Badge challenges (menu option 7-8)") + print(" - Available badge challenges (menu option 7-4)") + print(" - Adhoc challenges (menu option 7-3)") + + +def add_hydration_data_entry(api: Garmin) -> None: + """Add hydration data entry.""" + try: + import datetime + + value_in_ml = 240 + raw_date = config.today + cdate = str(raw_date) + raw_ts = datetime.datetime.now() + timestamp = datetime.datetime.strftime(raw_ts, "%Y-%m-%dT%H:%M:%S.%f") + + call_and_display( + api.add_hydration_data, + value_in_ml=value_in_ml, + cdate=cdate, + timestamp=timestamp, + method_name="add_hydration_data", + api_call_desc=f"api.add_hydration_data(value_in_ml={value_in_ml}, cdate='{cdate}', timestamp='{timestamp}')", + ) + print("✅ Hydration data added successfully!") + except Exception as e: + print(f"❌ Error adding hydration data: {e}") + + +def set_blood_pressure_data(api: Garmin) -> None: + """Set blood pressure (and pulse) data.""" + try: + print("🩸 Adding blood pressure (and pulse) measurement") + print("Enter blood pressure values (press Enter for defaults):") + + # Get systolic pressure + systolic_input = input("Systolic pressure [120]: ").strip() + systolic = int(systolic_input) if systolic_input else 120 + + # Get diastolic pressure + diastolic_input = input("Diastolic pressure [80]: ").strip() + diastolic = int(diastolic_input) if diastolic_input else 80 + + # Get pulse + pulse_input = input("Pulse rate [60]: ").strip() + pulse = int(pulse_input) if pulse_input else 60 + + # Get notes (optional) + notes = input("Notes (optional): ").strip() or "Added via demo.py" + + # Validate ranges + if not (50 <= systolic <= 300): + print("❌ Invalid systolic pressure (should be between 50-300)") + return + if not (30 <= diastolic <= 200): + print("❌ Invalid diastolic pressure (should be between 30-200)") + return + if not (30 <= pulse <= 250): + print("❌ Invalid pulse rate (should be between 30-250)") + return + + print(f"📊 Recording: {systolic}/{diastolic} mmHg, pulse {pulse} bpm") + + call_and_display( + api.set_blood_pressure, + systolic, + diastolic, + pulse, + notes=notes, + method_name="set_blood_pressure", + api_call_desc=f"api.set_blood_pressure({systolic}, {diastolic}, {pulse}, notes='{notes}')", + ) + print("✅ Blood pressure data set successfully!") + + except ValueError: + print("❌ Invalid input - please enter numeric values") + except Exception as e: + print(f"❌ Error setting blood pressure: {e}") + + +def track_gear_usage_data(api: Garmin) -> None: + """Calculate total time of use of a piece of gear by going through all activities where said gear has been used.""" + try: + device_last_used = api.get_device_last_used() + user_profile_number = device_last_used.get("userProfileNumber") + if user_profile_number: + gear_list = api.get_gear(user_profile_number) + # call_and_display(api.get_gear, user_profile_number, method_name="get_gear", api_call_desc=f"api.get_gear({user_profile_number})") + if gear_list and isinstance(gear_list, list): + first_gear = gear_list[0] + gear_uuid = first_gear.get("uuid") + gear_name = first_gear.get("displayName", "Unknown") + print(f"Tracking usage for gear: {gear_name} (UUID: {gear_uuid})") + activityList = api.get_gear_activities(gear_uuid) + if len(activityList) == 0: + print("No activities found for the given gear uuid.") + else: + print("Found " + str(len(activityList)) + " activities.") + + D = 0 + for a in activityList: + print( + "Activity: " + + a["startTimeLocal"] + + (" | " + a["activityName"] if a["activityName"] else "") + ) + print( + " Duration: " + + format_timedelta(datetime.timedelta(seconds=a["duration"])) + ) + D += a["duration"] + print("") + print( + "Total Duration: " + format_timedelta(datetime.timedelta(seconds=D)) + ) + print("") + else: + print("No gear found for this user.") + else: + print("❌ Could not get user profile number") + except Exception as e: + print(f"❌ Error getting gear for track_gear_usage_data: {e}") + + +def execute_api_call(api: Garmin, key: str) -> None: + """Execute an API call based on the key.""" + if not api: + print("API not available") + return + + try: + # Map of keys to API methods - this can be extended as needed + api_methods = { + # User & Profile + "get_full_name": lambda: call_and_display( + api.get_full_name, + method_name="get_full_name", + api_call_desc="api.get_full_name()", + ), + "get_unit_system": lambda: call_and_display( + api.get_unit_system, + method_name="get_unit_system", + api_call_desc="api.get_unit_system()", + ), + "get_user_profile": lambda: call_and_display( + api.get_user_profile, + method_name="get_user_profile", + api_call_desc="api.get_user_profile()", + ), + "get_userprofile_settings": lambda: call_and_display( + api.get_userprofile_settings, + method_name="get_userprofile_settings", + api_call_desc="api.get_userprofile_settings()", + ), + # Daily Health & Activity + "get_stats": lambda: call_and_display( + api.get_stats, + config.today.isoformat(), + method_name="get_stats", + api_call_desc=f"api.get_stats('{config.today.isoformat()}')", + ), + "get_user_summary": lambda: call_and_display( + api.get_user_summary, + config.today.isoformat(), + method_name="get_user_summary", + api_call_desc=f"api.get_user_summary('{config.today.isoformat()}')", + ), + "get_stats_and_body": lambda: call_and_display( + api.get_stats_and_body, + config.today.isoformat(), + method_name="get_stats_and_body", + api_call_desc=f"api.get_stats_and_body('{config.today.isoformat()}')", + ), + "get_steps_data": lambda: call_and_display( + api.get_steps_data, + config.today.isoformat(), + method_name="get_steps_data", + api_call_desc=f"api.get_steps_data('{config.today.isoformat()}')", + ), + "get_heart_rates": lambda: call_and_display( + api.get_heart_rates, + config.today.isoformat(), + method_name="get_heart_rates", + api_call_desc=f"api.get_heart_rates('{config.today.isoformat()}')", + ), + "get_resting_heart_rate": lambda: call_and_display( + api.get_rhr_day, + config.today.isoformat(), + method_name="get_rhr_day", + api_call_desc=f"api.get_rhr_day('{config.today.isoformat()}')", + ), + "get_sleep_data": lambda: call_and_display( + api.get_sleep_data, + config.today.isoformat(), + method_name="get_sleep_data", + api_call_desc=f"api.get_sleep_data('{config.today.isoformat()}')", + ), + "get_all_day_stress": lambda: call_and_display( + api.get_all_day_stress, + config.today.isoformat(), + method_name="get_all_day_stress", + api_call_desc=f"api.get_all_day_stress('{config.today.isoformat()}')", + ), + # Advanced Health Metrics + "get_training_readiness": lambda: call_and_display( + api.get_training_readiness, + config.today.isoformat(), + method_name="get_training_readiness", + api_call_desc=f"api.get_training_readiness('{config.today.isoformat()}')", + ), + "get_training_status": lambda: call_and_display( + api.get_training_status, + config.today.isoformat(), + method_name="get_training_status", + api_call_desc=f"api.get_training_status('{config.today.isoformat()}')", + ), + "get_respiration_data": lambda: call_and_display( + api.get_respiration_data, + config.today.isoformat(), + method_name="get_respiration_data", + api_call_desc=f"api.get_respiration_data('{config.today.isoformat()}')", + ), + "get_spo2_data": lambda: call_and_display( + api.get_spo2_data, + config.today.isoformat(), + method_name="get_spo2_data", + api_call_desc=f"api.get_spo2_data('{config.today.isoformat()}')", + ), + "get_max_metrics": lambda: call_and_display( + api.get_max_metrics, + config.today.isoformat(), + method_name="get_max_metrics", + api_call_desc=f"api.get_max_metrics('{config.today.isoformat()}')", + ), + "get_hrv_data": lambda: call_and_display( + api.get_hrv_data, + config.today.isoformat(), + method_name="get_hrv_data", + api_call_desc=f"api.get_hrv_data('{config.today.isoformat()}')", + ), + "get_fitnessage_data": lambda: call_and_display( + api.get_fitnessage_data, + config.today.isoformat(), + method_name="get_fitnessage_data", + api_call_desc=f"api.get_fitnessage_data('{config.today.isoformat()}')", + ), + "get_stress_data": lambda: call_and_display( + api.get_stress_data, + config.today.isoformat(), + method_name="get_stress_data", + api_call_desc=f"api.get_stress_data('{config.today.isoformat()}')", + ), + "get_lactate_threshold": lambda: get_lactate_threshold_data(api), + "get_intensity_minutes_data": lambda: call_and_display( + api.get_intensity_minutes_data, + config.today.isoformat(), + method_name="get_intensity_minutes_data", + api_call_desc=f"api.get_intensity_minutes_data('{config.today.isoformat()}')", + ), + # Historical Data & Trends + "get_daily_steps": lambda: call_and_display( + api.get_daily_steps, + config.week_start.isoformat(), + config.today.isoformat(), + method_name="get_daily_steps", + api_call_desc=f"api.get_daily_steps('{config.week_start.isoformat()}', '{config.today.isoformat()}')", + ), + "get_body_battery": lambda: call_and_display( + api.get_body_battery, + config.week_start.isoformat(), + config.today.isoformat(), + method_name="get_body_battery", + api_call_desc=f"api.get_body_battery('{config.week_start.isoformat()}', '{config.today.isoformat()}')", + ), + "get_floors": lambda: call_and_display( + api.get_floors, + config.week_start.isoformat(), + method_name="get_floors", + api_call_desc=f"api.get_floors('{config.week_start.isoformat()}')", + ), + "get_blood_pressure": lambda: call_and_display( + api.get_blood_pressure, + config.week_start.isoformat(), + config.today.isoformat(), + method_name="get_blood_pressure", + api_call_desc=f"api.get_blood_pressure('{config.week_start.isoformat()}', '{config.today.isoformat()}')", + ), + "get_progress_summary_between_dates": lambda: call_and_display( + api.get_progress_summary_between_dates, + config.week_start.isoformat(), + config.today.isoformat(), + method_name="get_progress_summary_between_dates", + api_call_desc=f"api.get_progress_summary_between_dates('{config.week_start.isoformat()}', '{config.today.isoformat()}')", + ), + "get_body_battery_events": lambda: call_and_display( + api.get_body_battery_events, + config.week_start.isoformat(), + method_name="get_body_battery_events", + api_call_desc=f"api.get_body_battery_events('{config.week_start.isoformat()}')", + ), + # Activities & Workouts + "get_activities": lambda: call_and_display( + api.get_activities, + config.start, + config.default_limit, + method_name="get_activities", + api_call_desc=f"api.get_activities({config.start}, {config.default_limit})", + ), + "get_last_activity": lambda: call_and_display( + api.get_last_activity, + method_name="get_last_activity", + api_call_desc="api.get_last_activity()", + ), + "get_activities_fordate": lambda: call_and_display( + api.get_activities_fordate, + config.today.isoformat(), + method_name="get_activities_fordate", + api_call_desc=f"api.get_activities_fordate('{config.today.isoformat()}')", + ), + "get_activity_types": lambda: call_and_display( + api.get_activity_types, + method_name="get_activity_types", + api_call_desc="api.get_activity_types()", + ), + "get_workouts": lambda: call_and_display( + api.get_workouts, + method_name="get_workouts", + api_call_desc="api.get_workouts()", + ), + "upload_activity": lambda: upload_activity_file(api), + "download_activities": lambda: download_activities_by_date(api), + "get_activity_splits": lambda: get_activity_splits_data(api), + "get_activity_typed_splits": lambda: get_activity_typed_splits_data(api), + "get_activity_split_summaries": lambda: get_activity_split_summaries_data( + api + ), + "get_activity_weather": lambda: get_activity_weather_data(api), + "get_activity_hr_in_timezones": lambda: get_activity_hr_timezones_data(api), + "get_activity_details": lambda: get_activity_details_data(api), + "get_activity_gear": lambda: get_activity_gear_data(api), + "get_activity": lambda: get_single_activity_data(api), + "get_activity_exercise_sets": lambda: get_activity_exercise_sets_data(api), + "get_workout_by_id": lambda: get_workout_by_id_data(api), + "download_workout": lambda: download_workout_data(api), + "upload_workout": lambda: upload_workout_data(api), + # Body Composition & Weight + "get_body_composition": lambda: call_and_display( + api.get_body_composition, + config.today.isoformat(), + method_name="get_body_composition", + api_call_desc=f"api.get_body_composition('{config.today.isoformat()}')", + ), + "get_weigh_ins": lambda: call_and_display( + api.get_weigh_ins, + config.week_start.isoformat(), + config.today.isoformat(), + method_name="get_weigh_ins", + api_call_desc=f"api.get_weigh_ins('{config.week_start.isoformat()}', '{config.today.isoformat()}')", + ), + "get_daily_weigh_ins": lambda: call_and_display( + api.get_daily_weigh_ins, + config.today.isoformat(), + method_name="get_daily_weigh_ins", + api_call_desc=f"api.get_daily_weigh_ins('{config.today.isoformat()}')", + ), + "add_weigh_in": lambda: add_weigh_in_data(api), + "set_body_composition": lambda: set_body_composition_data(api), + "add_body_composition": lambda: add_body_composition_data(api), + "delete_weigh_ins": lambda: delete_weigh_ins_data(api), + "delete_weigh_in": lambda: delete_weigh_in_data(api), + # Goals & Achievements + "get_personal_records": lambda: call_and_display( + api.get_personal_record, + method_name="get_personal_record", + api_call_desc="api.get_personal_record()", + ), + "get_earned_badges": lambda: call_and_display( + api.get_earned_badges, + method_name="get_earned_badges", + api_call_desc="api.get_earned_badges()", + ), + "get_adhoc_challenges": lambda: call_and_display( + api.get_adhoc_challenges, + config.start, + config.default_limit, + method_name="get_adhoc_challenges", + api_call_desc=f"api.get_adhoc_challenges({config.start}, {config.default_limit})", + ), + "get_available_badge_challenges": lambda: call_and_display( + api.get_available_badge_challenges, + config.start_badge, + config.default_limit, + method_name="get_available_badge_challenges", + api_call_desc=f"api.get_available_badge_challenges({config.start_badge}, {config.default_limit})", + ), + "get_active_goals": lambda: call_and_display( + api.get_goals, + status="active", + start=config.start, + limit=config.default_limit, + method_name="get_goals", + api_call_desc=f"api.get_goals(status='active', start={config.start}, limit={config.default_limit})", + ), + "get_future_goals": lambda: call_and_display( + api.get_goals, + status="future", + start=config.start, + limit=config.default_limit, + method_name="get_goals", + api_call_desc=f"api.get_goals(status='future', start={config.start}, limit={config.default_limit})", + ), + "get_past_goals": lambda: call_and_display( + api.get_goals, + status="past", + start=config.start, + limit=config.default_limit, + method_name="get_goals", + api_call_desc=f"api.get_goals(status='past', start={config.start}, limit={config.default_limit})", + ), + "get_badge_challenges": lambda: call_and_display( + api.get_badge_challenges, + config.start_badge, + config.default_limit, + method_name="get_badge_challenges", + api_call_desc=f"api.get_badge_challenges({config.start_badge}, {config.default_limit})", + ), + "get_non_completed_badge_challenges": lambda: call_and_display( + api.get_non_completed_badge_challenges, + config.start_badge, + config.default_limit, + method_name="get_non_completed_badge_challenges", + api_call_desc=f"api.get_non_completed_badge_challenges({config.start_badge}, {config.default_limit})", + ), + "get_inprogress_virtual_challenges": lambda: get_virtual_challenges_data( + api + ), + "get_race_predictions": lambda: call_and_display( + api.get_race_predictions, + method_name="get_race_predictions", + api_call_desc="api.get_race_predictions()", + ), + "get_hill_score": lambda: call_and_display( + api.get_hill_score, + config.week_start.isoformat(), + config.today.isoformat(), + method_name="get_hill_score", + api_call_desc=f"api.get_hill_score('{config.week_start.isoformat()}', '{config.today.isoformat()}')", + ), + "get_endurance_score": lambda: call_and_display( + api.get_endurance_score, + config.week_start.isoformat(), + config.today.isoformat(), + method_name="get_endurance_score", + api_call_desc=f"api.get_endurance_score('{config.week_start.isoformat()}', '{config.today.isoformat()}')", + ), + "get_available_badges": lambda: call_and_display( + api.get_available_badges, + method_name="get_available_badges", + api_call_desc="api.get_available_badges()", + ), + "get_in_progress_badges": lambda: call_and_display( + api.get_in_progress_badges, + method_name="get_in_progress_badges", + api_call_desc="api.get_in_progress_badges()", + ), + # Device & Technical + "get_devices": lambda: call_and_display( + api.get_devices, + method_name="get_devices", + api_call_desc="api.get_devices()", + ), + "get_device_alarms": lambda: call_and_display( + api.get_device_alarms, + method_name="get_device_alarms", + api_call_desc="api.get_device_alarms()", + ), + "get_solar_data": lambda: get_solar_data(api), + "request_reload": lambda: call_and_display( + api.request_reload, + config.today.isoformat(), + method_name="request_reload", + api_call_desc=f"api.request_reload('{config.today.isoformat()}')", + ), + "get_device_settings": lambda: get_device_settings_data(api), + "get_device_last_used": lambda: call_and_display( + api.get_device_last_used, + method_name="get_device_last_used", + api_call_desc="api.get_device_last_used()", + ), + "get_primary_training_device": lambda: call_and_display( + api.get_primary_training_device, + method_name="get_primary_training_device", + api_call_desc="api.get_primary_training_device()", + ), + # Gear & Equipment + "get_gear": lambda: get_gear_data(api), + "get_gear_defaults": lambda: get_gear_defaults_data(api), + "get_gear_stats": lambda: get_gear_stats_data(api), + "get_gear_activities": lambda: get_gear_activities_data(api), + "set_gear_default": lambda: set_gear_default_data(api), + "track_gear_usage": lambda: track_gear_usage_data(api), + # Hydration & Wellness + "get_hydration_data": lambda: call_and_display( + api.get_hydration_data, + config.today.isoformat(), + method_name="get_hydration_data", + api_call_desc=f"api.get_hydration_data('{config.today.isoformat()}')", + ), + "get_pregnancy_summary": lambda: call_and_display( + api.get_pregnancy_summary, + method_name="get_pregnancy_summary", + api_call_desc="api.get_pregnancy_summary()", + ), + "get_all_day_events": lambda: call_and_display( + api.get_all_day_events, + config.week_start.isoformat(), + method_name="get_all_day_events", + api_call_desc=f"api.get_all_day_events('{config.week_start.isoformat()}')", + ), + "add_hydration_data": lambda: add_hydration_data_entry(api), + "set_blood_pressure": lambda: set_blood_pressure_data(api), + "get_menstrual_data_for_date": lambda: call_and_display( + api.get_menstrual_data_for_date, + config.today.isoformat(), + method_name="get_menstrual_data_for_date", + api_call_desc=f"api.get_menstrual_data_for_date('{config.today.isoformat()}')", + ), + "get_menstrual_calendar_data": lambda: call_and_display( + api.get_menstrual_calendar_data, + config.week_start.isoformat(), + config.today.isoformat(), + method_name="get_menstrual_calendar_data", + api_call_desc=f"api.get_menstrual_calendar_data('{config.week_start.isoformat()}', '{config.today.isoformat()}')", + ), + # Blood Pressure Management + "delete_blood_pressure": lambda: delete_blood_pressure_data(api), + # Activity Management + "set_activity_name": lambda: set_activity_name_data(api), + "set_activity_type": lambda: set_activity_type_data(api), + "create_manual_activity": lambda: create_manual_activity_data(api), + "delete_activity": lambda: delete_activity_data(api), + "get_activities_by_date": lambda: call_and_display( + api.get_activities_by_date, + config.today.isoformat(), + config.today.isoformat(), + method_name="get_activities_by_date", + api_call_desc=f"api.get_activities_by_date('{config.today.isoformat()}', '{config.today.isoformat()}')", + ), + # System & Export + "create_health_report": lambda: DataExporter.create_health_report(api), + "remove_tokens": lambda: remove_stored_tokens(), + "disconnect": lambda: disconnect_api(api), + # GraphQL Queries + "query_garmin_graphql": lambda: query_garmin_graphql_data(api), + } + + if key in api_methods: + print(f"\n🔄 Executing: {key}") + api_methods[key]() + else: + print(f"❌ API method '{key}' not implemented yet. You can add it later!") + + except Exception as e: + print(f"❌ Error executing {key}: {e}") + + +def remove_stored_tokens(): + """Remove stored login tokens.""" + try: + import os + import shutil + + token_path = os.path.expanduser(config.tokenstore) + if os.path.isdir(token_path): + shutil.rmtree(token_path) + print("✅ Stored login tokens directory removed") + else: + print("ℹ️ No stored login tokens found") + except Exception as e: + print(f"❌ Error removing stored login tokens: {e}") + + +def disconnect_api(api: Garmin): + """Disconnect from Garmin Connect.""" + api.logout() + print("✅ Disconnected from Garmin Connect") + + +def init_api(email: str | None = None, password: str | None = None) -> Garmin | None: + """Initialize Garmin API with smart error handling and recovery.""" + # First try to login with stored tokens + try: + print(f"Attempting to login using stored tokens from: {config.tokenstore}") + + garmin = Garmin() + garmin.login(config.tokenstore) + print("Successfully logged in using stored tokens!") + return garmin + + except ( + FileNotFoundError, + GarthHTTPError, + GarminConnectAuthenticationError, + GarminConnectConnectionError, + ): + print("No valid tokens found. Requesting fresh login credentials.") + + # Loop for credential entry with retry on auth failure + while True: + try: + # Get credentials if not provided + if not email or not password: + email = input("Email address: ").strip() + password = getpass("Password: ") + + print("Logging in with credentials...") + garmin = Garmin( + email=email, password=password, is_cn=False, return_on_mfa=True + ) + result1, result2 = garmin.login() + + if result1 == "needs_mfa": + print("Multi-factor authentication required") + + mfa_code = get_mfa() + print("🔄 Submitting MFA code...") + + try: + garmin.resume_login(result2, mfa_code) + print("✅ MFA authentication successful!") + + except GarthHTTPError as garth_error: + # Handle specific HTTP errors from MFA + error_str = str(garth_error) + print(f"🔍 Debug: MFA error details: {error_str}") + + if "429" in error_str and "Too Many Requests" in error_str: + print("❌ Too many MFA attempts") + print("💡 Please wait 30 minutes before trying again") + sys.exit(1) + elif "401" in error_str or "403" in error_str: + print("❌ Invalid MFA code") + print("💡 Please verify your MFA code and try again") + continue + else: + # Other HTTP errors - don't retry + print(f"❌ MFA authentication failed: {garth_error}") + sys.exit(1) + + except GarthException as garth_error: + print(f"❌ MFA authentication failed: {garth_error}") + print("💡 Please verify your MFA code and try again") + continue + + # Save tokens for future use + garmin.garth.dump(config.tokenstore) + print(f"Login successful! Tokens saved to: {config.tokenstore}") + + return garmin + + except GarminConnectAuthenticationError: + print("❌ Authentication failed:") + print("💡 Please check your username and password and try again") + # Clear the provided credentials to force re-entry + email = None + password = None + continue + + except ( + FileNotFoundError, + GarthHTTPError, + GarthException, + GarminConnectConnectionError, + requests.exceptions.HTTPError, + ) as err: + print(f"❌ Connection error: {err}") + print("💡 Please check your internet connection and try again") + return None + + except KeyboardInterrupt: + print("\nLogin cancelled by user") + return None + + +def main(): + """Main program loop with funny health status in menu prompt.""" + # Display export directory information on startup + print(f"📁 Exported data will be saved to the directory: '{config.export_dir}'") + print("📄 All API responses are written to: 'response.json'") + + api_instance = init_api(config.email, config.password) + current_category = None + + while True: + try: + if api_instance: + # Add health status in menu prompt + try: + summary = api_instance.get_user_summary(config.today.isoformat()) + hydration_data = None + with suppress(Exception): + hydration_data = api_instance.get_hydration_data( + config.today.isoformat() + ) + + if summary: + steps = summary.get("totalSteps", 0) + calories = summary.get("totalKilocalories", 0) + + # Build stats string with hydration if available + stats_parts = [f"{steps:,} steps", f"{calories} kcal"] + + if hydration_data and hydration_data.get("valueInML"): + hydration_ml = int(hydration_data.get("valueInML", 0)) + hydration_cups = round(hydration_ml / 240, 1) + hydration_goal = hydration_data.get("goalInML", 0) + + if hydration_goal > 0: + hydration_percent = round( + (hydration_ml / hydration_goal) * 100 + ) + stats_parts.append( + f"{hydration_ml}ml water ({hydration_percent}% of goal)" + ) + else: + stats_parts.append( + f"{hydration_ml}ml water ({hydration_cups} cups)" + ) + + stats_string = " | ".join(stats_parts) + print(f"\n📊 Your Stats Today: {stats_string}") + + if steps < 5000: + print("🐌 Time to get those legs moving!") + elif steps > 15000: + print("🏃‍♂️ You're crushing it today!") + else: + print("👍 Nice progress! Keep it up!") + except Exception as e: + print( + f"Unable to fetch stats for display: {e}" + ) # Silently skip if stats can't be fetched + + # Display appropriate menu + if current_category is None: + print_main_menu() + option = readchar.readkey() + + # Handle main menu options + if option == "q": + print( + "Be active, generate some data to play with next time ;-) Bye!" + ) + break + elif option in menu_categories: + current_category = option + else: + print( + f"❌ Invalid selection. Use {', '.join(menu_categories.keys())} for categories or 'q' to quit" + ) + else: + # In a category - show category menu + print_category_menu(current_category) + option = readchar.readkey() + + # Handle category menu options + if option == "q": + current_category = None # Back to main menu + elif option in "0123456789abcdefghijklmnopqrstuvwxyz": + try: + category_data = menu_categories[current_category] + category_options = category_data["options"] + if option in category_options: + api_key = category_options[option]["key"] + execute_api_call(api_instance, api_key) + else: + valid_keys = ", ".join(category_options.keys()) + print( + f"❌ Invalid option selection. Valid options: {valid_keys}" + ) + except Exception as e: + print(f"❌ Error processing option {option}: {e}") + else: + print( + "❌ Invalid selection. Use numbers/letters for options or 'q' to go back/quit" + ) + + except KeyboardInterrupt: + print("\nInterrupted by user. Press q to quit.") + except Exception as e: + print(f"Unexpected error: {e}") + + +if __name__ == "__main__": + main() + + +================================================ +FILE: example.py +================================================ +#!/usr/bin/env python3 +""" +🏃‍♂️ Simple Garmin Connect API Example +===================================== + +This example demonstrates the basic usage of python-garminconnect: +- Authentication with email/password +- Token storage and automatic reuse +- MFA (Multi-Factor Authentication) support +- Comprehensive error handling for all API calls +- Basic API calls for user stats + +For a comprehensive demo of all available API calls, see demo.py + +Dependencies: +pip3 install garth requests + +Environment Variables (optional): +export EMAIL= +export PASSWORD= +export GARMINTOKENS= +""" + +import logging +import os +import sys +from datetime import date +from getpass import getpass +from pathlib import Path + +import requests +from garth.exc import GarthException, GarthHTTPError + +from garminconnect import ( + Garmin, + GarminConnectAuthenticationError, + GarminConnectConnectionError, + GarminConnectTooManyRequestsError, +) + +# Suppress garminconnect library logging to avoid tracebacks in normal operation +logging.getLogger("garminconnect").setLevel(logging.CRITICAL) + + +def safe_api_call(api_method, *args, **kwargs): + """ + Safe API call wrapper with comprehensive error handling. + + This demonstrates the error handling patterns used throughout the library. + Returns (success: bool, result: Any, error_message: str) + """ + try: + result = api_method(*args, **kwargs) + return True, result, None + + except GarthHTTPError as e: + # Handle specific HTTP errors gracefully + error_str = str(e) + status_code = getattr(getattr(e, "response", None), "status_code", None) + + if status_code == 400 or "400" in error_str: + return ( + False, + None, + "Endpoint not available (400 Bad Request) - Feature may not be enabled for your account", + ) + elif status_code == 401 or "401" in error_str: + return ( + False, + None, + "Authentication required (401 Unauthorized) - Please re-authenticate", + ) + elif status_code == 403 or "403" in error_str: + return ( + False, + None, + "Access denied (403 Forbidden) - Account may not have permission", + ) + elif status_code == 404 or "404" in error_str: + return ( + False, + None, + "Endpoint not found (404) - Feature may have been moved or removed", + ) + elif status_code == 429 or "429" in error_str: + return ( + False, + None, + "Rate limit exceeded (429) - Please wait before making more requests", + ) + elif status_code == 500 or "500" in error_str: + return ( + False, + None, + "Server error (500) - Garmin's servers are experiencing issues", + ) + elif status_code == 503 or "503" in error_str: + return ( + False, + None, + "Service unavailable (503) - Garmin's servers are temporarily unavailable", + ) + else: + return False, None, f"HTTP error: {e}" + + except FileNotFoundError: + return ( + False, + None, + "No valid tokens found. Please login with your email/password to create new tokens.", + ) + + except GarminConnectAuthenticationError as e: + return False, None, f"Authentication issue: {e}" + + except GarminConnectConnectionError as e: + return False, None, f"Connection issue: {e}" + + except GarminConnectTooManyRequestsError as e: + return False, None, f"Rate limit exceeded: {e}" + + except Exception as e: + return False, None, f"Unexpected error: {e}" + + +def get_credentials(): + """Get email and password from environment or user input.""" + email = os.getenv("EMAIL") + password = os.getenv("PASSWORD") + + if not email: + email = input("Login email: ") + if not password: + password = getpass("Enter password: ") + + return email, password + + +def init_api() -> Garmin | None: + """Initialize Garmin API with authentication and token management.""" + + # Configure token storage + tokenstore = os.getenv("GARMINTOKENS", "~/.garminconnect") + tokenstore_path = Path(tokenstore).expanduser() + + print(f"🔐 Token storage: {tokenstore_path}") + + # Check if token files exist + if tokenstore_path.exists(): + print("📄 Found existing token directory") + token_files = list(tokenstore_path.glob("*.json")) + if token_files: + print( + f"🔑 Found {len(token_files)} token file(s): {[f.name for f in token_files]}" + ) + else: + print("⚠️ Token directory exists but no token files found") + else: + print("📭 No existing token directory found") + + # First try to login with stored tokens + try: + print("🔄 Attempting to use saved authentication tokens...") + garmin = Garmin() + garmin.login(str(tokenstore_path)) + print("✅ Successfully logged in using saved tokens!") + return garmin + + except ( + FileNotFoundError, + GarthHTTPError, + GarminConnectAuthenticationError, + GarminConnectConnectionError, + ): + print("🔑 No valid tokens found. Requesting fresh login credentials.") + + # Loop for credential entry with retry on auth failure + while True: + try: + # Get credentials + email, password = get_credentials() + + print("� Logging in with credentials...") + garmin = Garmin( + email=email, password=password, is_cn=False, return_on_mfa=True + ) + result1, result2 = garmin.login() + + if result1 == "needs_mfa": + print("🔐 Multi-factor authentication required") + + mfa_code = input("Please enter your MFA code: ") + print("🔄 Submitting MFA code...") + + try: + garmin.resume_login(result2, mfa_code) + print("✅ MFA authentication successful!") + + except GarthHTTPError as garth_error: + # Handle specific HTTP errors from MFA + error_str = str(garth_error) + if "429" in error_str and "Too Many Requests" in error_str: + print("❌ Too many MFA attempts") + print("💡 Please wait 30 minutes before trying again") + sys.exit(1) + elif "401" in error_str or "403" in error_str: + print("❌ Invalid MFA code") + print("💡 Please verify your MFA code and try again") + continue + else: + # Other HTTP errors - don't retry + print(f"❌ MFA authentication failed: {garth_error}") + sys.exit(1) + + except GarthException as garth_error: + print(f"❌ MFA authentication failed: {garth_error}") + print("💡 Please verify your MFA code and try again") + continue + + # Save tokens for future use + garmin.garth.dump(str(tokenstore_path)) + print(f"💾 Authentication tokens saved to: {tokenstore_path}") + print("✅ Login successful!") + return garmin + + except GarminConnectAuthenticationError: + print("❌ Authentication failed:") + print("💡 Please check your username and password and try again") + # Continue the loop to retry + continue + + except ( + FileNotFoundError, + GarthHTTPError, + GarminConnectConnectionError, + requests.exceptions.HTTPError, + ) as err: + print(f"❌ Connection error: {err}") + print("💡 Please check your internet connection and try again") + return None + + except KeyboardInterrupt: + print("\n👋 Cancelled by user") + return None + + +def display_user_info(api: Garmin): + """Display basic user information with proper error handling.""" + print("\n" + "=" * 60) + print("👤 User Information") + print("=" * 60) + + # Get user's full name + success, full_name, error_msg = safe_api_call(api.get_full_name) + if success: + print(f"📝 Name: {full_name}") + else: + print(f"📝 Name: ⚠️ {error_msg}") + + # Get user profile number from device info + success, device_info, error_msg = safe_api_call(api.get_device_last_used) + if success and device_info and device_info.get("userProfileNumber"): + user_profile_number = device_info.get("userProfileNumber") + print(f"🆔 Profile Number: {user_profile_number}") + else: + if not success: + print(f"🆔 Profile Number: ⚠️ {error_msg}") + else: + print("🆔 Profile Number: Not available") + + +def display_daily_stats(api: Garmin): + """Display today's activity statistics with proper error handling.""" + today = date.today().isoformat() + + print("\n" + "=" * 60) + print(f"📊 Daily Stats for {today}") + print("=" * 60) + + # Get user summary (steps, calories, etc.) + success, summary, error_msg = safe_api_call(api.get_user_summary, today) + if success and summary: + steps = summary.get("totalSteps", 0) + distance = summary.get("totalDistanceMeters", 0) / 1000 # Convert to km + calories = summary.get("totalKilocalories", 0) + floors = summary.get("floorsClimbed", 0) + + print(f"👣 Steps: {steps:,}") + print(f"📏 Distance: {distance:.2f} km") + print(f"🔥 Calories: {calories}") + print(f"🏢 Floors: {floors}") + + # Fun motivation based on steps + if steps < 5000: + print("🐌 Time to get those legs moving!") + elif steps > 15000: + print("🏃‍♂️ You're crushing it today!") + else: + print("👍 Nice progress! Keep it up!") + else: + if not success: + print(f"⚠️ Could not fetch daily stats: {error_msg}") + else: + print("⚠️ No activity summary available for today") + + # Get hydration data + success, hydration, error_msg = safe_api_call(api.get_hydration_data, today) + if success and hydration and hydration.get("valueInML"): + hydration_ml = int(hydration.get("valueInML", 0)) + hydration_goal = hydration.get("goalInML", 0) + hydration_cups = round(hydration_ml / 240, 1) # 240ml = 1 cup + + print(f"💧 Hydration: {hydration_ml}ml ({hydration_cups} cups)") + + if hydration_goal > 0: + hydration_percent = round((hydration_ml / hydration_goal) * 100) + print(f"🎯 Goal Progress: {hydration_percent}% of {hydration_goal}ml") + else: + if not success: + print(f"💧 Hydration: ⚠️ {error_msg}") + else: + print("💧 Hydration: No data available") + + +def main(): + """Main example demonstrating basic Garmin Connect API usage.""" + print("🏃‍♂️ Simple Garmin Connect API Example") + print("=" * 60) + + # Initialize API with authentication (will only prompt for credentials if needed) + api = init_api() + + if not api: + print("❌ Failed to initialize API. Exiting.") + return + + # Display user information + display_user_info(api) + + # Display daily statistics + display_daily_stats(api) + + print("\n" + "=" * 60) + print("✅ Example completed successfully!") + print("💡 For a comprehensive demo of all API features, run: python demo.py") + print("=" * 60) + + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + print("\n\n🚪 Exiting example. Goodbye! 👋") + except Exception as e: + print(f"\n❌ Unexpected error: {e}") + + +================================================ +FILE: docs/graphql_queries.txt +================================================ +GRAPHQL_QUERIES_WITH_PARAMS = [ + { + "query": 'query{{activitiesScalar(displayName:"{self.display_name}", startTimestampLocal:"{startDateTime}", endTimestampLocal:"{endDateTime}", limit:{limit})}}', + "params": { + "limit": "int", + "startDateTime": "YYYY-MM-DDThh:mm:ss.ms", + "endDateTime": "YYYY-MM-DDThh:mm:ss.ms", + }, + }, + { + "query": 'query{{healthSnapshotScalar(startDate:"{startDate}", endDate:"{endDate}")}}', + "params": {"startDate": "YYYY-MM-DD", "endDate": "YYYY-MM-DD"}, + }, + { + "query": 'query{{golfScorecardScalar(startTimestampLocal:"{startDateTime}", endTimestampLocal:"{endDateTime}")}}', + "params": { + "startDateTime": "YYYY-MM-DDThh:mm:ss.ms", + "endDateTime": "YYYY-MM-DDThh:mm:ss.ms", + }, + }, + { + "query": 'query{{weightScalar(startDate:"{startDate}", endDate:"{endDate}")}}', + "params": {"startDate": "YYYY-MM-DD", "endDate": "YYYY-MM-DD"}, + }, + { + "query": 'query{{bloodPressureScalar(startDate:"{startDate}", endDate:"{endDate}")}}', + "params": {"startDate": "YYYY-MM-DD", "endDate": "YYYY-MM-DD"}, + }, + { + "query": 'query{{sleepSummariesScalar(startDate:"{startDate}", endDate:"{endDate}")}}', + "params": {"startDate": "YYYY-MM-DD", "endDate": "YYYY-MM-DD"}, + }, + { + "query": 'query{{heartRateVariabilityScalar(startDate:"{startDate}", endDate:"{endDate}")}}', + "params": {"startDate": "YYYY-MM-DD", "endDate": "YYYY-MM-DD"}, + }, + { + "query": 'query{{userDailySummaryV2Scalar(startDate:"{startDate}", endDate:"{endDate}")}}', + "params": {"startDate": "YYYY-MM-DD", "endDate": "YYYY-MM-DD"}, + }, + { + "query": 'query{{workoutScheduleSummariesScalar(startDate:"{startDate}", endDate:"{endDate}")}}', + "params": {"startDate": "YYYY-MM-DD", "endDate": "YYYY-MM-DD"}, + }, + { + "query": 'query{{trainingPlanScalar(calendarDate:"{calendarDate}", lang:"en-US", firstDayOfWeek:"monday")}}', + "params": { + "calendarDate": "YYYY-MM-DD", + "lang": "str", + "firstDayOfWeek": "str", + }, + }, + { + "query": 'query{{menstrualCycleDetail(date:"{date}", todayDate:"{todayDate}"){{daySummary{{pregnancyCycle}}dayLog{{calendarDate, symptoms, moods, discharge, hasBabyMovement}}}}', + "params": {"date": "YYYY-MM-DD", "todayDate": "YYYY-MM-DD"}, + }, + { + "query": 'query{{activityStatsScalar(aggregation:"daily", startDate:"{startDate}", endDate:"{endDate}", metrics:["duration", "distance"], activityType:["running", "cycling", "swimming", "walking", "multi_sport", "fitness_equipment", "para_sports"], groupByParentActivityType:true, standardizedUnits:true)}}', + "params": { + "startDate": "YYYY-MM-DD", + "endDate": "YYYY-MM-DD", + "aggregation": "str", + "metrics": "list[str]", + "activityType": "list[str]", + "groupByParentActivityType": "bool", + "standardizedUnits": "bool", + }, + }, + { + "query": 'query{{activityStatsScalar(aggregation:"daily", startDate:"{startDate}", endDate:"{endDate}", metrics:["duration", "distance"], groupByParentActivityType:false, standardizedUnits:true)}}', + "params": { + "startDate": "YYYY-MM-DD", + "endDate": "YYYY-MM-DD", + "aggregation": "str", + "metrics": "list[str]", + "activityType": "list[str]", + "groupByParentActivityType": "bool", + "standardizedUnits": "bool", + }, + }, + { + "query": 'query{{sleepScalar(date:"{date}", sleepOnly:false)}}', + "params": {"date": "YYYY-MM-DD", "sleepOnly": "bool"}, + }, + { + "query": 'query{{jetLagScalar(date:"{date}")}}', + "params": {"date": "YYYY-MM-DD"}, + }, + { + "query": 'query{{myDayCardEventsScalar(timeZone:"GMT", date:"{date}")}}', + "params": {"date": "YYYY-MM-DD", "timezone": "str"}, + }, + {"query": "query{{adhocChallengesScalar}", "params": {}}, + {"query": "query{{adhocChallengePendingInviteScalar}", "params": {}}, + {"query": "query{{badgeChallengesScalar}", "params": {}}, + {"query": "query{{expeditionsChallengesScalar}", "params": {}}, + { + "query": 'query{{trainingReadinessRangeScalar(startDate:"{startDate}", endDate:"{endDate}")}}', + "params": {"startDate": "YYYY-MM-DD", "endDate": "YYYY-MM-DD"}, + }, + { + "query": 'query{{trainingStatusDailyScalar(calendarDate:"{calendarDate}")}}', + "params": {"calendarDate": "YYYY-MM-DD"}, + }, + { + "query": 'query{{trainingStatusWeeklyScalar(startDate:"{startDate}", endDate:"{endDate}", displayName:"{self.display_name}")}}', + "params": {"startDate": "YYYY-MM-DD", "endDate": "YYYY-MM-DD"}, + }, + { + "query": 'query{{trainingLoadBalanceScalar(calendarDate:"{calendarDate}", fullHistoryScan:true)}}', + "params": {"calendarDate": "YYYY-MM-DD", "fullHistoryScan": "bool"}, + }, + { + "query": 'query{{heatAltitudeAcclimationScalar(date:"{date}")}}', + "params": {"date": "YYYY-MM-DD"}, + }, + { + "query": 'query{{vo2MaxScalar(startDate:"{startDate}", endDate:"{endDate}")}}', + "params": {"startDate": "YYYY-MM-DD", "endDate": "YYYY-MM-DD"}, + }, + { + "query": 'query{{activityTrendsScalar(activityType:"running", date:"{date}")}}', + "params": {"date": "YYYY-MM-DD", "activityType": "str"}, + }, + { + "query": 'query{{activityTrendsScalar(activityType:"all", date:"{date}")}}', + "params": {"date": "YYYY-MM-DD", "activityType": "str"}, + }, + { + "query": 'query{{activityTrendsScalar(activityType:"fitness_equipment", date:"{date}")}}', + "params": {"date": "YYYY-MM-DD", "activityType": "str"}, + }, + {"query": "query{{userGoalsScalar}", "params": {}}, + { + "query": 'query{{trainingStatusWeeklyScalar(startDate:"{startDate}", endDate:"{endDate}", displayName:"{self.display_name}")}}', + "params": {"startDate": "YYYY-MM-DD", "endDate": "YYYY-MM-DD"}, + }, + { + "query": 'query{{enduranceScoreScalar(startDate:"{startDate}", endDate:"{endDate}", aggregation:"weekly")}}', + "params": { + "startDate": "YYYY-MM-DD", + "endDate": "YYYY-MM-DD", + "aggregation": "str", + }, + }, + { + "query": 'query{{latestWeightScalar(asOfDate:"{asOfDate}")}}', + "params": {"asOfDate": "str"}, + }, + { + "query": 'query{{pregnancyScalar(date:"{date}")}}', + "params": {"date": "YYYY-MM-DD"}, + }, + { + "query": 'query{{epochChartScalar(date:"{date}", include:["stress"])}}', + "params": {"date": "YYYY-MM-DD", "include": "list[str]"}, + }, +] + +GRAPHQL_QUERIES_WITH_SAMPLE_RESPONSES = [ + { + "query": { + "query": 'query{activitiesScalar(displayName:"ca8406dd-d7dd-4adb-825e-16967b1e82fb", startTimestampLocal:"2024-07-02T00:00:00.00", endTimestampLocal:"2024-07-08T23:59:59.999", limit:40)}' + }, + "response": { + "data": { + "activitiesScalar": { + "activityList": [ + { + "activityId": 16204035614, + "activityName": "Merrimac - Base with Hill Sprints and Strid", + "startTimeLocal": "2024-07-02 06:56:49", + "startTimeGMT": "2024-07-02 10:56:49", + "activityType": { + "typeId": 1, + "typeKey": "running", + "parentTypeId": 17, + "isHidden": false, + "trimmable": true, + "restricted": false, + }, + "eventType": { + "typeId": 9, + "typeKey": "uncategorized", + "sortOrder": 10, + }, + "distance": 12951.5302734375, + "duration": 3777.14892578125, + "elapsedDuration": 3806.303955078125, + "movingDuration": 3762.374988555908, + "elevationGain": 106.0, + "elevationLoss": 108.0, + "averageSpeed": 3.428999900817871, + "maxSpeed": 6.727000236511231, + "startLatitude": 42.84449494443834, + "startLongitude": -71.0120471008122, + "hasPolyline": true, + "hasImages": false, + "ownerId": "user_id: int", + "ownerDisplayName": "display_name", + "ownerFullName": "owner_name", + "ownerProfileImageUrlSmall": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/7768ce88-bdf9-4ba3-a19f-74a1674b760f-user_id.png", + "ownerProfileImageUrlMedium": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/d1f17694-b757-4434-818b-36224f064b67-user_id.png", + "ownerProfileImageUrlLarge": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/db7c55db-a9f9-40e2-af33-eef9dedecee4-user_id.png", + "calories": 955.0, + "bmrCalories": 97.0, + "averageHR": 139.0, + "maxHR": 164.0, + "averageRunningCadenceInStepsPerMinute": 165.59375, + "maxRunningCadenceInStepsPerMinute": 219.0, + "steps": 10158, + "userRoles": [ + "SCOPE_GOLF_API_READ", + "SCOPE_ATP_READ", + "SCOPE_DIVE_API_WRITE", + "SCOPE_COMMUNITY_COURSE_ADMIN_READ", + "SCOPE_DIVE_API_READ", + "SCOPE_DI_OAUTH_2_CLIENT_READ", + "SCOPE_CONNECT_WRITE", + "SCOPE_COMMUNITY_COURSE_WRITE", + "SCOPE_MESSAGE_GENERATION_READ", + "SCOPE_DI_OAUTH_2_CLIENT_REVOCATION_ADMIN", + "SCOPE_CONNECT_WEB_TEMPLATE_RENDER", + "SCOPE_CONNECT_NON_SOCIAL_SHARED_READ", + "SCOPE_CONNECT_READ", + "SCOPE_DI_OAUTH_2_TOKEN_ADMIN", + "ROLE_CONNECTUSER", + "ROLE_FITNESS_USER", + "ROLE_WELLNESS_USER", + "ROLE_OUTDOOR_USER", + ], + "privacy": {"typeId": 2, "typeKey": "private"}, + "userPro": false, + "hasVideo": false, + "timeZoneId": 149, + "beginTimestamp": 1719917809000, + "sportTypeId": 1, + "avgPower": 388.0, + "maxPower": 707.0, + "aerobicTrainingEffect": 3.200000047683716, + "anaerobicTrainingEffect": 2.4000000953674316, + "normPower": 397.0, + "avgVerticalOscillation": 9.480000305175782, + "avgGroundContactTime": 241.60000610351562, + "avgStrideLength": 124.90999755859376, + "vO2MaxValue": 60.0, + "avgVerticalRatio": 7.539999961853027, + "avgGroundContactBalance": 52.310001373291016, + "workoutId": 802967097, + "deviceId": 3472661486, + "minTemperature": 20.0, + "maxTemperature": 26.0, + "minElevation": 31.399999618530273, + "maxElevation": 51.0, + "maxDoubleCadence": 219.0, + "summarizedDiveInfo": {"summarizedDiveGases": []}, + "maxVerticalSpeed": 0.8000030517578125, + "manufacturer": "GARMIN", + "locationName": "Merrimac", + "lapCount": 36, + "endLatitude": 42.84442646428943, + "endLongitude": -71.01196898147464, + "waterEstimated": 1048.0, + "minRespirationRate": 21.68000030517578, + "maxRespirationRate": 42.36000061035156, + "avgRespirationRate": 30.920000076293945, + "trainingEffectLabel": "AEROBIC_BASE", + "activityTrainingLoad": 158.7926483154297, + "minActivityLapDuration": 15.0, + "aerobicTrainingEffectMessage": "IMPROVING_AEROBIC_BASE_8", + "anaerobicTrainingEffectMessage": "MAINTAINING_ANAEROBIC_POWER_7", + "splitSummaries": [ + { + "noOfSplits": 16, + "totalAscent": 67.0, + "duration": 2869.5791015625, + "splitType": "INTERVAL_ACTIVE", + "numClimbSends": 0, + "maxElevationGain": 63.0, + "averageElevationGain": 4.0, + "maxDistance": 8083, + "distance": 10425.3701171875, + "averageSpeed": 3.632999897003174, + "maxSpeed": 6.7270002365112305, + "numFalls": 0, + "elevationLoss": 89.0, + }, + { + "noOfSplits": 1, + "totalAscent": 0.0, + "duration": 3.000999927520752, + "splitType": "RWD_STAND", + "numClimbSends": 0, + "maxElevationGain": 0.0, + "averageElevationGain": 0.0, + "maxDistance": 4, + "distance": 4.570000171661377, + "averageSpeed": 1.5230000019073486, + "maxSpeed": 0.671999990940094, + "numFalls": 0, + "elevationLoss": 0.0, + }, + { + "noOfSplits": 8, + "totalAscent": 102.0, + "duration": 3698.02294921875, + "splitType": "RWD_RUN", + "numClimbSends": 0, + "maxElevationGain": 75.0, + "averageElevationGain": 13.0, + "maxDistance": 8593, + "distance": 12818.2900390625, + "averageSpeed": 3.4660000801086426, + "maxSpeed": 6.7270002365112305, + "numFalls": 0, + "elevationLoss": 105.0, + }, + { + "noOfSplits": 14, + "totalAscent": 29.0, + "duration": 560.0, + "splitType": "INTERVAL_RECOVERY", + "numClimbSends": 0, + "maxElevationGain": 7.0, + "averageElevationGain": 2.0, + "maxDistance": 121, + "distance": 1354.5899658203125, + "averageSpeed": 2.4189999103546143, + "maxSpeed": 6.568999767303467, + "numFalls": 0, + "elevationLoss": 18.0, + }, + { + "noOfSplits": 6, + "totalAscent": 3.0, + "duration": 79.0009994506836, + "splitType": "RWD_WALK", + "numClimbSends": 0, + "maxElevationGain": 2.0, + "averageElevationGain": 1.0, + "maxDistance": 38, + "distance": 128.6699981689453, + "averageSpeed": 1.628999948501587, + "maxSpeed": 1.996999979019165, + "numFalls": 0, + "elevationLoss": 3.0, + }, + { + "noOfSplits": 1, + "totalAscent": 9.0, + "duration": 346.8739929199219, + "splitType": "INTERVAL_COOLDOWN", + "numClimbSends": 0, + "maxElevationGain": 9.0, + "averageElevationGain": 9.0, + "maxDistance": 1175, + "distance": 1175.6099853515625, + "averageSpeed": 3.3889999389648438, + "maxSpeed": 3.7039999961853027, + "numFalls": 0, + "elevationLoss": 1.0, + }, + ], + "hasSplits": true, + "moderateIntensityMinutes": 55, + "vigorousIntensityMinutes": 1, + "avgGradeAdjustedSpeed": 3.4579999446868896, + "differenceBodyBattery": -18, + "purposeful": false, + "manualActivity": false, + "pr": false, + "autoCalcCalories": false, + "elevationCorrected": false, + "atpActivity": false, + "favorite": false, + "decoDive": false, + "parent": false, + }, + { + "activityId": 16226633730, + "activityName": "Long Beach Running", + "startTimeLocal": "2024-07-03 12:01:28", + "startTimeGMT": "2024-07-03 16:01:28", + "activityType": { + "typeId": 1, + "typeKey": "running", + "parentTypeId": 17, + "isHidden": false, + "trimmable": true, + "restricted": false, + }, + "eventType": { + "typeId": 9, + "typeKey": "uncategorized", + "sortOrder": 10, + }, + "distance": 19324.55078125, + "duration": 4990.2158203125, + "elapsedDuration": 4994.26708984375, + "movingDuration": 4985.841033935547, + "elevationGain": 5.0, + "elevationLoss": 2.0, + "averageSpeed": 3.871999979019165, + "maxSpeed": 4.432000160217285, + "startLatitude": 39.750197203829885, + "startLongitude": -74.1200018953532, + "hasPolyline": true, + "hasImages": false, + "ownerId": "user_id: int", + "ownerDisplayName": "display_name", + "ownerFullName": "owner_name", + "ownerProfileImageUrlSmall": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/7768ce88-bdf9-4ba3-a19f-74a1674b760f-user_id.png", + "ownerProfileImageUrlMedium": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/d1f17694-b757-4434-818b-36224f064b67-user_id.png", + "ownerProfileImageUrlLarge": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/db7c55db-a9f9-40e2-af33-eef9dedecee4-user_id.png", + "calories": 1410.0, + "bmrCalories": 129.0, + "averageHR": 151.0, + "maxHR": 163.0, + "averageRunningCadenceInStepsPerMinute": 173.109375, + "maxRunningCadenceInStepsPerMinute": 181.0, + "steps": 14260, + "userRoles": [ + "SCOPE_GOLF_API_READ", + "SCOPE_ATP_READ", + "SCOPE_DIVE_API_WRITE", + "SCOPE_COMMUNITY_COURSE_ADMIN_READ", + "SCOPE_DIVE_API_READ", + "SCOPE_DI_OAUTH_2_CLIENT_READ", + "SCOPE_CONNECT_WRITE", + "SCOPE_COMMUNITY_COURSE_WRITE", + "SCOPE_MESSAGE_GENERATION_READ", + "SCOPE_DI_OAUTH_2_CLIENT_REVOCATION_ADMIN", + "SCOPE_CONNECT_WEB_TEMPLATE_RENDER", + "SCOPE_CONNECT_NON_SOCIAL_SHARED_READ", + "SCOPE_CONNECT_READ", + "SCOPE_DI_OAUTH_2_TOKEN_ADMIN", + "ROLE_CONNECTUSER", + "ROLE_FITNESS_USER", + "ROLE_WELLNESS_USER", + "ROLE_OUTDOOR_USER", + ], + "privacy": {"typeId": 2, "typeKey": "private"}, + "userPro": false, + "hasVideo": false, + "timeZoneId": 149, + "beginTimestamp": 1720022488000, + "sportTypeId": 1, + "avgPower": 429.0, + "maxPower": 503.0, + "aerobicTrainingEffect": 4.099999904632568, + "anaerobicTrainingEffect": 0.0, + "normPower": 430.0, + "avgVerticalOscillation": 9.45999984741211, + "avgGroundContactTime": 221.39999389648438, + "avgStrideLength": 134.6199951171875, + "vO2MaxValue": 60.0, + "avgVerticalRatio": 6.809999942779541, + "avgGroundContactBalance": 52.790000915527344, + "deviceId": 3472661486, + "minTemperature": 29.0, + "maxTemperature": 34.0, + "minElevation": 2.5999999046325684, + "maxElevation": 7.800000190734863, + "maxDoubleCadence": 181.0, + "summarizedDiveInfo": {"summarizedDiveGases": []}, + "maxVerticalSpeed": 0.6000001430511475, + "manufacturer": "GARMIN", + "locationName": "Long Beach", + "lapCount": 13, + "endLatitude": 39.75033424794674, + "endLongitude": -74.12003693170846, + "waterEstimated": 1385.0, + "minRespirationRate": 13.300000190734863, + "maxRespirationRate": 42.77000045776367, + "avgRespirationRate": 28.969999313354492, + "trainingEffectLabel": "TEMPO", + "activityTrainingLoad": 210.4363555908203, + "minActivityLapDuration": 201.4739990234375, + "aerobicTrainingEffectMessage": "HIGHLY_IMPACTING_TEMPO_23", + "anaerobicTrainingEffectMessage": "NO_ANAEROBIC_BENEFIT_0", + "splitSummaries": [ + { + "noOfSplits": 1, + "totalAscent": 5.0, + "duration": 4990.2158203125, + "splitType": "INTERVAL_ACTIVE", + "numClimbSends": 0, + "maxElevationGain": 5.0, + "averageElevationGain": 2.0, + "maxDistance": 19324, + "distance": 19324.560546875, + "averageSpeed": 3.871999979019165, + "maxSpeed": 4.432000160217285, + "numFalls": 0, + "elevationLoss": 2.0, + }, + { + "noOfSplits": 1, + "totalAscent": 0.0, + "duration": 3.0, + "splitType": "RWD_STAND", + "numClimbSends": 0, + "maxElevationGain": 0.0, + "averageElevationGain": 0.0, + "maxDistance": 5, + "distance": 5.239999771118164, + "averageSpeed": 1.746999979019165, + "maxSpeed": 0.31700000166893005, + "numFalls": 0, + "elevationLoss": 0.0, + }, + { + "noOfSplits": 1, + "totalAscent": 5.0, + "duration": 4990.09619140625, + "splitType": "RWD_RUN", + "numClimbSends": 0, + "maxElevationGain": 5.0, + "averageElevationGain": 5.0, + "maxDistance": 19319, + "distance": 19319.3203125, + "averageSpeed": 3.871999979019165, + "maxSpeed": 4.432000160217285, + "numFalls": 0, + "elevationLoss": 2.0, + }, + ], + "hasSplits": true, + "moderateIntensityMinutes": 61, + "vigorousIntensityMinutes": 19, + "avgGradeAdjustedSpeed": 3.871000051498413, + "differenceBodyBattery": -20, + "purposeful": false, + "manualActivity": false, + "pr": false, + "autoCalcCalories": false, + "elevationCorrected": false, + "atpActivity": false, + "favorite": false, + "decoDive": false, + "parent": false, + }, + { + "activityId": 16238254136, + "activityName": "Long Beach - Base", + "startTimeLocal": "2024-07-04 07:45:46", + "startTimeGMT": "2024-07-04 11:45:46", + "activityType": { + "typeId": 1, + "typeKey": "running", + "parentTypeId": 17, + "isHidden": false, + "trimmable": true, + "restricted": false, + }, + "eventType": { + "typeId": 9, + "typeKey": "uncategorized", + "sortOrder": 10, + }, + "distance": 8373.5498046875, + "duration": 2351.343017578125, + "elapsedDuration": 2351.343017578125, + "movingDuration": 2349.2779846191406, + "elevationGain": 4.0, + "elevationLoss": 2.0, + "averageSpeed": 3.5610001087188725, + "maxSpeed": 3.7980000972747807, + "startLatitude": 39.75017515942454, + "startLongitude": -74.12003056146204, + "hasPolyline": true, + "hasImages": false, + "ownerId": "user_id: int", + "ownerDisplayName": "display_name", + "ownerFullName": "owner_name", + "ownerProfileImageUrlSmall": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/7768ce88-bdf9-4ba3-a19f-74a1674b760f-user_id.png", + "ownerProfileImageUrlMedium": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/d1f17694-b757-4434-818b-36224f064b67-user_id.png", + "ownerProfileImageUrlLarge": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/db7c55db-a9f9-40e2-af33-eef9dedecee4-user_id.png", + "calories": 622.0, + "bmrCalories": 61.0, + "averageHR": 142.0, + "maxHR": 149.0, + "averageRunningCadenceInStepsPerMinute": 167.53125, + "maxRunningCadenceInStepsPerMinute": 180.0, + "steps": 6506, + "userRoles": [ + "SCOPE_GOLF_API_READ", + "SCOPE_ATP_READ", + "SCOPE_DIVE_API_WRITE", + "SCOPE_COMMUNITY_COURSE_ADMIN_READ", + "SCOPE_DIVE_API_READ", + "SCOPE_DI_OAUTH_2_CLIENT_READ", + "SCOPE_CONNECT_WRITE", + "SCOPE_COMMUNITY_COURSE_WRITE", + "SCOPE_MESSAGE_GENERATION_READ", + "SCOPE_DI_OAUTH_2_CLIENT_REVOCATION_ADMIN", + "SCOPE_CONNECT_WEB_TEMPLATE_RENDER", + "SCOPE_CONNECT_NON_SOCIAL_SHARED_READ", + "SCOPE_CONNECT_READ", + "SCOPE_DI_OAUTH_2_TOKEN_ADMIN", + "ROLE_CONNECTUSER", + "ROLE_FITNESS_USER", + "ROLE_WELLNESS_USER", + "ROLE_OUTDOOR_USER", + ], + "privacy": {"typeId": 2, "typeKey": "private"}, + "userPro": false, + "hasVideo": false, + "timeZoneId": 149, + "beginTimestamp": 1720093546000, + "sportTypeId": 1, + "avgPower": 413.0, + "maxPower": 475.0, + "aerobicTrainingEffect": 3.0, + "anaerobicTrainingEffect": 0.0, + "normPower": 416.0, + "avgVerticalOscillation": 9.880000305175782, + "avgGroundContactTime": 236.5, + "avgStrideLength": 127.95999755859376, + "vO2MaxValue": 60.0, + "avgVerticalRatio": 7.510000228881836, + "avgGroundContactBalance": 51.61000061035156, + "workoutId": 271119547, + "deviceId": 3472661486, + "minTemperature": 25.0, + "maxTemperature": 31.0, + "minElevation": 3.0, + "maxElevation": 7.0, + "maxDoubleCadence": 180.0, + "summarizedDiveInfo": {"summarizedDiveGases": []}, + "maxVerticalSpeed": 0.20000028610229495, + "manufacturer": "GARMIN", + "locationName": "Long Beach", + "lapCount": 6, + "endLatitude": 39.750206507742405, + "endLongitude": -74.1200394462794, + "waterEstimated": 652.0, + "minRespirationRate": 16.700000762939453, + "maxRespirationRate": 40.41999816894531, + "avgRespirationRate": 26.940000534057617, + "trainingEffectLabel": "AEROBIC_BASE", + "activityTrainingLoad": 89.67962646484375, + "minActivityLapDuration": 92.66699981689453, + "aerobicTrainingEffectMessage": "IMPROVING_AEROBIC_BASE_8", + "anaerobicTrainingEffectMessage": "NO_ANAEROBIC_BENEFIT_0", + "splitSummaries": [ + { + "noOfSplits": 1, + "totalAscent": 4.0, + "duration": 2351.343017578125, + "splitType": "INTERVAL_ACTIVE", + "numClimbSends": 0, + "maxElevationGain": 4.0, + "averageElevationGain": 4.0, + "maxDistance": 8373, + "distance": 8373.5595703125, + "averageSpeed": 3.561000108718872, + "maxSpeed": 3.7980000972747803, + "numFalls": 0, + "elevationLoss": 2.0, + }, + { + "noOfSplits": 1, + "totalAscent": 0.0, + "duration": 3.0, + "splitType": "RWD_STAND", + "numClimbSends": 0, + "maxElevationGain": 0.0, + "averageElevationGain": 0.0, + "maxDistance": 6, + "distance": 6.110000133514404, + "averageSpeed": 2.0369999408721924, + "maxSpeed": 1.3619999885559082, + "numFalls": 0, + "elevationLoss": 0.0, + }, + { + "noOfSplits": 1, + "totalAscent": 4.0, + "duration": 2351.19189453125, + "splitType": "RWD_RUN", + "numClimbSends": 0, + "maxElevationGain": 4.0, + "averageElevationGain": 4.0, + "maxDistance": 8367, + "distance": 8367.4501953125, + "averageSpeed": 3.559000015258789, + "maxSpeed": 3.7980000972747803, + "numFalls": 0, + "elevationLoss": 2.0, + }, + ], + "hasSplits": true, + "moderateIntensityMinutes": 35, + "vigorousIntensityMinutes": 0, + "avgGradeAdjustedSpeed": 3.562999963760376, + "differenceBodyBattery": -10, + "purposeful": false, + "manualActivity": false, + "pr": false, + "autoCalcCalories": false, + "elevationCorrected": false, + "atpActivity": false, + "favorite": false, + "decoDive": false, + "parent": false, + }, + { + "activityId": 16258207221, + "activityName": "Long Beach Running", + "startTimeLocal": "2024-07-05 09:28:26", + "startTimeGMT": "2024-07-05 13:28:26", + "activityType": { + "typeId": 1, + "typeKey": "running", + "parentTypeId": 17, + "isHidden": false, + "trimmable": true, + "restricted": false, + }, + "eventType": { + "typeId": 9, + "typeKey": "uncategorized", + "sortOrder": 10, + }, + "distance": 28973.609375, + "duration": 8030.9619140625, + "elapsedDuration": 8102.52685546875, + "movingDuration": 8027.666015625, + "elevationGain": 9.0, + "elevationLoss": 7.0, + "averageSpeed": 3.6080000400543213, + "maxSpeed": 3.9100000858306885, + "startLatitude": 39.750175746157765, + "startLongitude": -74.12008135579526, + "hasPolyline": true, + "hasImages": false, + "ownerId": "user_id: int", + "ownerDisplayName": "display_name", + "ownerFullName": "owner_name", + "ownerProfileImageUrlSmall": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/7768ce88-bdf9-4ba3-a19f-74a1674b760f-user_id.png", + "ownerProfileImageUrlMedium": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/d1f17694-b757-4434-818b-36224f064b67-user_id.png", + "ownerProfileImageUrlLarge": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/db7c55db-a9f9-40e2-af33-eef9dedecee4-user_id.png", + "calories": 2139.0, + "bmrCalories": 207.0, + "averageHR": 148.0, + "maxHR": 156.0, + "averageRunningCadenceInStepsPerMinute": 170.859375, + "maxRunningCadenceInStepsPerMinute": 182.0, + "steps": 22650, + "userRoles": [ + "SCOPE_GOLF_API_READ", + "SCOPE_ATP_READ", + "SCOPE_DIVE_API_WRITE", + "SCOPE_COMMUNITY_COURSE_ADMIN_READ", + "SCOPE_DIVE_API_READ", + "SCOPE_DI_OAUTH_2_CLIENT_READ", + "SCOPE_CONNECT_WRITE", + "SCOPE_COMMUNITY_COURSE_WRITE", + "SCOPE_MESSAGE_GENERATION_READ", + "SCOPE_DI_OAUTH_2_CLIENT_REVOCATION_ADMIN", + "SCOPE_CONNECT_WEB_TEMPLATE_RENDER", + "SCOPE_CONNECT_NON_SOCIAL_SHARED_READ", + "SCOPE_CONNECT_READ", + "SCOPE_DI_OAUTH_2_TOKEN_ADMIN", + "ROLE_CONNECTUSER", + "ROLE_FITNESS_USER", + "ROLE_WELLNESS_USER", + "ROLE_OUTDOOR_USER", + ], + "privacy": {"typeId": 2, "typeKey": "private"}, + "userPro": false, + "hasVideo": false, + "timeZoneId": 149, + "beginTimestamp": 1720186106000, + "sportTypeId": 1, + "avgPower": 432.0, + "maxPower": 520.0, + "aerobicTrainingEffect": 4.300000190734863, + "anaerobicTrainingEffect": 0.0, + "normPower": 433.0, + "avgVerticalOscillation": 9.8, + "avgGroundContactTime": 240.5, + "avgStrideLength": 127.30000000000001, + "vO2MaxValue": 60.0, + "avgVerticalRatio": 7.46999979019165, + "avgGroundContactBalance": 54.040000915527344, + "deviceId": 3472661486, + "minTemperature": 27.0, + "maxTemperature": 29.0, + "minElevation": 2.5999999046325684, + "maxElevation": 8.199999809265137, + "maxDoubleCadence": 182.0, + "summarizedDiveInfo": {"summarizedDiveGases": []}, + "maxVerticalSpeed": 0.40000009536743164, + "manufacturer": "GARMIN", + "locationName": "Long Beach", + "lapCount": 19, + "endLatitude": 39.75011992268264, + "endLongitude": -74.12015100941062, + "waterEstimated": 2230.0, + "minRespirationRate": 15.739999771118164, + "maxRespirationRate": 42.810001373291016, + "avgRespirationRate": 29.559999465942383, + "trainingEffectLabel": "AEROBIC_BASE", + "activityTrainingLoad": 235.14840698242188, + "minActivityLapDuration": 1.315999984741211, + "aerobicTrainingEffectMessage": "HIGHLY_IMPROVING_AEROBIC_ENDURANCE_10", + "anaerobicTrainingEffectMessage": "NO_ANAEROBIC_BENEFIT_0", + "splitSummaries": [ + { + "noOfSplits": 1, + "totalAscent": 9.0, + "duration": 8030.9619140625, + "splitType": "INTERVAL_ACTIVE", + "numClimbSends": 0, + "maxElevationGain": 9.0, + "averageElevationGain": 9.0, + "maxDistance": 28973, + "distance": 28973.619140625, + "averageSpeed": 3.6080000400543213, + "maxSpeed": 3.9100000858306885, + "numFalls": 0, + "elevationLoss": 7.0, + }, + { + "noOfSplits": 1, + "totalAscent": 0.0, + "duration": 3.0, + "splitType": "RWD_STAND", + "numClimbSends": 0, + "maxElevationGain": 0.0, + "averageElevationGain": 0.0, + "maxDistance": 4, + "distance": 4.989999771118164, + "averageSpeed": 1.6629999876022339, + "maxSpeed": 1.4559999704360962, + "numFalls": 0, + "elevationLoss": 0.0, + }, + { + "noOfSplits": 3, + "totalAscent": 9.0, + "duration": 8026.0361328125, + "splitType": "RWD_RUN", + "numClimbSends": 0, + "maxElevationGain": 6.0, + "averageElevationGain": 3.0, + "maxDistance": 12667, + "distance": 28956.9609375, + "averageSpeed": 3.6080000400543213, + "maxSpeed": 3.9100000858306885, + "numFalls": 0, + "elevationLoss": 7.0, + }, + { + "noOfSplits": 2, + "totalAscent": 0.0, + "duration": 4.758999824523926, + "splitType": "RWD_WALK", + "numClimbSends": 0, + "maxElevationGain": 0.0, + "averageElevationGain": 0.0, + "maxDistance": 8, + "distance": 11.680000305175781, + "averageSpeed": 2.4539999961853027, + "maxSpeed": 1.222000002861023, + "numFalls": 0, + "elevationLoss": 0.0, + }, + ], + "hasSplits": true, + "moderateIntensityMinutes": 131, + "vigorousIntensityMinutes": 0, + "avgGradeAdjustedSpeed": 3.6059999465942383, + "differenceBodyBattery": -30, + "purposeful": false, + "manualActivity": false, + "pr": false, + "autoCalcCalories": false, + "elevationCorrected": false, + "atpActivity": false, + "favorite": false, + "decoDive": false, + "parent": false, + }, + { + "activityId": 16271956235, + "activityName": "Long Beach - Base", + "startTimeLocal": "2024-07-06 08:28:19", + "startTimeGMT": "2024-07-06 12:28:19", + "activityType": { + "typeId": 1, + "typeKey": "running", + "parentTypeId": 17, + "isHidden": false, + "trimmable": true, + "restricted": false, + }, + "eventType": { + "typeId": 9, + "typeKey": "uncategorized", + "sortOrder": 10, + }, + "distance": 7408.22998046875, + "duration": 2123.346923828125, + "elapsedDuration": 2123.346923828125, + "movingDuration": 2121.5660095214844, + "elevationGain": 5.0, + "elevationLoss": 38.0, + "averageSpeed": 3.4890000820159917, + "maxSpeed": 3.686000108718872, + "startLatitude": 39.750188402831554, + "startLongitude": -74.11999653093517, + "hasPolyline": true, + "hasImages": false, + "ownerId": "user_id: int", + "ownerDisplayName": "display_name", + "ownerFullName": "owner_name", + "ownerProfileImageUrlSmall": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/7768ce88-bdf9-4ba3-a19f-74a1674b760f-user_id.png", + "ownerProfileImageUrlMedium": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/d1f17694-b757-4434-818b-36224f064b67-user_id.png", + "ownerProfileImageUrlLarge": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/db7c55db-a9f9-40e2-af33-eef9dedecee4-user_id.png", + "calories": 558.0, + "bmrCalories": 55.0, + "averageHR": 141.0, + "maxHR": 149.0, + "averageRunningCadenceInStepsPerMinute": 166.859375, + "maxRunningCadenceInStepsPerMinute": 177.0, + "steps": 5832, + "userRoles": [ + "SCOPE_GOLF_API_READ", + "SCOPE_ATP_READ", + "SCOPE_DIVE_API_WRITE", + "SCOPE_COMMUNITY_COURSE_ADMIN_READ", + "SCOPE_DIVE_API_READ", + "SCOPE_DI_OAUTH_2_CLIENT_READ", + "SCOPE_CONNECT_WRITE", + "SCOPE_COMMUNITY_COURSE_WRITE", + "SCOPE_MESSAGE_GENERATION_READ", + "SCOPE_DI_OAUTH_2_CLIENT_REVOCATION_ADMIN", + "SCOPE_CONNECT_WEB_TEMPLATE_RENDER", + "SCOPE_CONNECT_NON_SOCIAL_SHARED_READ", + "SCOPE_CONNECT_READ", + "SCOPE_DI_OAUTH_2_TOKEN_ADMIN", + "ROLE_CONNECTUSER", + "ROLE_FITNESS_USER", + "ROLE_WELLNESS_USER", + "ROLE_OUTDOOR_USER", + ], + "privacy": {"typeId": 2, "typeKey": "private"}, + "userPro": false, + "hasVideo": false, + "timeZoneId": 149, + "beginTimestamp": 1720268899000, + "sportTypeId": 1, + "avgPower": 409.0, + "maxPower": 478.0, + "aerobicTrainingEffect": 2.9000000953674316, + "anaerobicTrainingEffect": 0.0, + "normPower": 413.0, + "avgVerticalOscillation": 9.790000152587892, + "avgGroundContactTime": 243.8000030517578, + "avgStrideLength": 125.7800048828125, + "vO2MaxValue": 60.0, + "avgVerticalRatio": 7.559999942779541, + "avgGroundContactBalance": 52.72999954223633, + "deviceId": 3472661486, + "minTemperature": 27.0, + "maxTemperature": 30.0, + "minElevation": 1.2000000476837158, + "maxElevation": 5.800000190734863, + "maxDoubleCadence": 177.0, + "summarizedDiveInfo": {"summarizedDiveGases": []}, + "maxVerticalSpeed": 0.40000009536743164, + "manufacturer": "GARMIN", + "locationName": "Long Beach", + "lapCount": 5, + "endLatitude": 39.7502083517611, + "endLongitude": -74.1200505103916, + "waterEstimated": 589.0, + "minRespirationRate": 23.950000762939453, + "maxRespirationRate": 45.40999984741211, + "avgRespirationRate": 33.619998931884766, + "trainingEffectLabel": "AEROBIC_BASE", + "activityTrainingLoad": 81.58389282226562, + "minActivityLapDuration": 276.1619873046875, + "aerobicTrainingEffectMessage": "MAINTAINING_AEROBIC_FITNESS_1", + "anaerobicTrainingEffectMessage": "NO_ANAEROBIC_BENEFIT_0", + "splitSummaries": [ + { + "noOfSplits": 1, + "totalAscent": 5.0, + "duration": 2123.346923828125, + "splitType": "INTERVAL_ACTIVE", + "numClimbSends": 0, + "maxElevationGain": 5.0, + "averageElevationGain": 5.0, + "maxDistance": 7408, + "distance": 7408.240234375, + "averageSpeed": 3.489000082015991, + "maxSpeed": 3.686000108718872, + "numFalls": 0, + "elevationLoss": 38.0, + }, + { + "noOfSplits": 1, + "totalAscent": 0.0, + "duration": 3.000999927520752, + "splitType": "RWD_STAND", + "numClimbSends": 0, + "maxElevationGain": 0.0, + "averageElevationGain": 0.0, + "maxDistance": 3, + "distance": 3.9000000953674316, + "averageSpeed": 1.2999999523162842, + "maxSpeed": 0.0, + "numFalls": 0, + "elevationLoss": 0.0, + }, + { + "noOfSplits": 1, + "totalAscent": 5.0, + "duration": 2123.1708984375, + "splitType": "RWD_RUN", + "numClimbSends": 0, + "maxElevationGain": 5.0, + "averageElevationGain": 5.0, + "maxDistance": 7404, + "distance": 7404.33984375, + "averageSpeed": 3.486999988555908, + "maxSpeed": 3.686000108718872, + "numFalls": 0, + "elevationLoss": 38.0, + }, + ], + "hasSplits": true, + "moderateIntensityMinutes": 31, + "vigorousIntensityMinutes": 0, + "avgGradeAdjustedSpeed": 3.4860000610351562, + "differenceBodyBattery": -10, + "purposeful": false, + "manualActivity": false, + "pr": false, + "autoCalcCalories": false, + "elevationCorrected": false, + "atpActivity": false, + "favorite": false, + "decoDive": false, + "parent": false, + }, + { + "activityId": 16278290894, + "activityName": "Long Beach Kayaking", + "startTimeLocal": "2024-07-06 15:12:08", + "startTimeGMT": "2024-07-06 19:12:08", + "activityType": { + "typeId": 231, + "typeKey": "kayaking_v2", + "parentTypeId": 228, + "isHidden": false, + "trimmable": true, + "restricted": false, + }, + "eventType": { + "typeId": 9, + "typeKey": "uncategorized", + "sortOrder": 10, + }, + "distance": 2285.330078125, + "duration": 2198.8310546875, + "elapsedDuration": 2198.8310546875, + "movingDuration": 1654.0, + "elevationGain": 3.0, + "elevationLoss": 1.0, + "averageSpeed": 1.0390000343322754, + "maxSpeed": 1.968999981880188, + "startLatitude": 39.75069425068796, + "startLongitude": -74.12023625336587, + "hasPolyline": true, + "hasImages": false, + "ownerId": "user_id: int", + "ownerDisplayName": "display_name", + "ownerFullName": "owner_name", + "ownerProfileImageUrlSmall": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/7768ce88-bdf9-4ba3-a19f-74a1674b760f-user_id.png", + "ownerProfileImageUrlMedium": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/d1f17694-b757-4434-818b-36224f064b67-user_id.png", + "ownerProfileImageUrlLarge": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/db7c55db-a9f9-40e2-af33-eef9dedecee4-user_id.png", + "calories": 146.0, + "bmrCalories": 57.0, + "averageHR": 77.0, + "maxHR": 107.0, + "userRoles": [ + "SCOPE_GOLF_API_READ", + "SCOPE_ATP_READ", + "SCOPE_DIVE_API_WRITE", + "SCOPE_COMMUNITY_COURSE_ADMIN_READ", + "SCOPE_DIVE_API_READ", + "SCOPE_DI_OAUTH_2_CLIENT_READ", + "SCOPE_CONNECT_WRITE", + "SCOPE_COMMUNITY_COURSE_WRITE", + "SCOPE_MESSAGE_GENERATION_READ", + "SCOPE_DI_OAUTH_2_CLIENT_REVOCATION_ADMIN", + "SCOPE_CONNECT_WEB_TEMPLATE_RENDER", + "SCOPE_CONNECT_NON_SOCIAL_SHARED_READ", + "SCOPE_CONNECT_READ", + "SCOPE_DI_OAUTH_2_TOKEN_ADMIN", + "ROLE_CONNECTUSER", + "ROLE_FITNESS_USER", + "ROLE_WELLNESS_USER", + "ROLE_OUTDOOR_USER", + ], + "privacy": {"typeId": 2, "typeKey": "private"}, + "userPro": false, + "hasVideo": false, + "timeZoneId": 149, + "beginTimestamp": 1720293128000, + "sportTypeId": 41, + "aerobicTrainingEffect": 0.10000000149011612, + "anaerobicTrainingEffect": 0.0, + "deviceId": 3472661486, + "minElevation": 1.2000000476837158, + "maxElevation": 3.5999999046325684, + "summarizedDiveInfo": {"summarizedDiveGases": []}, + "maxVerticalSpeed": 0.40000009536743164, + "manufacturer": "GARMIN", + "locationName": "Long Beach", + "lapCount": 1, + "endLatitude": 39.75058360956609, + "endLongitude": -74.12024606019258, + "waterEstimated": 345.0, + "trainingEffectLabel": "UNKNOWN", + "activityTrainingLoad": 2.1929931640625, + "minActivityLapDuration": 2198.8310546875, + "aerobicTrainingEffectMessage": "NO_AEROBIC_BENEFIT_18", + "anaerobicTrainingEffectMessage": "NO_ANAEROBIC_BENEFIT_0", + "splitSummaries": [], + "hasSplits": false, + "differenceBodyBattery": -3, + "purposeful": false, + "manualActivity": false, + "pr": false, + "autoCalcCalories": false, + "elevationCorrected": false, + "atpActivity": false, + "favorite": false, + "decoDive": false, + "parent": false, + }, + { + "activityId": 16279951766, + "activityName": "Long Beach Cycling", + "startTimeLocal": "2024-07-06 19:55:27", + "startTimeGMT": "2024-07-06 23:55:27", + "activityType": { + "typeId": 2, + "typeKey": "cycling", + "parentTypeId": 17, + "isHidden": false, + "trimmable": true, + "restricted": false, + }, + "eventType": { + "typeId": 9, + "typeKey": "uncategorized", + "sortOrder": 10, + }, + "distance": 15816.48046875, + "duration": 2853.280029296875, + "elapsedDuration": 2853.280029296875, + "movingDuration": 2850.14404296875, + "elevationGain": 8.0, + "elevationLoss": 6.0, + "averageSpeed": 5.543000221252441, + "maxSpeed": 7.146999835968018, + "startLatitude": 39.75072040222585, + "startLongitude": -74.11923930980265, + "hasPolyline": true, + "hasImages": false, + "ownerId": "user_id: int", + "ownerDisplayName": "display_name", + "ownerFullName": "owner_name", + "ownerProfileImageUrlSmall": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/7768ce88-bdf9-4ba3-a19f-74a1674b760f-user_id.png", + "ownerProfileImageUrlMedium": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/d1f17694-b757-4434-818b-36224f064b67-user_id.png", + "ownerProfileImageUrlLarge": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/db7c55db-a9f9-40e2-af33-eef9dedecee4-user_id.png", + "calories": 414.0, + "bmrCalories": 74.0, + "averageHR": 112.0, + "maxHR": 129.0, + "userRoles": [ + "SCOPE_GOLF_API_READ", + "SCOPE_ATP_READ", + "SCOPE_DIVE_API_WRITE", + "SCOPE_COMMUNITY_COURSE_ADMIN_READ", + "SCOPE_DIVE_API_READ", + "SCOPE_DI_OAUTH_2_CLIENT_READ", + "SCOPE_CONNECT_WRITE", + "SCOPE_COMMUNITY_COURSE_WRITE", + "SCOPE_MESSAGE_GENERATION_READ", + "SCOPE_DI_OAUTH_2_CLIENT_REVOCATION_ADMIN", + "SCOPE_CONNECT_WEB_TEMPLATE_RENDER", + "SCOPE_CONNECT_NON_SOCIAL_SHARED_READ", + "SCOPE_CONNECT_READ", + "SCOPE_DI_OAUTH_2_TOKEN_ADMIN", + "ROLE_CONNECTUSER", + "ROLE_FITNESS_USER", + "ROLE_WELLNESS_USER", + "ROLE_OUTDOOR_USER", + ], + "privacy": {"typeId": 2, "typeKey": "private"}, + "userPro": false, + "hasVideo": false, + "timeZoneId": 149, + "beginTimestamp": 1720310127000, + "sportTypeId": 2, + "aerobicTrainingEffect": 1.2999999523162842, + "anaerobicTrainingEffect": 0.0, + "deviceId": 3472661486, + "minElevation": 2.4000000953674316, + "maxElevation": 5.800000190734863, + "summarizedDiveInfo": {"summarizedDiveGases": []}, + "maxVerticalSpeed": 0.7999999523162843, + "manufacturer": "GARMIN", + "locationName": "Long Beach", + "lapCount": 2, + "endLatitude": 39.750200640410185, + "endLongitude": -74.12000114098191, + "waterEstimated": 442.0, + "trainingEffectLabel": "RECOVERY", + "activityTrainingLoad": 18.74017333984375, + "minActivityLapDuration": 1378.135986328125, + "aerobicTrainingEffectMessage": "RECOVERY_5", + "anaerobicTrainingEffectMessage": "NO_ANAEROBIC_BENEFIT_0", + "splitSummaries": [], + "hasSplits": false, + "moderateIntensityMinutes": 22, + "vigorousIntensityMinutes": 0, + "differenceBodyBattery": -3, + "purposeful": false, + "manualActivity": false, + "pr": false, + "autoCalcCalories": false, + "elevationCorrected": false, + "atpActivity": false, + "favorite": false, + "decoDive": false, + "parent": false, + }, + { + "activityId": 16287285483, + "activityName": "Long Beach Running", + "startTimeLocal": "2024-07-07 07:19:09", + "startTimeGMT": "2024-07-07 11:19:09", + "activityType": { + "typeId": 1, + "typeKey": "running", + "parentTypeId": 17, + "isHidden": false, + "trimmable": true, + "restricted": false, + }, + "eventType": { + "typeId": 9, + "typeKey": "uncategorized", + "sortOrder": 10, + }, + "distance": 9866.7802734375, + "duration": 2516.8779296875, + "elapsedDuration": 2547.64794921875, + "movingDuration": 2514.3160095214844, + "elevationGain": 6.0, + "elevationLoss": 3.0, + "averageSpeed": 3.9200000762939458, + "maxSpeed": 4.48799991607666, + "startLatitude": 39.75016954354942, + "startLongitude": -74.1200158931315, + "hasPolyline": true, + "hasImages": false, + "ownerId": "user_id: int", + "ownerDisplayName": "display_name", + "ownerFullName": "owner_name", + "ownerProfileImageUrlSmall": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/7768ce88-bdf9-4ba3-a19f-74a1674b760f-user_id.png", + "ownerProfileImageUrlMedium": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/d1f17694-b757-4434-818b-36224f064b67-user_id.png", + "ownerProfileImageUrlLarge": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/db7c55db-a9f9-40e2-af33-eef9dedecee4-user_id.png", + "calories": 722.0, + "bmrCalories": 65.0, + "averageHR": 152.0, + "maxHR": 166.0, + "averageRunningCadenceInStepsPerMinute": 175.265625, + "maxRunningCadenceInStepsPerMinute": 186.0, + "steps": 7290, + "userRoles": [ + "SCOPE_GOLF_API_READ", + "SCOPE_ATP_READ", + "SCOPE_DIVE_API_WRITE", + "SCOPE_COMMUNITY_COURSE_ADMIN_READ", + "SCOPE_DIVE_API_READ", + "SCOPE_DI_OAUTH_2_CLIENT_READ", + "SCOPE_CONNECT_WRITE", + "SCOPE_COMMUNITY_COURSE_WRITE", + "SCOPE_MESSAGE_GENERATION_READ", + "SCOPE_DI_OAUTH_2_CLIENT_REVOCATION_ADMIN", + "SCOPE_CONNECT_WEB_TEMPLATE_RENDER", + "SCOPE_CONNECT_NON_SOCIAL_SHARED_READ", + "SCOPE_CONNECT_READ", + "SCOPE_DI_OAUTH_2_TOKEN_ADMIN", + "ROLE_CONNECTUSER", + "ROLE_FITNESS_USER", + "ROLE_WELLNESS_USER", + "ROLE_OUTDOOR_USER", + ], + "privacy": {"typeId": 2, "typeKey": "private"}, + "userPro": false, + "hasVideo": false, + "timeZoneId": 149, + "beginTimestamp": 1720351149000, + "sportTypeId": 1, + "avgPower": 432.0, + "maxPower": 515.0, + "aerobicTrainingEffect": 3.5, + "anaerobicTrainingEffect": 0.0, + "normPower": 436.0, + "avgVerticalOscillation": 9.040000152587892, + "avgGroundContactTime": 228.0, + "avgStrideLength": 134.25999755859377, + "vO2MaxValue": 60.0, + "avgVerticalRatio": 6.579999923706055, + "avgGroundContactBalance": 54.38999938964844, + "deviceId": 3472661486, + "minTemperature": 28.0, + "maxTemperature": 32.0, + "minElevation": 2.5999999046325684, + "maxElevation": 6.199999809265137, + "maxDoubleCadence": 186.0, + "summarizedDiveInfo": {"summarizedDiveGases": []}, + "maxVerticalSpeed": 0.40000009536743164, + "manufacturer": "GARMIN", + "locationName": "Long Beach", + "lapCount": 7, + "endLatitude": 39.75026350468397, + "endLongitude": -74.12007171660662, + "waterEstimated": 698.0, + "minRespirationRate": 18.989999771118164, + "maxRespirationRate": 41.900001525878906, + "avgRespirationRate": 33.88999938964844, + "trainingEffectLabel": "LACTATE_THRESHOLD", + "activityTrainingLoad": 143.64161682128906, + "minActivityLapDuration": 152.44200134277344, + "aerobicTrainingEffectMessage": "IMPROVING_LACTATE_THRESHOLD_12", + "anaerobicTrainingEffectMessage": "NO_ANAEROBIC_BENEFIT_0", + "splitSummaries": [ + { + "noOfSplits": 1, + "totalAscent": 0.0, + "duration": 3.000999927520752, + "splitType": "RWD_STAND", + "numClimbSends": 0, + "maxElevationGain": 0.0, + "averageElevationGain": 0.0, + "maxDistance": 3, + "distance": 3.7899999618530273, + "averageSpeed": 1.2630000114440918, + "maxSpeed": 0.7179999947547913, + "numFalls": 0, + "elevationLoss": 0.0, + }, + { + "noOfSplits": 1, + "totalAscent": 6.0, + "duration": 2516.8779296875, + "splitType": "INTERVAL_ACTIVE", + "numClimbSends": 0, + "maxElevationGain": 6.0, + "averageElevationGain": 2.0, + "maxDistance": 9866, + "distance": 9866.7802734375, + "averageSpeed": 3.9200000762939453, + "maxSpeed": 4.48799991607666, + "numFalls": 0, + "elevationLoss": 3.0, + }, + { + "noOfSplits": 2, + "totalAscent": 6.0, + "duration": 2516.760986328125, + "splitType": "RWD_RUN", + "numClimbSends": 0, + "maxElevationGain": 4.0, + "averageElevationGain": 3.0, + "maxDistance": 6614, + "distance": 9862.990234375, + "averageSpeed": 3.9189999103546143, + "maxSpeed": 4.48799991607666, + "numFalls": 0, + "elevationLoss": 3.0, + }, + ], + "hasSplits": true, + "moderateIntensityMinutes": 26, + "vigorousIntensityMinutes": 14, + "avgGradeAdjustedSpeed": 3.9110000133514404, + "differenceBodyBattery": -12, + "purposeful": false, + "manualActivity": false, + "pr": false, + "autoCalcCalories": false, + "elevationCorrected": false, + "atpActivity": false, + "favorite": false, + "decoDive": false, + "parent": false, + }, + ], + "filter": { + "userProfileId": "user_id: int", + "includedPrivacyList": [], + "excludeUntitled": false, + }, + "requestorRelationship": "SELF", + } + } + }, + }, + { + "query": { + "query": 'query{healthSnapshotScalar(startDate:"2024-07-02", endDate:"2024-07-08")}' + }, + "response": {"data": {"healthSnapshotScalar": []}}, + }, + { + "query": { + "query": 'query{golfScorecardScalar(startTimestampLocal:"2024-07-02T00:00:00.00", endTimestampLocal:"2024-07-08T23:59:59.999")}' + }, + "response": {"data": {"golfScorecardScalar": []}}, + }, + { + "query": { + "query": 'query{weightScalar(startDate:"2024-07-02", endDate:"2024-07-08")}' + }, + "response": { + "data": { + "weightScalar": { + "dailyWeightSummaries": [ + { + "summaryDate": "2024-07-08", + "numOfWeightEntries": 1, + "minWeight": 82372.0, + "maxWeight": 82372.0, + "latestWeight": { + "samplePk": 1720435190064, + "date": 1720396800000, + "calendarDate": "2024-07-08", + "weight": 82372.0, + "bmi": null, + "bodyFat": null, + "bodyWater": null, + "boneMass": null, + "muscleMass": null, + "physiqueRating": null, + "visceralFat": null, + "metabolicAge": null, + "sourceType": "MFP", + "timestampGMT": 1720435137000, + "weightDelta": 907.18474, + }, + "allWeightMetrics": [], + }, + { + "summaryDate": "2024-07-02", + "numOfWeightEntries": 1, + "minWeight": 81465.0, + "maxWeight": 81465.0, + "latestWeight": { + "samplePk": 1719915378494, + "date": 1719878400000, + "calendarDate": "2024-07-02", + "weight": 81465.0, + "bmi": null, + "bodyFat": null, + "bodyWater": null, + "boneMass": null, + "muscleMass": null, + "physiqueRating": null, + "visceralFat": null, + "metabolicAge": null, + "sourceType": "MFP", + "timestampGMT": 1719915025000, + "weightDelta": 816.4662659999923, + }, + "allWeightMetrics": [], + }, + ], + "totalAverage": { + "from": 1719878400000, + "until": 1720483199999, + "weight": 81918.5, + "bmi": null, + "bodyFat": null, + "bodyWater": null, + "boneMass": null, + "muscleMass": null, + "physiqueRating": null, + "visceralFat": null, + "metabolicAge": null, + }, + "previousDateWeight": { + "samplePk": 1719828202070, + "date": 1719792000000, + "calendarDate": "2024-07-01", + "weight": 80648.0, + "bmi": null, + "bodyFat": null, + "bodyWater": null, + "boneMass": null, + "muscleMass": null, + "physiqueRating": null, + "visceralFat": null, + "metabolicAge": null, + "sourceType": "MFP", + "timestampGMT": 1719828107000, + "weightDelta": null, + }, + "nextDateWeight": { + "samplePk": null, + "date": null, + "calendarDate": null, + "weight": null, + "bmi": null, + "bodyFat": null, + "bodyWater": null, + "boneMass": null, + "muscleMass": null, + "physiqueRating": null, + "visceralFat": null, + "metabolicAge": null, + "sourceType": null, + "timestampGMT": null, + "weightDelta": null, + }, + } + } + }, + }, + { + "query": { + "query": 'query{bloodPressureScalar(startDate:"2024-07-02", endDate:"2024-07-08")}' + }, + "response": { + "data": { + "bloodPressureScalar": { + "from": "2024-07-02", + "until": "2024-07-08", + "measurementSummaries": [], + "categoryStats": null, + } + } + }, + }, + { + "query": { + "query": 'query{sleepSummariesScalar(startDate:"2024-06-11", endDate:"2024-07-08")}' + }, + "response": { + "data": { + "sleepSummariesScalar": [ + { + "id": 1718072795000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-11", + "sleepTimeSeconds": 28800, + "napTimeSeconds": 1200, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1718072795000, + "sleepEndTimestampGMT": 1718101835000, + "sleepStartTimestampLocal": 1718058395000, + "sleepEndTimestampLocal": 1718087435000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 6060, + "lightSleepSeconds": 16380, + "remSleepSeconds": 6360, + "awakeSleepSeconds": 240, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 95.0, + "lowestSpO2Value": 85, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 43.0, + "averageRespirationValue": 15.0, + "lowestRespirationValue": 8.0, + "highestRespirationValue": 23.0, + "awakeCount": 0, + "avgSleepStress": 13.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_OPTIMAL_STRUCTURE", + "sleepScoreInsight": "POSITIVE_EXERCISE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "EXCELLENT", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": { + "value": 96, + "qualifierKey": "EXCELLENT", + }, + "remPercentage": { + "value": 22, + "qualifierKey": "GOOD", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 6048.0, + "idealEndInSeconds": 8928.0, + }, + "restlessness": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 57, + "qualifierKey": "EXCELLENT", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 8640.0, + "idealEndInSeconds": 18432.0, + }, + "deepPercentage": { + "value": 21, + "qualifierKey": "EXCELLENT", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4608.0, + "idealEndInSeconds": 9504.0, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-11", + "deviceId": 3472661486, + "timestampGmt": "2024-06-10T22:10:37", + "baseline": 480, + "actual": 480, + "feedback": "NO_CHANGE_BALANCED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "DECREASING_HIGH_QUALITY", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": false, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-12", + "deviceId": 3472661486, + "timestampGmt": "2024-06-11T21:40:17", + "baseline": 480, + "actual": 460, + "feedback": "DECREASED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "DECREASING_HIGH_QUALITY", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "DECREASING", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "dailyNapDTOS": [ + { + "userProfilePK": "user_id: int", + "deviceId": 3472661486, + "calendarDate": "2024-06-11", + "napTimeSec": 1200, + "napStartTimestampGMT": "2024-06-11T20:00:58", + "napEndTimestampGMT": "2024-06-11T20:20:58", + "napFeedback": "IDEAL_DURATION_LOW_NEED", + "napSource": 1, + "napStartTimeOffset": -240, + "napEndTimeOffset": -240, + } + ], + }, + { + "id": 1718160434000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-12", + "sleepTimeSeconds": 28320, + "napTimeSeconds": 0, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1718160434000, + "sleepEndTimestampGMT": 1718188874000, + "sleepStartTimestampLocal": 1718146034000, + "sleepEndTimestampLocal": 1718174474000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 6540, + "lightSleepSeconds": 18060, + "remSleepSeconds": 3720, + "awakeSleepSeconds": 120, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 95.0, + "lowestSpO2Value": 86, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 45.0, + "averageRespirationValue": 14.0, + "lowestRespirationValue": 8.0, + "highestRespirationValue": 22.0, + "awakeCount": 0, + "avgSleepStress": 13.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_LONG_AND_DEEP", + "sleepScoreInsight": "POSITIVE_EXERCISE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "EXCELLENT", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "GOOD", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": {"value": 89, "qualifierKey": "GOOD"}, + "remPercentage": { + "value": 13, + "qualifierKey": "FAIR", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 5947.2, + "idealEndInSeconds": 8779.2, + }, + "restlessness": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 64, + "qualifierKey": "GOOD", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 8496.0, + "idealEndInSeconds": 18124.8, + }, + "deepPercentage": { + "value": 23, + "qualifierKey": "EXCELLENT", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4531.2, + "idealEndInSeconds": 9345.6, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-12", + "deviceId": 3472661486, + "timestampGmt": "2024-06-11T21:40:17", + "baseline": 480, + "actual": 460, + "feedback": "DECREASED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "DECREASING_HIGH_QUALITY", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "DECREASING", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-13", + "deviceId": 3472661486, + "timestampGmt": "2024-06-12T20:13:31", + "baseline": 480, + "actual": 480, + "feedback": "NO_CHANGE_BALANCED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "DECREASING_HIGH_QUALITY", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": false, + "preferredActivityTracker": true, + }, + }, + { + "id": 1718245530000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-13", + "sleepTimeSeconds": 26820, + "napTimeSeconds": 2400, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1718245530000, + "sleepEndTimestampGMT": 1718273790000, + "sleepStartTimestampLocal": 1718231130000, + "sleepEndTimestampLocal": 1718259390000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 3960, + "lightSleepSeconds": 18120, + "remSleepSeconds": 4740, + "awakeSleepSeconds": 1440, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 94.0, + "lowestSpO2Value": 84, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 46.0, + "averageRespirationValue": 14.0, + "lowestRespirationValue": 8.0, + "highestRespirationValue": 21.0, + "awakeCount": 2, + "avgSleepStress": 16.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_LONG_AND_CALM", + "sleepScoreInsight": "NONE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "EXCELLENT", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "FAIR", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "FAIR", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": {"value": 82, "qualifierKey": "GOOD"}, + "remPercentage": { + "value": 18, + "qualifierKey": "FAIR", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 5632.2, + "idealEndInSeconds": 8314.2, + }, + "restlessness": { + "qualifierKey": "FAIR", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 68, + "qualifierKey": "FAIR", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 8046.0, + "idealEndInSeconds": 17164.8, + }, + "deepPercentage": { + "value": 15, + "qualifierKey": "FAIR", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4291.2, + "idealEndInSeconds": 8850.6, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-13", + "deviceId": 3472661486, + "timestampGmt": "2024-06-12T20:13:31", + "baseline": 480, + "actual": 480, + "feedback": "NO_CHANGE_BALANCED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "DECREASING_HIGH_QUALITY", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": false, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-14", + "deviceId": 3472661486, + "timestampGmt": "2024-06-14T01:47:53", + "baseline": 480, + "actual": 460, + "feedback": "DECREASED", + "trainingFeedback": "DAILY_ACTIVITY_AND_CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "DECREASING", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "dailyNapDTOS": [ + { + "userProfilePK": "user_id: int", + "deviceId": 3472661486, + "calendarDate": "2024-06-13", + "napTimeSec": 2400, + "napStartTimestampGMT": "2024-06-13T18:06:33", + "napEndTimestampGMT": "2024-06-13T18:46:33", + "napFeedback": "LONG_DURATION_LOW_NEED", + "napSource": 1, + "napStartTimeOffset": -240, + "napEndTimeOffset": -240, + } + ], + }, + { + "id": 1718332508000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-14", + "sleepTimeSeconds": 27633, + "napTimeSeconds": 0, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1718332508000, + "sleepEndTimestampGMT": 1718361041000, + "sleepStartTimestampLocal": 1718318108000, + "sleepEndTimestampLocal": 1718346641000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 4500, + "lightSleepSeconds": 19620, + "remSleepSeconds": 3540, + "awakeSleepSeconds": 900, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 94.0, + "lowestSpO2Value": 87, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 47.0, + "averageRespirationValue": 14.0, + "lowestRespirationValue": 8.0, + "highestRespirationValue": 22.0, + "awakeCount": 1, + "avgSleepStress": 19.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_LONG_AND_CONTINUOUS", + "sleepScoreInsight": "NONE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "EXCELLENT", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "FAIR", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "GOOD", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": {"value": 81, "qualifierKey": "GOOD"}, + "remPercentage": { + "value": 13, + "qualifierKey": "FAIR", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 5802.93, + "idealEndInSeconds": 8566.23, + }, + "restlessness": { + "qualifierKey": "GOOD", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 71, + "qualifierKey": "FAIR", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 8289.9, + "idealEndInSeconds": 17685.12, + }, + "deepPercentage": { + "value": 16, + "qualifierKey": "GOOD", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4421.28, + "idealEndInSeconds": 9118.89, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-14", + "deviceId": 3472661486, + "timestampGmt": "2024-06-14T01:47:53", + "baseline": 480, + "actual": 460, + "feedback": "DECREASED", + "trainingFeedback": "DAILY_ACTIVITY_AND_CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "DECREASING", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-15", + "deviceId": 3472661486, + "timestampGmt": "2024-06-14T10:30:42", + "baseline": 480, + "actual": 500, + "feedback": "INCREASED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + }, + { + "id": 1718417681000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-15", + "sleepTimeSeconds": 30344, + "napTimeSeconds": 2699, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1718417681000, + "sleepEndTimestampGMT": 1718448085000, + "sleepStartTimestampLocal": 1718403281000, + "sleepEndTimestampLocal": 1718433685000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 4680, + "lightSleepSeconds": 17520, + "remSleepSeconds": 8160, + "awakeSleepSeconds": 60, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 94.0, + "lowestSpO2Value": 83, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 48.0, + "averageRespirationValue": 16.0, + "lowestRespirationValue": 8.0, + "highestRespirationValue": 23.0, + "awakeCount": 0, + "avgSleepStress": 21.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_LONG_AND_REFRESHING", + "sleepScoreInsight": "NONE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "EXCELLENT", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "FAIR", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": {"value": 86, "qualifierKey": "GOOD"}, + "remPercentage": { + "value": 27, + "qualifierKey": "EXCELLENT", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 6372.24, + "idealEndInSeconds": 9406.64, + }, + "restlessness": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 58, + "qualifierKey": "EXCELLENT", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 9103.2, + "idealEndInSeconds": 19420.16, + }, + "deepPercentage": { + "value": 15, + "qualifierKey": "FAIR", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4855.04, + "idealEndInSeconds": 10013.52, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-15", + "deviceId": 3472661486, + "timestampGmt": "2024-06-14T10:30:42", + "baseline": 480, + "actual": 500, + "feedback": "INCREASED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-16", + "deviceId": 3472661486, + "timestampGmt": "2024-06-15T20:30:37", + "baseline": 480, + "actual": 440, + "feedback": "DECREASED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "DECREASING_HIGH_QUALITY", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "DECREASING", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "dailyNapDTOS": [ + { + "userProfilePK": "user_id: int", + "deviceId": 3472661486, + "calendarDate": "2024-06-15", + "napTimeSec": 2699, + "napStartTimestampGMT": "2024-06-15T19:45:37", + "napEndTimestampGMT": "2024-06-15T20:30:36", + "napFeedback": "LATE_TIMING_LONG_DURATION_LOW_NEED", + "napSource": 1, + "napStartTimeOffset": -240, + "napEndTimeOffset": -240, + } + ], + }, + { + "id": 1718503447000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-16", + "sleepTimeSeconds": 30400, + "napTimeSeconds": 2700, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1718503447000, + "sleepEndTimestampGMT": 1718533847000, + "sleepStartTimestampLocal": 1718489047000, + "sleepEndTimestampLocal": 1718519447000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 7020, + "lightSleepSeconds": 18240, + "remSleepSeconds": 5160, + "awakeSleepSeconds": 0, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 94.0, + "lowestSpO2Value": 83, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 48.0, + "averageRespirationValue": 17.0, + "lowestRespirationValue": 8.0, + "highestRespirationValue": 25.0, + "awakeCount": 0, + "avgSleepStress": 16.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_LONG_AND_DEEP", + "sleepScoreInsight": "POSITIVE_EXERCISE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "EXCELLENT", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "GOOD", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": {"value": 89, "qualifierKey": "GOOD"}, + "remPercentage": { + "value": 17, + "qualifierKey": "FAIR", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 6384.0, + "idealEndInSeconds": 9424.0, + }, + "restlessness": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 60, + "qualifierKey": "GOOD", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 9120.0, + "idealEndInSeconds": 19456.0, + }, + "deepPercentage": { + "value": 23, + "qualifierKey": "EXCELLENT", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4864.0, + "idealEndInSeconds": 10032.0, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-16", + "deviceId": 3472661486, + "timestampGmt": "2024-06-15T20:30:37", + "baseline": 480, + "actual": 440, + "feedback": "DECREASED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "DECREASING_HIGH_QUALITY", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "DECREASING", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-17", + "deviceId": 3472661486, + "timestampGmt": "2024-06-16T23:55:04", + "baseline": 480, + "actual": 430, + "feedback": "DECREASED", + "trainingFeedback": "DAILY_ACTIVITY_AND_CHRONIC", + "sleepHistoryAdjustment": "DECREASING", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "DECREASING", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "dailyNapDTOS": [ + { + "userProfilePK": "user_id: int", + "deviceId": 3472661486, + "calendarDate": "2024-06-16", + "napTimeSec": 2700, + "napStartTimestampGMT": "2024-06-16T18:05:20", + "napEndTimestampGMT": "2024-06-16T18:50:20", + "napFeedback": "IDEAL_TIMING_LONG_DURATION_LOW_NEED", + "napSource": 1, + "napStartTimeOffset": -240, + "napEndTimeOffset": -240, + } + ], + }, + { + "id": 1718593410000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-17", + "sleepTimeSeconds": 29700, + "napTimeSeconds": 0, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1718593410000, + "sleepEndTimestampGMT": 1718623230000, + "sleepStartTimestampLocal": 1718579010000, + "sleepEndTimestampLocal": 1718608830000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 4200, + "lightSleepSeconds": 20400, + "remSleepSeconds": 5100, + "awakeSleepSeconds": 120, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 93.0, + "lowestSpO2Value": 82, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 44.0, + "averageRespirationValue": 15.0, + "lowestRespirationValue": 8.0, + "highestRespirationValue": 24.0, + "awakeCount": 0, + "avgSleepStress": 9.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_HIGHLY_RECOVERING", + "sleepScoreInsight": "NONE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "EXCELLENT", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": { + "value": 91, + "qualifierKey": "EXCELLENT", + }, + "remPercentage": { + "value": 17, + "qualifierKey": "FAIR", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 6237.0, + "idealEndInSeconds": 9207.0, + }, + "restlessness": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 69, + "qualifierKey": "FAIR", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 8910.0, + "idealEndInSeconds": 19008.0, + }, + "deepPercentage": { + "value": 14, + "qualifierKey": "FAIR", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4752.0, + "idealEndInSeconds": 9801.0, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-17", + "deviceId": 3472661486, + "timestampGmt": "2024-06-16T23:55:04", + "baseline": 480, + "actual": 430, + "feedback": "DECREASED", + "trainingFeedback": "DAILY_ACTIVITY_AND_CHRONIC", + "sleepHistoryAdjustment": "DECREASING", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "DECREASING", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-18", + "deviceId": 3472661486, + "timestampGmt": "2024-06-17T11:20:35", + "baseline": 480, + "actual": 480, + "feedback": "NO_CHANGE_BALANCED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "DECREASING", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": false, + "preferredActivityTracker": true, + }, + }, + { + "id": 1718680773000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-18", + "sleepTimeSeconds": 26760, + "napTimeSeconds": 0, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1718680773000, + "sleepEndTimestampGMT": 1718708853000, + "sleepStartTimestampLocal": 1718666373000, + "sleepEndTimestampLocal": 1718694453000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 2640, + "lightSleepSeconds": 19860, + "remSleepSeconds": 4260, + "awakeSleepSeconds": 1320, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 93.0, + "lowestSpO2Value": 85, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 47.0, + "averageRespirationValue": 15.0, + "lowestRespirationValue": 9.0, + "highestRespirationValue": 24.0, + "awakeCount": 2, + "avgSleepStress": 15.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_LONG_AND_CALM", + "sleepScoreInsight": "NONE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "EXCELLENT", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "GOOD", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "FAIR", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": {"value": 82, "qualifierKey": "GOOD"}, + "remPercentage": { + "value": 16, + "qualifierKey": "FAIR", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 5619.6, + "idealEndInSeconds": 8295.6, + }, + "restlessness": { + "qualifierKey": "FAIR", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 74, + "qualifierKey": "FAIR", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 8028.0, + "idealEndInSeconds": 17126.4, + }, + "deepPercentage": { + "value": 10, + "qualifierKey": "FAIR", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4281.6, + "idealEndInSeconds": 8830.8, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-18", + "deviceId": 3472661486, + "timestampGmt": "2024-06-17T11:20:35", + "baseline": 480, + "actual": 480, + "feedback": "NO_CHANGE_BALANCED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "DECREASING", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": false, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-19", + "deviceId": 3472661486, + "timestampGmt": "2024-06-18T12:47:48", + "baseline": 480, + "actual": 480, + "feedback": "NO_CHANGE_NO_ADJUSTMENTS", + "trainingFeedback": "NO_CHANGE", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": false, + "preferredActivityTracker": true, + }, + }, + { + "id": 1718764726000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-19", + "sleepTimeSeconds": 28740, + "napTimeSeconds": 0, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1718764726000, + "sleepEndTimestampGMT": 1718793946000, + "sleepStartTimestampLocal": 1718750326000, + "sleepEndTimestampLocal": 1718779546000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 780, + "lightSleepSeconds": 23760, + "remSleepSeconds": 4200, + "awakeSleepSeconds": 480, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 93.0, + "lowestSpO2Value": 87, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 44.0, + "averageRespirationValue": 15.0, + "lowestRespirationValue": 8.0, + "highestRespirationValue": 23.0, + "awakeCount": 0, + "avgSleepStress": 13.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "NEGATIVE_LONG_BUT_LIGHT", + "sleepScoreInsight": "NONE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "EXCELLENT", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": {"value": 70, "qualifierKey": "FAIR"}, + "remPercentage": { + "value": 15, + "qualifierKey": "FAIR", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 6035.4, + "idealEndInSeconds": 8909.4, + }, + "restlessness": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 83, + "qualifierKey": "POOR", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 8622.0, + "idealEndInSeconds": 18393.6, + }, + "deepPercentage": { + "value": 3, + "qualifierKey": "POOR", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4598.4, + "idealEndInSeconds": 9484.2, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-19", + "deviceId": 3472661486, + "timestampGmt": "2024-06-18T12:47:48", + "baseline": 480, + "actual": 480, + "feedback": "NO_CHANGE_NO_ADJUSTMENTS", + "trainingFeedback": "NO_CHANGE", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": false, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-20", + "deviceId": 3472661486, + "timestampGmt": "2024-06-19T12:01:35", + "baseline": 480, + "actual": 480, + "feedback": "NO_CHANGE_NO_ADJUSTMENTS", + "trainingFeedback": "NO_CHANGE", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": false, + "preferredActivityTracker": true, + }, + }, + { + "id": 1718849432000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-20", + "sleepTimeSeconds": 28740, + "napTimeSeconds": 0, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1718849432000, + "sleepEndTimestampGMT": 1718878292000, + "sleepStartTimestampLocal": 1718835032000, + "sleepEndTimestampLocal": 1718863892000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 6240, + "lightSleepSeconds": 18960, + "remSleepSeconds": 3540, + "awakeSleepSeconds": 120, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 94.0, + "lowestSpO2Value": 86, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 46.0, + "averageRespirationValue": 15.0, + "lowestRespirationValue": 8.0, + "highestRespirationValue": 23.0, + "awakeCount": 0, + "avgSleepStress": 23.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_LONG_AND_DEEP", + "sleepScoreInsight": "POSITIVE_EXERCISE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "EXCELLENT", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "FAIR", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": {"value": 81, "qualifierKey": "GOOD"}, + "remPercentage": { + "value": 12, + "qualifierKey": "FAIR", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 6035.4, + "idealEndInSeconds": 8909.4, + }, + "restlessness": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 66, + "qualifierKey": "FAIR", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 8622.0, + "idealEndInSeconds": 18393.6, + }, + "deepPercentage": { + "value": 22, + "qualifierKey": "EXCELLENT", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4598.4, + "idealEndInSeconds": 9484.2, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-20", + "deviceId": 3472661486, + "timestampGmt": "2024-06-19T12:01:35", + "baseline": 480, + "actual": 480, + "feedback": "NO_CHANGE_NO_ADJUSTMENTS", + "trainingFeedback": "NO_CHANGE", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": false, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-21", + "deviceId": 3472661486, + "timestampGmt": "2024-06-20T22:19:56", + "baseline": 480, + "actual": 500, + "feedback": "INCREASED", + "trainingFeedback": "TODAYS_LOAD_AND_CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + }, + { + "id": 1718936034000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-21", + "sleepTimeSeconds": 27352, + "napTimeSeconds": 0, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1718936034000, + "sleepEndTimestampGMT": 1718964346000, + "sleepStartTimestampLocal": 1718921634000, + "sleepEndTimestampLocal": 1718949946000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 3240, + "lightSleepSeconds": 20580, + "remSleepSeconds": 3540, + "awakeSleepSeconds": 960, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 94.0, + "lowestSpO2Value": 85, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 45.0, + "averageRespirationValue": 17.0, + "lowestRespirationValue": 10.0, + "highestRespirationValue": 24.0, + "awakeCount": 1, + "avgSleepStress": 14.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_LONG_AND_RECOVERING", + "sleepScoreInsight": "POSITIVE_RESTFUL_EVENING", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "EXCELLENT", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "GOOD", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "GOOD", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": {"value": 82, "qualifierKey": "GOOD"}, + "remPercentage": { + "value": 13, + "qualifierKey": "FAIR", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 5743.92, + "idealEndInSeconds": 8479.12, + }, + "restlessness": { + "qualifierKey": "GOOD", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 75, + "qualifierKey": "FAIR", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 8205.6, + "idealEndInSeconds": 17505.28, + }, + "deepPercentage": { + "value": 12, + "qualifierKey": "FAIR", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4376.32, + "idealEndInSeconds": 9026.16, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-21", + "deviceId": 3472661486, + "timestampGmt": "2024-06-20T22:19:56", + "baseline": 480, + "actual": 500, + "feedback": "INCREASED", + "trainingFeedback": "TODAYS_LOAD_AND_CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-22", + "deviceId": 3472661486, + "timestampGmt": "2024-06-21T11:50:20", + "baseline": 480, + "actual": 480, + "feedback": "NO_CHANGE_NO_ADJUSTMENTS", + "trainingFeedback": "NO_CHANGE", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": false, + "preferredActivityTracker": true, + }, + }, + { + "id": 1719023238000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-22", + "sleepTimeSeconds": 29520, + "napTimeSeconds": 0, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1719023238000, + "sleepEndTimestampGMT": 1719054198000, + "sleepStartTimestampLocal": 1719008838000, + "sleepEndTimestampLocal": 1719039798000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 7260, + "lightSleepSeconds": 16620, + "remSleepSeconds": 5640, + "awakeSleepSeconds": 1440, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 96.0, + "lowestSpO2Value": 88, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 44.0, + "averageRespirationValue": 16.0, + "lowestRespirationValue": 8.0, + "highestRespirationValue": 23.0, + "awakeCount": 1, + "avgSleepStress": 16.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_LONG_AND_DEEP", + "sleepScoreInsight": "POSITIVE_EXERCISE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "EXCELLENT", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "FAIR", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "GOOD", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": {"value": 88, "qualifierKey": "GOOD"}, + "remPercentage": { + "value": 19, + "qualifierKey": "FAIR", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 6199.2, + "idealEndInSeconds": 9151.2, + }, + "restlessness": { + "qualifierKey": "GOOD", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 56, + "qualifierKey": "EXCELLENT", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 8856.0, + "idealEndInSeconds": 18892.8, + }, + "deepPercentage": { + "value": 25, + "qualifierKey": "EXCELLENT", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4723.2, + "idealEndInSeconds": 9741.6, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-22", + "deviceId": 3472661486, + "timestampGmt": "2024-06-21T11:50:20", + "baseline": 480, + "actual": 480, + "feedback": "NO_CHANGE_NO_ADJUSTMENTS", + "trainingFeedback": "NO_CHANGE", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": false, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-23", + "deviceId": 3472661486, + "timestampGmt": "2024-06-23T02:32:45", + "baseline": 480, + "actual": 520, + "feedback": "INCREASED", + "trainingFeedback": "DAILY_ACTIVITY_AND_CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + }, + { + "id": 1719116021000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-23", + "sleepTimeSeconds": 27600, + "napTimeSeconds": 0, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1719116021000, + "sleepEndTimestampGMT": 1719143801000, + "sleepStartTimestampLocal": 1719101621000, + "sleepEndTimestampLocal": 1719129401000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 5400, + "lightSleepSeconds": 20220, + "remSleepSeconds": 1980, + "awakeSleepSeconds": 180, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 93.0, + "lowestSpO2Value": 81, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 49.0, + "averageRespirationValue": 13.0, + "lowestRespirationValue": 8.0, + "highestRespirationValue": 23.0, + "awakeCount": 0, + "avgSleepStress": 14.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "NEGATIVE_LONG_BUT_NOT_ENOUGH_REM", + "sleepScoreInsight": "NEGATIVE_STRENUOUS_EXERCISE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "EXCELLENT", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "GOOD", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": {"value": 76, "qualifierKey": "FAIR"}, + "remPercentage": { + "value": 7, + "qualifierKey": "POOR", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 5796.0, + "idealEndInSeconds": 8556.0, + }, + "restlessness": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 73, + "qualifierKey": "FAIR", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 8280.0, + "idealEndInSeconds": 17664.0, + }, + "deepPercentage": { + "value": 20, + "qualifierKey": "EXCELLENT", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4416.0, + "idealEndInSeconds": 9108.0, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-23", + "deviceId": 3472661486, + "timestampGmt": "2024-06-23T02:32:45", + "baseline": 480, + "actual": 520, + "feedback": "INCREASED", + "trainingFeedback": "DAILY_ACTIVITY_AND_CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-24", + "deviceId": 3472661486, + "timestampGmt": "2024-06-24T01:27:51", + "baseline": 480, + "actual": 500, + "feedback": "INCREASED", + "trainingFeedback": "DAILY_ACTIVITY_AND_CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + }, + { + "id": 1719197080000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-24", + "sleepTimeSeconds": 30120, + "napTimeSeconds": 0, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1719197080000, + "sleepEndTimestampGMT": 1719227680000, + "sleepStartTimestampLocal": 1719182680000, + "sleepEndTimestampLocal": 1719213280000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 7680, + "lightSleepSeconds": 15900, + "remSleepSeconds": 6540, + "awakeSleepSeconds": 480, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 93.0, + "lowestSpO2Value": 81, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 42.0, + "averageRespirationValue": 15.0, + "lowestRespirationValue": 9.0, + "highestRespirationValue": 21.0, + "awakeCount": 0, + "avgSleepStress": 12.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_OPTIMAL_STRUCTURE", + "sleepScoreInsight": "POSITIVE_EXERCISE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "EXCELLENT", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": { + "value": 96, + "qualifierKey": "EXCELLENT", + }, + "remPercentage": { + "value": 22, + "qualifierKey": "GOOD", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 6325.2, + "idealEndInSeconds": 9337.2, + }, + "restlessness": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 53, + "qualifierKey": "EXCELLENT", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 9036.0, + "idealEndInSeconds": 19276.8, + }, + "deepPercentage": { + "value": 25, + "qualifierKey": "EXCELLENT", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4819.2, + "idealEndInSeconds": 9939.6, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-24", + "deviceId": 3472661486, + "timestampGmt": "2024-06-24T01:27:51", + "baseline": 480, + "actual": 500, + "feedback": "INCREASED", + "trainingFeedback": "DAILY_ACTIVITY_AND_CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-25", + "deviceId": 3472661486, + "timestampGmt": "2024-06-24T11:25:44", + "baseline": 480, + "actual": 480, + "feedback": "NO_CHANGE_BALANCED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "DECREASING", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": false, + "preferredActivityTracker": true, + }, + }, + { + "id": 1719287383000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-25", + "sleepTimeSeconds": 24660, + "napTimeSeconds": 0, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1719287383000, + "sleepEndTimestampGMT": 1719313063000, + "sleepStartTimestampLocal": 1719272983000, + "sleepEndTimestampLocal": 1719298663000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 5760, + "lightSleepSeconds": 13620, + "remSleepSeconds": 5280, + "awakeSleepSeconds": 1020, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 93.0, + "lowestSpO2Value": 85, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 43.0, + "averageRespirationValue": 12.0, + "lowestRespirationValue": 8.0, + "highestRespirationValue": 21.0, + "awakeCount": 2, + "avgSleepStress": 13.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_DEEP", + "sleepScoreInsight": "NONE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "FAIR", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "FAIR", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": {"value": 81, "qualifierKey": "GOOD"}, + "remPercentage": { + "value": 21, + "qualifierKey": "GOOD", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 5178.6, + "idealEndInSeconds": 7644.6, + }, + "restlessness": { + "qualifierKey": "FAIR", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 55, + "qualifierKey": "EXCELLENT", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 7398.0, + "idealEndInSeconds": 15782.4, + }, + "deepPercentage": { + "value": 23, + "qualifierKey": "EXCELLENT", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 3945.6, + "idealEndInSeconds": 8137.8, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-25", + "deviceId": 3472661486, + "timestampGmt": "2024-06-24T11:25:44", + "baseline": 480, + "actual": 480, + "feedback": "NO_CHANGE_BALANCED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "DECREASING", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": false, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-26", + "deviceId": 3472661486, + "timestampGmt": "2024-06-25T23:16:07", + "baseline": 480, + "actual": 500, + "feedback": "INCREASED", + "trainingFeedback": "TODAYS_LOAD_AND_CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + }, + { + "id": 1719367204000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-26", + "sleepTimeSeconds": 30044, + "napTimeSeconds": 0, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1719367204000, + "sleepEndTimestampGMT": 1719397548000, + "sleepStartTimestampLocal": 1719352804000, + "sleepEndTimestampLocal": 1719383148000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 4680, + "lightSleepSeconds": 21900, + "remSleepSeconds": 3480, + "awakeSleepSeconds": 300, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 94.0, + "lowestSpO2Value": 81, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 43.0, + "averageRespirationValue": 15.0, + "lowestRespirationValue": 8.0, + "highestRespirationValue": 24.0, + "awakeCount": 0, + "avgSleepStress": 10.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_LONG_AND_RECOVERING", + "sleepScoreInsight": "NONE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "EXCELLENT", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": {"value": 88, "qualifierKey": "GOOD"}, + "remPercentage": { + "value": 12, + "qualifierKey": "FAIR", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 6309.24, + "idealEndInSeconds": 9313.64, + }, + "restlessness": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 73, + "qualifierKey": "FAIR", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 9013.2, + "idealEndInSeconds": 19228.16, + }, + "deepPercentage": { + "value": 16, + "qualifierKey": "FAIR", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4807.04, + "idealEndInSeconds": 9914.52, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-26", + "deviceId": 3472661486, + "timestampGmt": "2024-06-25T23:16:07", + "baseline": 480, + "actual": 500, + "feedback": "INCREASED", + "trainingFeedback": "TODAYS_LOAD_AND_CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-27", + "deviceId": 3472661486, + "timestampGmt": "2024-06-26T16:04:42", + "baseline": 480, + "actual": 480, + "feedback": "NO_CHANGE_BALANCED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "DECREASING_HIGH_QUALITY", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": false, + "preferredActivityTracker": true, + }, + }, + { + "id": 1719455799000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-27", + "sleepTimeSeconds": 29520, + "napTimeSeconds": 0, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1719455799000, + "sleepEndTimestampGMT": 1719485739000, + "sleepStartTimestampLocal": 1719441399000, + "sleepEndTimestampLocal": 1719471339000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 6540, + "lightSleepSeconds": 17820, + "remSleepSeconds": 5160, + "awakeSleepSeconds": 420, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 93.0, + "lowestSpO2Value": 82, + "highestSpO2Value": 99, + "averageSpO2HRSleep": 44.0, + "averageRespirationValue": 15.0, + "lowestRespirationValue": 8.0, + "highestRespirationValue": 24.0, + "awakeCount": 0, + "avgSleepStress": 17.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_LONG_AND_DEEP", + "sleepScoreInsight": "POSITIVE_RESTFUL_DAY", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "EXCELLENT", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "FAIR", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": {"value": 89, "qualifierKey": "GOOD"}, + "remPercentage": { + "value": 17, + "qualifierKey": "FAIR", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 6199.2, + "idealEndInSeconds": 9151.2, + }, + "restlessness": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 60, + "qualifierKey": "GOOD", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 8856.0, + "idealEndInSeconds": 18892.8, + }, + "deepPercentage": { + "value": 22, + "qualifierKey": "EXCELLENT", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4723.2, + "idealEndInSeconds": 9741.6, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-27", + "deviceId": 3472661486, + "timestampGmt": "2024-06-26T16:04:42", + "baseline": 480, + "actual": 480, + "feedback": "NO_CHANGE_BALANCED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "DECREASING_HIGH_QUALITY", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": false, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-28", + "deviceId": 3472661486, + "timestampGmt": "2024-06-27T19:47:12", + "baseline": 480, + "actual": 480, + "feedback": "NO_CHANGE_BALANCED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "DECREASING_HIGH_QUALITY", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": false, + "preferredActivityTracker": true, + }, + }, + { + "id": 1719541869000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-28", + "sleepTimeSeconds": 26700, + "napTimeSeconds": 0, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1719541869000, + "sleepEndTimestampGMT": 1719569769000, + "sleepStartTimestampLocal": 1719527469000, + "sleepEndTimestampLocal": 1719555369000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 5700, + "lightSleepSeconds": 15720, + "remSleepSeconds": 5280, + "awakeSleepSeconds": 1200, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 94.0, + "lowestSpO2Value": 87, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 43.0, + "averageRespirationValue": 15.0, + "lowestRespirationValue": 8.0, + "highestRespirationValue": 20.0, + "awakeCount": 1, + "avgSleepStress": 12.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_LONG_AND_DEEP", + "sleepScoreInsight": "POSITIVE_EXERCISE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "GOOD", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "GOOD", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": {"value": 87, "qualifierKey": "GOOD"}, + "remPercentage": { + "value": 20, + "qualifierKey": "FAIR", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 5607.0, + "idealEndInSeconds": 8277.0, + }, + "restlessness": { + "qualifierKey": "GOOD", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 59, + "qualifierKey": "GOOD", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 8010.0, + "idealEndInSeconds": 17088.0, + }, + "deepPercentage": { + "value": 21, + "qualifierKey": "EXCELLENT", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4272.0, + "idealEndInSeconds": 8811.0, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-28", + "deviceId": 3472661486, + "timestampGmt": "2024-06-27T19:47:12", + "baseline": 480, + "actual": 480, + "feedback": "NO_CHANGE_BALANCED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "DECREASING_HIGH_QUALITY", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": false, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-29", + "deviceId": 3472661486, + "timestampGmt": "2024-06-28T17:34:41", + "baseline": 480, + "actual": 500, + "feedback": "INCREASED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + }, + { + "id": 1719629318000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-29", + "sleepTimeSeconds": 27213, + "napTimeSeconds": 3600, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1719629318000, + "sleepEndTimestampGMT": 1719656591000, + "sleepStartTimestampLocal": 1719614918000, + "sleepEndTimestampLocal": 1719642191000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 4560, + "lightSleepSeconds": 14700, + "remSleepSeconds": 7980, + "awakeSleepSeconds": 60, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 93.0, + "lowestSpO2Value": 84, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 42.0, + "averageRespirationValue": 13.0, + "lowestRespirationValue": 8.0, + "highestRespirationValue": 20.0, + "awakeCount": 0, + "avgSleepStress": 9.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_HIGHLY_RECOVERING", + "sleepScoreInsight": "NONE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "GOOD", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": { + "value": 92, + "qualifierKey": "EXCELLENT", + }, + "remPercentage": { + "value": 29, + "qualifierKey": "EXCELLENT", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 5714.73, + "idealEndInSeconds": 8436.03, + }, + "restlessness": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 54, + "qualifierKey": "EXCELLENT", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 8163.9, + "idealEndInSeconds": 17416.32, + }, + "deepPercentage": { + "value": 17, + "qualifierKey": "GOOD", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4354.08, + "idealEndInSeconds": 8980.29, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-29", + "deviceId": 3472661486, + "timestampGmt": "2024-06-28T17:34:41", + "baseline": 480, + "actual": 500, + "feedback": "INCREASED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-30", + "deviceId": 3472661486, + "timestampGmt": "2024-06-30T02:02:28", + "baseline": 480, + "actual": 440, + "feedback": "DECREASED", + "trainingFeedback": "TODAYS_LOAD_AND_CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "DECREASING", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "dailyNapDTOS": [ + { + "userProfilePK": "user_id: int", + "deviceId": 3472661486, + "calendarDate": "2024-06-29", + "napTimeSec": 3600, + "napStartTimestampGMT": "2024-06-29T18:53:28", + "napEndTimestampGMT": "2024-06-29T19:53:28", + "napFeedback": "LATE_TIMING_LONG_DURATION_LOW_NEED", + "napSource": 1, + "napStartTimeOffset": -240, + "napEndTimeOffset": -240, + } + ], + }, + { + "id": 1719714951000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-30", + "sleepTimeSeconds": 27180, + "napTimeSeconds": 3417, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1719714951000, + "sleepEndTimestampGMT": 1719743511000, + "sleepStartTimestampLocal": 1719700551000, + "sleepEndTimestampLocal": 1719729111000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 5640, + "lightSleepSeconds": 18900, + "remSleepSeconds": 2640, + "awakeSleepSeconds": 1380, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 92.0, + "lowestSpO2Value": 82, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 45.0, + "averageRespirationValue": 13.0, + "lowestRespirationValue": 8.0, + "highestRespirationValue": 23.0, + "awakeCount": 1, + "avgSleepStress": 16.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "NEGATIVE_LONG_BUT_NOT_ENOUGH_REM", + "sleepScoreInsight": "NONE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "GOOD", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "FAIR", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "GOOD", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": {"value": 79, "qualifierKey": "FAIR"}, + "remPercentage": { + "value": 10, + "qualifierKey": "POOR", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 5707.8, + "idealEndInSeconds": 8425.8, + }, + "restlessness": { + "qualifierKey": "GOOD", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 70, + "qualifierKey": "FAIR", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 8154.0, + "idealEndInSeconds": 17395.2, + }, + "deepPercentage": { + "value": 21, + "qualifierKey": "EXCELLENT", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4348.8, + "idealEndInSeconds": 8969.4, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-30", + "deviceId": 3472661486, + "timestampGmt": "2024-06-30T02:02:28", + "baseline": 480, + "actual": 440, + "feedback": "DECREASED", + "trainingFeedback": "TODAYS_LOAD_AND_CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "DECREASING", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-01", + "deviceId": 3472661486, + "timestampGmt": "2024-06-30T18:38:49", + "baseline": 480, + "actual": 450, + "feedback": "DECREASED", + "trainingFeedback": "TODAYS_LOAD_AND_CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "DECREASING", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "dailyNapDTOS": [ + { + "userProfilePK": "user_id: int", + "deviceId": 3472661486, + "calendarDate": "2024-06-30", + "napTimeSec": 3417, + "napStartTimestampGMT": "2024-06-30T17:41:52", + "napEndTimestampGMT": "2024-06-30T18:38:49", + "napFeedback": "IDEAL_TIMING_LONG_DURATION_LOW_NEED", + "napSource": 1, + "napStartTimeOffset": -240, + "napEndTimeOffset": -240, + } + ], + }, + { + "id": 1719800738000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-07-01", + "sleepTimeSeconds": 26280, + "napTimeSeconds": 3300, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1719800738000, + "sleepEndTimestampGMT": 1719827798000, + "sleepStartTimestampLocal": 1719786338000, + "sleepEndTimestampLocal": 1719813398000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 6360, + "lightSleepSeconds": 16320, + "remSleepSeconds": 3600, + "awakeSleepSeconds": 780, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 96.0, + "lowestSpO2Value": 86, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 41.0, + "averageRespirationValue": 14.0, + "lowestRespirationValue": 8.0, + "highestRespirationValue": 22.0, + "awakeCount": 1, + "avgSleepStress": 12.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_LONG_AND_DEEP", + "sleepScoreInsight": "NONE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "EXCELLENT", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "GOOD", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": {"value": 89, "qualifierKey": "GOOD"}, + "remPercentage": { + "value": 14, + "qualifierKey": "FAIR", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 5518.8, + "idealEndInSeconds": 8146.8, + }, + "restlessness": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 62, + "qualifierKey": "GOOD", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 7884.0, + "idealEndInSeconds": 16819.2, + }, + "deepPercentage": { + "value": 24, + "qualifierKey": "EXCELLENT", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4204.8, + "idealEndInSeconds": 8672.4, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-01", + "deviceId": 3472661486, + "timestampGmt": "2024-06-30T18:38:49", + "baseline": 480, + "actual": 450, + "feedback": "DECREASED", + "trainingFeedback": "TODAYS_LOAD_AND_CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "DECREASING", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-02", + "deviceId": 3472661486, + "timestampGmt": "2024-07-01T18:54:21", + "baseline": 480, + "actual": 450, + "feedback": "DECREASED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "DECREASING", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "dailyNapDTOS": [ + { + "userProfilePK": "user_id: int", + "deviceId": 3472661486, + "calendarDate": "2024-07-01", + "napTimeSec": 3300, + "napStartTimestampGMT": "2024-07-01T17:59:21", + "napEndTimestampGMT": "2024-07-01T18:54:21", + "napFeedback": "IDEAL_TIMING_LONG_DURATION_LOW_NEED", + "napSource": 1, + "napStartTimeOffset": -240, + "napEndTimeOffset": -240, + } + ], + }, + { + "id": 1719885617000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-07-02", + "sleepTimeSeconds": 28440, + "napTimeSeconds": 3600, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1719885617000, + "sleepEndTimestampGMT": 1719914117000, + "sleepStartTimestampLocal": 1719871217000, + "sleepEndTimestampLocal": 1719899717000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 6300, + "lightSleepSeconds": 15960, + "remSleepSeconds": 6180, + "awakeSleepSeconds": 60, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 96.0, + "lowestSpO2Value": 86, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 41.0, + "averageRespirationValue": 13.0, + "lowestRespirationValue": 8.0, + "highestRespirationValue": 23.0, + "awakeCount": 0, + "avgSleepStress": 11.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_OPTIMAL_STRUCTURE", + "sleepScoreInsight": "POSITIVE_EXERCISE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "EXCELLENT", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": { + "value": 97, + "qualifierKey": "EXCELLENT", + }, + "remPercentage": { + "value": 22, + "qualifierKey": "GOOD", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 5972.4, + "idealEndInSeconds": 8816.4, + }, + "restlessness": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 56, + "qualifierKey": "EXCELLENT", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 8532.0, + "idealEndInSeconds": 18201.6, + }, + "deepPercentage": { + "value": 22, + "qualifierKey": "EXCELLENT", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4550.4, + "idealEndInSeconds": 9385.2, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-02", + "deviceId": 3472661486, + "timestampGmt": "2024-07-01T18:54:21", + "baseline": 480, + "actual": 450, + "feedback": "DECREASED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "DECREASING", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-03", + "deviceId": 3472661486, + "timestampGmt": "2024-07-02T17:17:49", + "baseline": 480, + "actual": 420, + "feedback": "DECREASED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "DECREASING_HIGH_QUALITY", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "DECREASING", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "dailyNapDTOS": [ + { + "userProfilePK": "user_id: int", + "deviceId": 3472661486, + "calendarDate": "2024-07-02", + "napTimeSec": 3600, + "napStartTimestampGMT": "2024-07-02T16:17:48", + "napEndTimestampGMT": "2024-07-02T17:17:48", + "napFeedback": "IDEAL_TIMING_LONG_DURATION_LOW_NEED", + "napSource": 1, + "napStartTimeOffset": -240, + "napEndTimeOffset": -240, + } + ], + }, + { + "id": 1719980934000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-07-03", + "sleepTimeSeconds": 23940, + "napTimeSeconds": 2700, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1719980934000, + "sleepEndTimestampGMT": 1720005294000, + "sleepStartTimestampLocal": 1719966534000, + "sleepEndTimestampLocal": 1719990894000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 4260, + "lightSleepSeconds": 16140, + "remSleepSeconds": 3540, + "awakeSleepSeconds": 420, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 94.0, + "lowestSpO2Value": 84, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 42.0, + "averageRespirationValue": 14.0, + "lowestRespirationValue": 9.0, + "highestRespirationValue": 23.0, + "awakeCount": 0, + "avgSleepStress": 12.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_CONTINUOUS", + "sleepScoreInsight": "POSITIVE_EXERCISE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "FAIR", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": {"value": 83, "qualifierKey": "GOOD"}, + "remPercentage": { + "value": 15, + "qualifierKey": "FAIR", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 5027.4, + "idealEndInSeconds": 7421.4, + }, + "restlessness": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 67, + "qualifierKey": "FAIR", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 7182.0, + "idealEndInSeconds": 15321.6, + }, + "deepPercentage": { + "value": 18, + "qualifierKey": "GOOD", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 3830.4, + "idealEndInSeconds": 7900.2, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-03", + "deviceId": 3472661486, + "timestampGmt": "2024-07-02T17:17:49", + "baseline": 480, + "actual": 420, + "feedback": "DECREASED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "DECREASING_HIGH_QUALITY", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "DECREASING", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-04", + "deviceId": 3472661486, + "timestampGmt": "2024-07-03T20:30:09", + "baseline": 480, + "actual": 460, + "feedback": "DECREASED", + "trainingFeedback": "TODAYS_LOAD_AND_CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "DECREASING", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "dailyNapDTOS": [ + { + "userProfilePK": "user_id: int", + "deviceId": 3472661486, + "calendarDate": "2024-07-03", + "napTimeSec": 2700, + "napStartTimestampGMT": "2024-07-03T19:45:08", + "napEndTimestampGMT": "2024-07-03T20:30:08", + "napFeedback": "LATE_TIMING_LONG_DURATION_LOW_NEED", + "napSource": 1, + "napStartTimeOffset": -240, + "napEndTimeOffset": -240, + } + ], + }, + { + "id": 1720066612000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-07-04", + "sleepTimeSeconds": 25860, + "napTimeSeconds": 1199, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1720066612000, + "sleepEndTimestampGMT": 1720092712000, + "sleepStartTimestampLocal": 1720052212000, + "sleepEndTimestampLocal": 1720078312000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 4860, + "lightSleepSeconds": 16440, + "remSleepSeconds": 4560, + "awakeSleepSeconds": 240, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 95.0, + "lowestSpO2Value": 88, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 45.0, + "averageRespirationValue": 16.0, + "lowestRespirationValue": 8.0, + "highestRespirationValue": 25.0, + "awakeCount": 0, + "avgSleepStress": 16.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_LONG_AND_CONTINUOUS", + "sleepScoreInsight": "NONE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "EXCELLENT", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "FAIR", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": {"value": 89, "qualifierKey": "GOOD"}, + "remPercentage": { + "value": 18, + "qualifierKey": "FAIR", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 5430.6, + "idealEndInSeconds": 8016.6, + }, + "restlessness": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 64, + "qualifierKey": "GOOD", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 7758.0, + "idealEndInSeconds": 16550.4, + }, + "deepPercentage": { + "value": 19, + "qualifierKey": "EXCELLENT", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4137.6, + "idealEndInSeconds": 8533.8, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-04", + "deviceId": 3472661486, + "timestampGmt": "2024-07-03T20:30:09", + "baseline": 480, + "actual": 460, + "feedback": "DECREASED", + "trainingFeedback": "TODAYS_LOAD_AND_CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "DECREASING", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-05", + "deviceId": 3472661486, + "timestampGmt": "2024-07-04T18:52:50", + "baseline": 480, + "actual": 480, + "feedback": "NO_CHANGE_BALANCED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "DECREASING", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "dailyNapDTOS": [ + { + "userProfilePK": "user_id: int", + "deviceId": 3472661486, + "calendarDate": "2024-07-04", + "napTimeSec": 1199, + "napStartTimestampGMT": "2024-07-04T18:32:50", + "napEndTimestampGMT": "2024-07-04T18:52:49", + "napFeedback": "IDEAL_TIMING_IDEAL_DURATION_LOW_NEED", + "napSource": 1, + "napStartTimeOffset": -240, + "napEndTimeOffset": -240, + } + ], + }, + { + "id": 1720146625000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-07-05", + "sleepTimeSeconds": 32981, + "napTimeSeconds": 0, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1720146625000, + "sleepEndTimestampGMT": 1720180146000, + "sleepStartTimestampLocal": 1720132225000, + "sleepEndTimestampLocal": 1720165746000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 5880, + "lightSleepSeconds": 22740, + "remSleepSeconds": 4380, + "awakeSleepSeconds": 540, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 95.0, + "lowestSpO2Value": 84, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 45.0, + "averageRespirationValue": 14.0, + "lowestRespirationValue": 9.0, + "highestRespirationValue": 23.0, + "awakeCount": 0, + "avgSleepStress": 13.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_LONG_AND_CONTINUOUS", + "sleepScoreInsight": "POSITIVE_EXERCISE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "EXCELLENT", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": {"value": 89, "qualifierKey": "GOOD"}, + "remPercentage": { + "value": 13, + "qualifierKey": "FAIR", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 6926.01, + "idealEndInSeconds": 10224.11, + }, + "restlessness": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 69, + "qualifierKey": "FAIR", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 9894.3, + "idealEndInSeconds": 21107.84, + }, + "deepPercentage": { + "value": 18, + "qualifierKey": "GOOD", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 5276.96, + "idealEndInSeconds": 10883.73, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-05", + "deviceId": 3472661486, + "timestampGmt": "2024-07-04T18:52:50", + "baseline": 480, + "actual": 480, + "feedback": "NO_CHANGE_BALANCED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "DECREASING", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-06", + "deviceId": 3472661486, + "timestampGmt": "2024-07-05T15:45:39", + "baseline": 480, + "actual": 480, + "feedback": "NO_CHANGE_BALANCED", + "trainingFeedback": "TODAYS_LOAD_AND_CHRONIC", + "sleepHistoryAdjustment": "DECREASING", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": false, + "preferredActivityTracker": true, + }, + }, + { + "id": 1720235015000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-07-06", + "sleepTimeSeconds": 29760, + "napTimeSeconds": 0, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1720235015000, + "sleepEndTimestampGMT": 1720265435000, + "sleepStartTimestampLocal": 1720220615000, + "sleepEndTimestampLocal": 1720251035000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 4020, + "lightSleepSeconds": 22200, + "remSleepSeconds": 3540, + "awakeSleepSeconds": 660, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 94.0, + "lowestSpO2Value": 86, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 47.0, + "averageRespirationValue": 14.0, + "lowestRespirationValue": 8.0, + "highestRespirationValue": 23.0, + "awakeCount": 1, + "avgSleepStress": 16.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_LONG_AND_CONTINUOUS", + "sleepScoreInsight": "NONE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "EXCELLENT", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "FAIR", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "GOOD", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": {"value": 83, "qualifierKey": "GOOD"}, + "remPercentage": { + "value": 12, + "qualifierKey": "FAIR", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 6249.6, + "idealEndInSeconds": 9225.6, + }, + "restlessness": { + "qualifierKey": "GOOD", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 75, + "qualifierKey": "FAIR", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 8928.0, + "idealEndInSeconds": 19046.4, + }, + "deepPercentage": { + "value": 14, + "qualifierKey": "FAIR", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4761.6, + "idealEndInSeconds": 9820.8, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-06", + "deviceId": 3472661486, + "timestampGmt": "2024-07-05T15:45:39", + "baseline": 480, + "actual": 480, + "feedback": "NO_CHANGE_BALANCED", + "trainingFeedback": "TODAYS_LOAD_AND_CHRONIC", + "sleepHistoryAdjustment": "DECREASING", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": false, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-07", + "deviceId": 3472661486, + "timestampGmt": "2024-07-07T00:44:08", + "baseline": 480, + "actual": 480, + "feedback": "NO_CHANGE_BALANCED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "DECREASING", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": false, + "preferredActivityTracker": true, + }, + }, + { + "id": 1720323004000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-07-07", + "sleepTimeSeconds": 25114, + "napTimeSeconds": 0, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1720323004000, + "sleepEndTimestampGMT": 1720349138000, + "sleepStartTimestampLocal": 1720308604000, + "sleepEndTimestampLocal": 1720334738000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 4260, + "lightSleepSeconds": 15420, + "remSleepSeconds": 5460, + "awakeSleepSeconds": 1020, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 95.0, + "lowestSpO2Value": 87, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 44.0, + "averageRespirationValue": 13.0, + "lowestRespirationValue": 8.0, + "highestRespirationValue": 22.0, + "awakeCount": 1, + "avgSleepStress": 12.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_CALM", + "sleepScoreInsight": "NONE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "FAIR", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "GOOD", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": {"value": 83, "qualifierKey": "GOOD"}, + "remPercentage": { + "value": 22, + "qualifierKey": "GOOD", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 5273.94, + "idealEndInSeconds": 7785.34, + }, + "restlessness": { + "qualifierKey": "GOOD", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 61, + "qualifierKey": "GOOD", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 7534.2, + "idealEndInSeconds": 16072.96, + }, + "deepPercentage": { + "value": 17, + "qualifierKey": "GOOD", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4018.24, + "idealEndInSeconds": 8287.62, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-07", + "deviceId": 3472661486, + "timestampGmt": "2024-07-07T00:44:08", + "baseline": 480, + "actual": 480, + "feedback": "NO_CHANGE_BALANCED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "DECREASING", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": false, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-08", + "deviceId": 3472661486, + "timestampGmt": "2024-07-07T12:03:49", + "baseline": 480, + "actual": 500, + "feedback": "INCREASED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + }, + { + "id": 1720403925000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-07-08", + "sleepTimeSeconds": 29580, + "napTimeSeconds": 0, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1720403925000, + "sleepEndTimestampGMT": 1720434105000, + "sleepStartTimestampLocal": 1720389525000, + "sleepEndTimestampLocal": 1720419705000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 6360, + "lightSleepSeconds": 16260, + "remSleepSeconds": 6960, + "awakeSleepSeconds": 600, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 95.0, + "lowestSpO2Value": 89, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 42.0, + "averageRespirationValue": 14.0, + "lowestRespirationValue": 8.0, + "highestRespirationValue": 21.0, + "awakeCount": 1, + "avgSleepStress": 20.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_LONG_AND_DEEP", + "sleepScoreInsight": "NONE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "EXCELLENT", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "FAIR", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": {"value": 89, "qualifierKey": "GOOD"}, + "remPercentage": { + "value": 24, + "qualifierKey": "EXCELLENT", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 6211.8, + "idealEndInSeconds": 9169.8, + }, + "restlessness": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 55, + "qualifierKey": "EXCELLENT", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 8874.0, + "idealEndInSeconds": 18931.2, + }, + "deepPercentage": { + "value": 22, + "qualifierKey": "EXCELLENT", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4732.8, + "idealEndInSeconds": 9761.4, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-08", + "deviceId": 3472661486, + "timestampGmt": "2024-07-07T12:03:49", + "baseline": 480, + "actual": 500, + "feedback": "INCREASED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-09", + "deviceId": 3472661486, + "timestampGmt": "2024-07-08T13:33:50", + "baseline": 480, + "actual": 480, + "feedback": "NO_CHANGE_BALANCED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "DECREASING_HIGH_QUALITY", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": false, + "preferredActivityTracker": true, + }, + }, + ] + } + }, + }, + { + "query": { + "query": 'query{heartRateVariabilityScalar(startDate:"2024-06-11", endDate:"2024-07-08")}' + }, + "response": { + "data": { + "heartRateVariabilityScalar": { + "hrvSummaries": [ + { + "calendarDate": "2024-06-11", + "weeklyAvg": 58, + "lastNightAvg": 64, + "lastNight5MinHigh": 98, + "baseline": { + "lowUpper": 47, + "balancedLow": 51, + "balancedUpper": 72, + "markerValue": 0.4166565, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_6", + "createTimeStamp": "2024-06-11T10:33:35.355", + }, + { + "calendarDate": "2024-06-12", + "weeklyAvg": 57, + "lastNightAvg": 56, + "lastNight5MinHigh": 91, + "baseline": { + "lowUpper": 47, + "balancedLow": 51, + "balancedUpper": 72, + "markerValue": 0.39285278, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_7", + "createTimeStamp": "2024-06-12T10:43:40.422", + }, + { + "calendarDate": "2024-06-13", + "weeklyAvg": 59, + "lastNightAvg": 54, + "lastNight5MinHigh": 117, + "baseline": { + "lowUpper": 46, + "balancedLow": 51, + "balancedUpper": 72, + "markerValue": 0.44047546, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_8", + "createTimeStamp": "2024-06-13T10:24:54.374", + }, + { + "calendarDate": "2024-06-14", + "weeklyAvg": 59, + "lastNightAvg": 48, + "lastNight5MinHigh": 79, + "baseline": { + "lowUpper": 46, + "balancedLow": 50, + "balancedUpper": 72, + "markerValue": 0.45454407, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_3", + "createTimeStamp": "2024-06-14T10:35:53.767", + }, + { + "calendarDate": "2024-06-15", + "weeklyAvg": 57, + "lastNightAvg": 50, + "lastNight5MinHigh": 106, + "baseline": { + "lowUpper": 46, + "balancedLow": 51, + "balancedUpper": 72, + "markerValue": 0.39285278, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_3", + "createTimeStamp": "2024-06-15T10:41:34.861", + }, + { + "calendarDate": "2024-06-16", + "weeklyAvg": 58, + "lastNightAvg": 64, + "lastNight5MinHigh": 110, + "baseline": { + "lowUpper": 47, + "balancedLow": 51, + "balancedUpper": 72, + "markerValue": 0.4166565, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_7", + "createTimeStamp": "2024-06-16T10:31:30.613", + }, + { + "calendarDate": "2024-06-17", + "weeklyAvg": 59, + "lastNightAvg": 78, + "lastNight5MinHigh": 126, + "baseline": { + "lowUpper": 47, + "balancedLow": 51, + "balancedUpper": 73, + "markerValue": 0.43180847, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_8", + "createTimeStamp": "2024-06-17T11:34:58.64", + }, + { + "calendarDate": "2024-06-18", + "weeklyAvg": 59, + "lastNightAvg": 65, + "lastNight5MinHigh": 90, + "baseline": { + "lowUpper": 47, + "balancedLow": 51, + "balancedUpper": 73, + "markerValue": 0.43180847, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_5", + "createTimeStamp": "2024-06-18T11:12:34.991", + }, + { + "calendarDate": "2024-06-19", + "weeklyAvg": 60, + "lastNightAvg": 65, + "lastNight5MinHigh": 114, + "baseline": { + "lowUpper": 47, + "balancedLow": 51, + "balancedUpper": 73, + "markerValue": 0.45454407, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_6", + "createTimeStamp": "2024-06-19T10:48:54.401", + }, + { + "calendarDate": "2024-06-20", + "weeklyAvg": 58, + "lastNightAvg": 43, + "lastNight5MinHigh": 71, + "baseline": { + "lowUpper": 47, + "balancedLow": 51, + "balancedUpper": 73, + "markerValue": 0.40908813, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_3", + "createTimeStamp": "2024-06-20T10:17:59.241", + }, + { + "calendarDate": "2024-06-21", + "weeklyAvg": 60, + "lastNightAvg": 62, + "lastNight5MinHigh": 86, + "baseline": { + "lowUpper": 47, + "balancedLow": 51, + "balancedUpper": 72, + "markerValue": 0.46427917, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_8", + "createTimeStamp": "2024-06-21T10:06:40.223", + }, + { + "calendarDate": "2024-06-22", + "weeklyAvg": 62, + "lastNightAvg": 59, + "lastNight5MinHigh": 92, + "baseline": { + "lowUpper": 47, + "balancedLow": 51, + "balancedUpper": 72, + "markerValue": 0.51190186, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_5", + "createTimeStamp": "2024-06-22T11:08:16.381", + }, + { + "calendarDate": "2024-06-23", + "weeklyAvg": 62, + "lastNightAvg": 69, + "lastNight5MinHigh": 94, + "baseline": { + "lowUpper": 47, + "balancedLow": 51, + "balancedUpper": 72, + "markerValue": 0.51190186, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_6", + "createTimeStamp": "2024-06-23T11:57:54.770", + }, + { + "calendarDate": "2024-06-24", + "weeklyAvg": 61, + "lastNightAvg": 67, + "lastNight5MinHigh": 108, + "baseline": { + "lowUpper": 47, + "balancedLow": 52, + "balancedUpper": 73, + "markerValue": 0.46427917, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_2", + "createTimeStamp": "2024-06-24T11:53:55.689", + }, + { + "calendarDate": "2024-06-25", + "weeklyAvg": 60, + "lastNightAvg": 59, + "lastNight5MinHigh": 84, + "baseline": { + "lowUpper": 47, + "balancedLow": 52, + "balancedUpper": 74, + "markerValue": 0.43180847, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_8", + "createTimeStamp": "2024-06-25T11:23:04.158", + }, + { + "calendarDate": "2024-06-26", + "weeklyAvg": 61, + "lastNightAvg": 74, + "lastNight5MinHigh": 114, + "baseline": { + "lowUpper": 48, + "balancedLow": 52, + "balancedUpper": 74, + "markerValue": 0.45454407, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_5", + "createTimeStamp": "2024-06-26T10:25:59.977", + }, + { + "calendarDate": "2024-06-27", + "weeklyAvg": 64, + "lastNightAvg": 58, + "lastNight5MinHigh": 118, + "baseline": { + "lowUpper": 47, + "balancedLow": 52, + "balancedUpper": 74, + "markerValue": 0.52272034, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_6", + "createTimeStamp": "2024-06-27T11:00:34.905", + }, + { + "calendarDate": "2024-06-28", + "weeklyAvg": 65, + "lastNightAvg": 70, + "lastNight5MinHigh": 106, + "baseline": { + "lowUpper": 47, + "balancedLow": 52, + "balancedUpper": 74, + "markerValue": 0.5454407, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_7", + "createTimeStamp": "2024-06-28T10:21:44.856", + }, + { + "calendarDate": "2024-06-29", + "weeklyAvg": 67, + "lastNightAvg": 71, + "lastNight5MinHigh": 166, + "baseline": { + "lowUpper": 48, + "balancedLow": 52, + "balancedUpper": 73, + "markerValue": 0.60713196, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_8", + "createTimeStamp": "2024-06-29T10:24:15.636", + }, + { + "calendarDate": "2024-06-30", + "weeklyAvg": 65, + "lastNightAvg": 57, + "lastNight5MinHigh": 99, + "baseline": { + "lowUpper": 48, + "balancedLow": 52, + "balancedUpper": 74, + "markerValue": 0.5454407, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_2", + "createTimeStamp": "2024-06-30T11:08:14.932", + }, + { + "calendarDate": "2024-07-01", + "weeklyAvg": 65, + "lastNightAvg": 68, + "lastNight5MinHigh": 108, + "baseline": { + "lowUpper": 48, + "balancedLow": 52, + "balancedUpper": 74, + "markerValue": 0.5454407, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_2", + "createTimeStamp": "2024-07-01T09:58:02.551", + }, + { + "calendarDate": "2024-07-02", + "weeklyAvg": 66, + "lastNightAvg": 70, + "lastNight5MinHigh": 122, + "baseline": { + "lowUpper": 48, + "balancedLow": 52, + "balancedUpper": 74, + "markerValue": 0.56817627, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_2", + "createTimeStamp": "2024-07-02T09:58:09.417", + }, + { + "calendarDate": "2024-07-03", + "weeklyAvg": 65, + "lastNightAvg": 66, + "lastNight5MinHigh": 105, + "baseline": { + "lowUpper": 48, + "balancedLow": 53, + "balancedUpper": 75, + "markerValue": 0.52272034, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_2", + "createTimeStamp": "2024-07-03T11:17:55.863", + }, + { + "calendarDate": "2024-07-04", + "weeklyAvg": 66, + "lastNightAvg": 62, + "lastNight5MinHigh": 94, + "baseline": { + "lowUpper": 48, + "balancedLow": 53, + "balancedUpper": 74, + "markerValue": 0.5595093, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_2", + "createTimeStamp": "2024-07-04T11:33:18.634", + }, + { + "calendarDate": "2024-07-05", + "weeklyAvg": 66, + "lastNightAvg": 69, + "lastNight5MinHigh": 114, + "baseline": { + "lowUpper": 49, + "balancedLow": 53, + "balancedUpper": 75, + "markerValue": 0.5454407, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_6", + "createTimeStamp": "2024-07-05T11:49:13.497", + }, + { + "calendarDate": "2024-07-06", + "weeklyAvg": 68, + "lastNightAvg": 83, + "lastNight5MinHigh": 143, + "baseline": { + "lowUpper": 49, + "balancedLow": 53, + "balancedUpper": 75, + "markerValue": 0.5908966, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_2", + "createTimeStamp": "2024-07-06T11:32:05.710", + }, + { + "calendarDate": "2024-07-07", + "weeklyAvg": 70, + "lastNightAvg": 73, + "lastNight5MinHigh": 117, + "baseline": { + "lowUpper": 49, + "balancedLow": 53, + "balancedUpper": 75, + "markerValue": 0.63635254, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_8", + "createTimeStamp": "2024-07-07T10:46:31.459", + }, + { + "calendarDate": "2024-07-08", + "weeklyAvg": 68, + "lastNightAvg": 53, + "lastNight5MinHigh": 105, + "baseline": { + "lowUpper": 49, + "balancedLow": 53, + "balancedUpper": 75, + "markerValue": 0.5908966, + }, + "status": "BALANCED", + "feedbackPhrase": "HRV_BALANCED_5", + "createTimeStamp": "2024-07-08T10:25:55.940", + }, + ], + "userProfilePk": "user_id: int", + } + } + }, + }, + { + "query": { + "query": 'query{userDailySummaryV2Scalar(startDate:"2024-06-11", endDate:"2024-07-08")}' + }, + "response": { + "data": { + "userDailySummaryV2Scalar": { + "data": [ + { + "uuid": "367dd1c0-87d9-4203-9e16-9243f8918f0f", + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-11", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": true, + "wellnessChronology": { + "startTimestampGmt": "2024-06-11T04:00:00.0", + "startTimestampLocal": "2024-06-11T00:00:00.0", + "endTimestampGmt": "2024-06-12T04:00:00.0", + "endTimestampLocal": "2024-06-12T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 23540, + "value": 27303, + "distanceInMeters": 28657.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 54, + "distanceInMeters": 163.5, + }, + "floorsDescended": { + "value": 55, + "distanceInMeters": 167.74, + }, + }, + "calories": { + "burnedResting": 2214, + "burnedActive": 1385, + "burnedTotal": 3599, + "consumedGoal": 1780, + "consumedValue": 3585, + "consumedRemaining": 14, + }, + "heartRate": { + "minValue": 38, + "maxValue": 171, + "restingValue": 39, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 1, + "vigorous": 63, + }, + "stress": { + "avgLevel": 18, + "maxLevel": 92, + "restProportion": 0.5, + "activityProportion": 0.26, + "uncategorizedProportion": 0.12, + "lowStressProportion": 0.09, + "mediumStressProportion": 0.02, + "highStressProportion": 0.01, + "qualifier": "balanced", + "totalDurationInMillis": 84660000, + "restDurationInMillis": 42720000, + "activityDurationInMillis": 21660000, + "uncategorizedDurationInMillis": 10380000, + "lowStressDurationInMillis": 7680000, + "mediumStressDurationInMillis": 1680000, + "highStressDurationInMillis": 540000, + }, + "bodyBattery": { + "minValue": 29, + "maxValue": 100, + "chargedValue": 71, + "drainedValue": 71, + "latestValue": 42, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-12T01:55:42.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_ACTIVE_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_ACTIVE_AND_INTENSIVE_EXERCISE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-12T03:30:15.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_NOT_STRESS_DATA_AND_ACTIVE_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_TIME_PASSED_NOT_STRESS_DATA_AND_ACTIVE_AND_INTENSIVE_EXERCISE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-06-11T02:26:35.0", + "eventStartTimeLocal": "2024-06-10T22:26:35.0", + "bodyBatteryImpact": 69, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 29040000, + }, + { + "eventType": "NAP", + "eventStartTimeGmt": "2024-06-11T20:00:58.0", + "eventStartTimeLocal": "2024-06-11T16:00:58.0", + "bodyBatteryImpact": -1, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 1200000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-06-11T20:36:02.0", + "eventStartTimeLocal": "2024-06-11T16:36:02.0", + "bodyBatteryImpact": -13, + "feedbackType": "EXERCISE_TRAINING_EFFECT_4", + "shortFeedback": "HIGHLY_IMPROVING_VO2MAX", + "deviceId": 3472661486, + "durationInMillis": 3660000, + }, + ], + }, + "hydration": { + "goalInMl": 3030, + "goalInFractionalMl": 3030.0, + "consumedInMl": 0, + "consumedInFractionalMl": 0.0, + }, + "respiration": { + "avgValue": 16, + "maxValue": 43, + "minValue": 8, + "latestValue": 12, + "latestTimestampGmt": "2024-06-12T04:00:00.0", + }, + "pulseOx": { + "avgValue": 95, + "minValue": 84, + "latestValue": 93, + "latestTimestampGmt": "2024-06-12T04:00:00.0", + "latestTimestampLocal": "2024-06-12T00:00:00.0", + "avgAltitudeInMeters": 19.0, + }, + "jetLag": {}, + }, + { + "uuid": "9bc35cc0-28f1-45cb-b746-21fba172215d", + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-12", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": true, + "wellnessChronology": { + "startTimestampGmt": "2024-06-12T04:00:00.0", + "startTimestampLocal": "2024-06-12T00:00:00.0", + "endTimestampGmt": "2024-06-13T04:00:00.0", + "endTimestampLocal": "2024-06-13T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 23920, + "value": 24992, + "distanceInMeters": 26997.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 85, + "distanceInMeters": 260.42, + }, + "floorsDescended": { + "value": 86, + "distanceInMeters": 262.23, + }, + }, + "calories": { + "burnedResting": 2211, + "burnedActive": 1612, + "burnedTotal": 3823, + "consumedGoal": 1780, + "consumedValue": 3133, + "consumedRemaining": 690, + }, + "heartRate": { + "minValue": 41, + "maxValue": 156, + "restingValue": 42, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 0, + "vigorous": 88, + }, + "stress": { + "avgLevel": 21, + "maxLevel": 96, + "restProportion": 0.52, + "activityProportion": 0.2, + "uncategorizedProportion": 0.16, + "lowStressProportion": 0.09, + "mediumStressProportion": 0.02, + "highStressProportion": 0.01, + "qualifier": "balanced", + "totalDurationInMillis": 86100000, + "restDurationInMillis": 44760000, + "activityDurationInMillis": 16980000, + "uncategorizedDurationInMillis": 14100000, + "lowStressDurationInMillis": 7800000, + "mediumStressDurationInMillis": 1620000, + "highStressDurationInMillis": 840000, + }, + "bodyBattery": { + "minValue": 25, + "maxValue": 96, + "chargedValue": 66, + "drainedValue": 71, + "latestValue": 37, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-13T01:16:26.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-13T03:30:10.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_TIME_PASSED_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-06-12T02:47:14.0", + "eventStartTimeLocal": "2024-06-11T22:47:14.0", + "bodyBatteryImpact": 65, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 28440000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-06-12T18:46:03.0", + "eventStartTimeLocal": "2024-06-12T14:46:03.0", + "bodyBatteryImpact": -16, + "feedbackType": "EXERCISE_TRAINING_EFFECT_3", + "shortFeedback": "IMPROVING_AEROBIC_ENDURANCE", + "deviceId": 3472661486, + "durationInMillis": 5100000, + }, + ], + }, + "hydration": { + "goalInMl": 3368, + "goalInFractionalMl": 3368.0, + "consumedInMl": 0, + "consumedInFractionalMl": 0.0, + }, + "respiration": { + "avgValue": 17, + "maxValue": 37, + "minValue": 8, + "latestValue": 12, + "latestTimestampGmt": "2024-06-13T04:00:00.0", + }, + "pulseOx": { + "avgValue": 95, + "minValue": 87, + "latestValue": 88, + "latestTimestampGmt": "2024-06-13T04:00:00.0", + "latestTimestampLocal": "2024-06-13T00:00:00.0", + "avgAltitudeInMeters": 42.0, + }, + "jetLag": {}, + }, + { + "uuid": "d89a181e-d7fb-4d2d-8583-3d6c7efbd2c4", + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-13", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": true, + "wellnessChronology": { + "startTimestampGmt": "2024-06-13T04:00:00.0", + "startTimestampLocal": "2024-06-13T00:00:00.0", + "endTimestampGmt": "2024-06-14T04:00:00.0", + "endTimestampLocal": "2024-06-14T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 24140, + "value": 25546, + "distanceInMeters": 26717.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 62, + "distanceInMeters": 190.45, + }, + "floorsDescended": { + "value": 71, + "distanceInMeters": 215.13, + }, + }, + "calories": { + "burnedResting": 2203, + "burnedActive": 1594, + "burnedTotal": 3797, + "consumedGoal": 1780, + "consumedValue": 2244, + "consumedRemaining": 1553, + }, + "heartRate": { + "minValue": 39, + "maxValue": 152, + "restingValue": 43, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 0, + "vigorous": 76, + }, + "stress": { + "avgLevel": 24, + "maxLevel": 96, + "restProportion": 0.43, + "activityProportion": 0.23, + "uncategorizedProportion": 0.15, + "lowStressProportion": 0.14, + "mediumStressProportion": 0.05, + "highStressProportion": 0.01, + "qualifier": "stressful", + "totalDurationInMillis": 86160000, + "restDurationInMillis": 36900000, + "activityDurationInMillis": 19440000, + "uncategorizedDurationInMillis": 12660000, + "lowStressDurationInMillis": 12000000, + "mediumStressDurationInMillis": 4260000, + "highStressDurationInMillis": 900000, + }, + "bodyBattery": { + "minValue": 20, + "maxValue": 88, + "chargedValue": 61, + "drainedValue": 69, + "latestValue": 29, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-14T00:52:20.0", + "bodyBatteryLevel": "MODERATE", + "feedbackShortType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-14T03:16:57.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_BALANCED_AND_ACTIVE_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_TIME_PASSED_BALANCED_AND_ACTIVE_AND_INTENSIVE_EXERCISE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-06-13T02:25:30.0", + "eventStartTimeLocal": "2024-06-12T22:25:30.0", + "bodyBatteryImpact": 63, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 28260000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-06-13T15:21:45.0", + "eventStartTimeLocal": "2024-06-13T11:21:45.0", + "bodyBatteryImpact": -14, + "feedbackType": "EXERCISE_TRAINING_EFFECT_3", + "shortFeedback": "IMPROVING_AEROBIC_BASE", + "deviceId": 3472661486, + "durationInMillis": 4200000, + }, + { + "eventType": "NAP", + "eventStartTimeGmt": "2024-06-13T18:06:33.0", + "eventStartTimeLocal": "2024-06-13T14:06:33.0", + "bodyBatteryImpact": -1, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 2400000, + }, + ], + }, + "hydration": { + "goalInMl": 3165, + "goalInFractionalMl": 3165.0, + "consumedInMl": 0, + "consumedInFractionalMl": 0.0, + }, + "respiration": { + "avgValue": 15, + "maxValue": 37, + "minValue": 8, + "latestValue": 8, + "latestTimestampGmt": "2024-06-14T04:00:00.0", + }, + "pulseOx": { + "avgValue": 95, + "minValue": 84, + "latestValue": 94, + "latestTimestampGmt": "2024-06-14T04:00:00.0", + "latestTimestampLocal": "2024-06-14T00:00:00.0", + "avgAltitudeInMeters": 49.0, + }, + "jetLag": {}, + }, + { + "uuid": "e44d344b-1f7e-428f-ad39-891862b77c6f", + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-14", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": false, + "wellnessChronology": { + "startTimestampGmt": "2024-06-14T04:00:00.0", + "startTimestampLocal": "2024-06-14T00:00:00.0", + "endTimestampGmt": "2024-06-15T04:00:00.0", + "endTimestampLocal": "2024-06-15T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 24430, + "value": 15718, + "distanceInMeters": 13230.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 45, + "distanceInMeters": 137.59, + }, + "floorsDescended": { + "value": 47, + "distanceInMeters": 143.09, + }, + }, + "calories": { + "burnedResting": 2206, + "burnedActive": 531, + "burnedTotal": 2737, + "consumedGoal": 1780, + "consumedValue": 0, + "consumedRemaining": 2737, + }, + "heartRate": { + "minValue": 43, + "maxValue": 110, + "restingValue": 44, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 0, + "vigorous": 2, + }, + "stress": { + "avgLevel": 26, + "maxLevel": 93, + "restProportion": 0.48, + "activityProportion": 0.18, + "uncategorizedProportion": 0.04, + "lowStressProportion": 0.26, + "mediumStressProportion": 0.04, + "highStressProportion": 0.01, + "qualifier": "balanced", + "totalDurationInMillis": 84660000, + "restDurationInMillis": 40680000, + "activityDurationInMillis": 15060000, + "uncategorizedDurationInMillis": 3540000, + "lowStressDurationInMillis": 21900000, + "mediumStressDurationInMillis": 3000000, + "highStressDurationInMillis": 480000, + }, + "bodyBattery": { + "minValue": 29, + "maxValue": 81, + "chargedValue": 62, + "drainedValue": 52, + "latestValue": 39, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-15T00:05:00.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_PREPARATION_RECOVERING_AND_INACTIVE", + "feedbackLongType": "SLEEP_PREPARATION_RECOVERING_AND_INACTIVE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-15T03:30:04.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_RECOVERING_AND_INACTIVE", + "feedbackLongType": "SLEEP_TIME_PASSED_RECOVERING_AND_INACTIVE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-06-14T02:35:08.0", + "eventStartTimeLocal": "2024-06-13T22:35:08.0", + "bodyBatteryImpact": 61, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 28500000, + } + ], + }, + "hydration": {}, + "respiration": { + "avgValue": 14, + "maxValue": 21, + "minValue": 8, + "latestValue": 12, + "latestTimestampGmt": "2024-06-15T04:00:00.0", + }, + "pulseOx": { + "avgValue": 92, + "minValue": 84, + "latestValue": 95, + "latestTimestampGmt": "2024-06-15T04:00:00.0", + "latestTimestampLocal": "2024-06-15T00:00:00.0", + "avgAltitudeInMeters": 85.0, + }, + "jetLag": {}, + }, + { + "uuid": "72069c99-5246-4d78-9ebe-8daf237372e0", + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-15", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": true, + "wellnessChronology": { + "startTimestampGmt": "2024-06-15T04:00:00.0", + "startTimestampLocal": "2024-06-15T00:00:00.0", + "endTimestampGmt": "2024-06-16T04:00:00.0", + "endTimestampLocal": "2024-06-16T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 23560, + "value": 19729, + "distanceInMeters": 20342.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 85, + "distanceInMeters": 259.85, + }, + "floorsDescended": { + "value": 80, + "distanceInMeters": 245.04, + }, + }, + "calories": { + "burnedResting": 2206, + "burnedActive": 1114, + "burnedTotal": 3320, + "consumedGoal": 1780, + "consumedValue": 0, + "consumedRemaining": 3320, + }, + "heartRate": { + "minValue": 41, + "maxValue": 154, + "restingValue": 45, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 0, + "vigorous": 59, + }, + "stress": { + "avgLevel": 24, + "maxLevel": 98, + "restProportion": 0.55, + "activityProportion": 0.13, + "uncategorizedProportion": 0.15, + "lowStressProportion": 0.12, + "mediumStressProportion": 0.04, + "highStressProportion": 0.02, + "qualifier": "balanced", + "totalDurationInMillis": 85020000, + "restDurationInMillis": 46620000, + "activityDurationInMillis": 10680000, + "uncategorizedDurationInMillis": 12660000, + "lowStressDurationInMillis": 10440000, + "mediumStressDurationInMillis": 3120000, + "highStressDurationInMillis": 1500000, + }, + "bodyBattery": { + "minValue": 37, + "maxValue": 85, + "chargedValue": 63, + "drainedValue": 54, + "latestValue": 48, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-16T00:27:21.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_PREPARATION_RECOVERING_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_PREPARATION_RECOVERING_AND_INTENSIVE_EXERCISE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-16T03:30:09.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_RECOVERING_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_TIME_PASSED_RECOVERING_AND_INTENSIVE_EXERCISE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-06-15T02:14:41.0", + "eventStartTimeLocal": "2024-06-14T22:14:41.0", + "bodyBatteryImpact": 55, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 30360000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-06-15T11:27:59.0", + "eventStartTimeLocal": "2024-06-15T07:27:59.0", + "bodyBatteryImpact": -12, + "feedbackType": "EXERCISE_TRAINING_EFFECT_3", + "shortFeedback": "IMPROVING_AEROBIC_BASE", + "deviceId": 3472661486, + "durationInMillis": 2940000, + }, + { + "eventType": "RECOVERY", + "eventStartTimeGmt": "2024-06-15T15:38:02.0", + "eventStartTimeLocal": "2024-06-15T11:38:02.0", + "bodyBatteryImpact": 2, + "feedbackType": "RECOVERY_BODY_BATTERY_INCREASE", + "shortFeedback": "BODY_BATTERY_RECHARGE", + "deviceId": 3472661486, + "durationInMillis": 2400000, + }, + { + "eventType": "NAP", + "eventStartTimeGmt": "2024-06-15T19:45:37.0", + "eventStartTimeLocal": "2024-06-15T15:45:37.0", + "bodyBatteryImpact": 4, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 2640000, + }, + ], + }, + "hydration": { + "goalInMl": 2806, + "goalInFractionalMl": 2806.0, + "consumedInMl": 0, + "consumedInFractionalMl": 0.0, + }, + "respiration": { + "avgValue": 17, + "maxValue": 40, + "minValue": 9, + "latestValue": 12, + "latestTimestampGmt": "2024-06-16T04:00:00.0", + }, + "pulseOx": { + "avgValue": 94, + "minValue": 83, + "latestValue": 88, + "latestTimestampGmt": "2024-06-16T04:00:00.0", + "latestTimestampLocal": "2024-06-16T00:00:00.0", + "avgAltitudeInMeters": 52.0, + }, + "jetLag": {}, + }, + { + "uuid": "6da2bf6c-95c2-49e1-a3a6-649c61bc1bb3", + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-16", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": true, + "wellnessChronology": { + "startTimestampGmt": "2024-06-16T04:00:00.0", + "startTimestampLocal": "2024-06-16T00:00:00.0", + "endTimestampGmt": "2024-06-17T04:00:00.0", + "endTimestampLocal": "2024-06-17T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 22800, + "value": 30464, + "distanceInMeters": 30330.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 77, + "distanceInMeters": 233.52, + }, + "floorsDescended": { + "value": 70, + "distanceInMeters": 212.2, + }, + }, + "calories": { + "burnedResting": 2206, + "burnedActive": 1584, + "burnedTotal": 3790, + "consumedGoal": 1780, + "consumedValue": 0, + "consumedRemaining": 3790, + }, + "heartRate": { + "minValue": 39, + "maxValue": 145, + "restingValue": 41, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 0, + "vigorous": 66, + }, + "stress": { + "avgLevel": 21, + "maxLevel": 98, + "restProportion": 0.53, + "activityProportion": 0.18, + "uncategorizedProportion": 0.15, + "lowStressProportion": 0.09, + "mediumStressProportion": 0.03, + "highStressProportion": 0.02, + "qualifier": "balanced", + "totalDurationInMillis": 84780000, + "restDurationInMillis": 45120000, + "activityDurationInMillis": 15600000, + "uncategorizedDurationInMillis": 12480000, + "lowStressDurationInMillis": 7320000, + "mediumStressDurationInMillis": 2940000, + "highStressDurationInMillis": 1320000, + }, + "bodyBattery": { + "minValue": 39, + "maxValue": 98, + "chargedValue": 58, + "drainedValue": 59, + "latestValue": 48, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-17T00:05:00.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_ACTIVE_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_ACTIVE_AND_INTENSIVE_EXERCISE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-17T03:57:54.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_RECOVERING_AND_ACTIVE_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_TIME_PASSED_RECOVERING_AND_ACTIVE_AND_INTENSIVE_EXERCISE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-06-16T02:04:07.0", + "eventStartTimeLocal": "2024-06-15T22:04:07.0", + "bodyBatteryImpact": 61, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 30360000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-06-16T11:17:58.0", + "eventStartTimeLocal": "2024-06-16T07:17:58.0", + "bodyBatteryImpact": -17, + "feedbackType": "EXERCISE_TRAINING_EFFECT_3", + "shortFeedback": "IMPROVING_AEROBIC_BASE", + "deviceId": 3472661486, + "durationInMillis": 3780000, + }, + { + "eventType": "RECOVERY", + "eventStartTimeGmt": "2024-06-16T16:51:20.0", + "eventStartTimeLocal": "2024-06-16T12:51:20.0", + "bodyBatteryImpact": 0, + "feedbackType": "RECOVERY_BODY_BATTERY_NOT_INCREASE", + "shortFeedback": "RESTFUL_PERIOD", + "deviceId": 3472661486, + "durationInMillis": 1920000, + }, + { + "eventType": "NAP", + "eventStartTimeGmt": "2024-06-16T18:05:20.0", + "eventStartTimeLocal": "2024-06-16T14:05:20.0", + "bodyBatteryImpact": -1, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 2700000, + }, + ], + }, + "hydration": { + "goalInMl": 3033, + "goalInFractionalMl": 3033.0, + "consumedInMl": 0, + "consumedInFractionalMl": 0.0, + }, + "respiration": { + "avgValue": 16, + "maxValue": 40, + "minValue": 8, + "latestValue": 11, + "latestTimestampGmt": "2024-06-17T04:00:00.0", + }, + "pulseOx": { + "avgValue": 94, + "minValue": 83, + "latestValue": 92, + "latestTimestampGmt": "2024-06-17T04:00:00.0", + "latestTimestampLocal": "2024-06-17T00:00:00.0", + "avgAltitudeInMeters": 57.0, + }, + "jetLag": {}, + }, + { + "uuid": "f2396b62-8384-4548-9bd1-260c5e3b29d2", + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-17", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": false, + "wellnessChronology": { + "startTimestampGmt": "2024-06-17T04:00:00.0", + "startTimestampLocal": "2024-06-17T00:00:00.0", + "endTimestampGmt": "2024-06-18T04:00:00.0", + "endTimestampLocal": "2024-06-18T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 23570, + "value": 16161, + "distanceInMeters": 13603.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 56, + "distanceInMeters": 169.86, + }, + "floorsDescended": { + "value": 63, + "distanceInMeters": 193.24, + }, + }, + "calories": { + "burnedResting": 2206, + "burnedActive": 477, + "burnedTotal": 2683, + "consumedGoal": 1780, + "consumedValue": 0, + "consumedRemaining": 2683, + }, + "heartRate": { + "minValue": 38, + "maxValue": 109, + "restingValue": 40, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 0, + "vigorous": 2, + }, + "stress": { + "avgLevel": 21, + "maxLevel": 96, + "restProportion": 0.52, + "activityProportion": 0.16, + "uncategorizedProportion": 0.12, + "lowStressProportion": 0.15, + "mediumStressProportion": 0.04, + "highStressProportion": 0.01, + "qualifier": "balanced", + "totalDurationInMillis": 85020000, + "restDurationInMillis": 44520000, + "activityDurationInMillis": 13380000, + "uncategorizedDurationInMillis": 9900000, + "lowStressDurationInMillis": 13080000, + "mediumStressDurationInMillis": 3480000, + "highStressDurationInMillis": 660000, + }, + "bodyBattery": { + "minValue": 36, + "maxValue": 100, + "chargedValue": 54, + "drainedValue": 64, + "latestValue": 38, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-18T00:13:50.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_PREPARATION_RECOVERING_AND_INACTIVE", + "feedbackLongType": "SLEEP_PREPARATION_RECOVERING_AND_INACTIVE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-18T03:30:09.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_RECOVERING_AND_INACTIVE", + "feedbackLongType": "SLEEP_TIME_PASSED_RECOVERING_AND_INACTIVE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-06-17T03:03:30.0", + "eventStartTimeLocal": "2024-06-16T23:03:30.0", + "bodyBatteryImpact": 58, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 29820000, + } + ], + }, + "hydration": {}, + "respiration": { + "avgValue": 15, + "maxValue": 25, + "minValue": 8, + "latestValue": 9, + "latestTimestampGmt": "2024-06-18T04:00:00.0", + }, + "pulseOx": { + "avgValue": 94, + "minValue": 82, + "latestValue": 96, + "latestTimestampGmt": "2024-06-18T04:00:00.0", + "latestTimestampLocal": "2024-06-18T00:00:00.0", + "avgAltitudeInMeters": 39.0, + }, + "jetLag": {}, + }, + { + "uuid": "718af8d5-8c88-4f91-9690-d3fa4e4a6f37", + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-18", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": true, + "wellnessChronology": { + "startTimestampGmt": "2024-06-18T04:00:00.0", + "startTimestampLocal": "2024-06-18T00:00:00.0", + "endTimestampGmt": "2024-06-19T04:00:00.0", + "endTimestampLocal": "2024-06-19T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 22830, + "value": 17088, + "distanceInMeters": 18769.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 53, + "distanceInMeters": 160.13, + }, + "floorsDescended": { + "value": 47, + "distanceInMeters": 142.2, + }, + }, + "calories": { + "burnedResting": 2206, + "burnedActive": 1177, + "burnedTotal": 3383, + "consumedGoal": 1780, + "consumedValue": 0, + "consumedRemaining": 3383, + }, + "heartRate": { + "minValue": 41, + "maxValue": 168, + "restingValue": 42, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 4, + "vigorous": 59, + }, + "stress": { + "avgLevel": 23, + "maxLevel": 99, + "restProportion": 0.42, + "activityProportion": 0.07, + "uncategorizedProportion": 0.37, + "lowStressProportion": 0.1, + "mediumStressProportion": 0.02, + "highStressProportion": 0.02, + "qualifier": "stressful", + "totalDurationInMillis": 85200000, + "restDurationInMillis": 35460000, + "activityDurationInMillis": 6300000, + "uncategorizedDurationInMillis": 31920000, + "lowStressDurationInMillis": 8220000, + "mediumStressDurationInMillis": 1920000, + "highStressDurationInMillis": 1380000, + }, + "bodyBattery": { + "minValue": 24, + "maxValue": 92, + "chargedValue": 62, + "drainedValue": 46, + "latestValue": 32, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-19T02:59:57.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-19T03:30:05.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_TIME_PASSED_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-06-18T03:19:33.0", + "eventStartTimeLocal": "2024-06-17T23:19:33.0", + "bodyBatteryImpact": 56, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 28080000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-06-18T11:50:39.0", + "eventStartTimeLocal": "2024-06-18T07:50:39.0", + "bodyBatteryImpact": -14, + "feedbackType": "EXERCISE_TRAINING_EFFECT_3", + "shortFeedback": "IMPROVING_VO2MAX", + "deviceId": 3472661486, + "durationInMillis": 3180000, + }, + ], + }, + "hydration": { + "goalInMl": 2888, + "goalInFractionalMl": 2888.0, + "consumedInMl": 0, + "consumedInFractionalMl": 0.0, + }, + "respiration": { + "avgValue": 16, + "maxValue": 41, + "minValue": 8, + "latestValue": 16, + "latestTimestampGmt": "2024-06-19T04:00:00.0", + }, + "pulseOx": { + "avgValue": 92, + "minValue": 85, + "latestValue": 94, + "latestTimestampGmt": "2024-06-19T04:00:00.0", + "latestTimestampLocal": "2024-06-19T00:00:00.0", + "avgAltitudeInMeters": 37.0, + }, + "jetLag": {}, + }, + { + "uuid": "4b8046ce-2e66-494a-be96-6df4e5d5181c", + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-19", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": true, + "wellnessChronology": { + "startTimestampGmt": "2024-06-19T04:00:00.0", + "startTimestampLocal": "2024-06-19T00:00:00.0", + "endTimestampGmt": "2024-06-20T04:00:00.0", + "endTimestampLocal": "2024-06-20T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 21690, + "value": 15688, + "distanceInMeters": 16548.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 41, + "distanceInMeters": 125.38, + }, + "floorsDescended": { + "value": 47, + "distanceInMeters": 144.18, + }, + }, + "calories": { + "burnedResting": 2206, + "burnedActive": 884, + "burnedTotal": 3090, + "consumedGoal": 1780, + "consumedValue": 0, + "consumedRemaining": 3090, + }, + "heartRate": { + "minValue": 38, + "maxValue": 162, + "restingValue": 38, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 6, + "vigorous": 48, + }, + "stress": { + "avgLevel": 29, + "maxLevel": 97, + "restProportion": 0.42, + "activityProportion": 0.15, + "uncategorizedProportion": 0.13, + "lowStressProportion": 0.17, + "mediumStressProportion": 0.12, + "highStressProportion": 0.02, + "qualifier": "stressful", + "totalDurationInMillis": 84240000, + "restDurationInMillis": 35040000, + "activityDurationInMillis": 12660000, + "uncategorizedDurationInMillis": 10800000, + "lowStressDurationInMillis": 14340000, + "mediumStressDurationInMillis": 9840000, + "highStressDurationInMillis": 1560000, + }, + "bodyBattery": { + "minValue": 23, + "maxValue": 97, + "chargedValue": 74, + "drainedValue": 74, + "latestValue": 32, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-20T02:35:03.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_PREPARATION_STRESSFUL_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_PREPARATION_STRESSFUL_AND_INTENSIVE_EXERCISE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-20T03:30:04.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_STRESSFUL_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_TIME_PASSED_STRESSFUL_AND_INTENSIVE_EXERCISE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-06-19T02:38:46.0", + "eventStartTimeLocal": "2024-06-18T22:38:46.0", + "bodyBatteryImpact": 72, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 29220000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-06-19T11:12:12.0", + "eventStartTimeLocal": "2024-06-19T07:12:12.0", + "bodyBatteryImpact": -14, + "feedbackType": "EXERCISE_TRAINING_EFFECT_3", + "shortFeedback": "IMPROVING_AEROBIC_BASE", + "deviceId": 3472661486, + "durationInMillis": 2820000, + }, + ], + }, + "hydration": { + "goalInMl": 2779, + "goalInFractionalMl": 2779.0, + "consumedInMl": 0, + "consumedInFractionalMl": 0.0, + }, + "respiration": { + "avgValue": 15, + "maxValue": 38, + "minValue": 9, + "latestValue": 16, + "latestTimestampGmt": "2024-06-20T04:00:00.0", + }, + "pulseOx": { + "avgValue": 93, + "minValue": 87, + "latestValue": 97, + "latestTimestampGmt": "2024-06-20T04:00:00.0", + "latestTimestampLocal": "2024-06-20T00:00:00.0", + "avgAltitudeInMeters": 83.0, + }, + "jetLag": {}, + }, + { + "uuid": "38dc2bbc-1b04-46ca-9f57-a90d0a768cac", + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-20", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": true, + "wellnessChronology": { + "startTimestampGmt": "2024-06-20T04:00:00.0", + "startTimestampLocal": "2024-06-20T00:00:00.0", + "endTimestampGmt": "2024-06-21T04:00:00.0", + "endTimestampLocal": "2024-06-21T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 20490, + "value": 20714, + "distanceInMeters": 21420.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 48, + "distanceInMeters": 147.37, + }, + "floorsDescended": { + "value": 52, + "distanceInMeters": 157.31, + }, + }, + "calories": { + "burnedResting": 2226, + "burnedActive": 1769, + "burnedTotal": 3995, + "consumedGoal": 1780, + "consumedValue": 3667, + "consumedRemaining": 328, + }, + "heartRate": { + "minValue": 41, + "maxValue": 162, + "restingValue": 41, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 34, + "vigorous": 93, + }, + "stress": { + "avgLevel": 24, + "maxLevel": 99, + "restProportion": 0.49, + "activityProportion": 0.16, + "uncategorizedProportion": 0.2, + "lowStressProportion": 0.1, + "mediumStressProportion": 0.04, + "highStressProportion": 0.01, + "qualifier": "balanced", + "totalDurationInMillis": 84300000, + "restDurationInMillis": 41400000, + "activityDurationInMillis": 13440000, + "uncategorizedDurationInMillis": 16440000, + "lowStressDurationInMillis": 8520000, + "mediumStressDurationInMillis": 3720000, + "highStressDurationInMillis": 780000, + }, + "bodyBattery": { + "minValue": 26, + "maxValue": 77, + "chargedValue": 54, + "drainedValue": 51, + "latestValue": 35, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-21T00:05:00.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-21T03:11:38.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_TIME_PASSED_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-06-20T02:10:32.0", + "eventStartTimeLocal": "2024-06-19T22:10:32.0", + "bodyBatteryImpact": 52, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 28860000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-06-20T11:10:18.0", + "eventStartTimeLocal": "2024-06-20T07:10:18.0", + "bodyBatteryImpact": -14, + "feedbackType": "EXERCISE_TRAINING_EFFECT_3", + "shortFeedback": "IMPROVING_TEMPO", + "deviceId": 3472661486, + "durationInMillis": 3540000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-06-20T21:03:34.0", + "eventStartTimeLocal": "2024-06-20T17:03:34.0", + "bodyBatteryImpact": -6, + "feedbackType": "EXERCISE_TRAINING_EFFECT_2", + "shortFeedback": "MINOR_ANAEROBIC_EFFECT", + "deviceId": 3472661486, + "durationInMillis": 4560000, + }, + ], + }, + "hydration": { + "goalInMl": 3952, + "goalInFractionalMl": 3952.0, + "consumedInMl": 0, + "consumedInFractionalMl": 0.0, + }, + "respiration": { + "avgValue": 17, + "maxValue": 40, + "minValue": 8, + "latestValue": 21, + "latestTimestampGmt": "2024-06-21T04:00:00.0", + }, + "pulseOx": { + "avgValue": 95, + "minValue": 86, + "latestValue": 94, + "latestTimestampGmt": "2024-06-21T04:00:00.0", + "latestTimestampLocal": "2024-06-21T00:00:00.0", + "avgAltitudeInMeters": 54.0, + }, + "jetLag": {}, + }, + { + "uuid": "aeb4f77d-e02f-4539-8089-a4744a79cbf3", + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-21", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": true, + "wellnessChronology": { + "startTimestampGmt": "2024-06-21T04:00:00.0", + "startTimestampLocal": "2024-06-21T00:00:00.0", + "endTimestampGmt": "2024-06-22T04:00:00.0", + "endTimestampLocal": "2024-06-22T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 20520, + "value": 20690, + "distanceInMeters": 20542.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 40, + "distanceInMeters": 121.92, + }, + "floorsDescended": { + "value": 48, + "distanceInMeters": 146.59, + }, + }, + "calories": { + "burnedResting": 2228, + "burnedActive": 1114, + "burnedTotal": 3342, + "consumedGoal": 1780, + "consumedValue": 3087, + "consumedRemaining": 255, + }, + "heartRate": { + "minValue": 40, + "maxValue": 148, + "restingValue": 41, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 0, + "vigorous": 54, + }, + "stress": { + "avgLevel": 21, + "maxLevel": 99, + "restProportion": 0.52, + "activityProportion": 0.21, + "uncategorizedProportion": 0.11, + "lowStressProportion": 0.11, + "mediumStressProportion": 0.03, + "highStressProportion": 0.01, + "qualifier": "balanced", + "totalDurationInMillis": 84600000, + "restDurationInMillis": 44340000, + "activityDurationInMillis": 17580000, + "uncategorizedDurationInMillis": 9660000, + "lowStressDurationInMillis": 9360000, + "mediumStressDurationInMillis": 2640000, + "highStressDurationInMillis": 1020000, + }, + "bodyBattery": { + "minValue": 29, + "maxValue": 95, + "chargedValue": 73, + "drainedValue": 67, + "latestValue": 41, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-22T02:35:26.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_PREPARATION_RECOVERING_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_PREPARATION_RECOVERING_AND_INTENSIVE_EXERCISE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-22T03:05:55.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_RECOVERING_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_TIME_PASSED_RECOVERING_AND_INTENSIVE_EXERCISE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-06-21T02:13:54.0", + "eventStartTimeLocal": "2024-06-20T22:13:54.0", + "bodyBatteryImpact": 68, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 28260000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-06-21T11:00:14.0", + "eventStartTimeLocal": "2024-06-21T07:00:14.0", + "bodyBatteryImpact": -13, + "feedbackType": "EXERCISE_TRAINING_EFFECT_3", + "shortFeedback": "IMPROVING_AEROBIC_BASE", + "deviceId": 3472661486, + "durationInMillis": 2820000, + }, + ], + }, + "hydration": { + "goalInMl": 2787, + "goalInFractionalMl": 2787.0, + "consumedInMl": 0, + "consumedInFractionalMl": 0.0, + }, + "respiration": { + "avgValue": 16, + "maxValue": 32, + "minValue": 10, + "latestValue": 21, + "latestTimestampGmt": "2024-06-22T04:00:00.0", + }, + "pulseOx": { + "avgValue": 94, + "minValue": 85, + "latestValue": 96, + "latestTimestampGmt": "2024-06-22T03:58:00.0", + "latestTimestampLocal": "2024-06-21T23:58:00.0", + "avgAltitudeInMeters": 58.0, + }, + "jetLag": {}, + }, + { + "uuid": "93917ebe-72af-42b9-bb9e-2873f6805b9b", + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-22", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": true, + "wellnessChronology": { + "startTimestampGmt": "2024-06-22T04:00:00.0", + "startTimestampLocal": "2024-06-22T00:00:00.0", + "endTimestampGmt": "2024-06-23T04:00:00.0", + "endTimestampLocal": "2024-06-23T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 20560, + "value": 40346, + "distanceInMeters": 45842.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 68, + "distanceInMeters": 206.24, + }, + "floorsDescended": { + "value": 68, + "distanceInMeters": 206.31, + }, + }, + "calories": { + "burnedResting": 2222, + "burnedActive": 2844, + "burnedTotal": 5066, + "consumedGoal": 1780, + "consumedValue": 2392, + "consumedRemaining": 2674, + }, + "heartRate": { + "minValue": 38, + "maxValue": 157, + "restingValue": 39, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 6, + "vigorous": 171, + }, + "stress": { + "avgLevel": 24, + "maxLevel": 95, + "restProportion": 0.37, + "activityProportion": 0.25, + "uncategorizedProportion": 0.24, + "lowStressProportion": 0.07, + "mediumStressProportion": 0.05, + "highStressProportion": 0.02, + "qualifier": "stressful", + "totalDurationInMillis": 84780000, + "restDurationInMillis": 31200000, + "activityDurationInMillis": 21540000, + "uncategorizedDurationInMillis": 20760000, + "lowStressDurationInMillis": 5580000, + "mediumStressDurationInMillis": 4320000, + "highStressDurationInMillis": 1380000, + }, + "bodyBattery": { + "minValue": 15, + "maxValue": 100, + "chargedValue": 58, + "drainedValue": 85, + "latestValue": 15, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-23T00:05:00.0", + "bodyBatteryLevel": "MODERATE", + "feedbackShortType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_ACTIVE_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_ACTIVE_AND_INTENSIVE_EXERCISE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-23T03:30:47.0", + "bodyBatteryLevel": "MODERATE", + "feedbackShortType": "SLEEP_TIME_PASSED_NOT_STRESS_DATA_AND_ACTIVE_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_TIME_PASSED_NOT_STRESS_DATA_AND_ACTIVE_AND_INTENSIVE_EXERCISE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-06-22T02:27:18.0", + "eventStartTimeLocal": "2024-06-21T22:27:18.0", + "bodyBatteryImpact": 69, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 30960000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-06-22T16:32:00.0", + "eventStartTimeLocal": "2024-06-22T12:32:00.0", + "bodyBatteryImpact": -30, + "feedbackType": "EXERCISE_TRAINING_EFFECT_4", + "shortFeedback": "HIGHLY_IMPROVING_LACTATE_THRESHOLD", + "deviceId": 3472661486, + "durationInMillis": 9000000, + }, + ], + }, + "hydration": { + "goalInMl": 4412, + "goalInFractionalMl": 4412.0, + "consumedInMl": 0, + "consumedInFractionalMl": 0.0, + }, + "respiration": { + "avgValue": 18, + "maxValue": 37, + "minValue": 8, + "latestValue": 13, + "latestTimestampGmt": "2024-06-23T03:56:00.0", + }, + "pulseOx": { + "avgValue": 96, + "minValue": 87, + "latestValue": 99, + "latestTimestampGmt": "2024-06-23T04:00:00.0", + "latestTimestampLocal": "2024-06-23T00:00:00.0", + "avgAltitudeInMeters": 35.0, + }, + "jetLag": {}, + }, + { + "uuid": "2120430b-f380-4370-9b1c-dbfb75c15ab3", + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-23", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": true, + "wellnessChronology": { + "startTimestampGmt": "2024-06-23T04:00:00.0", + "startTimestampLocal": "2024-06-23T00:00:00.0", + "endTimestampGmt": "2024-06-24T04:00:00.0", + "endTimestampLocal": "2024-06-24T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 22560, + "value": 21668, + "distanceInMeters": 21550.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 27, + "distanceInMeters": 83.75, + }, + "floorsDescended": { + "value": 27, + "distanceInMeters": 82.64, + }, + }, + "calories": { + "burnedResting": 2213, + "burnedActive": 1639, + "burnedTotal": 3852, + "consumedGoal": 1780, + "consumedRemaining": 3852, + }, + "heartRate": { + "minValue": 42, + "maxValue": 148, + "restingValue": 44, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 30, + "vigorous": 85, + }, + "stress": { + "avgLevel": 20, + "maxLevel": 96, + "restProportion": 0.43, + "activityProportion": 0.26, + "uncategorizedProportion": 0.21, + "lowStressProportion": 0.07, + "mediumStressProportion": 0.03, + "highStressProportion": 0.01, + "qualifier": "stressful", + "totalDurationInMillis": 85920000, + "restDurationInMillis": 37080000, + "activityDurationInMillis": 22680000, + "uncategorizedDurationInMillis": 17700000, + "lowStressDurationInMillis": 5640000, + "mediumStressDurationInMillis": 2280000, + "highStressDurationInMillis": 540000, + }, + "bodyBattery": { + "minValue": 15, + "maxValue": 82, + "chargedValue": 78, + "drainedValue": 62, + "latestValue": 31, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-24T03:00:59.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_ACTIVE_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_ACTIVE_AND_INTENSIVE_EXERCISE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-24T03:30:14.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_NOT_STRESS_DATA_AND_ACTIVE_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_TIME_PASSED_NOT_STRESS_DATA_AND_ACTIVE_AND_INTENSIVE_EXERCISE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-06-23T04:13:41.0", + "eventStartTimeLocal": "2024-06-23T00:13:41.0", + "bodyBatteryImpact": 67, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 27780000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-06-23T18:00:27.0", + "eventStartTimeLocal": "2024-06-23T14:00:27.0", + "bodyBatteryImpact": -8, + "feedbackType": "EXERCISE_TRAINING_EFFECT_2", + "shortFeedback": "MAINTAINING_ANAEROBIC_FITNESS", + "deviceId": 3472661486, + "durationInMillis": 6000000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-06-23T20:25:19.0", + "eventStartTimeLocal": "2024-06-23T16:25:19.0", + "bodyBatteryImpact": -8, + "feedbackType": "EXERCISE_TRAINING_EFFECT_3", + "shortFeedback": "IMPROVING_AEROBIC_BASE", + "deviceId": 3472661486, + "durationInMillis": 3060000, + }, + ], + }, + "hydration": { + "goalInMl": 4184, + "goalInFractionalMl": 4184.0, + "consumedInMl": 0, + "consumedInFractionalMl": 0.0, + }, + "respiration": { + "avgValue": 17, + "maxValue": 35, + "minValue": 8, + "latestValue": 12, + "latestTimestampGmt": "2024-06-24T04:00:00.0", + }, + "pulseOx": { + "avgValue": 93, + "minValue": 81, + "latestValue": 94, + "latestTimestampGmt": "2024-06-24T04:00:00.0", + "latestTimestampLocal": "2024-06-24T00:00:00.0", + "avgAltitudeInMeters": 41.0, + }, + "jetLag": {}, + }, + { + "uuid": "2a188f96-f0fa-43e7-b62c-4f142476f791", + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-24", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": false, + "wellnessChronology": { + "startTimestampGmt": "2024-06-24T04:00:00.0", + "startTimestampLocal": "2024-06-24T00:00:00.0", + "endTimestampGmt": "2024-06-25T04:00:00.0", + "endTimestampLocal": "2024-06-25T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 22470, + "value": 16159, + "distanceInMeters": 13706.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 23, + "distanceInMeters": 69.31, + }, + "floorsDescended": { + "value": 18, + "distanceInMeters": 53.38, + }, + }, + "calories": { + "burnedResting": 2224, + "burnedActive": 411, + "burnedTotal": 2635, + "consumedGoal": 1780, + "consumedValue": 1628, + "consumedRemaining": 1007, + }, + "heartRate": { + "minValue": 37, + "maxValue": 113, + "restingValue": 39, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 0, + "vigorous": 2, + }, + "stress": { + "avgLevel": 18, + "maxLevel": 86, + "restProportion": 0.52, + "activityProportion": 0.3, + "uncategorizedProportion": 0.07, + "lowStressProportion": 0.1, + "mediumStressProportion": 0.02, + "highStressProportion": 0.0, + "qualifier": "balanced", + "totalDurationInMillis": 85140000, + "restDurationInMillis": 44280000, + "activityDurationInMillis": 25260000, + "uncategorizedDurationInMillis": 5760000, + "lowStressDurationInMillis": 8280000, + "mediumStressDurationInMillis": 1380000, + "highStressDurationInMillis": 180000, + }, + "bodyBattery": { + "minValue": 31, + "maxValue": 100, + "chargedValue": 72, + "drainedValue": 63, + "latestValue": 40, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-25T02:30:14.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_PREPARATION_RECOVERING_AND_INACTIVE", + "feedbackLongType": "SLEEP_PREPARATION_RECOVERING_AND_INACTIVE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-25T03:30:02.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_RECOVERING_AND_INACTIVE", + "feedbackLongType": "SLEEP_TIME_PASSED_RECOVERING_AND_INACTIVE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-06-24T02:44:40.0", + "eventStartTimeLocal": "2024-06-23T22:44:40.0", + "bodyBatteryImpact": 77, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 30600000, + } + ], + }, + "hydration": {}, + "respiration": { + "avgValue": 14, + "maxValue": 21, + "minValue": 8, + "latestValue": 10, + "latestTimestampGmt": "2024-06-25T04:00:00.0", + }, + "pulseOx": { + "avgValue": 95, + "minValue": 81, + "latestValue": 93, + "latestTimestampGmt": "2024-06-25T04:00:00.0", + "latestTimestampLocal": "2024-06-25T00:00:00.0", + "avgAltitudeInMeters": 31.0, + }, + "jetLag": {}, + }, + { + "uuid": "85f6ead2-7521-41d4-80ff-535281057eac", + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-25", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": true, + "wellnessChronology": { + "startTimestampGmt": "2024-06-25T04:00:00.0", + "startTimestampLocal": "2024-06-25T00:00:00.0", + "endTimestampGmt": "2024-06-26T04:00:00.0", + "endTimestampLocal": "2024-06-26T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 21210, + "value": 26793, + "distanceInMeters": 28291.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 80, + "distanceInMeters": 242.38, + }, + "floorsDescended": { + "value": 84, + "distanceInMeters": 255.96, + }, + }, + "calories": { + "burnedResting": 2228, + "burnedActive": 2013, + "burnedTotal": 4241, + "consumedGoal": 1780, + "consumedValue": 3738, + "consumedRemaining": 503, + }, + "heartRate": { + "minValue": 39, + "maxValue": 153, + "restingValue": 39, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 21, + "vigorous": 122, + }, + "stress": { + "avgLevel": 19, + "maxLevel": 99, + "restProportion": 0.46, + "activityProportion": 0.23, + "uncategorizedProportion": 0.2, + "lowStressProportion": 0.08, + "mediumStressProportion": 0.02, + "highStressProportion": 0.01, + "qualifier": "balanced", + "totalDurationInMillis": 82020000, + "restDurationInMillis": 37440000, + "activityDurationInMillis": 19080000, + "uncategorizedDurationInMillis": 16800000, + "lowStressDurationInMillis": 6300000, + "mediumStressDurationInMillis": 1860000, + "highStressDurationInMillis": 540000, + }, + "bodyBattery": { + "minValue": 24, + "maxValue": 99, + "chargedValue": 79, + "drainedValue": 75, + "latestValue": 44, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-26T02:05:16.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-26T03:30:14.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_TIME_PASSED_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-06-25T03:49:43.0", + "eventStartTimeLocal": "2024-06-24T23:49:43.0", + "bodyBatteryImpact": 62, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 25680000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-06-25T14:59:35.0", + "eventStartTimeLocal": "2024-06-25T10:59:35.0", + "bodyBatteryImpact": -20, + "feedbackType": "EXERCISE_TRAINING_EFFECT_3", + "shortFeedback": "IMPROVING_AEROBIC_ENDURANCE", + "deviceId": 3472661486, + "durationInMillis": 5160000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-06-25T22:18:58.0", + "eventStartTimeLocal": "2024-06-25T18:18:58.0", + "bodyBatteryImpact": -7, + "feedbackType": "EXERCISE_TRAINING_EFFECT_2", + "shortFeedback": "MAINTAINING_ANAEROBIC_FITNESS", + "deviceId": 3472661486, + "durationInMillis": 3420000, + }, + ], + }, + "hydration": { + "goalInMl": 4178, + "goalInFractionalMl": 4178.0, + "consumedInMl": 0, + "consumedInFractionalMl": 0.0, + }, + "respiration": { + "avgValue": 17, + "maxValue": 41, + "minValue": 8, + "latestValue": 20, + "latestTimestampGmt": "2024-06-26T03:59:00.0", + }, + "pulseOx": { + "avgValue": 94, + "minValue": 81, + "latestValue": 98, + "latestTimestampGmt": "2024-06-26T04:00:00.0", + "latestTimestampLocal": "2024-06-26T00:00:00.0", + "avgAltitudeInMeters": 42.0, + }, + "jetLag": {}, + }, + { + "uuid": "d09bc8df-01a5-417d-a21d-0c46f7469cef", + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-26", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": true, + "wellnessChronology": { + "startTimestampGmt": "2024-06-26T04:00:00.0", + "startTimestampLocal": "2024-06-26T00:00:00.0", + "endTimestampGmt": "2024-06-27T04:00:00.0", + "endTimestampLocal": "2024-06-27T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 5000, + "value": 18760, + "distanceInMeters": 18589.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 42, + "distanceInMeters": 128.02, + }, + "floorsDescended": { + "value": 42, + "distanceInMeters": 128.89, + }, + }, + "calories": { + "burnedResting": 2217, + "burnedActive": 1113, + "burnedTotal": 3330, + "consumedGoal": 1780, + "consumedValue": 951, + "consumedRemaining": 2379, + }, + "heartRate": { + "minValue": 37, + "maxValue": 157, + "restingValue": 39, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 38, + "vigorous": 0, + }, + "stress": { + "avgLevel": 21, + "maxLevel": 90, + "restProportion": 0.5, + "activityProportion": 0.15, + "uncategorizedProportion": 0.13, + "lowStressProportion": 0.17, + "mediumStressProportion": 0.04, + "highStressProportion": 0.0, + "qualifier": "balanced", + "totalDurationInMillis": 84840000, + "restDurationInMillis": 42420000, + "activityDurationInMillis": 12960000, + "uncategorizedDurationInMillis": 10740000, + "lowStressDurationInMillis": 14640000, + "mediumStressDurationInMillis": 3720000, + "highStressDurationInMillis": 360000, + }, + "bodyBattery": { + "minValue": 34, + "maxValue": 100, + "chargedValue": 68, + "drainedValue": 66, + "latestValue": 46, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-27T00:05:00.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_PREPARATION_RECOVERING_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_PREPARATION_RECOVERING_AND_INTENSIVE_EXERCISE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-27T03:25:59.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_RECOVERING_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_TIME_PASSED_RECOVERING_AND_INTENSIVE_EXERCISE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-06-26T02:00:04.0", + "eventStartTimeLocal": "2024-06-25T22:00:04.0", + "bodyBatteryImpact": 76, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 30300000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-06-26T15:01:35.0", + "eventStartTimeLocal": "2024-06-26T11:01:35.0", + "bodyBatteryImpact": -12, + "feedbackType": "EXERCISE_TRAINING_EFFECT_3", + "shortFeedback": "IMPROVING_AEROBIC_BASE", + "deviceId": 3472661486, + "durationInMillis": 2460000, + }, + ], + }, + "hydration": { + "goalInMl": 2663, + "goalInFractionalMl": 2663.0, + "consumedInMl": 0, + "consumedInFractionalMl": 0.0, + }, + "respiration": { + "avgValue": 14, + "maxValue": 31, + "minValue": 8, + "latestValue": 9, + "latestTimestampGmt": "2024-06-27T04:00:00.0", + }, + "pulseOx": { + "avgValue": 94, + "minValue": 86, + "latestValue": 96, + "latestTimestampGmt": "2024-06-27T04:00:00.0", + "latestTimestampLocal": "2024-06-27T00:00:00.0", + "avgAltitudeInMeters": 50.0, + }, + "jetLag": {}, + }, + { + "uuid": "b22e425d-709d-44c0-9fea-66a67eb5d9d7", + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-27", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": true, + "wellnessChronology": { + "startTimestampGmt": "2024-06-27T04:00:00.0", + "startTimestampLocal": "2024-06-27T00:00:00.0", + "endTimestampGmt": "2024-06-28T04:00:00.0", + "endTimestampLocal": "2024-06-28T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 5000, + "value": 28104, + "distanceInMeters": 31093.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 69, + "distanceInMeters": 211.56, + }, + "floorsDescended": { + "value": 70, + "distanceInMeters": 214.7, + }, + }, + "calories": { + "burnedResting": 2213, + "burnedActive": 1845, + "burnedTotal": 4058, + "consumedGoal": 1780, + "consumedValue": 3401, + "consumedRemaining": 657, + }, + "heartRate": { + "minValue": 40, + "maxValue": 156, + "restingValue": 41, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 101, + "vigorous": 1, + }, + "stress": { + "avgLevel": 21, + "maxLevel": 97, + "restProportion": 0.51, + "activityProportion": 0.19, + "uncategorizedProportion": 0.16, + "lowStressProportion": 0.1, + "mediumStressProportion": 0.03, + "highStressProportion": 0.01, + "qualifier": "balanced", + "totalDurationInMillis": 84600000, + "restDurationInMillis": 43440000, + "activityDurationInMillis": 15780000, + "uncategorizedDurationInMillis": 13680000, + "lowStressDurationInMillis": 8460000, + "mediumStressDurationInMillis": 2460000, + "highStressDurationInMillis": 780000, + }, + "bodyBattery": { + "minValue": 26, + "maxValue": 98, + "chargedValue": 64, + "drainedValue": 72, + "latestValue": 39, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-28T01:14:49.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-28T03:30:16.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_TIME_PASSED_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-06-27T02:36:39.0", + "eventStartTimeLocal": "2024-06-26T22:36:39.0", + "bodyBatteryImpact": 64, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 29940000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-06-27T18:04:19.0", + "eventStartTimeLocal": "2024-06-27T14:04:19.0", + "bodyBatteryImpact": -21, + "feedbackType": "EXERCISE_TRAINING_EFFECT_4", + "shortFeedback": "HIGHLY_IMPROVING_TEMPO", + "deviceId": 3472661486, + "durationInMillis": 6000000, + }, + ], + }, + "hydration": { + "goalInMl": 3675, + "goalInFractionalMl": 3675.0, + "consumedInMl": 0, + "consumedInFractionalMl": 0.0, + }, + "respiration": { + "avgValue": 17, + "maxValue": 41, + "minValue": 8, + "latestValue": 15, + "latestTimestampGmt": "2024-06-28T04:00:00.0", + }, + "pulseOx": { + "avgValue": 97, + "minValue": 82, + "latestValue": 92, + "latestTimestampGmt": "2024-06-28T04:00:00.0", + "latestTimestampLocal": "2024-06-28T00:00:00.0", + "avgAltitudeInMeters": 36.0, + }, + "jetLag": {}, + }, + { + "uuid": "6b846775-8ed4-4b79-b426-494345d18f8c", + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-28", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": true, + "wellnessChronology": { + "startTimestampGmt": "2024-06-28T04:00:00.0", + "startTimestampLocal": "2024-06-28T00:00:00.0", + "endTimestampGmt": "2024-06-29T04:00:00.0", + "endTimestampLocal": "2024-06-29T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 5000, + "value": 20494, + "distanceInMeters": 20618.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 54, + "distanceInMeters": 164.59, + }, + "floorsDescended": { + "value": 56, + "distanceInMeters": 171.31, + }, + }, + "calories": { + "burnedResting": 2211, + "burnedActive": 978, + "burnedTotal": 3189, + "consumedGoal": 1780, + "consumedValue": 3361, + "consumedRemaining": -172, + }, + "heartRate": { + "minValue": 37, + "maxValue": 157, + "restingValue": 38, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 44, + "vigorous": 1, + }, + "stress": { + "avgLevel": 19, + "maxLevel": 98, + "restProportion": 0.51, + "activityProportion": 0.21, + "uncategorizedProportion": 0.15, + "lowStressProportion": 0.1, + "mediumStressProportion": 0.03, + "highStressProportion": 0.0, + "qualifier": "balanced", + "totalDurationInMillis": 84960000, + "restDurationInMillis": 43560000, + "activityDurationInMillis": 17460000, + "uncategorizedDurationInMillis": 12420000, + "lowStressDurationInMillis": 8400000, + "mediumStressDurationInMillis": 2760000, + "highStressDurationInMillis": 360000, + }, + "bodyBattery": { + "minValue": 34, + "maxValue": 100, + "chargedValue": 72, + "drainedValue": 66, + "latestValue": 45, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-29T02:47:33.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_PREPARATION_RECOVERING_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_PREPARATION_RECOVERING_AND_INTENSIVE_EXERCISE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-29T03:16:23.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_RECOVERING_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_TIME_PASSED_RECOVERING_AND_INTENSIVE_EXERCISE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-06-28T02:31:09.0", + "eventStartTimeLocal": "2024-06-27T22:31:09.0", + "bodyBatteryImpact": 74, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 27900000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-06-28T16:47:11.0", + "eventStartTimeLocal": "2024-06-28T12:47:11.0", + "bodyBatteryImpact": -10, + "feedbackType": "EXERCISE_TRAINING_EFFECT_3", + "shortFeedback": "IMPROVING_AEROBIC_BASE", + "deviceId": 3472661486, + "durationInMillis": 2700000, + }, + ], + }, + "hydration": { + "goalInMl": 2749, + "goalInFractionalMl": 2749.0, + "consumedInMl": 0, + "consumedInFractionalMl": 0.0, + }, + "respiration": { + "avgValue": 15, + "maxValue": 38, + "minValue": 8, + "latestValue": 13, + "latestTimestampGmt": "2024-06-29T04:00:00.0", + }, + "pulseOx": { + "avgValue": 95, + "minValue": 87, + "latestValue": 94, + "latestTimestampGmt": "2024-06-29T04:00:00.0", + "latestTimestampLocal": "2024-06-29T00:00:00.0", + "avgAltitudeInMeters": 36.0, + }, + "jetLag": {}, + }, + { + "uuid": "cb9c43cd-5a2c-4241-b7d7-054e3d67db25", + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-29", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": true, + "wellnessChronology": { + "startTimestampGmt": "2024-06-29T04:00:00.0", + "startTimestampLocal": "2024-06-29T00:00:00.0", + "endTimestampGmt": "2024-06-30T04:00:00.0", + "endTimestampLocal": "2024-06-30T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 5000, + "value": 21108, + "distanceInMeters": 21092.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 47, + "distanceInMeters": 142.43, + }, + "floorsDescended": { + "value": 48, + "distanceInMeters": 145.31, + }, + }, + "calories": { + "burnedResting": 2213, + "burnedActive": 1428, + "burnedTotal": 3641, + "consumedGoal": 1780, + "consumedValue": 413, + "consumedRemaining": 3228, + }, + "heartRate": { + "minValue": 37, + "maxValue": 176, + "restingValue": 37, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 13, + "vigorous": 17, + }, + "stress": { + "avgLevel": 19, + "maxLevel": 97, + "restProportion": 0.52, + "activityProportion": 0.24, + "uncategorizedProportion": 0.12, + "lowStressProportion": 0.08, + "mediumStressProportion": 0.02, + "highStressProportion": 0.02, + "qualifier": "balanced", + "totalDurationInMillis": 83760000, + "restDurationInMillis": 43140000, + "activityDurationInMillis": 20400000, + "uncategorizedDurationInMillis": 10440000, + "lowStressDurationInMillis": 6420000, + "mediumStressDurationInMillis": 2040000, + "highStressDurationInMillis": 1320000, + }, + "bodyBattery": { + "minValue": 30, + "maxValue": 100, + "chargedValue": 68, + "drainedValue": 71, + "latestValue": 42, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-30T00:05:00.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_RACE_COMPLETED", + "feedbackLongType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_RACE_COMPLETED", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-06-30T03:23:29.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_NOT_STRESS_DATA_AND_RACE_COMPLETED", + "feedbackLongType": "SLEEP_TIME_PASSED_NOT_STRESS_DATA_AND_RACE_COMPLETED", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-06-29T02:48:38.0", + "eventStartTimeLocal": "2024-06-28T22:48:38.0", + "bodyBatteryImpact": 63, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 27240000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-06-29T13:29:12.0", + "eventStartTimeLocal": "2024-06-29T09:29:12.0", + "bodyBatteryImpact": -3, + "feedbackType": "EXERCISE_TRAINING_EFFECT_BELOW_2", + "shortFeedback": "EASY_RECOVERY", + "deviceId": 3472661486, + "durationInMillis": 480000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-06-29T14:01:13.0", + "eventStartTimeLocal": "2024-06-29T10:01:13.0", + "bodyBatteryImpact": -8, + "feedbackType": "EXERCISE_TRAINING_EFFECT_3", + "shortFeedback": "IMPROVING_VO2MAX", + "deviceId": 3472661486, + "durationInMillis": 1020000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-06-29T14:33:50.0", + "eventStartTimeLocal": "2024-06-29T10:33:50.0", + "bodyBatteryImpact": -2, + "feedbackType": "EXERCISE_TRAINING_EFFECT_BELOW_2", + "shortFeedback": "EASY_RECOVERY", + "deviceId": 3472661486, + "durationInMillis": 360000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-06-29T17:17:09.0", + "eventStartTimeLocal": "2024-06-29T13:17:09.0", + "bodyBatteryImpact": -4, + "feedbackType": "EXERCISE_TRAINING_EFFECT_BELOW_2", + "shortFeedback": "EASY_AEROBIC_BASE", + "deviceId": 3472661486, + "durationInMillis": 3300000, + }, + { + "eventType": "RECOVERY", + "eventStartTimeGmt": "2024-06-29T18:21:01.0", + "eventStartTimeLocal": "2024-06-29T14:21:01.0", + "bodyBatteryImpact": 1, + "feedbackType": "RECOVERY_SHORT", + "shortFeedback": "BODY_BATTERY_RECHARGE", + "deviceId": 3472661486, + "durationInMillis": 540000, + }, + { + "eventType": "NAP", + "eventStartTimeGmt": "2024-06-29T18:53:28.0", + "eventStartTimeLocal": "2024-06-29T14:53:28.0", + "bodyBatteryImpact": 0, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 3600000, + }, + ], + }, + "hydration": { + "goalInMl": 3181, + "goalInFractionalMl": 3181.0, + "consumedInMl": 0, + "consumedInFractionalMl": 0.0, + }, + "respiration": { + "avgValue": 14, + "maxValue": 43, + "minValue": 8, + "latestValue": 9, + "latestTimestampGmt": "2024-06-30T04:00:00.0", + }, + "pulseOx": { + "avgValue": 94, + "minValue": 84, + "latestValue": 98, + "latestTimestampGmt": "2024-06-30T04:00:00.0", + "latestTimestampLocal": "2024-06-30T00:00:00.0", + "avgAltitudeInMeters": 60.0, + }, + "jetLag": {}, + }, + { + "uuid": "634479ef-635a-4e89-a003-d49130f3e1db", + "userProfilePk": "user_id: int", + "calendarDate": "2024-06-30", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": true, + "wellnessChronology": { + "startTimestampGmt": "2024-06-30T04:00:00.0", + "startTimestampLocal": "2024-06-30T00:00:00.0", + "endTimestampGmt": "2024-07-01T04:00:00.0", + "endTimestampLocal": "2024-07-01T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 5000, + "value": 34199, + "distanceInMeters": 38485.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 43, + "distanceInMeters": 131.38, + }, + "floorsDescended": { + "value": 41, + "distanceInMeters": 125.38, + }, + }, + "calories": { + "burnedResting": 2226, + "burnedActive": 2352, + "burnedTotal": 4578, + "consumedGoal": 1780, + "consumedValue": 4432, + "consumedRemaining": 146, + }, + "heartRate": { + "minValue": 40, + "maxValue": 157, + "restingValue": 42, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 139, + "vigorous": 4, + }, + "stress": { + "avgLevel": 20, + "maxLevel": 98, + "restProportion": 0.54, + "activityProportion": 0.17, + "uncategorizedProportion": 0.19, + "lowStressProportion": 0.07, + "mediumStressProportion": 0.02, + "highStressProportion": 0.01, + "qualifier": "balanced", + "totalDurationInMillis": 84660000, + "restDurationInMillis": 45780000, + "activityDurationInMillis": 14220000, + "uncategorizedDurationInMillis": 16260000, + "lowStressDurationInMillis": 6000000, + "mediumStressDurationInMillis": 1920000, + "highStressDurationInMillis": 480000, + }, + "bodyBattery": { + "minValue": 29, + "maxValue": 89, + "chargedValue": 63, + "drainedValue": 63, + "latestValue": 42, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-07-01T00:05:00.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-07-01T03:30:16.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_TIME_PASSED_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-06-30T02:35:51.0", + "eventStartTimeLocal": "2024-06-29T22:35:51.0", + "bodyBatteryImpact": 59, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 28560000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-06-30T13:57:31.0", + "eventStartTimeLocal": "2024-06-30T09:57:31.0", + "bodyBatteryImpact": -28, + "feedbackType": "EXERCISE_TRAINING_EFFECT_4_GOOD_TIMING", + "shortFeedback": "HIGHLY_IMPROVING_TEMPO", + "deviceId": 3472661486, + "durationInMillis": 8700000, + }, + { + "eventType": "NAP", + "eventStartTimeGmt": "2024-06-30T17:41:52.0", + "eventStartTimeLocal": "2024-06-30T13:41:52.0", + "bodyBatteryImpact": 1, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 3360000, + }, + ], + }, + "hydration": { + "goalInMl": 4301, + "goalInFractionalMl": 4301.0, + "consumedInMl": 0, + "consumedInFractionalMl": 0.0, + }, + "respiration": { + "avgValue": 17, + "maxValue": 38, + "minValue": 8, + "latestValue": 15, + "latestTimestampGmt": "2024-07-01T04:00:00.0", + }, + "pulseOx": { + "avgValue": 95, + "minValue": 82, + "latestValue": 95, + "latestTimestampGmt": "2024-07-01T04:00:00.0", + "latestTimestampLocal": "2024-07-01T00:00:00.0", + "avgAltitudeInMeters": 77.0, + }, + "jetLag": {}, + }, + { + "uuid": "0b8f694c-dac8-439a-be98-7c85e1945d18", + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-01", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": true, + "wellnessChronology": { + "startTimestampGmt": "2024-07-01T04:00:00.0", + "startTimestampLocal": "2024-07-01T00:00:00.0", + "endTimestampGmt": "2024-07-02T04:00:00.0", + "endTimestampLocal": "2024-07-02T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 5000, + "value": 19694, + "distanceInMeters": 20126.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 46, + "distanceInMeters": 139.19, + }, + "floorsDescended": { + "value": 52, + "distanceInMeters": 159.88, + }, + }, + "calories": { + "burnedResting": 2210, + "burnedActive": 961, + "burnedTotal": 3171, + "consumedGoal": 1780, + "consumedValue": 1678, + "consumedRemaining": 1493, + }, + "heartRate": { + "minValue": 36, + "maxValue": 146, + "restingValue": 37, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 42, + "vigorous": 0, + }, + "stress": { + "avgLevel": 16, + "maxLevel": 93, + "restProportion": 0.6, + "activityProportion": 0.2, + "uncategorizedProportion": 0.12, + "lowStressProportion": 0.06, + "mediumStressProportion": 0.02, + "highStressProportion": 0.01, + "qualifier": "balanced", + "totalDurationInMillis": 85620000, + "restDurationInMillis": 51060000, + "activityDurationInMillis": 17340000, + "uncategorizedDurationInMillis": 10140000, + "lowStressDurationInMillis": 5280000, + "mediumStressDurationInMillis": 1320000, + "highStressDurationInMillis": 480000, + }, + "bodyBattery": { + "minValue": 37, + "maxValue": 100, + "chargedValue": 77, + "drainedValue": 65, + "latestValue": 55, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-07-02T02:29:59.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_PREPARATION_RECOVERING_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_PREPARATION_RECOVERING_AND_INTENSIVE_EXERCISE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-07-02T02:57:00.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_RECOVERING_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_TIME_PASSED_RECOVERING_AND_INTENSIVE_EXERCISE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-07-01T02:25:38.0", + "eventStartTimeLocal": "2024-06-30T22:25:38.0", + "bodyBatteryImpact": 69, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 27060000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-07-01T15:06:15.0", + "eventStartTimeLocal": "2024-07-01T11:06:15.0", + "bodyBatteryImpact": -11, + "feedbackType": "EXERCISE_TRAINING_EFFECT_3", + "shortFeedback": "IMPROVING_AEROBIC_BASE", + "deviceId": 3472661486, + "durationInMillis": 2640000, + }, + { + "eventType": "RECOVERY", + "eventStartTimeGmt": "2024-07-01T16:47:52.0", + "eventStartTimeLocal": "2024-07-01T12:47:52.0", + "bodyBatteryImpact": 0, + "feedbackType": "RECOVERY_BODY_BATTERY_NOT_INCREASE", + "shortFeedback": "RESTFUL_PERIOD", + "deviceId": 3472661486, + "durationInMillis": 2280000, + }, + { + "eventType": "NAP", + "eventStartTimeGmt": "2024-07-01T17:59:21.0", + "eventStartTimeLocal": "2024-07-01T13:59:21.0", + "bodyBatteryImpact": 2, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 3300000, + }, + ], + }, + "hydration": { + "goalInMl": 2748, + "goalInFractionalMl": 2748.0, + "consumedInMl": 0, + "consumedInFractionalMl": 0.0, + }, + "respiration": { + "avgValue": 14, + "maxValue": 34, + "minValue": 8, + "latestValue": 9, + "latestTimestampGmt": "2024-07-02T04:00:00.0", + }, + "pulseOx": { + "avgValue": 95, + "minValue": 86, + "latestValue": 96, + "latestTimestampGmt": "2024-07-02T04:00:00.0", + "latestTimestampLocal": "2024-07-02T00:00:00.0", + "avgAltitudeInMeters": 42.0, + }, + "jetLag": {}, + }, + { + "uuid": "c5214e31-5d29-41dd-8a69-543282b04294", + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-02", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": true, + "wellnessChronology": { + "startTimestampGmt": "2024-07-02T04:00:00.0", + "startTimestampLocal": "2024-07-02T00:00:00.0", + "endTimestampGmt": "2024-07-03T04:00:00.0", + "endTimestampLocal": "2024-07-03T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 5000, + "value": 20198, + "distanceInMeters": 21328.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 56, + "distanceInMeters": 169.93, + }, + "floorsDescended": { + "value": 60, + "distanceInMeters": 182.05, + }, + }, + "calories": { + "burnedResting": 2221, + "burnedActive": 1094, + "burnedTotal": 3315, + "consumedGoal": 1780, + "consumedValue": 1303, + "consumedRemaining": 2012, + }, + "heartRate": { + "minValue": 34, + "maxValue": 156, + "restingValue": 37, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 58, + "vigorous": 1, + }, + "stress": { + "avgLevel": 20, + "maxLevel": 99, + "restProportion": 0.54, + "activityProportion": 0.2, + "uncategorizedProportion": 0.15, + "lowStressProportion": 0.08, + "mediumStressProportion": 0.03, + "highStressProportion": 0.01, + "qualifier": "balanced", + "totalDurationInMillis": 85920000, + "restDurationInMillis": 46080000, + "activityDurationInMillis": 16800000, + "uncategorizedDurationInMillis": 12540000, + "lowStressDurationInMillis": 6840000, + "mediumStressDurationInMillis": 2520000, + "highStressDurationInMillis": 1140000, + }, + "bodyBattery": { + "minValue": 31, + "maxValue": 100, + "chargedValue": 50, + "drainedValue": 74, + "latestValue": 31, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-07-03T00:05:00.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-07-03T02:55:33.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_TIME_PASSED_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-07-02T02:00:17.0", + "eventStartTimeLocal": "2024-07-01T22:00:17.0", + "bodyBatteryImpact": 63, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 28500000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-07-02T10:56:49.0", + "eventStartTimeLocal": "2024-07-02T06:56:49.0", + "bodyBatteryImpact": -18, + "feedbackType": "EXERCISE_TRAINING_EFFECT_3", + "shortFeedback": "IMPROVING_AEROBIC_BASE", + "deviceId": 3472661486, + "durationInMillis": 3780000, + }, + { + "eventType": "NAP", + "eventStartTimeGmt": "2024-07-02T16:17:48.0", + "eventStartTimeLocal": "2024-07-02T12:17:48.0", + "bodyBatteryImpact": 3, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 3600000, + }, + { + "eventType": "RECOVERY", + "eventStartTimeGmt": "2024-07-02T20:38:24.0", + "eventStartTimeLocal": "2024-07-02T16:38:24.0", + "bodyBatteryImpact": 2, + "feedbackType": "RECOVERY_BODY_BATTERY_INCREASE", + "shortFeedback": "BODY_BATTERY_RECHARGE", + "deviceId": 3472661486, + "durationInMillis": 1320000, + }, + ], + }, + "hydration": { + "goalInMl": 3048, + "goalInFractionalMl": 3048.0, + "consumedInMl": 0, + "consumedInFractionalMl": 0.0, + }, + "respiration": { + "avgValue": 15, + "maxValue": 38, + "minValue": 8, + "latestValue": 14, + "latestTimestampGmt": "2024-07-03T03:48:00.0", + }, + "pulseOx": { + "avgValue": 95, + "minValue": 84, + "latestValue": 88, + "latestTimestampGmt": "2024-07-03T04:00:00.0", + "latestTimestampLocal": "2024-07-03T00:00:00.0", + "avgAltitudeInMeters": 51.0, + }, + "jetLag": {}, + }, + { + "uuid": "d589d57b-6550-4f8d-8d3e-433d67758a4c", + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-03", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": true, + "wellnessChronology": { + "startTimestampGmt": "2024-07-03T04:00:00.0", + "startTimestampLocal": "2024-07-03T00:00:00.0", + "endTimestampGmt": "2024-07-04T04:00:00.0", + "endTimestampLocal": "2024-07-04T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 5000, + "value": 19844, + "distanceInMeters": 23937.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 16, + "distanceInMeters": 49.33, + }, + "floorsDescended": { + "value": 20, + "distanceInMeters": 62.12, + }, + }, + "calories": { + "burnedResting": 2221, + "burnedActive": 1396, + "burnedTotal": 3617, + "consumedGoal": 1780, + "consumedValue": 0, + "consumedRemaining": 3617, + }, + "heartRate": { + "minValue": 38, + "maxValue": 161, + "restingValue": 39, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 64, + "vigorous": 19, + }, + "stress": { + "avgLevel": 20, + "maxLevel": 90, + "restProportion": 0.56, + "activityProportion": 0.11, + "uncategorizedProportion": 0.17, + "lowStressProportion": 0.13, + "mediumStressProportion": 0.03, + "highStressProportion": 0.01, + "qualifier": "balanced", + "totalDurationInMillis": 86400000, + "restDurationInMillis": 48360000, + "activityDurationInMillis": 9660000, + "uncategorizedDurationInMillis": 14640000, + "lowStressDurationInMillis": 10860000, + "mediumStressDurationInMillis": 2160000, + "highStressDurationInMillis": 720000, + }, + "bodyBattery": { + "minValue": 28, + "maxValue": 94, + "chargedValue": 66, + "drainedValue": 69, + "latestValue": 28, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-07-04T02:51:24.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_PREPARATION_RECOVERING_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_PREPARATION_RECOVERING_AND_INTENSIVE_EXERCISE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-07-04T03:30:18.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_RECOVERING_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_TIME_PASSED_RECOVERING_AND_INTENSIVE_EXERCISE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-07-03T04:28:54.0", + "eventStartTimeLocal": "2024-07-03T00:28:54.0", + "bodyBatteryImpact": 62, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 24360000, + }, + { + "eventType": "RECOVERY", + "eventStartTimeGmt": "2024-07-03T13:44:22.0", + "eventStartTimeLocal": "2024-07-03T09:44:22.0", + "bodyBatteryImpact": -1, + "feedbackType": "RECOVERY_BODY_BATTERY_NOT_INCREASE", + "shortFeedback": "RESTFUL_PERIOD", + "deviceId": 3472661486, + "durationInMillis": 1860000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-07-03T16:01:28.0", + "eventStartTimeLocal": "2024-07-03T12:01:28.0", + "bodyBatteryImpact": -20, + "feedbackType": "EXERCISE_TRAINING_EFFECT_4_GOOD_TIMING", + "shortFeedback": "HIGHLY_IMPROVING_TEMPO", + "deviceId": 3472661486, + "durationInMillis": 4980000, + }, + { + "eventType": "NAP", + "eventStartTimeGmt": "2024-07-03T19:45:08.0", + "eventStartTimeLocal": "2024-07-03T15:45:08.0", + "bodyBatteryImpact": 2, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 2700000, + }, + ], + }, + "hydration": { + "goalInMl": 3385, + "goalInFractionalMl": 3385.0, + "consumedInMl": 0, + "consumedInFractionalMl": 0.0, + }, + "respiration": { + "avgValue": 16, + "maxValue": 40, + "minValue": 9, + "latestValue": 15, + "latestTimestampGmt": "2024-07-04T03:58:00.0", + }, + "pulseOx": { + "avgValue": 95, + "minValue": 84, + "latestValue": 87, + "latestTimestampGmt": "2024-07-04T04:00:00.0", + "latestTimestampLocal": "2024-07-04T00:00:00.0", + "avgAltitudeInMeters": 22.0, + }, + "jetLag": {}, + }, + { + "uuid": "dac513f1-797b-470d-affd-5c13363b62ae", + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-04", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": true, + "wellnessChronology": { + "startTimestampGmt": "2024-07-04T04:00:00.0", + "startTimestampLocal": "2024-07-04T00:00:00.0", + "endTimestampGmt": "2024-07-05T04:00:00.0", + "endTimestampLocal": "2024-07-05T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 5000, + "value": 12624, + "distanceInMeters": 13490.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 23, + "distanceInMeters": 70.26, + }, + "floorsDescended": { + "value": 24, + "distanceInMeters": 72.7, + }, + }, + "calories": { + "burnedResting": 2221, + "burnedActive": 748, + "burnedTotal": 2969, + "consumedGoal": 1780, + "consumedValue": 0, + "consumedRemaining": 2969, + }, + "heartRate": { + "minValue": 41, + "maxValue": 147, + "restingValue": 42, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 39, + "vigorous": 0, + }, + "stress": { + "avgLevel": 26, + "maxLevel": 98, + "restProportion": 0.49, + "activityProportion": 0.13, + "uncategorizedProportion": 0.14, + "lowStressProportion": 0.16, + "mediumStressProportion": 0.07, + "highStressProportion": 0.02, + "qualifier": "balanced", + "totalDurationInMillis": 84480000, + "restDurationInMillis": 41580000, + "activityDurationInMillis": 10920000, + "uncategorizedDurationInMillis": 11880000, + "lowStressDurationInMillis": 13260000, + "mediumStressDurationInMillis": 5520000, + "highStressDurationInMillis": 1320000, + }, + "bodyBattery": { + "minValue": 27, + "maxValue": 88, + "chargedValue": 72, + "drainedValue": 62, + "latestValue": 38, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-07-05T01:51:08.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_PREPARATION_BALANCED_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_PREPARATION_BALANCED_AND_INTENSIVE_EXERCISE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-07-05T03:30:09.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_BALANCED_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_TIME_PASSED_BALANCED_AND_INTENSIVE_EXERCISE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-07-04T04:16:52.0", + "eventStartTimeLocal": "2024-07-04T00:16:52.0", + "bodyBatteryImpact": 59, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 26100000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-07-04T11:45:46.0", + "eventStartTimeLocal": "2024-07-04T07:45:46.0", + "bodyBatteryImpact": -10, + "feedbackType": "EXERCISE_TRAINING_EFFECT_3", + "shortFeedback": "IMPROVING_AEROBIC_BASE", + "deviceId": 3472661486, + "durationInMillis": 2340000, + }, + { + "eventType": "NAP", + "eventStartTimeGmt": "2024-07-04T18:32:50.0", + "eventStartTimeLocal": "2024-07-04T14:32:50.0", + "bodyBatteryImpact": 0, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 1140000, + }, + ], + }, + "hydration": { + "goalInMl": 2652, + "goalInFractionalMl": 2652.0, + "consumedInMl": 0, + "consumedInFractionalMl": 0.0, + }, + "respiration": { + "avgValue": 16, + "maxValue": 36, + "minValue": 8, + "latestValue": 19, + "latestTimestampGmt": "2024-07-05T04:00:00.0", + }, + "pulseOx": { + "avgValue": 96, + "minValue": 88, + "latestValue": 95, + "latestTimestampGmt": "2024-07-05T04:00:00.0", + "latestTimestampLocal": "2024-07-05T00:00:00.0", + "avgAltitudeInMeters": 24.0, + }, + "jetLag": {}, + }, + { + "uuid": "8b7fb813-a275-455a-b797-ae757519afcc", + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-05", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": true, + "wellnessChronology": { + "startTimestampGmt": "2024-07-05T04:00:00.0", + "startTimestampLocal": "2024-07-05T00:00:00.0", + "endTimestampGmt": "2024-07-06T04:00:00.0", + "endTimestampLocal": "2024-07-06T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 5000, + "value": 30555, + "distanceInMeters": 35490.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 14, + "distanceInMeters": 43.3, + }, + "floorsDescended": { + "value": 19, + "distanceInMeters": 57.59, + }, + }, + "calories": { + "burnedResting": 2221, + "burnedActive": 2168, + "burnedTotal": 4389, + "consumedGoal": 1780, + "consumedValue": 0, + "consumedRemaining": 4389, + }, + "heartRate": { + "minValue": 38, + "maxValue": 154, + "restingValue": 40, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 135, + "vigorous": 0, + }, + "stress": { + "avgLevel": 24, + "maxLevel": 93, + "restProportion": 0.49, + "activityProportion": 0.14, + "uncategorizedProportion": 0.18, + "lowStressProportion": 0.1, + "mediumStressProportion": 0.07, + "highStressProportion": 0.02, + "qualifier": "balanced", + "totalDurationInMillis": 84720000, + "restDurationInMillis": 41400000, + "activityDurationInMillis": 11880000, + "uncategorizedDurationInMillis": 15420000, + "lowStressDurationInMillis": 8640000, + "mediumStressDurationInMillis": 5760000, + "highStressDurationInMillis": 1620000, + }, + "bodyBattery": { + "minValue": 32, + "maxValue": 100, + "chargedValue": 66, + "drainedValue": 68, + "latestValue": 36, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-07-06T00:05:00.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_PREPARATION_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-07-06T03:30:04.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_TIME_PASSED_NOT_STRESS_DATA_AND_INTENSIVE_EXERCISE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-07-05T02:30:25.0", + "eventStartTimeLocal": "2024-07-04T22:30:25.0", + "bodyBatteryImpact": 71, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 33480000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-07-05T13:28:26.0", + "eventStartTimeLocal": "2024-07-05T09:28:26.0", + "bodyBatteryImpact": -31, + "feedbackType": "EXERCISE_TRAINING_EFFECT_4_GOOD_TIMING", + "shortFeedback": "HIGHLY_IMPROVING_AEROBIC_ENDURANCE", + "deviceId": 3472661486, + "durationInMillis": 8100000, + }, + { + "eventType": "RECOVERY", + "eventStartTimeGmt": "2024-07-05T21:20:20.0", + "eventStartTimeLocal": "2024-07-05T17:20:20.0", + "bodyBatteryImpact": 0, + "feedbackType": "RECOVERY_BODY_BATTERY_NOT_INCREASE", + "shortFeedback": "RESTFUL_PERIOD", + "deviceId": 3472661486, + "durationInMillis": 1860000, + }, + ], + }, + "hydration": { + "goalInMl": 4230, + "goalInFractionalMl": 4230.0, + "consumedInMl": 0, + "consumedInFractionalMl": 0.0, + }, + "respiration": { + "avgValue": 15, + "maxValue": 38, + "minValue": 9, + "latestValue": 11, + "latestTimestampGmt": "2024-07-06T04:00:00.0", + }, + "pulseOx": { + "avgValue": 95, + "minValue": 84, + "latestValue": 95, + "latestTimestampGmt": "2024-07-06T04:00:00.0", + "latestTimestampLocal": "2024-07-06T00:00:00.0", + "avgAltitudeInMeters": 16.0, + }, + "jetLag": {}, + }, + { + "uuid": "6e054903-7c33-491c-9eac-0ea62ddbcb21", + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-06", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": true, + "wellnessChronology": { + "startTimestampGmt": "2024-07-06T04:00:00.0", + "startTimestampLocal": "2024-07-06T00:00:00.0", + "endTimestampGmt": "2024-07-07T04:00:00.0", + "endTimestampLocal": "2024-07-07T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 5000, + "value": 11886, + "distanceInMeters": 12449.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 15, + "distanceInMeters": 45.72, + }, + "floorsDescended": { + "value": 12, + "distanceInMeters": 36.25, + }, + }, + "calories": { + "burnedResting": 2221, + "burnedActive": 1052, + "burnedTotal": 3273, + "consumedGoal": 1780, + "consumedRemaining": 3273, + }, + "heartRate": { + "minValue": 39, + "maxValue": 145, + "restingValue": 40, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 57, + "vigorous": 0, + }, + "stress": { + "avgLevel": 22, + "maxLevel": 98, + "restProportion": 0.48, + "activityProportion": 0.16, + "uncategorizedProportion": 0.18, + "lowStressProportion": 0.13, + "mediumStressProportion": 0.04, + "highStressProportion": 0.01, + "qualifier": "balanced", + "totalDurationInMillis": 84060000, + "restDurationInMillis": 40200000, + "activityDurationInMillis": 13140000, + "uncategorizedDurationInMillis": 15120000, + "lowStressDurationInMillis": 11220000, + "mediumStressDurationInMillis": 3420000, + "highStressDurationInMillis": 960000, + }, + "bodyBattery": { + "minValue": 32, + "maxValue": 100, + "chargedValue": 69, + "drainedValue": 68, + "latestValue": 37, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-07-07T03:16:23.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_PREPARATION_RECOVERING_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_PREPARATION_RECOVERING_AND_INTENSIVE_EXERCISE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-07-07T03:30:12.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_RECOVERING_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_TIME_PASSED_RECOVERING_AND_INTENSIVE_EXERCISE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-07-06T03:03:35.0", + "eventStartTimeLocal": "2024-07-05T23:03:35.0", + "bodyBatteryImpact": 68, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 30420000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-07-06T12:28:19.0", + "eventStartTimeLocal": "2024-07-06T08:28:19.0", + "bodyBatteryImpact": -10, + "feedbackType": "EXERCISE_TRAINING_EFFECT_2", + "shortFeedback": "MAINTAINING_AEROBIC", + "deviceId": 3472661486, + "durationInMillis": 2100000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-07-06T19:12:08.0", + "eventStartTimeLocal": "2024-07-06T15:12:08.0", + "bodyBatteryImpact": -3, + "feedbackType": "EXERCISE_TRAINING_EFFECT_BELOW_2", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 2160000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-07-06T23:55:27.0", + "eventStartTimeLocal": "2024-07-06T19:55:27.0", + "bodyBatteryImpact": -3, + "feedbackType": "EXERCISE_TRAINING_EFFECT_BELOW_2", + "shortFeedback": "EASY_RECOVERY", + "deviceId": 3472661486, + "durationInMillis": 2820000, + }, + ], + }, + "hydration": { + "goalInMl": 3376, + "goalInFractionalMl": 3376.0, + "consumedInMl": 0, + "consumedInFractionalMl": 0.0, + }, + "respiration": { + "avgValue": 15, + "maxValue": 39, + "minValue": 8, + "latestValue": 10, + "latestTimestampGmt": "2024-07-07T04:00:00.0", + }, + "pulseOx": { + "avgValue": 94, + "minValue": 86, + "latestValue": 94, + "latestTimestampGmt": "2024-07-07T04:00:00.0", + "latestTimestampLocal": "2024-07-07T00:00:00.0", + "avgAltitudeInMeters": 13.0, + }, + "jetLag": {}, + }, + { + "uuid": "f0d9541c-9130-4f5d-aacd-e9c3de3276d4", + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-07", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": true, + "wellnessChronology": { + "startTimestampGmt": "2024-07-07T04:00:00.0", + "startTimestampLocal": "2024-07-07T00:00:00.0", + "endTimestampGmt": "2024-07-08T04:00:00.0", + "endTimestampLocal": "2024-07-08T00:00:00.0", + "totalDurationInMillis": 86400000, + }, + "movement": { + "steps": { + "goal": 5000, + "value": 13815, + "distanceInMeters": 15369.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 13, + "distanceInMeters": 39.62, + }, + "floorsDescended": { + "value": 13, + "distanceInMeters": 39.23, + }, + }, + "calories": { + "burnedResting": 2221, + "burnedActive": 861, + "burnedTotal": 3082, + "consumedGoal": 1780, + "consumedRemaining": 3082, + }, + "heartRate": { + "minValue": 38, + "maxValue": 163, + "restingValue": 39, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 27, + "vigorous": 14, + }, + "stress": { + "avgLevel": 27, + "maxLevel": 90, + "restProportion": 0.47, + "activityProportion": 0.13, + "uncategorizedProportion": 0.12, + "lowStressProportion": 0.18, + "mediumStressProportion": 0.09, + "highStressProportion": 0.01, + "qualifier": "balanced", + "totalDurationInMillis": 84840000, + "restDurationInMillis": 39840000, + "activityDurationInMillis": 10740000, + "uncategorizedDurationInMillis": 10200000, + "lowStressDurationInMillis": 15600000, + "mediumStressDurationInMillis": 7380000, + "highStressDurationInMillis": 1080000, + }, + "bodyBattery": { + "minValue": 29, + "maxValue": 98, + "chargedValue": 74, + "drainedValue": 69, + "latestValue": 42, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-07-08T00:05:01.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_PREPARATION_BALANCED_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_PREPARATION_BALANCED_AND_INTENSIVE_EXERCISE", + }, + "endOfDayDynamicFeedbackEvent": { + "eventTimestampGmt": "2024-07-08T03:30:05.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "SLEEP_TIME_PASSED_BALANCED_AND_INTENSIVE_EXERCISE", + "feedbackLongType": "SLEEP_TIME_PASSED_BALANCED_AND_INTENSIVE_EXERCISE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-07-07T03:30:04.0", + "eventStartTimeLocal": "2024-07-06T23:30:04.0", + "bodyBatteryImpact": 66, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 26100000, + }, + { + "eventType": "ACTIVITY", + "eventStartTimeGmt": "2024-07-07T11:19:09.0", + "eventStartTimeLocal": "2024-07-07T07:19:09.0", + "bodyBatteryImpact": -12, + "feedbackType": "EXERCISE_TRAINING_EFFECT_3", + "shortFeedback": "IMPROVING_LACTATE_THRESHOLD", + "deviceId": 3472661486, + "durationInMillis": 2520000, + }, + ], + }, + "hydration": { + "goalInMl": 2698, + "goalInFractionalMl": 2698.0, + "consumedInMl": 0, + "consumedInFractionalMl": 0.0, + }, + "respiration": { + "avgValue": 16, + "maxValue": 39, + "minValue": 8, + "latestValue": 9, + "latestTimestampGmt": "2024-07-08T04:00:00.0", + }, + "pulseOx": { + "avgValue": 94, + "minValue": 87, + "latestValue": 91, + "latestTimestampGmt": "2024-07-08T04:00:00.0", + "latestTimestampLocal": "2024-07-08T00:00:00.0", + "avgAltitudeInMeters": 52.0, + }, + "jetLag": {}, + }, + { + "uuid": "4afb7589-4a40-42b7-b9d1-7950aa133f81", + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-08", + "source": "garmin", + "includesWellnessData": true, + "includesActivityData": false, + "wellnessChronology": { + "startTimestampGmt": "2024-07-08T04:00:00.0", + "startTimestampLocal": "2024-07-08T00:00:00.0", + "endTimestampGmt": "2024-07-08T15:47:00.0", + "endTimestampLocal": "2024-07-08T11:47:00.0", + "totalDurationInMillis": 42420000, + }, + "movement": { + "steps": { + "goal": 5000, + "value": 5721, + "distanceInMeters": 4818.0, + }, + "pushes": {}, + "floorsAscended": { + "goal": 10, + "value": 6, + "distanceInMeters": 18.29, + }, + "floorsDescended": { + "value": 7, + "distanceInMeters": 20.87, + }, + }, + "calories": { + "burnedResting": 1095, + "burnedActive": 137, + "burnedTotal": 1232, + "consumedGoal": 1780, + "consumedValue": 1980, + "consumedRemaining": -748, + }, + "heartRate": { + "minValue": 38, + "maxValue": 87, + "restingValue": 38, + }, + "intensityMinutes": { + "goal": 150, + "moderate": 0, + "vigorous": 0, + }, + "stress": { + "avgLevel": 19, + "maxLevel": 75, + "restProportion": 0.66, + "activityProportion": 0.15, + "uncategorizedProportion": 0.04, + "lowStressProportion": 0.13, + "mediumStressProportion": 0.02, + "highStressProportion": 0.0, + "qualifier": "unknown", + "totalDurationInMillis": 41460000, + "restDurationInMillis": 27480000, + "activityDurationInMillis": 6180000, + "uncategorizedDurationInMillis": 1560000, + "lowStressDurationInMillis": 5580000, + "mediumStressDurationInMillis": 660000, + }, + "bodyBattery": { + "minValue": 43, + "maxValue": 92, + "chargedValue": 49, + "drainedValue": 26, + "latestValue": 66, + "featureVersion": "3.0", + "dynamicFeedbackEvent": { + "eventTimestampGmt": "2024-07-08T14:22:04.0", + "bodyBatteryLevel": "HIGH", + "feedbackShortType": "DAY_RECOVERING_AND_INACTIVE", + "feedbackLongType": "DAY_RECOVERING_AND_INACTIVE", + }, + "activityEvents": [ + { + "eventType": "SLEEP", + "eventStartTimeGmt": "2024-07-08T01:58:45.0", + "eventStartTimeLocal": "2024-07-07T21:58:45.0", + "bodyBatteryImpact": 63, + "feedbackType": "NONE", + "shortFeedback": "NONE", + "deviceId": 3472661486, + "durationInMillis": 30180000, + } + ], + }, + "hydration": { + "goalInMl": 2000, + "goalInFractionalMl": 2000.0, + "consumedInMl": 0, + "consumedInFractionalMl": 0.0, + }, + "respiration": { + "avgValue": 13, + "maxValue": 20, + "minValue": 8, + "latestValue": 14, + "latestTimestampGmt": "2024-07-08T15:43:00.0", + }, + "pulseOx": { + "avgValue": 96, + "minValue": 89, + "latestValue": 96, + "latestTimestampGmt": "2024-07-08T15:45:00.0", + "latestTimestampLocal": "2024-07-08T11:45:00.0", + "avgAltitudeInMeters": 47.0, + }, + "jetLag": {}, + }, + ] + } + } + }, + }, + { + "query": { + "query": 'query{workoutScheduleSummariesScalar(startDate:"2024-07-08", endDate:"2024-07-09")}' + }, + "response": {"data": {"workoutScheduleSummariesScalar": []}}, + }, + { + "query": { + "query": 'query{trainingPlanScalar(calendarDate:"2024-07-08", lang:"en-US", firstDayOfWeek:"monday")}' + }, + "response": { + "data": { + "trainingPlanScalar": {"trainingPlanWorkoutScheduleDTOS": []} + } + }, + }, + { + "query": { + "query": 'query{\n menstrualCycleDetail(date:"2024-07-08", todayDate:"2024-07-08"){\n daySummary { pregnancyCycle } \n dayLog { calendarDate, symptoms, moods, discharge, hasBabyMovement }\n }\n }' + }, + "response": {"data": {"menstrualCycleDetail": null}}, + }, + { + "query": { + "query": 'query{activityStatsScalar(\n aggregation:"daily",\n startDate:"2024-06-10",\n endDate:"2024-07-08",\n metrics:["duration","distance"],\n activityType:["running","cycling","swimming","walking","multi_sport","fitness_equipment","para_sports"],\n groupByParentActivityType:true,\n standardizedUnits: true)}' + }, + "response": { + "data": { + "activityStatsScalar": [ + { + "date": "2024-06-10", + "countOfActivities": 1, + "stats": { + "running": { + "duration": { + "count": 1, + "min": 2845.68505859375, + "max": 2845.68505859375, + "avg": 2845.68505859375, + "sum": 2845.68505859375, + }, + "distance": { + "count": 1, + "min": 9771.4697265625, + "max": 9771.4697265625, + "avg": 9771.4697265625, + "sum": 9771.4697265625, + }, + }, + "walking": { + "duration": { + "count": 1, + "min": 3926.763916015625, + "max": 3926.763916015625, + "avg": 3926.763916015625, + "sum": 3926.763916015625, + }, + "distance": { + "count": 1, + "min": 3562.929931640625, + "max": 3562.929931640625, + "avg": 3562.929931640625, + "sum": 3562.929931640625, + }, + }, + "fitness_equipment": { + "duration": { + "count": 1, + "min": 2593.52197265625, + "max": 2593.52197265625, + "avg": 2593.52197265625, + "sum": 2593.52197265625, + }, + "distance": { + "count": 1, + "min": 0.0, + "max": 0.0, + "avg": 0.0, + "sum": 0.0, + }, + }, + }, + }, + { + "date": "2024-06-11", + "countOfActivities": 1, + "stats": { + "running": { + "duration": { + "count": 1, + "min": 3711.85693359375, + "max": 3711.85693359375, + "avg": 3711.85693359375, + "sum": 3711.85693359375, + }, + "distance": { + "count": 1, + "min": 14531.3095703125, + "max": 14531.3095703125, + "avg": 14531.3095703125, + "sum": 14531.3095703125, + }, + } + }, + }, + { + "date": "2024-06-12", + "countOfActivities": 1, + "stats": { + "running": { + "duration": { + "count": 1, + "min": 4927.0830078125, + "max": 4927.0830078125, + "avg": 4927.0830078125, + "sum": 4927.0830078125, + }, + "distance": { + "count": 1, + "min": 17479.609375, + "max": 17479.609375, + "avg": 17479.609375, + "sum": 17479.609375, + }, + } + }, + }, + { + "date": "2024-06-13", + "countOfActivities": 1, + "stats": { + "running": { + "duration": { + "count": 1, + "min": 4195.57421875, + "max": 4195.57421875, + "avg": 4195.57421875, + "sum": 4195.57421875, + }, + "distance": { + "count": 1, + "min": 14953.9501953125, + "max": 14953.9501953125, + "avg": 14953.9501953125, + "sum": 14953.9501953125, + }, + } + }, + }, + { + "date": "2024-06-15", + "countOfActivities": 1, + "stats": { + "running": { + "duration": { + "count": 1, + "min": 2906.675048828125, + "max": 2906.675048828125, + "avg": 2906.675048828125, + "sum": 2906.675048828125, + }, + "distance": { + "count": 1, + "min": 10443.400390625, + "max": 10443.400390625, + "avg": 10443.400390625, + "sum": 10443.400390625, + }, + } + }, + }, + { + "date": "2024-06-16", + "countOfActivities": 1, + "stats": { + "running": { + "duration": { + "count": 1, + "min": 3721.305908203125, + "max": 3721.305908203125, + "avg": 3721.305908203125, + "sum": 3721.305908203125, + }, + "distance": { + "count": 1, + "min": 13450.8701171875, + "max": 13450.8701171875, + "avg": 13450.8701171875, + "sum": 13450.8701171875, + }, + } + }, + }, + { + "date": "2024-06-18", + "countOfActivities": 1, + "stats": { + "running": { + "duration": { + "count": 1, + "min": 3197.089111328125, + "max": 3197.089111328125, + "avg": 3197.089111328125, + "sum": 3197.089111328125, + }, + "distance": { + "count": 1, + "min": 11837.3095703125, + "max": 11837.3095703125, + "avg": 11837.3095703125, + "sum": 11837.3095703125, + }, + } + }, + }, + { + "date": "2024-06-19", + "countOfActivities": 1, + "stats": { + "running": { + "duration": { + "count": 1, + "min": 2806.593017578125, + "max": 2806.593017578125, + "avg": 2806.593017578125, + "sum": 2806.593017578125, + }, + "distance": { + "count": 1, + "min": 9942.1103515625, + "max": 9942.1103515625, + "avg": 9942.1103515625, + "sum": 9942.1103515625, + }, + } + }, + }, + { + "date": "2024-06-20", + "countOfActivities": 1, + "stats": { + "running": { + "duration": { + "count": 1, + "min": 3574.9140625, + "max": 3574.9140625, + "avg": 3574.9140625, + "sum": 3574.9140625, + }, + "distance": { + "count": 1, + "min": 12095.3896484375, + "max": 12095.3896484375, + "avg": 12095.3896484375, + "sum": 12095.3896484375, + }, + }, + "fitness_equipment": { + "duration": { + "count": 1, + "min": 4576.27001953125, + "max": 4576.27001953125, + "avg": 4576.27001953125, + "sum": 4576.27001953125, + }, + "distance": { + "count": 1, + "min": 0.0, + "max": 0.0, + "avg": 0.0, + "sum": 0.0, + }, + }, + }, + }, + { + "date": "2024-06-21", + "countOfActivities": 1, + "stats": { + "running": { + "duration": { + "count": 1, + "min": 2835.626953125, + "max": 2835.626953125, + "avg": 2835.626953125, + "sum": 2835.626953125, + }, + "distance": { + "count": 1, + "min": 9723.2001953125, + "max": 9723.2001953125, + "avg": 9723.2001953125, + "sum": 9723.2001953125, + }, + } + }, + }, + { + "date": "2024-06-22", + "countOfActivities": 1, + "stats": { + "running": { + "duration": { + "count": 1, + "min": 8684.939453125, + "max": 8684.939453125, + "avg": 8684.939453125, + "sum": 8684.939453125, + }, + "distance": { + "count": 1, + "min": 32826.390625, + "max": 32826.390625, + "avg": 32826.390625, + "sum": 32826.390625, + }, + } + }, + }, + { + "date": "2024-06-23", + "countOfActivities": 1, + "stats": { + "running": { + "duration": { + "count": 1, + "min": 3077.04296875, + "max": 3077.04296875, + "avg": 3077.04296875, + "sum": 3077.04296875, + }, + "distance": { + "count": 1, + "min": 10503.599609375, + "max": 10503.599609375, + "avg": 10503.599609375, + "sum": 10503.599609375, + }, + } + }, + }, + { + "date": "2024-06-25", + "countOfActivities": 1, + "stats": { + "running": { + "duration": { + "count": 1, + "min": 5137.69384765625, + "max": 5137.69384765625, + "avg": 5137.69384765625, + "sum": 5137.69384765625, + }, + "distance": { + "count": 1, + "min": 17729.759765625, + "max": 17729.759765625, + "avg": 17729.759765625, + "sum": 17729.759765625, + }, + }, + "fitness_equipment": { + "duration": { + "count": 1, + "min": 3424.47705078125, + "max": 3424.47705078125, + "avg": 3424.47705078125, + "sum": 3424.47705078125, + }, + "distance": { + "count": 1, + "min": 0.0, + "max": 0.0, + "avg": 0.0, + "sum": 0.0, + }, + }, + }, + }, + { + "date": "2024-06-26", + "countOfActivities": 1, + "stats": { + "running": { + "duration": { + "count": 1, + "min": 2388.825927734375, + "max": 2388.825927734375, + "avg": 2388.825927734375, + "sum": 2388.825927734375, + }, + "distance": { + "count": 1, + "min": 8279.1103515625, + "max": 8279.1103515625, + "avg": 8279.1103515625, + "sum": 8279.1103515625, + }, + } + }, + }, + { + "date": "2024-06-27", + "countOfActivities": 1, + "stats": { + "running": { + "duration": { + "count": 1, + "min": 6033.0078125, + "max": 6033.0078125, + "avg": 6033.0078125, + "sum": 6033.0078125, + }, + "distance": { + "count": 1, + "min": 21711.5390625, + "max": 21711.5390625, + "avg": 21711.5390625, + "sum": 21711.5390625, + }, + } + }, + }, + { + "date": "2024-06-28", + "countOfActivities": 1, + "stats": { + "running": { + "duration": { + "count": 1, + "min": 2700.639892578125, + "max": 2700.639892578125, + "avg": 2700.639892578125, + "sum": 2700.639892578125, + }, + "distance": { + "count": 1, + "min": 9678.0703125, + "max": 9678.0703125, + "avg": 9678.0703125, + "sum": 9678.0703125, + }, + } + }, + }, + { + "date": "2024-06-29", + "countOfActivities": 1, + "stats": { + "running": { + "duration": { + "count": 3, + "min": 379.8340148925781, + "max": 1066.72802734375, + "avg": 655.4540100097656, + "sum": 1966.3620300292969, + }, + "distance": { + "count": 3, + "min": 1338.8199462890625, + "max": 4998.83984375, + "avg": 2704.4499104817705, + "sum": 8113.3497314453125, + }, + }, + "fitness_equipment": { + "duration": { + "count": 1, + "min": 3340.532958984375, + "max": 3340.532958984375, + "avg": 3340.532958984375, + "sum": 3340.532958984375, + }, + "distance": { + "count": 1, + "min": 0.0, + "max": 0.0, + "avg": 0.0, + "sum": 0.0, + }, + }, + }, + }, + { + "date": "2024-06-30", + "countOfActivities": 1, + "stats": { + "running": { + "duration": { + "count": 1, + "min": 8286.94140625, + "max": 8286.94140625, + "avg": 8286.94140625, + "sum": 8286.94140625, + }, + "distance": { + "count": 1, + "min": 29314.099609375, + "max": 29314.099609375, + "avg": 29314.099609375, + "sum": 29314.099609375, + }, + } + }, + }, + { + "date": "2024-07-01", + "countOfActivities": 1, + "stats": { + "running": { + "duration": { + "count": 1, + "min": 2693.840087890625, + "max": 2693.840087890625, + "avg": 2693.840087890625, + "sum": 2693.840087890625, + }, + "distance": { + "count": 1, + "min": 9801.0595703125, + "max": 9801.0595703125, + "avg": 9801.0595703125, + "sum": 9801.0595703125, + }, + } + }, + }, + { + "date": "2024-07-02", + "countOfActivities": 1, + "stats": { + "running": { + "duration": { + "count": 1, + "min": 3777.14892578125, + "max": 3777.14892578125, + "avg": 3777.14892578125, + "sum": 3777.14892578125, + }, + "distance": { + "count": 1, + "min": 12951.5302734375, + "max": 12951.5302734375, + "avg": 12951.5302734375, + "sum": 12951.5302734375, + }, + } + }, + }, + { + "date": "2024-07-03", + "countOfActivities": 1, + "stats": { + "running": { + "duration": { + "count": 1, + "min": 4990.2158203125, + "max": 4990.2158203125, + "avg": 4990.2158203125, + "sum": 4990.2158203125, + }, + "distance": { + "count": 1, + "min": 19324.55078125, + "max": 19324.55078125, + "avg": 19324.55078125, + "sum": 19324.55078125, + }, + } + }, + }, + { + "date": "2024-07-04", + "countOfActivities": 1, + "stats": { + "running": { + "duration": { + "count": 1, + "min": 2351.343017578125, + "max": 2351.343017578125, + "avg": 2351.343017578125, + "sum": 2351.343017578125, + }, + "distance": { + "count": 1, + "min": 8373.5498046875, + "max": 8373.5498046875, + "avg": 8373.5498046875, + "sum": 8373.5498046875, + }, + } + }, + }, + { + "date": "2024-07-05", + "countOfActivities": 1, + "stats": { + "running": { + "duration": { + "count": 1, + "min": 8030.9619140625, + "max": 8030.9619140625, + "avg": 8030.9619140625, + "sum": 8030.9619140625, + }, + "distance": { + "count": 1, + "min": 28973.609375, + "max": 28973.609375, + "avg": 28973.609375, + "sum": 28973.609375, + }, + } + }, + }, + { + "date": "2024-07-06", + "countOfActivities": 1, + "stats": { + "running": { + "duration": { + "count": 1, + "min": 2123.346923828125, + "max": 2123.346923828125, + "avg": 2123.346923828125, + "sum": 2123.346923828125, + }, + "distance": { + "count": 1, + "min": 7408.22998046875, + "max": 7408.22998046875, + "avg": 7408.22998046875, + "sum": 7408.22998046875, + }, + }, + "cycling": { + "duration": { + "count": 1, + "min": 2853.280029296875, + "max": 2853.280029296875, + "avg": 2853.280029296875, + "sum": 2853.280029296875, + }, + "distance": { + "count": 1, + "min": 15816.48046875, + "max": 15816.48046875, + "avg": 15816.48046875, + "sum": 15816.48046875, + }, + }, + }, + }, + { + "date": "2024-07-07", + "countOfActivities": 1, + "stats": { + "running": { + "duration": { + "count": 1, + "min": 2516.8779296875, + "max": 2516.8779296875, + "avg": 2516.8779296875, + "sum": 2516.8779296875, + }, + "distance": { + "count": 1, + "min": 9866.7802734375, + "max": 9866.7802734375, + "avg": 9866.7802734375, + "sum": 9866.7802734375, + }, + } + }, + }, + ] + } + }, + }, + { + "query": { + "query": 'query{activityStatsScalar(\n aggregation:"daily",\n startDate:"2024-06-10",\n endDate:"2024-07-08",\n metrics:["duration","distance"],\n groupByParentActivityType:false,\n standardizedUnits: true)}' + }, + "response": { + "data": { + "activityStatsScalar": [ + { + "date": "2024-06-10", + "countOfActivities": 3, + "stats": { + "all": { + "duration": { + "count": 3, + "min": 2593.52197265625, + "max": 3926.763916015625, + "avg": 3121.9903157552085, + "sum": 9365.970947265625, + }, + "distance": { + "count": 3, + "min": 0.0, + "max": 9771.4697265625, + "avg": 4444.799886067708, + "sum": 13334.399658203125, + }, + } + }, + }, + { + "date": "2024-06-11", + "countOfActivities": 1, + "stats": { + "all": { + "duration": { + "count": 1, + "min": 3711.85693359375, + "max": 3711.85693359375, + "avg": 3711.85693359375, + "sum": 3711.85693359375, + }, + "distance": { + "count": 1, + "min": 14531.3095703125, + "max": 14531.3095703125, + "avg": 14531.3095703125, + "sum": 14531.3095703125, + }, + } + }, + }, + { + "date": "2024-06-12", + "countOfActivities": 1, + "stats": { + "all": { + "duration": { + "count": 1, + "min": 4927.0830078125, + "max": 4927.0830078125, + "avg": 4927.0830078125, + "sum": 4927.0830078125, + }, + "distance": { + "count": 1, + "min": 17479.609375, + "max": 17479.609375, + "avg": 17479.609375, + "sum": 17479.609375, + }, + } + }, + }, + { + "date": "2024-06-13", + "countOfActivities": 1, + "stats": { + "all": { + "duration": { + "count": 1, + "min": 4195.57421875, + "max": 4195.57421875, + "avg": 4195.57421875, + "sum": 4195.57421875, + }, + "distance": { + "count": 1, + "min": 14953.9501953125, + "max": 14953.9501953125, + "avg": 14953.9501953125, + "sum": 14953.9501953125, + }, + } + }, + }, + { + "date": "2024-06-15", + "countOfActivities": 1, + "stats": { + "all": { + "duration": { + "count": 1, + "min": 2906.675048828125, + "max": 2906.675048828125, + "avg": 2906.675048828125, + "sum": 2906.675048828125, + }, + "distance": { + "count": 1, + "min": 10443.400390625, + "max": 10443.400390625, + "avg": 10443.400390625, + "sum": 10443.400390625, + }, + } + }, + }, + { + "date": "2024-06-16", + "countOfActivities": 1, + "stats": { + "all": { + "duration": { + "count": 1, + "min": 3721.305908203125, + "max": 3721.305908203125, + "avg": 3721.305908203125, + "sum": 3721.305908203125, + }, + "distance": { + "count": 1, + "min": 13450.8701171875, + "max": 13450.8701171875, + "avg": 13450.8701171875, + "sum": 13450.8701171875, + }, + } + }, + }, + { + "date": "2024-06-18", + "countOfActivities": 1, + "stats": { + "all": { + "duration": { + "count": 1, + "min": 3197.089111328125, + "max": 3197.089111328125, + "avg": 3197.089111328125, + "sum": 3197.089111328125, + }, + "distance": { + "count": 1, + "min": 11837.3095703125, + "max": 11837.3095703125, + "avg": 11837.3095703125, + "sum": 11837.3095703125, + }, + } + }, + }, + { + "date": "2024-06-19", + "countOfActivities": 1, + "stats": { + "all": { + "duration": { + "count": 1, + "min": 2806.593017578125, + "max": 2806.593017578125, + "avg": 2806.593017578125, + "sum": 2806.593017578125, + }, + "distance": { + "count": 1, + "min": 9942.1103515625, + "max": 9942.1103515625, + "avg": 9942.1103515625, + "sum": 9942.1103515625, + }, + } + }, + }, + { + "date": "2024-06-20", + "countOfActivities": 2, + "stats": { + "all": { + "duration": { + "count": 2, + "min": 3574.9140625, + "max": 4576.27001953125, + "avg": 4075.592041015625, + "sum": 8151.18408203125, + }, + "distance": { + "count": 2, + "min": 0.0, + "max": 12095.3896484375, + "avg": 6047.69482421875, + "sum": 12095.3896484375, + }, + } + }, + }, + { + "date": "2024-06-21", + "countOfActivities": 1, + "stats": { + "all": { + "duration": { + "count": 1, + "min": 2835.626953125, + "max": 2835.626953125, + "avg": 2835.626953125, + "sum": 2835.626953125, + }, + "distance": { + "count": 1, + "min": 9723.2001953125, + "max": 9723.2001953125, + "avg": 9723.2001953125, + "sum": 9723.2001953125, + }, + } + }, + }, + { + "date": "2024-06-22", + "countOfActivities": 1, + "stats": { + "all": { + "duration": { + "count": 1, + "min": 8684.939453125, + "max": 8684.939453125, + "avg": 8684.939453125, + "sum": 8684.939453125, + }, + "distance": { + "count": 1, + "min": 32826.390625, + "max": 32826.390625, + "avg": 32826.390625, + "sum": 32826.390625, + }, + } + }, + }, + { + "date": "2024-06-23", + "countOfActivities": 2, + "stats": { + "all": { + "duration": { + "count": 2, + "min": 3077.04296875, + "max": 6026.98193359375, + "avg": 4552.012451171875, + "sum": 9104.02490234375, + }, + "distance": { + "count": 2, + "min": 10503.599609375, + "max": 12635.1796875, + "avg": 11569.3896484375, + "sum": 23138.779296875, + }, + } + }, + }, + { + "date": "2024-06-25", + "countOfActivities": 2, + "stats": { + "all": { + "duration": { + "count": 2, + "min": 3424.47705078125, + "max": 5137.69384765625, + "avg": 4281.08544921875, + "sum": 8562.1708984375, + }, + "distance": { + "count": 2, + "min": 0.0, + "max": 17729.759765625, + "avg": 8864.8798828125, + "sum": 17729.759765625, + }, + } + }, + }, + { + "date": "2024-06-26", + "countOfActivities": 1, + "stats": { + "all": { + "duration": { + "count": 1, + "min": 2388.825927734375, + "max": 2388.825927734375, + "avg": 2388.825927734375, + "sum": 2388.825927734375, + }, + "distance": { + "count": 1, + "min": 8279.1103515625, + "max": 8279.1103515625, + "avg": 8279.1103515625, + "sum": 8279.1103515625, + }, + } + }, + }, + { + "date": "2024-06-27", + "countOfActivities": 1, + "stats": { + "all": { + "duration": { + "count": 1, + "min": 6033.0078125, + "max": 6033.0078125, + "avg": 6033.0078125, + "sum": 6033.0078125, + }, + "distance": { + "count": 1, + "min": 21711.5390625, + "max": 21711.5390625, + "avg": 21711.5390625, + "sum": 21711.5390625, + }, + } + }, + }, + { + "date": "2024-06-28", + "countOfActivities": 1, + "stats": { + "all": { + "duration": { + "count": 1, + "min": 2700.639892578125, + "max": 2700.639892578125, + "avg": 2700.639892578125, + "sum": 2700.639892578125, + }, + "distance": { + "count": 1, + "min": 9678.0703125, + "max": 9678.0703125, + "avg": 9678.0703125, + "sum": 9678.0703125, + }, + } + }, + }, + { + "date": "2024-06-29", + "countOfActivities": 4, + "stats": { + "all": { + "duration": { + "count": 4, + "min": 379.8340148925781, + "max": 3340.532958984375, + "avg": 1326.723747253418, + "sum": 5306.894989013672, + }, + "distance": { + "count": 4, + "min": 0.0, + "max": 4998.83984375, + "avg": 2028.3374328613281, + "sum": 8113.3497314453125, + }, + } + }, + }, + { + "date": "2024-06-30", + "countOfActivities": 1, + "stats": { + "all": { + "duration": { + "count": 1, + "min": 8286.94140625, + "max": 8286.94140625, + "avg": 8286.94140625, + "sum": 8286.94140625, + }, + "distance": { + "count": 1, + "min": 29314.099609375, + "max": 29314.099609375, + "avg": 29314.099609375, + "sum": 29314.099609375, + }, + } + }, + }, + { + "date": "2024-07-01", + "countOfActivities": 1, + "stats": { + "all": { + "duration": { + "count": 1, + "min": 2693.840087890625, + "max": 2693.840087890625, + "avg": 2693.840087890625, + "sum": 2693.840087890625, + }, + "distance": { + "count": 1, + "min": 9801.0595703125, + "max": 9801.0595703125, + "avg": 9801.0595703125, + "sum": 9801.0595703125, + }, + } + }, + }, + { + "date": "2024-07-02", + "countOfActivities": 1, + "stats": { + "all": { + "duration": { + "count": 1, + "min": 3777.14892578125, + "max": 3777.14892578125, + "avg": 3777.14892578125, + "sum": 3777.14892578125, + }, + "distance": { + "count": 1, + "min": 12951.5302734375, + "max": 12951.5302734375, + "avg": 12951.5302734375, + "sum": 12951.5302734375, + }, + } + }, + }, + { + "date": "2024-07-03", + "countOfActivities": 1, + "stats": { + "all": { + "duration": { + "count": 1, + "min": 4990.2158203125, + "max": 4990.2158203125, + "avg": 4990.2158203125, + "sum": 4990.2158203125, + }, + "distance": { + "count": 1, + "min": 19324.55078125, + "max": 19324.55078125, + "avg": 19324.55078125, + "sum": 19324.55078125, + }, + } + }, + }, + { + "date": "2024-07-04", + "countOfActivities": 1, + "stats": { + "all": { + "duration": { + "count": 1, + "min": 2351.343017578125, + "max": 2351.343017578125, + "avg": 2351.343017578125, + "sum": 2351.343017578125, + }, + "distance": { + "count": 1, + "min": 8373.5498046875, + "max": 8373.5498046875, + "avg": 8373.5498046875, + "sum": 8373.5498046875, + }, + } + }, + }, + { + "date": "2024-07-05", + "countOfActivities": 1, + "stats": { + "all": { + "duration": { + "count": 1, + "min": 8030.9619140625, + "max": 8030.9619140625, + "avg": 8030.9619140625, + "sum": 8030.9619140625, + }, + "distance": { + "count": 1, + "min": 28973.609375, + "max": 28973.609375, + "avg": 28973.609375, + "sum": 28973.609375, + }, + } + }, + }, + { + "date": "2024-07-06", + "countOfActivities": 3, + "stats": { + "all": { + "duration": { + "count": 3, + "min": 2123.346923828125, + "max": 2853.280029296875, + "avg": 2391.8193359375, + "sum": 7175.4580078125, + }, + "distance": { + "count": 3, + "min": 2285.330078125, + "max": 15816.48046875, + "avg": 8503.346842447916, + "sum": 25510.04052734375, + }, + } + }, + }, + { + "date": "2024-07-07", + "countOfActivities": 1, + "stats": { + "all": { + "duration": { + "count": 1, + "min": 2516.8779296875, + "max": 2516.8779296875, + "avg": 2516.8779296875, + "sum": 2516.8779296875, + }, + "distance": { + "count": 1, + "min": 9866.7802734375, + "max": 9866.7802734375, + "avg": 9866.7802734375, + "sum": 9866.7802734375, + }, + } + }, + }, + ] + } + }, + }, + { + "query": { + "query": 'query{sleepScalar(date:"2024-07-08", sleepOnly: false)}' + }, + "response": { + "data": { + "sleepScalar": { + "dailySleepDTO": { + "id": 1720403925000, + "userProfilePK": "user_id: int", + "calendarDate": "2024-07-08", + "sleepTimeSeconds": 29580, + "napTimeSeconds": 0, + "sleepWindowConfirmed": true, + "sleepWindowConfirmationType": "enhanced_confirmed_final", + "sleepStartTimestampGMT": 1720403925000, + "sleepEndTimestampGMT": 1720434105000, + "sleepStartTimestampLocal": 1720389525000, + "sleepEndTimestampLocal": 1720419705000, + "autoSleepStartTimestampGMT": null, + "autoSleepEndTimestampGMT": null, + "sleepQualityTypePK": null, + "sleepResultTypePK": null, + "unmeasurableSleepSeconds": 0, + "deepSleepSeconds": 6360, + "lightSleepSeconds": 16260, + "remSleepSeconds": 6960, + "awakeSleepSeconds": 600, + "deviceRemCapable": true, + "retro": false, + "sleepFromDevice": true, + "averageSpO2Value": 95.0, + "lowestSpO2Value": 89, + "highestSpO2Value": 100, + "averageSpO2HRSleep": 42.0, + "averageRespirationValue": 14.0, + "lowestRespirationValue": 8.0, + "highestRespirationValue": 21.0, + "awakeCount": 1, + "avgSleepStress": 20.0, + "ageGroup": "ADULT", + "sleepScoreFeedback": "POSITIVE_LONG_AND_DEEP", + "sleepScoreInsight": "NONE", + "sleepScorePersonalizedInsight": "NOT_AVAILABLE", + "sleepScores": { + "totalDuration": { + "qualifierKey": "EXCELLENT", + "optimalStart": 28800.0, + "optimalEnd": 28800.0, + }, + "stress": { + "qualifierKey": "FAIR", + "optimalStart": 0.0, + "optimalEnd": 15.0, + }, + "awakeCount": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 1.0, + }, + "overall": {"value": 89, "qualifierKey": "GOOD"}, + "remPercentage": { + "value": 24, + "qualifierKey": "EXCELLENT", + "optimalStart": 21.0, + "optimalEnd": 31.0, + "idealStartInSeconds": 6211.8, + "idealEndInSeconds": 9169.8, + }, + "restlessness": { + "qualifierKey": "EXCELLENT", + "optimalStart": 0.0, + "optimalEnd": 5.0, + }, + "lightPercentage": { + "value": 55, + "qualifierKey": "EXCELLENT", + "optimalStart": 30.0, + "optimalEnd": 64.0, + "idealStartInSeconds": 8874.0, + "idealEndInSeconds": 18931.2, + }, + "deepPercentage": { + "value": 22, + "qualifierKey": "EXCELLENT", + "optimalStart": 16.0, + "optimalEnd": 33.0, + "idealStartInSeconds": 4732.8, + "idealEndInSeconds": 9761.4, + }, + }, + "sleepVersion": 2, + "sleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-08", + "deviceId": 3472661486, + "timestampGmt": "2024-07-07T12:03:49", + "baseline": 480, + "actual": 500, + "feedback": "INCREASED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "NO_CHANGE", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": true, + "preferredActivityTracker": true, + }, + "nextSleepNeed": { + "userProfilePk": "user_id: int", + "calendarDate": "2024-07-09", + "deviceId": 3472661486, + "timestampGmt": "2024-07-08T13:33:50", + "baseline": 480, + "actual": 480, + "feedback": "NO_CHANGE_BALANCED", + "trainingFeedback": "CHRONIC", + "sleepHistoryAdjustment": "DECREASING_HIGH_QUALITY", + "hrvAdjustment": "NO_CHANGE", + "napAdjustment": "NO_CHANGE", + "displayedForTheDay": false, + "preferredActivityTracker": true, + }, + }, + "sleepMovement": [ + { + "startGMT": "2024-07-08T00:58:00.0", + "endGMT": "2024-07-08T00:59:00.0", + "activityLevel": 5.950187900954773, + }, + { + "startGMT": "2024-07-08T00:59:00.0", + "endGMT": "2024-07-08T01:00:00.0", + "activityLevel": 5.6630425762949645, + }, + { + "startGMT": "2024-07-08T01:00:00.0", + "endGMT": "2024-07-08T01:01:00.0", + "activityLevel": 5.422739096659621, + }, + { + "startGMT": "2024-07-08T01:01:00.0", + "endGMT": "2024-07-08T01:02:00.0", + "activityLevel": 5.251316003495859, + }, + { + "startGMT": "2024-07-08T01:02:00.0", + "endGMT": "2024-07-08T01:03:00.0", + "activityLevel": 5.166378219824125, + }, + { + "startGMT": "2024-07-08T01:03:00.0", + "endGMT": "2024-07-08T01:04:00.0", + "activityLevel": 5.176831912428479, + }, + { + "startGMT": "2024-07-08T01:04:00.0", + "endGMT": "2024-07-08T01:05:00.0", + "activityLevel": 5.280364670798585, + }, + { + "startGMT": "2024-07-08T01:05:00.0", + "endGMT": "2024-07-08T01:06:00.0", + "activityLevel": 5.467423966676771, + }, + { + "startGMT": "2024-07-08T01:06:00.0", + "endGMT": "2024-07-08T01:07:00.0", + "activityLevel": 5.707501653783791, + }, + { + "startGMT": "2024-07-08T01:07:00.0", + "endGMT": "2024-07-08T01:08:00.0", + "activityLevel": 5.98610568657474, + }, + { + "startGMT": "2024-07-08T01:08:00.0", + "endGMT": "2024-07-08T01:09:00.0", + "activityLevel": 6.271329168295636, + }, + { + "startGMT": "2024-07-08T01:09:00.0", + "endGMT": "2024-07-08T01:10:00.0", + "activityLevel": 6.542904534717018, + }, + { + "startGMT": "2024-07-08T01:10:00.0", + "endGMT": "2024-07-08T01:11:00.0", + "activityLevel": 6.783019710668306, + }, + { + "startGMT": "2024-07-08T01:11:00.0", + "endGMT": "2024-07-08T01:12:00.0", + "activityLevel": 6.977938839949864, + }, + { + "startGMT": "2024-07-08T01:12:00.0", + "endGMT": "2024-07-08T01:13:00.0", + "activityLevel": 7.117872615089607, + }, + { + "startGMT": "2024-07-08T01:13:00.0", + "endGMT": "2024-07-08T01:14:00.0", + "activityLevel": 7.192558858020865, + }, + { + "startGMT": "2024-07-08T01:14:00.0", + "endGMT": "2024-07-08T01:15:00.0", + "activityLevel": 7.2017123514939305, + }, + { + "startGMT": "2024-07-08T01:15:00.0", + "endGMT": "2024-07-08T01:16:00.0", + "activityLevel": 7.154542063772914, + }, + { + "startGMT": "2024-07-08T01:16:00.0", + "endGMT": "2024-07-08T01:17:00.0", + "activityLevel": 7.049364449097269, + }, + { + "startGMT": "2024-07-08T01:17:00.0", + "endGMT": "2024-07-08T01:18:00.0", + "activityLevel": 6.898245332898234, + }, + { + "startGMT": "2024-07-08T01:18:00.0", + "endGMT": "2024-07-08T01:19:00.0", + "activityLevel": 6.713207432023164, + }, + { + "startGMT": "2024-07-08T01:19:00.0", + "endGMT": "2024-07-08T01:20:00.0", + "activityLevel": 6.512140450991122, + }, + { + "startGMT": "2024-07-08T01:20:00.0", + "endGMT": "2024-07-08T01:21:00.0", + "activityLevel": 6.307503482446506, + }, + { + "startGMT": "2024-07-08T01:21:00.0", + "endGMT": "2024-07-08T01:22:00.0", + "activityLevel": 6.117088515503814, + }, + { + "startGMT": "2024-07-08T01:22:00.0", + "endGMT": "2024-07-08T01:23:00.0", + "activityLevel": 5.947438672664253, + }, + { + "startGMT": "2024-07-08T01:23:00.0", + "endGMT": "2024-07-08T01:24:00.0", + "activityLevel": 5.801580596048765, + }, + { + "startGMT": "2024-07-08T01:24:00.0", + "endGMT": "2024-07-08T01:25:00.0", + "activityLevel": 5.687383310059647, + }, + { + "startGMT": "2024-07-08T01:25:00.0", + "endGMT": "2024-07-08T01:26:00.0", + "activityLevel": 5.607473140911092, + }, + { + "startGMT": "2024-07-08T01:26:00.0", + "endGMT": "2024-07-08T01:27:00.0", + "activityLevel": 5.550376997982641, + }, + { + "startGMT": "2024-07-08T01:27:00.0", + "endGMT": "2024-07-08T01:28:00.0", + "activityLevel": 5.504002553323602, + }, + { + "startGMT": "2024-07-08T01:28:00.0", + "endGMT": "2024-07-08T01:29:00.0", + "activityLevel": 5.454741498776686, + }, + { + "startGMT": "2024-07-08T01:29:00.0", + "endGMT": "2024-07-08T01:30:00.0", + "activityLevel": 5.389279086311523, + }, + { + "startGMT": "2024-07-08T01:30:00.0", + "endGMT": "2024-07-08T01:31:00.0", + "activityLevel": 5.296350273791964, + }, + { + "startGMT": "2024-07-08T01:31:00.0", + "endGMT": "2024-07-08T01:32:00.0", + "activityLevel": 5.166266682100087, + }, + { + "startGMT": "2024-07-08T01:32:00.0", + "endGMT": "2024-07-08T01:33:00.0", + "activityLevel": 4.994160322824111, + }, + { + "startGMT": "2024-07-08T01:33:00.0", + "endGMT": "2024-07-08T01:34:00.0", + "activityLevel": 4.777398813781819, + }, + { + "startGMT": "2024-07-08T01:34:00.0", + "endGMT": "2024-07-08T01:35:00.0", + "activityLevel": 4.5118027801978915, + }, + { + "startGMT": "2024-07-08T01:35:00.0", + "endGMT": "2024-07-08T01:36:00.0", + "activityLevel": 4.212847971803436, + }, + { + "startGMT": "2024-07-08T01:36:00.0", + "endGMT": "2024-07-08T01:37:00.0", + "activityLevel": 3.8745757238098144, + }, + { + "startGMT": "2024-07-08T01:37:00.0", + "endGMT": "2024-07-08T01:38:00.0", + "activityLevel": 3.5150258390645144, + }, + { + "startGMT": "2024-07-08T01:38:00.0", + "endGMT": "2024-07-08T01:39:00.0", + "activityLevel": 3.1470510566095293, + }, + { + "startGMT": "2024-07-08T01:39:00.0", + "endGMT": "2024-07-08T01:40:00.0", + "activityLevel": 2.782578793979288, + }, + { + "startGMT": "2024-07-08T01:40:00.0", + "endGMT": "2024-07-08T01:41:00.0", + "activityLevel": 2.4350545122931098, + }, + { + "startGMT": "2024-07-08T01:41:00.0", + "endGMT": "2024-07-08T01:42:00.0", + "activityLevel": 2.118513195009655, + }, + { + "startGMT": "2024-07-08T01:42:00.0", + "endGMT": "2024-07-08T01:43:00.0", + "activityLevel": 1.8463148494411195, + }, + { + "startGMT": "2024-07-08T01:43:00.0", + "endGMT": "2024-07-08T01:44:00.0", + "activityLevel": 1.643217983028883, + }, + { + "startGMT": "2024-07-08T01:44:00.0", + "endGMT": "2024-07-08T01:45:00.0", + "activityLevel": 1.483284286142881, + }, + { + "startGMT": "2024-07-08T01:45:00.0", + "endGMT": "2024-07-08T01:46:00.0", + "activityLevel": 1.3917872757152812, + }, + { + "startGMT": "2024-07-08T01:46:00.0", + "endGMT": "2024-07-08T01:47:00.0", + "activityLevel": 1.3402119301851376, + }, + { + "startGMT": "2024-07-08T01:47:00.0", + "endGMT": "2024-07-08T01:48:00.0", + "activityLevel": 1.3092613064762222, + }, + { + "startGMT": "2024-07-08T01:48:00.0", + "endGMT": "2024-07-08T01:49:00.0", + "activityLevel": 1.2643594394586326, + }, + { + "startGMT": "2024-07-08T01:49:00.0", + "endGMT": "2024-07-08T01:50:00.0", + "activityLevel": 1.209814570608861, + }, + { + "startGMT": "2024-07-08T01:50:00.0", + "endGMT": "2024-07-08T01:51:00.0", + "activityLevel": 1.1516711989205035, + }, + { + "startGMT": "2024-07-08T01:51:00.0", + "endGMT": "2024-07-08T01:52:00.0", + "activityLevel": 1.0911192963662364, + }, + { + "startGMT": "2024-07-08T01:52:00.0", + "endGMT": "2024-07-08T01:53:00.0", + "activityLevel": 1.0265521481940802, + }, + { + "startGMT": "2024-07-08T01:53:00.0", + "endGMT": "2024-07-08T01:54:00.0", + "activityLevel": 0.9669786424963646, + }, + { + "startGMT": "2024-07-08T01:54:00.0", + "endGMT": "2024-07-08T01:55:00.0", + "activityLevel": 0.9133403337020598, + }, + { + "startGMT": "2024-07-08T01:55:00.0", + "endGMT": "2024-07-08T01:56:00.0", + "activityLevel": 0.865400793239344, + }, + { + "startGMT": "2024-07-08T01:56:00.0", + "endGMT": "2024-07-08T01:57:00.0", + "activityLevel": 0.8246717999431822, + }, + { + "startGMT": "2024-07-08T01:57:00.0", + "endGMT": "2024-07-08T01:58:00.0", + "activityLevel": 0.7927471733036636, + }, + { + "startGMT": "2024-07-08T01:58:00.0", + "endGMT": "2024-07-08T01:59:00.0", + "activityLevel": 0.7709117217028698, + }, + { + "startGMT": "2024-07-08T01:59:00.0", + "endGMT": "2024-07-08T02:00:00.0", + "activityLevel": 0.7570478862055404, + }, + { + "startGMT": "2024-07-08T02:00:00.0", + "endGMT": "2024-07-08T02:01:00.0", + "activityLevel": 0.7562462857454977, + }, + { + "startGMT": "2024-07-08T02:01:00.0", + "endGMT": "2024-07-08T02:02:00.0", + "activityLevel": 0.7614366200309307, + }, + { + "startGMT": "2024-07-08T02:02:00.0", + "endGMT": "2024-07-08T02:03:00.0", + "activityLevel": 0.7724004080777223, + }, + { + "startGMT": "2024-07-08T02:03:00.0", + "endGMT": "2024-07-08T02:04:00.0", + "activityLevel": 0.7859070301665612, + }, + { + "startGMT": "2024-07-08T02:04:00.0", + "endGMT": "2024-07-08T02:05:00.0", + "activityLevel": 0.7983281462311097, + }, + { + "startGMT": "2024-07-08T02:05:00.0", + "endGMT": "2024-07-08T02:06:00.0", + "activityLevel": 0.8062062764723182, + }, + { + "startGMT": "2024-07-08T02:06:00.0", + "endGMT": "2024-07-08T02:07:00.0", + "activityLevel": 0.8115529073538644, + }, + { + "startGMT": "2024-07-08T02:07:00.0", + "endGMT": "2024-07-08T02:08:00.0", + "activityLevel": 0.8015122478351525, + }, + { + "startGMT": "2024-07-08T02:08:00.0", + "endGMT": "2024-07-08T02:09:00.0", + "activityLevel": 0.7795774714080115, + }, + { + "startGMT": "2024-07-08T02:09:00.0", + "endGMT": "2024-07-08T02:10:00.0", + "activityLevel": 0.7467119467385426, + }, + { + "startGMT": "2024-07-08T02:10:00.0", + "endGMT": "2024-07-08T02:11:00.0", + "activityLevel": 0.702936539109698, + }, + { + "startGMT": "2024-07-08T02:11:00.0", + "endGMT": "2024-07-08T02:12:00.0", + "activityLevel": 0.6484888180908535, + }, + { + "startGMT": "2024-07-08T02:12:00.0", + "endGMT": "2024-07-08T02:13:00.0", + "activityLevel": 0.5855640746547759, + }, + { + "startGMT": "2024-07-08T02:13:00.0", + "endGMT": "2024-07-08T02:14:00.0", + "activityLevel": 0.516075710571075, + }, + { + "startGMT": "2024-07-08T02:14:00.0", + "endGMT": "2024-07-08T02:15:00.0", + "activityLevel": 0.4420512517154544, + }, + { + "startGMT": "2024-07-08T02:15:00.0", + "endGMT": "2024-07-08T02:16:00.0", + "activityLevel": 0.3655068810407815, + }, + { + "startGMT": "2024-07-08T02:16:00.0", + "endGMT": "2024-07-08T02:17:00.0", + "activityLevel": 0.2882629894112111, + }, + { + "startGMT": "2024-07-08T02:17:00.0", + "endGMT": "2024-07-08T02:18:00.0", + "activityLevel": 0.2115766559902864, + }, + { + "startGMT": "2024-07-08T02:18:00.0", + "endGMT": "2024-07-08T02:19:00.0", + "activityLevel": 0.1349333939486886, + }, + { + "startGMT": "2024-07-08T02:19:00.0", + "endGMT": "2024-07-08T02:20:00.0", + "activityLevel": 0.0448732441707528, + }, + { + "startGMT": "2024-07-08T02:20:00.0", + "endGMT": "2024-07-08T02:21:00.0", + "activityLevel": 0.07686529550989835, + }, + { + "startGMT": "2024-07-08T02:21:00.0", + "endGMT": "2024-07-08T02:22:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T02:22:00.0", + "endGMT": "2024-07-08T02:23:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T02:23:00.0", + "endGMT": "2024-07-08T02:24:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T02:24:00.0", + "endGMT": "2024-07-08T02:25:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T02:25:00.0", + "endGMT": "2024-07-08T02:26:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T02:26:00.0", + "endGMT": "2024-07-08T02:27:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T02:27:00.0", + "endGMT": "2024-07-08T02:28:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T02:28:00.0", + "endGMT": "2024-07-08T02:29:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T02:29:00.0", + "endGMT": "2024-07-08T02:30:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T02:30:00.0", + "endGMT": "2024-07-08T02:31:00.0", + "activityLevel": 0.07686529550989835, + }, + { + "startGMT": "2024-07-08T02:31:00.0", + "endGMT": "2024-07-08T02:32:00.0", + "activityLevel": 0.0448732441707528, + }, + { + "startGMT": "2024-07-08T02:32:00.0", + "endGMT": "2024-07-08T02:33:00.0", + "activityLevel": 0.1349333939486886, + }, + { + "startGMT": "2024-07-08T02:33:00.0", + "endGMT": "2024-07-08T02:34:00.0", + "activityLevel": 0.2115766559902864, + }, + { + "startGMT": "2024-07-08T02:34:00.0", + "endGMT": "2024-07-08T02:35:00.0", + "activityLevel": 0.2882629894112111, + }, + { + "startGMT": "2024-07-08T02:35:00.0", + "endGMT": "2024-07-08T02:36:00.0", + "activityLevel": 0.3655068810407815, + }, + { + "startGMT": "2024-07-08T02:36:00.0", + "endGMT": "2024-07-08T02:37:00.0", + "activityLevel": 0.4420512517154544, + }, + { + "startGMT": "2024-07-08T02:37:00.0", + "endGMT": "2024-07-08T02:38:00.0", + "activityLevel": 0.516075710571075, + }, + { + "startGMT": "2024-07-08T02:38:00.0", + "endGMT": "2024-07-08T02:39:00.0", + "activityLevel": 0.5855640746547759, + }, + { + "startGMT": "2024-07-08T02:39:00.0", + "endGMT": "2024-07-08T02:40:00.0", + "activityLevel": 0.6484888180908535, + }, + { + "startGMT": "2024-07-08T02:40:00.0", + "endGMT": "2024-07-08T02:41:00.0", + "activityLevel": 0.702936539109698, + }, + { + "startGMT": "2024-07-08T02:41:00.0", + "endGMT": "2024-07-08T02:42:00.0", + "activityLevel": 0.7472063072597769, + }, + { + "startGMT": "2024-07-08T02:42:00.0", + "endGMT": "2024-07-08T02:43:00.0", + "activityLevel": 0.7798896506098385, + }, + { + "startGMT": "2024-07-08T02:43:00.0", + "endGMT": "2024-07-08T02:44:00.0", + "activityLevel": 0.799933937787455, + }, + { + "startGMT": "2024-07-08T02:44:00.0", + "endGMT": "2024-07-08T02:45:00.0", + "activityLevel": 0.8066886999730392, + }, + { + "startGMT": "2024-07-08T02:45:00.0", + "endGMT": "2024-07-08T02:46:00.0", + "activityLevel": 0.799933937787455, + }, + { + "startGMT": "2024-07-08T02:46:00.0", + "endGMT": "2024-07-08T02:47:00.0", + "activityLevel": 0.7798896506098385, + }, + { + "startGMT": "2024-07-08T02:47:00.0", + "endGMT": "2024-07-08T02:48:00.0", + "activityLevel": 0.7472063072597769, + }, + { + "startGMT": "2024-07-08T02:48:00.0", + "endGMT": "2024-07-08T02:49:00.0", + "activityLevel": 0.702936539109698, + }, + { + "startGMT": "2024-07-08T02:49:00.0", + "endGMT": "2024-07-08T02:50:00.0", + "activityLevel": 0.6484888180908535, + }, + { + "startGMT": "2024-07-08T02:50:00.0", + "endGMT": "2024-07-08T02:51:00.0", + "activityLevel": 0.5830361469920986, + }, + { + "startGMT": "2024-07-08T02:51:00.0", + "endGMT": "2024-07-08T02:52:00.0", + "activityLevel": 0.5141855756784043, + }, + { + "startGMT": "2024-07-08T02:52:00.0", + "endGMT": "2024-07-08T02:53:00.0", + "activityLevel": 0.45007275716127054, + }, + { + "startGMT": "2024-07-08T02:53:00.0", + "endGMT": "2024-07-08T02:54:00.0", + "activityLevel": 0.40753887568014413, + }, + { + "startGMT": "2024-07-08T02:54:00.0", + "endGMT": "2024-07-08T02:55:00.0", + "activityLevel": 0.39513184847301797, + }, + { + "startGMT": "2024-07-08T02:55:00.0", + "endGMT": "2024-07-08T02:56:00.0", + "activityLevel": 0.4189181753233822, + }, + { + "startGMT": "2024-07-08T02:56:00.0", + "endGMT": "2024-07-08T02:57:00.0", + "activityLevel": 0.47355790664958386, + }, + { + "startGMT": "2024-07-08T02:57:00.0", + "endGMT": "2024-07-08T02:58:00.0", + "activityLevel": 0.5447282215489629, + }, + { + "startGMT": "2024-07-08T02:58:00.0", + "endGMT": "2024-07-08T02:59:00.0", + "activityLevel": 0.6304069298658225, + }, + { + "startGMT": "2024-07-08T02:59:00.0", + "endGMT": "2024-07-08T03:00:00.0", + "activityLevel": 0.7238660762044068, + }, + { + "startGMT": "2024-07-08T03:00:00.0", + "endGMT": "2024-07-08T03:01:00.0", + "activityLevel": 0.8069409805217257, + }, + { + "startGMT": "2024-07-08T03:01:00.0", + "endGMT": "2024-07-08T03:02:00.0", + "activityLevel": 0.8820630198226972, + }, + { + "startGMT": "2024-07-08T03:02:00.0", + "endGMT": "2024-07-08T03:03:00.0", + "activityLevel": 0.9471695177846488, + }, + { + "startGMT": "2024-07-08T03:03:00.0", + "endGMT": "2024-07-08T03:04:00.0", + "activityLevel": 1.000462079917193, + }, + { + "startGMT": "2024-07-08T03:04:00.0", + "endGMT": "2024-07-08T03:05:00.0", + "activityLevel": 1.0404813716876704, + }, + { + "startGMT": "2024-07-08T03:05:00.0", + "endGMT": "2024-07-08T03:06:00.0", + "activityLevel": 1.0661661582133397, + }, + { + "startGMT": "2024-07-08T03:06:00.0", + "endGMT": "2024-07-08T03:07:00.0", + "activityLevel": 1.0768952079486527, + }, + { + "startGMT": "2024-07-08T03:07:00.0", + "endGMT": "2024-07-08T03:08:00.0", + "activityLevel": 1.0725108893565585, + }, + { + "startGMT": "2024-07-08T03:08:00.0", + "endGMT": "2024-07-08T03:09:00.0", + "activityLevel": 1.0533238287348863, + }, + { + "startGMT": "2024-07-08T03:09:00.0", + "endGMT": "2024-07-08T03:10:00.0", + "activityLevel": 1.0200986858979675, + }, + { + "startGMT": "2024-07-08T03:10:00.0", + "endGMT": "2024-07-08T03:11:00.0", + "activityLevel": 0.9740218466633179, + }, + { + "startGMT": "2024-07-08T03:11:00.0", + "endGMT": "2024-07-08T03:12:00.0", + "activityLevel": 0.9166525597031866, + }, + { + "startGMT": "2024-07-08T03:12:00.0", + "endGMT": "2024-07-08T03:13:00.0", + "activityLevel": 0.8498597056382565, + }, + { + "startGMT": "2024-07-08T03:13:00.0", + "endGMT": "2024-07-08T03:14:00.0", + "activityLevel": 0.7757469289017959, + }, + { + "startGMT": "2024-07-08T03:14:00.0", + "endGMT": "2024-07-08T03:15:00.0", + "activityLevel": 0.6965692377303351, + }, + { + "startGMT": "2024-07-08T03:15:00.0", + "endGMT": "2024-07-08T03:16:00.0", + "activityLevel": 0.6146443241940822, + }, + { + "startGMT": "2024-07-08T03:16:00.0", + "endGMT": "2024-07-08T03:17:00.0", + "activityLevel": 0.5322616839561646, + }, + { + "startGMT": "2024-07-08T03:17:00.0", + "endGMT": "2024-07-08T03:18:00.0", + "activityLevel": 0.45159195947849645, + }, + { + "startGMT": "2024-07-08T03:18:00.0", + "endGMT": "2024-07-08T03:19:00.0", + "activityLevel": 0.3745974467562052, + }, + { + "startGMT": "2024-07-08T03:19:00.0", + "endGMT": "2024-07-08T03:20:00.0", + "activityLevel": 0.3094467995728701, + }, + { + "startGMT": "2024-07-08T03:20:00.0", + "endGMT": "2024-07-08T03:21:00.0", + "activityLevel": 0.2526727195744883, + }, + { + "startGMT": "2024-07-08T03:21:00.0", + "endGMT": "2024-07-08T03:22:00.0", + "activityLevel": 0.2038327145777733, + }, + { + "startGMT": "2024-07-08T03:22:00.0", + "endGMT": "2024-07-08T03:23:00.0", + "activityLevel": 0.1496072881915049, + }, + { + "startGMT": "2024-07-08T03:23:00.0", + "endGMT": "2024-07-08T03:24:00.0", + "activityLevel": 0.09541231786963358, + }, + { + "startGMT": "2024-07-08T03:24:00.0", + "endGMT": "2024-07-08T03:25:00.0", + "activityLevel": 0.03173017524697902, + }, + { + "startGMT": "2024-07-08T03:25:00.0", + "endGMT": "2024-07-08T03:26:00.0", + "activityLevel": 0.05435197169295701, + }, + { + "startGMT": "2024-07-08T03:26:00.0", + "endGMT": "2024-07-08T03:27:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T03:27:00.0", + "endGMT": "2024-07-08T03:28:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T03:28:00.0", + "endGMT": "2024-07-08T03:29:00.0", + "activityLevel": 0.07686529550989835, + }, + { + "startGMT": "2024-07-08T03:29:00.0", + "endGMT": "2024-07-08T03:30:00.0", + "activityLevel": 0.0448732441707528, + }, + { + "startGMT": "2024-07-08T03:30:00.0", + "endGMT": "2024-07-08T03:31:00.0", + "activityLevel": 0.1349333939486886, + }, + { + "startGMT": "2024-07-08T03:31:00.0", + "endGMT": "2024-07-08T03:32:00.0", + "activityLevel": 0.2115766559902864, + }, + { + "startGMT": "2024-07-08T03:32:00.0", + "endGMT": "2024-07-08T03:33:00.0", + "activityLevel": 0.2882629894112111, + }, + { + "startGMT": "2024-07-08T03:33:00.0", + "endGMT": "2024-07-08T03:34:00.0", + "activityLevel": 0.3655068810407815, + }, + { + "startGMT": "2024-07-08T03:34:00.0", + "endGMT": "2024-07-08T03:35:00.0", + "activityLevel": 0.4420512517154544, + }, + { + "startGMT": "2024-07-08T03:35:00.0", + "endGMT": "2024-07-08T03:36:00.0", + "activityLevel": 0.516075710571075, + }, + { + "startGMT": "2024-07-08T03:36:00.0", + "endGMT": "2024-07-08T03:37:00.0", + "activityLevel": 0.5855640746547759, + }, + { + "startGMT": "2024-07-08T03:37:00.0", + "endGMT": "2024-07-08T03:38:00.0", + "activityLevel": 0.6484888180908535, + }, + { + "startGMT": "2024-07-08T03:38:00.0", + "endGMT": "2024-07-08T03:39:00.0", + "activityLevel": 0.702936539109698, + }, + { + "startGMT": "2024-07-08T03:39:00.0", + "endGMT": "2024-07-08T03:40:00.0", + "activityLevel": 0.7472063072597769, + }, + { + "startGMT": "2024-07-08T03:40:00.0", + "endGMT": "2024-07-08T03:41:00.0", + "activityLevel": 0.7798896506098385, + }, + { + "startGMT": "2024-07-08T03:41:00.0", + "endGMT": "2024-07-08T03:42:00.0", + "activityLevel": 0.799933937787455, + }, + { + "startGMT": "2024-07-08T03:42:00.0", + "endGMT": "2024-07-08T03:43:00.0", + "activityLevel": 0.8066886999730392, + }, + { + "startGMT": "2024-07-08T03:43:00.0", + "endGMT": "2024-07-08T03:44:00.0", + "activityLevel": 0.799933937787455, + }, + { + "startGMT": "2024-07-08T03:44:00.0", + "endGMT": "2024-07-08T03:45:00.0", + "activityLevel": 0.7798896506098385, + }, + { + "startGMT": "2024-07-08T03:45:00.0", + "endGMT": "2024-07-08T03:46:00.0", + "activityLevel": 0.7472063072597769, + }, + { + "startGMT": "2024-07-08T03:46:00.0", + "endGMT": "2024-07-08T03:47:00.0", + "activityLevel": 0.702936539109698, + }, + { + "startGMT": "2024-07-08T03:47:00.0", + "endGMT": "2024-07-08T03:48:00.0", + "activityLevel": 0.6484888180908535, + }, + { + "startGMT": "2024-07-08T03:48:00.0", + "endGMT": "2024-07-08T03:49:00.0", + "activityLevel": 0.5855640746547759, + }, + { + "startGMT": "2024-07-08T03:49:00.0", + "endGMT": "2024-07-08T03:50:00.0", + "activityLevel": 0.5132056139740951, + }, + { + "startGMT": "2024-07-08T03:50:00.0", + "endGMT": "2024-07-08T03:51:00.0", + "activityLevel": 0.43984312696402567, + }, + { + "startGMT": "2024-07-08T03:51:00.0", + "endGMT": "2024-07-08T03:52:00.0", + "activityLevel": 0.37908520745423446, + }, + { + "startGMT": "2024-07-08T03:52:00.0", + "endGMT": "2024-07-08T03:53:00.0", + "activityLevel": 0.3384987476277571, + }, + { + "startGMT": "2024-07-08T03:53:00.0", + "endGMT": "2024-07-08T03:54:00.0", + "activityLevel": 0.32968894062766496, + }, + { + "startGMT": "2024-07-08T03:54:00.0", + "endGMT": "2024-07-08T03:55:00.0", + "activityLevel": 0.35574209250345395, + }, + { + "startGMT": "2024-07-08T03:55:00.0", + "endGMT": "2024-07-08T03:56:00.0", + "activityLevel": 0.4080636012413849, + }, + { + "startGMT": "2024-07-08T03:56:00.0", + "endGMT": "2024-07-08T03:57:00.0", + "activityLevel": 0.4743031208399287, + }, + { + "startGMT": "2024-07-08T03:57:00.0", + "endGMT": "2024-07-08T03:58:00.0", + "activityLevel": 0.5519145878520263, + }, + { + "startGMT": "2024-07-08T03:58:00.0", + "endGMT": "2024-07-08T03:59:00.0", + "activityLevel": 0.6178280637504159, + }, + { + "startGMT": "2024-07-08T03:59:00.0", + "endGMT": "2024-07-08T04:00:00.0", + "activityLevel": 0.6762608687497718, + }, + { + "startGMT": "2024-07-08T04:00:00.0", + "endGMT": "2024-07-08T04:01:00.0", + "activityLevel": 0.7254092099030423, + }, + { + "startGMT": "2024-07-08T04:01:00.0", + "endGMT": "2024-07-08T04:02:00.0", + "activityLevel": 0.7637228334733511, + }, + { + "startGMT": "2024-07-08T04:02:00.0", + "endGMT": "2024-07-08T04:03:00.0", + "activityLevel": 0.7899753704871058, + }, + { + "startGMT": "2024-07-08T04:03:00.0", + "endGMT": "2024-07-08T04:04:00.0", + "activityLevel": 0.8033184186511398, + }, + { + "startGMT": "2024-07-08T04:04:00.0", + "endGMT": "2024-07-08T04:05:00.0", + "activityLevel": 0.8033184186511398, + }, + { + "startGMT": "2024-07-08T04:05:00.0", + "endGMT": "2024-07-08T04:06:00.0", + "activityLevel": 0.7899753704871058, + }, + { + "startGMT": "2024-07-08T04:06:00.0", + "endGMT": "2024-07-08T04:07:00.0", + "activityLevel": 0.7637228334733511, + }, + { + "startGMT": "2024-07-08T04:07:00.0", + "endGMT": "2024-07-08T04:08:00.0", + "activityLevel": 0.7254092099030423, + }, + { + "startGMT": "2024-07-08T04:08:00.0", + "endGMT": "2024-07-08T04:09:00.0", + "activityLevel": 0.6762608687497718, + }, + { + "startGMT": "2024-07-08T04:09:00.0", + "endGMT": "2024-07-08T04:10:00.0", + "activityLevel": 0.6178280637504159, + }, + { + "startGMT": "2024-07-08T04:10:00.0", + "endGMT": "2024-07-08T04:11:00.0", + "activityLevel": 0.5519145878520263, + }, + { + "startGMT": "2024-07-08T04:11:00.0", + "endGMT": "2024-07-08T04:12:00.0", + "activityLevel": 0.48049112800583527, + }, + { + "startGMT": "2024-07-08T04:12:00.0", + "endGMT": "2024-07-08T04:13:00.0", + "activityLevel": 0.405588824569514, + }, + { + "startGMT": "2024-07-08T04:13:00.0", + "endGMT": "2024-07-08T04:14:00.0", + "activityLevel": 0.3291586480349924, + }, + { + "startGMT": "2024-07-08T04:14:00.0", + "endGMT": "2024-07-08T04:15:00.0", + "activityLevel": 0.251379358749743, + }, + { + "startGMT": "2024-07-08T04:15:00.0", + "endGMT": "2024-07-08T04:16:00.0", + "activityLevel": 0.17815036370036688, + }, + { + "startGMT": "2024-07-08T04:16:00.0", + "endGMT": "2024-07-08T04:17:00.0", + "activityLevel": 0.111293270339109, + }, + { + "startGMT": "2024-07-08T04:17:00.0", + "endGMT": "2024-07-08T04:18:00.0", + "activityLevel": 0.06040076460025982, + }, + { + "startGMT": "2024-07-08T04:18:00.0", + "endGMT": "2024-07-08T04:19:00.0", + "activityLevel": 0.08621372893062913, + }, + { + "startGMT": "2024-07-08T04:19:00.0", + "endGMT": "2024-07-08T04:20:00.0", + "activityLevel": 0.12922619707714067, + }, + { + "startGMT": "2024-07-08T04:20:00.0", + "endGMT": "2024-07-08T04:21:00.0", + "activityLevel": 0.15628871885999962, + }, + { + "startGMT": "2024-07-08T04:21:00.0", + "endGMT": "2024-07-08T04:22:00.0", + "activityLevel": 0.1824603172752366, + }, + { + "startGMT": "2024-07-08T04:22:00.0", + "endGMT": "2024-07-08T04:23:00.0", + "activityLevel": 0.2070281640038089, + }, + { + "startGMT": "2024-07-08T04:23:00.0", + "endGMT": "2024-07-08T04:24:00.0", + "activityLevel": 0.22927542039784596, + }, + { + "startGMT": "2024-07-08T04:24:00.0", + "endGMT": "2024-07-08T04:25:00.0", + "activityLevel": 0.2485255967741351, + }, + { + "startGMT": "2024-07-08T04:25:00.0", + "endGMT": "2024-07-08T04:26:00.0", + "activityLevel": 0.2641773234043736, + }, + { + "startGMT": "2024-07-08T04:26:00.0", + "endGMT": "2024-07-08T04:27:00.0", + "activityLevel": 0.275732630261712, + }, + { + "startGMT": "2024-07-08T04:27:00.0", + "endGMT": "2024-07-08T04:28:00.0", + "activityLevel": 0.28281935595538366, + }, + { + "startGMT": "2024-07-08T04:28:00.0", + "endGMT": "2024-07-08T04:29:00.0", + "activityLevel": 0.28520752502874813, + }, + { + "startGMT": "2024-07-08T04:29:00.0", + "endGMT": "2024-07-08T04:30:00.0", + "activityLevel": 0.28281935595538366, + }, + { + "startGMT": "2024-07-08T04:30:00.0", + "endGMT": "2024-07-08T04:31:00.0", + "activityLevel": 0.275732630261712, + }, + { + "startGMT": "2024-07-08T04:31:00.0", + "endGMT": "2024-07-08T04:32:00.0", + "activityLevel": 0.2641773234043736, + }, + { + "startGMT": "2024-07-08T04:32:00.0", + "endGMT": "2024-07-08T04:33:00.0", + "activityLevel": 0.2485255967741351, + }, + { + "startGMT": "2024-07-08T04:33:00.0", + "endGMT": "2024-07-08T04:34:00.0", + "activityLevel": 0.22927542039784596, + }, + { + "startGMT": "2024-07-08T04:34:00.0", + "endGMT": "2024-07-08T04:35:00.0", + "activityLevel": 0.2070281640038089, + }, + { + "startGMT": "2024-07-08T04:35:00.0", + "endGMT": "2024-07-08T04:36:00.0", + "activityLevel": 0.1824603172752366, + }, + { + "startGMT": "2024-07-08T04:36:00.0", + "endGMT": "2024-07-08T04:37:00.0", + "activityLevel": 0.15628871885999962, + }, + { + "startGMT": "2024-07-08T04:37:00.0", + "endGMT": "2024-07-08T04:38:00.0", + "activityLevel": 0.12922619707714067, + }, + { + "startGMT": "2024-07-08T04:38:00.0", + "endGMT": "2024-07-08T04:39:00.0", + "activityLevel": 0.10191635728888665, + }, + { + "startGMT": "2024-07-08T04:39:00.0", + "endGMT": "2024-07-08T04:40:00.0", + "activityLevel": 0.07480364409575245, + }, + { + "startGMT": "2024-07-08T04:40:00.0", + "endGMT": "2024-07-08T04:41:00.0", + "activityLevel": 0.039208970830487244, + }, + { + "startGMT": "2024-07-08T04:41:00.0", + "endGMT": "2024-07-08T04:42:00.0", + "activityLevel": 0.0224366220853764, + }, + { + "startGMT": "2024-07-08T04:42:00.0", + "endGMT": "2024-07-08T04:43:00.0", + "activityLevel": 0.039208970830487244, + }, + { + "startGMT": "2024-07-08T04:43:00.0", + "endGMT": "2024-07-08T04:44:00.0", + "activityLevel": 0.07480364409575245, + }, + { + "startGMT": "2024-07-08T04:44:00.0", + "endGMT": "2024-07-08T04:45:00.0", + "activityLevel": 0.10191635728888665, + }, + { + "startGMT": "2024-07-08T04:45:00.0", + "endGMT": "2024-07-08T04:46:00.0", + "activityLevel": 0.12922619707714067, + }, + { + "startGMT": "2024-07-08T04:46:00.0", + "endGMT": "2024-07-08T04:47:00.0", + "activityLevel": 0.14653336417344687, + }, + { + "startGMT": "2024-07-08T04:47:00.0", + "endGMT": "2024-07-08T04:48:00.0", + "activityLevel": 0.1851987348806249, + }, + { + "startGMT": "2024-07-08T04:48:00.0", + "endGMT": "2024-07-08T04:49:00.0", + "activityLevel": 0.22795651140523274, + }, + { + "startGMT": "2024-07-08T04:49:00.0", + "endGMT": "2024-07-08T04:50:00.0", + "activityLevel": 0.27376917116181104, + }, + { + "startGMT": "2024-07-08T04:50:00.0", + "endGMT": "2024-07-08T04:51:00.0", + "activityLevel": 0.3214230044413187, + }, + { + "startGMT": "2024-07-08T04:51:00.0", + "endGMT": "2024-07-08T04:52:00.0", + "activityLevel": 0.3695771884805379, + }, + { + "startGMT": "2024-07-08T04:52:00.0", + "endGMT": "2024-07-08T04:53:00.0", + "activityLevel": 0.4168130731666678, + }, + { + "startGMT": "2024-07-08T04:53:00.0", + "endGMT": "2024-07-08T04:54:00.0", + "activityLevel": 0.46168588631637636, + }, + { + "startGMT": "2024-07-08T04:54:00.0", + "endGMT": "2024-07-08T04:55:00.0", + "activityLevel": 0.5027782563876206, + }, + { + "startGMT": "2024-07-08T04:55:00.0", + "endGMT": "2024-07-08T04:56:00.0", + "activityLevel": 0.5387538043461539, + }, + { + "startGMT": "2024-07-08T04:56:00.0", + "endGMT": "2024-07-08T04:57:00.0", + "activityLevel": 0.5677586090867086, + }, + { + "startGMT": "2024-07-08T04:57:00.0", + "endGMT": "2024-07-08T04:58:00.0", + "activityLevel": 0.5909314613479265, + }, + { + "startGMT": "2024-07-08T04:58:00.0", + "endGMT": "2024-07-08T04:59:00.0", + "activityLevel": 0.6067575985650464, + }, + { + "startGMT": "2024-07-08T04:59:00.0", + "endGMT": "2024-07-08T05:00:00.0", + "activityLevel": 0.6149064611635537, + }, + { + "startGMT": "2024-07-08T05:00:00.0", + "endGMT": "2024-07-08T05:01:00.0", + "activityLevel": 0.6129166314263368, + }, + { + "startGMT": "2024-07-08T05:01:00.0", + "endGMT": "2024-07-08T05:02:00.0", + "activityLevel": 0.609052652752187, + }, + { + "startGMT": "2024-07-08T05:02:00.0", + "endGMT": "2024-07-08T05:03:00.0", + "activityLevel": 0.6017223373377658, + }, + { + "startGMT": "2024-07-08T05:03:00.0", + "endGMT": "2024-07-08T05:04:00.0", + "activityLevel": 0.592901468100402, + }, + { + "startGMT": "2024-07-08T05:04:00.0", + "endGMT": "2024-07-08T05:05:00.0", + "activityLevel": 0.5846839052973222, + }, + { + "startGMT": "2024-07-08T05:05:00.0", + "endGMT": "2024-07-08T05:06:00.0", + "activityLevel": 0.5764331534360398, + }, + { + "startGMT": "2024-07-08T05:06:00.0", + "endGMT": "2024-07-08T05:07:00.0", + "activityLevel": 0.5780959705863811, + }, + { + "startGMT": "2024-07-08T05:07:00.0", + "endGMT": "2024-07-08T05:08:00.0", + "activityLevel": 0.5877746240261619, + }, + { + "startGMT": "2024-07-08T05:08:00.0", + "endGMT": "2024-07-08T05:09:00.0", + "activityLevel": 0.6056563276306803, + }, + { + "startGMT": "2024-07-08T05:09:00.0", + "endGMT": "2024-07-08T05:10:00.0", + "activityLevel": 0.631348617859957, + }, + { + "startGMT": "2024-07-08T05:10:00.0", + "endGMT": "2024-07-08T05:11:00.0", + "activityLevel": 0.660869606591957, + }, + { + "startGMT": "2024-07-08T05:11:00.0", + "endGMT": "2024-07-08T05:12:00.0", + "activityLevel": 0.6922661454664889, + }, + { + "startGMT": "2024-07-08T05:12:00.0", + "endGMT": "2024-07-08T05:13:00.0", + "activityLevel": 0.7227814309161422, + }, + { + "startGMT": "2024-07-08T05:13:00.0", + "endGMT": "2024-07-08T05:14:00.0", + "activityLevel": 0.7492981537350796, + }, + { + "startGMT": "2024-07-08T05:14:00.0", + "endGMT": "2024-07-08T05:15:00.0", + "activityLevel": 0.7711710182293295, + }, + { + "startGMT": "2024-07-08T05:15:00.0", + "endGMT": "2024-07-08T05:16:00.0", + "activityLevel": 0.7885747506855358, + }, + { + "startGMT": "2024-07-08T05:16:00.0", + "endGMT": "2024-07-08T05:17:00.0", + "activityLevel": 0.7948136965536994, + }, + { + "startGMT": "2024-07-08T05:17:00.0", + "endGMT": "2024-07-08T05:18:00.0", + "activityLevel": 0.7918025496497091, + }, + { + "startGMT": "2024-07-08T05:18:00.0", + "endGMT": "2024-07-08T05:19:00.0", + "activityLevel": 0.7798285805699557, + }, + { + "startGMT": "2024-07-08T05:19:00.0", + "endGMT": "2024-07-08T05:20:00.0", + "activityLevel": 0.7594522872310361, + }, + { + "startGMT": "2024-07-08T05:20:00.0", + "endGMT": "2024-07-08T05:21:00.0", + "activityLevel": 0.731483770454574, + }, + { + "startGMT": "2024-07-08T05:21:00.0", + "endGMT": "2024-07-08T05:22:00.0", + "activityLevel": 0.6969485267547956, + }, + { + "startGMT": "2024-07-08T05:22:00.0", + "endGMT": "2024-07-08T05:23:00.0", + "activityLevel": 0.6570436693058681, + }, + { + "startGMT": "2024-07-08T05:23:00.0", + "endGMT": "2024-07-08T05:24:00.0", + "activityLevel": 0.6106718148745437, + }, + { + "startGMT": "2024-07-08T05:24:00.0", + "endGMT": "2024-07-08T05:25:00.0", + "activityLevel": 0.5647304138394204, + }, + { + "startGMT": "2024-07-08T05:25:00.0", + "endGMT": "2024-07-08T05:26:00.0", + "activityLevel": 0.529116037610532, + }, + { + "startGMT": "2024-07-08T05:26:00.0", + "endGMT": "2024-07-08T05:27:00.0", + "activityLevel": 0.5037293113431717, + }, + { + "startGMT": "2024-07-08T05:27:00.0", + "endGMT": "2024-07-08T05:28:00.0", + "activityLevel": 0.4939482838698683, + }, + { + "startGMT": "2024-07-08T05:28:00.0", + "endGMT": "2024-07-08T05:29:00.0", + "activityLevel": 0.5021709936828391, + }, + { + "startGMT": "2024-07-08T05:29:00.0", + "endGMT": "2024-07-08T05:30:00.0", + "activityLevel": 0.5311106791798353, + }, + { + "startGMT": "2024-07-08T05:30:00.0", + "endGMT": "2024-07-08T05:31:00.0", + "activityLevel": 0.5683693543580925, + }, + { + "startGMT": "2024-07-08T05:31:00.0", + "endGMT": "2024-07-08T05:32:00.0", + "activityLevel": 0.6127627558338284, + }, + { + "startGMT": "2024-07-08T05:32:00.0", + "endGMT": "2024-07-08T05:33:00.0", + "activityLevel": 0.6597617287910849, + }, + { + "startGMT": "2024-07-08T05:33:00.0", + "endGMT": "2024-07-08T05:34:00.0", + "activityLevel": 0.7051491235661235, + }, + { + "startGMT": "2024-07-08T05:34:00.0", + "endGMT": "2024-07-08T05:35:00.0", + "activityLevel": 0.7480042039937583, + }, + { + "startGMT": "2024-07-08T05:35:00.0", + "endGMT": "2024-07-08T05:36:00.0", + "activityLevel": 0.7795503383434992, + }, + { + "startGMT": "2024-07-08T05:36:00.0", + "endGMT": "2024-07-08T05:37:00.0", + "activityLevel": 0.8004751688761245, + }, + { + "startGMT": "2024-07-08T05:37:00.0", + "endGMT": "2024-07-08T05:38:00.0", + "activityLevel": 0.8097576338801654, + }, + { + "startGMT": "2024-07-08T05:38:00.0", + "endGMT": "2024-07-08T05:39:00.0", + "activityLevel": 0.8067936953857362, + }, + { + "startGMT": "2024-07-08T05:39:00.0", + "endGMT": "2024-07-08T05:40:00.0", + "activityLevel": 0.7914145333367046, + }, + { + "startGMT": "2024-07-08T05:40:00.0", + "endGMT": "2024-07-08T05:41:00.0", + "activityLevel": 0.7638876012698891, + }, + { + "startGMT": "2024-07-08T05:41:00.0", + "endGMT": "2024-07-08T05:42:00.0", + "activityLevel": 0.7248999845533368, + }, + { + "startGMT": "2024-07-08T05:42:00.0", + "endGMT": "2024-07-08T05:43:00.0", + "activityLevel": 0.6762608687497718, + }, + { + "startGMT": "2024-07-08T05:43:00.0", + "endGMT": "2024-07-08T05:44:00.0", + "activityLevel": 0.6178280637504159, + }, + { + "startGMT": "2024-07-08T05:44:00.0", + "endGMT": "2024-07-08T05:45:00.0", + "activityLevel": 0.5519145878520263, + }, + { + "startGMT": "2024-07-08T05:45:00.0", + "endGMT": "2024-07-08T05:46:00.0", + "activityLevel": 0.48049112800583527, + }, + { + "startGMT": "2024-07-08T05:46:00.0", + "endGMT": "2024-07-08T05:47:00.0", + "activityLevel": 0.405588824569514, + }, + { + "startGMT": "2024-07-08T05:47:00.0", + "endGMT": "2024-07-08T05:48:00.0", + "activityLevel": 0.3291586480349924, + }, + { + "startGMT": "2024-07-08T05:48:00.0", + "endGMT": "2024-07-08T05:49:00.0", + "activityLevel": 0.2528440551252095, + }, + { + "startGMT": "2024-07-08T05:49:00.0", + "endGMT": "2024-07-08T05:50:00.0", + "activityLevel": 0.17744252895310075, + }, + { + "startGMT": "2024-07-08T05:50:00.0", + "endGMT": "2024-07-08T05:51:00.0", + "activityLevel": 0.10055005928620828, + }, + { + "startGMT": "2024-07-08T05:51:00.0", + "endGMT": "2024-07-08T05:52:00.0", + "activityLevel": 0.044128593969307475, + }, + { + "startGMT": "2024-07-08T05:52:00.0", + "endGMT": "2024-07-08T05:53:00.0", + "activityLevel": 0.05435197169295701, + }, + { + "startGMT": "2024-07-08T05:53:00.0", + "endGMT": "2024-07-08T05:54:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T05:54:00.0", + "endGMT": "2024-07-08T05:55:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T05:55:00.0", + "endGMT": "2024-07-08T05:56:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T05:56:00.0", + "endGMT": "2024-07-08T05:57:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T05:57:00.0", + "endGMT": "2024-07-08T05:58:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T05:58:00.0", + "endGMT": "2024-07-08T05:59:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T05:59:00.0", + "endGMT": "2024-07-08T06:00:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:00:00.0", + "endGMT": "2024-07-08T06:01:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:01:00.0", + "endGMT": "2024-07-08T06:02:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:02:00.0", + "endGMT": "2024-07-08T06:03:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:03:00.0", + "endGMT": "2024-07-08T06:04:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:04:00.0", + "endGMT": "2024-07-08T06:05:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:05:00.0", + "endGMT": "2024-07-08T06:06:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:06:00.0", + "endGMT": "2024-07-08T06:07:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:07:00.0", + "endGMT": "2024-07-08T06:08:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:08:00.0", + "endGMT": "2024-07-08T06:09:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:09:00.0", + "endGMT": "2024-07-08T06:10:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:10:00.0", + "endGMT": "2024-07-08T06:11:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:11:00.0", + "endGMT": "2024-07-08T06:12:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:12:00.0", + "endGMT": "2024-07-08T06:13:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:13:00.0", + "endGMT": "2024-07-08T06:14:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:14:00.0", + "endGMT": "2024-07-08T06:15:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:15:00.0", + "endGMT": "2024-07-08T06:16:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:16:00.0", + "endGMT": "2024-07-08T06:17:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:17:00.0", + "endGMT": "2024-07-08T06:18:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:18:00.0", + "endGMT": "2024-07-08T06:19:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:19:00.0", + "endGMT": "2024-07-08T06:20:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:20:00.0", + "endGMT": "2024-07-08T06:21:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:21:00.0", + "endGMT": "2024-07-08T06:22:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:22:00.0", + "endGMT": "2024-07-08T06:23:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:23:00.0", + "endGMT": "2024-07-08T06:24:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:24:00.0", + "endGMT": "2024-07-08T06:25:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:25:00.0", + "endGMT": "2024-07-08T06:26:00.0", + "activityLevel": 0.05435197169295701, + }, + { + "startGMT": "2024-07-08T06:26:00.0", + "endGMT": "2024-07-08T06:27:00.0", + "activityLevel": 0.044128593969307475, + }, + { + "startGMT": "2024-07-08T06:27:00.0", + "endGMT": "2024-07-08T06:28:00.0", + "activityLevel": 0.10055005928620828, + }, + { + "startGMT": "2024-07-08T06:28:00.0", + "endGMT": "2024-07-08T06:29:00.0", + "activityLevel": 0.17744252895310075, + }, + { + "startGMT": "2024-07-08T06:29:00.0", + "endGMT": "2024-07-08T06:30:00.0", + "activityLevel": 0.2528440551252095, + }, + { + "startGMT": "2024-07-08T06:30:00.0", + "endGMT": "2024-07-08T06:31:00.0", + "activityLevel": 0.3291586480349924, + }, + { + "startGMT": "2024-07-08T06:31:00.0", + "endGMT": "2024-07-08T06:32:00.0", + "activityLevel": 0.405588824569514, + }, + { + "startGMT": "2024-07-08T06:32:00.0", + "endGMT": "2024-07-08T06:33:00.0", + "activityLevel": 0.48049112800583527, + }, + { + "startGMT": "2024-07-08T06:33:00.0", + "endGMT": "2024-07-08T06:34:00.0", + "activityLevel": 0.5519145878520263, + }, + { + "startGMT": "2024-07-08T06:34:00.0", + "endGMT": "2024-07-08T06:35:00.0", + "activityLevel": 0.6130279297909387, + }, + { + "startGMT": "2024-07-08T06:35:00.0", + "endGMT": "2024-07-08T06:36:00.0", + "activityLevel": 0.6777480141207379, + }, + { + "startGMT": "2024-07-08T06:36:00.0", + "endGMT": "2024-07-08T06:37:00.0", + "activityLevel": 0.7378519787970133, + }, + { + "startGMT": "2024-07-08T06:37:00.0", + "endGMT": "2024-07-08T06:38:00.0", + "activityLevel": 0.7924880110945502, + }, + { + "startGMT": "2024-07-08T06:38:00.0", + "endGMT": "2024-07-08T06:39:00.0", + "activityLevel": 0.8409260591993377, + }, + { + "startGMT": "2024-07-08T06:39:00.0", + "endGMT": "2024-07-08T06:40:00.0", + "activityLevel": 0.8825620441829163, + }, + { + "startGMT": "2024-07-08T06:40:00.0", + "endGMT": "2024-07-08T06:41:00.0", + "activityLevel": 0.9169131861236199, + }, + { + "startGMT": "2024-07-08T06:41:00.0", + "endGMT": "2024-07-08T06:42:00.0", + "activityLevel": 0.9436075587963887, + }, + { + "startGMT": "2024-07-08T06:42:00.0", + "endGMT": "2024-07-08T06:43:00.0", + "activityLevel": 0.9623709533723823, + }, + { + "startGMT": "2024-07-08T06:43:00.0", + "endGMT": "2024-07-08T06:44:00.0", + "activityLevel": 0.9714947926644363, + }, + { + "startGMT": "2024-07-08T06:44:00.0", + "endGMT": "2024-07-08T06:45:00.0", + "activityLevel": 0.975938186894498, + }, + { + "startGMT": "2024-07-08T06:45:00.0", + "endGMT": "2024-07-08T06:46:00.0", + "activityLevel": 0.9742342081694915, + }, + { + "startGMT": "2024-07-08T06:46:00.0", + "endGMT": "2024-07-08T06:47:00.0", + "activityLevel": 0.9670676915770808, + }, + { + "startGMT": "2024-07-08T06:47:00.0", + "endGMT": "2024-07-08T06:48:00.0", + "activityLevel": 0.9551511945491185, + }, + { + "startGMT": "2024-07-08T06:48:00.0", + "endGMT": "2024-07-08T06:49:00.0", + "activityLevel": 0.939173356374611, + }, + { + "startGMT": "2024-07-08T06:49:00.0", + "endGMT": "2024-07-08T06:50:00.0", + "activityLevel": 0.9197523443688349, + }, + { + "startGMT": "2024-07-08T06:50:00.0", + "endGMT": "2024-07-08T06:51:00.0", + "activityLevel": 0.8973990488412699, + }, + { + "startGMT": "2024-07-08T06:51:00.0", + "endGMT": "2024-07-08T06:52:00.0", + "activityLevel": 0.8724939882046271, + }, + { + "startGMT": "2024-07-08T06:52:00.0", + "endGMT": "2024-07-08T06:53:00.0", + "activityLevel": 0.845280406748208, + }, + { + "startGMT": "2024-07-08T06:53:00.0", + "endGMT": "2024-07-08T06:54:00.0", + "activityLevel": 0.8158739506755465, + }, + { + "startGMT": "2024-07-08T06:54:00.0", + "endGMT": "2024-07-08T06:55:00.0", + "activityLevel": 0.7868225857865215, + }, + { + "startGMT": "2024-07-08T06:55:00.0", + "endGMT": "2024-07-08T06:56:00.0", + "activityLevel": 0.7552801285652947, + }, + { + "startGMT": "2024-07-08T06:56:00.0", + "endGMT": "2024-07-08T06:57:00.0", + "activityLevel": 0.7178833202932577, + }, + { + "startGMT": "2024-07-08T06:57:00.0", + "endGMT": "2024-07-08T06:58:00.0", + "activityLevel": 0.677472220404834, + }, + { + "startGMT": "2024-07-08T06:58:00.0", + "endGMT": "2024-07-08T06:59:00.0", + "activityLevel": 0.6348564432029968, + }, + { + "startGMT": "2024-07-08T06:59:00.0", + "endGMT": "2024-07-08T07:00:00.0", + "activityLevel": 0.5906594745910709, + }, + { + "startGMT": "2024-07-08T07:00:00.0", + "endGMT": "2024-07-08T07:01:00.0", + "activityLevel": 0.5453124366882788, + }, + { + "startGMT": "2024-07-08T07:01:00.0", + "endGMT": "2024-07-08T07:02:00.0", + "activityLevel": 0.4990726370481235, + }, + { + "startGMT": "2024-07-08T07:02:00.0", + "endGMT": "2024-07-08T07:03:00.0", + "activityLevel": 0.45206260621800165, + }, + { + "startGMT": "2024-07-08T07:03:00.0", + "endGMT": "2024-07-08T07:04:00.0", + "activityLevel": 0.4140563280076178, + }, + { + "startGMT": "2024-07-08T07:04:00.0", + "endGMT": "2024-07-08T07:05:00.0", + "activityLevel": 0.36085029124805756, + }, + { + "startGMT": "2024-07-08T07:05:00.0", + "endGMT": "2024-07-08T07:06:00.0", + "activityLevel": 0.3141837974702133, + }, + { + "startGMT": "2024-07-08T07:06:00.0", + "endGMT": "2024-07-08T07:07:00.0", + "activityLevel": 0.27550163419721485, + }, + { + "startGMT": "2024-07-08T07:07:00.0", + "endGMT": "2024-07-08T07:08:00.0", + "activityLevel": 0.2528440551252095, + }, + { + "startGMT": "2024-07-08T07:08:00.0", + "endGMT": "2024-07-08T07:09:00.0", + "activityLevel": 0.2528440551252095, + }, + { + "startGMT": "2024-07-08T07:09:00.0", + "endGMT": "2024-07-08T07:10:00.0", + "activityLevel": 0.27550163419721485, + }, + { + "startGMT": "2024-07-08T07:10:00.0", + "endGMT": "2024-07-08T07:11:00.0", + "activityLevel": 0.3141837974702133, + }, + { + "startGMT": "2024-07-08T07:11:00.0", + "endGMT": "2024-07-08T07:12:00.0", + "activityLevel": 0.36085029124805756, + }, + { + "startGMT": "2024-07-08T07:12:00.0", + "endGMT": "2024-07-08T07:13:00.0", + "activityLevel": 0.4140563280076178, + }, + { + "startGMT": "2024-07-08T07:13:00.0", + "endGMT": "2024-07-08T07:14:00.0", + "activityLevel": 0.4585508407956919, + }, + { + "startGMT": "2024-07-08T07:14:00.0", + "endGMT": "2024-07-08T07:15:00.0", + "activityLevel": 0.4970511935482702, + }, + { + "startGMT": "2024-07-08T07:15:00.0", + "endGMT": "2024-07-08T07:16:00.0", + "activityLevel": 0.5255516111453603, + }, + { + "startGMT": "2024-07-08T07:16:00.0", + "endGMT": "2024-07-08T07:17:00.0", + "activityLevel": 0.5523773507172176, + }, + { + "startGMT": "2024-07-08T07:17:00.0", + "endGMT": "2024-07-08T07:18:00.0", + "activityLevel": 0.5736293775717279, + }, + { + "startGMT": "2024-07-08T07:18:00.0", + "endGMT": "2024-07-08T07:19:00.0", + "activityLevel": 0.589708122728619, + }, + { + "startGMT": "2024-07-08T07:19:00.0", + "endGMT": "2024-07-08T07:20:00.0", + "activityLevel": 0.601244482672578, + }, + { + "startGMT": "2024-07-08T07:20:00.0", + "endGMT": "2024-07-08T07:21:00.0", + "activityLevel": 0.6090251009673148, + }, + { + "startGMT": "2024-07-08T07:21:00.0", + "endGMT": "2024-07-08T07:22:00.0", + "activityLevel": 0.6138919183178714, + }, + { + "startGMT": "2024-07-08T07:22:00.0", + "endGMT": "2024-07-08T07:23:00.0", + "activityLevel": 0.6142253834721974, + }, + { + "startGMT": "2024-07-08T07:23:00.0", + "endGMT": "2024-07-08T07:24:00.0", + "activityLevel": 0.618642320229381, + }, + { + "startGMT": "2024-07-08T07:24:00.0", + "endGMT": "2024-07-08T07:25:00.0", + "activityLevel": 0.6251520029231643, + }, + { + "startGMT": "2024-07-08T07:25:00.0", + "endGMT": "2024-07-08T07:26:00.0", + "activityLevel": 0.6345150110190427, + }, + { + "startGMT": "2024-07-08T07:26:00.0", + "endGMT": "2024-07-08T07:27:00.0", + "activityLevel": 0.6468470166184119, + }, + { + "startGMT": "2024-07-08T07:27:00.0", + "endGMT": "2024-07-08T07:28:00.0", + "activityLevel": 0.6615959595193489, + }, + { + "startGMT": "2024-07-08T07:28:00.0", + "endGMT": "2024-07-08T07:29:00.0", + "activityLevel": 0.6776426658024243, + }, + { + "startGMT": "2024-07-08T07:29:00.0", + "endGMT": "2024-07-08T07:30:00.0", + "activityLevel": 0.6934859331903077, + }, + { + "startGMT": "2024-07-08T07:30:00.0", + "endGMT": "2024-07-08T07:31:00.0", + "activityLevel": 0.7074555149099341, + }, + { + "startGMT": "2024-07-08T07:31:00.0", + "endGMT": "2024-07-08T07:32:00.0", + "activityLevel": 0.7179064083707625, + }, + { + "startGMT": "2024-07-08T07:32:00.0", + "endGMT": "2024-07-08T07:33:00.0", + "activityLevel": 0.7233701576546021, + }, + { + "startGMT": "2024-07-08T07:33:00.0", + "endGMT": "2024-07-08T07:34:00.0", + "activityLevel": 0.7254092099030423, + }, + { + "startGMT": "2024-07-08T07:34:00.0", + "endGMT": "2024-07-08T07:35:00.0", + "activityLevel": 0.7172048571772252, + }, + { + "startGMT": "2024-07-08T07:35:00.0", + "endGMT": "2024-07-08T07:36:00.0", + "activityLevel": 0.7009920079253571, + }, + { + "startGMT": "2024-07-08T07:36:00.0", + "endGMT": "2024-07-08T07:37:00.0", + "activityLevel": 0.6771561111389426, + }, + { + "startGMT": "2024-07-08T07:37:00.0", + "endGMT": "2024-07-08T07:38:00.0", + "activityLevel": 0.6462598602603074, + }, + { + "startGMT": "2024-07-08T07:38:00.0", + "endGMT": "2024-07-08T07:39:00.0", + "activityLevel": 0.6090251009673148, + }, + { + "startGMT": "2024-07-08T07:39:00.0", + "endGMT": "2024-07-08T07:40:00.0", + "activityLevel": 0.5663094634001272, + }, + { + "startGMT": "2024-07-08T07:40:00.0", + "endGMT": "2024-07-08T07:41:00.0", + "activityLevel": 0.519078250062335, + }, + { + "startGMT": "2024-07-08T07:41:00.0", + "endGMT": "2024-07-08T07:42:00.0", + "activityLevel": 0.46837205723195313, + }, + { + "startGMT": "2024-07-08T07:42:00.0", + "endGMT": "2024-07-08T07:43:00.0", + "activityLevel": 0.41527032976647393, + }, + { + "startGMT": "2024-07-08T07:43:00.0", + "endGMT": "2024-07-08T07:44:00.0", + "activityLevel": 0.36085029124805756, + }, + { + "startGMT": "2024-07-08T07:44:00.0", + "endGMT": "2024-07-08T07:45:00.0", + "activityLevel": 0.31257743771999924, + }, + { + "startGMT": "2024-07-08T07:45:00.0", + "endGMT": "2024-07-08T07:46:00.0", + "activityLevel": 0.25845239415428134, + }, + { + "startGMT": "2024-07-08T07:46:00.0", + "endGMT": "2024-07-08T07:47:00.0", + "activityLevel": 0.19645263730790685, + }, + { + "startGMT": "2024-07-08T07:47:00.0", + "endGMT": "2024-07-08T07:48:00.0", + "activityLevel": 0.15293509963778754, + }, + { + "startGMT": "2024-07-08T07:48:00.0", + "endGMT": "2024-07-08T07:49:00.0", + "activityLevel": 0.1349333939486886, + }, + { + "startGMT": "2024-07-08T07:49:00.0", + "endGMT": "2024-07-08T07:50:00.0", + "activityLevel": 0.15293509963778754, + }, + { + "startGMT": "2024-07-08T07:50:00.0", + "endGMT": "2024-07-08T07:51:00.0", + "activityLevel": 0.19645263730790685, + }, + { + "startGMT": "2024-07-08T07:51:00.0", + "endGMT": "2024-07-08T07:52:00.0", + "activityLevel": 0.25845239415428134, + }, + { + "startGMT": "2024-07-08T07:52:00.0", + "endGMT": "2024-07-08T07:53:00.0", + "activityLevel": 0.31257743771999924, + }, + { + "startGMT": "2024-07-08T07:53:00.0", + "endGMT": "2024-07-08T07:54:00.0", + "activityLevel": 0.35673350819189387, + }, + { + "startGMT": "2024-07-08T07:54:00.0", + "endGMT": "2024-07-08T07:55:00.0", + "activityLevel": 0.4164807928411105, + }, + { + "startGMT": "2024-07-08T07:55:00.0", + "endGMT": "2024-07-08T07:56:00.0", + "activityLevel": 0.4779915212605219, + }, + { + "startGMT": "2024-07-08T07:56:00.0", + "endGMT": "2024-07-08T07:57:00.0", + "activityLevel": 0.5402078955067132, + }, + { + "startGMT": "2024-07-08T07:57:00.0", + "endGMT": "2024-07-08T07:58:00.0", + "activityLevel": 0.6018755551346839, + }, + { + "startGMT": "2024-07-08T07:58:00.0", + "endGMT": "2024-07-08T07:59:00.0", + "activityLevel": 0.6615959595193489, + }, + { + "startGMT": "2024-07-08T07:59:00.0", + "endGMT": "2024-07-08T08:00:00.0", + "activityLevel": 0.7178833202932577, + }, + { + "startGMT": "2024-07-08T08:00:00.0", + "endGMT": "2024-07-08T08:01:00.0", + "activityLevel": 0.769225239038304, + }, + { + "startGMT": "2024-07-08T08:01:00.0", + "endGMT": "2024-07-08T08:02:00.0", + "activityLevel": 0.8141452191951851, + }, + { + "startGMT": "2024-07-08T08:02:00.0", + "endGMT": "2024-07-08T08:03:00.0", + "activityLevel": 0.8512647536184262, + }, + { + "startGMT": "2024-07-08T08:03:00.0", + "endGMT": "2024-07-08T08:04:00.0", + "activityLevel": 0.8793625025095828, + }, + { + "startGMT": "2024-07-08T08:04:00.0", + "endGMT": "2024-07-08T08:05:00.0", + "activityLevel": 0.8974280776845307, + }, + { + "startGMT": "2024-07-08T08:05:00.0", + "endGMT": "2024-07-08T08:06:00.0", + "activityLevel": 0.903073974763895, + }, + { + "startGMT": "2024-07-08T08:06:00.0", + "endGMT": "2024-07-08T08:07:00.0", + "activityLevel": 0.901301143685339, + }, + { + "startGMT": "2024-07-08T08:07:00.0", + "endGMT": "2024-07-08T08:08:00.0", + "activityLevel": 0.8905151534848624, + }, + { + "startGMT": "2024-07-08T08:08:00.0", + "endGMT": "2024-07-08T08:09:00.0", + "activityLevel": 0.8717690635000533, + }, + { + "startGMT": "2024-07-08T08:09:00.0", + "endGMT": "2024-07-08T08:10:00.0", + "activityLevel": 0.846506516634432, + }, + { + "startGMT": "2024-07-08T08:10:00.0", + "endGMT": "2024-07-08T08:11:00.0", + "activityLevel": 0.8164941403249725, + }, + { + "startGMT": "2024-07-08T08:11:00.0", + "endGMT": "2024-07-08T08:12:00.0", + "activityLevel": 0.7837134509928587, + }, + { + "startGMT": "2024-07-08T08:12:00.0", + "endGMT": "2024-07-08T08:13:00.0", + "activityLevel": 0.7502055232473618, + }, + { + "startGMT": "2024-07-08T08:13:00.0", + "endGMT": "2024-07-08T08:14:00.0", + "activityLevel": 0.7178681858883704, + }, + { + "startGMT": "2024-07-08T08:14:00.0", + "endGMT": "2024-07-08T08:15:00.0", + "activityLevel": 0.6882215310559268, + }, + { + "startGMT": "2024-07-08T08:15:00.0", + "endGMT": "2024-07-08T08:16:00.0", + "activityLevel": 0.6651835822921067, + }, + { + "startGMT": "2024-07-08T08:16:00.0", + "endGMT": "2024-07-08T08:17:00.0", + "activityLevel": 0.6424592694424729, + }, + { + "startGMT": "2024-07-08T08:17:00.0", + "endGMT": "2024-07-08T08:18:00.0", + "activityLevel": 0.622261588585103, + }, + { + "startGMT": "2024-07-08T08:18:00.0", + "endGMT": "2024-07-08T08:19:00.0", + "activityLevel": 0.6039137635226606, + }, + { + "startGMT": "2024-07-08T08:19:00.0", + "endGMT": "2024-07-08T08:20:00.0", + "activityLevel": 0.5861572742315906, + }, + { + "startGMT": "2024-07-08T08:20:00.0", + "endGMT": "2024-07-08T08:21:00.0", + "activityLevel": 0.56741586200465, + }, + { + "startGMT": "2024-07-08T08:21:00.0", + "endGMT": "2024-07-08T08:22:00.0", + "activityLevel": 0.5460820999724711, + }, + { + "startGMT": "2024-07-08T08:22:00.0", + "endGMT": "2024-07-08T08:23:00.0", + "activityLevel": 0.5283546468087472, + }, + { + "startGMT": "2024-07-08T08:23:00.0", + "endGMT": "2024-07-08T08:24:00.0", + "activityLevel": 0.4970511935482702, + }, + { + "startGMT": "2024-07-08T08:24:00.0", + "endGMT": "2024-07-08T08:25:00.0", + "activityLevel": 0.4585508407956919, + }, + { + "startGMT": "2024-07-08T08:25:00.0", + "endGMT": "2024-07-08T08:26:00.0", + "activityLevel": 0.4140563280076178, + }, + { + "startGMT": "2024-07-08T08:26:00.0", + "endGMT": "2024-07-08T08:27:00.0", + "activityLevel": 0.3649206345504732, + }, + { + "startGMT": "2024-07-08T08:27:00.0", + "endGMT": "2024-07-08T08:28:00.0", + "activityLevel": 0.31257743771999924, + }, + { + "startGMT": "2024-07-08T08:28:00.0", + "endGMT": "2024-07-08T08:29:00.0", + "activityLevel": 0.25845239415428134, + }, + { + "startGMT": "2024-07-08T08:29:00.0", + "endGMT": "2024-07-08T08:30:00.0", + "activityLevel": 0.2038327145777733, + }, + { + "startGMT": "2024-07-08T08:30:00.0", + "endGMT": "2024-07-08T08:31:00.0", + "activityLevel": 0.1496072881915049, + }, + { + "startGMT": "2024-07-08T08:31:00.0", + "endGMT": "2024-07-08T08:32:00.0", + "activityLevel": 0.09541231786963358, + }, + { + "startGMT": "2024-07-08T08:32:00.0", + "endGMT": "2024-07-08T08:33:00.0", + "activityLevel": 0.03173017524697902, + }, + { + "startGMT": "2024-07-08T08:33:00.0", + "endGMT": "2024-07-08T08:34:00.0", + "activityLevel": 0.0607673517082981, + }, + { + "startGMT": "2024-07-08T08:34:00.0", + "endGMT": "2024-07-08T08:35:00.0", + "activityLevel": 0.01586508762348951, + }, + { + "startGMT": "2024-07-08T08:35:00.0", + "endGMT": "2024-07-08T08:36:00.0", + "activityLevel": 0.04770615893481679, + }, + { + "startGMT": "2024-07-08T08:36:00.0", + "endGMT": "2024-07-08T08:37:00.0", + "activityLevel": 0.07480364409575245, + }, + { + "startGMT": "2024-07-08T08:37:00.0", + "endGMT": "2024-07-08T08:38:00.0", + "activityLevel": 0.10191635728888665, + }, + { + "startGMT": "2024-07-08T08:38:00.0", + "endGMT": "2024-07-08T08:39:00.0", + "activityLevel": 0.12922619707714067, + }, + { + "startGMT": "2024-07-08T08:39:00.0", + "endGMT": "2024-07-08T08:40:00.0", + "activityLevel": 0.15628871885999962, + }, + { + "startGMT": "2024-07-08T08:40:00.0", + "endGMT": "2024-07-08T08:41:00.0", + "activityLevel": 0.1824603172752366, + }, + { + "startGMT": "2024-07-08T08:41:00.0", + "endGMT": "2024-07-08T08:42:00.0", + "activityLevel": 0.2070281640038089, + }, + { + "startGMT": "2024-07-08T08:42:00.0", + "endGMT": "2024-07-08T08:43:00.0", + "activityLevel": 0.22927542039784596, + }, + { + "startGMT": "2024-07-08T08:43:00.0", + "endGMT": "2024-07-08T08:44:00.0", + "activityLevel": 0.2485255967741351, + }, + { + "startGMT": "2024-07-08T08:44:00.0", + "endGMT": "2024-07-08T08:45:00.0", + "activityLevel": 0.2641773234043736, + }, + { + "startGMT": "2024-07-08T08:45:00.0", + "endGMT": "2024-07-08T08:46:00.0", + "activityLevel": 0.275732630261712, + }, + { + "startGMT": "2024-07-08T08:46:00.0", + "endGMT": "2024-07-08T08:47:00.0", + "activityLevel": 0.28281935595538366, + }, + { + "startGMT": "2024-07-08T08:47:00.0", + "endGMT": "2024-07-08T08:48:00.0", + "activityLevel": 0.28520752502874813, + }, + { + "startGMT": "2024-07-08T08:48:00.0", + "endGMT": "2024-07-08T08:49:00.0", + "activityLevel": 0.28281935595538366, + }, + { + "startGMT": "2024-07-08T08:49:00.0", + "endGMT": "2024-07-08T08:50:00.0", + "activityLevel": 0.275732630261712, + }, + { + "startGMT": "2024-07-08T08:50:00.0", + "endGMT": "2024-07-08T08:51:00.0", + "activityLevel": 0.2641773234043736, + }, + { + "startGMT": "2024-07-08T08:51:00.0", + "endGMT": "2024-07-08T08:52:00.0", + "activityLevel": 0.2485255967741351, + }, + { + "startGMT": "2024-07-08T08:52:00.0", + "endGMT": "2024-07-08T08:53:00.0", + "activityLevel": 0.22927542039784596, + }, + { + "startGMT": "2024-07-08T08:53:00.0", + "endGMT": "2024-07-08T08:54:00.0", + "activityLevel": 0.2070281640038089, + }, + { + "startGMT": "2024-07-08T08:54:00.0", + "endGMT": "2024-07-08T08:55:00.0", + "activityLevel": 0.1824603172752366, + }, + { + "startGMT": "2024-07-08T08:55:00.0", + "endGMT": "2024-07-08T08:56:00.0", + "activityLevel": 0.15628871885999962, + }, + { + "startGMT": "2024-07-08T08:56:00.0", + "endGMT": "2024-07-08T08:57:00.0", + "activityLevel": 0.12922619707714067, + }, + { + "startGMT": "2024-07-08T08:57:00.0", + "endGMT": "2024-07-08T08:58:00.0", + "activityLevel": 0.10191635728888665, + }, + { + "startGMT": "2024-07-08T08:58:00.0", + "endGMT": "2024-07-08T08:59:00.0", + "activityLevel": 0.07480364409575245, + }, + { + "startGMT": "2024-07-08T08:59:00.0", + "endGMT": "2024-07-08T09:00:00.0", + "activityLevel": 0.04770615893481679, + }, + { + "startGMT": "2024-07-08T09:00:00.0", + "endGMT": "2024-07-08T09:01:00.0", + "activityLevel": 0.01586508762348951, + }, + { + "startGMT": "2024-07-08T09:01:00.0", + "endGMT": "2024-07-08T09:02:00.0", + "activityLevel": 0.027175985846478505, + }, + { + "startGMT": "2024-07-08T09:02:00.0", + "endGMT": "2024-07-08T09:03:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T09:03:00.0", + "endGMT": "2024-07-08T09:04:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T09:04:00.0", + "endGMT": "2024-07-08T09:05:00.0", + "activityLevel": 0.027175985846478505, + }, + { + "startGMT": "2024-07-08T09:05:00.0", + "endGMT": "2024-07-08T09:06:00.0", + "activityLevel": 0.01586508762348951, + }, + { + "startGMT": "2024-07-08T09:06:00.0", + "endGMT": "2024-07-08T09:07:00.0", + "activityLevel": 0.04770615893481679, + }, + { + "startGMT": "2024-07-08T09:07:00.0", + "endGMT": "2024-07-08T09:08:00.0", + "activityLevel": 0.07480364409575245, + }, + { + "startGMT": "2024-07-08T09:08:00.0", + "endGMT": "2024-07-08T09:09:00.0", + "activityLevel": 0.10191635728888665, + }, + { + "startGMT": "2024-07-08T09:09:00.0", + "endGMT": "2024-07-08T09:10:00.0", + "activityLevel": 0.12922619707714067, + }, + { + "startGMT": "2024-07-08T09:10:00.0", + "endGMT": "2024-07-08T09:11:00.0", + "activityLevel": 0.15628871885999962, + }, + { + "startGMT": "2024-07-08T09:11:00.0", + "endGMT": "2024-07-08T09:12:00.0", + "activityLevel": 0.1824603172752366, + }, + { + "startGMT": "2024-07-08T09:12:00.0", + "endGMT": "2024-07-08T09:13:00.0", + "activityLevel": 0.2070281640038089, + }, + { + "startGMT": "2024-07-08T09:13:00.0", + "endGMT": "2024-07-08T09:14:00.0", + "activityLevel": 0.22927542039784596, + }, + { + "startGMT": "2024-07-08T09:14:00.0", + "endGMT": "2024-07-08T09:15:00.0", + "activityLevel": 0.2485255967741351, + }, + { + "startGMT": "2024-07-08T09:15:00.0", + "endGMT": "2024-07-08T09:16:00.0", + "activityLevel": 0.2641773234043736, + }, + { + "startGMT": "2024-07-08T09:16:00.0", + "endGMT": "2024-07-08T09:17:00.0", + "activityLevel": 0.275732630261712, + }, + { + "startGMT": "2024-07-08T09:17:00.0", + "endGMT": "2024-07-08T09:18:00.0", + "activityLevel": 0.28281935595538366, + }, + { + "startGMT": "2024-07-08T09:18:00.0", + "endGMT": "2024-07-08T09:19:00.0", + "activityLevel": 0.28520752502874813, + }, + { + "startGMT": "2024-07-08T09:19:00.0", + "endGMT": "2024-07-08T09:20:00.0", + "activityLevel": 0.28281935595538366, + }, + { + "startGMT": "2024-07-08T09:20:00.0", + "endGMT": "2024-07-08T09:21:00.0", + "activityLevel": 0.275732630261712, + }, + { + "startGMT": "2024-07-08T09:21:00.0", + "endGMT": "2024-07-08T09:22:00.0", + "activityLevel": 0.2641773234043736, + }, + { + "startGMT": "2024-07-08T09:22:00.0", + "endGMT": "2024-07-08T09:23:00.0", + "activityLevel": 0.2485255967741351, + }, + { + "startGMT": "2024-07-08T09:23:00.0", + "endGMT": "2024-07-08T09:24:00.0", + "activityLevel": 0.22927542039784596, + }, + { + "startGMT": "2024-07-08T09:24:00.0", + "endGMT": "2024-07-08T09:25:00.0", + "activityLevel": 0.2070281640038089, + }, + { + "startGMT": "2024-07-08T09:25:00.0", + "endGMT": "2024-07-08T09:26:00.0", + "activityLevel": 0.1824603172752366, + }, + { + "startGMT": "2024-07-08T09:26:00.0", + "endGMT": "2024-07-08T09:27:00.0", + "activityLevel": 0.15628871885999962, + }, + { + "startGMT": "2024-07-08T09:27:00.0", + "endGMT": "2024-07-08T09:28:00.0", + "activityLevel": 0.12922619707714067, + }, + { + "startGMT": "2024-07-08T09:28:00.0", + "endGMT": "2024-07-08T09:29:00.0", + "activityLevel": 0.10191635728888665, + }, + { + "startGMT": "2024-07-08T09:29:00.0", + "endGMT": "2024-07-08T09:30:00.0", + "activityLevel": 0.07480364409575245, + }, + { + "startGMT": "2024-07-08T09:30:00.0", + "endGMT": "2024-07-08T09:31:00.0", + "activityLevel": 0.04770615893481679, + }, + { + "startGMT": "2024-07-08T09:31:00.0", + "endGMT": "2024-07-08T09:32:00.0", + "activityLevel": 0.01586508762348951, + }, + { + "startGMT": "2024-07-08T09:32:00.0", + "endGMT": "2024-07-08T09:33:00.0", + "activityLevel": 0.027175985846478505, + }, + { + "startGMT": "2024-07-08T09:33:00.0", + "endGMT": "2024-07-08T09:34:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T09:34:00.0", + "endGMT": "2024-07-08T09:35:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T09:35:00.0", + "endGMT": "2024-07-08T09:36:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T09:36:00.0", + "endGMT": "2024-07-08T09:37:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T09:37:00.0", + "endGMT": "2024-07-08T09:38:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T09:38:00.0", + "endGMT": "2024-07-08T09:39:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T09:39:00.0", + "endGMT": "2024-07-08T09:40:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T09:40:00.0", + "endGMT": "2024-07-08T09:41:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T09:41:00.0", + "endGMT": "2024-07-08T09:42:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T09:42:00.0", + "endGMT": "2024-07-08T09:43:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T09:43:00.0", + "endGMT": "2024-07-08T09:44:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T09:44:00.0", + "endGMT": "2024-07-08T09:45:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T09:45:00.0", + "endGMT": "2024-07-08T09:46:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T09:46:00.0", + "endGMT": "2024-07-08T09:47:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T09:47:00.0", + "endGMT": "2024-07-08T09:48:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T09:48:00.0", + "endGMT": "2024-07-08T09:49:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T09:49:00.0", + "endGMT": "2024-07-08T09:50:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T09:50:00.0", + "endGMT": "2024-07-08T09:51:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T09:51:00.0", + "endGMT": "2024-07-08T09:52:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T09:52:00.0", + "endGMT": "2024-07-08T09:53:00.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T09:53:00.0", + "endGMT": "2024-07-08T09:54:00.0", + "activityLevel": 0.07686529550989835, + }, + { + "startGMT": "2024-07-08T09:54:00.0", + "endGMT": "2024-07-08T09:55:00.0", + "activityLevel": 0.0448732441707528, + }, + { + "startGMT": "2024-07-08T09:55:00.0", + "endGMT": "2024-07-08T09:56:00.0", + "activityLevel": 0.1349333939486886, + }, + { + "startGMT": "2024-07-08T09:56:00.0", + "endGMT": "2024-07-08T09:57:00.0", + "activityLevel": 0.2115766559902864, + }, + { + "startGMT": "2024-07-08T09:57:00.0", + "endGMT": "2024-07-08T09:58:00.0", + "activityLevel": 0.2882629894112111, + }, + { + "startGMT": "2024-07-08T09:58:00.0", + "endGMT": "2024-07-08T09:59:00.0", + "activityLevel": 0.3655068810407815, + }, + { + "startGMT": "2024-07-08T09:59:00.0", + "endGMT": "2024-07-08T10:00:00.0", + "activityLevel": 0.4420512517154544, + }, + { + "startGMT": "2024-07-08T10:00:00.0", + "endGMT": "2024-07-08T10:01:00.0", + "activityLevel": 0.516075710571075, + }, + { + "startGMT": "2024-07-08T10:01:00.0", + "endGMT": "2024-07-08T10:02:00.0", + "activityLevel": 0.5855640746547759, + }, + { + "startGMT": "2024-07-08T10:02:00.0", + "endGMT": "2024-07-08T10:03:00.0", + "activityLevel": 0.6484888180908535, + }, + { + "startGMT": "2024-07-08T10:03:00.0", + "endGMT": "2024-07-08T10:04:00.0", + "activityLevel": 0.702936539109698, + }, + { + "startGMT": "2024-07-08T10:04:00.0", + "endGMT": "2024-07-08T10:05:00.0", + "activityLevel": 0.7472063072597769, + }, + { + "startGMT": "2024-07-08T10:05:00.0", + "endGMT": "2024-07-08T10:06:00.0", + "activityLevel": 0.7798896506098385, + }, + { + "startGMT": "2024-07-08T10:06:00.0", + "endGMT": "2024-07-08T10:07:00.0", + "activityLevel": 0.7962323977145869, + }, + { + "startGMT": "2024-07-08T10:07:00.0", + "endGMT": "2024-07-08T10:08:00.0", + "activityLevel": 0.8042710942541551, + }, + { + "startGMT": "2024-07-08T10:08:00.0", + "endGMT": "2024-07-08T10:09:00.0", + "activityLevel": 0.8124745741677484, + }, + { + "startGMT": "2024-07-08T10:09:00.0", + "endGMT": "2024-07-08T10:10:00.0", + "activityLevel": 0.8192677030683438, + }, + { + "startGMT": "2024-07-08T10:10:00.0", + "endGMT": "2024-07-08T10:11:00.0", + "activityLevel": 0.8283583150020962, + }, + { + "startGMT": "2024-07-08T10:11:00.0", + "endGMT": "2024-07-08T10:12:00.0", + "activityLevel": 0.8360586473808641, + }, + { + "startGMT": "2024-07-08T10:12:00.0", + "endGMT": "2024-07-08T10:13:00.0", + "activityLevel": 0.8612508375597668, + }, + { + "startGMT": "2024-07-08T10:13:00.0", + "endGMT": "2024-07-08T10:14:00.0", + "activityLevel": 0.8931986353382947, + }, + { + "startGMT": "2024-07-08T10:14:00.0", + "endGMT": "2024-07-08T10:15:00.0", + "activityLevel": 1.0028904650887294, + }, + { + "startGMT": "2024-07-08T10:15:00.0", + "endGMT": "2024-07-08T10:16:00.0", + "activityLevel": 1.1475931334673173, + }, + { + "startGMT": "2024-07-08T10:16:00.0", + "endGMT": "2024-07-08T10:17:00.0", + "activityLevel": 1.358310949374774, + }, + { + "startGMT": "2024-07-08T10:17:00.0", + "endGMT": "2024-07-08T10:18:00.0", + "activityLevel": 1.6316661380057063, + }, + { + "startGMT": "2024-07-08T10:18:00.0", + "endGMT": "2024-07-08T10:19:00.0", + "activityLevel": 1.9692171001776986, + }, + { + "startGMT": "2024-07-08T10:19:00.0", + "endGMT": "2024-07-08T10:20:00.0", + "activityLevel": 2.340081573322653, + }, + { + "startGMT": "2024-07-08T10:20:00.0", + "endGMT": "2024-07-08T10:21:00.0", + "activityLevel": 2.725034226599384, + }, + { + "startGMT": "2024-07-08T10:21:00.0", + "endGMT": "2024-07-08T10:22:00.0", + "activityLevel": 3.1275206640940922, + }, + { + "startGMT": "2024-07-08T10:22:00.0", + "endGMT": "2024-07-08T10:23:00.0", + "activityLevel": 3.5406211235211957, + }, + { + "startGMT": "2024-07-08T10:23:00.0", + "endGMT": "2024-07-08T10:24:00.0", + "activityLevel": 3.9588062068049887, + }, + { + "startGMT": "2024-07-08T10:24:00.0", + "endGMT": "2024-07-08T10:25:00.0", + "activityLevel": 4.361745599369039, + }, + { + "startGMT": "2024-07-08T10:25:00.0", + "endGMT": "2024-07-08T10:26:00.0", + "activityLevel": 4.753375301969818, + }, + { + "startGMT": "2024-07-08T10:26:00.0", + "endGMT": "2024-07-08T10:27:00.0", + "activityLevel": 5.119252838888224, + }, + { + "startGMT": "2024-07-08T10:27:00.0", + "endGMT": "2024-07-08T10:28:00.0", + "activityLevel": 5.448264351748779, + }, + { + "startGMT": "2024-07-08T10:28:00.0", + "endGMT": "2024-07-08T10:29:00.0", + "activityLevel": 5.744688055401102, + }, + { + "startGMT": "2024-07-08T10:29:00.0", + "endGMT": "2024-07-08T10:30:00.0", + "activityLevel": 5.99753575679536, + }, + { + "startGMT": "2024-07-08T10:30:00.0", + "endGMT": "2024-07-08T10:31:00.0", + "activityLevel": 6.202295450727306, + }, + { + "startGMT": "2024-07-08T10:31:00.0", + "endGMT": "2024-07-08T10:32:00.0", + "activityLevel": 6.3555949112142525, + }, + { + "startGMT": "2024-07-08T10:32:00.0", + "endGMT": "2024-07-08T10:33:00.0", + "activityLevel": 6.455280652427611, + }, + { + "startGMT": "2024-07-08T10:33:00.0", + "endGMT": "2024-07-08T10:34:00.0", + "activityLevel": 6.500461886729058, + }, + { + "startGMT": "2024-07-08T10:34:00.0", + "endGMT": "2024-07-08T10:35:00.0", + "activityLevel": 6.491975731253427, + }, + { + "startGMT": "2024-07-08T10:35:00.0", + "endGMT": "2024-07-08T10:36:00.0", + "activityLevel": 6.4307833174597135, + }, + { + "startGMT": "2024-07-08T10:36:00.0", + "endGMT": "2024-07-08T10:37:00.0", + "activityLevel": 6.318869199067785, + }, + { + "startGMT": "2024-07-08T10:37:00.0", + "endGMT": "2024-07-08T10:38:00.0", + "activityLevel": 6.158852858184711, + }, + { + "startGMT": "2024-07-08T10:38:00.0", + "endGMT": "2024-07-08T10:39:00.0", + "activityLevel": 5.955719049228967, + }, + { + "startGMT": "2024-07-08T10:39:00.0", + "endGMT": "2024-07-08T10:40:00.0", + "activityLevel": 5.714703785071322, + }, + { + "startGMT": "2024-07-08T10:40:00.0", + "endGMT": "2024-07-08T10:41:00.0", + "activityLevel": 5.439031865941106, + }, + { + "startGMT": "2024-07-08T10:41:00.0", + "endGMT": "2024-07-08T10:42:00.0", + "activityLevel": 5.147138408507956, + }, + { + "startGMT": "2024-07-08T10:42:00.0", + "endGMT": "2024-07-08T10:43:00.0", + "activityLevel": 4.847876630473029, + }, + { + "startGMT": "2024-07-08T10:43:00.0", + "endGMT": "2024-07-08T10:44:00.0", + "activityLevel": 4.536134945409765, + }, + { + "startGMT": "2024-07-08T10:44:00.0", + "endGMT": "2024-07-08T10:45:00.0", + "activityLevel": 4.24416929713549, + }, + { + "startGMT": "2024-07-08T10:45:00.0", + "endGMT": "2024-07-08T10:46:00.0", + "activityLevel": 3.9924448274697677, + }, + { + "startGMT": "2024-07-08T10:46:00.0", + "endGMT": "2024-07-08T10:47:00.0", + "activityLevel": 3.7918004538380656, + }, + { + "startGMT": "2024-07-08T10:47:00.0", + "endGMT": "2024-07-08T10:48:00.0", + "activityLevel": 3.6512674437920847, + }, + { + "startGMT": "2024-07-08T10:48:00.0", + "endGMT": "2024-07-08T10:49:00.0", + "activityLevel": 3.584620461930404, + }, + { + "startGMT": "2024-07-08T10:49:00.0", + "endGMT": "2024-07-08T10:50:00.0", + "activityLevel": 3.5990230099206846, + }, + { + "startGMT": "2024-07-08T10:50:00.0", + "endGMT": "2024-07-08T10:51:00.0", + "activityLevel": 3.674984075963328, + }, + { + "startGMT": "2024-07-08T10:51:00.0", + "endGMT": "2024-07-08T10:52:00.0", + "activityLevel": 3.7917730103054015, + }, + { + "startGMT": "2024-07-08T10:52:00.0", + "endGMT": "2024-07-08T10:53:00.0", + "activityLevel": 3.9213390099934085, + }, + { + "startGMT": "2024-07-08T10:53:00.0", + "endGMT": "2024-07-08T10:54:00.0", + "activityLevel": 4.055291331031145, + }, + { + "startGMT": "2024-07-08T10:54:00.0", + "endGMT": "2024-07-08T10:55:00.0", + "activityLevel": 4.164815193371208, + }, + { + "startGMT": "2024-07-08T10:55:00.0", + "endGMT": "2024-07-08T10:56:00.0", + "activityLevel": 4.242608873995664, + }, + { + "startGMT": "2024-07-08T10:56:00.0", + "endGMT": "2024-07-08T10:57:00.0", + "activityLevel": 4.285332348673107, + }, + { + "startGMT": "2024-07-08T10:57:00.0", + "endGMT": "2024-07-08T10:58:00.0", + "activityLevel": 4.274079702441345, + }, + { + "startGMT": "2024-07-08T10:58:00.0", + "endGMT": "2024-07-08T10:59:00.0", + "activityLevel": 4.212809157336095, + }, + { + "startGMT": "2024-07-08T10:59:00.0", + "endGMT": "2024-07-08T11:00:00.0", + "activityLevel": 4.103002510680104, + }, + { + "startGMT": "2024-07-08T11:00:00.0", + "endGMT": "2024-07-08T11:01:00.0", + "activityLevel": 3.9484775387293265, + }, + { + "startGMT": "2024-07-08T11:01:00.0", + "endGMT": "2024-07-08T11:02:00.0", + "activityLevel": 3.7552774472343597, + }, + { + "startGMT": "2024-07-08T11:02:00.0", + "endGMT": "2024-07-08T11:03:00.0", + "activityLevel": 3.5315135300455616, + }, + { + "startGMT": "2024-07-08T11:03:00.0", + "endGMT": "2024-07-08T11:04:00.0", + "activityLevel": 3.2791977894871196, + }, + { + "startGMT": "2024-07-08T11:04:00.0", + "endGMT": "2024-07-08T11:05:00.0", + "activityLevel": 3.027222392705982, + }, + { + "startGMT": "2024-07-08T11:05:00.0", + "endGMT": "2024-07-08T11:06:00.0", + "activityLevel": 2.801379125353849, + }, + { + "startGMT": "2024-07-08T11:06:00.0", + "endGMT": "2024-07-08T11:07:00.0", + "activityLevel": 2.643352285387023, + }, + { + "startGMT": "2024-07-08T11:07:00.0", + "endGMT": "2024-07-08T11:08:00.0", + "activityLevel": 2.5608249575455866, + }, + { + "startGMT": "2024-07-08T11:08:00.0", + "endGMT": "2024-07-08T11:09:00.0", + "activityLevel": 2.5885196981247356, + }, + { + "startGMT": "2024-07-08T11:09:00.0", + "endGMT": "2024-07-08T11:10:00.0", + "activityLevel": 2.74385322203688, + }, + { + "startGMT": "2024-07-08T11:10:00.0", + "endGMT": "2024-07-08T11:11:00.0", + "activityLevel": 2.9894334635828512, + }, + { + "startGMT": "2024-07-08T11:11:00.0", + "endGMT": "2024-07-08T11:12:00.0", + "activityLevel": 3.313357211851606, + }, + { + "startGMT": "2024-07-08T11:12:00.0", + "endGMT": "2024-07-08T11:13:00.0", + "activityLevel": 3.7000375630578843, + }, + { + "startGMT": "2024-07-08T11:13:00.0", + "endGMT": "2024-07-08T11:14:00.0", + "activityLevel": 4.11680080737648, + }, + { + "startGMT": "2024-07-08T11:14:00.0", + "endGMT": "2024-07-08T11:15:00.0", + "activityLevel": 4.539146075899416, + }, + { + "startGMT": "2024-07-08T11:15:00.0", + "endGMT": "2024-07-08T11:16:00.0", + "activityLevel": 4.961953721222002, + }, + { + "startGMT": "2024-07-08T11:16:00.0", + "endGMT": "2024-07-08T11:17:00.0", + "activityLevel": 5.374999768764193, + }, + { + "startGMT": "2024-07-08T11:17:00.0", + "endGMT": "2024-07-08T11:18:00.0", + "activityLevel": 5.7713868984932155, + }, + { + "startGMT": "2024-07-08T11:18:00.0", + "endGMT": "2024-07-08T11:19:00.0", + "activityLevel": 6.143863876841869, + }, + { + "startGMT": "2024-07-08T11:19:00.0", + "endGMT": "2024-07-08T11:20:00.0", + "activityLevel": 6.48686139548907, + }, + { + "startGMT": "2024-07-08T11:20:00.0", + "endGMT": "2024-07-08T11:21:00.0", + "activityLevel": 6.796272400617864, + }, + ], + "remSleepData": true, + "sleepLevels": [ + { + "startGMT": "2024-07-08T01:58:45.0", + "endGMT": "2024-07-08T02:15:45.0", + "activityLevel": 1.0, + }, + { + "startGMT": "2024-07-08T02:15:45.0", + "endGMT": "2024-07-08T02:21:45.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T02:21:45.0", + "endGMT": "2024-07-08T02:28:45.0", + "activityLevel": 1.0, + }, + { + "startGMT": "2024-07-08T02:28:45.0", + "endGMT": "2024-07-08T02:44:45.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T02:44:45.0", + "endGMT": "2024-07-08T02:45:45.0", + "activityLevel": 3.0, + }, + { + "startGMT": "2024-07-08T02:45:45.0", + "endGMT": "2024-07-08T03:06:45.0", + "activityLevel": 1.0, + }, + { + "startGMT": "2024-07-08T03:06:45.0", + "endGMT": "2024-07-08T03:12:45.0", + "activityLevel": 3.0, + }, + { + "startGMT": "2024-07-08T03:12:45.0", + "endGMT": "2024-07-08T03:20:45.0", + "activityLevel": 1.0, + }, + { + "startGMT": "2024-07-08T03:20:45.0", + "endGMT": "2024-07-08T03:42:45.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T03:42:45.0", + "endGMT": "2024-07-08T03:53:45.0", + "activityLevel": 1.0, + }, + { + "startGMT": "2024-07-08T03:53:45.0", + "endGMT": "2024-07-08T04:04:45.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T04:04:45.0", + "endGMT": "2024-07-08T05:12:45.0", + "activityLevel": 1.0, + }, + { + "startGMT": "2024-07-08T05:12:45.0", + "endGMT": "2024-07-08T05:27:45.0", + "activityLevel": 2.0, + }, + { + "startGMT": "2024-07-08T05:27:45.0", + "endGMT": "2024-07-08T05:51:45.0", + "activityLevel": 1.0, + }, + { + "startGMT": "2024-07-08T05:51:45.0", + "endGMT": "2024-07-08T06:11:45.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T06:11:45.0", + "endGMT": "2024-07-08T07:07:45.0", + "activityLevel": 1.0, + }, + { + "startGMT": "2024-07-08T07:07:45.0", + "endGMT": "2024-07-08T07:18:45.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T07:18:45.0", + "endGMT": "2024-07-08T07:21:45.0", + "activityLevel": 3.0, + }, + { + "startGMT": "2024-07-08T07:21:45.0", + "endGMT": "2024-07-08T07:32:45.0", + "activityLevel": 1.0, + }, + { + "startGMT": "2024-07-08T07:32:45.0", + "endGMT": "2024-07-08T08:15:45.0", + "activityLevel": 2.0, + }, + { + "startGMT": "2024-07-08T08:15:45.0", + "endGMT": "2024-07-08T08:27:45.0", + "activityLevel": 1.0, + }, + { + "startGMT": "2024-07-08T08:27:45.0", + "endGMT": "2024-07-08T08:47:45.0", + "activityLevel": 0.0, + }, + { + "startGMT": "2024-07-08T08:47:45.0", + "endGMT": "2024-07-08T09:12:45.0", + "activityLevel": 1.0, + }, + { + "startGMT": "2024-07-08T09:12:45.0", + "endGMT": "2024-07-08T09:33:45.0", + "activityLevel": 2.0, + }, + { + "startGMT": "2024-07-08T09:33:45.0", + "endGMT": "2024-07-08T09:44:45.0", + "activityLevel": 1.0, + }, + { + "startGMT": "2024-07-08T09:44:45.0", + "endGMT": "2024-07-08T10:21:45.0", + "activityLevel": 2.0, + }, + ], + "sleepRestlessMoments": [ + {"value": 1, "startGMT": 1720404285000}, + {"value": 1, "startGMT": 1720406445000}, + {"value": 2, "startGMT": 1720407705000}, + {"value": 1, "startGMT": 1720407885000}, + {"value": 1, "startGMT": 1720410045000}, + {"value": 1, "startGMT": 1720411305000}, + {"value": 1, "startGMT": 1720412745000}, + {"value": 1, "startGMT": 1720414365000}, + {"value": 1, "startGMT": 1720414725000}, + {"value": 1, "startGMT": 1720415265000}, + {"value": 1, "startGMT": 1720415445000}, + {"value": 1, "startGMT": 1720415805000}, + {"value": 1, "startGMT": 1720416345000}, + {"value": 1, "startGMT": 1720417065000}, + {"value": 1, "startGMT": 1720420665000}, + {"value": 1, "startGMT": 1720421205000}, + {"value": 1, "startGMT": 1720421745000}, + {"value": 1, "startGMT": 1720423005000}, + {"value": 1, "startGMT": 1720423545000}, + {"value": 1, "startGMT": 1720424085000}, + {"value": 1, "startGMT": 1720425525000}, + {"value": 1, "startGMT": 1720425885000}, + {"value": 1, "startGMT": 1720426605000}, + {"value": 1, "startGMT": 1720428225000}, + {"value": 1, "startGMT": 1720428945000}, + {"value": 1, "startGMT": 1720432005000}, + {"value": 1, "startGMT": 1720433085000}, + {"value": 1, "startGMT": 1720433985000}, + ], + "restlessMomentsCount": 29, + "wellnessSpO2SleepSummaryDTO": { + "userProfilePk": "user_id: int", + "deviceId": 3472661486, + "sleepMeasurementStartGMT": "2024-07-08T02:00:00.0", + "sleepMeasurementEndGMT": "2024-07-08T10:21:00.0", + "alertThresholdValue": null, + "numberOfEventsBelowThreshold": null, + "durationOfEventsBelowThreshold": null, + "averageSPO2": 95.0, + "averageSpO2HR": 42.0, + "lowestSPO2": 89, + }, + "wellnessEpochSPO2DataDTOList": [ + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:00:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 8, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:01:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 9, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:02:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:03:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:04:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:05:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:06:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:07:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 15, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:08:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:09:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 10, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:10:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:11:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:12:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:13:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:14:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:15:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:16:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:17:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:18:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:19:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:20:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:21:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:22:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:23:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:24:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:25:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:26:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:27:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:28:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:29:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:30:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:31:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:32:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:33:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:34:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:35:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:36:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:37:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:38:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:39:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:40:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:41:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:42:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:43:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:44:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:45:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:46:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:47:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:48:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 91, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:49:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:50:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:51:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:52:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:53:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:54:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:55:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:56:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:57:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:58:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T02:59:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:00:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:01:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:02:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:03:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 91, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:04:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:05:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:06:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:07:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:08:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 8, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:09:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:10:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:11:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 7, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:12:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:13:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:14:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:15:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:16:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:17:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:18:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 9, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:19:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:20:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:21:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:22:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:23:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:24:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:25:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:26:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 9, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:27:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:28:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:29:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:30:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:31:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:32:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:33:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:34:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:35:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:36:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:37:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:38:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:39:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:40:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:41:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:42:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:43:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:44:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 17, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:45:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:46:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 11, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:47:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:48:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 17, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:49:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:50:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 11, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:51:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:52:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 7, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:53:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:54:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:55:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:56:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:57:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:58:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T03:59:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:00:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-07T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 91, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:01:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:02:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 7, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:03:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 13, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:04:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:05:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 7, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:06:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:07:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:08:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:09:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:10:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:11:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:12:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:13:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 7, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:14:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:15:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:16:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:17:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:18:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:19:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:20:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:21:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 7, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:22:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:23:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:24:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:25:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:26:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:27:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 7, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:28:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:29:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 13, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:30:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 25, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:31:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:32:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 12, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:33:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 8, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:34:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 14, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:35:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 9, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:36:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:37:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 10, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:38:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:39:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:40:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:41:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:42:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:43:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:44:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 10, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:45:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:46:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:47:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:48:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:49:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 8, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:50:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:51:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:52:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:53:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 15, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:54:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:55:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 8, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:56:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:57:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:58:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T04:59:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:00:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 11, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:01:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:02:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 16, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:03:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 17, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:04:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 17, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:05:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:06:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 10, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:07:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:08:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 9, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:09:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:10:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:11:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:12:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:13:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 15, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:14:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:15:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:16:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:17:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 8, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:18:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:19:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:20:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:21:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:22:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:23:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:24:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:25:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:26:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:27:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:28:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:29:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:30:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:31:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 8, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:32:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:33:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:34:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 9, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:35:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:36:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:37:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 8, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:38:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:39:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:40:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:41:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:42:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:43:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:44:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:45:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:46:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:47:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:48:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:49:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 91, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:50:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 90, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:51:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 90, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:52:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:53:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:54:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:55:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 90, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:56:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 90, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:57:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:58:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T05:59:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:00:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 11, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:01:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 91, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:02:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:03:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:04:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:05:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:06:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:07:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 7, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:08:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:09:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:10:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:11:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 8, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:12:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:13:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:14:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 91, + "readingConfidence": 8, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:15:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:16:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 91, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:17:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 91, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:18:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 8, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:19:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:20:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:21:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:22:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:23:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:24:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:25:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:26:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:27:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:28:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:29:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:30:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:31:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:32:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:33:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:34:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 7, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:35:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:36:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:37:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:38:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:39:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:40:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:41:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:42:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:43:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:44:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:45:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 91, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:46:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 89, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:47:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 89, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:48:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 89, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:49:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:50:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:51:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:52:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:53:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:54:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 98, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:55:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 98, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:56:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 7, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:57:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:58:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T06:59:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:00:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 98, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:01:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 7, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:02:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 7, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:03:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:04:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 98, + "readingConfidence": 22, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:05:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 11, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:06:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 9, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:07:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:08:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:09:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:10:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:11:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 8, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:12:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 98, + "readingConfidence": 23, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:13:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:14:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:15:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 98, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:16:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 98, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:17:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:18:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:19:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:20:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 7, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:21:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:22:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:23:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:24:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 9, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:25:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:26:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 9, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:27:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:28:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:29:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 11, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:30:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:31:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:32:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:33:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:34:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:35:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:36:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:37:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:38:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:39:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 11, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:40:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:41:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:42:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:43:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 7, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:44:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 7, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:45:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:46:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 98, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:47:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:48:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 9, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:49:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 98, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:50:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 7, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:51:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:52:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:53:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:54:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:55:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:56:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 92, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:57:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:58:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T07:59:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:00:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:01:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:02:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:03:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:04:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:05:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:06:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:07:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:08:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:09:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:10:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:11:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:12:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:13:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:14:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:15:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:16:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 13, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:17:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:18:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:19:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:20:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:21:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 98, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:22:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:23:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:24:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:25:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:26:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:27:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 7, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:28:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:29:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:30:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:31:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:32:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 8, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:33:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:34:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 9, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:35:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:36:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:37:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 20, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:38:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:39:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:40:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 98, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:41:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:42:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:43:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 98, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:44:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:45:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 98, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:46:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 98, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:47:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:48:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:49:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:50:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:51:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:52:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:53:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:54:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:55:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:56:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:57:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:58:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T08:59:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:00:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 98, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:01:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:02:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:03:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:04:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:05:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 98, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:06:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 98, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:07:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 98, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:08:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:09:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:10:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:11:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:12:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 11, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:13:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 8, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:14:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 8, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:15:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:16:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:17:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:18:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:19:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 98, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:20:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:21:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:22:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:23:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:24:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:25:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:26:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:27:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:28:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:29:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:30:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:31:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:32:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:33:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:34:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:35:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:36:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:37:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:38:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:39:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:40:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:41:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:42:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:43:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:44:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:45:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:46:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:47:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:48:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:49:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 95, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:50:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 96, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:51:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:52:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:53:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:54:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:55:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:56:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 2, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:57:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 24, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:58:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 8, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T09:59:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T10:00:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 98, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T10:01:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T10:02:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T10:03:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T10:04:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T10:05:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T10:06:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T10:07:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 99, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T10:08:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 100, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T10:09:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 97, + "readingConfidence": 6, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T10:10:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 90, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T10:11:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 5, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T10:12:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T10:13:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T10:14:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 94, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T10:15:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T10:16:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 3, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T10:17:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T10:18:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 91, + "readingConfidence": 4, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T10:19:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 11, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T10:20:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 93, + "readingConfidence": 9, + }, + { + "userProfilePK": "user_id: int", + "epochTimestamp": "2024-07-08T10:21:00.0", + "deviceId": 3472661486, + "calendarDate": "2024-07-08T00:00:00.0", + "epochDuration": 60, + "spo2Reading": 98, + "readingConfidence": 5, + }, + ], + "wellnessEpochRespirationDataDTOList": [ + { + "startTimeGMT": 1720403925000, + "respirationValue": 11.0, + }, + { + "startTimeGMT": 1720404000000, + "respirationValue": 12.0, + }, + { + "startTimeGMT": 1720404120000, + "respirationValue": 13.0, + }, + { + "startTimeGMT": 1720404240000, + "respirationValue": 13.0, + }, + { + "startTimeGMT": 1720404360000, + "respirationValue": 14.0, + }, + { + "startTimeGMT": 1720404480000, + "respirationValue": 16.0, + }, + { + "startTimeGMT": 1720404600000, + "respirationValue": 16.0, + }, + { + "startTimeGMT": 1720404720000, + "respirationValue": 16.0, + }, + { + "startTimeGMT": 1720404840000, + "respirationValue": 17.0, + }, + { + "startTimeGMT": 1720404960000, + "respirationValue": 20.0, + }, + { + "startTimeGMT": 1720405080000, + "respirationValue": 20.0, + }, + { + "startTimeGMT": 1720405200000, + "respirationValue": 20.0, + }, + { + "startTimeGMT": 1720405320000, + "respirationValue": 20.0, + }, + { + "startTimeGMT": 1720405440000, + "respirationValue": 21.0, + }, + { + "startTimeGMT": 1720405560000, + "respirationValue": 21.0, + }, + { + "startTimeGMT": 1720405680000, + "respirationValue": 20.0, + }, + { + "startTimeGMT": 1720405800000, + "respirationValue": 20.0, + }, + { + "startTimeGMT": 1720405920000, + "respirationValue": 20.0, + }, + { + "startTimeGMT": 1720406040000, + "respirationValue": 21.0, + }, + { + "startTimeGMT": 1720406160000, + "respirationValue": 20.0, + }, + { + "startTimeGMT": 1720406280000, + "respirationValue": 20.0, + }, + { + "startTimeGMT": 1720406400000, + "respirationValue": 20.0, + }, + { + "startTimeGMT": 1720406520000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720406640000, + "respirationValue": 15.0, + }, + { + "startTimeGMT": 1720406760000, + "respirationValue": 13.0, + }, + { + "startTimeGMT": 1720406880000, + "respirationValue": 14.0, + }, + { + "startTimeGMT": 1720407000000, + "respirationValue": 14.0, + }, + { + "startTimeGMT": 1720407120000, + "respirationValue": 13.0, + }, + { + "startTimeGMT": 1720407240000, + "respirationValue": 12.0, + }, + { + "startTimeGMT": 1720407360000, + "respirationValue": 12.0, + }, + { + "startTimeGMT": 1720407480000, + "respirationValue": 13.0, + }, + { + "startTimeGMT": 1720407600000, + "respirationValue": 12.0, + }, + { + "startTimeGMT": 1720407720000, + "respirationValue": 14.0, + }, + { + "startTimeGMT": 1720407840000, + "respirationValue": 14.0, + }, + { + "startTimeGMT": 1720407960000, + "respirationValue": 14.0, + }, + { + "startTimeGMT": 1720408080000, + "respirationValue": 13.0, + }, + { + "startTimeGMT": 1720408200000, + "respirationValue": 12.0, + }, + { + "startTimeGMT": 1720408320000, + "respirationValue": 13.0, + }, + { + "startTimeGMT": 1720408440000, + "respirationValue": 13.0, + }, + { + "startTimeGMT": 1720408560000, + "respirationValue": 10.0, + }, + { + "startTimeGMT": 1720408680000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720408800000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720408920000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720409040000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720409160000, + "respirationValue": 10.0, + }, + { + "startTimeGMT": 1720409280000, + "respirationValue": 12.0, + }, + { + "startTimeGMT": 1720409400000, + "respirationValue": 14.0, + }, + { + "startTimeGMT": 1720409520000, + "respirationValue": 14.0, + }, + { + "startTimeGMT": 1720409640000, + "respirationValue": 13.0, + }, + { + "startTimeGMT": 1720409760000, + "respirationValue": 13.0, + }, + { + "startTimeGMT": 1720409880000, + "respirationValue": 12.0, + }, + { + "startTimeGMT": 1720410000000, + "respirationValue": 12.0, + }, + { + "startTimeGMT": 1720410120000, + "respirationValue": 12.0, + }, + { + "startTimeGMT": 1720410240000, + "respirationValue": 13.0, + }, + { + "startTimeGMT": 1720410360000, + "respirationValue": 10.0, + }, + { + "startTimeGMT": 1720410480000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720410600000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720410720000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720410840000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720410960000, + "respirationValue": 10.0, + }, + { + "startTimeGMT": 1720411080000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720411200000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720411320000, + "respirationValue": 11.0, + }, + { + "startTimeGMT": 1720411440000, + "respirationValue": 14.0, + }, + { + "startTimeGMT": 1720411560000, + "respirationValue": 14.0, + }, + { + "startTimeGMT": 1720411680000, + "respirationValue": 14.0, + }, + { + "startTimeGMT": 1720411800000, + "respirationValue": 12.0, + }, + { + "startTimeGMT": 1720411920000, + "respirationValue": 12.0, + }, + { + "startTimeGMT": 1720412040000, + "respirationValue": 10.0, + }, + { + "startTimeGMT": 1720412160000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720412280000, + "respirationValue": 10.0, + }, + { + "startTimeGMT": 1720412400000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720412520000, + "respirationValue": 10.0, + }, + { + "startTimeGMT": 1720412640000, + "respirationValue": 11.0, + }, + { + "startTimeGMT": 1720412760000, + "respirationValue": 12.0, + }, + { + "startTimeGMT": 1720412880000, + "respirationValue": 13.0, + }, + { + "startTimeGMT": 1720413000000, + "respirationValue": 11.0, + }, + { + "startTimeGMT": 1720413120000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720413240000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720413360000, + "respirationValue": 10.0, + }, + { + "startTimeGMT": 1720413480000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720413600000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720413720000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720413840000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720413960000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720414080000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720414200000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720414320000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720414440000, + "respirationValue": 10.0, + }, + { + "startTimeGMT": 1720414560000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720414680000, + "respirationValue": 10.0, + }, + { + "startTimeGMT": 1720414800000, + "respirationValue": 10.0, + }, + { + "startTimeGMT": 1720414920000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720415040000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720415160000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720415280000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720415400000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720415520000, + "respirationValue": 10.0, + }, + { + "startTimeGMT": 1720415640000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720415760000, + "respirationValue": 10.0, + }, + { + "startTimeGMT": 1720415880000, + "respirationValue": 12.0, + }, + { + "startTimeGMT": 1720416000000, + "respirationValue": 13.0, + }, + { + "startTimeGMT": 1720416120000, + "respirationValue": 12.0, + }, + { + "startTimeGMT": 1720416240000, + "respirationValue": 13.0, + }, + { + "startTimeGMT": 1720416360000, + "respirationValue": 13.0, + }, + { + "startTimeGMT": 1720416480000, + "respirationValue": 12.0, + }, + { + "startTimeGMT": 1720416600000, + "respirationValue": 15.0, + }, + { + "startTimeGMT": 1720416720000, + "respirationValue": 16.0, + }, + { + "startTimeGMT": 1720416840000, + "respirationValue": 15.0, + }, + { + "startTimeGMT": 1720416960000, + "respirationValue": 15.0, + }, + { + "startTimeGMT": 1720417080000, + "respirationValue": 15.0, + }, + { + "startTimeGMT": 1720417200000, + "respirationValue": 16.0, + }, + { + "startTimeGMT": 1720417320000, + "respirationValue": 17.0, + }, + { + "startTimeGMT": 1720417440000, + "respirationValue": 17.0, + }, + { + "startTimeGMT": 1720417560000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720417680000, + "respirationValue": 19.0, + }, + { + "startTimeGMT": 1720417800000, + "respirationValue": 19.0, + }, + { + "startTimeGMT": 1720417920000, + "respirationValue": 19.0, + }, + { + "startTimeGMT": 1720418040000, + "respirationValue": 19.0, + }, + { + "startTimeGMT": 1720418160000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720418280000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720418400000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720418520000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720418640000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720418760000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720418880000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720419000000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720419120000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720419240000, + "respirationValue": 17.0, + }, + { + "startTimeGMT": 1720419360000, + "respirationValue": 17.0, + }, + { + "startTimeGMT": 1720419480000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720419600000, + "respirationValue": 19.0, + }, + { + "startTimeGMT": 1720419720000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720419840000, + "respirationValue": 17.0, + }, + { + "startTimeGMT": 1720419960000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720420080000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720420200000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720420320000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720420440000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720420560000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720420680000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720420800000, + "respirationValue": 16.0, + }, + { + "startTimeGMT": 1720420920000, + "respirationValue": 15.0, + }, + { + "startTimeGMT": 1720421040000, + "respirationValue": 14.0, + }, + { + "startTimeGMT": 1720421160000, + "respirationValue": 15.0, + }, + { + "startTimeGMT": 1720421280000, + "respirationValue": 16.0, + }, + { + "startTimeGMT": 1720421400000, + "respirationValue": 16.0, + }, + { + "startTimeGMT": 1720421520000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720421640000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720421760000, + "respirationValue": 17.0, + }, + { + "startTimeGMT": 1720421880000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720422000000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720422120000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720422240000, + "respirationValue": 19.0, + }, + { + "startTimeGMT": 1720422360000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720422480000, + "respirationValue": 19.0, + }, + { + "startTimeGMT": 1720422600000, + "respirationValue": 19.0, + }, + { + "startTimeGMT": 1720422720000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720422840000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720422960000, + "respirationValue": 19.0, + }, + { + "startTimeGMT": 1720423080000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720423200000, + "respirationValue": 16.0, + }, + { + "startTimeGMT": 1720423320000, + "respirationValue": 15.0, + }, + { + "startTimeGMT": 1720423440000, + "respirationValue": 16.0, + }, + { + "startTimeGMT": 1720423560000, + "respirationValue": 16.0, + }, + { + "startTimeGMT": 1720423680000, + "respirationValue": 16.0, + }, + { + "startTimeGMT": 1720423800000, + "respirationValue": 15.0, + }, + { + "startTimeGMT": 1720423920000, + "respirationValue": 13.0, + }, + { + "startTimeGMT": 1720424040000, + "respirationValue": 13.0, + }, + { + "startTimeGMT": 1720424160000, + "respirationValue": 14.0, + }, + { + "startTimeGMT": 1720424280000, + "respirationValue": 15.0, + }, + { + "startTimeGMT": 1720424400000, + "respirationValue": 15.0, + }, + { + "startTimeGMT": 1720424520000, + "respirationValue": 15.0, + }, + { + "startTimeGMT": 1720424640000, + "respirationValue": 14.0, + }, + { + "startTimeGMT": 1720424760000, + "respirationValue": 14.0, + }, + { + "startTimeGMT": 1720424880000, + "respirationValue": 15.0, + }, + { + "startTimeGMT": 1720425000000, + "respirationValue": 16.0, + }, + { + "startTimeGMT": 1720425120000, + "respirationValue": 16.0, + }, + { + "startTimeGMT": 1720425240000, + "respirationValue": 17.0, + }, + { + "startTimeGMT": 1720425360000, + "respirationValue": 13.0, + }, + { + "startTimeGMT": 1720425480000, + "respirationValue": 14.0, + }, + { + "startTimeGMT": 1720425600000, + "respirationValue": 14.0, + }, + { + "startTimeGMT": 1720425720000, + "respirationValue": 16.0, + }, + { + "startTimeGMT": 1720425840000, + "respirationValue": 16.0, + }, + { + "startTimeGMT": 1720425960000, + "respirationValue": 17.0, + }, + { + "startTimeGMT": 1720426080000, + "respirationValue": 16.0, + }, + { + "startTimeGMT": 1720426200000, + "respirationValue": 15.0, + }, + { + "startTimeGMT": 1720426320000, + "respirationValue": 12.0, + }, + { + "startTimeGMT": 1720426440000, + "respirationValue": 13.0, + }, + { + "startTimeGMT": 1720426560000, + "respirationValue": 13.0, + }, + { + "startTimeGMT": 1720426680000, + "respirationValue": 13.0, + }, + { + "startTimeGMT": 1720426800000, + "respirationValue": 14.0, + }, + { + "startTimeGMT": 1720426920000, + "respirationValue": 17.0, + }, + { + "startTimeGMT": 1720427040000, + "respirationValue": 17.0, + }, + { + "startTimeGMT": 1720427160000, + "respirationValue": 17.0, + }, + { + "startTimeGMT": 1720427280000, + "respirationValue": 17.0, + }, + { + "startTimeGMT": 1720427400000, + "respirationValue": 16.0, + }, + { + "startTimeGMT": 1720427520000, + "respirationValue": 18.0, + }, + { + "startTimeGMT": 1720427640000, + "respirationValue": 17.0, + }, + { + "startTimeGMT": 1720427760000, + "respirationValue": 17.0, + }, + { + "startTimeGMT": 1720427880000, + "respirationValue": 17.0, + }, + { + "startTimeGMT": 1720428000000, + "respirationValue": 16.0, + }, + { + "startTimeGMT": 1720428120000, + "respirationValue": 16.0, + }, + { + "startTimeGMT": 1720428240000, + "respirationValue": 15.0, + }, + { + "startTimeGMT": 1720428360000, + "respirationValue": 15.0, + }, + { + "startTimeGMT": 1720428480000, + "respirationValue": 15.0, + }, + { + "startTimeGMT": 1720428600000, + "respirationValue": 14.0, + }, + { + "startTimeGMT": 1720428720000, + "respirationValue": 13.0, + }, + { + "startTimeGMT": 1720428840000, + "respirationValue": 13.0, + }, + { + "startTimeGMT": 1720428960000, + "respirationValue": 11.0, + }, + { + "startTimeGMT": 1720429080000, + "respirationValue": 8.0, + }, + { + "startTimeGMT": 1720429200000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720429320000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720429440000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720429560000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720429680000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720429800000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720429920000, + "respirationValue": 8.0, + }, + { + "startTimeGMT": 1720430040000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720430160000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720430280000, + "respirationValue": 11.0, + }, + { + "startTimeGMT": 1720430400000, + "respirationValue": 11.0, + }, + { + "startTimeGMT": 1720430520000, + "respirationValue": 12.0, + }, + { + "startTimeGMT": 1720430640000, + "respirationValue": 12.0, + }, + { + "startTimeGMT": 1720430760000, + "respirationValue": 11.0, + }, + { + "startTimeGMT": 1720430880000, + "respirationValue": 11.0, + }, + { + "startTimeGMT": 1720431000000, + "respirationValue": 12.0, + }, + { + "startTimeGMT": 1720431120000, + "respirationValue": 14.0, + }, + { + "startTimeGMT": 1720431240000, + "respirationValue": 12.0, + }, + { + "startTimeGMT": 1720431360000, + "respirationValue": 10.0, + }, + { + "startTimeGMT": 1720431480000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720431600000, + "respirationValue": 10.0, + }, + { + "startTimeGMT": 1720431720000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720431840000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720431960000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720432080000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720432200000, + "respirationValue": 10.0, + }, + { + "startTimeGMT": 1720432320000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720432440000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720432560000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720432680000, + "respirationValue": 10.0, + }, + { + "startTimeGMT": 1720432800000, + "respirationValue": 9.0, + }, + { + "startTimeGMT": 1720432920000, + "respirationValue": 10.0, + }, + { + "startTimeGMT": 1720433040000, + "respirationValue": 10.0, + }, + { + "startTimeGMT": 1720433160000, + "respirationValue": 13.0, + }, + { + "startTimeGMT": 1720433280000, + "respirationValue": 14.0, + }, + { + "startTimeGMT": 1720433400000, + "respirationValue": 14.0, + }, + { + "startTimeGMT": 1720433520000, + "respirationValue": 16.0, + }, + { + "startTimeGMT": 1720433640000, + "respirationValue": 16.0, + }, + { + "startTimeGMT": 1720433760000, + "respirationValue": 16.0, + }, + { + "startTimeGMT": 1720433880000, + "respirationValue": 17.0, + }, + { + "startTimeGMT": 1720434000000, + "respirationValue": 17.0, + }, + ], + "sleepHeartRate": [ + {"value": 44, "startGMT": 1720403880000}, + {"value": 45, "startGMT": 1720404000000}, + {"value": 46, "startGMT": 1720404120000}, + {"value": 46, "startGMT": 1720404240000}, + {"value": 46, "startGMT": 1720404360000}, + {"value": 49, "startGMT": 1720404480000}, + {"value": 47, "startGMT": 1720404600000}, + {"value": 47, "startGMT": 1720404720000}, + {"value": 47, "startGMT": 1720404840000}, + {"value": 47, "startGMT": 1720404960000}, + {"value": 47, "startGMT": 1720405080000}, + {"value": 47, "startGMT": 1720405200000}, + {"value": 47, "startGMT": 1720405320000}, + {"value": 47, "startGMT": 1720405440000}, + {"value": 47, "startGMT": 1720405560000}, + {"value": 47, "startGMT": 1720405680000}, + {"value": 47, "startGMT": 1720405800000}, + {"value": 47, "startGMT": 1720405920000}, + {"value": 47, "startGMT": 1720406040000}, + {"value": 47, "startGMT": 1720406160000}, + {"value": 47, "startGMT": 1720406280000}, + {"value": 48, "startGMT": 1720406400000}, + {"value": 48, "startGMT": 1720406520000}, + {"value": 54, "startGMT": 1720406640000}, + {"value": 46, "startGMT": 1720406760000}, + {"value": 47, "startGMT": 1720406880000}, + {"value": 46, "startGMT": 1720407000000}, + {"value": 47, "startGMT": 1720407120000}, + {"value": 47, "startGMT": 1720407240000}, + {"value": 47, "startGMT": 1720407360000}, + {"value": 47, "startGMT": 1720407480000}, + {"value": 47, "startGMT": 1720407600000}, + {"value": 48, "startGMT": 1720407720000}, + {"value": 49, "startGMT": 1720407840000}, + {"value": 47, "startGMT": 1720407960000}, + {"value": 46, "startGMT": 1720408080000}, + {"value": 47, "startGMT": 1720408200000}, + {"value": 50, "startGMT": 1720408320000}, + {"value": 46, "startGMT": 1720408440000}, + {"value": 46, "startGMT": 1720408560000}, + {"value": 46, "startGMT": 1720408680000}, + {"value": 46, "startGMT": 1720408800000}, + {"value": 46, "startGMT": 1720408920000}, + {"value": 47, "startGMT": 1720409040000}, + {"value": 46, "startGMT": 1720409160000}, + {"value": 46, "startGMT": 1720409280000}, + {"value": 46, "startGMT": 1720409400000}, + {"value": 46, "startGMT": 1720409520000}, + {"value": 46, "startGMT": 1720409640000}, + {"value": 45, "startGMT": 1720409760000}, + {"value": 46, "startGMT": 1720409880000}, + {"value": 45, "startGMT": 1720410000000}, + {"value": 51, "startGMT": 1720410120000}, + {"value": 45, "startGMT": 1720410240000}, + {"value": 44, "startGMT": 1720410360000}, + {"value": 45, "startGMT": 1720410480000}, + {"value": 44, "startGMT": 1720410600000}, + {"value": 45, "startGMT": 1720410720000}, + {"value": 44, "startGMT": 1720410840000}, + {"value": 44, "startGMT": 1720410960000}, + {"value": 47, "startGMT": 1720411080000}, + {"value": 47, "startGMT": 1720411200000}, + {"value": 47, "startGMT": 1720411320000}, + {"value": 50, "startGMT": 1720411440000}, + {"value": 43, "startGMT": 1720411560000}, + {"value": 44, "startGMT": 1720411680000}, + {"value": 43, "startGMT": 1720411800000}, + {"value": 43, "startGMT": 1720411920000}, + {"value": 44, "startGMT": 1720412040000}, + {"value": 43, "startGMT": 1720412160000}, + {"value": 43, "startGMT": 1720412280000}, + {"value": 44, "startGMT": 1720412400000}, + {"value": 43, "startGMT": 1720412520000}, + {"value": 44, "startGMT": 1720412640000}, + {"value": 43, "startGMT": 1720412760000}, + {"value": 44, "startGMT": 1720412880000}, + {"value": 48, "startGMT": 1720413000000}, + {"value": 42, "startGMT": 1720413120000}, + {"value": 42, "startGMT": 1720413240000}, + {"value": 42, "startGMT": 1720413360000}, + {"value": 42, "startGMT": 1720413480000}, + {"value": 42, "startGMT": 1720413600000}, + {"value": 42, "startGMT": 1720413720000}, + {"value": 42, "startGMT": 1720413840000}, + {"value": 42, "startGMT": 1720413960000}, + {"value": 41, "startGMT": 1720414080000}, + {"value": 41, "startGMT": 1720414200000}, + {"value": 43, "startGMT": 1720414320000}, + {"value": 42, "startGMT": 1720414440000}, + {"value": 44, "startGMT": 1720414560000}, + {"value": 41, "startGMT": 1720414680000}, + {"value": 42, "startGMT": 1720414800000}, + {"value": 42, "startGMT": 1720414920000}, + {"value": 42, "startGMT": 1720415040000}, + {"value": 43, "startGMT": 1720415160000}, + {"value": 44, "startGMT": 1720415280000}, + {"value": 42, "startGMT": 1720415400000}, + {"value": 44, "startGMT": 1720415520000}, + {"value": 45, "startGMT": 1720415640000}, + {"value": 43, "startGMT": 1720415760000}, + {"value": 42, "startGMT": 1720415880000}, + {"value": 48, "startGMT": 1720416000000}, + {"value": 41, "startGMT": 1720416120000}, + {"value": 42, "startGMT": 1720416240000}, + {"value": 41, "startGMT": 1720416360000}, + {"value": 44, "startGMT": 1720416480000}, + {"value": 39, "startGMT": 1720416600000}, + {"value": 40, "startGMT": 1720416720000}, + {"value": 41, "startGMT": 1720416840000}, + {"value": 41, "startGMT": 1720416960000}, + {"value": 41, "startGMT": 1720417080000}, + {"value": 46, "startGMT": 1720417200000}, + {"value": 41, "startGMT": 1720417320000}, + {"value": 40, "startGMT": 1720417440000}, + {"value": 40, "startGMT": 1720417560000}, + {"value": 40, "startGMT": 1720417680000}, + {"value": 39, "startGMT": 1720417800000}, + {"value": 39, "startGMT": 1720417920000}, + {"value": 39, "startGMT": 1720418040000}, + {"value": 40, "startGMT": 1720418160000}, + {"value": 39, "startGMT": 1720418280000}, + {"value": 39, "startGMT": 1720418400000}, + {"value": 39, "startGMT": 1720418520000}, + {"value": 39, "startGMT": 1720418640000}, + {"value": 39, "startGMT": 1720418760000}, + {"value": 39, "startGMT": 1720418880000}, + {"value": 40, "startGMT": 1720419000000}, + {"value": 40, "startGMT": 1720419120000}, + {"value": 40, "startGMT": 1720419240000}, + {"value": 40, "startGMT": 1720419360000}, + {"value": 40, "startGMT": 1720419480000}, + {"value": 40, "startGMT": 1720419600000}, + {"value": 41, "startGMT": 1720419720000}, + {"value": 41, "startGMT": 1720419840000}, + {"value": 40, "startGMT": 1720419960000}, + {"value": 39, "startGMT": 1720420080000}, + {"value": 40, "startGMT": 1720420200000}, + {"value": 40, "startGMT": 1720420320000}, + {"value": 40, "startGMT": 1720420440000}, + {"value": 40, "startGMT": 1720420560000}, + {"value": 40, "startGMT": 1720420680000}, + {"value": 51, "startGMT": 1720420800000}, + {"value": 42, "startGMT": 1720420920000}, + {"value": 41, "startGMT": 1720421040000}, + {"value": 40, "startGMT": 1720421160000}, + {"value": 45, "startGMT": 1720421280000}, + {"value": 41, "startGMT": 1720421400000}, + {"value": 38, "startGMT": 1720421520000}, + {"value": 38, "startGMT": 1720421640000}, + {"value": 38, "startGMT": 1720421760000}, + {"value": 40, "startGMT": 1720421880000}, + {"value": 38, "startGMT": 1720422000000}, + {"value": 38, "startGMT": 1720422120000}, + {"value": 38, "startGMT": 1720422240000}, + {"value": 38, "startGMT": 1720422360000}, + {"value": 38, "startGMT": 1720422480000}, + {"value": 38, "startGMT": 1720422600000}, + {"value": 38, "startGMT": 1720422720000}, + {"value": 38, "startGMT": 1720422840000}, + {"value": 38, "startGMT": 1720422960000}, + {"value": 45, "startGMT": 1720423080000}, + {"value": 43, "startGMT": 1720423200000}, + {"value": 41, "startGMT": 1720423320000}, + {"value": 41, "startGMT": 1720423440000}, + {"value": 41, "startGMT": 1720423560000}, + {"value": 40, "startGMT": 1720423680000}, + {"value": 40, "startGMT": 1720423800000}, + {"value": 41, "startGMT": 1720423920000}, + {"value": 45, "startGMT": 1720424040000}, + {"value": 44, "startGMT": 1720424160000}, + {"value": 44, "startGMT": 1720424280000}, + {"value": 40, "startGMT": 1720424400000}, + {"value": 40, "startGMT": 1720424520000}, + {"value": 40, "startGMT": 1720424640000}, + {"value": 41, "startGMT": 1720424760000}, + {"value": 40, "startGMT": 1720424880000}, + {"value": 40, "startGMT": 1720425000000}, + {"value": 41, "startGMT": 1720425120000}, + {"value": 40, "startGMT": 1720425240000}, + {"value": 43, "startGMT": 1720425360000}, + {"value": 43, "startGMT": 1720425480000}, + {"value": 46, "startGMT": 1720425600000}, + {"value": 42, "startGMT": 1720425720000}, + {"value": 40, "startGMT": 1720425840000}, + {"value": 40, "startGMT": 1720425960000}, + {"value": 40, "startGMT": 1720426080000}, + {"value": 39, "startGMT": 1720426200000}, + {"value": 38, "startGMT": 1720426320000}, + {"value": 39, "startGMT": 1720426440000}, + {"value": 38, "startGMT": 1720426560000}, + {"value": 38, "startGMT": 1720426680000}, + {"value": 44, "startGMT": 1720426800000}, + {"value": 38, "startGMT": 1720426920000}, + {"value": 38, "startGMT": 1720427040000}, + {"value": 38, "startGMT": 1720427160000}, + {"value": 38, "startGMT": 1720427280000}, + {"value": 38, "startGMT": 1720427400000}, + {"value": 39, "startGMT": 1720427520000}, + {"value": 39, "startGMT": 1720427640000}, + {"value": 39, "startGMT": 1720427760000}, + {"value": 38, "startGMT": 1720427880000}, + {"value": 38, "startGMT": 1720428000000}, + {"value": 38, "startGMT": 1720428120000}, + {"value": 39, "startGMT": 1720428240000}, + {"value": 38, "startGMT": 1720428360000}, + {"value": 48, "startGMT": 1720428480000}, + {"value": 38, "startGMT": 1720428600000}, + {"value": 39, "startGMT": 1720428720000}, + {"value": 38, "startGMT": 1720428840000}, + {"value": 38, "startGMT": 1720428960000}, + {"value": 38, "startGMT": 1720429080000}, + {"value": 46, "startGMT": 1720429200000}, + {"value": 38, "startGMT": 1720429320000}, + {"value": 38, "startGMT": 1720429440000}, + {"value": 38, "startGMT": 1720429560000}, + {"value": 39, "startGMT": 1720429680000}, + {"value": 38, "startGMT": 1720429800000}, + {"value": 39, "startGMT": 1720429920000}, + {"value": 40, "startGMT": 1720430040000}, + {"value": 40, "startGMT": 1720430160000}, + {"value": 41, "startGMT": 1720430280000}, + {"value": 41, "startGMT": 1720430400000}, + {"value": 40, "startGMT": 1720430520000}, + {"value": 40, "startGMT": 1720430640000}, + {"value": 41, "startGMT": 1720430760000}, + {"value": 41, "startGMT": 1720430880000}, + {"value": 40, "startGMT": 1720431000000}, + {"value": 41, "startGMT": 1720431120000}, + {"value": 41, "startGMT": 1720431240000}, + {"value": 40, "startGMT": 1720431360000}, + {"value": 41, "startGMT": 1720431480000}, + {"value": 42, "startGMT": 1720431600000}, + {"value": 42, "startGMT": 1720431720000}, + {"value": 44, "startGMT": 1720431840000}, + {"value": 45, "startGMT": 1720431960000}, + {"value": 46, "startGMT": 1720432080000}, + {"value": 42, "startGMT": 1720432200000}, + {"value": 40, "startGMT": 1720432320000}, + {"value": 41, "startGMT": 1720432440000}, + {"value": 42, "startGMT": 1720432560000}, + {"value": 42, "startGMT": 1720432680000}, + {"value": 42, "startGMT": 1720432800000}, + {"value": 41, "startGMT": 1720432920000}, + {"value": 42, "startGMT": 1720433040000}, + {"value": 44, "startGMT": 1720433160000}, + {"value": 46, "startGMT": 1720433280000}, + {"value": 42, "startGMT": 1720433400000}, + {"value": 43, "startGMT": 1720433520000}, + {"value": 43, "startGMT": 1720433640000}, + {"value": 42, "startGMT": 1720433760000}, + {"value": 41, "startGMT": 1720433880000}, + {"value": 43, "startGMT": 1720434000000}, + ], + "sleepStress": [ + {"value": 20, "startGMT": 1720403820000}, + {"value": 17, "startGMT": 1720404000000}, + {"value": 19, "startGMT": 1720404180000}, + {"value": 15, "startGMT": 1720404360000}, + {"value": 18, "startGMT": 1720404540000}, + {"value": 19, "startGMT": 1720404720000}, + {"value": 20, "startGMT": 1720404900000}, + {"value": 18, "startGMT": 1720405080000}, + {"value": 18, "startGMT": 1720405260000}, + {"value": 17, "startGMT": 1720405440000}, + {"value": 17, "startGMT": 1720405620000}, + {"value": 16, "startGMT": 1720405800000}, + {"value": 19, "startGMT": 1720405980000}, + {"value": 19, "startGMT": 1720406160000}, + {"value": 20, "startGMT": 1720406340000}, + {"value": 22, "startGMT": 1720406520000}, + {"value": 19, "startGMT": 1720406700000}, + {"value": 19, "startGMT": 1720406880000}, + {"value": 17, "startGMT": 1720407060000}, + {"value": 20, "startGMT": 1720407240000}, + {"value": 20, "startGMT": 1720407420000}, + {"value": 23, "startGMT": 1720407600000}, + {"value": 22, "startGMT": 1720407780000}, + {"value": 20, "startGMT": 1720407960000}, + {"value": 21, "startGMT": 1720408140000}, + {"value": 20, "startGMT": 1720408320000}, + {"value": 19, "startGMT": 1720408500000}, + {"value": 20, "startGMT": 1720408680000}, + {"value": 19, "startGMT": 1720408860000}, + {"value": 21, "startGMT": 1720409040000}, + {"value": 22, "startGMT": 1720409220000}, + {"value": 21, "startGMT": 1720409400000}, + {"value": 20, "startGMT": 1720409580000}, + {"value": 20, "startGMT": 1720409760000}, + {"value": 20, "startGMT": 1720409940000}, + {"value": 17, "startGMT": 1720410120000}, + {"value": 18, "startGMT": 1720410300000}, + {"value": 17, "startGMT": 1720410480000}, + {"value": 17, "startGMT": 1720410660000}, + {"value": 17, "startGMT": 1720410840000}, + {"value": 23, "startGMT": 1720411020000}, + {"value": 23, "startGMT": 1720411200000}, + {"value": 20, "startGMT": 1720411380000}, + {"value": 20, "startGMT": 1720411560000}, + {"value": 12, "startGMT": 1720411740000}, + {"value": 15, "startGMT": 1720411920000}, + {"value": 15, "startGMT": 1720412100000}, + {"value": 13, "startGMT": 1720412280000}, + {"value": 14, "startGMT": 1720412460000}, + {"value": 16, "startGMT": 1720412640000}, + {"value": 16, "startGMT": 1720412820000}, + {"value": 14, "startGMT": 1720413000000}, + {"value": 15, "startGMT": 1720413180000}, + {"value": 16, "startGMT": 1720413360000}, + {"value": 15, "startGMT": 1720413540000}, + {"value": 17, "startGMT": 1720413720000}, + {"value": 15, "startGMT": 1720413900000}, + {"value": 15, "startGMT": 1720414080000}, + {"value": 15, "startGMT": 1720414260000}, + {"value": 13, "startGMT": 1720414440000}, + {"value": 11, "startGMT": 1720414620000}, + {"value": 7, "startGMT": 1720414800000}, + {"value": 15, "startGMT": 1720414980000}, + {"value": 23, "startGMT": 1720415160000}, + {"value": 21, "startGMT": 1720415340000}, + {"value": 17, "startGMT": 1720415520000}, + {"value": 12, "startGMT": 1720415700000}, + {"value": 17, "startGMT": 1720415880000}, + {"value": 18, "startGMT": 1720416060000}, + {"value": 17, "startGMT": 1720416240000}, + {"value": 13, "startGMT": 1720416420000}, + {"value": 12, "startGMT": 1720416600000}, + {"value": 17, "startGMT": 1720416780000}, + {"value": 15, "startGMT": 1720416960000}, + {"value": 14, "startGMT": 1720417140000}, + {"value": 21, "startGMT": 1720417320000}, + {"value": 20, "startGMT": 1720417500000}, + {"value": 23, "startGMT": 1720417680000}, + {"value": 21, "startGMT": 1720417860000}, + {"value": 19, "startGMT": 1720418040000}, + {"value": 11, "startGMT": 1720418220000}, + {"value": 13, "startGMT": 1720418400000}, + {"value": 9, "startGMT": 1720418580000}, + {"value": 9, "startGMT": 1720418760000}, + {"value": 10, "startGMT": 1720418940000}, + {"value": 10, "startGMT": 1720419120000}, + {"value": 9, "startGMT": 1720419300000}, + {"value": 10, "startGMT": 1720419480000}, + {"value": 10, "startGMT": 1720419660000}, + {"value": 9, "startGMT": 1720419840000}, + {"value": 8, "startGMT": 1720420020000}, + {"value": 10, "startGMT": 1720420200000}, + {"value": 10, "startGMT": 1720420380000}, + {"value": 9, "startGMT": 1720420560000}, + {"value": 15, "startGMT": 1720420740000}, + {"value": 6, "startGMT": 1720420920000}, + {"value": 7, "startGMT": 1720421100000}, + {"value": 8, "startGMT": 1720421280000}, + {"value": 12, "startGMT": 1720421460000}, + {"value": 12, "startGMT": 1720421640000}, + {"value": 10, "startGMT": 1720421820000}, + {"value": 16, "startGMT": 1720422000000}, + {"value": 16, "startGMT": 1720422180000}, + {"value": 18, "startGMT": 1720422360000}, + {"value": 20, "startGMT": 1720422540000}, + {"value": 20, "startGMT": 1720422720000}, + {"value": 17, "startGMT": 1720422900000}, + {"value": 11, "startGMT": 1720423080000}, + {"value": 21, "startGMT": 1720423260000}, + {"value": 18, "startGMT": 1720423440000}, + {"value": 8, "startGMT": 1720423620000}, + {"value": 12, "startGMT": 1720423800000}, + {"value": 18, "startGMT": 1720423980000}, + {"value": 10, "startGMT": 1720424160000}, + {"value": 8, "startGMT": 1720424340000}, + {"value": 8, "startGMT": 1720424520000}, + {"value": 9, "startGMT": 1720424700000}, + {"value": 11, "startGMT": 1720424880000}, + {"value": 9, "startGMT": 1720425060000}, + {"value": 15, "startGMT": 1720425240000}, + {"value": 14, "startGMT": 1720425420000}, + {"value": 12, "startGMT": 1720425600000}, + {"value": 10, "startGMT": 1720425780000}, + {"value": 8, "startGMT": 1720425960000}, + {"value": 12, "startGMT": 1720426140000}, + {"value": 16, "startGMT": 1720426320000}, + {"value": 12, "startGMT": 1720426500000}, + {"value": 17, "startGMT": 1720426680000}, + {"value": 16, "startGMT": 1720426860000}, + {"value": 20, "startGMT": 1720427040000}, + {"value": 17, "startGMT": 1720427220000}, + {"value": 20, "startGMT": 1720427400000}, + {"value": 21, "startGMT": 1720427580000}, + {"value": 19, "startGMT": 1720427760000}, + {"value": 15, "startGMT": 1720427940000}, + {"value": 18, "startGMT": 1720428120000}, + {"value": 16, "startGMT": 1720428300000}, + {"value": 11, "startGMT": 1720428480000}, + {"value": 11, "startGMT": 1720428660000}, + {"value": 14, "startGMT": 1720428840000}, + {"value": 12, "startGMT": 1720429020000}, + {"value": 7, "startGMT": 1720429200000}, + {"value": 12, "startGMT": 1720429380000}, + {"value": 15, "startGMT": 1720429560000}, + {"value": 12, "startGMT": 1720429740000}, + {"value": 17, "startGMT": 1720429920000}, + {"value": 18, "startGMT": 1720430100000}, + {"value": 12, "startGMT": 1720430280000}, + {"value": 15, "startGMT": 1720430460000}, + {"value": 16, "startGMT": 1720430640000}, + {"value": 19, "startGMT": 1720430820000}, + {"value": 20, "startGMT": 1720431000000}, + {"value": 17, "startGMT": 1720431180000}, + {"value": 20, "startGMT": 1720431360000}, + {"value": 20, "startGMT": 1720431540000}, + {"value": 22, "startGMT": 1720431720000}, + {"value": 20, "startGMT": 1720431900000}, + {"value": 9, "startGMT": 1720432080000}, + {"value": 16, "startGMT": 1720432260000}, + {"value": 22, "startGMT": 1720432440000}, + {"value": 20, "startGMT": 1720432620000}, + {"value": 17, "startGMT": 1720432800000}, + {"value": 21, "startGMT": 1720432980000}, + {"value": 13, "startGMT": 1720433160000}, + {"value": 15, "startGMT": 1720433340000}, + {"value": 17, "startGMT": 1720433520000}, + {"value": 17, "startGMT": 1720433700000}, + {"value": 17, "startGMT": 1720433880000}, + ], + "sleepBodyBattery": [ + {"value": 29, "startGMT": 1720403820000}, + {"value": 29, "startGMT": 1720404000000}, + {"value": 29, "startGMT": 1720404180000}, + {"value": 29, "startGMT": 1720404360000}, + {"value": 29, "startGMT": 1720404540000}, + {"value": 29, "startGMT": 1720404720000}, + {"value": 29, "startGMT": 1720404900000}, + {"value": 29, "startGMT": 1720405080000}, + {"value": 30, "startGMT": 1720405260000}, + {"value": 31, "startGMT": 1720405440000}, + {"value": 31, "startGMT": 1720405620000}, + {"value": 31, "startGMT": 1720405800000}, + {"value": 32, "startGMT": 1720405980000}, + {"value": 32, "startGMT": 1720406160000}, + {"value": 32, "startGMT": 1720406340000}, + {"value": 32, "startGMT": 1720406520000}, + {"value": 32, "startGMT": 1720406700000}, + {"value": 33, "startGMT": 1720406880000}, + {"value": 34, "startGMT": 1720407060000}, + {"value": 34, "startGMT": 1720407240000}, + {"value": 35, "startGMT": 1720407420000}, + {"value": 35, "startGMT": 1720407600000}, + {"value": 35, "startGMT": 1720407780000}, + {"value": 35, "startGMT": 1720407960000}, + {"value": 35, "startGMT": 1720408140000}, + {"value": 35, "startGMT": 1720408320000}, + {"value": 37, "startGMT": 1720408500000}, + {"value": 37, "startGMT": 1720408680000}, + {"value": 37, "startGMT": 1720408860000}, + {"value": 37, "startGMT": 1720409040000}, + {"value": 37, "startGMT": 1720409220000}, + {"value": 37, "startGMT": 1720409400000}, + {"value": 38, "startGMT": 1720409580000}, + {"value": 38, "startGMT": 1720409760000}, + {"value": 38, "startGMT": 1720409940000}, + {"value": 39, "startGMT": 1720410120000}, + {"value": 40, "startGMT": 1720410300000}, + {"value": 40, "startGMT": 1720410480000}, + {"value": 41, "startGMT": 1720410660000}, + {"value": 42, "startGMT": 1720410840000}, + {"value": 42, "startGMT": 1720411020000}, + {"value": 43, "startGMT": 1720411200000}, + {"value": 44, "startGMT": 1720411380000}, + {"value": 44, "startGMT": 1720411560000}, + {"value": 45, "startGMT": 1720411740000}, + {"value": 45, "startGMT": 1720411920000}, + {"value": 45, "startGMT": 1720412100000}, + {"value": 46, "startGMT": 1720412280000}, + {"value": 47, "startGMT": 1720412460000}, + {"value": 47, "startGMT": 1720412640000}, + {"value": 48, "startGMT": 1720412820000}, + {"value": 49, "startGMT": 1720413000000}, + {"value": 50, "startGMT": 1720413180000}, + {"value": 51, "startGMT": 1720413360000}, + {"value": 51, "startGMT": 1720413540000}, + {"value": 52, "startGMT": 1720413720000}, + {"value": 52, "startGMT": 1720413900000}, + {"value": 53, "startGMT": 1720414080000}, + {"value": 54, "startGMT": 1720414260000}, + {"value": 55, "startGMT": 1720414440000}, + {"value": 55, "startGMT": 1720414620000}, + {"value": 56, "startGMT": 1720414800000}, + {"value": 56, "startGMT": 1720414980000}, + {"value": 57, "startGMT": 1720415160000}, + {"value": 57, "startGMT": 1720415340000}, + {"value": 57, "startGMT": 1720415520000}, + {"value": 58, "startGMT": 1720415700000}, + {"value": 59, "startGMT": 1720415880000}, + {"value": 59, "startGMT": 1720416060000}, + {"value": 59, "startGMT": 1720416240000}, + {"value": 60, "startGMT": 1720416420000}, + {"value": 60, "startGMT": 1720416600000}, + {"value": 60, "startGMT": 1720416780000}, + {"value": 61, "startGMT": 1720416960000}, + {"value": 62, "startGMT": 1720417140000}, + {"value": 62, "startGMT": 1720417320000}, + {"value": 62, "startGMT": 1720417500000}, + {"value": 62, "startGMT": 1720417680000}, + {"value": 62, "startGMT": 1720417860000}, + {"value": 62, "startGMT": 1720418040000}, + {"value": 63, "startGMT": 1720418220000}, + {"value": 64, "startGMT": 1720418400000}, + {"value": 65, "startGMT": 1720418580000}, + {"value": 65, "startGMT": 1720418760000}, + {"value": 66, "startGMT": 1720418940000}, + {"value": 66, "startGMT": 1720419120000}, + {"value": 67, "startGMT": 1720419300000}, + {"value": 67, "startGMT": 1720419480000}, + {"value": 68, "startGMT": 1720419660000}, + {"value": 68, "startGMT": 1720419840000}, + {"value": 68, "startGMT": 1720420020000}, + {"value": 69, "startGMT": 1720420200000}, + {"value": 69, "startGMT": 1720420380000}, + {"value": 71, "startGMT": 1720420560000}, + {"value": 71, "startGMT": 1720420740000}, + {"value": 72, "startGMT": 1720420920000}, + {"value": 72, "startGMT": 1720421100000}, + {"value": 73, "startGMT": 1720421280000}, + {"value": 73, "startGMT": 1720421460000}, + {"value": 73, "startGMT": 1720421640000}, + {"value": 73, "startGMT": 1720421820000}, + {"value": 74, "startGMT": 1720422000000}, + {"value": 74, "startGMT": 1720422180000}, + {"value": 75, "startGMT": 1720422360000}, + {"value": 75, "startGMT": 1720422540000}, + {"value": 75, "startGMT": 1720422720000}, + {"value": 76, "startGMT": 1720422900000}, + {"value": 76, "startGMT": 1720423080000}, + {"value": 77, "startGMT": 1720423260000}, + {"value": 77, "startGMT": 1720423440000}, + {"value": 77, "startGMT": 1720423620000}, + {"value": 77, "startGMT": 1720423800000}, + {"value": 78, "startGMT": 1720423980000}, + {"value": 78, "startGMT": 1720424160000}, + {"value": 78, "startGMT": 1720424340000}, + {"value": 79, "startGMT": 1720424520000}, + {"value": 80, "startGMT": 1720424700000}, + {"value": 80, "startGMT": 1720424880000}, + {"value": 80, "startGMT": 1720425060000}, + {"value": 81, "startGMT": 1720425240000}, + {"value": 81, "startGMT": 1720425420000}, + {"value": 82, "startGMT": 1720425600000}, + {"value": 82, "startGMT": 1720425780000}, + {"value": 82, "startGMT": 1720425960000}, + {"value": 83, "startGMT": 1720426140000}, + {"value": 83, "startGMT": 1720426320000}, + {"value": 83, "startGMT": 1720426500000}, + {"value": 83, "startGMT": 1720426680000}, + {"value": 84, "startGMT": 1720426860000}, + {"value": 84, "startGMT": 1720427040000}, + {"value": 84, "startGMT": 1720427220000}, + {"value": 85, "startGMT": 1720427400000}, + {"value": 85, "startGMT": 1720427580000}, + {"value": 85, "startGMT": 1720427760000}, + {"value": 85, "startGMT": 1720427940000}, + {"value": 85, "startGMT": 1720428120000}, + {"value": 85, "startGMT": 1720428300000}, + {"value": 86, "startGMT": 1720428480000}, + {"value": 86, "startGMT": 1720428660000}, + {"value": 87, "startGMT": 1720428840000}, + {"value": 87, "startGMT": 1720429020000}, + {"value": 87, "startGMT": 1720429200000}, + {"value": 87, "startGMT": 1720429380000}, + {"value": 88, "startGMT": 1720429560000}, + {"value": 88, "startGMT": 1720429740000}, + {"value": 88, "startGMT": 1720429920000}, + {"value": 88, "startGMT": 1720430100000}, + {"value": 88, "startGMT": 1720430280000}, + {"value": 88, "startGMT": 1720430460000}, + {"value": 89, "startGMT": 1720430640000}, + {"value": 89, "startGMT": 1720430820000}, + {"value": 90, "startGMT": 1720431000000}, + {"value": 90, "startGMT": 1720431180000}, + {"value": 90, "startGMT": 1720431360000}, + {"value": 90, "startGMT": 1720431540000}, + {"value": 90, "startGMT": 1720431720000}, + {"value": 90, "startGMT": 1720431900000}, + {"value": 90, "startGMT": 1720432080000}, + {"value": 90, "startGMT": 1720432260000}, + {"value": 90, "startGMT": 1720432440000}, + {"value": 90, "startGMT": 1720432620000}, + {"value": 91, "startGMT": 1720432800000}, + {"value": 91, "startGMT": 1720432980000}, + {"value": 92, "startGMT": 1720433160000}, + {"value": 92, "startGMT": 1720433340000}, + {"value": 92, "startGMT": 1720433520000}, + {"value": 92, "startGMT": 1720433700000}, + {"value": 92, "startGMT": 1720433880000}, + ], + "skinTempDataExists": false, + "hrvData": [ + {"value": 54.0, "startGMT": 1720404080000}, + {"value": 54.0, "startGMT": 1720404380000}, + {"value": 74.0, "startGMT": 1720404680000}, + {"value": 54.0, "startGMT": 1720404980000}, + {"value": 59.0, "startGMT": 1720405280000}, + {"value": 65.0, "startGMT": 1720405580000}, + {"value": 60.0, "startGMT": 1720405880000}, + {"value": 62.0, "startGMT": 1720406180000}, + {"value": 52.0, "startGMT": 1720406480000}, + {"value": 62.0, "startGMT": 1720406780000}, + {"value": 62.0, "startGMT": 1720407080000}, + {"value": 48.0, "startGMT": 1720407380000}, + {"value": 46.0, "startGMT": 1720407680000}, + {"value": 45.0, "startGMT": 1720407980000}, + {"value": 43.0, "startGMT": 1720408280000}, + {"value": 53.0, "startGMT": 1720408580000}, + {"value": 47.0, "startGMT": 1720408880000}, + {"value": 43.0, "startGMT": 1720409180000}, + {"value": 37.0, "startGMT": 1720409480000}, + {"value": 40.0, "startGMT": 1720409780000}, + {"value": 39.0, "startGMT": 1720410080000}, + {"value": 51.0, "startGMT": 1720410380000}, + {"value": 46.0, "startGMT": 1720410680000}, + {"value": 54.0, "startGMT": 1720410980000}, + {"value": 30.0, "startGMT": 1720411280000}, + {"value": 47.0, "startGMT": 1720411580000}, + {"value": 61.0, "startGMT": 1720411880000}, + {"value": 56.0, "startGMT": 1720412180000}, + {"value": 59.0, "startGMT": 1720412480000}, + {"value": 49.0, "startGMT": 1720412780000}, + {"value": 58.0, "startGMT": 1720413077000}, + {"value": 45.0, "startGMT": 1720413377000}, + {"value": 45.0, "startGMT": 1720413677000}, + {"value": 41.0, "startGMT": 1720413977000}, + {"value": 45.0, "startGMT": 1720414277000}, + {"value": 55.0, "startGMT": 1720414577000}, + {"value": 58.0, "startGMT": 1720414877000}, + {"value": 49.0, "startGMT": 1720415177000}, + {"value": 28.0, "startGMT": 1720415477000}, + {"value": 62.0, "startGMT": 1720415777000}, + {"value": 49.0, "startGMT": 1720416077000}, + {"value": 49.0, "startGMT": 1720416377000}, + {"value": 67.0, "startGMT": 1720416677000}, + {"value": 51.0, "startGMT": 1720416977000}, + {"value": 69.0, "startGMT": 1720417277000}, + {"value": 34.0, "startGMT": 1720417577000}, + {"value": 29.0, "startGMT": 1720417877000}, + {"value": 35.0, "startGMT": 1720418177000}, + {"value": 52.0, "startGMT": 1720418477000}, + {"value": 71.0, "startGMT": 1720418777000}, + {"value": 61.0, "startGMT": 1720419077000}, + {"value": 61.0, "startGMT": 1720419377000}, + {"value": 62.0, "startGMT": 1720419677000}, + {"value": 64.0, "startGMT": 1720419977000}, + {"value": 67.0, "startGMT": 1720420277000}, + {"value": 57.0, "startGMT": 1720420577000}, + {"value": 60.0, "startGMT": 1720420877000}, + {"value": 70.0, "startGMT": 1720421177000}, + {"value": 105.0, "startGMT": 1720421477000}, + {"value": 52.0, "startGMT": 1720421777000}, + {"value": 36.0, "startGMT": 1720422077000}, + {"value": 42.0, "startGMT": 1720422377000}, + {"value": 32.0, "startGMT": 1720422674000}, + {"value": 32.0, "startGMT": 1720422974000}, + {"value": 58.0, "startGMT": 1720423274000}, + {"value": 32.0, "startGMT": 1720423574000}, + {"value": 64.0, "startGMT": 1720423874000}, + {"value": 50.0, "startGMT": 1720424174000}, + {"value": 66.0, "startGMT": 1720424474000}, + {"value": 77.0, "startGMT": 1720424774000}, + {"value": 57.0, "startGMT": 1720425074000}, + {"value": 57.0, "startGMT": 1720425374000}, + {"value": 58.0, "startGMT": 1720425674000}, + {"value": 71.0, "startGMT": 1720425974000}, + {"value": 59.0, "startGMT": 1720426274000}, + {"value": 42.0, "startGMT": 1720426574000}, + {"value": 43.0, "startGMT": 1720426874000}, + {"value": 35.0, "startGMT": 1720427174000}, + {"value": 32.0, "startGMT": 1720427474000}, + {"value": 29.0, "startGMT": 1720427774000}, + {"value": 42.0, "startGMT": 1720428074000}, + {"value": 36.0, "startGMT": 1720428374000}, + {"value": 41.0, "startGMT": 1720428674000}, + {"value": 45.0, "startGMT": 1720428974000}, + {"value": 60.0, "startGMT": 1720429274000}, + {"value": 55.0, "startGMT": 1720429574000}, + {"value": 45.0, "startGMT": 1720429874000}, + {"value": 48.0, "startGMT": 1720430174000}, + {"value": 50.0, "startGMT": 1720430471000}, + {"value": 49.0, "startGMT": 1720430771000}, + {"value": 48.0, "startGMT": 1720431071000}, + {"value": 39.0, "startGMT": 1720431371000}, + {"value": 32.0, "startGMT": 1720431671000}, + {"value": 39.0, "startGMT": 1720431971000}, + {"value": 71.0, "startGMT": 1720432271000}, + {"value": 33.0, "startGMT": 1720432571000}, + {"value": 50.0, "startGMT": 1720432871000}, + {"value": 32.0, "startGMT": 1720433171000}, + {"value": 52.0, "startGMT": 1720433471000}, + {"value": 49.0, "startGMT": 1720433771000}, + {"value": 52.0, "startGMT": 1720434071000}, + ], + "avgOvernightHrv": 53.0, + "hrvStatus": "BALANCED", + "bodyBatteryChange": 63, + "restingHeartRate": 38, + } + } + }, + }, + { + "query": {"query": 'query{jetLagScalar(date:"2024-07-08")}'}, + "response": {"data": {"jetLagScalar": null}}, + }, + { + "query": { + "query": 'query{myDayCardEventsScalar(timeZone:"GMT", date:"2024-07-08")}' + }, + "response": { + "data": { + "myDayCardEventsScalar": { + "eventMyDay": [ + { + "id": 15567882, + "eventName": "Harvard Pilgrim Seafood Fest 5k (5K)", + "date": "2024-09-08", + "completionTarget": { + "value": 5000.0, + "unit": "meter", + "unitType": "distance", + }, + "eventTimeLocal": null, + "eventImageUUID": null, + "locationStartPoint": { + "lat": 42.937593, + "lon": -70.838922, + }, + "eventType": "running", + "shareableEventUuid": "37f8f1e9-8ec1-4c09-ae68-41a8bf62a900", + "eventCustomization": null, + "eventOrganizer": false, + }, + { + "id": 14784831, + "eventName": "Bank of America Chicago Marathon", + "date": "2024-10-13", + "completionTarget": { + "value": 42195.0, + "unit": "meter", + "unitType": "distance", + }, + "eventTimeLocal": { + "startTimeHhMm": "07:30", + "timeZoneId": "America/Chicago", + }, + "eventImageUUID": null, + "locationStartPoint": { + "lat": 41.8756, + "lon": -87.6276, + }, + "eventType": "running", + "shareableEventUuid": "4c1dba6c-9150-4980-b206-49efa5405ac9", + "eventCustomization": { + "customGoal": { + "value": 10080.0, + "unit": "second", + "unitType": "time", + }, + "isPrimaryEvent": true, + "associatedWithActivityId": null, + "isTrainingEvent": true, + "isGoalMet": false, + "trainingPlanId": null, + "trainingPlanType": null, + }, + "eventOrganizer": false, + }, + { + "id": 15480554, + "eventName": "Xfinity Newburyport Half Marathon", + "date": "2024-10-27", + "completionTarget": { + "value": 21097.0, + "unit": "meter", + "unitType": "distance", + }, + "eventTimeLocal": null, + "eventImageUUID": null, + "locationStartPoint": { + "lat": 42.812591, + "lon": -70.877275, + }, + "eventType": "running", + "shareableEventUuid": "42ea57d1-495a-4d36-8ad2-cf1af1a2fb9b", + "eventCustomization": { + "customGoal": { + "value": 4680.0, + "unit": "second", + "unitType": "time", + }, + "isPrimaryEvent": false, + "associatedWithActivityId": null, + "isTrainingEvent": true, + "isGoalMet": false, + "trainingPlanId": null, + "trainingPlanType": null, + }, + "eventOrganizer": false, + }, + ], + "hasMoreTrainingEvents": true, + } + } + }, + }, + { + "query": { + "query": "\n query {\n adhocChallengesScalar\n }\n " + }, + "response": {"data": {"adhocChallengesScalar": []}}, + }, + { + "query": { + "query": "\n query {\n adhocChallengePendingInviteScalar\n }\n " + }, + "response": {"data": {"adhocChallengePendingInviteScalar": []}}, + }, + { + "query": { + "query": "\n query {\n badgeChallengesScalar\n }\n " + }, + "response": { + "data": { + "badgeChallengesScalar": [ + { + "uuid": "0B5DC7B9881649988ADF51A93481BAC9", + "badgeChallengeName": "July Weekend 10K", + "startDate": "2024-07-12T00:00:00.0", + "endDate": "2024-07-14T23:59:59.0", + "progressValue": 0.0, + "targetValue": 0.0, + "unitId": 0, + "badgeKey": "challenge_run_10k_2024_07", + "challengeCategoryId": 1, + }, + { + "uuid": "64978DFD369B402C9DF627DF4072892F", + "badgeChallengeName": "Active July", + "startDate": "2024-07-01T00:00:00.0", + "endDate": "2024-07-31T23:59:59.0", + "progressValue": 9.0, + "targetValue": 20.0, + "unitId": 3, + "badgeKey": "challenge_total_activity_20_2024_07", + "challengeCategoryId": 9, + }, + { + "uuid": "9ABEF1B3C2EE412E8129AD5448A07D6B", + "badgeChallengeName": "July Step Month", + "startDate": "2024-07-01T00:00:00.0", + "endDate": "2024-07-31T23:59:59.0", + "progressValue": 134337.0, + "targetValue": 300000.0, + "unitId": 5, + "badgeKey": "challenge_total_step_300k_2024_07", + "challengeCategoryId": 4, + }, + ] + } + }, + }, + { + "query": { + "query": "\n query {\n expeditionsChallengesScalar\n }\n " + }, + "response": { + "data": { + "expeditionsChallengesScalar": [ + { + "uuid": "82E978F2D19542EFBC6A51EB7207792A", + "badgeChallengeName": "Aconcagua", + "startDate": null, + "endDate": null, + "progressValue": 1595.996, + "targetValue": 6961.0, + "unitId": 2, + "badgeKey": "virtual_climb_aconcagua", + "challengeCategoryId": 13, + }, + { + "uuid": "52F145179EC040AA9120A69E7265CDE1", + "badgeChallengeName": "Appalachian Trail", + "startDate": null, + "endDate": null, + "progressValue": 594771.0, + "targetValue": 3500000.0, + "unitId": 1, + "badgeKey": "virtual_hike_appalachian_trail", + "challengeCategoryId": 12, + }, + ] + } + }, + }, + { + "query": { + "query": 'query{trainingReadinessRangeScalar(startDate:"2024-06-11", endDate:"2024-07-08")}' + }, + "response": { + "data": { + "trainingReadinessRangeScalar": [ + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-07-08", + "timestamp": "2024-07-08T10:25:38.0", + "timestampLocal": "2024-07-08T06:25:38.0", + "deviceId": 3472661486, + "level": "HIGH", + "feedbackLong": "HIGH_RT_HIGHEST_SS_AVAILABLE", + "feedbackShort": "WELL_RECOVERED", + "score": 83, + "sleepScore": 89, + "sleepScoreFactorPercent": 88, + "sleepScoreFactorFeedback": "GOOD", + "recoveryTime": 242, + "recoveryTimeFactorPercent": 93, + "recoveryTimeFactorFeedback": "GOOD", + "acwrFactorPercent": 96, + "acwrFactorFeedback": "GOOD", + "acuteLoad": 886, + "stressHistoryFactorPercent": 83, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 88, + "hrvFactorFeedback": "GOOD", + "hrvWeeklyAverage": 68, + "sleepHistoryFactorPercent": 76, + "sleepHistoryFactorFeedback": "GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "NO_CHANGE_SLEEP", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-07-07", + "timestamp": "2024-07-07T10:45:39.0", + "timestampLocal": "2024-07-07T06:45:39.0", + "deviceId": 3472661486, + "level": "HIGH", + "feedbackLong": "HIGH_RT_HIGHEST_SS_AVAILABLE", + "feedbackShort": "WELL_RECOVERED", + "score": 78, + "sleepScore": 83, + "sleepScoreFactorPercent": 76, + "sleepScoreFactorFeedback": "GOOD", + "recoveryTime": 169, + "recoveryTimeFactorPercent": 95, + "recoveryTimeFactorFeedback": "GOOD", + "acwrFactorPercent": 95, + "acwrFactorFeedback": "GOOD", + "acuteLoad": 913, + "stressHistoryFactorPercent": 85, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 81, + "hrvFactorFeedback": "GOOD", + "hrvWeeklyAverage": 70, + "sleepHistoryFactorPercent": 80, + "sleepHistoryFactorFeedback": "GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "NO_CHANGE_SLEEP", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-07-06", + "timestamp": "2024-07-06T11:30:59.0", + "timestampLocal": "2024-07-06T07:30:59.0", + "deviceId": 3472661486, + "level": "MODERATE", + "feedbackLong": "MOD_RT_MOD_SS_GOOD", + "feedbackShort": "BOOSTED_BY_GOOD_SLEEP", + "score": 69, + "sleepScore": 83, + "sleepScoreFactorPercent": 76, + "sleepScoreFactorFeedback": "GOOD", + "recoveryTime": 1412, + "recoveryTimeFactorPercent": 62, + "recoveryTimeFactorFeedback": "MODERATE", + "acwrFactorPercent": 91, + "acwrFactorFeedback": "GOOD", + "acuteLoad": 998, + "stressHistoryFactorPercent": 87, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 88, + "hrvFactorFeedback": "GOOD", + "hrvWeeklyAverage": 68, + "sleepHistoryFactorPercent": 88, + "sleepHistoryFactorFeedback": "GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "NO_CHANGE_SLEEP", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-07-05", + "timestamp": "2024-07-05T11:49:07.0", + "timestampLocal": "2024-07-05T07:49:07.0", + "deviceId": 3472661486, + "level": "HIGH", + "feedbackLong": "HIGH_RT_HIGHEST_SS_AVAILABLE", + "feedbackShort": "WELL_RECOVERED", + "score": 88, + "sleepScore": 89, + "sleepScoreFactorPercent": 88, + "sleepScoreFactorFeedback": "GOOD", + "recoveryTime": 1, + "recoveryTimeFactorPercent": 99, + "recoveryTimeFactorFeedback": "GOOD", + "acwrFactorPercent": 93, + "acwrFactorFeedback": "GOOD", + "acuteLoad": 912, + "stressHistoryFactorPercent": 92, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 91, + "hrvFactorFeedback": "GOOD", + "hrvWeeklyAverage": 66, + "sleepHistoryFactorPercent": 84, + "sleepHistoryFactorFeedback": "GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "NO_CHANGE_SLEEP", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-07-04", + "timestamp": "2024-07-04T11:32:14.0", + "timestampLocal": "2024-07-04T07:32:14.0", + "deviceId": 3472661486, + "level": "MODERATE", + "feedbackLong": "MOD_RT_MOD_SS_GOOD", + "feedbackShort": "BOOSTED_BY_GOOD_SLEEP", + "score": 72, + "sleepScore": 89, + "sleepScoreFactorPercent": 88, + "sleepScoreFactorFeedback": "GOOD", + "recoveryTime": 1190, + "recoveryTimeFactorPercent": 68, + "recoveryTimeFactorFeedback": "MODERATE", + "acwrFactorPercent": 89, + "acwrFactorFeedback": "GOOD", + "acuteLoad": 1007, + "stressHistoryFactorPercent": 100, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 90, + "hrvFactorFeedback": "GOOD", + "hrvWeeklyAverage": 66, + "sleepHistoryFactorPercent": 85, + "sleepHistoryFactorFeedback": "GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "NO_CHANGE_SLEEP", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-07-03", + "timestamp": "2024-07-03T11:16:48.0", + "timestampLocal": "2024-07-03T07:16:48.0", + "deviceId": 3472661486, + "level": "HIGH", + "feedbackLong": "HIGH_RT_HIGHEST_SS_AVAILABLE_SLEEP_HISTORY_POS", + "feedbackShort": "WELL_RESTED_AND_RECOVERED", + "score": 86, + "sleepScore": 83, + "sleepScoreFactorPercent": 76, + "sleepScoreFactorFeedback": "GOOD", + "recoveryTime": 425, + "recoveryTimeFactorPercent": 88, + "recoveryTimeFactorFeedback": "GOOD", + "acwrFactorPercent": 92, + "acwrFactorFeedback": "GOOD", + "acuteLoad": 938, + "stressHistoryFactorPercent": 100, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 92, + "hrvFactorFeedback": "GOOD", + "hrvWeeklyAverage": 65, + "sleepHistoryFactorPercent": 94, + "sleepHistoryFactorFeedback": "VERY_GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "NO_CHANGE_SLEEP", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-07-02", + "timestamp": "2024-07-02T09:55:58.0", + "timestampLocal": "2024-07-02T05:55:58.0", + "deviceId": 3472661486, + "level": "HIGH", + "feedbackLong": "HIGH_RT_AVAILABLE_SS_HIGHEST", + "feedbackShort": "RESTED_AND_READY", + "score": 93, + "sleepScore": 97, + "sleepScoreFactorPercent": 97, + "sleepScoreFactorFeedback": "VERY_GOOD", + "recoveryTime": 0, + "recoveryTimeFactorPercent": 100, + "recoveryTimeFactorFeedback": "VERY_GOOD", + "acwrFactorPercent": 92, + "acwrFactorFeedback": "GOOD", + "acuteLoad": 928, + "stressHistoryFactorPercent": 100, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 88, + "hrvFactorFeedback": "GOOD", + "hrvWeeklyAverage": 66, + "sleepHistoryFactorPercent": 81, + "sleepHistoryFactorFeedback": "GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "REACHED_ZERO", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-07-01", + "timestamp": "2024-07-01T09:56:56.0", + "timestampLocal": "2024-07-01T05:56:56.0", + "deviceId": 3472661486, + "level": "MODERATE", + "feedbackLong": "MOD_RT_MOD_SS_GOOD", + "feedbackShort": "BOOSTED_BY_GOOD_SLEEP", + "score": 69, + "sleepScore": 89, + "sleepScoreFactorPercent": 88, + "sleepScoreFactorFeedback": "GOOD", + "recoveryTime": 1473, + "recoveryTimeFactorPercent": 60, + "recoveryTimeFactorFeedback": "MODERATE", + "acwrFactorPercent": 88, + "acwrFactorFeedback": "GOOD", + "acuteLoad": 1013, + "stressHistoryFactorPercent": 98, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 92, + "hrvFactorFeedback": "GOOD", + "hrvWeeklyAverage": 65, + "sleepHistoryFactorPercent": 76, + "sleepHistoryFactorFeedback": "GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "NO_CHANGE_SLEEP", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-30", + "timestamp": "2024-06-30T10:46:24.0", + "timestampLocal": "2024-06-30T06:46:24.0", + "deviceId": 3472661486, + "level": "HIGH", + "feedbackLong": "HIGH_RT_HIGHEST_SS_AVAILABLE_SLEEP_HISTORY_POS", + "feedbackShort": "WELL_RESTED_AND_RECOVERED", + "score": 84, + "sleepScore": 79, + "sleepScoreFactorPercent": 68, + "sleepScoreFactorFeedback": "MODERATE", + "recoveryTime": 323, + "recoveryTimeFactorPercent": 91, + "recoveryTimeFactorFeedback": "GOOD", + "acwrFactorPercent": 91, + "acwrFactorFeedback": "GOOD", + "acuteLoad": 928, + "stressHistoryFactorPercent": 94, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 92, + "hrvFactorFeedback": "GOOD", + "hrvWeeklyAverage": 65, + "sleepHistoryFactorPercent": 90, + "sleepHistoryFactorFeedback": "VERY_GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "NO_CHANGE_SLEEP", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-29", + "timestamp": "2024-06-29T10:23:11.0", + "timestampLocal": "2024-06-29T06:23:11.0", + "deviceId": 3472661486, + "level": "HIGH", + "feedbackLong": "HIGH_EVENT_DATE", + "feedbackShort": "GO_GET_IT", + "score": 83, + "sleepScore": 92, + "sleepScoreFactorPercent": 92, + "sleepScoreFactorFeedback": "VERY_GOOD", + "recoveryTime": 644, + "recoveryTimeFactorPercent": 83, + "recoveryTimeFactorFeedback": "GOOD", + "acwrFactorPercent": 94, + "acwrFactorFeedback": "GOOD", + "acuteLoad": 827, + "stressHistoryFactorPercent": 95, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 87, + "hrvFactorFeedback": "GOOD", + "hrvWeeklyAverage": 67, + "sleepHistoryFactorPercent": 85, + "sleepHistoryFactorFeedback": "GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "GOOD_SLEEP", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-28", + "timestamp": "2024-06-28T10:21:35.0", + "timestampLocal": "2024-06-28T06:21:35.0", + "deviceId": 3472661486, + "level": "MODERATE", + "feedbackLong": "MOD_RT_MOD_SS_GOOD", + "feedbackShort": "BOOSTED_BY_GOOD_SLEEP", + "score": 74, + "sleepScore": 87, + "sleepScoreFactorPercent": 84, + "sleepScoreFactorFeedback": "GOOD", + "recoveryTime": 1312, + "recoveryTimeFactorPercent": 65, + "recoveryTimeFactorFeedback": "MODERATE", + "acwrFactorPercent": 93, + "acwrFactorFeedback": "GOOD", + "acuteLoad": 841, + "stressHistoryFactorPercent": 91, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 91, + "hrvFactorFeedback": "GOOD", + "hrvWeeklyAverage": 65, + "sleepHistoryFactorPercent": 87, + "sleepHistoryFactorFeedback": "GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "NO_CHANGE_SLEEP", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-27", + "timestamp": "2024-06-27T10:55:40.0", + "timestampLocal": "2024-06-27T06:55:40.0", + "deviceId": 3472661486, + "level": "HIGH", + "feedbackLong": "HIGH_RT_HIGHEST_SS_AVAILABLE", + "feedbackShort": "WELL_RECOVERED", + "score": 87, + "sleepScore": 89, + "sleepScoreFactorPercent": 88, + "sleepScoreFactorFeedback": "GOOD", + "recoveryTime": 187, + "recoveryTimeFactorPercent": 95, + "recoveryTimeFactorFeedback": "GOOD", + "acwrFactorPercent": 95, + "acwrFactorFeedback": "GOOD", + "acuteLoad": 792, + "stressHistoryFactorPercent": 93, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 94, + "hrvFactorFeedback": "GOOD", + "hrvWeeklyAverage": 64, + "sleepHistoryFactorPercent": 81, + "sleepHistoryFactorFeedback": "GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "NO_CHANGE_SLEEP", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-26", + "timestamp": "2024-06-26T10:25:48.0", + "timestampLocal": "2024-06-26T06:25:48.0", + "deviceId": 3472661486, + "level": "HIGH", + "feedbackLong": "HIGH_RT_AVAILABLE_SS_HIGHEST", + "feedbackShort": "RESTED_AND_READY", + "score": 77, + "sleepScore": 88, + "sleepScoreFactorPercent": 86, + "sleepScoreFactorFeedback": "GOOD", + "recoveryTime": 1059, + "recoveryTimeFactorPercent": 72, + "recoveryTimeFactorFeedback": "GOOD", + "acwrFactorPercent": 92, + "acwrFactorFeedback": "GOOD", + "acuteLoad": 855, + "stressHistoryFactorPercent": 89, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 100, + "hrvFactorFeedback": "VERY_GOOD", + "hrvWeeklyAverage": 61, + "sleepHistoryFactorPercent": 82, + "sleepHistoryFactorFeedback": "GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "NO_CHANGE_SLEEP", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-25", + "timestamp": "2024-06-25T10:59:43.0", + "timestampLocal": "2024-06-25T06:59:43.0", + "deviceId": 3472661486, + "level": "MODERATE", + "feedbackLong": "MOD_RT_MOD_SS_GOOD", + "feedbackShort": "BOOSTED_BY_GOOD_SLEEP", + "score": 74, + "sleepScore": 81, + "sleepScoreFactorPercent": 72, + "sleepScoreFactorFeedback": "GOOD", + "recoveryTime": 1174, + "recoveryTimeFactorPercent": 69, + "recoveryTimeFactorFeedback": "MODERATE", + "acwrFactorPercent": 96, + "acwrFactorFeedback": "GOOD", + "acuteLoad": 761, + "stressHistoryFactorPercent": 87, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 100, + "hrvFactorFeedback": "VERY_GOOD", + "hrvWeeklyAverage": 60, + "sleepHistoryFactorPercent": 88, + "sleepHistoryFactorFeedback": "GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "NO_CHANGE_SLEEP", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-24", + "timestamp": "2024-06-24T11:25:43.0", + "timestampLocal": "2024-06-24T07:25:43.0", + "deviceId": 3472661486, + "level": "MODERATE", + "feedbackLong": "MOD_RT_HIGH_SS_GOOD", + "feedbackShort": "BOOSTED_BY_GOOD_SLEEP", + "score": 52, + "sleepScore": 96, + "sleepScoreFactorPercent": 96, + "sleepScoreFactorFeedback": "VERY_GOOD", + "recoveryTime": 2607, + "recoveryTimeFactorPercent": 34, + "recoveryTimeFactorFeedback": "POOR", + "acwrFactorPercent": 89, + "acwrFactorFeedback": "GOOD", + "acuteLoad": 920, + "stressHistoryFactorPercent": 80, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 100, + "hrvFactorFeedback": "VERY_GOOD", + "hrvWeeklyAverage": 61, + "sleepHistoryFactorPercent": 70, + "sleepHistoryFactorFeedback": "GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "EXCELLENT_SLEEP", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-23", + "timestamp": "2024-06-23T11:57:03.0", + "timestampLocal": "2024-06-23T07:57:03.0", + "deviceId": 3472661486, + "level": "LOW", + "feedbackLong": "LOW_RT_HIGH_SS_GOOD_OR_MOD", + "feedbackShort": "HIGH_RECOVERY_NEEDS", + "score": 38, + "sleepScore": 76, + "sleepScoreFactorPercent": 64, + "sleepScoreFactorFeedback": "MODERATE", + "recoveryTime": 2684, + "recoveryTimeFactorPercent": 33, + "recoveryTimeFactorFeedback": "POOR", + "acwrFactorPercent": 91, + "acwrFactorFeedback": "GOOD", + "acuteLoad": 878, + "stressHistoryFactorPercent": 86, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 95, + "hrvFactorFeedback": "GOOD", + "hrvWeeklyAverage": 62, + "sleepHistoryFactorPercent": 82, + "sleepHistoryFactorFeedback": "GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "NO_CHANGE_SLEEP", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-22", + "timestamp": "2024-06-22T11:05:15.0", + "timestampLocal": "2024-06-22T07:05:15.0", + "deviceId": 3472661486, + "level": "HIGH", + "feedbackLong": "HIGH_RT_HIGHEST_SS_AVAILABLE", + "feedbackShort": "WELL_RECOVERED", + "score": 90, + "sleepScore": 88, + "sleepScoreFactorPercent": 86, + "sleepScoreFactorFeedback": "GOOD", + "recoveryTime": 1, + "recoveryTimeFactorPercent": 99, + "recoveryTimeFactorFeedback": "GOOD", + "acwrFactorPercent": 99, + "acwrFactorFeedback": "GOOD", + "acuteLoad": 710, + "stressHistoryFactorPercent": 88, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 97, + "hrvFactorFeedback": "GOOD", + "hrvWeeklyAverage": 62, + "sleepHistoryFactorPercent": 73, + "sleepHistoryFactorFeedback": "GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "NO_CHANGE_SLEEP", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-21", + "timestamp": "2024-06-21T10:05:47.0", + "timestampLocal": "2024-06-21T06:05:47.0", + "deviceId": 3472661486, + "level": "HIGH", + "feedbackLong": "HIGH_RT_HIGHEST_SS_AVAILABLE", + "feedbackShort": "WELL_RECOVERED", + "score": 76, + "sleepScore": 82, + "sleepScoreFactorPercent": 74, + "sleepScoreFactorFeedback": "GOOD", + "recoveryTime": 633, + "recoveryTimeFactorPercent": 83, + "recoveryTimeFactorFeedback": "GOOD", + "acwrFactorPercent": 98, + "acwrFactorFeedback": "GOOD", + "acuteLoad": 738, + "stressHistoryFactorPercent": 81, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 100, + "hrvFactorFeedback": "VERY_GOOD", + "hrvWeeklyAverage": 60, + "sleepHistoryFactorPercent": 66, + "sleepHistoryFactorFeedback": "MODERATE", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "NO_CHANGE_SLEEP", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-20", + "timestamp": "2024-06-20T10:17:04.0", + "timestampLocal": "2024-06-20T06:17:04.0", + "deviceId": 3472661486, + "level": "HIGH", + "feedbackLong": "HIGH_RT_HIGHEST_SS_AVAILABLE", + "feedbackShort": "WELL_RECOVERED", + "score": 79, + "sleepScore": 81, + "sleepScoreFactorPercent": 72, + "sleepScoreFactorFeedback": "GOOD", + "recoveryTime": 61, + "recoveryTimeFactorPercent": 98, + "recoveryTimeFactorFeedback": "GOOD", + "acwrFactorPercent": 100, + "acwrFactorFeedback": "VERY_GOOD", + "acuteLoad": 569, + "stressHistoryFactorPercent": 77, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 100, + "hrvFactorFeedback": "VERY_GOOD", + "hrvWeeklyAverage": 58, + "sleepHistoryFactorPercent": 61, + "sleepHistoryFactorFeedback": "MODERATE", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "NO_CHANGE_SLEEP", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-19", + "timestamp": "2024-06-19T10:46:11.0", + "timestampLocal": "2024-06-19T06:46:11.0", + "deviceId": 3472661486, + "level": "MODERATE", + "feedbackLong": "MOD_RT_LOW_SS_MOD", + "feedbackShort": "GOOD_SLEEP_HISTORY", + "score": 72, + "sleepScore": 70, + "sleepScoreFactorPercent": 55, + "sleepScoreFactorFeedback": "MODERATE", + "recoveryTime": 410, + "recoveryTimeFactorPercent": 89, + "recoveryTimeFactorFeedback": "GOOD", + "acwrFactorPercent": 100, + "acwrFactorFeedback": "VERY_GOOD", + "acuteLoad": 562, + "stressHistoryFactorPercent": 94, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 100, + "hrvFactorFeedback": "VERY_GOOD", + "hrvWeeklyAverage": 60, + "sleepHistoryFactorPercent": 80, + "sleepHistoryFactorFeedback": "GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "NO_CHANGE_SLEEP", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-18", + "timestamp": "2024-06-18T11:08:29.0", + "timestampLocal": "2024-06-18T07:08:29.0", + "deviceId": 3472661486, + "level": "PRIME", + "feedbackLong": "PRIME_RT_HIGHEST_SS_AVAILABLE_SLEEP_HISTORY_POS", + "feedbackShort": "READY_TO_GO", + "score": 95, + "sleepScore": 82, + "sleepScoreFactorPercent": 74, + "sleepScoreFactorFeedback": "GOOD", + "recoveryTime": 1, + "recoveryTimeFactorPercent": 99, + "recoveryTimeFactorFeedback": "GOOD", + "acwrFactorPercent": 100, + "acwrFactorFeedback": "VERY_GOOD", + "acuteLoad": 495, + "stressHistoryFactorPercent": 100, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 100, + "hrvFactorFeedback": "VERY_GOOD", + "hrvWeeklyAverage": 59, + "sleepHistoryFactorPercent": 90, + "sleepHistoryFactorFeedback": "VERY_GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "NO_CHANGE_SLEEP", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-17", + "timestamp": "2024-06-17T11:20:34.0", + "timestampLocal": "2024-06-17T07:20:34.0", + "deviceId": 3472661486, + "level": "HIGH", + "feedbackLong": "HIGH_RT_HIGHEST_SS_AVAILABLE", + "feedbackShort": "WELL_RECOVERED", + "score": 92, + "sleepScore": 91, + "sleepScoreFactorPercent": 91, + "sleepScoreFactorFeedback": "VERY_GOOD", + "recoveryTime": 0, + "recoveryTimeFactorPercent": 100, + "recoveryTimeFactorFeedback": "VERY_GOOD", + "acwrFactorPercent": 100, + "acwrFactorFeedback": "VERY_GOOD", + "acuteLoad": 643, + "stressHistoryFactorPercent": 100, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 100, + "hrvFactorFeedback": "VERY_GOOD", + "hrvWeeklyAverage": 59, + "sleepHistoryFactorPercent": 86, + "sleepHistoryFactorFeedback": "GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "REACHED_ZERO", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-16", + "timestamp": "2024-06-16T10:30:48.0", + "timestampLocal": "2024-06-16T06:30:48.0", + "deviceId": 3472661486, + "level": "HIGH", + "feedbackLong": "HIGH_RT_HIGHEST_SS_AVAILABLE", + "feedbackShort": "WELL_RECOVERED", + "score": 89, + "sleepScore": 89, + "sleepScoreFactorPercent": 88, + "sleepScoreFactorFeedback": "GOOD", + "recoveryTime": 1, + "recoveryTimeFactorPercent": 99, + "recoveryTimeFactorFeedback": "GOOD", + "acwrFactorPercent": 100, + "acwrFactorFeedback": "VERY_GOOD", + "acuteLoad": 680, + "stressHistoryFactorPercent": 94, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 100, + "hrvFactorFeedback": "VERY_GOOD", + "hrvWeeklyAverage": 58, + "sleepHistoryFactorPercent": 78, + "sleepHistoryFactorFeedback": "GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "NO_CHANGE_SLEEP", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-15", + "timestamp": "2024-06-15T10:41:26.0", + "timestampLocal": "2024-06-15T06:41:26.0", + "deviceId": 3472661486, + "level": "HIGH", + "feedbackLong": "HIGH_RT_HIGHEST_SS_AVAILABLE", + "feedbackShort": "WELL_RECOVERED", + "score": 85, + "sleepScore": 86, + "sleepScoreFactorPercent": 82, + "sleepScoreFactorFeedback": "GOOD", + "recoveryTime": 1, + "recoveryTimeFactorPercent": 99, + "recoveryTimeFactorFeedback": "GOOD", + "acwrFactorPercent": 100, + "acwrFactorFeedback": "VERY_GOOD", + "acuteLoad": 724, + "stressHistoryFactorPercent": 86, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 100, + "hrvFactorFeedback": "VERY_GOOD", + "hrvWeeklyAverage": 57, + "sleepHistoryFactorPercent": 72, + "sleepHistoryFactorFeedback": "GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "NO_CHANGE_SLEEP", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-14", + "timestamp": "2024-06-14T10:30:42.0", + "timestampLocal": "2024-06-14T06:30:42.0", + "deviceId": 3472661486, + "level": "MODERATE", + "feedbackLong": "MOD_RT_LOW_SS_GOOD", + "feedbackShort": "RECOVERED_AND_READY", + "score": 71, + "sleepScore": 81, + "sleepScoreFactorPercent": 72, + "sleepScoreFactorFeedback": "GOOD", + "recoveryTime": 1041, + "recoveryTimeFactorPercent": 72, + "recoveryTimeFactorFeedback": "GOOD", + "acwrFactorPercent": 94, + "acwrFactorFeedback": "GOOD", + "acuteLoad": 884, + "stressHistoryFactorPercent": 86, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 100, + "hrvFactorFeedback": "VERY_GOOD", + "hrvWeeklyAverage": 59, + "sleepHistoryFactorPercent": 78, + "sleepHistoryFactorFeedback": "GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "NO_CHANGE_SLEEP", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-13", + "timestamp": "2024-06-13T10:24:07.0", + "timestampLocal": "2024-06-13T06:24:07.0", + "deviceId": 3472661486, + "level": "HIGH", + "feedbackLong": "HIGH_RT_AVAILABLE_SS_HIGHEST_SLEEP_HISTORY_POS", + "feedbackShort": "ENERGIZED_BY_GOOD_SLEEP", + "score": 75, + "sleepScore": 82, + "sleepScoreFactorPercent": 74, + "sleepScoreFactorFeedback": "GOOD", + "recoveryTime": 1602, + "recoveryTimeFactorPercent": 57, + "recoveryTimeFactorFeedback": "MODERATE", + "acwrFactorPercent": 93, + "acwrFactorFeedback": "GOOD", + "acuteLoad": 894, + "stressHistoryFactorPercent": 93, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 100, + "hrvFactorFeedback": "VERY_GOOD", + "hrvWeeklyAverage": 59, + "sleepHistoryFactorPercent": 91, + "sleepHistoryFactorFeedback": "VERY_GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "NO_CHANGE_SLEEP", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-12", + "timestamp": "2024-06-12T10:42:16.0", + "timestampLocal": "2024-06-12T06:42:16.0", + "deviceId": 3472661486, + "level": "HIGH", + "feedbackLong": "HIGH_RT_AVAILABLE_SS_HIGHEST_SLEEP_HISTORY_POS", + "feedbackShort": "ENERGIZED_BY_GOOD_SLEEP", + "score": 79, + "sleepScore": 89, + "sleepScoreFactorPercent": 88, + "sleepScoreFactorFeedback": "GOOD", + "recoveryTime": 1922, + "recoveryTimeFactorPercent": 48, + "recoveryTimeFactorFeedback": "MODERATE", + "acwrFactorPercent": 94, + "acwrFactorFeedback": "GOOD", + "acuteLoad": 882, + "stressHistoryFactorPercent": 97, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 100, + "hrvFactorFeedback": "VERY_GOOD", + "hrvWeeklyAverage": 57, + "sleepHistoryFactorPercent": 94, + "sleepHistoryFactorFeedback": "VERY_GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "NO_CHANGE_SLEEP", + }, + { + "userProfilePK": "user_id: int", + "calendarDate": "2024-06-11", + "timestamp": "2024-06-11T10:32:30.0", + "timestampLocal": "2024-06-11T06:32:30.0", + "deviceId": 3472661486, + "level": "HIGH", + "feedbackLong": "HIGH_RT_AVAILABLE_SS_HIGHEST_SLEEP_HISTORY_POS", + "feedbackShort": "ENERGIZED_BY_GOOD_SLEEP", + "score": 82, + "sleepScore": 96, + "sleepScoreFactorPercent": 96, + "sleepScoreFactorFeedback": "VERY_GOOD", + "recoveryTime": 1415, + "recoveryTimeFactorPercent": 62, + "recoveryTimeFactorFeedback": "MODERATE", + "acwrFactorPercent": 97, + "acwrFactorFeedback": "GOOD", + "acuteLoad": 802, + "stressHistoryFactorPercent": 95, + "stressHistoryFactorFeedback": "GOOD", + "hrvFactorPercent": 100, + "hrvFactorFeedback": "VERY_GOOD", + "hrvWeeklyAverage": 58, + "sleepHistoryFactorPercent": 89, + "sleepHistoryFactorFeedback": "GOOD", + "validSleep": true, + "inputContext": null, + "recoveryTimeChangePhrase": "EXCELLENT_SLEEP", + }, + ] + } + }, + }, + { + "query": { + "query": 'query{trainingStatusDailyScalar(calendarDate:"2024-07-08")}' + }, + "response": { + "data": { + "trainingStatusDailyScalar": { + "userId": "user_id: int", + "latestTrainingStatusData": { + "3472661486": { + "calendarDate": "2024-07-08", + "sinceDate": "2024-06-28", + "weeklyTrainingLoad": null, + "trainingStatus": 4, + "timestamp": 1720445627000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 2, + "trainingStatusFeedbackPhrase": "MAINTAINING_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 33, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 886, + "maxTrainingLoadChronic": 1506.0, + "minTrainingLoadChronic": 803.2, + "dailyTrainingLoadChronic": 1004, + "dailyAcuteChronicWorkloadRatio": 0.8, + }, + "primaryTrainingDevice": true, + } + }, + "recordedDevices": [ + { + "deviceId": 3472661486, + "imageURL": "https://res.garmin.com/en/products/010-02809-02/v/c1_01_md.png", + "deviceName": "Forerunner 965", + "category": 0, + } + ], + "showSelector": false, + "lastPrimarySyncDate": "2024-07-08", + } + } + }, + }, + { + "query": { + "query": 'query{trainingStatusWeeklyScalar(startDate:"2024-06-11", endDate:"2024-07-08", displayName:"ca8406dd-d7dd-4adb-825e-16967b1e82fb")}' + }, + "response": { + "data": { + "trainingStatusWeeklyScalar": { + "userId": "user_id: int", + "fromCalendarDate": "2024-06-11", + "toCalendarDate": "2024-07-08", + "showSelector": false, + "recordedDevices": [ + { + "deviceId": 3472661486, + "imageURL": "https://res.garmin.com/en/products/010-02809-02/v/c1_01_md.png", + "deviceName": "Forerunner 965", + "category": 0, + } + ], + "reportData": { + "3472661486": [ + { + "calendarDate": "2024-06-11", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 7, + "timestamp": 1718142014000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 3, + "trainingStatusFeedbackPhrase": "PRODUCTIVE_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 42, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 1049, + "maxTrainingLoadChronic": 1483.5, + "minTrainingLoadChronic": 791.2, + "dailyTrainingLoadChronic": 989, + "dailyAcuteChronicWorkloadRatio": 1.0, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-06-12", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 7, + "timestamp": 1718223210000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 3, + "trainingStatusFeedbackPhrase": "PRODUCTIVE_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 42, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 1080, + "maxTrainingLoadChronic": 1477.5, + "minTrainingLoadChronic": 788.0, + "dailyTrainingLoadChronic": 985, + "dailyAcuteChronicWorkloadRatio": 1.0, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-06-13", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 7, + "timestamp": 1718296688000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 3, + "trainingStatusFeedbackPhrase": "PRODUCTIVE_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 42, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 1068, + "maxTrainingLoadChronic": 1473.0, + "minTrainingLoadChronic": 785.6, + "dailyTrainingLoadChronic": 982, + "dailyAcuteChronicWorkloadRatio": 1.0, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-06-14", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 7, + "timestamp": 1718361041000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 3, + "trainingStatusFeedbackPhrase": "PRODUCTIVE_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 38, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 884, + "maxTrainingLoadChronic": 1423.5, + "minTrainingLoadChronic": 759.2, + "dailyTrainingLoadChronic": 949, + "dailyAcuteChronicWorkloadRatio": 0.9, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-06-15", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 7, + "timestamp": 1718453887000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 3, + "trainingStatusFeedbackPhrase": "PRODUCTIVE_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 38, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 852, + "maxTrainingLoadChronic": 1404.0, + "minTrainingLoadChronic": 748.8000000000001, + "dailyTrainingLoadChronic": 936, + "dailyAcuteChronicWorkloadRatio": 0.9, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-06-16", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 7, + "timestamp": 1718540790000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 3, + "trainingStatusFeedbackPhrase": "PRODUCTIVE_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 33, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 812, + "maxTrainingLoadChronic": 1387.5, + "minTrainingLoadChronic": 740.0, + "dailyTrainingLoadChronic": 925, + "dailyAcuteChronicWorkloadRatio": 0.8, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-06-17", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 7, + "timestamp": 1718623233000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 3, + "trainingStatusFeedbackPhrase": "PRODUCTIVE_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 29, + "acwrStatus": "LOW", + "acwrStatusFeedback": "FEEDBACK_1", + "dailyTrainingLoadAcute": 643, + "maxTrainingLoadChronic": 1336.5, + "minTrainingLoadChronic": 712.8000000000001, + "dailyTrainingLoadChronic": 891, + "dailyAcuteChronicWorkloadRatio": 0.7, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-06-18", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 6, + "timestamp": 1718714866000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 3, + "trainingStatusFeedbackPhrase": "PEAKING_1", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 29, + "acwrStatus": "LOW", + "acwrStatusFeedback": "FEEDBACK_1", + "dailyTrainingLoadAcute": 715, + "maxTrainingLoadChronic": 1344.0, + "minTrainingLoadChronic": 716.8000000000001, + "dailyTrainingLoadChronic": 896, + "dailyAcuteChronicWorkloadRatio": 0.7, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-06-19", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 6, + "timestamp": 1718798492000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 3, + "trainingStatusFeedbackPhrase": "PEAKING_1", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 29, + "acwrStatus": "LOW", + "acwrStatusFeedback": "FEEDBACK_1", + "dailyTrainingLoadAcute": 710, + "maxTrainingLoadChronic": 1333.5, + "minTrainingLoadChronic": 711.2, + "dailyTrainingLoadChronic": 889, + "dailyAcuteChronicWorkloadRatio": 0.7, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-06-20", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 7, + "timestamp": 1718921994000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 3, + "trainingStatusFeedbackPhrase": "PRODUCTIVE_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 38, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 895, + "maxTrainingLoadChronic": 1369.5, + "minTrainingLoadChronic": 730.4000000000001, + "dailyTrainingLoadChronic": 913, + "dailyAcuteChronicWorkloadRatio": 0.9, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-06-21", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 7, + "timestamp": 1718970618000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 3, + "trainingStatusFeedbackPhrase": "PRODUCTIVE_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 38, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 854, + "maxTrainingLoadChronic": 1347.0, + "minTrainingLoadChronic": 718.4000000000001, + "dailyTrainingLoadChronic": 898, + "dailyAcuteChronicWorkloadRatio": 0.9, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-06-22", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 7, + "timestamp": 1719083081000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 3, + "trainingStatusFeedbackPhrase": "PRODUCTIVE_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 47, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 1035, + "maxTrainingLoadChronic": 1381.5, + "minTrainingLoadChronic": 736.8000000000001, + "dailyTrainingLoadChronic": 921, + "dailyAcuteChronicWorkloadRatio": 1.1, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-06-23", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 7, + "timestamp": 1719177700000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 3, + "trainingStatusFeedbackPhrase": "PRODUCTIVE_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 47, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 1080, + "maxTrainingLoadChronic": 1383.0, + "minTrainingLoadChronic": 737.6, + "dailyTrainingLoadChronic": 922, + "dailyAcuteChronicWorkloadRatio": 1.1, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-06-24", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 7, + "timestamp": 1719228343000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 3, + "trainingStatusFeedbackPhrase": "PRODUCTIVE_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 42, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 920, + "maxTrainingLoadChronic": 1330.5, + "minTrainingLoadChronic": 709.6, + "dailyTrainingLoadChronic": 887, + "dailyAcuteChronicWorkloadRatio": 1.0, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-06-25", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 7, + "timestamp": 1719357364000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 3, + "trainingStatusFeedbackPhrase": "PRODUCTIVE_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 47, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 1029, + "maxTrainingLoadChronic": 1356.0, + "minTrainingLoadChronic": 723.2, + "dailyTrainingLoadChronic": 904, + "dailyAcuteChronicWorkloadRatio": 1.1, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-06-26", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 7, + "timestamp": 1719431699000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 3, + "trainingStatusFeedbackPhrase": "PRODUCTIVE_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 42, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 963, + "maxTrainingLoadChronic": 1339.5, + "minTrainingLoadChronic": 714.4000000000001, + "dailyTrainingLoadChronic": 893, + "dailyAcuteChronicWorkloadRatio": 1.0, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-06-27", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 7, + "timestamp": 1719517629000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 3, + "trainingStatusFeedbackPhrase": "PRODUCTIVE_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 47, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 1037, + "maxTrainingLoadChronic": 1362.0, + "minTrainingLoadChronic": 726.4000000000001, + "dailyTrainingLoadChronic": 908, + "dailyAcuteChronicWorkloadRatio": 1.1, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-06-28", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 4, + "timestamp": 1719596078000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 2, + "trainingStatusFeedbackPhrase": "MAINTAINING_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 47, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 1018, + "maxTrainingLoadChronic": 1371.0, + "minTrainingLoadChronic": 731.2, + "dailyTrainingLoadChronic": 914, + "dailyAcuteChronicWorkloadRatio": 1.1, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-06-29", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 4, + "timestamp": 1719684771000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 2, + "trainingStatusFeedbackPhrase": "MAINTAINING_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 52, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 1136, + "maxTrainingLoadChronic": 1416.0, + "minTrainingLoadChronic": 755.2, + "dailyTrainingLoadChronic": 944, + "dailyAcuteChronicWorkloadRatio": 1.2, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-06-30", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 4, + "timestamp": 1719764678000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 2, + "trainingStatusFeedbackPhrase": "MAINTAINING_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 52, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 1217, + "maxTrainingLoadChronic": 1458.0, + "minTrainingLoadChronic": 777.6, + "dailyTrainingLoadChronic": 972, + "dailyAcuteChronicWorkloadRatio": 1.2, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-07-01", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 4, + "timestamp": 1719849197000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 2, + "trainingStatusFeedbackPhrase": "MAINTAINING_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 47, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 1133, + "maxTrainingLoadChronic": 1453.5, + "minTrainingLoadChronic": 775.2, + "dailyTrainingLoadChronic": 969, + "dailyAcuteChronicWorkloadRatio": 1.1, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-07-02", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 4, + "timestamp": 1719921774000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 2, + "trainingStatusFeedbackPhrase": "MAINTAINING_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 47, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 1130, + "maxTrainingLoadChronic": 1468.5, + "minTrainingLoadChronic": 783.2, + "dailyTrainingLoadChronic": 979, + "dailyAcuteChronicWorkloadRatio": 1.1, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-07-03", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 4, + "timestamp": 1720027612000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 2, + "trainingStatusFeedbackPhrase": "MAINTAINING_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 52, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 1206, + "maxTrainingLoadChronic": 1500.0, + "minTrainingLoadChronic": 800.0, + "dailyTrainingLoadChronic": 1000, + "dailyAcuteChronicWorkloadRatio": 1.2, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-07-04", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 4, + "timestamp": 1720096045000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 2, + "trainingStatusFeedbackPhrase": "MAINTAINING_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 47, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 1122, + "maxTrainingLoadChronic": 1489.5, + "minTrainingLoadChronic": 794.4000000000001, + "dailyTrainingLoadChronic": 993, + "dailyAcuteChronicWorkloadRatio": 1.1, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-07-05", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 4, + "timestamp": 1720194335000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 2, + "trainingStatusFeedbackPhrase": "MAINTAINING_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 47, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 1211, + "maxTrainingLoadChronic": 1534.5, + "minTrainingLoadChronic": 818.4000000000001, + "dailyTrainingLoadChronic": 1023, + "dailyAcuteChronicWorkloadRatio": 1.1, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-07-06", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 4, + "timestamp": 1720313044000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 2, + "trainingStatusFeedbackPhrase": "MAINTAINING_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 47, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 1128, + "maxTrainingLoadChronic": 1534.5, + "minTrainingLoadChronic": 818.4000000000001, + "dailyTrainingLoadChronic": 1023, + "dailyAcuteChronicWorkloadRatio": 1.1, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-07-07", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 4, + "timestamp": 1720353825000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 2, + "trainingStatusFeedbackPhrase": "MAINTAINING_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 42, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 1096, + "maxTrainingLoadChronic": 1546.5, + "minTrainingLoadChronic": 824.8000000000001, + "dailyTrainingLoadChronic": 1031, + "dailyAcuteChronicWorkloadRatio": 1.0, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-07-08", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 4, + "timestamp": 1720445627000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 2, + "trainingStatusFeedbackPhrase": "MAINTAINING_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 33, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 886, + "maxTrainingLoadChronic": 1506.0, + "minTrainingLoadChronic": 803.2, + "dailyTrainingLoadChronic": 1004, + "dailyAcuteChronicWorkloadRatio": 0.8, + }, + "primaryTrainingDevice": true, + }, + ] + }, + } + } + }, + }, + { + "query": { + "query": 'query{trainingLoadBalanceScalar(calendarDate:"2024-07-08", fullHistoryScan:true)}' + }, + "response": { + "data": { + "trainingLoadBalanceScalar": { + "userId": "user_id: int", + "metricsTrainingLoadBalanceDTOMap": { + "3472661486": { + "calendarDate": "2024-07-08", + "deviceId": 3472661486, + "monthlyLoadAerobicLow": 1926.3918, + "monthlyLoadAerobicHigh": 1651.8569, + "monthlyLoadAnaerobic": 260.00317, + "monthlyLoadAerobicLowTargetMin": 1404, + "monthlyLoadAerobicLowTargetMax": 2282, + "monthlyLoadAerobicHighTargetMin": 1229, + "monthlyLoadAerobicHighTargetMax": 2107, + "monthlyLoadAnaerobicTargetMin": 175, + "monthlyLoadAnaerobicTargetMax": 702, + "trainingBalanceFeedbackPhrase": "ON_TARGET", + "primaryTrainingDevice": true, + } + }, + "recordedDevices": [ + { + "deviceId": 3472661486, + "imageURL": "https://res.garmin.com/en/products/010-02809-02/v/c1_01_md.png", + "deviceName": "Forerunner 965", + "category": 0, + } + ], + } + } + }, + }, + { + "query": { + "query": 'query{heatAltitudeAcclimationScalar(date:"2024-07-08")}' + }, + "response": { + "data": { + "heatAltitudeAcclimationScalar": { + "calendarDate": "2024-07-08", + "altitudeAcclimationDate": "2024-07-08", + "previousAltitudeAcclimationDate": "2024-07-08", + "heatAcclimationDate": "2024-07-08", + "previousHeatAcclimationDate": "2024-06-30", + "altitudeAcclimation": 0, + "previousAltitudeAcclimation": 0, + "heatAcclimationPercentage": 100, + "previousHeatAcclimationPercentage": 100, + "heatTrend": "ACCLIMATIZED", + "altitudeTrend": null, + "currentAltitude": 0, + "previousAltitude": 0, + "acclimationPercentage": 0, + "previousAcclimationPercentage": 0, + "altitudeAcclimationLocalTimestamp": "2024-07-08T09:33:47.0", + } + } + }, + }, + { + "query": { + "query": 'query{vo2MaxScalar(startDate:"2024-06-11", endDate:"2024-07-08")}' + }, + "response": { + "data": { + "vo2MaxScalar": [ + { + "userId": "user_id: int", + "generic": { + "calendarDate": "2024-06-11", + "vo2MaxPreciseValue": 60.5, + "vo2MaxValue": 61.0, + "fitnessAge": null, + "fitnessAgeDescription": null, + "maxMetCategory": 0, + }, + "cycling": null, + "heatAltitudeAcclimation": { + "calendarDate": "2024-06-11", + "altitudeAcclimationDate": "2024-06-12", + "previousAltitudeAcclimationDate": "2024-06-12", + "heatAcclimationDate": "2024-06-11", + "previousHeatAcclimationDate": "2024-06-10", + "altitudeAcclimation": 0, + "previousAltitudeAcclimation": 0, + "heatAcclimationPercentage": 45, + "previousHeatAcclimationPercentage": 45, + "heatTrend": "ACCLIMATIZED", + "altitudeTrend": null, + "currentAltitude": 48, + "previousAltitude": 0, + "acclimationPercentage": 0, + "previousAcclimationPercentage": 0, + "altitudeAcclimationLocalTimestamp": "2024-06-11T23:56:55.0", + }, + }, + { + "userId": "user_id: int", + "generic": { + "calendarDate": "2024-06-12", + "vo2MaxPreciseValue": 60.5, + "vo2MaxValue": 61.0, + "fitnessAge": null, + "fitnessAgeDescription": null, + "maxMetCategory": 0, + }, + "cycling": null, + "heatAltitudeAcclimation": { + "calendarDate": "2024-06-12", + "altitudeAcclimationDate": "2024-06-13", + "previousAltitudeAcclimationDate": "2024-06-13", + "heatAcclimationDate": "2024-06-12", + "previousHeatAcclimationDate": "2024-06-11", + "altitudeAcclimation": 0, + "previousAltitudeAcclimation": 0, + "heatAcclimationPercentage": 48, + "previousHeatAcclimationPercentage": 45, + "heatTrend": "ACCLIMATIZING", + "altitudeTrend": null, + "currentAltitude": 54, + "previousAltitude": 0, + "acclimationPercentage": 0, + "previousAcclimationPercentage": 0, + "altitudeAcclimationLocalTimestamp": "2024-06-12T23:54:41.0", + }, + }, + { + "userId": "user_id: int", + "generic": { + "calendarDate": "2024-06-13", + "vo2MaxPreciseValue": 60.5, + "vo2MaxValue": 60.0, + "fitnessAge": null, + "fitnessAgeDescription": null, + "maxMetCategory": 0, + }, + "cycling": null, + "heatAltitudeAcclimation": { + "calendarDate": "2024-06-13", + "altitudeAcclimationDate": "2024-06-14", + "previousAltitudeAcclimationDate": "2024-06-14", + "heatAcclimationDate": "2024-06-13", + "previousHeatAcclimationDate": "2024-06-12", + "altitudeAcclimation": 0, + "previousAltitudeAcclimation": 0, + "heatAcclimationPercentage": 52, + "previousHeatAcclimationPercentage": 48, + "heatTrend": "ACCLIMATIZING", + "altitudeTrend": null, + "currentAltitude": 67, + "previousAltitude": 0, + "acclimationPercentage": 0, + "previousAcclimationPercentage": 0, + "altitudeAcclimationLocalTimestamp": "2024-06-13T23:54:57.0", + }, + }, + { + "userId": "user_id: int", + "generic": { + "calendarDate": "2024-06-15", + "vo2MaxPreciseValue": 60.5, + "vo2MaxValue": 61.0, + "fitnessAge": null, + "fitnessAgeDescription": null, + "maxMetCategory": 0, + }, + "cycling": null, + "heatAltitudeAcclimation": { + "calendarDate": "2024-06-15", + "altitudeAcclimationDate": "2024-06-16", + "previousAltitudeAcclimationDate": "2024-06-16", + "heatAcclimationDate": "2024-06-15", + "previousHeatAcclimationDate": "2024-06-14", + "altitudeAcclimation": 0, + "previousAltitudeAcclimation": 0, + "heatAcclimationPercentage": 47, + "previousHeatAcclimationPercentage": 52, + "heatTrend": "DEACCLIMATIZING", + "altitudeTrend": null, + "currentAltitude": 65, + "previousAltitude": 0, + "acclimationPercentage": 0, + "previousAcclimationPercentage": 0, + "altitudeAcclimationLocalTimestamp": "2024-06-15T23:57:48.0", + }, + }, + { + "userId": "user_id: int", + "generic": { + "calendarDate": "2024-06-16", + "vo2MaxPreciseValue": 60.7, + "vo2MaxValue": 61.0, + "fitnessAge": null, + "fitnessAgeDescription": null, + "maxMetCategory": 0, + }, + "cycling": null, + "heatAltitudeAcclimation": { + "calendarDate": "2024-06-16", + "altitudeAcclimationDate": "2024-06-17", + "previousAltitudeAcclimationDate": "2024-06-17", + "heatAcclimationDate": "2024-06-16", + "previousHeatAcclimationDate": "2024-06-15", + "altitudeAcclimation": 0, + "previousAltitudeAcclimation": 0, + "heatAcclimationPercentage": 45, + "previousHeatAcclimationPercentage": 47, + "heatTrend": "DEACCLIMATIZING", + "altitudeTrend": null, + "currentAltitude": 73, + "previousAltitude": 0, + "acclimationPercentage": 0, + "previousAcclimationPercentage": 0, + "altitudeAcclimationLocalTimestamp": "2024-06-16T23:54:44.0", + }, + }, + { + "userId": "user_id: int", + "generic": { + "calendarDate": "2024-06-18", + "vo2MaxPreciseValue": 60.7, + "vo2MaxValue": 61.0, + "fitnessAge": null, + "fitnessAgeDescription": null, + "maxMetCategory": 0, + }, + "cycling": null, + "heatAltitudeAcclimation": { + "calendarDate": "2024-06-18", + "altitudeAcclimationDate": "2024-06-19", + "previousAltitudeAcclimationDate": "2024-06-19", + "heatAcclimationDate": "2024-06-18", + "previousHeatAcclimationDate": "2024-06-17", + "altitudeAcclimation": 0, + "previousAltitudeAcclimation": 0, + "heatAcclimationPercentage": 34, + "previousHeatAcclimationPercentage": 39, + "heatTrend": "DEACCLIMATIZING", + "altitudeTrend": null, + "currentAltitude": 68, + "previousAltitude": 0, + "acclimationPercentage": 0, + "previousAcclimationPercentage": 0, + "altitudeAcclimationLocalTimestamp": "2024-06-18T23:55:05.0", + }, + }, + { + "userId": "user_id: int", + "generic": { + "calendarDate": "2024-06-19", + "vo2MaxPreciseValue": 60.8, + "vo2MaxValue": 61.0, + "fitnessAge": null, + "fitnessAgeDescription": null, + "maxMetCategory": 0, + }, + "cycling": null, + "heatAltitudeAcclimation": { + "calendarDate": "2024-06-19", + "altitudeAcclimationDate": "2024-06-20", + "previousAltitudeAcclimationDate": "2024-06-20", + "heatAcclimationDate": "2024-06-19", + "previousHeatAcclimationDate": "2024-06-18", + "altitudeAcclimation": 0, + "previousAltitudeAcclimation": 0, + "heatAcclimationPercentage": 39, + "previousHeatAcclimationPercentage": 34, + "heatTrend": "ACCLIMATIZING", + "altitudeTrend": null, + "currentAltitude": 52, + "previousAltitude": 0, + "acclimationPercentage": 0, + "previousAcclimationPercentage": 0, + "altitudeAcclimationLocalTimestamp": "2024-06-19T23:57:54.0", + }, + }, + { + "userId": "user_id: int", + "generic": { + "calendarDate": "2024-06-20", + "vo2MaxPreciseValue": 60.5, + "vo2MaxValue": 61.0, + "fitnessAge": null, + "fitnessAgeDescription": null, + "maxMetCategory": 0, + }, + "cycling": null, + "heatAltitudeAcclimation": { + "calendarDate": "2024-06-20", + "altitudeAcclimationDate": "2024-06-21", + "previousAltitudeAcclimationDate": "2024-06-21", + "heatAcclimationDate": "2024-06-20", + "previousHeatAcclimationDate": "2024-06-19", + "altitudeAcclimation": 0, + "previousAltitudeAcclimation": 0, + "heatAcclimationPercentage": 45, + "previousHeatAcclimationPercentage": 39, + "heatTrend": "ACCLIMATIZING", + "altitudeTrend": null, + "currentAltitude": 69, + "previousAltitude": 0, + "acclimationPercentage": 0, + "previousAcclimationPercentage": 0, + "altitudeAcclimationLocalTimestamp": "2024-06-20T23:58:53.0", + }, + }, + { + "userId": "user_id: int", + "generic": { + "calendarDate": "2024-06-21", + "vo2MaxPreciseValue": 60.4, + "vo2MaxValue": 60.0, + "fitnessAge": null, + "fitnessAgeDescription": null, + "maxMetCategory": 0, + }, + "cycling": null, + "heatAltitudeAcclimation": { + "calendarDate": "2024-06-21", + "altitudeAcclimationDate": "2024-06-22", + "previousAltitudeAcclimationDate": "2024-06-22", + "heatAcclimationDate": "2024-06-21", + "previousHeatAcclimationDate": "2024-06-20", + "altitudeAcclimation": 0, + "previousAltitudeAcclimation": 0, + "heatAcclimationPercentage": 48, + "previousHeatAcclimationPercentage": 45, + "heatTrend": "ACCLIMATIZING", + "altitudeTrend": null, + "currentAltitude": 64, + "previousAltitude": 0, + "acclimationPercentage": 0, + "previousAcclimationPercentage": 0, + "altitudeAcclimationLocalTimestamp": "2024-06-21T23:58:46.0", + }, + }, + { + "userId": "user_id: int", + "generic": { + "calendarDate": "2024-06-22", + "vo2MaxPreciseValue": 60.5, + "vo2MaxValue": 60.0, + "fitnessAge": null, + "fitnessAgeDescription": null, + "maxMetCategory": 0, + }, + "cycling": null, + "heatAltitudeAcclimation": { + "calendarDate": "2024-06-22", + "altitudeAcclimationDate": "2024-06-23", + "previousAltitudeAcclimationDate": "2024-06-23", + "heatAcclimationDate": "2024-06-22", + "previousHeatAcclimationDate": "2024-06-21", + "altitudeAcclimation": 0, + "previousAltitudeAcclimation": 0, + "heatAcclimationPercentage": 48, + "previousHeatAcclimationPercentage": 48, + "heatTrend": "ACCLIMATIZED", + "altitudeTrend": null, + "currentAltitude": 60, + "previousAltitude": 0, + "acclimationPercentage": 0, + "previousAcclimationPercentage": 0, + "altitudeAcclimationLocalTimestamp": "2024-06-22T23:57:49.0", + }, + }, + { + "userId": "user_id: int", + "generic": { + "calendarDate": "2024-06-23", + "vo2MaxPreciseValue": 60.5, + "vo2MaxValue": 60.0, + "fitnessAge": null, + "fitnessAgeDescription": null, + "maxMetCategory": 0, + }, + "cycling": null, + "heatAltitudeAcclimation": { + "calendarDate": "2024-06-23", + "altitudeAcclimationDate": "2024-06-24", + "previousAltitudeAcclimationDate": "2024-06-24", + "heatAcclimationDate": "2024-06-23", + "previousHeatAcclimationDate": "2024-06-22", + "altitudeAcclimation": 0, + "previousAltitudeAcclimation": 0, + "heatAcclimationPercentage": 67, + "previousHeatAcclimationPercentage": 48, + "heatTrend": "ACCLIMATIZING", + "altitudeTrend": null, + "currentAltitude": 61, + "previousAltitude": 0, + "acclimationPercentage": 0, + "previousAcclimationPercentage": 0, + "altitudeAcclimationLocalTimestamp": "2024-06-23T23:55:07.0", + }, + }, + { + "userId": "user_id: int", + "generic": { + "calendarDate": "2024-06-25", + "vo2MaxPreciseValue": 60.4, + "vo2MaxValue": 60.0, + "fitnessAge": null, + "fitnessAgeDescription": null, + "maxMetCategory": 0, + }, + "cycling": null, + "heatAltitudeAcclimation": { + "calendarDate": "2024-06-25", + "altitudeAcclimationDate": "2024-06-26", + "previousAltitudeAcclimationDate": "2024-06-26", + "heatAcclimationDate": "2024-06-25", + "previousHeatAcclimationDate": "2024-06-24", + "altitudeAcclimation": 0, + "previousAltitudeAcclimation": 0, + "heatAcclimationPercentage": 73, + "previousHeatAcclimationPercentage": 67, + "heatTrend": "ACCLIMATIZING", + "altitudeTrend": null, + "currentAltitude": 65, + "previousAltitude": 0, + "acclimationPercentage": 0, + "previousAcclimationPercentage": 0, + "altitudeAcclimationLocalTimestamp": "2024-06-25T23:55:56.0", + }, + }, + { + "userId": "user_id: int", + "generic": { + "calendarDate": "2024-06-26", + "vo2MaxPreciseValue": 60.3, + "vo2MaxValue": 60.0, + "fitnessAge": null, + "fitnessAgeDescription": null, + "maxMetCategory": 0, + }, + "cycling": null, + "heatAltitudeAcclimation": { + "calendarDate": "2024-06-26", + "altitudeAcclimationDate": "2024-06-27", + "previousAltitudeAcclimationDate": "2024-06-27", + "heatAcclimationDate": "2024-06-26", + "previousHeatAcclimationDate": "2024-06-25", + "altitudeAcclimation": 0, + "previousAltitudeAcclimation": 0, + "heatAcclimationPercentage": 82, + "previousHeatAcclimationPercentage": 73, + "heatTrend": "ACCLIMATIZING", + "altitudeTrend": null, + "currentAltitude": 54, + "previousAltitude": 0, + "acclimationPercentage": 0, + "previousAcclimationPercentage": 0, + "altitudeAcclimationLocalTimestamp": "2024-06-26T23:55:51.0", + }, + }, + { + "userId": "user_id: int", + "generic": { + "calendarDate": "2024-06-27", + "vo2MaxPreciseValue": 60.3, + "vo2MaxValue": 60.0, + "fitnessAge": null, + "fitnessAgeDescription": null, + "maxMetCategory": 0, + }, + "cycling": null, + "heatAltitudeAcclimation": { + "calendarDate": "2024-06-27", + "altitudeAcclimationDate": "2024-06-28", + "previousAltitudeAcclimationDate": "2024-06-28", + "heatAcclimationDate": "2024-06-27", + "previousHeatAcclimationDate": "2024-06-26", + "altitudeAcclimation": 0, + "previousAltitudeAcclimation": 0, + "heatAcclimationPercentage": 96, + "previousHeatAcclimationPercentage": 82, + "heatTrend": "ACCLIMATIZING", + "altitudeTrend": null, + "currentAltitude": 42, + "previousAltitude": 0, + "acclimationPercentage": 0, + "previousAcclimationPercentage": 0, + "altitudeAcclimationLocalTimestamp": "2024-06-27T23:57:42.0", + }, + }, + { + "userId": "user_id: int", + "generic": { + "calendarDate": "2024-06-28", + "vo2MaxPreciseValue": 60.4, + "vo2MaxValue": 60.0, + "fitnessAge": null, + "fitnessAgeDescription": null, + "maxMetCategory": 0, + }, + "cycling": null, + "heatAltitudeAcclimation": { + "calendarDate": "2024-06-28", + "altitudeAcclimationDate": "2024-06-29", + "previousAltitudeAcclimationDate": "2024-06-29", + "heatAcclimationDate": "2024-06-28", + "previousHeatAcclimationDate": "2024-06-27", + "altitudeAcclimation": 0, + "previousAltitudeAcclimation": 0, + "heatAcclimationPercentage": 96, + "previousHeatAcclimationPercentage": 96, + "heatTrend": "ACCLIMATIZED", + "altitudeTrend": null, + "currentAltitude": 47, + "previousAltitude": 0, + "acclimationPercentage": 0, + "previousAcclimationPercentage": 0, + "altitudeAcclimationLocalTimestamp": "2024-06-28T23:57:37.0", + }, + }, + { + "userId": "user_id: int", + "generic": { + "calendarDate": "2024-06-29", + "vo2MaxPreciseValue": 60.4, + "vo2MaxValue": 60.0, + "fitnessAge": null, + "fitnessAgeDescription": null, + "maxMetCategory": 0, + }, + "cycling": null, + "heatAltitudeAcclimation": { + "calendarDate": "2024-06-29", + "altitudeAcclimationDate": "2024-06-30", + "previousAltitudeAcclimationDate": "2024-06-30", + "heatAcclimationDate": "2024-06-29", + "previousHeatAcclimationDate": "2024-06-28", + "altitudeAcclimation": 0, + "previousAltitudeAcclimation": 0, + "heatAcclimationPercentage": 91, + "previousHeatAcclimationPercentage": 96, + "heatTrend": "DEACCLIMATIZING", + "altitudeTrend": null, + "currentAltitude": 120, + "previousAltitude": 0, + "acclimationPercentage": 0, + "previousAcclimationPercentage": 0, + "altitudeAcclimationLocalTimestamp": "2024-06-29T23:56:02.0", + }, + }, + { + "userId": "user_id: int", + "generic": { + "calendarDate": "2024-06-30", + "vo2MaxPreciseValue": 60.4, + "vo2MaxValue": 60.0, + "fitnessAge": null, + "fitnessAgeDescription": null, + "maxMetCategory": 0, + }, + "cycling": null, + "heatAltitudeAcclimation": { + "calendarDate": "2024-06-30", + "altitudeAcclimationDate": "2024-07-01", + "previousAltitudeAcclimationDate": "2024-07-01", + "heatAcclimationDate": "2024-06-30", + "previousHeatAcclimationDate": "2024-06-30", + "altitudeAcclimation": 0, + "previousAltitudeAcclimation": 0, + "heatAcclimationPercentage": 100, + "previousHeatAcclimationPercentage": 91, + "heatTrend": "ACCLIMATIZING", + "altitudeTrend": null, + "currentAltitude": 41, + "previousAltitude": 0, + "acclimationPercentage": 0, + "previousAcclimationPercentage": 0, + "altitudeAcclimationLocalTimestamp": "2024-06-30T23:55:24.0", + }, + }, + { + "userId": "user_id: int", + "generic": { + "calendarDate": "2024-07-01", + "vo2MaxPreciseValue": 60.5, + "vo2MaxValue": 60.0, + "fitnessAge": null, + "fitnessAgeDescription": null, + "maxMetCategory": 0, + }, + "cycling": null, + "heatAltitudeAcclimation": { + "calendarDate": "2024-07-01", + "altitudeAcclimationDate": "2024-07-02", + "previousAltitudeAcclimationDate": "2024-07-02", + "heatAcclimationDate": "2024-07-01", + "previousHeatAcclimationDate": "2024-06-30", + "altitudeAcclimation": 0, + "previousAltitudeAcclimation": 0, + "heatAcclimationPercentage": 100, + "previousHeatAcclimationPercentage": 100, + "heatTrend": "ACCLIMATIZED", + "altitudeTrend": null, + "currentAltitude": 43, + "previousAltitude": 0, + "acclimationPercentage": 0, + "previousAcclimationPercentage": 0, + "altitudeAcclimationLocalTimestamp": "2024-07-01T23:56:31.0", + }, + }, + { + "userId": "user_id: int", + "generic": { + "calendarDate": "2024-07-02", + "vo2MaxPreciseValue": 60.5, + "vo2MaxValue": 61.0, + "fitnessAge": null, + "fitnessAgeDescription": null, + "maxMetCategory": 0, + }, + "cycling": null, + "heatAltitudeAcclimation": { + "calendarDate": "2024-07-02", + "altitudeAcclimationDate": "2024-07-03", + "previousAltitudeAcclimationDate": "2024-07-03", + "heatAcclimationDate": "2024-07-02", + "previousHeatAcclimationDate": "2024-06-30", + "altitudeAcclimation": 0, + "previousAltitudeAcclimation": 0, + "heatAcclimationPercentage": 100, + "previousHeatAcclimationPercentage": 100, + "heatTrend": "ACCLIMATIZED", + "altitudeTrend": null, + "currentAltitude": 0, + "previousAltitude": 0, + "acclimationPercentage": 0, + "previousAcclimationPercentage": 0, + "altitudeAcclimationLocalTimestamp": "2024-07-02T23:58:21.0", + }, + }, + { + "userId": "user_id: int", + "generic": { + "calendarDate": "2024-07-03", + "vo2MaxPreciseValue": 60.6, + "vo2MaxValue": 61.0, + "fitnessAge": null, + "fitnessAgeDescription": null, + "maxMetCategory": 0, + }, + "cycling": null, + "heatAltitudeAcclimation": { + "calendarDate": "2024-07-03", + "altitudeAcclimationDate": "2024-07-04", + "previousAltitudeAcclimationDate": "2024-07-04", + "heatAcclimationDate": "2024-07-03", + "previousHeatAcclimationDate": "2024-06-30", + "altitudeAcclimation": 0, + "previousAltitudeAcclimation": 0, + "heatAcclimationPercentage": 100, + "previousHeatAcclimationPercentage": 100, + "heatTrend": "ACCLIMATIZED", + "altitudeTrend": null, + "currentAltitude": 19, + "previousAltitude": 0, + "acclimationPercentage": 0, + "previousAcclimationPercentage": 0, + "altitudeAcclimationLocalTimestamp": "2024-07-03T23:57:17.0", + }, + }, + { + "userId": "user_id: int", + "generic": { + "calendarDate": "2024-07-04", + "vo2MaxPreciseValue": 60.6, + "vo2MaxValue": 61.0, + "fitnessAge": null, + "fitnessAgeDescription": null, + "maxMetCategory": 0, + }, + "cycling": null, + "heatAltitudeAcclimation": { + "calendarDate": "2024-07-04", + "altitudeAcclimationDate": "2024-07-05", + "previousAltitudeAcclimationDate": "2024-07-05", + "heatAcclimationDate": "2024-07-04", + "previousHeatAcclimationDate": "2024-06-30", + "altitudeAcclimation": 0, + "previousAltitudeAcclimation": 0, + "heatAcclimationPercentage": 100, + "previousHeatAcclimationPercentage": 100, + "heatTrend": "ACCLIMATIZED", + "altitudeTrend": null, + "currentAltitude": 24, + "previousAltitude": 0, + "acclimationPercentage": 0, + "previousAcclimationPercentage": 0, + "altitudeAcclimationLocalTimestamp": "2024-07-04T23:56:04.0", + }, + }, + { + "userId": "user_id: int", + "generic": { + "calendarDate": "2024-07-05", + "vo2MaxPreciseValue": 60.6, + "vo2MaxValue": 61.0, + "fitnessAge": null, + "fitnessAgeDescription": null, + "maxMetCategory": 0, + }, + "cycling": null, + "heatAltitudeAcclimation": { + "calendarDate": "2024-07-05", + "altitudeAcclimationDate": "2024-07-06", + "previousAltitudeAcclimationDate": "2024-07-06", + "heatAcclimationDate": "2024-07-05", + "previousHeatAcclimationDate": "2024-06-30", + "altitudeAcclimation": 0, + "previousAltitudeAcclimation": 0, + "heatAcclimationPercentage": 100, + "previousHeatAcclimationPercentage": 100, + "heatTrend": "ACCLIMATIZED", + "altitudeTrend": null, + "currentAltitude": 0, + "previousAltitude": 0, + "acclimationPercentage": 0, + "previousAcclimationPercentage": 0, + "altitudeAcclimationLocalTimestamp": "2024-07-05T23:55:41.0", + }, + }, + { + "userId": "user_id: int", + "generic": { + "calendarDate": "2024-07-06", + "vo2MaxPreciseValue": 60.6, + "vo2MaxValue": 61.0, + "fitnessAge": null, + "fitnessAgeDescription": null, + "maxMetCategory": 0, + }, + "cycling": null, + "heatAltitudeAcclimation": { + "calendarDate": "2024-07-06", + "altitudeAcclimationDate": "2024-07-07", + "previousAltitudeAcclimationDate": "2024-07-07", + "heatAcclimationDate": "2024-07-07", + "previousHeatAcclimationDate": "2024-06-30", + "altitudeAcclimation": 0, + "previousAltitudeAcclimation": 0, + "heatAcclimationPercentage": 100, + "previousHeatAcclimationPercentage": 100, + "heatTrend": "ACCLIMATIZED", + "altitudeTrend": null, + "currentAltitude": 3, + "previousAltitude": 0, + "acclimationPercentage": 0, + "previousAcclimationPercentage": 0, + "altitudeAcclimationLocalTimestamp": "2024-07-06T23:55:12.0", + }, + }, + { + "userId": "user_id: int", + "generic": { + "calendarDate": "2024-07-07", + "vo2MaxPreciseValue": 60.6, + "vo2MaxValue": 61.0, + "fitnessAge": null, + "fitnessAgeDescription": null, + "maxMetCategory": 0, + }, + "cycling": null, + "heatAltitudeAcclimation": { + "calendarDate": "2024-07-07", + "altitudeAcclimationDate": "2024-07-08", + "previousAltitudeAcclimationDate": "2024-07-08", + "heatAcclimationDate": "2024-07-07", + "previousHeatAcclimationDate": "2024-06-30", + "altitudeAcclimation": 0, + "previousAltitudeAcclimation": 0, + "heatAcclimationPercentage": 100, + "previousHeatAcclimationPercentage": 100, + "heatTrend": "ACCLIMATIZED", + "altitudeTrend": null, + "currentAltitude": 62, + "previousAltitude": 0, + "acclimationPercentage": 0, + "previousAcclimationPercentage": 0, + "altitudeAcclimationLocalTimestamp": "2024-07-07T23:54:28.0", + }, + }, + ] + } + }, + }, + { + "query": { + "query": 'query{activityTrendsScalar(activityType:"running",date:"2024-07-08")}' + }, + "response": { + "data": {"activityTrendsScalar": {"RUNNING": "2024-06-25"}} + }, + }, + { + "query": { + "query": 'query{activityTrendsScalar(activityType:"all",date:"2024-07-08")}' + }, + "response": {"data": {"activityTrendsScalar": {"ALL": "2024-06-25"}}}, + }, + { + "query": { + "query": 'query{activityTrendsScalar(activityType:"fitness_equipment",date:"2024-07-08")}' + }, + "response": { + "data": {"activityTrendsScalar": {"FITNESS_EQUIPMENT": null}} + }, + }, + { + "query": { + "query": "\n query {\n userGoalsScalar\n }\n " + }, + "response": { + "data": { + "userGoalsScalar": [ + { + "userGoalPk": 3354140802, + "userProfilePk": "user_id: int", + "userGoalCategory": "MANUAL", + "userGoalType": "HYDRATION", + "startDate": "2024-05-15", + "endDate": null, + "goalName": null, + "goalValue": 2000.0, + "updateDate": "2024-05-15T11:17:41.0", + "createDate": "2024-05-15T11:17:41.0", + "rulePk": null, + "activityTypePk": 9, + "trackingPeriodType": "DAILY", + }, + { + "userGoalPk": 3353706978, + "userProfilePk": "user_id: int", + "userGoalCategory": "MYFITNESSPAL", + "userGoalType": "NET_CALORIES", + "startDate": "2024-05-06", + "endDate": null, + "goalName": null, + "goalValue": 1780.0, + "updateDate": "2024-05-06T10:53:34.0", + "createDate": "2024-05-06T10:53:34.0", + "rulePk": null, + "activityTypePk": null, + "trackingPeriodType": "DAILY", + }, + { + "userGoalPk": 3352551190, + "userProfilePk": "user_id: int", + "userGoalCategory": "MANUAL", + "userGoalType": "WEIGHT_GRAMS", + "startDate": "2024-04-10", + "endDate": null, + "goalName": null, + "goalValue": 77110.0, + "updateDate": "2024-04-10T22:15:30.0", + "createDate": "2024-04-10T22:15:30.0", + "rulePk": null, + "activityTypePk": 9, + "trackingPeriodType": "DAILY", + }, + { + "userGoalPk": 413558487, + "userProfilePk": "user_id: int", + "userGoalCategory": "MANUAL", + "userGoalType": "STEPS", + "startDate": "2024-06-26", + "endDate": null, + "goalName": null, + "goalValue": 5000.0, + "updateDate": "2024-06-26T13:30:05.0", + "createDate": "2018-09-11T22:32:18.0", + "rulePk": null, + "activityTypePk": null, + "trackingPeriodType": "DAILY", + }, + ] + } + }, + }, + { + "query": { + "query": 'query{trainingStatusWeeklyScalar(startDate:"2024-07-02", endDate:"2024-07-08", displayName:"ca8406dd-d7dd-4adb-825e-16967b1e82fb")}' + }, + "response": { + "data": { + "trainingStatusWeeklyScalar": { + "userId": "user_id: int", + "fromCalendarDate": "2024-07-02", + "toCalendarDate": "2024-07-08", + "showSelector": false, + "recordedDevices": [ + { + "deviceId": 3472661486, + "imageURL": "https://res.garmin.com/en/products/010-02809-02/v/c1_01_md.png", + "deviceName": "Forerunner 965", + "category": 0, + } + ], + "reportData": { + "3472661486": [ + { + "calendarDate": "2024-07-02", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 4, + "timestamp": 1719921774000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 2, + "trainingStatusFeedbackPhrase": "MAINTAINING_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 47, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 1130, + "maxTrainingLoadChronic": 1468.5, + "minTrainingLoadChronic": 783.2, + "dailyTrainingLoadChronic": 979, + "dailyAcuteChronicWorkloadRatio": 1.1, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-07-03", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 4, + "timestamp": 1720027612000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 2, + "trainingStatusFeedbackPhrase": "MAINTAINING_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 52, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 1206, + "maxTrainingLoadChronic": 1500.0, + "minTrainingLoadChronic": 800.0, + "dailyTrainingLoadChronic": 1000, + "dailyAcuteChronicWorkloadRatio": 1.2, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-07-04", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 4, + "timestamp": 1720096045000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 2, + "trainingStatusFeedbackPhrase": "MAINTAINING_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 47, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 1122, + "maxTrainingLoadChronic": 1489.5, + "minTrainingLoadChronic": 794.4000000000001, + "dailyTrainingLoadChronic": 993, + "dailyAcuteChronicWorkloadRatio": 1.1, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-07-05", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 4, + "timestamp": 1720194335000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 2, + "trainingStatusFeedbackPhrase": "MAINTAINING_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 47, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 1211, + "maxTrainingLoadChronic": 1534.5, + "minTrainingLoadChronic": 818.4000000000001, + "dailyTrainingLoadChronic": 1023, + "dailyAcuteChronicWorkloadRatio": 1.1, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-07-06", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 4, + "timestamp": 1720313044000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 2, + "trainingStatusFeedbackPhrase": "MAINTAINING_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 47, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 1128, + "maxTrainingLoadChronic": 1534.5, + "minTrainingLoadChronic": 818.4000000000001, + "dailyTrainingLoadChronic": 1023, + "dailyAcuteChronicWorkloadRatio": 1.1, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-07-07", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 4, + "timestamp": 1720353825000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 2, + "trainingStatusFeedbackPhrase": "MAINTAINING_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 42, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 1096, + "maxTrainingLoadChronic": 1546.5, + "minTrainingLoadChronic": 824.8000000000001, + "dailyTrainingLoadChronic": 1031, + "dailyAcuteChronicWorkloadRatio": 1.0, + }, + "primaryTrainingDevice": true, + }, + { + "calendarDate": "2024-07-08", + "sinceDate": null, + "weeklyTrainingLoad": null, + "trainingStatus": 4, + "timestamp": 1720445627000, + "deviceId": 3472661486, + "loadTunnelMin": null, + "loadTunnelMax": null, + "loadLevelTrend": null, + "sport": "RUNNING", + "subSport": "GENERIC", + "fitnessTrendSport": "RUNNING", + "fitnessTrend": 2, + "trainingStatusFeedbackPhrase": "MAINTAINING_3", + "trainingPaused": false, + "acuteTrainingLoadDTO": { + "acwrPercent": 33, + "acwrStatus": "OPTIMAL", + "acwrStatusFeedback": "FEEDBACK_2", + "dailyTrainingLoadAcute": 886, + "maxTrainingLoadChronic": 1506.0, + "minTrainingLoadChronic": 803.2, + "dailyTrainingLoadChronic": 1004, + "dailyAcuteChronicWorkloadRatio": 0.8, + }, + "primaryTrainingDevice": true, + }, + ] + }, + } + } + }, + }, + { + "query": { + "query": 'query{enduranceScoreScalar(startDate:"2024-04-16", endDate:"2024-07-08", aggregation:"weekly")}' + }, + "response": { + "data": { + "enduranceScoreScalar": { + "userProfilePK": "user_id: int", + "startDate": "2024-04-16", + "endDate": "2024-07-08", + "avg": 8383, + "max": 8649, + "groupMap": { + "2024-04-16": { + "groupAverage": 8614, + "groupMax": 8649, + "enduranceContributorDTOList": [ + { + "activityTypeId": null, + "group": 3, + "contribution": 5.8842854, + }, + { + "activityTypeId": null, + "group": 0, + "contribution": 83.06714, + }, + { + "activityTypeId": null, + "group": 1, + "contribution": 9.064286, + }, + { + "activityTypeId": null, + "group": 8, + "contribution": 1.9842857, + }, + ], + }, + "2024-04-23": { + "groupAverage": 8499, + "groupMax": 8578, + "enduranceContributorDTOList": [ + { + "activityTypeId": null, + "group": 3, + "contribution": 5.3585715, + }, + { + "activityTypeId": null, + "group": 0, + "contribution": 81.944275, + }, + { + "activityTypeId": null, + "group": 1, + "contribution": 8.255714, + }, + { + "activityTypeId": null, + "group": 8, + "contribution": 4.4414287, + }, + ], + }, + "2024-04-30": { + "groupAverage": 8295, + "groupMax": 8406, + "enduranceContributorDTOList": [ + { + "activityTypeId": null, + "group": 3, + "contribution": 0.7228571, + }, + { + "activityTypeId": null, + "group": 0, + "contribution": 80.9, + }, + { + "activityTypeId": null, + "group": 1, + "contribution": 7.531429, + }, + { + "activityTypeId": 13, + "group": null, + "contribution": 4.9157143, + }, + { + "activityTypeId": null, + "group": 8, + "contribution": 5.9300003, + }, + ], + }, + "2024-05-07": { + "groupAverage": 8172, + "groupMax": 8216, + "enduranceContributorDTOList": [ + { + "activityTypeId": null, + "group": 0, + "contribution": 81.51143, + }, + { + "activityTypeId": null, + "group": 1, + "contribution": 6.6957145, + }, + { + "activityTypeId": 13, + "group": null, + "contribution": 7.5371428, + }, + { + "activityTypeId": null, + "group": 8, + "contribution": 4.2557144, + }, + ], + }, + "2024-05-14": { + "groupAverage": 8314, + "groupMax": 8382, + "enduranceContributorDTOList": [ + { + "activityTypeId": null, + "group": 0, + "contribution": 82.93285, + }, + { + "activityTypeId": null, + "group": 1, + "contribution": 6.4171433, + }, + { + "activityTypeId": 13, + "group": null, + "contribution": 8.967142, + }, + { + "activityTypeId": null, + "group": 8, + "contribution": 1.6828573, + }, + ], + }, + "2024-05-21": { + "groupAverage": 8263, + "groupMax": 8294, + "enduranceContributorDTOList": [ + { + "activityTypeId": null, + "group": 0, + "contribution": 82.55286, + }, + { + "activityTypeId": null, + "group": 1, + "contribution": 4.245714, + }, + { + "activityTypeId": 13, + "group": null, + "contribution": 11.4657135, + }, + { + "activityTypeId": null, + "group": 8, + "contribution": 1.7357142, + }, + ], + }, + "2024-05-28": { + "groupAverage": 8282, + "groupMax": 8307, + "enduranceContributorDTOList": [ + { + "activityTypeId": null, + "group": 0, + "contribution": 84.18428, + }, + { + "activityTypeId": 13, + "group": null, + "contribution": 12.667143, + }, + { + "activityTypeId": null, + "group": 8, + "contribution": 3.148571, + }, + ], + }, + "2024-06-04": { + "groupAverage": 8334, + "groupMax": 8360, + "enduranceContributorDTOList": [ + { + "activityTypeId": null, + "group": 0, + "contribution": 84.24714, + }, + { + "activityTypeId": 13, + "group": null, + "contribution": 13.321428, + }, + { + "activityTypeId": null, + "group": 8, + "contribution": 2.4314287, + }, + ], + }, + "2024-06-11": { + "groupAverage": 8376, + "groupMax": 8400, + "enduranceContributorDTOList": [ + { + "activityTypeId": null, + "group": 0, + "contribution": 84.138565, + }, + { + "activityTypeId": 13, + "group": null, + "contribution": 13.001429, + }, + { + "activityTypeId": null, + "group": 8, + "contribution": 2.8600001, + }, + ], + }, + "2024-06-18": { + "groupAverage": 8413, + "groupMax": 8503, + "enduranceContributorDTOList": [ + { + "activityTypeId": null, + "group": 0, + "contribution": 84.28715, + }, + { + "activityTypeId": 13, + "group": null, + "contribution": 13.105714, + }, + { + "activityTypeId": null, + "group": 8, + "contribution": 2.607143, + }, + ], + }, + "2024-06-25": { + "groupAverage": 8445, + "groupMax": 8555, + "enduranceContributorDTOList": [ + { + "activityTypeId": null, + "group": 0, + "contribution": 84.56285, + }, + { + "activityTypeId": 13, + "group": null, + "contribution": 12.332857, + }, + { + "activityTypeId": null, + "group": 8, + "contribution": 3.104286, + }, + ], + }, + "2024-07-02": { + "groupAverage": 8593, + "groupMax": 8643, + "enduranceContributorDTOList": [ + { + "activityTypeId": null, + "group": 0, + "contribution": 86.76143, + }, + { + "activityTypeId": 13, + "group": null, + "contribution": 10.441428, + }, + { + "activityTypeId": null, + "group": 8, + "contribution": 2.7971427, + }, + ], + }, + }, + "enduranceScoreDTO": { + "userProfilePK": "user_id: int", + "deviceId": 3472661486, + "calendarDate": "2024-07-08", + "overallScore": 8587, + "classification": 6, + "feedbackPhrase": 78, + "primaryTrainingDevice": true, + "gaugeLowerLimit": 3570, + "classificationLowerLimitIntermediate": 5100, + "classificationLowerLimitTrained": 5800, + "classificationLowerLimitWellTrained": 6600, + "classificationLowerLimitExpert": 7300, + "classificationLowerLimitSuperior": 8100, + "classificationLowerLimitElite": 8800, + "gaugeUpperLimit": 10560, + "contributors": [ + { + "activityTypeId": null, + "group": 0, + "contribution": 87.65, + }, + { + "activityTypeId": 13, + "group": null, + "contribution": 9.49, + }, + { + "activityTypeId": null, + "group": 8, + "contribution": 2.86, + }, + ], + }, + } + } + }, + }, + { + "query": {"query": 'query{latestWeightScalar(asOfDate:"2024-07-08")}'}, + "response": { + "data": { + "latestWeightScalar": { + "date": 1720396800000, + "version": 1720435190064, + "weight": 82372.0, + "bmi": null, + "bodyFat": null, + "bodyWater": null, + "boneMass": null, + "muscleMass": null, + "physiqueRating": null, + "visceralFat": null, + "metabolicAge": null, + "caloricIntake": null, + "sourceType": "MFP", + "timestampGMT": 1720435137000, + "weightDelta": 907, + } + } + }, + }, + { + "query": {"query": 'query{pregnancyScalar(date:"2024-07-08")}'}, + "response": {"data": {"pregnancyScalar": null}}, + }, + { + "query": { + "query": 'query{epochChartScalar(date:"2024-07-08", include:["stress"])}' + }, + "response": { + "data": { + "epochChartScalar": { + "stress": { + "labels": ["timestampGmt", "value"], + "data": [ + ["2024-07-08T04:03:00.0", 23], + ["2024-07-08T04:06:00.0", 20], + ["2024-07-08T04:09:00.0", 20], + ["2024-07-08T04:12:00.0", 12], + ["2024-07-08T04:15:00.0", 15], + ["2024-07-08T04:18:00.0", 15], + ["2024-07-08T04:21:00.0", 13], + ["2024-07-08T04:24:00.0", 14], + ["2024-07-08T04:27:00.0", 16], + ["2024-07-08T04:30:00.0", 16], + ["2024-07-08T04:33:00.0", 14], + ["2024-07-08T04:36:00.0", 15], + ["2024-07-08T04:39:00.0", 16], + ["2024-07-08T04:42:00.0", 15], + ["2024-07-08T04:45:00.0", 17], + ["2024-07-08T04:48:00.0", 15], + ["2024-07-08T04:51:00.0", 15], + ["2024-07-08T04:54:00.0", 15], + ["2024-07-08T04:57:00.0", 13], + ["2024-07-08T05:00:00.0", 11], + ["2024-07-08T05:03:00.0", 7], + ["2024-07-08T05:06:00.0", 15], + ["2024-07-08T05:09:00.0", 23], + ["2024-07-08T05:12:00.0", 21], + ["2024-07-08T05:15:00.0", 17], + ["2024-07-08T05:18:00.0", 12], + ["2024-07-08T05:21:00.0", 17], + ["2024-07-08T05:24:00.0", 18], + ["2024-07-08T05:27:00.0", 17], + ["2024-07-08T05:30:00.0", 13], + ["2024-07-08T05:33:00.0", 12], + ["2024-07-08T05:36:00.0", 17], + ["2024-07-08T05:39:00.0", 15], + ["2024-07-08T05:42:00.0", 14], + ["2024-07-08T05:45:00.0", 21], + ["2024-07-08T05:48:00.0", 20], + ["2024-07-08T05:51:00.0", 23], + ["2024-07-08T05:54:00.0", 21], + ["2024-07-08T05:57:00.0", 19], + ["2024-07-08T06:00:00.0", 11], + ["2024-07-08T06:03:00.0", 13], + ["2024-07-08T06:06:00.0", 9], + ["2024-07-08T06:09:00.0", 9], + ["2024-07-08T06:12:00.0", 10], + ["2024-07-08T06:15:00.0", 10], + ["2024-07-08T06:18:00.0", 9], + ["2024-07-08T06:21:00.0", 10], + ["2024-07-08T06:24:00.0", 10], + ["2024-07-08T06:27:00.0", 9], + ["2024-07-08T06:30:00.0", 8], + ["2024-07-08T06:33:00.0", 10], + ["2024-07-08T06:36:00.0", 10], + ["2024-07-08T06:39:00.0", 9], + ["2024-07-08T06:42:00.0", 15], + ["2024-07-08T06:45:00.0", 6], + ["2024-07-08T06:48:00.0", 7], + ["2024-07-08T06:51:00.0", 8], + ["2024-07-08T06:54:00.0", 12], + ["2024-07-08T06:57:00.0", 12], + ["2024-07-08T07:00:00.0", 10], + ["2024-07-08T07:03:00.0", 16], + ["2024-07-08T07:06:00.0", 16], + ["2024-07-08T07:09:00.0", 18], + ["2024-07-08T07:12:00.0", 20], + ["2024-07-08T07:15:00.0", 20], + ["2024-07-08T07:18:00.0", 17], + ["2024-07-08T07:21:00.0", 11], + ["2024-07-08T07:24:00.0", 21], + ["2024-07-08T07:27:00.0", 18], + ["2024-07-08T07:30:00.0", 8], + ["2024-07-08T07:33:00.0", 12], + ["2024-07-08T07:36:00.0", 18], + ["2024-07-08T07:39:00.0", 10], + ["2024-07-08T07:42:00.0", 8], + ["2024-07-08T07:45:00.0", 8], + ["2024-07-08T07:48:00.0", 9], + ["2024-07-08T07:51:00.0", 11], + ["2024-07-08T07:54:00.0", 9], + ["2024-07-08T07:57:00.0", 15], + ["2024-07-08T08:00:00.0", 14], + ["2024-07-08T08:03:00.0", 12], + ["2024-07-08T08:06:00.0", 10], + ["2024-07-08T08:09:00.0", 8], + ["2024-07-08T08:12:00.0", 12], + ["2024-07-08T08:15:00.0", 16], + ["2024-07-08T08:18:00.0", 12], + ["2024-07-08T08:21:00.0", 17], + ["2024-07-08T08:24:00.0", 16], + ["2024-07-08T08:27:00.0", 20], + ["2024-07-08T08:30:00.0", 17], + ["2024-07-08T08:33:00.0", 20], + ["2024-07-08T08:36:00.0", 21], + ["2024-07-08T08:39:00.0", 19], + ["2024-07-08T08:42:00.0", 15], + ["2024-07-08T08:45:00.0", 18], + ["2024-07-08T08:48:00.0", 16], + ["2024-07-08T08:51:00.0", 11], + ["2024-07-08T08:54:00.0", 11], + ["2024-07-08T08:57:00.0", 14], + ["2024-07-08T09:00:00.0", 12], + ["2024-07-08T09:03:00.0", 7], + ["2024-07-08T09:06:00.0", 12], + ["2024-07-08T09:09:00.0", 15], + ["2024-07-08T09:12:00.0", 12], + ["2024-07-08T09:15:00.0", 17], + ["2024-07-08T09:18:00.0", 18], + ["2024-07-08T09:21:00.0", 12], + ["2024-07-08T09:24:00.0", 15], + ["2024-07-08T09:27:00.0", 16], + ["2024-07-08T09:30:00.0", 19], + ["2024-07-08T09:33:00.0", 20], + ["2024-07-08T09:36:00.0", 17], + ["2024-07-08T09:39:00.0", 20], + ["2024-07-08T09:42:00.0", 20], + ["2024-07-08T09:45:00.0", 22], + ["2024-07-08T09:48:00.0", 20], + ["2024-07-08T09:51:00.0", 9], + ["2024-07-08T09:54:00.0", 16], + ["2024-07-08T09:57:00.0", 22], + ["2024-07-08T10:00:00.0", 20], + ["2024-07-08T10:03:00.0", 17], + ["2024-07-08T10:06:00.0", 21], + ["2024-07-08T10:09:00.0", 13], + ["2024-07-08T10:12:00.0", 15], + ["2024-07-08T10:15:00.0", 17], + ["2024-07-08T10:18:00.0", 17], + ["2024-07-08T10:21:00.0", 17], + ["2024-07-08T10:24:00.0", 15], + ["2024-07-08T10:27:00.0", 21], + ["2024-07-08T10:30:00.0", -2], + ["2024-07-08T10:33:00.0", -2], + ["2024-07-08T10:36:00.0", -2], + ["2024-07-08T10:39:00.0", -1], + ["2024-07-08T10:42:00.0", 32], + ["2024-07-08T10:45:00.0", 38], + ["2024-07-08T10:48:00.0", 14], + ["2024-07-08T10:51:00.0", 23], + ["2024-07-08T10:54:00.0", 15], + ["2024-07-08T10:57:00.0", 19], + ["2024-07-08T11:00:00.0", 28], + ["2024-07-08T11:03:00.0", 17], + ["2024-07-08T11:06:00.0", 23], + ["2024-07-08T11:09:00.0", 28], + ["2024-07-08T11:12:00.0", 25], + ["2024-07-08T11:15:00.0", 22], + ["2024-07-08T11:18:00.0", 25], + ["2024-07-08T11:21:00.0", -1], + ["2024-07-08T11:24:00.0", 21], + ["2024-07-08T11:27:00.0", -1], + ["2024-07-08T11:30:00.0", 21], + ["2024-07-08T11:33:00.0", 21], + ["2024-07-08T11:36:00.0", 18], + ["2024-07-08T11:39:00.0", 33], + ["2024-07-08T11:42:00.0", -1], + ["2024-07-08T11:45:00.0", 40], + ["2024-07-08T11:48:00.0", -1], + ["2024-07-08T11:51:00.0", 25], + ["2024-07-08T11:54:00.0", -1], + ["2024-07-08T11:57:00.0", -1], + ["2024-07-08T12:00:00.0", 23], + ["2024-07-08T12:03:00.0", -2], + ["2024-07-08T12:06:00.0", -1], + ["2024-07-08T12:09:00.0", -1], + ["2024-07-08T12:12:00.0", -2], + ["2024-07-08T12:15:00.0", -2], + ["2024-07-08T12:18:00.0", -2], + ["2024-07-08T12:21:00.0", -2], + ["2024-07-08T12:24:00.0", -2], + ["2024-07-08T12:27:00.0", -2], + ["2024-07-08T12:30:00.0", -2], + ["2024-07-08T12:33:00.0", -2], + ["2024-07-08T12:36:00.0", -2], + ["2024-07-08T12:39:00.0", -2], + ["2024-07-08T12:42:00.0", -2], + ["2024-07-08T12:45:00.0", 25], + ["2024-07-08T12:48:00.0", 24], + ["2024-07-08T12:51:00.0", 23], + ["2024-07-08T12:54:00.0", 24], + ["2024-07-08T12:57:00.0", -1], + ["2024-07-08T13:00:00.0", -2], + ["2024-07-08T13:03:00.0", 21], + ["2024-07-08T13:06:00.0", -1], + ["2024-07-08T13:09:00.0", 18], + ["2024-07-08T13:12:00.0", 25], + ["2024-07-08T13:15:00.0", 24], + ["2024-07-08T13:18:00.0", 25], + ["2024-07-08T13:21:00.0", 34], + ["2024-07-08T13:24:00.0", 24], + ["2024-07-08T13:27:00.0", 28], + ["2024-07-08T13:30:00.0", 28], + ["2024-07-08T13:33:00.0", 28], + ["2024-07-08T13:36:00.0", 27], + ["2024-07-08T13:39:00.0", 21], + ["2024-07-08T13:42:00.0", 32], + ["2024-07-08T13:45:00.0", 30], + ["2024-07-08T13:48:00.0", 29], + ["2024-07-08T13:51:00.0", 20], + ["2024-07-08T13:54:00.0", 35], + ["2024-07-08T13:57:00.0", 31], + ["2024-07-08T14:00:00.0", 37], + ["2024-07-08T14:03:00.0", 32], + ["2024-07-08T14:06:00.0", 34], + ["2024-07-08T14:09:00.0", 25], + ["2024-07-08T14:12:00.0", 38], + ["2024-07-08T14:15:00.0", 37], + ["2024-07-08T14:18:00.0", 38], + ["2024-07-08T14:21:00.0", 42], + ["2024-07-08T14:24:00.0", 30], + ["2024-07-08T14:27:00.0", 26], + ["2024-07-08T14:30:00.0", 40], + ["2024-07-08T14:33:00.0", -1], + ["2024-07-08T14:36:00.0", 21], + ["2024-07-08T14:39:00.0", -2], + ["2024-07-08T14:42:00.0", -2], + ["2024-07-08T14:45:00.0", -2], + ["2024-07-08T14:48:00.0", -1], + ["2024-07-08T14:51:00.0", 31], + ["2024-07-08T14:54:00.0", -1], + ["2024-07-08T14:57:00.0", -2], + ["2024-07-08T15:00:00.0", -2], + ["2024-07-08T15:03:00.0", -2], + ["2024-07-08T15:06:00.0", -2], + ["2024-07-08T15:09:00.0", -2], + ["2024-07-08T15:12:00.0", -1], + ["2024-07-08T15:15:00.0", 25], + ["2024-07-08T15:18:00.0", 24], + ["2024-07-08T15:21:00.0", 28], + ["2024-07-08T15:24:00.0", 28], + ["2024-07-08T15:27:00.0", 23], + ["2024-07-08T15:30:00.0", 25], + ["2024-07-08T15:33:00.0", 34], + ["2024-07-08T15:36:00.0", -1], + ["2024-07-08T15:39:00.0", 59], + ["2024-07-08T15:42:00.0", 50], + ["2024-07-08T15:45:00.0", -1], + ["2024-07-08T15:48:00.0", -2], + ], + } + } + } + }, + }, +] + + +================================================ +FILE: garminconnect/__init__.py +================================================ +"""Python 3 API wrapper for Garmin Connect.""" + +import logging +import numbers +import os +import re +from collections.abc import Callable +from datetime import date, datetime, timezone +from enum import Enum, auto +from pathlib import Path +from typing import Any + +import garth +import requests +from garth.exc import GarthException, GarthHTTPError +from requests import HTTPError + +from .fit import FitEncoderWeight # type: ignore + +logger = logging.getLogger(__name__) + +# Constants for validation +MAX_ACTIVITY_LIMIT = 1000 +MAX_HYDRATION_ML = 10000 # 10 liters +DATE_FORMAT_REGEX = r"^\d{4}-\d{2}-\d{2}$" +DATE_FORMAT_STR = "%Y-%m-%d" +VALID_WEIGHT_UNITS = {"kg", "lbs"} + + +# Add validation utilities +def _validate_date_format(date_str: str, param_name: str = "date") -> str: + """Validate date string format YYYY-MM-DD.""" + if not isinstance(date_str, str): + raise ValueError(f"{param_name} must be a string") + + # Remove any extra whitespace + date_str = date_str.strip() + + if not re.fullmatch(DATE_FORMAT_REGEX, date_str): + raise ValueError( + f"{param_name} must be in format 'YYYY-MM-DD', got: {date_str}" + ) + + try: + # Validate that it's a real date + datetime.strptime(date_str, DATE_FORMAT_STR) + except ValueError as e: + raise ValueError(f"invalid {param_name}: {e}") from e + + return date_str + + +def _validate_positive_number( + value: int | float, param_name: str = "value" +) -> int | float: + """Validate that a number is positive.""" + if not isinstance(value, numbers.Real): + raise ValueError(f"{param_name} must be a number") + + if isinstance(value, bool): + raise ValueError(f"{param_name} must be a number, not bool") + + if value <= 0: + raise ValueError(f"{param_name} must be positive, got: {value}") + + return value + + +def _validate_non_negative_integer(value: int, param_name: str = "value") -> int: + """Validate that a value is a non-negative integer.""" + if not isinstance(value, int) or isinstance(value, bool): + raise ValueError(f"{param_name} must be an integer") + + if value < 0: + raise ValueError(f"{param_name} must be non-negative, got: {value}") + + return value + + +def _validate_positive_integer(value: int, param_name: str = "value") -> int: + """Validate that a value is a positive integer.""" + if not isinstance(value, int) or isinstance(value, bool): + raise ValueError(f"{param_name} must be an integer") + if value <= 0: + raise ValueError(f"{param_name} must be a positive integer, got: {value}") + return value + + +def _fmt_ts(dt: datetime) -> str: + # Use ms precision to match server expectations + return dt.replace(tzinfo=None).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + + +class Garmin: + """Class for fetching data from Garmin Connect.""" + + def __init__( + self, + email: str | None = None, + password: str | None = None, + is_cn: bool = False, + prompt_mfa: Callable[[], str] | None = None, + return_on_mfa: bool = False, + ) -> None: + """Create a new class instance.""" + + # Validate input types + if email is not None and not isinstance(email, str): + raise ValueError("email must be a string or None") + if password is not None and not isinstance(password, str): + raise ValueError("password must be a string or None") + if not isinstance(is_cn, bool): + raise ValueError("is_cn must be a boolean") + if not isinstance(return_on_mfa, bool): + raise ValueError("return_on_mfa must be a boolean") + + self.username = email + self.password = password + self.is_cn = is_cn + self.prompt_mfa = prompt_mfa + self.return_on_mfa = return_on_mfa + + self.garmin_connect_user_settings_url = ( + "/userprofile-service/userprofile/user-settings" + ) + self.garmin_connect_userprofile_settings_url = ( + "/userprofile-service/userprofile/settings" + ) + self.garmin_connect_devices_url = "/device-service/deviceregistration/devices" + self.garmin_connect_device_url = "/device-service/deviceservice" + + self.garmin_connect_primary_device_url = ( + "/web-gateway/device-info/primary-training-device" + ) + + self.garmin_connect_solar_url = "/web-gateway/solar" + self.garmin_connect_weight_url = "/weight-service" + self.garmin_connect_daily_summary_url = "/usersummary-service/usersummary/daily" + self.garmin_connect_metrics_url = "/metrics-service/metrics/maxmet/daily" + self.garmin_connect_biometric_url = "/biometric-service/biometric" + + self.garmin_connect_biometric_stats_url = "/biometric-service/stats" + self.garmin_connect_daily_hydration_url = ( + "/usersummary-service/usersummary/hydration/daily" + ) + self.garmin_connect_set_hydration_url = ( + "/usersummary-service/usersummary/hydration/log" + ) + self.garmin_connect_daily_stats_steps_url = ( + "/usersummary-service/stats/steps/daily" + ) + self.garmin_connect_personal_record_url = ( + "/personalrecord-service/personalrecord/prs" + ) + self.garmin_connect_earned_badges_url = "/badge-service/badge/earned" + self.garmin_connect_available_badges_url = "/badge-service/badge/available" + self.garmin_connect_adhoc_challenges_url = ( + "/adhocchallenge-service/adHocChallenge/historical" + ) + self.garmin_connect_badge_challenges_url = ( + "/badgechallenge-service/badgeChallenge/completed" + ) + self.garmin_connect_available_badge_challenges_url = ( + "/badgechallenge-service/badgeChallenge/available" + ) + self.garmin_connect_non_completed_badge_challenges_url = ( + "/badgechallenge-service/badgeChallenge/non-completed" + ) + self.garmin_connect_inprogress_virtual_challenges_url = ( + "/badgechallenge-service/virtualChallenge/inProgress" + ) + self.garmin_connect_daily_sleep_url = ( + "/wellness-service/wellness/dailySleepData" + ) + self.garmin_connect_daily_stress_url = "/wellness-service/wellness/dailyStress" + self.garmin_connect_hill_score_url = "/metrics-service/metrics/hillscore" + + self.garmin_connect_daily_body_battery_url = ( + "/wellness-service/wellness/bodyBattery/reports/daily" + ) + + self.garmin_connect_body_battery_events_url = ( + "/wellness-service/wellness/bodyBattery/events" + ) + + self.garmin_connect_blood_pressure_endpoint = ( + "/bloodpressure-service/bloodpressure/range" + ) + + self.garmin_connect_set_blood_pressure_endpoint = ( + "/bloodpressure-service/bloodpressure" + ) + + self.garmin_connect_endurance_score_url = ( + "/metrics-service/metrics/endurancescore" + ) + self.garmin_connect_menstrual_calendar_url = ( + "/periodichealth-service/menstrualcycle/calendar" + ) + + self.garmin_connect_menstrual_dayview_url = ( + "/periodichealth-service/menstrualcycle/dayview" + ) + self.garmin_connect_pregnancy_snapshot_url = ( + "/periodichealth-service/menstrualcycle/pregnancysnapshot" + ) + self.garmin_connect_goals_url = "/goal-service/goal/goals" + + self.garmin_connect_rhr_url = "/userstats-service/wellness/daily" + + self.garmin_connect_hrv_url = "/hrv-service/hrv" + + self.garmin_connect_training_readiness_url = ( + "/metrics-service/metrics/trainingreadiness" + ) + + self.garmin_connect_race_predictor_url = ( + "/metrics-service/metrics/racepredictions" + ) + self.garmin_connect_training_status_url = ( + "/metrics-service/metrics/trainingstatus/aggregated" + ) + self.garmin_connect_user_summary_chart = ( + "/wellness-service/wellness/dailySummaryChart" + ) + self.garmin_connect_floors_chart_daily_url = ( + "/wellness-service/wellness/floorsChartData/daily" + ) + self.garmin_connect_heartrates_daily_url = ( + "/wellness-service/wellness/dailyHeartRate" + ) + self.garmin_connect_daily_respiration_url = ( + "/wellness-service/wellness/daily/respiration" + ) + self.garmin_connect_daily_spo2_url = "/wellness-service/wellness/daily/spo2" + self.garmin_connect_daily_intensity_minutes = ( + "/wellness-service/wellness/daily/im" + ) + self.garmin_daily_events_url = "/wellness-service/wellness/dailyEvents" + self.garmin_connect_activities = ( + "/activitylist-service/activities/search/activities" + ) + self.garmin_connect_activities_baseurl = "/activitylist-service/activities/" + self.garmin_connect_activity = "/activity-service/activity" + self.garmin_connect_activity_types = "/activity-service/activity/activityTypes" + self.garmin_connect_activity_fordate = "/mobile-gateway/heartRate/forDate" + self.garmin_connect_fitnessstats = "/fitnessstats-service/activity" + self.garmin_connect_fitnessage = "/fitnessage-service/fitnessage" + + self.garmin_connect_fit_download = "/download-service/files/activity" + self.garmin_connect_tcx_download = "/download-service/export/tcx/activity" + self.garmin_connect_gpx_download = "/download-service/export/gpx/activity" + self.garmin_connect_kml_download = "/download-service/export/kml/activity" + self.garmin_connect_csv_download = "/download-service/export/csv/activity" + + self.garmin_connect_upload = "/upload-service/upload" + + self.garmin_connect_gear = "/gear-service/gear/filterGear" + self.garmin_connect_gear_baseurl = "/gear-service/gear/" + + self.garmin_request_reload_url = "/wellness-service/wellness/epoch/request" + + self.garmin_workouts = "/workout-service" + + self.garmin_connect_delete_activity_url = "/activity-service/activity" + + self.garmin_graphql_endpoint = "graphql-gateway/graphql" + + self.garth = garth.Client( + domain="garmin.cn" if is_cn else "garmin.com", + pool_connections=20, + pool_maxsize=20, + ) + + self.display_name = None + self.full_name = None + self.unit_system = None + + def connectapi(self, path: str, **kwargs: Any) -> Any: + """Wrapper for garth connectapi with error handling.""" + try: + return self.garth.connectapi(path, **kwargs) + except (HTTPError, GarthHTTPError) as e: + # For GarthHTTPError, extract status from the wrapped HTTPError + if isinstance(e, GarthHTTPError): + status = getattr( + getattr(e.error, "response", None), "status_code", None + ) + else: + status = getattr(getattr(e, "response", None), "status_code", None) + + logger.error( + "API call failed for path '%s': %s (status=%s)", path, e, status + ) + if status == 401: + raise GarminConnectAuthenticationError( + f"Authentication failed: {e}" + ) from e + elif status == 429: + raise GarminConnectTooManyRequestsError( + f"Rate limit exceeded: {e}" + ) from e + elif status and 400 <= status < 500: + # Client errors (400-499) - API endpoint issues, bad parameters, etc. + raise GarminConnectConnectionError( + f"API client error ({status}): {e}" + ) from e + else: + raise GarminConnectConnectionError(f"HTTP error: {e}") from e + except Exception as e: + logger.exception("Connection error during connectapi path=%s", path) + raise GarminConnectConnectionError(f"Connection error: {e}") from e + + def download(self, path: str, **kwargs: Any) -> Any: + """Wrapper for garth download with error handling.""" + try: + return self.garth.download(path, **kwargs) + except (HTTPError, GarthHTTPError) as e: + # For GarthHTTPError, extract status from the wrapped HTTPError + if isinstance(e, GarthHTTPError): + status = getattr( + getattr(e.error, "response", None), "status_code", None + ) + else: + status = getattr(getattr(e, "response", None), "status_code", None) + + logger.exception("Download failed for path '%s' (status=%s)", path, status) + if status == 401: + raise GarminConnectAuthenticationError(f"Download error: {e}") from e + elif status == 429: + raise GarminConnectTooManyRequestsError(f"Download error: {e}") from e + elif status and 400 <= status < 500: + # Client errors (400-499) - API endpoint issues, bad parameters, etc. + raise GarminConnectConnectionError( + f"Download client error ({status}): {e}" + ) from e + else: + raise GarminConnectConnectionError(f"Download error: {e}") from e + except Exception as e: + logger.exception("Download failed for path '%s'", path) + raise GarminConnectConnectionError(f"Download error: {e}") from e + + def login(self, /, tokenstore: str | None = None) -> tuple[str | None, str | None]: + """ + Log in using Garth. + + Returns: + Tuple[str | None, str | None]: (access_token, refresh_token) when using credential flow; + (None, None) when loading from tokenstore. + """ + tokenstore = tokenstore or os.getenv("GARMINTOKENS") + + try: + token1 = None + token2 = None + + if tokenstore: + if len(tokenstore) > 512: + self.garth.loads(tokenstore) + else: + self.garth.load(tokenstore) + else: + # Validate credentials before attempting login + if not self.username or not self.password: + raise GarminConnectAuthenticationError( + "Username and password are required" + ) + + # Validate email format when actually used for login + if not self.is_cn and self.username and "@" not in self.username: + raise GarminConnectAuthenticationError( + "Email must contain '@' symbol" + ) + + if self.return_on_mfa: + token1, token2 = self.garth.login( + self.username, + self.password, + return_on_mfa=self.return_on_mfa, + ) + # In MFA early-return mode, profile/settings are not loaded yet + return token1, token2 + else: + token1, token2 = self.garth.login( + self.username, + self.password, + prompt_mfa=self.prompt_mfa, + ) + # Continue to load profile/settings below + + # Ensure profile is loaded (tokenstore path may not populate it) + if not getattr(self.garth, "profile", None): + try: + prof = self.garth.connectapi( + "/userprofile-service/userprofile/profile" + ) + except Exception as e: + raise GarminConnectAuthenticationError( + "Failed to retrieve profile" + ) from e + if not prof or "displayName" not in prof: + raise GarminConnectAuthenticationError("Invalid profile data found") + # Use profile data directly since garth.profile is read-only + self.display_name = prof.get("displayName") + self.full_name = prof.get("fullName") + else: + self.display_name = self.garth.profile.get("displayName") + self.full_name = self.garth.profile.get("fullName") + + settings = self.garth.connectapi(self.garmin_connect_user_settings_url) + + if not settings: + raise GarminConnectAuthenticationError( + "Failed to retrieve user settings" + ) + + if "userData" not in settings: + raise GarminConnectAuthenticationError("Invalid user settings found") + + self.unit_system = settings["userData"].get("measurementSystem") + + return token1, token2 + + except (HTTPError, requests.exceptions.HTTPError, GarthException) as e: + status = getattr(getattr(e, "response", None), "status_code", None) + logger.error("Login failed: %s (status=%s)", e, status) + + # Check status code first + if status == 401: + raise GarminConnectAuthenticationError( + f"Authentication failed: {e}" + ) from e + elif status == 429: + raise GarminConnectTooManyRequestsError( + f"Rate limit exceeded: {e}" + ) from e + + # If no status code, check error message for authentication indicators + error_str = str(e).lower() + auth_indicators = ["401", "unauthorized", "authentication failed"] + if any(indicator in error_str for indicator in auth_indicators): + raise GarminConnectAuthenticationError( + f"Authentication failed: {e}" + ) from e + + # Default to connection error + raise GarminConnectConnectionError(f"Login failed: {e}") from e + except FileNotFoundError: + # Let FileNotFoundError pass through - this is expected when no tokens exist + raise + except Exception as e: + if isinstance(e, GarminConnectAuthenticationError): + raise + # Check if this is an authentication error based on the error message + error_str = str( + e + ).lower() # Convert to lowercase for case-insensitive matching + auth_indicators = ["401", "unauthorized", "authentication", "login failed"] + is_auth_error = any(indicator in error_str for indicator in auth_indicators) + + if is_auth_error: + raise GarminConnectAuthenticationError( + f"Authentication failed: {e}" + ) from e + logger.exception("Login failed") + raise GarminConnectConnectionError(f"Login failed: {e}") from e + + def resume_login( + self, client_state: dict[str, Any], mfa_code: str + ) -> tuple[Any, Any]: + """Resume login using Garth.""" + result1, result2 = self.garth.resume_login(client_state, mfa_code) + + if self.garth.profile: + self.display_name = self.garth.profile["displayName"] + self.full_name = self.garth.profile["fullName"] + + settings = self.garth.connectapi(self.garmin_connect_user_settings_url) + if settings and "userData" in settings: + self.unit_system = settings["userData"]["measurementSystem"] + + return result1, result2 + + def get_full_name(self) -> str | None: + """Return full name.""" + + return self.full_name + + def get_unit_system(self) -> str | None: + """Return unit system.""" + + return self.unit_system + + def get_stats(self, cdate: str) -> dict[str, Any]: + """ + Return user activity summary for 'cdate' format 'YYYY-MM-DD' + (compat for garminconnect). + """ + + return self.get_user_summary(cdate) + + def get_user_summary(self, cdate: str) -> dict[str, Any]: + """Return user activity summary for 'cdate' format 'YYYY-MM-DD'.""" + + # Validate input + cdate = _validate_date_format(cdate, "cdate") + + url = f"{self.garmin_connect_daily_summary_url}/{self.display_name}" + params = {"calendarDate": cdate} + logger.debug("Requesting user summary") + + response = self.connectapi(url, params=params) + + if not response: + raise GarminConnectConnectionError("No data received from server") + + if response.get("privacyProtected") is True: + raise GarminConnectAuthenticationError("Authentication error") + + return response + + def get_steps_data(self, cdate: str) -> list[dict[str, Any]]: + """Fetch available steps data 'cDate' format 'YYYY-MM-DD'.""" + + # Validate input + cdate = _validate_date_format(cdate, "cdate") + + url = f"{self.garmin_connect_user_summary_chart}/{self.display_name}" + params = {"date": cdate} + logger.debug("Requesting steps data") + + response = self.connectapi(url, params=params) + + if response is None: + logger.warning("No steps data received") + return [] + + return response + + def get_floors(self, cdate: str) -> dict[str, Any]: + """Fetch available floors data 'cDate' format 'YYYY-MM-DD'.""" + + # Validate input + cdate = _validate_date_format(cdate, "cdate") + + url = f"{self.garmin_connect_floors_chart_daily_url}/{cdate}" + logger.debug("Requesting floors data") + + response = self.connectapi(url) + + if response is None: + raise GarminConnectConnectionError("No floors data received") + + return response + + def get_daily_steps(self, start: str, end: str) -> list[dict[str, Any]]: + """Fetch available steps data 'start' and 'end' format 'YYYY-MM-DD'.""" + + # Validate inputs + start = _validate_date_format(start, "start") + end = _validate_date_format(end, "end") + + # Validate date range + start_date = datetime.strptime(start, DATE_FORMAT_STR).date() + end_date = datetime.strptime(end, DATE_FORMAT_STR).date() + + if start_date > end_date: + raise ValueError("start date cannot be after end date") + + url = f"{self.garmin_connect_daily_stats_steps_url}/{start}/{end}" + logger.debug("Requesting daily steps data") + + return self.connectapi(url) + + def get_heart_rates(self, cdate: str) -> dict[str, Any]: + """Fetch available heart rates data 'cDate' format 'YYYY-MM-DD'. + + Args: + cdate: Date string in format 'YYYY-MM-DD' + + Returns: + Dictionary containing heart rate data for the specified date + + Raises: + ValueError: If cdate format is invalid + GarminConnectConnectionError: If no data received + GarminConnectAuthenticationError: If authentication fails + """ + + # Validate input + cdate = _validate_date_format(cdate, "cdate") + + url = f"{self.garmin_connect_heartrates_daily_url}/{self.display_name}" + params = {"date": cdate} + logger.debug("Requesting heart rates") + + response = self.connectapi(url, params=params) + + if response is None: + raise GarminConnectConnectionError("No heart rate data received") + + return response + + def get_stats_and_body(self, cdate: str) -> dict[str, Any]: + """Return activity data and body composition (compat for garminconnect).""" + + stats = self.get_stats(cdate) + body = self.get_body_composition(cdate) + body_avg = body.get("totalAverage") or {} + if not isinstance(body_avg, dict): + body_avg = {} + return {**stats, **body_avg} + + def get_body_composition( + self, startdate: str, enddate: str | None = None + ) -> dict[str, Any]: + """ + Return available body composition data for 'startdate' format + 'YYYY-MM-DD' through enddate 'YYYY-MM-DD'. + """ + + startdate = _validate_date_format(startdate, "startdate") + enddate = ( + startdate if enddate is None else _validate_date_format(enddate, "enddate") + ) + if ( + datetime.strptime(startdate, DATE_FORMAT_STR).date() + > datetime.strptime(enddate, DATE_FORMAT_STR).date() + ): + raise ValueError("startdate cannot be after enddate") + url = f"{self.garmin_connect_weight_url}/weight/dateRange" + params = {"startDate": str(startdate), "endDate": str(enddate)} + logger.debug("Requesting body composition") + + return self.connectapi(url, params=params) + + def add_body_composition( + self, + timestamp: str | None, + weight: float, + percent_fat: float | None = None, + percent_hydration: float | None = None, + visceral_fat_mass: float | None = None, + bone_mass: float | None = None, + muscle_mass: float | None = None, + basal_met: float | None = None, + active_met: float | None = None, + physique_rating: float | None = None, + metabolic_age: float | None = None, + visceral_fat_rating: float | None = None, + bmi: float | None = None, + ) -> dict[str, Any]: + weight = _validate_positive_number(weight, "weight") + dt = datetime.fromisoformat(timestamp) if timestamp else datetime.now() + fitEncoder = FitEncoderWeight() + fitEncoder.write_file_info() + fitEncoder.write_file_creator() + fitEncoder.write_device_info(dt) + fitEncoder.write_weight_scale( + dt, + weight=weight, + percent_fat=percent_fat, + percent_hydration=percent_hydration, + visceral_fat_mass=visceral_fat_mass, + bone_mass=bone_mass, + muscle_mass=muscle_mass, + basal_met=basal_met, + active_met=active_met, + physique_rating=physique_rating, + metabolic_age=metabolic_age, + visceral_fat_rating=visceral_fat_rating, + bmi=bmi, + ) + fitEncoder.finish() + + url = self.garmin_connect_upload + files = { + "file": ("body_composition.fit", fitEncoder.getvalue()), + } + return self.garth.post("connectapi", url, files=files, api=True).json() + + def add_weigh_in( + self, weight: int | float, unitKey: str = "kg", timestamp: str = "" + ) -> dict[str, Any]: + """Add a weigh-in (default to kg)""" + + # Validate inputs + weight = _validate_positive_number(weight, "weight") + + if unitKey not in VALID_WEIGHT_UNITS: + raise ValueError(f"unitKey must be one of {VALID_WEIGHT_UNITS}") + + url = f"{self.garmin_connect_weight_url}/user-weight" + + try: + dt = datetime.fromisoformat(timestamp) if timestamp else datetime.now() + except ValueError as e: + raise ValueError(f"invalid timestamp format: {e}") from e + + # Apply timezone offset to get UTC/GMT time + dtGMT = dt.astimezone(timezone.utc) + payload = { + "dateTimestamp": _fmt_ts(dt), + "gmtTimestamp": _fmt_ts(dtGMT), + "unitKey": unitKey, + "sourceType": "MANUAL", + "value": weight, + } + logger.debug("Adding weigh-in") + + return self.garth.post("connectapi", url, json=payload).json() + + def add_weigh_in_with_timestamps( + self, + weight: int | float, + unitKey: str = "kg", + dateTimestamp: str = "", + gmtTimestamp: str = "", + ) -> dict[str, Any]: + """Add a weigh-in with explicit timestamps (default to kg)""" + + url = f"{self.garmin_connect_weight_url}/user-weight" + + if unitKey not in VALID_WEIGHT_UNITS: + raise ValueError(f"unitKey must be one of {VALID_WEIGHT_UNITS}") + # Make local timestamp timezone-aware + dt = ( + datetime.fromisoformat(dateTimestamp).astimezone() + if dateTimestamp + else datetime.now().astimezone() + ) + if gmtTimestamp: + g = datetime.fromisoformat(gmtTimestamp) + # Assume provided GMT is UTC if naive; otherwise convert to UTC + if g.tzinfo is None: + g = g.replace(tzinfo=timezone.utc) + dtGMT = g.astimezone(timezone.utc) + else: + dtGMT = dt.astimezone(timezone.utc) + + # Validate weight for consistency with add_weigh_in + weight = _validate_positive_number(weight, "weight") + # Build the payload + payload = { + "dateTimestamp": _fmt_ts(dt), # Local time (ms) + "gmtTimestamp": _fmt_ts(dtGMT), # GMT/UTC time (ms) + "unitKey": unitKey, + "sourceType": "MANUAL", + "value": weight, + } + + # Debug log for payload + logger.debug("Adding weigh-in with explicit timestamps: %s", payload) + + # Make the POST request + return self.garth.post("connectapi", url, json=payload).json() + + def get_weigh_ins(self, startdate: str, enddate: str) -> dict[str, Any]: + """Get weigh-ins between startdate and enddate using format 'YYYY-MM-DD'.""" + + startdate = _validate_date_format(startdate, "startdate") + enddate = _validate_date_format(enddate, "enddate") + url = f"{self.garmin_connect_weight_url}/weight/range/{startdate}/{enddate}" + params = {"includeAll": True} + logger.debug("Requesting weigh-ins") + + return self.connectapi(url, params=params) + + def get_daily_weigh_ins(self, cdate: str) -> dict[str, Any]: + """Get weigh-ins for 'cdate' format 'YYYY-MM-DD'.""" + + cdate = _validate_date_format(cdate, "cdate") + url = f"{self.garmin_connect_weight_url}/weight/dayview/{cdate}" + params = {"includeAll": True} + logger.debug("Requesting weigh-ins") + + return self.connectapi(url, params=params) + + def delete_weigh_in(self, weight_pk: str, cdate: str) -> Any: + """Delete specific weigh-in.""" + cdate = _validate_date_format(cdate, "cdate") + url = f"{self.garmin_connect_weight_url}/weight/{cdate}/byversion/{weight_pk}" + logger.debug("Deleting weigh-in") + + return self.garth.request( + "DELETE", + "connectapi", + url, + api=True, + ) + + def delete_weigh_ins(self, cdate: str, delete_all: bool = False) -> int | None: + """ + Delete weigh-in for 'cdate' format 'YYYY-MM-DD'. + Includes option to delete all weigh-ins for that date. + """ + + daily_weigh_ins = self.get_daily_weigh_ins(cdate) + weigh_ins = daily_weigh_ins.get("dateWeightList", []) + if not weigh_ins or len(weigh_ins) == 0: + logger.warning(f"No weigh-ins found on {cdate}") + return None + elif len(weigh_ins) > 1: + logger.warning(f"Multiple weigh-ins found for {cdate}") + if not delete_all: + logger.warning( + f"Set delete_all to True to delete all {len(weigh_ins)} weigh-ins" + ) + return None + + for w in weigh_ins: + self.delete_weigh_in(w["samplePk"], cdate) + + return len(weigh_ins) + + def get_body_battery( + self, startdate: str, enddate: str | None = None + ) -> list[dict[str, Any]]: + """ + Return body battery values by day for 'startdate' format + 'YYYY-MM-DD' through enddate 'YYYY-MM-DD' + """ + + startdate = _validate_date_format(startdate, "startdate") + if enddate is None: + enddate = startdate + else: + enddate = _validate_date_format(enddate, "enddate") + url = self.garmin_connect_daily_body_battery_url + params = {"startDate": str(startdate), "endDate": str(enddate)} + logger.debug("Requesting body battery data") + + return self.connectapi(url, params=params) + + def get_body_battery_events(self, cdate: str) -> list[dict[str, Any]]: + """ + Return body battery events for date 'cdate' format 'YYYY-MM-DD'. + The return value is a list of dictionaries, where each dictionary contains event data for a specific event. + Events can include sleep, recorded activities, auto-detected activities, and naps + """ + + cdate = _validate_date_format(cdate, "cdate") + url = f"{self.garmin_connect_body_battery_events_url}/{cdate}" + logger.debug("Requesting body battery event data") + + return self.connectapi(url) + + def set_blood_pressure( + self, + systolic: int, + diastolic: int, + pulse: int, + timestamp: str = "", + notes: str = "", + ) -> dict[str, Any]: + """ + Add blood pressure measurement + """ + + url = f"{self.garmin_connect_set_blood_pressure_endpoint}" + dt = datetime.fromisoformat(timestamp) if timestamp else datetime.now() + # Apply timezone offset to get UTC/GMT time + dtGMT = dt.astimezone(timezone.utc) + payload = { + "measurementTimestampLocal": _fmt_ts(dt), + "measurementTimestampGMT": _fmt_ts(dtGMT), + "systolic": systolic, + "diastolic": diastolic, + "pulse": pulse, + "sourceType": "MANUAL", + "notes": notes, + } + for name, val, lo, hi in ( + ("systolic", systolic, 70, 260), + ("diastolic", diastolic, 40, 150), + ("pulse", pulse, 20, 250), + ): + if not isinstance(val, int) or not (lo <= val <= hi): + raise ValueError(f"{name} must be an int in [{lo}, {hi}]") + logger.debug("Adding blood pressure") + + return self.garth.post("connectapi", url, json=payload).json() + + def get_blood_pressure( + self, startdate: str, enddate: str | None = None + ) -> dict[str, Any]: + """ + Returns blood pressure by day for 'startdate' format + 'YYYY-MM-DD' through enddate 'YYYY-MM-DD' + """ + + startdate = _validate_date_format(startdate, "startdate") + if enddate is None: + enddate = startdate + else: + enddate = _validate_date_format(enddate, "enddate") + url = f"{self.garmin_connect_blood_pressure_endpoint}/{startdate}/{enddate}" + params = {"includeAll": True} + logger.debug("Requesting blood pressure data") + + return self.connectapi(url, params=params) + + def delete_blood_pressure(self, version: str, cdate: str) -> dict[str, Any]: + """Delete specific blood pressure measurement.""" + url = f"{self.garmin_connect_set_blood_pressure_endpoint}/{cdate}/{version}" + logger.debug("Deleting blood pressure measurement") + + return self.garth.request( + "DELETE", + "connectapi", + url, + api=True, + ).json() + + def get_max_metrics(self, cdate: str) -> dict[str, Any]: + """Return available max metric data for 'cdate' format 'YYYY-MM-DD'.""" + + cdate = _validate_date_format(cdate, "cdate") + url = f"{self.garmin_connect_metrics_url}/{cdate}/{cdate}" + logger.debug("Requesting max metrics") + + return self.connectapi(url) + + def get_lactate_threshold( + self, + *, + latest: bool = True, + start_date: str | date | None = None, + end_date: str | date | None = None, + aggregation: str = "daily", + ) -> dict[str, Any]: + """ + Returns Running Lactate Threshold information, including heart rate, power, and speed + + :param bool (Required) - latest: Whether to query for the latest Lactate Threshold info or a range. False if querying a range + :param date (Optional) - start_date: The first date in the range to query, format 'YYYY-MM-DD'. Required if `latest` is False. Ignored if `latest` is True + :param date (Optional) - end_date: The last date in the range to query, format 'YYYY-MM-DD'. Defaults to current data. Ignored if `latest` is True + :param str (Optional) - aggregation: How to aggregate the data. Must be one of `daily`, `weekly`, `monthly`, `yearly`. + """ + + if latest: + speed_and_heart_rate_url = ( + f"{self.garmin_connect_biometric_url}/latestLactateThreshold" + ) + power_url = f"{self.garmin_connect_biometric_url}/powerToWeight/latest/{date.today()}?sport=Running" + + power = self.connectapi(power_url) + if isinstance(power, list) and power: + power_dict = power[0] + elif isinstance(power, dict): + power_dict = power + else: + power_dict = {} + + speed_and_heart_rate = self.connectapi(speed_and_heart_rate_url) + + speed_and_heart_rate_dict = { + "userProfilePK": None, + "version": None, + "calendarDate": None, + "sequence": None, + "speed": None, + "heartRate": None, + "heartRateCycling": None, + } + + # Garmin /latestLactateThreshold endpoint returns a list of two + # (or more, if cyclingHeartRate ever gets values) nearly identical dicts. + # We're combining them here + for entry in speed_and_heart_rate: + speed = entry.get("speed") + if speed is not None: + speed_and_heart_rate_dict["userProfilePK"] = entry["userProfilePK"] + speed_and_heart_rate_dict["version"] = entry["version"] + speed_and_heart_rate_dict["calendarDate"] = entry["calendarDate"] + speed_and_heart_rate_dict["sequence"] = entry["sequence"] + speed_and_heart_rate_dict["speed"] = speed + + # Prefer correct key; fall back to Garmin's historical typo ("hearRate") + hr = entry.get("heartRate") or entry.get("hearRate") + if hr is not None: + speed_and_heart_rate_dict["heartRate"] = hr + + # Doesn't exist for me but adding it just in case. We'll check for each entry + hrc = entry.get("heartRateCycling") + if hrc is not None: + speed_and_heart_rate_dict["heartRateCycling"] = hrc + return { + "speed_and_heart_rate": speed_and_heart_rate_dict, + "power": power_dict, + } + + if start_date is None: + raise ValueError("you must either specify 'latest=True' or a start_date") + + if end_date is None: + end_date = date.today().isoformat() + + # Normalize and validate + if isinstance(start_date, date): + start_date = start_date.isoformat() + else: + start_date = _validate_date_format(start_date, "start_date") + if isinstance(end_date, date): + end_date = end_date.isoformat() + else: + end_date = _validate_date_format(end_date, "end_date") + + _valid_aggregations = {"daily", "weekly", "monthly", "yearly"} + if aggregation not in _valid_aggregations: + raise ValueError(f"aggregation must be one of {_valid_aggregations}") + + speed_url = f"{self.garmin_connect_biometric_stats_url}/lactateThresholdSpeed/range/{start_date}/{end_date}?sport=RUNNING&aggregation={aggregation}&aggregationStrategy=LATEST" + + heart_rate_url = f"{self.garmin_connect_biometric_stats_url}/lactateThresholdHeartRate/range/{start_date}/{end_date}?sport=RUNNING&aggregation={aggregation}&aggregationStrategy=LATEST" + + power_url = f"{self.garmin_connect_biometric_stats_url}/functionalThresholdPower/range/{start_date}/{end_date}?sport=RUNNING&aggregation={aggregation}&aggregationStrategy=LATEST" + + speed = self.connectapi(speed_url) + heart_rate = self.connectapi(heart_rate_url) + power = self.connectapi(power_url) + + return {"speed": speed, "heart_rate": heart_rate, "power": power} + + def add_hydration_data( + self, + value_in_ml: float, + timestamp: str | None = None, + cdate: str | None = None, + ) -> dict[str, Any]: + """Add hydration data in ml. Defaults to current date and current timestamp if left empty + :param float required - value_in_ml: The number of ml of water you wish to add (positive) or subtract (negative) + :param timestamp optional - timestamp: The timestamp of the hydration update, format 'YYYY-MM-DDThh:mm:ss.ms' Defaults to current timestamp + :param date optional - cdate: The date of the weigh in, format 'YYYY-MM-DD'. Defaults to current date + """ + + # Validate inputs + if not isinstance(value_in_ml, numbers.Real): + raise ValueError("value_in_ml must be a number") + + # Allow negative values for subtraction but validate reasonable range + if abs(value_in_ml) > MAX_HYDRATION_ML: + raise ValueError( + f"value_in_ml seems unreasonably high (>{MAX_HYDRATION_ML}ml)" + ) + + url = self.garmin_connect_set_hydration_url + + if timestamp is None and cdate is None: + # If both are null, use today and now + raw_date = date.today() + cdate = str(raw_date) + + raw_ts = datetime.now() + timestamp = _fmt_ts(raw_ts) + + elif cdate is not None and timestamp is None: + # If cdate is provided, validate and use midnight local time + cdate = _validate_date_format(cdate, "cdate") + raw_ts = datetime.strptime(cdate, DATE_FORMAT_STR) # midnight local + timestamp = _fmt_ts(raw_ts) + + elif cdate is None and timestamp is not None: + # If timestamp is provided, normalize and set cdate to its date part + if not isinstance(timestamp, str): + raise ValueError("timestamp must be a string") + try: + try: + raw_ts = datetime.fromisoformat(timestamp) + except ValueError: + raw_ts = datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%S") + cdate = raw_ts.date().isoformat() + timestamp = _fmt_ts(raw_ts) + except ValueError as e: + raise ValueError("Invalid timestamp format (expected ISO 8601)") from e + else: + # Both provided - validate consistency and normalize + cdate = _validate_date_format(cdate, "cdate") + if not isinstance(timestamp, str): + raise ValueError("timestamp must be a string") + try: + try: + raw_ts = datetime.fromisoformat(timestamp) + except ValueError: + raw_ts = datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%S") + ts_date = raw_ts.date().isoformat() + if ts_date != cdate: + raise ValueError( + f"timestamp date ({ts_date}) doesn't match cdate ({cdate})" + ) + timestamp = _fmt_ts(raw_ts) + except ValueError: + raise + + payload = { + "calendarDate": cdate, + "timestampLocal": timestamp, + "valueInML": value_in_ml, + } + + logger.debug("Adding hydration data") + return self.garth.put("connectapi", url, json=payload).json() + + def get_hydration_data(self, cdate: str) -> dict[str, Any]: + """Return available hydration data 'cdate' format 'YYYY-MM-DD'.""" + + cdate = _validate_date_format(cdate, "cdate") + url = f"{self.garmin_connect_daily_hydration_url}/{cdate}" + logger.debug("Requesting hydration data") + + return self.connectapi(url) + + def get_respiration_data(self, cdate: str) -> dict[str, Any]: + """Return available respiration data 'cdate' format 'YYYY-MM-DD'.""" + + cdate = _validate_date_format(cdate, "cdate") + url = f"{self.garmin_connect_daily_respiration_url}/{cdate}" + logger.debug("Requesting respiration data") + + return self.connectapi(url) + + def get_spo2_data(self, cdate: str) -> dict[str, Any]: + """Return available SpO2 data 'cdate' format 'YYYY-MM-DD'.""" + + cdate = _validate_date_format(cdate, "cdate") + url = f"{self.garmin_connect_daily_spo2_url}/{cdate}" + logger.debug("Requesting SpO2 data") + + return self.connectapi(url) + + def get_intensity_minutes_data(self, cdate: str) -> dict[str, Any]: + """Return available Intensity Minutes data 'cdate' format 'YYYY-MM-DD'.""" + + cdate = _validate_date_format(cdate, "cdate") + url = f"{self.garmin_connect_daily_intensity_minutes}/{cdate}" + logger.debug("Requesting Intensity Minutes data") + + return self.connectapi(url) + + def get_all_day_stress(self, cdate: str) -> dict[str, Any]: + """Return available all day stress data 'cdate' format 'YYYY-MM-DD'.""" + + cdate = _validate_date_format(cdate, "cdate") + url = f"{self.garmin_connect_daily_stress_url}/{cdate}" + logger.debug("Requesting all day stress data") + + return self.connectapi(url) + + def get_all_day_events(self, cdate: str) -> dict[str, Any]: + """ + Return available daily events data 'cdate' format 'YYYY-MM-DD'. + Includes autodetected activities, even if not recorded on the watch + """ + + cdate = _validate_date_format(cdate, "cdate") + url = f"{self.garmin_daily_events_url}?calendarDate={cdate}" + logger.debug("Requesting all day events data") + + return self.connectapi(url) + + def get_personal_record(self) -> dict[str, Any]: + """Return personal records for current user.""" + + url = f"{self.garmin_connect_personal_record_url}/{self.display_name}" + logger.debug("Requesting personal records for user") + + return self.connectapi(url) + + def get_earned_badges(self) -> list[dict[str, Any]]: + """Return earned badges for current user.""" + + url = self.garmin_connect_earned_badges_url + logger.debug("Requesting earned badges for user") + + return self.connectapi(url) + + def get_available_badges(self) -> list[dict[str, Any]]: + """Return available badges for current user.""" + + url = self.garmin_connect_available_badges_url + logger.debug("Requesting available badges for user") + + return self.connectapi(url, params={"showExclusiveBadge": "true"}) + + def get_in_progress_badges(self) -> list[dict[str, Any]]: + """Return in progress badges for current user.""" + + logger.debug("Requesting in progress badges for user") + + earned_badges = self.get_earned_badges() + available_badges = self.get_available_badges() + + # Filter out badges that are not in progress + def is_badge_in_progress(badge: dict) -> bool: + """Return True if the badge is in progress.""" + progress = badge.get("badgeProgressValue") + if not progress: + return False + if progress == 0: + return False + target = badge.get("badgeTargetValue") + if progress == target: + if badge.get("badgeLimitCount") is None: + return False + return badge.get("badgeEarnedNumber", 0) < badge["badgeLimitCount"] + return True + + earned_in_progress_badges = list(filter(is_badge_in_progress, earned_badges)) + available_in_progress_badges = list( + filter(is_badge_in_progress, available_badges) + ) + + combined = {b["badgeId"]: b for b in earned_in_progress_badges} + combined.update({b["badgeId"]: b for b in available_in_progress_badges}) + return list(combined.values()) + + def get_adhoc_challenges(self, start: int, limit: int) -> dict[str, Any]: + """Return adhoc challenges for current user.""" + + start = _validate_non_negative_integer(start, "start") + limit = _validate_positive_integer(limit, "limit") + url = self.garmin_connect_adhoc_challenges_url + params = {"start": str(start), "limit": str(limit)} + logger.debug("Requesting adhoc challenges for user") + + return self.connectapi(url, params=params) + + def get_badge_challenges(self, start: int, limit: int) -> dict[str, Any]: + """Return badge challenges for current user.""" + + start = _validate_non_negative_integer(start, "start") + limit = _validate_positive_integer(limit, "limit") + url = self.garmin_connect_badge_challenges_url + params = {"start": str(start), "limit": str(limit)} + logger.debug("Requesting badge challenges for user") + + return self.connectapi(url, params=params) + + def get_available_badge_challenges(self, start: int, limit: int) -> dict[str, Any]: + """Return available badge challenges.""" + + start = _validate_non_negative_integer(start, "start") + limit = _validate_positive_integer(limit, "limit") + url = self.garmin_connect_available_badge_challenges_url + params = {"start": str(start), "limit": str(limit)} + logger.debug("Requesting available badge challenges") + + return self.connectapi(url, params=params) + + def get_non_completed_badge_challenges( + self, start: int, limit: int + ) -> dict[str, Any]: + """Return badge non-completed challenges for current user.""" + + start = _validate_non_negative_integer(start, "start") + limit = _validate_positive_integer(limit, "limit") + url = self.garmin_connect_non_completed_badge_challenges_url + params = {"start": str(start), "limit": str(limit)} + logger.debug("Requesting badge challenges for user") + + return self.connectapi(url, params=params) + + def get_inprogress_virtual_challenges( + self, start: int, limit: int + ) -> dict[str, Any]: + """Return in-progress virtual challenges for current user.""" + + start = _validate_non_negative_integer(start, "start") + limit = _validate_positive_integer(limit, "limit") + url = self.garmin_connect_inprogress_virtual_challenges_url + params = {"start": str(start), "limit": str(limit)} + logger.debug("Requesting in-progress virtual challenges for user") + + return self.connectapi(url, params=params) + + def get_sleep_data(self, cdate: str) -> dict[str, Any]: + """Return sleep data for current user.""" + + cdate = _validate_date_format(cdate, "cdate") + url = f"{self.garmin_connect_daily_sleep_url}/{self.display_name}" + params = {"date": cdate, "nonSleepBufferMinutes": 60} + logger.debug("Requesting sleep data") + + return self.connectapi(url, params=params) + + def get_stress_data(self, cdate: str) -> dict[str, Any]: + """Return stress data for current user.""" + + cdate = _validate_date_format(cdate, "cdate") + url = f"{self.garmin_connect_daily_stress_url}/{cdate}" + logger.debug("Requesting stress data") + + return self.connectapi(url) + + def get_rhr_day(self, cdate: str) -> dict[str, Any]: + """Return resting heartrate data for current user.""" + + cdate = _validate_date_format(cdate, "cdate") + url = f"{self.garmin_connect_rhr_url}/{self.display_name}" + params = { + "fromDate": cdate, + "untilDate": cdate, + "metricId": 60, + } + logger.debug("Requesting resting heartrate data") + + return self.connectapi(url, params=params) + + def get_hrv_data(self, cdate: str) -> dict[str, Any] | None: + """Return Heart Rate Variability (hrv) data for current user.""" + + cdate = _validate_date_format(cdate, "cdate") + url = f"{self.garmin_connect_hrv_url}/{cdate}" + logger.debug("Requesting Heart Rate Variability (hrv) data") + + return self.connectapi(url) + + def get_training_readiness(self, cdate: str) -> dict[str, Any]: + """Return training readiness data for current user.""" + + cdate = _validate_date_format(cdate, "cdate") + url = f"{self.garmin_connect_training_readiness_url}/{cdate}" + logger.debug("Requesting training readiness data") + + return self.connectapi(url) + + def get_endurance_score( + self, startdate: str, enddate: str | None = None + ) -> dict[str, Any]: + """ + Return endurance score by day for 'startdate' format 'YYYY-MM-DD' + through enddate 'YYYY-MM-DD'. + Using a single day returns the precise values for that day. + Using a range returns the aggregated weekly values for that week. + """ + + startdate = _validate_date_format(startdate, "startdate") + if enddate is None: + url = self.garmin_connect_endurance_score_url + params = {"calendarDate": str(startdate)} + logger.debug("Requesting endurance score data for a single day") + + return self.connectapi(url, params=params) + else: + url = f"{self.garmin_connect_endurance_score_url}/stats" + enddate = _validate_date_format(enddate, "enddate") + params = { + "startDate": str(startdate), + "endDate": str(enddate), + "aggregation": "weekly", + } + logger.debug("Requesting endurance score data for a range of days") + + return self.connectapi(url, params=params) + + def get_race_predictions( + self, + startdate: str | None = None, + enddate: str | None = None, + _type: str | None = None, + ) -> dict[str, Any]: + """ + Return race predictions for the 5k, 10k, half marathon and marathon. + Accepts either 0 parameters or all three: + If all parameters are empty, returns the race predictions for the current date + Or returns the race predictions for each day or month in the range provided + + Keyword Arguments: + 'startdate' the date of the earliest race predictions + Cannot be more than one year before 'enddate' + 'enddate' the date of the last race predictions + '_type' either 'daily' (the predictions for each day in the range) or + 'monthly' (the aggregated monthly prediction for each month in the range) + """ + + valid = {"daily", "monthly", None} + if _type not in valid: + raise ValueError(f"results: _type must be one of {valid!r}.") + + if _type is None and startdate is None and enddate is None: + url = ( + self.garmin_connect_race_predictor_url + f"/latest/{self.display_name}" + ) + return self.connectapi(url) + + elif _type is not None and startdate is not None and enddate is not None: + startdate = _validate_date_format(startdate, "startdate") + enddate = _validate_date_format(enddate, "enddate") + if ( + datetime.strptime(enddate, DATE_FORMAT_STR).date() + - datetime.strptime(startdate, DATE_FORMAT_STR).date() + ).days > 366: + raise ValueError( + "Startdate cannot be more than one year before enddate" + ) + url = ( + self.garmin_connect_race_predictor_url + f"/{_type}/{self.display_name}" + ) + params = {"fromCalendarDate": startdate, "toCalendarDate": enddate} + return self.connectapi(url, params=params) + + else: + raise ValueError("you must either provide all parameters or no parameters") + + def get_training_status(self, cdate: str) -> dict[str, Any]: + """Return training status data for current user.""" + + cdate = _validate_date_format(cdate, "cdate") + url = f"{self.garmin_connect_training_status_url}/{cdate}" + logger.debug("Requesting training status data") + + return self.connectapi(url) + + def get_fitnessage_data(self, cdate: str) -> dict[str, Any]: + """Return Fitness Age data for current user.""" + + cdate = _validate_date_format(cdate, "cdate") + url = f"{self.garmin_connect_fitnessage}/{cdate}" + logger.debug("Requesting Fitness Age data") + + return self.connectapi(url) + + def get_hill_score( + self, startdate: str, enddate: str | None = None + ) -> dict[str, Any]: + """ + Return hill score by day from 'startdate' format 'YYYY-MM-DD' + to enddate 'YYYY-MM-DD' + """ + + if enddate is None: + url = self.garmin_connect_hill_score_url + startdate = _validate_date_format(startdate, "startdate") + params = {"calendarDate": str(startdate)} + logger.debug("Requesting hill score data for a single day") + + return self.connectapi(url, params=params) + + else: + url = f"{self.garmin_connect_hill_score_url}/stats" + startdate = _validate_date_format(startdate, "startdate") + enddate = _validate_date_format(enddate, "enddate") + params = { + "startDate": str(startdate), + "endDate": str(enddate), + "aggregation": "daily", + } + logger.debug("Requesting hill score data for a range of days") + + return self.connectapi(url, params=params) + + def get_devices(self) -> list[dict[str, Any]]: + """Return available devices for the current user account.""" + + url = self.garmin_connect_devices_url + logger.debug("Requesting devices") + + return self.connectapi(url) + + def get_device_settings(self, device_id: str) -> dict[str, Any]: + """Return device settings for device with 'device_id'.""" + + url = f"{self.garmin_connect_device_url}/device-info/settings/{device_id}" + logger.debug("Requesting device settings") + + return self.connectapi(url) + + def get_primary_training_device(self) -> dict[str, Any]: + """Return detailed information around primary training devices, included the specified device and the + priority of all devices. + """ + + url = self.garmin_connect_primary_device_url + logger.debug("Requesting primary training device information") + + return self.connectapi(url) + + def get_device_solar_data( + self, device_id: str, startdate: str, enddate: str | None = None + ) -> list[dict[str, Any]]: + """Return solar data for compatible device with 'device_id'""" + if enddate is None: + enddate = startdate + single_day = True + else: + single_day = False + + startdate = _validate_date_format(startdate, "startdate") + enddate = _validate_date_format(enddate, "enddate") + params = {"singleDayView": single_day} + + url = f"{self.garmin_connect_solar_url}/{device_id}/{startdate}/{enddate}" + + resp = self.connectapi(url, params=params) + if not resp or "deviceSolarInput" not in resp: + raise GarminConnectConnectionError("No device solar input data received") + return resp["deviceSolarInput"] + + def get_device_alarms(self) -> list[Any]: + """Get list of active alarms from all devices.""" + + logger.debug("Requesting device alarms") + + alarms = [] + devices = self.get_devices() + for device in devices: + device_settings = self.get_device_settings(device["deviceId"]) + device_alarms = device_settings.get("alarms") + if device_alarms is not None: + alarms += device_alarms + return alarms + + def get_device_last_used(self) -> dict[str, Any]: + """Return device last used.""" + + url = f"{self.garmin_connect_device_url}/mylastused" + logger.debug("Requesting device last used") + + return self.connectapi(url) + + def get_activities( + self, + start: int = 0, + limit: int = 20, + activitytype: str | None = None, + ) -> dict[str, Any] | list[Any]: + """ + Return available activities. + :param start: Starting activity offset, where 0 means the most recent activity + :param limit: Number of activities to return + :param activitytype: (Optional) Filter activities by type + :return: List of activities from Garmin + """ + + # Validate inputs + start = _validate_non_negative_integer(start, "start") + limit = _validate_positive_integer(limit, "limit") + + if limit > MAX_ACTIVITY_LIMIT: + raise ValueError(f"limit cannot exceed {MAX_ACTIVITY_LIMIT}") + + url = self.garmin_connect_activities + params = {"start": str(start), "limit": str(limit)} + if activitytype: + params["activityType"] = str(activitytype) + + logger.debug("Requesting activities from %d with limit %d", start, limit) + + activities = self.connectapi(url, params=params) + + if activities is None: + logger.warning("No activities data received") + return [] + + return activities + + def get_activities_fordate(self, fordate: str) -> dict[str, Any]: + """Return available activities for date.""" + + fordate = _validate_date_format(fordate, "fordate") + url = f"{self.garmin_connect_activity_fordate}/{fordate}" + logger.debug("Requesting activities for date %s", fordate) + + return self.connectapi(url) + + def set_activity_name(self, activity_id: str, title: str) -> Any: + """Set name for activity with id.""" + + url = f"{self.garmin_connect_activity}/{activity_id}" + payload = {"activityId": activity_id, "activityName": title} + + return self.garth.put("connectapi", url, json=payload, api=True) + + def set_activity_type( + self, + activity_id: str, + type_id: int, + type_key: str, + parent_type_id: int, + ) -> Any: + url = f"{self.garmin_connect_activity}/{activity_id}" + payload = { + "activityId": activity_id, + "activityTypeDTO": { + "typeId": type_id, + "typeKey": type_key, + "parentTypeId": parent_type_id, + }, + } + logger.debug("Changing activity type: %s", payload) + return self.garth.put("connectapi", url, json=payload, api=True) + + def create_manual_activity_from_json(self, payload: dict[str, Any]) -> Any: + url = f"{self.garmin_connect_activity}" + logger.debug("Uploading manual activity: %s", str(payload)) + return self.garth.post("connectapi", url, json=payload, api=True) + + def create_manual_activity( + self, + start_datetime: str, + time_zone: str, + type_key: str, + distance_km: float, + duration_min: int, + activity_name: str, + ) -> Any: + """ + Create a private activity manually with a few basic parameters. + type_key - Garmin field representing type of activity. See https://connect.garmin.com/modern/main/js/properties/activity_types/activity_types.properties + Value to use is the key without 'activity_type_' prefix, e.g. 'resort_skiing' + start_datetime - timestamp in this pattern "2023-12-02T10:00:00.000" + time_zone - local timezone of the activity, e.g. 'Europe/Paris' + distance_km - distance of the activity in kilometers + duration_min - duration of the activity in minutes + activity_name - the title + """ + payload = { + "activityTypeDTO": {"typeKey": type_key}, + "accessControlRuleDTO": {"typeId": 2, "typeKey": "private"}, + "timeZoneUnitDTO": {"unitKey": time_zone}, + "activityName": activity_name, + "metadataDTO": { + "autoCalcCalories": True, + }, + "summaryDTO": { + "startTimeLocal": start_datetime, + "distance": distance_km * 1000, + "duration": duration_min * 60, + }, + } + return self.create_manual_activity_from_json(payload) + + def get_last_activity(self) -> dict[str, Any] | None: + """Return last activity.""" + + activities = self.get_activities(0, 1) + if activities and isinstance(activities, list) and len(activities) > 0: + return activities[-1] + elif ( + activities and isinstance(activities, dict) and "activityList" in activities + ): + activity_list = activities["activityList"] + if activity_list and len(activity_list) > 0: + return activity_list[-1] + + return None + + def upload_activity(self, activity_path: str) -> Any: + """Upload activity in fit format from file.""" + # This code is borrowed from python-garminconnect-enhanced ;-) + + # Validate input + if not activity_path: + raise ValueError("activity_path cannot be empty") + + if not isinstance(activity_path, str): + raise ValueError("activity_path must be a string") + + # Check if file exists + p = Path(activity_path) + if not p.exists(): + raise FileNotFoundError(f"File not found: {activity_path}") + + # Check if it's actually a file + if not p.is_file(): + raise ValueError(f"path is not a file: {activity_path}") + + file_base_name = p.name + + if not file_base_name: + raise ValueError("invalid file path - no filename found") + + # More robust extension checking + file_parts = file_base_name.split(".") + if len(file_parts) < 2: + raise GarminConnectInvalidFileFormatError( + f"File has no extension: {activity_path}" + ) + + file_extension = file_parts[-1] + allowed_file_extension = ( + file_extension.upper() in Garmin.ActivityUploadFormat.__members__ + ) + + if allowed_file_extension: + try: + # Use context manager for file handling + with p.open("rb") as file_handle: + files = {"file": (file_base_name, file_handle)} + url = self.garmin_connect_upload + return self.garth.post("connectapi", url, files=files, api=True) + except OSError as e: + raise GarminConnectConnectionError( + f"Failed to read file {activity_path}: {e}" + ) from e + else: + allowed_formats = ", ".join(Garmin.ActivityUploadFormat.__members__.keys()) + raise GarminConnectInvalidFileFormatError( + f"Invalid file format '{file_extension}'. Allowed formats: {allowed_formats}" + ) + + def delete_activity(self, activity_id: str) -> Any: + """Delete activity with specified id""" + + url = f"{self.garmin_connect_delete_activity_url}/{activity_id}" + logger.debug("Deleting activity with id %s", activity_id) + + return self.garth.request( + "DELETE", + "connectapi", + url, + api=True, + ) + + def get_activities_by_date( + self, + startdate: str, + enddate: str | None = None, + activitytype: str | None = None, + sortorder: str | None = None, + ) -> list[dict[str, Any]]: + """ + Fetch available activities between specific dates + :param startdate: String in the format YYYY-MM-DD + :param enddate: (Optional) String in the format YYYY-MM-DD + :param activitytype: (Optional) Type of activity you are searching + Possible values are [cycling, running, swimming, + multi_sport, fitness_equipment, hiking, walking, other] + :param sortorder: (Optional) sorting direction. By default, Garmin uses descending order by startLocal field. + Use "asc" to get activities from oldest to newest. + :return: list of JSON activities + """ + + activities = [] + start = 0 + limit = 20 + # mimicking the behavior of the web interface that fetches + # 20 activities at a time + # and automatically loads more on scroll + url = self.garmin_connect_activities + startdate = _validate_date_format(startdate, "startdate") + if enddate is not None: + enddate = _validate_date_format(enddate, "enddate") + params = { + "startDate": startdate, + "start": str(start), + "limit": str(limit), + } + if enddate: + params["endDate"] = enddate + if activitytype: + params["activityType"] = str(activitytype) + if sortorder: + params["sortOrder"] = str(sortorder) + + logger.debug("Requesting activities by date from %s to %s", startdate, enddate) + while True: + params["start"] = str(start) + logger.debug("Requesting activities %d to %d", start, start + limit) + act = self.connectapi(url, params=params) + if act: + activities.extend(act) + start = start + limit + else: + break + + return activities + + def get_progress_summary_between_dates( + self, + startdate: str, + enddate: str, + metric: str = "distance", + groupbyactivities: bool = True, + ) -> dict[str, Any]: + """ + Fetch progress summary data between specific dates + :param startdate: String in the format YYYY-MM-DD + :param enddate: String in the format YYYY-MM-DD + :param metric: metric to be calculated in the summary: + "elevationGain", "duration", "distance", "movingDuration" + :param groupbyactivities: group the summary by activity type + :return: list of JSON activities with their aggregated progress summary + """ + + url = self.garmin_connect_fitnessstats + startdate = _validate_date_format(startdate, "startdate") + enddate = _validate_date_format(enddate, "enddate") + params = { + "startDate": str(startdate), + "endDate": str(enddate), + "aggregation": "lifetime", + "groupByParentActivityType": str(groupbyactivities), + "metric": str(metric), + } + + logger.debug( + "Requesting fitnessstats by date from %s to %s", startdate, enddate + ) + return self.connectapi(url, params=params) + + def get_activity_types(self) -> dict[str, Any]: + url = self.garmin_connect_activity_types + logger.debug("Requesting activity types") + return self.connectapi(url) + + def get_goals( + self, status: str = "active", start: int = 1, limit: int = 30 + ) -> list[dict[str, Any]]: + """ + Fetch all goals based on status + :param status: Status of goals (valid options are "active", "future", or "past") + :type status: str + :param start: Initial goal index + :type start: int + :param limit: Pagination limit when retrieving goals + :type limit: int + :return: list of goals in JSON format + """ + + goals = [] + url = self.garmin_connect_goals_url + valid_statuses = {"active", "future", "past"} + if status not in valid_statuses: + raise ValueError(f"status must be one of {valid_statuses}") + start = _validate_positive_integer(start, "start") + limit = _validate_positive_integer(limit, "limit") + params = { + "status": status, + "start": str(start), + "limit": str(limit), + "sortOrder": "asc", + } + + logger.debug("Requesting %s goals", status) + while True: + params["start"] = str(start) + logger.debug( + "Requesting %s goals %d to %d", status, start, start + limit - 1 + ) + goals_json = self.connectapi(url, params=params) + if goals_json: + goals.extend(goals_json) + start = start + limit + else: + break + + return goals + + def get_gear(self, userProfileNumber: str) -> dict[str, Any]: + """Return all user gear.""" + url = f"{self.garmin_connect_gear}?userProfilePk={userProfileNumber}" + logger.debug("Requesting gear for user %s", userProfileNumber) + + return self.connectapi(url) + + def get_gear_stats(self, gearUUID: str) -> dict[str, Any]: + url = f"{self.garmin_connect_gear_baseurl}stats/{gearUUID}" + logger.debug("Requesting gear stats for gearUUID %s", gearUUID) + return self.connectapi(url) + + def get_gear_defaults(self, userProfileNumber: str) -> dict[str, Any]: + url = ( + f"{self.garmin_connect_gear_baseurl}user/" + f"{userProfileNumber}/activityTypes" + ) + logger.debug("Requesting gear defaults for user %s", userProfileNumber) + return self.connectapi(url) + + def set_gear_default( + self, activityType: str, gearUUID: str, defaultGear: bool = True + ) -> Any: + defaultGearString = "/default/true" if defaultGear else "" + method_override = "PUT" if defaultGear else "DELETE" + url = ( + f"{self.garmin_connect_gear_baseurl}{gearUUID}/" + f"activityType/{activityType}{defaultGearString}" + ) + return self.garth.request(method_override, "connectapi", url, api=True) + + class ActivityDownloadFormat(Enum): + """Activity variables.""" + + ORIGINAL = auto() + TCX = auto() + GPX = auto() + KML = auto() + CSV = auto() + + class ActivityUploadFormat(Enum): + FIT = auto() + GPX = auto() + TCX = auto() + + def download_activity( + self, + activity_id: str, + dl_fmt: ActivityDownloadFormat = ActivityDownloadFormat.TCX, + ) -> bytes: + """ + Downloads activity in requested format and returns the raw bytes. For + "Original" will return the zip file content, up to user to extract it. + "CSV" will return a csv of the splits. + """ + activity_id = str(activity_id) + urls = { + Garmin.ActivityDownloadFormat.ORIGINAL: f"{self.garmin_connect_fit_download}/{activity_id}", # noqa + Garmin.ActivityDownloadFormat.TCX: f"{self.garmin_connect_tcx_download}/{activity_id}", # noqa + Garmin.ActivityDownloadFormat.GPX: f"{self.garmin_connect_gpx_download}/{activity_id}", # noqa + Garmin.ActivityDownloadFormat.KML: f"{self.garmin_connect_kml_download}/{activity_id}", # noqa + Garmin.ActivityDownloadFormat.CSV: f"{self.garmin_connect_csv_download}/{activity_id}", # noqa + } + if dl_fmt not in urls: + raise ValueError(f"unexpected value {dl_fmt} for dl_fmt") + url = urls[dl_fmt] + + logger.debug("Downloading activity from %s", url) + + return self.download(url) + + def get_activity_splits(self, activity_id: str) -> dict[str, Any]: + """Return activity splits.""" + + activity_id = str(activity_id) + url = f"{self.garmin_connect_activity}/{activity_id}/splits" + logger.debug("Requesting splits for activity id %s", activity_id) + + return self.connectapi(url) + + def get_activity_typed_splits(self, activity_id: str) -> dict[str, Any]: + """Return typed activity splits. Contains similar info to `get_activity_splits`, but for certain activity types + (e.g., Bouldering), this contains more detail.""" + + activity_id = str(activity_id) + url = f"{self.garmin_connect_activity}/{activity_id}/typedsplits" + logger.debug("Requesting typed splits for activity id %s", activity_id) + + return self.connectapi(url) + + def get_activity_split_summaries(self, activity_id: str) -> dict[str, Any]: + """Return activity split summaries.""" + + activity_id = str(activity_id) + url = f"{self.garmin_connect_activity}/{activity_id}/split_summaries" + logger.debug("Requesting split summaries for activity id %s", activity_id) + + return self.connectapi(url) + + def get_activity_weather(self, activity_id: str) -> dict[str, Any]: + """Return activity weather.""" + + activity_id = str(activity_id) + url = f"{self.garmin_connect_activity}/{activity_id}/weather" + logger.debug("Requesting weather for activity id %s", activity_id) + + return self.connectapi(url) + + def get_activity_hr_in_timezones(self, activity_id: str) -> dict[str, Any]: + """Return activity heartrate in timezones.""" + + activity_id = str(activity_id) + url = f"{self.garmin_connect_activity}/{activity_id}/hrTimeInZones" + logger.debug("Requesting HR time-in-zones for activity id %s", activity_id) + + return self.connectapi(url) + + def get_activity(self, activity_id: str) -> dict[str, Any]: + """Return activity summary, including basic splits.""" + + activity_id = str(activity_id) + url = f"{self.garmin_connect_activity}/{activity_id}" + logger.debug("Requesting activity summary data for activity id %s", activity_id) + + return self.connectapi(url) + + def get_activity_details( + self, activity_id: str, maxchart: int = 2000, maxpoly: int = 4000 + ) -> dict[str, Any]: + """Return activity details.""" + + activity_id = str(activity_id) + maxchart = _validate_positive_integer(maxchart, "maxchart") + maxpoly = _validate_positive_integer(maxpoly, "maxpoly") + params = {"maxChartSize": str(maxchart), "maxPolylineSize": str(maxpoly)} + url = f"{self.garmin_connect_activity}/{activity_id}/details" + logger.debug("Requesting details for activity id %s", activity_id) + + return self.connectapi(url, params=params) + + def get_activity_exercise_sets(self, activity_id: int | str) -> dict[str, Any]: + """Return activity exercise sets.""" + + activity_id = _validate_positive_integer(int(activity_id), "activity_id") + url = f"{self.garmin_connect_activity}/{activity_id}/exerciseSets" + logger.debug("Requesting exercise sets for activity id %s", activity_id) + + return self.connectapi(url) + + def get_activity_gear(self, activity_id: int | str) -> dict[str, Any]: + """Return gears used for activity id.""" + + activity_id = _validate_positive_integer(int(activity_id), "activity_id") + params = { + "activityId": str(activity_id), + } + url = self.garmin_connect_gear + logger.debug("Requesting gear for activity_id %s", activity_id) + + return self.connectapi(url, params=params) + + def get_gear_activities( + self, gearUUID: str, limit: int = 1000 + ) -> list[dict[str, Any]]: + """Return activities where gear uuid was used. + :param gearUUID: UUID of the gear to get activities for + :param limit: Maximum number of activities to return (default: 1000) + :return: List of activities where the specified gear was used + """ + gearUUID = str(gearUUID) + limit = _validate_positive_integer(limit, "limit") + # Optional: enforce a reasonable ceiling to avoid heavy responses + limit = min(limit, MAX_ACTIVITY_LIMIT) + url = f"{self.garmin_connect_activities_baseurl}{gearUUID}/gear?start=0&limit={limit}" + logger.debug("Requesting activities for gearUUID %s", gearUUID) + + return self.connectapi(url) + + def get_user_profile(self) -> dict[str, Any]: + """Get all users settings.""" + + url = self.garmin_connect_user_settings_url + logger.debug("Requesting user profile.") + + return self.connectapi(url) + + def get_userprofile_settings(self) -> dict[str, Any]: + """Get user settings.""" + + url = self.garmin_connect_userprofile_settings_url + logger.debug("Getting userprofile settings") + + return self.connectapi(url) + + def request_reload(self, cdate: str) -> dict[str, Any]: + """ + Request reload of data for a specific date. This is necessary because + Garmin offloads older data. + """ + + cdate = _validate_date_format(cdate, "cdate") + url = f"{self.garmin_request_reload_url}/{cdate}" + logger.debug("Requesting reload of data for %s.", cdate) + + return self.garth.post("connectapi", url, api=True).json() + + def get_workouts(self, start: int = 0, limit: int = 100) -> dict[str, Any]: + """Return workouts starting at offset `start` with at most `limit` results.""" + + url = f"{self.garmin_workouts}/workouts" + start = _validate_non_negative_integer(start, "start") + limit = _validate_positive_integer(limit, "limit") + logger.debug("Requesting workouts from %d with limit %d", start, limit) + params = {"start": start, "limit": limit} + return self.connectapi(url, params=params) + + def get_workout_by_id(self, workout_id: int | str) -> dict[str, Any]: + """Return workout by id.""" + + workout_id = _validate_positive_integer(int(workout_id), "workout_id") + url = f"{self.garmin_workouts}/workout/{workout_id}" + return self.connectapi(url) + + def download_workout(self, workout_id: int | str) -> bytes: + """Download workout by id.""" + + workout_id = _validate_positive_integer(int(workout_id), "workout_id") + url = f"{self.garmin_workouts}/workout/FIT/{workout_id}" + logger.debug("Downloading workout from %s", url) + + return self.download(url) + + def upload_workout( + self, workout_json: dict[str, Any] | list[Any] | str + ) -> dict[str, Any]: + """Upload workout using json data.""" + + url = f"{self.garmin_workouts}/workout" + logger.debug("Uploading workout using %s", url) + + if isinstance(workout_json, str): + import json as _json + + try: + payload = _json.loads(workout_json) + except Exception as e: + raise ValueError(f"invalid workout_json string: {e}") from e + else: + payload = workout_json + if not isinstance(payload, dict | list): + raise ValueError("workout_json must be a JSON object or array") + return self.garth.post("connectapi", url, json=payload, api=True).json() + + def get_menstrual_data_for_date(self, fordate: str) -> dict[str, Any]: + """Return menstrual data for date.""" + + fordate = _validate_date_format(fordate, "fordate") + url = f"{self.garmin_connect_menstrual_dayview_url}/{fordate}" + logger.debug("Requesting menstrual data for date %s", fordate) + + return self.connectapi(url) + + def get_menstrual_calendar_data( + self, startdate: str, enddate: str + ) -> dict[str, Any]: + """Return summaries of cycles that have days between startdate and enddate.""" + + startdate = _validate_date_format(startdate, "startdate") + enddate = _validate_date_format(enddate, "enddate") + url = f"{self.garmin_connect_menstrual_calendar_url}/{startdate}/{enddate}" + logger.debug( + "Requesting menstrual data for dates %s through %s", startdate, enddate + ) + + return self.connectapi(url) + + def get_pregnancy_summary(self) -> dict[str, Any]: + """Return snapshot of pregnancy data""" + + url = f"{self.garmin_connect_pregnancy_snapshot_url}" + logger.debug("Requesting pregnancy snapshot data") + + return self.connectapi(url) + + def query_garmin_graphql(self, query: dict[str, Any]) -> dict[str, Any]: + """Execute a POST to Garmin's GraphQL endpoint. + + Args: + query: A GraphQL request body, e.g. {"query": "...", "variables": {...}} + See example.py for example queries. + Returns: + Parsed JSON response as a dict. + """ + + op = ( + (query.get("operationName") or "unnamed") + if isinstance(query, dict) + else "unnamed" + ) + vars_keys = ( + sorted((query.get("variables") or {}).keys()) + if isinstance(query, dict) + else [] + ) + logger.debug("Querying Garmin GraphQL op=%s vars=%s", op, vars_keys) + return self.garth.post( + "connectapi", self.garmin_graphql_endpoint, json=query + ).json() + + def logout(self) -> None: + """Log user out of session.""" + + logger.warning( + "Deprecated: Alternative is to delete the login tokens to logout." + ) + + +class GarminConnectConnectionError(Exception): + """Raised when communication ended in error.""" + + +class GarminConnectTooManyRequestsError(Exception): + """Raised when rate limit is exceeded.""" + + +class GarminConnectAuthenticationError(Exception): + """Raised when authentication is failed.""" + + +class GarminConnectInvalidFileFormatError(Exception): + """Raised when an invalid file format is passed to upload.""" + + +================================================ +FILE: garminconnect/fit.py +================================================ +# type: ignore # Complex binary data handling - mypy errors expected +import time +from datetime import datetime +from io import BytesIO +from struct import pack, unpack +from typing import Any + + +def _calcCRC(crc: int, byte: int) -> int: + table = [ + 0x0000, + 0xCC01, + 0xD801, + 0x1400, + 0xF001, + 0x3C00, + 0x2800, + 0xE401, + 0xA001, + 0x6C00, + 0x7800, + 0xB401, + 0x5000, + 0x9C01, + 0x8801, + 0x4400, + ] + # compute checksum of lower four bits of byte + tmp = table[crc & 0xF] + crc = (crc >> 4) & 0x0FFF + crc = crc ^ tmp ^ table[byte & 0xF] + # now compute checksum of upper four bits of byte + tmp = table[crc & 0xF] + crc = (crc >> 4) & 0x0FFF + crc = crc ^ tmp ^ table[(byte >> 4) & 0xF] + return crc + + +class FitBaseType: + """BaseType Definition + + see FIT Protocol Document(Page.20)""" + + enum = { + "#": 0, + "endian": 0, + "field": 0x00, + "name": "enum", + "invalid": 0xFF, + "size": 1, + } + sint8 = { + "#": 1, + "endian": 0, + "field": 0x01, + "name": "sint8", + "invalid": 0x7F, + "size": 1, + } + uint8 = { + "#": 2, + "endian": 0, + "field": 0x02, + "name": "uint8", + "invalid": 0xFF, + "size": 1, + } + sint16 = { + "#": 3, + "endian": 1, + "field": 0x83, + "name": "sint16", + "invalid": 0x7FFF, + "size": 2, + } + uint16 = { + "#": 4, + "endian": 1, + "field": 0x84, + "name": "uint16", + "invalid": 0xFFFF, + "size": 2, + } + sint32 = { + "#": 5, + "endian": 1, + "field": 0x85, + "name": "sint32", + "invalid": 0x7FFFFFFF, + "size": 4, + } + uint32 = { + "#": 6, + "endian": 1, + "field": 0x86, + "name": "uint32", + "invalid": 0xFFFFFFFF, + "size": 4, + } + string = { + "#": 7, + "endian": 0, + "field": 0x07, + "name": "string", + "invalid": 0x00, + "size": 1, + } + float32 = { + "#": 8, + "endian": 1, + "field": 0x88, + "name": "float32", + "invalid": 0xFFFFFFFF, + "size": 2, + } + float64 = { + "#": 9, + "endian": 1, + "field": 0x89, + "name": "float64", + "invalid": 0xFFFFFFFFFFFFFFFF, + "size": 4, + } + uint8z = { + "#": 10, + "endian": 0, + "field": 0x0A, + "name": "uint8z", + "invalid": 0x00, + "size": 1, + } + uint16z = { + "#": 11, + "endian": 1, + "field": 0x8B, + "name": "uint16z", + "invalid": 0x0000, + "size": 2, + } + uint32z = { + "#": 12, + "endian": 1, + "field": 0x8C, + "name": "uint32z", + "invalid": 0x00000000, + "size": 4, + } + byte = { + "#": 13, + "endian": 0, + "field": 0x0D, + "name": "byte", + "invalid": 0xFF, + "size": 1, + } # array of byte, field is invalid if all bytes are invalid + + @staticmethod + def get_format(basetype: int) -> str: + formats = { + 0: "B", + 1: "b", + 2: "B", + 3: "h", + 4: "H", + 5: "i", + 6: "I", + 7: "s", + 8: "f", + 9: "d", + 10: "B", + 11: "H", + 12: "I", + 13: "c", + } + return formats[basetype["#"]] + + @staticmethod + def pack(basetype: dict[str, Any], value: Any) -> bytes: + """function to avoid DeprecationWarning""" + if basetype["#"] in (1, 2, 3, 4, 5, 6, 10, 11, 12): + value = int(value) + fmt = FitBaseType.get_format(basetype) + return pack(fmt, value) + + +class Fit: + HEADER_SIZE = 12 + + # not sure if this is the mesg_num + GMSG_NUMS = { + "file_id": 0, + "device_info": 23, + "weight_scale": 30, + "file_creator": 49, + "blood_pressure": 51, + } + + +class FitEncoder(Fit): + FILE_TYPE = 9 + LMSG_TYPE_FILE_INFO = 0 + LMSG_TYPE_FILE_CREATOR = 1 + LMSG_TYPE_DEVICE_INFO = 2 + + def __init__(self) -> None: + self.buf = BytesIO() + self.write_header() # create header first + self.device_info_defined = False + + def __str__(self) -> str: + orig_pos = self.buf.tell() + self.buf.seek(0) + lines = [] + while True: + b = self.buf.read(16) + if not b: + break + lines.append(" ".join([f"{ord(c):02x}" for c in b])) + self.buf.seek(orig_pos) + return "\n".join(lines) + + def write_header( + self, + header_size: int = 12, # Fit.HEADER_SIZE + protocol_version: int = 16, + profile_version: int = 108, + data_size: int = 0, + data_type: bytes = b".FIT", + ) -> None: + self.buf.seek(0) + s = pack( + "BBHI4s", + header_size, + protocol_version, + profile_version, + data_size, + data_type, + ) + self.buf.write(s) + + def _build_content_block(self, content: dict[str, Any]) -> bytes: + field_defs = [] + values = [] + for num, basetype, value, scale in content: + s = pack("BBB", num, basetype["size"], basetype["field"]) + field_defs.append(s) + if value is None: + # invalid value + value = basetype["invalid"] + elif scale is not None: + value *= scale + values.append(FitBaseType.pack(basetype, value)) + return (b"".join(field_defs), b"".join(values)) + + def write_file_info( + self, + serial_number: int | None = None, + time_created: datetime | None = None, + manufacturer: int | None = None, + product: int | None = None, + number: int | None = None, + ) -> None: + if time_created is None: + time_created = datetime.now() + + content = [ + (3, FitBaseType.uint32z, serial_number, None), + (4, FitBaseType.uint32, self.timestamp(time_created), None), + (1, FitBaseType.uint16, manufacturer, None), + (2, FitBaseType.uint16, product, None), + (5, FitBaseType.uint16, number, None), + (0, FitBaseType.enum, self.FILE_TYPE, None), # type + ] + fields, values = self._build_content_block(content) + + # create fixed content + msg_number = self.GMSG_NUMS["file_id"] + fixed_content = pack( + "BBHB", 0, 0, msg_number, len(content) + ) # reserved, architecture(0: little endian) + + self.buf.write( + b"".join( + [ + # definition + self.record_header( + definition=True, lmsg_type=self.LMSG_TYPE_FILE_INFO + ), + fixed_content, + fields, + # record + self.record_header(lmsg_type=self.LMSG_TYPE_FILE_INFO), + values, + ] + ) + ) + + def write_file_creator( + self, + software_version: int | None = None, + hardware_version: int | None = None, + ) -> None: + content = [ + (0, FitBaseType.uint16, software_version, None), + (1, FitBaseType.uint8, hardware_version, None), + ] + fields, values = self._build_content_block(content) + + msg_number = self.GMSG_NUMS["file_creator"] + fixed_content = pack( + "BBHB", 0, 0, msg_number, len(content) + ) # reserved, architecture(0: little endian) + self.buf.write( + b"".join( + [ + # definition + self.record_header( + definition=True, lmsg_type=self.LMSG_TYPE_FILE_CREATOR + ), + fixed_content, + fields, + # record + self.record_header(lmsg_type=self.LMSG_TYPE_FILE_CREATOR), + values, + ] + ) + ) + + def write_device_info( + self, + timestamp: datetime, + serial_number: int | None = None, + cum_operationg_time: int | None = None, + manufacturer: int | None = None, + product: int | None = None, + software_version: int | None = None, + battery_voltage: int | None = None, + device_index: int | None = None, + device_type: int | None = None, + hardware_version: int | None = None, + battery_status: int | None = None, + ) -> None: + content = [ + (253, FitBaseType.uint32, self.timestamp(timestamp), 1), + (3, FitBaseType.uint32z, serial_number, 1), + (7, FitBaseType.uint32, cum_operationg_time, 1), + (8, FitBaseType.uint32, None, None), # unknown field(undocumented) + (2, FitBaseType.uint16, manufacturer, 1), + (4, FitBaseType.uint16, product, 1), + (5, FitBaseType.uint16, software_version, 100), + (10, FitBaseType.uint16, battery_voltage, 256), + (0, FitBaseType.uint8, device_index, 1), + (1, FitBaseType.uint8, device_type, 1), + (6, FitBaseType.uint8, hardware_version, 1), + (11, FitBaseType.uint8, battery_status, None), + ] + fields, values = self._build_content_block(content) + + if not self.device_info_defined: + header = self.record_header( + definition=True, lmsg_type=self.LMSG_TYPE_DEVICE_INFO + ) + msg_number = self.GMSG_NUMS["device_info"] + fixed_content = pack( + "BBHB", 0, 0, msg_number, len(content) + ) # reserved, architecture(0: little endian) + self.buf.write(header + fixed_content + fields) + self.device_info_defined = True + + header = self.record_header(lmsg_type=self.LMSG_TYPE_DEVICE_INFO) + self.buf.write(header + values) + + def record_header(self, definition: bool = False, lmsg_type: int = 0) -> bytes: + msg = 0 + if definition: + msg = 1 << 6 # 6th bit is a definition message + return pack("B", msg + lmsg_type) + + def crc(self) -> int: + orig_pos = self.buf.tell() + self.buf.seek(0) + + crc = 0 + while True: + b = self.buf.read(1) + if not b: + break + crc = _calcCRC(crc, unpack("b", b)[0]) + self.buf.seek(orig_pos) + return pack("H", crc) + + def finish(self) -> None: + """re-weite file-header, then append crc to end of file""" + data_size = self.get_size() - self.HEADER_SIZE + self.write_header(data_size=data_size) + crc = self.crc() + self.buf.seek(0, 2) + self.buf.write(crc) + + def get_size(self) -> int: + orig_pos = self.buf.tell() + self.buf.seek(0, 2) + size = self.buf.tell() + self.buf.seek(orig_pos) + return size + + def getvalue(self) -> bytes: + return self.buf.getvalue() + + def timestamp(self, t: datetime | float) -> float: + """the timestamp in fit protocol is seconds since + UTC 00:00 Dec 31 1989 (631065600)""" + if isinstance(t, datetime): + t = time.mktime(t.timetuple()) + return t - 631065600 + + +class FitEncoderBloodPressure(FitEncoder): + # Here might be dragons - no idea what lsmg stand for, found 14 somewhere in the deepest web + LMSG_TYPE_BLOOD_PRESSURE = 14 + + def __init__(self) -> None: + super().__init__() + self.blood_pressure_monitor_defined = False + + def write_blood_pressure( + self, + timestamp: datetime | int | float, + diastolic_blood_pressure: int | None = None, + systolic_blood_pressure: int | None = None, + mean_arterial_pressure: int | None = None, + map_3_sample_mean: int | None = None, + map_morning_values: int | None = None, + map_evening_values: int | None = None, + heart_rate: int | None = None, + ) -> None: + # BLOOD PRESSURE FILE MESSAGES + content = [ + (253, FitBaseType.uint32, self.timestamp(timestamp), 1), + (0, FitBaseType.uint16, systolic_blood_pressure, 1), + (1, FitBaseType.uint16, diastolic_blood_pressure, 1), + (2, FitBaseType.uint16, mean_arterial_pressure, 1), + (3, FitBaseType.uint16, map_3_sample_mean, 1), + (4, FitBaseType.uint16, map_morning_values, 1), + (5, FitBaseType.uint16, map_evening_values, 1), + (6, FitBaseType.uint8, heart_rate, 1), + ] + fields, values = self._build_content_block(content) + + if not self.blood_pressure_monitor_defined: + header = self.record_header( + definition=True, lmsg_type=self.LMSG_TYPE_BLOOD_PRESSURE + ) + msg_number = self.GMSG_NUMS["blood_pressure"] + fixed_content = pack( + "BBHB", 0, 0, msg_number, len(content) + ) # reserved, architecture(0: little endian) + self.buf.write(header + fixed_content + fields) + self.blood_pressure_monitor_defined = True + + header = self.record_header(lmsg_type=self.LMSG_TYPE_BLOOD_PRESSURE) + self.buf.write(header + values) + + +class FitEncoderWeight(FitEncoder): + LMSG_TYPE_WEIGHT_SCALE = 3 + + def __init__(self) -> None: + super().__init__() + self.weight_scale_defined = False + + def write_weight_scale( + self, + timestamp: datetime | int | float, + weight: int | float, + percent_fat: int | float | None = None, + percent_hydration: int | float | None = None, + visceral_fat_mass: int | float | None = None, + bone_mass: int | float | None = None, + muscle_mass: int | float | None = None, + basal_met: int | float | None = None, + active_met: int | float | None = None, + physique_rating: int | float | None = None, + metabolic_age: int | float | None = None, + visceral_fat_rating: int | float | None = None, + bmi: int | float | None = None, + ) -> None: + content = [ + (253, FitBaseType.uint32, self.timestamp(timestamp), 1), + (0, FitBaseType.uint16, weight, 100), + (1, FitBaseType.uint16, percent_fat, 100), + (2, FitBaseType.uint16, percent_hydration, 100), + (3, FitBaseType.uint16, visceral_fat_mass, 100), + (4, FitBaseType.uint16, bone_mass, 100), + (5, FitBaseType.uint16, muscle_mass, 100), + (7, FitBaseType.uint16, basal_met, 4), + (9, FitBaseType.uint16, active_met, 4), + (8, FitBaseType.uint8, physique_rating, 1), + (10, FitBaseType.uint8, metabolic_age, 1), + (11, FitBaseType.uint8, visceral_fat_rating, 1), + (13, FitBaseType.uint16, bmi, 10), + ] + fields, values = self._build_content_block(content) + + if not self.weight_scale_defined: + header = self.record_header( + definition=True, lmsg_type=self.LMSG_TYPE_WEIGHT_SCALE + ) + msg_number = self.GMSG_NUMS["weight_scale"] + fixed_content = pack( + "BBHB", 0, 0, msg_number, len(content) + ) # reserved, architecture(0: little endian) + self.buf.write(header + fixed_content + fields) + self.weight_scale_defined = True + + header = self.record_header(lmsg_type=self.LMSG_TYPE_WEIGHT_SCALE) + self.buf.write(header + values) + + +================================================ +FILE: tests/conftest.py +================================================ +import json +import os +import re +from typing import Any + +import pytest + + +@pytest.fixture +def vcr(vcr: Any) -> Any: + # Set default GARMINTOKENS path if not already set + if "GARMINTOKENS" not in os.environ: + os.environ["GARMINTOKENS"] = os.path.expanduser("~/.garminconnect") + return vcr + + +def sanitize_cookie(cookie_value: str) -> str: + return re.sub(r"=[^;]*", "=SANITIZED", cookie_value) + + +def scrub_dates(response: Any) -> Any: + """Scrub ISO datetime strings to make cassettes more stable.""" + body_container = response.get("body") or {} + body = body_container.get("string") + if isinstance(body, str): + # Replace ISO datetime strings with a fixed timestamp + body = re.sub( + r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+", "1970-01-01T00:00:00.000", body + ) + body_container["string"] = body + elif isinstance(body, bytes): + # Handle bytes body + body_str = body.decode("utf-8", errors="ignore") + body_str = re.sub( + r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+", + "1970-01-01T00:00:00.000", + body_str, + ) + body_container["string"] = body_str.encode("utf-8") + response["body"] = body_container + return response + + +def sanitize_request(request: Any) -> Any: + if request.body: + try: + body = request.body.decode("utf8") + except UnicodeDecodeError: + return request # leave as-is; binary bodies not sanitized + else: + for key in ["username", "password", "refresh_token"]: + body = re.sub(key + r"=[^&]*", f"{key}=SANITIZED", body) + request.body = body.encode("utf8") + + if "Cookie" in request.headers: + cookies = request.headers["Cookie"].split("; ") + sanitized_cookies = [sanitize_cookie(cookie) for cookie in cookies] + request.headers["Cookie"] = "; ".join(sanitized_cookies) + return request + + +def sanitize_response(response: Any) -> Any: + # First scrub dates to normalize timestamps + response = scrub_dates(response) + + # Remove variable headers that can change between requests + headers_to_remove = { + "date", + "cf-ray", + "cf-cache-status", + "alt-svc", + "nel", + "report-to", + "transfer-encoding", + "pragma", + "content-encoding", + } + if "headers" in response: + response["headers"] = { + k: v + for k, v in response["headers"].items() + if k.lower() not in headers_to_remove + } + + for key in ["set-cookie", "Set-Cookie"]: + if key in response["headers"]: + cookies = response["headers"][key] + sanitized_cookies = [sanitize_cookie(cookie) for cookie in cookies] + response["headers"][key] = sanitized_cookies + + body = response["body"]["string"] + if isinstance(body, bytes): + body = body.decode("utf8") + + patterns = [ + "oauth_token=[^&]*", + "oauth_token_secret=[^&]*", + "mfa_token=[^&]*", + ] + for pattern in patterns: + body = re.sub(pattern, pattern.split("=")[0] + "=SANITIZED", body) + try: + body_json = json.loads(body) + except json.JSONDecodeError: + pass + else: + for field in [ + "access_token", + "refresh_token", + "jti", + "consumer_key", + "consumer_secret", + ]: + if field in body_json: + body_json[field] = "SANITIZED" + + body = json.dumps(body_json) + + if "body" in response and "string" in response["body"]: + if isinstance(response["body"]["string"], bytes): + response["body"]["string"] = body.encode("utf8") + else: + response["body"]["string"] = body + return response + + +@pytest.fixture(scope="session") +def vcr_config() -> dict[str, Any]: + return { + "filter_headers": [ + ("Authorization", "Bearer SANITIZED"), + ("Cookie", "SANITIZED"), + ], + "before_record_request": sanitize_request, + "before_record_response": sanitize_response, + } + + +================================================ +FILE: tests/test_garmin.py +================================================ +import pytest + +import garminconnect + +DATE = "2023-07-01" + + +@pytest.fixture(scope="session") +def garmin() -> garminconnect.Garmin: + return garminconnect.Garmin("email@example.org", "password") + + +@pytest.mark.vcr +def test_stats(garmin: garminconnect.Garmin) -> None: + garmin.login() + stats = garmin.get_stats(DATE) + assert "totalKilocalories" in stats + assert "activeKilocalories" in stats + + +@pytest.mark.vcr +def test_user_summary(garmin: garminconnect.Garmin) -> None: + garmin.login() + user_summary = garmin.get_user_summary(DATE) + assert "totalKilocalories" in user_summary + assert "activeKilocalories" in user_summary + + +@pytest.mark.vcr +def test_steps_data(garmin: garminconnect.Garmin) -> None: + garmin.login() + steps = garmin.get_steps_data(DATE) + if not steps: + pytest.skip("No steps data for date") + steps_data = steps[0] + assert "steps" in steps_data + + +@pytest.mark.vcr +def test_floors(garmin: garminconnect.Garmin) -> None: + garmin.login() + floors_data = garmin.get_floors(DATE) + assert "floorValuesArray" in floors_data + + +@pytest.mark.vcr +def test_daily_steps(garmin: garminconnect.Garmin) -> None: + garmin.login() + daily_steps_data = garmin.get_daily_steps(DATE, DATE) + # The API returns a list of daily step dictionaries + assert isinstance(daily_steps_data, list) + assert len(daily_steps_data) > 0 + + # Check the first day's data + daily_steps = daily_steps_data[0] + assert "calendarDate" in daily_steps + assert "totalSteps" in daily_steps + + +@pytest.mark.vcr +def test_heart_rates(garmin: garminconnect.Garmin) -> None: + garmin.login() + heart_rates = garmin.get_heart_rates(DATE) + assert "calendarDate" in heart_rates + assert "restingHeartRate" in heart_rates + + +@pytest.mark.vcr +def test_stats_and_body(garmin: garminconnect.Garmin) -> None: + garmin.login() + stats_and_body = garmin.get_stats_and_body(DATE) + assert "calendarDate" in stats_and_body + assert "metabolicAge" in stats_and_body + + +@pytest.mark.vcr +def test_body_composition(garmin: garminconnect.Garmin) -> None: + garmin.login() + body_composition = garmin.get_body_composition(DATE) + assert "totalAverage" in body_composition + assert "metabolicAge" in body_composition["totalAverage"] + + +@pytest.mark.vcr +def test_body_battery(garmin: garminconnect.Garmin) -> None: + garmin.login() + bb = garmin.get_body_battery(DATE) + if not bb: + pytest.skip("No body battery data for date") + body_battery = bb[0] + assert "date" in body_battery + assert "charged" in body_battery + + +@pytest.mark.vcr +def test_hydration_data(garmin: garminconnect.Garmin) -> None: + garmin.login() + hydration_data = garmin.get_hydration_data(DATE) + assert hydration_data + assert "calendarDate" in hydration_data + + +@pytest.mark.vcr +def test_respiration_data(garmin: garminconnect.Garmin) -> None: + garmin.login() + respiration_data = garmin.get_respiration_data(DATE) + assert "calendarDate" in respiration_data + assert "avgSleepRespirationValue" in respiration_data + + +@pytest.mark.vcr +def test_spo2_data(garmin: garminconnect.Garmin) -> None: + garmin.login() + spo2_data = garmin.get_spo2_data(DATE) + assert "calendarDate" in spo2_data + assert "averageSpO2" in spo2_data + + +@pytest.mark.vcr +def test_hrv_data(garmin: garminconnect.Garmin) -> None: + garmin.login() + hrv_data = garmin.get_hrv_data(DATE) + # HRV data might not be available for all dates (API returns 204 No Content) + if hrv_data is not None: + # If data exists, validate the structure + assert "hrvSummary" in hrv_data + assert "weeklyAvg" in hrv_data["hrvSummary"] + else: + # If no data, that's also a valid response (204 No Content) + assert hrv_data is None + + +@pytest.mark.vcr +def test_download_activity(garmin: garminconnect.Garmin) -> None: + garmin.login() + activity_id = "11998957007" + # This test may fail with 403 Forbidden if the activity is private or not accessible + # In such cases, we verify that the appropriate error is raised + try: + activity = garmin.download_activity(activity_id) + assert activity # If successful, activity should not be None/empty + except garminconnect.GarminConnectConnectionError as e: + # Expected error for inaccessible activities + assert "403" in str(e) or "Forbidden" in str(e) + pytest.skip( + "Activity not accessible (403 Forbidden) - expected in test environment" + ) + + +@pytest.mark.vcr +def test_all_day_stress(garmin: garminconnect.Garmin) -> None: + garmin.login() + all_day_stress = garmin.get_all_day_stress(DATE) + # Validate stress data structure + assert "calendarDate" in all_day_stress + assert "avgStressLevel" in all_day_stress + assert "maxStressLevel" in all_day_stress + assert "stressValuesArray" in all_day_stress + + +@pytest.mark.vcr +def test_upload(garmin: garminconnect.Garmin) -> None: + garmin.login() + fpath = "tests/12129115726_ACTIVITY.fit" + # This test may fail with 409 Conflict if the activity already exists + # In such cases, we verify that the appropriate error is raised + try: + result = garmin.upload_activity(fpath) + assert result # If successful, should return upload result + except Exception as e: + # Expected error for duplicate uploads + if "409" in str(e) or "Conflict" in str(e): + pytest.skip( + "Activity already exists (409 Conflict) - expected in test environment" + ) + else: + # Re-raise unexpected errors + raise + + +@pytest.mark.vcr +def test_request_reload(garmin: garminconnect.Garmin) -> None: + garmin.login() + cdate = "2021-01-01" + # Get initial steps data + sum(steps["steps"] for steps in garmin.get_steps_data(cdate)) + # Test that request_reload returns a valid response + reload_response = garmin.request_reload(cdate) + assert reload_response is not None + # Get steps data after reload - should still be accessible + final_steps = sum(steps["steps"] for steps in garmin.get_steps_data(cdate)) + assert final_steps >= 0 # Steps data should be non-negative diff --git a/main.py b/main.py index 46cfbbc..aa1e028 100644 --- a/main.py +++ b/main.py @@ -11,6 +11,7 @@ from pathlib import Path import sys from typing import Optional from datetime import datetime +import os from textual.app import App, ComposeResult from textual.containers import Container, Horizontal, Vertical @@ -83,7 +84,7 @@ class CyclingCoachApp(App): self.current_view = "dashboard" self._setup_logging() - def _setup_logging(self): + def _setup_logging(self, level=logging.INFO): """Configure logging for the TUI application.""" # Create logs directory logs_dir = Path("logs") @@ -91,7 +92,7 @@ class CyclingCoachApp(App): # Set up logger logger = logging.getLogger("cycling_coach") - logger.setLevel(logging.INFO) + logger.setLevel(level) # Add Textual handler for TUI-compatible logging textual_handler = TextualHandler() @@ -109,7 +110,6 @@ class CyclingCoachApp(App): def compose(self) -> ComposeResult: """Create the main application layout.""" - sys.stdout.write("CyclingCoachApp.compose: START\n") yield Header() with Container(): @@ -144,18 +144,14 @@ class CyclingCoachApp(App): yield RouteView(id="route-view") yield Footer() - sys.stdout.write("CyclingCoachApp.compose: END\n") async def on_mount(self) -> None: """Initialize the application when mounted.""" - sys.stdout.write("CyclingCoachApp.on_mount: START\n") # Set initial active navigation and tab self.query_one("#nav-dashboard").add_class("-active") tabs = self.query_one("#main-tabs", TabbedContent) if tabs: tabs.active = "dashboard-tab" - sys.stdout.write("CyclingCoachApp.on_mount: Activated dashboard-tab\n") - sys.stdout.write("CyclingCoachApp.on_mount: END\n") async def on_button_pressed(self, event: Button.Pressed) -> None: """Handle navigation button presses.""" @@ -186,28 +182,45 @@ class CyclingCoachApp(App): @on(TabbedContent.TabActivated) async def on_tab_activated(self, event: TabbedContent.TabActivated) -> None: - sys.stdout.write(f"CyclingCoachApp.on_tab_activated: Tab {event.pane.id} activated\n") """Handle tab activation to load data for the active tab.""" if event.pane.id == "workouts-tab": workout_view = self.query_one("#workout-view", WorkoutView) - sys.stdout.write("CyclingCoachApp.on_tab_activated: Calling workout_view.load_data()\n") workout_view.load_data() def action_quit(self) -> None: self.exit() async def init_db_async(): + logger = logging.getLogger("cycling_coach") try: await init_db() - sys.stdout.write("Database initialized successfully\n") + logger.info("Database initialized successfully") except Exception as e: - sys.stdout.write(f"Database initialization failed: {e}\n") + logger.error(f"Database initialization failed: {e}") + sys.exit(1) + +async def sync_garmin_activities_cli(): + """Sync Garmin activities in CLI format without starting TUI.""" + logger = logging.getLogger("cycling_coach") + try: + logger.info("Initializing database for Garmin sync...") + await init_db_async() + + logger.info("Starting Garmin activity sync...") + async with AsyncSessionLocal() as db: + workout_service = WorkoutService(db) + await workout_service.sync_garmin_activities() + logger.info("Garmin activity sync completed successfully.") + except Exception as e: + logger.error(f"Error during Garmin activity sync: {e}") sys.exit(1) async def list_workouts_cli(): """Display workouts in CLI format without starting TUI.""" + logger = logging.getLogger("cycling_coach") try: # Initialize database + logger.info("Initializing database for listing workouts...") await init_db_async() # Get workouts using WorkoutService @@ -216,14 +229,14 @@ async def list_workouts_cli(): workouts = await workout_service.get_workouts(limit=50) if not workouts: - print("No workouts found.") + logger.info("No workouts found.") return # Print header - print("AI Cycling Coach - Workouts") - print("=" * 80) - print(f"{'Date':<12} {'Type':<15} {'Duration':<10} {'Distance':<10} {'Avg HR':<8} {'Avg Power':<10}") - print("-" * 80) + logger.info("AI Cycling Coach - Workouts") + logger.info("=" * 80) + logger.info(f"{'Date':<12} {'Type':<15} {'Duration':<10} {'Distance':<10} {'Avg HR':<8} {'Avg Power':<10}") + logger.info("-" * 80) # Print each workout for workout in workouts: @@ -257,12 +270,12 @@ async def list_workouts_cli(): if workout.get("avg_power"): power_str = f"{workout['avg_power']} W" - print(f"{date_str:<12} {workout.get('activity_type', 'Unknown')[:14]:<15} {duration_str:<10} {distance_str:<10} {hr_str:<8} {power_str:<10}") + logger.info(f"{date_str:<12} {workout.get('activity_type', 'Unknown')[:14]:<15} {duration_str:<10} {distance_str:<10} {hr_str:<8} {power_str:<10}") - print(f"\nTotal workouts: {len(workouts)}") + logger.info(f"\nTotal workouts: {len(workouts)}") except Exception as e: - print(f"Error listing workouts: {e}") + logger.error(f"Error listing workouts: {e}") sys.exit(1) def main(): @@ -270,12 +283,30 @@ def main(): parser = argparse.ArgumentParser(description="AI Cycling Coach - Terminal Training Interface") parser.add_argument("--list-workouts", action="store_true", help="List all workouts in CLI format and exit") + parser.add_argument("--sync-garmin", action="store_true", + help="Sync Garmin activities and exit") + parser.add_argument("--debug", action="store_true", help="Enable debug logging") args = parser.parse_args() + + log_level = logging.DEBUG if args.debug else logging.INFO # Handle CLI commands that don't need TUI - if args.list_workouts: - asyncio.run(list_workouts_cli()) + if args.list_workouts or args.sync_garmin: + # Configure logging using the app's setup + app = CyclingCoachApp() + app._setup_logging(level=log_level) + + # Get the configured logger + cli_logger = logging.getLogger("cycling_coach") + + if args.list_workouts: + asyncio.run(list_workouts_cli()) + elif args.sync_garmin: + asyncio.run(sync_garmin_activities_cli()) + + # Exit gracefully after CLI commands + return return # Create data directory if it doesn't exist @@ -288,11 +319,8 @@ def main(): asyncio.run(init_db_async()) # Run the TUI application - sys.stdout.write("main(): Initializing CyclingCoachApp\n") - app = CyclingCoachApp() - sys.stdout.write("main(): CyclingCoachApp initialized. Running app.run()\n") + # Run the TUI application app.run() - sys.stdout.write("main(): app.run() finished.\n") if __name__ == "__main__": diff --git a/pyproject.toml b/pyproject.toml index abb08a2..dce6d6f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,7 +46,7 @@ dependencies = [ "gpxpy>=1.5.0", # External integrations - "garth==0.4.46", + "garminconnect", # Using python-garminconnect "httpx==0.25.2", # Backend framework diff --git a/requirements.txt b/requirements.txt index 86a22ec..78ac802 100644 --- a/requirements.txt +++ b/requirements.txt @@ -19,7 +19,7 @@ gpxpy # GPX parsing library aiosqlite==0.20.0 # Async SQLite driver # External integrations -garth==0.4.46 # Garmin Connect API client +garminconnect # Using python-garminconnect httpx==0.25.2 # Async HTTP client for OpenRouter API # Testing diff --git a/tui/services/workout_service.py b/tui/services/workout_service.py index 8bf5d2e..ccc5bdb 100644 --- a/tui/services/workout_service.py +++ b/tui/services/workout_service.py @@ -2,6 +2,7 @@ Enhanced workout service with debugging for TUI application. """ from typing import Dict, List, Optional +import logging from sqlalchemy import select, desc, text from sqlalchemy.ext.asyncio import AsyncSession @@ -11,6 +12,8 @@ from backend.app.models.garmin_sync_log import GarminSyncLog from backend.app.services.workout_sync import WorkoutSyncService from backend.app.services.ai_service import AIService +logger = logging.getLogger(__name__) + class WorkoutService: """Service for workout operations.""" @@ -182,11 +185,14 @@ class WorkoutService: async def sync_garmin_activities(self, days_back: int = 7) -> Dict: """Sync Garmin activities.""" + logger.debug(f"Initiating Garmin activity sync from TUI with days_back={days_back}.") try: sync_service = WorkoutSyncService(self.db) synced_count = await sync_service.sync_recent_activities(days_back=days_back) + logger.info(f"Garmin activity sync completed successfully from TUI. Synced {synced_count} activities.") return {"status": "success", "activities_synced": synced_count} except Exception as e: + logger.error(f"Garmin activity sync failed from TUI: {e}", exc_info=True) return {"status": "error", "message": str(e)} async def analyze_workout(self, workout_id: int) -> Dict: