Skip to content

Commit

Permalink
Merge pull request #26 from AaronDavidSchneider/cleaner_devices
Browse files Browse the repository at this point in the history
Group Sonos Alarm with Sonos devices
  • Loading branch information
AaronDavidSchneider authored Apr 21, 2021
2 parents 9c64e63 + 509d75e commit d45447f
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 21 deletions.
25 changes: 25 additions & 0 deletions custom_components/sonos_alarm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
from homeassistant.const import ATTR_ENTITY_ID, ATTR_TIME, CONF_HOSTS
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.core import callback

from .const import DOMAIN

Expand Down Expand Up @@ -59,4 +61,27 @@ async def async_setup_entry(hass, entry):
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, domain)
)
async_cleanup_sonos_devices(hass, entry)
return True


@callback
def async_cleanup_sonos_devices(hass, entry):
"""Clean up old and invalid devices from the registry."""
device_registry = dr.async_get(hass)
entity_registry = er.async_get(hass)

device_entries = hass.helpers.device_registry.async_entries_for_config_entry(
device_registry, entry.entry_id
)

for device_entry in device_entries:
if (
len(
hass.helpers.entity_registry.async_entries_for_device(
entity_registry, device_entry.id, include_disabled_entities=True
)
)
== 0
):
device_registry.async_remove_device(device_entry.id)
46 changes: 25 additions & 21 deletions custom_components/sonos_alarm/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from pysonos.exceptions import SoCoUPnPException

from homeassistant.components.switch import ENTITY_ID_FORMAT, SwitchEntity
import homeassistant.helpers.device_registry as dr
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.util import slugify

from . import (
Expand Down Expand Up @@ -152,25 +152,42 @@ def _get_current_alarm_instance(self):
else:
return False

async def _async_remove(self):
"""remove this entity as it is not available anymore"""
entity_registry = er.async_get(self.hass)
entity_registry.async_remove(self.entity_id)

async def _async_update_device(self):
"""update the device, since this alarm moved to a different player"""
device_registry = dr.async_get(self.hass)
entity_registry = er.async_get(self.hass)
entry_id = entity_registry.async_get(self.entity_id).config_entry_id

new_device = device_registry.async_get_or_create(config_entry_id=entry_id, identifiers = {(SONOS_DOMAIN, self._unique_player_id)}, connections={(dr.CONNECTION_NETWORK_MAC, self._mac_address)})
if not entity_registry.async_get(self.entity_id).device_id == new_device.id:
entity_registry._async_update_entity(self.entity_id, device_id=new_device.id)

async def async_update(self, now=None):
"""Retrieve latest state."""
_LOGGER.debug("updating alarms")
try:
self._is_available = await self.hass.async_add_executor_job(self._get_current_alarm_instance)

if not self._is_available:
self.hass.async_create_task(self._async_remove())
return

self._is_on = self.alarm.enabled


if self._unique_player_id != self.alarm.zone.uid:
speaker_info = await self.hass.async_add_executor_job(lambda: self.alarm.zone.get_speaker_info(True))
self._speaker_name: str = speaker_info["zone_name"]
self._model: str = speaker_info["model_name"]
self._sw_version: str = speaker_info["software_version"]
self._mac_address: str = speaker_info["mac_address"]
self._unique_player_id: str = self.alarm.zone.uid
await self._update_device()


self._name = "Sonos Alarm {} {} {}".format(
self._speaker_name,
Expand Down Expand Up @@ -246,32 +263,19 @@ def unique_id(self):
"""Return a unique ID."""
return self._unique_id

# For future reference: Use the same device_info like sonos: -> needs some way to update the device_info
#
# @property
# def device_info(self) -> dict:
# """Return information about the device."""
# return {
# "identifiers": {(SONOS_DOMAIN, self._unique_player_id)},
# "name": self._speaker_name,
# "model": self._model.replace("Sonos ", ""),
# "sw_version": self._sw_version,
# "connections": {(dr.CONNECTION_NETWORK_MAC, self._mac_address)},
# "manufacturer": "Sonos",
# "suggested_area": self._speaker_name,
# }
#
@property
def device_info(self) -> dict:
"""Return information about the device."""
return {
"identifiers": {(SONOS_DOMAIN, self._unique_id)},
"name": "Sonos Alarm - ID: {}".format(self._id),
"model": "alarm",
"identifiers": {(SONOS_DOMAIN, self._unique_player_id)},
"name": self._speaker_name,
"model": self._model.replace("Sonos ", ""),
"sw_version": self._sw_version,
"connections": {(dr.CONNECTION_NETWORK_MAC, self._mac_address)},
"manufacturer": "Sonos",
"suggested_area": self._speaker_name,
}


@property
def available(self) -> bool:
"""Return unavailability of alarm switch."""
Expand Down

0 comments on commit d45447f

Please sign in to comment.