1
0
mirror of https://github.com/home-assistant/core.git synced 2026-05-08 17:49:37 +01:00

Add device storage sensor entities to Xbox (#155657)

This commit is contained in:
Manu
2025-11-12 13:53:42 +01:00
committed by GitHub
parent 78f26edc29
commit b6c8b787e8
10 changed files with 561 additions and 27 deletions
+15 -10
View File
@@ -9,7 +9,12 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_validation as cv
from .const import DOMAIN
from .coordinator import XboxConfigEntry, XboxUpdateCoordinator
from .coordinator import (
XboxConfigEntry,
XboxConsolesCoordinator,
XboxCoordinators,
XboxUpdateCoordinator,
)
_LOGGER = logging.getLogger(__name__)
@@ -30,7 +35,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: XboxConfigEntry) -> bool
coordinator = XboxUpdateCoordinator(hass, entry)
await coordinator.async_config_entry_first_refresh()
entry.runtime_data = coordinator
consoles = XboxConsolesCoordinator(hass, entry, coordinator)
entry.runtime_data = XboxCoordinators(coordinator, consoles)
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
@@ -53,16 +60,14 @@ async def async_migrate_unique_id(hass: HomeAssistant, entry: XboxConfigEntry) -
if entry.version == 1 and entry.minor_version < 2:
# Migrate unique_id from `xbox` to account xuid and
# change generic entry name to user's gamertag
coordinator = entry.runtime_data.status
xuid = coordinator.client.xuid
gamertag = coordinator.data.presence[xuid].gamertag
return hass.config_entries.async_update_entry(
entry,
unique_id=entry.runtime_data.client.xuid,
title=(
entry.runtime_data.data.presence[
entry.runtime_data.client.xuid
].gamertag
if entry.title == "Home Assistant Cloud"
else entry.title
),
unique_id=xuid,
title=(gamertag if entry.title == "Home Assistant Cloud" else entry.title),
minor_version=2,
)
@@ -111,7 +111,7 @@ async def async_setup_entry(
) -> None:
"""Set up Xbox Live friends."""
xuids_added: set[str] = set()
coordinator = entry.runtime_data
coordinator = entry.runtime_data.status
@callback
def add_entities() -> None:
+49 -1
View File
@@ -35,7 +35,7 @@ from .const import DOMAIN
_LOGGER = logging.getLogger(__name__)
type XboxConfigEntry = ConfigEntry[XboxUpdateCoordinator]
type XboxConfigEntry = ConfigEntry[XboxCoordinators]
@dataclass
@@ -55,6 +55,14 @@ class XboxData:
title_info: dict[str, Title] = field(default_factory=dict)
@dataclass
class XboxCoordinators:
"""Xbox coordinators."""
status: XboxUpdateCoordinator
consoles: XboxConsolesCoordinator
class XboxUpdateCoordinator(DataUpdateCoordinator[XboxData]):
"""Store Xbox Console Status."""
@@ -280,3 +288,43 @@ class XboxUpdateCoordinator(DataUpdateCoordinator[XboxData]):
for entry in self.hass.config_entries.async_entries(DOMAIN)
if entry.unique_id is not None
}
class XboxConsolesCoordinator(DataUpdateCoordinator[SmartglassConsoleList]):
"""Update list of Xbox consoles."""
config_entry: XboxConfigEntry
def __init__(
self,
hass: HomeAssistant,
config_entry: XboxConfigEntry,
coordinator: XboxUpdateCoordinator,
) -> None:
"""Initialize."""
super().__init__(
hass,
_LOGGER,
config_entry=config_entry,
name=DOMAIN,
update_interval=timedelta(minutes=10),
)
self.client = coordinator.client
self.async_set_updated_data(coordinator.consoles)
async def _async_update_data(self) -> SmartglassConsoleList:
"""Fetch console data."""
try:
return await self.client.smartglass.get_console_list()
except TimeoutException as e:
raise UpdateFailed(
translation_domain=DOMAIN,
translation_key="timeout_exception",
) from e
except (RequestError, HTTPStatusError) as e:
_LOGGER.debug("Xbox exception:", exc_info=True)
raise UpdateFailed(
translation_domain=DOMAIN,
translation_key="request_exception",
) from e
+1 -1
View File
@@ -64,7 +64,7 @@ async def async_setup_entry(
) -> None:
"""Set up Xbox images."""
coordinator = config_entry.runtime_data
coordinator = config_entry.runtime_data.status
xuids_added: set[str] = set()
@@ -56,7 +56,7 @@ async def async_setup_entry(
) -> None:
"""Set up Xbox media_player from a config entry."""
coordinator = entry.runtime_data
coordinator = entry.runtime_data.status
async_add_entities(
[
@@ -112,7 +112,7 @@ class XboxSource(MediaSource):
translation_key="account_not_configured",
) from e
client = entry.runtime_data.client
client = entry.runtime_data.status.client
if identifier.media_type in (ATTR_GAMECLIPS, ATTR_COMMUNITY_GAMECLIPS):
try:
@@ -302,7 +302,7 @@ class XboxSource(MediaSource):
async def _build_games(self, entry: XboxConfigEntry) -> list[BrowseMediaSource]:
"""List Xbox games for the selected account."""
client = entry.runtime_data.client
client = entry.runtime_data.status.client
if TYPE_CHECKING:
assert entry.unique_id
fields = [
@@ -346,7 +346,7 @@ class XboxSource(MediaSource):
self, entry: XboxConfigEntry, identifier: XboxMediaSourceIdentifier
) -> BrowseMediaSource:
"""Display game title."""
client = entry.runtime_data.client
client = entry.runtime_data.status.client
try:
game = (await client.titlehub.get_title_info(identifier.title_id)).titles[0]
except TimeoutException as e:
@@ -402,7 +402,7 @@ class XboxSource(MediaSource):
self, entry: XboxConfigEntry, identifier: XboxMediaSourceIdentifier
) -> BrowseMediaSource:
"""List game media."""
client = entry.runtime_data.client
client = entry.runtime_data.status.client
try:
game = (await client.titlehub.get_title_info(identifier.title_id)).titles[0]
except TimeoutException as e:
@@ -439,7 +439,7 @@ class XboxSource(MediaSource):
self, entry: XboxConfigEntry, identifier: XboxMediaSourceIdentifier
) -> list[BrowseMediaSource]:
"""List media items."""
client = entry.runtime_data.client
client = entry.runtime_data.status.client
if identifier.media_type != ATTR_GAMECLIPS:
return []
@@ -483,7 +483,7 @@ class XboxSource(MediaSource):
self, entry: XboxConfigEntry, identifier: XboxMediaSourceIdentifier
) -> list[BrowseMediaSource]:
"""List media items."""
client = entry.runtime_data.client
client = entry.runtime_data.status.client
if identifier.media_type != ATTR_COMMUNITY_GAMECLIPS:
return []
@@ -527,7 +527,7 @@ class XboxSource(MediaSource):
self, entry: XboxConfigEntry, identifier: XboxMediaSourceIdentifier
) -> list[BrowseMediaSource]:
"""List media items."""
client = entry.runtime_data.client
client = entry.runtime_data.status.client
if identifier.media_type != ATTR_SCREENSHOTS:
return []
@@ -571,7 +571,7 @@ class XboxSource(MediaSource):
self, entry: XboxConfigEntry, identifier: XboxMediaSourceIdentifier
) -> list[BrowseMediaSource]:
"""List media items."""
client = entry.runtime_data.client
client = entry.runtime_data.status.client
if identifier.media_type != ATTR_COMMUNITY_SCREENSHOTS:
return []
@@ -640,7 +640,7 @@ class XboxSource(MediaSource):
def gamerpic(config_entry: XboxConfigEntry) -> str | None:
"""Return gamerpic."""
coordinator = config_entry.runtime_data
coordinator = config_entry.runtime_data.status
if TYPE_CHECKING:
assert config_entry.unique_id
person = coordinator.data.presence[coordinator.client.xuid]
+1 -1
View File
@@ -27,7 +27,7 @@ async def async_setup_entry(
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up Xbox media_player from a config entry."""
coordinator = entry.runtime_data
coordinator = entry.runtime_data.status
async_add_entities(
[XboxRemote(console, coordinator) for console in coordinator.consoles.result]
+124 -3
View File
@@ -9,20 +9,32 @@ from enum import StrEnum
from typing import Any
from pythonxbox.api.provider.people.models import Person
from pythonxbox.api.provider.smartglass.models import SmartglassConsole, StorageDevice
from pythonxbox.api.provider.titlehub.models import Title
from homeassistant.components.sensor import (
DOMAIN as SENSOR_DOMAIN,
EntityCategory,
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.const import CONF_NAME, UnitOfInformation
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.typing import StateType
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .coordinator import XboxConfigEntry
from .entity import XboxBaseEntity, XboxBaseEntityDescription, check_deprecated_entity
from .const import DOMAIN
from .coordinator import XboxConfigEntry, XboxConsolesCoordinator
from .entity import (
MAP_MODEL,
XboxBaseEntity,
XboxBaseEntityDescription,
check_deprecated_entity,
)
MAP_JOIN_RESTRICTIONS = {
"local": "invite_only",
@@ -44,6 +56,8 @@ class XboxSensor(StrEnum):
FRIENDS = "friends"
IN_PARTY = "in_party"
JOIN_RESTRICTIONS = "join_restrictions"
TOTAL_STORAGE = "total_storage"
FREE_STORAGE = "free_storage"
@dataclass(kw_only=True, frozen=True)
@@ -53,6 +67,15 @@ class XboxSensorEntityDescription(XboxBaseEntityDescription, SensorEntityDescrip
value_fn: Callable[[Person, Title | None], StateType | datetime]
@dataclass(kw_only=True, frozen=True)
class XboxStorageDeviceSensorEntityDescription(
XboxBaseEntityDescription, SensorEntityDescription
):
"""Xbox console sensor description."""
value_fn: Callable[[StorageDevice], StateType]
def now_playing_attributes(_: Person, title: Title | None) -> dict[str, Any]:
"""Attributes of the currently played title."""
attributes: dict[str, Any] = {
@@ -195,6 +218,31 @@ SENSOR_DESCRIPTIONS: tuple[XboxSensorEntityDescription, ...] = (
),
)
STORAGE_SENSOR_DESCRIPTIONS: tuple[XboxStorageDeviceSensorEntityDescription, ...] = (
XboxStorageDeviceSensorEntityDescription(
key=XboxSensor.TOTAL_STORAGE,
translation_key=XboxSensor.TOTAL_STORAGE,
value_fn=lambda x: x.total_space_bytes,
device_class=SensorDeviceClass.DATA_SIZE,
native_unit_of_measurement=UnitOfInformation.BYTES,
suggested_unit_of_measurement=UnitOfInformation.GIBIBYTES,
suggested_display_precision=0,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.MEASUREMENT,
),
XboxStorageDeviceSensorEntityDescription(
key=XboxSensor.FREE_STORAGE,
translation_key=XboxSensor.FREE_STORAGE,
value_fn=lambda x: x.free_space_bytes,
device_class=SensorDeviceClass.DATA_SIZE,
native_unit_of_measurement=UnitOfInformation.BYTES,
suggested_unit_of_measurement=UnitOfInformation.GIBIBYTES,
suggested_display_precision=0,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.MEASUREMENT,
),
)
async def async_setup_entry(
hass: HomeAssistant,
@@ -203,7 +251,7 @@ async def async_setup_entry(
) -> None:
"""Set up Xbox Live friends."""
xuids_added: set[str] = set()
coordinator = config_entry.runtime_data
coordinator = config_entry.runtime_data.status
@callback
def add_entities() -> None:
@@ -225,6 +273,20 @@ async def async_setup_entry(
coordinator.async_add_listener(add_entities)
add_entities()
consoles_coordinator = config_entry.runtime_data.consoles
async_add_entities(
[
XboxStorageDeviceSensorEntity(
console, storage_device, consoles_coordinator, description
)
for description in STORAGE_SENSOR_DESCRIPTIONS
for console in coordinator.consoles.result
if console.storage_devices
for storage_device in console.storage_devices
]
)
class XboxSensorEntity(XboxBaseEntity, SensorEntity):
"""Representation of a Xbox presence state."""
@@ -235,3 +297,62 @@ class XboxSensorEntity(XboxBaseEntity, SensorEntity):
def native_value(self) -> StateType | datetime:
"""Return the state of the requested attribute."""
return self.entity_description.value_fn(self.data, self.title_info)
class XboxStorageDeviceSensorEntity(
CoordinatorEntity[XboxConsolesCoordinator], SensorEntity
):
"""Console storage device entity for the Xbox integration."""
_attr_has_entity_name = True
entity_description: XboxStorageDeviceSensorEntityDescription
def __init__(
self,
console: SmartglassConsole,
storage_device: StorageDevice,
coordinator: XboxConsolesCoordinator,
entity_description: XboxStorageDeviceSensorEntityDescription,
) -> None:
"""Initialize the Xbox Console entity."""
super().__init__(coordinator)
self.entity_description = entity_description
self.client = coordinator.client
self._console = console
self._storage_device = storage_device
self._attr_unique_id = (
f"{console.id}_{storage_device.storage_device_id}_{entity_description.key}"
)
self._attr_translation_placeholders = {
CONF_NAME: storage_device.storage_device_name
}
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, console.id)},
manufacturer="Microsoft",
model=MAP_MODEL.get(self._console.console_type, "Unknown"),
name=console.name,
)
@property
def data(self):
"""Storage device data."""
consoles = self.coordinator.data.result
console = next((c for c in consoles if c.id == self._console.id), None)
if not console or not console.storage_devices:
return None
return next(
(
d
for d in console.storage_devices
if d.storage_device_id == self._storage_device.storage_device_id
),
None,
)
@property
def native_value(self) -> StateType:
"""Return the state of the requested attribute."""
return self.entity_description.value_fn(self.data) if self.data else None
@@ -65,6 +65,9 @@
"name": "Following",
"unit_of_measurement": "people"
},
"free_storage": {
"name": "Free space - {name}"
},
"friends": {
"name": "Friends",
"unit_of_measurement": "[%key:component::xbox::entity::sensor::following::unit_of_measurement%]"
@@ -105,6 +108,9 @@
},
"status": {
"name": "Status"
},
"total_storage": {
"name": "Total space - {name}"
}
}
},
@@ -1371,3 +1371,357 @@
'state': 'Offline',
})
# ---
# name: test_sensors[sensor.xone_free_space_external-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.xone_free_space_external',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
'sensor': dict({
'suggested_display_precision': 0,
}),
'sensor.private': dict({
'suggested_unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
}),
}),
'original_device_class': <SensorDeviceClass.DATA_SIZE: 'data_size'>,
'original_icon': None,
'original_name': 'Free space - External',
'platform': 'xbox',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': <XboxSensor.FREE_STORAGE: 'free_storage'>,
'unique_id': 'HIJKLMN_3_free_storage',
'unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
})
# ---
# name: test_sensors[sensor.xone_free_space_external-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'data_size',
'friendly_name': 'XONE Free space - External',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
}),
'context': <ANY>,
'entity_id': 'sensor.xone_free_space_external',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '2980.89726638794',
})
# ---
# name: test_sensors[sensor.xone_free_space_internal-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.xone_free_space_internal',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
'sensor': dict({
'suggested_display_precision': 0,
}),
'sensor.private': dict({
'suggested_unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
}),
}),
'original_device_class': <SensorDeviceClass.DATA_SIZE: 'data_size'>,
'original_icon': None,
'original_name': 'Free space - Internal',
'platform': 'xbox',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': <XboxSensor.FREE_STORAGE: 'free_storage'>,
'unique_id': 'HIJKLMN_2_free_storage',
'unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
})
# ---
# name: test_sensors[sensor.xone_free_space_internal-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'data_size',
'friendly_name': 'XONE Free space - Internal',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
}),
'context': <ANY>,
'entity_id': 'sensor.xone_free_space_internal',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '137.056728363037',
})
# ---
# name: test_sensors[sensor.xone_total_space_external-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.xone_total_space_external',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
'sensor': dict({
'suggested_display_precision': 0,
}),
'sensor.private': dict({
'suggested_unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
}),
}),
'original_device_class': <SensorDeviceClass.DATA_SIZE: 'data_size'>,
'original_icon': None,
'original_name': 'Total space - External',
'platform': 'xbox',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': <XboxSensor.TOTAL_STORAGE: 'total_storage'>,
'unique_id': 'HIJKLMN_3_total_storage',
'unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
})
# ---
# name: test_sensors[sensor.xone_total_space_external-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'data_size',
'friendly_name': 'XONE Total space - External',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
}),
'context': <ANY>,
'entity_id': 'sensor.xone_total_space_external',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '3726.02327680588',
})
# ---
# name: test_sensors[sensor.xone_total_space_internal-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.xone_total_space_internal',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
'sensor': dict({
'suggested_display_precision': 0,
}),
'sensor.private': dict({
'suggested_unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
}),
}),
'original_device_class': <SensorDeviceClass.DATA_SIZE: 'data_size'>,
'original_icon': None,
'original_name': 'Total space - Internal',
'platform': 'xbox',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': <XboxSensor.TOTAL_STORAGE: 'total_storage'>,
'unique_id': 'HIJKLMN_2_total_storage',
'unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
})
# ---
# name: test_sensors[sensor.xone_total_space_internal-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'data_size',
'friendly_name': 'XONE Total space - Internal',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
}),
'context': <ANY>,
'entity_id': 'sensor.xone_total_space_internal',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '364.999996185303',
})
# ---
# name: test_sensors[sensor.xonex_free_space_internal-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.xonex_free_space_internal',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
'sensor': dict({
'suggested_display_precision': 0,
}),
'sensor.private': dict({
'suggested_unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
}),
}),
'original_device_class': <SensorDeviceClass.DATA_SIZE: 'data_size'>,
'original_icon': None,
'original_name': 'Free space - Internal',
'platform': 'xbox',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': <XboxSensor.FREE_STORAGE: 'free_storage'>,
'unique_id': 'ABCDEFG_1_free_storage',
'unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
})
# ---
# name: test_sensors[sensor.xonex_free_space_internal-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'data_size',
'friendly_name': 'XONEX Free space - Internal',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
}),
'context': <ANY>,
'entity_id': 'sensor.xonex_free_space_internal',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '220.041568756104',
})
# ---
# name: test_sensors[sensor.xonex_total_space_internal-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.xonex_total_space_internal',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
'sensor': dict({
'suggested_display_precision': 0,
}),
'sensor.private': dict({
'suggested_unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
}),
}),
'original_device_class': <SensorDeviceClass.DATA_SIZE: 'data_size'>,
'original_icon': None,
'original_name': 'Total space - Internal',
'platform': 'xbox',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': <XboxSensor.TOTAL_STORAGE: 'total_storage'>,
'unique_id': 'ABCDEFG_1_total_storage',
'unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
})
# ---
# name: test_sensors[sensor.xonex_total_space_internal-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'data_size',
'friendly_name': 'XONEX Total space - Internal',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
}),
'context': <ANY>,
'entity_id': 'sensor.xonex_total_space_internal',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '780.999996185303',
})
# ---