def async_send_notification(self, data, fallback_send): """Send a push notification.""" if not self.support_confirm: self._send_message(data) return confirm_id = random_uuid_hex() data["hass_confirm_id"] = confirm_id async def handle_push_failed(_=None): """Handle a failed local push notification.""" # Remove this handler from the pending dict # If it didn't exist we hit a race condition between call_later and another # push failing and tearing down the connection. if self.pending_confirms.pop(confirm_id, None) is None: return # Drop local channel if it's still open if self.on_teardown is not None: await self.async_teardown() await fallback_send(data) self.pending_confirms[confirm_id] = { "unsub_scheduled_push_failed": async_call_later( self.hass, PUSH_CONFIRM_TIMEOUT, handle_push_failed ), "handle_push_failed": handle_push_failed, } self._send_message(data)
def __init__( self, *, domain="test", data=None, version=1, entry_id=None, source=config_entries.SOURCE_USER, title="Mock Title", state=None, options={}, system_options={}, unique_id=None, disabled_by=None, reason=None, ): """Initialize a mock config entry.""" kwargs = { "entry_id": entry_id or uuid_util.random_uuid_hex(), "domain": domain, "data": data or {}, "system_options": system_options, "options": options, "version": version, "title": title, "unique_id": unique_id, "disabled_by": disabled_by, } if source is not None: kwargs["source"] = source if state is not None: kwargs["state"] = state super().__init__(**kwargs) if reason is not None: self.reason = reason
def __init__( self, version: int, domain: str, title: str, data: dict, source: str, connection_class: str, system_options: dict, options: Optional[dict] = None, unique_id: Optional[str] = None, entry_id: Optional[str] = None, state: str = ENTRY_STATE_NOT_LOADED, ) -> None: """Initialize a config entry.""" # Unique id of the config entry self.entry_id = entry_id or uuid_util.random_uuid_hex() # Version of the configuration. self.version = version # Domain the configuration belongs to self.domain = domain # Title of the configuration self.title = title # Config data self.data = MappingProxyType(data) # Entry options self.options = MappingProxyType(options or {}) # Entry system options self.system_options = SystemOptions(**system_options) # Source of the configuration (user, discovery, cloud) self.source = source # Connection class self.connection_class = connection_class # State of the entry (LOADED, NOT_LOADED) self.state = state # Unique ID of this entry. self.unique_id = unique_id # Supports unload self.supports_unload = False # Listeners to call on update self.update_listeners: List[ weakref.ReferenceType[UpdateListenerType]] = [] # Function to cancel a scheduled retry self._async_cancel_retry_setup: Optional[Callable[[], Any]] = None
async def async_join_players(self, group_members): """Add all clients given in entities to the group of the server. Creates a new group if necessary. Used for join service. """ _LOGGER.info( "%s wants to add the following entities %s", self.entity_id, str(group_members), ) entities = [ entity for entity in self.get_all_mc_entities() if entity.entity_id in group_members ] if not self.is_server and self.musiccast_zone_entity.is_server: # The MusicCast Distribution Module of this device is already in use. To use it as a server, we first # have to unjoin and wait until the servers are updated. await self.musiccast_zone_entity.async_server_close_group() elif self.musiccast_zone_entity.is_client: await self.async_client_leave_group(True) # Use existing group id if we are server, generate a new one else. group = (self.coordinator.data.group_id if self.is_server else uuid.random_uuid_hex().upper()) # First let the clients join for client in entities: if client != self: try: await client.async_client_join(group, self) except MusicCastGroupException: _LOGGER.warning( "%s is struggling to update its group data. Will retry perform the update", client.entity_id, ) await client.async_client_join(group, self) await self.coordinator.musiccast.mc_server_group_extend( self._zone_id, [ entity.ip_address for entity in entities if entity.ip_address != self.ip_address ], group, self.get_distribution_num(), ) _LOGGER.debug("%s added the following entities %s", self.entity_id, str(entities)) _LOGGER.info( "%s has now the following musiccast group %s", self.entity_id, str(self.musiccast_group), ) await self.update_all_mc_entities()
async def _async_migrate(old_major_version: int, old_minor_version: int, data: dict) -> dict: """Migrate to the new version.""" if old_major_version == 1 and old_minor_version < 2: # From version 1.1 for entity in data["entities"]: # Populate all keys entity["area_id"] = entity.get("area_id") entity["capabilities"] = entity.get("capabilities") or {} entity["config_entry_id"] = entity.get("config_entry_id") entity["device_class"] = entity.get("device_class") entity["device_id"] = entity.get("device_id") entity["disabled_by"] = entity.get("disabled_by") entity["entity_category"] = entity.get("entity_category") entity["icon"] = entity.get("icon") entity["name"] = entity.get("name") entity["original_icon"] = entity.get("original_icon") entity["original_name"] = entity.get("original_name") entity["platform"] = entity["platform"] entity["supported_features"] = entity.get("supported_features", 0) entity["unit_of_measurement"] = entity.get("unit_of_measurement") if old_major_version == 1 and old_minor_version < 3: # Version 1.3 adds original_device_class for entity in data["entities"]: # Move device_class to original_device_class entity["original_device_class"] = entity["device_class"] entity["device_class"] = None if old_major_version == 1 and old_minor_version < 4: # Version 1.4 adds id for entity in data["entities"]: entity["id"] = uuid_util.random_uuid_hex() if old_major_version == 1 and old_minor_version < 5: # Version 1.5 adds entity options for entity in data["entities"]: entity["options"] = {} if old_major_version == 1 and old_minor_version < 6: # Version 1.6 adds hidden_by for entity in data["entities"]: entity["hidden_by"] = None if old_major_version == 1 and old_minor_version < 7: # Version 1.6 adds has_entity_name for entity in data["entities"]: entity["has_entity_name"] = False if old_major_version > 1: raise NotImplementedError return data
def __init__( self, item_id: str, config: dict[str, Any], blueprint_inputs: dict[str, Any], context: Context, ) -> None: """Container for script trace.""" self._trace: dict[str, deque[TraceElement]] | None = None self._config: dict[str, Any] = config self._blueprint_inputs: dict[str, Any] = blueprint_inputs self.context: Context = context self._error: Exception | None = None self._state: str = "running" self._script_execution: str | None = None self.run_id: str = uuid_util.random_uuid_hex() self._timestamp_finish: dt.datetime | None = None self._timestamp_start: dt.datetime = dt_util.utcnow() self.key = f"{self._domain}.{item_id}" self._dict: dict[str, Any] | None = None self._short_dict: dict[str, Any] | None = None if trace_id_get(): trace_set_child_id(self.key, self.run_id) trace_id_set((self.key, self.run_id))
async def test_uuid_util_random_uuid_hex(): """Verify we can generate a random uuid.""" assert len(uuid_util.random_uuid_hex()) == 32 assert uuid.UUID(uuid_util.random_uuid_hex())