mirror of
https://github.com/cyberjunky/home-assistant-garmin_connect.git
synced 2026-01-07 20:13:57 -05:00
Added morning training readiness, fallback midnight
This commit is contained in:
@@ -127,14 +127,23 @@ class GarminConnectDataUpdateCoordinator(DataUpdateCoordinator):
|
||||
self.api.get_user_summary, today.isoformat()
|
||||
)
|
||||
|
||||
# Midnight fallback: During 0:00-2:00 window, if today's data is empty/None,
|
||||
# fallback to yesterday's data to avoid gaps due to UTC/GMT timezone differences
|
||||
if current_hour < 2 and (not summary or summary.get("totalSteps") in (None, 0)):
|
||||
_LOGGER.debug("Midnight fallback: Today's data empty, fetching yesterday's data")
|
||||
# Smart fallback: detect when Garmin servers haven't populated today's data yet
|
||||
# Key signal: dailyStepGoal is None means the day data structure doesn't exist
|
||||
# This works regardless of timezone - no fixed hour window needed
|
||||
today_data_not_ready = (
|
||||
not summary
|
||||
or summary.get("dailyStepGoal") is None
|
||||
)
|
||||
|
||||
if today_data_not_ready:
|
||||
_LOGGER.debug(
|
||||
"Today's data not ready (dailyStepGoal=%s), fetching yesterday's data",
|
||||
summary.get("dailyStepGoal") if summary else None
|
||||
)
|
||||
yesterday_summary = await self.hass.async_add_executor_job(
|
||||
self.api.get_user_summary, yesterday_date
|
||||
)
|
||||
if yesterday_summary and yesterday_summary.get("totalSteps"):
|
||||
if yesterday_summary and yesterday_summary.get("dailyStepGoal") is not None:
|
||||
summary = yesterday_summary
|
||||
_LOGGER.debug("Using yesterday's summary data as fallback")
|
||||
|
||||
@@ -205,6 +214,15 @@ class GarminConnectDataUpdateCoordinator(DataUpdateCoordinator):
|
||||
except Exception:
|
||||
summary["trainingReadiness"] = {}
|
||||
|
||||
# Fetch morning training readiness (AFTER_WAKEUP_RESET context)
|
||||
try:
|
||||
morning_training_readiness = await self.hass.async_add_executor_job(
|
||||
self.api.get_morning_training_readiness, today.isoformat()
|
||||
)
|
||||
summary["morningTrainingReadiness"] = morning_training_readiness or {}
|
||||
except Exception:
|
||||
summary["morningTrainingReadiness"] = {}
|
||||
|
||||
# Fetch training status
|
||||
try:
|
||||
training_status = await self.hass.async_add_executor_job(
|
||||
|
||||
@@ -886,6 +886,24 @@ ACTIVITY_TRACKING_SENSORS: tuple[GarminConnectSensorEntityDescription, ...] = (
|
||||
value_fn=lambda data: data.get("trainingStatus", {}).get("trainingStatusPhrase"),
|
||||
attributes_fn=lambda data: data.get("trainingStatus", {}),
|
||||
),
|
||||
GarminConnectSensorEntityDescription(
|
||||
key="morningTrainingReadiness",
|
||||
translation_key="morning_training_readiness",
|
||||
icon="mdi:weather-sunset-up",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
|
||||
value_fn=lambda data: data.get("morningTrainingReadiness", {}).get("score"),
|
||||
attributes_fn=lambda data: {
|
||||
"level": data.get("morningTrainingReadiness", {}).get("level"),
|
||||
"sleep_score": data.get("morningTrainingReadiness", {}).get("sleepScore"),
|
||||
"recovery_score": data.get("morningTrainingReadiness", {}).get("recoveryScore"),
|
||||
"hrv_status": data.get("morningTrainingReadiness", {}).get("hrvStatus"),
|
||||
"acuteLoad": data.get("morningTrainingReadiness", {}).get("acuteLoad"),
|
||||
"input_context": data.get("morningTrainingReadiness", {}).get("inputContext"),
|
||||
**{k: v for k, v in data.get("morningTrainingReadiness", {}).items()
|
||||
if k not in ("score", "level", "sleepScore", "recoveryScore", "hrvStatus", "acuteLoad", "inputContext")},
|
||||
},
|
||||
),
|
||||
GarminConnectSensorEntityDescription(
|
||||
key="lactateThresholdHeartRate",
|
||||
translation_key="lactate_threshold_hr",
|
||||
|
||||
@@ -349,6 +349,9 @@
|
||||
"training_status": {
|
||||
"name": "Training status"
|
||||
},
|
||||
"morning_training_readiness": {
|
||||
"name": "Morning training readiness"
|
||||
},
|
||||
"lactate_threshold_hr": {
|
||||
"name": "Lactate threshold heart rate"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user