Skip to content

Commit c7d42da

Browse files
nikolay-eclaude
andcommitted
Add enhanced sleep data extraction with new fields
- Update Sleep model with new columns: body_battery_change, skin_temp_celsius, awake_count, sleep_quality_score, sleep_recovery_score, spo2_avg, spo2_min, respiratory_rate - Extend GarminSleepData schema with field mappings for all new metrics including body battery changes, skin temperature, awakening counts, sleep quality scores, SpO2 data, and respiratory rate - Update extract_sleep_data function to save new fields to database - Remove unused alembic directory since project uses direct SQLAlchemy table creation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 84096f7 commit c7d42da

File tree

3 files changed

+61
-0
lines changed

3 files changed

+61
-0
lines changed

garmin_schemas.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,20 @@ class GarminSleepData(BaseModel):
2727
)
2828
sleep_score: float | None = Field(None, description="Sleep quality score")
2929

30+
# New fields for enhanced sleep tracking
31+
body_battery_change: int | None = Field(
32+
None, description="Body battery charge change"
33+
)
34+
skin_temp_celsius: float | None = Field(
35+
None, description="Average skin temperature in Celsius"
36+
)
37+
awake_count: int | None = Field(None, description="Number of times awakened")
38+
sleep_quality_score: float | None = Field(None, description="Sleep quality score")
39+
sleep_recovery_score: float | None = Field(None, description="Sleep recovery score")
40+
spo2_avg: float | None = Field(None, description="Average SpO2 percentage")
41+
spo2_min: float | None = Field(None, description="Minimum SpO2 percentage")
42+
respiratory_rate: float | None = Field(None, description="Average respiratory rate")
43+
3044
# Validation and conversion
3145
@field_validator(
3246
"deep_sleep_duration",
@@ -110,6 +124,35 @@ def from_garmin_response(cls, data: dict[str, Any]) -> Optional["GarminSleepData
110124
"totalMinutes",
111125
],
112126
"sleep_score": ["sleepScore", "sleep_score", "overallScore", "score"],
127+
"body_battery_change": [
128+
"bodyBatteryChange",
129+
"bodyBatteryDrain",
130+
"batteryChange",
131+
],
132+
"skin_temp_celsius": [
133+
"skinTempCelsius",
134+
"avgSkinTempCelsius",
135+
"skinTemp",
136+
],
137+
"awake_count": ["awakeCount", "awakeDuringSleep", "numberOfAwakenings"],
138+
"sleep_quality_score": [
139+
"sleepQualityScore",
140+
"qualityScore",
141+
"sleepScores",
142+
],
143+
"sleep_recovery_score": ["sleepRecoveryScore", "recoveryScore"],
144+
"spo2_avg": [
145+
"avgSpO2",
146+
"averageSpO2",
147+
"oxygenSaturation",
148+
"avgOxygenSaturation",
149+
],
150+
"spo2_min": ["lowestSpO2", "minSpO2", "minimumSpO2"],
151+
"respiratory_rate": [
152+
"avgRespiratoryRate",
153+
"averageRespRate",
154+
"respiratoryRate",
155+
],
113156
}
114157

115158
parsed_data = {}

models.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,15 @@ class Sleep(Base):
147147
awake_minutes = Column(Float)
148148
total_sleep_minutes = Column(Float)
149149
sleep_score = Column(Integer)
150+
# New fields for enhanced sleep tracking
151+
body_battery_change = Column(Integer)
152+
skin_temp_celsius = Column(Float)
153+
awake_count = Column(Integer)
154+
sleep_quality_score = Column(Float)
155+
sleep_recovery_score = Column(Float)
156+
spo2_avg = Column(Float)
157+
spo2_min = Column(Float)
158+
respiratory_rate = Column(Float)
150159
created_at = Column(DateTime, default=datetime.datetime.utcnow)
151160

152161
# Relationships

pull_garmin_data.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,15 @@ def extract_sleep_data(
178178
awake_minutes=(parsed_sleep.awake_duration or 0) / 60,
179179
total_sleep_minutes=(parsed_sleep.total_sleep_time or 0) / 60,
180180
sleep_score=parsed_sleep.sleep_score,
181+
# New enhanced fields
182+
body_battery_change=parsed_sleep.body_battery_change,
183+
skin_temp_celsius=parsed_sleep.skin_temp_celsius,
184+
awake_count=parsed_sleep.awake_count,
185+
sleep_quality_score=parsed_sleep.sleep_quality_score,
186+
sleep_recovery_score=parsed_sleep.sleep_recovery_score,
187+
spo2_avg=parsed_sleep.spo2_avg,
188+
spo2_min=parsed_sleep.spo2_min,
189+
respiratory_rate=parsed_sleep.respiratory_rate,
181190
)
182191

183192
except Exception as e:

0 commit comments

Comments
 (0)