Skip to content

Commit

Permalink
Merge pull request #14 from slajob/main
Browse files Browse the repository at this point in the history
Changes to view and set real blind position and refactor based on HA core requirements
  • Loading branch information
sanjoyg authored Mar 6, 2024
2 parents 49c85a3 + ef8eab0 commit fba4f98
Show file tree
Hide file tree
Showing 18 changed files with 1,074 additions and 713 deletions.
111 changes: 73 additions & 38 deletions custom_components/dirigera_platform/__init__.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,32 @@
"""Platform for IKEA dirigera hub integration."""
from __future__ import annotations
import voluptuous as vol

import asyncio
import logging

import voluptuous as vol

# Import the device class from the component that you want to support
from homeassistant.core import HomeAssistant
from homeassistant import config_entries, core
import homeassistant.helpers.config_validation as cv
from homeassistant.components.light import PLATFORM_SCHEMA
from homeassistant.const import CONF_IP_ADDRESS, CONF_TOKEN

# Import the device class from the component that you want to support
from homeassistant.core import HomeAssistant
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import DeviceInfo

from .const import DOMAIN

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

# Validation of the user's configuration
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_IP_ADDRESS): cv.string,
vol.Required(CONF_TOKEN): cv.string,
})
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_IP_ADDRESS): cv.string,
vol.Required(CONF_TOKEN): cv.string,
}
)


async def async_setup(hass: HomeAssistant, config: dict) -> bool:
logger.debug("Starting async_setup...")
Expand All @@ -29,6 +35,7 @@ async def async_setup(hass: HomeAssistant, config: dict) -> bool:

def handle_dump_data(call):
import dirigera

logger.info("=== START Devices JSON ===")

# we could have multiple hubs set up
Expand All @@ -40,17 +47,20 @@ def handle_dump_data(call):
if ip == "mock":
logger.info("{ MOCK JSON }")
else:
hub = dirigera.Hub(token, ip)
hub = dirigera.Hub(token, ip)
json_resp = hub.get("/devices")
logger.info(json_resp)
logger.info("--------------")

logger.info("=== END Devices JSON ===")
hass.services.async_register(DOMAIN, "dump_data", handle_dump_data)

hass.services.async_register(DOMAIN, "dump_data", handle_dump_data)
return True

async def async_setup_entry(hass: core.HomeAssistant, entry: config_entries.ConfigEntry) -> bool:

async def async_setup_entry(
hass: core.HomeAssistant, entry: config_entries.ConfigEntry
) -> bool:
"""Set up platform from a ConfigEntry."""
logger.debug("Staring async_setup_entry in init...")
logger.debug(dict(entry.data))
Expand All @@ -60,48 +70,68 @@ async def async_setup_entry(hass: core.HomeAssistant, entry: config_entries.Conf

logger.debug("hass_data")
logger.debug(hass_data)

ip = hass_data[CONF_IP_ADDRESS]

# Registers update listener to update config entry when options are updated.
unsub_options_update_listener = entry.add_update_listener(options_update_listener)

# Store a reference to the unsubscribe function to cleanup if an entry is unloaded.
hass_data["unsub_options_update_listener"] = unsub_options_update_listener
hass.data[DOMAIN][entry.entry_id] = hass_data

# Setup the entities
hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, "light"))
hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, "switch"))
hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, "binary_sensor"))
hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, "sensor"))
hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, "cover"))
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, "light")
)
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, "switch")
)
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, "binary_sensor")
)
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, "sensor")
)
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, "cover")
)
hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, "fan"))

logger.debug("Complete async_setup_entry...")

return True

async def options_update_listener(hass: core.HomeAssistant, config_entry: config_entries.ConfigEntry):

async def options_update_listener(
hass: core.HomeAssistant, config_entry: config_entries.ConfigEntry
):
logger.debug("In options_update_listener")
"""Handle options update."""
await hass.config_entries.async_reload(config_entry.entry_id)


async def async_unload_entry(hass: core.HomeAssistant, entry: config_entries.ConfigEntry) -> bool:
async def async_unload_entry(
hass: core.HomeAssistant, entry: config_entries.ConfigEntry
) -> bool:
logger.debug("Starting async_unload_entry")

"""Unload a config entry."""
unload_ok = all(
[await asyncio.gather(
*[hass.config_entries.async_forward_entry_unload(entry, "light"),
hass.config_entries.async_forward_entry_unload(entry, "switch"),
hass.config_entries.async_forward_entry_unload(entry, "binary_sensor"),
hass.config_entries.async_forward_entry_unload(entry, "sensor"),
hass.config_entries.async_forward_entry_unload(entry, "cover"),
hass.config_entries.async_forward_entry_unload(entry, "fan")
]
)]
[
await asyncio.gather(
*[
hass.config_entries.async_forward_entry_unload(entry, "light"),
hass.config_entries.async_forward_entry_unload(entry, "switch"),
hass.config_entries.async_forward_entry_unload(
entry, "binary_sensor"
),
hass.config_entries.async_forward_entry_unload(entry, "sensor"),
hass.config_entries.async_forward_entry_unload(entry, "cover"),
hass.config_entries.async_forward_entry_unload(entry, "fan"),
]
)
]
)
# Remove options_update_listener.
hass.data[DOMAIN][entry.entry_id]["unsub_options_update_listener"]()
Expand All @@ -111,8 +141,13 @@ async def async_unload_entry(hass: core.HomeAssistant, entry: config_entries.Con

return unload_ok

async def async_remove_config_entry_device( hass: HomeAssistant, config_entry: config_entries.ConfigEntry, device_entry: config_entries.DeviceEntry) -> bool:

async def async_remove_config_entry_device(
hass: HomeAssistant,
config_entry: config_entries.ConfigEntry,
device_entry: config_entries.DeviceEntry,
) -> bool:
logger.info("Got request to remove device")
logger.info(config_entry)
logger.info(device_entry)
return True
return True
110 changes: 74 additions & 36 deletions custom_components/dirigera_platform/binary_sensor.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import logging

import dirigera

from homeassistant import config_entries, core
from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
BinarySensorEntity,
)
from homeassistant.const import CONF_IP_ADDRESS, CONF_TOKEN
from homeassistant.core import HomeAssistantError
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.components.binary_sensor import BinarySensorEntity

import dirigera
from .dirigera_lib_patch import HubX

from .const import DOMAIN
from .dirigera_lib_patch import HubX
from .mocks.ikea_motion_sensor_mock import ikea_motion_sensor_mock
from .mocks.ikea_open_close_mock import ikea_open_close_mock

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


async def async_setup_entry(
hass: core.HomeAssistant,
config_entry: config_entries.ConfigEntry,
Expand All @@ -24,91 +29,124 @@ async def async_setup_entry(
config = hass.data[DOMAIN][config_entry.entry_id]
logger.debug(config)

#hub = dirigera.Hub(config[CONF_TOKEN], config[CONF_IP_ADDRESS])
# hub = dirigera.Hub(config[CONF_TOKEN], config[CONF_IP_ADDRESS])
hub = HubX(config[CONF_TOKEN], config[CONF_IP_ADDRESS])

lights = []

# If mock then start with mocks
if config[CONF_IP_ADDRESS] == "mock":
if config[CONF_IP_ADDRESS] == "mock":
logger.warning("Setting up mock motion sensors")
mock_motion_sensor1 = ikea_motion_sensor_mock()
motion_sensors = [mock_motion_sensor1]
motion_sensors = [mock_motion_sensor1]

logger.warning("Setting up mock open/close sensors")
mock_open_close_sensor1 = ikea_open_close_mock()
mock_open_close_sensor2 = ikea_open_close_mock()
open_close_sensors = [mock_open_close_sensor1]
open_close_sensors = [mock_open_close_sensor1]

else:
else:
hub_motion_sensors = await hass.async_add_executor_job(hub.get_motion_sensors)
motion_sensors = [ikea_motion_sensor(hub, motion_sensor) for motion_sensor in hub_motion_sensors]
motion_sensors = [
ikea_motion_sensor(hub, motion_sensor)
for motion_sensor in hub_motion_sensors
]

hub_open_close_sensors = await hass.async_add_executor_job(hub.get_open_close_sensors)
open_close_sensors = [ikea_open_close(hub, open_close_sensor) for open_close_sensor in hub_open_close_sensors]
hub_open_close_sensors = await hass.async_add_executor_job(
hub.get_open_close_sensors
)
open_close_sensors = [
ikea_open_close(hub, open_close_sensor)
for open_close_sensor in hub_open_close_sensors
]

logger.debug("Found {} motion_sensor entities to setup...".format(len(motion_sensors)))
logger.debug(
"Found {} motion_sensor entities to setup...".format(len(motion_sensors))
)
async_add_entities(motion_sensors)
logger.debug("Found {} open close entities to setup...".format(len(open_close_sensors)))
logger.debug(
"Found {} open close entities to setup...".format(len(open_close_sensors))
)
async_add_entities(open_close_sensors)

logger.debug("Binary Sensor Complete async_setup_entry")


class ikea_motion_sensor(BinarySensorEntity):
def __init__(self, hub, json_data):
logger.debug("ikea_motion_sensor ctor...")
self._hub = hub
self._hub = hub
self._json_data = json_data

@property
def unique_id(self):
return self._json_data.id
return self._json_data.id

@property
def available(self):
return self._json_data.is_reachable

@property
def device_info(self) -> DeviceInfo:
return DeviceInfo(
identifiers={("dirigera_platform",self._json_data.id)},
name = self._json_data.attributes.custom_name,
manufacturer = self._json_data.attributes.manufacturer,
model=self._json_data.attributes.model ,
sw_version=self._json_data.attributes.firmware_version
identifiers={("dirigera_platform", self._json_data.id)},
name=self._json_data.attributes.custom_name,
manufacturer=self._json_data.attributes.manufacturer,
model=self._json_data.attributes.model,
sw_version=self._json_data.attributes.firmware_version,
)

@property
def name(self):
return self._json_data.attributes.custom_name
return self._json_data.attributes.custom_name

@property
def is_on(self):
return self._json_data.attributes.is_on

def update(self):
logger.debug("motion sensor update...")
try:
self._json_data = self._hub.get_motion_sensor_by_id(self._json_data.id)
except Exception as ex:
logger.error("error encountered running update on : {}".format(self.name))
logger.error(ex)
raise HomeAssistantError(ex,DOMAIN,"hub_exception")

raise HomeAssistantError(ex, DOMAIN, "hub_exception")


class ikea_open_close(ikea_motion_sensor):
def __init__(self, hub, json_data):
logger.debug("ikea_open_close ctor...")
self._hub = hub
self._hub = hub
self._json_data = json_data


@property
def device_info(self) -> DeviceInfo:
return DeviceInfo(
identifiers={("dirigera_platform", self._json_data.id)},
name=self._json_data.attributes.custom_name,
manufacturer=self._json_data.attributes.manufacturer,
model=self._json_data.attributes.model,
sw_version=self._json_data.attributes.firmware_version,
)

@property
def device_class(self) -> str:
return BinarySensorDeviceClass.WINDOW

@property
def name(self):
return self._json_data.attributes.custom_name

@property
def is_on(self):
return self._json_data.attributes.is_open

def update(self):
logger.debug("open close sensor update...")
try:
self._json_data = self._hub.get_open_close_by_id(self._json_data.id)
except Exception as ex:
logger.error("error encountered running update on : {}".format(self.name))
logger.error(ex)
raise HomeAssistantError(ex,DOMAIN,"hub_exception")

def is_on(self):
return self._json_data.attributes.is_open
raise HomeAssistantError(ex, DOMAIN, "hub_exception")
Loading

0 comments on commit fba4f98

Please sign in to comment.