Skip to content

Commit

Permalink
Changes to support INSPELNING sensor attributes and also fixes to Bat…
Browse files Browse the repository at this point in the history
…tery Sensor
  • Loading branch information
c503ghosh committed Oct 8, 2024
1 parent ed6c472 commit b50b9e5
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 47 deletions.
34 changes: 23 additions & 11 deletions custom_components/dirigera_platform/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ async def async_setup_entry(
hass.data.setdefault(DOMAIN, {})
hass_data = dict(entry.data)

logger.debug(f"hass_data : {hass_data}")
logger.error(f"hass_data : {hass_data}")

# for backward compatibility
hide_device_set_bulbs : bool = True
Expand Down Expand Up @@ -111,11 +111,23 @@ async def async_setup_entry(
hub_events = hub_event_listener(hub, hass)
hub_events.start()

logger.debug("Complete async_setup_entry...")
# Lets get all devices, we do this hear so that the right sensor type can be associated
# Get Lights
from dirigera.devices.motion_sensor import MotionSensor
from dirigera.devices.open_close_sensor import OpenCloseSensor
from dirigera.devices.water_sensor import WaterSensor
from .core.motion_sensor import ikea_motion_sensor_device

hub_motion_sensors : list[MotionSensor] = await hass.async_add_executor_job(hub.get_motion_sensors)
motion_sensor_devices : list[ikea_motion_sensor_device] = [ikea_motion_sensor_device(hass, hub, m) for m in hub_motion_sensors]
logger.error("Found {} motion_sensor entities to setup...".format(len(motion_sensor_devices)))

logger.error("Complete async_setup_entry...")

return True



async def options_update_listener(
hass: core.HomeAssistant, config_entry: config_entries.ConfigEntry
):
Expand All @@ -139,15 +151,15 @@ async def async_unload_entry(
hub = Hub(hass_data[CONF_TOKEN], hass_data[CONF_IP_ADDRESS])

# For each controller if there is an empty scene delete it
logger.error("In unload so forcing delete of scenes...")
scenes: list[DirigeraScene] = await hass.async_add_executor_job(hub.get_scenes)
for scene in scenes:
if scene.info.name is None or not scene.info.name.startswith("dirigera_platform_empty_scene_"):
logger.error(f"Ignoring scene : {scene.info.name}, as not empty scene")
continue
logger.error(f"Deleting scene {scene.id}...")
await hass.async_add_executor_job(hass.delete_scene,scene.id)
logger.error("Done deleting scene....")
#logger.error("In unload so forcing delete of scenes...")
#scenes: list[DirigeraScene] = await hass.async_add_executor_job(hub.get_scenes)
#for scene in scenes:
# if scene.info.name is None or not scene.info.name.startswith("dirigera_platform_empty_scene_"):
# logger.error(f"Ignoring scene : {scene.info.name}, as not empty scene")
# continue
# logger.error(f"Deleting scene {scene.id}...")
# await hass.async_add_executor_job(hass.delete_scene,scene.id)
#logger.error("Done deleting scene....")

"""Unload a config entry."""
unload_ok = all(
Expand Down
4 changes: 3 additions & 1 deletion custom_components/dirigera_platform/base_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from homeassistant.components.datetime import DateTimeEntity
from homeassistant.helpers.entity import DeviceInfo, Entity, EntityCategory
from homeassistant.core import HomeAssistantError
from homeassistant.components.number import NumberEntity, NumberDeviceClass


from .hub_event_listener import hub_event_listener, registry_entry
from .const import DOMAIN
Expand Down Expand Up @@ -158,7 +160,7 @@ def __init__(self, device):
uom="A",
icon="mdi:current-ac",
device_class=SensorDeviceClass.CURRENT)

@property
def native_value(self):
return getattr(self._device, "current_amps")
Expand Down
6 changes: 0 additions & 6 deletions custom_components/dirigera_platform/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
from .const import DOMAIN
from .mocks.ikea_motion_sensor_mock import ikea_motion_sensor_mock
from .mocks.ikea_open_close_mock import ikea_open_close_mock
from .base_classes import battery_percentage_sensor
from .base_classes import ikea_base_device, ikea_base_device_sensor

logger = logging.getLogger("custom_components.dirigera_platform")
Expand All @@ -30,8 +29,6 @@ async def async_setup_entry(
# hub = dirigera.Hub(config[CONF_TOKEN], config[CONF_IP_ADDRESS])
hub = Hub(config[CONF_TOKEN], config[CONF_IP_ADDRESS])

lights = []

# If mock then start with mocks
if config[CONF_IP_ADDRESS] == "mock":
logger.warning("Setting up mock motion sensors")
Expand All @@ -50,7 +47,6 @@ async def async_setup_entry(
motion_sensors = []
for device in motion_sensor_devices:
motion_sensors.append(ikea_motion_sensor(device))
motion_sensors.append(battery_percentage_sensor(device))

logger.debug("Found {} motion_sensor entities to setup...".format(len(motion_sensors)/2))
async_add_entities(motion_sensors)
Expand All @@ -64,7 +60,6 @@ async def async_setup_entry(
open_close_sensors = []
for device in open_close_devices:
open_close_sensors.append(ikea_open_close(device))
open_close_sensors.append(battery_percentage_sensor(device))

logger.debug("Found {} open close entities to setup...".format(len(open_close_sensors)/2))
async_add_entities(open_close_sensors)
Expand All @@ -76,7 +71,6 @@ async def async_setup_entry(

water_sensors = []
for device in water_sensor_devices:
water_sensors.append(battery_percentage_sensor(device))
water_sensors.append(ikea_water_sensor(device))

logger.debug(f"Found {len(hub_water_sensors)/2} water sensors to setup....")
Expand Down
8 changes: 2 additions & 6 deletions custom_components/dirigera_platform/cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

from .const import DOMAIN
from .mocks.ikea_blinds_mock import ikea_blinds_mock
from .base_classes import ikea_base_device, ikea_base_device_sensor, battery_percentage_sensor
from .base_classes import ikea_base_device, ikea_base_device_sensor

logger = logging.getLogger("custom_components.dirigera_platform")

Expand All @@ -29,7 +29,6 @@ async def async_setup_entry(
hub = Hub(config[CONF_TOKEN], config[CONF_IP_ADDRESS])

blinds = []
battery_sensors = []

# If mock then start with mocks
if config[CONF_IP_ADDRESS] == "mock":
Expand All @@ -41,12 +40,9 @@ async def async_setup_entry(
devices = [IkeaBlindsDevice(hass, hub, b) for b in hub_blinds]
for device in devices:
blinds.append(IkeaBlinds(device))
if getattr(device,"battery_percentage",None) is not None:
battery_sensors.append(battery_percentage_sensor(device))


logger.debug("Found {} blinds entities to setup...".format(len(blinds)))
async_add_entities(blinds)
async_add_entities(battery_sensors)
logger.debug("BLINDS Complete async_setup_entry")

class IkeaBlindsDevice(ikea_base_device):
Expand Down
87 changes: 73 additions & 14 deletions custom_components/dirigera_platform/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,23 @@
from dirigera.devices.environment_sensor import EnvironmentSensor
from dirigera.devices.controller import Controller
from dirigera.devices.scene import Info, Icon
from dirigera.devices.outlet import Outlet
from .base_classes import ikea_base_device, battery_percentage_sensor,ikea_base_device_sensor, current_amps_sensor , current_active_power_sensor, current_voltage_sensor, total_energy_consumed_sensor, energy_consumed_at_last_reset_sensor , total_energy_consumed_last_updated_sensor, total_energy_consumed_sensor, time_of_last_energy_reset_sensor
from .switch import ikea_outlet, ikea_outlet_switch_sensor
from dirigera.devices.motion_sensor import MotionSensor
from dirigera.devices.open_close_sensor import OpenCloseSensor
from dirigera.devices.water_sensor import WaterSensor
from .binary_sensor import ikea_motion_sensor, ikea_motion_sensor_device, ikea_open_close_device, ikea_open_close, ikea_water_sensor_device, ikea_water_sensor
from dirigera.devices.blinds import Blind
from .cover import IkeaBlindsDevice, IkeaBlinds

from homeassistant.helpers.entity import Entity
from homeassistant import config_entries, core
from homeassistant.components.sensor import SensorDeviceClass, SensorEntity
from homeassistant.const import CONF_IP_ADDRESS, CONF_TOKEN
from homeassistant.core import HomeAssistantError
from homeassistant.helpers.entity import EntityCategory

from .const import DOMAIN
from .base_classes import ikea_base_device, ikea_base_device_sensor
logger = logging.getLogger("custom_components.dirigera_platform")
Expand All @@ -24,11 +33,11 @@ async def async_setup_entry(
config_entry: config_entries.ConfigEntry,
async_add_entities,
):
logger.debug("EnvSensor & Controllers Starting async_setup_entry")
logger.debug("sensor Starting async_setup_entry")
"""Setup sensors from a config entry created in the integrations UI."""
logger.error("Staring async_setup_entry in SENSOR...")
logger.error(dict(config_entry.data))
logger.error(f"async_setup_entry SENSOR {config_entry.unique_id} {config_entry.state} {config_entry.entry_id} {config_entry.title} {config_entry.domain}")
logger.debug("Staring async_setup_entry in SENSOR...")
logger.debug(dict(config_entry.data))
logger.debug(f"async_setup_entry SENSOR {config_entry.unique_id} {config_entry.state} {config_entry.entry_id} {config_entry.title} {config_entry.domain}")

config = hass.data[DOMAIN][config_entry.entry_id]
logger.debug(config)
Expand Down Expand Up @@ -62,7 +71,7 @@ async def async_setup_entry(
]

hub_controllers = await hass.async_add_executor_job(hub.get_controllers)
logger.error(f"Got {len(hub_controllers)} controllers...")
logger.debug(f"Got {len(hub_controllers)} controllers...")

# Controllers with more one button are returned as spearate controllers
# their uniqueid has _1, _2 suffixes. Only the primary controller has
Expand Down Expand Up @@ -101,7 +110,57 @@ async def async_setup_entry(
async_add_entities(env_sensors)
async_add_entities(controller_devices)

logger.debug("EnvSensor & Controllers Complete async_setup_entry")
# Add sensors for the outlets
hub_outlets : list[Outlet] = await hass.async_add_executor_job(hub.get_outlets)
extra_entities = []

extra_attrs=["current_amps","current_active_power","current_voltage","total_energy_consumed","energy_consumed_at_last_reset","time_of_last_energy_reset","total_energy_consumed_last_updated"]
# Some outlets like INSPELNING Smart plug have ability to report power, so add those as well
logger.debug("Looking for extra attributes of power/current/voltage in outlet....")
for hub_outlet in hub_outlets:
outlet = ikea_outlet(hass, hub, hub_outlet)
for attr in extra_attrs:
if getattr(hub_outlet.attributes,attr) is not None:
extra_entities.append(eval(f"{attr}_sensor(outlet)"))

logger.debug(f"Found {len(extra_entities)}, power attribute sensors for outlets")
async_add_entities(extra_entities)

# Add battery sensors
battery_sensors = []

hub_motion_sensors : list[MotionSensor] = await hass.async_add_executor_job(hub.get_motion_sensors)
motion_sensor_devices : list[ikea_motion_sensor_device] = [ikea_motion_sensor_device(hass, hub, m) for m in hub_motion_sensors]

for device in motion_sensor_devices:
battery_sensors.append(battery_percentage_sensor(device))

hub_open_close_sensors : list[OpenCloseSensor] = await hass.async_add_executor_job(hub.get_open_close_sensors)
open_close_devices : list[ikea_open_close_device] = [
ikea_open_close_device(hass, hub, open_close_sensor)
for open_close_sensor in hub_open_close_sensors
]

for device in open_close_devices:
battery_sensors.append(battery_percentage_sensor(device))

hub_water_sensors : list[WaterSensor] = await hass.async_add_executor_job(hub.get_water_sensors)
water_sensor_devices = [ ikea_water_sensor_device(hass, hub, hub_water_sensor)
for hub_water_sensor in hub_water_sensors
]

for device in water_sensor_devices:
battery_sensors.append(battery_percentage_sensor(device))

hub_blinds = await hass.async_add_executor_job(hub.get_blinds)
devices = [IkeaBlindsDevice(hass, hub, b) for b in hub_blinds]
for device in devices:
if getattr(device,"battery_percentage",None) is not None:
battery_sensors.append(battery_percentage_sensor(device))

logger.debug(f"Found {len(battery_sensors)} battery sensors...")
async_add_entities(battery_sensors)
logger.debug("sensor Complete async_setup_entry")

class ikea_vindstyrka_device(ikea_base_device):
def __init__(self, hass:core.HomeAssistant, hub:Hub , json_data:EnvironmentSensor) -> None:
Expand All @@ -123,7 +182,7 @@ async def async_update(self):

class ikea_vindstyrka_temperature(ikea_base_device_sensor, SensorEntity):
def __init__(self, device: ikea_vindstyrka_device) -> None:
super().__init__(device, id_suffix="TEMP", name_suffix="Temperature")
super().__init__(device, id_suffix="TEMP", name="Temperature")
logger.debug("ikea_vindstyrka_temperature ctor...")

@property
Expand All @@ -145,7 +204,7 @@ def state_class(self) -> str:
class ikea_vindstyrka_humidity(ikea_base_device_sensor, SensorEntity):
def __init__(self, device: ikea_vindstyrka_device) -> None:
logger.debug("ikea_vindstyrka_humidity ctor...")
super().__init__(device, id_suffix="HUM", name_suffix="Humidity")
super().__init__(device, id_suffix="HUM", name="Humidity")

@property
def device_class(self):
Expand Down Expand Up @@ -174,15 +233,15 @@ def __init__(
name_suffix = " "
if self._pm25_type == WhichPM25.CURRENT:
id_suffix = "CURPM25"
name_suffix = "Current PM2.5"
name = "Current PM2.5"
if self._pm25_type == WhichPM25.MAX:
id_suffix = "MAXPM25"
name_suffix = "Max Measured PM2.5"
name = "Max Measured PM2.5"
if self._pm25_type == WhichPM25.MIN:
id_suffix = "MINPM25"
name_suffix = "Min Measured PM2.5"
name = "Min Measured PM2.5"

super().__init__(device, id_suffix=id_suffix, name_suffix=name_suffix)
super().__init__(device, id_suffix=id_suffix, name=name_suffix)

@property
def device_class(self):
Expand All @@ -206,7 +265,7 @@ def native_unit_of_measurement(self) -> str:
class ikea_vindstyrka_voc_index(ikea_base_device_sensor, SensorEntity):
def __init__(self, device: ikea_vindstyrka_device) -> None:
logger.debug("ikea_vindstyrka_voc_index ctor...")
super().__init__(device, id_suffix="VOC", name_suffix="VOC Index")
super().__init__(device, id_suffix="VOC", name="VOC Index")

@property
def device_class(self):
Expand Down
31 changes: 22 additions & 9 deletions custom_components/dirigera_platform/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

from .const import DOMAIN
from .mocks.ikea_outlet_mock import ikea_outlet_mock
from .base_classes import ikea_base_device, current_amps_sensor , current_active_power_sensor, current_voltage_sensor, total_energy_consumed_sensor, energy_consumed_at_last_reset_sensor , total_energy_consumed_last_updated_sensor, total_energy_consumed_sensor, time_of_last_energy_reset_sensor
from .base_classes import ikea_base_device, ikea_base_device_sensor, current_amps_sensor , current_active_power_sensor, current_voltage_sensor, total_energy_consumed_sensor, energy_consumed_at_last_reset_sensor , total_energy_consumed_last_updated_sensor, total_energy_consumed_sensor, time_of_last_energy_reset_sensor
logger = logging.getLogger("custom_components.dirigera_platform")


Expand Down Expand Up @@ -42,10 +42,11 @@ async def async_setup_entry(
logger.debug("Looking for extra attributes of power/current/voltage in outlet....")
for hub_outlet in hub_outlets:
outlet = ikea_outlet(hass, hub, hub_outlet)
outlets.append(outlet)
for attr in extra_attrs:
if getattr(hub_outlet.attributes,attr) is not None:
extra_entities.append(eval(f"{attr}_sensor(outlet)"))
switch_sensor = ikea_outlet_switch_sensor(outlet)
outlets.append(switch_sensor)
#for attr in extra_attrs:
#if getattr(hub_outlet.attributes,attr) is not None:
#extra_entities.append(eval(f"{attr}_sensor(outlet)"))

logger.debug("Found {} outlet entities to setup...".format(len(outlets)))
async_add_entities(outlets)
Expand All @@ -55,14 +56,14 @@ async def async_setup_entry(

logger.debug("SWITCH Complete async_setup_entry")

class ikea_outlet(ikea_base_device, SwitchEntity):
class ikea_outlet(ikea_base_device):
def __init__(self, hass, hub, json_data):
super().__init__(hass, hub, json_data, hub.get_outlet_by_id)

async def async_turn_on(self):
logger.debug("outlet turn_on")
try:
await self.hass.async_add_executor_job(self._json_data.set_on, True)
await self._hass.async_add_executor_job(self._json_data.set_on, True)
except Exception as ex:
logger.error("error encountered turning on : {}".format(self.name))
logger.error(ex)
Expand All @@ -71,8 +72,20 @@ async def async_turn_on(self):
async def async_turn_off(self):
logger.debug("outlet turn_off")
try:
await self.hass.async_add_executor_job(self._json_data.set_on, False)
await self._hass.async_add_executor_job(self._json_data.set_on, False)
except Exception as ex:
logger.error("error encountered turning off : {}".format(self.name))
logger.error(ex)
raise HomeAssistantError(ex, DOMAIN, "hub_exception")
raise HomeAssistantError(ex, DOMAIN, "hub_exception")

class ikea_outlet_switch_sensor(ikea_base_device_sensor, SwitchEntity):
def __init__(self, device):
super().__init__(device = device, name = device.name )

async def async_turn_on(self):
logger.debug("sensor: outlet turn_on")
await self._device.async_turn_on()

async def async_turn_off(self):
logger.debug("sensor: outlet turn_off")
await self._device.async_turn_off()

0 comments on commit b50b9e5

Please sign in to comment.