mirror of
https://github.com/cyberjunky/home-assistant-garmin_connect.git
synced 2026-01-07 20:13:57 -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 |
|
||||
| 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
|
||||
|
||||
| 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)
|
||||
|
||||
# Register integration-level services (only once for first entry)
|
||||
if len(hass.config_entries.async_entries(DOMAIN)) == 1:
|
||||
# Register integration-level services (only once)
|
||||
if not hass.services.has_service(DOMAIN, "add_body_composition"):
|
||||
await async_setup_services(hass)
|
||||
|
||||
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 services only if this is the last entry
|
||||
if unload_ok and len(hass.config_entries.async_entries(DOMAIN)) == 1:
|
||||
# Unload services only if this is the last entry (no entries remaining after unload)
|
||||
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)
|
||||
|
||||
return bool(unload_ok)
|
||||
|
||||
@@ -253,6 +253,41 @@ class GarminConnectDataUpdateCoordinator(DataUpdateCoordinator):
|
||||
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:
|
||||
raise ConfigEntryAuthFailed from err
|
||||
except GarminConnectTooManyRequestsError:
|
||||
@@ -367,6 +402,7 @@ class GarminConnectDataUpdateCoordinator(DataUpdateCoordinator):
|
||||
**fitnessage_data,
|
||||
**hydration_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: tuple[GarminConnectSensorEntityDescription, ...] = (
|
||||
GarminConnectSensorEntityDescription(
|
||||
@@ -1103,6 +1135,7 @@ ALL_SENSOR_DESCRIPTIONS: tuple[GarminConnectSensorEntityDescription, ...] = (
|
||||
*ADDITIONAL_DISTANCE_SENSORS,
|
||||
*WELLNESS_SENSORS,
|
||||
*MENSTRUAL_CYCLE_SENSORS,
|
||||
*BLOOD_PRESSURE_SENSORS,
|
||||
*DIAGNOSTIC_SENSORS,
|
||||
)
|
||||
|
||||
|
||||
@@ -36,10 +36,6 @@ set_active_gear:
|
||||
add_body_composition:
|
||||
name: Add body composition
|
||||
description: Add body composition metrics to Garmin Connect.
|
||||
target:
|
||||
entity:
|
||||
integration: garmin_connect
|
||||
domain: sensor
|
||||
fields:
|
||||
weight:
|
||||
name: Weight
|
||||
@@ -181,10 +177,6 @@ add_body_composition:
|
||||
add_blood_pressure:
|
||||
name: Add blood pressure
|
||||
description: Add blood pressure measurement to Garmin Connect.
|
||||
target:
|
||||
entity:
|
||||
integration: garmin_connect
|
||||
domain: sensor
|
||||
fields:
|
||||
systolic:
|
||||
name: Systolic
|
||||
|
||||
@@ -379,6 +379,18 @@
|
||||
"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": {
|
||||
"name": "Device last synced"
|
||||
}
|
||||
|
||||
@@ -83,6 +83,13 @@ This integration provides **110+ sensors** covering various health and fitness m
|
||||
- **Hydration Goal** - Target intake
|
||||
- **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
|
||||
|
||||
- **SpO2** - Blood oxygen levels (average, lowest, latest)
|
||||
|
||||
Reference in New Issue
Block a user