mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 20:57:21 +00:00
Add next alarm time sensor to Garmin (#40420)
* Add sensor for garmin next alarm(s) * code-review changes * type fix * linter fix * review fixes
This commit is contained in:
parent
e997e3a2eb
commit
af048715f0
@ -304,6 +304,7 @@ omit =
|
||||
homeassistant/components/garmin_connect/__init__.py
|
||||
homeassistant/components/garmin_connect/const.py
|
||||
homeassistant/components/garmin_connect/sensor.py
|
||||
homeassistant/components/garmin_connect/alarm_util.py
|
||||
homeassistant/components/gc100/*
|
||||
homeassistant/components/geniushub/*
|
||||
homeassistant/components/geizhals/sensor.py
|
||||
|
@ -90,6 +90,17 @@ class GarminConnectData:
|
||||
self.client = client
|
||||
self.data = None
|
||||
|
||||
async def _get_combined_alarms_of_all_devices(self):
|
||||
"""Combine the list of active alarms from all garmin devices."""
|
||||
alarms = []
|
||||
devices = await self.hass.async_add_executor_job(self.client.get_devices)
|
||||
for device in devices:
|
||||
device_settings = await self.hass.async_add_executor_job(
|
||||
self.client.get_device_settings, device["deviceId"]
|
||||
)
|
||||
alarms += device_settings["alarms"]
|
||||
return alarms
|
||||
|
||||
@Throttle(MIN_SCAN_INTERVAL)
|
||||
async def async_update(self):
|
||||
"""Update data via library."""
|
||||
@ -99,6 +110,7 @@ class GarminConnectData:
|
||||
self.data = await self.hass.async_add_executor_job(
|
||||
self.client.get_stats_and_body, today.isoformat()
|
||||
)
|
||||
self.data["nextAlarm"] = await self._get_combined_alarms_of_all_devices()
|
||||
except (
|
||||
GarminConnectAuthenticationError,
|
||||
GarminConnectTooManyRequestsError,
|
||||
|
50
homeassistant/components/garmin_connect/alarm_util.py
Normal file
50
homeassistant/components/garmin_connect/alarm_util.py
Normal file
@ -0,0 +1,50 @@
|
||||
"""Utility method for converting Garmin Connect alarms to python datetime."""
|
||||
from datetime import date, datetime, timedelta
|
||||
import logging
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DAY_TO_NUMBER = {
|
||||
"Mo": 1,
|
||||
"M": 1,
|
||||
"Tu": 2,
|
||||
"We": 3,
|
||||
"W": 3,
|
||||
"Th": 4,
|
||||
"Fr": 5,
|
||||
"F": 5,
|
||||
"Sa": 6,
|
||||
"Su": 7,
|
||||
}
|
||||
|
||||
|
||||
def calculate_next_active_alarms(alarms):
|
||||
"""
|
||||
Calculate garmin next active alarms from settings.
|
||||
|
||||
Alarms are sorted by time
|
||||
"""
|
||||
active_alarms = []
|
||||
_LOGGER.debug(alarms)
|
||||
|
||||
for alarm_setting in alarms:
|
||||
if alarm_setting["alarmMode"] != "ON":
|
||||
continue
|
||||
for day in alarm_setting["alarmDays"]:
|
||||
alarm_time = alarm_setting["alarmTime"]
|
||||
if day == "ONCE":
|
||||
midnight = datetime.combine(date.today(), datetime.min.time())
|
||||
alarm = midnight + timedelta(minutes=alarm_time)
|
||||
if alarm < datetime.now():
|
||||
alarm += timedelta(days=1)
|
||||
else:
|
||||
start_of_week = datetime.combine(
|
||||
date.today() - timedelta(days=datetime.today().isoweekday() % 7),
|
||||
datetime.min.time(),
|
||||
)
|
||||
days_to_add = DAY_TO_NUMBER[day] % 7
|
||||
alarm = start_of_week + timedelta(minutes=alarm_time, days=days_to_add)
|
||||
if alarm < datetime.now():
|
||||
alarm += timedelta(days=7)
|
||||
active_alarms.append(alarm.isoformat())
|
||||
return sorted(active_alarms) if active_alarms else None
|
@ -348,4 +348,5 @@ GARMIN_ENTITY_LIST = {
|
||||
"physiqueRating": ["Physique Rating", "", "mdi:numeric", None, False],
|
||||
"visceralFat": ["Visceral Fat", "", "mdi:food", None, False],
|
||||
"metabolicAge": ["Metabolic Age", "", "mdi:calendar-heart", None, False],
|
||||
"nextAlarm": ["Next Alarm Time", "", "mdi:alarm", DEVICE_CLASS_TIMESTAMP, True],
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
"domain": "garmin_connect",
|
||||
"name": "Garmin Connect",
|
||||
"documentation": "https://www.home-assistant.io/integrations/garmin_connect",
|
||||
"requirements": ["garminconnect==0.1.13"],
|
||||
"requirements": ["garminconnect==0.1.16"],
|
||||
"codeowners": ["@cyberjunky"],
|
||||
"config_flow": true
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ from homeassistant.const import ATTR_ATTRIBUTION, CONF_ID
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
|
||||
from .alarm_util import calculate_next_active_alarms
|
||||
from .const import ATTRIBUTION, DOMAIN, GARMIN_ENTITY_LIST
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@ -123,11 +124,16 @@ class GarminConnectSensor(Entity):
|
||||
"""Return attributes for sensor."""
|
||||
if not self._data.data:
|
||||
return {}
|
||||
return {
|
||||
attributes = {
|
||||
"source": self._data.data["source"],
|
||||
"last_synced": self._data.data["lastSyncTimestampGMT"],
|
||||
ATTR_ATTRIBUTION: ATTRIBUTION,
|
||||
}
|
||||
if self._type == "nextAlarm":
|
||||
attributes["next_alarms"] = calculate_next_active_alarms(
|
||||
self._data.data[self._type]
|
||||
)
|
||||
return attributes
|
||||
|
||||
@property
|
||||
def device_info(self) -> Dict[str, Any]:
|
||||
@ -177,6 +183,12 @@ class GarminConnectSensor(Entity):
|
||||
self._type == "bodyFat" or self._type == "bodyWater" or self._type == "bmi"
|
||||
):
|
||||
self._state = round(data[self._type], 2)
|
||||
elif self._type == "nextAlarm":
|
||||
active_alarms = calculate_next_active_alarms(data[self._type])
|
||||
if active_alarms:
|
||||
self._state = active_alarms[0]
|
||||
else:
|
||||
self._available = False
|
||||
else:
|
||||
self._state = data[self._type]
|
||||
|
||||
|
@ -622,7 +622,7 @@ fritzconnection==1.2.0
|
||||
gTTS-token==1.1.3
|
||||
|
||||
# homeassistant.components.garmin_connect
|
||||
garminconnect==0.1.13
|
||||
garminconnect==0.1.16
|
||||
|
||||
# homeassistant.components.geizhals
|
||||
geizhals==0.0.9
|
||||
|
@ -305,7 +305,7 @@ foobot_async==0.3.2
|
||||
gTTS-token==1.1.3
|
||||
|
||||
# homeassistant.components.garmin_connect
|
||||
garminconnect==0.1.13
|
||||
garminconnect==0.1.16
|
||||
|
||||
# homeassistant.components.geo_json_events
|
||||
# homeassistant.components.usgs_earthquakes_feed
|
||||
|
Loading…
x
Reference in New Issue
Block a user