From b8038108a4f6b69315b3cb9e01629874a49843e3 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 4 Sep 2018 15:24:37 +0200 Subject: [PATCH] Add dev reg info --- docs/device_registry_index.md | 65 +++++++++++++++--- website/i18n/en.json | 3 + .../img/en/device_registry/overview.png | Bin 0 -> 12617 bytes 3 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 website/static/img/en/device_registry/overview.png diff --git a/docs/device_registry_index.md b/docs/device_registry_index.md index 80643cc9..31d08e17 100644 --- a/docs/device_registry_index.md +++ b/docs/device_registry_index.md @@ -3,23 +3,66 @@ title: Device Registry sidebar_label: Introduction --- -The device registry is a registry where Home Assistant keeps track of devices that exposes entities. Any entity that is added to Home Assistant through a config entry and follows entity registry requirements can be put in the registry. +The device registry is a registry where Home Assistant keeps track of devices. A device is represented in Home Assistant via one or more entities. For example, a battery-powered temperature and a humidity sensor might expose entities for temperature, humidity and battery level. -Assigning an entity to the device registry is done by having a device_info property. For hubs you need to manually create a device entry to the device registry. +Device registry overview -Being registered has the advantage that there is a single point of identifying entities belonging to one device. +| Attribute | Description | +| --------- | ----------- | +| id | Unique ID of device (generated by Home Assistant) +| name | Name of this device +| connections | A set of tuples of `(connection_type, connection identifier)`. Connection types are defined in the device registry module. +| identifiers | Identifiers identify the device in the outside world. An example is a serial number. +| manufacturer | The manufacturer of the device. +| model | The model of the device. +| config_entries | Config entries that are linked to this device. +| sw_version | The firmware version of the device. -## Defining a device +## Defining devices -Attributes for a device are connections, identifiers, manufacturer, model, name and sw_version. For hubs the config entry is also required. +Each entity is able to define a device via the `device_info` property. This property is read when an entity is added to Home Assistant via a config entry. A device will be be matched up with an existing device via supplied identifiers and connections, like serial numbers or MAC addresses. -A device is looked up in the registry based on its' identifiers and connections (sets of tuples with keyword and a unique value). Identifiers needs to be common spanning all related entities. +```python +# Inside a platform +class HueLight(LightEntity): -Good sources for identifiers are + @property + def device_info(self): + return { + 'identifiers': { + # Serial numbers are unique identifiers within a specific domain + (hue.DOMAIN, self.unique_id) + }, + 'name': self.name, + 'manufacturer': self.light.manufacturername, + 'model': self.light.productname, + 'sw_version': self.light.swversion, + } - - Serial number of a device - - MAC address of a device +``` -Good sources for connections are +Components are also able to register devices in the case that there are no entities representing them. An example is a hub that communicates with the lights. -- MAC address of a device +```python +# Inside a component +from homeassistant.helpers import device_registry as dr + +device_registry = await dr.async_get_registry(hass) + +device_registry.async_get_or_create( + config_entry=entry.entry_id, + connections={ + (dr.CONNECTION_NETWORK_MAC, config.mac) + }, + identifiers={ + (DOMAIN, config.bridgeid) + }, + manufacturer='Signify', + name=config.name, + model=config.modelid, + sw_version=config.swversion, +) +``` diff --git a/website/i18n/en.json b/website/i18n/en.json index 1bfaf640..69930964 100644 --- a/website/i18n/en.json +++ b/website/i18n/en.json @@ -52,6 +52,7 @@ "development_testing": "Testing your code", "development_typing": "Adding type hints to your code", "development_validation": "Validate the input", + "device_registry_index": "Device Registry", "documentation_create_page": "Create a new page", "documentation_index": "Documentation", "documentation_standards": "Standards", @@ -104,6 +105,7 @@ "hassio_addon_presentation": "Presenting your add-on", "hassio_addon_publishing": "Publishing your add-on", "hassio_addon_repository": "Create an add-on repository", + "hassio_addon_security": "hassio_addon_security", "hassio_addon_testing": "Local add-on testing", "hassio_addon_tutorial": "Tutorial: Making your first add-on", "hassio_debugging": "Debugging Hass.io", @@ -133,6 +135,7 @@ "Config Entries": "Config Entries", "Data Entry Flow": "Data Entry Flow", "Entity Registry": "Entity Registry", + "Device Registry": "Device Registry", "Extending the frontend": "Extending the frontend", "Custom UI": "Custom UI", "Developing a feature": "Developing a feature", diff --git a/website/static/img/en/device_registry/overview.png b/website/static/img/en/device_registry/overview.png new file mode 100644 index 0000000000000000000000000000000000000000..df5c6485856f606c6a7063aef0e3e03ac6755206 GIT binary patch literal 12617 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