diff --git a/homeassistant/components/airzone/manifest.json b/homeassistant/components/airzone/manifest.json
index 637066629db..88b918f699c 100644
--- a/homeassistant/components/airzone/manifest.json
+++ b/homeassistant/components/airzone/manifest.json
@@ -11,5 +11,5 @@
   "documentation": "https://www.home-assistant.io/integrations/airzone",
   "iot_class": "local_polling",
   "loggers": ["aioairzone"],
-  "requirements": ["aioairzone==0.6.3"]
+  "requirements": ["aioairzone==0.6.4"]
 }
diff --git a/homeassistant/components/bluetooth_tracker/device_tracker.py b/homeassistant/components/bluetooth_tracker/device_tracker.py
index 659243df733..f4fc6a8df08 100644
--- a/homeassistant/components/bluetooth_tracker/device_tracker.py
+++ b/homeassistant/components/bluetooth_tracker/device_tracker.py
@@ -173,7 +173,11 @@ async def async_setup_scanner(
                     rssi = await hass.async_add_executor_job(client.request_rssi)
                     client.close()
 
-                tasks.append(see_device(hass, async_see, mac, friendly_name, rssi))
+                tasks.append(
+                    asyncio.create_task(
+                        see_device(hass, async_see, mac, friendly_name, rssi)
+                    )
+                )
 
             if tasks:
                 await asyncio.wait(tasks)
diff --git a/homeassistant/components/bmw_connected_drive/manifest.json b/homeassistant/components/bmw_connected_drive/manifest.json
index c9612d00c64..d30198bdc12 100644
--- a/homeassistant/components/bmw_connected_drive/manifest.json
+++ b/homeassistant/components/bmw_connected_drive/manifest.json
@@ -6,5 +6,5 @@
   "documentation": "https://www.home-assistant.io/integrations/bmw_connected_drive",
   "iot_class": "cloud_polling",
   "loggers": ["bimmer_connected"],
-  "requirements": ["bimmer_connected==0.13.6"]
+  "requirements": ["bimmer-connected==0.13.7"]
 }
diff --git a/homeassistant/components/bthome/manifest.json b/homeassistant/components/bthome/manifest.json
index ef3d9bc002d..91f4940a4e5 100644
--- a/homeassistant/components/bthome/manifest.json
+++ b/homeassistant/components/bthome/manifest.json
@@ -20,5 +20,5 @@
   "dependencies": ["bluetooth_adapters"],
   "documentation": "https://www.home-assistant.io/integrations/bthome",
   "iot_class": "local_push",
-  "requirements": ["bthome-ble==2.11.3"]
+  "requirements": ["bthome-ble==2.12.0"]
 }
diff --git a/homeassistant/components/bthome/sensor.py b/homeassistant/components/bthome/sensor.py
index f8693c5fb34..fc8673e801b 100644
--- a/homeassistant/components/bthome/sensor.py
+++ b/homeassistant/components/bthome/sensor.py
@@ -47,6 +47,15 @@ from .coordinator import (
 from .device import device_key_to_bluetooth_entity_key
 
 SENSOR_DESCRIPTIONS = {
+    # Acceleration (m/s²)
+    (
+        BTHomeSensorDeviceClass.ACCELERATION,
+        Units.ACCELERATION_METERS_PER_SQUARE_SECOND,
+    ): SensorEntityDescription(
+        key=f"{BTHomeSensorDeviceClass.ACCELERATION}_{Units.ACCELERATION_METERS_PER_SQUARE_SECOND}",
+        native_unit_of_measurement=Units.ACCELERATION_METERS_PER_SQUARE_SECOND,
+        state_class=SensorStateClass.MEASUREMENT,
+    ),
     # Battery (percent)
     (BTHomeSensorDeviceClass.BATTERY, Units.PERCENTAGE): SensorEntityDescription(
         key=f"{BTHomeSensorDeviceClass.BATTERY}_{Units.PERCENTAGE}",
@@ -131,6 +140,15 @@ SENSOR_DESCRIPTIONS = {
         native_unit_of_measurement=UnitOfVolume.CUBIC_METERS,
         state_class=SensorStateClass.TOTAL,
     ),
+    # Gyroscope (°/s)
+    (
+        BTHomeSensorDeviceClass.GYROSCOPE,
+        Units.GYROSCOPE_DEGREES_PER_SECOND,
+    ): SensorEntityDescription(
+        key=f"{BTHomeSensorDeviceClass.GYROSCOPE}_{Units.GYROSCOPE_DEGREES_PER_SECOND}",
+        native_unit_of_measurement=Units.GYROSCOPE_DEGREES_PER_SECOND,
+        state_class=SensorStateClass.MEASUREMENT,
+    ),
     # Humidity in (percent)
     (BTHomeSensorDeviceClass.HUMIDITY, Units.PERCENTAGE): SensorEntityDescription(
         key=f"{BTHomeSensorDeviceClass.HUMIDITY}_{Units.PERCENTAGE}",
@@ -242,6 +260,15 @@ SENSOR_DESCRIPTIONS = {
         native_unit_of_measurement=UnitOfTemperature.CELSIUS,
         state_class=SensorStateClass.MEASUREMENT,
     ),
+    # Timestamp (datetime object)
+    (
+        BTHomeSensorDeviceClass.TIMESTAMP,
+        None,
+    ): SensorEntityDescription(
+        key=f"{BTHomeSensorDeviceClass.TIMESTAMP}",
+        device_class=SensorDeviceClass.TIMESTAMP,
+        state_class=SensorStateClass.MEASUREMENT,
+    ),
     # UV index (-)
     (
         BTHomeSensorDeviceClass.UV_INDEX,
diff --git a/homeassistant/components/fortios/device_tracker.py b/homeassistant/components/fortios/device_tracker.py
index 95a418ae40f..d941375c8a3 100644
--- a/homeassistant/components/fortios/device_tracker.py
+++ b/homeassistant/components/fortios/device_tracker.py
@@ -43,7 +43,7 @@ def get_scanner(hass: HomeAssistant, config: ConfigType) -> FortiOSDeviceScanner
     fgt = FortiOSAPI()
 
     try:
-        fgt.tokenlogin(host, token, verify_ssl)
+        fgt.tokenlogin(host, token, verify_ssl, None, 12, "root")
     except ConnectionError as ex:
         _LOGGER.error("ConnectionError to FortiOS API: %s", ex)
         return None
@@ -77,7 +77,12 @@ class FortiOSDeviceScanner(DeviceScanner):
 
     def update(self):
         """Update clients from the device."""
-        clients_json = self._fgt.monitor("user/device/query", "")
+        clients_json = self._fgt.monitor(
+            "user/device/query",
+            "",
+            parameters={"filter": "format=master_mac|hostname|is_online"},
+        )
+
         self._clients_json = clients_json
 
         self._clients = []
@@ -85,8 +90,12 @@ class FortiOSDeviceScanner(DeviceScanner):
         if clients_json:
             try:
                 for client in clients_json["results"]:
-                    if client["is_online"]:
-                        self._clients.append(client["mac"].upper())
+                    if (
+                        "is_online" in client
+                        and "master_mac" in client
+                        and client["is_online"]
+                    ):
+                        self._clients.append(client["master_mac"].upper())
             except KeyError as kex:
                 _LOGGER.error("Key not found in clients: %s", kex)
 
@@ -106,17 +115,10 @@ class FortiOSDeviceScanner(DeviceScanner):
             return None
 
         for client in data["results"]:
-            if client["mac"] == device:
-                try:
+            if "master_mac" in client and client["master_mac"] == device:
+                if "hostname" in client:
                     name = client["hostname"]
-                    _LOGGER.debug("Getting device name=%s", name)
-                    return name
-                except KeyError as kex:
-                    _LOGGER.debug(
-                        "No hostname found for %s in client data: %s",
-                        device,
-                        kex,
-                    )
-                    return device.replace(":", "_")
-
+                else:
+                    name = client["master_mac"].replace(":", "_")
+                return name
         return None
diff --git a/homeassistant/components/fully_kiosk/__init__.py b/homeassistant/components/fully_kiosk/__init__.py
index dd1cc70c9f4..217e73e4d1c 100644
--- a/homeassistant/components/fully_kiosk/__init__.py
+++ b/homeassistant/components/fully_kiosk/__init__.py
@@ -2,6 +2,7 @@
 from homeassistant.config_entries import ConfigEntry
 from homeassistant.const import Platform
 from homeassistant.core import HomeAssistant
+from homeassistant.helpers.typing import ConfigType
 
 from .const import DOMAIN
 from .coordinator import FullyKioskDataUpdateCoordinator
@@ -17,6 +18,14 @@ PLATFORMS = [
 ]
 
 
+async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
+    """Set up Fully Kiosk Browser."""
+
+    await async_setup_services(hass)
+
+    return True
+
+
 async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
     """Set up Fully Kiosk Browser from a config entry."""
 
@@ -28,8 +37,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
     await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
     coordinator.async_update_listeners()
 
-    await async_setup_services(hass)
-
     return True
 
 
diff --git a/homeassistant/components/fully_kiosk/services.py b/homeassistant/components/fully_kiosk/services.py
index 3fca9228735..b3c5886187a 100644
--- a/homeassistant/components/fully_kiosk/services.py
+++ b/homeassistant/components/fully_kiosk/services.py
@@ -1,14 +1,12 @@
 """Services for the Fully Kiosk Browser integration."""
 from __future__ import annotations
 
-from collections.abc import Callable
-from typing import Any
-
-from fullykiosk import FullyKiosk
 import voluptuous as vol
 
+from homeassistant.config_entries import ConfigEntry, ConfigEntryState
 from homeassistant.const import ATTR_DEVICE_ID
 from homeassistant.core import HomeAssistant, ServiceCall
+from homeassistant.exceptions import HomeAssistantError
 import homeassistant.helpers.config_validation as cv
 import homeassistant.helpers.device_registry as dr
 
@@ -16,59 +14,53 @@ from .const import (
     ATTR_APPLICATION,
     ATTR_URL,
     DOMAIN,
-    LOGGER,
     SERVICE_LOAD_URL,
     SERVICE_START_APPLICATION,
 )
+from .coordinator import FullyKioskDataUpdateCoordinator
 
 
 async def async_setup_services(hass: HomeAssistant) -> None:
     """Set up the services for the Fully Kiosk Browser integration."""
 
-    async def execute_service(
-        call: ServiceCall,
-        fully_method: Callable,
-        *args: list[str],
-        **kwargs: dict[str, Any],
-    ) -> None:
-        """Execute a Fully service call.
-
-        :param call: {ServiceCall} HA service call.
-        :param fully_method: {Callable} A method of the FullyKiosk class.
-        :param args: Arguments for fully_method.
-        :param kwargs: Key-word arguments for fully_method.
-        :return: None
-        """
-        LOGGER.debug(
-            "Calling Fully service %s with args: %s, %s", ServiceCall, args, kwargs
-        )
+    async def collect_coordinators(
+        device_ids: list[str],
+    ) -> list[FullyKioskDataUpdateCoordinator]:
+        config_entries = list[ConfigEntry]()
         registry = dr.async_get(hass)
-        for target in call.data[ATTR_DEVICE_ID]:
+        for target in device_ids:
             device = registry.async_get(target)
             if device:
-                for key in device.config_entries:
-                    entry = hass.config_entries.async_get_entry(key)
-                    if not entry:
-                        continue
-                    if entry.domain != DOMAIN:
-                        continue
-                    coordinator = hass.data[DOMAIN][key]
-                    # fully_method(coordinator.fully, *args, **kwargs) would make
-                    # test_services.py fail.
-                    await getattr(coordinator.fully, fully_method.__name__)(
-                        *args, **kwargs
+                device_entries = list[ConfigEntry]()
+                for entry_id in device.config_entries:
+                    entry = hass.config_entries.async_get_entry(entry_id)
+                    if entry and entry.domain == DOMAIN:
+                        device_entries.append(entry)
+                if not device_entries:
+                    raise HomeAssistantError(
+                        f"Device '{target}' is not a {DOMAIN} device"
                     )
-                    break
+                config_entries.extend(device_entries)
+            else:
+                raise HomeAssistantError(
+                    f"Device '{target}' not found in device registry"
+                )
+        coordinators = list[FullyKioskDataUpdateCoordinator]()
+        for config_entry in config_entries:
+            if config_entry.state != ConfigEntryState.LOADED:
+                raise HomeAssistantError(f"{config_entry.title} is not loaded")
+            coordinators.append(hass.data[DOMAIN][config_entry.entry_id])
+        return coordinators
 
     async def async_load_url(call: ServiceCall) -> None:
         """Load a URL on the Fully Kiosk Browser."""
-        await execute_service(call, FullyKiosk.loadUrl, call.data[ATTR_URL])
+        for coordinator in await collect_coordinators(call.data[ATTR_DEVICE_ID]):
+            await coordinator.fully.loadUrl(call.data[ATTR_URL])
 
     async def async_start_app(call: ServiceCall) -> None:
         """Start an app on the device."""
-        await execute_service(
-            call, FullyKiosk.startApplication, call.data[ATTR_APPLICATION]
-        )
+        for coordinator in await collect_coordinators(call.data[ATTR_DEVICE_ID]):
+            await coordinator.fully.startApplication(call.data[ATTR_APPLICATION])
 
     # Register all the above services
     service_mapping = [
diff --git a/homeassistant/components/glances/sensor.py b/homeassistant/components/glances/sensor.py
index f4a3f882749..e952164792f 100644
--- a/homeassistant/components/glances/sensor.py
+++ b/homeassistant/components/glances/sensor.py
@@ -223,13 +223,6 @@ SENSOR_TYPES = {
         icon="mdi:docker",
         state_class=SensorStateClass.MEASUREMENT,
     ),
-    ("raid", "used"): GlancesSensorEntityDescription(
-        key="used",
-        type="raid",
-        name_suffix="Raid used",
-        icon="mdi:harddisk",
-        state_class=SensorStateClass.MEASUREMENT,
-    ),
     ("raid", "available"): GlancesSensorEntityDescription(
         key="available",
         type="raid",
@@ -237,6 +230,13 @@ SENSOR_TYPES = {
         icon="mdi:harddisk",
         state_class=SensorStateClass.MEASUREMENT,
     ),
+    ("raid", "used"): GlancesSensorEntityDescription(
+        key="used",
+        type="raid",
+        name_suffix="Raid used",
+        icon="mdi:harddisk",
+        state_class=SensorStateClass.MEASUREMENT,
+    ),
 }
 
 
@@ -269,36 +269,36 @@ async def async_setup_entry(
         if sensor_type in ["fs", "sensors", "raid"]:
             for sensor_label, params in sensors.items():
                 for param in params:
-                    sensor_description = SENSOR_TYPES[(sensor_type, param)]
+                    if sensor_description := SENSOR_TYPES.get((sensor_type, param)):
+                        _migrate_old_unique_ids(
+                            hass,
+                            f"{coordinator.host}-{name} {sensor_label} {sensor_description.name_suffix}",
+                            f"{sensor_label}-{sensor_description.key}",
+                        )
+                        entities.append(
+                            GlancesSensor(
+                                coordinator,
+                                name,
+                                sensor_label,
+                                sensor_description,
+                            )
+                        )
+        else:
+            for sensor in sensors:
+                if sensor_description := SENSOR_TYPES.get((sensor_type, sensor)):
                     _migrate_old_unique_ids(
                         hass,
-                        f"{coordinator.host}-{name} {sensor_label} {sensor_description.name_suffix}",
-                        f"{sensor_label}-{sensor_description.key}",
+                        f"{coordinator.host}-{name}  {sensor_description.name_suffix}",
+                        f"-{sensor_description.key}",
                     )
                     entities.append(
                         GlancesSensor(
                             coordinator,
                             name,
-                            sensor_label,
+                            "",
                             sensor_description,
                         )
                     )
-        else:
-            for sensor in sensors:
-                sensor_description = SENSOR_TYPES[(sensor_type, sensor)]
-                _migrate_old_unique_ids(
-                    hass,
-                    f"{coordinator.host}-{name}  {sensor_description.name_suffix}",
-                    f"-{sensor_description.key}",
-                )
-                entities.append(
-                    GlancesSensor(
-                        coordinator,
-                        name,
-                        "",
-                        sensor_description,
-                    )
-                )
 
     async_add_entities(entities)
 
diff --git a/homeassistant/components/goodwe/sensor.py b/homeassistant/components/goodwe/sensor.py
index d76d6202832..4a4296bc526 100644
--- a/homeassistant/components/goodwe/sensor.py
+++ b/homeassistant/components/goodwe/sensor.py
@@ -243,7 +243,7 @@ class InverterSensor(CoordinatorEntity[GoodweUpdateCoordinator], SensorEntity):
         In contrast to "total" sensors, these "daily" sensors need to be reset to 0 on midnight.
         """
         if not self.coordinator.last_update_success:
-            self.coordinator.reset_sensor(self._sensor.id)
+            self.coordinator.reset_sensor(self._sensor.id_)
             self.async_write_ha_state()
             _LOGGER.debug("Goodwe reset %s to 0", self.name)
         next_midnight = dt_util.start_of_local_day(
diff --git a/homeassistant/components/habitica/sensor.py b/homeassistant/components/habitica/sensor.py
index e085167301f..d9e0fb227c0 100644
--- a/homeassistant/components/habitica/sensor.py
+++ b/homeassistant/components/habitica/sensor.py
@@ -24,7 +24,7 @@ MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=15)
 SensorType = namedtuple("SensorType", ["name", "icon", "unit", "path"])
 
 SENSORS_TYPES = {
-    "name": SensorType("Name", None, "", ["profile", "name"]),
+    "name": SensorType("Name", None, None, ["profile", "name"]),
     "hp": SensorType("HP", "mdi:heart", "HP", ["stats", "hp"]),
     "maxHealth": SensorType("max HP", "mdi:heart", "HP", ["stats", "maxHealth"]),
     "mp": SensorType("Mana", "mdi:auto-fix", "MP", ["stats", "mp"]),
@@ -35,7 +35,7 @@ SENSORS_TYPES = {
         "Lvl", "mdi:arrow-up-bold-circle-outline", "Lvl", ["stats", "lvl"]
     ),
     "gp": SensorType("Gold", "mdi:circle-multiple", "Gold", ["stats", "gp"]),
-    "class": SensorType("Class", "mdi:sword", "", ["stats", "class"]),
+    "class": SensorType("Class", "mdi:sword", None, ["stats", "class"]),
 }
 
 TASKS_TYPES = {
diff --git a/homeassistant/components/hassio/issues.py b/homeassistant/components/hassio/issues.py
index a92fc392fa4..8f7f06a3931 100644
--- a/homeassistant/components/hassio/issues.py
+++ b/homeassistant/components/hassio/issues.py
@@ -305,7 +305,11 @@ class SupervisorIssues:
 
     async def update(self) -> None:
         """Update issues from Supervisor resolution center."""
-        data = await self._client.get_resolution_info()
+        try:
+            data = await self._client.get_resolution_info()
+        except HassioAPIError as err:
+            _LOGGER.error("Failed to update supervisor issues: %r", err)
+            return
         self.unhealthy_reasons = set(data[ATTR_UNHEALTHY])
         self.unsupported_reasons = set(data[ATTR_UNSUPPORTED])
 
diff --git a/homeassistant/components/homekit/accessories.py b/homeassistant/components/homekit/accessories.py
index dc8a2a7c639..a2e3f8487c6 100644
--- a/homeassistant/components/homekit/accessories.py
+++ b/homeassistant/components/homekit/accessories.py
@@ -626,10 +626,10 @@ class HomeDriver(AccessoryDriver):  # type: ignore[misc]
 
     @pyhap_callback  # type: ignore[misc]
     def pair(
-        self, client_uuid: UUID, client_public: str, client_permissions: int
+        self, client_username_bytes: bytes, client_public: str, client_permissions: int
     ) -> bool:
         """Override super function to dismiss setup message if paired."""
-        success = super().pair(client_uuid, client_public, client_permissions)
+        success = super().pair(client_username_bytes, client_public, client_permissions)
         if success:
             async_dismiss_setup_message(self.hass, self._entry_id)
         return cast(bool, success)
diff --git a/homeassistant/components/homekit/manifest.json b/homeassistant/components/homekit/manifest.json
index 746b097e99a..245dbd0a19e 100644
--- a/homeassistant/components/homekit/manifest.json
+++ b/homeassistant/components/homekit/manifest.json
@@ -9,7 +9,7 @@
   "iot_class": "local_push",
   "loggers": ["pyhap"],
   "requirements": [
-    "HAP-python==4.6.0",
+    "HAP-python==4.7.0",
     "fnv-hash-fast==0.3.1",
     "PyQRCode==1.2.1",
     "base36==0.1.1"
diff --git a/homeassistant/components/insteon/utils.py b/homeassistant/components/insteon/utils.py
index f9c22ef62a5..d7cbe676eee 100644
--- a/homeassistant/components/insteon/utils.py
+++ b/homeassistant/components/insteon/utils.py
@@ -115,8 +115,8 @@ def add_insteon_events(hass: HomeAssistant, device: Device) -> None:
     """Register Insteon device events."""
 
     @callback
-    def async_fire_group_on_off_event(
-        name: str, address: Address, group: int, button: str
+    def async_fire_insteon_event(
+        name: str, address: Address, group: int, button: str | None = None
     ):
         # Firing an event when a button is pressed.
         if button and button[-2] == "_":
@@ -146,9 +146,9 @@ def add_insteon_events(hass: HomeAssistant, device: Device) -> None:
     for name_or_group, event in device.events.items():
         if isinstance(name_or_group, int):
             for _, event in device.events[name_or_group].items():
-                _register_event(event, async_fire_group_on_off_event)
+                _register_event(event, async_fire_insteon_event)
         else:
-            _register_event(event, async_fire_group_on_off_event)
+            _register_event(event, async_fire_insteon_event)
 
 
 def register_new_device_callback(hass):
diff --git a/homeassistant/components/knx/device_trigger.py b/homeassistant/components/knx/device_trigger.py
index 8a074b43b7d..1abafb221db 100644
--- a/homeassistant/components/knx/device_trigger.py
+++ b/homeassistant/components/knx/device_trigger.py
@@ -84,6 +84,7 @@ async def async_attach_trigger(
     trigger_info: TriggerInfo,
 ) -> CALLBACK_TYPE:
     """Attach a trigger."""
+    trigger_data = trigger_info["trigger_data"]
     dst_addresses: list[str] = config.get(EXTRA_FIELD_DESTINATION, [])
     job = HassJob(action, f"KNX device trigger {trigger_info}")
     knx: KNXModule = hass.data[DOMAIN]
@@ -95,7 +96,7 @@ async def async_attach_trigger(
             return
         hass.async_run_hass_job(
             job,
-            {"trigger": telegram},
+            {"trigger": {**trigger_data, **telegram}},
         )
 
     return knx.telegrams.async_listen_telegram(
diff --git a/homeassistant/components/lastfm/sensor.py b/homeassistant/components/lastfm/sensor.py
index d8cf96be5ac..08179df5b7e 100644
--- a/homeassistant/components/lastfm/sensor.py
+++ b/homeassistant/components/lastfm/sensor.py
@@ -3,7 +3,7 @@ from __future__ import annotations
 
 import hashlib
 
-from pylast import LastFMNetwork, Track, User, WSError
+from pylast import LastFMNetwork, PyLastError, Track, User
 import voluptuous as vol
 
 from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
@@ -104,26 +104,30 @@ class LastFmSensor(SensorEntity):
 
     def update(self) -> None:
         """Update device state."""
+        self._attr_native_value = STATE_NOT_SCROBBLING
         try:
-            self._user.get_playcount()
-        except WSError as exc:
+            play_count = self._user.get_playcount()
+            self._attr_entity_picture = self._user.get_image()
+            now_playing = self._user.get_now_playing()
+            top_tracks = self._user.get_top_tracks(limit=1)
+            last_tracks = self._user.get_recent_tracks(limit=1)
+        except PyLastError as exc:
             self._attr_available = False
             LOGGER.error("Failed to load LastFM user `%s`: %r", self._user.name, exc)
             return
-        self._attr_entity_picture = self._user.get_image()
-        if now_playing := self._user.get_now_playing():
+        self._attr_available = True
+        if now_playing:
             self._attr_native_value = format_track(now_playing)
-        else:
-            self._attr_native_value = STATE_NOT_SCROBBLING
-        top_played = None
-        if top_tracks := self._user.get_top_tracks(limit=1):
-            top_played = format_track(top_tracks[0].item)
-        last_played = None
-        if last_tracks := self._user.get_recent_tracks(limit=1):
-            last_played = format_track(last_tracks[0].track)
-        play_count = self._user.get_playcount()
         self._attr_extra_state_attributes = {
-            ATTR_LAST_PLAYED: last_played,
             ATTR_PLAY_COUNT: play_count,
-            ATTR_TOP_PLAYED: top_played,
+            ATTR_LAST_PLAYED: None,
+            ATTR_TOP_PLAYED: None,
         }
+        if len(last_tracks) > 0:
+            self._attr_extra_state_attributes[ATTR_LAST_PLAYED] = format_track(
+                last_tracks[0].track
+            )
+        if len(top_tracks) > 0:
+            self._attr_extra_state_attributes[ATTR_TOP_PLAYED] = format_track(
+                top_tracks[0].item
+            )
diff --git a/homeassistant/components/local_calendar/manifest.json b/homeassistant/components/local_calendar/manifest.json
index 049f9de03ea..b56acffe4e2 100644
--- a/homeassistant/components/local_calendar/manifest.json
+++ b/homeassistant/components/local_calendar/manifest.json
@@ -6,5 +6,5 @@
   "documentation": "https://www.home-assistant.io/integrations/local_calendar",
   "iot_class": "local_polling",
   "loggers": ["ical"],
-  "requirements": ["ical==4.5.1"]
+  "requirements": ["ical==4.5.4"]
 }
diff --git a/homeassistant/components/matter/__init__.py b/homeassistant/components/matter/__init__.py
index 4c47cd4d235..59c5ec9efc8 100644
--- a/homeassistant/components/matter/__init__.py
+++ b/homeassistant/components/matter/__init__.py
@@ -2,11 +2,12 @@
 from __future__ import annotations
 
 import asyncio
+from contextlib import suppress
 
 import async_timeout
 from matter_server.client import MatterClient
 from matter_server.client.exceptions import CannotConnect, InvalidServerVersion
-from matter_server.common.errors import MatterError, NodeCommissionFailed
+from matter_server.common.errors import MatterError, NodeCommissionFailed, NodeNotExists
 import voluptuous as vol
 
 from homeassistant.components.hassio import AddonError, AddonManager, AddonState
@@ -207,7 +208,9 @@ async def async_remove_config_entry_device(
                 )
 
     matter = get_matter(hass)
-    await matter.matter_client.remove_node(node.node_id)
+    with suppress(NodeNotExists):
+        # ignore if the server has already removed the node.
+        await matter.matter_client.remove_node(node.node_id)
 
     return True
 
diff --git a/homeassistant/components/matter/adapter.py b/homeassistant/components/matter/adapter.py
index 7d73ceafc7a..9f16dae8334 100644
--- a/homeassistant/components/matter/adapter.py
+++ b/homeassistant/components/matter/adapter.py
@@ -92,7 +92,7 @@ class MatterAdapter:
             get_clean_name(basic_info.nodeLabel)
             or get_clean_name(basic_info.productLabel)
             or get_clean_name(basic_info.productName)
-            or device_type.__class__.__name__
+            or device_type.__name__
             if device_type
             else None
         )
@@ -117,7 +117,7 @@ class MatterAdapter:
             identifiers.add((DOMAIN, f"{ID_TYPE_SERIAL}_{basic_info.serialNumber}"))
 
         model = (
-            get_clean_name(basic_info.productName) or device_type.__class__.__name__
+            get_clean_name(basic_info.productName) or device_type.__name__
             if device_type
             else None
         )
diff --git a/homeassistant/components/matter/manifest.json b/homeassistant/components/matter/manifest.json
index 5af01f2eea5..707f7e70ee3 100644
--- a/homeassistant/components/matter/manifest.json
+++ b/homeassistant/components/matter/manifest.json
@@ -6,5 +6,5 @@
   "dependencies": ["websocket_api"],
   "documentation": "https://www.home-assistant.io/integrations/matter",
   "iot_class": "local_push",
-  "requirements": ["python-matter-server==3.4.1"]
+  "requirements": ["python-matter-server==3.5.1"]
 }
diff --git a/homeassistant/components/meteo_france/__init__.py b/homeassistant/components/meteo_france/__init__.py
index 3b82399f217..ccd23762850 100644
--- a/homeassistant/components/meteo_france/__init__.py
+++ b/homeassistant/components/meteo_france/__init__.py
@@ -133,10 +133,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
 
             await coordinator_alert.async_refresh()
 
-            if not coordinator_alert.last_update_success:
-                raise ConfigEntryNotReady
-
-            hass.data[DOMAIN][department] = True
+            if coordinator_alert.last_update_success:
+                hass.data[DOMAIN][department] = True
         else:
             _LOGGER.warning(
                 (
@@ -158,11 +156,12 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
     undo_listener = entry.add_update_listener(_async_update_listener)
 
     hass.data[DOMAIN][entry.entry_id] = {
+        UNDO_UPDATE_LISTENER: undo_listener,
         COORDINATOR_FORECAST: coordinator_forecast,
         COORDINATOR_RAIN: coordinator_rain,
-        COORDINATOR_ALERT: coordinator_alert,
-        UNDO_UPDATE_LISTENER: undo_listener,
     }
+    if coordinator_alert and coordinator_alert.last_update_success:
+        hass.data[DOMAIN][entry.entry_id][COORDINATOR_ALERT] = coordinator_alert
 
     await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
 
diff --git a/homeassistant/components/rapt_ble/manifest.json b/homeassistant/components/rapt_ble/manifest.json
index d3eab0641a6..1bde135de35 100644
--- a/homeassistant/components/rapt_ble/manifest.json
+++ b/homeassistant/components/rapt_ble/manifest.json
@@ -16,5 +16,5 @@
   "dependencies": ["bluetooth_adapters"],
   "documentation": "https://www.home-assistant.io/integrations/rapt_ble",
   "iot_class": "local_push",
-  "requirements": ["rapt-ble==0.1.1"]
+  "requirements": ["rapt-ble==0.1.2"]
 }
diff --git a/homeassistant/components/totalconnect/binary_sensor.py b/homeassistant/components/totalconnect/binary_sensor.py
index ef252d54e4e..9caa642b5f4 100644
--- a/homeassistant/components/totalconnect/binary_sensor.py
+++ b/homeassistant/components/totalconnect/binary_sensor.py
@@ -81,15 +81,9 @@ class TotalConnectZoneSecurityBinarySensor(TotalConnectZoneBinarySensor):
             return BinarySensorDeviceClass.MOTION
         if self._zone.is_type_medical():
             return BinarySensorDeviceClass.SAFETY
-        # "security" type is a generic category so test for it last
-        if self._zone.is_type_security():
-            return BinarySensorDeviceClass.DOOR
-
-        _LOGGER.error(
-            "TotalConnect zone %s reported an unexpected device class",
-            self._zone.zoneid,
-        )
-        return None
+        if self._zone.is_type_temperature():
+            return BinarySensorDeviceClass.PROBLEM
+        return BinarySensorDeviceClass.DOOR
 
     def update(self):
         """Return the state of the device."""
diff --git a/homeassistant/components/youtube/coordinator.py b/homeassistant/components/youtube/coordinator.py
index 190e79e3393..d3430d8329c 100644
--- a/homeassistant/components/youtube/coordinator.py
+++ b/homeassistant/components/youtube/coordinator.py
@@ -85,9 +85,16 @@ class YouTubeDataUpdateCoordinator(DataUpdateCoordinator):
                     ATTR_PUBLISHED_AT: video["snippet"]["publishedAt"],
                     ATTR_TITLE: video["snippet"]["title"],
                     ATTR_DESCRIPTION: video["snippet"]["description"],
-                    ATTR_THUMBNAIL: video["snippet"]["thumbnails"]["standard"]["url"],
+                    ATTR_THUMBNAIL: self._get_thumbnail(video),
                     ATTR_VIDEO_ID: video["contentDetails"]["videoId"],
                 },
                 ATTR_SUBSCRIBER_COUNT: int(channel["statistics"]["subscriberCount"]),
             }
         return data
+
+    def _get_thumbnail(self, video: dict[str, Any]) -> str | None:
+        thumbnails = video["snippet"]["thumbnails"]
+        for size in ("standard", "high", "medium", "default"):
+            if size in thumbnails:
+                return thumbnails[size]["url"]
+        return None
diff --git a/homeassistant/components/youtube/sensor.py b/homeassistant/components/youtube/sensor.py
index c605b960475..4560dcfda8c 100644
--- a/homeassistant/components/youtube/sensor.py
+++ b/homeassistant/components/youtube/sensor.py
@@ -30,7 +30,7 @@ class YouTubeMixin:
     """Mixin for required keys."""
 
     value_fn: Callable[[Any], StateType]
-    entity_picture_fn: Callable[[Any], str]
+    entity_picture_fn: Callable[[Any], str | None]
     attributes_fn: Callable[[Any], dict[str, Any]] | None
 
 
@@ -87,7 +87,7 @@ class YouTubeSensor(YouTubeChannelEntity, SensorEntity):
         return self.entity_description.value_fn(self.coordinator.data[self._channel_id])
 
     @property
-    def entity_picture(self) -> str:
+    def entity_picture(self) -> str | None:
         """Return the value reported by the sensor."""
         return self.entity_description.entity_picture_fn(
             self.coordinator.data[self._channel_id]
diff --git a/homeassistant/components/youtube/strings.json b/homeassistant/components/youtube/strings.json
index eb89738708e..1ecc2bc4db8 100644
--- a/homeassistant/components/youtube/strings.json
+++ b/homeassistant/components/youtube/strings.json
@@ -17,6 +17,10 @@
         "data": {
           "channels": "YouTube channels"
         }
+      },
+      "reauth_confirm": {
+        "title": "[%key:common::config_flow::title::reauth%]",
+        "description": "The YouTube integration needs to re-authenticate your account"
       }
     }
   },
diff --git a/homeassistant/components/zwave_js/diagnostics.py b/homeassistant/components/zwave_js/diagnostics.py
index 4f52c41a085..2fe2b17fe1b 100644
--- a/homeassistant/components/zwave_js/diagnostics.py
+++ b/homeassistant/components/zwave_js/diagnostics.py
@@ -65,7 +65,7 @@ def redact_node_state(node_state: NodeDataType) -> NodeDataType:
 
 
 def get_device_entities(
-    hass: HomeAssistant, node: Node, device: dr.DeviceEntry
+    hass: HomeAssistant, node: Node, config_entry: ConfigEntry, device: dr.DeviceEntry
 ) -> list[dict[str, Any]]:
     """Get entities for a device."""
     entity_entries = er.async_entries_for_device(
@@ -73,6 +73,10 @@ def get_device_entities(
     )
     entities = []
     for entry in entity_entries:
+        # Skip entities that are not part of this integration
+        if entry.config_entry_id != config_entry.entry_id:
+            continue
+
         # If the value ID returns as None, we don't need to include this entity
         if (value_id := get_value_id_from_unique_id(entry.unique_id)) is None:
             continue
@@ -142,7 +146,7 @@ async def async_get_device_diagnostics(
     if node_id is None or node_id not in driver.controller.nodes:
         raise ValueError(f"Node for device {device.id} can't be found")
     node = driver.controller.nodes[node_id]
-    entities = get_device_entities(hass, node, device)
+    entities = get_device_entities(hass, node, config_entry, device)
     assert client.version
     node_state = redact_node_state(async_redact_data(node.data, KEYS_TO_REDACT))
     return {
diff --git a/homeassistant/components/zwave_js/triggers/event.py b/homeassistant/components/zwave_js/triggers/event.py
index 32bd3130e03..33cb59d8505 100644
--- a/homeassistant/components/zwave_js/triggers/event.py
+++ b/homeassistant/components/zwave_js/triggers/event.py
@@ -142,8 +142,9 @@ async def async_attach_trigger(
 ) -> CALLBACK_TYPE:
     """Listen for state changes based on configuration."""
     dev_reg = dr.async_get(hass)
-    nodes = async_get_nodes_from_targets(hass, config, dev_reg=dev_reg)
-    if config[ATTR_EVENT_SOURCE] == "node" and not nodes:
+    if config[ATTR_EVENT_SOURCE] == "node" and not async_get_nodes_from_targets(
+        hass, config, dev_reg=dev_reg
+    ):
         raise ValueError(
             f"No nodes found for given {ATTR_DEVICE_ID}s or {ATTR_ENTITY_ID}s."
         )
@@ -215,7 +216,7 @@ async def async_attach_trigger(
         # Nodes list can come from different drivers and we will need to listen to
         # server connections for all of them.
         drivers: set[Driver] = set()
-        if not nodes:
+        if not (nodes := async_get_nodes_from_targets(hass, config, dev_reg=dev_reg)):
             entry_id = config[ATTR_CONFIG_ENTRY_ID]
             client: Client = hass.data[DOMAIN][entry_id][DATA_CLIENT]
             driver = client.driver
diff --git a/homeassistant/components/zwave_js/triggers/value_updated.py b/homeassistant/components/zwave_js/triggers/value_updated.py
index 4e21774c98f..52ecc0a7742 100644
--- a/homeassistant/components/zwave_js/triggers/value_updated.py
+++ b/homeassistant/components/zwave_js/triggers/value_updated.py
@@ -91,7 +91,7 @@ async def async_attach_trigger(
 ) -> CALLBACK_TYPE:
     """Listen for state changes based on configuration."""
     dev_reg = dr.async_get(hass)
-    if not (nodes := async_get_nodes_from_targets(hass, config, dev_reg=dev_reg)):
+    if not async_get_nodes_from_targets(hass, config, dev_reg=dev_reg):
         raise ValueError(
             f"No nodes found for given {ATTR_DEVICE_ID}s or {ATTR_ENTITY_ID}s."
         )
@@ -174,7 +174,7 @@ async def async_attach_trigger(
         # Nodes list can come from different drivers and we will need to listen to
         # server connections for all of them.
         drivers: set[Driver] = set()
-        for node in nodes:
+        for node in async_get_nodes_from_targets(hass, config, dev_reg=dev_reg):
             driver = node.client.driver
             assert driver is not None  # The node comes from the driver.
             drivers.add(driver)
diff --git a/homeassistant/const.py b/homeassistant/const.py
index 2d5e5ebb14c..71edc76d9dc 100644
--- a/homeassistant/const.py
+++ b/homeassistant/const.py
@@ -8,7 +8,7 @@ from .backports.enum import StrEnum
 APPLICATION_NAME: Final = "HomeAssistant"
 MAJOR_VERSION: Final = 2023
 MINOR_VERSION: Final = 6
-PATCH_VERSION: Final = "2"
+PATCH_VERSION: Final = "3"
 __short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
 __version__: Final = f"{__short_version__}.{PATCH_VERSION}"
 REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 10, 0)
diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt
index a7688415905..3c4fc9a6746 100644
--- a/homeassistant/package_constraints.txt
+++ b/homeassistant/package_constraints.txt
@@ -46,7 +46,7 @@ pyyaml==6.0
 requests==2.31.0
 scapy==2.5.0
 sqlalchemy==2.0.15
-typing-extensions>=4.5.0,<5.0
+typing_extensions>=4.6.3,<5.0
 ulid-transform==0.7.2
 voluptuous-serialize==2.6.0
 voluptuous==0.13.1
diff --git a/pyproject.toml b/pyproject.toml
index ff8898aa90a..563b07570a6 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
 
 [project]
 name        = "homeassistant"
-version     = "2023.6.2"
+version     = "2023.6.3"
 license     = {text = "Apache-2.0"}
 description = "Open-source home automation platform running on Python 3."
 readme      = "README.rst"
@@ -49,7 +49,7 @@ dependencies    = [
     "python-slugify==4.0.1",
     "pyyaml==6.0",
     "requests==2.31.0",
-    "typing-extensions>=4.5.0,<5.0",
+    "typing_extensions>=4.6.3,<5.0",
     "ulid-transform==0.7.2",
     "voluptuous==0.13.1",
     "voluptuous-serialize==2.6.0",
diff --git a/requirements.txt b/requirements.txt
index 818eeec8515..48dfff5d662 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -23,7 +23,7 @@ pip>=21.0,<23.2
 python-slugify==4.0.1
 pyyaml==6.0
 requests==2.31.0
-typing-extensions>=4.5.0,<5.0
+typing_extensions>=4.6.3,<5.0
 ulid-transform==0.7.2
 voluptuous==0.13.1
 voluptuous-serialize==2.6.0
diff --git a/requirements_all.txt b/requirements_all.txt
index 7e62831c75e..2d3fab79538 100644
--- a/requirements_all.txt
+++ b/requirements_all.txt
@@ -11,7 +11,7 @@ AIOAladdinConnect==0.1.56
 Adax-local==0.1.5
 
 # homeassistant.components.homekit
-HAP-python==4.6.0
+HAP-python==4.7.0
 
 # homeassistant.components.mastodon
 Mastodon.py==1.5.1
@@ -119,7 +119,7 @@ aioairq==0.2.4
 aioairzone-cloud==0.1.8
 
 # homeassistant.components.airzone
-aioairzone==0.6.3
+aioairzone==0.6.4
 
 # homeassistant.components.ambient_station
 aioambient==2023.04.0
@@ -434,7 +434,7 @@ beautifulsoup4==4.11.1
 bellows==0.35.5
 
 # homeassistant.components.bmw_connected_drive
-bimmer_connected==0.13.6
+bimmer-connected==0.13.7
 
 # homeassistant.components.bizkaibus
 bizkaibus==0.1.1
@@ -502,7 +502,7 @@ brunt==1.2.0
 bt_proximity==0.2.1
 
 # homeassistant.components.bthome
-bthome-ble==2.11.3
+bthome-ble==2.12.0
 
 # homeassistant.components.bt_home_hub_5
 bthomehub5-devicelist==0.1.1
@@ -966,7 +966,7 @@ ibeacon_ble==1.0.1
 ibmiotf==0.3.4
 
 # homeassistant.components.local_calendar
-ical==4.5.1
+ical==4.5.4
 
 # homeassistant.components.ping
 icmplib==3.0
@@ -2087,7 +2087,7 @@ python-kasa==0.5.1
 # python-lirc==1.2.3
 
 # homeassistant.components.matter
-python-matter-server==3.4.1
+python-matter-server==3.5.1
 
 # homeassistant.components.xiaomi_miio
 python-miio==0.5.12
@@ -2240,7 +2240,7 @@ radiotherm==2.1.0
 raincloudy==0.0.7
 
 # homeassistant.components.rapt_ble
-rapt-ble==0.1.1
+rapt-ble==0.1.2
 
 # homeassistant.components.raspyrfm
 raspyrfm-client==1.2.8
diff --git a/requirements_test_all.txt b/requirements_test_all.txt
index bb5fa31f9fa..712b10c12a6 100644
--- a/requirements_test_all.txt
+++ b/requirements_test_all.txt
@@ -13,7 +13,7 @@ AIOAladdinConnect==0.1.56
 Adax-local==0.1.5
 
 # homeassistant.components.homekit
-HAP-python==4.6.0
+HAP-python==4.7.0
 
 # homeassistant.components.flick_electric
 PyFlick==0.0.2
@@ -109,7 +109,7 @@ aioairq==0.2.4
 aioairzone-cloud==0.1.8
 
 # homeassistant.components.airzone
-aioairzone==0.6.3
+aioairzone==0.6.4
 
 # homeassistant.components.ambient_station
 aioambient==2023.04.0
@@ -367,7 +367,7 @@ beautifulsoup4==4.11.1
 bellows==0.35.5
 
 # homeassistant.components.bmw_connected_drive
-bimmer_connected==0.13.6
+bimmer-connected==0.13.7
 
 # homeassistant.components.bluetooth
 bleak-retry-connector==3.0.2
@@ -415,7 +415,7 @@ brottsplatskartan==0.0.1
 brunt==1.2.0
 
 # homeassistant.components.bthome
-bthome-ble==2.11.3
+bthome-ble==2.12.0
 
 # homeassistant.components.buienradar
 buienradar==1.0.5
@@ -746,7 +746,7 @@ iaqualink==0.5.0
 ibeacon_ble==1.0.1
 
 # homeassistant.components.local_calendar
-ical==4.5.1
+ical==4.5.4
 
 # homeassistant.components.ping
 icmplib==3.0
@@ -1522,7 +1522,7 @@ python-juicenet==1.1.0
 python-kasa==0.5.1
 
 # homeassistant.components.matter
-python-matter-server==3.4.1
+python-matter-server==3.5.1
 
 # homeassistant.components.xiaomi_miio
 python-miio==0.5.12
@@ -1627,7 +1627,7 @@ radios==0.1.1
 radiotherm==2.1.0
 
 # homeassistant.components.rapt_ble
-rapt-ble==0.1.1
+rapt-ble==0.1.2
 
 # homeassistant.components.rainmachine
 regenmaschine==2023.06.0
diff --git a/tests/components/bthome/test_sensor.py b/tests/components/bthome/test_sensor.py
index 7aafe7ba7a9..4450bfcc936 100644
--- a/tests/components/bthome/test_sensor.py
+++ b/tests/components/bthome/test_sensor.py
@@ -858,6 +858,57 @@ async def test_v1_sensors(
                 },
             ],
         ),
+        (
+            "A4:C1:38:8D:18:B2",
+            make_bthome_v2_adv(
+                "A4:C1:38:8D:18:B2",
+                b"\x44\x50\x5D\x39\x61\x64",
+            ),
+            None,
+            [
+                {
+                    "sensor_entity": "sensor.test_device_18b2_timestamp",
+                    "friendly_name": "Test Device 18B2 Timestamp",
+                    "unit_of_measurement": "s",
+                    "state_class": "measurement",
+                    "expected_state": "2023-05-14T19:41:17+00:00",
+                },
+            ],
+        ),
+        (
+            "A4:C1:38:8D:18:B2",
+            make_bthome_v2_adv(
+                "A4:C1:38:8D:18:B2",
+                b"\x44\x51\x87\x56",
+            ),
+            None,
+            [
+                {
+                    "sensor_entity": "sensor.test_device_18b2_acceleration",
+                    "friendly_name": "Test Device 18B2 Acceleration",
+                    "unit_of_measurement": "m/s²",
+                    "state_class": "measurement",
+                    "expected_state": "22.151",
+                },
+            ],
+        ),
+        (
+            "A4:C1:38:8D:18:B2",
+            make_bthome_v2_adv(
+                "A4:C1:38:8D:18:B2",
+                b"\x44\x52\x87\x56",
+            ),
+            None,
+            [
+                {
+                    "sensor_entity": "sensor.test_device_18b2_gyroscope",
+                    "friendly_name": "Test Device 18B2 Gyroscope",
+                    "unit_of_measurement": "°/s",
+                    "state_class": "measurement",
+                    "expected_state": "22.151",
+                },
+            ],
+        ),
         (
             "A4:C1:38:8D:18:B2",
             make_bthome_v2_adv(
diff --git a/tests/components/fully_kiosk/test_services.py b/tests/components/fully_kiosk/test_services.py
index 386bc542e3c..504aa4893e6 100644
--- a/tests/components/fully_kiosk/test_services.py
+++ b/tests/components/fully_kiosk/test_services.py
@@ -1,6 +1,8 @@
 """Test Fully Kiosk Browser services."""
 from unittest.mock import MagicMock
 
+import pytest
+
 from homeassistant.components.fully_kiosk.const import (
     ATTR_APPLICATION,
     ATTR_URL,
@@ -10,6 +12,7 @@ from homeassistant.components.fully_kiosk.const import (
 )
 from homeassistant.const import ATTR_DEVICE_ID
 from homeassistant.core import HomeAssistant
+from homeassistant.exceptions import HomeAssistantError
 from homeassistant.helpers import device_registry as dr
 
 from tests.common import MockConfigEntry
@@ -28,20 +31,111 @@ async def test_services(
 
     assert device_entry
 
+    url = "https://example.com"
     await hass.services.async_call(
         DOMAIN,
         SERVICE_LOAD_URL,
-        {ATTR_DEVICE_ID: [device_entry.id], ATTR_URL: "https://example.com"},
+        {ATTR_DEVICE_ID: [device_entry.id], ATTR_URL: url},
         blocking=True,
     )
 
-    assert len(mock_fully_kiosk.loadUrl.mock_calls) == 1
+    mock_fully_kiosk.loadUrl.assert_called_once_with(url)
 
+    app = "de.ozerov.fully"
     await hass.services.async_call(
         DOMAIN,
         SERVICE_START_APPLICATION,
-        {ATTR_DEVICE_ID: [device_entry.id], ATTR_APPLICATION: "de.ozerov.fully"},
+        {ATTR_DEVICE_ID: [device_entry.id], ATTR_APPLICATION: app},
         blocking=True,
     )
 
-    assert len(mock_fully_kiosk.startApplication.mock_calls) == 1
+    mock_fully_kiosk.startApplication.assert_called_once_with(app)
+
+
+async def test_service_unloaded_entry(
+    hass: HomeAssistant,
+    mock_fully_kiosk: MagicMock,
+    init_integration: MockConfigEntry,
+) -> None:
+    """Test service not called when config entry unloaded."""
+    await init_integration.async_unload(hass)
+
+    device_registry = dr.async_get(hass)
+    device_entry = device_registry.async_get_device(
+        identifiers={(DOMAIN, "abcdef-123456")}
+    )
+
+    assert device_entry
+
+    with pytest.raises(HomeAssistantError) as excinfo:
+        await hass.services.async_call(
+            DOMAIN,
+            SERVICE_LOAD_URL,
+            {ATTR_DEVICE_ID: [device_entry.id], ATTR_URL: "https://nabucasa.com"},
+            blocking=True,
+        )
+    assert "Test device is not loaded" in str(excinfo)
+    mock_fully_kiosk.loadUrl.assert_not_called()
+
+    with pytest.raises(HomeAssistantError) as excinfo:
+        await hass.services.async_call(
+            DOMAIN,
+            SERVICE_START_APPLICATION,
+            {ATTR_DEVICE_ID: [device_entry.id], ATTR_APPLICATION: "de.ozerov.fully"},
+            blocking=True,
+        )
+    assert "Test device is not loaded" in str(excinfo)
+    mock_fully_kiosk.startApplication.assert_not_called()
+
+
+async def test_service_bad_device_id(
+    hass: HomeAssistant,
+    mock_fully_kiosk: MagicMock,
+    init_integration: MockConfigEntry,
+) -> None:
+    """Test Fully Kiosk Browser service invocation with bad device id."""
+    with pytest.raises(HomeAssistantError) as excinfo:
+        await hass.services.async_call(
+            DOMAIN,
+            SERVICE_LOAD_URL,
+            {ATTR_DEVICE_ID: ["bad-device_id"], ATTR_URL: "https://example.com"},
+            blocking=True,
+        )
+
+    assert "Device 'bad-device_id' not found in device registry" in str(excinfo)
+
+
+async def test_service_called_with_non_fkb_target_devices(
+    hass: HomeAssistant,
+    mock_fully_kiosk: MagicMock,
+    init_integration: MockConfigEntry,
+) -> None:
+    """Services raise exception when no valid devices provided."""
+    device_registry = dr.async_get(hass)
+
+    other_domain = "NotFullyKiosk"
+    other_config_id = "555"
+    await hass.config_entries.async_add(
+        MockConfigEntry(
+            title="Not Fully Kiosk", domain=other_domain, entry_id=other_config_id
+        )
+    )
+    device_entry = device_registry.async_get_or_create(
+        config_entry_id=other_config_id,
+        identifiers={
+            (other_domain, 1),
+        },
+    )
+
+    with pytest.raises(HomeAssistantError) as excinfo:
+        await hass.services.async_call(
+            DOMAIN,
+            SERVICE_LOAD_URL,
+            {
+                ATTR_DEVICE_ID: [device_entry.id],
+                ATTR_URL: "https://example.com",
+            },
+            blocking=True,
+        )
+
+    assert f"Device '{device_entry.id}' is not a fully_kiosk device" in str(excinfo)
diff --git a/tests/components/glances/__init__.py b/tests/components/glances/__init__.py
index 064c5ab0eb5..41f2675c41c 100644
--- a/tests/components/glances/__init__.py
+++ b/tests/components/glances/__init__.py
@@ -137,6 +137,40 @@ MOCK_DATA = {
         "os_version": "5.15.6-200.fc35.x86_64",
         "hr_name": "Fedora Linux 35 64bit",
     },
+    "raid": {
+        "md3": {
+            "status": "active",
+            "type": "raid1",
+            "components": {"sdh1": "2", "sdi1": "0"},
+            "available": "2",
+            "used": "2",
+            "config": "UU",
+        },
+        "md1": {
+            "status": "active",
+            "type": "raid1",
+            "components": {"sdg": "0", "sde": "1"},
+            "available": "2",
+            "used": "2",
+            "config": "UU",
+        },
+        "md4": {
+            "status": "active",
+            "type": "raid1",
+            "components": {"sdf1": "1", "sdb1": "0"},
+            "available": "2",
+            "used": "2",
+            "config": "UU",
+        },
+        "md0": {
+            "status": "active",
+            "type": "raid1",
+            "components": {"sdc": "2", "sdd": "3"},
+            "available": "2",
+            "used": "2",
+            "config": "UU",
+        },
+    },
     "uptime": "3 days, 10:25:20",
 }
 
@@ -156,4 +190,22 @@ HA_SENSOR_DATA: dict[str, Any] = {
         "memory_free": 2745.0,
     },
     "docker": {"docker_active": 2, "docker_cpu_use": 77.2, "docker_memory_use": 1149.6},
+    "raid": {
+        "md3": {
+            "status": "active",
+            "type": "raid1",
+            "components": {"sdh1": "2", "sdi1": "0"},
+            "available": "2",
+            "used": "2",
+            "config": "UU",
+        },
+        "md1": {
+            "status": "active",
+            "type": "raid1",
+            "components": {"sdg": "0", "sde": "1"},
+            "available": "2",
+            "used": "2",
+            "config": "UU",
+        },
+    },
 }
diff --git a/tests/components/glances/test_sensor.py b/tests/components/glances/test_sensor.py
index 2366e10d11b..d7705854720 100644
--- a/tests/components/glances/test_sensor.py
+++ b/tests/components/glances/test_sensor.py
@@ -35,6 +35,14 @@ async def test_sensor_states(hass: HomeAssistant) -> None:
         assert state.state == HA_SENSOR_DATA["docker"]["docker_cpu_use"]
     if state := hass.states.get("sensor.0_0_0_0_docker_memory_use"):
         assert state.state == HA_SENSOR_DATA["docker"]["docker_memory_use"]
+    if state := hass.states.get("sensor.0_0_0_0_md3_available"):
+        assert state.state == HA_SENSOR_DATA["raid"]["md3"]["available"]
+    if state := hass.states.get("sensor.0_0_0_0_md3_used"):
+        assert state.state == HA_SENSOR_DATA["raid"]["md3"]["used"]
+    if state := hass.states.get("sensor.0_0_0_0_md1_available"):
+        assert state.state == HA_SENSOR_DATA["raid"]["md1"]["available"]
+    if state := hass.states.get("sensor.0_0_0_0_md1_used"):
+        assert state.state == HA_SENSOR_DATA["raid"]["md1"]["used"]
 
 
 @pytest.mark.parametrize(
diff --git a/tests/components/hassio/test_issues.py b/tests/components/hassio/test_issues.py
index 7bd30e452c0..4d694b79e46 100644
--- a/tests/components/hassio/test_issues.py
+++ b/tests/components/hassio/test_issues.py
@@ -715,3 +715,21 @@ async def test_supervisor_remove_missing_issue_without_error(
     msg = await client.receive_json()
     assert msg["success"]
     await hass.async_block_till_done()
+
+
+async def test_system_is_not_ready(
+    hass: HomeAssistant,
+    aioclient_mock: AiohttpClientMocker,
+    caplog: pytest.LogCaptureFixture,
+) -> None:
+    """Ensure hassio starts despite error."""
+    aioclient_mock.get(
+        "http://127.0.0.1/resolution/info",
+        json={
+            "result": "",
+            "message": "System is not ready with state: setup",
+        },
+    )
+
+    assert await async_setup_component(hass, "hassio", {})
+    assert "Failed to update supervisor issues" in caplog.text
diff --git a/tests/components/homekit/test_homekit.py b/tests/components/homekit/test_homekit.py
index 0b74763c6a7..0ffa7893fbd 100644
--- a/tests/components/homekit/test_homekit.py
+++ b/tests/components/homekit/test_homekit.py
@@ -3,6 +3,7 @@ from __future__ import annotations
 
 import asyncio
 from unittest.mock import ANY, AsyncMock, MagicMock, Mock, patch
+from uuid import uuid1
 
 from pyhap.accessory import Accessory
 from pyhap.const import CATEGORY_CAMERA, CATEGORY_TELEVISION
@@ -868,11 +869,11 @@ async def test_homekit_unpair(
         homekit.driver.aio_stop_event = MagicMock()
 
         state = homekit.driver.state
-        state.add_paired_client("client1", "any", b"1")
-        state.add_paired_client("client2", "any", b"0")
-        state.add_paired_client("client3", "any", b"1")
-        state.add_paired_client("client4", "any", b"0")
-        state.add_paired_client("client5", "any", b"0")
+        state.add_paired_client(str(uuid1()).encode("utf-8"), "any", b"1")
+        state.add_paired_client(str(uuid1()).encode("utf-8"), "any", b"0")
+        state.add_paired_client(str(uuid1()).encode("utf-8"), "any", b"1")
+        state.add_paired_client(str(uuid1()).encode("utf-8"), "any", b"0")
+        state.add_paired_client(str(uuid1()).encode("utf-8"), "any", b"0")
 
         formatted_mac = dr.format_mac(state.mac)
         hk_bridge_dev = device_registry.async_get_device(
@@ -917,7 +918,8 @@ async def test_homekit_unpair_missing_device_id(
         homekit.driver.aio_stop_event = MagicMock()
 
         state = homekit.driver.state
-        state.add_paired_client("client1", "any", b"1")
+        client_1 = str(uuid1()).encode("utf-8")
+        state.add_paired_client(client_1, "any", b"1")
         with pytest.raises(HomeAssistantError):
             await hass.services.async_call(
                 DOMAIN,
@@ -926,7 +928,7 @@ async def test_homekit_unpair_missing_device_id(
                 blocking=True,
             )
         await hass.async_block_till_done()
-        state.paired_clients = {"client1": "any"}
+        state.paired_clients = {client_1.decode("utf-8"): "any"}
         homekit.status = STATUS_STOPPED
 
 
@@ -967,7 +969,8 @@ async def test_homekit_unpair_not_homekit_device(
         )
 
         state = homekit.driver.state
-        state.add_paired_client("client1", "any", b"1")
+        client_1 = str(uuid1()).encode("utf-8")
+        state.add_paired_client(client_1, "any", b"1")
         with pytest.raises(HomeAssistantError):
             await hass.services.async_call(
                 DOMAIN,
@@ -976,7 +979,7 @@ async def test_homekit_unpair_not_homekit_device(
                 blocking=True,
             )
         await hass.async_block_till_done()
-        state.paired_clients = {"client1": "any"}
+        state.paired_clients = {client_1.decode("utf-8"): "any"}
         homekit.status = STATUS_STOPPED
 
 
diff --git a/tests/components/knx/test_device_trigger.py b/tests/components/knx/test_device_trigger.py
index c7063997585..c3d3ed67b03 100644
--- a/tests/components/knx/test_device_trigger.py
+++ b/tests/components/knx/test_device_trigger.py
@@ -56,6 +56,7 @@ async def test_if_fires_on_telegram(
         identifiers={(DOMAIN, f"_{knx.mock_config_entry.entry_id}_interface")}
     )
 
+    # "id" field added to action to test if `trigger_data` passed correctly in `async_attach_trigger`
     assert await async_setup_component(
         hass,
         automation.DOMAIN,
@@ -71,7 +72,8 @@ async def test_if_fires_on_telegram(
                     "action": {
                         "service": "test.automation",
                         "data_template": {
-                            "catch_all": ("telegram - {{ trigger.destination }}")
+                            "catch_all": ("telegram - {{ trigger.destination }}"),
+                            "id": (" {{ trigger.id }}"),
                         },
                     },
                 },
@@ -82,11 +84,13 @@ async def test_if_fires_on_telegram(
                         "device_id": device_entry.id,
                         "type": "telegram",
                         "destination": ["1/2/3", "1/2/4"],
+                        "id": "test-id",
                     },
                     "action": {
                         "service": "test.automation",
                         "data_template": {
-                            "specific": ("telegram - {{ trigger.destination }}")
+                            "specific": ("telegram - {{ trigger.destination }}"),
+                            "id": (" {{ trigger.id }}"),
                         },
                     },
                 },
@@ -96,12 +100,18 @@ async def test_if_fires_on_telegram(
 
     await knx.receive_write("0/0/1", (0x03, 0x2F))
     assert len(calls) == 1
-    assert calls.pop().data["catch_all"] == "telegram - 0/0/1"
+    test_call = calls.pop()
+    assert test_call.data["catch_all"] == "telegram - 0/0/1"
+    assert test_call.data["id"] == 0
 
     await knx.receive_write("1/2/4", (0x03, 0x2F))
     assert len(calls) == 2
-    assert calls.pop().data["specific"] == "telegram - 1/2/4"
-    assert calls.pop().data["catch_all"] == "telegram - 1/2/4"
+    test_call = calls.pop()
+    assert test_call.data["specific"] == "telegram - 1/2/4"
+    assert test_call.data["id"] == "test-id"
+    test_call = calls.pop()
+    assert test_call.data["catch_all"] == "telegram - 1/2/4"
+    assert test_call.data["id"] == 0
 
 
 async def test_remove_device_trigger(
diff --git a/tests/components/totalconnect/common.py b/tests/components/totalconnect/common.py
index 54f321c6770..ccee4c43781 100644
--- a/tests/components/totalconnect/common.py
+++ b/tests/components/totalconnect/common.py
@@ -189,14 +189,23 @@ ZONE_5 = {
 # 99 is an unknown ZoneType
 ZONE_6 = {
     "ZoneID": "6",
-    "ZoneDescription": "Medical",
+    "ZoneDescription": "Unknown",
     "ZoneStatus": ZoneStatus.NORMAL,
     "ZoneTypeId": 99,
     "PartitionId": "1",
     "CanBeBypassed": 0,
 }
 
-ZONE_INFO = [ZONE_NORMAL, ZONE_2, ZONE_3, ZONE_4, ZONE_5, ZONE_6]
+ZONE_7 = {
+    "ZoneID": 7,
+    "ZoneDescription": "Temperature",
+    "ZoneStatus": ZoneStatus.NORMAL,
+    "ZoneTypeId": ZoneType.MONITOR,
+    "PartitionId": "1",
+    "CanBeBypassed": 0,
+}
+
+ZONE_INFO = [ZONE_NORMAL, ZONE_2, ZONE_3, ZONE_4, ZONE_5, ZONE_6, ZONE_7]
 ZONES = {"ZoneInfo": ZONE_INFO}
 
 METADATA_DISARMED = {
diff --git a/tests/components/totalconnect/test_binary_sensor.py b/tests/components/totalconnect/test_binary_sensor.py
index 966daeb5a63..8f9cabe670c 100644
--- a/tests/components/totalconnect/test_binary_sensor.py
+++ b/tests/components/totalconnect/test_binary_sensor.py
@@ -84,3 +84,21 @@ async def test_state_and_attributes(hass: HomeAssistant) -> None:
         assert state.state == STATE_OFF
         state = hass.states.get("binary_sensor.gas_tamper")
         assert state.state == STATE_ON
+
+        # Zone 6 is unknown type, assume it is a security (door) sensor
+        state = hass.states.get("binary_sensor.unknown")
+        assert state.state == STATE_OFF
+        assert state.attributes.get("device_class") == BinarySensorDeviceClass.DOOR
+        state = hass.states.get("binary_sensor.unknown_low_battery")
+        assert state.state == STATE_OFF
+        state = hass.states.get("binary_sensor.unknown_tamper")
+        assert state.state == STATE_OFF
+
+        # Zone 7 is temperature
+        state = hass.states.get("binary_sensor.temperature")
+        assert state.state == STATE_OFF
+        assert state.attributes.get("device_class") == BinarySensorDeviceClass.PROBLEM
+        state = hass.states.get("binary_sensor.temperature_low_battery")
+        assert state.state == STATE_OFF
+        state = hass.states.get("binary_sensor.temperature_tamper")
+        assert state.state == STATE_OFF
diff --git a/tests/components/youtube/fixtures/thumbnail/default.json b/tests/components/youtube/fixtures/thumbnail/default.json
new file mode 100644
index 00000000000..6b5d66d6501
--- /dev/null
+++ b/tests/components/youtube/fixtures/thumbnail/default.json
@@ -0,0 +1,42 @@
+{
+  "kind": "youtube#playlistItemListResponse",
+  "etag": "O0Ah8Wd5pUD2Gsv-n0A42RDRcX8",
+  "nextPageToken": "EAAaBlBUOkNBVQ",
+  "items": [
+    {
+      "kind": "youtube#playlistItem",
+      "etag": "qgpoAJRNskzLhD99njC8e2kPB0M",
+      "id": "VVVfeDVYRzFPVjJQNnVaWjVGU005VHR3Lnd5c3VrRHJNZHFV",
+      "snippet": {
+        "publishedAt": "2023-05-11T00:20:46Z",
+        "channelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw",
+        "title": "What's new in Google Home in less than 1 minute",
+        "description": "Discover how your connected devices can do more with Google Home using Matter and Automations at Google I/O 2023.\n\nTo learn more about what's new in Google Home, check out the keynote → https://goo.gle/IO23_homekey\n\nSubscribe to Google Developers → https://goo.gle/developers \n\n#GoogleIO #GoogleHome",
+        "thumbnails": {
+          "default": {
+            "url": "https://i.ytimg.com/vi/wysukDrMdqU/default.jpg",
+            "width": 120,
+            "height": 90
+          }
+        },
+        "channelTitle": "Google for Developers",
+        "playlistId": "UU_x5XG1OV2P6uZZ5FSM9Ttw",
+        "position": 0,
+        "resourceId": {
+          "kind": "youtube#video",
+          "videoId": "wysukDrMdqU"
+        },
+        "videoOwnerChannelTitle": "Google for Developers",
+        "videoOwnerChannelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw"
+      },
+      "contentDetails": {
+        "videoId": "wysukDrMdqU",
+        "videoPublishedAt": "2023-05-11T00:20:46Z"
+      }
+    }
+  ],
+  "pageInfo": {
+    "totalResults": 5798,
+    "resultsPerPage": 1
+  }
+}
diff --git a/tests/components/youtube/fixtures/thumbnail/high.json b/tests/components/youtube/fixtures/thumbnail/high.json
new file mode 100644
index 00000000000..430ad3715cc
--- /dev/null
+++ b/tests/components/youtube/fixtures/thumbnail/high.json
@@ -0,0 +1,52 @@
+{
+  "kind": "youtube#playlistItemListResponse",
+  "etag": "O0Ah8Wd5pUD2Gsv-n0A42RDRcX8",
+  "nextPageToken": "EAAaBlBUOkNBVQ",
+  "items": [
+    {
+      "kind": "youtube#playlistItem",
+      "etag": "qgpoAJRNskzLhD99njC8e2kPB0M",
+      "id": "VVVfeDVYRzFPVjJQNnVaWjVGU005VHR3Lnd5c3VrRHJNZHFV",
+      "snippet": {
+        "publishedAt": "2023-05-11T00:20:46Z",
+        "channelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw",
+        "title": "What's new in Google Home in less than 1 minute",
+        "description": "Discover how your connected devices can do more with Google Home using Matter and Automations at Google I/O 2023.\n\nTo learn more about what's new in Google Home, check out the keynote → https://goo.gle/IO23_homekey\n\nSubscribe to Google Developers → https://goo.gle/developers \n\n#GoogleIO #GoogleHome",
+        "thumbnails": {
+          "default": {
+            "url": "https://i.ytimg.com/vi/wysukDrMdqU/default.jpg",
+            "width": 120,
+            "height": 90
+          },
+          "medium": {
+            "url": "https://i.ytimg.com/vi/wysukDrMdqU/mqdefault.jpg",
+            "width": 320,
+            "height": 180
+          },
+          "high": {
+            "url": "https://i.ytimg.com/vi/wysukDrMdqU/hqdefault.jpg",
+            "width": 480,
+            "height": 360
+          }
+        },
+        "channelTitle": "Google for Developers",
+        "playlistId": "UU_x5XG1OV2P6uZZ5FSM9Ttw",
+        "position": 0,
+        "resourceId": {
+          "kind": "youtube#video",
+          "videoId": "wysukDrMdqU"
+        },
+        "videoOwnerChannelTitle": "Google for Developers",
+        "videoOwnerChannelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw"
+      },
+      "contentDetails": {
+        "videoId": "wysukDrMdqU",
+        "videoPublishedAt": "2023-05-11T00:20:46Z"
+      }
+    }
+  ],
+  "pageInfo": {
+    "totalResults": 5798,
+    "resultsPerPage": 1
+  }
+}
diff --git a/tests/components/youtube/fixtures/thumbnail/medium.json b/tests/components/youtube/fixtures/thumbnail/medium.json
new file mode 100644
index 00000000000..21cb09bd886
--- /dev/null
+++ b/tests/components/youtube/fixtures/thumbnail/medium.json
@@ -0,0 +1,47 @@
+{
+  "kind": "youtube#playlistItemListResponse",
+  "etag": "O0Ah8Wd5pUD2Gsv-n0A42RDRcX8",
+  "nextPageToken": "EAAaBlBUOkNBVQ",
+  "items": [
+    {
+      "kind": "youtube#playlistItem",
+      "etag": "qgpoAJRNskzLhD99njC8e2kPB0M",
+      "id": "VVVfeDVYRzFPVjJQNnVaWjVGU005VHR3Lnd5c3VrRHJNZHFV",
+      "snippet": {
+        "publishedAt": "2023-05-11T00:20:46Z",
+        "channelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw",
+        "title": "What's new in Google Home in less than 1 minute",
+        "description": "Discover how your connected devices can do more with Google Home using Matter and Automations at Google I/O 2023.\n\nTo learn more about what's new in Google Home, check out the keynote → https://goo.gle/IO23_homekey\n\nSubscribe to Google Developers → https://goo.gle/developers \n\n#GoogleIO #GoogleHome",
+        "thumbnails": {
+          "default": {
+            "url": "https://i.ytimg.com/vi/wysukDrMdqU/default.jpg",
+            "width": 120,
+            "height": 90
+          },
+          "medium": {
+            "url": "https://i.ytimg.com/vi/wysukDrMdqU/mqdefault.jpg",
+            "width": 320,
+            "height": 180
+          }
+        },
+        "channelTitle": "Google for Developers",
+        "playlistId": "UU_x5XG1OV2P6uZZ5FSM9Ttw",
+        "position": 0,
+        "resourceId": {
+          "kind": "youtube#video",
+          "videoId": "wysukDrMdqU"
+        },
+        "videoOwnerChannelTitle": "Google for Developers",
+        "videoOwnerChannelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw"
+      },
+      "contentDetails": {
+        "videoId": "wysukDrMdqU",
+        "videoPublishedAt": "2023-05-11T00:20:46Z"
+      }
+    }
+  ],
+  "pageInfo": {
+    "totalResults": 5798,
+    "resultsPerPage": 1
+  }
+}
diff --git a/tests/components/youtube/fixtures/thumbnail/none.json b/tests/components/youtube/fixtures/thumbnail/none.json
new file mode 100644
index 00000000000..d4c28730cab
--- /dev/null
+++ b/tests/components/youtube/fixtures/thumbnail/none.json
@@ -0,0 +1,36 @@
+{
+  "kind": "youtube#playlistItemListResponse",
+  "etag": "O0Ah8Wd5pUD2Gsv-n0A42RDRcX8",
+  "nextPageToken": "EAAaBlBUOkNBVQ",
+  "items": [
+    {
+      "kind": "youtube#playlistItem",
+      "etag": "qgpoAJRNskzLhD99njC8e2kPB0M",
+      "id": "VVVfeDVYRzFPVjJQNnVaWjVGU005VHR3Lnd5c3VrRHJNZHFV",
+      "snippet": {
+        "publishedAt": "2023-05-11T00:20:46Z",
+        "channelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw",
+        "title": "What's new in Google Home in less than 1 minute",
+        "description": "Discover how your connected devices can do more with Google Home using Matter and Automations at Google I/O 2023.\n\nTo learn more about what's new in Google Home, check out the keynote → https://goo.gle/IO23_homekey\n\nSubscribe to Google Developers → https://goo.gle/developers \n\n#GoogleIO #GoogleHome",
+        "thumbnails": {},
+        "channelTitle": "Google for Developers",
+        "playlistId": "UU_x5XG1OV2P6uZZ5FSM9Ttw",
+        "position": 0,
+        "resourceId": {
+          "kind": "youtube#video",
+          "videoId": "wysukDrMdqU"
+        },
+        "videoOwnerChannelTitle": "Google for Developers",
+        "videoOwnerChannelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw"
+      },
+      "contentDetails": {
+        "videoId": "wysukDrMdqU",
+        "videoPublishedAt": "2023-05-11T00:20:46Z"
+      }
+    }
+  ],
+  "pageInfo": {
+    "totalResults": 5798,
+    "resultsPerPage": 1
+  }
+}
diff --git a/tests/components/youtube/fixtures/thumbnail/standard.json b/tests/components/youtube/fixtures/thumbnail/standard.json
new file mode 100644
index 00000000000..bdbedfcf4c9
--- /dev/null
+++ b/tests/components/youtube/fixtures/thumbnail/standard.json
@@ -0,0 +1,57 @@
+{
+  "kind": "youtube#playlistItemListResponse",
+  "etag": "O0Ah8Wd5pUD2Gsv-n0A42RDRcX8",
+  "nextPageToken": "EAAaBlBUOkNBVQ",
+  "items": [
+    {
+      "kind": "youtube#playlistItem",
+      "etag": "qgpoAJRNskzLhD99njC8e2kPB0M",
+      "id": "VVVfeDVYRzFPVjJQNnVaWjVGU005VHR3Lnd5c3VrRHJNZHFV",
+      "snippet": {
+        "publishedAt": "2023-05-11T00:20:46Z",
+        "channelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw",
+        "title": "What's new in Google Home in less than 1 minute",
+        "description": "Discover how your connected devices can do more with Google Home using Matter and Automations at Google I/O 2023.\n\nTo learn more about what's new in Google Home, check out the keynote → https://goo.gle/IO23_homekey\n\nSubscribe to Google Developers → https://goo.gle/developers \n\n#GoogleIO #GoogleHome",
+        "thumbnails": {
+          "default": {
+            "url": "https://i.ytimg.com/vi/wysukDrMdqU/default.jpg",
+            "width": 120,
+            "height": 90
+          },
+          "medium": {
+            "url": "https://i.ytimg.com/vi/wysukDrMdqU/mqdefault.jpg",
+            "width": 320,
+            "height": 180
+          },
+          "high": {
+            "url": "https://i.ytimg.com/vi/wysukDrMdqU/hqdefault.jpg",
+            "width": 480,
+            "height": 360
+          },
+          "standard": {
+            "url": "https://i.ytimg.com/vi/wysukDrMdqU/sddefault.jpg",
+            "width": 640,
+            "height": 480
+          }
+        },
+        "channelTitle": "Google for Developers",
+        "playlistId": "UU_x5XG1OV2P6uZZ5FSM9Ttw",
+        "position": 0,
+        "resourceId": {
+          "kind": "youtube#video",
+          "videoId": "wysukDrMdqU"
+        },
+        "videoOwnerChannelTitle": "Google for Developers",
+        "videoOwnerChannelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw"
+      },
+      "contentDetails": {
+        "videoId": "wysukDrMdqU",
+        "videoPublishedAt": "2023-05-11T00:20:46Z"
+      }
+    }
+  ],
+  "pageInfo": {
+    "totalResults": 5798,
+    "resultsPerPage": 1
+  }
+}
diff --git a/tests/components/youtube/test_sensor.py b/tests/components/youtube/test_sensor.py
index 3462e291af8..6bd99399952 100644
--- a/tests/components/youtube/test_sensor.py
+++ b/tests/components/youtube/test_sensor.py
@@ -3,6 +3,7 @@ from datetime import timedelta
 from unittest.mock import patch
 
 from google.auth.exceptions import RefreshError
+import pytest
 
 from homeassistant import config_entries
 from homeassistant.components.youtube import DOMAIN
@@ -87,3 +88,38 @@ async def test_sensor_reauth_trigger(
     assert flow["step_id"] == "reauth_confirm"
     assert flow["handler"] == DOMAIN
     assert flow["context"]["source"] == config_entries.SOURCE_REAUTH
+
+
+@pytest.mark.parametrize(
+    ("fixture", "url", "has_entity_picture"),
+    [
+        ("standard", "https://i.ytimg.com/vi/wysukDrMdqU/sddefault.jpg", True),
+        ("high", "https://i.ytimg.com/vi/wysukDrMdqU/hqdefault.jpg", True),
+        ("medium", "https://i.ytimg.com/vi/wysukDrMdqU/mqdefault.jpg", True),
+        ("default", "https://i.ytimg.com/vi/wysukDrMdqU/default.jpg", True),
+        ("none", None, False),
+    ],
+)
+async def test_thumbnail(
+    hass: HomeAssistant,
+    setup_integration: ComponentSetup,
+    fixture: str,
+    url: str | None,
+    has_entity_picture: bool,
+) -> None:
+    """Test if right thumbnail is selected."""
+    await setup_integration()
+
+    with patch(
+        "homeassistant.components.youtube.api.build",
+        return_value=MockService(
+            playlist_items_fixture=f"youtube/thumbnail/{fixture}.json"
+        ),
+    ):
+        future = dt_util.utcnow() + timedelta(minutes=15)
+        async_fire_time_changed(hass, future)
+        await hass.async_block_till_done()
+    state = hass.states.get("sensor.google_for_developers_latest_upload")
+    assert state
+    assert ("entity_picture" in state.attributes) is has_entity_picture
+    assert state.attributes.get("entity_picture") == url
diff --git a/tests/components/zwave_js/test_diagnostics.py b/tests/components/zwave_js/test_diagnostics.py
index e7d7d9594bd..aa5ec77b798 100644
--- a/tests/components/zwave_js/test_diagnostics.py
+++ b/tests/components/zwave_js/test_diagnostics.py
@@ -18,11 +18,11 @@ from homeassistant.components.zwave_js.helpers import (
     get_value_id_from_unique_id,
 )
 from homeassistant.core import HomeAssistant
-from homeassistant.helpers.device_registry import async_get as async_get_dev_reg
-from homeassistant.helpers.entity_registry import async_get as async_get_ent_reg
+from homeassistant.helpers import device_registry as dr, entity_registry as er
 
 from .common import PROPERTY_ULTRAVIOLET
 
+from tests.common import MockConfigEntry
 from tests.components.diagnostics import (
     get_diagnostics_for_config_entry,
     get_diagnostics_for_device,
@@ -57,10 +57,26 @@ async def test_device_diagnostics(
     version_state,
 ) -> None:
     """Test the device level diagnostics data dump."""
-    dev_reg = async_get_dev_reg(hass)
+    dev_reg = dr.async_get(hass)
     device = dev_reg.async_get_device({get_device_id(client.driver, multisensor_6)})
     assert device
 
+    # Create mock config entry for fake entity
+    mock_config_entry = MockConfigEntry(domain="test_integration")
+    mock_config_entry.add_to_hass(hass)
+
+    # Add an entity entry to the device that is not part of this config entry
+    ent_reg = er.async_get(hass)
+    ent_reg.async_get_or_create(
+        "test",
+        "test_integration",
+        "test_unique_id",
+        suggested_object_id="unrelated_entity",
+        config_entry=mock_config_entry,
+        device_id=device.id,
+    )
+    assert ent_reg.async_get("test.unrelated_entity")
+
     # Update a value and ensure it is reflected in the node state
     event = Event(
         type="value updated",
@@ -92,16 +108,27 @@ async def test_device_diagnostics(
     }
     # Assert that we only have the entities that were discovered for this device
     # Entities that are created outside of discovery (e.g. node status sensor and
-    # ping button) should not be in dump.
+    # ping button) as well as helper entities created from other integrations should
+    # not be in dump.
     assert len(diagnostics_data["entities"]) == len(
         list(async_discover_node_values(multisensor_6, device, {device.id: set()}))
     )
+    assert any(
+        entity.entity_id == "test.unrelated_entity"
+        for entity in er.async_entries_for_device(ent_reg, device.id)
+    )
+    # Explicitly check that the entity that is not part of this config entry is not
+    # in the dump.
+    assert not any(
+        entity["entity_id"] == "test.unrelated_entity"
+        for entity in diagnostics_data["entities"]
+    )
     assert diagnostics_data["state"] == multisensor_6.data
 
 
 async def test_device_diagnostics_error(hass: HomeAssistant, integration) -> None:
     """Test the device diagnostics raises exception when an invalid device is used."""
-    dev_reg = async_get_dev_reg(hass)
+    dev_reg = dr.async_get(hass)
     device = dev_reg.async_get_or_create(
         config_entry_id=integration.entry_id, identifiers={("test", "test")}
     )
@@ -123,12 +150,12 @@ async def test_device_diagnostics_missing_primary_value(
     hass_client: ClientSessionGenerator,
 ) -> None:
     """Test that device diagnostics handles an entity with a missing primary value."""
-    dev_reg = async_get_dev_reg(hass)
+    dev_reg = dr.async_get(hass)
     device = dev_reg.async_get_device({get_device_id(client.driver, multisensor_6)})
     assert device
 
     entity_id = "sensor.multisensor_6_air_temperature"
-    ent_reg = async_get_ent_reg(hass)
+    ent_reg = er.async_get(hass)
     entry = ent_reg.async_get(entity_id)
 
     # check that the primary value for the entity exists in the diagnostics
@@ -212,7 +239,7 @@ async def test_device_diagnostics_secret_value(
     client.driver.controller.nodes[node.node_id] = node
     client.driver.controller.emit("node added", {"node": node})
     await hass.async_block_till_done()
-    dev_reg = async_get_dev_reg(hass)
+    dev_reg = dr.async_get(hass)
     device = dev_reg.async_get_device({get_device_id(client.driver, node)})
     assert device
 
diff --git a/tests/components/zwave_js/test_trigger.py b/tests/components/zwave_js/test_trigger.py
index 0fb3b829d9a..eae9d6f5416 100644
--- a/tests/components/zwave_js/test_trigger.py
+++ b/tests/components/zwave_js/test_trigger.py
@@ -1112,20 +1112,21 @@ def test_get_trigger_platform_failure() -> None:
 
 
 async def test_server_reconnect_event(
-    hass: HomeAssistant, client, lock_schlage_be469, integration
+    hass: HomeAssistant,
+    client,
+    lock_schlage_be469,
+    lock_schlage_be469_state,
+    integration,
 ) -> None:
     """Test that when we reconnect to server, event triggers reattach."""
     trigger_type = f"{DOMAIN}.event"
-    node: Node = lock_schlage_be469
-    dev_reg = async_get_dev_reg(hass)
-    device = dev_reg.async_get_device(
-        {get_device_id(client.driver, lock_schlage_be469)}
-    )
-    assert device
+    old_node: Node = lock_schlage_be469
 
     event_name = "interview stage completed"
 
-    original_len = len(node._listeners.get(event_name, []))
+    old_node = client.driver.controller.nodes[20]
+
+    original_len = len(old_node._listeners.get(event_name, []))
 
     assert await async_setup_component(
         hass,
@@ -1147,34 +1148,65 @@ async def test_server_reconnect_event(
         },
     )
 
-    assert len(node._listeners.get(event_name, [])) == original_len + 1
-    old_listener = node._listeners.get(event_name, [])[original_len]
+    assert len(old_node._listeners.get(event_name, [])) == original_len + 1
+    old_listener = old_node._listeners.get(event_name, [])[original_len]
 
+    # Remove node so that we can create a new node instance and make sure the listener
+    # attaches
+    node_removed_event = Event(
+        type="node removed",
+        data={
+            "source": "controller",
+            "event": "node removed",
+            "replaced": False,
+            "node": lock_schlage_be469_state,
+        },
+    )
+    client.driver.controller.receive_event(node_removed_event)
+    assert 20 not in client.driver.controller.nodes
+    await hass.async_block_till_done()
+
+    # Add node like new server connection would
+    node_added_event = Event(
+        type="node added",
+        data={
+            "source": "controller",
+            "event": "node added",
+            "node": lock_schlage_be469_state,
+            "result": {},
+        },
+    )
+    client.driver.controller.receive_event(node_added_event)
+    await hass.async_block_till_done()
+
+    # Reload integration to trigger the dispatch signal
     await hass.config_entries.async_reload(integration.entry_id)
     await hass.async_block_till_done()
 
-    # Make sure there is still a listener added for the trigger
-    assert len(node._listeners.get(event_name, [])) == original_len + 1
+    # Make sure there is a listener added for the trigger to the new node
+    new_node = client.driver.controller.nodes[20]
+    assert len(new_node._listeners.get(event_name, [])) == original_len + 1
 
-    # Make sure the old listener was removed
-    assert old_listener not in node._listeners.get(event_name, [])
+    # Make sure the old listener is no longer referenced
+    assert old_listener not in new_node._listeners.get(event_name, [])
 
 
 async def test_server_reconnect_value_updated(
-    hass: HomeAssistant, client, lock_schlage_be469, integration
+    hass: HomeAssistant,
+    client,
+    lock_schlage_be469,
+    lock_schlage_be469_state,
+    integration,
 ) -> None:
     """Test that when we reconnect to server, value_updated triggers reattach."""
     trigger_type = f"{DOMAIN}.value_updated"
-    node: Node = lock_schlage_be469
-    dev_reg = async_get_dev_reg(hass)
-    device = dev_reg.async_get_device(
-        {get_device_id(client.driver, lock_schlage_be469)}
-    )
-    assert device
+    old_node: Node = lock_schlage_be469
 
     event_name = "value updated"
 
-    original_len = len(node._listeners.get(event_name, []))
+    old_node = client.driver.controller.nodes[20]
+
+    original_len = len(old_node._listeners.get(event_name, []))
 
     assert await async_setup_component(
         hass,
@@ -1196,14 +1228,44 @@ async def test_server_reconnect_value_updated(
         },
     )
 
-    assert len(node._listeners.get(event_name, [])) == original_len + 1
-    old_listener = node._listeners.get(event_name, [])[original_len]
+    assert len(old_node._listeners.get(event_name, [])) == original_len + 1
+    old_listener = old_node._listeners.get(event_name, [])[original_len]
 
+    # Remove node so that we can create a new node instance and make sure the listener
+    # attaches
+    node_removed_event = Event(
+        type="node removed",
+        data={
+            "source": "controller",
+            "event": "node removed",
+            "replaced": False,
+            "node": lock_schlage_be469_state,
+        },
+    )
+    client.driver.controller.receive_event(node_removed_event)
+    assert 20 not in client.driver.controller.nodes
+    await hass.async_block_till_done()
+
+    # Add node like new server connection would
+    node_added_event = Event(
+        type="node added",
+        data={
+            "source": "controller",
+            "event": "node added",
+            "node": lock_schlage_be469_state,
+            "result": {},
+        },
+    )
+    client.driver.controller.receive_event(node_added_event)
+    await hass.async_block_till_done()
+
+    # Reload integration to trigger the dispatch signal
     await hass.config_entries.async_reload(integration.entry_id)
     await hass.async_block_till_done()
 
-    # Make sure there is still a listener added for the trigger
-    assert len(node._listeners.get(event_name, [])) == original_len + 1
+    # Make sure there is a listener added for the trigger to the new node
+    new_node = client.driver.controller.nodes[20]
+    assert len(new_node._listeners.get(event_name, [])) == original_len + 1
 
-    # Make sure the old listener was removed
-    assert old_listener not in node._listeners.get(event_name, [])
+    # Make sure the old listener is no longer referenced
+    assert old_listener not in new_node._listeners.get(event_name, [])