Add battery sensor to iCloud (#29818)
* Add battery sensor to iCloud * Update .coveragerc * Review: @balloob & @MartinHjelmare * Review: use f string
This commit is contained in:
parent
003658a3f0
commit
820780996a
5 changed files with 104 additions and 20 deletions
|
@ -321,6 +321,7 @@ omit =
|
|||
homeassistant/components/iaqualink/switch.py
|
||||
homeassistant/components/icloud/__init__.py
|
||||
homeassistant/components/icloud/device_tracker.py
|
||||
homeassistant/components/icloud/sensor.py
|
||||
homeassistant/components/izone/climate.py
|
||||
homeassistant/components/izone/discovery.py
|
||||
homeassistant/components/izone/__init__.py
|
||||
|
|
|
@ -560,11 +560,6 @@ class IcloudDevice:
|
|||
"""Return a unique ID."""
|
||||
return self._device_id
|
||||
|
||||
@property
|
||||
def dev_id(self) -> str:
|
||||
"""Return the device ID."""
|
||||
return self._device_id
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""Return the Apple device name."""
|
||||
|
|
|
@ -14,8 +14,7 @@ DEFAULT_GPS_ACCURACY_THRESHOLD = 500 # meters
|
|||
STORAGE_KEY = DOMAIN
|
||||
STORAGE_VERSION = 1
|
||||
|
||||
# Next PR will add sensor
|
||||
ICLOUD_COMPONENTS = ["device_tracker"]
|
||||
ICLOUD_COMPONENTS = ["device_tracker", "sensor"]
|
||||
|
||||
# pyicloud.AppleDevice status
|
||||
DEVICE_BATTERY_LEVEL = "batteryLevel"
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
"""Support for tracking for iCloud devices."""
|
||||
import logging
|
||||
from typing import Dict
|
||||
|
||||
from homeassistant.components.device_tracker import SOURCE_TYPE_GPS
|
||||
from homeassistant.components.device_tracker.config_entry import TrackerEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_USERNAME
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
|
@ -26,13 +28,15 @@ async def async_setup_scanner(
|
|||
pass
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistantType, entry, async_add_entities):
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistantType, entry: ConfigEntry, async_add_entities
|
||||
):
|
||||
"""Configure a dispatcher connection based on a config entry."""
|
||||
username = entry.data[CONF_USERNAME]
|
||||
|
||||
for device in hass.data[DOMAIN][username].devices.values():
|
||||
if device.location is None:
|
||||
_LOGGER.debug("No position found for device %s", device.name)
|
||||
_LOGGER.debug("No position found for %s", device.name)
|
||||
continue
|
||||
|
||||
_LOGGER.debug("Adding device_tracker for %s", device.name)
|
||||
|
@ -49,12 +53,12 @@ class IcloudTrackerEntity(TrackerEntity):
|
|||
self._unsub_dispatcher = None
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
def unique_id(self) -> str:
|
||||
"""Return a unique ID."""
|
||||
return f"{self._device.unique_id}_tracker"
|
||||
return self._device.unique_id
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
def name(self) -> str:
|
||||
"""Return the name of the device."""
|
||||
return self._device.name
|
||||
|
||||
|
@ -74,36 +78,36 @@ class IcloudTrackerEntity(TrackerEntity):
|
|||
return self._device.location[DEVICE_LOCATION_LONGITUDE]
|
||||
|
||||
@property
|
||||
def should_poll(self):
|
||||
def should_poll(self) -> bool:
|
||||
"""No polling needed."""
|
||||
return False
|
||||
|
||||
@property
|
||||
def battery_level(self):
|
||||
def battery_level(self) -> int:
|
||||
"""Return the battery level of the device."""
|
||||
return self._device.battery_level
|
||||
|
||||
@property
|
||||
def source_type(self):
|
||||
def source_type(self) -> str:
|
||||
"""Return the source type, eg gps or router, of the device."""
|
||||
return SOURCE_TYPE_GPS
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
def icon(self) -> str:
|
||||
"""Return the icon."""
|
||||
return icon_for_icloud_device(self._device)
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
def device_state_attributes(self) -> Dict[str, any]:
|
||||
"""Return the device state attributes."""
|
||||
return self._device.state_attributes
|
||||
|
||||
@property
|
||||
def device_info(self):
|
||||
def device_info(self) -> Dict[str, any]:
|
||||
"""Return the device information."""
|
||||
return {
|
||||
"identifiers": {(DOMAIN, self.unique_id)},
|
||||
"name": self.name,
|
||||
"identifiers": {(DOMAIN, self._device.unique_id)},
|
||||
"name": self._device.name,
|
||||
"manufacturer": "Apple",
|
||||
"model": self._device.device_model,
|
||||
}
|
||||
|
|
85
homeassistant/components/icloud/sensor.py
Normal file
85
homeassistant/components/icloud/sensor.py
Normal file
|
@ -0,0 +1,85 @@
|
|||
"""Support for iCloud sensors."""
|
||||
import logging
|
||||
from typing import Dict
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_USERNAME, DEVICE_CLASS_BATTERY
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.icon import icon_for_battery_level
|
||||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
|
||||
from . import IcloudDevice
|
||||
from .const import DOMAIN
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistantType, entry: ConfigEntry, async_add_entities
|
||||
) -> None:
|
||||
"""Set up iCloud devices sensors based on a config entry."""
|
||||
username = entry.data[CONF_USERNAME]
|
||||
|
||||
entities = []
|
||||
for device in hass.data[DOMAIN][username].devices.values():
|
||||
if device.battery_level is not None:
|
||||
_LOGGER.debug("Adding battery sensor for %s", device.name)
|
||||
entities.append(IcloudDeviceBatterySensor(device))
|
||||
|
||||
async_add_entities(entities, True)
|
||||
|
||||
|
||||
class IcloudDeviceBatterySensor(Entity):
|
||||
"""Representation of a iCloud device battery sensor."""
|
||||
|
||||
def __init__(self, device: IcloudDevice):
|
||||
"""Initialize the battery sensor."""
|
||||
self._device = device
|
||||
|
||||
@property
|
||||
def unique_id(self) -> str:
|
||||
"""Return a unique ID."""
|
||||
return f"{self._device.unique_id}_battery"
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""Sensor name."""
|
||||
return f"{self._device.name} battery state"
|
||||
|
||||
@property
|
||||
def device_class(self) -> str:
|
||||
"""Return the device class of the sensor."""
|
||||
return DEVICE_CLASS_BATTERY
|
||||
|
||||
@property
|
||||
def state(self) -> int:
|
||||
"""Battery state percentage."""
|
||||
return self._device.battery_level
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self) -> str:
|
||||
"""Battery state measured in percentage."""
|
||||
return "%"
|
||||
|
||||
@property
|
||||
def icon(self) -> str:
|
||||
"""Battery state icon handling."""
|
||||
return icon_for_battery_level(
|
||||
battery_level=self._device.battery_level,
|
||||
charging=self._device.battery_status == "Charging",
|
||||
)
|
||||
|
||||
@property
|
||||
def device_state_attributes(self) -> Dict[str, any]:
|
||||
"""Return default attributes for the iCloud device entity."""
|
||||
return self._device.state_attributes
|
||||
|
||||
@property
|
||||
def device_info(self) -> Dict[str, any]:
|
||||
"""Return the device information."""
|
||||
return {
|
||||
"identifiers": {(DOMAIN, self._device.unique_id)},
|
||||
"name": self._device.name,
|
||||
"manufacturer": "Apple",
|
||||
"model": self._device.device_model,
|
||||
}
|
Loading…
Add table
Reference in a new issue