mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
2025.4.3 (#143253)
This commit is contained in:
commit
6f0a9910ea
@ -120,6 +120,7 @@ class AppleTvMediaPlayer(
|
|||||||
"""Initialize the Apple TV media player."""
|
"""Initialize the Apple TV media player."""
|
||||||
super().__init__(name, identifier, manager)
|
super().__init__(name, identifier, manager)
|
||||||
self._playing: Playing | None = None
|
self._playing: Playing | None = None
|
||||||
|
self._playing_last_updated: datetime | None = None
|
||||||
self._app_list: dict[str, str] = {}
|
self._app_list: dict[str, str] = {}
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
@ -209,6 +210,7 @@ class AppleTvMediaPlayer(
|
|||||||
This is a callback function from pyatv.interface.PushListener.
|
This is a callback function from pyatv.interface.PushListener.
|
||||||
"""
|
"""
|
||||||
self._playing = playstatus
|
self._playing = playstatus
|
||||||
|
self._playing_last_updated = dt_util.utcnow()
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
@ -316,7 +318,7 @@ class AppleTvMediaPlayer(
|
|||||||
def media_position_updated_at(self) -> datetime | None:
|
def media_position_updated_at(self) -> datetime | None:
|
||||||
"""Last valid time of media position."""
|
"""Last valid time of media position."""
|
||||||
if self.state in {MediaPlayerState.PLAYING, MediaPlayerState.PAUSED}:
|
if self.state in {MediaPlayerState.PLAYING, MediaPlayerState.PAUSED}:
|
||||||
return dt_util.utcnow()
|
return self._playing_last_updated
|
||||||
return None
|
return None
|
||||||
|
|
||||||
async def async_play_media(
|
async def async_play_media(
|
||||||
|
@ -81,4 +81,7 @@ class ComelitSwitchEntity(CoordinatorEntity[ComelitSerialBridge], SwitchEntity):
|
|||||||
@property
|
@property
|
||||||
def is_on(self) -> bool:
|
def is_on(self) -> bool:
|
||||||
"""Return True if switch is on."""
|
"""Return True if switch is on."""
|
||||||
return self.coordinator.data[OTHER][self._device.index].status == STATE_ON
|
return (
|
||||||
|
self.coordinator.data[self._device.type][self._device.index].status
|
||||||
|
== STATE_ON
|
||||||
|
)
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"integration_type": "device",
|
"integration_type": "device",
|
||||||
"iot_class": "local_polling",
|
"iot_class": "local_polling",
|
||||||
"loggers": ["devolo_plc_api"],
|
"loggers": ["devolo_plc_api"],
|
||||||
"requirements": ["devolo-plc-api==1.4.1"],
|
"requirements": ["devolo-plc-api==1.5.1"],
|
||||||
"zeroconf": [
|
"zeroconf": [
|
||||||
{
|
{
|
||||||
"type": "_dvl-deviceapi._tcp.local.",
|
"type": "_dvl-deviceapi._tcp.local.",
|
||||||
|
@ -179,22 +179,18 @@ class DukeEnergyCoordinator(DataUpdateCoordinator[None]):
|
|||||||
one = timedelta(days=1)
|
one = timedelta(days=1)
|
||||||
if start_time is None:
|
if start_time is None:
|
||||||
# Max 3 years of data
|
# Max 3 years of data
|
||||||
agreement_date = dt_util.parse_datetime(meter["agreementActiveDate"])
|
start = dt_util.now(tz) - timedelta(days=3 * 365)
|
||||||
if agreement_date is None:
|
|
||||||
start = dt_util.now(tz) - timedelta(days=3 * 365)
|
|
||||||
else:
|
|
||||||
start = max(
|
|
||||||
agreement_date.replace(tzinfo=tz),
|
|
||||||
dt_util.now(tz) - timedelta(days=3 * 365),
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
start = datetime.fromtimestamp(start_time, tz=tz) - lookback
|
start = datetime.fromtimestamp(start_time, tz=tz) - lookback
|
||||||
|
agreement_date = dt_util.parse_datetime(meter["agreementActiveDate"])
|
||||||
|
if agreement_date is not None:
|
||||||
|
start = max(agreement_date.replace(tzinfo=tz), start)
|
||||||
|
|
||||||
start = start.replace(hour=0, minute=0, second=0, microsecond=0)
|
start = start.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||||
end = dt_util.now(tz).replace(hour=0, minute=0, second=0, microsecond=0) - one
|
end = dt_util.now(tz).replace(hour=0, minute=0, second=0, microsecond=0) - one
|
||||||
_LOGGER.debug("Data lookup range: %s - %s", start, end)
|
_LOGGER.debug("Data lookup range: %s - %s", start, end)
|
||||||
|
|
||||||
start_step = end - lookback
|
start_step = max(end - lookback, start)
|
||||||
end_step = end
|
end_step = end
|
||||||
usage: dict[datetime, dict[str, float | int]] = {}
|
usage: dict[datetime, dict[str, float | int]] = {}
|
||||||
while True:
|
while True:
|
||||||
|
@ -35,7 +35,7 @@ async def validate_input(data):
|
|||||||
lon = weather_data.lon
|
lon = weather_data.lon
|
||||||
|
|
||||||
return {
|
return {
|
||||||
CONF_TITLE: weather_data.metadata.get("location"),
|
CONF_TITLE: weather_data.metadata.location,
|
||||||
CONF_STATION: weather_data.station_id,
|
CONF_STATION: weather_data.station_id,
|
||||||
CONF_LATITUDE: lat,
|
CONF_LATITUDE: lat,
|
||||||
CONF_LONGITUDE: lon,
|
CONF_LONGITUDE: lon,
|
||||||
|
@ -7,7 +7,7 @@ from datetime import timedelta
|
|||||||
import logging
|
import logging
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
from env_canada import ECAirQuality, ECRadar, ECWeather, ec_exc
|
from env_canada import ECAirQuality, ECRadar, ECWeather, ECWeatherUpdateFailed, ec_exc
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
@ -65,6 +65,6 @@ class ECDataUpdateCoordinator[DataT: ECDataType](DataUpdateCoordinator[DataT]):
|
|||||||
"""Fetch data from EC."""
|
"""Fetch data from EC."""
|
||||||
try:
|
try:
|
||||||
await self.ec_data.update()
|
await self.ec_data.update()
|
||||||
except (ET.ParseError, ec_exc.UnknownStationId) as ex:
|
except (ET.ParseError, ECWeatherUpdateFailed, ec_exc.UnknownStationId) as ex:
|
||||||
raise UpdateFailed(f"Error fetching {self.name} data: {ex}") from ex
|
raise UpdateFailed(f"Error fetching {self.name} data: {ex}") from ex
|
||||||
return self.ec_data
|
return self.ec_data
|
||||||
|
@ -6,5 +6,5 @@
|
|||||||
"documentation": "https://www.home-assistant.io/integrations/environment_canada",
|
"documentation": "https://www.home-assistant.io/integrations/environment_canada",
|
||||||
"iot_class": "cloud_polling",
|
"iot_class": "cloud_polling",
|
||||||
"loggers": ["env_canada"],
|
"loggers": ["env_canada"],
|
||||||
"requirements": ["env-canada==0.8.0"]
|
"requirements": ["env-canada==0.10.1"]
|
||||||
}
|
}
|
||||||
|
@ -145,7 +145,7 @@ SENSOR_TYPES: tuple[ECSensorEntityDescription, ...] = (
|
|||||||
key="timestamp",
|
key="timestamp",
|
||||||
translation_key="timestamp",
|
translation_key="timestamp",
|
||||||
device_class=SensorDeviceClass.TIMESTAMP,
|
device_class=SensorDeviceClass.TIMESTAMP,
|
||||||
value_fn=lambda data: data.metadata.get("timestamp"),
|
value_fn=lambda data: data.metadata.timestamp,
|
||||||
),
|
),
|
||||||
ECSensorEntityDescription(
|
ECSensorEntityDescription(
|
||||||
key="uv_index",
|
key="uv_index",
|
||||||
@ -289,7 +289,7 @@ class ECBaseSensorEntity[DataT: ECDataType](
|
|||||||
super().__init__(coordinator)
|
super().__init__(coordinator)
|
||||||
self.entity_description = description
|
self.entity_description = description
|
||||||
self._ec_data = coordinator.ec_data
|
self._ec_data = coordinator.ec_data
|
||||||
self._attr_attribution = self._ec_data.metadata["attribution"]
|
self._attr_attribution = self._ec_data.metadata.attribution
|
||||||
self._attr_unique_id = f"{coordinator.config_entry.title}-{description.key}"
|
self._attr_unique_id = f"{coordinator.config_entry.title}-{description.key}"
|
||||||
self._attr_device_info = coordinator.device_info
|
self._attr_device_info = coordinator.device_info
|
||||||
|
|
||||||
@ -313,8 +313,8 @@ class ECSensorEntity[DataT: ECDataType](ECBaseSensorEntity[DataT]):
|
|||||||
"""Initialize the sensor."""
|
"""Initialize the sensor."""
|
||||||
super().__init__(coordinator, description)
|
super().__init__(coordinator, description)
|
||||||
self._attr_extra_state_attributes = {
|
self._attr_extra_state_attributes = {
|
||||||
ATTR_LOCATION: self._ec_data.metadata.get("location"),
|
ATTR_LOCATION: self._ec_data.metadata.location,
|
||||||
ATTR_STATION: self._ec_data.metadata.get("station"),
|
ATTR_STATION: self._ec_data.metadata.station,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -329,8 +329,8 @@ class ECAlertSensorEntity(ECBaseSensorEntity[ECWeather]):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
extra_state_attrs = {
|
extra_state_attrs = {
|
||||||
ATTR_LOCATION: self._ec_data.metadata.get("location"),
|
ATTR_LOCATION: self._ec_data.metadata.location,
|
||||||
ATTR_STATION: self._ec_data.metadata.get("station"),
|
ATTR_STATION: self._ec_data.metadata.station,
|
||||||
}
|
}
|
||||||
for index, alert in enumerate(value, start=1):
|
for index, alert in enumerate(value, start=1):
|
||||||
extra_state_attrs[f"alert_{index}"] = alert.get("title")
|
extra_state_attrs[f"alert_{index}"] = alert.get("title")
|
||||||
|
@ -115,7 +115,7 @@ class ECWeatherEntity(
|
|||||||
"""Initialize Environment Canada weather."""
|
"""Initialize Environment Canada weather."""
|
||||||
super().__init__(coordinator)
|
super().__init__(coordinator)
|
||||||
self.ec_data = coordinator.ec_data
|
self.ec_data = coordinator.ec_data
|
||||||
self._attr_attribution = self.ec_data.metadata["attribution"]
|
self._attr_attribution = self.ec_data.metadata.attribution
|
||||||
self._attr_translation_key = "forecast"
|
self._attr_translation_key = "forecast"
|
||||||
self._attr_unique_id = _calculate_unique_id(
|
self._attr_unique_id = _calculate_unique_id(
|
||||||
coordinator.config_entry.unique_id, False
|
coordinator.config_entry.unique_id, False
|
||||||
|
@ -74,7 +74,7 @@ def build_rrule(task: TaskData) -> rrule:
|
|||||||
|
|
||||||
bysetpos = None
|
bysetpos = None
|
||||||
if rrule_frequency == MONTHLY and task.weeksOfMonth:
|
if rrule_frequency == MONTHLY and task.weeksOfMonth:
|
||||||
bysetpos = task.weeksOfMonth
|
bysetpos = [i + 1 for i in task.weeksOfMonth]
|
||||||
weekdays = weekdays if weekdays else [MO]
|
weekdays = weekdays if weekdays else [MO]
|
||||||
|
|
||||||
return rrule(
|
return rrule(
|
||||||
|
@ -5,5 +5,5 @@
|
|||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/holiday",
|
"documentation": "https://www.home-assistant.io/integrations/holiday",
|
||||||
"iot_class": "local_polling",
|
"iot_class": "local_polling",
|
||||||
"requirements": ["holidays==0.69", "babel==2.15.0"]
|
"requirements": ["holidays==0.70", "babel==2.15.0"]
|
||||||
}
|
}
|
||||||
|
@ -204,7 +204,7 @@ class HomeConnectCoordinator(
|
|||||||
events = self.data[event_message_ha_id].events
|
events = self.data[event_message_ha_id].events
|
||||||
for event in event_message.data.items:
|
for event in event_message.data.items:
|
||||||
event_key = event.key
|
event_key = event.key
|
||||||
if event_key in SettingKey:
|
if event_key in SettingKey.__members__.values(): # type: ignore[comparison-overlap]
|
||||||
setting_key = SettingKey(event_key)
|
setting_key = SettingKey(event_key)
|
||||||
if setting_key in settings:
|
if setting_key in settings:
|
||||||
settings[setting_key].value = event.value
|
settings[setting_key].value = event.value
|
||||||
|
@ -61,11 +61,14 @@ OPTIONS_SCHEMA = vol.Schema(
|
|||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def _get_data_schema(hass: HomeAssistant) -> vol.Schema:
|
async def _get_data_schema(hass: HomeAssistant) -> vol.Schema:
|
||||||
default_location = {
|
default_location = {
|
||||||
CONF_LATITUDE: hass.config.latitude,
|
CONF_LATITUDE: hass.config.latitude,
|
||||||
CONF_LONGITUDE: hass.config.longitude,
|
CONF_LONGITUDE: hass.config.longitude,
|
||||||
}
|
}
|
||||||
|
get_timezones: list[str] = list(
|
||||||
|
await hass.async_add_executor_job(zoneinfo.available_timezones)
|
||||||
|
)
|
||||||
return vol.Schema(
|
return vol.Schema(
|
||||||
{
|
{
|
||||||
vol.Required(CONF_DIASPORA, default=DEFAULT_DIASPORA): BooleanSelector(),
|
vol.Required(CONF_DIASPORA, default=DEFAULT_DIASPORA): BooleanSelector(),
|
||||||
@ -75,9 +78,7 @@ def _get_data_schema(hass: HomeAssistant) -> vol.Schema:
|
|||||||
vol.Optional(CONF_LOCATION, default=default_location): LocationSelector(),
|
vol.Optional(CONF_LOCATION, default=default_location): LocationSelector(),
|
||||||
vol.Optional(CONF_ELEVATION, default=hass.config.elevation): int,
|
vol.Optional(CONF_ELEVATION, default=hass.config.elevation): int,
|
||||||
vol.Optional(CONF_TIME_ZONE, default=hass.config.time_zone): SelectSelector(
|
vol.Optional(CONF_TIME_ZONE, default=hass.config.time_zone): SelectSelector(
|
||||||
SelectSelectorConfig(
|
SelectSelectorConfig(options=get_timezones, sort=True)
|
||||||
options=sorted(zoneinfo.available_timezones()),
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -109,7 +110,7 @@ class JewishCalendarConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
return self.async_show_form(
|
return self.async_show_form(
|
||||||
step_id="user",
|
step_id="user",
|
||||||
data_schema=self.add_suggested_values_to_schema(
|
data_schema=self.add_suggested_values_to_schema(
|
||||||
_get_data_schema(self.hass), user_input
|
await _get_data_schema(self.hass), user_input
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -121,7 +122,7 @@ class JewishCalendarConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
if not user_input:
|
if not user_input:
|
||||||
return self.async_show_form(
|
return self.async_show_form(
|
||||||
data_schema=self.add_suggested_values_to_schema(
|
data_schema=self.add_suggested_values_to_schema(
|
||||||
_get_data_schema(self.hass),
|
await _get_data_schema(self.hass),
|
||||||
reconfigure_entry.data,
|
reconfigure_entry.data,
|
||||||
),
|
),
|
||||||
step_id="reconfigure",
|
step_id="reconfigure",
|
||||||
|
@ -145,7 +145,10 @@ class KrakenData:
|
|||||||
await asyncio.sleep(CALL_RATE_LIMIT_SLEEP)
|
await asyncio.sleep(CALL_RATE_LIMIT_SLEEP)
|
||||||
|
|
||||||
def _get_websocket_name_asset_pairs(self) -> str:
|
def _get_websocket_name_asset_pairs(self) -> str:
|
||||||
return ",".join(wsname for wsname in self.tradable_asset_pairs.values())
|
return ",".join(
|
||||||
|
self.tradable_asset_pairs[tracked_pair]
|
||||||
|
for tracked_pair in self._config_entry.options[CONF_TRACKED_ASSET_PAIRS]
|
||||||
|
)
|
||||||
|
|
||||||
def set_update_interval(self, update_interval: int) -> None:
|
def set_update_interval(self, update_interval: int) -> None:
|
||||||
"""Set the coordinator update_interval to the supplied update_interval."""
|
"""Set the coordinator update_interval to the supplied update_interval."""
|
||||||
|
@ -254,7 +254,7 @@ def _generate_device_config(
|
|||||||
comp_config = config[CONF_COMPONENTS]
|
comp_config = config[CONF_COMPONENTS]
|
||||||
for platform, discover_id in mqtt_data.discovery_already_discovered:
|
for platform, discover_id in mqtt_data.discovery_already_discovered:
|
||||||
ids = discover_id.split(" ")
|
ids = discover_id.split(" ")
|
||||||
component_node_id = ids.pop(0)
|
component_node_id = f"{ids.pop(1)} {ids.pop(0)}" if len(ids) > 2 else ids.pop(0)
|
||||||
component_object_id = " ".join(ids)
|
component_object_id = " ".join(ids)
|
||||||
if not ids:
|
if not ids:
|
||||||
continue
|
continue
|
||||||
|
@ -371,6 +371,9 @@ def migrate_entity_ids(
|
|||||||
new_device_id = f"{host.unique_id}"
|
new_device_id = f"{host.unique_id}"
|
||||||
else:
|
else:
|
||||||
new_device_id = f"{host.unique_id}_{device_uid[1]}"
|
new_device_id = f"{host.unique_id}_{device_uid[1]}"
|
||||||
|
_LOGGER.debug(
|
||||||
|
"Updating Reolink device UID from %s to %s", device_uid, new_device_id
|
||||||
|
)
|
||||||
new_identifiers = {(DOMAIN, new_device_id)}
|
new_identifiers = {(DOMAIN, new_device_id)}
|
||||||
device_reg.async_update_device(device.id, new_identifiers=new_identifiers)
|
device_reg.async_update_device(device.id, new_identifiers=new_identifiers)
|
||||||
|
|
||||||
@ -383,6 +386,9 @@ def migrate_entity_ids(
|
|||||||
new_device_id = f"{host.unique_id}_{host.api.camera_uid(ch)}"
|
new_device_id = f"{host.unique_id}_{host.api.camera_uid(ch)}"
|
||||||
else:
|
else:
|
||||||
new_device_id = f"{device_uid[0]}_{host.api.camera_uid(ch)}"
|
new_device_id = f"{device_uid[0]}_{host.api.camera_uid(ch)}"
|
||||||
|
_LOGGER.debug(
|
||||||
|
"Updating Reolink device UID from %s to %s", device_uid, new_device_id
|
||||||
|
)
|
||||||
new_identifiers = {(DOMAIN, new_device_id)}
|
new_identifiers = {(DOMAIN, new_device_id)}
|
||||||
existing_device = device_reg.async_get_device(identifiers=new_identifiers)
|
existing_device = device_reg.async_get_device(identifiers=new_identifiers)
|
||||||
if existing_device is None:
|
if existing_device is None:
|
||||||
@ -415,6 +421,11 @@ def migrate_entity_ids(
|
|||||||
host.unique_id
|
host.unique_id
|
||||||
):
|
):
|
||||||
new_id = f"{host.unique_id}_{entity.unique_id.split('_', 1)[1]}"
|
new_id = f"{host.unique_id}_{entity.unique_id.split('_', 1)[1]}"
|
||||||
|
_LOGGER.debug(
|
||||||
|
"Updating Reolink entity unique_id from %s to %s",
|
||||||
|
entity.unique_id,
|
||||||
|
new_id,
|
||||||
|
)
|
||||||
entity_reg.async_update_entity(entity.entity_id, new_unique_id=new_id)
|
entity_reg.async_update_entity(entity.entity_id, new_unique_id=new_id)
|
||||||
|
|
||||||
if entity.device_id in ch_device_ids:
|
if entity.device_id in ch_device_ids:
|
||||||
@ -430,6 +441,11 @@ def migrate_entity_ids(
|
|||||||
continue
|
continue
|
||||||
if host.api.supported(ch, "UID") and id_parts[1] != host.api.camera_uid(ch):
|
if host.api.supported(ch, "UID") and id_parts[1] != host.api.camera_uid(ch):
|
||||||
new_id = f"{host.unique_id}_{host.api.camera_uid(ch)}_{id_parts[2]}"
|
new_id = f"{host.unique_id}_{host.api.camera_uid(ch)}_{id_parts[2]}"
|
||||||
|
_LOGGER.debug(
|
||||||
|
"Updating Reolink entity unique_id from %s to %s",
|
||||||
|
entity.unique_id,
|
||||||
|
new_id,
|
||||||
|
)
|
||||||
existing_entity = entity_reg.async_get_entity_id(
|
existing_entity = entity_reg.async_get_entity_id(
|
||||||
entity.domain, entity.platform, new_id
|
entity.domain, entity.platform, new_id
|
||||||
)
|
)
|
||||||
|
@ -19,5 +19,5 @@
|
|||||||
"iot_class": "local_push",
|
"iot_class": "local_push",
|
||||||
"loggers": ["reolink_aio"],
|
"loggers": ["reolink_aio"],
|
||||||
"quality_scale": "platinum",
|
"quality_scale": "platinum",
|
||||||
"requirements": ["reolink-aio==0.13.1"]
|
"requirements": ["reolink-aio==0.13.2"]
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ class ReolinkVODMediaSource(MediaSource):
|
|||||||
host = get_host(self.hass, config_entry_id)
|
host = get_host(self.hass, config_entry_id)
|
||||||
|
|
||||||
def get_vod_type() -> VodRequestType:
|
def get_vod_type() -> VodRequestType:
|
||||||
if filename.endswith((".mp4", ".vref")):
|
if filename.endswith((".mp4", ".vref")) or host.api.is_hub:
|
||||||
if host.api.is_nvr:
|
if host.api.is_nvr:
|
||||||
return VodRequestType.DOWNLOAD
|
return VodRequestType.DOWNLOAD
|
||||||
return VodRequestType.PLAYBACK
|
return VodRequestType.PLAYBACK
|
||||||
|
@ -79,11 +79,15 @@ def get_device_uid_and_ch(
|
|||||||
device: dr.DeviceEntry, host: ReolinkHost
|
device: dr.DeviceEntry, host: ReolinkHost
|
||||||
) -> tuple[list[str], int | None, bool]:
|
) -> tuple[list[str], int | None, bool]:
|
||||||
"""Get the channel and the split device_uid from a reolink DeviceEntry."""
|
"""Get the channel and the split device_uid from a reolink DeviceEntry."""
|
||||||
device_uid = [
|
device_uid = []
|
||||||
dev_id[1].split("_") for dev_id in device.identifiers if dev_id[0] == DOMAIN
|
|
||||||
][0]
|
|
||||||
|
|
||||||
is_chime = False
|
is_chime = False
|
||||||
|
|
||||||
|
for dev_id in device.identifiers:
|
||||||
|
if dev_id[0] == DOMAIN:
|
||||||
|
device_uid = dev_id[1].split("_")
|
||||||
|
if device_uid[0] == host.unique_id:
|
||||||
|
break
|
||||||
|
|
||||||
if len(device_uid) < 2:
|
if len(device_uid) < 2:
|
||||||
# NVR itself
|
# NVR itself
|
||||||
ch = None
|
ch = None
|
||||||
|
@ -209,7 +209,7 @@ KELVIN_MIN_VALUE_COLOR: Final = 3000
|
|||||||
BLOCK_WRONG_SLEEP_PERIOD = 21600
|
BLOCK_WRONG_SLEEP_PERIOD = 21600
|
||||||
BLOCK_EXPECTED_SLEEP_PERIOD = 43200
|
BLOCK_EXPECTED_SLEEP_PERIOD = 43200
|
||||||
|
|
||||||
UPTIME_DEVIATION: Final = 5
|
UPTIME_DEVIATION: Final = 60
|
||||||
|
|
||||||
# Time to wait before reloading entry upon device config change
|
# Time to wait before reloading entry upon device config change
|
||||||
ENTRY_RELOAD_COOLDOWN = 60
|
ENTRY_RELOAD_COOLDOWN = 60
|
||||||
|
@ -200,8 +200,18 @@ def get_device_uptime(uptime: float, last_uptime: datetime | None) -> datetime:
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
not last_uptime
|
not last_uptime
|
||||||
or abs((delta_uptime - last_uptime).total_seconds()) > UPTIME_DEVIATION
|
or (diff := abs((delta_uptime - last_uptime).total_seconds()))
|
||||||
|
> UPTIME_DEVIATION
|
||||||
):
|
):
|
||||||
|
if last_uptime:
|
||||||
|
LOGGER.debug(
|
||||||
|
"Time deviation %s > %s: uptime=%s, last_uptime=%s, delta_uptime=%s",
|
||||||
|
diff,
|
||||||
|
UPTIME_DEVIATION,
|
||||||
|
uptime,
|
||||||
|
last_uptime,
|
||||||
|
delta_uptime,
|
||||||
|
)
|
||||||
return delta_uptime
|
return delta_uptime
|
||||||
|
|
||||||
return last_uptime
|
return last_uptime
|
||||||
|
@ -59,10 +59,11 @@ CAPABILITY_TO_SENSORS: dict[
|
|||||||
Category.DOOR: BinarySensorDeviceClass.DOOR,
|
Category.DOOR: BinarySensorDeviceClass.DOOR,
|
||||||
Category.WINDOW: BinarySensorDeviceClass.WINDOW,
|
Category.WINDOW: BinarySensorDeviceClass.WINDOW,
|
||||||
},
|
},
|
||||||
exists_fn=lambda key: key in {"freezer", "cooler"},
|
exists_fn=lambda key: key in {"freezer", "cooler", "cvroom"},
|
||||||
component_translation_key={
|
component_translation_key={
|
||||||
"freezer": "freezer_door",
|
"freezer": "freezer_door",
|
||||||
"cooler": "cooler_door",
|
"cooler": "cooler_door",
|
||||||
|
"cvroom": "cool_select_plus_door",
|
||||||
},
|
},
|
||||||
deprecated_fn=(
|
deprecated_fn=(
|
||||||
lambda status: "fridge_door"
|
lambda status: "fridge_door"
|
||||||
|
@ -23,7 +23,6 @@ from .entity import SmartThingsEntity
|
|||||||
MEDIA_PLAYER_CAPABILITIES = (
|
MEDIA_PLAYER_CAPABILITIES = (
|
||||||
Capability.AUDIO_MUTE,
|
Capability.AUDIO_MUTE,
|
||||||
Capability.AUDIO_VOLUME,
|
Capability.AUDIO_VOLUME,
|
||||||
Capability.MEDIA_PLAYBACK,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
CONTROLLABLE_SOURCES = ["bluetooth", "wifi"]
|
CONTROLLABLE_SOURCES = ["bluetooth", "wifi"]
|
||||||
@ -100,27 +99,25 @@ class SmartThingsMediaPlayer(SmartThingsEntity, MediaPlayerEntity):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def _determine_features(self) -> MediaPlayerEntityFeature:
|
def _determine_features(self) -> MediaPlayerEntityFeature:
|
||||||
flags = MediaPlayerEntityFeature(0)
|
flags = (
|
||||||
playback_commands = self.get_attribute_value(
|
MediaPlayerEntityFeature.VOLUME_SET
|
||||||
Capability.MEDIA_PLAYBACK, Attribute.SUPPORTED_PLAYBACK_COMMANDS
|
| MediaPlayerEntityFeature.VOLUME_STEP
|
||||||
|
| MediaPlayerEntityFeature.VOLUME_MUTE
|
||||||
)
|
)
|
||||||
if "play" in playback_commands:
|
if self.supports_capability(Capability.MEDIA_PLAYBACK):
|
||||||
flags |= MediaPlayerEntityFeature.PLAY
|
playback_commands = self.get_attribute_value(
|
||||||
if "pause" in playback_commands:
|
Capability.MEDIA_PLAYBACK, Attribute.SUPPORTED_PLAYBACK_COMMANDS
|
||||||
flags |= MediaPlayerEntityFeature.PAUSE
|
|
||||||
if "stop" in playback_commands:
|
|
||||||
flags |= MediaPlayerEntityFeature.STOP
|
|
||||||
if "rewind" in playback_commands:
|
|
||||||
flags |= MediaPlayerEntityFeature.PREVIOUS_TRACK
|
|
||||||
if "fastForward" in playback_commands:
|
|
||||||
flags |= MediaPlayerEntityFeature.NEXT_TRACK
|
|
||||||
if self.supports_capability(Capability.AUDIO_VOLUME):
|
|
||||||
flags |= (
|
|
||||||
MediaPlayerEntityFeature.VOLUME_SET
|
|
||||||
| MediaPlayerEntityFeature.VOLUME_STEP
|
|
||||||
)
|
)
|
||||||
if self.supports_capability(Capability.AUDIO_MUTE):
|
if "play" in playback_commands:
|
||||||
flags |= MediaPlayerEntityFeature.VOLUME_MUTE
|
flags |= MediaPlayerEntityFeature.PLAY
|
||||||
|
if "pause" in playback_commands:
|
||||||
|
flags |= MediaPlayerEntityFeature.PAUSE
|
||||||
|
if "stop" in playback_commands:
|
||||||
|
flags |= MediaPlayerEntityFeature.STOP
|
||||||
|
if "rewind" in playback_commands:
|
||||||
|
flags |= MediaPlayerEntityFeature.PREVIOUS_TRACK
|
||||||
|
if "fastForward" in playback_commands:
|
||||||
|
flags |= MediaPlayerEntityFeature.NEXT_TRACK
|
||||||
if self.supports_capability(Capability.SWITCH):
|
if self.supports_capability(Capability.SWITCH):
|
||||||
flags |= (
|
flags |= (
|
||||||
MediaPlayerEntityFeature.TURN_ON | MediaPlayerEntityFeature.TURN_OFF
|
MediaPlayerEntityFeature.TURN_ON | MediaPlayerEntityFeature.TURN_OFF
|
||||||
@ -270,6 +267,13 @@ class SmartThingsMediaPlayer(SmartThingsEntity, MediaPlayerEntity):
|
|||||||
def state(self) -> MediaPlayerState | None:
|
def state(self) -> MediaPlayerState | None:
|
||||||
"""State of the media player."""
|
"""State of the media player."""
|
||||||
if self.supports_capability(Capability.SWITCH):
|
if self.supports_capability(Capability.SWITCH):
|
||||||
|
if not self.supports_capability(Capability.MEDIA_PLAYBACK):
|
||||||
|
if (
|
||||||
|
self.get_attribute_value(Capability.SWITCH, Attribute.SWITCH)
|
||||||
|
== "on"
|
||||||
|
):
|
||||||
|
return MediaPlayerState.ON
|
||||||
|
return MediaPlayerState.OFF
|
||||||
if self.get_attribute_value(Capability.SWITCH, Attribute.SWITCH) == "on":
|
if self.get_attribute_value(Capability.SWITCH, Attribute.SWITCH) == "on":
|
||||||
if (
|
if (
|
||||||
self.source is not None
|
self.source is not None
|
||||||
|
@ -194,13 +194,7 @@ CAPABILITY_TO_SENSORS: dict[
|
|||||||
native_unit_of_measurement=PERCENTAGE,
|
native_unit_of_measurement=PERCENTAGE,
|
||||||
deprecated=(
|
deprecated=(
|
||||||
lambda status: "media_player"
|
lambda status: "media_player"
|
||||||
if all(
|
if Capability.AUDIO_MUTE in status
|
||||||
capability in status
|
|
||||||
for capability in (
|
|
||||||
Capability.AUDIO_MUTE,
|
|
||||||
Capability.MEDIA_PLAYBACK,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else None
|
else None
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -48,6 +48,9 @@
|
|||||||
"cooler_door": {
|
"cooler_door": {
|
||||||
"name": "Cooler door"
|
"name": "Cooler door"
|
||||||
},
|
},
|
||||||
|
"cool_select_plus_door": {
|
||||||
|
"name": "CoolSelect+ door"
|
||||||
|
},
|
||||||
"remote_control": {
|
"remote_control": {
|
||||||
"name": "Remote control"
|
"name": "Remote control"
|
||||||
},
|
},
|
||||||
|
@ -38,7 +38,6 @@ AC_CAPABILITIES = (
|
|||||||
MEDIA_PLAYER_CAPABILITIES = (
|
MEDIA_PLAYER_CAPABILITIES = (
|
||||||
Capability.AUDIO_MUTE,
|
Capability.AUDIO_MUTE,
|
||||||
Capability.AUDIO_VOLUME,
|
Capability.AUDIO_VOLUME,
|
||||||
Capability.MEDIA_PLAYBACK,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,5 +6,5 @@
|
|||||||
"documentation": "https://www.home-assistant.io/integrations/smhi",
|
"documentation": "https://www.home-assistant.io/integrations/smhi",
|
||||||
"iot_class": "cloud_polling",
|
"iot_class": "cloud_polling",
|
||||||
"loggers": ["pysmhi"],
|
"loggers": ["pysmhi"],
|
||||||
"requirements": ["pysmhi==1.0.1"]
|
"requirements": ["pysmhi==1.0.2"]
|
||||||
}
|
}
|
||||||
|
@ -148,7 +148,7 @@ def _build_response_apps_radios_category(
|
|||||||
) -> BrowseMedia:
|
) -> BrowseMedia:
|
||||||
"""Build item for App or radio category."""
|
"""Build item for App or radio category."""
|
||||||
return BrowseMedia(
|
return BrowseMedia(
|
||||||
media_content_id=item.get("id", ""),
|
media_content_id=item["id"],
|
||||||
title=item["title"],
|
title=item["title"],
|
||||||
media_content_type=cmd,
|
media_content_type=cmd,
|
||||||
media_class=browse_data.content_type_media_class[cmd]["item"],
|
media_class=browse_data.content_type_media_class[cmd]["item"],
|
||||||
@ -163,7 +163,7 @@ def _build_response_known_app(
|
|||||||
"""Build item for app or radio."""
|
"""Build item for app or radio."""
|
||||||
|
|
||||||
return BrowseMedia(
|
return BrowseMedia(
|
||||||
media_content_id=item.get("id", ""),
|
media_content_id=item["id"],
|
||||||
title=item["title"],
|
title=item["title"],
|
||||||
media_content_type=search_type,
|
media_content_type=search_type,
|
||||||
media_class=browse_data.content_type_media_class[search_type]["item"],
|
media_class=browse_data.content_type_media_class[search_type]["item"],
|
||||||
@ -185,7 +185,7 @@ def _build_response_favorites(item: dict[str, Any]) -> BrowseMedia:
|
|||||||
)
|
)
|
||||||
if item["hasitems"] and not item["isaudio"]:
|
if item["hasitems"] and not item["isaudio"]:
|
||||||
return BrowseMedia(
|
return BrowseMedia(
|
||||||
media_content_id=item.get("id", ""),
|
media_content_id=item["id"],
|
||||||
title=item["title"],
|
title=item["title"],
|
||||||
media_content_type="Favorites",
|
media_content_type="Favorites",
|
||||||
media_class=CONTENT_TYPE_MEDIA_CLASS["Favorites"]["item"],
|
media_class=CONTENT_TYPE_MEDIA_CLASS["Favorites"]["item"],
|
||||||
@ -193,7 +193,7 @@ def _build_response_favorites(item: dict[str, Any]) -> BrowseMedia:
|
|||||||
can_play=False,
|
can_play=False,
|
||||||
)
|
)
|
||||||
return BrowseMedia(
|
return BrowseMedia(
|
||||||
media_content_id=item.get("id", ""),
|
media_content_id=item["id"],
|
||||||
title=item["title"],
|
title=item["title"],
|
||||||
media_content_type="Favorites",
|
media_content_type="Favorites",
|
||||||
media_class=CONTENT_TYPE_MEDIA_CLASS[MediaType.TRACK]["item"],
|
media_class=CONTENT_TYPE_MEDIA_CLASS[MediaType.TRACK]["item"],
|
||||||
@ -217,7 +217,7 @@ def _get_item_thumbnail(
|
|||||||
item_thumbnail = player.generate_image_url_from_track_id(artwork_track_id)
|
item_thumbnail = player.generate_image_url_from_track_id(artwork_track_id)
|
||||||
elif item_type is not None:
|
elif item_type is not None:
|
||||||
item_thumbnail = entity.get_browse_image_url(
|
item_thumbnail = entity.get_browse_image_url(
|
||||||
item_type, item.get("id", ""), artwork_track_id
|
item_type, item["id"], artwork_track_id
|
||||||
)
|
)
|
||||||
|
|
||||||
elif search_type in ["Apps", "Radios"]:
|
elif search_type in ["Apps", "Radios"]:
|
||||||
@ -263,6 +263,8 @@ async def build_item_response(
|
|||||||
|
|
||||||
children = []
|
children = []
|
||||||
for item in result["items"]:
|
for item in result["items"]:
|
||||||
|
# Force the item id to a string in case it's numeric from some lms
|
||||||
|
item["id"] = str(item.get("id", ""))
|
||||||
if search_type == "Favorites":
|
if search_type == "Favorites":
|
||||||
child_media = _build_response_favorites(item)
|
child_media = _build_response_favorites(item)
|
||||||
|
|
||||||
@ -294,7 +296,7 @@ async def build_item_response(
|
|||||||
|
|
||||||
elif item_type:
|
elif item_type:
|
||||||
child_media = BrowseMedia(
|
child_media = BrowseMedia(
|
||||||
media_content_id=str(item.get("id", "")),
|
media_content_id=item["id"],
|
||||||
title=item["title"],
|
title=item["title"],
|
||||||
media_content_type=item_type,
|
media_content_type=item_type,
|
||||||
media_class=CONTENT_TYPE_MEDIA_CLASS[item_type]["item"],
|
media_class=CONTENT_TYPE_MEDIA_CLASS[item_type]["item"],
|
||||||
|
@ -113,7 +113,9 @@ SENSORS: tuple[StarlinkSensorEntityDescription, ...] = (
|
|||||||
translation_key="last_boot_time",
|
translation_key="last_boot_time",
|
||||||
device_class=SensorDeviceClass.TIMESTAMP,
|
device_class=SensorDeviceClass.TIMESTAMP,
|
||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
value_fn=lambda data: now() - timedelta(seconds=data.status["uptime"]),
|
value_fn=lambda data: (
|
||||||
|
now() - timedelta(seconds=data.status["uptime"])
|
||||||
|
).replace(microsecond=0),
|
||||||
),
|
),
|
||||||
StarlinkSensorEntityDescription(
|
StarlinkSensorEntityDescription(
|
||||||
key="ping_drop_rate",
|
key="ping_drop_rate",
|
||||||
|
@ -6,7 +6,12 @@ import logging
|
|||||||
|
|
||||||
from aiohttp import ClientError, ClientResponseError
|
from aiohttp import ClientError, ClientResponseError
|
||||||
from tesla_fleet_api.const import Scope
|
from tesla_fleet_api.const import Scope
|
||||||
from tesla_fleet_api.exceptions import TeslaFleetError
|
from tesla_fleet_api.exceptions import (
|
||||||
|
Forbidden,
|
||||||
|
InvalidToken,
|
||||||
|
SubscriptionRequired,
|
||||||
|
TeslaFleetError,
|
||||||
|
)
|
||||||
from tesla_fleet_api.tessie import Tessie
|
from tesla_fleet_api.tessie import Tessie
|
||||||
from tessie_api import get_state_of_all_vehicles
|
from tessie_api import get_state_of_all_vehicles
|
||||||
|
|
||||||
@ -124,12 +129,24 @@ async def async_setup_entry(hass: HomeAssistant, entry: TessieConfigEntry) -> bo
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
api = tessie.energySites.create(site_id)
|
api = tessie.energySites.create(site_id)
|
||||||
|
|
||||||
|
try:
|
||||||
|
live_status = (await api.live_status())["response"]
|
||||||
|
except (InvalidToken, Forbidden, SubscriptionRequired) as e:
|
||||||
|
raise ConfigEntryAuthFailed from e
|
||||||
|
except TeslaFleetError as e:
|
||||||
|
raise ConfigEntryNotReady(e.message) from e
|
||||||
|
|
||||||
energysites.append(
|
energysites.append(
|
||||||
TessieEnergyData(
|
TessieEnergyData(
|
||||||
api=api,
|
api=api,
|
||||||
id=site_id,
|
id=site_id,
|
||||||
live_coordinator=TessieEnergySiteLiveCoordinator(
|
live_coordinator=(
|
||||||
hass, entry, api
|
TessieEnergySiteLiveCoordinator(
|
||||||
|
hass, entry, api, live_status
|
||||||
|
)
|
||||||
|
if isinstance(live_status, dict)
|
||||||
|
else None
|
||||||
),
|
),
|
||||||
info_coordinator=TessieEnergySiteInfoCoordinator(
|
info_coordinator=TessieEnergySiteInfoCoordinator(
|
||||||
hass, entry, api
|
hass, entry, api
|
||||||
@ -147,6 +164,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: TessieConfigEntry) -> bo
|
|||||||
*(
|
*(
|
||||||
energysite.live_coordinator.async_config_entry_first_refresh()
|
energysite.live_coordinator.async_config_entry_first_refresh()
|
||||||
for energysite in energysites
|
for energysite in energysites
|
||||||
|
if energysite.live_coordinator is not None
|
||||||
),
|
),
|
||||||
*(
|
*(
|
||||||
energysite.info_coordinator.async_config_entry_first_refresh()
|
energysite.info_coordinator.async_config_entry_first_refresh()
|
||||||
|
@ -191,6 +191,7 @@ async def async_setup_entry(
|
|||||||
TessieEnergyLiveBinarySensorEntity(energy, description)
|
TessieEnergyLiveBinarySensorEntity(energy, description)
|
||||||
for energy in entry.runtime_data.energysites
|
for energy in entry.runtime_data.energysites
|
||||||
for description in ENERGY_LIVE_DESCRIPTIONS
|
for description in ENERGY_LIVE_DESCRIPTIONS
|
||||||
|
if energy.live_coordinator is not None
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
TessieEnergyInfoBinarySensorEntity(vehicle, description)
|
TessieEnergyInfoBinarySensorEntity(vehicle, description)
|
||||||
@ -233,6 +234,7 @@ class TessieEnergyLiveBinarySensorEntity(TessieEnergyEntity, BinarySensorEntity)
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the binary sensor."""
|
"""Initialize the binary sensor."""
|
||||||
self.entity_description = description
|
self.entity_description = description
|
||||||
|
assert data.live_coordinator is not None
|
||||||
super().__init__(data, data.live_coordinator, description.key)
|
super().__init__(data, data.live_coordinator, description.key)
|
||||||
|
|
||||||
def _async_update_attrs(self) -> None:
|
def _async_update_attrs(self) -> None:
|
||||||
|
@ -102,7 +102,11 @@ class TessieEnergySiteLiveCoordinator(DataUpdateCoordinator[dict[str, Any]]):
|
|||||||
config_entry: TessieConfigEntry
|
config_entry: TessieConfigEntry
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, hass: HomeAssistant, config_entry: TessieConfigEntry, api: EnergySite
|
self,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config_entry: TessieConfigEntry,
|
||||||
|
api: EnergySite,
|
||||||
|
data: dict[str, Any],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize Tessie Energy Site Live coordinator."""
|
"""Initialize Tessie Energy Site Live coordinator."""
|
||||||
super().__init__(
|
super().__init__(
|
||||||
@ -114,6 +118,12 @@ class TessieEnergySiteLiveCoordinator(DataUpdateCoordinator[dict[str, Any]]):
|
|||||||
)
|
)
|
||||||
self.api = api
|
self.api = api
|
||||||
|
|
||||||
|
# Convert Wall Connectors from array to dict
|
||||||
|
data["wall_connectors"] = {
|
||||||
|
wc["din"]: wc for wc in (data.get("wall_connectors") or [])
|
||||||
|
}
|
||||||
|
self.data = data
|
||||||
|
|
||||||
async def _async_update_data(self) -> dict[str, Any]:
|
async def _async_update_data(self) -> dict[str, Any]:
|
||||||
"""Update energy site data using Tessie API."""
|
"""Update energy site data using Tessie API."""
|
||||||
|
|
||||||
|
@ -41,7 +41,9 @@ async def async_get_config_entry_diagnostics(
|
|||||||
]
|
]
|
||||||
energysites = [
|
energysites = [
|
||||||
{
|
{
|
||||||
"live": async_redact_data(x.live_coordinator.data, ENERGY_LIVE_REDACT),
|
"live": async_redact_data(x.live_coordinator.data, ENERGY_LIVE_REDACT)
|
||||||
|
if x.live_coordinator
|
||||||
|
else None,
|
||||||
"info": async_redact_data(x.info_coordinator.data, ENERGY_INFO_REDACT),
|
"info": async_redact_data(x.info_coordinator.data, ENERGY_INFO_REDACT),
|
||||||
}
|
}
|
||||||
for x in entry.runtime_data.energysites
|
for x in entry.runtime_data.energysites
|
||||||
|
@ -155,7 +155,7 @@ class TessieWallConnectorEntity(TessieBaseEntity):
|
|||||||
via_device=(DOMAIN, str(data.id)),
|
via_device=(DOMAIN, str(data.id)),
|
||||||
serial_number=din.split("-")[-1],
|
serial_number=din.split("-")[-1],
|
||||||
)
|
)
|
||||||
|
assert data.live_coordinator
|
||||||
super().__init__(data.live_coordinator, key)
|
super().__init__(data.live_coordinator, key)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -28,7 +28,7 @@ class TessieEnergyData:
|
|||||||
"""Data for a Energy Site in the Tessie integration."""
|
"""Data for a Energy Site in the Tessie integration."""
|
||||||
|
|
||||||
api: EnergySite
|
api: EnergySite
|
||||||
live_coordinator: TessieEnergySiteLiveCoordinator
|
live_coordinator: TessieEnergySiteLiveCoordinator | None
|
||||||
info_coordinator: TessieEnergySiteInfoCoordinator
|
info_coordinator: TessieEnergySiteInfoCoordinator
|
||||||
id: int
|
id: int
|
||||||
device: DeviceInfo
|
device: DeviceInfo
|
||||||
|
@ -396,12 +396,16 @@ async def async_setup_entry(
|
|||||||
TessieEnergyLiveSensorEntity(energysite, description)
|
TessieEnergyLiveSensorEntity(energysite, description)
|
||||||
for energysite in entry.runtime_data.energysites
|
for energysite in entry.runtime_data.energysites
|
||||||
for description in ENERGY_LIVE_DESCRIPTIONS
|
for description in ENERGY_LIVE_DESCRIPTIONS
|
||||||
if description.key in energysite.live_coordinator.data
|
if energysite.live_coordinator is not None
|
||||||
or description.key == "percentage_charged"
|
and (
|
||||||
|
description.key in energysite.live_coordinator.data
|
||||||
|
or description.key == "percentage_charged"
|
||||||
|
)
|
||||||
),
|
),
|
||||||
( # Add wall connectors
|
( # Add wall connectors
|
||||||
TessieWallConnectorSensorEntity(energysite, din, description)
|
TessieWallConnectorSensorEntity(energysite, din, description)
|
||||||
for energysite in entry.runtime_data.energysites
|
for energysite in entry.runtime_data.energysites
|
||||||
|
if energysite.live_coordinator is not None
|
||||||
for din in energysite.live_coordinator.data.get("wall_connectors", {})
|
for din in energysite.live_coordinator.data.get("wall_connectors", {})
|
||||||
for description in WALL_CONNECTOR_DESCRIPTIONS
|
for description in WALL_CONNECTOR_DESCRIPTIONS
|
||||||
),
|
),
|
||||||
@ -446,6 +450,7 @@ class TessieEnergyLiveSensorEntity(TessieEnergyEntity, SensorEntity):
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the sensor."""
|
"""Initialize the sensor."""
|
||||||
self.entity_description = description
|
self.entity_description = description
|
||||||
|
assert data.live_coordinator is not None
|
||||||
super().__init__(data, data.live_coordinator, description.key)
|
super().__init__(data, data.live_coordinator, description.key)
|
||||||
|
|
||||||
def _async_update_attrs(self) -> None:
|
def _async_update_attrs(self) -> None:
|
||||||
|
@ -163,7 +163,7 @@ class UkTransportLiveBusTimeSensor(UkTransportSensor):
|
|||||||
self._destination_re = re.compile(f"{bus_direction}", re.IGNORECASE)
|
self._destination_re = re.compile(f"{bus_direction}", re.IGNORECASE)
|
||||||
|
|
||||||
sensor_name = f"Next bus to {bus_direction}"
|
sensor_name = f"Next bus to {bus_direction}"
|
||||||
stop_url = f"bus/stop/{stop_atcocode}/live.json"
|
stop_url = f"bus/stop/{stop_atcocode}.json"
|
||||||
|
|
||||||
UkTransportSensor.__init__(self, sensor_name, api_app_id, api_app_key, stop_url)
|
UkTransportSensor.__init__(self, sensor_name, api_app_id, api_app_key, stop_url)
|
||||||
self.update = Throttle(interval)(self._update)
|
self.update = Throttle(interval)(self._update)
|
||||||
@ -226,7 +226,7 @@ class UkTransportLiveTrainTimeSensor(UkTransportSensor):
|
|||||||
self._next_trains = []
|
self._next_trains = []
|
||||||
|
|
||||||
sensor_name = f"Next train to {calling_at}"
|
sensor_name = f"Next train to {calling_at}"
|
||||||
query_url = f"train/station/{station_code}/live.json"
|
query_url = f"train/station/{station_code}.json"
|
||||||
|
|
||||||
UkTransportSensor.__init__(
|
UkTransportSensor.__init__(
|
||||||
self, sensor_name, api_app_id, api_app_key, query_url
|
self, sensor_name, api_app_id, api_app_key, query_url
|
||||||
|
@ -7,5 +7,5 @@
|
|||||||
"iot_class": "local_polling",
|
"iot_class": "local_polling",
|
||||||
"loggers": ["holidays"],
|
"loggers": ["holidays"],
|
||||||
"quality_scale": "internal",
|
"quality_scale": "internal",
|
||||||
"requirements": ["holidays==0.69"]
|
"requirements": ["holidays==0.70"]
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
"zha",
|
"zha",
|
||||||
"universal_silabs_flasher"
|
"universal_silabs_flasher"
|
||||||
],
|
],
|
||||||
"requirements": ["zha==0.0.55"],
|
"requirements": ["zha==0.0.56"],
|
||||||
"usb": [
|
"usb": [
|
||||||
{
|
{
|
||||||
"vid": "10C4",
|
"vid": "10C4",
|
||||||
|
@ -25,7 +25,7 @@ if TYPE_CHECKING:
|
|||||||
APPLICATION_NAME: Final = "HomeAssistant"
|
APPLICATION_NAME: Final = "HomeAssistant"
|
||||||
MAJOR_VERSION: Final = 2025
|
MAJOR_VERSION: Final = 2025
|
||||||
MINOR_VERSION: Final = 4
|
MINOR_VERSION: Final = 4
|
||||||
PATCH_VERSION: Final = "2"
|
PATCH_VERSION: Final = "3"
|
||||||
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
||||||
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
|
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
|
||||||
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 13, 0)
|
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 13, 0)
|
||||||
|
@ -71,6 +71,19 @@ NO_ENTITIES_PROMPT = (
|
|||||||
"to their voice assistant in Home Assistant."
|
"to their voice assistant in Home Assistant."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
DYNAMIC_CONTEXT_PROMPT = """You ARE equipped to answer questions about the current state of
|
||||||
|
the home using the `GetLiveContext` tool. This is a primary function. Do not state you lack the
|
||||||
|
functionality if the question requires live data.
|
||||||
|
If the user asks about device existence/type (e.g., "Do I have lights in the bedroom?"): Answer
|
||||||
|
from the static context below.
|
||||||
|
If the user asks about the CURRENT state, value, or mode (e.g., "Is the lock locked?",
|
||||||
|
"Is the fan on?", "What mode is the thermostat in?", "What is the temperature outside?"):
|
||||||
|
1. Recognize this requires live data.
|
||||||
|
2. You MUST call `GetLiveContext`. This tool will provide the needed real-time information (like temperature from the local weather, lock status, etc.).
|
||||||
|
3. Use the tool's response** to answer the user accurately (e.g., "The temperature outside is [value from tool].").
|
||||||
|
For general knowledge questions not about the home: Answer truthfully from internal knowledge.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_render_no_api_prompt(hass: HomeAssistant) -> str:
|
def async_render_no_api_prompt(hass: HomeAssistant) -> str:
|
||||||
@ -384,6 +397,8 @@ class AssistAPI(API):
|
|||||||
):
|
):
|
||||||
prompt.append("This device is not able to start timers.")
|
prompt.append("This device is not able to start timers.")
|
||||||
|
|
||||||
|
prompt.append(DYNAMIC_CONTEXT_PROMPT)
|
||||||
|
|
||||||
return prompt
|
return prompt
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
@ -395,7 +410,7 @@ class AssistAPI(API):
|
|||||||
|
|
||||||
if exposed_entities and exposed_entities["entities"]:
|
if exposed_entities and exposed_entities["entities"]:
|
||||||
prompt.append(
|
prompt.append(
|
||||||
"An overview of the areas and the devices in this smart home:"
|
"Static Context: An overview of the areas and the devices in this smart home:"
|
||||||
)
|
)
|
||||||
prompt.append(yaml_util.dump(list(exposed_entities["entities"].values())))
|
prompt.append(yaml_util.dump(list(exposed_entities["entities"].values())))
|
||||||
|
|
||||||
@ -457,7 +472,7 @@ class AssistAPI(API):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if exposed_domains:
|
if exposed_domains:
|
||||||
tools.append(GetHomeStateTool())
|
tools.append(GetLiveContextTool())
|
||||||
|
|
||||||
return tools
|
return tools
|
||||||
|
|
||||||
@ -898,7 +913,7 @@ class CalendarGetEventsTool(Tool):
|
|||||||
return {"success": True, "result": events}
|
return {"success": True, "result": events}
|
||||||
|
|
||||||
|
|
||||||
class GetHomeStateTool(Tool):
|
class GetLiveContextTool(Tool):
|
||||||
"""Tool for getting the current state of exposed entities.
|
"""Tool for getting the current state of exposed entities.
|
||||||
|
|
||||||
This returns state for all entities that have been exposed to
|
This returns state for all entities that have been exposed to
|
||||||
@ -906,8 +921,13 @@ class GetHomeStateTool(Tool):
|
|||||||
returns state for entities based on intent parameters.
|
returns state for entities based on intent parameters.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name = "get_home_state"
|
name = "GetLiveContext"
|
||||||
description = "Get the current state of all devices in the home. "
|
description = (
|
||||||
|
"Use this tool when the user asks a question about the CURRENT state, "
|
||||||
|
"value, or mode of a specific device, sensor, entity, or area in the "
|
||||||
|
"smart home, and the answer can be improved with real-time data not "
|
||||||
|
"available in the static device overview list. "
|
||||||
|
)
|
||||||
|
|
||||||
async def async_call(
|
async def async_call(
|
||||||
self,
|
self,
|
||||||
@ -925,7 +945,7 @@ class GetHomeStateTool(Tool):
|
|||||||
if not exposed_entities["entities"]:
|
if not exposed_entities["entities"]:
|
||||||
return {"success": False, "error": NO_ENTITIES_PROMPT}
|
return {"success": False, "error": NO_ENTITIES_PROMPT}
|
||||||
prompt = [
|
prompt = [
|
||||||
"An overview of the areas and the devices in this smart home:",
|
"Live Context: An overview of the areas and the devices in this smart home:",
|
||||||
yaml_util.dump(list(exposed_entities["entities"].values())),
|
yaml_util.dump(list(exposed_entities["entities"].values())),
|
||||||
]
|
]
|
||||||
return {
|
return {
|
||||||
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "homeassistant"
|
name = "homeassistant"
|
||||||
version = "2025.4.2"
|
version = "2025.4.3"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
license-files = ["LICENSE*", "homeassistant/backports/LICENSE*"]
|
license-files = ["LICENSE*", "homeassistant/backports/LICENSE*"]
|
||||||
description = "Open-source home automation platform running on Python 3."
|
description = "Open-source home automation platform running on Python 3."
|
||||||
|
12
requirements_all.txt
generated
12
requirements_all.txt
generated
@ -781,7 +781,7 @@ devialet==1.5.7
|
|||||||
devolo-home-control-api==0.18.3
|
devolo-home-control-api==0.18.3
|
||||||
|
|
||||||
# homeassistant.components.devolo_home_network
|
# homeassistant.components.devolo_home_network
|
||||||
devolo-plc-api==1.4.1
|
devolo-plc-api==1.5.1
|
||||||
|
|
||||||
# homeassistant.components.chacon_dio
|
# homeassistant.components.chacon_dio
|
||||||
dio-chacon-wifi-api==1.2.1
|
dio-chacon-wifi-api==1.2.1
|
||||||
@ -871,7 +871,7 @@ enocean==0.50
|
|||||||
enturclient==0.2.4
|
enturclient==0.2.4
|
||||||
|
|
||||||
# homeassistant.components.environment_canada
|
# homeassistant.components.environment_canada
|
||||||
env-canada==0.8.0
|
env-canada==0.10.1
|
||||||
|
|
||||||
# homeassistant.components.season
|
# homeassistant.components.season
|
||||||
ephem==4.1.6
|
ephem==4.1.6
|
||||||
@ -1154,7 +1154,7 @@ hole==0.8.0
|
|||||||
|
|
||||||
# homeassistant.components.holiday
|
# homeassistant.components.holiday
|
||||||
# homeassistant.components.workday
|
# homeassistant.components.workday
|
||||||
holidays==0.69
|
holidays==0.70
|
||||||
|
|
||||||
# homeassistant.components.frontend
|
# homeassistant.components.frontend
|
||||||
home-assistant-frontend==20250411.0
|
home-assistant-frontend==20250411.0
|
||||||
@ -2325,7 +2325,7 @@ pysmartthings==3.0.4
|
|||||||
pysmarty2==0.10.2
|
pysmarty2==0.10.2
|
||||||
|
|
||||||
# homeassistant.components.smhi
|
# homeassistant.components.smhi
|
||||||
pysmhi==1.0.1
|
pysmhi==1.0.2
|
||||||
|
|
||||||
# homeassistant.components.edl21
|
# homeassistant.components.edl21
|
||||||
pysml==0.0.12
|
pysml==0.0.12
|
||||||
@ -2627,7 +2627,7 @@ renault-api==0.2.9
|
|||||||
renson-endura-delta==1.7.2
|
renson-endura-delta==1.7.2
|
||||||
|
|
||||||
# homeassistant.components.reolink
|
# homeassistant.components.reolink
|
||||||
reolink-aio==0.13.1
|
reolink-aio==0.13.2
|
||||||
|
|
||||||
# homeassistant.components.idteck_prox
|
# homeassistant.components.idteck_prox
|
||||||
rfk101py==0.0.1
|
rfk101py==0.0.1
|
||||||
@ -3152,7 +3152,7 @@ zeroconf==0.146.0
|
|||||||
zeversolar==0.3.2
|
zeversolar==0.3.2
|
||||||
|
|
||||||
# homeassistant.components.zha
|
# homeassistant.components.zha
|
||||||
zha==0.0.55
|
zha==0.0.56
|
||||||
|
|
||||||
# homeassistant.components.zhong_hong
|
# homeassistant.components.zhong_hong
|
||||||
zhong-hong-hvac==1.0.13
|
zhong-hong-hvac==1.0.13
|
||||||
|
12
requirements_test_all.txt
generated
12
requirements_test_all.txt
generated
@ -672,7 +672,7 @@ devialet==1.5.7
|
|||||||
devolo-home-control-api==0.18.3
|
devolo-home-control-api==0.18.3
|
||||||
|
|
||||||
# homeassistant.components.devolo_home_network
|
# homeassistant.components.devolo_home_network
|
||||||
devolo-plc-api==1.4.1
|
devolo-plc-api==1.5.1
|
||||||
|
|
||||||
# homeassistant.components.chacon_dio
|
# homeassistant.components.chacon_dio
|
||||||
dio-chacon-wifi-api==1.2.1
|
dio-chacon-wifi-api==1.2.1
|
||||||
@ -741,7 +741,7 @@ energyzero==2.1.1
|
|||||||
enocean==0.50
|
enocean==0.50
|
||||||
|
|
||||||
# homeassistant.components.environment_canada
|
# homeassistant.components.environment_canada
|
||||||
env-canada==0.8.0
|
env-canada==0.10.1
|
||||||
|
|
||||||
# homeassistant.components.season
|
# homeassistant.components.season
|
||||||
ephem==4.1.6
|
ephem==4.1.6
|
||||||
@ -981,7 +981,7 @@ hole==0.8.0
|
|||||||
|
|
||||||
# homeassistant.components.holiday
|
# homeassistant.components.holiday
|
||||||
# homeassistant.components.workday
|
# homeassistant.components.workday
|
||||||
holidays==0.69
|
holidays==0.70
|
||||||
|
|
||||||
# homeassistant.components.frontend
|
# homeassistant.components.frontend
|
||||||
home-assistant-frontend==20250411.0
|
home-assistant-frontend==20250411.0
|
||||||
@ -1895,7 +1895,7 @@ pysmartthings==3.0.4
|
|||||||
pysmarty2==0.10.2
|
pysmarty2==0.10.2
|
||||||
|
|
||||||
# homeassistant.components.smhi
|
# homeassistant.components.smhi
|
||||||
pysmhi==1.0.1
|
pysmhi==1.0.2
|
||||||
|
|
||||||
# homeassistant.components.edl21
|
# homeassistant.components.edl21
|
||||||
pysml==0.0.12
|
pysml==0.0.12
|
||||||
@ -2128,7 +2128,7 @@ renault-api==0.2.9
|
|||||||
renson-endura-delta==1.7.2
|
renson-endura-delta==1.7.2
|
||||||
|
|
||||||
# homeassistant.components.reolink
|
# homeassistant.components.reolink
|
||||||
reolink-aio==0.13.1
|
reolink-aio==0.13.2
|
||||||
|
|
||||||
# homeassistant.components.rflink
|
# homeassistant.components.rflink
|
||||||
rflink==0.0.66
|
rflink==0.0.66
|
||||||
@ -2542,7 +2542,7 @@ zeroconf==0.146.0
|
|||||||
zeversolar==0.3.2
|
zeversolar==0.3.2
|
||||||
|
|
||||||
# homeassistant.components.zha
|
# homeassistant.components.zha
|
||||||
zha==0.0.55
|
zha==0.0.56
|
||||||
|
|
||||||
# homeassistant.components.zwave_js
|
# homeassistant.components.zwave_js
|
||||||
zwave-js-server-python==0.62.0
|
zwave-js-server-python==0.62.0
|
||||||
|
@ -88,6 +88,7 @@ OSI_APPROVED_LICENSES_SPDX = {
|
|||||||
"MPL-1.1",
|
"MPL-1.1",
|
||||||
"MPL-2.0",
|
"MPL-2.0",
|
||||||
"PSF-2.0",
|
"PSF-2.0",
|
||||||
|
"Python-2.0",
|
||||||
"Unlicense",
|
"Unlicense",
|
||||||
"Zlib",
|
"Zlib",
|
||||||
"ZPL-2.1",
|
"ZPL-2.1",
|
||||||
|
@ -33,7 +33,7 @@ async def init_integration(hass: HomeAssistant, ec_data) -> MockConfigEntry:
|
|||||||
config_entry.add_to_hass(hass)
|
config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
weather_mock = mock_ec()
|
weather_mock = mock_ec()
|
||||||
ec_data["metadata"]["timestamp"] = datetime(2022, 10, 4, tzinfo=UTC)
|
ec_data["metadata"].timestamp = datetime(2022, 10, 4, tzinfo=UTC)
|
||||||
weather_mock.conditions = ec_data["conditions"]
|
weather_mock.conditions = ec_data["conditions"]
|
||||||
weather_mock.alerts = ec_data["alerts"]
|
weather_mock.alerts = ec_data["alerts"]
|
||||||
weather_mock.daily_forecasts = ec_data["daily_forecasts"]
|
weather_mock.daily_forecasts = ec_data["daily_forecasts"]
|
||||||
|
@ -4,6 +4,7 @@ import contextlib
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
from env_canada.ec_weather import MetaData
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from tests.common import load_fixture
|
from tests.common import load_fixture
|
||||||
@ -13,7 +14,7 @@ from tests.common import load_fixture
|
|||||||
def ec_data():
|
def ec_data():
|
||||||
"""Load Environment Canada data."""
|
"""Load Environment Canada data."""
|
||||||
|
|
||||||
def date_hook(weather):
|
def data_hook(weather):
|
||||||
"""Convert timestamp string to datetime."""
|
"""Convert timestamp string to datetime."""
|
||||||
|
|
||||||
if t := weather.get("timestamp"):
|
if t := weather.get("timestamp"):
|
||||||
@ -22,9 +23,11 @@ def ec_data():
|
|||||||
elif t := weather.get("period"):
|
elif t := weather.get("period"):
|
||||||
with contextlib.suppress(ValueError):
|
with contextlib.suppress(ValueError):
|
||||||
weather["period"] = datetime.fromisoformat(t)
|
weather["period"] = datetime.fromisoformat(t)
|
||||||
|
if t := weather.get("metadata"):
|
||||||
|
weather["metadata"] = MetaData(**t)
|
||||||
return weather
|
return weather
|
||||||
|
|
||||||
return json.loads(
|
return json.loads(
|
||||||
load_fixture("environment_canada/current_conditions_data.json"),
|
load_fixture("environment_canada/current_conditions_data.json"),
|
||||||
object_hook=date_hook,
|
object_hook=data_hook,
|
||||||
)
|
)
|
||||||
|
@ -30,7 +30,7 @@ def mocked_ec():
|
|||||||
ec_mock.lat = FAKE_CONFIG[CONF_LATITUDE]
|
ec_mock.lat = FAKE_CONFIG[CONF_LATITUDE]
|
||||||
ec_mock.lon = FAKE_CONFIG[CONF_LONGITUDE]
|
ec_mock.lon = FAKE_CONFIG[CONF_LONGITUDE]
|
||||||
ec_mock.language = FAKE_CONFIG[CONF_LANGUAGE]
|
ec_mock.language = FAKE_CONFIG[CONF_LANGUAGE]
|
||||||
ec_mock.metadata = {"location": FAKE_TITLE}
|
ec_mock.metadata.location = FAKE_TITLE
|
||||||
|
|
||||||
ec_mock.update = AsyncMock()
|
ec_mock.update = AsyncMock()
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
"""Test Environment Canada diagnostics."""
|
"""Test Environment Canada diagnostics."""
|
||||||
|
|
||||||
import json
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from syrupy import SnapshotAssertion
|
from syrupy import SnapshotAssertion
|
||||||
@ -11,7 +10,6 @@ from homeassistant.core import HomeAssistant
|
|||||||
|
|
||||||
from . import init_integration
|
from . import init_integration
|
||||||
|
|
||||||
from tests.common import load_fixture
|
|
||||||
from tests.components.diagnostics import get_diagnostics_for_config_entry
|
from tests.components.diagnostics import get_diagnostics_for_config_entry
|
||||||
from tests.typing import ClientSessionGenerator
|
from tests.typing import ClientSessionGenerator
|
||||||
|
|
||||||
@ -31,10 +29,6 @@ async def test_entry_diagnostics(
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Test config entry diagnostics."""
|
"""Test config entry diagnostics."""
|
||||||
|
|
||||||
ec_data = json.loads(
|
|
||||||
load_fixture("environment_canada/current_conditions_data.json")
|
|
||||||
)
|
|
||||||
|
|
||||||
config_entry = await init_integration(hass, ec_data)
|
config_entry = await init_integration(hass, ec_data)
|
||||||
diagnostics = await get_diagnostics_for_config_entry(
|
diagnostics = await get_diagnostics_for_config_entry(
|
||||||
hass, hass_client, config_entry
|
hass, hass_client, config_entry
|
||||||
|
@ -624,6 +624,49 @@
|
|||||||
"isDue": false,
|
"isDue": false,
|
||||||
"id": "6e53f1f5-a315-4edd-984d-8d762e4a08ef"
|
"id": "6e53f1f5-a315-4edd-984d-8d762e4a08ef"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"repeat": {
|
||||||
|
"m": false,
|
||||||
|
"t": false,
|
||||||
|
"w": false,
|
||||||
|
"th": false,
|
||||||
|
"f": false,
|
||||||
|
"s": false,
|
||||||
|
"su": true
|
||||||
|
},
|
||||||
|
"challenge": {},
|
||||||
|
"group": {
|
||||||
|
"completedBy": {},
|
||||||
|
"assignedUsers": []
|
||||||
|
},
|
||||||
|
"_id": "369afeed-61e3-4bf7-9747-66e05807134c",
|
||||||
|
"frequency": "monthly",
|
||||||
|
"everyX": 1,
|
||||||
|
"streak": 1,
|
||||||
|
"nextDue": ["2024-12-14T23:00:00.000Z", "2025-01-18T23:00:00.000Z"],
|
||||||
|
"yesterDaily": true,
|
||||||
|
"history": [],
|
||||||
|
"completed": false,
|
||||||
|
"collapseChecklist": false,
|
||||||
|
"type": "daily",
|
||||||
|
"text": "Monatliche Finanzübersicht erstellen",
|
||||||
|
"notes": "Setze dich einmal im Monat hin, um deine Einnahmen und Ausgaben zu überprüfen und dein Budget zu planen.",
|
||||||
|
"tags": [],
|
||||||
|
"value": -0.9215181434950852,
|
||||||
|
"priority": 1,
|
||||||
|
"attribute": "str",
|
||||||
|
"byHabitica": false,
|
||||||
|
"startDate": "2024-04-04T22:00:00.000Z",
|
||||||
|
"daysOfMonth": [],
|
||||||
|
"weeksOfMonth": [0],
|
||||||
|
"checklist": [],
|
||||||
|
"reminders": [],
|
||||||
|
"createdAt": "2024-04-04T22:00:00.000Z",
|
||||||
|
"updatedAt": "2024-04-04T22:00:00.000Z",
|
||||||
|
"userId": "5f359083-ef78-4af0-985a-0b2c6d05797c",
|
||||||
|
"isDue": false,
|
||||||
|
"id": "369afeed-61e3-4bf7-9747-66e05807134c"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"repeat": {
|
"repeat": {
|
||||||
"m": false,
|
"m": false,
|
||||||
|
@ -66,7 +66,8 @@
|
|||||||
"564b9ac9-c53d-4638-9e7f-1cd96fe19baa",
|
"564b9ac9-c53d-4638-9e7f-1cd96fe19baa",
|
||||||
"f2c85972-1a19-4426-bc6d-ce3337b9d99f",
|
"f2c85972-1a19-4426-bc6d-ce3337b9d99f",
|
||||||
"2c6d136c-a1c3-4bef-b7c4-fa980784b1e1",
|
"2c6d136c-a1c3-4bef-b7c4-fa980784b1e1",
|
||||||
"6e53f1f5-a315-4edd-984d-8d762e4a08ef"
|
"6e53f1f5-a315-4edd-984d-8d762e4a08ef",
|
||||||
|
"369afeed-61e3-4bf7-9747-66e05807134c"
|
||||||
],
|
],
|
||||||
"habits": ["1d147de6-5c02-4740-8e2f-71d3015a37f4"]
|
"habits": ["1d147de6-5c02-4740-8e2f-71d3015a37f4"]
|
||||||
},
|
},
|
||||||
|
@ -87,6 +87,20 @@
|
|||||||
'summary': 'Fitnessstudio besuchen',
|
'summary': 'Fitnessstudio besuchen',
|
||||||
'uid': '2c6d136c-a1c3-4bef-b7c4-fa980784b1e1',
|
'uid': '2c6d136c-a1c3-4bef-b7c4-fa980784b1e1',
|
||||||
}),
|
}),
|
||||||
|
dict({
|
||||||
|
'description': 'Klicke um den Namen Deines aktuellen Projekts anzugeben & setze einen Terminplan!',
|
||||||
|
'end': dict({
|
||||||
|
'date': '2024-09-23',
|
||||||
|
}),
|
||||||
|
'location': None,
|
||||||
|
'recurrence_id': None,
|
||||||
|
'rrule': 'FREQ=MONTHLY;BYSETPOS=4;BYDAY=SU',
|
||||||
|
'start': dict({
|
||||||
|
'date': '2024-09-22',
|
||||||
|
}),
|
||||||
|
'summary': 'Arbeite an einem kreativen Projekt',
|
||||||
|
'uid': '6e53f1f5-a315-4edd-984d-8d762e4a08ef',
|
||||||
|
}),
|
||||||
dict({
|
dict({
|
||||||
'description': 'Klicke um Änderungen zu machen!',
|
'description': 'Klicke um Änderungen zu machen!',
|
||||||
'end': dict({
|
'end': dict({
|
||||||
@ -563,6 +577,20 @@
|
|||||||
'summary': 'Fitnessstudio besuchen',
|
'summary': 'Fitnessstudio besuchen',
|
||||||
'uid': '2c6d136c-a1c3-4bef-b7c4-fa980784b1e1',
|
'uid': '2c6d136c-a1c3-4bef-b7c4-fa980784b1e1',
|
||||||
}),
|
}),
|
||||||
|
dict({
|
||||||
|
'description': 'Setze dich einmal im Monat hin, um deine Einnahmen und Ausgaben zu überprüfen und dein Budget zu planen.',
|
||||||
|
'end': dict({
|
||||||
|
'date': '2024-10-07',
|
||||||
|
}),
|
||||||
|
'location': None,
|
||||||
|
'recurrence_id': None,
|
||||||
|
'rrule': 'FREQ=MONTHLY;BYSETPOS=1;BYDAY=SU',
|
||||||
|
'start': dict({
|
||||||
|
'date': '2024-10-06',
|
||||||
|
}),
|
||||||
|
'summary': 'Monatliche Finanzübersicht erstellen',
|
||||||
|
'uid': '369afeed-61e3-4bf7-9747-66e05807134c',
|
||||||
|
}),
|
||||||
dict({
|
dict({
|
||||||
'description': 'Klicke um Änderungen zu machen!',
|
'description': 'Klicke um Änderungen zu machen!',
|
||||||
'end': dict({
|
'end': dict({
|
||||||
|
@ -1193,6 +1193,81 @@
|
|||||||
]),
|
]),
|
||||||
'yesterDaily': True,
|
'yesterDaily': True,
|
||||||
}),
|
}),
|
||||||
|
dict({
|
||||||
|
'alias': None,
|
||||||
|
'attribute': 'str',
|
||||||
|
'byHabitica': False,
|
||||||
|
'challenge': dict({
|
||||||
|
'broken': None,
|
||||||
|
'id': None,
|
||||||
|
'shortName': None,
|
||||||
|
'taskId': None,
|
||||||
|
'winner': None,
|
||||||
|
}),
|
||||||
|
'checklist': list([
|
||||||
|
]),
|
||||||
|
'collapseChecklist': False,
|
||||||
|
'completed': False,
|
||||||
|
'counterDown': None,
|
||||||
|
'counterUp': None,
|
||||||
|
'createdAt': '2024-04-04T22:00:00+00:00',
|
||||||
|
'date': None,
|
||||||
|
'daysOfMonth': list([
|
||||||
|
]),
|
||||||
|
'down': None,
|
||||||
|
'everyX': 1,
|
||||||
|
'frequency': 'monthly',
|
||||||
|
'group': dict({
|
||||||
|
'assignedDate': None,
|
||||||
|
'assignedUsers': list([
|
||||||
|
]),
|
||||||
|
'assignedUsersDetail': dict({
|
||||||
|
}),
|
||||||
|
'assigningUsername': None,
|
||||||
|
'completedBy': dict({
|
||||||
|
'date': None,
|
||||||
|
'userId': None,
|
||||||
|
}),
|
||||||
|
'id': None,
|
||||||
|
'managerNotes': None,
|
||||||
|
'taskId': None,
|
||||||
|
}),
|
||||||
|
'history': list([
|
||||||
|
]),
|
||||||
|
'id': '369afeed-61e3-4bf7-9747-66e05807134c',
|
||||||
|
'isDue': False,
|
||||||
|
'nextDue': list([
|
||||||
|
'2024-12-14T23:00:00+00:00',
|
||||||
|
'2025-01-18T23:00:00+00:00',
|
||||||
|
]),
|
||||||
|
'notes': 'Setze dich einmal im Monat hin, um deine Einnahmen und Ausgaben zu überprüfen und dein Budget zu planen.',
|
||||||
|
'priority': 1,
|
||||||
|
'reminders': list([
|
||||||
|
]),
|
||||||
|
'repeat': dict({
|
||||||
|
'f': False,
|
||||||
|
'm': False,
|
||||||
|
's': False,
|
||||||
|
'su': True,
|
||||||
|
't': False,
|
||||||
|
'th': False,
|
||||||
|
'w': False,
|
||||||
|
}),
|
||||||
|
'startDate': '2024-04-04T22:00:00+00:00',
|
||||||
|
'streak': 1,
|
||||||
|
'tags': list([
|
||||||
|
]),
|
||||||
|
'text': 'Monatliche Finanzübersicht erstellen',
|
||||||
|
'type': 'daily',
|
||||||
|
'up': None,
|
||||||
|
'updatedAt': '2024-04-04T22:00:00+00:00',
|
||||||
|
'userId': '5f359083-ef78-4af0-985a-0b2c6d05797c',
|
||||||
|
'value': -0.9215181434950852,
|
||||||
|
'weeksOfMonth': list([
|
||||||
|
0,
|
||||||
|
]),
|
||||||
|
'yesterDaily': True,
|
||||||
|
}),
|
||||||
dict({
|
dict({
|
||||||
'alias': None,
|
'alias': None,
|
||||||
'attribute': 'str',
|
'attribute': 'str',
|
||||||
@ -3465,6 +3540,81 @@
|
|||||||
]),
|
]),
|
||||||
'yesterDaily': True,
|
'yesterDaily': True,
|
||||||
}),
|
}),
|
||||||
|
dict({
|
||||||
|
'alias': None,
|
||||||
|
'attribute': 'str',
|
||||||
|
'byHabitica': False,
|
||||||
|
'challenge': dict({
|
||||||
|
'broken': None,
|
||||||
|
'id': None,
|
||||||
|
'shortName': None,
|
||||||
|
'taskId': None,
|
||||||
|
'winner': None,
|
||||||
|
}),
|
||||||
|
'checklist': list([
|
||||||
|
]),
|
||||||
|
'collapseChecklist': False,
|
||||||
|
'completed': False,
|
||||||
|
'counterDown': None,
|
||||||
|
'counterUp': None,
|
||||||
|
'createdAt': '2024-04-04T22:00:00+00:00',
|
||||||
|
'date': None,
|
||||||
|
'daysOfMonth': list([
|
||||||
|
]),
|
||||||
|
'down': None,
|
||||||
|
'everyX': 1,
|
||||||
|
'frequency': 'monthly',
|
||||||
|
'group': dict({
|
||||||
|
'assignedDate': None,
|
||||||
|
'assignedUsers': list([
|
||||||
|
]),
|
||||||
|
'assignedUsersDetail': dict({
|
||||||
|
}),
|
||||||
|
'assigningUsername': None,
|
||||||
|
'completedBy': dict({
|
||||||
|
'date': None,
|
||||||
|
'userId': None,
|
||||||
|
}),
|
||||||
|
'id': None,
|
||||||
|
'managerNotes': None,
|
||||||
|
'taskId': None,
|
||||||
|
}),
|
||||||
|
'history': list([
|
||||||
|
]),
|
||||||
|
'id': '369afeed-61e3-4bf7-9747-66e05807134c',
|
||||||
|
'isDue': False,
|
||||||
|
'nextDue': list([
|
||||||
|
'2024-12-14T23:00:00+00:00',
|
||||||
|
'2025-01-18T23:00:00+00:00',
|
||||||
|
]),
|
||||||
|
'notes': 'Setze dich einmal im Monat hin, um deine Einnahmen und Ausgaben zu überprüfen und dein Budget zu planen.',
|
||||||
|
'priority': 1,
|
||||||
|
'reminders': list([
|
||||||
|
]),
|
||||||
|
'repeat': dict({
|
||||||
|
'f': False,
|
||||||
|
'm': False,
|
||||||
|
's': False,
|
||||||
|
'su': True,
|
||||||
|
't': False,
|
||||||
|
'th': False,
|
||||||
|
'w': False,
|
||||||
|
}),
|
||||||
|
'startDate': '2024-04-04T22:00:00+00:00',
|
||||||
|
'streak': 1,
|
||||||
|
'tags': list([
|
||||||
|
]),
|
||||||
|
'text': 'Monatliche Finanzübersicht erstellen',
|
||||||
|
'type': 'daily',
|
||||||
|
'up': None,
|
||||||
|
'updatedAt': '2024-04-04T22:00:00+00:00',
|
||||||
|
'userId': '5f359083-ef78-4af0-985a-0b2c6d05797c',
|
||||||
|
'value': -0.9215181434950852,
|
||||||
|
'weeksOfMonth': list([
|
||||||
|
0,
|
||||||
|
]),
|
||||||
|
'yesterDaily': True,
|
||||||
|
}),
|
||||||
dict({
|
dict({
|
||||||
'alias': None,
|
'alias': None,
|
||||||
'attribute': 'str',
|
'attribute': 'str',
|
||||||
@ -4608,6 +4758,81 @@
|
|||||||
]),
|
]),
|
||||||
'yesterDaily': True,
|
'yesterDaily': True,
|
||||||
}),
|
}),
|
||||||
|
dict({
|
||||||
|
'alias': None,
|
||||||
|
'attribute': 'str',
|
||||||
|
'byHabitica': False,
|
||||||
|
'challenge': dict({
|
||||||
|
'broken': None,
|
||||||
|
'id': None,
|
||||||
|
'shortName': None,
|
||||||
|
'taskId': None,
|
||||||
|
'winner': None,
|
||||||
|
}),
|
||||||
|
'checklist': list([
|
||||||
|
]),
|
||||||
|
'collapseChecklist': False,
|
||||||
|
'completed': False,
|
||||||
|
'counterDown': None,
|
||||||
|
'counterUp': None,
|
||||||
|
'createdAt': '2024-04-04T22:00:00+00:00',
|
||||||
|
'date': None,
|
||||||
|
'daysOfMonth': list([
|
||||||
|
]),
|
||||||
|
'down': None,
|
||||||
|
'everyX': 1,
|
||||||
|
'frequency': 'monthly',
|
||||||
|
'group': dict({
|
||||||
|
'assignedDate': None,
|
||||||
|
'assignedUsers': list([
|
||||||
|
]),
|
||||||
|
'assignedUsersDetail': dict({
|
||||||
|
}),
|
||||||
|
'assigningUsername': None,
|
||||||
|
'completedBy': dict({
|
||||||
|
'date': None,
|
||||||
|
'userId': None,
|
||||||
|
}),
|
||||||
|
'id': None,
|
||||||
|
'managerNotes': None,
|
||||||
|
'taskId': None,
|
||||||
|
}),
|
||||||
|
'history': list([
|
||||||
|
]),
|
||||||
|
'id': '369afeed-61e3-4bf7-9747-66e05807134c',
|
||||||
|
'isDue': False,
|
||||||
|
'nextDue': list([
|
||||||
|
'2024-12-14T23:00:00+00:00',
|
||||||
|
'2025-01-18T23:00:00+00:00',
|
||||||
|
]),
|
||||||
|
'notes': 'Setze dich einmal im Monat hin, um deine Einnahmen und Ausgaben zu überprüfen und dein Budget zu planen.',
|
||||||
|
'priority': 1,
|
||||||
|
'reminders': list([
|
||||||
|
]),
|
||||||
|
'repeat': dict({
|
||||||
|
'f': False,
|
||||||
|
'm': False,
|
||||||
|
's': False,
|
||||||
|
'su': True,
|
||||||
|
't': False,
|
||||||
|
'th': False,
|
||||||
|
'w': False,
|
||||||
|
}),
|
||||||
|
'startDate': '2024-04-04T22:00:00+00:00',
|
||||||
|
'streak': 1,
|
||||||
|
'tags': list([
|
||||||
|
]),
|
||||||
|
'text': 'Monatliche Finanzübersicht erstellen',
|
||||||
|
'type': 'daily',
|
||||||
|
'up': None,
|
||||||
|
'updatedAt': '2024-04-04T22:00:00+00:00',
|
||||||
|
'userId': '5f359083-ef78-4af0-985a-0b2c6d05797c',
|
||||||
|
'value': -0.9215181434950852,
|
||||||
|
'weeksOfMonth': list([
|
||||||
|
0,
|
||||||
|
]),
|
||||||
|
'yesterDaily': True,
|
||||||
|
}),
|
||||||
dict({
|
dict({
|
||||||
'alias': None,
|
'alias': None,
|
||||||
'attribute': 'str',
|
'attribute': 'str',
|
||||||
@ -5199,6 +5424,81 @@
|
|||||||
]),
|
]),
|
||||||
'yesterDaily': True,
|
'yesterDaily': True,
|
||||||
}),
|
}),
|
||||||
|
dict({
|
||||||
|
'alias': None,
|
||||||
|
'attribute': 'str',
|
||||||
|
'byHabitica': False,
|
||||||
|
'challenge': dict({
|
||||||
|
'broken': None,
|
||||||
|
'id': None,
|
||||||
|
'shortName': None,
|
||||||
|
'taskId': None,
|
||||||
|
'winner': None,
|
||||||
|
}),
|
||||||
|
'checklist': list([
|
||||||
|
]),
|
||||||
|
'collapseChecklist': False,
|
||||||
|
'completed': False,
|
||||||
|
'counterDown': None,
|
||||||
|
'counterUp': None,
|
||||||
|
'createdAt': '2024-04-04T22:00:00+00:00',
|
||||||
|
'date': None,
|
||||||
|
'daysOfMonth': list([
|
||||||
|
]),
|
||||||
|
'down': None,
|
||||||
|
'everyX': 1,
|
||||||
|
'frequency': 'monthly',
|
||||||
|
'group': dict({
|
||||||
|
'assignedDate': None,
|
||||||
|
'assignedUsers': list([
|
||||||
|
]),
|
||||||
|
'assignedUsersDetail': dict({
|
||||||
|
}),
|
||||||
|
'assigningUsername': None,
|
||||||
|
'completedBy': dict({
|
||||||
|
'date': None,
|
||||||
|
'userId': None,
|
||||||
|
}),
|
||||||
|
'id': None,
|
||||||
|
'managerNotes': None,
|
||||||
|
'taskId': None,
|
||||||
|
}),
|
||||||
|
'history': list([
|
||||||
|
]),
|
||||||
|
'id': '369afeed-61e3-4bf7-9747-66e05807134c',
|
||||||
|
'isDue': False,
|
||||||
|
'nextDue': list([
|
||||||
|
'2024-12-14T23:00:00+00:00',
|
||||||
|
'2025-01-18T23:00:00+00:00',
|
||||||
|
]),
|
||||||
|
'notes': 'Setze dich einmal im Monat hin, um deine Einnahmen und Ausgaben zu überprüfen und dein Budget zu planen.',
|
||||||
|
'priority': 1,
|
||||||
|
'reminders': list([
|
||||||
|
]),
|
||||||
|
'repeat': dict({
|
||||||
|
'f': False,
|
||||||
|
'm': False,
|
||||||
|
's': False,
|
||||||
|
'su': True,
|
||||||
|
't': False,
|
||||||
|
'th': False,
|
||||||
|
'w': False,
|
||||||
|
}),
|
||||||
|
'startDate': '2024-04-04T22:00:00+00:00',
|
||||||
|
'streak': 1,
|
||||||
|
'tags': list([
|
||||||
|
]),
|
||||||
|
'text': 'Monatliche Finanzübersicht erstellen',
|
||||||
|
'type': 'daily',
|
||||||
|
'up': None,
|
||||||
|
'updatedAt': '2024-04-04T22:00:00+00:00',
|
||||||
|
'userId': '5f359083-ef78-4af0-985a-0b2c6d05797c',
|
||||||
|
'value': -0.9215181434950852,
|
||||||
|
'weeksOfMonth': list([
|
||||||
|
0,
|
||||||
|
]),
|
||||||
|
'yesterDaily': True,
|
||||||
|
}),
|
||||||
dict({
|
dict({
|
||||||
'alias': None,
|
'alias': None,
|
||||||
'attribute': 'str',
|
'attribute': 'str',
|
||||||
|
@ -49,6 +49,13 @@
|
|||||||
'summary': 'Arbeite an einem kreativen Projekt',
|
'summary': 'Arbeite an einem kreativen Projekt',
|
||||||
'uid': '6e53f1f5-a315-4edd-984d-8d762e4a08ef',
|
'uid': '6e53f1f5-a315-4edd-984d-8d762e4a08ef',
|
||||||
}),
|
}),
|
||||||
|
dict({
|
||||||
|
'description': 'Setze dich einmal im Monat hin, um deine Einnahmen und Ausgaben zu überprüfen und dein Budget zu planen.',
|
||||||
|
'due': '2024-12-14',
|
||||||
|
'status': 'needs_action',
|
||||||
|
'summary': 'Monatliche Finanzübersicht erstellen',
|
||||||
|
'uid': '369afeed-61e3-4bf7-9747-66e05807134c',
|
||||||
|
}),
|
||||||
dict({
|
dict({
|
||||||
'description': 'Wähle eine Programmiersprache aus, die du noch nicht kennst, und lerne die Grundlagen.',
|
'description': 'Wähle eine Programmiersprache aus, die du noch nicht kennst, und lerne die Grundlagen.',
|
||||||
'status': 'needs_action',
|
'status': 'needs_action',
|
||||||
@ -151,7 +158,7 @@
|
|||||||
'last_changed': <ANY>,
|
'last_changed': <ANY>,
|
||||||
'last_reported': <ANY>,
|
'last_reported': <ANY>,
|
||||||
'last_updated': <ANY>,
|
'last_updated': <ANY>,
|
||||||
'state': '4',
|
'state': '5',
|
||||||
})
|
})
|
||||||
# ---
|
# ---
|
||||||
# name: test_todos[todo.test_user_to_do_s-entry]
|
# name: test_todos[todo.test_user_to_do_s-entry]
|
||||||
|
@ -388,23 +388,181 @@ async def test_only_valid_components(
|
|||||||
assert not mock_dispatcher_send.called
|
assert not mock_dispatcher_send.called
|
||||||
|
|
||||||
|
|
||||||
async def test_correct_config_discovery(
|
@pytest.mark.parametrize(
|
||||||
hass: HomeAssistant, mqtt_mock_entry: MqttMockHAClientGenerator
|
("discovery_topic", "discovery_hash"),
|
||||||
|
[
|
||||||
|
("homeassistant/binary_sensor/bla/config", ("binary_sensor", "bla")),
|
||||||
|
("homeassistant/binary_sensor/node/bla/config", ("binary_sensor", "node bla")),
|
||||||
|
],
|
||||||
|
ids=["without_node", "with_node"],
|
||||||
|
)
|
||||||
|
async def test_correct_config_discovery_component(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mqtt_mock_entry: MqttMockHAClientGenerator,
|
||||||
|
device_registry: dr.DeviceRegistry,
|
||||||
|
discovery_topic: str,
|
||||||
|
discovery_hash: tuple[str, str],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test sending in correct JSON."""
|
"""Test sending in correct JSON."""
|
||||||
await mqtt_mock_entry()
|
await mqtt_mock_entry()
|
||||||
|
config_init = {
|
||||||
|
"name": "Beer",
|
||||||
|
"state_topic": "test-topic",
|
||||||
|
"unique_id": "bla001",
|
||||||
|
"device": {"identifiers": "0AFFD2", "name": "test_device1"},
|
||||||
|
"o": {"name": "foobar"},
|
||||||
|
}
|
||||||
async_fire_mqtt_message(
|
async_fire_mqtt_message(
|
||||||
hass,
|
hass,
|
||||||
"homeassistant/binary_sensor/bla/config",
|
discovery_topic,
|
||||||
'{ "name": "Beer", "state_topic": "test-topic" }',
|
json.dumps(config_init),
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
state = hass.states.get("binary_sensor.beer")
|
state = hass.states.get("binary_sensor.test_device1_beer")
|
||||||
|
|
||||||
assert state is not None
|
assert state is not None
|
||||||
assert state.name == "Beer"
|
assert state.name == "test_device1 Beer"
|
||||||
assert ("binary_sensor", "bla") in hass.data["mqtt"].discovery_already_discovered
|
assert discovery_hash in hass.data["mqtt"].discovery_already_discovered
|
||||||
|
|
||||||
|
device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")})
|
||||||
|
assert device_entry is not None
|
||||||
|
assert device_entry.name == "test_device1"
|
||||||
|
|
||||||
|
# Update the device and component
|
||||||
|
config_update = {
|
||||||
|
"name": "Milk",
|
||||||
|
"state_topic": "test-topic",
|
||||||
|
"unique_id": "bla001",
|
||||||
|
"device": {"identifiers": "0AFFD2", "name": "test_device2"},
|
||||||
|
"o": {"name": "foobar"},
|
||||||
|
}
|
||||||
|
async_fire_mqtt_message(
|
||||||
|
hass,
|
||||||
|
discovery_topic,
|
||||||
|
json.dumps(config_update),
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get("binary_sensor.test_device1_beer")
|
||||||
|
|
||||||
|
assert state is not None
|
||||||
|
assert state.name == "test_device2 Milk"
|
||||||
|
assert discovery_hash in hass.data["mqtt"].discovery_already_discovered
|
||||||
|
|
||||||
|
device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")})
|
||||||
|
assert device_entry is not None
|
||||||
|
assert device_entry.name == "test_device2"
|
||||||
|
|
||||||
|
# Remove the device and component
|
||||||
|
async_fire_mqtt_message(
|
||||||
|
hass,
|
||||||
|
discovery_topic,
|
||||||
|
"",
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get("binary_sensor.test_device1_beer")
|
||||||
|
|
||||||
|
assert state is None
|
||||||
|
|
||||||
|
device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")})
|
||||||
|
assert device_entry is None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("discovery_topic", "discovery_hash"),
|
||||||
|
[
|
||||||
|
("homeassistant/device/some_id/config", ("binary_sensor", "some_id bla")),
|
||||||
|
(
|
||||||
|
"homeassistant/device/node_id/some_id/config",
|
||||||
|
("binary_sensor", "some_id node_id bla"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
ids=["without_node", "with_node"],
|
||||||
|
)
|
||||||
|
async def test_correct_config_discovery_device(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mqtt_mock_entry: MqttMockHAClientGenerator,
|
||||||
|
device_registry: dr.DeviceRegistry,
|
||||||
|
discovery_topic: str,
|
||||||
|
discovery_hash: tuple[str, str],
|
||||||
|
) -> None:
|
||||||
|
"""Test sending in correct JSON."""
|
||||||
|
await mqtt_mock_entry()
|
||||||
|
config_init = {
|
||||||
|
"cmps": {
|
||||||
|
"bla": {
|
||||||
|
"platform": "binary_sensor",
|
||||||
|
"name": "Beer",
|
||||||
|
"state_topic": "test-topic",
|
||||||
|
"unique_id": "bla001",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"device": {"identifiers": "0AFFD2", "name": "test_device1"},
|
||||||
|
"o": {"name": "foobar"},
|
||||||
|
}
|
||||||
|
async_fire_mqtt_message(
|
||||||
|
hass,
|
||||||
|
discovery_topic,
|
||||||
|
json.dumps(config_init),
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get("binary_sensor.test_device1_beer")
|
||||||
|
|
||||||
|
assert state is not None
|
||||||
|
assert state.name == "test_device1 Beer"
|
||||||
|
assert discovery_hash in hass.data["mqtt"].discovery_already_discovered
|
||||||
|
|
||||||
|
device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")})
|
||||||
|
assert device_entry is not None
|
||||||
|
assert device_entry.name == "test_device1"
|
||||||
|
|
||||||
|
# Update the device and component
|
||||||
|
config_update = {
|
||||||
|
"cmps": {
|
||||||
|
"bla": {
|
||||||
|
"platform": "binary_sensor",
|
||||||
|
"name": "Milk",
|
||||||
|
"state_topic": "test-topic",
|
||||||
|
"unique_id": "bla001",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"device": {"identifiers": "0AFFD2", "name": "test_device2"},
|
||||||
|
"o": {"name": "foobar"},
|
||||||
|
}
|
||||||
|
async_fire_mqtt_message(
|
||||||
|
hass,
|
||||||
|
discovery_topic,
|
||||||
|
json.dumps(config_update),
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get("binary_sensor.test_device1_beer")
|
||||||
|
|
||||||
|
assert state is not None
|
||||||
|
assert state.name == "test_device2 Milk"
|
||||||
|
assert discovery_hash in hass.data["mqtt"].discovery_already_discovered
|
||||||
|
|
||||||
|
device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")})
|
||||||
|
assert device_entry is not None
|
||||||
|
assert device_entry.name == "test_device2"
|
||||||
|
|
||||||
|
# Remove the device and component
|
||||||
|
async_fire_mqtt_message(
|
||||||
|
hass,
|
||||||
|
discovery_topic,
|
||||||
|
"",
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get("binary_sensor.test_device1_beer")
|
||||||
|
|
||||||
|
assert state is None
|
||||||
|
|
||||||
|
device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")})
|
||||||
|
assert device_entry is None
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
@ -77,6 +77,7 @@ def reolink_connect_class() -> Generator[MagicMock]:
|
|||||||
host_mock.check_new_firmware.return_value = False
|
host_mock.check_new_firmware.return_value = False
|
||||||
host_mock.unsubscribe.return_value = True
|
host_mock.unsubscribe.return_value = True
|
||||||
host_mock.logout.return_value = True
|
host_mock.logout.return_value = True
|
||||||
|
host_mock.is_nvr = True
|
||||||
host_mock.is_hub = False
|
host_mock.is_hub = False
|
||||||
host_mock.mac_address = TEST_MAC
|
host_mock.mac_address = TEST_MAC
|
||||||
host_mock.uid = TEST_UID
|
host_mock.uid = TEST_UID
|
||||||
|
@ -23,15 +23,21 @@ from homeassistant.components.number import (
|
|||||||
DOMAIN as NUMBER_DOMAIN,
|
DOMAIN as NUMBER_DOMAIN,
|
||||||
SERVICE_SET_VALUE,
|
SERVICE_SET_VALUE,
|
||||||
)
|
)
|
||||||
|
from homeassistant.components.reolink.const import DOMAIN
|
||||||
|
from homeassistant.components.reolink.util import get_device_uid_and_ch
|
||||||
from homeassistant.config_entries import ConfigEntryState
|
from homeassistant.config_entries import ConfigEntryState
|
||||||
from homeassistant.const import ATTR_ENTITY_ID, Platform
|
from homeassistant.const import ATTR_ENTITY_ID, Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
|
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
|
||||||
|
from homeassistant.helpers import device_registry as dr
|
||||||
|
|
||||||
from .conftest import TEST_NVR_NAME
|
from .conftest import TEST_NVR_NAME, TEST_UID, TEST_UID_CAM
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
|
DEV_ID_NVR = f"{TEST_UID}_{TEST_UID_CAM}"
|
||||||
|
DEV_ID_STANDALONE_CAM = f"{TEST_UID_CAM}"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("side_effect", "expected"),
|
("side_effect", "expected"),
|
||||||
@ -123,3 +129,36 @@ async def test_try_function(
|
|||||||
assert err.value.translation_key == expected.translation_key
|
assert err.value.translation_key == expected.translation_key
|
||||||
|
|
||||||
reolink_connect.set_volume.reset_mock(side_effect=True)
|
reolink_connect.set_volume.reset_mock(side_effect=True)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("identifiers"),
|
||||||
|
[
|
||||||
|
({(DOMAIN, DEV_ID_NVR), (DOMAIN, DEV_ID_STANDALONE_CAM)}),
|
||||||
|
({(DOMAIN, DEV_ID_STANDALONE_CAM), (DOMAIN, DEV_ID_NVR)}),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_get_device_uid_and_ch(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config_entry: MockConfigEntry,
|
||||||
|
reolink_connect: MagicMock,
|
||||||
|
device_registry: dr.DeviceRegistry,
|
||||||
|
identifiers: set[tuple[str, str]],
|
||||||
|
) -> None:
|
||||||
|
"""Test get_device_uid_and_ch with multiple identifiers."""
|
||||||
|
reolink_connect.channels = [0]
|
||||||
|
|
||||||
|
dev_entry = device_registry.async_get_or_create(
|
||||||
|
identifiers=identifiers,
|
||||||
|
config_entry_id=config_entry.entry_id,
|
||||||
|
disabled_by=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
# setup CH 0 and host entities/device
|
||||||
|
with patch("homeassistant.components.reolink.PLATFORMS", [Platform.SWITCH]):
|
||||||
|
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
result = get_device_uid_and_ch(dev_entry, config_entry.runtime_data.host)
|
||||||
|
# always get the uid and channel form the DEV_ID_NVR since is_nvr = True
|
||||||
|
assert result == ([TEST_UID, TEST_UID_CAM], 0, False)
|
||||||
|
@ -21,6 +21,7 @@ from homeassistant.components.shelly.const import (
|
|||||||
GEN1_RELEASE_URL,
|
GEN1_RELEASE_URL,
|
||||||
GEN2_BETA_RELEASE_URL,
|
GEN2_BETA_RELEASE_URL,
|
||||||
GEN2_RELEASE_URL,
|
GEN2_RELEASE_URL,
|
||||||
|
UPTIME_DEVIATION,
|
||||||
)
|
)
|
||||||
from homeassistant.components.shelly.utils import (
|
from homeassistant.components.shelly.utils import (
|
||||||
get_block_channel_name,
|
get_block_channel_name,
|
||||||
@ -188,8 +189,9 @@ async def test_get_device_uptime() -> None:
|
|||||||
) == dt_util.as_utc(dt_util.parse_datetime("2019-01-10 18:42:00+00:00"))
|
) == dt_util.as_utc(dt_util.parse_datetime("2019-01-10 18:42:00+00:00"))
|
||||||
|
|
||||||
assert get_device_uptime(
|
assert get_device_uptime(
|
||||||
50, dt_util.as_utc(dt_util.parse_datetime("2019-01-10 18:42:00+00:00"))
|
55 - UPTIME_DEVIATION,
|
||||||
) == dt_util.as_utc(dt_util.parse_datetime("2019-01-10 18:42:10+00:00"))
|
dt_util.as_utc(dt_util.parse_datetime("2019-01-10 18:42:00+00:00")),
|
||||||
|
) == dt_util.as_utc(dt_util.parse_datetime("2019-01-10 18:43:05+00:00"))
|
||||||
|
|
||||||
|
|
||||||
async def test_get_block_input_triggers(
|
async def test_get_block_input_triggers(
|
||||||
|
@ -107,7 +107,9 @@ def mock_smartthings() -> Generator[AsyncMock]:
|
|||||||
"centralite",
|
"centralite",
|
||||||
"da_ref_normal_000001",
|
"da_ref_normal_000001",
|
||||||
"da_ref_normal_01011",
|
"da_ref_normal_01011",
|
||||||
|
"da_ref_normal_01001",
|
||||||
"vd_network_audio_002s",
|
"vd_network_audio_002s",
|
||||||
|
"vd_network_audio_003s",
|
||||||
"vd_sensor_light_2023",
|
"vd_sensor_light_2023",
|
||||||
"iphone",
|
"iphone",
|
||||||
"da_sac_ehs_000001_sub",
|
"da_sac_ehs_000001_sub",
|
||||||
|
@ -0,0 +1,929 @@
|
|||||||
|
{
|
||||||
|
"components": {
|
||||||
|
"pantry-01": {
|
||||||
|
"samsungce.foodDefrost": {
|
||||||
|
"supportedOptions": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"foodType": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"weight": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"operationTime": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"remainingTime": {
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungce.fridgePantryInfo": {
|
||||||
|
"name": {
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"custom.disabledCapabilities": {
|
||||||
|
"disabledCapabilities": {
|
||||||
|
"value": ["samsungce.meatAging", "samsungce.foodDefrost"],
|
||||||
|
"timestamp": "2022-02-07T10:54:05.580Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungce.meatAging": {
|
||||||
|
"zoneInfo": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"supportedMeatTypes": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"supportedAgingMethods": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungce.fridgePantryMode": {
|
||||||
|
"mode": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"supportedModes": {
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"icemaker": {
|
||||||
|
"custom.disabledCapabilities": {
|
||||||
|
"disabledCapabilities": {
|
||||||
|
"value": [],
|
||||||
|
"timestamp": "2022-02-07T10:54:05.580Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"switch": {
|
||||||
|
"switch": {
|
||||||
|
"value": "on",
|
||||||
|
"timestamp": "2025-02-07T12:01:52.528Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"scale-10": {
|
||||||
|
"samsungce.connectionState": {
|
||||||
|
"connectionState": {
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"custom.disabledCapabilities": {
|
||||||
|
"disabledCapabilities": {
|
||||||
|
"value": [],
|
||||||
|
"timestamp": "2022-02-07T10:54:05.580Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungce.weightMeasurement": {
|
||||||
|
"weight": {
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungce.scaleSettings": {
|
||||||
|
"enabled": {
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungce.weightMeasurementCalibration": {}
|
||||||
|
},
|
||||||
|
"scale-11": {
|
||||||
|
"custom.disabledCapabilities": {
|
||||||
|
"disabledCapabilities": {
|
||||||
|
"value": [],
|
||||||
|
"timestamp": "2022-02-07T10:54:05.580Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungce.weightMeasurement": {
|
||||||
|
"weight": {
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"camera-01": {
|
||||||
|
"custom.disabledCapabilities": {
|
||||||
|
"disabledCapabilities": {
|
||||||
|
"value": ["switch"],
|
||||||
|
"timestamp": "2023-12-17T11:19:18.845Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"switch": {
|
||||||
|
"switch": {
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cooler": {
|
||||||
|
"contactSensor": {
|
||||||
|
"contact": {
|
||||||
|
"value": "closed",
|
||||||
|
"timestamp": "2025-02-09T00:23:41.655Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungce.unavailableCapabilities": {
|
||||||
|
"unavailableCommands": {
|
||||||
|
"value": [],
|
||||||
|
"timestamp": "2024-11-06T12:35:50.411Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"custom.disabledCapabilities": {
|
||||||
|
"disabledCapabilities": {
|
||||||
|
"value": [],
|
||||||
|
"timestamp": "2024-06-17T06:16:33.918Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"temperatureMeasurement": {
|
||||||
|
"temperatureRange": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"temperature": {
|
||||||
|
"value": 37,
|
||||||
|
"unit": "F",
|
||||||
|
"timestamp": "2025-02-01T19:39:00.493Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"custom.thermostatSetpointControl": {
|
||||||
|
"minimumSetpoint": {
|
||||||
|
"value": 34,
|
||||||
|
"unit": "F",
|
||||||
|
"timestamp": "2025-02-01T19:39:00.493Z"
|
||||||
|
},
|
||||||
|
"maximumSetpoint": {
|
||||||
|
"value": 44,
|
||||||
|
"unit": "F",
|
||||||
|
"timestamp": "2025-02-01T19:39:00.493Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"thermostatCoolingSetpoint": {
|
||||||
|
"coolingSetpointRange": {
|
||||||
|
"value": {
|
||||||
|
"minimum": 34,
|
||||||
|
"maximum": 44,
|
||||||
|
"step": 1
|
||||||
|
},
|
||||||
|
"unit": "F",
|
||||||
|
"timestamp": "2025-02-01T19:39:00.493Z"
|
||||||
|
},
|
||||||
|
"coolingSetpoint": {
|
||||||
|
"value": 37,
|
||||||
|
"unit": "F",
|
||||||
|
"timestamp": "2025-02-01T19:39:00.493Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"freezer": {
|
||||||
|
"contactSensor": {
|
||||||
|
"contact": {
|
||||||
|
"value": "closed",
|
||||||
|
"timestamp": "2025-02-09T00:00:44.267Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungce.unavailableCapabilities": {
|
||||||
|
"unavailableCommands": {
|
||||||
|
"value": [],
|
||||||
|
"timestamp": "2024-11-06T12:35:50.411Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"custom.disabledCapabilities": {
|
||||||
|
"disabledCapabilities": {
|
||||||
|
"value": ["samsungce.freezerConvertMode"],
|
||||||
|
"timestamp": "2024-11-06T09:00:29.743Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"temperatureMeasurement": {
|
||||||
|
"temperatureRange": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"temperature": {
|
||||||
|
"value": 0,
|
||||||
|
"unit": "F",
|
||||||
|
"timestamp": "2025-02-01T19:39:00.493Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"custom.thermostatSetpointControl": {
|
||||||
|
"minimumSetpoint": {
|
||||||
|
"value": -8,
|
||||||
|
"unit": "F",
|
||||||
|
"timestamp": "2025-02-01T19:39:00.493Z"
|
||||||
|
},
|
||||||
|
"maximumSetpoint": {
|
||||||
|
"value": 5,
|
||||||
|
"unit": "F",
|
||||||
|
"timestamp": "2025-02-01T19:39:00.493Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungce.freezerConvertMode": {
|
||||||
|
"supportedFreezerConvertModes": {
|
||||||
|
"value": [],
|
||||||
|
"timestamp": "2025-02-01T19:39:00.448Z"
|
||||||
|
},
|
||||||
|
"freezerConvertMode": {
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"thermostatCoolingSetpoint": {
|
||||||
|
"coolingSetpointRange": {
|
||||||
|
"value": {
|
||||||
|
"minimum": -8,
|
||||||
|
"maximum": 5,
|
||||||
|
"step": 1
|
||||||
|
},
|
||||||
|
"unit": "F",
|
||||||
|
"timestamp": "2025-02-01T19:39:00.493Z"
|
||||||
|
},
|
||||||
|
"coolingSetpoint": {
|
||||||
|
"value": 0,
|
||||||
|
"unit": "F",
|
||||||
|
"timestamp": "2025-02-01T19:39:00.493Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"main": {
|
||||||
|
"contactSensor": {
|
||||||
|
"contact": {
|
||||||
|
"value": "closed",
|
||||||
|
"timestamp": "2025-02-09T00:23:41.655Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungce.viewInside": {
|
||||||
|
"supportedFocusAreas": {
|
||||||
|
"value": ["mainShelves"],
|
||||||
|
"timestamp": "2025-02-01T19:39:00.946Z"
|
||||||
|
},
|
||||||
|
"contents": {
|
||||||
|
"value": [
|
||||||
|
{
|
||||||
|
"fileId": "d3e1f875-f8b3-a031-737b-366eaa227773",
|
||||||
|
"mimeType": "image/jpeg",
|
||||||
|
"expiredTime": "2025-01-20T16:17:04Z",
|
||||||
|
"focusArea": "mainShelves"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fileId": "9fccb6b4-e71f-6c7f-9935-f6082bb6ccfe",
|
||||||
|
"mimeType": "image/jpeg",
|
||||||
|
"expiredTime": "2025-01-20T16:17:04Z",
|
||||||
|
"focusArea": "mainShelves"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fileId": "20b57a4d-b7fc-17fc-3a03-0fb84fb4efab",
|
||||||
|
"mimeType": "image/jpeg",
|
||||||
|
"expiredTime": "2025-01-20T16:17:05Z",
|
||||||
|
"focusArea": "mainShelves"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": "2025-01-20T16:07:05.423Z"
|
||||||
|
},
|
||||||
|
"lastUpdatedTime": {
|
||||||
|
"value": "2025-02-07T12:01:52Z",
|
||||||
|
"timestamp": "2025-02-07T12:01:52.585Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungce.fridgeFoodList": {
|
||||||
|
"outOfSyncChanges": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"refreshResult": {
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungce.deviceIdentification": {
|
||||||
|
"micomAssayCode": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"modelName": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"serialNumber": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"serialNumberExtra": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"modelClassificationCode": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"releaseYear": {
|
||||||
|
"value": 19,
|
||||||
|
"timestamp": "2024-11-06T09:00:29.743Z"
|
||||||
|
},
|
||||||
|
"binaryId": {
|
||||||
|
"value": "24K_REF_LCD_FHUB9.0",
|
||||||
|
"timestamp": "2025-02-07T12:01:53.067Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungce.quickControl": {
|
||||||
|
"version": {
|
||||||
|
"value": "1.0",
|
||||||
|
"timestamp": "2025-02-01T19:39:01.848Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"custom.fridgeMode": {
|
||||||
|
"fridgeModeValue": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"fridgeMode": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"supportedFridgeModes": {
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ocf": {
|
||||||
|
"st": {
|
||||||
|
"value": "2024-11-08T11:56:59Z",
|
||||||
|
"timestamp": "2025-01-02T12:37:43.756Z"
|
||||||
|
},
|
||||||
|
"mndt": {
|
||||||
|
"value": "",
|
||||||
|
"timestamp": "2025-01-02T12:37:43.756Z"
|
||||||
|
},
|
||||||
|
"mnfv": {
|
||||||
|
"value": "20240616.213423",
|
||||||
|
"timestamp": "2025-01-02T12:37:43.756Z"
|
||||||
|
},
|
||||||
|
"mnhw": {
|
||||||
|
"value": "",
|
||||||
|
"timestamp": "2025-01-02T12:37:43.756Z"
|
||||||
|
},
|
||||||
|
"di": {
|
||||||
|
"value": "7d3feb98-8a36-4351-c362-5e21ad3a78dd",
|
||||||
|
"timestamp": "2025-01-02T12:37:43.756Z"
|
||||||
|
},
|
||||||
|
"mnsl": {
|
||||||
|
"value": "",
|
||||||
|
"timestamp": "2025-01-02T12:37:43.756Z"
|
||||||
|
},
|
||||||
|
"dmv": {
|
||||||
|
"value": "res.1.1.0,sh.1.1.0",
|
||||||
|
"timestamp": "2025-01-02T12:37:43.756Z"
|
||||||
|
},
|
||||||
|
"n": {
|
||||||
|
"value": "Family Hub",
|
||||||
|
"timestamp": "2025-01-02T12:37:43.756Z"
|
||||||
|
},
|
||||||
|
"mnmo": {
|
||||||
|
"value": "24K_REF_LCD_FHUB9.0|00113141|0002034e051324200103000000000000",
|
||||||
|
"timestamp": "2025-01-02T12:37:43.756Z"
|
||||||
|
},
|
||||||
|
"vid": {
|
||||||
|
"value": "DA-REF-NORMAL-01001",
|
||||||
|
"timestamp": "2025-01-02T12:37:43.756Z"
|
||||||
|
},
|
||||||
|
"mnmn": {
|
||||||
|
"value": "Samsung Electronics",
|
||||||
|
"timestamp": "2025-01-02T12:37:43.756Z"
|
||||||
|
},
|
||||||
|
"mnml": {
|
||||||
|
"value": "",
|
||||||
|
"timestamp": "2025-01-02T12:37:43.756Z"
|
||||||
|
},
|
||||||
|
"mnpv": {
|
||||||
|
"value": "7.0",
|
||||||
|
"timestamp": "2025-01-02T12:37:43.756Z"
|
||||||
|
},
|
||||||
|
"mnos": {
|
||||||
|
"value": "Tizen",
|
||||||
|
"timestamp": "2025-01-02T12:37:43.756Z"
|
||||||
|
},
|
||||||
|
"pi": {
|
||||||
|
"value": "7d3feb98-8a36-4351-c362-5e21ad3a78dd",
|
||||||
|
"timestamp": "2025-01-02T12:37:43.756Z"
|
||||||
|
},
|
||||||
|
"icv": {
|
||||||
|
"value": "core.1.1.0",
|
||||||
|
"timestamp": "2025-01-02T12:37:43.756Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungce.fridgeVacationMode": {
|
||||||
|
"vacationMode": {
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"custom.disabledCapabilities": {
|
||||||
|
"disabledCapabilities": {
|
||||||
|
"value": [
|
||||||
|
"thermostatCoolingSetpoint",
|
||||||
|
"temperatureMeasurement",
|
||||||
|
"custom.fridgeMode",
|
||||||
|
"custom.deviceReportStateConfiguration",
|
||||||
|
"samsungce.fridgeFoodList",
|
||||||
|
"samsungce.runestoneHomeContext",
|
||||||
|
"demandResponseLoadControl",
|
||||||
|
"samsungce.fridgeVacationMode",
|
||||||
|
"samsungce.sabbathMode"
|
||||||
|
],
|
||||||
|
"timestamp": "2025-02-08T23:57:45.739Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungce.driverVersion": {
|
||||||
|
"versionNumber": {
|
||||||
|
"value": 24090102,
|
||||||
|
"timestamp": "2024-11-06T09:00:29.743Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sec.diagnosticsInformation": {
|
||||||
|
"logType": {
|
||||||
|
"value": ["errCode", "dump"],
|
||||||
|
"timestamp": "2025-02-01T19:39:00.523Z"
|
||||||
|
},
|
||||||
|
"endpoint": {
|
||||||
|
"value": "SSM",
|
||||||
|
"timestamp": "2025-02-01T19:39:00.523Z"
|
||||||
|
},
|
||||||
|
"minVersion": {
|
||||||
|
"value": "1.0",
|
||||||
|
"timestamp": "2025-02-01T19:39:00.523Z"
|
||||||
|
},
|
||||||
|
"signinPermission": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"setupId": {
|
||||||
|
"value": "500",
|
||||||
|
"timestamp": "2025-02-01T19:39:00.523Z"
|
||||||
|
},
|
||||||
|
"protocolType": {
|
||||||
|
"value": "wifi_https",
|
||||||
|
"timestamp": "2025-02-01T19:39:00.523Z"
|
||||||
|
},
|
||||||
|
"tsId": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"mnId": {
|
||||||
|
"value": "0AJT",
|
||||||
|
"timestamp": "2025-02-01T19:39:00.523Z"
|
||||||
|
},
|
||||||
|
"dumpType": {
|
||||||
|
"value": "file",
|
||||||
|
"timestamp": "2025-02-01T19:39:00.523Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"temperatureMeasurement": {
|
||||||
|
"temperatureRange": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"temperature": {
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"custom.deviceReportStateConfiguration": {
|
||||||
|
"reportStateRealtimePeriod": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"reportStateRealtime": {
|
||||||
|
"value": {
|
||||||
|
"state": "disabled"
|
||||||
|
},
|
||||||
|
"timestamp": "2025-02-01T19:39:00.345Z"
|
||||||
|
},
|
||||||
|
"reportStatePeriod": {
|
||||||
|
"value": "enabled",
|
||||||
|
"timestamp": "2025-02-01T19:39:00.345Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"thermostatCoolingSetpoint": {
|
||||||
|
"coolingSetpointRange": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"coolingSetpoint": {
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"custom.disabledComponents": {
|
||||||
|
"disabledComponents": {
|
||||||
|
"value": [
|
||||||
|
"icemaker-02",
|
||||||
|
"icemaker-03",
|
||||||
|
"pantry-01",
|
||||||
|
"camera-01",
|
||||||
|
"scale-10",
|
||||||
|
"scale-11"
|
||||||
|
],
|
||||||
|
"timestamp": "2025-02-07T12:01:52.638Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"demandResponseLoadControl": {
|
||||||
|
"drlcStatus": {
|
||||||
|
"value": {
|
||||||
|
"drlcType": 1,
|
||||||
|
"drlcLevel": 0,
|
||||||
|
"duration": 0,
|
||||||
|
"override": false
|
||||||
|
},
|
||||||
|
"timestamp": "2025-02-01T19:38:59.899Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungce.sabbathMode": {
|
||||||
|
"supportedActions": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"powerConsumptionReport": {
|
||||||
|
"powerConsumption": {
|
||||||
|
"value": {
|
||||||
|
"energy": 4381422,
|
||||||
|
"deltaEnergy": 27,
|
||||||
|
"power": 144,
|
||||||
|
"powerEnergy": 27.01890500307083,
|
||||||
|
"persistedEnergy": 0,
|
||||||
|
"energySaved": 0,
|
||||||
|
"start": "2025-02-09T00:13:39Z",
|
||||||
|
"end": "2025-02-09T00:25:23Z"
|
||||||
|
},
|
||||||
|
"timestamp": "2025-02-09T00:25:23.843Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"refresh": {},
|
||||||
|
"samsungce.runestoneHomeContext": {
|
||||||
|
"supportedContexts": {
|
||||||
|
"value": [
|
||||||
|
{
|
||||||
|
"context": "HOME_IN",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "ASLEEP",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "AWAKE",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "COOKING",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "FINISH_COOKING",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "EATING",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "FINISH_EATING",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "DOING_LAUNDRY",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "FINISH_DOING_LAUNDRY",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "CLEANING_HOUSE",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "FINISH_CLEANING_HOUSE",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "MUSIC_LISTENING",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "FINISH_MUSIC_LISTENING",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "AIR_CONDITIONING",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "FINISH_AIR_CONDITIONING",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "WASHING_DISHES",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "FINISH_WASHING_DISHES",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "CARING_CLOTHING",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "FINISH_CARING_CLOTHING",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "WATCHING_TV",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "FINISH_WATCHING_TV",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "BEFORE_BEDTIME",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "BEFORE_COOKING",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "BEFORE_HOME_OUT",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "ORDERING_DELIVERY_FOOD",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "FINISH_ORDERING_DELIVERY_FOOD",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "ONLINE_GROCERY_SHOPPING",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "FINISH_ONLINE_GROCERY_SHOPPING",
|
||||||
|
"place": "HOME",
|
||||||
|
"startTime": "99:99",
|
||||||
|
"endTime": "99:99"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": "2025-02-01T19:39:02.150Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"execute": {
|
||||||
|
"data": {
|
||||||
|
"value": {
|
||||||
|
"payload": {
|
||||||
|
"rt": ["x.com.samsung.da.fridge"],
|
||||||
|
"if": ["oic.if.a"],
|
||||||
|
"x.com.samsung.da.rapidFridge": "Off",
|
||||||
|
"x.com.samsung.da.rapidFreezing": "Off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"data": {
|
||||||
|
"href": "/refrigeration/vs/0"
|
||||||
|
},
|
||||||
|
"timestamp": "2024-03-26T09:06:17.169Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sec.wifiConfiguration": {
|
||||||
|
"autoReconnection": {
|
||||||
|
"value": true,
|
||||||
|
"timestamp": "2025-02-01T19:39:01.951Z"
|
||||||
|
},
|
||||||
|
"minVersion": {
|
||||||
|
"value": "1.0",
|
||||||
|
"timestamp": "2025-02-01T19:39:01.951Z"
|
||||||
|
},
|
||||||
|
"supportedWiFiFreq": {
|
||||||
|
"value": ["2.4G", "5G"],
|
||||||
|
"timestamp": "2025-02-01T19:39:01.951Z"
|
||||||
|
},
|
||||||
|
"supportedAuthType": {
|
||||||
|
"value": ["OPEN", "WEP", "WPA-PSK", "WPA2-PSK"],
|
||||||
|
"timestamp": "2025-02-01T19:39:01.951Z"
|
||||||
|
},
|
||||||
|
"protocolType": {
|
||||||
|
"value": ["helper_hotspot"],
|
||||||
|
"timestamp": "2025-02-01T19:39:01.951Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"refrigeration": {
|
||||||
|
"defrost": {
|
||||||
|
"value": "off",
|
||||||
|
"timestamp": "2025-02-01T19:38:59.276Z"
|
||||||
|
},
|
||||||
|
"rapidCooling": {
|
||||||
|
"value": "off",
|
||||||
|
"timestamp": "2025-02-01T19:39:00.497Z"
|
||||||
|
},
|
||||||
|
"rapidFreezing": {
|
||||||
|
"value": "off",
|
||||||
|
"timestamp": "2025-02-01T19:39:00.497Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungce.powerCool": {
|
||||||
|
"activated": {
|
||||||
|
"value": false,
|
||||||
|
"timestamp": "2025-02-01T19:39:00.497Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"custom.energyType": {
|
||||||
|
"energyType": {
|
||||||
|
"value": "2.0",
|
||||||
|
"timestamp": "2022-02-07T10:54:05.580Z"
|
||||||
|
},
|
||||||
|
"energySavingSupport": {
|
||||||
|
"value": false,
|
||||||
|
"timestamp": "2022-02-07T10:57:35.490Z"
|
||||||
|
},
|
||||||
|
"drMaxDuration": {
|
||||||
|
"value": 1440,
|
||||||
|
"unit": "min",
|
||||||
|
"timestamp": "2022-02-07T11:50:40.228Z"
|
||||||
|
},
|
||||||
|
"energySavingLevel": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"energySavingInfo": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"supportedEnergySavingLevels": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"energySavingOperation": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"notificationTemplateID": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"energySavingOperationSupport": {
|
||||||
|
"value": false,
|
||||||
|
"timestamp": "2022-02-07T11:50:40.228Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungce.softwareUpdate": {
|
||||||
|
"targetModule": {
|
||||||
|
"value": {},
|
||||||
|
"timestamp": "2025-02-01T19:39:00.200Z"
|
||||||
|
},
|
||||||
|
"otnDUID": {
|
||||||
|
"value": "2DCEZFTFQZPMO",
|
||||||
|
"timestamp": "2025-02-01T19:39:00.523Z"
|
||||||
|
},
|
||||||
|
"lastUpdatedDate": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"availableModules": {
|
||||||
|
"value": [],
|
||||||
|
"timestamp": "2025-02-01T19:39:00.523Z"
|
||||||
|
},
|
||||||
|
"newVersionAvailable": {
|
||||||
|
"value": false,
|
||||||
|
"timestamp": "2025-02-01T19:39:00.200Z"
|
||||||
|
},
|
||||||
|
"operatingState": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"progress": {
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungce.powerFreeze": {
|
||||||
|
"activated": {
|
||||||
|
"value": false,
|
||||||
|
"timestamp": "2025-02-01T19:39:00.497Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"custom.waterFilter": {
|
||||||
|
"waterFilterUsageStep": {
|
||||||
|
"value": 1,
|
||||||
|
"timestamp": "2025-02-01T19:38:59.973Z"
|
||||||
|
},
|
||||||
|
"waterFilterResetType": {
|
||||||
|
"value": ["replaceable"],
|
||||||
|
"timestamp": "2025-02-01T19:38:59.973Z"
|
||||||
|
},
|
||||||
|
"waterFilterCapacity": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"waterFilterLastResetDate": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"waterFilterUsage": {
|
||||||
|
"value": 52,
|
||||||
|
"timestamp": "2025-02-08T05:06:45.769Z"
|
||||||
|
},
|
||||||
|
"waterFilterStatus": {
|
||||||
|
"value": "normal",
|
||||||
|
"timestamp": "2025-02-01T19:38:59.973Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cvroom": {
|
||||||
|
"custom.fridgeMode": {
|
||||||
|
"fridgeModeValue": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"fridgeMode": {
|
||||||
|
"value": "CV_FDR_DELI",
|
||||||
|
"timestamp": "2025-02-01T19:39:00.448Z"
|
||||||
|
},
|
||||||
|
"supportedFridgeModes": {
|
||||||
|
"value": [
|
||||||
|
"CV_FDR_WINE",
|
||||||
|
"CV_FDR_DELI",
|
||||||
|
"CV_FDR_BEVERAGE",
|
||||||
|
"CV_FDR_MEAT"
|
||||||
|
],
|
||||||
|
"timestamp": "2025-02-01T19:39:00.448Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"contactSensor": {
|
||||||
|
"contact": {
|
||||||
|
"value": "closed",
|
||||||
|
"timestamp": "2025-02-08T23:22:04.631Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"custom.disabledCapabilities": {
|
||||||
|
"disabledCapabilities": {
|
||||||
|
"value": [],
|
||||||
|
"timestamp": "2021-07-27T01:19:43.145Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"icemaker-02": {
|
||||||
|
"custom.disabledCapabilities": {
|
||||||
|
"disabledCapabilities": {
|
||||||
|
"value": [],
|
||||||
|
"timestamp": "2022-07-28T18:47:07.039Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"switch": {
|
||||||
|
"switch": {
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"icemaker-03": {
|
||||||
|
"custom.disabledCapabilities": {
|
||||||
|
"disabledCapabilities": {
|
||||||
|
"value": [],
|
||||||
|
"timestamp": "2023-12-15T01:05:09.803Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"switch": {
|
||||||
|
"switch": {
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,231 @@
|
|||||||
|
{
|
||||||
|
"components": {
|
||||||
|
"main": {
|
||||||
|
"samsungvd.soundFrom": {
|
||||||
|
"mode": {
|
||||||
|
"value": 29,
|
||||||
|
"timestamp": "2025-04-05T13:51:47.865Z"
|
||||||
|
},
|
||||||
|
"detailName": {
|
||||||
|
"value": "None",
|
||||||
|
"timestamp": "2025-04-05T13:51:50.230Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"audioVolume": {
|
||||||
|
"volume": {
|
||||||
|
"value": 6,
|
||||||
|
"unit": "%",
|
||||||
|
"timestamp": "2025-04-17T11:17:25.272Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungvd.audioGroupInfo": {
|
||||||
|
"role": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"channel": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"refresh": {},
|
||||||
|
"audioNotification": {},
|
||||||
|
"execute": {
|
||||||
|
"data": {
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungvd.audioInputSource": {
|
||||||
|
"supportedInputSources": {
|
||||||
|
"value": ["D.IN", "BT", "WIFI"],
|
||||||
|
"timestamp": "2025-03-18T19:11:54.071Z"
|
||||||
|
},
|
||||||
|
"inputSource": {
|
||||||
|
"value": "D.IN",
|
||||||
|
"timestamp": "2025-04-17T11:18:02.048Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"switch": {
|
||||||
|
"switch": {
|
||||||
|
"value": "off",
|
||||||
|
"timestamp": "2025-04-17T14:42:04.704Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sec.wifiConfiguration": {
|
||||||
|
"autoReconnection": {
|
||||||
|
"value": true,
|
||||||
|
"timestamp": "2025-03-18T19:11:54.484Z"
|
||||||
|
},
|
||||||
|
"minVersion": {
|
||||||
|
"value": "1.0",
|
||||||
|
"timestamp": "2025-03-18T19:11:54.484Z"
|
||||||
|
},
|
||||||
|
"supportedWiFiFreq": {
|
||||||
|
"value": ["2.4G", "5G"],
|
||||||
|
"timestamp": "2025-03-18T19:11:54.484Z"
|
||||||
|
},
|
||||||
|
"supportedAuthType": {
|
||||||
|
"value": [
|
||||||
|
"OPEN",
|
||||||
|
"WEP",
|
||||||
|
"WPA-PSK",
|
||||||
|
"WPA2-PSK",
|
||||||
|
"EAP",
|
||||||
|
"SAE",
|
||||||
|
"OWE",
|
||||||
|
"FT-PSK"
|
||||||
|
],
|
||||||
|
"timestamp": "2025-03-18T19:11:54.484Z"
|
||||||
|
},
|
||||||
|
"protocolType": {
|
||||||
|
"value": ["ble_ocf"],
|
||||||
|
"timestamp": "2025-03-18T19:11:54.484Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ocf": {
|
||||||
|
"st": {
|
||||||
|
"value": "1970-01-01T00:00:47Z",
|
||||||
|
"timestamp": "2025-02-21T15:09:52.348Z"
|
||||||
|
},
|
||||||
|
"mndt": {
|
||||||
|
"value": "2024-01-01",
|
||||||
|
"timestamp": "2025-02-21T15:09:52.348Z"
|
||||||
|
},
|
||||||
|
"mnfv": {
|
||||||
|
"value": "SAT-MT8532D24WWC-1016.0",
|
||||||
|
"timestamp": "2025-02-21T16:47:38.134Z"
|
||||||
|
},
|
||||||
|
"mnhw": {
|
||||||
|
"value": "",
|
||||||
|
"timestamp": "2025-02-21T15:09:52.348Z"
|
||||||
|
},
|
||||||
|
"di": {
|
||||||
|
"value": "a75cb1e1-03fd-3c77-ca9f-d4e56c4096c6",
|
||||||
|
"timestamp": "2025-02-21T15:09:52.348Z"
|
||||||
|
},
|
||||||
|
"mnsl": {
|
||||||
|
"value": "",
|
||||||
|
"timestamp": "2025-02-21T15:09:52.348Z"
|
||||||
|
},
|
||||||
|
"dmv": {
|
||||||
|
"value": "res.1.1.0,sh.1.1.0",
|
||||||
|
"timestamp": "2025-02-21T15:09:52.348Z"
|
||||||
|
},
|
||||||
|
"n": {
|
||||||
|
"value": "Soundbar",
|
||||||
|
"timestamp": "2025-02-21T16:47:38.134Z"
|
||||||
|
},
|
||||||
|
"mnmo": {
|
||||||
|
"value": "HW-S60D",
|
||||||
|
"timestamp": "2025-02-21T15:09:52.348Z"
|
||||||
|
},
|
||||||
|
"vid": {
|
||||||
|
"value": "VD-NetworkAudio-003S",
|
||||||
|
"timestamp": "2025-02-21T15:09:52.348Z"
|
||||||
|
},
|
||||||
|
"mnmn": {
|
||||||
|
"value": "Samsung Electronics",
|
||||||
|
"timestamp": "2025-02-21T15:09:52.348Z"
|
||||||
|
},
|
||||||
|
"mnml": {
|
||||||
|
"value": "",
|
||||||
|
"timestamp": "2025-02-21T15:09:52.348Z"
|
||||||
|
},
|
||||||
|
"mnpv": {
|
||||||
|
"value": "8.0",
|
||||||
|
"timestamp": "2025-02-21T15:09:52.348Z"
|
||||||
|
},
|
||||||
|
"mnos": {
|
||||||
|
"value": "Tizen",
|
||||||
|
"timestamp": "2025-02-21T15:09:52.348Z"
|
||||||
|
},
|
||||||
|
"pi": {
|
||||||
|
"value": "a75cb1e1-03fd-3c77-ca9f-d4e56c4096c6",
|
||||||
|
"timestamp": "2025-02-21T15:09:52.348Z"
|
||||||
|
},
|
||||||
|
"icv": {
|
||||||
|
"value": "core.1.1.0",
|
||||||
|
"timestamp": "2025-02-21T15:09:52.348Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungvd.supportsFeatures": {
|
||||||
|
"mediaOutputSupported": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"imeAdvSupported": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"wifiUpdateSupport": {
|
||||||
|
"value": true,
|
||||||
|
"timestamp": "2025-03-18T19:11:53.853Z"
|
||||||
|
},
|
||||||
|
"executableServiceList": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"remotelessSupported": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"artSupported": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"mobileCamSupported": {
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sec.diagnosticsInformation": {
|
||||||
|
"logType": {
|
||||||
|
"value": ["errCode", "dump"],
|
||||||
|
"timestamp": "2025-03-18T19:11:54.336Z"
|
||||||
|
},
|
||||||
|
"endpoint": {
|
||||||
|
"value": "PIPER",
|
||||||
|
"timestamp": "2025-03-18T19:11:54.336Z"
|
||||||
|
},
|
||||||
|
"minVersion": {
|
||||||
|
"value": "3.0",
|
||||||
|
"timestamp": "2025-03-18T19:11:54.336Z"
|
||||||
|
},
|
||||||
|
"signinPermission": {
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
"setupId": {
|
||||||
|
"value": "301",
|
||||||
|
"timestamp": "2025-03-18T19:11:54.336Z"
|
||||||
|
},
|
||||||
|
"protocolType": {
|
||||||
|
"value": "ble_ocf",
|
||||||
|
"timestamp": "2025-03-18T19:11:54.336Z"
|
||||||
|
},
|
||||||
|
"tsId": {
|
||||||
|
"value": "VD02",
|
||||||
|
"timestamp": "2025-03-18T19:11:54.336Z"
|
||||||
|
},
|
||||||
|
"mnId": {
|
||||||
|
"value": "0AJK",
|
||||||
|
"timestamp": "2025-03-18T19:11:54.336Z"
|
||||||
|
},
|
||||||
|
"dumpType": {
|
||||||
|
"value": "file",
|
||||||
|
"timestamp": "2025-03-18T19:11:54.336Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"audioMute": {
|
||||||
|
"mute": {
|
||||||
|
"value": "muted",
|
||||||
|
"timestamp": "2025-04-17T11:36:04.814Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungvd.thingStatus": {
|
||||||
|
"updatedTime": {
|
||||||
|
"value": 1744900925,
|
||||||
|
"timestamp": "2025-04-17T14:42:04.770Z"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"value": "Idle",
|
||||||
|
"timestamp": "2025-03-18T19:11:54.101Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,433 @@
|
|||||||
|
{
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"deviceId": "7d3feb98-8a36-4351-c362-5e21ad3a78dd",
|
||||||
|
"name": "Family Hub",
|
||||||
|
"label": "Refrigerator",
|
||||||
|
"manufacturerName": "Samsung Electronics",
|
||||||
|
"presentationId": "DA-REF-NORMAL-01001",
|
||||||
|
"deviceManufacturerCode": "Samsung Electronics",
|
||||||
|
"locationId": "2487472a-06c4-4bce-8f4c-700c5f8644f8",
|
||||||
|
"ownerId": "b603d7e8-6066-4e10-8102-afa752a63816",
|
||||||
|
"roomId": "acaa060a-7c19-4579-8a4a-5ad891a2f0c1",
|
||||||
|
"deviceTypeName": "Samsung OCF Refrigerator",
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"id": "main",
|
||||||
|
"label": "main",
|
||||||
|
"capabilities": [
|
||||||
|
{
|
||||||
|
"id": "contactSensor",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "execute",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ocf",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "powerConsumptionReport",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "demandResponseLoadControl",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "refresh",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "refrigeration",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "temperatureMeasurement",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "thermostatCoolingSetpoint",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "custom.deviceReportStateConfiguration",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "custom.energyType",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "custom.fridgeMode",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "custom.disabledCapabilities",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "custom.disabledComponents",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "custom.waterFilter",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungce.fridgeFoodList",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungce.softwareUpdate",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungce.deviceIdentification",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungce.driverVersion",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungce.fridgeVacationMode",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungce.powerCool",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungce.powerFreeze",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungce.sabbathMode",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungce.viewInside",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungce.runestoneHomeContext",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungce.quickControl",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "sec.diagnosticsInformation",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "sec.wifiConfiguration",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"categories": [
|
||||||
|
{
|
||||||
|
"name": "Refrigerator",
|
||||||
|
"categoryType": "manufacturer"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "freezer",
|
||||||
|
"label": "freezer",
|
||||||
|
"capabilities": [
|
||||||
|
{
|
||||||
|
"id": "contactSensor",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "temperatureMeasurement",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "thermostatCoolingSetpoint",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "custom.disabledCapabilities",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "custom.thermostatSetpointControl",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungce.freezerConvertMode",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungce.unavailableCapabilities",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"categories": [
|
||||||
|
{
|
||||||
|
"name": "Other",
|
||||||
|
"categoryType": "manufacturer"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "cooler",
|
||||||
|
"label": "cooler",
|
||||||
|
"capabilities": [
|
||||||
|
{
|
||||||
|
"id": "contactSensor",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "temperatureMeasurement",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "thermostatCoolingSetpoint",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "custom.disabledCapabilities",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "custom.thermostatSetpointControl",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungce.unavailableCapabilities",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"categories": [
|
||||||
|
{
|
||||||
|
"name": "Other",
|
||||||
|
"categoryType": "manufacturer"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "cvroom",
|
||||||
|
"label": "cvroom",
|
||||||
|
"capabilities": [
|
||||||
|
{
|
||||||
|
"id": "contactSensor",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "custom.disabledCapabilities",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "custom.fridgeMode",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"categories": [
|
||||||
|
{
|
||||||
|
"name": "Other",
|
||||||
|
"categoryType": "manufacturer"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "icemaker",
|
||||||
|
"label": "icemaker",
|
||||||
|
"capabilities": [
|
||||||
|
{
|
||||||
|
"id": "switch",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "custom.disabledCapabilities",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"categories": [
|
||||||
|
{
|
||||||
|
"name": "Other",
|
||||||
|
"categoryType": "manufacturer"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "icemaker-02",
|
||||||
|
"label": "icemaker-02",
|
||||||
|
"capabilities": [
|
||||||
|
{
|
||||||
|
"id": "switch",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "custom.disabledCapabilities",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"categories": [
|
||||||
|
{
|
||||||
|
"name": "Other",
|
||||||
|
"categoryType": "manufacturer"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "icemaker-03",
|
||||||
|
"label": "icemaker-03",
|
||||||
|
"capabilities": [
|
||||||
|
{
|
||||||
|
"id": "switch",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "custom.disabledCapabilities",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"categories": [
|
||||||
|
{
|
||||||
|
"name": "Other",
|
||||||
|
"categoryType": "manufacturer"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "scale-10",
|
||||||
|
"label": "scale-10",
|
||||||
|
"capabilities": [
|
||||||
|
{
|
||||||
|
"id": "samsungce.weightMeasurement",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungce.weightMeasurementCalibration",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungce.connectionState",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungce.scaleSettings",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "custom.disabledCapabilities",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"categories": [
|
||||||
|
{
|
||||||
|
"name": "Other",
|
||||||
|
"categoryType": "manufacturer"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "scale-11",
|
||||||
|
"label": "scale-11",
|
||||||
|
"capabilities": [
|
||||||
|
{
|
||||||
|
"id": "samsungce.weightMeasurement",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "custom.disabledCapabilities",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"categories": [
|
||||||
|
{
|
||||||
|
"name": "Other",
|
||||||
|
"categoryType": "manufacturer"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "pantry-01",
|
||||||
|
"label": "pantry-01",
|
||||||
|
"capabilities": [
|
||||||
|
{
|
||||||
|
"id": "samsungce.fridgePantryInfo",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungce.fridgePantryMode",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungce.meatAging",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungce.foodDefrost",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "custom.disabledCapabilities",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"categories": [
|
||||||
|
{
|
||||||
|
"name": "Other",
|
||||||
|
"categoryType": "manufacturer"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "camera-01",
|
||||||
|
"label": "camera-01",
|
||||||
|
"capabilities": [
|
||||||
|
{
|
||||||
|
"id": "switch",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "custom.disabledCapabilities",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"categories": [
|
||||||
|
{
|
||||||
|
"name": "Other",
|
||||||
|
"categoryType": "manufacturer"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"createTime": "2021-07-27T01:19:42.051Z",
|
||||||
|
"profile": {
|
||||||
|
"id": "4c654f1b-8ef4-35b0-920e-c12568554213"
|
||||||
|
},
|
||||||
|
"ocf": {
|
||||||
|
"ocfDeviceType": "oic.d.refrigerator",
|
||||||
|
"name": "Family Hub",
|
||||||
|
"specVersion": "core.1.1.0",
|
||||||
|
"verticalDomainSpecVersion": "res.1.1.0,sh.1.1.0",
|
||||||
|
"manufacturerName": "Samsung Electronics",
|
||||||
|
"modelNumber": "24K_REF_LCD_FHUB9.0|00113141|0002034e051324200103000000000000",
|
||||||
|
"platformVersion": "7.0",
|
||||||
|
"platformOS": "Tizen",
|
||||||
|
"hwVersion": "",
|
||||||
|
"firmwareVersion": "20240616.213423",
|
||||||
|
"vendorId": "DA-REF-NORMAL-01001",
|
||||||
|
"vendorResourceClientServerVersion": "4.0.22",
|
||||||
|
"locale": "",
|
||||||
|
"lastSignupTime": "2021-07-27T01:19:40.244392Z",
|
||||||
|
"transferCandidate": false,
|
||||||
|
"additionalAuthCodeRequired": false
|
||||||
|
},
|
||||||
|
"type": "OCF",
|
||||||
|
"restrictionTier": 0,
|
||||||
|
"allowed": [],
|
||||||
|
"executionContext": "CLOUD"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"_links": {}
|
||||||
|
}
|
@ -0,0 +1,115 @@
|
|||||||
|
{
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"deviceId": "a75cb1e1-03fd-3c77-ca9f-d4e56c4096c6",
|
||||||
|
"name": "Soundbar",
|
||||||
|
"label": "Soundbar",
|
||||||
|
"manufacturerName": "Samsung Electronics",
|
||||||
|
"presentationId": "VD-NetworkAudio-003S",
|
||||||
|
"deviceManufacturerCode": "Samsung Electronics",
|
||||||
|
"locationId": "6bdf6730-8167-488b-8645-d0c5046ff763",
|
||||||
|
"ownerId": "15f0ae72-da51-14e2-65cf-ef59ae867e7f",
|
||||||
|
"roomId": "3b0fe9a8-51d6-49cf-b64a-8a719013c0a7",
|
||||||
|
"deviceTypeName": "Samsung OCF Network Audio Player",
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"id": "main",
|
||||||
|
"label": "main",
|
||||||
|
"capabilities": [
|
||||||
|
{
|
||||||
|
"id": "ocf",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "execute",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "refresh",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "switch",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "audioVolume",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "audioMute",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungvd.audioInputSource",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "audioNotification",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungvd.soundFrom",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "sec.diagnosticsInformation",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungvd.thingStatus",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungvd.supportsFeatures",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "sec.wifiConfiguration",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungvd.audioGroupInfo",
|
||||||
|
"version": 1,
|
||||||
|
"ephemeral": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"categories": [
|
||||||
|
{
|
||||||
|
"name": "NetworkAudio",
|
||||||
|
"categoryType": "manufacturer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"createTime": "2025-02-21T14:25:21.843Z",
|
||||||
|
"profile": {
|
||||||
|
"id": "25504ad5-8563-3b07-8770-e52ad29a9c5a"
|
||||||
|
},
|
||||||
|
"ocf": {
|
||||||
|
"ocfDeviceType": "oic.d.networkaudio",
|
||||||
|
"name": "Soundbar",
|
||||||
|
"specVersion": "core.1.1.0",
|
||||||
|
"verticalDomainSpecVersion": "res.1.1.0,sh.1.1.0",
|
||||||
|
"manufacturerName": "Samsung Electronics",
|
||||||
|
"modelNumber": "HW-S60D",
|
||||||
|
"platformVersion": "8.0",
|
||||||
|
"platformOS": "Tizen",
|
||||||
|
"hwVersion": "",
|
||||||
|
"firmwareVersion": "SAT-MT8532D24WWC-1016.0",
|
||||||
|
"vendorId": "VD-NetworkAudio-003S",
|
||||||
|
"vendorResourceClientServerVersion": "4.0.26",
|
||||||
|
"lastSignupTime": "2025-03-18T19:11:51.176292902Z",
|
||||||
|
"transferCandidate": false,
|
||||||
|
"additionalAuthCodeRequired": false
|
||||||
|
},
|
||||||
|
"type": "OCF",
|
||||||
|
"restrictionTier": 0,
|
||||||
|
"allowed": null,
|
||||||
|
"executionContext": "CLOUD",
|
||||||
|
"relationships": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"_links": {}
|
||||||
|
}
|
@ -761,6 +761,150 @@
|
|||||||
'state': 'off',
|
'state': 'off',
|
||||||
})
|
})
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_all_entities[da_ref_normal_01001][binary_sensor.refrigerator_cooler_door-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': 'binary_sensor',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'binary_sensor.refrigerator_cooler_door',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'original_device_class': <BinarySensorDeviceClass.DOOR: 'door'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'Cooler door',
|
||||||
|
'platform': 'smartthings',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': 'cooler_door',
|
||||||
|
'unique_id': '7d3feb98-8a36-4351-c362-5e21ad3a78dd_cooler_contactSensor_contact_contact',
|
||||||
|
'unit_of_measurement': None,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[da_ref_normal_01001][binary_sensor.refrigerator_cooler_door-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'door',
|
||||||
|
'friendly_name': 'Refrigerator Cooler door',
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'binary_sensor.refrigerator_cooler_door',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': 'off',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[da_ref_normal_01001][binary_sensor.refrigerator_coolselect_door-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': 'binary_sensor',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'binary_sensor.refrigerator_coolselect_door',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'original_device_class': <BinarySensorDeviceClass.DOOR: 'door'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'CoolSelect+ door',
|
||||||
|
'platform': 'smartthings',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': 'cool_select_plus_door',
|
||||||
|
'unique_id': '7d3feb98-8a36-4351-c362-5e21ad3a78dd_cvroom_contactSensor_contact_contact',
|
||||||
|
'unit_of_measurement': None,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[da_ref_normal_01001][binary_sensor.refrigerator_coolselect_door-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'door',
|
||||||
|
'friendly_name': 'Refrigerator CoolSelect+ door',
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'binary_sensor.refrigerator_coolselect_door',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': 'off',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[da_ref_normal_01001][binary_sensor.refrigerator_freezer_door-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': 'binary_sensor',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'binary_sensor.refrigerator_freezer_door',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'original_device_class': <BinarySensorDeviceClass.DOOR: 'door'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'Freezer door',
|
||||||
|
'platform': 'smartthings',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': 'freezer_door',
|
||||||
|
'unique_id': '7d3feb98-8a36-4351-c362-5e21ad3a78dd_freezer_contactSensor_contact_contact',
|
||||||
|
'unit_of_measurement': None,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[da_ref_normal_01001][binary_sensor.refrigerator_freezer_door-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'door',
|
||||||
|
'friendly_name': 'Refrigerator Freezer door',
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'binary_sensor.refrigerator_freezer_door',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': 'off',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
# name: test_all_entities[da_ref_normal_01011][binary_sensor.frigo_cooler_door-entry]
|
# name: test_all_entities[da_ref_normal_01011][binary_sensor.frigo_cooler_door-entry]
|
||||||
EntityRegistryEntrySnapshot({
|
EntityRegistryEntrySnapshot({
|
||||||
'aliases': set({
|
'aliases': set({
|
||||||
|
@ -187,3 +187,50 @@
|
|||||||
'state': 'unknown',
|
'state': 'unknown',
|
||||||
})
|
})
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_all_entities[da_ref_normal_01001][button.refrigerator_reset_water_filter-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': None,
|
||||||
|
'entity_id': 'button.refrigerator_reset_water_filter',
|
||||||
|
'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': 'Reset water filter',
|
||||||
|
'platform': 'smartthings',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': 'reset_water_filter',
|
||||||
|
'unique_id': '7d3feb98-8a36-4351-c362-5e21ad3a78dd_main_custom.waterFilter_resetWaterFilter',
|
||||||
|
'unit_of_measurement': None,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[da_ref_normal_01001][button.refrigerator_reset_water_filter-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'friendly_name': 'Refrigerator Reset water filter',
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'button.refrigerator_reset_water_filter',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': 'unknown',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
@ -629,6 +629,39 @@
|
|||||||
'via_device_id': None,
|
'via_device_id': None,
|
||||||
})
|
})
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_devices[da_ref_normal_01001]
|
||||||
|
DeviceRegistryEntrySnapshot({
|
||||||
|
'area_id': None,
|
||||||
|
'config_entries': <ANY>,
|
||||||
|
'config_entries_subentries': <ANY>,
|
||||||
|
'configuration_url': 'https://account.smartthings.com',
|
||||||
|
'connections': set({
|
||||||
|
}),
|
||||||
|
'disabled_by': None,
|
||||||
|
'entry_type': None,
|
||||||
|
'hw_version': '',
|
||||||
|
'id': <ANY>,
|
||||||
|
'identifiers': set({
|
||||||
|
tuple(
|
||||||
|
'smartthings',
|
||||||
|
'7d3feb98-8a36-4351-c362-5e21ad3a78dd',
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
'is_new': False,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'manufacturer': 'Samsung Electronics',
|
||||||
|
'model': '24K_REF_LCD_FHUB9.0',
|
||||||
|
'model_id': None,
|
||||||
|
'name': 'Refrigerator',
|
||||||
|
'name_by_user': None,
|
||||||
|
'primary_config_entry': <ANY>,
|
||||||
|
'serial_number': None,
|
||||||
|
'suggested_area': None,
|
||||||
|
'sw_version': '20240616.213423',
|
||||||
|
'via_device_id': None,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
# name: test_devices[da_ref_normal_01011]
|
# name: test_devices[da_ref_normal_01011]
|
||||||
DeviceRegistryEntrySnapshot({
|
DeviceRegistryEntrySnapshot({
|
||||||
'area_id': None,
|
'area_id': None,
|
||||||
@ -1652,6 +1685,39 @@
|
|||||||
'via_device_id': None,
|
'via_device_id': None,
|
||||||
})
|
})
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_devices[vd_network_audio_003s]
|
||||||
|
DeviceRegistryEntrySnapshot({
|
||||||
|
'area_id': None,
|
||||||
|
'config_entries': <ANY>,
|
||||||
|
'config_entries_subentries': <ANY>,
|
||||||
|
'configuration_url': 'https://account.smartthings.com',
|
||||||
|
'connections': set({
|
||||||
|
}),
|
||||||
|
'disabled_by': None,
|
||||||
|
'entry_type': None,
|
||||||
|
'hw_version': '',
|
||||||
|
'id': <ANY>,
|
||||||
|
'identifiers': set({
|
||||||
|
tuple(
|
||||||
|
'smartthings',
|
||||||
|
'a75cb1e1-03fd-3c77-ca9f-d4e56c4096c6',
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
'is_new': False,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'manufacturer': 'Samsung Electronics',
|
||||||
|
'model': 'HW-S60D',
|
||||||
|
'model_id': None,
|
||||||
|
'name': 'Soundbar',
|
||||||
|
'name_by_user': None,
|
||||||
|
'primary_config_entry': <ANY>,
|
||||||
|
'serial_number': None,
|
||||||
|
'suggested_area': None,
|
||||||
|
'sw_version': 'SAT-MT8532D24WWC-1016.0',
|
||||||
|
'via_device_id': None,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
# name: test_devices[vd_sensor_light_2023]
|
# name: test_devices[vd_sensor_light_2023]
|
||||||
DeviceRegistryEntrySnapshot({
|
DeviceRegistryEntrySnapshot({
|
||||||
'area_id': None,
|
'area_id': None,
|
||||||
|
@ -231,6 +231,56 @@
|
|||||||
'state': 'on',
|
'state': 'on',
|
||||||
})
|
})
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_all_entities[vd_network_audio_003s][media_player.soundbar-entry]
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': dict({
|
||||||
|
}),
|
||||||
|
'config_entry_id': <ANY>,
|
||||||
|
'config_subentry_id': <ANY>,
|
||||||
|
'device_class': None,
|
||||||
|
'device_id': <ANY>,
|
||||||
|
'disabled_by': None,
|
||||||
|
'domain': 'media_player',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'media_player.soundbar',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'original_device_class': <MediaPlayerDeviceClass.SPEAKER: 'speaker'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': None,
|
||||||
|
'platform': 'smartthings',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': <MediaPlayerEntityFeature: 1420>,
|
||||||
|
'translation_key': None,
|
||||||
|
'unique_id': 'a75cb1e1-03fd-3c77-ca9f-d4e56c4096c6_main',
|
||||||
|
'unit_of_measurement': None,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[vd_network_audio_003s][media_player.soundbar-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'speaker',
|
||||||
|
'friendly_name': 'Soundbar',
|
||||||
|
'supported_features': <MediaPlayerEntityFeature: 1420>,
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'media_player.soundbar',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': 'off',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
# name: test_all_entities[vd_stv_2017_k][media_player.tv_samsung_8_series_49-entry]
|
# name: test_all_entities[vd_stv_2017_k][media_player.tv_samsung_8_series_49-entry]
|
||||||
EntityRegistryEntrySnapshot({
|
EntityRegistryEntrySnapshot({
|
||||||
'aliases': set({
|
'aliases': set({
|
||||||
|
@ -4049,6 +4049,283 @@
|
|||||||
'state': '0.0135559777781698',
|
'state': '0.0135559777781698',
|
||||||
})
|
})
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_all_entities[da_ref_normal_01001][sensor.refrigerator_energy-entry]
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': dict({
|
||||||
|
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||||
|
}),
|
||||||
|
'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.refrigerator_energy',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
'sensor': dict({
|
||||||
|
'suggested_display_precision': 2,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'Energy',
|
||||||
|
'platform': 'smartthings',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': None,
|
||||||
|
'unique_id': '7d3feb98-8a36-4351-c362-5e21ad3a78dd_main_powerConsumptionReport_powerConsumption_energy_meter',
|
||||||
|
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[da_ref_normal_01001][sensor.refrigerator_energy-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'energy',
|
||||||
|
'friendly_name': 'Refrigerator Energy',
|
||||||
|
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||||
|
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'sensor.refrigerator_energy',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': '4381.422',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[da_ref_normal_01001][sensor.refrigerator_energy_difference-entry]
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': dict({
|
||||||
|
'state_class': <SensorStateClass.TOTAL: 'total'>,
|
||||||
|
}),
|
||||||
|
'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.refrigerator_energy_difference',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
'sensor': dict({
|
||||||
|
'suggested_display_precision': 2,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'Energy difference',
|
||||||
|
'platform': 'smartthings',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': 'energy_difference',
|
||||||
|
'unique_id': '7d3feb98-8a36-4351-c362-5e21ad3a78dd_main_powerConsumptionReport_powerConsumption_deltaEnergy_meter',
|
||||||
|
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[da_ref_normal_01001][sensor.refrigerator_energy_difference-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'energy',
|
||||||
|
'friendly_name': 'Refrigerator Energy difference',
|
||||||
|
'state_class': <SensorStateClass.TOTAL: 'total'>,
|
||||||
|
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'sensor.refrigerator_energy_difference',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': '0.027',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[da_ref_normal_01001][sensor.refrigerator_energy_saved-entry]
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': dict({
|
||||||
|
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||||
|
}),
|
||||||
|
'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.refrigerator_energy_saved',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
'sensor': dict({
|
||||||
|
'suggested_display_precision': 2,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'Energy saved',
|
||||||
|
'platform': 'smartthings',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': 'energy_saved',
|
||||||
|
'unique_id': '7d3feb98-8a36-4351-c362-5e21ad3a78dd_main_powerConsumptionReport_powerConsumption_energySaved_meter',
|
||||||
|
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[da_ref_normal_01001][sensor.refrigerator_energy_saved-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'energy',
|
||||||
|
'friendly_name': 'Refrigerator Energy saved',
|
||||||
|
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||||
|
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'sensor.refrigerator_energy_saved',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': '0.0',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[da_ref_normal_01001][sensor.refrigerator_power-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.refrigerator_power',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
'sensor': dict({
|
||||||
|
'suggested_display_precision': 2,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
'original_device_class': <SensorDeviceClass.POWER: 'power'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'Power',
|
||||||
|
'platform': 'smartthings',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': None,
|
||||||
|
'unique_id': '7d3feb98-8a36-4351-c362-5e21ad3a78dd_main_powerConsumptionReport_powerConsumption_power_meter',
|
||||||
|
'unit_of_measurement': <UnitOfPower.WATT: 'W'>,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[da_ref_normal_01001][sensor.refrigerator_power-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'power',
|
||||||
|
'friendly_name': 'Refrigerator Power',
|
||||||
|
'power_consumption_end': '2025-02-09T00:25:23Z',
|
||||||
|
'power_consumption_start': '2025-02-09T00:13:39Z',
|
||||||
|
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||||
|
'unit_of_measurement': <UnitOfPower.WATT: 'W'>,
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'sensor.refrigerator_power',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': '144',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[da_ref_normal_01001][sensor.refrigerator_power_energy-entry]
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': dict({
|
||||||
|
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||||
|
}),
|
||||||
|
'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.refrigerator_power_energy',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
'sensor': dict({
|
||||||
|
'suggested_display_precision': 2,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'Power energy',
|
||||||
|
'platform': 'smartthings',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': 'power_energy',
|
||||||
|
'unique_id': '7d3feb98-8a36-4351-c362-5e21ad3a78dd_main_powerConsumptionReport_powerConsumption_powerEnergy_meter',
|
||||||
|
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[da_ref_normal_01001][sensor.refrigerator_power_energy-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'energy',
|
||||||
|
'friendly_name': 'Refrigerator Power energy',
|
||||||
|
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||||
|
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'sensor.refrigerator_power_energy',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': '0.0270189050030708',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
# name: test_all_entities[da_ref_normal_01011][sensor.frigo_energy-entry]
|
# name: test_all_entities[da_ref_normal_01011][sensor.frigo_energy-entry]
|
||||||
EntityRegistryEntrySnapshot({
|
EntityRegistryEntrySnapshot({
|
||||||
'aliases': set({
|
'aliases': set({
|
||||||
|
@ -93,6 +93,53 @@
|
|||||||
'state': 'off',
|
'state': 'off',
|
||||||
})
|
})
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_all_entities[da_ref_normal_01001][switch.refrigerator_ice_maker-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': 'switch',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'switch.refrigerator_ice_maker',
|
||||||
|
'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': 'Ice maker',
|
||||||
|
'platform': 'smartthings',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': 'ice_maker',
|
||||||
|
'unique_id': '7d3feb98-8a36-4351-c362-5e21ad3a78dd_icemaker_switch_switch_switch',
|
||||||
|
'unit_of_measurement': None,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[da_ref_normal_01001][switch.refrigerator_ice_maker-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'friendly_name': 'Refrigerator Ice maker',
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'switch.refrigerator_ice_maker',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': 'on',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
# name: test_all_entities[da_rvc_normal_000001][switch.robot_vacuum-entry]
|
# name: test_all_entities[da_rvc_normal_000001][switch.robot_vacuum-entry]
|
||||||
EntityRegistryEntrySnapshot({
|
EntityRegistryEntrySnapshot({
|
||||||
'aliases': set({
|
'aliases': set({
|
||||||
|
@ -181,13 +181,13 @@ async def test_assist_api(
|
|||||||
|
|
||||||
assert len(llm.async_get_apis(hass)) == 1
|
assert len(llm.async_get_apis(hass)) == 1
|
||||||
api = await llm.async_get_api(hass, "assist", llm_context)
|
api = await llm.async_get_api(hass, "assist", llm_context)
|
||||||
assert [tool.name for tool in api.tools] == ["get_home_state"]
|
assert [tool.name for tool in api.tools] == ["GetLiveContext"]
|
||||||
|
|
||||||
# Match all
|
# Match all
|
||||||
intent_handler.platforms = None
|
intent_handler.platforms = None
|
||||||
|
|
||||||
api = await llm.async_get_api(hass, "assist", llm_context)
|
api = await llm.async_get_api(hass, "assist", llm_context)
|
||||||
assert [tool.name for tool in api.tools] == ["test_intent", "get_home_state"]
|
assert [tool.name for tool in api.tools] == ["test_intent", "GetLiveContext"]
|
||||||
|
|
||||||
# Match specific domain
|
# Match specific domain
|
||||||
intent_handler.platforms = {"light"}
|
intent_handler.platforms = {"light"}
|
||||||
@ -575,7 +575,7 @@ async def test_assist_api_prompt(
|
|||||||
suggested_area="Test Area 2",
|
suggested_area="Test Area 2",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
exposed_entities_prompt = """An overview of the areas and the devices in this smart home:
|
exposed_entities_prompt = """Live Context: An overview of the areas and the devices in this smart home:
|
||||||
- names: Kitchen
|
- names: Kitchen
|
||||||
domain: light
|
domain: light
|
||||||
state: 'on'
|
state: 'on'
|
||||||
@ -623,7 +623,7 @@ async def test_assist_api_prompt(
|
|||||||
state: unavailable
|
state: unavailable
|
||||||
areas: Test Area 2
|
areas: Test Area 2
|
||||||
"""
|
"""
|
||||||
stateless_exposed_entities_prompt = """An overview of the areas and the devices in this smart home:
|
stateless_exposed_entities_prompt = """Static Context: An overview of the areas and the devices in this smart home:
|
||||||
- names: Kitchen
|
- names: Kitchen
|
||||||
domain: light
|
domain: light
|
||||||
- names: Living Room
|
- names: Living Room
|
||||||
@ -669,17 +669,30 @@ async def test_assist_api_prompt(
|
|||||||
"When a user asks to turn on all devices of a specific type, "
|
"When a user asks to turn on all devices of a specific type, "
|
||||||
"ask user to specify an area, unless there is only one device of that type."
|
"ask user to specify an area, unless there is only one device of that type."
|
||||||
)
|
)
|
||||||
|
dynamic_context_prompt = """You ARE equipped to answer questions about the current state of
|
||||||
|
the home using the `GetLiveContext` tool. This is a primary function. Do not state you lack the
|
||||||
|
functionality if the question requires live data.
|
||||||
|
If the user asks about device existence/type (e.g., "Do I have lights in the bedroom?"): Answer
|
||||||
|
from the static context below.
|
||||||
|
If the user asks about the CURRENT state, value, or mode (e.g., "Is the lock locked?",
|
||||||
|
"Is the fan on?", "What mode is the thermostat in?", "What is the temperature outside?"):
|
||||||
|
1. Recognize this requires live data.
|
||||||
|
2. You MUST call `GetLiveContext`. This tool will provide the needed real-time information (like temperature from the local weather, lock status, etc.).
|
||||||
|
3. Use the tool's response** to answer the user accurately (e.g., "The temperature outside is [value from tool].").
|
||||||
|
For general knowledge questions not about the home: Answer truthfully from internal knowledge.
|
||||||
|
"""
|
||||||
api = await llm.async_get_api(hass, "assist", llm_context)
|
api = await llm.async_get_api(hass, "assist", llm_context)
|
||||||
assert api.api_prompt == (
|
assert api.api_prompt == (
|
||||||
f"""{first_part_prompt}
|
f"""{first_part_prompt}
|
||||||
{area_prompt}
|
{area_prompt}
|
||||||
{no_timer_prompt}
|
{no_timer_prompt}
|
||||||
|
{dynamic_context_prompt}
|
||||||
{stateless_exposed_entities_prompt}"""
|
{stateless_exposed_entities_prompt}"""
|
||||||
)
|
)
|
||||||
|
|
||||||
# Verify that the get_home_state tool returns the same results as the exposed_entities_prompt
|
# Verify that the GetLiveContext tool returns the same results as the exposed_entities_prompt
|
||||||
result = await api.async_call_tool(
|
result = await api.async_call_tool(
|
||||||
llm.ToolInput(tool_name="get_home_state", tool_args={})
|
llm.ToolInput(tool_name="GetLiveContext", tool_args={})
|
||||||
)
|
)
|
||||||
assert result == {
|
assert result == {
|
||||||
"success": True,
|
"success": True,
|
||||||
@ -697,6 +710,7 @@ async def test_assist_api_prompt(
|
|||||||
f"""{first_part_prompt}
|
f"""{first_part_prompt}
|
||||||
{area_prompt}
|
{area_prompt}
|
||||||
{no_timer_prompt}
|
{no_timer_prompt}
|
||||||
|
{dynamic_context_prompt}
|
||||||
{stateless_exposed_entities_prompt}"""
|
{stateless_exposed_entities_prompt}"""
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -712,6 +726,7 @@ async def test_assist_api_prompt(
|
|||||||
f"""{first_part_prompt}
|
f"""{first_part_prompt}
|
||||||
{area_prompt}
|
{area_prompt}
|
||||||
{no_timer_prompt}
|
{no_timer_prompt}
|
||||||
|
{dynamic_context_prompt}
|
||||||
{stateless_exposed_entities_prompt}"""
|
{stateless_exposed_entities_prompt}"""
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -723,6 +738,7 @@ async def test_assist_api_prompt(
|
|||||||
assert api.api_prompt == (
|
assert api.api_prompt == (
|
||||||
f"""{first_part_prompt}
|
f"""{first_part_prompt}
|
||||||
{area_prompt}
|
{area_prompt}
|
||||||
|
{dynamic_context_prompt}
|
||||||
{stateless_exposed_entities_prompt}"""
|
{stateless_exposed_entities_prompt}"""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user