mirror of
https://github.com/home-assistant/core.git
synced 2025-12-01 21:48:03 +00:00
Compare commits
30 Commits
add-app-pa
...
copilot/su
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
70668bf6f0 | ||
|
|
4b8202b828 | ||
|
|
0af8c8fd8c | ||
|
|
b9d6c3b9fe | ||
|
|
b700940bb9 | ||
|
|
3b73f6d37e | ||
|
|
2812bb21da | ||
|
|
5d474675e8 | ||
|
|
ea7bcf6cda | ||
|
|
43ba10eebd | ||
|
|
64bed19805 | ||
|
|
6357067f0f | ||
|
|
e328ba4045 | ||
|
|
332dbddce6 | ||
|
|
82d935a819 | ||
|
|
4b84998c0c | ||
|
|
725bd3d671 | ||
|
|
cfc4fa6342 | ||
|
|
b650e71660 | ||
|
|
9ddf15e348 | ||
|
|
15082f9111 | ||
|
|
12f16611ff | ||
|
|
8041be3d08 | ||
|
|
40b021e755 | ||
|
|
aab57eda96 | ||
|
|
f0dd37caa5 | ||
|
|
662b178495 | ||
|
|
cb3d30884a | ||
|
|
49e6f20372 | ||
|
|
75d02661eb |
@@ -68,9 +68,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: BoschAlarmConfigEntry) -
|
||||
config_entry_id=entry.entry_id,
|
||||
connections={(CONNECTION_NETWORK_MAC, mac)} if mac else set(),
|
||||
identifiers={(DOMAIN, entry.unique_id or entry.entry_id)},
|
||||
name=f"Bosch {panel.model}",
|
||||
name=f"Bosch {panel.model.name}",
|
||||
manufacturer="Bosch Security Systems",
|
||||
model=panel.model,
|
||||
model=panel.model.name,
|
||||
sw_version=panel.firmware_version,
|
||||
)
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
|
||||
@@ -83,7 +83,7 @@ async def try_connect(
|
||||
finally:
|
||||
await panel.disconnect()
|
||||
|
||||
return (panel.model, panel.serial_number)
|
||||
return (panel.model.name, panel.serial_number)
|
||||
|
||||
|
||||
class BoschAlarmConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
|
||||
@@ -20,7 +20,8 @@ async def async_get_config_entry_diagnostics(
|
||||
return {
|
||||
"entry_data": async_redact_data(entry.data, TO_REDACT),
|
||||
"data": {
|
||||
"model": entry.runtime_data.model,
|
||||
"model": entry.runtime_data.model.name,
|
||||
"family": entry.runtime_data.model.family.name,
|
||||
"serial_number": entry.runtime_data.serial_number,
|
||||
"protocol_version": entry.runtime_data.protocol_version,
|
||||
"firmware_version": entry.runtime_data.firmware_version,
|
||||
|
||||
@@ -26,7 +26,7 @@ class BoschAlarmEntity(Entity):
|
||||
self._attr_should_poll = False
|
||||
self._attr_device_info = DeviceInfo(
|
||||
identifiers={(DOMAIN, unique_id)},
|
||||
name=f"Bosch {panel.model}",
|
||||
name=f"Bosch {panel.model.name}",
|
||||
manufacturer="Bosch Security Systems",
|
||||
)
|
||||
|
||||
|
||||
@@ -12,5 +12,5 @@
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_push",
|
||||
"quality_scale": "platinum",
|
||||
"requirements": ["bosch-alarm-mode2==0.4.6"]
|
||||
"requirements": ["bosch-alarm-mode2==0.4.10"]
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"mqtt": ["esphome/discover/#"],
|
||||
"quality_scale": "platinum",
|
||||
"requirements": [
|
||||
"aioesphomeapi==42.8.0",
|
||||
"aioesphomeapi==42.9.0",
|
||||
"esphome-dashboard-api==1.3.0",
|
||||
"bleak-esphome==3.4.0"
|
||||
],
|
||||
|
||||
@@ -8,5 +8,5 @@
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["google_air_quality_api"],
|
||||
"quality_scale": "bronze",
|
||||
"requirements": ["google_air_quality_api==1.1.2"]
|
||||
"requirements": ["google_air_quality_api==1.1.3"]
|
||||
}
|
||||
|
||||
@@ -183,6 +183,16 @@ PUMP_CONTROL_MODE_MAP = {
|
||||
clusters.PumpConfigurationAndControl.Enums.ControlModeEnum.kUnknownEnumValue: None,
|
||||
}
|
||||
|
||||
SETPOINT_CHANGE_SOURCE_MAP = {
|
||||
clusters.Thermostat.Enums.SetpointChangeSourceEnum.kManual: "manual",
|
||||
clusters.Thermostat.Enums.SetpointChangeSourceEnum.kSchedule: "schedule",
|
||||
clusters.Thermostat.Enums.SetpointChangeSourceEnum.kExternal: "external",
|
||||
clusters.Thermostat.Enums.SetpointChangeSourceEnum.kUnknownEnumValue: None,
|
||||
}
|
||||
|
||||
MATTER_2000_TO_UNIX_EPOCH_OFFSET = (
|
||||
946684800 # Seconds from Matter 2000 epoch to Unix epoch
|
||||
)
|
||||
HUMIDITY_SCALING_FACTOR = 100
|
||||
TEMPERATURE_SCALING_FACTOR = 100
|
||||
|
||||
@@ -1488,4 +1498,54 @@ DISCOVERY_SCHEMAS = [
|
||||
entity_class=MatterSensor,
|
||||
required_attributes=(clusters.ServiceArea.Attributes.EstimatedEndTime,),
|
||||
),
|
||||
MatterDiscoverySchema(
|
||||
platform=Platform.SENSOR,
|
||||
entity_description=MatterSensorEntityDescription(
|
||||
key="SetpointChangeSource",
|
||||
translation_key="setpoint_change_source",
|
||||
device_class=SensorDeviceClass.ENUM,
|
||||
state_class=None,
|
||||
options=[x for x in SETPOINT_CHANGE_SOURCE_MAP.values() if x is not None],
|
||||
device_to_ha=lambda x: SETPOINT_CHANGE_SOURCE_MAP[x],
|
||||
),
|
||||
entity_class=MatterSensor,
|
||||
required_attributes=(clusters.Thermostat.Attributes.SetpointChangeSource,),
|
||||
device_type=(device_types.Thermostat,),
|
||||
),
|
||||
MatterDiscoverySchema(
|
||||
platform=Platform.SENSOR,
|
||||
entity_description=MatterSensorEntityDescription(
|
||||
key="SetpointChangeSourceTimestamp",
|
||||
translation_key="setpoint_change_timestamp",
|
||||
device_class=SensorDeviceClass.TIMESTAMP,
|
||||
state_class=None,
|
||||
device_to_ha=(
|
||||
lambda x: (
|
||||
dt_util.utc_from_timestamp(x + MATTER_2000_TO_UNIX_EPOCH_OFFSET)
|
||||
if x > 0
|
||||
else None
|
||||
)
|
||||
),
|
||||
),
|
||||
entity_class=MatterSensor,
|
||||
required_attributes=(
|
||||
clusters.Thermostat.Attributes.SetpointChangeSourceTimestamp,
|
||||
),
|
||||
device_type=(device_types.Thermostat,),
|
||||
),
|
||||
MatterDiscoverySchema(
|
||||
platform=Platform.SENSOR,
|
||||
entity_description=MatterSensorEntityDescription(
|
||||
key="ThermostatSetpointChangeAmount",
|
||||
translation_key="setpoint_change_amount",
|
||||
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
||||
suggested_display_precision=1,
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
device_to_ha=lambda x: x / TEMPERATURE_SCALING_FACTOR,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
entity_class=MatterSensor,
|
||||
required_attributes=(clusters.Thermostat.Attributes.SetpointChangeAmount,),
|
||||
device_type=(device_types.Thermostat,),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -528,6 +528,20 @@
|
||||
"rms_voltage": {
|
||||
"name": "Effective voltage"
|
||||
},
|
||||
"setpoint_change_amount": {
|
||||
"name": "Last change amount"
|
||||
},
|
||||
"setpoint_change_source": {
|
||||
"name": "Last change source",
|
||||
"state": {
|
||||
"external": "External",
|
||||
"manual": "Manual",
|
||||
"schedule": "Schedule"
|
||||
}
|
||||
},
|
||||
"setpoint_change_timestamp": {
|
||||
"name": "Last change"
|
||||
},
|
||||
"switch_current_position": {
|
||||
"name": "Current switch position"
|
||||
},
|
||||
|
||||
@@ -19,5 +19,5 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/nest",
|
||||
"iot_class": "cloud_push",
|
||||
"loggers": ["google_nest_sdm"],
|
||||
"requirements": ["google-nest-sdm==9.1.0"]
|
||||
"requirements": ["google-nest-sdm==9.1.1"]
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ class RpcBluTrvBinarySensor(RpcBinarySensor):
|
||||
)
|
||||
|
||||
|
||||
SENSORS: dict[tuple[str, str], BlockBinarySensorDescription] = {
|
||||
BLOCK_SENSORS: dict[tuple[str, str], BlockBinarySensorDescription] = {
|
||||
("device", "overtemp"): BlockBinarySensorDescription(
|
||||
key="device|overtemp",
|
||||
translation_key="overheating",
|
||||
@@ -376,7 +376,7 @@ def _async_setup_block_entry(
|
||||
hass,
|
||||
config_entry,
|
||||
async_add_entities,
|
||||
SENSORS,
|
||||
BLOCK_SENSORS,
|
||||
BlockSleepingBinarySensor,
|
||||
)
|
||||
else:
|
||||
@@ -384,7 +384,7 @@ def _async_setup_block_entry(
|
||||
hass,
|
||||
config_entry,
|
||||
async_add_entities,
|
||||
SENSORS,
|
||||
BLOCK_SENSORS,
|
||||
BlockBinarySensor,
|
||||
)
|
||||
async_setup_entry_rest(
|
||||
|
||||
@@ -198,7 +198,7 @@ class RpcBluTrvSensor(RpcSensor):
|
||||
)
|
||||
|
||||
|
||||
SENSORS: dict[tuple[str, str], BlockSensorDescription] = {
|
||||
BLOCK_SENSORS: dict[tuple[str, str], BlockSensorDescription] = {
|
||||
("device", "battery"): BlockSensorDescription(
|
||||
key="device|battery",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
@@ -1740,7 +1740,7 @@ def _async_setup_block_entry(
|
||||
hass,
|
||||
config_entry,
|
||||
async_add_entities,
|
||||
SENSORS,
|
||||
BLOCK_SENSORS,
|
||||
BlockSleepingSensor,
|
||||
)
|
||||
else:
|
||||
@@ -1748,7 +1748,7 @@ def _async_setup_block_entry(
|
||||
hass,
|
||||
config_entry,
|
||||
async_add_entities,
|
||||
SENSORS,
|
||||
BLOCK_SENSORS,
|
||||
BlockSensor,
|
||||
)
|
||||
async_setup_entry_rest(
|
||||
|
||||
@@ -15,7 +15,7 @@ from uiprotect.exceptions import BadRequest, ClientError, NotAuthorized
|
||||
# diagnostics module will not be imported in the executor.
|
||||
from uiprotect.test_util.anonymize import anonymize_data # noqa: F401
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry, ConfigEntryState
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.const import CONF_API_KEY, EVENT_HOMEASSISTANT_STOP
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import (
|
||||
@@ -208,7 +208,7 @@ async def async_remove_config_entry_device(
|
||||
return True
|
||||
|
||||
|
||||
async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
async def async_migrate_entry(hass: HomeAssistant, entry: UFPConfigEntry) -> bool:
|
||||
"""Migrate entry."""
|
||||
_LOGGER.debug("Migrating configuration from version %s", entry.version)
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ import voluptuous as vol
|
||||
|
||||
from homeassistant.config_entries import (
|
||||
SOURCE_IGNORE,
|
||||
ConfigEntry,
|
||||
ConfigEntryState,
|
||||
ConfigFlow,
|
||||
ConfigFlowResult,
|
||||
@@ -55,7 +54,7 @@ from .const import (
|
||||
MIN_REQUIRED_PROTECT_V,
|
||||
OUTDATED_LOG_MESSAGE,
|
||||
)
|
||||
from .data import async_last_update_was_successful
|
||||
from .data import UFPConfigEntry, async_last_update_was_successful
|
||||
from .discovery import async_start_discovery
|
||||
from .utils import _async_resolve, _async_short_mac, _async_unifi_mac_from_hass
|
||||
|
||||
@@ -80,7 +79,7 @@ def _host_is_direct_connect(host: str) -> bool:
|
||||
|
||||
async def _async_console_is_offline(
|
||||
hass: HomeAssistant,
|
||||
entry: ConfigEntry,
|
||||
entry: UFPConfigEntry,
|
||||
) -> bool:
|
||||
"""Check if a console is offline.
|
||||
|
||||
@@ -224,7 +223,7 @@ class ProtectFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
@staticmethod
|
||||
@callback
|
||||
def async_get_options_flow(
|
||||
config_entry: ConfigEntry,
|
||||
config_entry: UFPConfigEntry,
|
||||
) -> OptionsFlowHandler:
|
||||
"""Get the options flow for this handler."""
|
||||
return OptionsFlowHandler()
|
||||
|
||||
@@ -23,6 +23,7 @@ from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
|
||||
from .const import DOMAIN
|
||||
from .data import ProtectDeviceType, UFPConfigEntry
|
||||
from .entity import ProtectDeviceEntity
|
||||
|
||||
@@ -123,7 +124,10 @@ class ProtectMediaPlayer(ProtectDeviceEntity, MediaPlayerEntity):
|
||||
media_id = async_process_play_media_url(self.hass, play_item.url)
|
||||
|
||||
if media_type != MediaType.MUSIC:
|
||||
raise HomeAssistantError("Only music media type is supported")
|
||||
raise HomeAssistantError(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="only_music_supported",
|
||||
)
|
||||
|
||||
_LOGGER.debug(
|
||||
"Playing Media %s for %s Speaker", media_id, self.device.display_name
|
||||
@@ -132,7 +136,11 @@ class ProtectMediaPlayer(ProtectDeviceEntity, MediaPlayerEntity):
|
||||
try:
|
||||
await self.device.play_audio(media_id, blocking=False)
|
||||
except StreamError as err:
|
||||
raise HomeAssistantError(err) from err
|
||||
_LOGGER.debug("Error playing audio: %s", err)
|
||||
raise HomeAssistantError(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="stream_error",
|
||||
) from err
|
||||
|
||||
# update state after starting player
|
||||
self._async_updated_event(self.device)
|
||||
|
||||
@@ -10,7 +10,6 @@ import voluptuous as vol
|
||||
|
||||
from homeassistant import data_entry_flow
|
||||
from homeassistant.components.repairs import ConfirmRepairFlow, RepairsFlow
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import issue_registry as ir
|
||||
|
||||
@@ -165,7 +164,7 @@ class RTSPRepair(ProtectRepair):
|
||||
|
||||
@callback
|
||||
def _async_get_or_create_api_client(
|
||||
hass: HomeAssistant, entry: ConfigEntry
|
||||
hass: HomeAssistant, entry: UFPConfigEntry
|
||||
) -> ProtectApiClient:
|
||||
"""Get or create an API client."""
|
||||
if data := async_get_data_for_entry_id(hass, entry.entry_id):
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
from typing import Any, cast
|
||||
|
||||
from pydantic import ValidationError
|
||||
@@ -45,6 +46,8 @@ from .const import (
|
||||
)
|
||||
from .data import async_ufp_instance_for_config_entry_ids
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
SERVICE_ADD_DOORBELL_TEXT = "add_doorbell_text"
|
||||
SERVICE_REMOVE_DOORBELL_TEXT = "remove_doorbell_text"
|
||||
SERVICE_SET_PRIVACY_ZONE = "set_privacy_zone"
|
||||
@@ -92,7 +95,11 @@ GET_USER_KEYRING_INFO_SCHEMA = vol.Schema(
|
||||
def _async_get_ufp_instance(hass: HomeAssistant, device_id: str) -> ProtectApiClient:
|
||||
device_registry = dr.async_get(hass)
|
||||
if not (device_entry := device_registry.async_get(device_id)):
|
||||
raise HomeAssistantError(f"No device found for device id: {device_id}")
|
||||
raise HomeAssistantError(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="device_not_found",
|
||||
translation_placeholders={"device_id": device_id},
|
||||
)
|
||||
|
||||
if device_entry.via_device_id is not None:
|
||||
return _async_get_ufp_instance(hass, device_entry.via_device_id)
|
||||
@@ -101,7 +108,11 @@ def _async_get_ufp_instance(hass: HomeAssistant, device_id: str) -> ProtectApiCl
|
||||
if ufp_instance := async_ufp_instance_for_config_entry_ids(hass, config_entry_ids):
|
||||
return ufp_instance
|
||||
|
||||
raise HomeAssistantError(f"No device found for device id: {device_id}")
|
||||
raise HomeAssistantError(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="device_not_found",
|
||||
translation_placeholders={"device_id": device_id},
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
@@ -141,7 +152,11 @@ async def _async_service_call_nvr(
|
||||
*(getattr(i.bootstrap.nvr, method)(*args, **kwargs) for i in instances)
|
||||
)
|
||||
except (ClientError, ValidationError) as err:
|
||||
raise HomeAssistantError(str(err)) from err
|
||||
_LOGGER.debug("Error calling UniFi Protect service: %s", err)
|
||||
raise HomeAssistantError(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="service_error",
|
||||
) from err
|
||||
|
||||
|
||||
async def add_doorbell_text(call: ServiceCall) -> None:
|
||||
@@ -170,7 +185,12 @@ async def remove_privacy_zone(call: ServiceCall) -> None:
|
||||
|
||||
if remove_index is None:
|
||||
raise ServiceValidationError(
|
||||
f"Could not find privacy zone with name {name} on camera {camera.display_name}."
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="privacy_zone_not_found",
|
||||
translation_placeholders={
|
||||
"zone_name": name,
|
||||
"camera_name": camera.display_name,
|
||||
},
|
||||
)
|
||||
|
||||
def remove_zone() -> None:
|
||||
@@ -230,7 +250,10 @@ async def get_user_keyring_info(call: ServiceCall) -> ServiceResponse:
|
||||
camera = _async_get_ufp_camera(call)
|
||||
ulp_users = camera.api.bootstrap.ulp_users.as_list()
|
||||
if not ulp_users:
|
||||
raise HomeAssistantError("No users found, please check Protect permissions.")
|
||||
raise HomeAssistantError(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="no_users_found",
|
||||
)
|
||||
|
||||
user_keyrings: list[JsonValueType] = [
|
||||
{
|
||||
|
||||
@@ -20,7 +20,9 @@
|
||||
"username": "[%key:common::config_flow::data::username%]"
|
||||
},
|
||||
"data_description": {
|
||||
"api_key": "API key for your local user account."
|
||||
"api_key": "[%key:component::unifiprotect::config::step::user::data_description::api_key%]",
|
||||
"password": "[%key:component::unifiprotect::config::step::user::data_description::password%]",
|
||||
"username": "[%key:component::unifiprotect::config::step::user::data_description::username%]"
|
||||
},
|
||||
"description": "Do you want to set up {name} ({ip_address})? You will need a local user created in your UniFi OS Console to log in with. Ubiquiti Cloud users will not work. For more information: {local_user_documentation_url}",
|
||||
"title": "UniFi Protect discovered"
|
||||
@@ -34,8 +36,11 @@
|
||||
"username": "[%key:common::config_flow::data::username%]"
|
||||
},
|
||||
"data_description": {
|
||||
"api_key": "API key for your local user account.",
|
||||
"username": "Username for your local (not cloud) user account."
|
||||
"api_key": "[%key:component::unifiprotect::config::step::user::data_description::api_key%]",
|
||||
"host": "[%key:component::unifiprotect::config::step::user::data_description::host%]",
|
||||
"password": "[%key:component::unifiprotect::config::step::user::data_description::password%]",
|
||||
"port": "[%key:component::unifiprotect::config::step::user::data_description::port%]",
|
||||
"username": "[%key:component::unifiprotect::config::step::user::data_description::username%]"
|
||||
},
|
||||
"description": "Your credentials or API key seem to be missing or invalid. For instructions on how to create a local user or generate a new API key, please refer to the documentation: {local_user_documentation_url}",
|
||||
"title": "UniFi Protect reauth"
|
||||
@@ -51,7 +56,11 @@
|
||||
},
|
||||
"data_description": {
|
||||
"api_key": "API key for your local user account.",
|
||||
"host": "Hostname or IP address of your UniFi Protect device."
|
||||
"host": "Hostname or IP address of your UniFi Protect device.",
|
||||
"password": "Password for your local user account.",
|
||||
"port": "Port of your UniFi Protect device.",
|
||||
"username": "Username for your local (not cloud) user account.",
|
||||
"verify_ssl": "Verify SSL certificate of the UniFi Protect device."
|
||||
},
|
||||
"description": "You will need a local user created in your UniFi OS Console to log in with. Ubiquiti Cloud users will not work. For more information: {local_user_documentation_url}",
|
||||
"title": "UniFi Protect setup"
|
||||
@@ -567,8 +576,26 @@
|
||||
"api_key_required": {
|
||||
"message": "API key is required. Please reauthenticate this integration to provide an API key."
|
||||
},
|
||||
"device_not_found": {
|
||||
"message": "No device found for device id: {device_id}"
|
||||
},
|
||||
"no_users_found": {
|
||||
"message": "No users found, please check Protect permissions"
|
||||
},
|
||||
"only_music_supported": {
|
||||
"message": "Only music media type is supported"
|
||||
},
|
||||
"privacy_zone_not_found": {
|
||||
"message": "Could not find privacy zone with name {zone_name} on camera {camera_name}"
|
||||
},
|
||||
"protect_version": {
|
||||
"message": "Your UniFi Protect version ({current_version}) is too old. Minimum required: {min_version}."
|
||||
"message": "Your UniFi Protect version ({current_version}) is too old. Minimum required: {min_version}"
|
||||
},
|
||||
"service_error": {
|
||||
"message": "Error calling UniFi Protect service, check the logs for more details"
|
||||
},
|
||||
"stream_error": {
|
||||
"message": "Error playing audio, check the logs for more details"
|
||||
}
|
||||
},
|
||||
"issues": {
|
||||
@@ -627,6 +654,12 @@
|
||||
"max_media": "Max number of event to load for Media Browser (increases RAM usage)",
|
||||
"override_connection_host": "Override connection host"
|
||||
},
|
||||
"data_description": {
|
||||
"all_updates": "Enable realtime metrics updates. Only use if you have enabled diagnostic sensors and want them updated in realtime.",
|
||||
"disable_rtsp": "Disable the RTSP stream for all cameras. Use this if you don't need live video feeds.",
|
||||
"max_media": "Maximum number of events to load in the Media Browser. Higher values use more RAM.",
|
||||
"override_connection_host": "Override the connection host for the UniFi Protect device."
|
||||
},
|
||||
"description": "Realtime metrics option should only be enabled if you have enabled the diagnostics sensors and want them updated in realtime. If not enabled, they will only update once every 15 minutes.",
|
||||
"title": "UniFi Protect options"
|
||||
}
|
||||
|
||||
8
requirements_all.txt
generated
8
requirements_all.txt
generated
@@ -252,7 +252,7 @@ aioelectricitymaps==1.1.1
|
||||
aioemonitor==1.0.5
|
||||
|
||||
# homeassistant.components.esphome
|
||||
aioesphomeapi==42.8.0
|
||||
aioesphomeapi==42.9.0
|
||||
|
||||
# homeassistant.components.matrix
|
||||
# homeassistant.components.slack
|
||||
@@ -675,7 +675,7 @@ bluetooth-data-tools==1.28.4
|
||||
bond-async==0.2.1
|
||||
|
||||
# homeassistant.components.bosch_alarm
|
||||
bosch-alarm-mode2==0.4.6
|
||||
bosch-alarm-mode2==0.4.10
|
||||
|
||||
# homeassistant.components.bosch_shc
|
||||
boschshcpy==0.2.107
|
||||
@@ -1087,13 +1087,13 @@ google-genai==1.38.0
|
||||
google-maps-routing==0.6.15
|
||||
|
||||
# homeassistant.components.nest
|
||||
google-nest-sdm==9.1.0
|
||||
google-nest-sdm==9.1.1
|
||||
|
||||
# homeassistant.components.google_photos
|
||||
google-photos-library-api==0.12.1
|
||||
|
||||
# homeassistant.components.google_air_quality
|
||||
google_air_quality_api==1.1.2
|
||||
google_air_quality_api==1.1.3
|
||||
|
||||
# homeassistant.components.slide
|
||||
# homeassistant.components.slide_local
|
||||
|
||||
8
requirements_test_all.txt
generated
8
requirements_test_all.txt
generated
@@ -243,7 +243,7 @@ aioelectricitymaps==1.1.1
|
||||
aioemonitor==1.0.5
|
||||
|
||||
# homeassistant.components.esphome
|
||||
aioesphomeapi==42.8.0
|
||||
aioesphomeapi==42.9.0
|
||||
|
||||
# homeassistant.components.matrix
|
||||
# homeassistant.components.slack
|
||||
@@ -609,7 +609,7 @@ bluetooth-data-tools==1.28.4
|
||||
bond-async==0.2.1
|
||||
|
||||
# homeassistant.components.bosch_alarm
|
||||
bosch-alarm-mode2==0.4.6
|
||||
bosch-alarm-mode2==0.4.10
|
||||
|
||||
# homeassistant.components.bosch_shc
|
||||
boschshcpy==0.2.107
|
||||
@@ -963,13 +963,13 @@ google-genai==1.38.0
|
||||
google-maps-routing==0.6.15
|
||||
|
||||
# homeassistant.components.nest
|
||||
google-nest-sdm==9.1.0
|
||||
google-nest-sdm==9.1.1
|
||||
|
||||
# homeassistant.components.google_photos
|
||||
google-photos-library-api==0.12.1
|
||||
|
||||
# homeassistant.components.google_air_quality
|
||||
google_air_quality_api==1.1.2
|
||||
google_air_quality_api==1.1.3
|
||||
|
||||
# homeassistant.components.slide
|
||||
# homeassistant.components.slide_local
|
||||
|
||||
@@ -4,6 +4,7 @@ from collections.abc import Generator
|
||||
from typing import Any
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from bosch_alarm_mode2.const import PANEL_FAMILY, PanelModel
|
||||
from bosch_alarm_mode2.panel import Area, Door, Output, Point
|
||||
from bosch_alarm_mode2.utils import Observable
|
||||
import pytest
|
||||
@@ -39,10 +40,10 @@ def model(request: pytest.FixtureRequest) -> Generator[str]:
|
||||
|
||||
@pytest.fixture
|
||||
def extra_config_entry_data(
|
||||
model: str, model_name: str, config_flow_data: dict[str, Any]
|
||||
model: str, panel_model: PanelModel, config_flow_data: dict[str, Any]
|
||||
) -> dict[str, Any]:
|
||||
"""Return extra config entry data."""
|
||||
return {CONF_MODEL: model_name} | config_flow_data
|
||||
return {CONF_MODEL: panel_model.name} | config_flow_data
|
||||
|
||||
|
||||
@pytest.fixture(params=[None])
|
||||
@@ -64,12 +65,12 @@ def config_flow_data(model: str) -> dict[str, Any]:
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def model_name(model: str) -> str | None:
|
||||
def panel_model(model: str) -> PanelModel | None:
|
||||
"""Return extra config entry data."""
|
||||
return {
|
||||
"solution_3000": "Solution 3000",
|
||||
"amax_3000": "AMAX 3000",
|
||||
"b5512": "B5512 (US1B)",
|
||||
"solution_3000": PanelModel("Solution 3000", PANEL_FAMILY.SOLUTION),
|
||||
"amax_3000": PanelModel("AMAX 3000", PANEL_FAMILY.AMAX),
|
||||
"b5512": PanelModel("B5512 (US1B)", PANEL_FAMILY.BG_SERIES),
|
||||
}.get(model)
|
||||
|
||||
|
||||
@@ -166,7 +167,7 @@ def mock_panel(
|
||||
door: AsyncMock,
|
||||
output: AsyncMock,
|
||||
points: dict[int, AsyncMock],
|
||||
model_name: str,
|
||||
panel_model: str,
|
||||
serial_number: str | None,
|
||||
) -> Generator[AsyncMock]:
|
||||
"""Define a fixture to set up Bosch Alarm."""
|
||||
@@ -181,7 +182,7 @@ def mock_panel(
|
||||
client.doors = {1: door}
|
||||
client.outputs = {1: output}
|
||||
client.points = points
|
||||
client.model = model_name
|
||||
client.model = panel_model
|
||||
client.faults = []
|
||||
client.events = []
|
||||
client.panel_faults_ids = []
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
'open': False,
|
||||
}),
|
||||
]),
|
||||
'family': 'AMAX',
|
||||
'firmware_version': '1.0.0',
|
||||
'history_events': list([
|
||||
]),
|
||||
@@ -124,6 +125,7 @@
|
||||
'open': False,
|
||||
}),
|
||||
]),
|
||||
'family': 'BG_SERIES',
|
||||
'firmware_version': '1.0.0',
|
||||
'history_events': list([
|
||||
]),
|
||||
@@ -219,6 +221,7 @@
|
||||
'open': False,
|
||||
}),
|
||||
]),
|
||||
'family': 'SOLUTION',
|
||||
'firmware_version': '1.0.0',
|
||||
'history_events': list([
|
||||
]),
|
||||
|
||||
@@ -4,6 +4,7 @@ import asyncio
|
||||
from typing import Any
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from bosch_alarm_mode2.const import PANEL_FAMILY, PanelModel
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.bosch_alarm.const import DOMAIN
|
||||
@@ -22,7 +23,7 @@ async def test_form_user(
|
||||
hass: HomeAssistant,
|
||||
mock_setup_entry: AsyncMock,
|
||||
mock_panel: AsyncMock,
|
||||
model_name: str,
|
||||
panel_model: PanelModel,
|
||||
serial_number: str,
|
||||
config_flow_data: dict[str, Any],
|
||||
) -> None:
|
||||
@@ -45,13 +46,13 @@ async def test_form_user(
|
||||
config_flow_data,
|
||||
)
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == f"Bosch {model_name}"
|
||||
assert result["title"] == f"Bosch {panel_model.name}"
|
||||
assert (
|
||||
result["data"]
|
||||
== {
|
||||
CONF_HOST: "1.1.1.1",
|
||||
CONF_PORT: 7700,
|
||||
CONF_MODEL: model_name,
|
||||
CONF_MODEL: panel_model.name,
|
||||
}
|
||||
| config_flow_data
|
||||
)
|
||||
@@ -211,7 +212,7 @@ async def test_dhcp_can_finish(
|
||||
hass: HomeAssistant,
|
||||
mock_setup_entry: AsyncMock,
|
||||
mock_panel: AsyncMock,
|
||||
model_name: str,
|
||||
panel_model: PanelModel,
|
||||
serial_number: str,
|
||||
config_flow_data: dict[str, Any],
|
||||
) -> None:
|
||||
@@ -237,12 +238,12 @@ async def test_dhcp_can_finish(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == f"Bosch {model_name}"
|
||||
assert result["title"] == f"Bosch {panel_model.name}"
|
||||
assert result["data"] == {
|
||||
CONF_HOST: "1.1.1.1",
|
||||
CONF_MAC: "34:ea:34:b4:3b:5a",
|
||||
CONF_PORT: 7700,
|
||||
CONF_MODEL: model_name,
|
||||
CONF_MODEL: panel_model.name,
|
||||
**config_flow_data,
|
||||
}
|
||||
|
||||
@@ -258,7 +259,7 @@ async def test_dhcp_exceptions(
|
||||
hass: HomeAssistant,
|
||||
mock_setup_entry: AsyncMock,
|
||||
mock_panel: AsyncMock,
|
||||
model_name: str,
|
||||
panel_model: PanelModel,
|
||||
serial_number: str,
|
||||
config_flow_data: dict[str, Any],
|
||||
exception: Exception,
|
||||
@@ -316,7 +317,7 @@ async def test_dhcp_discovery_if_panel_setup_config_flow(
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_panel: AsyncMock,
|
||||
serial_number: str,
|
||||
model_name: str,
|
||||
panel_model: PanelModel,
|
||||
config_flow_data: dict[str, Any],
|
||||
) -> None:
|
||||
"""Test DHCP discovery doesn't fail if a different panel was set up via config flow."""
|
||||
@@ -346,12 +347,12 @@ async def test_dhcp_discovery_if_panel_setup_config_flow(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == f"Bosch {model_name}"
|
||||
assert result["title"] == f"Bosch {panel_model.name}"
|
||||
assert result["data"] == {
|
||||
CONF_HOST: "4.5.6.7",
|
||||
CONF_MAC: "34:ea:34:b4:3b:5a",
|
||||
CONF_PORT: 7700,
|
||||
CONF_MODEL: model_name,
|
||||
CONF_MODEL: panel_model.name,
|
||||
**config_flow_data,
|
||||
}
|
||||
assert mock_config_entry.unique_id == serial_number
|
||||
@@ -395,7 +396,7 @@ async def test_dhcp_updates_mac(
|
||||
mock_setup_entry: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_panel: AsyncMock,
|
||||
model_name: str,
|
||||
panel_model: PanelModel,
|
||||
serial_number: str,
|
||||
config_flow_data: dict[str, Any],
|
||||
) -> None:
|
||||
@@ -424,7 +425,7 @@ async def test_reauth_flow_success(
|
||||
mock_setup_entry: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_panel: AsyncMock,
|
||||
model_name: str,
|
||||
panel_model: PanelModel,
|
||||
serial_number: str,
|
||||
config_flow_data: dict[str, Any],
|
||||
) -> None:
|
||||
@@ -459,7 +460,7 @@ async def test_reauth_flow_error(
|
||||
mock_setup_entry: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_panel: AsyncMock,
|
||||
model_name: str,
|
||||
panel_model: PanelModel,
|
||||
serial_number: str,
|
||||
config_flow_data: dict[str, Any],
|
||||
exception: Exception,
|
||||
@@ -494,7 +495,7 @@ async def test_reconfig_flow(
|
||||
mock_setup_entry: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_panel: AsyncMock,
|
||||
model_name: str,
|
||||
panel_model: PanelModel,
|
||||
serial_number: str,
|
||||
config_flow_data: dict[str, Any],
|
||||
) -> None:
|
||||
@@ -529,7 +530,7 @@ async def test_reconfig_flow(
|
||||
assert mock_config_entry.data == {
|
||||
CONF_HOST: "1.1.1.1",
|
||||
CONF_PORT: 7700,
|
||||
CONF_MODEL: model_name,
|
||||
CONF_MODEL: panel_model.name,
|
||||
**config_flow_data,
|
||||
}
|
||||
|
||||
@@ -540,7 +541,7 @@ async def test_reconfig_flow_incorrect_model(
|
||||
mock_setup_entry: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_panel: AsyncMock,
|
||||
model_name: str,
|
||||
panel_model: PanelModel,
|
||||
serial_number: str,
|
||||
config_flow_data: dict[str, Any],
|
||||
) -> None:
|
||||
@@ -556,7 +557,7 @@ async def test_reconfig_flow_incorrect_model(
|
||||
},
|
||||
)
|
||||
|
||||
mock_panel.model = "Solution 3000"
|
||||
mock_panel.model = PanelModel("Solution 3000", family=PANEL_FAMILY.SOLUTION)
|
||||
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "user"
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
from typing import Any
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from bosch_alarm_mode2.const import PanelModel
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
@@ -19,7 +20,7 @@ async def test_diagnostics(
|
||||
hass_client: ClientSessionGenerator,
|
||||
mock_panel: AsyncMock,
|
||||
area: AsyncMock,
|
||||
model_name: str,
|
||||
panel_model: PanelModel,
|
||||
serial_number: str,
|
||||
snapshot: SnapshotAssertion,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
|
||||
@@ -113,6 +113,7 @@ async def integration_fixture(
|
||||
"light_sensor",
|
||||
"microwave_oven",
|
||||
"mock_lock",
|
||||
"mock_thermostat",
|
||||
"mounted_dimmable_load_control_fixture",
|
||||
"multi_endpoint_light",
|
||||
"occupancy_sensor",
|
||||
|
||||
526
tests/components/matter/fixtures/nodes/mock_thermostat.json
Normal file
526
tests/components/matter/fixtures/nodes/mock_thermostat.json
Normal file
@@ -0,0 +1,526 @@
|
||||
{
|
||||
"node_id": 150,
|
||||
"date_commissioned": "2025-11-18T06:53:08.679289",
|
||||
"last_interview": "2025-11-18T06:53:08.679325",
|
||||
"interview_version": 6,
|
||||
"available": true,
|
||||
"is_bridge": false,
|
||||
"attributes": {
|
||||
"0/49/0": 1,
|
||||
"0/49/1": [
|
||||
{
|
||||
"0": "ZW5zMzM=",
|
||||
"1": true
|
||||
}
|
||||
],
|
||||
"0/49/4": true,
|
||||
"0/49/5": 0,
|
||||
"0/49/6": "ZW5zMzM=",
|
||||
"0/49/7": null,
|
||||
"0/49/65532": 4,
|
||||
"0/49/65533": 2,
|
||||
"0/49/65528": [],
|
||||
"0/49/65529": [],
|
||||
"0/49/65531": [0, 1, 4, 5, 6, 7, 65532, 65533, 65528, 65529, 65531],
|
||||
"0/65/0": [],
|
||||
"0/65/65532": 0,
|
||||
"0/65/65533": 1,
|
||||
"0/65/65528": [],
|
||||
"0/65/65529": [],
|
||||
"0/65/65531": [0, 65532, 65533, 65528, 65529, 65531],
|
||||
"0/63/0": [],
|
||||
"0/63/1": [],
|
||||
"0/63/2": 4,
|
||||
"0/63/3": 3,
|
||||
"0/63/65532": 0,
|
||||
"0/63/65533": 2,
|
||||
"0/63/65528": [5, 2],
|
||||
"0/63/65529": [0, 1, 3, 4],
|
||||
"0/63/65531": [0, 1, 2, 3, 65532, 65533, 65528, 65529, 65531],
|
||||
"0/62/0": [
|
||||
{
|
||||
"1": "FTABAQEkAgE3AyQTAhgmBIAigScmBYAlTTo3BiQVAiQRlhgkBwEkCAEwCUEE2p7AKvoklmZUFHB0JFUiCsv5FCm0dmeH35yXz4UUH4HAWUwpbeU+R7hMGbAITM3T1R/mVWYthssdVcPNsfIVcjcKNQEoARgkAgE2AwQCBAEYMAQUQbZ3toX8hpE/FmJz7M6xHTbh6RMwBRS5+zzv8ZPGnI9mC3wH9vq10JnwlhgwC0DughBITJJHW/pS7o0J6o6FYTe1ufe0vCpaCj3qYeWb/QxLUydUaJQbce5Z3lUcFeHybUa/M9HID+0PRp2Ker3/GA==",
|
||||
"2": "FTABAQEkAgE3AyQUARgmBIAigScmBYAlTTo3BiQTAhgkBwEkCAEwCUEE/DujEcdTsX19xbxX+KuKKWiMaA5D9u99P/pVxIOmscd2BA2PadEMNnjvtPOpf+WE2Zxar4rby1IfAClGUUuQrTcKNQEpARgkAmAwBBS5+zzv8ZPGnI9mC3wH9vq10JnwljAFFPT6p93JKGcb7g+rTWnA6evF2EdGGDALQGkPpvsbkAFEbfPN6H3Kf23R0zzmW/gpAA3kgaL6wKB2Ofm+Tmylw22qM536Kj8mOMwaV0EL1dCCGcuxF98aL6gY",
|
||||
"254": 1
|
||||
}
|
||||
],
|
||||
"0/62/1": [
|
||||
{
|
||||
"1": "BBmX+KwLR5HGlVNbvlC+dO8Jv9fPthHiTfGpUzi2JJADX5az6GxBAFn02QKHwLcZHyh+lh9faf6rf38/nPYF7/M=",
|
||||
"2": 4939,
|
||||
"3": 2,
|
||||
"4": 150,
|
||||
"5": "ha",
|
||||
"254": 1
|
||||
}
|
||||
],
|
||||
"0/62/2": 16,
|
||||
"0/62/3": 1,
|
||||
"0/62/4": [
|
||||
"FTABAQEkAgE3AyQUARgmBIAigScmBYAlTTo3BiQUARgkBwEkCAEwCUEEGZf4rAtHkcaVU1u+UL507wm/18+2EeJN8alTOLYkkANflrPobEEAWfTZAofAtxkfKH6WH19p/qt/fz+c9gXv8zcKNQEpARgkAmAwBBT0+qfdyShnG+4Pq01pwOnrxdhHRjAFFPT6p93JKGcb7g+rTWnA6evF2EdGGDALQPVrsFnfFplsQGV5m5EUua+rmo9hAr+OP1bvaifdLqiEIn3uXLTLoKmVUkPImRL2Fb+xcMEAqR2p7RM6ZlFCR20Y"
|
||||
],
|
||||
"0/62/5": 1,
|
||||
"0/62/65532": 0,
|
||||
"0/62/65533": 2,
|
||||
"0/62/65528": [1, 3, 5, 8, 14],
|
||||
"0/62/65529": [0, 2, 4, 6, 7, 9, 10, 11, 12, 13],
|
||||
"0/62/65531": [0, 1, 2, 3, 4, 5, 65532, 65533, 65528, 65529, 65531],
|
||||
"0/60/0": 0,
|
||||
"0/60/1": null,
|
||||
"0/60/2": null,
|
||||
"0/60/65532": 0,
|
||||
"0/60/65533": 1,
|
||||
"0/60/65528": [],
|
||||
"0/60/65529": [0, 2],
|
||||
"0/60/65531": [0, 1, 2, 65532, 65533, 65528, 65529, 65531],
|
||||
"0/55/2": 425,
|
||||
"0/55/3": 61,
|
||||
"0/55/4": 0,
|
||||
"0/55/5": 0,
|
||||
"0/55/6": 0,
|
||||
"0/55/7": null,
|
||||
"0/55/1": true,
|
||||
"0/55/0": 2,
|
||||
"0/55/8": 16,
|
||||
"0/55/65532": 3,
|
||||
"0/55/65533": 1,
|
||||
"0/55/65528": [],
|
||||
"0/55/65529": [0],
|
||||
"0/55/65531": [
|
||||
2, 3, 4, 5, 6, 7, 1, 0, 8, 65532, 65533, 65528, 65529, 65531
|
||||
],
|
||||
"0/54/0": null,
|
||||
"0/54/1": null,
|
||||
"0/54/2": 3,
|
||||
"0/54/3": null,
|
||||
"0/54/4": null,
|
||||
"0/54/5": null,
|
||||
"0/54/12": null,
|
||||
"0/54/6": null,
|
||||
"0/54/7": null,
|
||||
"0/54/8": null,
|
||||
"0/54/9": null,
|
||||
"0/54/10": null,
|
||||
"0/54/11": null,
|
||||
"0/54/65532": 3,
|
||||
"0/54/65533": 1,
|
||||
"0/54/65528": [],
|
||||
"0/54/65529": [0],
|
||||
"0/54/65531": [
|
||||
0, 1, 2, 3, 4, 5, 12, 6, 7, 8, 9, 10, 11, 65532, 65533, 65528, 65529,
|
||||
65531
|
||||
],
|
||||
"0/52/0": [
|
||||
{
|
||||
"0": 6163,
|
||||
"1": "6163"
|
||||
},
|
||||
{
|
||||
"0": 6162,
|
||||
"1": "6162"
|
||||
},
|
||||
{
|
||||
"0": 6161,
|
||||
"1": "6161"
|
||||
},
|
||||
{
|
||||
"0": 6160,
|
||||
"1": "6160"
|
||||
},
|
||||
{
|
||||
"0": 6159,
|
||||
"1": "6159"
|
||||
}
|
||||
],
|
||||
"0/52/1": 545392,
|
||||
"0/52/2": 650640,
|
||||
"0/52/3": 650640,
|
||||
"0/52/65532": 1,
|
||||
"0/52/65533": 1,
|
||||
"0/52/65528": [],
|
||||
"0/52/65529": [0],
|
||||
"0/52/65531": [0, 1, 2, 3, 65532, 65533, 65528, 65529, 65531],
|
||||
"0/51/0": [
|
||||
{
|
||||
"0": "docker0",
|
||||
"1": false,
|
||||
"2": null,
|
||||
"3": null,
|
||||
"4": "8mJ0KirG",
|
||||
"5": ["rBEAAQ=="],
|
||||
"6": [],
|
||||
"7": 0
|
||||
},
|
||||
{
|
||||
"0": "ens33",
|
||||
"1": true,
|
||||
"2": null,
|
||||
"3": null,
|
||||
"4": "AAwpaqXN",
|
||||
"5": ["wKgBxA=="],
|
||||
"6": [
|
||||
"KgEOCgKzOZAcmuLd4EsaUA==",
|
||||
"KgEOCgKzOZA2wMm9YG06Ag==",
|
||||
"/oAAAAAAAACluAo+qvkuxw=="
|
||||
],
|
||||
"7": 2
|
||||
},
|
||||
{
|
||||
"0": "lo",
|
||||
"1": true,
|
||||
"2": null,
|
||||
"3": null,
|
||||
"4": "AAAAAAAA",
|
||||
"5": ["fwAAAQ=="],
|
||||
"6": ["AAAAAAAAAAAAAAAAAAAAAQ=="],
|
||||
"7": 0
|
||||
}
|
||||
],
|
||||
"0/51/1": 1,
|
||||
"0/51/8": false,
|
||||
"0/51/3": 0,
|
||||
"0/51/4": 0,
|
||||
"0/51/2": 16,
|
||||
"0/51/65532": 0,
|
||||
"0/51/65533": 2,
|
||||
"0/51/65528": [2],
|
||||
"0/51/65529": [0, 1],
|
||||
"0/51/65531": [0, 1, 8, 3, 4, 2, 65532, 65533, 65528, 65529, 65531],
|
||||
"0/50/65532": 0,
|
||||
"0/50/65533": 1,
|
||||
"0/50/65528": [1],
|
||||
"0/50/65529": [0],
|
||||
"0/50/65531": [65532, 65533, 65528, 65529, 65531],
|
||||
"0/48/0": 0,
|
||||
"0/48/1": {
|
||||
"0": 60,
|
||||
"1": 900
|
||||
},
|
||||
"0/48/2": 0,
|
||||
"0/48/3": 2,
|
||||
"0/48/4": true,
|
||||
"0/48/65532": 0,
|
||||
"0/48/65533": 2,
|
||||
"0/48/65528": [1, 3, 5],
|
||||
"0/48/65529": [0, 2, 4],
|
||||
"0/48/65531": [0, 1, 2, 3, 4, 65532, 65533, 65528, 65529, 65531],
|
||||
"0/43/0": "en-US",
|
||||
"0/43/1": ["en-US"],
|
||||
"0/43/65532": 0,
|
||||
"0/43/65533": 1,
|
||||
"0/43/65528": [],
|
||||
"0/43/65529": [],
|
||||
"0/43/65531": [0, 1, 65532, 65533, 65528, 65529, 65531],
|
||||
"0/40/0": 19,
|
||||
"0/40/1": "TEST_VENDOR",
|
||||
"0/40/2": 65521,
|
||||
"0/40/3": "Mock Thermostat",
|
||||
"0/40/4": 32769,
|
||||
"0/40/5": "",
|
||||
"0/40/6": "**REDACTED**",
|
||||
"0/40/7": 0,
|
||||
"0/40/8": "TEST_VERSION",
|
||||
"0/40/9": 1,
|
||||
"0/40/10": "1.0",
|
||||
"0/40/19": {
|
||||
"0": 3,
|
||||
"1": 65535
|
||||
},
|
||||
"0/40/21": 17104896,
|
||||
"0/40/22": 1,
|
||||
"0/40/24": 1,
|
||||
"0/40/11": "20200101",
|
||||
"0/40/12": "",
|
||||
"0/40/13": "",
|
||||
"0/40/14": "",
|
||||
"0/40/15": "TEST_SN",
|
||||
"0/40/16": false,
|
||||
"0/40/18": "29DB8B9DB518F05F",
|
||||
"0/40/65532": 0,
|
||||
"0/40/65533": 5,
|
||||
"0/40/65528": [],
|
||||
"0/40/65529": [],
|
||||
"0/40/65531": [
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 19, 21, 22, 24, 11, 12, 13, 14, 15, 16,
|
||||
18, 65532, 65533, 65528, 65529, 65531
|
||||
],
|
||||
"0/31/0": [
|
||||
{
|
||||
"1": 5,
|
||||
"2": 2,
|
||||
"3": [112233],
|
||||
"4": null,
|
||||
"254": 1
|
||||
}
|
||||
],
|
||||
"0/31/2": 4,
|
||||
"0/31/3": 3,
|
||||
"0/31/4": 4,
|
||||
"0/31/65532": 0,
|
||||
"0/31/65533": 3,
|
||||
"0/31/65528": [],
|
||||
"0/31/65529": [],
|
||||
"0/31/65531": [0, 2, 3, 4, 65532, 65533, 65528, 65529, 65531],
|
||||
"0/30/0": [],
|
||||
"0/30/65532": 0,
|
||||
"0/30/65533": 1,
|
||||
"0/30/65528": [],
|
||||
"0/30/65529": [],
|
||||
"0/30/65531": [0, 65532, 65533, 65528, 65529, 65531],
|
||||
"0/29/0": [
|
||||
{
|
||||
"0": 18,
|
||||
"1": 1
|
||||
},
|
||||
{
|
||||
"0": 22,
|
||||
"1": 3
|
||||
}
|
||||
],
|
||||
"0/29/1": [
|
||||
49, 65, 63, 62, 60, 55, 54, 52, 51, 50, 48, 43, 40, 31, 30, 29, 3, 42, 45,
|
||||
53
|
||||
],
|
||||
"0/29/2": [41],
|
||||
"0/29/3": [1],
|
||||
"0/29/65532": 0,
|
||||
"0/29/65533": 3,
|
||||
"0/29/65528": [],
|
||||
"0/29/65529": [],
|
||||
"0/29/65531": [0, 1, 2, 3, 65532, 65533, 65528, 65529, 65531],
|
||||
"0/3/0": 0,
|
||||
"0/3/1": 2,
|
||||
"0/3/65532": 0,
|
||||
"0/3/65533": 6,
|
||||
"0/3/65528": [],
|
||||
"0/3/65529": [0, 64],
|
||||
"0/3/65531": [0, 1, 65532, 65533, 65528, 65529, 65531],
|
||||
"0/42/0": [],
|
||||
"0/42/1": true,
|
||||
"0/42/2": 0,
|
||||
"0/42/3": 0,
|
||||
"0/42/65532": 0,
|
||||
"0/42/65533": 1,
|
||||
"0/42/65528": [],
|
||||
"0/42/65529": [0],
|
||||
"0/42/65531": [0, 1, 2, 3, 65532, 65533, 65528, 65529, 65531],
|
||||
"0/45/0": 1,
|
||||
"0/45/65532": 1,
|
||||
"0/45/65533": 2,
|
||||
"0/45/65528": [],
|
||||
"0/45/65529": [],
|
||||
"0/45/65531": [0, 65532, 65533, 65528, 65529, 65531],
|
||||
"0/53/0": null,
|
||||
"0/53/1": null,
|
||||
"0/53/2": null,
|
||||
"0/53/3": null,
|
||||
"0/53/4": null,
|
||||
"0/53/5": null,
|
||||
"0/53/6": 0,
|
||||
"0/53/7": [],
|
||||
"0/53/8": [],
|
||||
"0/53/9": null,
|
||||
"0/53/10": null,
|
||||
"0/53/11": null,
|
||||
"0/53/12": null,
|
||||
"0/53/13": null,
|
||||
"0/53/14": 0,
|
||||
"0/53/15": 0,
|
||||
"0/53/16": 0,
|
||||
"0/53/17": 0,
|
||||
"0/53/18": 0,
|
||||
"0/53/19": 0,
|
||||
"0/53/20": 0,
|
||||
"0/53/21": 0,
|
||||
"0/53/22": 0,
|
||||
"0/53/23": 0,
|
||||
"0/53/24": 0,
|
||||
"0/53/25": 0,
|
||||
"0/53/26": 0,
|
||||
"0/53/27": 0,
|
||||
"0/53/28": 0,
|
||||
"0/53/29": 0,
|
||||
"0/53/30": 0,
|
||||
"0/53/31": 0,
|
||||
"0/53/32": 0,
|
||||
"0/53/33": 0,
|
||||
"0/53/34": 0,
|
||||
"0/53/35": 0,
|
||||
"0/53/36": 0,
|
||||
"0/53/37": 0,
|
||||
"0/53/38": 0,
|
||||
"0/53/39": 0,
|
||||
"0/53/40": 0,
|
||||
"0/53/41": 0,
|
||||
"0/53/42": 0,
|
||||
"0/53/43": 0,
|
||||
"0/53/44": 0,
|
||||
"0/53/45": 0,
|
||||
"0/53/46": 0,
|
||||
"0/53/47": 0,
|
||||
"0/53/48": 0,
|
||||
"0/53/49": 0,
|
||||
"0/53/50": 0,
|
||||
"0/53/51": 0,
|
||||
"0/53/52": 0,
|
||||
"0/53/53": 0,
|
||||
"0/53/54": 0,
|
||||
"0/53/55": 0,
|
||||
"0/53/56": null,
|
||||
"0/53/57": null,
|
||||
"0/53/58": null,
|
||||
"0/53/59": null,
|
||||
"0/53/60": null,
|
||||
"0/53/61": null,
|
||||
"0/53/62": [],
|
||||
"0/53/65532": 15,
|
||||
"0/53/65533": 3,
|
||||
"0/53/65528": [],
|
||||
"0/53/65529": [0],
|
||||
"0/53/65531": [
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
|
||||
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
|
||||
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
|
||||
57, 58, 59, 60, 61, 62, 65532, 65533, 65528, 65529, 65531
|
||||
],
|
||||
"1/29/0": [
|
||||
{
|
||||
"0": 769,
|
||||
"1": 4
|
||||
}
|
||||
],
|
||||
"1/29/1": [29, 3, 4, 513, 516],
|
||||
"1/29/2": [3],
|
||||
"1/29/3": [],
|
||||
"1/29/65532": 0,
|
||||
"1/29/65533": 3,
|
||||
"1/29/65528": [],
|
||||
"1/29/65529": [],
|
||||
"1/29/65531": [0, 1, 2, 3, 65532, 65533, 65528, 65529, 65531],
|
||||
"1/3/0": 0,
|
||||
"1/3/1": 2,
|
||||
"1/3/65532": 0,
|
||||
"1/3/65533": 6,
|
||||
"1/3/65528": [],
|
||||
"1/3/65529": [0, 64],
|
||||
"1/3/65531": [0, 1, 65532, 65533, 65528, 65529, 65531],
|
||||
"1/4/0": 128,
|
||||
"1/4/65532": 1,
|
||||
"1/4/65533": 4,
|
||||
"1/4/65528": [0, 1, 2, 3],
|
||||
"1/4/65529": [0, 1, 2, 3, 4, 5],
|
||||
"1/4/65531": [0, 65532, 65533, 65528, 65529, 65531],
|
||||
|
||||
"1/513/0": 1800,
|
||||
"1/513/1": 500,
|
||||
"1/513/3": 700,
|
||||
"1/513/4": 3000,
|
||||
"1/513/5": 1600,
|
||||
"1/513/6": 3200,
|
||||
"1/513/7": 0,
|
||||
"1/513/8": 25,
|
||||
"1/513/16": 0,
|
||||
"1/513/17": 2600,
|
||||
"1/513/18": 2000,
|
||||
"1/513/21": 700,
|
||||
"1/513/22": 3000,
|
||||
"1/513/23": 1600,
|
||||
"1/513/24": 3200,
|
||||
"1/513/25": 25,
|
||||
"1/513/26": 0,
|
||||
"1/513/27": 4,
|
||||
"1/513/28": 1,
|
||||
"1/513/30": 4,
|
||||
"1/513/35": 0,
|
||||
"1/513/36": 0,
|
||||
"1/513/37": 0,
|
||||
"1/513/41": 1,
|
||||
"1/513/48": 0,
|
||||
"1/513/49": 150,
|
||||
"1/513/50": 789004800,
|
||||
"1/513/72": [
|
||||
{
|
||||
"0": 1,
|
||||
"1": 1,
|
||||
"2": 1
|
||||
},
|
||||
{
|
||||
"0": 2,
|
||||
"1": 1,
|
||||
"2": 1
|
||||
},
|
||||
{
|
||||
"0": 3,
|
||||
"1": 1,
|
||||
"2": 2
|
||||
},
|
||||
{
|
||||
"0": 4,
|
||||
"1": 1,
|
||||
"2": 2
|
||||
},
|
||||
{
|
||||
"0": 5,
|
||||
"1": 1,
|
||||
"2": 2
|
||||
},
|
||||
{
|
||||
"0": 254,
|
||||
"1": 1,
|
||||
"2": 2
|
||||
}
|
||||
],
|
||||
"1/513/73": [
|
||||
{
|
||||
"0": 4,
|
||||
"1": 1,
|
||||
"2": 2
|
||||
},
|
||||
{
|
||||
"0": 3,
|
||||
"1": 1,
|
||||
"2": 2
|
||||
}
|
||||
],
|
||||
"1/513/74": 5,
|
||||
"1/513/78": null,
|
||||
"1/513/80": [
|
||||
{
|
||||
"0": "AQ==",
|
||||
"1": 1,
|
||||
"3": 2500,
|
||||
"4": 2100,
|
||||
"5": true
|
||||
},
|
||||
{
|
||||
"0": "Ag==",
|
||||
"1": 2,
|
||||
"3": 2600,
|
||||
"4": 2000,
|
||||
"5": true
|
||||
}
|
||||
],
|
||||
"1/513/82": 0,
|
||||
"1/513/83": 5,
|
||||
"1/513/84": [],
|
||||
"1/513/85": null,
|
||||
"1/513/86": null,
|
||||
"1/513/65532": 419,
|
||||
"1/513/65533": 9,
|
||||
"1/513/65528": [2, 253],
|
||||
"1/513/65529": [0, 6, 7, 8, 254],
|
||||
"1/513/65531": [
|
||||
0, 1, 3, 4, 5, 6, 7, 8, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 30,
|
||||
35, 36, 37, 41, 48, 49, 50, 72, 73, 74, 78, 80, 82, 83, 84, 85, 86, 65532,
|
||||
65533, 65528, 65529, 65531
|
||||
],
|
||||
"1/516/0": 0,
|
||||
"1/516/1": 0,
|
||||
"1/516/65532": 0,
|
||||
"1/516/65533": 2,
|
||||
"1/516/65528": [],
|
||||
"1/516/65529": [],
|
||||
"1/516/65531": [0, 1, 65532, 65533, 65528, 65529, 65531]
|
||||
},
|
||||
"attribute_subscriptions": []
|
||||
}
|
||||
@@ -2290,6 +2290,104 @@
|
||||
'state': 'unknown',
|
||||
})
|
||||
# ---
|
||||
# name: test_buttons[mock_thermostat][button.mock_thermostat_identify_0-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'button',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'button.mock_thermostat_identify_0',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <ButtonDeviceClass.IDENTIFY: 'identify'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Identify (0)',
|
||||
'platform': 'matter',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000096-MatterNodeDevice-0-IdentifyButton-3-1',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_buttons[mock_thermostat][button.mock_thermostat_identify_0-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'identify',
|
||||
'friendly_name': 'Mock Thermostat Identify (0)',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'button.mock_thermostat_identify_0',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'unknown',
|
||||
})
|
||||
# ---
|
||||
# name: test_buttons[mock_thermostat][button.mock_thermostat_identify_1-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'button',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'button.mock_thermostat_identify_1',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <ButtonDeviceClass.IDENTIFY: 'identify'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Identify (1)',
|
||||
'platform': 'matter',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000096-MatterNodeDevice-1-IdentifyButton-3-1',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_buttons[mock_thermostat][button.mock_thermostat_identify_1-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'identify',
|
||||
'friendly_name': 'Mock Thermostat Identify (1)',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'button.mock_thermostat_identify_1',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'unknown',
|
||||
})
|
||||
# ---
|
||||
# name: test_buttons[multi_endpoint_light][button.inovelli_identify_1-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
|
||||
@@ -325,6 +325,77 @@
|
||||
'state': 'cool',
|
||||
})
|
||||
# ---
|
||||
# name: test_climates[mock_thermostat][climate.mock_thermostat-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'hvac_modes': list([
|
||||
<HVACMode.OFF: 'off'>,
|
||||
<HVACMode.HEAT: 'heat'>,
|
||||
<HVACMode.COOL: 'cool'>,
|
||||
<HVACMode.HEAT_COOL: 'heat_cool'>,
|
||||
]),
|
||||
'max_temp': 32.0,
|
||||
'min_temp': 7.0,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'climate',
|
||||
'entity_category': None,
|
||||
'entity_id': 'climate.mock_thermostat',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': None,
|
||||
'platform': 'matter',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': <ClimateEntityFeature: 387>,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000096-MatterNodeDevice-1-MatterThermostat-513-0',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_climates[mock_thermostat][climate.mock_thermostat-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'current_temperature': 18.0,
|
||||
'friendly_name': 'Mock Thermostat',
|
||||
'hvac_action': <HVACAction.HEATING: 'heating'>,
|
||||
'hvac_modes': list([
|
||||
<HVACMode.OFF: 'off'>,
|
||||
<HVACMode.HEAT: 'heat'>,
|
||||
<HVACMode.COOL: 'cool'>,
|
||||
<HVACMode.HEAT_COOL: 'heat_cool'>,
|
||||
]),
|
||||
'max_temp': 32.0,
|
||||
'min_temp': 7.0,
|
||||
'supported_features': <ClimateEntityFeature: 387>,
|
||||
'target_temp_high': 26.0,
|
||||
'target_temp_low': 20.0,
|
||||
'temperature': None,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'climate.mock_thermostat',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'heat_cool',
|
||||
})
|
||||
# ---
|
||||
# name: test_climates[room_airconditioner][climate.room_airconditioner-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
|
||||
@@ -2570,6 +2570,63 @@
|
||||
'state': 'silent',
|
||||
})
|
||||
# ---
|
||||
# name: test_selects[mock_thermostat][select.mock_thermostat_temperature_display_mode-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'options': list([
|
||||
'Celsius',
|
||||
'Fahrenheit',
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'select',
|
||||
'entity_category': <EntityCategory.CONFIG: 'config'>,
|
||||
'entity_id': 'select.mock_thermostat_temperature_display_mode',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Temperature display mode',
|
||||
'platform': 'matter',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'temperature_display_mode',
|
||||
'unique_id': '00000000000004D2-0000000000000096-MatterNodeDevice-1-TrvTemperatureDisplayMode-516-0',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_selects[mock_thermostat][select.mock_thermostat_temperature_display_mode-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'Mock Thermostat Temperature display mode',
|
||||
'options': list([
|
||||
'Celsius',
|
||||
'Fahrenheit',
|
||||
]),
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'select.mock_thermostat_temperature_display_mode',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'Celsius',
|
||||
})
|
||||
# ---
|
||||
# name: test_selects[mounted_dimmable_load_control_fixture][select.mock_mounted_dimmable_load_control_power_on_behavior_on_startup-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
|
||||
@@ -7259,6 +7259,332 @@
|
||||
'state': 'stopped',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_thermostat][sensor.mock_thermostat_heating_demand-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'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.mock_thermostat_heating_demand',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Heating demand',
|
||||
'platform': 'matter',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'pi_heating_demand',
|
||||
'unique_id': '00000000000004D2-0000000000000096-MatterNodeDevice-1-ThermostatPIHeatingDemand-513-8',
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_thermostat][sensor.mock_thermostat_heating_demand-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'Mock Thermostat Heating demand',
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.mock_thermostat_heating_demand',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '25',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_thermostat][sensor.mock_thermostat_last_change-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.mock_thermostat_last_change',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.TIMESTAMP: 'timestamp'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Last change',
|
||||
'platform': 'matter',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'setpoint_change_timestamp',
|
||||
'unique_id': '00000000000004D2-0000000000000096-MatterNodeDevice-1-SetpointChangeSourceTimestamp-513-50',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_thermostat][sensor.mock_thermostat_last_change-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'timestamp',
|
||||
'friendly_name': 'Mock Thermostat Last change',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.mock_thermostat_last_change',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '2025-01-01T00:00:00+00:00',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_thermostat][sensor.mock_thermostat_last_change_amount-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': None,
|
||||
'entity_id': 'sensor.mock_thermostat_last_change_amount',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 1,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.TEMPERATURE: 'temperature'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Last change amount',
|
||||
'platform': 'matter',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'setpoint_change_amount',
|
||||
'unique_id': '00000000000004D2-0000000000000096-MatterNodeDevice-1-ThermostatSetpointChangeAmount-513-49',
|
||||
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_thermostat][sensor.mock_thermostat_last_change_amount-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'temperature',
|
||||
'friendly_name': 'Mock Thermostat Last change amount',
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.mock_thermostat_last_change_amount',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '1.5',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_thermostat][sensor.mock_thermostat_last_change_source-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'options': list([
|
||||
'manual',
|
||||
'schedule',
|
||||
'external',
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.mock_thermostat_last_change_source',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.ENUM: 'enum'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Last change source',
|
||||
'platform': 'matter',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'setpoint_change_source',
|
||||
'unique_id': '00000000000004D2-0000000000000096-MatterNodeDevice-1-SetpointChangeSource-513-48',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_thermostat][sensor.mock_thermostat_last_change_source-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'enum',
|
||||
'friendly_name': 'Mock Thermostat Last change source',
|
||||
'options': list([
|
||||
'manual',
|
||||
'schedule',
|
||||
'external',
|
||||
]),
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.mock_thermostat_last_change_source',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'manual',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_thermostat][sensor.mock_thermostat_outdoor_temperature-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': None,
|
||||
'entity_id': 'sensor.mock_thermostat_outdoor_temperature',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 1,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.TEMPERATURE: 'temperature'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Outdoor temperature',
|
||||
'platform': 'matter',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'outdoor_temperature',
|
||||
'unique_id': '00000000000004D2-0000000000000096-MatterNodeDevice-1-ThermostatOutdoorTemperature-513-1',
|
||||
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_thermostat][sensor.mock_thermostat_outdoor_temperature-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'temperature',
|
||||
'friendly_name': 'Mock Thermostat Outdoor temperature',
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.mock_thermostat_outdoor_temperature',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '5.0',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_thermostat][sensor.mock_thermostat_temperature-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': None,
|
||||
'entity_id': 'sensor.mock_thermostat_temperature',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 1,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.TEMPERATURE: 'temperature'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Temperature',
|
||||
'platform': 'matter',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000096-MatterNodeDevice-1-ThermostatLocalTemperature-513-0',
|
||||
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[mock_thermostat][sensor.mock_thermostat_temperature-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'temperature',
|
||||
'friendly_name': 'Mock Thermostat Temperature',
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.mock_thermostat_temperature',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '18.0',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[multi_endpoint_light][sensor.inovelli_current_switch_position_config-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
|
||||
@@ -697,3 +697,91 @@ async def test_vacuum_operational_error_sensor(
|
||||
state = hass.states.get("sensor.mock_vacuum_operational_error")
|
||||
assert state
|
||||
assert state.state == "unknown"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("node_fixture", ["mock_thermostat"])
|
||||
async def test_thermostat_setpoint_change_source(
|
||||
hass: HomeAssistant,
|
||||
matter_client: MagicMock,
|
||||
matter_node: MatterNode,
|
||||
) -> None:
|
||||
"""Test Thermostat SetpointChangeSource sensor."""
|
||||
# Thermostat Cluster / SetpointChangeSource attribute (1/513/48)
|
||||
state = hass.states.get("sensor.mock_thermostat_last_change_source")
|
||||
assert state
|
||||
assert state.state == "manual"
|
||||
assert state.attributes["options"] == ["manual", "schedule", "external"]
|
||||
|
||||
# Test schedule source
|
||||
set_node_attribute(matter_node, 1, 513, 48, 1)
|
||||
await trigger_subscription_callback(hass, matter_client)
|
||||
|
||||
state = hass.states.get("sensor.mock_thermostat_last_change_source")
|
||||
assert state
|
||||
assert state.state == "schedule"
|
||||
|
||||
# Test external source
|
||||
set_node_attribute(matter_node, 1, 513, 48, 2)
|
||||
await trigger_subscription_callback(hass, matter_client)
|
||||
|
||||
state = hass.states.get("sensor.mock_thermostat_last_change_source")
|
||||
assert state
|
||||
assert state.state == "external"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("node_fixture", ["mock_thermostat"])
|
||||
async def test_thermostat_setpoint_change_timestamp(
|
||||
hass: HomeAssistant,
|
||||
matter_client: MagicMock,
|
||||
matter_node: MatterNode,
|
||||
) -> None:
|
||||
"""Test Thermostat SetpointChangeSourceTimestamp sensor."""
|
||||
# Thermostat Cluster / SetpointChangeSourceTimestamp attribute (1/513/50)
|
||||
state = hass.states.get("sensor.mock_thermostat_last_change")
|
||||
assert state
|
||||
assert state.state == "2025-01-01T00:00:00+00:00"
|
||||
|
||||
# Update to a new timestamp (2024-01-01 00:00:00+00:00 UTC)
|
||||
set_node_attribute(matter_node, 1, 513, 50, 757382400)
|
||||
await trigger_subscription_callback(hass, matter_client)
|
||||
|
||||
state = hass.states.get("sensor.mock_thermostat_last_change")
|
||||
assert state
|
||||
assert state.state == "2024-01-01T00:00:00+00:00"
|
||||
|
||||
# Test zero value (should be None/unknown)
|
||||
set_node_attribute(matter_node, 1, 513, 50, 0)
|
||||
await trigger_subscription_callback(hass, matter_client)
|
||||
|
||||
state = hass.states.get("sensor.mock_thermostat_last_change")
|
||||
assert state
|
||||
assert state.state == "unknown"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("node_fixture", ["mock_thermostat"])
|
||||
async def test_thermostat_setpoint_change_amount(
|
||||
hass: HomeAssistant,
|
||||
matter_client: MagicMock,
|
||||
matter_node: MatterNode,
|
||||
) -> None:
|
||||
"""Test Thermostat SetpointChangeAmount sensor."""
|
||||
# Thermostat Cluster / SetpointChangeAmount attribute (1/513/49)
|
||||
state = hass.states.get("sensor.mock_thermostat_last_change_amount")
|
||||
assert state
|
||||
assert state.state == "1.5"
|
||||
|
||||
# Update to 2.0°C (200 in Matter units)
|
||||
set_node_attribute(matter_node, 1, 513, 49, 200)
|
||||
await trigger_subscription_callback(hass, matter_client)
|
||||
|
||||
state = hass.states.get("sensor.mock_thermostat_last_change_amount")
|
||||
assert state
|
||||
assert state.state == "2.0"
|
||||
|
||||
# Update to -0.5°C (-50 in Matter units)
|
||||
set_node_attribute(matter_node, 1, 513, 49, -50)
|
||||
await trigger_subscription_callback(hass, matter_client)
|
||||
|
||||
state = hass.states.get("sensor.mock_thermostat_last_change_amount")
|
||||
assert state
|
||||
assert state.state == "-0.5"
|
||||
|
||||
@@ -333,7 +333,7 @@ async def test_get_user_keyring_info_no_users(
|
||||
camera_entry = entity_registry.async_get("binary_sensor.test_camera_doorbell")
|
||||
|
||||
with pytest.raises(
|
||||
HomeAssistantError, match="No users found, please check Protect permissions."
|
||||
HomeAssistantError, match="No users found, please check Protect permissions"
|
||||
):
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
|
||||
Reference in New Issue
Block a user