Skip to content

Commit

Permalink
Merge pull request #146 from GNeras/better-doorbell-suppression-support
Browse files Browse the repository at this point in the history
Better Doorbell Suppression Support
  • Loading branch information
kvj authored Mar 28, 2023
2 parents cb2d2c7 + 61c4d2f commit 8d8a92d
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 19 deletions.
19 changes: 19 additions & 0 deletions custom_components/nuki_ng/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from homeassistant.core import HomeAssistant
from homeassistant.helpers import service, entity_registry, device_registry
from homeassistant.helpers.entity import EntityCategory

# from homeassistant.helpers import device_registry
from homeassistant.helpers.update_coordinator import (
Expand Down Expand Up @@ -183,3 +184,21 @@ def device_info(self):
"model": model,
"sw_version": versions.get("firmwareVersion"),
}


class NukiOpenerRingSuppressionEntity(NukiEntity):

SUP_RING = 4
SUP_RTO = 2
SUP_CM = 1

@property
def entity_category(self):
return EntityCategory.CONFIG

@property
def doorbellSuppression(self):
return self.coordinator.info_field(self.device_id, 0, "openerAdvancedConfig", "doorbellSuppression")

async def update_doorbell_suppression(self, new_value):
await self.coordinator.update_config(self.device_id, "openerAdvancedConfig", dict(doorbellSuppression=new_value))
2 changes: 1 addition & 1 deletion custom_components/nuki_ng/constants.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
DOMAIN = "nuki_ng"
PLATFORMS = ["binary_sensor", "sensor", "lock", "switch", "button"]
PLATFORMS = ["binary_sensor", "sensor", "lock", "switch", "button", "select"]
70 changes: 70 additions & 0 deletions custom_components/nuki_ng/select.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
from email.policy import default
from homeassistant.components.select import SelectEntity
from homeassistant.helpers.entity import EntityCategory

import logging

from . import NukiEntity, NukiOpenerRingSuppressionEntity
from .constants import DOMAIN

_LOGGER = logging.getLogger(__name__)


async def async_setup_entry(
hass,
entry,
async_add_entities
):
entities = []
coordinator = hass.data[DOMAIN][entry.entry_id]

for dev_id in coordinator.data.get("devices", {}):
if coordinator.info_field(dev_id, -1, "openerAdvancedConfig", "doorbellSuppression") >= 0:
entities.append(NukiOpenerRingSuppressionSelect(coordinator, dev_id))
async_add_entities(entities)
return True


class NukiOpenerRingSuppressionSelect(NukiOpenerRingSuppressionEntity, SelectEntity):

SUP_OFF = 0
SUP_RING = NukiOpenerRingSuppressionEntity.SUP_RING
SUP_RTO = NukiOpenerRingSuppressionEntity.SUP_RTO
SUP_CM = NukiOpenerRingSuppressionEntity.SUP_CM

VALUES_TO_NAMES = {
# 0
SUP_OFF: 'Off',
# 4
SUP_RING: 'Ring',
# 2
SUP_RTO: 'Ring to Open',
# 1
SUP_CM: 'Continuous Mode',
# 4 + 2 == 6
SUP_RING | SUP_RTO: 'Ring & Ring to Open',
# 4 + 1 == 5
SUP_RING | SUP_CM: 'Ring & Continuous Mode',
# 2 + 1 == 3
SUP_RTO | SUP_CM: 'Ring to Open & Continuous Mode',
# 4 + 2 + 1 == 7
SUP_RING | SUP_RTO | SUP_CM: 'On (suppress all)',
}
NAMES_TO_VALUES = {v: k for k, v in VALUES_TO_NAMES.items()}

def __init__(self, coordinator, device_id):
super().__init__(coordinator, device_id)
self.set_id("select", "ring_suppression")
self.set_name("Ring suppression")
self._attr_icon = "mdi:bell-cancel"

@property
def current_option(self) -> str | None:
return self.VALUES_TO_NAMES[self.doorbellSuppression]

@property
def options(self) -> list[str]:
return list(self.NAMES_TO_VALUES.keys())

async def async_select_option(self, option: str) -> None:
await self.update_doorbell_suppression(self.NAMES_TO_VALUES[option])
57 changes: 39 additions & 18 deletions custom_components/nuki_ng/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import logging

from . import NukiEntity
from . import NukiEntity, NukiOpenerRingSuppressionEntity
from .constants import DOMAIN

_LOGGER = logging.getLogger(__name__)
Expand All @@ -26,6 +26,8 @@ async def async_setup_entry(
entities.append(LockAutoLock(coordinator, dev_id))
if coordinator.info_field(dev_id, -1, "openerAdvancedConfig", "doorbellSuppression") >= 0:
entities.append(OpenerRingSuppression(coordinator, dev_id))
entities.append(OpenerRingSuppressionRTO(coordinator, dev_id))
entities.append(OpenerRingSuppressionCM(coordinator, dev_id))
async_add_entities(entities)
return True

Expand Down Expand Up @@ -117,30 +119,49 @@ async def async_turn_off(self, **kwargs):
await self.coordinator.update_config(self.device_id, "advancedConfig", dict(autoLock=False))


class OpenerRingSuppression(NukiEntity, SwitchEntity):
class OpenerRingSuppressionSwitch(NukiOpenerRingSuppressionEntity, SwitchEntity):

def __init__(self, coordinator, device_id, suppression):
super().__init__(coordinator, device_id)
self._suppression = suppression

@property
def entity_registry_enabled_default(self):
return False

@property
def is_on(self):
return (self.doorbellSuppression & self._suppression) != 0

async def async_turn_on(self, **kwargs):
await self.update_doorbell_suppression(self.doorbellSuppression | self._suppression)

async def async_turn_off(self, **kwargs):
await self.update_doorbell_suppression(self.doorbellSuppression & (~self._suppression))


class OpenerRingSuppression(OpenerRingSuppressionSwitch):

def __init__(self, coordinator, device_id):
super().__init__(coordinator, device_id)
super().__init__(coordinator, device_id, NukiOpenerRingSuppressionEntity.SUP_RING)
self.set_id("switch", "ring_suppression")
self.set_name("Ring suppression")
self._attr_icon = "mdi:bell-cancel"

@property
def doorbellSuppression(self):
return self.coordinator.info_field(self.device_id, 0, "openerAdvancedConfig", "doorbellSuppression")

@property
def is_on(self):
return (self.doorbellSuppression & 1) != 0
class OpenerRingSuppressionRTO(OpenerRingSuppressionSwitch):

@property
def entity_category(self):
return EntityCategory.CONFIG
def __init__(self, coordinator, device_id):
super().__init__(coordinator, device_id, NukiOpenerRingSuppressionEntity.SUP_RTO)
self.set_id("switch", "ring_suppression_rto")
self.set_name("Ring suppression (Ring to Open)")
self._attr_icon = "mdi:bell-cancel"

async def async_turn_on(self, **kwargs):
new_value = self.doorbellSuppression | 1
await self.coordinator.update_config(self.device_id, "openerAdvancedConfig", dict(doorbellSuppression=new_value))

async def async_turn_off(self, **kwargs):
new_value = self.doorbellSuppression & (~1)
await self.coordinator.update_config(self.device_id, "openerAdvancedConfig", dict(doorbellSuppression=new_value))
class OpenerRingSuppressionCM(OpenerRingSuppressionSwitch):

def __init__(self, coordinator, device_id):
super().__init__(coordinator, device_id, NukiOpenerRingSuppressionEntity.SUP_CM)
self.set_id("switch", "ring_suppression_cm")
self.set_name("Ring suppression (Continuous Mode)")
self._attr_icon = "mdi:bell-cancel"

0 comments on commit 8d8a92d

Please sign in to comment.