Skip to content

Commit

Permalink
Merge pull request #85 from tykeal/device_linking
Browse files Browse the repository at this point in the history
Feat: Link calendar and sensors to device
  • Loading branch information
tykeal authored Mar 23, 2022
2 parents 464b370 + de8bd5b commit 6064732
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 36 deletions.
47 changes: 43 additions & 4 deletions custom_components/rental_control/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from homeassistant.const import CONF_VERIFY_SSL
from homeassistant.core import HomeAssistant
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers import device_registry as dr
from homeassistant.util import dt

from .const import CONF_CHECKIN
Expand All @@ -44,6 +45,7 @@
from .const import DOMAIN
from .const import PLATFORMS
from .const import REQUEST_TIMEOUT
from .const import VERSION
from .util import gen_uuid

_LOGGER = logging.getLogger(__name__)
Expand All @@ -69,7 +71,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
# hass.data[DOMAIN][entry.entry_id] = MyApi(...)
if DOMAIN not in hass.data:
hass.data[DOMAIN] = {}
hass.data[DOMAIN][entry.unique_id] = ICalEvents(hass=hass, config=config)
hass.data[DOMAIN][entry.unique_id] = ICalEvents(
hass=hass, config=config, unique_id=entry.unique_id
)

for component in PLATFORMS:
hass.async_create_task(
Expand Down Expand Up @@ -151,10 +155,11 @@ class ICalEvents:

# pylint: disable=too-many-instance-attributes

def __init__(self, hass, config):
def __init__(self, hass, config, unique_id):
"""Set up a calendar object."""
self.hass = hass
self.name = config.get(CONF_NAME)
self._name = config.get(CONF_NAME)
self._unique_id = unique_id
self.event_prefix = config.get(CONF_EVENT_PREFIX)
self.url = config.get(CONF_URL)
# Early versions did not have these variables, as such it may not be
Expand Down Expand Up @@ -182,6 +187,40 @@ def __init__(self, hass, config):
self.event = None
self.all_day = False
self.created = config.get(CONF_CREATION_DATETIME, str(dt.now()))
self._version = VERSION

# setup device
device_registry = dr.async_get(hass)
device_registry.async_get_or_create(
config_entry_id=self.unique_id,
identifiers={(DOMAIN, self.unique_id)},
name=self.name,
sw_version=self.version,
)

@property
def device_info(self):
"""Return the device info block."""
return {
"identifiers": {(DOMAIN, self.unique_id)},
"name": self.name,
"sw_version": self.version,
}

@property
def name(self):
"""Return the name."""
return self._name

@property
def unique_id(self):
"""Return the unique id."""
return self._unique_id

@property
def version(self):
"""Return the version."""
return self._version

async def async_get_events(
self, hass, start_date, end_date
Expand Down Expand Up @@ -227,7 +266,7 @@ async def update(self):

def update_config(self, config):
"""Update config entries."""
self.name = config.get(CONF_NAME)
self._name = config.get(CONF_NAME)
self.url = config.get(CONF_URL)
# Early versions did not have these variables, as such it may not be
# set, this should guard against issues until we're certain
Expand Down
29 changes: 22 additions & 7 deletions custom_components/rental_control/calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@

from homeassistant.components.calendar import calculate_offset
from homeassistant.components.calendar import CalendarEventDevice
from homeassistant.components.calendar import ENTITY_ID_FORMAT
from homeassistant.components.calendar import is_offset_reached
from homeassistant.const import CONF_NAME
from homeassistant.helpers.entity import generate_entity_id
from homeassistant.helpers.entity import EntityCategory

from .const import DOMAIN
from .const import NAME
from .util import gen_uuid

_LOGGER = logging.getLogger(__name__)
OFFSET = "!!"
Expand All @@ -22,11 +23,9 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
_LOGGER.debug("Conf: %s", config)
name = config.get(CONF_NAME)

entity_id = generate_entity_id(ENTITY_ID_FORMAT, DOMAIN + " " + name, hass=hass)

rental_control_events = hass.data[DOMAIN][config_entry.unique_id]

calendar = ICalCalendarEventDevice(hass, name, entity_id, rental_control_events)
calendar = ICalCalendarEventDevice(hass, f"{NAME} {name}", rental_control_events)

async_add_entities([calendar], True)

Expand All @@ -35,14 +34,25 @@ class ICalCalendarEventDevice(CalendarEventDevice):
"""A device for getting the next Task from a WebDav Calendar."""

def __init__(
self, hass, name, entity_id, rental_control_events
self, hass, name, rental_control_events
): # pylint: disable=unused-argument
"""Create the iCal Calendar Event Device."""
self.entity_id = entity_id
self._entity_category = EntityCategory.DIAGNOSTIC
self._event = None
self._name = name
self._offset_reached = False
self.rental_control_events = rental_control_events
self._unique_id = gen_uuid(f"{self.rental_control_events.unique_id} calendar")

@property
def device_info(self):
"""Return the device info block."""
return self.rental_control_events.device_info

@property
def entity_category(self):
"""Return the category."""
return self._entity_category

@property
def extra_state_attributes(self):
Expand All @@ -59,6 +69,11 @@ def name(self):
"""Return the name of the entity."""
return self._name

@property
def unique_id(self):
"""Return the unique_id."""
return self._unique_id

async def async_get_events(self, hass, start_date, end_date):
"""Get all events in a specific time frame."""
_LOGGER.debug("Running ICalCalendarEventDevice async get events")
Expand Down
62 changes: 37 additions & 25 deletions custom_components/rental_control/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@

from homeassistant.const import CONF_NAME
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.entity import generate_entity_id
from homeassistant.helpers.entity import EntityCategory

from .const import CONF_MAX_EVENTS
from .const import DOMAIN
from .const import ICON
from .const import NAME
from .util import gen_uuid

_LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -41,7 +43,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
ICalSensor(
hass,
rental_control_events,
DOMAIN + " " + name,
f"{NAME} {name}",
eventnumber,
)
)
Expand All @@ -65,18 +67,13 @@ def __init__(self, hass, rental_control_events, sensor_name, event_number):
sensor_name is typically the name of the calendar.
eventnumber indicates which upcoming event this is, starting at zero
"""
self._event_number = event_number
self._hass = hass
self.rental_control_events = rental_control_events
self._entity_id = generate_entity_id(
"sensor.{}",
f"{sensor_name} event {self._event_number}",
hass=self._hass,
)
if rental_control_events.event_prefix:
summary = f"{rental_control_events.event_prefix} No reservation"
else:
summary = "No reservation"
self._code_generator = rental_control_events.code_generator
self._entity_category = EntityCategory.DIAGNOSTIC
self._event_attributes = {
"summary": summary,
"description": None,
Expand All @@ -87,9 +84,14 @@ def __init__(self, hass, rental_control_events, sensor_name, event_number):
"slot_name": None,
"slot_code": None,
}
self._state = summary
self._event_number = event_number
self._hass = hass
self._is_available = None
self._code_generator = rental_control_events.code_generator
self._name = f"{sensor_name} Event {self._event_number}"
self._state = summary
self._unique_id = gen_uuid(
f"{self.rental_control_events.unique_id} sensor {self._event_number}"
)

def _generate_door_code(self) -> str:
"""Generate a door code based upon the selected type."""
Expand Down Expand Up @@ -175,34 +177,44 @@ def _get_slot_name(self) -> str:
return p.findall(summary)[0]

@property
def entity_id(self):
"""Return the entity_id of the sensor."""
return self._entity_id
def available(self):
"""Return True if ZoneMinder is available."""
return self._event_attributes["start"] is not None

@property
def device_info(self):
"""Return the device info block."""
return self.rental_control_events.device_info

@property
def name(self):
"""Return the name of the sensor."""
return self._event_attributes["summary"]
def entity_category(self):
"""Return the entity category."""
return self._entity_category

@property
def extra_state_attributes(self):
"""Return the attributes of the event."""
return self._event_attributes

@property
def icon(self):
"""Return the icon for the frontend."""
return ICON

@property
def name(self):
"""Return the name of the sensor."""
return self._name

@property
def state(self):
"""Return the date of the next event."""
return self._state

@property
def extra_state_attributes(self):
"""Return the attributes of the event."""
return self._event_attributes

@property
def available(self):
"""Return True if ZoneMinder is available."""
return self._event_attributes["start"] is not None
def unique_id(self):
"""Return the unique_id."""
return self._unique_id

async def async_update(self):
"""Update the sensor."""
Expand Down

0 comments on commit 6064732

Please sign in to comment.