Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions homeassistant/components/binary_sensor/deconz.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,15 @@ def device_state_attributes(self):
return attr

@property
def device(self):
def device_info(self):
"""Return a device description for device registry."""
if (self._sensor.uniqueid is None or
self._sensor.uniqueid.count(':') != 7):
return None
serial = self._sensor.uniqueid.split('-', 1)[0]
return {
'connection': [[CONNECTION_ZIGBEE, serial]],
'identifiers': [[DECONZ_DOMAIN, serial]],
'connections': {(CONNECTION_ZIGBEE, serial)},
'identifiers': {(DECONZ_DOMAIN, serial)},
'manufacturer': self._sensor.manufacturer,
'model': self._sensor.modelid,
'name': self._sensor.name,
Expand Down
5 changes: 3 additions & 2 deletions homeassistant/components/deconz/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,9 @@ def async_add_remote(sensors):
device_registry = await \
hass.helpers.device_registry.async_get_registry()
device_registry.async_get_or_create(
connection=[[CONNECTION_NETWORK_MAC, deconz.config.mac]],
identifiers=[[DOMAIN, deconz.config.bridgeid]],
config_entry=config_entry.entry_id,
connections={(CONNECTION_NETWORK_MAC, deconz.config.mac)},
identifiers={(DOMAIN, deconz.config.bridgeid)},
manufacturer='Dresden Elektronik', model=deconz.config.modelid,
name=deconz.config.name, sw_version=deconz.config.swversion)

Expand Down
6 changes: 3 additions & 3 deletions homeassistant/components/light/deconz.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,15 +202,15 @@ def device_state_attributes(self):
return attributes

@property
def device(self):
def device_info(self):
"""Return a device description for device registry."""
if (self._light.uniqueid is None or
self._light.uniqueid.count(':') != 7):
return None
serial = self._light.uniqueid.split('-', 1)[0]
return {
'connection': [[CONNECTION_ZIGBEE, serial]],
'identifiers': [[DECONZ_DOMAIN, serial]],
'connections': {(CONNECTION_ZIGBEE, serial)},
'identifiers': {(DECONZ_DOMAIN, serial)},
'manufacturer': self._light.manufacturer,
'model': self._light.modelid,
'name': self._light.name,
Expand Down
12 changes: 6 additions & 6 deletions homeassistant/components/media_player/roku.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def __init__(self, host):
self.ip_address = host
self.channels = []
self.current_app = None
self.device_info = {}
self._device_info = {}

self.update()

Expand All @@ -96,7 +96,7 @@ def update(self):
import requests.exceptions

try:
self.device_info = self.roku.device_info
self._device_info = self.roku.device_info
self.ip_address = self.roku.host
self.channels = self.get_source_list()

Expand All @@ -121,9 +121,9 @@ def should_poll(self):
@property
def name(self):
"""Return the name of the device."""
if self.device_info.userdevicename:
return self.device_info.userdevicename
return "Roku {}".format(self.device_info.sernum)
if self._device_info.userdevicename:
return self._device_info.userdevicename
return "Roku {}".format(self._device_info.sernum)

@property
def state(self):
Expand All @@ -149,7 +149,7 @@ def supported_features(self):
@property
def unique_id(self):
"""Return a unique, HASS-friendly identifier for this entity."""
return self.device_info.sernum
return self._device_info.sernum

@property
def media_content_type(self):
Expand Down
17 changes: 11 additions & 6 deletions homeassistant/components/media_player/soundtouch.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,11 @@ def config(self):
"""Return specific soundtouch configuration."""
return self._config

@property
def device(self):
"""Return Soundtouch device."""
return self._device

def update(self):
"""Retrieve the latest data."""
self._status = self._device.status()
Expand Down Expand Up @@ -318,8 +323,8 @@ def create_zone(self, slaves):
_LOGGER.warning("Unable to create zone without slaves")
else:
_LOGGER.info("Creating zone with master %s",
self._device.config.name)
self._device.create_zone([slave.device for slave in slaves])
self.device.config.name)
self.device.create_zone([slave.device for slave in slaves])

def remove_zone_slave(self, slaves):
"""
Expand All @@ -336,8 +341,8 @@ def remove_zone_slave(self, slaves):
_LOGGER.warning("Unable to find slaves to remove")
else:
_LOGGER.info("Removing slaves from zone with master %s",
self._device.config.name)
self._device.remove_zone_slave([slave.device for slave in slaves])
self.device.config.name)
self.device.remove_zone_slave([slave.device for slave in slaves])

def add_zone_slave(self, slaves):
"""
Expand All @@ -352,5 +357,5 @@ def add_zone_slave(self, slaves):
_LOGGER.warning("Unable to find slaves to add")
else:
_LOGGER.info("Adding slaves to zone with master %s",
self._device.config.name)
self._device.add_zone_slave([slave.device for slave in slaves])
self.device.config.name)
self.device.add_zone_slave([slave.device for slave in slaves])
12 changes: 6 additions & 6 deletions homeassistant/components/sensor/deconz.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,15 @@ def device_state_attributes(self):
return attr

@property
def device(self):
def device_info(self):
"""Return a device description for device registry."""
if (self._sensor.uniqueid is None or
self._sensor.uniqueid.count(':') != 7):
return None
serial = self._sensor.uniqueid.split('-', 1)[0]
return {
'connection': [[CONNECTION_ZIGBEE, serial]],
'identifiers': [[DECONZ_DOMAIN, serial]],
'connections': {(CONNECTION_ZIGBEE, serial)},
'identifiers': {(DECONZ_DOMAIN, serial)},
'manufacturer': self._sensor.manufacturer,
'model': self._sensor.modelid,
'name': self._sensor.name,
Expand Down Expand Up @@ -211,15 +211,15 @@ def device_state_attributes(self):
return attr

@property
def device(self):
def device_info(self):
"""Return a device description for device registry."""
if (self._device.uniqueid is None or
self._device.uniqueid.count(':') != 7):
return None
serial = self._device.uniqueid.split('-', 1)[0]
return {
'connection': [[CONNECTION_ZIGBEE, serial]],
'identifiers': [[DECONZ_DOMAIN, serial]],
'connections': {(CONNECTION_ZIGBEE, serial)},
'identifiers': {(DECONZ_DOMAIN, serial)},
'manufacturer': self._device.manufacturer,
'model': self._device.modelid,
'name': self._device.name,
Expand Down
6 changes: 3 additions & 3 deletions homeassistant/components/switch/deconz.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,15 @@ def should_poll(self):
return False

@property
def device(self):
def device_info(self):
"""Return a device description for device registry."""
if (self._switch.uniqueid is None or
self._switch.uniqueid.count(':') != 7):
return None
serial = self._switch.uniqueid.split('-', 1)[0]
return {
'connection': [[CONNECTION_ZIGBEE, serial]],
'identifiers': [[DECONZ_DOMAIN, serial]],
'connections': {(CONNECTION_ZIGBEE, serial)},
'identifiers': {(DECONZ_DOMAIN, serial)},
'manufacturer': self._switch.manufacturer,
'model': self._switch.modelid,
'name': self._switch.name,
Expand Down
42 changes: 30 additions & 12 deletions homeassistant/helpers/device_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@
class DeviceEntry:
"""Device Registry Entry."""

connection = attr.ib(type=list)
identifiers = attr.ib(type=list)
config_entries = attr.ib(type=set, converter=set)
connections = attr.ib(type=set, converter=set)
identifiers = attr.ib(type=set, converter=set)
manufacturer = attr.ib(type=str)
model = attr.ib(type=str)
name = attr.ib(type=str, default=None)
Expand All @@ -46,29 +47,36 @@ def async_get_device(self, identifiers: str, connections: tuple):
"""Check if device is registered."""
for device in self.devices:
if any(iden in device.identifiers for iden in identifiers) or \
any(conn in device.connection for conn in connections):
any(conn in device.connections for conn in connections):
return device
return None

@callback
def async_get_or_create(self, *, connection, identifiers, manufacturer,
model, name=None, sw_version=None):
def async_get_or_create(self, *, config_entry, connections, identifiers,
manufacturer, model, name=None, sw_version=None):
"""Get device. Create if it doesn't exist."""
device = self.async_get_device(identifiers, connection)
if not identifiers and not connections:
return None

device = self.async_get_device(identifiers, connections)

if device is not None:
if config_entry not in device.config_entries:
device.config_entries.add(config_entry)
self.async_schedule_save()
return device

device = DeviceEntry(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not create a new device if it has no connections or identifiers, as it can never be retrieved again

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should identifiers be mandatory or should it check and fail for any of them?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess you're right that at least one is mandatory, I am fine with ignoring it when it doesn't match and just print a warning

connection=connection,
config_entries=[config_entry],
connections=connections,
identifiers=identifiers,
manufacturer=manufacturer,
model=model,
name=name,
sw_version=sw_version
)

self.devices.append(device)

self.async_schedule_save()

return device
Expand All @@ -81,7 +89,16 @@ async def async_load(self):
self.devices = []
return

self.devices = [DeviceEntry(**device) for device in devices['devices']]
self.devices = [DeviceEntry(
config_entries=device['config_entries'],
connections={tuple(conn) for conn in device['connections']},
identifiers={tuple(iden) for iden in device['identifiers']},
manufacturer=device['manufacturer'],
model=device['model'],
name=device['name'],
sw_version=device['sw_version'],
id=device['id'],
) for device in devices['devices']]

@callback
def async_schedule_save(self):
Expand All @@ -95,13 +112,14 @@ def _data_to_save(self):

data['devices'] = [
{
'id': entry.id,
'connection': entry.connection,
'identifiers': entry.identifiers,
'config_entries': list(entry.config_entries),
'connections': list(entry.connections),
'identifiers': list(entry.identifiers),
'manufacturer': entry.manufacturer,
'model': entry.model,
'name': entry.name,
'sw_version': entry.sw_version,
'id': entry.id,
} for entry in self.devices
]

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/helpers/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ def device_state_attributes(self):
return None

@property
def device(self):
def device_info(self):
"""Return device specific attributes.

Implemented by platform classes.
Expand Down
17 changes: 9 additions & 8 deletions homeassistant/helpers/entity_platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,15 +272,16 @@ async def _async_add_entity(self, entity, update_before_add,
else:
config_entry_id = None

device = entity.device
if device is not None:
device_info = entity.device_info
if config_entry_id is not None and device_info is not None:
device = device_registry.async_get_or_create(
connection=device['connection'],
identifiers=device['identifiers'],
manufacturer=device['manufacturer'],
model=device['model'],
name=device.get('name'),
sw_version=device.get('sw_version'))
config_entry=config_entry_id,
connections=device_info.get('connections', []),
identifiers=device_info.get('identifiers', []),
manufacturer=device_info.get('manufacturer'),
model=device_info.get('model'),
name=device_info.get('name'),
sw_version=device_info.get('sw_version'))
device_id = device.id
else:
device_id = None
Expand Down
Loading