mirror of
https://github.com/cyberjunky/home-assistant-garmin_connect.git
synced 2026-01-08 20:38:00 -05:00
Added blood pressure sensors
This commit is contained in:
@@ -93,6 +93,15 @@ Sensor values depend on your Garmin devices and connected apps.
|
|||||||
| Hydration Goal | Target intake |
|
| Hydration Goal | Target intake |
|
||||||
| Sweat Loss | Estimated fluid loss |
|
| Sweat Loss | Estimated fluid loss |
|
||||||
|
|
||||||
|
### Blood Pressure
|
||||||
|
|
||||||
|
| Sensor | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| Systolic | Systolic blood pressure (mmHg) |
|
||||||
|
| Diastolic | Diastolic blood pressure (mmHg) |
|
||||||
|
| Pulse | Pulse from blood pressure reading (bpm) |
|
||||||
|
| Measurement Time | When the BP was measured |
|
||||||
|
|
||||||
### Health Monitoring
|
### Health Monitoring
|
||||||
|
|
||||||
| Sensor | Description |
|
| Sensor | Description |
|
||||||
|
|||||||
@@ -99,8 +99,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
|
|
||||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||||
|
|
||||||
# Register integration-level services (only once for first entry)
|
# Register integration-level services (only once)
|
||||||
if len(hass.config_entries.async_entries(DOMAIN)) == 1:
|
if not hass.services.has_service(DOMAIN, "add_body_composition"):
|
||||||
await async_setup_services(hass)
|
await async_setup_services(hass)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
@@ -112,8 +112,9 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
|
|
||||||
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||||
|
|
||||||
# Unload services only if this is the last entry
|
# Unload services only if this is the last entry (no entries remaining after unload)
|
||||||
if unload_ok and len(hass.config_entries.async_entries(DOMAIN)) == 1:
|
remaining_entries = len(hass.config_entries.async_entries(DOMAIN))
|
||||||
|
if unload_ok and remaining_entries == 1: # This entry is being unloaded
|
||||||
await async_unload_services(hass)
|
await async_unload_services(hass)
|
||||||
|
|
||||||
return bool(unload_ok)
|
return bool(unload_ok)
|
||||||
|
|||||||
@@ -253,6 +253,41 @@ class GarminConnectDataUpdateCoordinator(DataUpdateCoordinator):
|
|||||||
self.api.get_hydration_data, today.isoformat()
|
self.api.get_hydration_data, today.isoformat()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Fetch blood pressure data (last 30 days for latest reading)
|
||||||
|
blood_pressure_data = {}
|
||||||
|
try:
|
||||||
|
bp_response = await self.hass.async_add_executor_job(
|
||||||
|
self.api.get_blood_pressure,
|
||||||
|
(today - timedelta(days=30)).isoformat(),
|
||||||
|
today.isoformat(),
|
||||||
|
)
|
||||||
|
_LOGGER.debug(
|
||||||
|
"Blood pressure API response: type=%s",
|
||||||
|
type(bp_response).__name__,
|
||||||
|
)
|
||||||
|
# API returns dict with measurementSummaries containing measurements
|
||||||
|
if bp_response and isinstance(bp_response, dict):
|
||||||
|
summaries = bp_response.get("measurementSummaries", [])
|
||||||
|
if summaries:
|
||||||
|
# Get measurements from the most recent day
|
||||||
|
latest_summary = summaries[-1]
|
||||||
|
measurements = latest_summary.get("measurements", [])
|
||||||
|
if measurements:
|
||||||
|
latest_bp = measurements[-1]
|
||||||
|
blood_pressure_data = {
|
||||||
|
"bpSystolic": latest_bp.get("systolic"),
|
||||||
|
"bpDiastolic": latest_bp.get("diastolic"),
|
||||||
|
"bpPulse": latest_bp.get("pulse"),
|
||||||
|
"bpMeasurementTime": latest_bp.get(
|
||||||
|
"measurementTimestampLocal"
|
||||||
|
),
|
||||||
|
}
|
||||||
|
_LOGGER.debug(
|
||||||
|
"Blood pressure data parsed: %s", blood_pressure_data
|
||||||
|
)
|
||||||
|
except Exception as err:
|
||||||
|
_LOGGER.debug("Blood pressure data not available: %s", err)
|
||||||
|
|
||||||
except GarminConnectAuthenticationError as err:
|
except GarminConnectAuthenticationError as err:
|
||||||
raise ConfigEntryAuthFailed from err
|
raise ConfigEntryAuthFailed from err
|
||||||
except GarminConnectTooManyRequestsError:
|
except GarminConnectTooManyRequestsError:
|
||||||
@@ -367,6 +402,7 @@ class GarminConnectDataUpdateCoordinator(DataUpdateCoordinator):
|
|||||||
**fitnessage_data,
|
**fitnessage_data,
|
||||||
**hydration_data,
|
**hydration_data,
|
||||||
**menstrual_data,
|
**menstrual_data,
|
||||||
|
**blood_pressure_data,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1071,6 +1071,38 @@ MENSTRUAL_CYCLE_SENSORS: tuple[GarminConnectSensorEntityDescription, ...] = (
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Blood Pressure Sensors
|
||||||
|
BLOOD_PRESSURE_SENSORS: tuple[GarminConnectSensorEntityDescription, ...] = (
|
||||||
|
GarminConnectSensorEntityDescription(
|
||||||
|
key="bpSystolic",
|
||||||
|
translation_key="bp_systolic",
|
||||||
|
native_unit_of_measurement="mmHg",
|
||||||
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
|
icon="mdi:heart-pulse",
|
||||||
|
),
|
||||||
|
GarminConnectSensorEntityDescription(
|
||||||
|
key="bpDiastolic",
|
||||||
|
translation_key="bp_diastolic",
|
||||||
|
native_unit_of_measurement="mmHg",
|
||||||
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
|
icon="mdi:heart-pulse",
|
||||||
|
),
|
||||||
|
GarminConnectSensorEntityDescription(
|
||||||
|
key="bpPulse",
|
||||||
|
translation_key="bp_pulse",
|
||||||
|
native_unit_of_measurement="bpm",
|
||||||
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
|
icon="mdi:heart",
|
||||||
|
),
|
||||||
|
GarminConnectSensorEntityDescription(
|
||||||
|
key="bpMeasurementTime",
|
||||||
|
translation_key="bp_measurement_time",
|
||||||
|
device_class=SensorDeviceClass.TIMESTAMP,
|
||||||
|
icon="mdi:clock-outline",
|
||||||
|
value_fn=lambda data: data.get("bpMeasurementTime"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
# Diagnostic Sensors
|
# Diagnostic Sensors
|
||||||
DIAGNOSTIC_SENSORS: tuple[GarminConnectSensorEntityDescription, ...] = (
|
DIAGNOSTIC_SENSORS: tuple[GarminConnectSensorEntityDescription, ...] = (
|
||||||
GarminConnectSensorEntityDescription(
|
GarminConnectSensorEntityDescription(
|
||||||
@@ -1103,6 +1135,7 @@ ALL_SENSOR_DESCRIPTIONS: tuple[GarminConnectSensorEntityDescription, ...] = (
|
|||||||
*ADDITIONAL_DISTANCE_SENSORS,
|
*ADDITIONAL_DISTANCE_SENSORS,
|
||||||
*WELLNESS_SENSORS,
|
*WELLNESS_SENSORS,
|
||||||
*MENSTRUAL_CYCLE_SENSORS,
|
*MENSTRUAL_CYCLE_SENSORS,
|
||||||
|
*BLOOD_PRESSURE_SENSORS,
|
||||||
*DIAGNOSTIC_SENSORS,
|
*DIAGNOSTIC_SENSORS,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -36,10 +36,6 @@ set_active_gear:
|
|||||||
add_body_composition:
|
add_body_composition:
|
||||||
name: Add body composition
|
name: Add body composition
|
||||||
description: Add body composition metrics to Garmin Connect.
|
description: Add body composition metrics to Garmin Connect.
|
||||||
target:
|
|
||||||
entity:
|
|
||||||
integration: garmin_connect
|
|
||||||
domain: sensor
|
|
||||||
fields:
|
fields:
|
||||||
weight:
|
weight:
|
||||||
name: Weight
|
name: Weight
|
||||||
@@ -181,10 +177,6 @@ add_body_composition:
|
|||||||
add_blood_pressure:
|
add_blood_pressure:
|
||||||
name: Add blood pressure
|
name: Add blood pressure
|
||||||
description: Add blood pressure measurement to Garmin Connect.
|
description: Add blood pressure measurement to Garmin Connect.
|
||||||
target:
|
|
||||||
entity:
|
|
||||||
integration: garmin_connect
|
|
||||||
domain: sensor
|
|
||||||
fields:
|
fields:
|
||||||
systolic:
|
systolic:
|
||||||
name: Systolic
|
name: Systolic
|
||||||
|
|||||||
@@ -379,6 +379,18 @@
|
|||||||
"menstrual_period_length": {
|
"menstrual_period_length": {
|
||||||
"name": "Menstrual period length"
|
"name": "Menstrual period length"
|
||||||
},
|
},
|
||||||
|
"bp_systolic": {
|
||||||
|
"name": "Blood pressure systolic"
|
||||||
|
},
|
||||||
|
"bp_diastolic": {
|
||||||
|
"name": "Blood pressure diastolic"
|
||||||
|
},
|
||||||
|
"bp_pulse": {
|
||||||
|
"name": "Blood pressure pulse"
|
||||||
|
},
|
||||||
|
"bp_measurement_time": {
|
||||||
|
"name": "Blood pressure measurement time"
|
||||||
|
},
|
||||||
"device_last_synced": {
|
"device_last_synced": {
|
||||||
"name": "Device last synced"
|
"name": "Device last synced"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,6 +83,13 @@ This integration provides **110+ sensors** covering various health and fitness m
|
|||||||
- **Hydration Goal** - Target intake
|
- **Hydration Goal** - Target intake
|
||||||
- **Sweat Loss** - Estimated fluid loss
|
- **Sweat Loss** - Estimated fluid loss
|
||||||
|
|
||||||
|
### Blood Pressure
|
||||||
|
|
||||||
|
- **Systolic** - Systolic blood pressure (mmHg)
|
||||||
|
- **Diastolic** - Diastolic blood pressure (mmHg)
|
||||||
|
- **Pulse** - Pulse from blood pressure reading (bpm)
|
||||||
|
- **Measurement Time** - When the BP was measured
|
||||||
|
|
||||||
### Health Monitoring
|
### Health Monitoring
|
||||||
|
|
||||||
- **SpO2** - Blood oxygen levels (average, lowest, latest)
|
- **SpO2** - Blood oxygen levels (average, lowest, latest)
|
||||||
|
|||||||
Reference in New Issue
Block a user