core/homeassistant/components/garmin_connect/sensor.py

186 lines
5.2 KiB
Python

"""Platform for Garmin Connect integration."""
import logging
from typing import Any, Dict
from garminconnect import (
GarminConnectAuthenticationError,
GarminConnectConnectionError,
GarminConnectTooManyRequestsError,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_ATTRIBUTION, CONF_ID
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.typing import HomeAssistantType
from .const import ATTRIBUTION, DOMAIN, GARMIN_ENTITY_LIST
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry(
hass: HomeAssistantType, entry: ConfigEntry, async_add_entities
) -> None:
"""Set up Garmin Connect sensor based on a config entry."""
garmin_data = hass.data[DOMAIN][entry.entry_id]
unique_id = entry.data[CONF_ID]
try:
await garmin_data.async_update()
except (
GarminConnectConnectionError,
GarminConnectAuthenticationError,
GarminConnectTooManyRequestsError,
) as err:
_LOGGER.error("Error occurred during Garmin Connect Client update: %s", err)
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Unknown error occurred during Garmin Connect Client update")
entities = []
for (
sensor_type,
(name, unit, icon, device_class, enabled_by_default),
) in GARMIN_ENTITY_LIST.items():
_LOGGER.debug(
"Registering entity: %s, %s, %s, %s, %s, %s",
sensor_type,
name,
unit,
icon,
device_class,
enabled_by_default,
)
entities.append(
GarminConnectSensor(
garmin_data,
unique_id,
sensor_type,
name,
unit,
icon,
device_class,
enabled_by_default,
)
)
async_add_entities(entities, True)
class GarminConnectSensor(Entity):
"""Representation of a Garmin Connect Sensor."""
def __init__(
self,
data,
unique_id,
sensor_type,
name,
unit,
icon,
device_class,
enabled_default: bool = True,
):
"""Initialize."""
self._data = data
self._unique_id = unique_id
self._type = sensor_type
self._name = name
self._unit = unit
self._icon = icon
self._device_class = device_class
self._enabled_default = enabled_default
self._available = True
self._state = None
@property
def name(self):
"""Return the name of the sensor."""
return self._name
@property
def icon(self):
"""Return the icon to use in the frontend."""
return self._icon
@property
def state(self):
"""Return the state of the sensor."""
return self._state
@property
def unique_id(self) -> str:
"""Return the unique ID for this sensor."""
return f"{self._unique_id}_{self._type}"
@property
def unit_of_measurement(self):
"""Return the unit of measurement."""
return self._unit
@property
def device_state_attributes(self):
"""Return attributes for sensor."""
if not self._data.data:
return {}
return {
"source": self._data.data["source"],
"last_synced": self._data.data["lastSyncTimestampGMT"],
ATTR_ATTRIBUTION: ATTRIBUTION,
}
@property
def device_info(self) -> Dict[str, Any]:
"""Return device information."""
return {
"identifiers": {(DOMAIN, self._unique_id)},
"name": "Garmin Connect",
"manufacturer": "Garmin Connect",
}
@property
def entity_registry_enabled_default(self) -> bool:
"""Return if the entity should be enabled when first added to the entity registry."""
return self._enabled_default
@property
def available(self) -> bool:
"""Return True if entity is available."""
return self._available
@property
def device_class(self):
"""Return the device class of the sensor."""
return self._device_class
async def async_update(self):
"""Update the data from Garmin Connect."""
if not self.enabled:
return
await self._data.async_update()
data = self._data.data
if not data:
_LOGGER.error("Didn't receive data from Garmin Connect")
return
if data.get(self._type) is None:
_LOGGER.debug("Entity type %s not set in fetched data", self._type)
self._available = False
return
self._available = True
if "Duration" in self._type or "Seconds" in self._type:
self._state = data[self._type] // 60
elif "Mass" in self._type or self._type == "weight":
self._state = round((data[self._type] / 1000), 2)
elif (
self._type == "bodyFat" or self._type == "bodyWater" or self._type == "bmi"
):
self._state = round(data[self._type], 2)
else:
self._state = data[self._type]
_LOGGER.debug(
"Entity %s set to state %s %s", self._type, self._state, self._unit
)