Add usage sensors for each device sense detects that show powe… (#32206)
* init * const * update docs string * update docs string * restore binary sensors * Restore binary sensors * match name * pylint * Fix bug in conf migration * Fix refactoring error * Address review items Imporve performance * Fix devices never turning back offpull/32368/head
parent
3b17e570df
commit
0364cd8db5
|
@ -24,11 +24,13 @@ from .const import (
|
|||
DOMAIN,
|
||||
SENSE_DATA,
|
||||
SENSE_DEVICE_UPDATE,
|
||||
SENSE_DEVICES_DATA,
|
||||
SENSE_DISCOVERED_DEVICES_DATA,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
PLATFORMS = ["sensor", "binary_sensor"]
|
||||
PLATFORMS = ["binary_sensor", "sensor"]
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
{
|
||||
|
@ -44,6 +46,24 @@ CONFIG_SCHEMA = vol.Schema(
|
|||
)
|
||||
|
||||
|
||||
class SenseDevicesData:
|
||||
"""Data for each sense device."""
|
||||
|
||||
def __init__(self):
|
||||
"""Create."""
|
||||
self._data_by_device = {}
|
||||
|
||||
def set_devices_data(self, devices):
|
||||
"""Store a device update."""
|
||||
self._data_by_device = {}
|
||||
for device in devices:
|
||||
self._data_by_device[device["id"]] = device
|
||||
|
||||
def get_device_by_id(self, sense_device_id):
|
||||
"""Get the latest device data."""
|
||||
return self._data_by_device.get(sense_device_id)
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: dict):
|
||||
"""Set up the Sense component."""
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
|
@ -58,7 +78,7 @@ async def async_setup(hass: HomeAssistant, config: dict):
|
|||
data={
|
||||
CONF_EMAIL: conf[CONF_EMAIL],
|
||||
CONF_PASSWORD: conf[CONF_PASSWORD],
|
||||
CONF_TIMEOUT: conf.get[CONF_TIMEOUT],
|
||||
CONF_TIMEOUT: conf[CONF_TIMEOUT],
|
||||
},
|
||||
)
|
||||
)
|
||||
|
@ -84,7 +104,14 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||
except SenseAPITimeoutException:
|
||||
raise ConfigEntryNotReady
|
||||
|
||||
hass.data[DOMAIN][entry.entry_id] = {SENSE_DATA: gateway}
|
||||
sense_devices_data = SenseDevicesData()
|
||||
sense_discovered_devices = await gateway.get_discovered_device_data()
|
||||
|
||||
hass.data[DOMAIN][entry.entry_id] = {
|
||||
SENSE_DATA: gateway,
|
||||
SENSE_DEVICES_DATA: sense_devices_data,
|
||||
SENSE_DISCOVERED_DEVICES_DATA: sense_discovered_devices,
|
||||
}
|
||||
|
||||
for component in PLATFORMS:
|
||||
hass.async_create_task(
|
||||
|
@ -94,14 +121,15 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||
async def async_sense_update(now):
|
||||
"""Retrieve latest state."""
|
||||
try:
|
||||
gateway = hass.data[DOMAIN][entry.entry_id][SENSE_DATA]
|
||||
await gateway.update_realtime()
|
||||
async_dispatcher_send(
|
||||
hass, f"{SENSE_DEVICE_UPDATE}-{gateway.sense_monitor_id}"
|
||||
)
|
||||
except SenseAPITimeoutException:
|
||||
_LOGGER.error("Timeout retrieving data")
|
||||
|
||||
data = gateway.get_realtime()
|
||||
if "devices" in data:
|
||||
sense_devices_data.set_devices_data(data["devices"])
|
||||
async_dispatcher_send(hass, f"{SENSE_DEVICE_UPDATE}-{gateway.sense_monitor_id}")
|
||||
|
||||
hass.data[DOMAIN][entry.entry_id][
|
||||
"track_time_remove_callback"
|
||||
] = async_track_time_interval(
|
||||
|
|
|
@ -2,69 +2,36 @@
|
|||
import logging
|
||||
|
||||
from homeassistant.components.binary_sensor import BinarySensorDevice
|
||||
from homeassistant.const import DEVICE_CLASS_POWER
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity_registry import async_get_registry
|
||||
|
||||
from .const import DOMAIN, SENSE_DATA, SENSE_DEVICE_UPDATE
|
||||
from .const import (
|
||||
DOMAIN,
|
||||
MDI_ICONS,
|
||||
SENSE_DATA,
|
||||
SENSE_DEVICE_UPDATE,
|
||||
SENSE_DEVICES_DATA,
|
||||
SENSE_DISCOVERED_DEVICES_DATA,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ATTR_WATTS = "watts"
|
||||
DEVICE_ID_SOLAR = "solar"
|
||||
BIN_SENSOR_CLASS = "power"
|
||||
MDI_ICONS = {
|
||||
"ac": "air-conditioner",
|
||||
"aquarium": "fish",
|
||||
"car": "car-electric",
|
||||
"computer": "desktop-classic",
|
||||
"cup": "coffee",
|
||||
"dehumidifier": "water-off",
|
||||
"dishes": "dishwasher",
|
||||
"drill": "toolbox",
|
||||
"fan": "fan",
|
||||
"freezer": "fridge-top",
|
||||
"fridge": "fridge-bottom",
|
||||
"game": "gamepad-variant",
|
||||
"garage": "garage",
|
||||
"grill": "stove",
|
||||
"heat": "fire",
|
||||
"heater": "radiatior",
|
||||
"humidifier": "water",
|
||||
"kettle": "kettle",
|
||||
"leafblower": "leaf",
|
||||
"lightbulb": "lightbulb",
|
||||
"media_console": "set-top-box",
|
||||
"modem": "router-wireless",
|
||||
"outlet": "power-socket-us",
|
||||
"papershredder": "shredder",
|
||||
"printer": "printer",
|
||||
"pump": "water-pump",
|
||||
"settings": "settings",
|
||||
"skillet": "pot",
|
||||
"smartcamera": "webcam",
|
||||
"socket": "power-plug",
|
||||
"solar_alt": "solar-power",
|
||||
"sound": "speaker",
|
||||
"stove": "stove",
|
||||
"trash": "trash-can",
|
||||
"tv": "television",
|
||||
"vacuum": "robot-vacuum",
|
||||
"washer": "washing-machine",
|
||||
}
|
||||
|
||||
|
||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||
"""Set up the Sense binary sensor."""
|
||||
data = hass.data[DOMAIN][config_entry.entry_id][SENSE_DATA]
|
||||
sense_devices_data = hass.data[DOMAIN][config_entry.entry_id][SENSE_DEVICES_DATA]
|
||||
sense_monitor_id = data.sense_monitor_id
|
||||
|
||||
sense_devices = await data.get_discovered_device_data()
|
||||
sense_devices = hass.data[DOMAIN][config_entry.entry_id][
|
||||
SENSE_DISCOVERED_DEVICES_DATA
|
||||
]
|
||||
devices = [
|
||||
SenseDevice(data, device, sense_monitor_id)
|
||||
SenseDevice(sense_devices_data, device, sense_monitor_id)
|
||||
for device in sense_devices
|
||||
if device["id"] == DEVICE_ID_SOLAR
|
||||
or device["tags"]["DeviceListAllowed"] == "true"
|
||||
if device["tags"]["DeviceListAllowed"] == "true"
|
||||
]
|
||||
|
||||
await _migrate_old_unique_ids(hass, devices)
|
||||
|
@ -96,20 +63,27 @@ def sense_to_mdi(sense_icon):
|
|||
class SenseDevice(BinarySensorDevice):
|
||||
"""Implementation of a Sense energy device binary sensor."""
|
||||
|
||||
def __init__(self, data, device, sense_monitor_id):
|
||||
def __init__(self, sense_devices_data, device, sense_monitor_id):
|
||||
"""Initialize the Sense binary sensor."""
|
||||
self._name = device["name"]
|
||||
self._id = device["id"]
|
||||
self._sense_monitor_id = sense_monitor_id
|
||||
self._unique_id = f"{sense_monitor_id}-{self._id}"
|
||||
self._icon = sense_to_mdi(device["icon"])
|
||||
self._data = data
|
||||
self._sense_devices_data = sense_devices_data
|
||||
self._undo_dispatch_subscription = None
|
||||
self._state = None
|
||||
self._available = False
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return true if the binary sensor is on."""
|
||||
return self._name in self._data.active_devices
|
||||
return self._state
|
||||
|
||||
@property
|
||||
def available(self):
|
||||
"""Return the availability of the binary sensor."""
|
||||
return self._available
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
|
@ -134,7 +108,7 @@ class SenseDevice(BinarySensorDevice):
|
|||
@property
|
||||
def device_class(self):
|
||||
"""Return the device class of the binary sensor."""
|
||||
return BIN_SENSOR_CLASS
|
||||
return DEVICE_CLASS_POWER
|
||||
|
||||
@property
|
||||
def should_poll(self):
|
||||
|
@ -143,17 +117,20 @@ class SenseDevice(BinarySensorDevice):
|
|||
|
||||
async def async_added_to_hass(self):
|
||||
"""Register callbacks."""
|
||||
|
||||
@callback
|
||||
def update():
|
||||
"""Update the state."""
|
||||
self.async_schedule_update_ha_state(True)
|
||||
|
||||
self._undo_dispatch_subscription = async_dispatcher_connect(
|
||||
self.hass, f"{SENSE_DEVICE_UPDATE}-{self._sense_monitor_id}", update
|
||||
self.hass,
|
||||
f"{SENSE_DEVICE_UPDATE}-{self._sense_monitor_id}",
|
||||
self._async_update_from_data,
|
||||
)
|
||||
|
||||
async def async_will_remove_from_hass(self):
|
||||
"""Undo subscription."""
|
||||
if self._undo_dispatch_subscription:
|
||||
self._undo_dispatch_subscription()
|
||||
|
||||
@callback
|
||||
def _async_update_from_data(self):
|
||||
"""Get the latest data, update state. Must not do I/O."""
|
||||
self._available = True
|
||||
self._state = bool(self._sense_devices_data.get_device_by_id(self._id))
|
||||
self.async_write_ha_state()
|
||||
|
|
|
@ -5,3 +5,55 @@ ACTIVE_UPDATE_RATE = 60
|
|||
DEFAULT_NAME = "Sense"
|
||||
SENSE_DATA = "sense_data"
|
||||
SENSE_DEVICE_UPDATE = "sense_devices_update"
|
||||
SENSE_DEVICES_DATA = "sense_devices_data"
|
||||
SENSE_DISCOVERED_DEVICES_DATA = "sense_discovered_devices"
|
||||
|
||||
ACTIVE_NAME = "Energy"
|
||||
ACTIVE_TYPE = "active"
|
||||
|
||||
CONSUMPTION_NAME = "Usage"
|
||||
CONSUMPTION_ID = "usage"
|
||||
PRODUCTION_NAME = "Production"
|
||||
PRODUCTION_ID = "production"
|
||||
|
||||
ICON = "mdi:flash"
|
||||
|
||||
MDI_ICONS = {
|
||||
"ac": "air-conditioner",
|
||||
"aquarium": "fish",
|
||||
"car": "car-electric",
|
||||
"computer": "desktop-classic",
|
||||
"cup": "coffee",
|
||||
"dehumidifier": "water-off",
|
||||
"dishes": "dishwasher",
|
||||
"drill": "toolbox",
|
||||
"fan": "fan",
|
||||
"freezer": "fridge-top",
|
||||
"fridge": "fridge-bottom",
|
||||
"game": "gamepad-variant",
|
||||
"garage": "garage",
|
||||
"grill": "stove",
|
||||
"heat": "fire",
|
||||
"heater": "radiatior",
|
||||
"humidifier": "water",
|
||||
"kettle": "kettle",
|
||||
"leafblower": "leaf",
|
||||
"lightbulb": "lightbulb",
|
||||
"media_console": "set-top-box",
|
||||
"modem": "router-wireless",
|
||||
"outlet": "power-socket-us",
|
||||
"papershredder": "shredder",
|
||||
"printer": "printer",
|
||||
"pump": "water-pump",
|
||||
"settings": "settings",
|
||||
"skillet": "pot",
|
||||
"smartcamera": "webcam",
|
||||
"socket": "power-plug",
|
||||
"solar_alt": "solar-power",
|
||||
"sound": "speaker",
|
||||
"stove": "stove",
|
||||
"trash": "trash-can",
|
||||
"tv": "television",
|
||||
"vacuum": "robot-vacuum",
|
||||
"washer": "washing-machine",
|
||||
}
|
||||
|
|
|
@ -4,24 +4,32 @@ import logging
|
|||
|
||||
from sense_energy import SenseAPITimeoutException
|
||||
|
||||
from homeassistant.const import ENERGY_KILO_WATT_HOUR, POWER_WATT
|
||||
from homeassistant.const import DEVICE_CLASS_POWER, ENERGY_KILO_WATT_HOUR, POWER_WATT
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.util import Throttle
|
||||
|
||||
from .const import DOMAIN, SENSE_DATA
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ACTIVE_NAME = "Energy"
|
||||
ACTIVE_TYPE = "active"
|
||||
|
||||
CONSUMPTION_NAME = "Usage"
|
||||
|
||||
ICON = "mdi:flash"
|
||||
from .const import (
|
||||
ACTIVE_NAME,
|
||||
ACTIVE_TYPE,
|
||||
CONSUMPTION_ID,
|
||||
CONSUMPTION_NAME,
|
||||
DOMAIN,
|
||||
ICON,
|
||||
MDI_ICONS,
|
||||
PRODUCTION_ID,
|
||||
PRODUCTION_NAME,
|
||||
SENSE_DATA,
|
||||
SENSE_DEVICE_UPDATE,
|
||||
SENSE_DEVICES_DATA,
|
||||
SENSE_DISCOVERED_DEVICES_DATA,
|
||||
)
|
||||
|
||||
MIN_TIME_BETWEEN_DAILY_UPDATES = timedelta(seconds=300)
|
||||
|
||||
PRODUCTION_NAME = "Production"
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SensorConfig:
|
||||
|
@ -34,8 +42,10 @@ class SensorConfig:
|
|||
|
||||
|
||||
# Sensor types/ranges
|
||||
SENSOR_TYPES = {
|
||||
"active": SensorConfig(ACTIVE_NAME, ACTIVE_TYPE),
|
||||
ACTIVE_SENSOR_TYPE = SensorConfig(ACTIVE_NAME, ACTIVE_TYPE)
|
||||
|
||||
# Sensor types/ranges
|
||||
TRENDS_SENSOR_TYPES = {
|
||||
"daily": SensorConfig("Daily", "DAY"),
|
||||
"weekly": SensorConfig("Weekly", "WEEK"),
|
||||
"monthly": SensorConfig("Monthly", "MONTH"),
|
||||
|
@ -43,47 +53,157 @@ SENSOR_TYPES = {
|
|||
}
|
||||
|
||||
# Production/consumption variants
|
||||
SENSOR_VARIANTS = [PRODUCTION_NAME.lower(), CONSUMPTION_NAME.lower()]
|
||||
SENSOR_VARIANTS = [PRODUCTION_ID, CONSUMPTION_ID]
|
||||
|
||||
|
||||
def sense_to_mdi(sense_icon):
|
||||
"""Convert sense icon to mdi icon."""
|
||||
return "mdi:{}".format(MDI_ICONS.get(sense_icon, "power-plug"))
|
||||
|
||||
|
||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||
"""Set up the Sense sensor."""
|
||||
data = hass.data[DOMAIN][config_entry.entry_id][SENSE_DATA]
|
||||
sense_devices_data = hass.data[DOMAIN][config_entry.entry_id][SENSE_DEVICES_DATA]
|
||||
|
||||
@Throttle(MIN_TIME_BETWEEN_DAILY_UPDATES)
|
||||
async def update_trends():
|
||||
"""Update the daily power usage."""
|
||||
await data.update_trend_data()
|
||||
|
||||
async def update_active():
|
||||
"""Update the active power usage."""
|
||||
await data.update_realtime()
|
||||
|
||||
sense_monitor_id = data.sense_monitor_id
|
||||
sense_devices = hass.data[DOMAIN][config_entry.entry_id][
|
||||
SENSE_DISCOVERED_DEVICES_DATA
|
||||
]
|
||||
await data.update_trend_data()
|
||||
|
||||
devices = []
|
||||
for type_id in SENSOR_TYPES:
|
||||
typ = SENSOR_TYPES[type_id]
|
||||
devices = [
|
||||
SenseEnergyDevice(sense_devices_data, device, sense_monitor_id)
|
||||
for device in sense_devices
|
||||
if device["tags"]["DeviceListAllowed"] == "true"
|
||||
]
|
||||
|
||||
for var in SENSOR_VARIANTS:
|
||||
name = ACTIVE_SENSOR_TYPE.name
|
||||
sensor_type = ACTIVE_SENSOR_TYPE.sensor_type
|
||||
is_production = var == PRODUCTION_ID
|
||||
|
||||
unique_id = f"{sense_monitor_id}-active-{var}"
|
||||
devices.append(
|
||||
SenseActiveSensor(
|
||||
data, name, sensor_type, is_production, sense_monitor_id, var, unique_id
|
||||
)
|
||||
)
|
||||
|
||||
for type_id in TRENDS_SENSOR_TYPES:
|
||||
typ = TRENDS_SENSOR_TYPES[type_id]
|
||||
for var in SENSOR_VARIANTS:
|
||||
name = typ.name
|
||||
sensor_type = typ.sensor_type
|
||||
is_production = var == PRODUCTION_NAME.lower()
|
||||
if sensor_type == ACTIVE_TYPE:
|
||||
update_call = update_active
|
||||
else:
|
||||
update_call = update_trends
|
||||
is_production = var == PRODUCTION_ID
|
||||
|
||||
unique_id = f"{sense_monitor_id}-{type_id}-{var}".lower()
|
||||
unique_id = f"{sense_monitor_id}-{type_id}-{var}"
|
||||
devices.append(
|
||||
Sense(
|
||||
data, name, sensor_type, is_production, update_call, var, unique_id
|
||||
SenseTrendsSensor(
|
||||
data,
|
||||
name,
|
||||
sensor_type,
|
||||
is_production,
|
||||
update_trends,
|
||||
var,
|
||||
unique_id,
|
||||
)
|
||||
)
|
||||
|
||||
async_add_entities(devices)
|
||||
|
||||
|
||||
class Sense(Entity):
|
||||
class SenseActiveSensor(Entity):
|
||||
"""Implementation of a Sense energy sensor."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
data,
|
||||
name,
|
||||
sensor_type,
|
||||
is_production,
|
||||
sense_monitor_id,
|
||||
sensor_id,
|
||||
unique_id,
|
||||
):
|
||||
"""Initialize the Sense sensor."""
|
||||
name_type = PRODUCTION_NAME if is_production else CONSUMPTION_NAME
|
||||
self._name = f"{name} {name_type}"
|
||||
self._unique_id = unique_id
|
||||
self._available = False
|
||||
self._data = data
|
||||
self._sense_monitor_id = sense_monitor_id
|
||||
self._sensor_type = sensor_type
|
||||
self._is_production = is_production
|
||||
self._state = None
|
||||
self._undo_dispatch_subscription = None
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the sensor."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
"""Return the state of the sensor."""
|
||||
return self._state
|
||||
|
||||
@property
|
||||
def available(self):
|
||||
"""Return the availability of the sensor."""
|
||||
return self._available
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
"""Return the unit of measurement of this entity, if any."""
|
||||
return POWER_WATT
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
"""Icon to use in the frontend, if any."""
|
||||
return ICON
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
"""Return the unique id."""
|
||||
return self._unique_id
|
||||
|
||||
@property
|
||||
def should_poll(self):
|
||||
"""Return the device should not poll for updates."""
|
||||
return False
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""Register callbacks."""
|
||||
self._undo_dispatch_subscription = async_dispatcher_connect(
|
||||
self.hass,
|
||||
f"{SENSE_DEVICE_UPDATE}-{self._sense_monitor_id}",
|
||||
self._async_update_from_data,
|
||||
)
|
||||
|
||||
async def async_will_remove_from_hass(self):
|
||||
"""Undo subscription."""
|
||||
if self._undo_dispatch_subscription:
|
||||
self._undo_dispatch_subscription()
|
||||
|
||||
@callback
|
||||
def _async_update_from_data(self):
|
||||
"""Update the sensor from the data. Must not do I/O."""
|
||||
self._state = round(
|
||||
self._data.active_solar_power
|
||||
if self._is_production
|
||||
else self._data.active_power
|
||||
)
|
||||
self._available = True
|
||||
self.async_write_ha_state()
|
||||
|
||||
|
||||
class SenseTrendsSensor(Entity):
|
||||
"""Implementation of a Sense energy sensor."""
|
||||
|
||||
def __init__(
|
||||
|
@ -99,11 +219,7 @@ class Sense(Entity):
|
|||
self.update_sensor = update_call
|
||||
self._is_production = is_production
|
||||
self._state = None
|
||||
|
||||
if sensor_type == ACTIVE_TYPE:
|
||||
self._unit_of_measurement = POWER_WATT
|
||||
else:
|
||||
self._unit_of_measurement = ENERGY_KILO_WATT_HOUR
|
||||
self._unit_of_measurement = ENERGY_KILO_WATT_HOUR
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
|
@ -144,13 +260,86 @@ class Sense(Entity):
|
|||
_LOGGER.error("Timeout retrieving data")
|
||||
return
|
||||
|
||||
if self._sensor_type == ACTIVE_TYPE:
|
||||
if self._is_production:
|
||||
self._state = round(self._data.active_solar_power)
|
||||
else:
|
||||
self._state = round(self._data.active_power)
|
||||
else:
|
||||
state = self._data.get_trend(self._sensor_type, self._is_production)
|
||||
self._state = round(state, 1)
|
||||
|
||||
state = self._data.get_trend(self._sensor_type, self._is_production)
|
||||
self._state = round(state, 1)
|
||||
self._available = True
|
||||
|
||||
|
||||
class SenseEnergyDevice(Entity):
|
||||
"""Implementation of a Sense energy device."""
|
||||
|
||||
def __init__(self, sense_devices_data, device, sense_monitor_id):
|
||||
"""Initialize the Sense binary sensor."""
|
||||
self._name = f"{device['name']} {CONSUMPTION_NAME}"
|
||||
self._id = device["id"]
|
||||
self._available = False
|
||||
self._sense_monitor_id = sense_monitor_id
|
||||
self._unique_id = f"{sense_monitor_id}-{self._id}-{CONSUMPTION_ID}"
|
||||
self._icon = sense_to_mdi(device["icon"])
|
||||
self._sense_devices_data = sense_devices_data
|
||||
self._undo_dispatch_subscription = None
|
||||
self._state = None
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
"""Return the wattage of the sensor."""
|
||||
return self._state
|
||||
|
||||
@property
|
||||
def available(self):
|
||||
"""Return the availability of the sensor."""
|
||||
return self._available
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the power sensor."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
"""Return the unique id of the power sensor."""
|
||||
return self._unique_id
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
"""Return the icon of the power sensor."""
|
||||
return self._icon
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
"""Return the unit of measurement of this entity."""
|
||||
return POWER_WATT
|
||||
|
||||
@property
|
||||
def device_class(self):
|
||||
"""Return the device class of the power sensor."""
|
||||
return DEVICE_CLASS_POWER
|
||||
|
||||
@property
|
||||
def should_poll(self):
|
||||
"""Return the device should not poll for updates."""
|
||||
return False
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""Register callbacks."""
|
||||
self._undo_dispatch_subscription = async_dispatcher_connect(
|
||||
self.hass,
|
||||
f"{SENSE_DEVICE_UPDATE}-{self._sense_monitor_id}",
|
||||
self._async_update_from_data,
|
||||
)
|
||||
|
||||
async def async_will_remove_from_hass(self):
|
||||
"""Undo subscription."""
|
||||
if self._undo_dispatch_subscription:
|
||||
self._undo_dispatch_subscription()
|
||||
|
||||
@callback
|
||||
def _async_update_from_data(self):
|
||||
"""Get the latest data, update state. Must not do I/O."""
|
||||
device_data = self._sense_devices_data.get_device_by_id(self._id)
|
||||
if not device_data or "w" not in device_data:
|
||||
self._state = 0
|
||||
else:
|
||||
self._state = int(device_data["w"])
|
||||
self._available = True
|
||||
self.async_write_ha_state()
|
||||
|
|
Loading…
Reference in New Issue