async def _async_setup_device_registry(self): attrs = { "identifiers": {(DOMAIN, self.config_entry.unique_id)}, "manufacturer": "Apple", "name": self.config_entry.data[CONF_NAME], } area = attrs["name"] name_trailer = f" {DEFAULT_NAME}" if area.endswith(name_trailer): area = area[: -len(name_trailer)] attrs["suggested_area"] = area if self.atv: dev_info = self.atv.device_info attrs["model"] = ( dev_info.raw_model if dev_info.model == DeviceModel.Unknown and dev_info.raw_model else model_str(dev_info.model) ) attrs["sw_version"] = dev_info.version if dev_info.mac: attrs["connections"] = {(dr.CONNECTION_NETWORK_MAC, dev_info.mac)} device_registry = await dr.async_get_registry(self.hass) device_registry.async_get_or_create( config_entry_id=self.config_entry.entry_id, **attrs )
def _async_setup_device_registry(self): attrs = { ATTR_IDENTIFIERS: {(DOMAIN, self.config_entry.unique_id)}, ATTR_MANUFACTURER: "Apple", ATTR_NAME: self.config_entry.data[CONF_NAME], } area = attrs[ATTR_NAME] name_trailer = f" {DEFAULT_NAME}" if area.endswith(name_trailer): area = area[:-len(name_trailer)] attrs[ATTR_SUGGESTED_AREA] = area if self.atv: dev_info = self.atv.device_info attrs[ATTR_MODEL] = ( dev_info.raw_model if dev_info.model == DeviceModel.Unknown and dev_info.raw_model else model_str(dev_info.model)) attrs[ATTR_SW_VERSION] = dev_info.version if dev_info.mac: attrs[ATTR_CONNECTIONS] = {(dr.CONNECTION_NETWORK_MAC, dev_info.mac)} device_registry = dr.async_get(self.hass) device_registry.async_get_or_create( config_entry_id=self.config_entry.entry_id, **attrs)
async def async_step_confirm(self, user_input=None): """Handle user-confirmation of discovered node.""" if user_input is not None: expected_identifier_count = len(self.context["all_identifiers"]) # If number of services found during device scan mismatch number of # identifiers collected during Zeroconf discovery, then trigger a new scan # with hopes of finding all services. if len(self.atv.all_identifiers) != expected_identifier_count: try: await self.async_find_device() except DeviceNotFound: return self.async_abort(reason="device_not_found") # If all services still were not found, bail out with an error if len(self.atv.all_identifiers) != expected_identifier_count: return self.async_abort(reason="inconsistent_device") return await self.async_pair_next_protocol() return self.async_show_form( step_id="confirm", description_placeholders={ "name": self.atv.name, "type": model_str(self.atv.device_info.model), }, )
async def async_find_device(self, allow_exist=False): """Scan for the selected device to discover services.""" self.scan_result, self.atv, self.atv_identifiers = await device_scan( self.target_device, self.hass.loop, cache=self.scan_result) if not self.atv: raise DeviceNotFound() # Protocols supported by the device are prospects for pairing self.protocols_to_pair.extend(service.protocol for service in self.atv.services) dev_info = self.atv.device_info self.context["title_placeholders"] = { "name": self.atv.name, "type": (dev_info.raw_model if dev_info.model == DeviceModel.Unknown and dev_info.raw_model else model_str(dev_info.model)), } if not allow_exist: for identifier in self.atv.all_identifiers: if identifier in self._async_current_ids(): raise DeviceAlreadyConfigured() # If credentials were found, save them for service in self.atv.services: if service.credentials: self.credentials[service.protocol.value] = service.credentials
async def async_step_confirm(self, user_input=None): """Handle user-confirmation of discovered node.""" if user_input is not None: return await self.async_pair_next_protocol() return self.async_show_form( step_id="confirm", description_placeholders={ "name": self.atv.name, "type": model_str(self.atv.device_info.model), }, )
async def async_find_device(self, allow_exist=False): """Scan for the selected device to discover services.""" self.atv, self.atv_identifiers = await device_scan( self.hass, self.scan_filter, self.hass.loop ) if not self.atv: raise DeviceNotFound() # Protocols supported by the device are prospects for pairing self.protocols_to_pair = deque( service.protocol for service in self.atv.services if service.enabled ) dev_info = self.atv.device_info self.context["title_placeholders"] = { "name": self.atv.name, "type": ( dev_info.raw_model if dev_info.model == DeviceModel.Unknown and dev_info.raw_model else model_str(dev_info.model) ), } all_identifiers = set(self.atv.all_identifiers) discovered_ip_address = str(self.atv.address) for entry in self._async_current_entries(): if not all_identifiers.intersection( entry.data.get(CONF_IDENTIFIERS, [entry.unique_id]) ): continue if entry.data.get(CONF_ADDRESS) != discovered_ip_address: self.hass.config_entries.async_update_entry( entry, data={**entry.data, CONF_ADDRESS: discovered_ip_address}, ) self.hass.async_create_task( self.hass.config_entries.async_reload(entry.entry_id) ) if not allow_exist: raise DeviceAlreadyConfigured()
def __str__(self) -> str: """Convert device info to readable string.""" # If no model is available but raw_model is, use that. Otherwise fall back # to whatever model_str returns. if self.model == DeviceModel.Unknown and self.raw_model: model = self.raw_model else: model = convert.model_str(self.model) output = (model + ", " + { OperatingSystem.Legacy: "ATV SW", OperatingSystem.TvOS: "tvOS", OperatingSystem.AirPortOS: "AirPortOS", }.get(self.operating_system, "Unknown OS")) if self.version: output += " " + self.version if self.build_number: output += " build " + self.build_number return output
def test_model_str(model, output): assert convert.model_str(model) == output