Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
143 commits
Select commit Hold shift + click to select a range
cff3d3d
Bump version to 2025.7.0b0
frenck Jun 25, 2025
a296324
Fix playing TTS and local media source over DLNA (#134903)
kepler Jun 26, 2025
d4b548b
Fixed issue when tests (should) fail in Smarla (#146102)
rlint-explicatis Jun 26, 2025
aec812a
Create a new client session for air-Q to fix cookie polution (#147027)
Sibgatulin Jun 26, 2025
71f281c
Fix Telegram bot default target when sending messages (#147470)
hanwg Jun 26, 2025
7d0e99d
Fixes in Google AI TTS (#147501)
tronikos Jun 25, 2025
b9a7371
Set end date for when allowing unique id collisions in config entries…
emontnemery Jun 26, 2025
150f416
Improve config flow strings for Alexa Devices (#147523)
chemelli74 Jun 26, 2025
e627811
Bump dependency on pyW215 for DLink integration to 0.8.0 (#147534)
andersfugmann Jun 26, 2025
2c4ea0d
Fix wind direction state class sensor for AEMET (#147535)
luca-angemi Jun 26, 2025
6b2aaf3
Show current Lametric version if there is no newer version (#147538)
joostlek Jun 26, 2025
03f9caf
Add action exceptions to Alexa Devices (#147546)
chemelli74 Jun 26, 2025
cfa6746
Fix unload for Alexa Devices (#147548)
chemelli74 Jun 25, 2025
914bb3a
Use default title for migrated Google Generative AI entries (#147551)
tronikos Jun 26, 2025
5fe2e4b
Include subentries in Google Generative AI diagnostics (#147558)
tronikos Jun 26, 2025
1e81e59
Bump zwave-js-server-python to 0.65.0 (#147561)
MindFreeze Jun 26, 2025
f28d658
Refactor in Google AI TTS in preparation for STT (#147562)
tronikos Jun 26, 2025
d523f85
Fix sending commands to Matter vacuum (#147567)
marcelveldt Jun 26, 2025
ae062b2
Remove obsolete routing info when migrating a Z-Wave network (#147568)
MindFreeze Jun 26, 2025
17fd850
Hide unnamed paths when selecting a USB Z-Wave adapter (#147571)
MindFreeze Jun 26, 2025
398dd3a
Set right model in OpenAI conversation (#147575)
joostlek Jun 26, 2025
153e1e4
Do not make the favorite button unavailable when no content playing o…
marcelveldt Jun 26, 2025
4cc10ca
Set Google AI model as device model (#147582)
joostlek Jun 26, 2025
1f57bba
Add default conversation name for OpenAI integration (#147597)
joostlek Jun 26, 2025
c7677b9
Add default title to migrated Claude entry (#147598)
joostlek Jun 26, 2025
a233b6b
Add default title to migrated Ollama entry (#147599)
joostlek Jun 26, 2025
9cc75f3
Update frontend to 20250626.0 (#147601)
bramkragten Jun 26, 2025
f8207a2
Remove default icon for wind direction sensor for Buienradar (#147603)
luca-angemi Jun 26, 2025
c8422c9
Improve explanation on how to get API token in Telegram (#147605)
joostlek Jun 26, 2025
4df1f70
Fix asset url in Habitica integration (#147612)
tr4nt0r Jun 26, 2025
26521f8
Hide Telegram bot proxy URL behind section (#147613)
joostlek Jun 26, 2025
c0ec987
Fix meaters not being added after a reload (#147614)
joostlek Jun 26, 2025
6a73855
Bump version to 2025.7.0b1
frenck Jun 26, 2025
cb359da
Make entities unavailable when machine is physically off in lamarzocc…
zweckj Jun 27, 2025
f93ab8d
Allow setup of Zigbee/Thread for ZBT-1 and Yellow without internet ac…
puddly Jun 27, 2025
28dfc99
Do not factory reset old Z-Wave controller during migration (#147576)
MindFreeze Jun 27, 2025
e5e6ed6
Fix Telegram bot yaml import for webhooks containing None value for U…
hanwg Jun 27, 2025
263823c
Fix config schema to make credentials optional in NUT flows (#147593)
mib1185 Jun 27, 2025
efb29d0
Add Diagnostics to PlayStation Network (#147607)
JackJPowell Jun 26, 2025
3fc154e
Make sure Google Generative AI integration migration is clean (#147625)
joostlek Jun 26, 2025
c2c388e
Make sure OpenAI integration migration is clean (#147627)
joostlek Jun 26, 2025
bc607dd
Make sure Anthropic integration migration is clean (#147629)
joostlek Jun 26, 2025
85343a9
Make sure Ollama integration migration is clean (#147630)
joostlek Jun 26, 2025
6bd6fa6
Bump pynecil to v4.1.1 (#147648)
tr4nt0r Jun 27, 2025
9782637
Clarify descriptions of `subaru.unlock_specific_door` action (#147655)
NoRi2909 Jun 27, 2025
41b9a7a
Bump version to 2025.7.0b2
frenck Jun 27, 2025
1829acd
Z-WaveJS config flow: Change keys question (#147518)
MindFreeze Jun 27, 2025
b9e2c5d
Add previously missing state classes to dsmr sensors (#147633)
bajansen Jun 27, 2025
62f7cbb
Remove dweet.io integration (#147645)
tr4nt0r Jun 27, 2025
47f3bf2
Fix energy history in Teslemetry (#147646)
Bre77 Jun 27, 2025
0b5d2ab
Respect availability of parent class in Husqvarna Automower (#147649)
Thomas55555 Jun 27, 2025
5c0f2d3
Make jellyfin not single config entry (#147656)
zweckj Jun 27, 2025
4977ee4
Bump jellyfin-apiclient-python to 1.11.0 (#147658)
zweckj Jun 27, 2025
77ccfbd
Fix: Unhandled NoneType sessions in jellyfin (#147659)
zweckj Jun 27, 2025
8cdc752
Fix Shelly entity removal (#147665)
thecode Jun 27, 2025
5451063
Update frontend to 20250627.0 (#147668)
piitaya Jun 27, 2025
8230557
Fix sentence-casing and spacing of button in `thermopro` (#147671)
NoRi2909 Jun 27, 2025
013a351
Bump aiosomecomfort to 0.0.33 (#147673)
mkmer Jun 27, 2025
e4d8207
Add codeowner for Telegram bot (#147680)
hanwg Jun 27, 2025
1883484
Bump aioamazondevices to 3.1.22 (#147681)
chemelli74 Jun 27, 2025
16c6bd0
Bump version to 2025.7.0b3
frenck Jun 27, 2025
b537850
Bump vulcan-api to 2.4.2 (#146857)
Antoni-Czaplicki Jun 28, 2025
a65eb57
Add lock models to switchbot cloud (#147569)
XiaoLing-git Jun 27, 2025
862b746
Move MQTT device sw and hw version to collapsed section in subentry f…
jbouwh Jun 28, 2025
d3c5684
Fix Shelly Block entity removal (#147694)
thecode Jun 28, 2025
81e712e
Bump pytibber to 0.31.6 (#147703)
Danielhiversen Jun 28, 2025
33e1c6d
Reduce idle timeout of HLS stream to conserve camera battery life (#1…
starkillerOG Jun 28, 2025
4b3449f
Fix error if cover position is not available or unknown (#147732)
mback2k Jun 28, 2025
2f69ed4
bump pypaperless to 4.1.1 (#147735)
fvgarrel Jun 28, 2025
c32b44b
Improve rest error logging (#147736)
bdraco Jun 28, 2025
cf2e69e
Bump version to 2025.7.0b4
balloob Jun 28, 2025
5a0a1bb
Person ble_trackers for non-home zones not processed correctly (#138475)
PeteRager Jun 30, 2025
a8b5d15
Populate hvac_modes list in opentherm_gw (#142074)
mvn23 Jun 30, 2025
578b43c
Bump aioshelly to 13.7.1 (#146221)
thecode Jun 29, 2025
adbace9
Fixed pushbullet handling of fields longer than 255 characters (#146993)
eseverson Jun 30, 2025
1543726
Wallbox Integration, Reduce API impact by limiting the amount of API …
hesselonline Jun 30, 2025
ae48e37
Update pywmspro to 0.3.0 to wait for short-lived actions (#147679)
mback2k Jun 29, 2025
6dc464a
Fix Telegram bot proxy URL not initialized when creating a new bot (#…
hanwg Jun 30, 2025
c771f5f
Preserve httpx boolean behavior in REST integration after aiohttp con…
bdraco Jun 28, 2025
3c7c917
Fix sensor displaying unknown when getting readings from heat meters …
tr4nt0r Jun 30, 2025
b50e599
Move the async_reload on updates in async_setup_entry in Google Gener…
tronikos Jun 29, 2025
62a1c8a
Fix Vesync set_percentage error (#147751)
cdnninja Jun 29, 2025
328e838
Use media selector for Assist Satellite actions (#147767)
balloob Jun 30, 2025
1f6d28d
Honeywell: Don't use shared session (#147772)
mkmer Jun 29, 2025
66cf9c4
Bump reolink_aio to 0.14.2 (#147797)
starkillerOG Jun 30, 2025
e8204e5
Await firmware installation task when flashing ZBT-1/Yellow firmware …
puddly Jun 30, 2025
db04c77
Bump version to 2025.7.0b5
frenck Jun 30, 2025
e4bcde7
Fix wrong state in Husqvarna Automower (#146075)
Thomas55555 Jul 1, 2025
08985d7
Fix Meteo france Ciel clair condition mapping (#146965)
piitaya Jul 1, 2025
414318f
Catch access denied errors in webdav and display proper message (#147…
jpbede Jul 1, 2025
c61935f
Include chat ID in Telegram bot subentry title (#147643)
hanwg Jul 1, 2025
47b232d
Add more mac address prefixes for discovery to PlayStation Network (#…
tr4nt0r Jul 1, 2025
748cc63
fix state_class for water used today sensor (#147787)
bob-laz Jul 1, 2025
f85fc71
Bump Nettigo Air Monitor backend library to version 5.0.0 (#147812)
bieniu Jul 1, 2025
ff25948
fix: Create new aiohttp session with DummyCookieJar (#147827)
micha91 Jul 1, 2025
b25acfe
Fix invalid configuration of MQTT device QoS option in subentry flow …
jbouwh Jul 1, 2025
5554e38
Implement suggested_display_precision for ESPHome (#147849)
jesserockz Jul 1, 2025
c42fc81
Correct Google generative AI config entry migration (#147856)
emontnemery Jul 1, 2025
725269e
Correct anthropic config entry migration (#147857)
emontnemery Jul 1, 2025
8b2f4f0
Correct ollama config entry migration (#147858)
emontnemery Jul 1, 2025
d5d1b62
Correct openai conversation config entry migration (#147859)
emontnemery Jul 1, 2025
e272ab1
Initialize EsphomeEntity._has_state (#147877)
emontnemery Jul 1, 2025
3548ab7
Update frontend to 20250701.0 (#147879)
piitaya Jul 1, 2025
c707bf6
Bump version to 2025.7.0b6
frenck Jul 1, 2025
60a9305
Fix station name sensor for metoffice (#145500)
avee87 Jul 1, 2025
01e7efc
Bump VoIP utils to 0.3.3 (#147880)
jaminh Jul 1, 2025
3ed440a
Bump Music Assistant Client to 1.2.3 (#147885)
marcelveldt Jul 1, 2025
b2c393d
Bump version to 2025.7.0b7
frenck Jul 1, 2025
04ae966
Bump aioamazondevices to 3.2.1 (#147912)
chemelli74 Jul 2, 2025
f838e85
Manager wrong country selection in Alexa Devices (#147914)
chemelli74 Jul 2, 2025
d4dec6c
Swap the Models label for the model name not it's display name, (#147…
IvanLH Jul 2, 2025
fdba791
Bump bluetooth-data-tools to 1.28.2 (#147920)
bdraco Jul 2, 2025
0e6bbb3
Bump version to 2025.7.0b8
frenck Jul 2, 2025
b677ce6
SMA add DHCP strictness (#145753)
erwindouna Jul 2, 2025
b8c19f2
UnifiProtect Change log level from debug to error for connection exce…
RaHehl Jul 2, 2025
fa1bed1
Skip processing request body for HTTP HEAD requests (#147899)
AudunVN Jul 2, 2025
2f27d55
Open repair issue when outbound WebSocket is enabled for Shelly non-s…
bieniu Jul 2, 2025
eb351e6
Bump thermopro-ble to 0.13.1 (#147924)
h3ss Jul 2, 2025
b816f1a
Handle additional errors in Nord Pool (#147937)
gjohansson-ST Jul 2, 2025
1fdf152
Bump deebot-client to 13.5.0 (#147938)
edenhaus Jul 2, 2025
116c745
Split Ollama entity (#147769)
balloob Jun 30, 2025
ec5e543
Ollama: Migrate pick model to subentry (#147944)
balloob Jul 2, 2025
12e8b81
Update frontend to 20250702.0 (#147952)
bramkragten Jul 2, 2025
9472ff5
Bump aioamazondevices to 3.2.2 (#147953)
chemelli74 Jul 2, 2025
4eb688b
Z-Wave JS: rename controller to adapter according to term decision (#…
c0ffeeca7 Jul 2, 2025
8fc3fa5
Bump version to 2025.7.0b9
frenck Jul 2, 2025
8334a03
Bump version to 2025.7.0
frenck Jul 2, 2025
4bc2951
2025.7.0 (#147533)
frenck Jul 2, 2025
c137c96
KNX: use `async_load_json_object_fixture` in tests (#147991)
farmio Jul 3, 2025
142c10c
Fix state being incorrectly reported in some situations on Music Assi…
marcelveldt Jul 3, 2025
a6962e9
Fix missing port in samsungtv (#147962)
epenet Jul 3, 2025
6f4757e
Use runtime_data in melnor (#148013)
epenet Jul 3, 2025
b973916
Move met_eireann coordinator to separate module (#148014)
epenet Jul 3, 2025
04e6947
Fix hass.data reference in lookin (#148008)
epenet Jul 3, 2025
e422352
Use runtime_data in melcloud (#148012)
epenet Jul 3, 2025
d738c0d
Merge branch 'master' into dev
frenck Jul 3, 2025
5008151
Use entry.async_on_unload in monoprice (#148016)
epenet Jul 3, 2025
bfc814c
Use entry.async_on_unload in meteo_france (#148015)
epenet Jul 3, 2025
b1e3561
Clarify description of autorelock setting in `zwave_js` (#148019)
NoRi2909 Jul 3, 2025
7d36a2e
Move meteoclimatic coordinator to separate module (#148018)
epenet Jul 3, 2025
3bc0082
Use runtime_data in mystrom (#148020)
epenet Jul 3, 2025
691681a
Move medcom_ble coordinator to separate module (#148009)
epenet Jul 3, 2025
a656b6e
Use HassKey in media_source (#148011)
epenet Jul 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion homeassistant/components/lookin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ async def async_remove_config_entry_device(
hass: HomeAssistant, entry: LookinConfigEntry, device_entry: dr.DeviceEntry
) -> bool:
"""Remove lookin config entry from a device."""
data: LookinData = hass.data[DOMAIN][entry.entry_id]
data = entry.runtime_data
all_identifiers: set[tuple[str, str]] = {
(DOMAIN, data.lookin_device.id),
*((DOMAIN, remote["UUID"]) for remote in data.devices),
Expand Down
36 changes: 3 additions & 33 deletions homeassistant/components/medcom_ble/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,23 @@

from __future__ import annotations

from datetime import timedelta
import logging

from bleak import BleakError
from medcom_ble import MedcomBleDeviceData

from homeassistant.components import bluetooth
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from homeassistant.util.unit_system import METRIC_SYSTEM

from .const import DEFAULT_SCAN_INTERVAL, DOMAIN
from .const import DOMAIN
from .coordinator import MedcomBleUpdateCoordinator

# Supported platforms
PLATFORMS: list[Platform] = [Platform.SENSOR]

_LOGGER = logging.getLogger(__name__)


async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Medcom BLE radiation monitor from a config entry."""

address = entry.unique_id
elevation = hass.config.elevation
is_metric = hass.config.units is METRIC_SYSTEM
assert address is not None

ble_device = bluetooth.async_ble_device_from_address(hass, address)
Expand All @@ -38,26 +27,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
f"Could not find Medcom BLE device with address {address}"
)

async def _async_update_method():
"""Get data from Medcom BLE radiation monitor."""
ble_device = bluetooth.async_ble_device_from_address(hass, address)
inspector = MedcomBleDeviceData(_LOGGER, elevation, is_metric)

try:
data = await inspector.update_device(ble_device)
except BleakError as err:
raise UpdateFailed(f"Unable to fetch data: {err}") from err

return data

coordinator = DataUpdateCoordinator(
hass,
_LOGGER,
config_entry=entry,
name=DOMAIN,
update_method=_async_update_method,
update_interval=timedelta(seconds=DEFAULT_SCAN_INTERVAL),
)
coordinator = MedcomBleUpdateCoordinator(hass, entry, address)

await coordinator.async_config_entry_first_refresh()

Expand Down
50 changes: 50 additions & 0 deletions homeassistant/components/medcom_ble/coordinator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""The Medcom BLE integration."""

from __future__ import annotations

from datetime import timedelta
import logging

from bleak import BleakError
from medcom_ble import MedcomBleDevice, MedcomBleDeviceData

from homeassistant.components import bluetooth
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from homeassistant.util.unit_system import METRIC_SYSTEM

from .const import DEFAULT_SCAN_INTERVAL, DOMAIN

_LOGGER = logging.getLogger(__name__)


class MedcomBleUpdateCoordinator(DataUpdateCoordinator[MedcomBleDevice]):
"""Coordinator for Medcom BLE radiation monitor data."""

config_entry: ConfigEntry

def __init__(self, hass: HomeAssistant, entry: ConfigEntry, address: str) -> None:
"""Initialize the coordinator."""
super().__init__(
hass,
_LOGGER,
config_entry=entry,
name=DOMAIN,
update_interval=timedelta(seconds=DEFAULT_SCAN_INTERVAL),
)
self._address = address
self._elevation = hass.config.elevation
self._is_metric = hass.config.units is METRIC_SYSTEM

async def _async_update_data(self) -> MedcomBleDevice:
"""Get data from Medcom BLE radiation monitor."""
ble_device = bluetooth.async_ble_device_from_address(self.hass, self._address)
inspector = MedcomBleDeviceData(_LOGGER, self._elevation, self._is_metric)

try:
data = await inspector.update_device(ble_device)
except BleakError as err:
raise UpdateFailed(f"Unable to fetch data: {err}") from err

return data
18 changes: 5 additions & 13 deletions homeassistant/components/medcom_ble/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

import logging

from medcom_ble import MedcomBleDevice

from homeassistant import config_entries
from homeassistant.components.sensor import (
SensorEntity,
Expand All @@ -15,12 +13,10 @@
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import CONNECTION_BLUETOOTH, DeviceInfo
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.update_coordinator import (
CoordinatorEntity,
DataUpdateCoordinator,
)
from homeassistant.helpers.update_coordinator import CoordinatorEntity

from .const import DOMAIN, UNIT_CPM
from .coordinator import MedcomBleUpdateCoordinator

_LOGGER = logging.getLogger(__name__)

Expand All @@ -41,9 +37,7 @@ async def async_setup_entry(
) -> None:
"""Set up Medcom BLE radiation monitor sensors."""

coordinator: DataUpdateCoordinator[MedcomBleDevice] = hass.data[DOMAIN][
entry.entry_id
]
coordinator: MedcomBleUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]

entities = []
_LOGGER.debug("got sensors: %s", coordinator.data.sensors)
Expand All @@ -62,16 +56,14 @@ async def async_setup_entry(
async_add_entities(entities)


class MedcomSensor(
CoordinatorEntity[DataUpdateCoordinator[MedcomBleDevice]], SensorEntity
):
class MedcomSensor(CoordinatorEntity[MedcomBleUpdateCoordinator], SensorEntity):
"""Medcom BLE radiation monitor sensors for the device."""

_attr_has_entity_name = True

def __init__(
self,
coordinator: DataUpdateCoordinator[MedcomBleDevice],
coordinator: MedcomBleUpdateCoordinator,
entity_description: SensorEntityDescription,
) -> None:
"""Populate the medcom entity with relevant data."""
Expand Down
9 changes: 5 additions & 4 deletions homeassistant/components/media_source/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
DOMAIN,
MEDIA_CLASS_MAP,
MEDIA_MIME_TYPES,
MEDIA_SOURCE_DATA,
URI_SCHEME,
URI_SCHEME_REGEX,
)
Expand Down Expand Up @@ -78,7 +79,7 @@ def generate_media_source_id(domain: str, identifier: str) -> str:

async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the media_source component."""
hass.data[DOMAIN] = {}
hass.data[MEDIA_SOURCE_DATA] = {}
websocket_api.async_register_command(hass, websocket_browse_media)
websocket_api.async_register_command(hass, websocket_resolve_media)
frontend.async_register_built_in_panel(
Expand All @@ -97,7 +98,7 @@ async def _process_media_source_platform(
platform: MediaSourceProtocol,
) -> None:
"""Process a media source platform."""
hass.data[DOMAIN][domain] = await platform.async_get_media_source(hass)
hass.data[MEDIA_SOURCE_DATA][domain] = await platform.async_get_media_source(hass)


@callback
Expand All @@ -109,10 +110,10 @@ def _get_media_item(
item = MediaSourceItem.from_uri(hass, media_content_id, target_media_player)
else:
# We default to our own domain if its only one registered
domain = None if len(hass.data[DOMAIN]) > 1 else DOMAIN
domain = None if len(hass.data[MEDIA_SOURCE_DATA]) > 1 else DOMAIN
return MediaSourceItem(hass, domain, "", target_media_player)

if item.domain is not None and item.domain not in hass.data[DOMAIN]:
if item.domain is not None and item.domain not in hass.data[MEDIA_SOURCE_DATA]:
raise UnknownMediaSource(
translation_domain=DOMAIN,
translation_key="unknown_media_source",
Expand Down
8 changes: 8 additions & 0 deletions homeassistant/components/media_source/const.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
"""Constants for the media_source integration."""

from __future__ import annotations

import re
from typing import TYPE_CHECKING

from homeassistant.components.media_player import MediaClass
from homeassistant.util.hass_dict import HassKey

if TYPE_CHECKING:
from .models import MediaSource

DOMAIN = "media_source"
MEDIA_SOURCE_DATA: HassKey[dict[str, MediaSource]] = HassKey(DOMAIN)
MEDIA_MIME_TYPES = ("audio", "video", "image")
MEDIA_CLASS_MAP = {
"audio": MediaClass.MUSIC,
Expand Down
8 changes: 4 additions & 4 deletions homeassistant/components/media_source/local_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import mimetypes
from pathlib import Path
import shutil
from typing import Any
from typing import Any, cast

from aiohttp import web
from aiohttp.web_request import FileField
Expand All @@ -18,7 +18,7 @@
from homeassistant.core import HomeAssistant, callback
from homeassistant.util import raise_if_invalid_filename, raise_if_invalid_path

from .const import DOMAIN, MEDIA_CLASS_MAP, MEDIA_MIME_TYPES
from .const import DOMAIN, MEDIA_CLASS_MAP, MEDIA_MIME_TYPES, MEDIA_SOURCE_DATA
from .error import Unresolvable
from .models import BrowseMediaSource, MediaSource, MediaSourceItem, PlayMedia

Expand All @@ -30,7 +30,7 @@
def async_setup(hass: HomeAssistant) -> None:
"""Set up local media source."""
source = LocalSource(hass)
hass.data[DOMAIN][DOMAIN] = source
hass.data[MEDIA_SOURCE_DATA][DOMAIN] = source
hass.http.register_view(LocalMediaView(hass, source))
hass.http.register_view(UploadMediaView(hass, source))
websocket_api.async_register_command(hass, websocket_remove_media)
Expand Down Expand Up @@ -352,7 +352,7 @@ async def websocket_remove_media(
connection.send_error(msg["id"], websocket_api.ERR_INVALID_FORMAT, str(err))
return

source: LocalSource = hass.data[DOMAIN][DOMAIN]
source = cast(LocalSource, hass.data[MEDIA_SOURCE_DATA][DOMAIN])

try:
source_dir_id, location = source.async_parse_identifier(item)
Expand Down
10 changes: 6 additions & 4 deletions homeassistant/components/media_source/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
from __future__ import annotations

from dataclasses import dataclass
from typing import Any, cast
from typing import TYPE_CHECKING, Any

from homeassistant.components.media_player import BrowseMedia, MediaClass, MediaType
from homeassistant.core import HomeAssistant, callback

from .const import DOMAIN, URI_SCHEME, URI_SCHEME_REGEX
from .const import MEDIA_SOURCE_DATA, URI_SCHEME, URI_SCHEME_REGEX


@dataclass(slots=True)
Expand Down Expand Up @@ -70,7 +70,7 @@ async def async_browse(self) -> BrowseMediaSource:
can_play=False,
can_expand=True,
)
for source in self.hass.data[DOMAIN].values()
for source in self.hass.data[MEDIA_SOURCE_DATA].values()
),
key=lambda item: item.title,
)
Expand All @@ -85,7 +85,9 @@ async def async_resolve(self) -> PlayMedia:
@callback
def async_media_source(self) -> MediaSource:
"""Return media source that owns this item."""
return cast(MediaSource, self.hass.data[DOMAIN][self.domain])
if TYPE_CHECKING:
assert self.domain is not None
return self.hass.data[MEDIA_SOURCE_DATA][self.domain]

@classmethod
def from_uri(
Expand Down
16 changes: 6 additions & 10 deletions homeassistant/components/melcloud/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@

PLATFORMS = [Platform.CLIMATE, Platform.SENSOR, Platform.WATER_HEATER]

type MelCloudConfigEntry = ConfigEntry[dict[str, list[MelCloudDevice]]]

async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Establish connection with MELClooud."""

async def async_setup_entry(hass: HomeAssistant, entry: MelCloudConfigEntry) -> bool:
"""Establish connection with MELCloud."""
conf = entry.data
try:
mel_devices = await mel_devices_setup(hass, conf[CONF_TOKEN])
Expand All @@ -40,20 +42,14 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
except (TimeoutError, ClientConnectionError) as ex:
raise ConfigEntryNotReady from ex

hass.data.setdefault(DOMAIN, {}).update({entry.entry_id: mel_devices})
entry.runtime_data = mel_devices
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
return True


async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
"""Unload a config entry."""
unload_ok = await hass.config_entries.async_unload_platforms(
config_entry, PLATFORMS
)
hass.data[DOMAIN].pop(config_entry.entry_id)
if not hass.data[DOMAIN]:
hass.data.pop(DOMAIN)
return unload_ok
return await hass.config_entries.async_unload_platforms(config_entry, PLATFORMS)


class MelCloudDevice:
Expand Down
8 changes: 3 additions & 5 deletions homeassistant/components/melcloud/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,19 @@
HVACAction,
HVACMode,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_TEMPERATURE, UnitOfTemperature
from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_validation as cv, entity_platform
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback

from . import MelCloudDevice
from . import MelCloudConfigEntry, MelCloudDevice
from .const import (
ATTR_STATUS,
ATTR_VANE_HORIZONTAL,
ATTR_VANE_HORIZONTAL_POSITIONS,
ATTR_VANE_VERTICAL,
ATTR_VANE_VERTICAL_POSITIONS,
CONF_POSITION,
DOMAIN,
SERVICE_SET_VANE_HORIZONTAL,
SERVICE_SET_VANE_VERTICAL,
)
Expand Down Expand Up @@ -77,11 +75,11 @@

async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
entry: MelCloudConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up MelCloud device climate based on config_entry."""
mel_devices = hass.data[DOMAIN][entry.entry_id]
mel_devices = entry.runtime_data
entities: list[AtaDeviceClimate | AtwDeviceZoneClimate] = [
AtaDeviceClimate(mel_device, mel_device.device)
for mel_device in mel_devices[DEVICE_TYPE_ATA]
Expand Down
Loading
Loading