Coverage for health / config.py: 89%

27 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-03-02 17:44 +0800

1""" 

2Configuration management for Garmin Health Sync system. 

3 

4Loads environment variables and defines data type configurations. 

5""" 

6 

7import os 

8from pathlib import Path 

9from typing import Dict, Any 

10from dotenv import load_dotenv 

11from health.utils.env_loader import load_env_with_extras 

12 

13# Load environment variables 

14load_env_with_extras() 

15 

16# Project paths 

17PROJECT_ROOT = Path(__file__).parent.parent 

18 

19# Support environment override for testing 

20_data_dir_env = os.getenv("DATA_DIR") 

21if _data_dir_env: 

22 DATA_DIR = Path(_data_dir_env) 

23else: 

24 DATA_DIR = PROJECT_ROOT / "data" / "health" 

25 

26DB_PATH = DATA_DIR / "health.db" 

27LOGS_DIR = PROJECT_ROOT / "logs" 

28TOKEN_STORE = Path.home() / ".garmin" / "tokens" 

29 

30# Ensure directories exist 

31DATA_DIR.mkdir(parents=True, exist_ok=True) 

32LOGS_DIR.mkdir(parents=True, exist_ok=True) 

33TOKEN_STORE.mkdir(parents=True, exist_ok=True) 

34 

35# Garmin credentials (optional during setup, required for actual sync) 

36GARMIN_EMAIL = os.getenv("GARMIN_EMAIL") 

37GARMIN_PASSWORD = os.getenv("GARMIN_PASSWORD") 

38 

39 

40def validate_credentials() -> None: 

41 """Validate that Garmin credentials are set. 

42 

43 Raises: 

44 ValueError: If credentials are missing 

45 """ 

46 if not GARMIN_EMAIL or not GARMIN_PASSWORD: 

47 raise ValueError( 

48 "Missing Garmin credentials. Please set GARMIN_EMAIL and GARMIN_PASSWORD " 

49 "in your .env file. See .env.example for reference." 

50 ) 

51 

52# Data type configurations 

53# Maps each data type to its API method, model, and storage path 

54DATA_TYPE_CONFIG: Dict[str, Dict[str, Any]] = { 

55 "steps": { 

56 "api_method": "get_steps_data", 

57 "storage_path": "daily_metrics/steps", 

58 "description": "Daily step count, distance, and calories", 

59 }, 

60 "heart_rate": { 

61 "api_method": "get_heart_rates", 

62 "storage_path": "daily_metrics/heart_rate", 

63 "description": "Heart rate data including min, max, resting", 

64 }, 

65 "sleep": { 

66 "api_method": "get_sleep_data", 

67 "storage_path": "daily_metrics/sleep", 

68 "description": "Sleep stages, duration, and quality scores", 

69 }, 

70 "stress": { 

71 "api_method": "get_stress_data", 

72 "storage_path": "daily_metrics/stress", 

73 "description": "Stress levels throughout the day", 

74 }, 

75 "body_battery": { 

76 "api_method": "get_body_battery", 

77 "storage_path": "daily_metrics/body_battery", 

78 "description": "Body Battery charge and drain", 

79 }, 

80 "spo2": { 

81 "api_method": "get_spo2_data", 

82 "storage_path": "daily_metrics/spo2", 

83 "description": "Blood oxygen saturation levels", 

84 }, 

85 "respiration": { 

86 "api_method": "get_respiration_data", 

87 "storage_path": "daily_metrics/respiration", 

88 "description": "Breathing rate data", 

89 }, 

90 "hydration": { 

91 "api_method": "get_hydration_data", 

92 "storage_path": "daily_metrics/hydration", 

93 "description": "Daily water intake tracking", 

94 }, 

95 "floors": { 

96 "api_method": "get_floors", 

97 "storage_path": "daily_metrics/floors", 

98 "description": "Floors climbed per day", 

99 }, 

100 "intensity_minutes": { 

101 "api_method": "get_intensity_minutes", 

102 "storage_path": "daily_metrics/intensity_minutes", 

103 "description": "Active intensity minutes (moderate and vigorous)", 

104 }, 

105 "hrv": { 

106 "api_method": "get_hrv_data", 

107 "storage_path": "daily_metrics/hrv", 

108 "description": "Heart rate variability", 

109 }, 

110 "rhr": { 

111 "api_method": "get_rhr_day", 

112 "storage_path": "daily_metrics/rhr", 

113 "description": "Resting heart rate", 

114 }, 

115 "activities": { 

116 "api_method": "get_activities_by_date", 

117 "storage_path": "activities", 

118 "description": "Exercise activities and workouts", 

119 "batch_by_date_range": True, 

120 }, 

121 "weight": { 

122 "api_method": "get_weigh_ins", 

123 "storage_path": "body_metrics/weight", 

124 "description": "Body weight measurements", 

125 }, 

126 "lifestyle_logging": { 

127 "api_method": "get_lifestyle_logging_data", 

128 "storage_path": "daily_metrics/lifestyle_logging", 

129 "description": "Lifestyle behaviors: alcohol, caffeine, meals, fasting, light exercise", 

130 }, 

131} 

132 

133# Sync settings 

134DEFAULT_BATCH_SIZE_DAYS = 30 # Process 30 days at a time for batch operations 

135MAX_RETRIES = 3 # Maximum retry attempts for API calls 

136RETRY_DELAY_SECONDS = 2 # Initial delay before retrying (exponential backoff) 

137 

138# Historical data start date (user configurable) 

139HISTORICAL_START_DATE = "2024-01-01" # Default, can be overridden via CLI