Skip to content

Commit

Permalink
Create entities for unused device attributes
Browse files Browse the repository at this point in the history
Many hubitat devices may have "unused" attributes -- attributes not
handled by any existing entity class. Create disabled generic sensor
entities for these unused attributes. Users may enable these entites and
customize them using HA's customization functionality.
  • Loading branch information
jason0x43 committed Jun 20, 2022
1 parent 1937828 commit a000712
Show file tree
Hide file tree
Showing 13 changed files with 208 additions and 32 deletions.
18 changes: 17 additions & 1 deletion custom_components/hubitat/alarm_control_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
)
from hubitatmaker.types import Device
from logging import getLogger
from typing import Any, Dict, List, Optional
from typing import Any, Dict, List, Optional, Sequence

from homeassistant.components.alarm_control_panel import (
SUPPORT_ALARM_ARM_AWAY,
Expand Down Expand Up @@ -60,10 +60,26 @@

_LOGGER = getLogger(__name__)

_device_attrs = (
HE_ATTR_ALARM,
HE_ATTR_CODE_CHANGED,
HE_ATTR_CODE_LENGTH,
HE_ATTR_ENTRY_DELAY,
HE_ATTR_EXIT_DELAY,
HE_ATTR_LOCK_CODES,
HE_ATTR_MAX_CODES,
HE_ATTR_SECURITY_KEYPAD,
)


class HubitatSecurityKeypad(HubitatEntity, AlarmControlPanelEntity):
"""Representation of a Hubitat security keypad."""

@property
def device_attrs(self) -> Optional[Sequence[str]]:
"""Return this entity's associated attributes"""
return _device_attrs

@property
def alarm(self) -> Optional[str]:
"""Alarm status."""
Expand Down
7 changes: 6 additions & 1 deletion custom_components/hubitat/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
Device,
)
import re
from typing import Dict, List, Optional, Tuple, Type
from typing import Dict, List, Optional, Sequence, Tuple, Type

from homeassistant.components.binary_sensor import (
DEVICE_CLASS_CONNECTIVITY,
Expand Down Expand Up @@ -48,6 +48,11 @@ class HubitatBinarySensor(HubitatEntity, BinarySensorEntity):
_attribute: str
_device_class: str

@property
def device_attrs(self) -> Optional[Sequence[str]]:
"""Return this entity's associated attributes"""
return (self._attribute,)

@property
def is_on(self) -> bool:
"""Return True if this sensor is on/active."""
Expand Down
20 changes: 19 additions & 1 deletion custom_components/hubitat/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
CMD_SET_HEATING_SETPOINT,
Device,
)
from typing import Any, Dict, List, Optional
from typing import Any, Dict, List, Optional, Sequence

from custom_components.hubitat.const import TEMP_C, TEMP_F

Expand Down Expand Up @@ -110,10 +110,28 @@
FAN_MODE_CIRCULATE = "circulate"
HASS_FAN_MODES = [FAN_ON, FAN_AUTO]

_device_attrs = (
ATTR_COOLING_SETPOINT,
ATTR_FAN_MODE,
ATTR_HEATING_SETPOINT,
ATTR_HUMIDITY,
ATTR_MODE,
ATTR_NEST_MODE,
ATTR_OPERATING_STATE,
ATTR_PRESENCE,
ATTR_TEMP,
ATTR_TEMP_UNIT,
)


class HubitatThermostat(HubitatEntity, ClimateEntity):
"""Representation of a Hubitat switch."""

@property
def device_attrs(self) -> Optional[Sequence[str]]:
"""Return this entity's associated attributes"""
return _device_attrs

@property
def current_humidity(self) -> Optional[int]:
"""Return the current humidity."""
Expand Down
11 changes: 10 additions & 1 deletion custom_components/hubitat/cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
Device,
)
from logging import getLogger
from typing import Any, Dict, List, Optional, Tuple, Type
from typing import Any, Dict, List, Optional, Sequence, Tuple, Type

from homeassistant.components.cover import (
ATTR_POSITION as HA_ATTR_POSITION,
Expand Down Expand Up @@ -46,6 +46,15 @@ class HubitatCover(HubitatEntity, CoverEntity):
_features: int
_device_class: Optional[str]

@property
def device_attrs(self) -> Optional[Sequence[str]]:
"""Return this entity's associated attributes"""
return (
self._attribute,
ATTR_LEVEL,
ATTR_POSITION,
)

@property
def device_class(self) -> Optional[str]:
"""Return this sensor's device class."""
Expand Down
9 changes: 6 additions & 3 deletions custom_components/hubitat/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@
from logging import getLogger
from typing import Any, Dict, List, Optional, Union, cast

from custom_components.hubitat.hub import Hub
from custom_components.hubitat.types import Removable, UpdateableEntity

from homeassistant.core import callback
from homeassistant.helpers import device_registry
from homeassistant.helpers.entity import DeviceInfo

from .const import DOMAIN
from .hub import Hub
from .types import Removable, UpdateableEntity
from .util import get_hub_device_id

_LOGGER = getLogger(__name__)
Expand Down Expand Up @@ -138,6 +137,10 @@ def __init__(self, hub: Hub, device: Device, temp: Optional[bool] = False) -> No
if not temp:
self._hub.add_device_listener(self._device.id, self.handle_event)

@property
def device_attrs(self) -> Optional[str]:
return None

@property
def should_poll(self) -> bool:
# Hubitat will push device updates
Expand Down
12 changes: 11 additions & 1 deletion custom_components/hubitat/fan.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
Device,
)
from logging import getLogger
from typing import Any, Dict, List, Optional
from typing import Any, Dict, List, Optional, Sequence

from homeassistant.components.fan import SUPPORT_SET_SPEED, FanEntity
from homeassistant.config_entries import ConfigEntry
Expand All @@ -27,10 +27,20 @@

_LOGGER = getLogger(__name__)

_device_attrs = (
ATTR_SWITCH,
ATTR_SPEED,
)


class HubitatFan(HubitatEntity, FanEntity):
"""Representation of a Hubitat fan."""

@property
def device_attrs(self) -> Optional[Sequence[str]]:
"""Return this entity's associated attributes"""
return _device_attrs

@property
def is_on(self) -> bool:
if CAP_SWITCH in self._device.capabilities:
Expand Down
32 changes: 16 additions & 16 deletions custom_components/hubitat/hub.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,20 @@
from ssl import SSLContext
from typing import Callable, Mapping, Optional, Sequence, Union, cast

from custom_components.hubitat.const import (
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
ATTR_HIDDEN,
CONF_ACCESS_TOKEN,
CONF_HOST,
CONF_ID,
CONF_TEMPERATURE_UNIT,
DEVICE_CLASS_TEMPERATURE,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry
from homeassistant.helpers.device_registry import DeviceEntry

from .const import (
ATTR_ATTRIBUTE,
ATTR_HA_DEVICE_ID,
ATTR_HUB,
Expand All @@ -20,21 +33,8 @@
TEMP_F,
TRIGGER_CAPABILITIES,
)
from custom_components.hubitat.types import Removable, UpdateableEntity
from custom_components.hubitat.util import get_hub_device_id, get_hub_short_id

from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
ATTR_HIDDEN,
CONF_ACCESS_TOKEN,
CONF_HOST,
CONF_ID,
CONF_TEMPERATURE_UNIT,
DEVICE_CLASS_TEMPERATURE,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry
from homeassistant.helpers.device_registry import DeviceEntry
from .types import Removable, UpdateableEntity
from .util import get_hub_device_id, get_hub_short_id

_LOGGER = getLogger(__name__)

Expand Down
17 changes: 16 additions & 1 deletion custom_components/hubitat/light.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
import json
from logging import getLogger
import re
from typing import Any, Dict, List, Optional, Tuple, Union
from typing import Any, Dict, List, Optional, Sequence, Tuple, Union

from homeassistant.components.light import (
ATTR_BRIGHTNESS,
Expand Down Expand Up @@ -64,10 +64,25 @@

_LOGGER = getLogger(__name__)

_device_attrs = (
HE_ATTR_COLOR_MODE,
HE_ATTR_COLOR_NAME,
HE_ATTR_COLOR_TEMP,
HE_ATTR_HUE,
HE_ATTR_LEVEL,
HE_ATTR_SATURATION,
HE_ATTR_SWITCH,
)


class HubitatLight(HubitatEntity, LightEntity):
"""Representation of a Hubitat light."""

@property
def device_attrs(self) -> Optional[Sequence[str]]:
"""Return this entity's associated attributes"""
return _device_attrs

@property
def color_mode(self) -> Optional[str]:
"""Return this light's color mode."""
Expand Down
15 changes: 14 additions & 1 deletion custom_components/hubitat/lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
STATE_LOCKED,
Device,
)
from typing import Any, Dict, List, Optional, Union
from typing import Any, Dict, List, Optional, Sequence, Union

from homeassistant.components.lock import LockEntity
from homeassistant.config_entries import ConfigEntry
Expand All @@ -24,10 +24,23 @@
from .entities import create_and_add_entities
from .types import EntityAdder

_device_attrs = (
HM_ATTR_CODE_LENGTH,
HM_ATTR_LAST_CODE_NAME,
HM_ATTR_LOCK,
HM_ATTR_LOCK_CODES,
HM_ATTR_MAX_CODES,
)


class HubitatLock(HubitatEntity, LockEntity):
"""Representation of a Hubitat lock."""

@property
def device_attrs(self) -> Optional[Sequence[str]]:
"""Return this entity's associated attributes"""
return _device_attrs

@property
def code_format(self) -> Optional[str]:
"""Regex for code format or None if no code is required."""
Expand Down
7 changes: 6 additions & 1 deletion custom_components/hubitat/select.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, List, Optional, Union
from typing import Any, List, Optional, Sequence, Union

from homeassistant.components.select import SelectEntity
from homeassistant.config_entries import ConfigEntry
Expand All @@ -15,6 +15,11 @@ class HubitatSelect(HubitatEntity, SelectEntity):
_options: List[str]
_device_class: str

@property
def device_attrs(self) -> Optional[Sequence[str]]:
"""Return this entity's associated attributes"""
return (self._attribute,)

@property
def device_class(self) -> Optional[str]:
"""Return this select's device class."""
Expand Down
Loading

0 comments on commit a000712

Please sign in to comment.