mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Update Fitbit to avoid a KeyError when restingHeartRate
is not present (#103872)
* Update Fitbit to avoid a KeyError when `restingHeartRate` is not present * Explicitly handle none response values
This commit is contained in:
parent
efe33d815f
commit
64c9aa0cff
@ -135,6 +135,17 @@ def _water_unit(unit_system: FitbitUnitSystem) -> UnitOfVolume:
|
||||
return UnitOfVolume.MILLILITERS
|
||||
|
||||
|
||||
def _int_value_or_none(field: str) -> Callable[[dict[str, Any]], int | None]:
|
||||
"""Value function that will parse the specified field if present."""
|
||||
|
||||
def convert(result: dict[str, Any]) -> int | None:
|
||||
if (value := result["value"].get(field)) is not None:
|
||||
return int(value)
|
||||
return None
|
||||
|
||||
return convert
|
||||
|
||||
|
||||
@dataclass
|
||||
class FitbitSensorEntityDescription(SensorEntityDescription):
|
||||
"""Describes Fitbit sensor entity."""
|
||||
@ -207,7 +218,7 @@ FITBIT_RESOURCES_LIST: Final[tuple[FitbitSensorEntityDescription, ...]] = (
|
||||
name="Resting Heart Rate",
|
||||
native_unit_of_measurement="bpm",
|
||||
icon="mdi:heart-pulse",
|
||||
value_fn=lambda result: int(result["value"]["restingHeartRate"]),
|
||||
value_fn=_int_value_or_none("restingHeartRate"),
|
||||
scope=FitbitScope.HEART_RATE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
|
@ -808,3 +808,60 @@ async def test_device_battery_level_reauth_required(
|
||||
flows = hass.config_entries.flow.async_progress()
|
||||
assert len(flows) == 1
|
||||
assert flows[0]["step_id"] == "reauth_confirm"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("scopes", "response_data", "expected_state"),
|
||||
[
|
||||
(["heartrate"], {}, "unknown"),
|
||||
(
|
||||
["heartrate"],
|
||||
{
|
||||
"restingHeartRate": 120,
|
||||
},
|
||||
"120",
|
||||
),
|
||||
(
|
||||
["heartrate"],
|
||||
{
|
||||
"restingHeartRate": 0,
|
||||
},
|
||||
"0",
|
||||
),
|
||||
],
|
||||
ids=("missing", "valid", "zero"),
|
||||
)
|
||||
async def test_resting_heart_rate_responses(
|
||||
hass: HomeAssistant,
|
||||
setup_credentials: None,
|
||||
integration_setup: Callable[[], Awaitable[bool]],
|
||||
register_timeseries: Callable[[str, dict[str, Any]], None],
|
||||
response_data: dict[str, Any],
|
||||
expected_state: str,
|
||||
) -> None:
|
||||
"""Test resting heart rate sensor with various values from response."""
|
||||
|
||||
register_timeseries(
|
||||
"activities/heart",
|
||||
timeseries_response(
|
||||
"activities-heart",
|
||||
{
|
||||
"customHeartRateZones": [],
|
||||
"heartRateZones": [
|
||||
{
|
||||
"caloriesOut": 0,
|
||||
"max": 220,
|
||||
"min": 159,
|
||||
"minutes": 0,
|
||||
"name": "Peak",
|
||||
},
|
||||
],
|
||||
**response_data,
|
||||
},
|
||||
),
|
||||
)
|
||||
assert await integration_setup()
|
||||
|
||||
state = hass.states.get("sensor.resting_heart_rate")
|
||||
assert state
|
||||
assert state.state == expected_state
|
||||
|
Loading…
x
Reference in New Issue
Block a user