core/homeassistant/components/surepetcare/sensor.py

135 lines
3.8 KiB
Python

"""Support for Sure PetCare Flaps/Pets sensors."""
import logging
from surepy import SureThingID
from homeassistant.const import (
ATTR_VOLTAGE,
CONF_ID,
CONF_NAME,
CONF_TYPE,
DEVICE_CLASS_BATTERY,
)
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import Entity
from .const import (
DATA_SURE_PETCARE,
SPC,
SURE_BATT_VOLTAGE_DIFF,
SURE_BATT_VOLTAGE_LOW,
TOPIC_UPDATE,
)
_LOGGER = logging.getLogger(__name__)
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Set up Sure PetCare Flaps sensors."""
if discovery_info is None:
return
spc = hass.data[DATA_SURE_PETCARE][SPC]
async_add_entities(
[
FlapBattery(entity[CONF_ID], entity[CONF_NAME], spc)
for entity in spc.ids
if entity[CONF_TYPE] == SureThingID.FLAP.name
],
True,
)
class FlapBattery(Entity):
"""Sure Petcare Flap."""
def __init__(self, _id: int, name: str, spc):
"""Initialize a Sure Petcare Flap battery sensor."""
self._id = _id
self._name = f"Flap {name.capitalize()} Battery Level"
self._spc = spc
self._state = self._spc.states[SureThingID.FLAP.name][self._id].get("data")
self._async_unsub_dispatcher_connect = None
@property
def should_poll(self):
"""Return true."""
return False
@property
def name(self):
"""Return the name of the device if any."""
return self._name
@property
def state(self):
"""Return battery level in percent."""
try:
per_battery_voltage = self._state["battery"] / 4
voltage_diff = per_battery_voltage - SURE_BATT_VOLTAGE_LOW
battery_percent = int(voltage_diff / SURE_BATT_VOLTAGE_DIFF * 100)
except (KeyError, TypeError):
battery_percent = None
return battery_percent
@property
def unique_id(self):
"""Return an unique ID."""
return f"{self._spc.household_id}-{self._id}"
@property
def device_class(self):
"""Return the device class."""
return DEVICE_CLASS_BATTERY
@property
def device_state_attributes(self):
"""Return state attributes."""
attributes = None
if self._state:
try:
voltage_per_battery = float(self._state["battery"]) / 4
attributes = {
ATTR_VOLTAGE: f"{float(self._state['battery']):.2f}",
f"{ATTR_VOLTAGE}_per_battery": f"{voltage_per_battery:.2f}",
}
except (KeyError, TypeError) as error:
attributes = self._state
_LOGGER.error(
"Error getting device state attributes from %s: %s\n\n%s",
self._name,
error,
self._state,
)
return attributes
@property
def unit_of_measurement(self):
"""Return the unit of measurement."""
return "%"
async def async_update(self):
"""Get the latest data and update the state."""
self._state = self._spc.states[SureThingID.FLAP.name][self._id].get("data")
async def async_added_to_hass(self):
"""Register callbacks."""
@callback
def update():
"""Update the state."""
self.async_schedule_update_ha_state(True)
self._async_unsub_dispatcher_connect = async_dispatcher_connect(
self.hass, TOPIC_UPDATE, update
)
async def async_will_remove_from_hass(self):
"""Disconnect dispatcher listener when removed."""
if self._async_unsub_dispatcher_connect:
self._async_unsub_dispatcher_connect()