Refactor SmartThings (#137940)

This commit is contained in:
Joost Lekkerkerker
2025-02-26 15:14:04 +01:00
committed by GitHub
parent bb9aba2a7d
commit bb120020a8
109 changed files with 22599 additions and 6175 deletions

2
CODEOWNERS generated
View File

@ -1401,6 +1401,8 @@ build.json @home-assistant/supervisor
/tests/components/smappee/ @bsmappee
/homeassistant/components/smart_meter_texas/ @grahamwetzler
/tests/components/smart_meter_texas/ @grahamwetzler
/homeassistant/components/smartthings/ @joostlek
/tests/components/smartthings/ @joostlek
/homeassistant/components/smarttub/ @mdz
/tests/components/smarttub/ @mdz
/homeassistant/components/smarty/ @z0mbieprocess

View File

@ -2,416 +2,144 @@
from __future__ import annotations
import asyncio
from collections.abc import Iterable
from http import HTTPStatus
import importlib
from dataclasses import dataclass
import logging
from typing import TYPE_CHECKING
from aiohttp.client_exceptions import ClientConnectionError, ClientResponseError
from pysmartapp.event import EVENT_TYPE_DEVICE
from pysmartthings import APIInvalidGrant, Attribute, Capability, SmartThings
from aiohttp import ClientError
from pysmartthings import (
Attribute,
Capability,
Device,
Scene,
SmartThings,
SmartThingsAuthenticationFailedError,
Status,
)
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_CLIENT_ID, CONF_CLIENT_SECRET
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_TOKEN, Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import (
ConfigEntryAuthFailed,
ConfigEntryError,
ConfigEntryNotReady,
)
from homeassistant.helpers import config_validation as cv
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers.event import async_track_time_interval
from homeassistant.helpers.typing import ConfigType
from homeassistant.loader import async_get_loaded_integration
from homeassistant.setup import SetupPhases, async_pause_setup
from homeassistant.helpers.config_entry_oauth2_flow import (
OAuth2Session,
async_get_config_entry_implementation,
)
from .config_flow import SmartThingsFlowHandler # noqa: F401
from .const import (
CONF_APP_ID,
CONF_INSTALLED_APP_ID,
CONF_LOCATION_ID,
CONF_REFRESH_TOKEN,
DATA_BROKERS,
DATA_MANAGER,
DOMAIN,
EVENT_BUTTON,
PLATFORMS,
SIGNAL_SMARTTHINGS_UPDATE,
TOKEN_REFRESH_INTERVAL,
)
from .smartapp import (
format_unique_id,
setup_smartapp,
setup_smartapp_endpoint,
smartapp_sync_subscriptions,
unload_smartapp_endpoint,
validate_installed_app,
validate_webhook_requirements,
)
from .const import CONF_INSTALLED_APP_ID, CONF_LOCATION_ID, MAIN, OLD_DATA
_LOGGER = logging.getLogger(__name__)
CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
@dataclass
class SmartThingsData:
"""Define an object to hold SmartThings data."""
devices: dict[str, FullDevice]
scenes: dict[str, Scene]
client: SmartThings
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Initialize the SmartThings platform."""
await setup_smartapp_endpoint(hass, False)
return True
@dataclass
class FullDevice:
"""Define an object to hold device data."""
device: Device
status: dict[str, dict[Capability, dict[Attribute, Status]]]
async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Handle migration of a previous version config entry.
type SmartThingsConfigEntry = ConfigEntry[SmartThingsData]
A config entry created under a previous version must go through the
integration setup again so we can properly retrieve the needed data
elements. Force this by removing the entry and triggering a new flow.
"""
# Remove the entry which will invoke the callback to delete the app.
hass.async_create_task(hass.config_entries.async_remove(entry.entry_id))
# only create new flow if there isn't a pending one for SmartThings.
if not hass.config_entries.flow.async_progress_by_handler(DOMAIN):
hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_IMPORT}
)
)
# Return False because it could not be migrated.
return False
PLATFORMS = [
Platform.BINARY_SENSOR,
Platform.CLIMATE,
Platform.COVER,
Platform.FAN,
Platform.LIGHT,
Platform.LOCK,
Platform.SCENE,
Platform.SENSOR,
Platform.SWITCH,
]
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_setup_entry(hass: HomeAssistant, entry: SmartThingsConfigEntry) -> bool:
"""Initialize config entry which represents an installed SmartApp."""
# For backwards compat
if entry.unique_id is None:
hass.config_entries.async_update_entry(
entry,
unique_id=format_unique_id(
entry.data[CONF_APP_ID], entry.data[CONF_LOCATION_ID]
),
)
if not validate_webhook_requirements(hass):
_LOGGER.warning(
"The 'base_url' of the 'http' integration must be configured and start with"
" 'https://'"
)
return False
api = SmartThings(async_get_clientsession(hass), entry.data[CONF_ACCESS_TOKEN])
# Ensure platform modules are loaded since the DeviceBroker will
# import them below and we want them to be cached ahead of time
# so the integration does not do blocking I/O in the event loop
# to import the modules.
await async_get_loaded_integration(hass, DOMAIN).async_get_platforms(PLATFORMS)
# The oauth smartthings entry will have a token, older ones are version 3
# after migration but still require reauthentication
if CONF_TOKEN not in entry.data:
raise ConfigEntryAuthFailed("Config entry missing token")
implementation = await async_get_config_entry_implementation(hass, entry)
session = OAuth2Session(hass, entry, implementation)
try:
# See if the app is already setup. This occurs when there are
# installs in multiple SmartThings locations (valid use-case)
manager = hass.data[DOMAIN][DATA_MANAGER]
smart_app = manager.smartapps.get(entry.data[CONF_APP_ID])
if not smart_app:
# Validate and setup the app.
app = await api.app(entry.data[CONF_APP_ID])
smart_app = setup_smartapp(hass, app)
await session.async_ensure_token_valid()
except ClientError as err:
raise ConfigEntryNotReady from err
# Validate and retrieve the installed app.
installed_app = await validate_installed_app(
api, entry.data[CONF_INSTALLED_APP_ID]
)
client = SmartThings(session=async_get_clientsession(hass))
# Get scenes
scenes = await async_get_entry_scenes(entry, api)
async def _refresh_token() -> str:
await session.async_ensure_token_valid()
token = session.token[CONF_ACCESS_TOKEN]
if TYPE_CHECKING:
assert isinstance(token, str)
return token
# Get SmartApp token to sync subscriptions
token = await api.generate_tokens(
entry.data[CONF_CLIENT_ID],
entry.data[CONF_CLIENT_SECRET],
entry.data[CONF_REFRESH_TOKEN],
)
hass.config_entries.async_update_entry(
entry, data={**entry.data, CONF_REFRESH_TOKEN: token.refresh_token}
)
client.refresh_token_function = _refresh_token
# Get devices and their current status
devices = await api.devices(location_ids=[installed_app.location_id])
device_status: dict[str, FullDevice] = {}
try:
devices = await client.get_devices()
for device in devices:
status = await client.get_device_status(device.device_id)
device_status[device.device_id] = FullDevice(device=device, status=status)
except SmartThingsAuthenticationFailedError as err:
raise ConfigEntryAuthFailed from err
async def retrieve_device_status(device):
try:
await device.status.refresh()
except ClientResponseError:
_LOGGER.debug(
(
"Unable to update status for device: %s (%s), the device will"
" be excluded"
),
device.label,
device.device_id,
exc_info=True,
)
devices.remove(device)
scenes = {
scene.scene_id: scene
for scene in await client.get_scenes(location_id=entry.data[CONF_LOCATION_ID])
}
await asyncio.gather(*(retrieve_device_status(d) for d in devices.copy()))
entry.runtime_data = SmartThingsData(
devices={
device_id: device
for device_id, device in device_status.items()
if MAIN in device.status
},
client=client,
scenes=scenes,
)
# Sync device subscriptions
await smartapp_sync_subscriptions(
hass,
token.access_token,
installed_app.location_id,
installed_app.installed_app_id,
devices,
)
# Setup device broker
with async_pause_setup(hass, SetupPhases.WAIT_IMPORT_PLATFORMS):
# DeviceBroker has a side effect of importing platform
# modules when its created. In the future this should be
# refactored to not do this.
broker = await hass.async_add_import_executor_job(
DeviceBroker, hass, entry, token, smart_app, devices, scenes
)
broker.connect()
hass.data[DOMAIN][DATA_BROKERS][entry.entry_id] = broker
except APIInvalidGrant as ex:
raise ConfigEntryAuthFailed from ex
except ClientResponseError as ex:
if ex.status in (HTTPStatus.UNAUTHORIZED, HTTPStatus.FORBIDDEN):
raise ConfigEntryError(
"The access token is no longer valid. Please remove the integration and set up again."
) from ex
_LOGGER.debug(ex, exc_info=True)
raise ConfigEntryNotReady from ex
except (ClientConnectionError, RuntimeWarning) as ex:
_LOGGER.debug(ex, exc_info=True)
raise ConfigEntryNotReady from ex
entry.async_create_background_task(
hass,
client.subscribe(
entry.data[CONF_LOCATION_ID], entry.data[CONF_TOKEN][CONF_INSTALLED_APP_ID]
),
"smartthings_webhook",
)
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
return True
async def async_get_entry_scenes(entry: ConfigEntry, api):
"""Get the scenes within an integration."""
try:
return await api.scenes(location_id=entry.data[CONF_LOCATION_ID])
except ClientResponseError as ex:
if ex.status == HTTPStatus.FORBIDDEN:
_LOGGER.exception(
(
"Unable to load scenes for configuration entry '%s' because the"
" access token does not have the required access"
),
entry.title,
)
else:
raise
return []
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_unload_entry(
hass: HomeAssistant, entry: SmartThingsConfigEntry
) -> bool:
"""Unload a config entry."""
broker = hass.data[DOMAIN][DATA_BROKERS].pop(entry.entry_id, None)
if broker:
broker.disconnect()
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Perform clean-up when entry is being removed."""
api = SmartThings(async_get_clientsession(hass), entry.data[CONF_ACCESS_TOKEN])
async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Handle config entry migration."""
# Remove the installed_app, which if already removed raises a HTTPStatus.FORBIDDEN error.
installed_app_id = entry.data[CONF_INSTALLED_APP_ID]
try:
await api.delete_installed_app(installed_app_id)
except ClientResponseError as ex:
if ex.status == HTTPStatus.FORBIDDEN:
_LOGGER.debug(
"Installed app %s has already been removed",
installed_app_id,
exc_info=True,
)
else:
raise
_LOGGER.debug("Removed installed app %s", installed_app_id)
# Remove the app if not referenced by other entries, which if already
# removed raises a HTTPStatus.FORBIDDEN error.
all_entries = hass.config_entries.async_entries(DOMAIN)
app_id = entry.data[CONF_APP_ID]
app_count = sum(1 for entry in all_entries if entry.data[CONF_APP_ID] == app_id)
if app_count > 1:
_LOGGER.debug(
(
"App %s was not removed because it is in use by other configuration"
" entries"
),
app_id,
)
return
# Remove the app
try:
await api.delete_app(app_id)
except ClientResponseError as ex:
if ex.status == HTTPStatus.FORBIDDEN:
_LOGGER.debug("App %s has already been removed", app_id, exc_info=True)
else:
raise
_LOGGER.debug("Removed app %s", app_id)
if len(all_entries) == 1:
await unload_smartapp_endpoint(hass)
class DeviceBroker:
"""Manages an individual SmartThings config entry."""
def __init__(
self,
hass: HomeAssistant,
entry: ConfigEntry,
token,
smart_app,
devices: Iterable,
scenes: Iterable,
) -> None:
"""Create a new instance of the DeviceBroker."""
self._hass = hass
self._entry = entry
self._installed_app_id = entry.data[CONF_INSTALLED_APP_ID]
self._smart_app = smart_app
self._token = token
self._event_disconnect = None
self._regenerate_token_remove = None
self._assignments = self._assign_capabilities(devices)
self.devices = {device.device_id: device for device in devices}
self.scenes = {scene.scene_id: scene for scene in scenes}
def _assign_capabilities(self, devices: Iterable):
"""Assign platforms to capabilities."""
assignments = {}
for device in devices:
capabilities = device.capabilities.copy()
slots = {}
for platform in PLATFORMS:
platform_module = importlib.import_module(
f".{platform}", self.__module__
)
if not hasattr(platform_module, "get_capabilities"):
continue
assigned = platform_module.get_capabilities(capabilities)
if not assigned:
continue
# Draw-down capabilities and set slot assignment
for capability in assigned:
if capability not in capabilities:
continue
capabilities.remove(capability)
slots[capability] = platform
assignments[device.device_id] = slots
return assignments
def connect(self):
"""Connect handlers/listeners for device/lifecycle events."""
# Setup interval to regenerate the refresh token on a periodic basis.
# Tokens expire in 30 days and once expired, cannot be recovered.
async def regenerate_refresh_token(now):
"""Generate a new refresh token and update the config entry."""
await self._token.refresh(
self._entry.data[CONF_CLIENT_ID],
self._entry.data[CONF_CLIENT_SECRET],
)
self._hass.config_entries.async_update_entry(
self._entry,
data={
**self._entry.data,
CONF_REFRESH_TOKEN: self._token.refresh_token,
},
)
_LOGGER.debug(
"Regenerated refresh token for installed app: %s",
self._installed_app_id,
)
self._regenerate_token_remove = async_track_time_interval(
self._hass, regenerate_refresh_token, TOKEN_REFRESH_INTERVAL
if entry.version < 3:
# We keep the old data around, so we can use that to clean up the webhook in the future
hass.config_entries.async_update_entry(
entry, version=3, data={OLD_DATA: dict(entry.data)}
)
# Connect handler to incoming device events
self._event_disconnect = self._smart_app.connect_event(self._event_handler)
def disconnect(self):
"""Disconnects handlers/listeners for device/lifecycle events."""
if self._regenerate_token_remove:
self._regenerate_token_remove()
if self._event_disconnect:
self._event_disconnect()
def get_assigned(self, device_id: str, platform: str):
"""Get the capabilities assigned to the platform."""
slots = self._assignments.get(device_id, {})
return [key for key, value in slots.items() if value == platform]
def any_assigned(self, device_id: str, platform: str):
"""Return True if the platform has any assigned capabilities."""
slots = self._assignments.get(device_id, {})
return any(value for value in slots.values() if value == platform)
async def _event_handler(self, req, resp, app):
"""Broker for incoming events."""
# Do not process events received from a different installed app
# under the same parent SmartApp (valid use-scenario)
if req.installed_app_id != self._installed_app_id:
return
updated_devices = set()
for evt in req.events:
if evt.event_type != EVENT_TYPE_DEVICE:
continue
if not (device := self.devices.get(evt.device_id)):
continue
device.status.apply_attribute_update(
evt.component_id,
evt.capability,
evt.attribute,
evt.value,
data=evt.data,
)
# Fire events for buttons
if (
evt.capability == Capability.button
and evt.attribute == Attribute.button
):
data = {
"component_id": evt.component_id,
"device_id": evt.device_id,
"location_id": evt.location_id,
"value": evt.value,
"name": device.label,
"data": evt.data,
}
self._hass.bus.async_fire(EVENT_BUTTON, data)
_LOGGER.debug("Fired button event: %s", data)
else:
data = {
"location_id": evt.location_id,
"device_id": evt.device_id,
"component_id": evt.component_id,
"capability": evt.capability,
"attribute": evt.attribute,
"value": evt.value,
"data": evt.data,
}
_LOGGER.debug("Push update received: %s", data)
updated_devices.add(device.device_id)
async_dispatcher_send(self._hass, SIGNAL_SMARTTHINGS_UPDATE, updated_devices)
return True

View File

@ -0,0 +1,64 @@
"""Application credentials platform for SmartThings."""
from json import JSONDecodeError
import logging
from typing import cast
from aiohttp import BasicAuth, ClientError
from homeassistant.components.application_credentials import (
AuthImplementation,
AuthorizationServer,
ClientCredential,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.config_entry_oauth2_flow import AbstractOAuth2Implementation
from .const import DOMAIN
_LOGGER = logging.getLogger(__name__)
async def async_get_auth_implementation(
hass: HomeAssistant, auth_domain: str, credential: ClientCredential
) -> AbstractOAuth2Implementation:
"""Return auth implementation."""
return SmartThingsOAuth2Implementation(
hass,
DOMAIN,
credential,
authorization_server=AuthorizationServer(
authorize_url="https://api.smartthings.com/oauth/authorize",
token_url="https://auth-global.api.smartthings.com/oauth/token",
),
)
class SmartThingsOAuth2Implementation(AuthImplementation):
"""Oauth2 implementation that only uses the external url."""
async def _token_request(self, data: dict) -> dict:
"""Make a token request."""
session = async_get_clientsession(self.hass)
resp = await session.post(
self.token_url,
data=data,
auth=BasicAuth(self.client_id, self.client_secret),
)
if resp.status >= 400:
try:
error_response = await resp.json()
except (ClientError, JSONDecodeError):
error_response = {}
error_code = error_response.get("error", "unknown")
error_description = error_response.get("error_description", "unknown error")
_LOGGER.error(
"Token request for %s failed (%s): %s",
self.domain,
error_code,
error_description,
)
resp.raise_for_status()
return cast(dict, await resp.json())

View File

@ -2,84 +2,144 @@
from __future__ import annotations
from collections.abc import Sequence
from dataclasses import dataclass
from pysmartthings import Attribute, Capability
from pysmartthings import Attribute, Capability, SmartThings
from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
BinarySensorEntity,
BinarySensorEntityDescription,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .const import DATA_BROKERS, DOMAIN
from . import FullDevice, SmartThingsConfigEntry
from .const import MAIN
from .entity import SmartThingsEntity
CAPABILITY_TO_ATTRIB = {
Capability.acceleration_sensor: Attribute.acceleration,
Capability.contact_sensor: Attribute.contact,
Capability.filter_status: Attribute.filter_status,
Capability.motion_sensor: Attribute.motion,
Capability.presence_sensor: Attribute.presence,
Capability.sound_sensor: Attribute.sound,
Capability.tamper_alert: Attribute.tamper,
Capability.valve: Attribute.valve,
Capability.water_sensor: Attribute.water,
}
ATTRIB_TO_CLASS = {
Attribute.acceleration: BinarySensorDeviceClass.MOVING,
Attribute.contact: BinarySensorDeviceClass.OPENING,
Attribute.filter_status: BinarySensorDeviceClass.PROBLEM,
Attribute.motion: BinarySensorDeviceClass.MOTION,
Attribute.presence: BinarySensorDeviceClass.PRESENCE,
Attribute.sound: BinarySensorDeviceClass.SOUND,
Attribute.tamper: BinarySensorDeviceClass.PROBLEM,
Attribute.valve: BinarySensorDeviceClass.OPENING,
Attribute.water: BinarySensorDeviceClass.MOISTURE,
}
ATTRIB_TO_ENTTIY_CATEGORY = {
Attribute.tamper: EntityCategory.DIAGNOSTIC,
@dataclass(frozen=True, kw_only=True)
class SmartThingsBinarySensorEntityDescription(BinarySensorEntityDescription):
"""Describe a SmartThings binary sensor entity."""
is_on_key: str
CAPABILITY_TO_SENSORS: dict[
Capability, dict[Attribute, SmartThingsBinarySensorEntityDescription]
] = {
Capability.ACCELERATION_SENSOR: {
Attribute.ACCELERATION: SmartThingsBinarySensorEntityDescription(
key=Attribute.ACCELERATION,
device_class=BinarySensorDeviceClass.MOVING,
is_on_key="active",
)
},
Capability.CONTACT_SENSOR: {
Attribute.CONTACT: SmartThingsBinarySensorEntityDescription(
key=Attribute.CONTACT,
device_class=BinarySensorDeviceClass.DOOR,
is_on_key="open",
)
},
Capability.FILTER_STATUS: {
Attribute.FILTER_STATUS: SmartThingsBinarySensorEntityDescription(
key=Attribute.FILTER_STATUS,
device_class=BinarySensorDeviceClass.PROBLEM,
is_on_key="replace",
)
},
Capability.MOTION_SENSOR: {
Attribute.MOTION: SmartThingsBinarySensorEntityDescription(
key=Attribute.MOTION,
device_class=BinarySensorDeviceClass.MOTION,
is_on_key="active",
)
},
Capability.PRESENCE_SENSOR: {
Attribute.PRESENCE: SmartThingsBinarySensorEntityDescription(
key=Attribute.PRESENCE,
device_class=BinarySensorDeviceClass.PRESENCE,
is_on_key="present",
)
},
Capability.SOUND_SENSOR: {
Attribute.SOUND: SmartThingsBinarySensorEntityDescription(
key=Attribute.SOUND,
device_class=BinarySensorDeviceClass.SOUND,
is_on_key="detected",
)
},
Capability.TAMPER_ALERT: {
Attribute.TAMPER: SmartThingsBinarySensorEntityDescription(
key=Attribute.TAMPER,
device_class=BinarySensorDeviceClass.PROBLEM,
is_on_key="detected",
entity_category=EntityCategory.DIAGNOSTIC,
)
},
Capability.VALVE: {
Attribute.VALVE: SmartThingsBinarySensorEntityDescription(
key=Attribute.VALVE,
device_class=BinarySensorDeviceClass.OPENING,
is_on_key="open",
)
},
Capability.WATER_SENSOR: {
Attribute.WATER: SmartThingsBinarySensorEntityDescription(
key=Attribute.WATER,
device_class=BinarySensorDeviceClass.MOISTURE,
is_on_key="wet",
)
},
}
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
entry: SmartThingsConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Add binary sensors for a config entry."""
broker = hass.data[DOMAIN][DATA_BROKERS][config_entry.entry_id]
sensors = []
for device in broker.devices.values():
for capability in broker.get_assigned(device.device_id, "binary_sensor"):
attrib = CAPABILITY_TO_ATTRIB[capability]
sensors.append(SmartThingsBinarySensor(device, attrib))
async_add_entities(sensors)
def get_capabilities(capabilities: Sequence[str]) -> Sequence[str] | None:
"""Return all capabilities supported if minimum required are present."""
return [
capability for capability in CAPABILITY_TO_ATTRIB if capability in capabilities
]
entry_data = entry.runtime_data
async_add_entities(
SmartThingsBinarySensor(
entry_data.client, device, description, capability, attribute
)
for device in entry_data.devices.values()
for capability, attribute_map in CAPABILITY_TO_SENSORS.items()
if capability in device.status[MAIN]
for attribute, description in attribute_map.items()
)
class SmartThingsBinarySensor(SmartThingsEntity, BinarySensorEntity):
"""Define a SmartThings Binary Sensor."""
def __init__(self, device, attribute):
entity_description: SmartThingsBinarySensorEntityDescription
def __init__(
self,
client: SmartThings,
device: FullDevice,
entity_description: SmartThingsBinarySensorEntityDescription,
capability: Capability,
attribute: Attribute,
) -> None:
"""Init the class."""
super().__init__(device)
super().__init__(client, device, {capability})
self._attribute = attribute
self._attr_name = f"{device.label} {attribute}"
self._attr_unique_id = f"{device.device_id}.{attribute}"
self._attr_device_class = ATTRIB_TO_CLASS[attribute]
self._attr_entity_category = ATTRIB_TO_ENTTIY_CATEGORY.get(attribute)
self.capability = capability
self.entity_description = entity_description
self._attr_name = f"{device.device.label} {attribute}"
self._attr_unique_id = f"{device.device.device_id}.{attribute}"
@property
def is_on(self):
def is_on(self) -> bool:
"""Return true if the binary sensor is on."""
return self._device.status.is_on(self._attribute)
return (
self.get_attribute_value(self.capability, self._attribute)
== self.entity_description.is_on_key
)

View File

@ -3,17 +3,15 @@
from __future__ import annotations
import asyncio
from collections.abc import Iterable, Sequence
import logging
from typing import Any
from pysmartthings import Attribute, Capability
from pysmartthings import Attribute, Capability, Command, SmartThings
from homeassistant.components.climate import (
ATTR_HVAC_MODE,
ATTR_TARGET_TEMP_HIGH,
ATTR_TARGET_TEMP_LOW,
DOMAIN as CLIMATE_DOMAIN,
SWING_BOTH,
SWING_HORIZONTAL,
SWING_OFF,
@ -23,12 +21,12 @@ from homeassistant.components.climate import (
HVACAction,
HVACMode,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_TEMPERATURE, UnitOfTemperature
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .const import DATA_BROKERS, DOMAIN
from . import FullDevice, SmartThingsConfigEntry
from .const import MAIN
from .entity import SmartThingsEntity
ATTR_OPERATION_STATE = "operation_state"
@ -97,124 +95,106 @@ UNIT_MAP = {"C": UnitOfTemperature.CELSIUS, "F": UnitOfTemperature.FAHRENHEIT}
_LOGGER = logging.getLogger(__name__)
AC_CAPABILITIES = [
Capability.AIR_CONDITIONER_MODE,
Capability.AIR_CONDITIONER_FAN_MODE,
Capability.SWITCH,
Capability.TEMPERATURE_MEASUREMENT,
Capability.THERMOSTAT_COOLING_SETPOINT,
]
THERMOSTAT_CAPABILITIES = [
Capability.TEMPERATURE_MEASUREMENT,
Capability.THERMOSTAT_HEATING_SETPOINT,
Capability.THERMOSTAT_MODE,
]
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
entry: SmartThingsConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Add climate entities for a config entry."""
ac_capabilities = [
Capability.air_conditioner_mode,
Capability.air_conditioner_fan_mode,
Capability.switch,
Capability.temperature_measurement,
Capability.thermostat_cooling_setpoint,
entry_data = entry.runtime_data
entities: list[ClimateEntity] = [
SmartThingsAirConditioner(entry_data.client, device)
for device in entry_data.devices.values()
if all(capability in device.status[MAIN] for capability in AC_CAPABILITIES)
]
broker = hass.data[DOMAIN][DATA_BROKERS][config_entry.entry_id]
entities: list[ClimateEntity] = []
for device in broker.devices.values():
if not broker.any_assigned(device.device_id, CLIMATE_DOMAIN):
continue
if all(capability in device.capabilities for capability in ac_capabilities):
entities.append(SmartThingsAirConditioner(device))
else:
entities.append(SmartThingsThermostat(device))
async_add_entities(entities, True)
def get_capabilities(capabilities: Sequence[str]) -> Sequence[str] | None:
"""Return all capabilities supported if minimum required are present."""
supported = [
Capability.air_conditioner_mode,
Capability.demand_response_load_control,
Capability.air_conditioner_fan_mode,
Capability.switch,
Capability.thermostat,
Capability.thermostat_cooling_setpoint,
Capability.thermostat_fan_mode,
Capability.thermostat_heating_setpoint,
Capability.thermostat_mode,
Capability.thermostat_operating_state,
]
# Can have this legacy/deprecated capability
if Capability.thermostat in capabilities:
return supported
# Or must have all of these thermostat capabilities
thermostat_capabilities = [
Capability.temperature_measurement,
Capability.thermostat_heating_setpoint,
Capability.thermostat_mode,
]
if all(capability in capabilities for capability in thermostat_capabilities):
return supported
# Or must have all of these A/C capabilities
ac_capabilities = [
Capability.air_conditioner_mode,
Capability.air_conditioner_fan_mode,
Capability.switch,
Capability.temperature_measurement,
Capability.thermostat_cooling_setpoint,
]
if all(capability in capabilities for capability in ac_capabilities):
return supported
return None
entities.extend(
SmartThingsThermostat(entry_data.client, device)
for device in entry_data.devices.values()
if all(
capability in device.status[MAIN] for capability in THERMOSTAT_CAPABILITIES
)
)
async_add_entities(entities)
class SmartThingsThermostat(SmartThingsEntity, ClimateEntity):
"""Define a SmartThings climate entities."""
def __init__(self, device):
def __init__(self, client: SmartThings, device: FullDevice) -> None:
"""Init the class."""
super().__init__(device)
super().__init__(
client,
device,
{
Capability.THERMOSTAT_FAN_MODE,
Capability.THERMOSTAT_MODE,
Capability.TEMPERATURE_MEASUREMENT,
Capability.THERMOSTAT_HEATING_SETPOINT,
Capability.THERMOSTAT_OPERATING_STATE,
Capability.THERMOSTAT_COOLING_SETPOINT,
Capability.RELATIVE_HUMIDITY_MEASUREMENT,
},
)
self._attr_supported_features = self._determine_features()
self._hvac_mode = None
self._hvac_modes = None
def _determine_features(self):
def _determine_features(self) -> ClimateEntityFeature:
flags = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
if self._device.get_capability(
Capability.thermostat_fan_mode, Capability.thermostat
if self.get_attribute_value(
Capability.THERMOSTAT_FAN_MODE, Attribute.THERMOSTAT_FAN_MODE
):
flags |= ClimateEntityFeature.FAN_MODE
return flags
async def async_set_fan_mode(self, fan_mode: str) -> None:
"""Set new target fan mode."""
await self._device.set_thermostat_fan_mode(fan_mode, set_status=True)
# State is set optimistically in the command above, therefore update
# the entity state ahead of receiving the confirming push updates
self.async_schedule_update_ha_state(True)
await self.execute_device_command(
Capability.THERMOSTAT_FAN_MODE,
Command.SET_THERMOSTAT_FAN_MODE,
argument=fan_mode,
)
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
"""Set new target operation mode."""
mode = STATE_TO_MODE[hvac_mode]
await self._device.set_thermostat_mode(mode, set_status=True)
# State is set optimistically in the command above, therefore update
# the entity state ahead of receiving the confirming push updates
self.async_schedule_update_ha_state(True)
await self.execute_device_command(
Capability.THERMOSTAT_MODE,
Command.SET_THERMOSTAT_MODE,
argument=STATE_TO_MODE[hvac_mode],
)
async def async_set_temperature(self, **kwargs: Any) -> None:
"""Set new operation mode and target temperatures."""
hvac_mode = self.hvac_mode
# Operation state
if operation_state := kwargs.get(ATTR_HVAC_MODE):
mode = STATE_TO_MODE[operation_state]
await self._device.set_thermostat_mode(mode, set_status=True)
await self.async_update()
await self.async_set_hvac_mode(operation_state)
hvac_mode = operation_state
# Heat/cool setpoint
heating_setpoint = None
cooling_setpoint = None
if self.hvac_mode == HVACMode.HEAT:
if hvac_mode == HVACMode.HEAT:
heating_setpoint = kwargs.get(ATTR_TEMPERATURE)
elif self.hvac_mode == HVACMode.COOL:
elif hvac_mode == HVACMode.COOL:
cooling_setpoint = kwargs.get(ATTR_TEMPERATURE)
else:
heating_setpoint = kwargs.get(ATTR_TARGET_TEMP_LOW)
@ -222,135 +202,145 @@ class SmartThingsThermostat(SmartThingsEntity, ClimateEntity):
tasks = []
if heating_setpoint is not None:
tasks.append(
self._device.set_heating_setpoint(
round(heating_setpoint, 3), set_status=True
self.execute_device_command(
Capability.THERMOSTAT_HEATING_SETPOINT,
Command.SET_HEATING_SETPOINT,
argument=round(heating_setpoint, 3),
)
)
if cooling_setpoint is not None:
tasks.append(
self._device.set_cooling_setpoint(
round(cooling_setpoint, 3), set_status=True
self.execute_device_command(
Capability.THERMOSTAT_COOLING_SETPOINT,
Command.SET_COOLING_SETPOINT,
argument=round(cooling_setpoint, 3),
)
)
await asyncio.gather(*tasks)
# State is set optimistically in the commands above, therefore update
# the entity state ahead of receiving the confirming push updates
self.async_schedule_update_ha_state(True)
async def async_update(self) -> None:
"""Update the attributes of the climate device."""
thermostat_mode = self._device.status.thermostat_mode
self._hvac_mode = MODE_TO_STATE.get(thermostat_mode)
if self._hvac_mode is None:
_LOGGER.debug(
"Device %s (%s) returned an invalid hvac mode: %s",
self._device.label,
self._device.device_id,
thermostat_mode,
)
modes = set()
supported_modes = self._device.status.supported_thermostat_modes
if isinstance(supported_modes, Iterable):
for mode in supported_modes:
if (state := MODE_TO_STATE.get(mode)) is not None:
modes.add(state)
else:
_LOGGER.debug(
(
"Device %s (%s) returned an invalid supported thermostat"
" mode: %s"
),
self._device.label,
self._device.device_id,
mode,
)
else:
_LOGGER.debug(
"Device %s (%s) returned invalid supported thermostat modes: %s",
self._device.label,
self._device.device_id,
supported_modes,
)
self._hvac_modes = list(modes)
@property
def current_humidity(self):
def current_humidity(self) -> float | None:
"""Return the current humidity."""
return self._device.status.humidity
if self.supports_capability(Capability.RELATIVE_HUMIDITY_MEASUREMENT):
return self.get_attribute_value(
Capability.RELATIVE_HUMIDITY_MEASUREMENT, Attribute.HUMIDITY
)
return None
@property
def current_temperature(self):
def current_temperature(self) -> float | None:
"""Return the current temperature."""
return self._device.status.temperature
return self.get_attribute_value(
Capability.TEMPERATURE_MEASUREMENT, Attribute.TEMPERATURE
)
@property
def fan_mode(self):
def fan_mode(self) -> str | None:
"""Return the fan setting."""
return self._device.status.thermostat_fan_mode
return self.get_attribute_value(
Capability.THERMOSTAT_FAN_MODE, Attribute.THERMOSTAT_FAN_MODE
)
@property
def fan_modes(self):
def fan_modes(self) -> list[str]:
"""Return the list of available fan modes."""
return self._device.status.supported_thermostat_fan_modes
return self.get_attribute_value(
Capability.THERMOSTAT_FAN_MODE, Attribute.SUPPORTED_THERMOSTAT_FAN_MODES
)
@property
def hvac_action(self) -> HVACAction | None:
"""Return the current running hvac operation if supported."""
return OPERATING_STATE_TO_ACTION.get(
self._device.status.thermostat_operating_state
self.get_attribute_value(
Capability.THERMOSTAT_OPERATING_STATE,
Attribute.THERMOSTAT_OPERATING_STATE,
)
)
@property
def hvac_mode(self) -> HVACMode:
def hvac_mode(self) -> HVACMode | None:
"""Return current operation ie. heat, cool, idle."""
return self._hvac_mode
return MODE_TO_STATE.get(
self.get_attribute_value(
Capability.THERMOSTAT_MODE, Attribute.THERMOSTAT_MODE
)
)
@property
def hvac_modes(self) -> list[HVACMode]:
"""Return the list of available operation modes."""
return self._hvac_modes
return [
state
for mode in self.get_attribute_value(
Capability.THERMOSTAT_MODE, Attribute.SUPPORTED_THERMOSTAT_MODES
)
if (state := AC_MODE_TO_STATE.get(mode)) is not None
]
@property
def target_temperature(self):
def target_temperature(self) -> float | None:
"""Return the temperature we try to reach."""
if self.hvac_mode == HVACMode.COOL:
return self._device.status.cooling_setpoint
return self.get_attribute_value(
Capability.THERMOSTAT_COOLING_SETPOINT, Attribute.COOLING_SETPOINT
)
if self.hvac_mode == HVACMode.HEAT:
return self._device.status.heating_setpoint
return self.get_attribute_value(
Capability.THERMOSTAT_HEATING_SETPOINT, Attribute.HEATING_SETPOINT
)
return None
@property
def target_temperature_high(self):
def target_temperature_high(self) -> float | None:
"""Return the highbound target temperature we try to reach."""
if self.hvac_mode == HVACMode.HEAT_COOL:
return self._device.status.cooling_setpoint
return self.get_attribute_value(
Capability.THERMOSTAT_COOLING_SETPOINT, Attribute.COOLING_SETPOINT
)
return None
@property
def target_temperature_low(self):
"""Return the lowbound target temperature we try to reach."""
if self.hvac_mode == HVACMode.HEAT_COOL:
return self._device.status.heating_setpoint
return self.get_attribute_value(
Capability.THERMOSTAT_HEATING_SETPOINT, Attribute.HEATING_SETPOINT
)
return None
@property
def temperature_unit(self):
def temperature_unit(self) -> str:
"""Return the unit of measurement."""
return UNIT_MAP.get(self._device.status.attributes[Attribute.temperature].unit)
unit = self._internal_state[Capability.TEMPERATURE_MEASUREMENT][
Attribute.TEMPERATURE
].unit
assert unit
return UNIT_MAP[unit]
class SmartThingsAirConditioner(SmartThingsEntity, ClimateEntity):
"""Define a SmartThings Air Conditioner."""
_hvac_modes: list[HVACMode]
_attr_preset_mode = None
def __init__(self, device) -> None:
def __init__(self, client: SmartThings, device: FullDevice) -> None:
"""Init the class."""
super().__init__(device)
self._hvac_modes = []
self._attr_preset_mode = None
super().__init__(
client,
device,
{
Capability.AIR_CONDITIONER_MODE,
Capability.SWITCH,
Capability.FAN_OSCILLATION_MODE,
Capability.AIR_CONDITIONER_FAN_MODE,
Capability.THERMOSTAT_COOLING_SETPOINT,
Capability.TEMPERATURE_MEASUREMENT,
Capability.CUSTOM_AIR_CONDITIONER_OPTIONAL_MODE,
Capability.DEMAND_RESPONSE_LOAD_CONTROL,
},
)
self._attr_hvac_modes = self._determine_hvac_modes()
self._attr_preset_modes = self._determine_preset_modes()
self._attr_swing_modes = self._determine_swing_modes()
self._attr_supported_features = self._determine_supported_features()
@ -362,7 +352,7 @@ class SmartThingsAirConditioner(SmartThingsEntity, ClimateEntity):
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
if self._device.get_capability(Capability.fan_oscillation_mode):
if self.supports_capability(Capability.FAN_OSCILLATION_MODE):
features |= ClimateEntityFeature.SWING_MODE
if (self._attr_preset_modes is not None) and len(self._attr_preset_modes) > 0:
features |= ClimateEntityFeature.PRESET_MODE
@ -370,14 +360,11 @@ class SmartThingsAirConditioner(SmartThingsEntity, ClimateEntity):
async def async_set_fan_mode(self, fan_mode: str) -> None:
"""Set new target fan mode."""
await self._device.set_fan_mode(fan_mode, set_status=True)
# setting the fan must reset the preset mode (it deactivates the windFree function)
self._attr_preset_mode = None
# State is set optimistically in the command above, therefore update
# the entity state ahead of receiving the confirming push updates
self.async_write_ha_state()
await self.execute_device_command(
Capability.AIR_CONDITIONER_FAN_MODE,
Command.SET_FAN_MODE,
argument=fan_mode,
)
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
"""Set new target operation mode."""
@ -386,23 +373,27 @@ class SmartThingsAirConditioner(SmartThingsEntity, ClimateEntity):
return
tasks = []
# Turn on the device if it's off before setting mode.
if not self._device.status.switch:
tasks.append(self._device.switch_on(set_status=True))
if self.get_attribute_value(Capability.SWITCH, Attribute.SWITCH) == "off":
tasks.append(self.async_turn_on())
mode = STATE_TO_AC_MODE[hvac_mode]
# If new hvac_mode is HVAC_MODE_FAN_ONLY and AirConditioner support "wind" mode the AirConditioner new mode has to be "wind"
# The conversion make the mode change working
# The conversion is made only for device that wrongly has capability "wind" instead "fan_only"
if hvac_mode == HVACMode.FAN_ONLY:
supported_modes = self._device.status.supported_ac_modes
if WIND in supported_modes:
if WIND in self.get_attribute_value(
Capability.AIR_CONDITIONER_MODE, Attribute.SUPPORTED_AC_MODES
):
mode = WIND
tasks.append(self._device.set_air_conditioner_mode(mode, set_status=True))
tasks.append(
self.execute_device_command(
Capability.AIR_CONDITIONER_MODE,
Command.SET_AIR_CONDITIONER_MODE,
argument=mode,
)
)
await asyncio.gather(*tasks)
# State is set optimistically in the command above, therefore update
# the entity state ahead of receiving the confirming push updates
self.async_write_ha_state()
async def async_set_temperature(self, **kwargs: Any) -> None:
"""Set new target temperature."""
@ -410,53 +401,44 @@ class SmartThingsAirConditioner(SmartThingsEntity, ClimateEntity):
# operation mode
if operation_mode := kwargs.get(ATTR_HVAC_MODE):
if operation_mode == HVACMode.OFF:
tasks.append(self._device.switch_off(set_status=True))
tasks.append(self.async_turn_off())
else:
if not self._device.status.switch:
tasks.append(self._device.switch_on(set_status=True))
if (
self.get_attribute_value(Capability.SWITCH, Attribute.SWITCH)
== "off"
):
tasks.append(self.async_turn_on())
tasks.append(self.async_set_hvac_mode(operation_mode))
# temperature
tasks.append(
self._device.set_cooling_setpoint(kwargs[ATTR_TEMPERATURE], set_status=True)
self.execute_device_command(
Capability.THERMOSTAT_COOLING_SETPOINT,
Command.SET_COOLING_SETPOINT,
argument=kwargs[ATTR_TEMPERATURE],
)
)
await asyncio.gather(*tasks)
# State is set optimistically in the command above, therefore update
# the entity state ahead of receiving the confirming push updates
self.async_write_ha_state()
async def async_turn_on(self) -> None:
"""Turn device on."""
await self._device.switch_on(set_status=True)
# State is set optimistically in the command above, therefore update
# the entity state ahead of receiving the confirming push updates
self.async_write_ha_state()
await self.execute_device_command(
Capability.SWITCH,
Command.ON,
)
async def async_turn_off(self) -> None:
"""Turn device off."""
await self._device.switch_off(set_status=True)
# State is set optimistically in the command above, therefore update
# the entity state ahead of receiving the confirming push updates
self.async_write_ha_state()
async def async_update(self) -> None:
"""Update the calculated fields of the AC."""
modes = {HVACMode.OFF}
for mode in self._device.status.supported_ac_modes:
if (state := AC_MODE_TO_STATE.get(mode)) is not None:
modes.add(state)
else:
_LOGGER.debug(
"Device %s (%s) returned an invalid supported AC mode: %s",
self._device.label,
self._device.device_id,
mode,
)
self._hvac_modes = list(modes)
await self.execute_device_command(
Capability.SWITCH,
Command.OFF,
)
@property
def current_temperature(self) -> float | None:
"""Return the current temperature."""
return self._device.status.temperature
return self.get_attribute_value(
Capability.TEMPERATURE_MEASUREMENT, Attribute.TEMPERATURE
)
@property
def extra_state_attributes(self) -> dict[str, Any]:
@ -465,100 +447,114 @@ class SmartThingsAirConditioner(SmartThingsEntity, ClimateEntity):
Include attributes from the Demand Response Load Control (drlc)
and Power Consumption capabilities.
"""
attributes = [
"drlc_status_duration",
"drlc_status_level",
"drlc_status_start",
"drlc_status_override",
]
state_attributes = {}
for attribute in attributes:
value = getattr(self._device.status, attribute)
if value is not None:
state_attributes[attribute] = value
return state_attributes
drlc_status = self.get_attribute_value(
Capability.DEMAND_RESPONSE_LOAD_CONTROL,
Attribute.DEMAND_RESPONSE_LOAD_CONTROL_STATUS,
)
return {
"drlc_status_duration": drlc_status["duration"],
"drlc_status_level": drlc_status["drlcLevel"],
"drlc_status_start": drlc_status["start"],
"drlc_status_override": drlc_status["override"],
}
@property
def fan_mode(self) -> str:
"""Return the fan setting."""
return self._device.status.fan_mode
return self.get_attribute_value(
Capability.AIR_CONDITIONER_FAN_MODE, Attribute.FAN_MODE
)
@property
def fan_modes(self) -> list[str]:
"""Return the list of available fan modes."""
return self._device.status.supported_ac_fan_modes
return self.get_attribute_value(
Capability.AIR_CONDITIONER_FAN_MODE, Attribute.SUPPORTED_AC_FAN_MODES
)
@property
def hvac_mode(self) -> HVACMode | None:
"""Return current operation ie. heat, cool, idle."""
if not self._device.status.switch:
if self.get_attribute_value(Capability.SWITCH, Attribute.SWITCH) == "off":
return HVACMode.OFF
return AC_MODE_TO_STATE.get(self._device.status.air_conditioner_mode)
@property
def hvac_modes(self) -> list[HVACMode]:
"""Return the list of available operation modes."""
return self._hvac_modes
return AC_MODE_TO_STATE.get(
self.get_attribute_value(
Capability.AIR_CONDITIONER_MODE, Attribute.AIR_CONDITIONER_MODE
)
)
@property
def target_temperature(self) -> float:
"""Return the temperature we try to reach."""
return self._device.status.cooling_setpoint
return self.get_attribute_value(
Capability.THERMOSTAT_COOLING_SETPOINT, Attribute.COOLING_SETPOINT
)
@property
def temperature_unit(self) -> str:
"""Return the unit of measurement."""
return UNIT_MAP[self._device.status.attributes[Attribute.temperature].unit]
unit = self._internal_state[Capability.TEMPERATURE_MEASUREMENT][
Attribute.TEMPERATURE
].unit
assert unit
return UNIT_MAP[unit]
def _determine_swing_modes(self) -> list[str] | None:
"""Return the list of available swing modes."""
supported_swings = None
supported_modes = self._device.status.attributes[
Attribute.supported_fan_oscillation_modes
][0]
if supported_modes is not None:
supported_swings = [
FAN_OSCILLATION_TO_SWING.get(m, SWING_OFF) for m in supported_modes
]
return supported_swings
if (
supported_modes := self.get_attribute_value(
Capability.FAN_OSCILLATION_MODE,
Attribute.SUPPORTED_FAN_OSCILLATION_MODES,
)
) is None:
return None
return [FAN_OSCILLATION_TO_SWING.get(m, SWING_OFF) for m in supported_modes]
async def async_set_swing_mode(self, swing_mode: str) -> None:
"""Set swing mode."""
fan_oscillation_mode = SWING_TO_FAN_OSCILLATION[swing_mode]
await self._device.set_fan_oscillation_mode(fan_oscillation_mode)
# setting the fan must reset the preset mode (it deactivates the windFree function)
self._attr_preset_mode = None
self.async_schedule_update_ha_state(True)
await self.execute_device_command(
Capability.FAN_OSCILLATION_MODE,
Command.SET_FAN_OSCILLATION_MODE,
argument=SWING_TO_FAN_OSCILLATION[swing_mode],
)
@property
def swing_mode(self) -> str:
"""Return the swing setting."""
return FAN_OSCILLATION_TO_SWING.get(
self._device.status.fan_oscillation_mode, SWING_OFF
self.get_attribute_value(
Capability.FAN_OSCILLATION_MODE, Attribute.FAN_OSCILLATION_MODE
),
SWING_OFF,
)
def _determine_preset_modes(self) -> list[str] | None:
"""Return a list of available preset modes."""
supported_modes: list | None = self._device.status.attributes[
"supportedAcOptionalMode"
].value
if supported_modes and WINDFREE in supported_modes:
return [WINDFREE]
if self.supports_capability(Capability.CUSTOM_AIR_CONDITIONER_OPTIONAL_MODE):
supported_modes = self.get_attribute_value(
Capability.CUSTOM_AIR_CONDITIONER_OPTIONAL_MODE,
Attribute.SUPPORTED_AC_OPTIONAL_MODE,
)
if supported_modes and WINDFREE in supported_modes:
return [WINDFREE]
return None
async def async_set_preset_mode(self, preset_mode: str) -> None:
"""Set special modes (currently only windFree is supported)."""
result = await self._device.command(
"main",
"custom.airConditionerOptionalMode",
"setAcOptionalMode",
[preset_mode],
await self.execute_device_command(
Capability.CUSTOM_AIR_CONDITIONER_OPTIONAL_MODE,
Command.SET_AC_OPTIONAL_MODE,
argument=preset_mode,
)
if result:
self._device.status.update_attribute_value("acOptionalMode", preset_mode)
self._attr_preset_mode = preset_mode
self.async_write_ha_state()
def _determine_hvac_modes(self) -> list[HVACMode]:
"""Determine the supported HVAC modes."""
modes = [HVACMode.OFF]
modes.extend(
state
for mode in self.get_attribute_value(
Capability.AIR_CONDITIONER_MODE, Attribute.SUPPORTED_AC_MODES
)
if (state := AC_MODE_TO_STATE.get(mode)) is not None
)
return modes

View File

@ -1,298 +1,83 @@
"""Config flow to configure SmartThings."""
from collections.abc import Mapping
from http import HTTPStatus
import logging
from typing import Any
from aiohttp import ClientResponseError
from pysmartthings import APIResponseError, AppOAuth, SmartThings
from pysmartthings.installedapp import format_install_url
import voluptuous as vol
from pysmartthings import SmartThings
from homeassistant.config_entries import SOURCE_REAUTH, ConfigFlow, ConfigFlowResult
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_CLIENT_ID, CONF_CLIENT_SECRET
from homeassistant.config_entries import SOURCE_REAUTH, ConfigFlowResult
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_TOKEN
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.config_entry_oauth2_flow import AbstractOAuth2FlowHandler
from .const import (
APP_OAUTH_CLIENT_NAME,
APP_OAUTH_SCOPES,
CONF_APP_ID,
CONF_INSTALLED_APP_ID,
CONF_LOCATION_ID,
CONF_REFRESH_TOKEN,
DOMAIN,
VAL_UID_MATCHER,
)
from .smartapp import (
create_app,
find_app,
format_unique_id,
get_webhook_url,
setup_smartapp,
setup_smartapp_endpoint,
update_app,
validate_webhook_requirements,
)
from .const import CONF_LOCATION_ID, DOMAIN, OLD_DATA, SCOPES
_LOGGER = logging.getLogger(__name__)
class SmartThingsFlowHandler(ConfigFlow, domain=DOMAIN):
class SmartThingsConfigFlow(AbstractOAuth2FlowHandler, domain=DOMAIN):
"""Handle configuration of SmartThings integrations."""
VERSION = 2
VERSION = 3
DOMAIN = DOMAIN
api: SmartThings
app_id: str
location_id: str
@property
def logger(self) -> logging.Logger:
"""Return logger."""
return logging.getLogger(__name__)
def __init__(self) -> None:
"""Create a new instance of the flow handler."""
self.access_token: str | None = None
self.oauth_client_secret = None
self.oauth_client_id = None
self.installed_app_id = None
self.refresh_token = None
self.endpoints_initialized = False
@property
def extra_authorize_data(self) -> dict[str, Any]:
"""Extra data that needs to be appended to the authorize url."""
return {"scope": " ".join(SCOPES)}
async def async_step_import(self, import_data: None) -> ConfigFlowResult:
"""Occurs when a previously entry setup fails and is re-initiated."""
return await self.async_step_user(import_data)
async def async_oauth_create_entry(self, data: dict[str, Any]) -> ConfigFlowResult:
"""Create an entry for SmartThings."""
client = SmartThings(session=async_get_clientsession(self.hass))
client.authenticate(data[CONF_TOKEN][CONF_ACCESS_TOKEN])
locations = await client.get_locations()
location = locations[0]
# We pick to use the location id as unique id rather than the installed app id
# as the installed app id could change with the right settings in the SmartApp
# or the app used to sign in changed for any reason.
await self.async_set_unique_id(location.location_id)
if self.source != SOURCE_REAUTH:
self._abort_if_unique_id_configured()
async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Validate and confirm webhook setup."""
if not self.endpoints_initialized:
self.endpoints_initialized = True
await setup_smartapp_endpoint(
self.hass, len(self._async_current_entries()) == 0
return self.async_create_entry(
title=location.name,
data={**data, CONF_LOCATION_ID: location.location_id},
)
webhook_url = get_webhook_url(self.hass)
# Abort if the webhook is invalid
if not validate_webhook_requirements(self.hass):
return self.async_abort(
reason="invalid_webhook_url",
description_placeholders={
"webhook_url": webhook_url,
"component_url": (
"https://www.home-assistant.io/integrations/smartthings/"
),
if (entry := self._get_reauth_entry()) and CONF_TOKEN not in entry.data:
if entry.data[OLD_DATA][CONF_LOCATION_ID] != location.location_id:
return self.async_abort(reason="reauth_location_mismatch")
return self.async_update_reload_and_abort(
self._get_reauth_entry(),
data_updates={
**data,
CONF_LOCATION_ID: location.location_id,
},
unique_id=location.location_id,
)
# Show the confirmation
if user_input is None:
return self.async_show_form(
step_id="user",
description_placeholders={"webhook_url": webhook_url},
)
# Show the next screen
return await self.async_step_pat()
async def async_step_pat(
self, user_input: dict[str, str] | None = None
) -> ConfigFlowResult:
"""Get the Personal Access Token and validate it."""
errors: dict[str, str] = {}
if user_input is None or CONF_ACCESS_TOKEN not in user_input:
return self._show_step_pat(errors)
self.access_token = user_input[CONF_ACCESS_TOKEN]
# Ensure token is a UUID
if not VAL_UID_MATCHER.match(self.access_token):
errors[CONF_ACCESS_TOKEN] = "token_invalid_format"
return self._show_step_pat(errors)
# Setup end-point
self.api = SmartThings(async_get_clientsession(self.hass), self.access_token)
try:
app = await find_app(self.hass, self.api)
if app:
await app.refresh() # load all attributes
await update_app(self.hass, app)
# Find an existing entry to copy the oauth client
existing = next(
(
entry
for entry in self._async_current_entries()
if entry.data[CONF_APP_ID] == app.app_id
),
None,
)
if existing:
self.oauth_client_id = existing.data[CONF_CLIENT_ID]
self.oauth_client_secret = existing.data[CONF_CLIENT_SECRET]
else:
# Get oauth client id/secret by regenerating it
app_oauth = AppOAuth(app.app_id)
app_oauth.client_name = APP_OAUTH_CLIENT_NAME
app_oauth.scope.extend(APP_OAUTH_SCOPES)
client = await self.api.generate_app_oauth(app_oauth)
self.oauth_client_secret = client.client_secret
self.oauth_client_id = client.client_id
else:
app, client = await create_app(self.hass, self.api)
self.oauth_client_secret = client.client_secret
self.oauth_client_id = client.client_id
setup_smartapp(self.hass, app)
self.app_id = app.app_id
except APIResponseError as ex:
if ex.is_target_error():
errors["base"] = "webhook_error"
else:
errors["base"] = "app_setup_error"
_LOGGER.exception(
"API error setting up the SmartApp: %s", ex.raw_error_response
)
return self._show_step_pat(errors)
except ClientResponseError as ex:
if ex.status == HTTPStatus.UNAUTHORIZED:
errors[CONF_ACCESS_TOKEN] = "token_unauthorized"
_LOGGER.debug(
"Unauthorized error received setting up SmartApp", exc_info=True
)
elif ex.status == HTTPStatus.FORBIDDEN:
errors[CONF_ACCESS_TOKEN] = "token_forbidden"
_LOGGER.debug(
"Forbidden error received setting up SmartApp", exc_info=True
)
else:
errors["base"] = "app_setup_error"
_LOGGER.exception("Unexpected error setting up the SmartApp")
return self._show_step_pat(errors)
except Exception:
errors["base"] = "app_setup_error"
_LOGGER.exception("Unexpected error setting up the SmartApp")
return self._show_step_pat(errors)
return await self.async_step_select_location()
async def async_step_select_location(
self, user_input: dict[str, str] | None = None
) -> ConfigFlowResult:
"""Ask user to select the location to setup."""
if user_input is None or CONF_LOCATION_ID not in user_input:
# Get available locations
existing_locations = [
entry.data[CONF_LOCATION_ID] for entry in self._async_current_entries()
]
locations = await self.api.locations()
locations_options = {
location.location_id: location.name
for location in locations
if location.location_id not in existing_locations
}
if not locations_options:
return self.async_abort(reason="no_available_locations")
return self.async_show_form(
step_id="select_location",
data_schema=vol.Schema(
{vol.Required(CONF_LOCATION_ID): vol.In(locations_options)}
),
)
self.location_id = user_input[CONF_LOCATION_ID]
await self.async_set_unique_id(format_unique_id(self.app_id, self.location_id))
return await self.async_step_authorize()
async def async_step_authorize(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Wait for the user to authorize the app installation."""
user_input = {} if user_input is None else user_input
self.installed_app_id = user_input.get(CONF_INSTALLED_APP_ID)
self.refresh_token = user_input.get(CONF_REFRESH_TOKEN)
if self.installed_app_id is None:
# Launch the external setup URL
url = format_install_url(self.app_id, self.location_id)
return self.async_external_step(step_id="authorize", url=url)
next_step_id = "install"
if self.source == SOURCE_REAUTH:
next_step_id = "update"
return self.async_external_step_done(next_step_id=next_step_id)
def _show_step_pat(self, errors):
if self.access_token is None:
# Get the token from an existing entry to make it easier to setup multiple locations.
self.access_token = next(
(
entry.data.get(CONF_ACCESS_TOKEN)
for entry in self._async_current_entries()
),
None,
)
return self.async_show_form(
step_id="pat",
data_schema=vol.Schema(
{vol.Required(CONF_ACCESS_TOKEN, default=self.access_token): str}
),
errors=errors,
description_placeholders={
"token_url": "https://account.smartthings.com/tokens",
"component_url": (
"https://www.home-assistant.io/integrations/smartthings/"
),
},
self._abort_if_unique_id_mismatch(reason="reauth_account_mismatch")
return self.async_update_reload_and_abort(
self._get_reauth_entry(), data_updates=data
)
async def async_step_reauth(
self, entry_data: Mapping[str, Any]
) -> ConfigFlowResult:
"""Handle re-authentication of an existing config entry."""
"""Perform reauth upon migration of old entries."""
return await self.async_step_reauth_confirm()
async def async_step_reauth_confirm(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle re-authentication of an existing config entry."""
"""Confirm reauth dialog."""
if user_input is None:
return self.async_show_form(step_id="reauth_confirm")
self.app_id = self._get_reauth_entry().data[CONF_APP_ID]
self.location_id = self._get_reauth_entry().data[CONF_LOCATION_ID]
self._set_confirm_only()
return await self.async_step_authorize()
async def async_step_update(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle re-authentication of an existing config entry."""
return await self.async_step_update_confirm()
async def async_step_update_confirm(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle re-authentication of an existing config entry."""
if user_input is None:
self._set_confirm_only()
return self.async_show_form(step_id="update_confirm")
entry = self._get_reauth_entry()
return self.async_update_reload_and_abort(
entry, data_updates={CONF_REFRESH_TOKEN: self.refresh_token}
)
async def async_step_install(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Create a config entry at completion of a flow and authorization of the app."""
data = {
CONF_ACCESS_TOKEN: self.access_token,
CONF_REFRESH_TOKEN: self.refresh_token,
CONF_CLIENT_ID: self.oauth_client_id,
CONF_CLIENT_SECRET: self.oauth_client_secret,
CONF_LOCATION_ID: self.location_id,
CONF_APP_ID: self.app_id,
CONF_INSTALLED_APP_ID: self.installed_app_id,
}
location = await self.api.location(data[CONF_LOCATION_ID])
return self.async_create_entry(title=location.name, data=data)
return self.async_show_form(
step_id="reauth_confirm",
)
return await self.async_step_user()

View File

@ -1,15 +1,23 @@
"""Constants used by the SmartThings component and platforms."""
from datetime import timedelta
import re
from homeassistant.const import Platform
DOMAIN = "smartthings"
APP_OAUTH_CLIENT_NAME = "Home Assistant"
APP_OAUTH_SCOPES = ["r:devices:*"]
APP_NAME_PREFIX = "homeassistant."
SCOPES = [
"r:devices:*",
"w:devices:*",
"x:devices:*",
"r:hubs:*",
"r:locations:*",
"w:locations:*",
"x:locations:*",
"r:scenes:*",
"x:scenes:*",
"r:rules:*",
"w:rules:*",
"r:installedapps",
"w:installedapps",
"sse",
]
CONF_APP_ID = "app_id"
CONF_CLOUDHOOK_URL = "cloudhook_url"
@ -18,41 +26,5 @@ CONF_INSTANCE_ID = "instance_id"
CONF_LOCATION_ID = "location_id"
CONF_REFRESH_TOKEN = "refresh_token"
DATA_MANAGER = "manager"
DATA_BROKERS = "brokers"
EVENT_BUTTON = "smartthings.button"
SIGNAL_SMARTTHINGS_UPDATE = "smartthings_update"
SIGNAL_SMARTAPP_PREFIX = "smartthings_smartap_"
SETTINGS_INSTANCE_ID = "hassInstanceId"
SUBSCRIPTION_WARNING_LIMIT = 40
STORAGE_KEY = DOMAIN
STORAGE_VERSION = 1
# Ordered 'specific to least-specific platform' in order for capabilities
# to be drawn-down and represented by the most appropriate platform.
PLATFORMS = [
Platform.BINARY_SENSOR,
Platform.CLIMATE,
Platform.COVER,
Platform.FAN,
Platform.LIGHT,
Platform.LOCK,
Platform.SCENE,
Platform.SENSOR,
Platform.SWITCH,
]
IGNORED_CAPABILITIES = [
"execute",
"healthCheck",
"ocf",
]
TOKEN_REFRESH_INTERVAL = timedelta(days=14)
VAL_UID = "^(?:([0-9a-fA-F]{32})|([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}))$"
VAL_UID_MATCHER = re.compile(VAL_UID)
MAIN = "main"
OLD_DATA = "old_data"

View File

@ -2,25 +2,23 @@
from __future__ import annotations
from collections.abc import Sequence
from typing import Any
from pysmartthings import Attribute, Capability
from pysmartthings import Attribute, Capability, Command, SmartThings
from homeassistant.components.cover import (
ATTR_POSITION,
DOMAIN as COVER_DOMAIN,
CoverDeviceClass,
CoverEntity,
CoverEntityFeature,
CoverState,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_BATTERY_LEVEL
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .const import DATA_BROKERS, DOMAIN
from . import FullDevice, SmartThingsConfigEntry
from .const import MAIN
from .entity import SmartThingsEntity
VALUE_TO_STATE = {
@ -32,114 +30,99 @@ VALUE_TO_STATE = {
"unknown": None,
}
CAPABILITIES = (Capability.WINDOW_SHADE, Capability.DOOR_CONTROL)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
entry: SmartThingsConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Add covers for a config entry."""
broker = hass.data[DOMAIN][DATA_BROKERS][config_entry.entry_id]
entry_data = entry.runtime_data
async_add_entities(
[
SmartThingsCover(device)
for device in broker.devices.values()
if broker.any_assigned(device.device_id, COVER_DOMAIN)
],
True,
SmartThingsCover(entry_data.client, device, capability)
for device in entry_data.devices.values()
for capability in device.status[MAIN]
if capability in CAPABILITIES
)
def get_capabilities(capabilities: Sequence[str]) -> Sequence[str] | None:
"""Return all capabilities supported if minimum required are present."""
min_required = [
Capability.door_control,
Capability.garage_door_control,
Capability.window_shade,
]
# Must have one of the min_required
if any(capability in capabilities for capability in min_required):
# Return all capabilities supported/consumed
return [
*min_required,
Capability.battery,
Capability.switch_level,
Capability.window_shade_level,
]
return None
class SmartThingsCover(SmartThingsEntity, CoverEntity):
"""Define a SmartThings cover."""
def __init__(self, device):
_state: CoverState | None = None
def __init__(
self, client: SmartThings, device: FullDevice, capability: Capability
) -> None:
"""Initialize the cover class."""
super().__init__(device)
self._current_cover_position = None
self._state = None
super().__init__(
client,
device,
{
capability,
Capability.BATTERY,
Capability.WINDOW_SHADE_LEVEL,
Capability.SWITCH_LEVEL,
},
)
self.capability = capability
self._attr_supported_features = (
CoverEntityFeature.OPEN | CoverEntityFeature.CLOSE
)
if (
Capability.switch_level in device.capabilities
or Capability.window_shade_level in device.capabilities
):
if self.supports_capability(Capability.WINDOW_SHADE_LEVEL):
self.level_capability = Capability.WINDOW_SHADE_LEVEL
self.level_command = Command.SET_SHADE_LEVEL
else:
self.level_capability = Capability.SWITCH_LEVEL
self.level_command = Command.SET_LEVEL
if self.supports_capability(
Capability.SWITCH_LEVEL
) or self.supports_capability(Capability.WINDOW_SHADE_LEVEL):
self._attr_supported_features |= CoverEntityFeature.SET_POSITION
if Capability.door_control in device.capabilities:
if self.supports_capability(Capability.DOOR_CONTROL):
self._attr_device_class = CoverDeviceClass.DOOR
elif Capability.window_shade in device.capabilities:
elif self.supports_capability(Capability.WINDOW_SHADE):
self._attr_device_class = CoverDeviceClass.SHADE
elif Capability.garage_door_control in device.capabilities:
self._attr_device_class = CoverDeviceClass.GARAGE
async def async_close_cover(self, **kwargs: Any) -> None:
"""Close cover."""
# Same command for all 3 supported capabilities
await self._device.close(set_status=True)
# State is set optimistically in the commands above, therefore update
# the entity state ahead of receiving the confirming push updates
self.async_schedule_update_ha_state(True)
await self.execute_device_command(self.capability, Command.CLOSE)
async def async_open_cover(self, **kwargs: Any) -> None:
"""Open the cover."""
# Same for all capability types
await self._device.open(set_status=True)
# State is set optimistically in the commands above, therefore update
# the entity state ahead of receiving the confirming push updates
self.async_schedule_update_ha_state(True)
await self.execute_device_command(self.capability, Command.OPEN)
async def async_set_cover_position(self, **kwargs: Any) -> None:
"""Move the cover to a specific position."""
if not self.supported_features & CoverEntityFeature.SET_POSITION:
return
# Do not set_status=True as device will report progress.
if Capability.window_shade_level in self._device.capabilities:
await self._device.set_window_shade_level(
kwargs[ATTR_POSITION], set_status=False
)
else:
await self._device.set_level(kwargs[ATTR_POSITION], set_status=False)
await self.execute_device_command(
self.level_capability,
self.level_command,
argument=kwargs[ATTR_POSITION],
)
async def async_update(self) -> None:
def _update_attr(self) -> None:
"""Update the attrs of the cover."""
if Capability.door_control in self._device.capabilities:
self._state = VALUE_TO_STATE.get(self._device.status.door)
elif Capability.window_shade in self._device.capabilities:
self._state = VALUE_TO_STATE.get(self._device.status.window_shade)
elif Capability.garage_door_control in self._device.capabilities:
self._state = VALUE_TO_STATE.get(self._device.status.door)
attribute = {
Capability.WINDOW_SHADE: Attribute.WINDOW_SHADE,
Capability.DOOR_CONTROL: Attribute.DOOR,
}[self.capability]
self._state = VALUE_TO_STATE.get(
self.get_attribute_value(self.capability, attribute)
)
if Capability.window_shade_level in self._device.capabilities:
self._attr_current_cover_position = self._device.status.shade_level
elif Capability.switch_level in self._device.capabilities:
self._attr_current_cover_position = self._device.status.level
if self.supports_capability(Capability.SWITCH_LEVEL):
self._attr_current_cover_position = self.get_attribute_value(
Capability.SWITCH_LEVEL, Attribute.LEVEL
)
self._attr_extra_state_attributes = {}
battery = self._device.status.attributes[Attribute.battery].value
if battery is not None:
self._attr_extra_state_attributes[ATTR_BATTERY_LEVEL] = battery
if self.supports_capability(Capability.BATTERY):
self._attr_extra_state_attributes[ATTR_BATTERY_LEVEL] = (
self.get_attribute_value(Capability.BATTERY, Attribute.BATTERY)
)
@property
def is_opening(self) -> bool:

View File

@ -2,13 +2,15 @@
from __future__ import annotations
from pysmartthings.device import DeviceEntity
from typing import Any, cast
from pysmartthings import Attribute, Capability, Command, DeviceEvent, SmartThings
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import Entity
from .const import DOMAIN, SIGNAL_SMARTTHINGS_UPDATE
from . import FullDevice
from .const import DOMAIN, MAIN
class SmartThingsEntity(Entity):
@ -16,35 +18,86 @@ class SmartThingsEntity(Entity):
_attr_should_poll = False
def __init__(self, device: DeviceEntity) -> None:
def __init__(
self, client: SmartThings, device: FullDevice, capabilities: set[Capability]
) -> None:
"""Initialize the instance."""
self._device = device
self._dispatcher_remove = None
self._attr_name = device.label
self._attr_unique_id = device.device_id
self.client = client
self.capabilities = capabilities
self._internal_state = {
capability: device.status[MAIN][capability]
for capability in capabilities
if capability in device.status[MAIN]
}
self.device = device
self._attr_name = device.device.label
self._attr_unique_id = device.device.device_id
self._attr_device_info = DeviceInfo(
configuration_url="https://account.smartthings.com",
identifiers={(DOMAIN, device.device_id)},
manufacturer=device.status.ocf_manufacturer_name,
model=device.status.ocf_model_number,
name=device.label,
hw_version=device.status.ocf_hardware_version,
sw_version=device.status.ocf_firmware_version,
identifiers={(DOMAIN, device.device.device_id)},
name=device.device.label,
)
if (ocf := device.status[MAIN].get(Capability.OCF)) is not None:
self._attr_device_info.update(
{
"manufacturer": cast(
str | None, ocf[Attribute.MANUFACTURER_NAME].value
),
"model": cast(str | None, ocf[Attribute.MODEL_NUMBER].value),
"hw_version": cast(
str | None, ocf[Attribute.HARDWARE_VERSION].value
),
"sw_version": cast(
str | None, ocf[Attribute.OCF_FIRMWARE_VERSION].value
),
}
)
async def async_added_to_hass(self):
"""Device added to hass."""
async def async_added_to_hass(self) -> None:
"""Subscribe to updates."""
await super().async_added_to_hass()
for capability in self._internal_state:
self.async_on_remove(
self.client.add_device_event_listener(
self.device.device.device_id,
MAIN,
capability,
self._update_handler,
)
)
self._update_attr()
async def async_update_state(devices):
"""Update device state."""
if self._device.device_id in devices:
await self.async_update_ha_state(True)
def _update_handler(self, event: DeviceEvent) -> None:
self._internal_state[event.capability][event.attribute].value = event.value
self._internal_state[event.capability][event.attribute].data = event.data
self._handle_update()
self._dispatcher_remove = async_dispatcher_connect(
self.hass, SIGNAL_SMARTTHINGS_UPDATE, async_update_state
def supports_capability(self, capability: Capability) -> bool:
"""Test if device supports a capability."""
return capability in self.device.status[MAIN]
def get_attribute_value(self, capability: Capability, attribute: Attribute) -> Any:
"""Get the value of a device attribute."""
return self._internal_state[capability][attribute].value
def _update_attr(self) -> None:
"""Update the attributes."""
def _handle_update(self) -> None:
"""Handle updated data from the coordinator."""
self._update_attr()
self.async_write_ha_state()
async def execute_device_command(
self,
capability: Capability,
command: Command,
argument: int | str | list[Any] | dict[str, Any] | None = None,
) -> None:
"""Execute a command on the device."""
kwargs = {}
if argument is not None:
kwargs["argument"] = argument
await self.client.execute_device_command(
self.device.device.device_id, capability, command, MAIN, **kwargs
)
async def async_will_remove_from_hass(self) -> None:
"""Disconnect the device when removed."""
if self._dispatcher_remove:
self._dispatcher_remove()

View File

@ -2,14 +2,12 @@
from __future__ import annotations
from collections.abc import Sequence
import math
from typing import Any
from pysmartthings import Capability
from pysmartthings import Attribute, Capability, Command, SmartThings
from homeassistant.components.fan import FanEntity, FanEntityFeature
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.util.percentage import (
@ -18,7 +16,8 @@ from homeassistant.util.percentage import (
)
from homeassistant.util.scaling import int_states_in_range
from .const import DATA_BROKERS, DOMAIN
from . import FullDevice, SmartThingsConfigEntry
from .const import MAIN
from .entity import SmartThingsEntity
SPEED_RANGE = (1, 3) # off is not included
@ -26,86 +25,73 @@ SPEED_RANGE = (1, 3) # off is not included
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
entry: SmartThingsConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Add fans for a config entry."""
broker = hass.data[DOMAIN][DATA_BROKERS][config_entry.entry_id]
entry_data = entry.runtime_data
async_add_entities(
SmartThingsFan(device)
for device in broker.devices.values()
if broker.any_assigned(device.device_id, "fan")
SmartThingsFan(entry_data.client, device)
for device in entry_data.devices.values()
if Capability.SWITCH in device.status[MAIN]
and any(
capability in device.status[MAIN]
for capability in (
Capability.FAN_SPEED,
Capability.AIR_CONDITIONER_FAN_MODE,
)
)
and Capability.THERMOSTAT_COOLING_SETPOINT not in device.status[MAIN]
)
def get_capabilities(capabilities: Sequence[str]) -> Sequence[str] | None:
"""Return all capabilities supported if minimum required are present."""
# MUST support switch as we need a way to turn it on and off
if Capability.switch not in capabilities:
return None
# These are all optional but at least one must be supported
optional = [
Capability.air_conditioner_fan_mode,
Capability.fan_speed,
]
# At least one of the optional capabilities must be supported
# to classify this entity as a fan.
# If they are not then return None and don't setup the platform.
if not any(capability in capabilities for capability in optional):
return None
supported = [Capability.switch]
supported.extend(
capability for capability in optional if capability in capabilities
)
return supported
class SmartThingsFan(SmartThingsEntity, FanEntity):
"""Define a SmartThings Fan."""
_attr_speed_count = int_states_in_range(SPEED_RANGE)
def __init__(self, device):
def __init__(self, client: SmartThings, device: FullDevice) -> None:
"""Init the class."""
super().__init__(device)
super().__init__(
client,
device,
{
Capability.SWITCH,
Capability.FAN_SPEED,
Capability.AIR_CONDITIONER_FAN_MODE,
},
)
self._attr_supported_features = self._determine_features()
def _determine_features(self):
flags = FanEntityFeature.TURN_OFF | FanEntityFeature.TURN_ON
if self._device.get_capability(Capability.fan_speed):
if self.supports_capability(Capability.FAN_SPEED):
flags |= FanEntityFeature.SET_SPEED
if self._device.get_capability(Capability.air_conditioner_fan_mode):
if self.supports_capability(Capability.AIR_CONDITIONER_FAN_MODE):
flags |= FanEntityFeature.PRESET_MODE
return flags
async def async_set_percentage(self, percentage: int) -> None:
"""Set the speed percentage of the fan."""
await self._async_set_percentage(percentage)
async def _async_set_percentage(self, percentage: int | None) -> None:
if percentage is None:
await self._device.switch_on(set_status=True)
elif percentage == 0:
await self._device.switch_off(set_status=True)
if percentage == 0:
await self.execute_device_command(Capability.SWITCH, Command.OFF)
else:
value = math.ceil(percentage_to_ranged_value(SPEED_RANGE, percentage))
await self._device.set_fan_speed(value, set_status=True)
# State is set optimistically in the command above, therefore update
# the entity state ahead of receiving the confirming push updates
self.async_write_ha_state()
await self.execute_device_command(
Capability.FAN_SPEED,
Command.SET_FAN_SPEED,
argument=value,
)
async def async_set_preset_mode(self, preset_mode: str) -> None:
"""Set the preset_mode of the fan."""
await self._device.set_fan_mode(preset_mode, set_status=True)
self.async_write_ha_state()
await self.execute_device_command(
Capability.AIR_CONDITIONER_FAN_MODE,
Command.SET_FAN_MODE,
argument=preset_mode,
)
async def async_turn_on(
self,
@ -114,32 +100,30 @@ class SmartThingsFan(SmartThingsEntity, FanEntity):
**kwargs: Any,
) -> None:
"""Turn the fan on."""
if FanEntityFeature.SET_SPEED in self._attr_supported_features:
# If speed is set in features then turn the fan on with the speed.
await self._async_set_percentage(percentage)
if (
FanEntityFeature.SET_SPEED in self._attr_supported_features
and percentage is not None
):
await self.async_set_percentage(percentage)
else:
# If speed is not valid then turn on the fan with the
await self._device.switch_on(set_status=True)
# State is set optimistically in the command above, therefore update
# the entity state ahead of receiving the confirming push updates
self.async_write_ha_state()
await self.execute_device_command(Capability.SWITCH, Command.ON)
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the fan off."""
await self._device.switch_off(set_status=True)
# State is set optimistically in the command above, therefore update
# the entity state ahead of receiving the confirming push updates
self.async_write_ha_state()
await self.execute_device_command(Capability.SWITCH, Command.OFF)
@property
def is_on(self) -> bool:
"""Return true if fan is on."""
return self._device.status.switch
return self.get_attribute_value(Capability.SWITCH, Attribute.SWITCH)
@property
def percentage(self) -> int | None:
"""Return the current speed percentage."""
return ranged_value_to_percentage(SPEED_RANGE, self._device.status.fan_speed)
return ranged_value_to_percentage(
SPEED_RANGE,
self.get_attribute_value(Capability.FAN_SPEED, Attribute.FAN_SPEED),
)
@property
def preset_mode(self) -> str | None:
@ -147,7 +131,9 @@ class SmartThingsFan(SmartThingsEntity, FanEntity):
Requires FanEntityFeature.PRESET_MODE.
"""
return self._device.status.fan_mode
return self.get_attribute_value(
Capability.AIR_CONDITIONER_FAN_MODE, Attribute.FAN_MODE
)
@property
def preset_modes(self) -> list[str] | None:
@ -155,4 +141,6 @@ class SmartThingsFan(SmartThingsEntity, FanEntity):
Requires FanEntityFeature.PRESET_MODE.
"""
return self._device.status.supported_ac_fan_modes
return self.get_attribute_value(
Capability.AIR_CONDITIONER_FAN_MODE, Attribute.SUPPORTED_AC_FAN_MODES
)

View File

@ -3,10 +3,9 @@
from __future__ import annotations
import asyncio
from collections.abc import Sequence
from typing import Any
from pysmartthings import Capability
from pysmartthings import Attribute, Capability, Command, SmartThings
from homeassistant.components.light import (
ATTR_BRIGHTNESS,
@ -18,54 +17,38 @@ from homeassistant.components.light import (
LightEntityFeature,
brightness_supported,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .const import DATA_BROKERS, DOMAIN
from . import FullDevice, SmartThingsConfigEntry
from .const import MAIN
from .entity import SmartThingsEntity
CAPABILITIES = (
Capability.SWITCH_LEVEL,
Capability.COLOR_CONTROL,
Capability.COLOR_TEMPERATURE,
)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
entry: SmartThingsConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Add lights for a config entry."""
broker = hass.data[DOMAIN][DATA_BROKERS][config_entry.entry_id]
entry_data = entry.runtime_data
async_add_entities(
[
SmartThingsLight(device)
for device in broker.devices.values()
if broker.any_assigned(device.device_id, "light")
],
True,
SmartThingsLight(entry_data.client, device)
for device in entry_data.devices.values()
if Capability.SWITCH in device.status[MAIN]
and any(capability in device.status[MAIN] for capability in CAPABILITIES)
)
def get_capabilities(capabilities: Sequence[str]) -> Sequence[str] | None:
"""Return all capabilities supported if minimum required are present."""
supported = [
Capability.switch,
Capability.switch_level,
Capability.color_control,
Capability.color_temperature,
]
# Must be able to be turned on/off.
if Capability.switch not in capabilities:
return None
# Must have one of these
light_capabilities = [
Capability.color_control,
Capability.color_temperature,
Capability.switch_level,
]
if any(capability in capabilities for capability in light_capabilities):
return supported
return None
def convert_scale(value, value_scale, target_scale, round_digits=4):
def convert_scale(
value: float, value_scale: int, target_scale: int, round_digits: int = 4
) -> float:
"""Convert a value to a different scale."""
return round(value * target_scale / value_scale, round_digits)
@ -76,46 +59,41 @@ class SmartThingsLight(SmartThingsEntity, LightEntity):
_attr_supported_color_modes: set[ColorMode]
# SmartThings does not expose this attribute, instead it's
# implemented within each device-type handler. This value is the
# implemented within each device-type handler. This value is the
# lowest kelvin found supported across 20+ handlers.
_attr_min_color_temp_kelvin = 2000 # 500 mireds
# SmartThings does not expose this attribute, instead it's
# implemented within each device-type handler. This value is the
# implemented within each device-type handler. This value is the
# highest kelvin found supported across 20+ handlers.
_attr_max_color_temp_kelvin = 9000 # 111 mireds
def __init__(self, device):
def __init__(self, client: SmartThings, device: FullDevice) -> None:
"""Initialize a SmartThingsLight."""
super().__init__(device)
self._attr_supported_color_modes = self._determine_color_modes()
self._attr_supported_features = self._determine_features()
def _determine_color_modes(self):
"""Get features supported by the device."""
super().__init__(
client,
device,
{
Capability.COLOR_CONTROL,
Capability.COLOR_TEMPERATURE,
Capability.SWITCH_LEVEL,
Capability.SWITCH,
},
)
color_modes = set()
# Color Temperature
if Capability.color_temperature in self._device.capabilities:
if self.supports_capability(Capability.COLOR_TEMPERATURE):
color_modes.add(ColorMode.COLOR_TEMP)
# Color
if Capability.color_control in self._device.capabilities:
if self.supports_capability(Capability.COLOR_CONTROL):
color_modes.add(ColorMode.HS)
# Brightness
if not color_modes and Capability.switch_level in self._device.capabilities:
if not color_modes and self.supports_capability(Capability.SWITCH_LEVEL):
color_modes.add(ColorMode.BRIGHTNESS)
if not color_modes:
color_modes.add(ColorMode.ONOFF)
return color_modes
def _determine_features(self) -> LightEntityFeature:
"""Get features supported by the device."""
self._attr_supported_color_modes = color_modes
features = LightEntityFeature(0)
# Transition
if Capability.switch_level in self._device.capabilities:
if self.supports_capability(Capability.SWITCH_LEVEL):
features |= LightEntityFeature.TRANSITION
return features
self._attr_supported_features = features
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the light on."""
@ -136,11 +114,10 @@ class SmartThingsLight(SmartThingsEntity, LightEntity):
kwargs[ATTR_BRIGHTNESS], kwargs.get(ATTR_TRANSITION, 0)
)
else:
await self._device.switch_on(set_status=True)
# State is set optimistically in the commands above, therefore update
# the entity state ahead of receiving the confirming push updates
self.async_schedule_update_ha_state(True)
await self.execute_device_command(
Capability.SWITCH,
Command.ON,
)
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the light off."""
@ -148,27 +125,39 @@ class SmartThingsLight(SmartThingsEntity, LightEntity):
if ATTR_TRANSITION in kwargs:
await self.async_set_level(0, int(kwargs[ATTR_TRANSITION]))
else:
await self._device.switch_off(set_status=True)
await self.execute_device_command(
Capability.SWITCH,
Command.OFF,
)
# State is set optimistically in the commands above, therefore update
# the entity state ahead of receiving the confirming push updates
self.async_schedule_update_ha_state(True)
async def async_update(self) -> None:
def _update_attr(self) -> None:
"""Update entity attributes when the device status has changed."""
# Brightness and transition
if brightness_supported(self._attr_supported_color_modes):
self._attr_brightness = int(
convert_scale(self._device.status.level, 100, 255, 0)
convert_scale(
self.get_attribute_value(Capability.SWITCH_LEVEL, Attribute.LEVEL),
100,
255,
0,
)
)
# Color Temperature
if ColorMode.COLOR_TEMP in self._attr_supported_color_modes:
self._attr_color_temp_kelvin = self._device.status.color_temperature
self._attr_color_temp_kelvin = self.get_attribute_value(
Capability.COLOR_TEMPERATURE, Attribute.COLOR_TEMPERATURE
)
# Color
if ColorMode.HS in self._attr_supported_color_modes:
self._attr_hs_color = (
convert_scale(self._device.status.hue, 100, 360),
self._device.status.saturation,
convert_scale(
self.get_attribute_value(Capability.COLOR_CONTROL, Attribute.HUE),
100,
360,
),
self.get_attribute_value(
Capability.COLOR_CONTROL, Attribute.SATURATION
),
)
async def async_set_color(self, hs_color):
@ -176,14 +165,22 @@ class SmartThingsLight(SmartThingsEntity, LightEntity):
hue = convert_scale(float(hs_color[0]), 360, 100)
hue = max(min(hue, 100.0), 0.0)
saturation = max(min(float(hs_color[1]), 100.0), 0.0)
await self._device.set_color(hue, saturation, set_status=True)
await self.execute_device_command(
Capability.COLOR_CONTROL,
Command.SET_COLOR,
argument={"hue": hue, "saturation": saturation},
)
async def async_set_color_temp(self, value: int):
"""Set the color temperature of the device."""
kelvin = max(min(value, 30000), 1)
await self._device.set_color_temperature(kelvin, set_status=True)
await self.execute_device_command(
Capability.COLOR_TEMPERATURE,
Command.SET_COLOR_TEMPERATURE,
argument=kelvin,
)
async def async_set_level(self, brightness: int, transition: int):
async def async_set_level(self, brightness: int, transition: int) -> None:
"""Set the brightness of the light over transition."""
level = int(convert_scale(brightness, 255, 100, 0))
# Due to rounding, set level to 1 (one) so we don't inadvertently
@ -191,7 +188,11 @@ class SmartThingsLight(SmartThingsEntity, LightEntity):
level = 1 if level == 0 and brightness > 0 else level
level = max(min(level, 100), 0)
duration = int(transition)
await self._device.set_level(level, duration, set_status=True)
await self.execute_device_command(
Capability.SWITCH_LEVEL,
Command.SET_LEVEL,
argument=[level, duration],
)
@property
def color_mode(self) -> ColorMode:
@ -208,4 +209,4 @@ class SmartThingsLight(SmartThingsEntity, LightEntity):
@property
def is_on(self) -> bool:
"""Return true if light is on."""
return self._device.status.switch
return self.get_attribute_value(Capability.SWITCH, Attribute.SWITCH) == "on"

View File

@ -2,17 +2,16 @@
from __future__ import annotations
from collections.abc import Sequence
from typing import Any
from pysmartthings import Attribute, Capability
from pysmartthings import Attribute, Capability, Command
from homeassistant.components.lock import LockEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .const import DATA_BROKERS, DOMAIN
from . import SmartThingsConfigEntry
from .const import MAIN
from .entity import SmartThingsEntity
ST_STATE_LOCKED = "locked"
@ -28,48 +27,47 @@ ST_LOCK_ATTR_MAP = {
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
entry: SmartThingsConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Add locks for a config entry."""
broker = hass.data[DOMAIN][DATA_BROKERS][config_entry.entry_id]
entry_data = entry.runtime_data
async_add_entities(
SmartThingsLock(device)
for device in broker.devices.values()
if broker.any_assigned(device.device_id, "lock")
SmartThingsLock(entry_data.client, device, {Capability.LOCK})
for device in entry_data.devices.values()
if Capability.LOCK in device.status[MAIN]
)
def get_capabilities(capabilities: Sequence[str]) -> Sequence[str] | None:
"""Return all capabilities supported if minimum required are present."""
if Capability.lock in capabilities:
return [Capability.lock]
return None
class SmartThingsLock(SmartThingsEntity, LockEntity):
"""Define a SmartThings lock."""
async def async_lock(self, **kwargs: Any) -> None:
"""Lock the device."""
await self._device.lock(set_status=True)
self.async_write_ha_state()
await self.execute_device_command(
Capability.LOCK,
Command.LOCK,
)
async def async_unlock(self, **kwargs: Any) -> None:
"""Unlock the device."""
await self._device.unlock(set_status=True)
self.async_write_ha_state()
await self.execute_device_command(
Capability.LOCK,
Command.UNLOCK,
)
@property
def is_locked(self) -> bool:
"""Return true if lock is locked."""
return self._device.status.lock == ST_STATE_LOCKED
return (
self.get_attribute_value(Capability.LOCK, Attribute.LOCK) == ST_STATE_LOCKED
)
@property
def extra_state_attributes(self) -> dict[str, Any]:
"""Return device specific state attributes."""
state_attrs = {}
status = self._device.status.attributes[Attribute.lock]
status = self._internal_state[Capability.LOCK][Attribute.LOCK]
if status.value:
state_attrs["lock_state"] = status.value
if isinstance(status.data, dict):

View File

@ -1,10 +1,9 @@
{
"domain": "smartthings",
"name": "SmartThings",
"after_dependencies": ["cloud"],
"codeowners": [],
"codeowners": ["@joostlek"],
"config_flow": true,
"dependencies": ["webhook"],
"dependencies": ["application_credentials"],
"dhcp": [
{
"hostname": "st*",
@ -29,6 +28,6 @@
],
"documentation": "https://www.home-assistant.io/integrations/smartthings",
"iot_class": "cloud_push",
"loggers": ["httpsig", "pysmartapp", "pysmartthings"],
"requirements": ["pysmartapp==0.3.5", "pysmartthings==0.7.8"]
"loggers": ["pysmartthings"],
"requirements": ["pysmartthings==1.2.0"]
}

View File

@ -2,39 +2,42 @@
from typing import Any
from pysmartthings import Scene as STScene, SmartThings
from homeassistant.components.scene import Scene
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .const import DATA_BROKERS, DOMAIN
from . import SmartThingsConfigEntry
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
entry: SmartThingsConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Add switches for a config entry."""
broker = hass.data[DOMAIN][DATA_BROKERS][config_entry.entry_id]
async_add_entities(SmartThingsScene(scene) for scene in broker.scenes.values())
"""Add lights for a config entry."""
client = entry.runtime_data.client
scenes = entry.runtime_data.scenes
async_add_entities(SmartThingsScene(scene, client) for scene in scenes.values())
class SmartThingsScene(Scene):
"""Define a SmartThings scene."""
def __init__(self, scene):
def __init__(self, scene: STScene, client: SmartThings) -> None:
"""Init the scene class."""
self.client = client
self._scene = scene
self._attr_name = scene.name
self._attr_unique_id = scene.scene_id
async def async_activate(self, **kwargs: Any) -> None:
"""Activate scene."""
await self._scene.execute()
await self.client.execute_scene(self._scene.scene_id)
@property
def extra_state_attributes(self):
def extra_state_attributes(self) -> dict[str, Any]:
"""Get attributes about the state."""
return {
"icon": self._scene.icon,

File diff suppressed because it is too large Load Diff

View File

@ -1,545 +0,0 @@
"""SmartApp functionality to receive cloud-push notifications."""
from __future__ import annotations
import asyncio
import functools
import logging
import secrets
from typing import Any
from urllib.parse import urlparse
from uuid import uuid4
from aiohttp import web
from pysmartapp import Dispatcher, SmartAppManager
from pysmartapp.const import SETTINGS_APP_ID
from pysmartthings import (
APP_TYPE_WEBHOOK,
CAPABILITIES,
CLASSIFICATION_AUTOMATION,
App,
AppEntity,
AppOAuth,
AppSettings,
InstalledAppStatus,
SmartThings,
SourceType,
Subscription,
SubscriptionEntity,
)
from homeassistant.components import cloud, webhook
from homeassistant.config_entries import ConfigFlowResult
from homeassistant.const import CONF_WEBHOOK_ID
from homeassistant.core import HomeAssistant
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.dispatcher import (
async_dispatcher_connect,
async_dispatcher_send,
)
from homeassistant.helpers.network import NoURLAvailableError, get_url
from homeassistant.helpers.storage import Store
from .const import (
APP_NAME_PREFIX,
APP_OAUTH_CLIENT_NAME,
APP_OAUTH_SCOPES,
CONF_CLOUDHOOK_URL,
CONF_INSTALLED_APP_ID,
CONF_INSTANCE_ID,
CONF_REFRESH_TOKEN,
DATA_BROKERS,
DATA_MANAGER,
DOMAIN,
IGNORED_CAPABILITIES,
SETTINGS_INSTANCE_ID,
SIGNAL_SMARTAPP_PREFIX,
STORAGE_KEY,
STORAGE_VERSION,
SUBSCRIPTION_WARNING_LIMIT,
)
_LOGGER = logging.getLogger(__name__)
def format_unique_id(app_id: str, location_id: str) -> str:
"""Format the unique id for a config entry."""
return f"{app_id}_{location_id}"
async def find_app(hass: HomeAssistant, api: SmartThings) -> AppEntity | None:
"""Find an existing SmartApp for this installation of hass."""
apps = await api.apps()
for app in [app for app in apps if app.app_name.startswith(APP_NAME_PREFIX)]:
# Load settings to compare instance id
settings = await app.settings()
if (
settings.settings.get(SETTINGS_INSTANCE_ID)
== hass.data[DOMAIN][CONF_INSTANCE_ID]
):
return app
return None
async def validate_installed_app(api, installed_app_id: str):
"""Ensure the specified installed SmartApp is valid and functioning.
Query the API for the installed SmartApp and validate that it is tied to
the specified app_id and is in an authorized state.
"""
installed_app = await api.installed_app(installed_app_id)
if installed_app.installed_app_status != InstalledAppStatus.AUTHORIZED:
raise RuntimeWarning(
f"Installed SmartApp instance '{installed_app.display_name}' "
f"({installed_app.installed_app_id}) is not AUTHORIZED "
f"but instead {installed_app.installed_app_status}"
)
return installed_app
def validate_webhook_requirements(hass: HomeAssistant) -> bool:
"""Ensure Home Assistant is setup properly to receive webhooks."""
if cloud.async_active_subscription(hass):
return True
if hass.data[DOMAIN][CONF_CLOUDHOOK_URL] is not None:
return True
return get_webhook_url(hass).lower().startswith("https://")
def get_webhook_url(hass: HomeAssistant) -> str:
"""Get the URL of the webhook.
Return the cloudhook if available, otherwise local webhook.
"""
cloudhook_url = hass.data[DOMAIN][CONF_CLOUDHOOK_URL]
if cloud.async_active_subscription(hass) and cloudhook_url is not None:
return cloudhook_url
return webhook.async_generate_url(hass, hass.data[DOMAIN][CONF_WEBHOOK_ID])
def _get_app_template(hass: HomeAssistant):
try:
endpoint = f"at {get_url(hass, allow_cloud=False, prefer_external=True)}"
except NoURLAvailableError:
endpoint = ""
cloudhook_url = hass.data[DOMAIN][CONF_CLOUDHOOK_URL]
if cloudhook_url is not None:
endpoint = "via Nabu Casa"
description = f"{hass.config.location_name} {endpoint}"
return {
"app_name": APP_NAME_PREFIX + str(uuid4()),
"display_name": "Home Assistant",
"description": description,
"webhook_target_url": get_webhook_url(hass),
"app_type": APP_TYPE_WEBHOOK,
"single_instance": True,
"classifications": [CLASSIFICATION_AUTOMATION],
}
async def create_app(hass: HomeAssistant, api):
"""Create a SmartApp for this instance of hass."""
# Create app from template attributes
template = _get_app_template(hass)
app = App()
for key, value in template.items():
setattr(app, key, value)
app, client = await api.create_app(app)
_LOGGER.debug("Created SmartApp '%s' (%s)", app.app_name, app.app_id)
# Set unique hass id in settings
settings = AppSettings(app.app_id)
settings.settings[SETTINGS_APP_ID] = app.app_id
settings.settings[SETTINGS_INSTANCE_ID] = hass.data[DOMAIN][CONF_INSTANCE_ID]
await api.update_app_settings(settings)
_LOGGER.debug(
"Updated App Settings for SmartApp '%s' (%s)", app.app_name, app.app_id
)
# Set oauth scopes
oauth = AppOAuth(app.app_id)
oauth.client_name = APP_OAUTH_CLIENT_NAME
oauth.scope.extend(APP_OAUTH_SCOPES)
await api.update_app_oauth(oauth)
_LOGGER.debug("Updated App OAuth for SmartApp '%s' (%s)", app.app_name, app.app_id)
return app, client
async def update_app(hass: HomeAssistant, app):
"""Ensure the SmartApp is up-to-date and update if necessary."""
template = _get_app_template(hass)
template.pop("app_name") # don't update this
update_required = False
for key, value in template.items():
if getattr(app, key) != value:
update_required = True
setattr(app, key, value)
if update_required:
await app.save()
_LOGGER.debug(
"SmartApp '%s' (%s) updated with latest settings", app.app_name, app.app_id
)
def setup_smartapp(hass, app):
"""Configure an individual SmartApp in hass.
Register the SmartApp with the SmartAppManager so that hass will service
lifecycle events (install, event, etc...). A unique SmartApp is created
for each SmartThings account that is configured in hass.
"""
manager = hass.data[DOMAIN][DATA_MANAGER]
if smartapp := manager.smartapps.get(app.app_id):
# already setup
return smartapp
smartapp = manager.register(app.app_id, app.webhook_public_key)
smartapp.name = app.display_name
smartapp.description = app.description
smartapp.permissions.extend(APP_OAUTH_SCOPES)
return smartapp
async def setup_smartapp_endpoint(hass: HomeAssistant, fresh_install: bool):
"""Configure the SmartApp webhook in hass.
SmartApps are an extension point within the SmartThings ecosystem and
is used to receive push updates (i.e. device updates) from the cloud.
"""
if hass.data.get(DOMAIN):
# already setup
if not fresh_install:
return
# We're doing a fresh install, clean up
await unload_smartapp_endpoint(hass)
# Get/create config to store a unique id for this hass instance.
store = Store[dict[str, Any]](hass, STORAGE_VERSION, STORAGE_KEY)
if fresh_install or not (config := await store.async_load()):
# Create config
config = {
CONF_INSTANCE_ID: str(uuid4()),
CONF_WEBHOOK_ID: secrets.token_hex(),
CONF_CLOUDHOOK_URL: None,
}
await store.async_save(config)
# Register webhook
webhook.async_register(
hass, DOMAIN, "SmartApp", config[CONF_WEBHOOK_ID], smartapp_webhook
)
# Create webhook if eligible
cloudhook_url = config.get(CONF_CLOUDHOOK_URL)
if (
cloudhook_url is None
and cloud.async_active_subscription(hass)
and not hass.config_entries.async_entries(DOMAIN)
):
cloudhook_url = await cloud.async_create_cloudhook(
hass, config[CONF_WEBHOOK_ID]
)
config[CONF_CLOUDHOOK_URL] = cloudhook_url
await store.async_save(config)
_LOGGER.debug("Created cloudhook '%s'", cloudhook_url)
# SmartAppManager uses a dispatcher to invoke callbacks when push events
# occur. Use hass' implementation instead of the built-in one.
dispatcher = Dispatcher(
signal_prefix=SIGNAL_SMARTAPP_PREFIX,
connect=functools.partial(async_dispatcher_connect, hass),
send=functools.partial(async_dispatcher_send, hass),
)
# Path is used in digital signature validation
path = (
urlparse(cloudhook_url).path
if cloudhook_url
else webhook.async_generate_path(config[CONF_WEBHOOK_ID])
)
manager = SmartAppManager(path, dispatcher=dispatcher)
manager.connect_install(functools.partial(smartapp_install, hass))
manager.connect_update(functools.partial(smartapp_update, hass))
manager.connect_uninstall(functools.partial(smartapp_uninstall, hass))
hass.data[DOMAIN] = {
DATA_MANAGER: manager,
CONF_INSTANCE_ID: config[CONF_INSTANCE_ID],
DATA_BROKERS: {},
CONF_WEBHOOK_ID: config[CONF_WEBHOOK_ID],
# Will not be present if not enabled
CONF_CLOUDHOOK_URL: config.get(CONF_CLOUDHOOK_URL),
}
_LOGGER.debug(
"Setup endpoint for %s",
cloudhook_url
if cloudhook_url
else webhook.async_generate_url(hass, config[CONF_WEBHOOK_ID]),
)
async def unload_smartapp_endpoint(hass: HomeAssistant):
"""Tear down the component configuration."""
if DOMAIN not in hass.data:
return
# Remove the cloudhook if it was created
cloudhook_url = hass.data[DOMAIN][CONF_CLOUDHOOK_URL]
if cloudhook_url and cloud.async_is_logged_in(hass):
await cloud.async_delete_cloudhook(hass, hass.data[DOMAIN][CONF_WEBHOOK_ID])
# Remove cloudhook from storage
store = Store[dict[str, Any]](hass, STORAGE_VERSION, STORAGE_KEY)
await store.async_save(
{
CONF_INSTANCE_ID: hass.data[DOMAIN][CONF_INSTANCE_ID],
CONF_WEBHOOK_ID: hass.data[DOMAIN][CONF_WEBHOOK_ID],
CONF_CLOUDHOOK_URL: None,
}
)
_LOGGER.debug("Cloudhook '%s' was removed", cloudhook_url)
# Remove the webhook
webhook.async_unregister(hass, hass.data[DOMAIN][CONF_WEBHOOK_ID])
# Disconnect all brokers
for broker in hass.data[DOMAIN][DATA_BROKERS].values():
broker.disconnect()
# Remove all handlers from manager
hass.data[DOMAIN][DATA_MANAGER].dispatcher.disconnect_all()
# Remove the component data
hass.data.pop(DOMAIN)
async def smartapp_sync_subscriptions(
hass: HomeAssistant,
auth_token: str,
location_id: str,
installed_app_id: str,
devices,
):
"""Synchronize subscriptions of an installed up."""
api = SmartThings(async_get_clientsession(hass), auth_token)
tasks = []
async def create_subscription(target: str):
sub = Subscription()
sub.installed_app_id = installed_app_id
sub.location_id = location_id
sub.source_type = SourceType.CAPABILITY
sub.capability = target
try:
await api.create_subscription(sub)
_LOGGER.debug(
"Created subscription for '%s' under app '%s'", target, installed_app_id
)
except Exception as error: # noqa: BLE001
_LOGGER.error(
"Failed to create subscription for '%s' under app '%s': %s",
target,
installed_app_id,
error,
)
async def delete_subscription(sub: SubscriptionEntity):
try:
await api.delete_subscription(installed_app_id, sub.subscription_id)
_LOGGER.debug(
(
"Removed subscription for '%s' under app '%s' because it was no"
" longer needed"
),
sub.capability,
installed_app_id,
)
except Exception as error: # noqa: BLE001
_LOGGER.error(
"Failed to remove subscription for '%s' under app '%s': %s",
sub.capability,
installed_app_id,
error,
)
# Build set of capabilities and prune unsupported ones
capabilities = set()
for device in devices:
capabilities.update(device.capabilities)
# Remove items not defined in the library
capabilities.intersection_update(CAPABILITIES)
# Remove unused capabilities
capabilities.difference_update(IGNORED_CAPABILITIES)
capability_count = len(capabilities)
if capability_count > SUBSCRIPTION_WARNING_LIMIT:
_LOGGER.warning(
(
"Some device attributes may not receive push updates and there may be"
" subscription creation failures under app '%s' because %s"
" subscriptions are required but there is a limit of %s per app"
),
installed_app_id,
capability_count,
SUBSCRIPTION_WARNING_LIMIT,
)
_LOGGER.debug(
"Synchronizing subscriptions for %s capabilities under app '%s': %s",
capability_count,
installed_app_id,
capabilities,
)
# Get current subscriptions and find differences
subscriptions = await api.subscriptions(installed_app_id)
for subscription in subscriptions:
if subscription.capability in capabilities:
capabilities.remove(subscription.capability)
else:
# Delete the subscription
tasks.append(delete_subscription(subscription))
# Remaining capabilities need subscriptions created
tasks.extend([create_subscription(c) for c in capabilities])
if tasks:
await asyncio.gather(*tasks)
else:
_LOGGER.debug("Subscriptions for app '%s' are up-to-date", installed_app_id)
async def _find_and_continue_flow(
hass: HomeAssistant,
app_id: str,
location_id: str,
installed_app_id: str,
refresh_token: str,
):
"""Continue a config flow if one is in progress for the specific installed app."""
unique_id = format_unique_id(app_id, location_id)
flow = next(
(
flow
for flow in hass.config_entries.flow.async_progress_by_handler(DOMAIN)
if flow["context"].get("unique_id") == unique_id
),
None,
)
if flow is not None:
await _continue_flow(hass, app_id, installed_app_id, refresh_token, flow)
async def _continue_flow(
hass: HomeAssistant,
app_id: str,
installed_app_id: str,
refresh_token: str,
flow: ConfigFlowResult,
) -> None:
await hass.config_entries.flow.async_configure(
flow["flow_id"],
{
CONF_INSTALLED_APP_ID: installed_app_id,
CONF_REFRESH_TOKEN: refresh_token,
},
)
_LOGGER.debug(
"Continued config flow '%s' for SmartApp '%s' under parent app '%s'",
flow["flow_id"],
installed_app_id,
app_id,
)
async def smartapp_install(hass: HomeAssistant, req, resp, app):
"""Handle a SmartApp installation and continue the config flow."""
await _find_and_continue_flow(
hass, app.app_id, req.location_id, req.installed_app_id, req.refresh_token
)
_LOGGER.debug(
"Installed SmartApp '%s' under parent app '%s'",
req.installed_app_id,
app.app_id,
)
async def smartapp_update(hass: HomeAssistant, req, resp, app):
"""Handle a SmartApp update and either update the entry or continue the flow."""
unique_id = format_unique_id(app.app_id, req.location_id)
flow = next(
(
flow
for flow in hass.config_entries.flow.async_progress_by_handler(DOMAIN)
if flow["context"].get("unique_id") == unique_id
and flow["step_id"] == "authorize"
),
None,
)
if flow is not None:
await _continue_flow(
hass, app.app_id, req.installed_app_id, req.refresh_token, flow
)
_LOGGER.debug(
"Continued reauth flow '%s' for SmartApp '%s' under parent app '%s'",
flow["flow_id"],
req.installed_app_id,
app.app_id,
)
return
entry = next(
(
entry
for entry in hass.config_entries.async_entries(DOMAIN)
if entry.data.get(CONF_INSTALLED_APP_ID) == req.installed_app_id
),
None,
)
if entry:
hass.config_entries.async_update_entry(
entry, data={**entry.data, CONF_REFRESH_TOKEN: req.refresh_token}
)
_LOGGER.debug(
"Updated config entry '%s' for SmartApp '%s' under parent app '%s'",
entry.entry_id,
req.installed_app_id,
app.app_id,
)
await _find_and_continue_flow(
hass, app.app_id, req.location_id, req.installed_app_id, req.refresh_token
)
_LOGGER.debug(
"Updated SmartApp '%s' under parent app '%s'", req.installed_app_id, app.app_id
)
async def smartapp_uninstall(hass: HomeAssistant, req, resp, app):
"""Handle when a SmartApp is removed from a location by the user.
Find and delete the config entry representing the integration.
"""
entry = next(
(
entry
for entry in hass.config_entries.async_entries(DOMAIN)
if entry.data.get(CONF_INSTALLED_APP_ID) == req.installed_app_id
),
None,
)
if entry:
# Add as job not needed because the current coroutine was invoked
# from the dispatcher and is not being awaited.
await hass.config_entries.async_remove(entry.entry_id)
_LOGGER.debug(
"Uninstalled SmartApp '%s' under parent app '%s'",
req.installed_app_id,
app.app_id,
)
async def smartapp_webhook(hass: HomeAssistant, webhook_id: str, request):
"""Handle a smartapp lifecycle event callback from SmartThings.
Requests from SmartThings are digitally signed and the SmartAppManager
validates the signature for authenticity.
"""
manager = hass.data[DOMAIN][DATA_MANAGER]
data = await request.json()
result = await manager.handle_request(data, request.headers)
return web.json_response(result)

View File

@ -1,43 +1,29 @@
{
"config": {
"step": {
"user": {
"title": "Confirm Callback URL",
"description": "SmartThings will be configured to send push updates to Home Assistant at:\n> {webhook_url}\n\nIf this is not correct, please update your configuration, restart Home Assistant, and try again."
"pick_implementation": {
"title": "[%key:common::config_flow::title::oauth2_pick_implementation%]"
},
"pat": {
"title": "Enter Personal Access Token",
"description": "Please enter a SmartThings [Personal Access Token]({token_url}) that has been created per the [instructions]({component_url}). This will be used to create the Home Assistant integration within your SmartThings account.\n\n**Please note that all Personal Access Tokens created after 30 December 2024 are only valid for 24 hours, after which the integration will stop working. We are working on a fix.**",
"data": {
"access_token": "[%key:common::config_flow::data::access_token%]"
}
},
"select_location": {
"title": "Select Location",
"description": "Please select the SmartThings Location you wish to add to Home Assistant. We will then open a new window and ask you to login and authorize installation of the Home Assistant integration into the selected location.",
"data": { "location_id": "[%key:common::config_flow::data::location%]" }
},
"authorize": { "title": "Authorize Home Assistant" },
"reauth_confirm": {
"title": "Reauthorize Home Assistant",
"description": "You are about to reauthorize Home Assistant with SmartThings. This will require you to log in and authorize the integration again."
},
"update_confirm": {
"title": "Finish reauthentication",
"description": "You have almost successfully reauthorized Home Assistant with SmartThings. Please press the button down below to finish the process."
"title": "[%key:common::config_flow::title::reauth%]",
"description": "The SmartThings integration needs to re-authenticate your account"
}
},
"abort": {
"invalid_webhook_url": "Home Assistant is not configured correctly to receive updates from SmartThings. The webhook URL is invalid:\n> {webhook_url}\n\nPlease update your configuration per the [instructions]({component_url}), restart Home Assistant, and try again.",
"no_available_locations": "There are no available SmartThings Locations to set up in Home Assistant.",
"reauth_successful": "Home Assistant has been successfully reauthorized with SmartThings."
},
"error": {
"token_invalid_format": "The token must be in the UID/GUID format",
"token_unauthorized": "The token is invalid or no longer authorized.",
"token_forbidden": "The token does not have the required OAuth scopes.",
"app_setup_error": "Unable to set up the SmartApp. Please try again.",
"webhook_error": "SmartThings could not validate the webhook URL. Please ensure the webhook URL is reachable from the internet and try again."
"already_configured": "[%key:common::config_flow::abort::already_configured_account%]"
},
"abort": {
"authorize_url_timeout": "[%key:common::config_flow::abort::oauth2_authorize_url_timeout%]",
"missing_configuration": "[%key:common::config_flow::abort::oauth2_missing_configuration%]",
"already_configured": "[%key:common::config_flow::abort::already_configured_account%]",
"no_url_available": "[%key:common::config_flow::abort::oauth2_no_url_available%]",
"oauth_error": "[%key:common::config_flow::abort::oauth2_error%]",
"oauth_timeout": "[%key:common::config_flow::abort::oauth2_timeout%]",
"oauth_unauthorized": "[%key:common::config_flow::abort::oauth2_unauthorized%]",
"oauth_failed": "[%key:common::config_flow::abort::oauth2_failed%]",
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]",
"reauth_account_mismatch": "Authenticated account does not match the account to be reauthenticated. Please log in with the correct account and pick the right location.",
"reauth_location_mismatch": "Authenticated location does not match the location to be reauthenticated. Please log in with the correct account and pick the right location."
}
}
}

View File

@ -2,60 +2,67 @@
from __future__ import annotations
from collections.abc import Sequence
from typing import Any
from pysmartthings import Capability
from pysmartthings import Attribute, Capability, Command
from homeassistant.components.switch import SwitchEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .const import DATA_BROKERS, DOMAIN
from . import SmartThingsConfigEntry
from .const import MAIN
from .entity import SmartThingsEntity
CAPABILITIES = (
Capability.SWITCH_LEVEL,
Capability.COLOR_CONTROL,
Capability.COLOR_TEMPERATURE,
Capability.FAN_SPEED,
)
AC_CAPABILITIES = (
Capability.AIR_CONDITIONER_MODE,
Capability.AIR_CONDITIONER_FAN_MODE,
Capability.TEMPERATURE_MEASUREMENT,
Capability.THERMOSTAT_COOLING_SETPOINT,
)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
entry: SmartThingsConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Add switches for a config entry."""
broker = hass.data[DOMAIN][DATA_BROKERS][config_entry.entry_id]
entry_data = entry.runtime_data
async_add_entities(
SmartThingsSwitch(device)
for device in broker.devices.values()
if broker.any_assigned(device.device_id, "switch")
SmartThingsSwitch(entry_data.client, device, {Capability.SWITCH})
for device in entry_data.devices.values()
if Capability.SWITCH in device.status[MAIN]
and not any(capability in device.status[MAIN] for capability in CAPABILITIES)
and not all(capability in device.status[MAIN] for capability in AC_CAPABILITIES)
)
def get_capabilities(capabilities: Sequence[str]) -> Sequence[str] | None:
"""Return all capabilities supported if minimum required are present."""
# Must be able to be turned on/off.
if Capability.switch in capabilities:
return [Capability.switch, Capability.energy_meter, Capability.power_meter]
return None
class SmartThingsSwitch(SmartThingsEntity, SwitchEntity):
"""Define a SmartThings switch."""
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the switch off."""
await self._device.switch_off(set_status=True)
# State is set optimistically in the command above, therefore update
# the entity state ahead of receiving the confirming push updates
self.async_write_ha_state()
await self.execute_device_command(
Capability.SWITCH,
Command.OFF,
)
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the switch on."""
await self._device.switch_on(set_status=True)
# State is set optimistically in the command above, therefore update
# the entity state ahead of receiving the confirming push updates
self.async_write_ha_state()
await self.execute_device_command(
Capability.SWITCH,
Command.ON,
)
@property
def is_on(self) -> bool:
"""Return true if light is on."""
return self._device.status.switch
return self.get_attribute_value(Capability.SWITCH, Attribute.SWITCH) == "on"

View File

@ -28,6 +28,7 @@ APPLICATION_CREDENTIALS = [
"onedrive",
"point",
"senz",
"smartthings",
"spotify",
"tesla_fleet",
"twitch",

5
requirements_all.txt generated
View File

@ -2310,10 +2310,7 @@ pysma==0.7.5
pysmappee==0.2.29
# homeassistant.components.smartthings
pysmartapp==0.3.5
# homeassistant.components.smartthings
pysmartthings==0.7.8
pysmartthings==1.2.0
# homeassistant.components.smarty
pysmarty2==0.10.2

View File

@ -1882,10 +1882,7 @@ pysma==0.7.5
pysmappee==0.2.29
# homeassistant.components.smartthings
pysmartapp==0.3.5
# homeassistant.components.smartthings
pysmartthings==0.7.8
pysmartthings==1.2.0
# homeassistant.components.smarty
pysmarty2==0.10.2

View File

@ -1 +1,75 @@
"""Tests for the SmartThings component."""
"""Tests for the SmartThings integration."""
from typing import Any
from unittest.mock import AsyncMock
from pysmartthings.models import Attribute, Capability, DeviceEvent
from syrupy import SnapshotAssertion
from homeassistant.components.smartthings.const import MAIN
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from tests.common import MockConfigEntry
async def setup_integration(hass: HomeAssistant, config_entry: MockConfigEntry) -> None:
"""Fixture for setting up the component."""
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
def snapshot_smartthings_entities(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
snapshot: SnapshotAssertion,
platform: Platform,
) -> None:
"""Snapshot SmartThings entities."""
entities = hass.states.async_all(platform)
for entity_state in entities:
entity_entry = entity_registry.async_get(entity_state.entity_id)
assert entity_entry == snapshot(name=f"{entity_entry.entity_id}-entry")
assert entity_state == snapshot(name=f"{entity_entry.entity_id}-state")
def set_attribute_value(
mock: AsyncMock,
capability: Capability,
attribute: Attribute,
value: Any,
component: str = MAIN,
) -> None:
"""Set the value of an attribute."""
mock.get_device_status.return_value[component][capability][attribute].value = value
async def trigger_update(
hass: HomeAssistant,
mock: AsyncMock,
device_id: str,
capability: Capability,
attribute: Attribute,
value: str | float | dict[str, Any] | list[Any] | None,
data: dict[str, Any] | None = None,
) -> None:
"""Trigger an update."""
for call in mock.add_device_event_listener.call_args_list:
if call[0][0] == device_id and call[0][2] == capability:
call[0][3](
DeviceEvent(
"abc",
"abc",
"abc",
device_id,
MAIN,
capability,
attribute,
value,
data,
)
)
await hass.async_block_till_done()

View File

@ -1,358 +1,178 @@
"""Test configuration and mocks for the SmartThings component."""
import secrets
from typing import Any
from unittest.mock import Mock, patch
from uuid import uuid4
from collections.abc import Generator
import time
from unittest.mock import AsyncMock, patch
from pysmartthings import (
CLASSIFICATION_AUTOMATION,
AppEntity,
AppOAuthClient,
AppSettings,
DeviceEntity,
from pysmartthings.models import (
DeviceResponse,
DeviceStatus,
InstalledApp,
InstalledAppStatus,
InstalledAppType,
Location,
SceneEntity,
SmartThings,
Subscription,
LocationResponse,
SceneResponse,
)
from pysmartthings.api import Api
import pytest
from homeassistant.components import webhook
from homeassistant.components.smartthings import DeviceBroker
from homeassistant.components.application_credentials import (
ClientCredential,
async_import_client_credential,
)
from homeassistant.components.smartthings import CONF_INSTALLED_APP_ID
from homeassistant.components.smartthings.const import (
APP_NAME_PREFIX,
CONF_APP_ID,
CONF_INSTALLED_APP_ID,
CONF_INSTANCE_ID,
CONF_LOCATION_ID,
CONF_REFRESH_TOKEN,
DATA_BROKERS,
DOMAIN,
SETTINGS_INSTANCE_ID,
STORAGE_KEY,
STORAGE_VERSION,
)
from homeassistant.config_entries import SOURCE_USER, ConfigEntryState
from homeassistant.const import (
CONF_ACCESS_TOKEN,
CONF_CLIENT_ID,
CONF_CLIENT_SECRET,
CONF_WEBHOOK_ID,
SCOPES,
)
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_CLIENT_ID, CONF_CLIENT_SECRET
from homeassistant.core import HomeAssistant
from homeassistant.core_config import async_process_ha_core_config
from homeassistant.setup import async_setup_component
from tests.common import MockConfigEntry
from tests.components.light.conftest import mock_light_profiles # noqa: F401
COMPONENT_PREFIX = "homeassistant.components.smartthings."
from tests.common import MockConfigEntry, load_fixture
async def setup_platform(
hass: HomeAssistant, platform: str, *, devices=None, scenes=None
):
"""Set up the SmartThings platform and prerequisites."""
hass.config.components.add(DOMAIN)
config_entry = MockConfigEntry(
version=2,
domain=DOMAIN,
title="Test",
data={CONF_INSTALLED_APP_ID: str(uuid4())},
)
config_entry.add_to_hass(hass)
broker = DeviceBroker(
hass, config_entry, Mock(), Mock(), devices or [], scenes or []
)
@pytest.fixture
def mock_setup_entry() -> Generator[AsyncMock]:
"""Override async_setup_entry."""
with patch(
"homeassistant.components.smartthings.async_setup_entry",
return_value=True,
) as mock_setup_entry:
yield mock_setup_entry
hass.data[DOMAIN] = {DATA_BROKERS: {config_entry.entry_id: broker}}
config_entry.mock_state(hass, ConfigEntryState.LOADED)
await hass.config_entries.async_forward_entry_setups(config_entry, [platform])
await hass.async_block_till_done()
return config_entry
@pytest.fixture(name="expires_at")
def mock_expires_at() -> int:
"""Fixture to set the oauth token expiration time."""
return time.time() + 3600
@pytest.fixture(autouse=True)
async def setup_component(
hass: HomeAssistant, config_file: dict[str, str], hass_storage: dict[str, Any]
) -> None:
"""Load the SmartThing component."""
hass_storage[STORAGE_KEY] = {"data": config_file, "version": STORAGE_VERSION}
await async_process_ha_core_config(
async def setup_credentials(hass: HomeAssistant) -> None:
"""Fixture to setup credentials."""
assert await async_setup_component(hass, "application_credentials", {})
await async_import_client_credential(
hass,
{"external_url": "https://test.local"},
)
await async_setup_component(hass, "smartthings", {})
def _create_location() -> Mock:
loc = Mock(Location)
loc.name = "Test Location"
loc.location_id = str(uuid4())
return loc
@pytest.fixture(name="location")
def location_fixture() -> Mock:
"""Fixture for a single location."""
return _create_location()
@pytest.fixture(name="locations")
def locations_fixture(location: Mock) -> list[Mock]:
"""Fixture for 2 locations."""
return [location, _create_location()]
@pytest.fixture(name="app")
async def app_fixture(hass: HomeAssistant, config_file: dict[str, str]) -> Mock:
"""Fixture for a single app."""
app = Mock(AppEntity)
app.app_name = APP_NAME_PREFIX + str(uuid4())
app.app_id = str(uuid4())
app.app_type = "WEBHOOK_SMART_APP"
app.classifications = [CLASSIFICATION_AUTOMATION]
app.display_name = "Home Assistant"
app.description = f"{hass.config.location_name} at https://test.local"
app.single_instance = True
app.webhook_target_url = webhook.async_generate_url(
hass, hass.data[DOMAIN][CONF_WEBHOOK_ID]
DOMAIN,
ClientCredential("CLIENT_ID", "CLIENT_SECRET"),
DOMAIN,
)
settings = Mock(AppSettings)
settings.app_id = app.app_id
settings.settings = {SETTINGS_INSTANCE_ID: config_file[CONF_INSTANCE_ID]}
app.settings.return_value = settings
return app
@pytest.fixture(name="app_oauth_client")
def app_oauth_client_fixture() -> Mock:
"""Fixture for a single app's oauth."""
client = Mock(AppOAuthClient)
client.client_id = str(uuid4())
client.client_secret = str(uuid4())
return client
@pytest.fixture(name="app_settings")
def app_settings_fixture(app, config_file):
"""Fixture for an app settings."""
settings = Mock(AppSettings)
settings.app_id = app.app_id
settings.settings = {SETTINGS_INSTANCE_ID: config_file[CONF_INSTANCE_ID]}
return settings
def _create_installed_app(location_id: str, app_id: str) -> Mock:
item = Mock(InstalledApp)
item.installed_app_id = str(uuid4())
item.installed_app_status = InstalledAppStatus.AUTHORIZED
item.installed_app_type = InstalledAppType.WEBHOOK_SMART_APP
item.app_id = app_id
item.location_id = location_id
return item
@pytest.fixture(name="installed_app")
def installed_app_fixture(location: Mock, app: Mock) -> Mock:
"""Fixture for a single installed app."""
return _create_installed_app(location.location_id, app.app_id)
@pytest.fixture(name="installed_apps")
def installed_apps_fixture(installed_app, locations, app):
"""Fixture for 2 installed apps."""
return [installed_app, _create_installed_app(locations[1].location_id, app.app_id)]
@pytest.fixture(name="config_file")
def config_file_fixture() -> dict[str, str]:
"""Fixture representing the local config file contents."""
return {CONF_INSTANCE_ID: str(uuid4()), CONF_WEBHOOK_ID: secrets.token_hex()}
@pytest.fixture(name="smartthings_mock")
def smartthings_mock_fixture(locations):
"""Fixture to mock smartthings API calls."""
async def _location(location_id):
return next(
location for location in locations if location.location_id == location_id
)
smartthings_mock = Mock(SmartThings)
smartthings_mock.location.side_effect = _location
mock = Mock(return_value=smartthings_mock)
@pytest.fixture
def mock_smartthings() -> Generator[AsyncMock]:
"""Mock a SmartThings client."""
with (
patch(COMPONENT_PREFIX + "SmartThings", new=mock),
patch(COMPONENT_PREFIX + "config_flow.SmartThings", new=mock),
patch(COMPONENT_PREFIX + "smartapp.SmartThings", new=mock),
patch(
"homeassistant.components.smartthings.SmartThings",
autospec=True,
) as mock_client,
patch(
"homeassistant.components.smartthings.config_flow.SmartThings",
new=mock_client,
),
):
yield smartthings_mock
client = mock_client.return_value
client.get_scenes.return_value = SceneResponse.from_json(
load_fixture("scenes.json", DOMAIN)
).items
client.get_locations.return_value = LocationResponse.from_json(
load_fixture("locations.json", DOMAIN)
).items
yield client
@pytest.fixture(name="device")
def device_fixture(location):
"""Fixture representing devices loaded."""
item = Mock(DeviceEntity)
item.device_id = "743de49f-036f-4e9c-839a-2f89d57607db"
item.name = "GE In-Wall Smart Dimmer"
item.label = "Front Porch Lights"
item.location_id = location.location_id
item.capabilities = [
"switch",
"switchLevel",
"refresh",
"indicator",
"sensor",
"actuator",
"healthCheck",
"light",
@pytest.fixture(
params=[
"da_ac_rac_000001",
"da_ac_rac_01001",
"multipurpose_sensor",
"contact_sensor",
"base_electric_meter",
"smart_plug",
"vd_stv_2017_k",
"c2c_arlo_pro_3_switch",
"yale_push_button_deadbolt_lock",
"ge_in_wall_smart_dimmer",
"centralite",
"da_ref_normal_000001",
"vd_network_audio_002s",
"iphone",
"da_wm_dw_000001",
"da_wm_wd_000001",
"da_wm_wm_000001",
"da_rvc_normal_000001",
"da_ks_microwave_0101x",
"hue_color_temperature_bulb",
"hue_rgbw_color_bulb",
"c2c_shade",
"sonos_player",
"aeotec_home_energy_meter_gen5",
"virtual_water_sensor",
"virtual_thermostat",
"virtual_valve",
"sensibo_airconditioner_1",
"ecobee_sensor",
"ecobee_thermostat",
"fake_fan",
]
item.components = {"main": item.capabilities}
item.status = Mock(DeviceStatus)
return item
)
def device_fixture(
mock_smartthings: AsyncMock, request: pytest.FixtureRequest
) -> Generator[str]:
"""Return every device."""
return request.param
@pytest.fixture(name="config_entry")
def config_entry_fixture(installed_app: Mock, location: Mock) -> MockConfigEntry:
"""Fixture representing a config entry."""
data = {
CONF_ACCESS_TOKEN: str(uuid4()),
CONF_INSTALLED_APP_ID: installed_app.installed_app_id,
CONF_APP_ID: installed_app.app_id,
CONF_LOCATION_ID: location.location_id,
CONF_REFRESH_TOKEN: str(uuid4()),
CONF_CLIENT_ID: str(uuid4()),
CONF_CLIENT_SECRET: str(uuid4()),
}
@pytest.fixture
def devices(mock_smartthings: AsyncMock, device_fixture: str) -> Generator[AsyncMock]:
"""Return a specific device."""
mock_smartthings.get_devices.return_value = DeviceResponse.from_json(
load_fixture(f"devices/{device_fixture}.json", DOMAIN)
).items
mock_smartthings.get_device_status.return_value = DeviceStatus.from_json(
load_fixture(f"device_status/{device_fixture}.json", DOMAIN)
).components
return mock_smartthings
@pytest.fixture
def mock_config_entry(expires_at: int) -> MockConfigEntry:
"""Mock a config entry."""
return MockConfigEntry(
domain=DOMAIN,
data=data,
title=location.name,
version=2,
source=SOURCE_USER,
title="My home",
unique_id="397678e5-9995-4a39-9d9f-ae6ba310236c",
data={
"auth_implementation": DOMAIN,
"token": {
"access_token": "mock-access-token",
"refresh_token": "mock-refresh-token",
"expires_at": expires_at,
"scope": " ".join(SCOPES),
"access_tier": 0,
"installed_app_id": "5aaaa925-2be1-4e40-b257-e4ef59083324",
},
CONF_LOCATION_ID: "397678e5-9995-4a39-9d9f-ae6ba310236c",
CONF_INSTALLED_APP_ID: "123",
},
version=3,
)
@pytest.fixture(name="subscription_factory")
def subscription_factory_fixture():
"""Fixture for creating mock subscriptions."""
def _factory(capability):
sub = Subscription()
sub.capability = capability
return sub
return _factory
@pytest.fixture(name="device_factory")
def device_factory_fixture():
"""Fixture for creating mock devices."""
api = Mock(Api)
api.post_device_command.return_value = {"results": [{"status": "ACCEPTED"}]}
def _factory(label, capabilities, status: dict | None = None):
device_data = {
"deviceId": str(uuid4()),
"name": "Device Type Handler Name",
"label": label,
"deviceManufacturerCode": "9135fc86-0929-4436-bf73-5d75f523d9db",
"locationId": "fcd829e9-82f4-45b9-acfd-62fda029af80",
"components": [
{
"id": "main",
"capabilities": [
{"id": capability, "version": 1} for capability in capabilities
],
}
],
"dth": {
"deviceTypeId": "b678b29d-2726-4e4f-9c3f-7aa05bd08964",
"deviceTypeName": "Switch",
"deviceNetworkType": "ZWAVE",
},
"type": "DTH",
}
device = DeviceEntity(api, data=device_data)
if status:
for attribute, value in status.items():
device.status.apply_attribute_update("main", "", attribute, value)
return device
return _factory
@pytest.fixture(name="scene_factory")
def scene_factory_fixture(location):
"""Fixture for creating mock devices."""
def _factory(name):
scene = Mock(SceneEntity)
scene.scene_id = str(uuid4())
scene.name = name
scene.icon = None
scene.color = None
scene.location_id = location.location_id
return scene
return _factory
@pytest.fixture(name="scene")
def scene_fixture(scene_factory):
"""Fixture for an individual scene."""
return scene_factory("Test Scene")
@pytest.fixture(name="event_factory")
def event_factory_fixture():
"""Fixture for creating mock devices."""
def _factory(
device_id,
event_type="DEVICE_EVENT",
capability="",
attribute="Updated",
value="Value",
data=None,
):
event = Mock()
event.event_type = event_type
event.device_id = device_id
event.component_id = "main"
event.capability = capability
event.attribute = attribute
event.value = value
event.data = data
event.location_id = str(uuid4())
return event
return _factory
@pytest.fixture(name="event_request_factory")
def event_request_factory_fixture(event_factory):
"""Fixture for creating mock smartapp event requests."""
def _factory(device_ids=None, events=None):
request = Mock()
request.installed_app_id = uuid4()
if events is None:
events = []
if device_ids:
events.extend([event_factory(device_id) for device_id in device_ids])
events.append(event_factory(uuid4()))
events.append(event_factory(device_ids[0], event_type="OTHER"))
request.events = events
return request
return _factory
@pytest.fixture
def mock_old_config_entry() -> MockConfigEntry:
"""Mock the old config entry."""
return MockConfigEntry(
domain=DOMAIN,
title="My home",
unique_id="appid123-2be1-4e40-b257-e4ef59083324_397678e5-9995-4a39-9d9f-ae6ba310236c",
data={
CONF_ACCESS_TOKEN: "mock-access-token",
CONF_REFRESH_TOKEN: "mock-refresh-token",
CONF_CLIENT_ID: "CLIENT_ID",
CONF_CLIENT_SECRET: "CLIENT_SECRET",
CONF_LOCATION_ID: "397678e5-9995-4a39-9d9f-ae6ba310236c",
CONF_INSTALLED_APP_ID: "123aa123-2be1-4e40-b257-e4ef59083324",
},
version=2,
)

View File

@ -0,0 +1,31 @@
{
"components": {
"main": {
"powerMeter": {
"power": {
"value": 2859.743,
"unit": "W",
"timestamp": "2025-02-10T21:09:08.228Z"
}
},
"voltageMeasurement": {
"voltage": {
"value": null
}
},
"powerConsumptionReport": {
"powerConsumption": {
"value": null
}
},
"energyMeter": {
"energy": {
"value": 19978.536,
"unit": "kWh",
"timestamp": "2025-02-10T21:09:08.357Z"
}
},
"refresh": {}
}
}
}

View File

@ -0,0 +1,21 @@
{
"components": {
"main": {
"powerMeter": {
"power": {
"value": 938.3,
"unit": "W",
"timestamp": "2025-02-09T17:56:21.748Z"
}
},
"energyMeter": {
"energy": {
"value": 1930.362,
"unit": "kWh",
"timestamp": "2025-02-09T17:56:21.918Z"
}
},
"refresh": {}
}
}
}

View File

@ -0,0 +1,82 @@
{
"components": {
"main": {
"videoCapture": {
"stream": {
"value": null
},
"clip": {
"value": null
}
},
"videoStream": {
"supportedFeatures": {
"value": null
},
"stream": {
"value": null
}
},
"healthCheck": {
"checkInterval": {
"value": 60,
"unit": "s",
"data": {
"deviceScheme": "UNTRACKED",
"protocol": "cloud"
},
"timestamp": "2025-02-03T21:55:57.991Z"
},
"healthStatus": {
"value": null
},
"DeviceWatch-Enroll": {
"value": null
},
"DeviceWatch-DeviceStatus": {
"value": "online",
"data": {},
"timestamp": "2025-02-08T21:56:09.761Z"
}
},
"alarm": {
"alarm": {
"value": "off",
"timestamp": "2025-02-08T21:56:09.761Z"
}
},
"refresh": {},
"soundSensor": {
"sound": {
"value": "not detected",
"timestamp": "2025-02-08T21:56:09.761Z"
}
},
"motionSensor": {
"motion": {
"value": "inactive",
"timestamp": "2025-02-08T21:56:09.761Z"
}
},
"battery": {
"quantity": {
"value": null
},
"battery": {
"value": 100,
"unit": "%",
"timestamp": "2025-02-08T21:56:10.041Z"
},
"type": {
"value": null
}
},
"switch": {
"switch": {
"value": "on",
"timestamp": "2025-02-08T21:56:10.041Z"
}
}
}
}
}

View File

@ -0,0 +1,50 @@
{
"components": {
"main": {
"healthCheck": {
"checkInterval": {
"value": 60,
"unit": "s",
"data": {
"deviceScheme": "UNTRACKED",
"protocol": "cloud"
},
"timestamp": "2025-02-07T23:01:15.966Z"
},
"healthStatus": {
"value": null
},
"DeviceWatch-Enroll": {
"value": null
},
"DeviceWatch-DeviceStatus": {
"value": "offline",
"data": {
"reason": "DEVICE-OFFLINE"
},
"timestamp": "2025-02-08T09:04:47.694Z"
}
},
"switchLevel": {
"levelRange": {
"value": null
},
"level": {
"value": 100,
"unit": "%",
"timestamp": "2025-02-08T09:04:47.694Z"
}
},
"refresh": {},
"windowShade": {
"supportedWindowShadeCommands": {
"value": null
},
"windowShade": {
"value": "open",
"timestamp": "2025-02-08T09:04:47.694Z"
}
}
}
}
}

View File

@ -0,0 +1,60 @@
{
"components": {
"main": {
"powerMeter": {
"power": {
"value": 0.0,
"unit": "W",
"timestamp": "2025-02-09T17:49:15.190Z"
}
},
"switchLevel": {
"levelRange": {
"value": null
},
"level": {
"value": 0,
"unit": "%",
"timestamp": "2025-02-09T17:49:15.112Z"
}
},
"refresh": {},
"firmwareUpdate": {
"lastUpdateStatusReason": {
"value": null
},
"availableVersion": {
"value": "16015010",
"timestamp": "2025-01-26T10:19:54.783Z"
},
"lastUpdateStatus": {
"value": null
},
"supportedCommands": {
"value": null
},
"state": {
"value": "normalOperation",
"timestamp": "2025-01-26T10:19:54.788Z"
},
"updateAvailable": {
"value": false,
"timestamp": "2025-01-26T10:19:54.789Z"
},
"currentVersion": {
"value": "16015010",
"timestamp": "2025-01-26T10:19:54.775Z"
},
"lastUpdateTime": {
"value": null
}
},
"switch": {
"switch": {
"value": "off",
"timestamp": "2025-02-09T17:24:16.864Z"
}
}
}
}
}

View File

@ -0,0 +1,66 @@
{
"components": {
"main": {
"contactSensor": {
"contact": {
"value": "closed",
"timestamp": "2025-02-09T17:16:42.674Z"
}
},
"temperatureMeasurement": {
"temperatureRange": {
"value": null
},
"temperature": {
"value": 59.0,
"unit": "F",
"timestamp": "2025-02-09T17:11:44.249Z"
}
},
"refresh": {},
"battery": {
"quantity": {
"value": null
},
"battery": {
"value": 100,
"unit": "%",
"timestamp": "2025-02-09T13:23:50.726Z"
},
"type": {
"value": null
}
},
"firmwareUpdate": {
"lastUpdateStatusReason": {
"value": null
},
"availableVersion": {
"value": "00000103",
"timestamp": "2025-02-09T13:59:19.101Z"
},
"lastUpdateStatus": {
"value": null
},
"supportedCommands": {
"value": null
},
"state": {
"value": "normalOperation",
"timestamp": "2025-02-09T13:59:19.101Z"
},
"updateAvailable": {
"value": false,
"timestamp": "2025-02-09T13:59:19.102Z"
},
"currentVersion": {
"value": "00000103",
"timestamp": "2025-02-09T13:59:19.102Z"
},
"lastUpdateTime": {
"value": null
}
}
}
}
}

View File

@ -0,0 +1,879 @@
{
"components": {
"1": {
"relativeHumidityMeasurement": {
"humidity": {
"value": 0,
"unit": "%",
"timestamp": "2021-04-06T16:43:35.291Z"
}
},
"custom.airConditionerOdorController": {
"airConditionerOdorControllerProgress": {
"value": null,
"timestamp": "2021-04-08T04:11:38.269Z"
},
"airConditionerOdorControllerState": {
"value": null,
"timestamp": "2021-04-08T04:11:38.269Z"
}
},
"custom.thermostatSetpointControl": {
"minimumSetpoint": {
"value": null,
"timestamp": "2021-04-08T04:04:19.901Z"
},
"maximumSetpoint": {
"value": null,
"timestamp": "2021-04-08T04:04:19.901Z"
}
},
"airConditionerMode": {
"availableAcModes": {
"value": null
},
"supportedAcModes": {
"value": null,
"timestamp": "2021-04-08T03:50:50.930Z"
},
"airConditionerMode": {
"value": null,
"timestamp": "2021-04-08T03:50:50.930Z"
}
},
"custom.spiMode": {
"spiMode": {
"value": null,
"timestamp": "2021-04-06T16:57:57.686Z"
}
},
"airQualitySensor": {
"airQuality": {
"value": null,
"unit": "CAQI",
"timestamp": "2021-04-06T16:57:57.602Z"
}
},
"custom.airConditionerOptionalMode": {
"supportedAcOptionalMode": {
"value": null,
"timestamp": "2021-04-06T16:57:57.659Z"
},
"acOptionalMode": {
"value": null,
"timestamp": "2021-04-06T16:57:57.659Z"
}
},
"switch": {
"switch": {
"value": null,
"timestamp": "2021-04-06T16:44:10.518Z"
}
},
"custom.airConditionerTropicalNightMode": {
"acTropicalNightModeLevel": {
"value": null,
"timestamp": "2021-04-06T16:44:10.498Z"
}
},
"ocf": {
"st": {
"value": null,
"timestamp": "2021-04-06T16:44:10.472Z"
},
"mndt": {
"value": null,
"timestamp": "2021-04-06T16:44:10.472Z"
},
"mnfv": {
"value": null,
"timestamp": "2021-04-06T16:44:10.472Z"
},
"mnhw": {
"value": null,
"timestamp": "2021-04-06T16:44:10.472Z"
},
"di": {
"value": null,
"timestamp": "2021-04-06T16:44:10.472Z"
},
"mnsl": {
"value": null,
"timestamp": "2021-04-06T16:44:10.472Z"
},
"dmv": {
"value": null,
"timestamp": "2021-04-06T16:44:10.472Z"
},
"n": {
"value": null,
"timestamp": "2021-04-06T16:44:10.472Z"
},
"mnmo": {
"value": null,
"timestamp": "2021-04-06T16:44:10.472Z"
},
"vid": {
"value": null,
"timestamp": "2021-04-06T16:44:10.472Z"
},
"mnmn": {
"value": null,
"timestamp": "2021-04-06T16:44:10.472Z"
},
"mnml": {
"value": null,
"timestamp": "2021-04-06T16:44:10.472Z"
},
"mnpv": {
"value": null,
"timestamp": "2021-04-06T16:44:10.472Z"
},
"mnos": {
"value": null,
"timestamp": "2021-04-06T16:44:10.472Z"
},
"pi": {
"value": null,
"timestamp": "2021-04-06T16:44:10.472Z"
},
"icv": {
"value": null,
"timestamp": "2021-04-06T16:44:10.472Z"
}
},
"airConditionerFanMode": {
"fanMode": {
"value": null,
"timestamp": "2021-04-06T16:44:10.381Z"
},
"supportedAcFanModes": {
"value": ["auto", "low", "medium", "high", "turbo"],
"timestamp": "2024-09-10T10:26:28.605Z"
},
"availableAcFanModes": {
"value": null
}
},
"custom.disabledCapabilities": {
"disabledCapabilities": {
"value": [
"remoteControlStatus",
"airQualitySensor",
"dustSensor",
"odorSensor",
"veryFineDustSensor",
"custom.dustFilter",
"custom.deodorFilter",
"custom.deviceReportStateConfiguration",
"audioVolume",
"custom.autoCleaningMode",
"custom.airConditionerTropicalNightMode",
"custom.airConditionerOdorController",
"demandResponseLoadControl",
"relativeHumidityMeasurement"
],
"timestamp": "2024-09-10T10:26:28.605Z"
}
},
"fanOscillationMode": {
"supportedFanOscillationModes": {
"value": null,
"timestamp": "2021-04-06T16:44:10.325Z"
},
"availableFanOscillationModes": {
"value": null
},
"fanOscillationMode": {
"value": "fixed",
"timestamp": "2025-02-08T00:44:53.247Z"
}
},
"temperatureMeasurement": {
"temperatureRange": {
"value": null
},
"temperature": {
"value": null,
"timestamp": "2021-04-06T16:44:10.373Z"
}
},
"dustSensor": {
"dustLevel": {
"value": null,
"unit": "\u03bcg/m^3",
"timestamp": "2021-04-06T16:44:10.122Z"
},
"fineDustLevel": {
"value": null,
"unit": "\u03bcg/m^3",
"timestamp": "2021-04-06T16:44:10.122Z"
}
},
"custom.deviceReportStateConfiguration": {
"reportStateRealtimePeriod": {
"value": null,
"timestamp": "2021-04-06T16:44:09.800Z"
},
"reportStateRealtime": {
"value": null,
"timestamp": "2021-04-06T16:44:09.800Z"
},
"reportStatePeriod": {
"value": null,
"timestamp": "2021-04-06T16:44:09.800Z"
}
},
"thermostatCoolingSetpoint": {
"coolingSetpointRange": {
"value": null
},
"coolingSetpoint": {
"value": null,
"timestamp": "2021-04-06T16:43:59.136Z"
}
},
"demandResponseLoadControl": {
"drlcStatus": {
"value": null,
"timestamp": "2021-04-06T16:43:54.748Z"
}
},
"audioVolume": {
"volume": {
"value": null,
"unit": "%",
"timestamp": "2021-04-06T16:43:53.541Z"
}
},
"powerConsumptionReport": {
"powerConsumption": {
"value": null,
"timestamp": "2021-04-06T16:43:53.364Z"
}
},
"custom.autoCleaningMode": {
"supportedAutoCleaningModes": {
"value": null
},
"timedCleanDuration": {
"value": null
},
"operatingState": {
"value": null
},
"timedCleanDurationRange": {
"value": null
},
"supportedOperatingStates": {
"value": null
},
"progress": {
"value": null
},
"autoCleaningMode": {
"value": null,
"timestamp": "2021-04-06T16:43:53.344Z"
}
},
"custom.dustFilter": {
"dustFilterUsageStep": {
"value": null,
"timestamp": "2021-04-06T16:43:39.145Z"
},
"dustFilterUsage": {
"value": null,
"timestamp": "2021-04-06T16:43:39.145Z"
},
"dustFilterLastResetDate": {
"value": null,
"timestamp": "2021-04-06T16:43:39.145Z"
},
"dustFilterStatus": {
"value": null,
"timestamp": "2021-04-06T16:43:39.145Z"
},
"dustFilterCapacity": {
"value": null,
"timestamp": "2021-04-06T16:43:39.145Z"
},
"dustFilterResetType": {
"value": null,
"timestamp": "2021-04-06T16:43:39.145Z"
}
},
"odorSensor": {
"odorLevel": {
"value": null,
"timestamp": "2021-04-06T16:43:38.992Z"
}
},
"remoteControlStatus": {
"remoteControlEnabled": {
"value": null,
"timestamp": "2021-04-06T16:43:39.097Z"
}
},
"custom.deodorFilter": {
"deodorFilterCapacity": {
"value": null,
"timestamp": "2021-04-06T16:43:39.118Z"
},
"deodorFilterLastResetDate": {
"value": null,
"timestamp": "2021-04-06T16:43:39.118Z"
},
"deodorFilterStatus": {
"value": null,
"timestamp": "2021-04-06T16:43:39.118Z"
},
"deodorFilterResetType": {
"value": null,
"timestamp": "2021-04-06T16:43:39.118Z"
},
"deodorFilterUsage": {
"value": null,
"timestamp": "2021-04-06T16:43:39.118Z"
},
"deodorFilterUsageStep": {
"value": null,
"timestamp": "2021-04-06T16:43:39.118Z"
}
},
"custom.energyType": {
"energyType": {
"value": null,
"timestamp": "2021-04-06T16:43:38.843Z"
},
"energySavingSupport": {
"value": null
},
"drMaxDuration": {
"value": null
},
"energySavingLevel": {
"value": null
},
"energySavingInfo": {
"value": null
},
"supportedEnergySavingLevels": {
"value": null
},
"energySavingOperation": {
"value": null
},
"notificationTemplateID": {
"value": null
},
"energySavingOperationSupport": {
"value": null
}
},
"veryFineDustSensor": {
"veryFineDustLevel": {
"value": null,
"unit": "\u03bcg/m^3",
"timestamp": "2021-04-06T16:43:38.529Z"
}
}
},
"main": {
"relativeHumidityMeasurement": {
"humidity": {
"value": 60,
"unit": "%",
"timestamp": "2024-12-30T13:10:23.759Z"
}
},
"custom.airConditionerOdorController": {
"airConditionerOdorControllerProgress": {
"value": null,
"timestamp": "2021-04-06T16:43:37.555Z"
},
"airConditionerOdorControllerState": {
"value": null,
"timestamp": "2021-04-06T16:43:37.555Z"
}
},
"custom.thermostatSetpointControl": {
"minimumSetpoint": {
"value": 16,
"unit": "C",
"timestamp": "2025-01-08T06:30:58.307Z"
},
"maximumSetpoint": {
"value": 30,
"unit": "C",
"timestamp": "2024-09-10T10:26:28.781Z"
}
},
"airConditionerMode": {
"availableAcModes": {
"value": null
},
"supportedAcModes": {
"value": ["cool", "dry", "wind", "auto", "heat"],
"timestamp": "2024-09-10T10:26:28.781Z"
},
"airConditionerMode": {
"value": "heat",
"timestamp": "2025-02-09T09:14:39.642Z"
}
},
"custom.spiMode": {
"spiMode": {
"value": "off",
"timestamp": "2025-02-09T09:14:39.642Z"
}
},
"samsungce.dongleSoftwareInstallation": {
"status": {
"value": "completed",
"timestamp": "2021-12-29T01:36:51.289Z"
}
},
"samsungce.deviceIdentification": {
"micomAssayCode": {
"value": null
},
"modelName": {
"value": null
},
"serialNumber": {
"value": null
},
"serialNumberExtra": {
"value": null
},
"modelClassificationCode": {
"value": null
},
"description": {
"value": null
},
"releaseYear": {
"value": null
},
"binaryId": {
"value": "ARTIK051_KRAC_18K",
"timestamp": "2025-02-08T00:44:53.855Z"
}
},
"airQualitySensor": {
"airQuality": {
"value": null,
"unit": "CAQI",
"timestamp": "2021-04-06T16:43:37.208Z"
}
},
"custom.airConditionerOptionalMode": {
"supportedAcOptionalMode": {
"value": ["off", "windFree"],
"timestamp": "2024-09-10T10:26:28.781Z"
},
"acOptionalMode": {
"value": "off",
"timestamp": "2025-02-09T09:14:39.642Z"
}
},
"switch": {
"switch": {
"value": "off",
"timestamp": "2025-02-09T16:37:54.072Z"
}
},
"custom.airConditionerTropicalNightMode": {
"acTropicalNightModeLevel": {
"value": 0,
"timestamp": "2025-02-09T09:14:39.642Z"
}
},
"ocf": {
"st": {
"value": null,
"timestamp": "2021-04-06T16:43:35.933Z"
},
"mndt": {
"value": null,
"timestamp": "2021-04-06T16:43:35.912Z"
},
"mnfv": {
"value": "0.1.0",
"timestamp": "2024-09-10T10:26:28.552Z"
},
"mnhw": {
"value": "1.0",
"timestamp": "2024-09-10T10:26:28.552Z"
},
"di": {
"value": "96a5ef74-5832-a84b-f1f7-ca799957065d",
"timestamp": "2024-09-10T10:26:28.552Z"
},
"mnsl": {
"value": null,
"timestamp": "2021-04-06T16:43:35.803Z"
},
"dmv": {
"value": "res.1.1.0,sh.1.1.0",
"timestamp": "2024-09-10T10:26:28.552Z"
},
"n": {
"value": "[room a/c] Samsung",
"timestamp": "2024-09-10T10:26:28.552Z"
},
"mnmo": {
"value": "ARTIK051_KRAC_18K|10193441|60010132001111110200000000000000",
"timestamp": "2024-09-10T10:26:28.781Z"
},
"vid": {
"value": "DA-AC-RAC-000001",
"timestamp": "2024-09-10T10:26:28.552Z"
},
"mnmn": {
"value": "Samsung Electronics",
"timestamp": "2024-09-10T10:26:28.552Z"
},
"mnml": {
"value": "http://www.samsung.com",
"timestamp": "2024-09-10T10:26:28.552Z"
},
"mnpv": {
"value": "0G3MPDCKA00010E",
"timestamp": "2024-09-10T10:26:28.552Z"
},
"mnos": {
"value": "TizenRT2.0",
"timestamp": "2024-09-10T10:26:28.552Z"
},
"pi": {
"value": "96a5ef74-5832-a84b-f1f7-ca799957065d",
"timestamp": "2024-09-10T10:26:28.552Z"
},
"icv": {
"value": "core.1.1.0",
"timestamp": "2024-09-10T10:26:28.552Z"
}
},
"airConditionerFanMode": {
"fanMode": {
"value": "low",
"timestamp": "2025-02-09T09:14:39.249Z"
},
"supportedAcFanModes": {
"value": ["auto", "low", "medium", "high", "turbo"],
"timestamp": "2025-02-09T09:14:39.249Z"
},
"availableAcFanModes": {
"value": null
}
},
"custom.disabledCapabilities": {
"disabledCapabilities": {
"value": [
"remoteControlStatus",
"airQualitySensor",
"dustSensor",
"veryFineDustSensor",
"custom.dustFilter",
"custom.deodorFilter",
"custom.deviceReportStateConfiguration",
"samsungce.dongleSoftwareInstallation",
"demandResponseLoadControl",
"custom.airConditionerOdorController"
],
"timestamp": "2025-02-09T09:14:39.642Z"
}
},
"samsungce.driverVersion": {
"versionNumber": {
"value": 24070101,
"timestamp": "2024-09-04T06:35:09.557Z"
}
},
"fanOscillationMode": {
"supportedFanOscillationModes": {
"value": null,
"timestamp": "2021-04-06T16:43:35.782Z"
},
"availableFanOscillationModes": {
"value": null
},
"fanOscillationMode": {
"value": "fixed",
"timestamp": "2025-02-09T09:14:39.249Z"
}
},
"temperatureMeasurement": {
"temperatureRange": {
"value": null
},
"temperature": {
"value": 25,
"unit": "C",
"timestamp": "2025-02-09T16:33:29.164Z"
}
},
"dustSensor": {
"dustLevel": {
"value": null,
"unit": "\u03bcg/m^3",
"timestamp": "2021-04-06T16:43:35.665Z"
},
"fineDustLevel": {
"value": null,
"unit": "\u03bcg/m^3",
"timestamp": "2021-04-06T16:43:35.665Z"
}
},
"custom.deviceReportStateConfiguration": {
"reportStateRealtimePeriod": {
"value": null,
"timestamp": "2021-04-06T16:43:35.643Z"
},
"reportStateRealtime": {
"value": null,
"timestamp": "2021-04-06T16:43:35.643Z"
},
"reportStatePeriod": {
"value": null,
"timestamp": "2021-04-06T16:43:35.643Z"
}
},
"thermostatCoolingSetpoint": {
"coolingSetpointRange": {
"value": null
},
"coolingSetpoint": {
"value": 25,
"unit": "C",
"timestamp": "2025-02-09T09:15:11.608Z"
}
},
"custom.disabledComponents": {
"disabledComponents": {
"value": ["1"],
"timestamp": "2025-02-09T09:14:39.642Z"
}
},
"demandResponseLoadControl": {
"drlcStatus": {
"value": {
"drlcType": 1,
"drlcLevel": -1,
"start": "1970-01-01T00:00:00Z",
"duration": 0,
"override": false
},
"timestamp": "2024-09-10T10:26:28.781Z"
}
},
"audioVolume": {
"volume": {
"value": 100,
"unit": "%",
"timestamp": "2025-02-09T09:14:39.642Z"
}
},
"powerConsumptionReport": {
"powerConsumption": {
"value": {
"energy": 2247300,
"deltaEnergy": 400,
"power": 0,
"powerEnergy": 0.0,
"persistedEnergy": 2247300,
"energySaved": 0,
"start": "2025-02-09T15:45:29Z",
"end": "2025-02-09T16:15:33Z"
},
"timestamp": "2025-02-09T16:15:33.639Z"
}
},
"custom.autoCleaningMode": {
"supportedAutoCleaningModes": {
"value": null
},
"timedCleanDuration": {
"value": null
},
"operatingState": {
"value": null
},
"timedCleanDurationRange": {
"value": null
},
"supportedOperatingStates": {
"value": null
},
"progress": {
"value": null
},
"autoCleaningMode": {
"value": "off",
"timestamp": "2025-02-09T09:14:39.642Z"
}
},
"refresh": {},
"execute": {
"data": {
"value": {
"payload": {
"rt": ["oic.r.temperature"],
"if": ["oic.if.baseline", "oic.if.a"],
"range": [16.0, 30.0],
"units": "C",
"temperature": 22.0
}
},
"data": {
"href": "/temperature/desired/0"
},
"timestamp": "2023-07-19T03:07:43.270Z"
}
},
"samsungce.selfCheck": {
"result": {
"value": null
},
"supportedActions": {
"value": ["start"],
"timestamp": "2024-09-04T06:35:09.557Z"
},
"progress": {
"value": null
},
"errors": {
"value": [],
"timestamp": "2025-02-08T00:44:53.349Z"
},
"status": {
"value": "ready",
"timestamp": "2025-02-08T00:44:53.549Z"
}
},
"custom.dustFilter": {
"dustFilterUsageStep": {
"value": null,
"timestamp": "2021-04-06T16:43:35.527Z"
},
"dustFilterUsage": {
"value": null,
"timestamp": "2021-04-06T16:43:35.527Z"
},
"dustFilterLastResetDate": {
"value": null,
"timestamp": "2021-04-06T16:43:35.527Z"
},
"dustFilterStatus": {
"value": null,
"timestamp": "2021-04-06T16:43:35.527Z"
},
"dustFilterCapacity": {
"value": null,
"timestamp": "2021-04-06T16:43:35.527Z"
},
"dustFilterResetType": {
"value": null,
"timestamp": "2021-04-06T16:43:35.527Z"
}
},
"remoteControlStatus": {
"remoteControlEnabled": {
"value": null,
"timestamp": "2021-04-06T16:43:35.379Z"
}
},
"custom.deodorFilter": {
"deodorFilterCapacity": {
"value": null,
"timestamp": "2021-04-06T16:43:35.502Z"
},
"deodorFilterLastResetDate": {
"value": null,
"timestamp": "2021-04-06T16:43:35.502Z"
},
"deodorFilterStatus": {
"value": null,
"timestamp": "2021-04-06T16:43:35.502Z"
},
"deodorFilterResetType": {
"value": null,
"timestamp": "2021-04-06T16:43:35.502Z"
},
"deodorFilterUsage": {
"value": null,
"timestamp": "2021-04-06T16:43:35.502Z"
},
"deodorFilterUsageStep": {
"value": null,
"timestamp": "2021-04-06T16:43:35.502Z"
}
},
"custom.energyType": {
"energyType": {
"value": "1.0",
"timestamp": "2024-09-10T10:26:28.781Z"
},
"energySavingSupport": {
"value": false,
"timestamp": "2021-12-29T07:29:17.526Z"
},
"drMaxDuration": {
"value": null
},
"energySavingLevel": {
"value": null
},
"energySavingInfo": {
"value": null
},
"supportedEnergySavingLevels": {
"value": null
},
"energySavingOperation": {
"value": null
},
"notificationTemplateID": {
"value": null
},
"energySavingOperationSupport": {
"value": null
}
},
"samsungce.softwareUpdate": {
"targetModule": {
"value": null
},
"otnDUID": {
"value": "43CEZFTFFL7Z2",
"timestamp": "2025-02-08T00:44:53.855Z"
},
"lastUpdatedDate": {
"value": null
},
"availableModules": {
"value": [],
"timestamp": "2025-02-08T00:44:53.855Z"
},
"newVersionAvailable": {
"value": false,
"timestamp": "2025-02-08T00:44:53.855Z"
},
"operatingState": {
"value": null
},
"progress": {
"value": null
}
},
"veryFineDustSensor": {
"veryFineDustLevel": {
"value": null,
"unit": "\u03bcg/m^3",
"timestamp": "2021-04-06T16:43:35.363Z"
}
}
}
}
}

View File

@ -0,0 +1,731 @@
{
"components": {
"main": {
"samsungce.unavailableCapabilities": {
"unavailableCommands": {
"value": ["custom.spiMode.setSpiMode"],
"timestamp": "2025-02-09T05:44:01.769Z"
}
},
"relativeHumidityMeasurement": {
"humidity": {
"value": 42,
"unit": "%",
"timestamp": "2025-02-09T17:02:45.042Z"
}
},
"custom.thermostatSetpointControl": {
"minimumSetpoint": {
"value": 16,
"unit": "C",
"timestamp": "2025-02-09T15:42:13.444Z"
},
"maximumSetpoint": {
"value": 30,
"unit": "C",
"timestamp": "2025-02-09T15:42:13.444Z"
}
},
"airConditionerMode": {
"availableAcModes": {
"value": [],
"timestamp": "2025-02-09T14:35:56.800Z"
},
"supportedAcModes": {
"value": ["auto", "cool", "dry", "wind", "heat"],
"timestamp": "2025-02-09T15:42:13.444Z"
},
"airConditionerMode": {
"value": "cool",
"timestamp": "2025-02-09T04:52:00.923Z"
}
},
"custom.spiMode": {
"spiMode": {
"value": null
}
},
"custom.airConditionerOptionalMode": {
"supportedAcOptionalMode": {
"value": [
"off",
"sleep",
"quiet",
"smart",
"speed",
"windFree",
"windFreeSleep"
],
"timestamp": "2025-02-09T15:42:13.444Z"
},
"acOptionalMode": {
"value": "off",
"timestamp": "2025-02-09T05:44:01.853Z"
}
},
"samsungce.airConditionerBeep": {
"beep": {
"value": "off",
"timestamp": "2025-02-09T04:52:00.923Z"
}
},
"ocf": {
"st": {
"value": null
},
"mndt": {
"value": null
},
"mnfv": {
"value": "ARA-WW-TP1-22-COMMON_11240702",
"timestamp": "2025-02-09T15:42:12.723Z"
},
"mnhw": {
"value": "Realtek",
"timestamp": "2025-02-09T15:42:12.723Z"
},
"di": {
"value": "4ece486b-89db-f06a-d54d-748b676b4d8e",
"timestamp": "2025-02-09T15:42:12.714Z"
},
"mnsl": {
"value": "http://www.samsung.com",
"timestamp": "2025-02-09T15:42:12.723Z"
},
"dmv": {
"value": "res.1.1.0,sh.1.1.0",
"timestamp": "2025-02-09T15:42:12.714Z"
},
"n": {
"value": "Samsung-Room-Air-Conditioner",
"timestamp": "2025-02-09T15:42:12.714Z"
},
"mnmo": {
"value": "ARA-WW-TP1-22-COMMON|10229641|60010523001511014600083200800000",
"timestamp": "2025-02-09T15:42:13.444Z"
},
"vid": {
"value": "DA-AC-RAC-01001",
"timestamp": "2025-02-09T15:42:12.723Z"
},
"mnmn": {
"value": "Samsung Electronics",
"timestamp": "2025-02-09T15:42:12.723Z"
},
"mnml": {
"value": "http://www.samsung.com",
"timestamp": "2025-02-09T15:42:12.723Z"
},
"mnpv": {
"value": "DAWIT 2.0",
"timestamp": "2025-02-09T15:42:12.723Z"
},
"mnos": {
"value": "TizenRT 3.1",
"timestamp": "2025-02-09T15:42:12.723Z"
},
"pi": {
"value": "4ece486b-89db-f06a-d54d-748b676b4d8e",
"timestamp": "2025-02-09T15:42:12.723Z"
},
"icv": {
"value": "core.1.1.0",
"timestamp": "2025-02-09T15:42:12.714Z"
}
},
"custom.disabledCapabilities": {
"disabledCapabilities": {
"value": [
"custom.deodorFilter",
"custom.electricHepaFilter",
"custom.periodicSensing",
"custom.doNotDisturbMode",
"samsungce.deviceInfoPrivate",
"samsungce.quickControl",
"samsungce.welcomeCooling",
"samsungce.airConditionerBeep",
"samsungce.airConditionerLighting",
"samsungce.individualControlLock",
"samsungce.alwaysOnSensing",
"samsungce.buttonDisplayCondition",
"airQualitySensor",
"dustSensor",
"odorSensor",
"veryFineDustSensor",
"custom.spiMode",
"audioNotification"
],
"timestamp": "2025-02-09T15:42:13.444Z"
}
},
"samsungce.driverVersion": {
"versionNumber": {
"value": 24100102,
"timestamp": "2025-01-28T21:31:35.935Z"
}
},
"sec.diagnosticsInformation": {
"logType": {
"value": ["errCode", "dump"],
"timestamp": "2025-02-09T15:42:13.444Z"
},
"endpoint": {
"value": "SSM",
"timestamp": "2025-02-09T15:42:13.444Z"
},
"minVersion": {
"value": "1.0",
"timestamp": "2025-02-09T15:42:13.444Z"
},
"signinPermission": {
"value": null
},
"setupId": {
"value": "010",
"timestamp": "2025-02-09T15:42:13.444Z"
},
"protocolType": {
"value": "wifi_https",
"timestamp": "2025-02-09T15:42:13.444Z"
},
"tsId": {
"value": "DA01",
"timestamp": "2025-02-09T15:42:13.444Z"
},
"mnId": {
"value": "0AJT",
"timestamp": "2025-02-09T15:42:13.444Z"
},
"dumpType": {
"value": "file",
"timestamp": "2025-02-09T15:42:13.444Z"
}
},
"fanOscillationMode": {
"supportedFanOscillationModes": {
"value": ["fixed", "vertical", "horizontal", "all"],
"timestamp": "2025-02-09T15:42:13.444Z"
},
"availableFanOscillationModes": {
"value": null
},
"fanOscillationMode": {
"value": "fixed",
"timestamp": "2025-02-09T15:42:13.444Z"
}
},
"custom.periodicSensing": {
"automaticExecutionSetting": {
"value": null
},
"automaticExecutionMode": {
"value": null
},
"supportedAutomaticExecutionSetting": {
"value": null
},
"supportedAutomaticExecutionMode": {
"value": null
},
"periodicSensing": {
"value": null
},
"periodicSensingInterval": {
"value": null
},
"lastSensingTime": {
"value": null
},
"lastSensingLevel": {
"value": null
},
"periodicSensingStatus": {
"value": null
}
},
"demandResponseLoadControl": {
"drlcStatus": {
"value": {
"drlcType": 1,
"drlcLevel": 0,
"start": "1970-01-01T00:00:00Z",
"duration": 0,
"override": false
},
"timestamp": "2025-02-09T15:42:13.444Z"
}
},
"audioVolume": {
"volume": {
"value": 0,
"unit": "%",
"timestamp": "2025-02-09T04:52:00.923Z"
}
},
"powerConsumptionReport": {
"powerConsumption": {
"value": {
"energy": 13836,
"deltaEnergy": 0,
"power": 0,
"powerEnergy": 0.0,
"persistedEnergy": 13836,
"energySaved": 0,
"persistedSavedEnergy": 0,
"start": "2025-02-09T16:08:15Z",
"end": "2025-02-09T17:02:44Z"
},
"timestamp": "2025-02-09T17:02:44.883Z"
}
},
"custom.autoCleaningMode": {
"supportedAutoCleaningModes": {
"value": null
},
"timedCleanDuration": {
"value": null
},
"operatingState": {
"value": null
},
"timedCleanDurationRange": {
"value": null
},
"supportedOperatingStates": {
"value": null
},
"progress": {
"value": null
},
"autoCleaningMode": {
"value": "on",
"timestamp": "2025-02-09T05:44:02.014Z"
}
},
"samsungce.individualControlLock": {
"lockState": {
"value": null
}
},
"audioNotification": {},
"execute": {
"data": {
"value": null
}
},
"samsungce.welcomeCooling": {
"latestRequestId": {
"value": null
},
"operatingState": {
"value": null
}
},
"sec.wifiConfiguration": {
"autoReconnection": {
"value": true,
"timestamp": "2025-02-09T15:42:13.444Z"
},
"minVersion": {
"value": "1.0",
"timestamp": "2025-02-09T15:42:13.444Z"
},
"supportedWiFiFreq": {
"value": ["2.4G"],
"timestamp": "2025-02-09T15:42:13.444Z"
},
"supportedAuthType": {
"value": ["OPEN", "WEP", "WPA-PSK", "WPA2-PSK", "SAE"],
"timestamp": "2025-02-09T15:42:13.444Z"
},
"protocolType": {
"value": ["helper_hotspot", "ble_ocf"],
"timestamp": "2025-02-09T15:42:13.444Z"
}
},
"samsungce.selfCheck": {
"result": {
"value": null
},
"supportedActions": {
"value": ["start", "cancel"],
"timestamp": "2025-02-09T04:52:00.923Z"
},
"progress": {
"value": 1,
"unit": "%",
"timestamp": "2025-02-09T04:52:00.923Z"
},
"errors": {
"value": [],
"timestamp": "2025-02-09T15:42:13.444Z"
},
"status": {
"value": "ready",
"timestamp": "2025-02-09T04:52:00.923Z"
}
},
"custom.dustFilter": {
"dustFilterUsageStep": {
"value": 1,
"timestamp": "2025-02-09T12:00:10.310Z"
},
"dustFilterUsage": {
"value": 12,
"timestamp": "2025-02-09T12:00:10.310Z"
},
"dustFilterLastResetDate": {
"value": null
},
"dustFilterStatus": {
"value": "normal",
"timestamp": "2025-02-09T12:00:10.310Z"
},
"dustFilterCapacity": {
"value": 500,
"unit": "Hour",
"timestamp": "2025-02-09T12:00:10.310Z"
},
"dustFilterResetType": {
"value": ["replaceable", "washable"],
"timestamp": "2025-02-09T12:00:10.310Z"
}
},
"custom.energyType": {
"energyType": {
"value": "1.0",
"timestamp": "2025-01-28T21:31:39.517Z"
},
"energySavingSupport": {
"value": true,
"timestamp": "2025-01-28T21:38:35.560Z"
},
"drMaxDuration": {
"value": 99999999,
"unit": "min",
"timestamp": "2025-01-28T21:31:37.357Z"
},
"energySavingLevel": {
"value": null
},
"energySavingInfo": {
"value": null
},
"supportedEnergySavingLevels": {
"value": null
},
"energySavingOperation": {
"value": false,
"timestamp": "2025-02-09T15:42:13.444Z"
},
"notificationTemplateID": {
"value": null
},
"energySavingOperationSupport": {
"value": true,
"timestamp": "2025-01-28T21:38:35.731Z"
}
},
"bypassable": {
"bypassStatus": {
"value": "bypassed",
"timestamp": "2025-01-28T21:31:35.935Z"
}
},
"samsungce.airQualityHealthConcern": {
"supportedAirQualityHealthConcerns": {
"value": null
},
"airQualityHealthConcern": {
"value": null
}
},
"samsungce.softwareUpdate": {
"targetModule": {
"value": {},
"timestamp": "2025-02-05T20:07:11.459Z"
},
"otnDUID": {
"value": "U7CB2ZD4QPDUC",
"timestamp": "2025-02-09T15:42:13.444Z"
},
"lastUpdatedDate": {
"value": null
},
"availableModules": {
"value": [],
"timestamp": "2025-01-28T21:31:38.089Z"
},
"newVersionAvailable": {
"value": false,
"timestamp": "2025-02-09T15:42:13.444Z"
},
"operatingState": {
"value": "none",
"timestamp": "2025-02-05T20:07:11.459Z"
},
"progress": {
"value": null
}
},
"veryFineDustSensor": {
"veryFineDustLevel": {
"value": null
}
},
"custom.veryFineDustFilter": {
"veryFineDustFilterStatus": {
"value": null
},
"veryFineDustFilterResetType": {
"value": null
},
"veryFineDustFilterUsage": {
"value": null
},
"veryFineDustFilterLastResetDate": {
"value": null
},
"veryFineDustFilterUsageStep": {
"value": null
},
"veryFineDustFilterCapacity": {
"value": null
}
},
"samsungce.silentAction": {},
"custom.airConditionerOdorController": {
"airConditionerOdorControllerProgress": {
"value": 0,
"timestamp": "2025-02-09T04:52:00.923Z"
},
"airConditionerOdorControllerState": {
"value": "off",
"timestamp": "2025-02-09T04:52:00.923Z"
}
},
"samsungce.deviceIdentification": {
"micomAssayCode": {
"value": null
},
"modelName": {
"value": null
},
"serialNumber": {
"value": null
},
"serialNumberExtra": {
"value": null
},
"modelClassificationCode": {
"value": null
},
"description": {
"value": null
},
"releaseYear": {
"value": 21,
"timestamp": "2025-01-28T21:31:35.935Z"
},
"binaryId": {
"value": "ARA-WW-TP1-22-COMMON",
"timestamp": "2025-02-09T15:42:13.444Z"
}
},
"airQualitySensor": {
"airQuality": {
"value": null
}
},
"switch": {
"switch": {
"value": "off",
"timestamp": "2025-02-09T15:42:13.444Z"
}
},
"samsungce.quickControl": {
"version": {
"value": null
}
},
"custom.airConditionerTropicalNightMode": {
"acTropicalNightModeLevel": {
"value": 6,
"timestamp": "2025-02-09T04:52:00.923Z"
}
},
"airConditionerFanMode": {
"fanMode": {
"value": "high",
"timestamp": "2025-02-09T14:07:45.816Z"
},
"supportedAcFanModes": {
"value": ["auto", "low", "medium", "high", "turbo"],
"timestamp": "2025-02-09T15:42:13.444Z"
},
"availableAcFanModes": {
"value": ["auto", "low", "medium", "high", "turbo"],
"timestamp": "2025-02-09T05:44:01.769Z"
}
},
"samsungce.dustFilterAlarm": {
"alarmThreshold": {
"value": 500,
"unit": "Hour",
"timestamp": "2025-02-09T12:00:10.310Z"
},
"supportedAlarmThresholds": {
"value": [180, 300, 500, 700],
"unit": "Hour",
"timestamp": "2025-02-09T15:42:13.444Z"
}
},
"custom.electricHepaFilter": {
"electricHepaFilterCapacity": {
"value": null
},
"electricHepaFilterUsageStep": {
"value": null
},
"electricHepaFilterLastResetDate": {
"value": null
},
"electricHepaFilterStatus": {
"value": null
},
"electricHepaFilterUsage": {
"value": null
},
"electricHepaFilterResetType": {
"value": null
}
},
"samsungce.airConditionerLighting": {
"supportedLightingLevels": {
"value": ["on", "off"],
"timestamp": "2025-02-09T15:42:13.444Z"
},
"lighting": {
"value": "on",
"timestamp": "2025-02-09T09:30:03.213Z"
}
},
"samsungce.buttonDisplayCondition": {
"switch": {
"value": "enabled",
"timestamp": "2025-02-09T05:17:41.282Z"
}
},
"temperatureMeasurement": {
"temperatureRange": {
"value": null
},
"temperature": {
"value": 27,
"unit": "C",
"timestamp": "2025-02-09T16:38:17.028Z"
}
},
"dustSensor": {
"dustLevel": {
"value": null
},
"fineDustLevel": {
"value": null
}
},
"sec.calmConnectionCare": {
"role": {
"value": ["things"],
"timestamp": "2025-02-09T15:42:13.444Z"
},
"protocols": {
"value": null
},
"version": {
"value": "1.0",
"timestamp": "2025-02-09T15:42:13.444Z"
}
},
"custom.deviceReportStateConfiguration": {
"reportStateRealtimePeriod": {
"value": "disabled",
"timestamp": "2025-02-09T05:17:39.792Z"
},
"reportStateRealtime": {
"value": {
"state": "disabled"
},
"timestamp": "2025-02-09T15:42:13.444Z"
},
"reportStatePeriod": {
"value": "enabled",
"timestamp": "2025-02-09T05:17:39.792Z"
}
},
"thermostatCoolingSetpoint": {
"coolingSetpointRange": {
"value": {
"minimum": 16,
"maximum": 30,
"step": 1
},
"unit": "C",
"timestamp": "2025-02-09T05:17:41.533Z"
},
"coolingSetpoint": {
"value": 23,
"unit": "C",
"timestamp": "2025-02-09T14:07:45.643Z"
}
},
"samsungce.alwaysOnSensing": {
"origins": {
"value": [],
"timestamp": "2025-02-09T15:42:13.444Z"
},
"alwaysOn": {
"value": "off",
"timestamp": "2025-02-09T15:42:13.444Z"
}
},
"refresh": {},
"odorSensor": {
"odorLevel": {
"value": null
}
},
"custom.deodorFilter": {
"deodorFilterCapacity": {
"value": null
},
"deodorFilterLastResetDate": {
"value": null
},
"deodorFilterStatus": {
"value": null
},
"deodorFilterResetType": {
"value": null
},
"deodorFilterUsage": {
"value": null
},
"deodorFilterUsageStep": {
"value": null
}
},
"custom.doNotDisturbMode": {
"doNotDisturb": {
"value": null
},
"startTime": {
"value": null
},
"endTime": {
"value": null
}
}
}
}
}

View File

@ -0,0 +1,600 @@
{
"components": {
"main": {
"doorControl": {
"door": {
"value": null
}
},
"samsungce.kitchenDeviceDefaults": {
"defaultOperationTime": {
"value": 30,
"timestamp": "2022-03-23T15:59:12.609Z"
},
"defaultOvenMode": {
"value": "MicroWave",
"timestamp": "2025-02-08T21:13:36.289Z"
},
"defaultOvenSetpoint": {
"value": null
}
},
"samsungce.deviceIdentification": {
"micomAssayCode": {
"value": null
},
"modelName": {
"value": null
},
"serialNumber": {
"value": null
},
"serialNumberExtra": {
"value": null
},
"modelClassificationCode": {
"value": null
},
"description": {
"value": null
},
"releaseYear": {
"value": null
},
"binaryId": {
"value": "TP2X_DA-KS-MICROWAVE-0101X",
"timestamp": "2025-02-08T21:13:36.256Z"
}
},
"switch": {
"switch": {
"value": "off",
"timestamp": "2025-02-09T00:11:12.010Z"
}
},
"ocf": {
"st": {
"value": null
},
"mndt": {
"value": null
},
"mnfv": {
"value": "AKS-WW-TP2-20-MICROWAVE-OTR_40230125",
"timestamp": "2023-07-03T06:44:54.757Z"
},
"mnhw": {
"value": "MediaTek",
"timestamp": "2022-03-23T15:59:12.742Z"
},
"di": {
"value": "2bad3237-4886-e699-1b90-4a51a3d55c8a",
"timestamp": "2022-03-23T15:59:12.742Z"
},
"mnsl": {
"value": "http://www.samsung.com",
"timestamp": "2022-03-23T15:59:12.742Z"
},
"dmv": {
"value": "res.1.1.0,sh.1.1.0",
"timestamp": "2023-07-03T22:00:58.832Z"
},
"n": {
"value": "Samsung Microwave",
"timestamp": "2023-07-03T06:44:54.757Z"
},
"mnmo": {
"value": "TP2X_DA-KS-MICROWAVE-0101X|40436241|50040100011411000200000000000000",
"timestamp": "2023-07-03T06:44:54.757Z"
},
"vid": {
"value": "DA-KS-MICROWAVE-0101X",
"timestamp": "2022-03-23T15:59:12.742Z"
},
"mnmn": {
"value": "Samsung Electronics",
"timestamp": "2022-03-23T15:59:12.742Z"
},
"mnml": {
"value": "http://www.samsung.com",
"timestamp": "2022-03-23T15:59:12.742Z"
},
"mnpv": {
"value": "DAWIT 3.0",
"timestamp": "2023-07-03T06:44:54.757Z"
},
"mnos": {
"value": "TizenRT 2.0 + IPv6",
"timestamp": "2023-07-03T06:44:54.757Z"
},
"pi": {
"value": "2bad3237-4886-e699-1b90-4a51a3d55c8a",
"timestamp": "2022-03-23T15:59:12.742Z"
},
"icv": {
"value": "core.1.1.0",
"timestamp": "2022-03-23T15:59:12.742Z"
}
},
"samsungce.kitchenDeviceIdentification": {
"regionCode": {
"value": "US",
"timestamp": "2025-02-08T21:13:36.289Z"
},
"modelCode": {
"value": "ME8000T-/AA0",
"timestamp": "2025-02-08T21:13:36.289Z"
},
"fuel": {
"value": null
},
"type": {
"value": "microwave",
"timestamp": "2022-03-23T15:59:10.971Z"
},
"representativeComponent": {
"value": null
}
},
"samsungce.kitchenModeSpecification": {
"specification": {
"value": {
"single": [
{
"mode": "MicroWave",
"supportedOptions": {
"operationTime": {
"max": "01:40:00"
},
"powerLevel": {
"default": "100%",
"supportedValues": [
"0%",
"10%",
"20%",
"30%",
"40%",
"50%",
"60%",
"70%",
"80%",
"90%",
"100%"
]
}
}
},
{
"mode": "ConvectionBake",
"supportedOptions": {
"temperature": {
"F": {
"min": 100,
"max": 425,
"default": 350,
"supportedValues": [
100, 200, 225, 250, 275, 300, 325, 350, 375, 400, 425
]
}
},
"operationTime": {
"max": "01:40:00"
}
}
},
{
"mode": "ConvectionRoast",
"supportedOptions": {
"temperature": {
"F": {
"min": 200,
"max": 425,
"default": 325,
"supportedValues": [
200, 225, 250, 275, 300, 325, 350, 375, 400, 425
]
}
},
"operationTime": {
"max": "01:40:00"
}
}
},
{
"mode": "Grill",
"supportedOptions": {
"temperature": {
"F": {
"min": 425,
"max": 425,
"default": 425,
"resolution": 5
}
},
"operationTime": {
"max": "01:40:00"
}
}
},
{
"mode": "SpeedBake",
"supportedOptions": {
"operationTime": {
"max": "01:40:00"
},
"powerLevel": {
"default": "30%",
"supportedValues": ["10%", "30%", "50%", "70%"]
}
}
},
{
"mode": "SpeedRoast",
"supportedOptions": {
"operationTime": {
"max": "01:40:00"
},
"powerLevel": {
"default": "30%",
"supportedValues": ["10%", "30%", "50%", "70%"]
}
}
},
{
"mode": "KeepWarm",
"supportedOptions": {
"temperature": {
"F": {
"min": 175,
"max": 175,
"default": 175,
"resolution": 5
}
},
"operationTime": {
"max": "01:40:00"
}
}
},
{
"mode": "Autocook",
"supportedOptions": {}
},
{
"mode": "Cookie",
"supportedOptions": {
"temperature": {
"F": {
"min": 325,
"max": 325,
"default": 325,
"resolution": 5
}
},
"operationTime": {
"max": "01:40:00"
}
}
},
{
"mode": "SteamClean",
"supportedOptions": {
"operationTime": {
"max": "00:06:30"
}
}
}
]
},
"timestamp": "2025-02-08T10:21:03.790Z"
}
},
"custom.disabledCapabilities": {
"disabledCapabilities": {
"value": ["doorControl", "samsungce.hoodFanSpeed"],
"timestamp": "2025-02-08T21:13:36.152Z"
}
},
"samsungce.driverVersion": {
"versionNumber": {
"value": 22120101,
"timestamp": "2023-07-03T09:36:13.282Z"
}
},
"sec.diagnosticsInformation": {
"logType": {
"value": ["errCode", "dump"],
"timestamp": "2025-02-08T21:13:36.256Z"
},
"endpoint": {
"value": "SSM",
"timestamp": "2025-02-08T21:13:36.256Z"
},
"minVersion": {
"value": "1.0",
"timestamp": "2025-02-08T21:13:36.256Z"
},
"signinPermission": {
"value": null
},
"setupId": {
"value": "621",
"timestamp": "2025-02-08T21:13:36.256Z"
},
"protocolType": {
"value": "wifi_https",
"timestamp": "2025-02-08T21:13:36.256Z"
},
"tsId": {
"value": null
},
"mnId": {
"value": "0AJT",
"timestamp": "2025-02-08T21:13:36.256Z"
},
"dumpType": {
"value": "file",
"timestamp": "2025-02-08T21:13:36.256Z"
}
},
"temperatureMeasurement": {
"temperatureRange": {
"value": null
},
"temperature": {
"value": 1,
"unit": "F",
"timestamp": "2025-02-09T00:11:15.291Z"
}
},
"samsungce.ovenOperatingState": {
"completionTime": {
"value": "2025-02-08T21:13:36.184Z",
"timestamp": "2025-02-08T21:13:36.188Z"
},
"operatingState": {
"value": "ready",
"timestamp": "2025-02-08T21:13:36.188Z"
},
"progress": {
"value": 0,
"timestamp": "2025-02-08T21:13:36.188Z"
},
"ovenJobState": {
"value": "ready",
"timestamp": "2025-02-08T21:13:36.160Z"
},
"operationTime": {
"value": "00:00:00",
"timestamp": "2025-02-08T21:13:36.188Z"
}
},
"ovenMode": {
"supportedOvenModes": {
"value": [
"Microwave",
"ConvectionBake",
"ConvectionRoast",
"grill",
"Others",
"warming"
],
"timestamp": "2025-02-08T10:21:03.790Z"
},
"ovenMode": {
"value": "Others",
"timestamp": "2025-02-08T21:13:36.289Z"
}
},
"samsungce.ovenMode": {
"supportedOvenModes": {
"value": [
"MicroWave",
"ConvectionBake",
"ConvectionRoast",
"Grill",
"SpeedBake",
"SpeedRoast",
"KeepWarm",
"Autocook",
"Cookie",
"SteamClean"
],
"timestamp": "2025-02-08T10:21:03.790Z"
},
"ovenMode": {
"value": "NoOperation",
"timestamp": "2025-02-08T21:13:36.289Z"
}
},
"samsungce.kidsLock": {
"lockState": {
"value": "unlocked",
"timestamp": "2025-02-08T21:13:36.152Z"
}
},
"ovenSetpoint": {
"ovenSetpointRange": {
"value": null
},
"ovenSetpoint": {
"value": 0,
"timestamp": "2025-02-09T00:01:09.108Z"
}
},
"refresh": {},
"samsungce.hoodFanSpeed": {
"settableMaxFanSpeed": {
"value": 3,
"timestamp": "2025-02-09T00:01:06.959Z"
},
"hoodFanSpeed": {
"value": 0,
"timestamp": "2025-02-09T00:01:07.813Z"
},
"supportedHoodFanSpeed": {
"value": [0, 1, 2, 3, 4, 5],
"timestamp": "2022-03-23T15:59:12.796Z"
},
"settableMinFanSpeed": {
"value": 0,
"timestamp": "2025-02-09T00:01:06.959Z"
}
},
"samsungce.doorState": {
"doorState": {
"value": "closed",
"timestamp": "2025-02-08T21:13:36.227Z"
}
},
"samsungce.microwavePower": {
"supportedPowerLevels": {
"value": [
"0%",
"10%",
"20%",
"30%",
"40%",
"50%",
"60%",
"70%",
"80%",
"90%",
"100%"
],
"timestamp": "2025-02-08T21:13:36.160Z"
},
"powerLevel": {
"value": "0%",
"timestamp": "2025-02-08T21:13:36.160Z"
}
},
"execute": {
"data": {
"value": {
"payload": {
"rt": ["x.com.samsung.da.temperatures"],
"if": ["oic.if.baseline", "oic.if.a"],
"x.com.samsung.da.items": [
{
"x.com.samsung.da.id": "0",
"x.com.samsung.da.description": "Temperature",
"x.com.samsung.da.desired": "0",
"x.com.samsung.da.current": "1",
"x.com.samsung.da.increment": "5",
"x.com.samsung.da.unit": "Fahrenheit"
}
]
}
},
"data": {
"href": "/temperatures/vs/0"
},
"timestamp": "2023-07-19T05:50:12.609Z"
}
},
"remoteControlStatus": {
"remoteControlEnabled": {
"value": "false",
"timestamp": "2025-02-08T21:13:36.357Z"
}
},
"samsungce.definedRecipe": {
"definedRecipe": {
"value": {
"cavityId": "0",
"recipeType": "0",
"categoryId": 0,
"itemId": 0,
"servingSize": 0,
"browingLevel": 0,
"option": 0
},
"timestamp": "2025-02-08T21:13:36.160Z"
}
},
"samsungce.softwareUpdate": {
"targetModule": {
"value": null
},
"otnDUID": {
"value": "U7CNQWBWSCD7C",
"timestamp": "2025-02-08T21:13:36.256Z"
},
"lastUpdatedDate": {
"value": null
},
"availableModules": {
"value": [],
"timestamp": "2025-02-08T21:13:36.213Z"
},
"newVersionAvailable": {
"value": false,
"timestamp": "2025-02-08T21:13:36.213Z"
},
"operatingState": {
"value": null
},
"progress": {
"value": null
}
},
"ovenOperatingState": {
"completionTime": {
"value": "2025-02-08T21:13:36.184Z",
"timestamp": "2025-02-08T21:13:36.188Z"
},
"machineState": {
"value": "ready",
"timestamp": "2025-02-08T21:13:36.188Z"
},
"progress": {
"value": 0,
"unit": "%",
"timestamp": "2025-02-08T21:13:36.188Z"
},
"supportedMachineStates": {
"value": null
},
"ovenJobState": {
"value": "ready",
"timestamp": "2025-02-08T21:13:36.160Z"
},
"operationTime": {
"value": 0,
"timestamp": "2025-02-08T21:13:36.188Z"
}
}
},
"hood": {
"samsungce.hoodFanSpeed": {
"settableMaxFanSpeed": {
"value": 3,
"timestamp": "2025-02-09T00:01:06.959Z"
},
"hoodFanSpeed": {
"value": 0,
"timestamp": "2025-02-09T00:01:07.813Z"
},
"supportedHoodFanSpeed": {
"value": [0, 1, 2, 3, 4, 5],
"timestamp": "2022-03-23T15:59:12.796Z"
},
"settableMinFanSpeed": {
"value": 0,
"timestamp": "2025-02-09T00:01:06.959Z"
}
},
"samsungce.lamp": {
"brightnessLevel": {
"value": "off",
"timestamp": "2025-02-08T21:13:36.289Z"
},
"supportedBrightnessLevel": {
"value": ["off", "low", "high"],
"timestamp": "2025-02-08T21:13:36.289Z"
}
}
}
}
}

View File

@ -0,0 +1,727 @@
{
"components": {
"pantry-01": {
"samsungce.fridgePantryInfo": {
"name": {
"value": null
}
},
"custom.disabledCapabilities": {
"disabledCapabilities": {
"value": [],
"timestamp": "2022-02-07T10:47:54.524Z"
}
},
"samsungce.fridgePantryMode": {
"mode": {
"value": null
},
"supportedModes": {
"value": null
}
}
},
"pantry-02": {
"samsungce.fridgePantryInfo": {
"name": {
"value": null
}
},
"custom.disabledCapabilities": {
"disabledCapabilities": {
"value": [],
"timestamp": "2022-02-07T10:47:54.524Z"
}
},
"samsungce.fridgePantryMode": {
"mode": {
"value": null
},
"supportedModes": {
"value": null
}
}
},
"icemaker": {
"custom.disabledCapabilities": {
"disabledCapabilities": {
"value": [],
"timestamp": "2024-10-12T13:55:04.008Z"
}
},
"switch": {
"switch": {
"value": "off",
"timestamp": "2025-02-09T13:55:01.720Z"
}
}
},
"onedoor": {
"custom.fridgeMode": {
"fridgeModeValue": {
"value": null
},
"fridgeMode": {
"value": null
},
"supportedFridgeModes": {
"value": null
}
},
"contactSensor": {
"contact": {
"value": null
}
},
"samsungce.unavailableCapabilities": {
"unavailableCommands": {
"value": [],
"timestamp": "2024-11-08T04:14:59.899Z"
}
},
"custom.disabledCapabilities": {
"disabledCapabilities": {
"value": ["samsungce.freezerConvertMode", "custom.fridgeMode"],
"timestamp": "2024-11-12T08:23:59.944Z"
}
},
"temperatureMeasurement": {
"temperatureRange": {
"value": null
},
"temperature": {
"value": null
}
},
"custom.thermostatSetpointControl": {
"minimumSetpoint": {
"value": null
},
"maximumSetpoint": {
"value": null
}
},
"samsungce.freezerConvertMode": {
"supportedFreezerConvertModes": {
"value": null
},
"freezerConvertMode": {
"value": null
}
},
"thermostatCoolingSetpoint": {
"coolingSetpointRange": {
"value": null
},
"coolingSetpoint": {
"value": null
}
}
},
"cooler": {
"custom.fridgeMode": {
"fridgeModeValue": {
"value": null
},
"fridgeMode": {
"value": null
},
"supportedFridgeModes": {
"value": null
}
},
"contactSensor": {
"contact": {
"value": "closed",
"timestamp": "2025-02-09T16:26:21.425Z"
}
},
"samsungce.unavailableCapabilities": {
"unavailableCommands": {
"value": [],
"timestamp": "2024-11-08T04:14:59.899Z"
}
},
"custom.disabledCapabilities": {
"disabledCapabilities": {
"value": ["custom.fridgeMode"],
"timestamp": "2024-10-12T13:55:04.008Z"
}
},
"temperatureMeasurement": {
"temperatureRange": {
"value": null
},
"temperature": {
"value": 37,
"unit": "F",
"timestamp": "2025-01-19T21:07:55.764Z"
}
},
"custom.thermostatSetpointControl": {
"minimumSetpoint": {
"value": 34,
"unit": "F",
"timestamp": "2025-01-19T21:07:55.764Z"
},
"maximumSetpoint": {
"value": 44,
"unit": "F",
"timestamp": "2025-01-19T21:07:55.764Z"
}
},
"thermostatCoolingSetpoint": {
"coolingSetpointRange": {
"value": {
"minimum": 34,
"maximum": 44,
"step": 1
},
"unit": "F",
"timestamp": "2025-01-19T21:07:55.764Z"
},
"coolingSetpoint": {
"value": 37,
"unit": "F",
"timestamp": "2025-01-19T21:07:55.764Z"
}
}
},
"freezer": {
"custom.fridgeMode": {
"fridgeModeValue": {
"value": null
},
"fridgeMode": {
"value": null
},
"supportedFridgeModes": {
"value": null
}
},
"contactSensor": {
"contact": {
"value": "closed",
"timestamp": "2025-02-09T14:48:16.247Z"
}
},
"samsungce.unavailableCapabilities": {
"unavailableCommands": {
"value": [],
"timestamp": "2024-11-08T04:14:59.899Z"
}
},
"custom.disabledCapabilities": {
"disabledCapabilities": {
"value": ["custom.fridgeMode", "samsungce.freezerConvertMode"],
"timestamp": "2024-11-08T01:09:17.382Z"
}
},
"temperatureMeasurement": {
"temperatureRange": {
"value": null
},
"temperature": {
"value": 0,
"unit": "F",
"timestamp": "2025-01-23T04:42:18.178Z"
}
},
"custom.thermostatSetpointControl": {
"minimumSetpoint": {
"value": -8,
"unit": "F",
"timestamp": "2025-01-19T21:07:55.764Z"
},
"maximumSetpoint": {
"value": 5,
"unit": "F",
"timestamp": "2025-01-19T21:07:55.764Z"
}
},
"samsungce.freezerConvertMode": {
"supportedFreezerConvertModes": {
"value": null
},
"freezerConvertMode": {
"value": null
}
},
"thermostatCoolingSetpoint": {
"coolingSetpointRange": {
"value": {
"minimum": -8,
"maximum": 5,
"step": 1
},
"unit": "F",
"timestamp": "2025-01-19T21:07:55.764Z"
},
"coolingSetpoint": {
"value": 0,
"unit": "F",
"timestamp": "2025-01-19T21:07:55.764Z"
}
}
},
"main": {
"contactSensor": {
"contact": {
"value": "closed",
"timestamp": "2025-02-09T16:26:21.425Z"
}
},
"samsungce.dongleSoftwareInstallation": {
"status": {
"value": "completed",
"timestamp": "2022-02-07T10:47:54.524Z"
}
},
"samsungce.deviceIdentification": {
"micomAssayCode": {
"value": null
},
"modelName": {
"value": null
},
"serialNumber": {
"value": null
},
"serialNumberExtra": {
"value": null
},
"modelClassificationCode": {
"value": null
},
"description": {
"value": null
},
"releaseYear": {
"value": 20,
"timestamp": "2024-11-08T01:09:17.382Z"
},
"binaryId": {
"value": "TP2X_REF_20K",
"timestamp": "2025-02-09T13:55:01.720Z"
}
},
"samsungce.quickControl": {
"version": {
"value": null
}
},
"custom.fridgeMode": {
"fridgeModeValue": {
"value": null
},
"fridgeMode": {
"value": null
},
"supportedFridgeModes": {
"value": null
}
},
"ocf": {
"st": {
"value": null
},
"mndt": {
"value": null
},
"mnfv": {
"value": "A-RFWW-TP2-21-COMMON_20220110",
"timestamp": "2024-12-21T22:04:22.037Z"
},
"mnhw": {
"value": "MediaTek",
"timestamp": "2024-12-21T22:04:22.037Z"
},
"di": {
"value": "7db87911-7dce-1cf2-7119-b953432a2f09",
"timestamp": "2024-12-21T22:04:22.037Z"
},
"mnsl": {
"value": "http://www.samsung.com",
"timestamp": "2024-12-21T22:04:22.037Z"
},
"dmv": {
"value": "res.1.1.0,sh.1.1.0",
"timestamp": "2024-12-21T22:04:22.037Z"
},
"n": {
"value": "[refrigerator] Samsung",
"timestamp": "2024-12-21T22:04:22.037Z"
},
"mnmo": {
"value": "TP2X_REF_20K|00115641|0004014D011411200103000020000000",
"timestamp": "2024-12-21T22:04:22.037Z"
},
"vid": {
"value": "DA-REF-NORMAL-000001",
"timestamp": "2024-12-21T22:04:22.037Z"
},
"mnmn": {
"value": "Samsung Electronics",
"timestamp": "2024-12-21T22:04:22.037Z"
},
"mnml": {
"value": "http://www.samsung.com",
"timestamp": "2024-12-21T22:04:22.037Z"
},
"mnpv": {
"value": "DAWIT 2.0",
"timestamp": "2024-12-21T22:04:22.037Z"
},
"mnos": {
"value": "TizenRT 1.0 + IPv6",
"timestamp": "2024-12-21T22:04:22.037Z"
},
"pi": {
"value": "7db87911-7dce-1cf2-7119-b953432a2f09",
"timestamp": "2024-12-21T22:04:22.037Z"
},
"icv": {
"value": "core.1.1.0",
"timestamp": "2024-12-21T22:04:22.037Z"
}
},
"samsungce.fridgeVacationMode": {
"vacationMode": {
"value": null
}
},
"custom.disabledCapabilities": {
"disabledCapabilities": {
"value": [
"temperatureMeasurement",
"thermostatCoolingSetpoint",
"custom.fridgeMode",
"custom.deodorFilter",
"samsungce.dongleSoftwareInstallation",
"samsungce.quickControl",
"samsungce.deviceInfoPrivate",
"demandResponseLoadControl",
"samsungce.fridgeVacationMode",
"sec.diagnosticsInformation"
],
"timestamp": "2025-02-09T13:55:01.720Z"
}
},
"samsungce.driverVersion": {
"versionNumber": {
"value": 24100101,
"timestamp": "2024-11-08T04:14:59.025Z"
}
},
"sec.diagnosticsInformation": {
"logType": {
"value": null
},
"endpoint": {
"value": null
},
"minVersion": {
"value": null
},
"signinPermission": {
"value": null
},
"setupId": {
"value": null
},
"protocolType": {
"value": null
},
"tsId": {
"value": null
},
"mnId": {
"value": null
},
"dumpType": {
"value": null
}
},
"temperatureMeasurement": {
"temperatureRange": {
"value": null
},
"temperature": {
"value": null
}
},
"custom.deviceReportStateConfiguration": {
"reportStateRealtimePeriod": {
"value": null
},
"reportStateRealtime": {
"value": {
"state": "disabled"
},
"timestamp": "2025-01-19T21:07:55.703Z"
},
"reportStatePeriod": {
"value": "enabled",
"timestamp": "2025-01-19T21:07:55.703Z"
}
},
"thermostatCoolingSetpoint": {
"coolingSetpointRange": {
"value": null
},
"coolingSetpoint": {
"value": null
}
},
"custom.disabledComponents": {
"disabledComponents": {
"value": [
"icemaker-02",
"pantry-01",
"pantry-02",
"cvroom",
"onedoor"
],
"timestamp": "2024-11-08T01:09:17.382Z"
}
},
"demandResponseLoadControl": {
"drlcStatus": {
"value": {
"drlcType": 1,
"drlcLevel": 0,
"duration": 0,
"override": false
},
"timestamp": "2025-01-19T21:07:55.691Z"
}
},
"samsungce.sabbathMode": {
"supportedActions": {
"value": ["on", "off"],
"timestamp": "2025-01-19T21:07:55.799Z"
},
"status": {
"value": "off",
"timestamp": "2025-01-19T21:07:55.799Z"
}
},
"powerConsumptionReport": {
"powerConsumption": {
"value": {
"energy": 1568087,
"deltaEnergy": 7,
"power": 6,
"powerEnergy": 13.555977778169844,
"persistedEnergy": 0,
"energySaved": 0,
"start": "2025-02-09T17:38:01Z",
"end": "2025-02-09T17:49:00Z"
},
"timestamp": "2025-02-09T17:49:00.507Z"
}
},
"refresh": {},
"execute": {
"data": {
"value": {
"payload": {
"rt": ["x.com.samsung.da.rm.micomdata"],
"if": ["oic.if.baseline", "oic.if.a"],
"x.com.samsung.rm.micomdata": "D0C0022B00000000000DFE15051F5AA54400000000000000000000000000000000000000000000000001F04A00C5E0",
"x.com.samsung.rm.micomdataLength": 94
}
},
"data": {
"href": "/rm/micomdata/vs/0"
},
"timestamp": "2023-07-19T05:25:39.852Z"
}
},
"refrigeration": {
"defrost": {
"value": "off",
"timestamp": "2025-01-19T21:07:55.772Z"
},
"rapidCooling": {
"value": "off",
"timestamp": "2025-01-19T21:07:55.725Z"
},
"rapidFreezing": {
"value": "off",
"timestamp": "2025-01-19T21:07:55.725Z"
}
},
"custom.deodorFilter": {
"deodorFilterCapacity": {
"value": null
},
"deodorFilterLastResetDate": {
"value": null
},
"deodorFilterStatus": {
"value": null
},
"deodorFilterResetType": {
"value": null
},
"deodorFilterUsage": {
"value": null
},
"deodorFilterUsageStep": {
"value": null
}
},
"samsungce.powerCool": {
"activated": {
"value": false,
"timestamp": "2025-01-19T21:07:55.725Z"
}
},
"custom.energyType": {
"energyType": {
"value": "2.0",
"timestamp": "2022-02-07T10:47:54.524Z"
},
"energySavingSupport": {
"value": false,
"timestamp": "2022-02-07T10:47:54.524Z"
},
"drMaxDuration": {
"value": 1440,
"unit": "min",
"timestamp": "2022-02-07T11:39:47.504Z"
},
"energySavingLevel": {
"value": null
},
"energySavingInfo": {
"value": null
},
"supportedEnergySavingLevels": {
"value": null
},
"energySavingOperation": {
"value": null
},
"notificationTemplateID": {
"value": null
},
"energySavingOperationSupport": {
"value": false,
"timestamp": "2022-02-07T11:39:47.504Z"
}
},
"samsungce.softwareUpdate": {
"targetModule": {
"value": {},
"timestamp": "2025-01-19T21:07:55.725Z"
},
"otnDUID": {
"value": "P7CNQWBWM3XBW",
"timestamp": "2025-01-19T21:07:55.744Z"
},
"lastUpdatedDate": {
"value": null
},
"availableModules": {
"value": [],
"timestamp": "2025-01-19T21:07:55.744Z"
},
"newVersionAvailable": {
"value": false,
"timestamp": "2025-01-19T21:07:55.725Z"
},
"operatingState": {
"value": null
},
"progress": {
"value": null
}
},
"samsungce.powerFreeze": {
"activated": {
"value": false,
"timestamp": "2025-01-19T21:07:55.725Z"
}
},
"custom.waterFilter": {
"waterFilterUsageStep": {
"value": 1,
"timestamp": "2025-01-19T21:07:55.758Z"
},
"waterFilterResetType": {
"value": ["replaceable"],
"timestamp": "2025-01-19T21:07:55.758Z"
},
"waterFilterCapacity": {
"value": null
},
"waterFilterLastResetDate": {
"value": null
},
"waterFilterUsage": {
"value": 100,
"timestamp": "2025-02-09T04:02:12.910Z"
},
"waterFilterStatus": {
"value": "replace",
"timestamp": "2025-02-09T04:02:12.910Z"
}
}
},
"cvroom": {
"custom.fridgeMode": {
"fridgeModeValue": {
"value": null
},
"fridgeMode": {
"value": null
},
"supportedFridgeModes": {
"value": null
}
},
"contactSensor": {
"contact": {
"value": null
}
},
"custom.disabledCapabilities": {
"disabledCapabilities": {
"value": ["temperatureMeasurement", "thermostatCoolingSetpoint"],
"timestamp": "2022-02-07T11:39:42.105Z"
}
},
"temperatureMeasurement": {
"temperatureRange": {
"value": null
},
"temperature": {
"value": null
}
},
"thermostatCoolingSetpoint": {
"coolingSetpointRange": {
"value": null
},
"coolingSetpoint": {
"value": null
}
}
},
"icemaker-02": {
"custom.disabledCapabilities": {
"disabledCapabilities": {
"value": [],
"timestamp": "2022-02-07T11:39:42.105Z"
}
},
"switch": {
"switch": {
"value": null
}
}
}
}
}

View File

@ -0,0 +1,274 @@
{
"components": {
"main": {
"custom.disabledComponents": {
"disabledComponents": {
"value": ["station"],
"timestamp": "2020-11-03T04:43:07.114Z"
}
},
"powerConsumptionReport": {
"powerConsumption": {
"value": null,
"timestamp": "2020-11-03T04:43:07.092Z"
}
},
"refresh": {},
"samsungce.robotCleanerOperatingState": {
"supportedOperatingState": {
"value": [
"homing",
"error",
"idle",
"charging",
"chargingForRemainingJob",
"paused",
"cleaning"
],
"timestamp": "2020-11-03T04:43:06.547Z"
},
"operatingState": {
"value": "idle",
"timestamp": "2023-06-18T15:59:24.580Z"
},
"cleaningStep": {
"value": null
},
"homingReason": {
"value": "none",
"timestamp": "2020-11-03T04:43:22.926Z"
},
"isMapBasedOperationAvailable": {
"value": null
}
},
"battery": {
"quantity": {
"value": null
},
"battery": {
"value": 100,
"unit": "%",
"timestamp": "2022-09-09T22:55:13.962Z"
},
"type": {
"value": null
}
},
"execute": {
"data": {
"value": {
"payload": {
"rt": ["x.com.samsung.da.alarms"],
"if": ["oic.if.baseline", "oic.if.a"],
"x.com.samsung.da.items": [
{
"x.com.samsung.da.code": "4",
"x.com.samsung.da.alarmType": "Device",
"x.com.samsung.da.triggeredTime": "2023-06-18T15:59:30",
"x.com.samsung.da.state": "deleted"
}
]
}
},
"data": {
"href": "/alarms/vs/0"
},
"timestamp": "2023-06-18T15:59:28.267Z"
}
},
"samsungce.deviceIdentification": {
"micomAssayCode": {
"value": null
},
"modelName": {
"value": null
},
"serialNumber": {
"value": null
},
"serialNumberExtra": {
"value": null
},
"modelClassificationCode": {
"value": null
},
"description": {
"value": null
},
"releaseYear": {
"value": null
},
"binaryId": {
"value": null
}
},
"switch": {
"switch": {
"value": "off",
"timestamp": "2023-06-18T15:59:27.658Z"
}
},
"robotCleanerTurboMode": {
"robotCleanerTurboMode": {
"value": "off",
"timestamp": "2022-09-08T02:53:49.826Z"
}
},
"ocf": {
"st": {
"value": null,
"timestamp": "2020-06-02T23:30:52.793Z"
},
"mndt": {
"value": null,
"timestamp": "2020-06-03T13:34:18.508Z"
},
"mnfv": {
"value": "1.0",
"timestamp": "2019-07-07T19:45:19.771Z"
},
"mnhw": {
"value": "1.0",
"timestamp": "2019-07-07T19:45:19.771Z"
},
"di": {
"value": "3442dfc6-17c0-a65f-dae0-4c6e01786f44",
"timestamp": "2019-07-07T19:45:19.771Z"
},
"mnsl": {
"value": null,
"timestamp": "2020-06-03T00:49:53.813Z"
},
"dmv": {
"value": "res.1.1.0,sh.1.1.0",
"timestamp": "2021-12-23T07:09:40.610Z"
},
"n": {
"value": "[robot vacuum] Samsung",
"timestamp": "2019-07-07T19:45:19.771Z"
},
"mnmo": {
"value": "powerbot_7000_17M|50016055|80010404011141000100000000000000",
"timestamp": "2022-09-07T06:42:36.551Z"
},
"vid": {
"value": "DA-RVC-NORMAL-000001",
"timestamp": "2019-07-07T19:45:19.771Z"
},
"mnmn": {
"value": "Samsung Electronics",
"timestamp": "2019-07-07T19:45:19.771Z"
},
"mnml": {
"value": "http://www.samsung.com",
"timestamp": "2019-07-07T19:45:19.771Z"
},
"mnpv": {
"value": "00",
"timestamp": "2019-07-07T19:45:19.771Z"
},
"mnos": {
"value": "Tizen(3/0)",
"timestamp": "2019-07-07T19:45:19.771Z"
},
"pi": {
"value": "3442dfc6-17c0-a65f-dae0-4c6e01786f44",
"timestamp": "2019-07-07T19:45:19.771Z"
},
"icv": {
"value": "core.1.1.0",
"timestamp": "2019-07-07T19:45:19.771Z"
}
},
"samsungce.robotCleanerCleaningMode": {
"supportedCleaningMode": {
"value": ["auto", "spot", "manual", "stop"],
"timestamp": "2020-11-03T04:43:06.547Z"
},
"repeatModeEnabled": {
"value": false,
"timestamp": "2020-12-21T01:32:56.245Z"
},
"supportRepeatMode": {
"value": true,
"timestamp": "2020-11-03T04:43:06.547Z"
},
"cleaningMode": {
"value": "stop",
"timestamp": "2022-09-09T21:25:20.601Z"
}
},
"robotCleanerMovement": {
"robotCleanerMovement": {
"value": "idle",
"timestamp": "2023-06-18T15:59:24.580Z"
}
},
"custom.disabledCapabilities": {
"disabledCapabilities": {
"value": [
"samsungce.robotCleanerMapAreaInfo",
"samsungce.robotCleanerMapCleaningInfo",
"samsungce.robotCleanerPatrol",
"samsungce.robotCleanerPetMonitoring",
"samsungce.robotCleanerPetMonitoringReport",
"samsungce.robotCleanerPetCleaningSchedule",
"soundDetection",
"samsungce.soundDetectionSensitivity",
"samsungce.musicPlaylist",
"mediaPlayback",
"mediaTrackControl",
"imageCapture",
"videoCapture",
"audioVolume",
"audioMute",
"audioNotification",
"powerConsumptionReport",
"custom.hepaFilter",
"samsungce.robotCleanerMotorFilter",
"samsungce.robotCleanerRelayCleaning",
"audioTrackAddressing",
"samsungce.robotCleanerWelcome"
],
"timestamp": "2022-09-08T01:03:48.820Z"
}
},
"robotCleanerCleaningMode": {
"robotCleanerCleaningMode": {
"value": "stop",
"timestamp": "2022-09-09T21:25:20.601Z"
}
},
"samsungce.softwareUpdate": {
"targetModule": {
"value": null
},
"otnDUID": {
"value": null
},
"lastUpdatedDate": {
"value": null
},
"availableModules": {
"value": null
},
"newVersionAvailable": {
"value": null
},
"operatingState": {
"value": null
},
"progress": {
"value": null
}
},
"samsungce.driverVersion": {
"versionNumber": {
"value": 22100101,
"timestamp": "2022-11-01T09:26:07.107Z"
}
}
}
}
}

View File

@ -0,0 +1,786 @@
{
"components": {
"main": {
"samsungce.dishwasherWashingCourse": {
"customCourseCandidates": {
"value": null
},
"washingCourse": {
"value": "normal",
"timestamp": "2025-02-08T20:21:26.497Z"
},
"supportedCourses": {
"value": [
"auto",
"normal",
"heavy",
"delicate",
"express",
"rinseOnly",
"selfClean"
],
"timestamp": "2025-02-08T18:00:37.194Z"
}
},
"dishwasherOperatingState": {
"completionTime": {
"value": "2025-02-08T22:49:26Z",
"timestamp": "2025-02-08T20:21:26.452Z"
},
"machineState": {
"value": "stop",
"timestamp": "2025-02-08T20:21:26.452Z"
},
"progress": {
"value": null
},
"supportedMachineStates": {
"value": ["stop", "run", "pause"],
"timestamp": "2024-09-10T10:21:02.853Z"
},
"dishwasherJobState": {
"value": "unknown",
"timestamp": "2025-02-08T20:21:26.452Z"
}
},
"samsungce.dishwasherWashingOptions": {
"dryPlus": {
"value": null
},
"stormWash": {
"value": null
},
"hotAirDry": {
"value": null
},
"selectedZone": {
"value": {
"value": "all",
"settable": ["none", "upper", "lower", "all"]
},
"timestamp": "2022-11-09T00:20:42.461Z"
},
"speedBooster": {
"value": {
"value": false,
"settable": [false, true]
},
"timestamp": "2023-11-24T14:46:55.375Z"
},
"highTempWash": {
"value": {
"value": false,
"settable": [false, true]
},
"timestamp": "2025-02-08T07:39:54.739Z"
},
"sanitizingWash": {
"value": null
},
"heatedDry": {
"value": null
},
"zoneBooster": {
"value": {
"value": "none",
"settable": ["none", "left", "right", "all"]
},
"timestamp": "2022-11-20T07:10:27.445Z"
},
"addRinse": {
"value": null
},
"supportedList": {
"value": [
"selectedZone",
"zoneBooster",
"speedBooster",
"sanitize",
"highTempWash"
],
"timestamp": "2021-06-27T01:19:38.000Z"
},
"rinsePlus": {
"value": null
},
"sanitize": {
"value": {
"value": false,
"settable": [false, true]
},
"timestamp": "2025-01-18T23:49:09.964Z"
},
"steamSoak": {
"value": null
}
},
"samsungce.deviceIdentification": {
"micomAssayCode": {
"value": null
},
"modelName": {
"value": null
},
"serialNumber": {
"value": null
},
"serialNumberExtra": {
"value": null
},
"modelClassificationCode": {
"value": null
},
"description": {
"value": null
},
"releaseYear": {
"value": null
},
"binaryId": {
"value": "DA_DW_A51_20_COMMON",
"timestamp": "2025-02-08T19:29:30.987Z"
}
},
"custom.dishwasherOperatingProgress": {
"dishwasherOperatingProgress": {
"value": "none",
"timestamp": "2025-02-08T20:21:26.452Z"
}
},
"switch": {
"switch": {
"value": "off",
"timestamp": "2025-02-08T20:21:26.386Z"
}
},
"samsungce.quickControl": {
"version": {
"value": null
}
},
"samsungce.waterConsumptionReport": {
"waterConsumption": {
"value": null
}
},
"ocf": {
"st": {
"value": null
},
"mndt": {
"value": null
},
"mnfv": {
"value": "DA_DW_A51_20_COMMON_30230714",
"timestamp": "2023-11-02T15:58:55.699Z"
},
"mnhw": {
"value": "ARTIK051",
"timestamp": "2021-06-27T01:19:37.615Z"
},
"di": {
"value": "f36dc7ce-cac0-0667-dc14-a3704eb5e676",
"timestamp": "2021-06-27T01:19:37.615Z"
},
"mnsl": {
"value": "http://www.samsung.com",
"timestamp": "2021-06-27T01:19:37.615Z"
},
"dmv": {
"value": "res.1.1.0,sh.1.1.0",
"timestamp": "2024-07-04T13:53:32.032Z"
},
"n": {
"value": "[dishwasher] Samsung",
"timestamp": "2021-06-27T01:19:37.615Z"
},
"mnmo": {
"value": "DA_DW_A51_20_COMMON|30007242|40010201001311000101000000000000",
"timestamp": "2021-06-27T01:19:37.615Z"
},
"vid": {
"value": "DA-WM-DW-000001",
"timestamp": "2021-06-27T01:19:37.615Z"
},
"mnmn": {
"value": "Samsung Electronics",
"timestamp": "2021-06-27T01:19:37.615Z"
},
"mnml": {
"value": "http://www.samsung.com",
"timestamp": "2021-06-27T01:19:37.615Z"
},
"mnpv": {
"value": "DAWIT 2.0",
"timestamp": "2021-06-27T01:19:37.615Z"
},
"mnos": {
"value": "TizenRT 1.0 + IPv6",
"timestamp": "2021-06-27T01:19:37.615Z"
},
"pi": {
"value": "f36dc7ce-cac0-0667-dc14-a3704eb5e676",
"timestamp": "2021-06-27T01:19:37.615Z"
},
"icv": {
"value": "core.1.1.0",
"timestamp": "2021-06-27T01:19:37.615Z"
}
},
"custom.disabledCapabilities": {
"disabledCapabilities": {
"value": [
"samsungce.waterConsumptionReport",
"sec.wifiConfiguration",
"samsungce.quickControl",
"samsungce.deviceInfoPrivate",
"demandResponseLoadControl",
"sec.diagnosticsInformation",
"custom.waterFilter"
],
"timestamp": "2025-02-08T19:29:32.447Z"
}
},
"samsungce.driverVersion": {
"versionNumber": {
"value": 24040105,
"timestamp": "2024-07-02T02:56:22.508Z"
}
},
"sec.diagnosticsInformation": {
"logType": {
"value": null
},
"endpoint": {
"value": null
},
"minVersion": {
"value": null
},
"signinPermission": {
"value": null
},
"setupId": {
"value": null
},
"protocolType": {
"value": null
},
"tsId": {
"value": null
},
"mnId": {
"value": null
},
"dumpType": {
"value": null
}
},
"samsungce.dishwasherOperation": {
"supportedOperatingState": {
"value": ["ready", "running", "paused"],
"timestamp": "2024-09-10T10:21:02.853Z"
},
"operatingState": {
"value": "ready",
"timestamp": "2025-02-08T20:21:26.452Z"
},
"reservable": {
"value": false,
"timestamp": "2025-02-08T18:00:37.194Z"
},
"progressPercentage": {
"value": 1,
"timestamp": "2025-02-08T20:21:26.452Z"
},
"remainingTimeStr": {
"value": "02:28",
"timestamp": "2025-02-08T20:21:26.452Z"
},
"operationTime": {
"value": null
},
"remainingTime": {
"value": 148.0,
"unit": "min",
"timestamp": "2025-02-08T20:21:26.452Z"
},
"timeLeftToStart": {
"value": 0.0,
"unit": "min",
"timestamp": "2025-02-08T18:00:37.482Z"
}
},
"samsungce.dishwasherJobState": {
"scheduledJobs": {
"value": [
{
"jobName": "washing",
"timeInSec": 3600
},
{
"jobName": "rinsing",
"timeInSec": 1020
},
{
"jobName": "drying",
"timeInSec": 1200
}
],
"timestamp": "2025-02-08T20:21:26.928Z"
},
"dishwasherJobState": {
"value": "none",
"timestamp": "2025-02-08T20:21:26.452Z"
}
},
"samsungce.kidsLock": {
"lockState": {
"value": "unlocked",
"timestamp": "2025-02-08T18:00:37.450Z"
}
},
"demandResponseLoadControl": {
"drlcStatus": {
"value": null
}
},
"powerConsumptionReport": {
"powerConsumption": {
"value": {
"energy": 101600,
"deltaEnergy": 0,
"power": 0,
"powerEnergy": 0.0,
"persistedEnergy": 0,
"energySaved": 0,
"persistedSavedEnergy": 0,
"start": "2025-02-08T20:21:21Z",
"end": "2025-02-08T20:21:26Z"
},
"timestamp": "2025-02-08T20:21:26.596Z"
}
},
"refresh": {},
"samsungce.dishwasherWashingCourseDetails": {
"predefinedCourses": {
"value": [
{
"courseName": "auto",
"energyUsage": 3,
"waterUsage": 3,
"temperature": {
"min": 50,
"max": 60,
"unit": "C"
},
"expectedTime": {
"time": 136,
"unit": "min"
},
"options": {
"highTempWash": {
"default": false,
"settable": [false, true]
},
"sanitize": {
"default": false,
"settable": [false, true]
},
"speedBooster": {
"default": false,
"settable": [false, true]
},
"zoneBooster": {
"default": "none",
"settable": ["none", "left"]
},
"selectedZone": {
"default": "all",
"settable": ["none", "lower", "all"]
}
}
},
{
"courseName": "normal",
"energyUsage": 3,
"waterUsage": 4,
"temperature": {
"min": 45,
"max": 62,
"unit": "C"
},
"expectedTime": {
"time": 148,
"unit": "min"
},
"options": {
"highTempWash": {
"default": false,
"settable": [false, true]
},
"sanitize": {
"default": false,
"settable": [false, true]
},
"speedBooster": {
"default": false,
"settable": [false, true]
},
"zoneBooster": {
"default": "none",
"settable": ["none", "left"]
},
"selectedZone": {
"default": "all",
"settable": ["none", "lower", "all"]
}
}
},
{
"courseName": "heavy",
"energyUsage": 4,
"waterUsage": 5,
"temperature": {
"min": 65,
"max": 65,
"unit": "C"
},
"expectedTime": {
"time": 155,
"unit": "min"
},
"options": {
"highTempWash": {
"default": false,
"settable": [false, true]
},
"sanitize": {
"default": false,
"settable": [false, true]
},
"speedBooster": {
"default": false,
"settable": [false, true]
},
"zoneBooster": {
"default": "none",
"settable": ["none", "left"]
},
"selectedZone": {
"default": "all",
"settable": ["none", "lower", "all"]
}
}
},
{
"courseName": "delicate",
"energyUsage": 2,
"waterUsage": 3,
"temperature": {
"min": 50,
"max": 50,
"unit": "C"
},
"expectedTime": {
"time": 112,
"unit": "min"
},
"options": {
"highTempWash": {
"default": false,
"settable": []
},
"sanitize": {
"default": false,
"settable": []
},
"speedBooster": {
"default": false,
"settable": [false, true]
},
"zoneBooster": {
"default": "none",
"settable": []
},
"selectedZone": {
"default": "all",
"settable": ["none", "lower", "all"]
}
}
},
{
"courseName": "express",
"energyUsage": 2,
"waterUsage": 2,
"temperature": {
"min": 52,
"max": 52,
"unit": "C"
},
"expectedTime": {
"time": 60,
"unit": "min"
},
"options": {
"highTempWash": {
"default": false,
"settable": [false, true]
},
"sanitize": {
"default": false,
"settable": [false, true]
},
"speedBooster": {
"default": false,
"settable": []
},
"zoneBooster": {
"default": "none",
"settable": ["none", "left"]
},
"selectedZone": {
"default": "all",
"settable": ["none", "lower", "all"]
}
}
},
{
"courseName": "rinseOnly",
"energyUsage": 1,
"waterUsage": 1,
"temperature": {
"min": 40,
"max": 40,
"unit": "C"
},
"expectedTime": {
"time": 14,
"unit": "min"
},
"options": {
"highTempWash": {
"default": false,
"settable": []
},
"sanitize": {
"default": false,
"settable": []
},
"speedBooster": {
"default": false,
"settable": []
},
"zoneBooster": {
"default": "none",
"settable": []
},
"selectedZone": {
"default": "all",
"settable": ["none", "lower", "all"]
}
}
},
{
"courseName": "selfClean",
"energyUsage": 5,
"waterUsage": 4,
"temperature": {
"min": 70,
"max": 70,
"unit": "C"
},
"expectedTime": {
"time": 139,
"unit": "min"
},
"options": {
"highTempWash": {
"default": false,
"settable": []
},
"sanitize": {
"default": false,
"settable": []
},
"speedBooster": {
"default": false,
"settable": []
},
"zoneBooster": {
"default": "none",
"settable": []
},
"selectedZone": {
"default": "all",
"settable": ["none", "all"]
}
}
}
],
"timestamp": "2025-02-08T18:00:37.194Z"
},
"waterUsageMax": {
"value": 5,
"timestamp": "2025-02-08T18:00:37.194Z"
},
"energyUsageMax": {
"value": 5,
"timestamp": "2025-02-08T18:00:37.194Z"
}
},
"execute": {
"data": {
"value": {
"payload": {
"rt": ["oic.r.operational.state"],
"if": ["oic.if.baseline", "oic.if.a"],
"currentMachineState": "idle",
"machineStates": ["pause", "active", "idle"],
"jobStates": [
"None",
"Predrain",
"Prewash",
"Wash",
"Rinse",
"Drying",
"Finish"
],
"currentJobState": "None",
"remainingTime": "02:16:00",
"progressPercentage": "1"
}
},
"data": {
"href": "/operational/state/0"
},
"timestamp": "2023-07-19T04:23:15.606Z"
}
},
"sec.wifiConfiguration": {
"autoReconnection": {
"value": null
},
"minVersion": {
"value": null
},
"supportedWiFiFreq": {
"value": null
},
"supportedAuthType": {
"value": null
},
"protocolType": {
"value": null
}
},
"custom.dishwasherOperatingPercentage": {
"dishwasherOperatingPercentage": {
"value": 1,
"timestamp": "2025-02-08T20:21:26.452Z"
}
},
"remoteControlStatus": {
"remoteControlEnabled": {
"value": "false",
"timestamp": "2025-02-08T18:00:37.555Z"
}
},
"custom.supportedOptions": {
"course": {
"value": null
},
"referenceTable": {
"value": null
},
"supportedCourses": {
"value": ["82", "83", "84", "85", "86", "87", "88"],
"timestamp": "2025-02-08T18:00:37.194Z"
}
},
"custom.dishwasherDelayStartTime": {
"dishwasherDelayStartTime": {
"value": "00:00:00",
"timestamp": "2025-02-08T18:00:37.482Z"
}
},
"custom.energyType": {
"energyType": {
"value": "2.0",
"timestamp": "2023-08-25T03:23:06.667Z"
},
"energySavingSupport": {
"value": true,
"timestamp": "2024-10-01T00:08:09.813Z"
},
"drMaxDuration": {
"value": null
},
"energySavingLevel": {
"value": null
},
"energySavingInfo": {
"value": null
},
"supportedEnergySavingLevels": {
"value": null
},
"energySavingOperation": {
"value": null
},
"notificationTemplateID": {
"value": null
},
"energySavingOperationSupport": {
"value": null
}
},
"samsungce.softwareUpdate": {
"targetModule": {
"value": null
},
"otnDUID": {
"value": "MTCNQWBWIV6TS",
"timestamp": "2025-02-08T18:00:37.538Z"
},
"lastUpdatedDate": {
"value": null
},
"availableModules": {
"value": [],
"timestamp": "2022-07-20T03:37:30.706Z"
},
"newVersionAvailable": {
"value": false,
"timestamp": "2025-02-08T18:00:37.538Z"
},
"operatingState": {
"value": null
},
"progress": {
"value": null
}
},
"custom.waterFilter": {
"waterFilterUsageStep": {
"value": null
},
"waterFilterResetType": {
"value": null
},
"waterFilterCapacity": {
"value": null
},
"waterFilterLastResetDate": {
"value": null
},
"waterFilterUsage": {
"value": null
},
"waterFilterStatus": {
"value": null
}
}
}
}
}

View File

@ -0,0 +1,719 @@
{
"components": {
"hca.main": {
"hca.dryerMode": {
"mode": {
"value": "normal",
"timestamp": "2025-02-08T18:10:11.023Z"
},
"supportedModes": {
"value": ["normal", "timeDry", "quickDry"],
"timestamp": "2025-02-08T18:10:10.497Z"
}
}
},
"main": {
"custom.dryerWrinklePrevent": {
"operatingState": {
"value": "ready",
"timestamp": "2025-02-08T18:10:10.497Z"
},
"dryerWrinklePrevent": {
"value": "off",
"timestamp": "2025-02-08T18:10:10.840Z"
}
},
"samsungce.dryerDryingTemperature": {
"dryingTemperature": {
"value": "medium",
"timestamp": "2025-02-08T18:10:10.840Z"
},
"supportedDryingTemperature": {
"value": ["none", "extraLow", "low", "mediumLow", "medium", "high"],
"timestamp": "2025-01-04T22:52:14.884Z"
}
},
"samsungce.welcomeMessage": {
"welcomeMessage": {
"value": null
}
},
"samsungce.dongleSoftwareInstallation": {
"status": {
"value": "completed",
"timestamp": "2022-06-14T06:49:02.183Z"
}
},
"samsungce.dryerCyclePreset": {
"maxNumberOfPresets": {
"value": 10,
"timestamp": "2025-02-08T18:10:10.990Z"
},
"presets": {
"value": null
}
},
"samsungce.deviceIdentification": {
"micomAssayCode": {
"value": "20233741",
"timestamp": "2025-02-08T18:10:11.113Z"
},
"modelName": {
"value": null
},
"serialNumber": {
"value": null
},
"serialNumberExtra": {
"value": null
},
"modelClassificationCode": {
"value": "3000000100111100020B000000000000",
"timestamp": "2025-02-08T18:10:11.113Z"
},
"description": {
"value": "DA_WM_A51_20_COMMON_DV6300R/DC92-02385A_0090",
"timestamp": "2025-02-08T18:10:11.113Z"
},
"releaseYear": {
"value": null
},
"binaryId": {
"value": "DA_WM_A51_20_COMMON",
"timestamp": "2025-02-08T18:10:11.113Z"
}
},
"switch": {
"switch": {
"value": "off",
"timestamp": "2025-02-08T18:10:10.911Z"
}
},
"samsungce.quickControl": {
"version": {
"value": null
}
},
"samsungce.dryerFreezePrevent": {
"operatingState": {
"value": null
}
},
"ocf": {
"st": {
"value": null
},
"mndt": {
"value": null
},
"mnfv": {
"value": "DA_WM_A51_20_COMMON_30230708",
"timestamp": "2025-01-04T22:52:14.222Z"
},
"mnhw": {
"value": "ARTIK051",
"timestamp": "2025-01-04T22:52:14.222Z"
},
"di": {
"value": "02f7256e-8353-5bdd-547f-bd5b1647e01b",
"timestamp": "2025-01-04T22:52:14.222Z"
},
"mnsl": {
"value": "http://www.samsung.com",
"timestamp": "2025-01-04T22:52:14.222Z"
},
"dmv": {
"value": "res.1.1.0,sh.1.1.0",
"timestamp": "2025-01-04T22:52:14.222Z"
},
"n": {
"value": "[dryer] Samsung",
"timestamp": "2025-01-04T22:52:14.222Z"
},
"mnmo": {
"value": "DA_WM_A51_20_COMMON|20233741|3000000100111100020B000000000000",
"timestamp": "2025-01-04T22:52:14.222Z"
},
"vid": {
"value": "DA-WM-WD-000001",
"timestamp": "2025-01-04T22:52:14.222Z"
},
"mnmn": {
"value": "Samsung Electronics",
"timestamp": "2025-01-04T22:52:14.222Z"
},
"mnml": {
"value": "http://www.samsung.com",
"timestamp": "2025-01-04T22:52:14.222Z"
},
"mnpv": {
"value": "DAWIT 2.0",
"timestamp": "2025-01-04T22:52:14.222Z"
},
"mnos": {
"value": "TizenRT 1.0 + IPv6",
"timestamp": "2025-01-04T22:52:14.222Z"
},
"pi": {
"value": "02f7256e-8353-5bdd-547f-bd5b1647e01b",
"timestamp": "2025-01-04T22:52:14.222Z"
},
"icv": {
"value": "core.1.1.0",
"timestamp": "2025-01-04T22:52:14.222Z"
}
},
"custom.dryerDryLevel": {
"dryerDryLevel": {
"value": "normal",
"timestamp": "2025-02-08T18:10:10.840Z"
},
"supportedDryerDryLevel": {
"value": ["none", "damp", "less", "normal", "more", "very"],
"timestamp": "2021-06-01T22:54:28.224Z"
}
},
"samsungce.dryerAutoCycleLink": {
"dryerAutoCycleLink": {
"value": "on",
"timestamp": "2025-02-08T18:10:11.986Z"
}
},
"samsungce.dryerCycle": {
"dryerCycle": {
"value": "Table_00_Course_01",
"timestamp": "2025-02-08T18:10:11.023Z"
},
"supportedCycles": {
"value": [
{
"cycle": "01",
"supportedOptions": {
"dryingLevel": {
"raw": "D33E",
"default": "normal",
"options": ["damp", "less", "normal", "more", "very"]
},
"dryingTemperature": {
"raw": "8410",
"default": "medium",
"options": ["medium"]
}
}
},
{
"cycle": "9C",
"supportedOptions": {
"dryingLevel": {
"raw": "D33E",
"default": "normal",
"options": ["damp", "less", "normal", "more", "very"]
},
"dryingTemperature": {
"raw": "8520",
"default": "high",
"options": ["high"]
}
}
},
{
"cycle": "A5",
"supportedOptions": {
"dryingLevel": {
"raw": "D33E",
"default": "normal",
"options": ["damp", "less", "normal", "more", "very"]
},
"dryingTemperature": {
"raw": "8520",
"default": "high",
"options": ["high"]
}
}
},
{
"cycle": "9E",
"supportedOptions": {
"dryingLevel": {
"raw": "D33E",
"default": "normal",
"options": ["damp", "less", "normal", "more", "very"]
},
"dryingTemperature": {
"raw": "8308",
"default": "mediumLow",
"options": ["mediumLow"]
}
}
},
{
"cycle": "9B",
"supportedOptions": {
"dryingLevel": {
"raw": "D520",
"default": "very",
"options": ["very"]
},
"dryingTemperature": {
"raw": "8520",
"default": "high",
"options": ["high"]
}
}
},
{
"cycle": "27",
"supportedOptions": {
"dryingLevel": {
"raw": "D000",
"default": "none",
"options": []
},
"dryingTemperature": {
"raw": "8520",
"default": "high",
"options": ["high"]
}
}
},
{
"cycle": "E5",
"supportedOptions": {
"dryingLevel": {
"raw": "D000",
"default": "none",
"options": []
},
"dryingTemperature": {
"raw": "8000",
"default": "none",
"options": []
}
}
},
{
"cycle": "A0",
"supportedOptions": {
"dryingLevel": {
"raw": "D000",
"default": "none",
"options": []
},
"dryingTemperature": {
"raw": "8000",
"default": "none",
"options": []
}
}
},
{
"cycle": "A4",
"supportedOptions": {
"dryingLevel": {
"raw": "D000",
"default": "none",
"options": []
},
"dryingTemperature": {
"raw": "853E",
"default": "high",
"options": ["extraLow", "low", "mediumLow", "medium", "high"]
}
}
},
{
"cycle": "A6",
"supportedOptions": {
"dryingLevel": {
"raw": "D000",
"default": "none",
"options": []
},
"dryingTemperature": {
"raw": "8520",
"default": "high",
"options": ["high"]
}
}
},
{
"cycle": "A3",
"supportedOptions": {
"dryingLevel": {
"raw": "D308",
"default": "normal",
"options": ["normal"]
},
"dryingTemperature": {
"raw": "8410",
"default": "medium",
"options": ["medium"]
}
}
},
{
"cycle": "A2",
"supportedOptions": {
"dryingLevel": {
"raw": "D33E",
"default": "normal",
"options": ["damp", "less", "normal", "more", "very"]
},
"dryingTemperature": {
"raw": "8102",
"default": "extraLow",
"options": ["extraLow"]
}
}
}
],
"timestamp": "2025-01-04T22:52:14.884Z"
},
"referenceTable": {
"value": {
"id": "Table_00"
},
"timestamp": "2025-02-08T18:10:11.023Z"
},
"specializedFunctionClassification": {
"value": 4,
"timestamp": "2025-02-08T18:10:10.497Z"
}
},
"custom.disabledCapabilities": {
"disabledCapabilities": {
"value": [
"samsungce.dryerCyclePreset",
"samsungce.welcomeMessage",
"samsungce.dongleSoftwareInstallation",
"sec.wifiConfiguration",
"samsungce.quickControl",
"samsungce.deviceInfoPrivate",
"demandResponseLoadControl",
"samsungce.dryerFreezePrevent",
"sec.diagnosticsInformation"
],
"timestamp": "2024-07-05T16:04:06.674Z"
}
},
"samsungce.driverVersion": {
"versionNumber": {
"value": 24110101,
"timestamp": "2024-12-03T02:59:11.115Z"
}
},
"sec.diagnosticsInformation": {
"logType": {
"value": null
},
"endpoint": {
"value": null
},
"minVersion": {
"value": null
},
"signinPermission": {
"value": null
},
"setupId": {
"value": null
},
"protocolType": {
"value": null
},
"tsId": {
"value": null
},
"mnId": {
"value": null
},
"dumpType": {
"value": null
}
},
"samsungce.kidsLock": {
"lockState": {
"value": "unlocked",
"timestamp": "2025-02-08T18:10:10.825Z"
}
},
"demandResponseLoadControl": {
"drlcStatus": {
"value": null
}
},
"samsungce.detergentOrder": {
"alarmEnabled": {
"value": false,
"timestamp": "2025-02-08T18:10:10.497Z"
},
"orderThreshold": {
"value": 0,
"unit": "cc",
"timestamp": "2025-02-08T18:10:10.497Z"
}
},
"powerConsumptionReport": {
"powerConsumption": {
"value": {
"energy": 4495500,
"deltaEnergy": 0,
"power": 0,
"powerEnergy": 0.0,
"persistedEnergy": 0,
"energySaved": 0,
"start": "2025-02-07T04:00:19Z",
"end": "2025-02-08T18:10:11Z"
},
"timestamp": "2025-02-08T18:10:11.053Z"
}
},
"dryerOperatingState": {
"completionTime": {
"value": "2025-02-08T19:25:10Z",
"timestamp": "2025-02-08T18:10:10.962Z"
},
"machineState": {
"value": "stop",
"timestamp": "2025-02-08T18:10:10.962Z"
},
"supportedMachineStates": {
"value": ["stop", "run", "pause"],
"timestamp": "2025-02-08T18:10:10.962Z"
},
"dryerJobState": {
"value": "none",
"timestamp": "2025-02-08T18:10:10.962Z"
}
},
"samsungce.detergentState": {
"remainingAmount": {
"value": 0,
"unit": "cc",
"timestamp": "2025-02-08T18:10:10.497Z"
},
"dosage": {
"value": 0,
"unit": "cc",
"timestamp": "2025-02-08T18:10:10.497Z"
},
"initialAmount": {
"value": 0,
"unit": "cc",
"timestamp": "2025-02-08T18:10:10.497Z"
},
"detergentType": {
"value": "none",
"timestamp": "2021-06-01T22:54:28.372Z"
}
},
"samsungce.dryerDelayEnd": {
"remainingTime": {
"value": 0,
"unit": "min",
"timestamp": "2025-02-08T18:10:10.962Z"
}
},
"refresh": {},
"custom.jobBeginningStatus": {
"jobBeginningStatus": {
"value": null
}
},
"execute": {
"data": {
"value": {
"payload": {
"rt": ["x.com.samsung.da.information"],
"if": ["oic.if.baseline", "oic.if.a"],
"x.com.samsung.da.modelNum": "DA_WM_A51_20_COMMON|20233741|3000000100111100020B000000000000",
"x.com.samsung.da.description": "DA_WM_A51_20_COMMON_DV6300R/DC92-02385A_0090",
"x.com.samsung.da.serialNum": "FFFFFFFFFFFFFFF",
"x.com.samsung.da.otnDUID": "7XCDM6YAIRCGM",
"x.com.samsung.da.items": [
{
"x.com.samsung.da.id": "0",
"x.com.samsung.da.description": "DA_WM_A51_20_COMMON|20233741|3000000100111100020B000000000000",
"x.com.samsung.da.type": "Software",
"x.com.samsung.da.number": "02198A220728(E256)",
"x.com.samsung.da.newVersionAvailable": "0"
},
{
"x.com.samsung.da.id": "1",
"x.com.samsung.da.description": "DA_WM_A51_20_COMMON",
"x.com.samsung.da.type": "Firmware",
"x.com.samsung.da.number": "18112816,20112625",
"x.com.samsung.da.newVersionAvailable": "0"
}
]
}
},
"data": {
"href": "/information/vs/0"
},
"timestamp": "2023-08-06T22:48:43.192Z"
}
},
"sec.wifiConfiguration": {
"autoReconnection": {
"value": null
},
"minVersion": {
"value": null
},
"supportedWiFiFreq": {
"value": null
},
"supportedAuthType": {
"value": null
},
"protocolType": {
"value": null
}
},
"remoteControlStatus": {
"remoteControlEnabled": {
"value": "false",
"timestamp": "2025-02-08T18:10:10.970Z"
}
},
"custom.supportedOptions": {
"course": {
"value": null
},
"referenceTable": {
"value": {
"id": "Table_00"
},
"timestamp": "2025-02-08T18:10:11.023Z"
},
"supportedCourses": {
"value": [
"01",
"9C",
"A5",
"9E",
"9B",
"27",
"E5",
"A0",
"A4",
"A6",
"A3",
"A2"
],
"timestamp": "2025-02-08T18:10:10.497Z"
}
},
"custom.energyType": {
"energyType": {
"value": "2.0",
"timestamp": "2022-06-14T06:49:02.183Z"
},
"energySavingSupport": {
"value": false,
"timestamp": "2022-06-14T06:49:02.721Z"
},
"drMaxDuration": {
"value": null
},
"energySavingLevel": {
"value": null
},
"energySavingInfo": {
"value": null
},
"supportedEnergySavingLevels": {
"value": null
},
"energySavingOperation": {
"value": null
},
"notificationTemplateID": {
"value": null
},
"energySavingOperationSupport": {
"value": null
}
},
"samsungce.dryerOperatingState": {
"operatingState": {
"value": "ready",
"timestamp": "2025-02-07T04:00:18.186Z"
},
"supportedOperatingStates": {
"value": ["ready", "running", "paused"],
"timestamp": "2022-11-01T13:43:26.961Z"
},
"scheduledJobs": {
"value": [
{
"jobName": "drying",
"timeInMin": 57
},
{
"jobName": "cooling",
"timeInMin": 3
}
],
"timestamp": "2025-02-08T18:10:10.497Z"
},
"progress": {
"value": 1,
"unit": "%",
"timestamp": "2025-02-07T04:00:18.186Z"
},
"remainingTimeStr": {
"value": "01:15",
"timestamp": "2025-02-07T04:00:18.186Z"
},
"dryerJobState": {
"value": "none",
"timestamp": "2025-02-07T04:00:18.186Z"
},
"remainingTime": {
"value": 75,
"unit": "min",
"timestamp": "2025-02-07T04:00:18.186Z"
}
},
"samsungce.softwareUpdate": {
"targetModule": {
"value": null
},
"otnDUID": {
"value": "7XCDM6YAIRCGM",
"timestamp": "2025-02-08T18:10:11.113Z"
},
"lastUpdatedDate": {
"value": null
},
"availableModules": {
"value": [],
"timestamp": "2024-12-02T00:29:53.432Z"
},
"newVersionAvailable": {
"value": false,
"timestamp": "2024-12-02T00:29:53.432Z"
},
"operatingState": {
"value": null
},
"progress": {
"value": null
}
},
"samsungce.dryerDryingTime": {
"supportedDryingTime": {
"value": ["0", "20", "30", "40", "50", "60"],
"timestamp": "2021-06-01T22:54:28.224Z"
},
"dryingTime": {
"value": "0",
"unit": "min",
"timestamp": "2025-02-08T18:10:10.840Z"
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,51 @@
{
"components": {
"main": {
"presenceSensor": {
"presence": {
"value": "not present",
"timestamp": "2025-02-11T13:58:50.044Z"
}
},
"healthCheck": {
"checkInterval": {
"value": 60,
"unit": "s",
"data": {
"deviceScheme": "UNTRACKED",
"protocol": "cloud"
},
"timestamp": "2025-01-16T21:14:07.471Z"
},
"healthStatus": {
"value": null
},
"DeviceWatch-Enroll": {
"value": null
},
"DeviceWatch-DeviceStatus": {
"value": "online",
"data": {},
"timestamp": "2025-02-11T14:23:22.053Z"
}
},
"temperatureMeasurement": {
"temperatureRange": {
"value": null
},
"temperature": {
"value": 71,
"unit": "F",
"timestamp": "2025-02-11T14:36:16.823Z"
}
},
"refresh": {},
"motionSensor": {
"motion": {
"value": "inactive",
"timestamp": "2025-02-11T13:58:50.044Z"
}
}
}
}
}

View File

@ -0,0 +1,98 @@
{
"components": {
"main": {
"relativeHumidityMeasurement": {
"humidity": {
"value": 32,
"unit": "%",
"timestamp": "2025-02-11T14:36:17.275Z"
}
},
"thermostatOperatingState": {
"thermostatOperatingState": {
"value": "heating",
"timestamp": "2025-02-11T13:39:58.286Z"
}
},
"healthCheck": {
"checkInterval": {
"value": 60,
"unit": "s",
"data": {
"deviceScheme": "UNTRACKED",
"protocol": "cloud"
},
"timestamp": "2025-01-16T21:14:07.448Z"
},
"healthStatus": {
"value": null
},
"DeviceWatch-Enroll": {
"value": null
},
"DeviceWatch-DeviceStatus": {
"value": "online",
"data": {},
"timestamp": "2025-02-11T13:39:58.286Z"
}
},
"temperatureMeasurement": {
"temperatureRange": {
"value": null
},
"temperature": {
"value": 71,
"unit": "F",
"timestamp": "2025-02-11T14:23:21.556Z"
}
},
"thermostatHeatingSetpoint": {
"heatingSetpoint": {
"value": 71,
"unit": "F",
"timestamp": "2025-02-11T13:39:58.286Z"
},
"heatingSetpointRange": {
"value": null
}
},
"thermostatFanMode": {
"thermostatFanMode": {
"value": "auto",
"data": {
"supportedThermostatFanModes": ["on", "auto"]
},
"timestamp": "2025-02-11T13:39:58.286Z"
},
"supportedThermostatFanModes": {
"value": ["on", "auto"],
"timestamp": "2025-02-11T13:39:58.286Z"
}
},
"refresh": {},
"thermostatMode": {
"thermostatMode": {
"value": "heat",
"data": {
"supportedThermostatModes": ["off", "cool", "auxheatonly", "auto"]
},
"timestamp": "2025-02-11T13:39:58.286Z"
},
"supportedThermostatModes": {
"value": ["off", "cool", "auxheatonly", "auto"],
"timestamp": "2025-02-11T13:39:58.286Z"
}
},
"thermostatCoolingSetpoint": {
"coolingSetpointRange": {
"value": null
},
"coolingSetpoint": {
"value": 73,
"unit": "F",
"timestamp": "2025-02-11T13:39:58.286Z"
}
}
}
}
}

View File

@ -0,0 +1,31 @@
{
"components": {
"main": {
"switch": {
"switch": {
"value": "off",
"timestamp": "2025-02-08T23:21:22.908Z"
}
},
"fanSpeed": {
"fanSpeed": {
"value": 60,
"timestamp": "2025-02-10T21:09:08.357Z"
}
},
"airConditionerFanMode": {
"fanMode": {
"value": null,
"timestamp": "2021-04-06T16:44:10.381Z"
},
"supportedAcFanModes": {
"value": ["auto", "low", "medium", "high", "turbo"],
"timestamp": "2024-09-10T10:26:28.605Z"
},
"availableAcFanModes": {
"value": null
}
}
}
}
}

View File

@ -0,0 +1,23 @@
{
"components": {
"main": {
"switchLevel": {
"levelRange": {
"value": null
},
"level": {
"value": 39,
"unit": "%",
"timestamp": "2025-02-07T02:39:25.819Z"
}
},
"refresh": {},
"switch": {
"switch": {
"value": "off",
"timestamp": "2025-02-08T23:21:22.908Z"
}
}
}
}
}

View File

@ -0,0 +1,75 @@
{
"components": {
"main": {
"healthCheck": {
"checkInterval": {
"value": 60,
"unit": "s",
"data": {
"deviceScheme": "UNTRACKED",
"protocol": "cloud"
},
"timestamp": "2023-12-17T18:11:41.671Z"
},
"healthStatus": {
"value": null
},
"DeviceWatch-Enroll": {
"value": null
},
"DeviceWatch-DeviceStatus": {
"value": "online",
"data": {},
"timestamp": "2025-02-07T15:14:53.823Z"
}
},
"switchLevel": {
"levelRange": {
"value": {
"minimum": 1,
"maximum": 100
},
"unit": "%",
"timestamp": "2025-02-07T15:14:53.823Z"
},
"level": {
"value": 70,
"unit": "%",
"timestamp": "2025-02-07T21:56:04.127Z"
}
},
"refresh": {},
"synthetic.lightingEffectFade": {
"fade": {
"value": null
}
},
"colorTemperature": {
"colorTemperatureRange": {
"value": {
"minimum": 2000,
"maximum": 6535
},
"unit": "K",
"timestamp": "2025-02-07T15:14:53.823Z"
},
"colorTemperature": {
"value": 3000,
"unit": "K",
"timestamp": "2025-02-07T21:56:04.127Z"
}
},
"switch": {
"switch": {
"value": "on",
"timestamp": "2025-02-07T21:56:04.127Z"
}
},
"synthetic.lightingEffectCircadian": {
"circadian": {
"value": null
}
}
}
}
}

View File

@ -0,0 +1,94 @@
{
"components": {
"main": {
"colorControl": {
"saturation": {
"value": 60,
"timestamp": "2025-02-07T15:14:53.812Z"
},
"color": {
"value": null
},
"hue": {
"value": 60.8072,
"timestamp": "2025-02-07T15:14:53.812Z"
}
},
"healthCheck": {
"checkInterval": {
"value": 60,
"unit": "s",
"data": {
"deviceScheme": "UNTRACKED",
"protocol": "cloud"
},
"timestamp": "2023-12-17T18:11:41.678Z"
},
"healthStatus": {
"value": null
},
"DeviceWatch-Enroll": {
"value": null
},
"DeviceWatch-DeviceStatus": {
"value": "online",
"data": {},
"timestamp": "2025-02-07T15:14:53.812Z"
}
},
"switchLevel": {
"levelRange": {
"value": {
"minimum": 1,
"maximum": 100
},
"unit": "%",
"timestamp": "2025-02-07T15:14:53.812Z"
},
"level": {
"value": 70,
"unit": "%",
"timestamp": "2025-02-07T21:56:02.381Z"
}
},
"refresh": {},
"synthetic.lightingEffectFade": {
"fade": {
"value": null
}
},
"samsungim.hueSyncMode": {
"mode": {
"value": "normal",
"timestamp": "2025-02-07T15:14:53.812Z"
}
},
"switch": {
"switch": {
"value": "off",
"timestamp": "2025-02-08T07:08:19.519Z"
}
},
"colorTemperature": {
"colorTemperatureRange": {
"value": {
"minimum": 2000,
"maximum": 6535
},
"unit": "K",
"timestamp": "2025-02-06T15:14:52.807Z"
},
"colorTemperature": {
"value": 3000,
"unit": "K",
"timestamp": "2025-02-07T21:56:02.381Z"
}
},
"synthetic.lightingEffectCircadian": {
"circadian": {
"value": null
}
}
}
}
}

View File

@ -0,0 +1,12 @@
{
"components": {
"main": {
"presenceSensor": {
"presence": {
"value": "present",
"timestamp": "2023-09-22T18:12:25.012Z"
}
}
}
}
}

View File

@ -0,0 +1,79 @@
{
"components": {
"main": {
"contactSensor": {
"contact": {
"value": "closed",
"timestamp": "2025-02-08T14:00:28.332Z"
}
},
"threeAxis": {
"threeAxis": {
"value": [20, 8, -1042],
"unit": "mG",
"timestamp": "2025-02-09T17:27:36.673Z"
}
},
"temperatureMeasurement": {
"temperatureRange": {
"value": null
},
"temperature": {
"value": 67.0,
"unit": "F",
"timestamp": "2025-02-09T17:56:19.744Z"
}
},
"refresh": {},
"battery": {
"quantity": {
"value": null
},
"battery": {
"value": 50,
"unit": "%",
"timestamp": "2025-02-09T12:24:02.074Z"
},
"type": {
"value": null
}
},
"firmwareUpdate": {
"lastUpdateStatusReason": {
"value": null
},
"availableVersion": {
"value": "0000001B",
"timestamp": "2025-02-09T04:20:25.600Z"
},
"lastUpdateStatus": {
"value": null
},
"supportedCommands": {
"value": null
},
"state": {
"value": "normalOperation",
"timestamp": "2025-02-09T04:20:25.600Z"
},
"updateAvailable": {
"value": false,
"timestamp": "2025-02-09T04:20:25.601Z"
},
"currentVersion": {
"value": "0000001B",
"timestamp": "2025-02-09T04:20:25.593Z"
},
"lastUpdateTime": {
"value": null
}
},
"accelerationSensor": {
"acceleration": {
"value": "inactive",
"timestamp": "2025-02-09T17:27:46.812Z"
}
}
}
}
}

View File

@ -0,0 +1,57 @@
{
"components": {
"main": {
"healthCheck": {
"checkInterval": {
"value": 60,
"unit": "s",
"data": {
"deviceScheme": "UNTRACKED",
"protocol": "cloud"
},
"timestamp": "2024-12-04T10:10:02.934Z"
},
"healthStatus": {
"value": null
},
"DeviceWatch-Enroll": {
"value": null
},
"DeviceWatch-DeviceStatus": {
"value": "online",
"data": {},
"timestamp": "2025-02-09T10:09:47.758Z"
}
},
"refresh": {},
"airConditionerMode": {
"availableAcModes": {
"value": null
},
"supportedAcModes": {
"value": null
},
"airConditionerMode": {
"value": "cool",
"timestamp": "2025-02-09T10:09:47.758Z"
}
},
"thermostatCoolingSetpoint": {
"coolingSetpointRange": {
"value": null
},
"coolingSetpoint": {
"value": 20,
"unit": "C",
"timestamp": "2025-02-09T10:09:47.758Z"
}
},
"switch": {
"switch": {
"value": "off",
"timestamp": "2025-02-09T10:09:47.758Z"
}
}
}
}
}

View File

@ -0,0 +1,43 @@
{
"components": {
"main": {
"refresh": {},
"firmwareUpdate": {
"lastUpdateStatusReason": {
"value": null
},
"availableVersion": {
"value": "00102101",
"timestamp": "2025-02-08T19:37:03.624Z"
},
"lastUpdateStatus": {
"value": null
},
"supportedCommands": {
"value": null
},
"state": {
"value": "normalOperation",
"timestamp": "2025-02-08T19:37:03.622Z"
},
"updateAvailable": {
"value": false,
"timestamp": "2025-02-08T19:37:03.624Z"
},
"currentVersion": {
"value": "00102101",
"timestamp": "2025-02-08T19:37:03.594Z"
},
"lastUpdateTime": {
"value": null
}
},
"switch": {
"switch": {
"value": "on",
"timestamp": "2025-02-09T17:31:12.210Z"
}
}
}
}
}

View File

@ -0,0 +1,259 @@
{
"components": {
"main": {
"mediaPlayback": {
"supportedPlaybackCommands": {
"value": ["play", "pause", "stop"],
"timestamp": "2025-02-02T13:18:40.078Z"
},
"playbackStatus": {
"value": "playing",
"timestamp": "2025-02-09T19:53:58.330Z"
}
},
"mediaPresets": {
"presets": {
"value": [
{
"id": "10",
"imageUrl": "https://www.storytel.com//images/320x320/0000059036.jpg",
"mediaSource": "Storytel",
"name": "Dra \u00e5t skogen Sune!"
},
{
"id": "22",
"imageUrl": "https://www.storytel.com//images/320x320/0000001894.jpg",
"mediaSource": "Storytel",
"name": "Fy katten Sune"
},
{
"id": "29",
"imageUrl": "https://www.storytel.com//images/320x320/0000001896.jpg",
"mediaSource": "Storytel",
"name": "Gult \u00e4r fult, Sune"
},
{
"id": "2",
"imageUrl": "https://static.mytuner.mobi/media/tvos_radios/2l5zg6lhjbab.png",
"mediaSource": "myTuner Radio",
"name": "Kiss"
},
{
"id": "3",
"imageUrl": "https://www.storytel.com//images/320x320/0000046017.jpg",
"mediaSource": "Storytel",
"name": "L\u00e4skigt Sune!"
},
{
"id": "16",
"imageUrl": "https://www.storytel.com//images/320x320/0002590598.jpg",
"mediaSource": "Storytel",
"name": "Pluggh\u00e4sten Sune"
},
{
"id": "14",
"imageUrl": "https://www.storytel.com//images/320x320/0000000070.jpg",
"mediaSource": "Storytel",
"name": "Sagan om Sune"
},
{
"id": "18",
"imageUrl": "https://www.storytel.com//images/320x320/0000006452.jpg",
"mediaSource": "Storytel",
"name": "Sk\u00e4mtaren Sune"
},
{
"id": "26",
"imageUrl": "https://www.storytel.com//images/320x320/0000001892.jpg",
"mediaSource": "Storytel",
"name": "Spik och panik, Sune!"
},
{
"id": "7",
"imageUrl": "https://www.storytel.com//images/320x320/0003119145.jpg",
"mediaSource": "Storytel",
"name": "Sune - T\u00e5gsemestern"
},
{
"id": "25",
"imageUrl": "https://www.storytel.com//images/320x320/0000000071.jpg",
"mediaSource": "Storytel",
"name": "Sune b\u00f6rjar tv\u00e5an"
},
{
"id": "9",
"imageUrl": "https://www.storytel.com//images/320x320/0000006448.jpg",
"mediaSource": "Storytel",
"name": "Sune i Grekland"
},
{
"id": "8",
"imageUrl": "https://www.storytel.com//images/320x320/0002492498.jpg",
"mediaSource": "Storytel",
"name": "Sune i Ullared"
},
{
"id": "30",
"imageUrl": "https://www.storytel.com//images/320x320/0002072946.jpg",
"mediaSource": "Storytel",
"name": "Sune och familjen Anderssons sjuka jul"
},
{
"id": "17",
"imageUrl": "https://www.storytel.com//images/320x320/0000000475.jpg",
"mediaSource": "Storytel",
"name": "Sune och klantpappan"
},
{
"id": "11",
"imageUrl": "https://www.storytel.com//images/320x320/0000042688.jpg",
"mediaSource": "Storytel",
"name": "Sune och Mamma Mysko"
},
{
"id": "20",
"imageUrl": "https://www.storytel.com//images/320x320/0000000072.jpg",
"mediaSource": "Storytel",
"name": "Sune och syster vampyr"
},
{
"id": "15",
"imageUrl": "https://www.storytel.com//images/320x320/0000039918.jpg",
"mediaSource": "Storytel",
"name": "Sune slutar f\u00f6rsta klass"
},
{
"id": "5",
"imageUrl": "https://www.storytel.com//images/320x320/0000017431.jpg",
"mediaSource": "Storytel",
"name": "Sune v\u00e4rsta killen!"
},
{
"id": "27",
"imageUrl": "https://www.storytel.com//images/320x320/0000068900.jpg",
"mediaSource": "Storytel",
"name": "Sunes halloween"
},
{
"id": "19",
"imageUrl": "https://www.storytel.com//images/320x320/0000000476.jpg",
"mediaSource": "Storytel",
"name": "Sunes hemligheter"
},
{
"id": "21",
"imageUrl": "https://www.storytel.com//images/320x320/0002370989.jpg",
"mediaSource": "Storytel",
"name": "Sunes hj\u00e4rnsl\u00e4pp"
},
{
"id": "24",
"imageUrl": "https://www.storytel.com//images/320x320/0000001889.jpg",
"mediaSource": "Storytel",
"name": "Sunes jul"
},
{
"id": "28",
"imageUrl": "https://www.storytel.com//images/320x320/0000034437.jpg",
"mediaSource": "Storytel",
"name": "Sunes party"
},
{
"id": "4",
"imageUrl": "https://www.storytel.com//images/320x320/0000006450.jpg",
"mediaSource": "Storytel",
"name": "Sunes skolresa"
},
{
"id": "13",
"imageUrl": "https://www.storytel.com//images/320x320/0000000477.jpg",
"mediaSource": "Storytel",
"name": "Sunes sommar"
},
{
"id": "12",
"imageUrl": "https://www.storytel.com//images/320x320/0000046015.jpg",
"mediaSource": "Storytel",
"name": "Sunes Sommarstuga"
},
{
"id": "6",
"imageUrl": "https://www.storytel.com//images/320x320/0002099327.jpg",
"mediaSource": "Storytel",
"name": "Supersnuten Sune"
},
{
"id": "23",
"imageUrl": "https://www.storytel.com//images/320x320/0000563738.jpg",
"mediaSource": "Storytel",
"name": "Zunes stolpskott"
}
],
"timestamp": "2025-02-02T13:18:48.272Z"
}
},
"audioVolume": {
"volume": {
"value": 15,
"unit": "%",
"timestamp": "2025-02-09T19:57:37.230Z"
}
},
"mediaGroup": {
"groupMute": {
"value": "unmuted",
"timestamp": "2025-02-07T01:19:54.911Z"
},
"groupPrimaryDeviceId": {
"value": "RINCON_38420B9108F601400",
"timestamp": "2025-02-09T19:52:24.000Z"
},
"groupId": {
"value": "RINCON_38420B9108F601400:3579458382",
"timestamp": "2025-02-09T19:54:06.936Z"
},
"groupVolume": {
"value": 12,
"unit": "%",
"timestamp": "2025-02-07T01:19:54.911Z"
},
"groupRole": {
"value": "ungrouped",
"timestamp": "2025-02-09T19:52:23.974Z"
}
},
"refresh": {},
"mediaTrackControl": {
"supportedTrackControlCommands": {
"value": ["nextTrack", "previousTrack"],
"timestamp": "2025-02-02T13:18:40.123Z"
}
},
"audioMute": {
"mute": {
"value": "unmuted",
"timestamp": "2025-02-09T19:57:35.487Z"
}
},
"audioNotification": {},
"audioTrackData": {
"totalTime": {
"value": null
},
"audioTrackData": {
"value": {
"album": "Forever Young",
"albumArtUrl": "http://192.168.1.123:1400/getaa?s=1&u=x-sonos-spotify%3aspotify%253atrack%253a3bg2qahpZmsg5wV2EMPXIk%3fsid%3d9%26flags%3d8232%26sn%3d9",
"artist": "David Guetta",
"mediaSource": "Spotify",
"title": "Forever Young"
},
"timestamp": "2025-02-09T19:53:55.615Z"
},
"elapsedTime": {
"value": null
}
}
}
}
}

View File

@ -0,0 +1,164 @@
{
"components": {
"main": {
"mediaPlayback": {
"supportedPlaybackCommands": {
"value": ["play", "pause", "stop"],
"timestamp": "2025-02-09T15:42:12.923Z"
},
"playbackStatus": {
"value": "stopped",
"timestamp": "2025-02-09T15:42:12.923Z"
}
},
"samsungvd.soundFrom": {
"mode": {
"value": 3,
"timestamp": "2025-02-09T15:42:13.215Z"
},
"detailName": {
"value": "External Device",
"timestamp": "2025-02-09T15:42:13.215Z"
}
},
"audioVolume": {
"volume": {
"value": 17,
"unit": "%",
"timestamp": "2025-02-09T17:25:51.839Z"
}
},
"samsungvd.audioGroupInfo": {
"role": {
"value": null
},
"status": {
"value": null
}
},
"refresh": {},
"audioNotification": {},
"execute": {
"data": {
"value": null
}
},
"samsungvd.audioInputSource": {
"supportedInputSources": {
"value": ["digital", "HDMI1", "bluetooth", "wifi", "HDMI2"],
"timestamp": "2025-02-09T17:18:44.680Z"
},
"inputSource": {
"value": "HDMI1",
"timestamp": "2025-02-09T17:18:44.680Z"
}
},
"switch": {
"switch": {
"value": "on",
"timestamp": "2025-02-09T17:25:51.536Z"
}
},
"ocf": {
"st": {
"value": "2024-12-10T02:12:44Z",
"timestamp": "2024-12-31T01:03:42.587Z"
},
"mndt": {
"value": "2023-01-01",
"timestamp": "2024-12-31T01:03:42.587Z"
},
"mnfv": {
"value": "SAT-iMX8M23WWC-1010.5",
"timestamp": "2024-12-31T01:03:42.587Z"
},
"mnhw": {
"value": "",
"timestamp": "2024-12-31T01:03:42.587Z"
},
"di": {
"value": "0d94e5db-8501-2355-eb4f-214163702cac",
"timestamp": "2024-12-31T01:03:42.587Z"
},
"mnsl": {
"value": "",
"timestamp": "2024-12-31T01:03:42.587Z"
},
"dmv": {
"value": "res.1.1.0,sh.1.1.0",
"timestamp": "2024-12-31T01:03:42.587Z"
},
"n": {
"value": "Soundbar Living",
"timestamp": "2024-12-31T01:03:42.587Z"
},
"mnmo": {
"value": "HW-Q990C",
"timestamp": "2024-12-31T01:03:42.587Z"
},
"vid": {
"value": "VD-NetworkAudio-002S",
"timestamp": "2024-12-31T01:03:42.587Z"
},
"mnmn": {
"value": "Samsung Electronics",
"timestamp": "2024-12-31T01:03:42.587Z"
},
"mnml": {
"value": "",
"timestamp": "2024-12-31T01:03:42.587Z"
},
"mnpv": {
"value": "7.0",
"timestamp": "2024-12-31T01:03:42.587Z"
},
"mnos": {
"value": "Tizen",
"timestamp": "2024-12-31T01:03:42.587Z"
},
"pi": {
"value": "0d94e5db-8501-2355-eb4f-214163702cac",
"timestamp": "2024-12-31T01:03:42.587Z"
},
"icv": {
"value": "core.1.1.0",
"timestamp": "2024-12-31T01:03:42.587Z"
}
},
"audioMute": {
"mute": {
"value": "unmuted",
"timestamp": "2025-02-09T17:18:44.787Z"
}
},
"samsungvd.thingStatus": {
"updatedTime": {
"value": 1739115734,
"timestamp": "2025-02-09T15:42:13.949Z"
},
"status": {
"value": "Idle",
"timestamp": "2025-02-09T15:42:13.949Z"
}
},
"audioTrackData": {
"totalTime": {
"value": 0,
"timestamp": "2024-12-31T00:29:29.953Z"
},
"audioTrackData": {
"value": {
"title": "",
"artist": "",
"album": ""
},
"timestamp": "2024-12-31T00:29:29.953Z"
},
"elapsedTime": {
"value": 0,
"timestamp": "2024-12-31T00:29:29.828Z"
}
}
}
}
}

View File

@ -0,0 +1,266 @@
{
"components": {
"main": {
"mediaPlayback": {
"supportedPlaybackCommands": {
"value": ["play", "pause", "stop", "fastForward", "rewind"],
"timestamp": "2020-05-07T02:58:10.250Z"
},
"playbackStatus": {
"value": null,
"timestamp": "2020-08-04T21:53:22.108Z"
}
},
"audioVolume": {
"volume": {
"value": 13,
"unit": "%",
"timestamp": "2021-08-21T19:19:52.832Z"
}
},
"samsungvd.supportsPowerOnByOcf": {
"supportsPowerOnByOcf": {
"value": null,
"timestamp": "2020-10-29T10:47:20.305Z"
}
},
"samsungvd.mediaInputSource": {
"supportedInputSourcesMap": {
"value": [
{
"id": "dtv",
"name": "TV"
},
{
"id": "HDMI1",
"name": "PlayStation 4"
},
{
"id": "HDMI4",
"name": "HT-CT370"
},
{
"id": "HDMI4",
"name": "HT-CT370"
}
],
"timestamp": "2021-10-16T15:18:11.622Z"
},
"inputSource": {
"value": "HDMI1",
"timestamp": "2021-08-28T16:29:59.716Z"
}
},
"mediaInputSource": {
"supportedInputSources": {
"value": ["digitalTv", "HDMI1", "HDMI4", "HDMI4"],
"timestamp": "2021-10-16T15:18:11.622Z"
},
"inputSource": {
"value": "HDMI1",
"timestamp": "2021-08-28T16:29:59.716Z"
}
},
"custom.tvsearch": {},
"samsungvd.ambient": {},
"refresh": {},
"custom.error": {
"error": {
"value": null,
"timestamp": "2020-08-04T21:53:22.148Z"
}
},
"execute": {
"data": {
"value": {
"payload": {
"rt": ["x.com.samsung.tv.deviceinfo"],
"if": ["oic.if.baseline", "oic.if.r"],
"x.com.samsung.country": "USA",
"x.com.samsung.infolinkversion": "T-INFOLINK2017-1008",
"x.com.samsung.modelid": "17_KANTM_UHD",
"x.com.samsung.tv.blemac": "CC:6E:A4:1F:4C:F7",
"x.com.samsung.tv.btmac": "CC:6E:A4:1F:4C:F7",
"x.com.samsung.tv.category": "tv",
"x.com.samsung.tv.countrycode": "US",
"x.com.samsung.tv.duid": "B2NBQRAG357IX",
"x.com.samsung.tv.ethmac": "c0:48:e6:e7:fc:2c",
"x.com.samsung.tv.p2pmac": "ce:6e:a4:1f:4c:f6",
"x.com.samsung.tv.udn": "717fb7ed-b310-4cfe-8954-1cd8211dd689",
"x.com.samsung.tv.wifimac": "cc:6e:a4:1f:4c:f6"
}
},
"data": {
"href": "/sec/tv/deviceinfo"
},
"timestamp": "2021-08-30T19:18:12.303Z"
}
},
"switch": {
"switch": {
"value": "on",
"timestamp": "2021-10-16T15:18:11.317Z"
}
},
"tvChannel": {
"tvChannel": {
"value": "",
"timestamp": "2020-05-07T02:58:10.479Z"
},
"tvChannelName": {
"value": "",
"timestamp": "2021-08-21T18:53:06.643Z"
}
},
"ocf": {
"st": {
"value": "2021-08-21T14:50:34Z",
"timestamp": "2021-08-21T19:19:51.890Z"
},
"mndt": {
"value": "2017-01-01",
"timestamp": "2021-08-21T19:19:51.890Z"
},
"mnfv": {
"value": "T-KTMAKUC-1290.3",
"timestamp": "2021-08-21T18:52:57.543Z"
},
"mnhw": {
"value": "0-0",
"timestamp": "2020-05-07T02:58:10.206Z"
},
"di": {
"value": "4588d2d9-a8cf-40f4-9a0b-ed5dfbaccda1",
"timestamp": "2020-05-07T02:58:10.206Z"
},
"mnsl": {
"value": "http://www.samsung.com/sec/tv/overview/",
"timestamp": "2021-08-21T19:19:51.890Z"
},
"dmv": {
"value": "res.1.1.0,sh.1.1.0",
"timestamp": "2021-08-21T18:52:58.071Z"
},
"n": {
"value": "[TV] Samsung 8 Series (49)",
"timestamp": "2020-05-07T02:58:10.206Z"
},
"mnmo": {
"value": "UN49MU8000",
"timestamp": "2020-05-07T02:58:10.206Z"
},
"vid": {
"value": "VD-STV_2017_K",
"timestamp": "2020-05-07T02:58:10.206Z"
},
"mnmn": {
"value": "Samsung Electronics",
"timestamp": "2020-05-07T02:58:10.206Z"
},
"mnml": {
"value": "http://www.samsung.com",
"timestamp": "2020-05-07T02:58:10.206Z"
},
"mnpv": {
"value": "Tizen 3.0",
"timestamp": "2020-05-07T02:58:10.206Z"
},
"mnos": {
"value": "4.1.10",
"timestamp": "2020-05-07T02:58:10.206Z"
},
"pi": {
"value": "4588d2d9-a8cf-40f4-9a0b-ed5dfbaccda1",
"timestamp": "2020-05-07T02:58:10.206Z"
},
"icv": {
"value": "core.1.1.0",
"timestamp": "2021-08-21T18:52:58.071Z"
}
},
"custom.picturemode": {
"pictureMode": {
"value": "Dynamic",
"timestamp": "2020-12-23T01:33:37.069Z"
},
"supportedPictureModes": {
"value": ["Dynamic", "Standard", "Natural", "Movie"],
"timestamp": "2020-05-07T02:58:10.585Z"
},
"supportedPictureModesMap": {
"value": [
{
"id": "modeDynamic",
"name": "Dynamic"
},
{
"id": "modeStandard",
"name": "Standard"
},
{
"id": "modeNatural",
"name": "Natural"
},
{
"id": "modeMovie",
"name": "Movie"
}
],
"timestamp": "2020-12-23T01:33:37.069Z"
}
},
"samsungvd.ambientContent": {
"supportedAmbientApps": {
"value": [],
"timestamp": "2021-01-17T01:10:11.985Z"
}
},
"custom.accessibility": {},
"custom.recording": {},
"custom.disabledCapabilities": {
"disabledCapabilities": {
"value": ["samsungvd.ambient", "samsungvd.ambientContent"],
"timestamp": "2021-01-17T01:10:11.985Z"
}
},
"custom.soundmode": {
"supportedSoundModesMap": {
"value": [
{
"id": "modeStandard",
"name": "Standard"
}
],
"timestamp": "2021-08-21T19:19:52.887Z"
},
"soundMode": {
"value": "Standard",
"timestamp": "2020-12-23T01:33:37.272Z"
},
"supportedSoundModes": {
"value": ["Standard"],
"timestamp": "2021-08-21T19:19:52.887Z"
}
},
"audioMute": {
"mute": {
"value": "muted",
"timestamp": "2021-08-21T19:19:52.832Z"
}
},
"mediaTrackControl": {
"supportedTrackControlCommands": {
"value": null,
"timestamp": "2020-08-04T21:53:22.384Z"
}
},
"custom.launchapp": {},
"samsungvd.firmwareVersion": {
"firmwareVersion": {
"value": null,
"timestamp": "2020-10-29T10:47:19.376Z"
}
}
}
}
}

View File

@ -0,0 +1,97 @@
{
"components": {
"main": {
"thermostatOperatingState": {
"thermostatOperatingState": {
"value": "pending cool",
"timestamp": "2025-02-10T22:04:56.341Z"
}
},
"thermostatHeatingSetpoint": {
"heatingSetpoint": {
"value": 814.7469111058201,
"unit": "F",
"timestamp": "2025-02-10T22:04:56.341Z"
},
"heatingSetpointRange": {
"value": {
"maximum": 3226.693210895862,
"step": 9234.459191378826,
"minimum": 6214.940743832475
},
"unit": "F",
"timestamp": "2025-02-10T22:04:56.341Z"
}
},
"temperatureMeasurement": {
"temperatureRange": {
"value": {
"maximum": 1826.722761785079,
"step": 138.2080712609211,
"minimum": 9268.726934158902
},
"unit": "F",
"timestamp": "2025-02-10T22:04:56.341Z"
},
"temperature": {
"value": 8554.194688973037,
"unit": "F",
"timestamp": "2025-02-10T22:04:56.341Z"
}
},
"thermostatFanMode": {
"thermostatFanMode": {
"value": "followschedule",
"data": {},
"timestamp": "2025-02-10T22:04:56.341Z"
},
"supportedThermostatFanModes": {
"value": ["on"],
"timestamp": "2025-02-10T22:04:56.341Z"
}
},
"thermostatMode": {
"thermostatMode": {
"value": "auxheatonly",
"data": {},
"timestamp": "2025-02-10T22:04:56.341Z"
},
"supportedThermostatModes": {
"value": ["rush hour"],
"timestamp": "2025-02-10T22:04:56.341Z"
}
},
"battery": {
"quantity": {
"value": 51,
"timestamp": "2025-02-10T22:04:56.341Z"
},
"battery": {
"value": 100,
"unit": "%",
"timestamp": "2025-02-10T22:04:56.341Z"
},
"type": {
"value": "38140",
"timestamp": "2025-02-10T22:04:56.341Z"
}
},
"thermostatCoolingSetpoint": {
"coolingSetpointRange": {
"value": {
"maximum": 7288.145606306409,
"step": 7620.031701049315,
"minimum": 4997.721228739137
},
"unit": "F",
"timestamp": "2025-02-10T22:04:56.341Z"
},
"coolingSetpoint": {
"value": 244.33726326608746,
"unit": "F",
"timestamp": "2025-02-10T22:04:56.341Z"
}
}
}
}
}

View File

@ -0,0 +1,13 @@
{
"components": {
"main": {
"refresh": {},
"valve": {
"valve": {
"value": "closed",
"timestamp": "2025-02-11T11:27:02.262Z"
}
}
}
}
}

View File

@ -0,0 +1,28 @@
{
"components": {
"main": {
"waterSensor": {
"water": {
"value": "dry",
"timestamp": "2025-02-10T21:58:18.784Z"
}
},
"refresh": {},
"battery": {
"quantity": {
"value": 84,
"timestamp": "2025-02-10T21:58:18.784Z"
},
"battery": {
"value": 100,
"unit": "%",
"timestamp": "2025-02-10T21:58:18.784Z"
},
"type": {
"value": "46120",
"timestamp": "2025-02-10T21:58:18.784Z"
}
}
}
}
}

View File

@ -0,0 +1,110 @@
{
"components": {
"main": {
"lock": {
"supportedUnlockDirections": {
"value": null
},
"supportedLockValues": {
"value": null
},
"lock": {
"value": "locked",
"data": {},
"timestamp": "2025-02-09T17:29:56.641Z"
},
"supportedLockCommands": {
"value": null
}
},
"refresh": {},
"battery": {
"quantity": {
"value": null
},
"battery": {
"value": 86,
"unit": "%",
"timestamp": "2025-02-09T17:18:14.150Z"
},
"type": {
"value": null
}
},
"firmwareUpdate": {
"lastUpdateStatusReason": {
"value": null
},
"availableVersion": {
"value": "00840847",
"timestamp": "2025-02-09T11:48:45.331Z"
},
"lastUpdateStatus": {
"value": null
},
"supportedCommands": {
"value": null
},
"state": {
"value": "normalOperation",
"timestamp": "2025-02-09T11:48:45.331Z"
},
"updateAvailable": {
"value": false,
"timestamp": "2025-02-09T11:48:45.332Z"
},
"currentVersion": {
"value": "00840847",
"timestamp": "2025-02-09T11:48:45.328Z"
},
"lastUpdateTime": {
"value": null
}
},
"lockCodes": {
"codeLength": {
"value": null,
"timestamp": "2020-08-04T15:29:24.127Z"
},
"maxCodes": {
"value": 250,
"timestamp": "2023-08-22T01:34:19.751Z"
},
"maxCodeLength": {
"value": 8,
"timestamp": "2023-08-22T01:34:18.690Z"
},
"codeChanged": {
"value": "8 unset",
"data": {
"codeName": "Code 8"
},
"timestamp": "2025-01-06T04:56:31.712Z"
},
"lock": {
"value": "locked",
"data": {
"method": "manual"
},
"timestamp": "2023-07-10T23:03:42.305Z"
},
"minCodeLength": {
"value": 4,
"timestamp": "2023-08-22T01:34:18.781Z"
},
"codeReport": {
"value": 5,
"timestamp": "2022-08-01T01:36:58.424Z"
},
"scanCodes": {
"value": "Complete",
"timestamp": "2025-01-06T04:56:31.730Z"
},
"lockCodes": {
"value": "{\"1\":\"Salim\",\"2\":\"Saima\",\"3\":\"Sarah\",\"4\":\"Aisha\",\"5\":\"Moiz\"}",
"timestamp": "2025-01-06T04:56:28.325Z"
}
}
}
}
}

View File

@ -0,0 +1,70 @@
{
"items": [
{
"deviceId": "f0af21a2-d5a1-437c-b10a-b34a87394b71",
"name": "aeotec-home-energy-meter-gen5",
"label": "Aeotec Energy Monitor",
"manufacturerName": "SmartThingsCommunity",
"presentationId": "3e0921d3-0a66-3d49-b458-752e596838e9",
"deviceManufacturerCode": "0086-0002-005F",
"locationId": "6911ddf5-f0cb-4516-a06a-3a2a6ec22bca",
"ownerId": "93257fc4-6471-2566-b06e-2fe72dd979fa",
"roomId": "cdf080f0-0542-41d7-a606-aff69683e04c",
"components": [
{
"id": "main",
"label": "Meter",
"capabilities": [
{
"id": "powerMeter",
"version": 1
},
{
"id": "energyMeter",
"version": 1
},
{
"id": "voltageMeasurement",
"version": 1
},
{
"id": "powerConsumptionReport",
"version": 1
},
{
"id": "refresh",
"version": 1
}
],
"categories": [
{
"name": "CurbPowerMeter",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2023-01-12T23:02:44.917Z",
"parentDeviceId": "6a2d07a4-dd77-48bc-9acf-017029aaf099",
"profile": {
"id": "6372c227-93c7-32ef-9be5-aef2221adff1"
},
"zwave": {
"networkId": "0A",
"driverId": "b98b34ce-1d1d-480c-bb17-41307a90cde0",
"executingLocally": true,
"hubId": "6a2d07a4-dd77-48bc-9acf-017029aaf099",
"networkSecurityLevel": "ZWAVE_S0_LEGACY",
"provisioningState": "PROVISIONED",
"manufacturerId": 134,
"productType": 2,
"productId": 95
},
"type": "ZWAVE",
"restrictionTier": 0,
"allowed": [],
"executionContext": "LOCAL"
}
],
"_links": {}
}

View File

@ -0,0 +1,62 @@
{
"items": [
{
"deviceId": "68e786a6-7f61-4c3a-9e13-70b803cf782b",
"name": "base-electric-meter",
"label": "Aeon Energy Monitor",
"manufacturerName": "SmartThingsCommunity",
"presentationId": "8e619cd9-c271-3ba0-9015-62bc074bc47f",
"deviceManufacturerCode": "0086-0002-0009",
"locationId": "c4d3b2a1-09f8-765e-4d3c-2b1a09f8e7d6 ",
"ownerId": "d47f2b19-3a6e-4c8d-bf21-9e8a7c5d134e",
"roomId": "94be4a1e-382a-4b7f-a5ef-fdb1a7d9f9e6",
"components": [
{
"id": "main",
"label": "main",
"capabilities": [
{
"id": "powerMeter",
"version": 1
},
{
"id": "energyMeter",
"version": 1
},
{
"id": "refresh",
"version": 1
}
],
"categories": [
{
"name": "CurbPowerMeter",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2023-06-03T16:23:57.284Z",
"parentDeviceId": "074fa784-8be8-4c70-8e22-6f5ed6f81b7e",
"profile": {
"id": "d382796f-8ed5-3088-8735-eb03e962203b"
},
"zwave": {
"networkId": "2A",
"driverId": "4fb7ec02-2697-4d73-977d-2b1c65c4484f",
"executingLocally": true,
"hubId": "074fa784-8be8-4c70-8e22-6f5ed6f81b7e",
"networkSecurityLevel": "ZWAVE_LEGACY_NON_SECURE",
"provisioningState": "PROVISIONED",
"manufacturerId": 134,
"productType": 2,
"productId": 9
},
"type": "ZWAVE",
"restrictionTier": 0,
"allowed": [],
"executionContext": "LOCAL"
}
],
"_links": {}
}

View File

@ -0,0 +1,79 @@
{
"items": [
{
"deviceId": "10e06a70-ee7d-4832-85e9-a0a06a7a05bd",
"name": "c2c-arlo-pro-3-switch",
"label": "2nd Floor Hallway",
"manufacturerName": "SmartThings",
"presentationId": "SmartThings-smartthings-c2c_arlo_pro_3",
"deviceManufacturerCode": "Arlo",
"locationId": "c4d3b2a1-09f8-765e-4d3c-2b1a09f8e7d6 ",
"ownerId": "d47f2b19-3a6e-4c8d-bf21-9e8a7c5d134e",
"roomId": "68b45114-9af8-4906-8636-b973a6faa271",
"components": [
{
"id": "main",
"label": "main",
"capabilities": [
{
"id": "switch",
"version": 1
},
{
"id": "refresh",
"version": 1
},
{
"id": "soundSensor",
"version": 1
},
{
"id": "healthCheck",
"version": 1
},
{
"id": "videoStream",
"version": 1
},
{
"id": "motionSensor",
"version": 1
},
{
"id": "videoCapture",
"version": 1
},
{
"id": "battery",
"version": 1
},
{
"id": "alarm",
"version": 1
}
],
"categories": [
{
"name": "Camera",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2024-11-21T21:55:59.340Z",
"profile": {
"id": "89aefc3a-e210-4678-944c-638d47d296f6"
},
"viper": {
"manufacturerName": "Arlo",
"modelName": "VMC4041PB",
"endpointAppId": "viper_555d6f40-b65a-11ea-8fe0-77cb99571462"
},
"type": "VIPER",
"restrictionTier": 0,
"allowed": [],
"executionContext": "CLOUD"
}
],
"_links": {}
}

View File

@ -0,0 +1,59 @@
{
"items": [
{
"deviceId": "571af102-15db-4030-b76b-245a691f74a5",
"name": "c2c-shade",
"label": "Curtain 1A",
"manufacturerName": "SmartThings",
"presentationId": "SmartThings-smartthings-c2c-shade",
"deviceManufacturerCode": "WonderLabs Company",
"locationId": "88a3a314-f0c8-40b4-bb44-44ba06c9c42f",
"ownerId": "12d4af93-cb68-b108-87f5-625437d7371f",
"components": [
{
"id": "main",
"label": "main",
"capabilities": [
{
"id": "windowShade",
"version": 1
},
{
"id": "switchLevel",
"version": 1
},
{
"id": "refresh",
"version": 1
},
{
"id": "healthCheck",
"version": 1
}
],
"categories": [
{
"name": "Blind",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2025-02-07T23:01:15.883Z",
"profile": {
"id": "0ceffb3e-10d3-4123-bb42-2a92c93c6e25"
},
"viper": {
"manufacturerName": "WonderLabs Company",
"modelName": "WoCurtain3",
"hwVersion": "WoCurtain3-WoCurtain3",
"endpointAppId": "viper_f18eb770-077d-11ea-bb72-9922e3ed0d38"
},
"type": "VIPER",
"restrictionTier": 0,
"allowed": [],
"executionContext": "CLOUD"
}
],
"_links": {}
}

View File

@ -0,0 +1,67 @@
{
"items": [
{
"deviceId": "d0268a69-abfb-4c92-a646-61cec2e510ad",
"name": "plug-level-power",
"label": "Dimmer Debian",
"manufacturerName": "SmartThingsCommunity",
"presentationId": "bb7c4cfb-6eaf-3efc-823b-06a54fc9ded9",
"deviceManufacturerCode": "CentraLite",
"locationId": "c4d3b2a1-09f8-765e-4d3c-2b1a09f8e7d6 ",
"ownerId": "d47f2b19-3a6e-4c8d-bf21-9e8a7c5d134e",
"roomId": "94be4a1e-382a-4b7f-a5ef-fdb1a7d9f9e6",
"components": [
{
"id": "main",
"label": "main",
"capabilities": [
{
"id": "switch",
"version": 1
},
{
"id": "switchLevel",
"version": 1
},
{
"id": "powerMeter",
"version": 1
},
{
"id": "firmwareUpdate",
"version": 1
},
{
"id": "refresh",
"version": 1
}
],
"categories": [
{
"name": "SmartPlug",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2024-08-15T22:16:37.926Z",
"parentDeviceId": "074fa784-8be8-4c70-8e22-6f5ed6f81b7e",
"profile": {
"id": "24195ea4-635c-3450-a235-71bc78ab3d1c"
},
"zigbee": {
"eui": "000D6F0003C04BC9",
"networkId": "F50E",
"driverId": "f2e891c6-00cc-446c-9192-8ebda63d9898",
"executingLocally": true,
"hubId": "074fa784-8be8-4c70-8e22-6f5ed6f81b7e",
"provisioningState": "PROVISIONED"
},
"type": "ZIGBEE",
"restrictionTier": 0,
"allowed": [],
"executionContext": "LOCAL"
}
],
"_links": {}
}

View File

@ -0,0 +1,71 @@
{
"items": [
{
"deviceId": "2d9a892b-1c93-45a5-84cb-0e81889498c6",
"name": "contact-profile",
"label": ".Front Door Open/Closed Sensor",
"manufacturerName": "SmartThingsCommunity",
"presentationId": "a7f2c1d9-89b3-35a4-b217-fc68d9e4e752",
"deviceManufacturerCode": "Visonic",
"locationId": "c4d3b2a1-09f8-765e-4d3c-2b1a09f8e7d6 ",
"ownerId": "d47f2b19-3a6e-4c8d-bf21-9e8a7c5d134e",
"roomId": "68b45114-9af8-4906-8636-b973a6faa271",
"components": [
{
"id": "main",
"label": "main",
"capabilities": [
{
"id": "contactSensor",
"version": 1
},
{
"id": "temperatureMeasurement",
"version": 1
},
{
"id": "battery",
"version": 1
},
{
"id": "firmwareUpdate",
"version": 1
},
{
"id": "refresh",
"version": 1
}
],
"categories": [
{
"name": "ContactSensor",
"categoryType": "manufacturer"
},
{
"name": "ContactSensor",
"categoryType": "user"
}
]
}
],
"createTime": "2023-09-28T17:38:59.179Z",
"parentDeviceId": "074fa784-8be8-4c70-8e22-6f5ed6f81b7e",
"profile": {
"id": "22aa5a07-ac33-365f-b2f1-5ecef8cdb0eb"
},
"zigbee": {
"eui": "000D6F000576F604",
"networkId": "5A44",
"driverId": "408981c2-91d4-4dfc-bbfb-84ca0205d993",
"executingLocally": true,
"hubId": "074fa784-8be8-4c70-8e22-6f5ed6f81b7e",
"provisioningState": "PROVISIONED"
},
"type": "ZIGBEE",
"restrictionTier": 0,
"allowed": [],
"executionContext": "LOCAL"
}
],
"_links": {}
}

View File

@ -0,0 +1,311 @@
{
"items": [
{
"deviceId": "96a5ef74-5832-a84b-f1f7-ca799957065d",
"name": "[room a/c] Samsung",
"label": "AC Office Granit",
"manufacturerName": "Samsung Electronics",
"presentationId": "DA-AC-RAC-000001",
"deviceManufacturerCode": "Samsung Electronics",
"locationId": "58d3fd7c-c512-4da3-b500-ef269382756c",
"ownerId": "f9a28d7c-1ed5-d9e9-a81c-18971ec081db",
"roomId": "85a79db4-9cf2-4f09-a5b2-cd70a5c0cef0",
"deviceTypeName": "Samsung OCF Air Conditioner",
"components": [
{
"id": "main",
"label": "main",
"capabilities": [
{
"id": "ocf",
"version": 1
},
{
"id": "switch",
"version": 1
},
{
"id": "airConditionerMode",
"version": 1
},
{
"id": "airConditionerFanMode",
"version": 1
},
{
"id": "fanOscillationMode",
"version": 1
},
{
"id": "airQualitySensor",
"version": 1
},
{
"id": "temperatureMeasurement",
"version": 1
},
{
"id": "thermostatCoolingSetpoint",
"version": 1
},
{
"id": "relativeHumidityMeasurement",
"version": 1
},
{
"id": "dustSensor",
"version": 1
},
{
"id": "veryFineDustSensor",
"version": 1
},
{
"id": "audioVolume",
"version": 1
},
{
"id": "remoteControlStatus",
"version": 1
},
{
"id": "powerConsumptionReport",
"version": 1
},
{
"id": "demandResponseLoadControl",
"version": 1
},
{
"id": "refresh",
"version": 1
},
{
"id": "execute",
"version": 1
},
{
"id": "custom.spiMode",
"version": 1
},
{
"id": "custom.thermostatSetpointControl",
"version": 1
},
{
"id": "custom.airConditionerOptionalMode",
"version": 1
},
{
"id": "custom.airConditionerTropicalNightMode",
"version": 1
},
{
"id": "custom.autoCleaningMode",
"version": 1
},
{
"id": "custom.deviceReportStateConfiguration",
"version": 1
},
{
"id": "custom.energyType",
"version": 1
},
{
"id": "custom.dustFilter",
"version": 1
},
{
"id": "custom.airConditionerOdorController",
"version": 1
},
{
"id": "custom.deodorFilter",
"version": 1
},
{
"id": "custom.disabledComponents",
"version": 1
},
{
"id": "custom.disabledCapabilities",
"version": 1
},
{
"id": "samsungce.deviceIdentification",
"version": 1
},
{
"id": "samsungce.dongleSoftwareInstallation",
"version": 1
},
{
"id": "samsungce.softwareUpdate",
"version": 1
},
{
"id": "samsungce.selfCheck",
"version": 1
},
{
"id": "samsungce.driverVersion",
"version": 1
}
],
"categories": [
{
"name": "AirConditioner",
"categoryType": "manufacturer"
}
]
},
{
"id": "1",
"label": "1",
"capabilities": [
{
"id": "switch",
"version": 1
},
{
"id": "airConditionerMode",
"version": 1
},
{
"id": "airConditionerFanMode",
"version": 1
},
{
"id": "fanOscillationMode",
"version": 1
},
{
"id": "temperatureMeasurement",
"version": 1
},
{
"id": "thermostatCoolingSetpoint",
"version": 1
},
{
"id": "relativeHumidityMeasurement",
"version": 1
},
{
"id": "airQualitySensor",
"version": 1
},
{
"id": "dustSensor",
"version": 1
},
{
"id": "veryFineDustSensor",
"version": 1
},
{
"id": "odorSensor",
"version": 1
},
{
"id": "remoteControlStatus",
"version": 1
},
{
"id": "audioVolume",
"version": 1
},
{
"id": "custom.thermostatSetpointControl",
"version": 1
},
{
"id": "custom.autoCleaningMode",
"version": 1
},
{
"id": "custom.airConditionerTropicalNightMode",
"version": 1
},
{
"id": "custom.disabledCapabilities",
"version": 1
},
{
"id": "ocf",
"version": 1
},
{
"id": "powerConsumptionReport",
"version": 1
},
{
"id": "demandResponseLoadControl",
"version": 1
},
{
"id": "custom.spiMode",
"version": 1
},
{
"id": "custom.airConditionerOptionalMode",
"version": 1
},
{
"id": "custom.deviceReportStateConfiguration",
"version": 1
},
{
"id": "custom.energyType",
"version": 1
},
{
"id": "custom.dustFilter",
"version": 1
},
{
"id": "custom.airConditionerOdorController",
"version": 1
},
{
"id": "custom.deodorFilter",
"version": 1
}
],
"categories": [
{
"name": "Other",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2021-04-06T16:43:34.753Z",
"profile": {
"id": "60fbc713-8da5-315d-b31a-6d6dcde4be7b"
},
"ocf": {
"ocfDeviceType": "oic.d.airconditioner",
"name": "[room a/c] Samsung",
"specVersion": "core.1.1.0",
"verticalDomainSpecVersion": "res.1.1.0,sh.1.1.0",
"manufacturerName": "Samsung Electronics",
"modelNumber": "ARTIK051_KRAC_18K|10193441|60010132001111110200000000000000",
"platformVersion": "0G3MPDCKA00010E",
"platformOS": "TizenRT2.0",
"hwVersion": "1.0",
"firmwareVersion": "0.1.0",
"vendorId": "DA-AC-RAC-000001",
"lastSignupTime": "2021-04-06T16:43:27.889445Z",
"transferCandidate": false,
"additionalAuthCodeRequired": false
},
"type": "OCF",
"restrictionTier": 0,
"allowed": [],
"executionContext": "CLOUD"
}
],
"_links": {}
}

View File

@ -0,0 +1,264 @@
{
"items": [
{
"deviceId": "4ece486b-89db-f06a-d54d-748b676b4d8e",
"name": "Samsung-Room-Air-Conditioner",
"label": "Aire Dormitorio Principal",
"manufacturerName": "Samsung Electronics",
"presentationId": "DA-AC-RAC-01001",
"deviceManufacturerCode": "Samsung Electronics",
"locationId": "c4189ac1-208f-461a-8ab6-ea67937b3743",
"ownerId": "85ea07e1-7063-f673-3ba5-125293f297c8",
"roomId": "1f66199a-1773-4d8f-97b7-44c312a62cf7",
"deviceTypeName": "Samsung OCF Air Conditioner",
"components": [
{
"id": "main",
"label": "main",
"capabilities": [
{
"id": "ocf",
"version": 1
},
{
"id": "switch",
"version": 1
},
{
"id": "airConditionerMode",
"version": 1
},
{
"id": "airConditionerFanMode",
"version": 1
},
{
"id": "bypassable",
"version": 1
},
{
"id": "fanOscillationMode",
"version": 1
},
{
"id": "temperatureMeasurement",
"version": 1
},
{
"id": "thermostatCoolingSetpoint",
"version": 1
},
{
"id": "relativeHumidityMeasurement",
"version": 1
},
{
"id": "airQualitySensor",
"version": 1
},
{
"id": "odorSensor",
"version": 1
},
{
"id": "dustSensor",
"version": 1
},
{
"id": "veryFineDustSensor",
"version": 1
},
{
"id": "audioVolume",
"version": 1
},
{
"id": "powerConsumptionReport",
"version": 1
},
{
"id": "demandResponseLoadControl",
"version": 1
},
{
"id": "refresh",
"version": 1
},
{
"id": "execute",
"version": 1
},
{
"id": "audioNotification",
"version": 1
},
{
"id": "custom.spiMode",
"version": 1
},
{
"id": "custom.thermostatSetpointControl",
"version": 1
},
{
"id": "custom.airConditionerOptionalMode",
"version": 1
},
{
"id": "custom.airConditionerTropicalNightMode",
"version": 1
},
{
"id": "custom.autoCleaningMode",
"version": 1
},
{
"id": "custom.deviceReportStateConfiguration",
"version": 1
},
{
"id": "custom.energyType",
"version": 1
},
{
"id": "custom.dustFilter",
"version": 1
},
{
"id": "custom.veryFineDustFilter",
"version": 1
},
{
"id": "custom.deodorFilter",
"version": 1
},
{
"id": "custom.electricHepaFilter",
"version": 1
},
{
"id": "custom.doNotDisturbMode",
"version": 1
},
{
"id": "custom.periodicSensing",
"version": 1
},
{
"id": "custom.airConditionerOdorController",
"version": 1
},
{
"id": "custom.disabledCapabilities",
"version": 1
},
{
"id": "samsungce.alwaysOnSensing",
"version": 1
},
{
"id": "samsungce.airConditionerBeep",
"version": 1
},
{
"id": "samsungce.airConditionerLighting",
"version": 1
},
{
"id": "samsungce.airQualityHealthConcern",
"version": 1
},
{
"id": "samsungce.buttonDisplayCondition",
"version": 1
},
{
"id": "samsungce.deviceIdentification",
"version": 1
},
{
"id": "samsungce.driverVersion",
"version": 1
},
{
"id": "samsungce.dustFilterAlarm",
"version": 1
},
{
"id": "samsungce.individualControlLock",
"version": 1
},
{
"id": "samsungce.softwareUpdate",
"version": 1
},
{
"id": "samsungce.selfCheck",
"version": 1
},
{
"id": "samsungce.silentAction",
"version": 1
},
{
"id": "samsungce.quickControl",
"version": 1
},
{
"id": "samsungce.welcomeCooling",
"version": 1
},
{
"id": "samsungce.unavailableCapabilities",
"version": 1
},
{
"id": "sec.diagnosticsInformation",
"version": 1
},
{
"id": "sec.wifiConfiguration",
"version": 1
},
{
"id": "sec.calmConnectionCare",
"version": 1
}
],
"categories": [
{
"name": "AirConditioner",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2025-01-28T21:31:35.755Z",
"profile": {
"id": "091a55f4-7054-39fa-b23e-b56deb7580f8"
},
"ocf": {
"ocfDeviceType": "oic.d.airconditioner",
"name": "Samsung-Room-Air-Conditioner",
"specVersion": "core.1.1.0",
"verticalDomainSpecVersion": "1.2.1",
"manufacturerName": "Samsung Electronics",
"modelNumber": "ARA-WW-TP1-22-COMMON|10229641|60010523001511014600083200800000",
"platformVersion": "DAWIT 2.0",
"platformOS": "TizenRT 3.1",
"hwVersion": "Realtek",
"firmwareVersion": "ARA-WW-TP1-22-COMMON_11240702",
"vendorId": "DA-AC-RAC-01001",
"vendorResourceClientServerVersion": "Realtek Release 3.1.240221",
"lastSignupTime": "2025-01-28T21:31:30.090416369Z",
"transferCandidate": false,
"additionalAuthCodeRequired": false
},
"type": "OCF",
"restrictionTier": 0,
"allowed": [],
"executionContext": "CLOUD"
}
],
"_links": {}
}

View File

@ -0,0 +1,176 @@
{
"items": [
{
"deviceId": "2bad3237-4886-e699-1b90-4a51a3d55c8a",
"name": "Samsung Microwave",
"label": "Microwave",
"manufacturerName": "Samsung Electronics",
"presentationId": "DA-KS-MICROWAVE-0101X",
"deviceManufacturerCode": "Samsung Electronics",
"locationId": "586e4602-34ab-4a22-993e-5f616b04604f",
"ownerId": "b603d7e8-6066-4e10-8102-afa752a63816",
"roomId": "f4d03391-ab13-4c1d-b4dc-d6ddf86014a2",
"deviceTypeName": "oic.d.microwave",
"components": [
{
"id": "main",
"label": "main",
"capabilities": [
{
"id": "ocf",
"version": 1
},
{
"id": "execute",
"version": 1
},
{
"id": "switch",
"version": 1
},
{
"id": "refresh",
"version": 1
},
{
"id": "remoteControlStatus",
"version": 1
},
{
"id": "ovenSetpoint",
"version": 1
},
{
"id": "ovenMode",
"version": 1
},
{
"id": "ovenOperatingState",
"version": 1
},
{
"id": "doorControl",
"version": 1
},
{
"id": "temperatureMeasurement",
"version": 1
},
{
"id": "samsungce.deviceIdentification",
"version": 1
},
{
"id": "samsungce.driverVersion",
"version": 1
},
{
"id": "samsungce.hoodFanSpeed",
"version": 1
},
{
"id": "samsungce.definedRecipe",
"version": 1
},
{
"id": "samsungce.doorState",
"version": 1
},
{
"id": "samsungce.kitchenDeviceIdentification",
"version": 1
},
{
"id": "samsungce.kitchenDeviceDefaults",
"version": 1
},
{
"id": "samsungce.ovenMode",
"version": 1
},
{
"id": "samsungce.ovenOperatingState",
"version": 1
},
{
"id": "samsungce.microwavePower",
"version": 1
},
{
"id": "samsungce.kitchenModeSpecification",
"version": 1
},
{
"id": "samsungce.kidsLock",
"version": 1
},
{
"id": "samsungce.softwareUpdate",
"version": 1
},
{
"id": "custom.disabledCapabilities",
"version": 1
},
{
"id": "sec.diagnosticsInformation",
"version": 1
}
],
"categories": [
{
"name": "Microwave",
"categoryType": "manufacturer"
}
]
},
{
"id": "hood",
"label": "hood",
"capabilities": [
{
"id": "samsungce.lamp",
"version": 1
},
{
"id": "samsungce.hoodFanSpeed",
"version": 1
}
],
"categories": [
{
"name": "Other",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2022-03-23T15:59:10.704Z",
"profile": {
"id": "e5db3b6f-cad6-3caa-9775-9c9cae20f4a4"
},
"ocf": {
"ocfDeviceType": "oic.d.microwave",
"name": "Samsung Microwave",
"specVersion": "core.1.1.0",
"verticalDomainSpecVersion": "res.1.1.0,sh.1.1.0",
"manufacturerName": "Samsung Electronics",
"modelNumber": "TP2X_DA-KS-MICROWAVE-0101X|40436241|50040100011411000200000000000000",
"platformVersion": "DAWIT 3.0",
"platformOS": "TizenRT 2.0 + IPv6",
"hwVersion": "MediaTek",
"firmwareVersion": "AKS-WW-TP2-20-MICROWAVE-OTR_40230125",
"vendorId": "DA-KS-MICROWAVE-0101X",
"vendorResourceClientServerVersion": "MediaTek Release 2.220916.2",
"lastSignupTime": "2022-04-17T15:33:11.063457Z",
"transferCandidate": false,
"additionalAuthCodeRequired": false
},
"type": "OCF",
"restrictionTier": 0,
"allowed": [],
"executionContext": "CLOUD"
}
],
"_links": {}
}

View File

@ -0,0 +1,412 @@
{
"items": [
{
"deviceId": "7db87911-7dce-1cf2-7119-b953432a2f09",
"name": "[refrigerator] Samsung",
"label": "Refrigerator",
"manufacturerName": "Samsung Electronics",
"presentationId": "DA-REF-NORMAL-000001",
"deviceManufacturerCode": "Samsung Electronics",
"locationId": "c4d3b2a1-09f8-765e-4d3c-2b1a09f8e7d6 ",
"ownerId": "d47f2b19-3a6e-4c8d-bf21-9e8a7c5d134e",
"roomId": "3a1f7e7c-4e59-4c29-adb0-0813be691efd",
"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.deodorFilter",
"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.softwareUpdate",
"version": 1
},
{
"id": "samsungce.deviceIdentification",
"version": 1
},
{
"id": "samsungce.dongleSoftwareInstallation",
"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.quickControl",
"version": 1
},
{
"id": "sec.diagnosticsInformation",
"version": 1
}
],
"categories": [
{
"name": "Refrigerator",
"categoryType": "manufacturer"
},
{
"name": "Refrigerator",
"categoryType": "user"
}
]
},
{
"id": "freezer",
"label": "freezer",
"capabilities": [
{
"id": "contactSensor",
"version": 1
},
{
"id": "temperatureMeasurement",
"version": 1
},
{
"id": "thermostatCoolingSetpoint",
"version": 1
},
{
"id": "custom.disabledCapabilities",
"version": 1
},
{
"id": "custom.fridgeMode",
"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.fridgeMode",
"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": "temperatureMeasurement",
"version": 1
},
{
"id": "thermostatCoolingSetpoint",
"version": 1
},
{
"id": "custom.disabledCapabilities",
"version": 1
},
{
"id": "custom.fridgeMode",
"version": 1
}
],
"categories": [
{
"name": "Other",
"categoryType": "manufacturer"
}
]
},
{
"id": "onedoor",
"label": "onedoor",
"capabilities": [
{
"id": "contactSensor",
"version": 1
},
{
"id": "temperatureMeasurement",
"version": 1
},
{
"id": "thermostatCoolingSetpoint",
"version": 1
},
{
"id": "custom.disabledCapabilities",
"version": 1
},
{
"id": "custom.fridgeMode",
"version": 1
},
{
"id": "custom.thermostatSetpointControl",
"version": 1
},
{
"id": "samsungce.freezerConvertMode",
"version": 1
},
{
"id": "samsungce.unavailableCapabilities",
"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": "pantry-01",
"label": "pantry-01",
"capabilities": [
{
"id": "samsungce.fridgePantryInfo",
"version": 1
},
{
"id": "samsungce.fridgePantryMode",
"version": 1
},
{
"id": "custom.disabledCapabilities",
"version": 1
}
],
"categories": [
{
"name": "Other",
"categoryType": "manufacturer"
}
]
},
{
"id": "pantry-02",
"label": "pantry-02",
"capabilities": [
{
"id": "samsungce.fridgePantryInfo",
"version": 1
},
{
"id": "samsungce.fridgePantryMode",
"version": 1
},
{
"id": "custom.disabledCapabilities",
"version": 1
}
],
"categories": [
{
"name": "Other",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2022-01-08T16:50:43.544Z",
"profile": {
"id": "f2a9af35-5df8-3477-91df-94941d302591"
},
"ocf": {
"ocfDeviceType": "oic.d.refrigerator",
"name": "[refrigerator] Samsung",
"specVersion": "core.1.1.0",
"verticalDomainSpecVersion": "res.1.1.0,sh.1.1.0",
"manufacturerName": "Samsung Electronics",
"modelNumber": "TP2X_REF_20K|00115641|0004014D011411200103000020000000",
"platformVersion": "DAWIT 2.0",
"platformOS": "TizenRT 1.0 + IPv6",
"hwVersion": "MediaTek",
"firmwareVersion": "A-RFWW-TP2-21-COMMON_20220110",
"vendorId": "DA-REF-NORMAL-000001",
"vendorResourceClientServerVersion": "MediaTek Release 2.210524.1",
"lastSignupTime": "2024-08-06T15:24:29.362093Z",
"transferCandidate": false,
"additionalAuthCodeRequired": false
},
"type": "OCF",
"restrictionTier": 0,
"allowed": [],
"executionContext": "CLOUD"
}
],
"_links": {}
}

View File

@ -0,0 +1,119 @@
{
"items": [
{
"deviceId": "3442dfc6-17c0-a65f-dae0-4c6e01786f44",
"name": "[robot vacuum] Samsung",
"label": "Robot vacuum",
"manufacturerName": "Samsung Electronics",
"presentationId": "DA-RVC-NORMAL-000001",
"deviceManufacturerCode": "Samsung Electronics",
"locationId": "586e4602-34ab-4a22-993e-5f616b04604f",
"ownerId": "b603d7e8-6066-4e10-8102-afa752a63816",
"roomId": "5d425f41-042a-4d9a-92c4-e43150a61bae",
"deviceTypeName": "Samsung OCF Robot Vacuum",
"components": [
{
"id": "main",
"label": "Robot vacuum",
"capabilities": [
{
"id": "ocf",
"version": 1
},
{
"id": "execute",
"version": 1
},
{
"id": "refresh",
"version": 1
},
{
"id": "battery",
"version": 1
},
{
"id": "switch",
"version": 1
},
{
"id": "powerConsumptionReport",
"version": 1
},
{
"id": "robotCleanerTurboMode",
"version": 1
},
{
"id": "robotCleanerMovement",
"version": 1
},
{
"id": "robotCleanerCleaningMode",
"version": 1
},
{
"id": "custom.disabledCapabilities",
"version": 1
},
{
"id": "custom.disabledComponents",
"version": 1
},
{
"id": "samsungce.deviceIdentification",
"version": 1
},
{
"id": "samsungce.softwareUpdate",
"version": 1
},
{
"id": "samsungce.robotCleanerCleaningMode",
"version": 1
},
{
"id": "samsungce.robotCleanerOperatingState",
"version": 1
},
{
"id": "samsungce.driverVersion",
"version": 1
}
],
"categories": [
{
"name": "RobotCleaner",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2018-06-06T23:04:25Z",
"profile": {
"id": "61b1c3cd-61cc-3dde-a4ba-9477d5e559cb"
},
"ocf": {
"ocfDeviceType": "oic.d.robotcleaner",
"name": "[robot vacuum] Samsung",
"specVersion": "core.1.1.0",
"verticalDomainSpecVersion": "res.1.1.0,sh.1.1.0",
"manufacturerName": "Samsung Electronics",
"modelNumber": "powerbot_7000_17M|50016055|80010404011141000100000000000000",
"platformVersion": "00",
"platformOS": "Tizen(3/0)",
"hwVersion": "1.0",
"firmwareVersion": "1.0",
"vendorId": "DA-RVC-NORMAL-000001",
"lastSignupTime": "2020-11-03T04:43:02.729Z",
"transferCandidate": false,
"additionalAuthCodeRequired": false
},
"type": "OCF",
"restrictionTier": 0,
"allowed": [],
"executionContext": "CLOUD"
}
],
"_links": {}
}

View File

@ -0,0 +1,168 @@
{
"items": [
{
"deviceId": "f36dc7ce-cac0-0667-dc14-a3704eb5e676",
"name": "[dishwasher] Samsung",
"label": "Dishwasher",
"manufacturerName": "Samsung Electronics",
"presentationId": "DA-WM-DW-000001",
"deviceManufacturerCode": "Samsung Electronics",
"locationId": "586e4602-34ab-4a22-993e-5f616b04604f",
"ownerId": "b603d7e8-6066-4e10-8102-afa752a63816",
"roomId": "f4d03391-ab13-4c1d-b4dc-d6ddf86014a2",
"deviceTypeName": "Samsung OCF Dishwasher",
"components": [
{
"id": "main",
"label": "main",
"capabilities": [
{
"id": "execute",
"version": 1
},
{
"id": "ocf",
"version": 1
},
{
"id": "powerConsumptionReport",
"version": 1
},
{
"id": "refresh",
"version": 1
},
{
"id": "remoteControlStatus",
"version": 1
},
{
"id": "switch",
"version": 1
},
{
"id": "demandResponseLoadControl",
"version": 1
},
{
"id": "dishwasherOperatingState",
"version": 1
},
{
"id": "custom.disabledCapabilities",
"version": 1
},
{
"id": "custom.dishwasherOperatingProgress",
"version": 1
},
{
"id": "custom.dishwasherOperatingPercentage",
"version": 1
},
{
"id": "custom.dishwasherDelayStartTime",
"version": 1
},
{
"id": "custom.energyType",
"version": 1
},
{
"id": "custom.supportedOptions",
"version": 1
},
{
"id": "custom.waterFilter",
"version": 1
},
{
"id": "samsungce.deviceIdentification",
"version": 1
},
{
"id": "samsungce.dishwasherJobState",
"version": 1
},
{
"id": "samsungce.dishwasherWashingCourse",
"version": 1
},
{
"id": "samsungce.dishwasherWashingCourseDetails",
"version": 1
},
{
"id": "samsungce.dishwasherOperation",
"version": 1
},
{
"id": "samsungce.dishwasherWashingOptions",
"version": 1
},
{
"id": "samsungce.driverVersion",
"version": 1
},
{
"id": "samsungce.softwareUpdate",
"version": 1
},
{
"id": "samsungce.kidsLock",
"version": 1
},
{
"id": "samsungce.waterConsumptionReport",
"version": 1
},
{
"id": "samsungce.quickControl",
"version": 1
},
{
"id": "sec.diagnosticsInformation",
"version": 1
},
{
"id": "sec.wifiConfiguration",
"version": 1
}
],
"categories": [
{
"name": "Dishwasher",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2021-06-27T01:19:35.408Z",
"profile": {
"id": "0cba797c-40ee-3473-aa01-4ee5b6cb8c67"
},
"ocf": {
"ocfDeviceType": "oic.d.dishwasher",
"name": "[dishwasher] Samsung",
"specVersion": "core.1.1.0",
"verticalDomainSpecVersion": "res.1.1.0,sh.1.1.0",
"manufacturerName": "Samsung Electronics",
"modelNumber": "DA_DW_A51_20_COMMON|30007242|40010201001311000101000000000000",
"platformVersion": "DAWIT 2.0",
"platformOS": "TizenRT 1.0 + IPv6",
"hwVersion": "ARTIK051",
"firmwareVersion": "DA_DW_A51_20_COMMON_30230714",
"vendorId": "DA-WM-DW-000001",
"vendorResourceClientServerVersion": "ARTIK051 Release 2.210224.1",
"lastSignupTime": "2021-10-16T17:28:59.984202Z",
"transferCandidate": false,
"additionalAuthCodeRequired": false
},
"type": "OCF",
"restrictionTier": 0,
"allowed": [],
"executionContext": "CLOUD"
}
],
"_links": {}
}

View File

@ -0,0 +1,204 @@
{
"items": [
{
"deviceId": "02f7256e-8353-5bdd-547f-bd5b1647e01b",
"name": "[dryer] Samsung",
"label": "Dryer",
"manufacturerName": "Samsung Electronics",
"presentationId": "DA-WM-WD-000001",
"deviceManufacturerCode": "Samsung Electronics",
"locationId": "781d5f1e-c87e-455e-87f7-8e954879e91d",
"ownerId": "b603d7e8-6066-4e10-8102-afa752a63816",
"roomId": "2a8637b2-77ad-475e-b537-7b6f7f97fff6",
"deviceTypeName": "Samsung OCF Dryer",
"components": [
{
"id": "main",
"label": "main",
"capabilities": [
{
"id": "ocf",
"version": 1
},
{
"id": "execute",
"version": 1
},
{
"id": "refresh",
"version": 1
},
{
"id": "switch",
"version": 1
},
{
"id": "remoteControlStatus",
"version": 1
},
{
"id": "dryerOperatingState",
"version": 1
},
{
"id": "powerConsumptionReport",
"version": 1
},
{
"id": "demandResponseLoadControl",
"version": 1
},
{
"id": "custom.disabledCapabilities",
"version": 1
},
{
"id": "custom.dryerDryLevel",
"version": 1
},
{
"id": "custom.dryerWrinklePrevent",
"version": 1
},
{
"id": "custom.energyType",
"version": 1
},
{
"id": "custom.jobBeginningStatus",
"version": 1
},
{
"id": "custom.supportedOptions",
"version": 1
},
{
"id": "samsungce.softwareUpdate",
"version": 1
},
{
"id": "samsungce.detergentOrder",
"version": 1
},
{
"id": "samsungce.detergentState",
"version": 1
},
{
"id": "samsungce.deviceIdentification",
"version": 1
},
{
"id": "samsungce.dongleSoftwareInstallation",
"version": 1
},
{
"id": "samsungce.driverVersion",
"version": 1
},
{
"id": "samsungce.dryerAutoCycleLink",
"version": 1
},
{
"id": "samsungce.dryerCycle",
"version": 1
},
{
"id": "samsungce.dryerCyclePreset",
"version": 1
},
{
"id": "samsungce.dryerDelayEnd",
"version": 1
},
{
"id": "samsungce.dryerDryingTemperature",
"version": 1
},
{
"id": "samsungce.dryerDryingTime",
"version": 1
},
{
"id": "samsungce.dryerFreezePrevent",
"version": 1
},
{
"id": "samsungce.dryerOperatingState",
"version": 1
},
{
"id": "samsungce.kidsLock",
"version": 1
},
{
"id": "samsungce.welcomeMessage",
"version": 1
},
{
"id": "samsungce.quickControl",
"version": 1
},
{
"id": "sec.diagnosticsInformation",
"version": 1
},
{
"id": "sec.wifiConfiguration",
"version": 1
}
],
"categories": [
{
"name": "Dryer",
"categoryType": "manufacturer"
}
]
},
{
"id": "hca.main",
"label": "hca.main",
"capabilities": [
{
"id": "hca.dryerMode",
"version": 1
}
],
"categories": [
{
"name": "Other",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2021-06-01T22:54:25.907Z",
"profile": {
"id": "53a1d049-eeda-396c-8324-e33438ef57be"
},
"ocf": {
"ocfDeviceType": "oic.d.dryer",
"name": "[dryer] Samsung",
"specVersion": "core.1.1.0",
"verticalDomainSpecVersion": "res.1.1.0,sh.1.1.0",
"manufacturerName": "Samsung Electronics",
"modelNumber": "DA_WM_A51_20_COMMON|20233741|3000000100111100020B000000000000",
"platformVersion": "DAWIT 2.0",
"platformOS": "TizenRT 1.0 + IPv6",
"hwVersion": "ARTIK051",
"firmwareVersion": "DA_WM_A51_20_COMMON_30230708",
"vendorId": "DA-WM-WD-000001",
"vendorResourceClientServerVersion": "ARTIK051 Release 2.210224.1",
"lastSignupTime": "2021-06-01T22:54:22.826697Z",
"transferCandidate": false,
"additionalAuthCodeRequired": false
},
"type": "OCF",
"restrictionTier": 0,
"allowed": [],
"executionContext": "CLOUD"
}
],
"_links": {}
}

View File

@ -0,0 +1,260 @@
{
"items": [
{
"deviceId": "f984b91d-f250-9d42-3436-33f09a422a47",
"name": "[washer] Samsung",
"label": "Washer",
"manufacturerName": "Samsung Electronics",
"presentationId": "DA-WM-WM-000001",
"deviceManufacturerCode": "Samsung Electronics",
"locationId": "781d5f1e-c87e-455e-87f7-8e954879e91d",
"ownerId": "b603d7e8-6066-4e10-8102-afa752a63816",
"roomId": "2a8637b2-77ad-475e-b537-7b6f7f97fff6",
"deviceTypeName": "Samsung OCF Washer",
"components": [
{
"id": "main",
"label": "main",
"capabilities": [
{
"id": "execute",
"version": 1
},
{
"id": "ocf",
"version": 1
},
{
"id": "powerConsumptionReport",
"version": 1
},
{
"id": "refresh",
"version": 1
},
{
"id": "remoteControlStatus",
"version": 1
},
{
"id": "demandResponseLoadControl",
"version": 1
},
{
"id": "switch",
"version": 1
},
{
"id": "washerOperatingState",
"version": 1
},
{
"id": "custom.disabledCapabilities",
"version": 1
},
{
"id": "custom.dryerDryLevel",
"version": 1
},
{
"id": "custom.energyType",
"version": 1
},
{
"id": "custom.jobBeginningStatus",
"version": 1
},
{
"id": "custom.supportedOptions",
"version": 1
},
{
"id": "custom.washerAutoDetergent",
"version": 1
},
{
"id": "custom.washerAutoSoftener",
"version": 1
},
{
"id": "custom.washerRinseCycles",
"version": 1
},
{
"id": "custom.washerSoilLevel",
"version": 1
},
{
"id": "custom.washerSpinLevel",
"version": 1
},
{
"id": "custom.washerWaterTemperature",
"version": 1
},
{
"id": "samsungce.autoDispenseDetergent",
"version": 1
},
{
"id": "samsungce.autoDispenseSoftener",
"version": 1
},
{
"id": "samsungce.detergentOrder",
"version": 1
},
{
"id": "samsungce.detergentState",
"version": 1
},
{
"id": "samsungce.deviceIdentification",
"version": 1
},
{
"id": "samsungce.dongleSoftwareInstallation",
"version": 1
},
{
"id": "samsungce.detergentAutoReplenishment",
"version": 1
},
{
"id": "samsungce.softenerAutoReplenishment",
"version": 1
},
{
"id": "samsungce.driverVersion",
"version": 1
},
{
"id": "samsungce.softwareUpdate",
"version": 1
},
{
"id": "samsungce.kidsLock",
"version": 1
},
{
"id": "samsungce.softenerOrder",
"version": 1
},
{
"id": "samsungce.softenerState",
"version": 1
},
{
"id": "samsungce.washerBubbleSoak",
"version": 1
},
{
"id": "samsungce.washerCycle",
"version": 1
},
{
"id": "samsungce.washerCyclePreset",
"version": 1
},
{
"id": "samsungce.washerDelayEnd",
"version": 1
},
{
"id": "samsungce.washerFreezePrevent",
"version": 1
},
{
"id": "samsungce.washerOperatingState",
"version": 1
},
{
"id": "samsungce.washerWashingTime",
"version": 1
},
{
"id": "samsungce.washerWaterLevel",
"version": 1
},
{
"id": "samsungce.washerWaterValve",
"version": 1
},
{
"id": "samsungce.welcomeMessage",
"version": 1
},
{
"id": "samsungce.waterConsumptionReport",
"version": 1
},
{
"id": "samsungce.quickControl",
"version": 1
},
{
"id": "samsungce.energyPlanner",
"version": 1
},
{
"id": "sec.diagnosticsInformation",
"version": 1
},
{
"id": "sec.wifiConfiguration",
"version": 1
}
],
"categories": [
{
"name": "Washer",
"categoryType": "manufacturer"
}
]
},
{
"id": "hca.main",
"label": "hca.main",
"capabilities": [
{
"id": "hca.washerMode",
"version": 1
}
],
"categories": [
{
"name": "Other",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2021-06-01T22:52:18.023Z",
"profile": {
"id": "3f221c79-d81c-315f-8e8b-b5742802a1e3"
},
"ocf": {
"ocfDeviceType": "oic.d.washer",
"name": "[washer] Samsung",
"specVersion": "core.1.1.0",
"verticalDomainSpecVersion": "res.1.1.0,sh.1.1.0",
"manufacturerName": "Samsung Electronics",
"modelNumber": "DA_WM_TP2_20_COMMON|20233741|2001000100131100022B010000000000",
"platformVersion": "DAWIT 2.0",
"platformOS": "TizenRT 2.0 + IPv6",
"hwVersion": "MediaTek",
"firmwareVersion": "DA_WM_TP2_20_COMMON_30230804",
"vendorId": "DA-WM-WM-000001",
"vendorResourceClientServerVersion": "MediaTek Release 2.211214.1",
"lastSignupTime": "2021-06-01T22:52:13.923649Z",
"transferCandidate": false,
"additionalAuthCodeRequired": false
},
"type": "OCF",
"restrictionTier": 0,
"allowed": [],
"executionContext": "CLOUD"
}
],
"_links": {}
}

View File

@ -0,0 +1,64 @@
{
"items": [
{
"deviceId": "d5dc3299-c266-41c7-bd08-f540aea54b89",
"name": "ecobee Sensor",
"label": "Child Bedroom",
"manufacturerName": "0A0b",
"presentationId": "ST_635a866e-a3ea-4184-9d60-9c72ea603dfd",
"deviceManufacturerCode": "ecobee",
"locationId": "b6fe1fcb-e82b-4ce8-a5e1-85e96adba06c",
"ownerId": "b473ee01-2b1f-7bb1-c433-3caec75960bc",
"components": [
{
"id": "main",
"label": "main",
"capabilities": [
{
"id": "temperatureMeasurement",
"version": 1
},
{
"id": "motionSensor",
"version": 1
},
{
"id": "presenceSensor",
"version": 1
},
{
"id": "refresh",
"version": 1
},
{
"id": "healthCheck",
"version": 1
}
],
"categories": [
{
"name": "MotionSensor",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2025-01-16T21:14:07.283Z",
"profile": {
"id": "8ab3ca07-0d07-471b-a276-065e46d7aa8a"
},
"viper": {
"manufacturerName": "ecobee",
"modelName": "aresSmart-ecobee3_remote_sensor",
"swVersion": "250206213001",
"hwVersion": "250206213001",
"endpointAppId": "viper_92ccdcc0-4184-11eb-b9c5-036180216747"
},
"type": "VIPER",
"restrictionTier": 0,
"allowed": [],
"executionContext": "CLOUD"
}
],
"_links": {}
}

View File

@ -0,0 +1,80 @@
{
"items": [
{
"deviceId": "028469cb-6e89-4f14-8d9a-bfbca5e0fbfc",
"name": "v4 - ecobee Thermostat - Heat and Cool (F)",
"label": "Main Floor",
"manufacturerName": "0A0b",
"presentationId": "ST_5334da38-8076-4b40-9f6c-ac3fccaa5d24",
"deviceManufacturerCode": "ecobee",
"locationId": "b6fe1fcb-e82b-4ce8-a5e1-85e96adba06c",
"ownerId": "b473ee01-2b1f-7bb1-c433-3caec75960bc",
"components": [
{
"id": "main",
"label": "main",
"capabilities": [
{
"id": "temperatureMeasurement",
"version": 1
},
{
"id": "relativeHumidityMeasurement",
"version": 1
},
{
"id": "thermostatHeatingSetpoint",
"version": 1
},
{
"id": "thermostatCoolingSetpoint",
"version": 1
},
{
"id": "thermostatOperatingState",
"version": 1
},
{
"id": "thermostatMode",
"version": 1
},
{
"id": "thermostatFanMode",
"version": 1
},
{
"id": "refresh",
"version": 1
},
{
"id": "healthCheck",
"version": 1
}
],
"categories": [
{
"name": "Thermostat",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2025-01-16T21:14:07.276Z",
"profile": {
"id": "234d537d-d388-497f-b0f4-2e25025119ba"
},
"viper": {
"manufacturerName": "ecobee",
"modelName": "aresSmart-thermostat",
"swVersion": "250206151734",
"hwVersion": "250206151734",
"endpointAppId": "viper_92ccdcc0-4184-11eb-b9c5-036180216747"
},
"type": "VIPER",
"restrictionTier": 0,
"allowed": [],
"executionContext": "CLOUD"
}
],
"_links": {}
}

View File

@ -0,0 +1,50 @@
{
"items": [
{
"deviceId": "f1af21a2-d5a1-437c-b10a-b34a87394b71",
"name": "fake-fan",
"label": "Fake fan",
"manufacturerName": "Myself",
"presentationId": "3f0921d3-0a66-3d49-b458-752e596838e9",
"deviceManufacturerCode": "0086-0002-005F",
"locationId": "6f11ddf5-f0cb-4516-a06a-3a2a6ec22bca",
"ownerId": "9f257fc4-6471-2566-b06e-2fe72dd979fa",
"roomId": "cdf080f0-0542-41d7-a606-aff69683e04c",
"components": [
{
"id": "main",
"capabilities": [
{
"id": "switch",
"version": 1
},
{
"id": "fanSpeed",
"version": 1
},
{
"id": "airConditionerFanMode",
"version": 1
}
],
"categories": [
{
"name": "Fan",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2023-01-12T23:02:44.917Z",
"parentDeviceId": "6a2dd7a4-dd77-48bc-9acf-017029aaf099",
"profile": {
"id": "6372cd27-93c7-32ef-9be5-aef2221adff1"
},
"type": "ZWAVE",
"restrictionTier": 0,
"allowed": [],
"executionContext": "LOCAL"
}
],
"_links": {}
}

View File

@ -0,0 +1,65 @@
{
"items": [
{
"deviceId": "aaedaf28-2ae0-4c1d-b57e-87f6a420c298",
"name": "GE Dimmer Switch",
"label": "Basement Exit Light",
"manufacturerName": "SmartThingsCommunity",
"presentationId": "31cf01ee-cb49-3d95-ac2d-2afab47f25c7",
"deviceManufacturerCode": "0063-4944-3130",
"locationId": "c4d3b2a1-09f8-765e-4d3c-2b1a09f8e7d6 ",
"roomId": "e73dcd00-6953-431d-ae79-73fd2f2c528e",
"components": [
{
"id": "main",
"label": "Basement Exit Light",
"capabilities": [
{
"id": "switch",
"version": 1
},
{
"id": "switchLevel",
"version": 1
},
{
"id": "refresh",
"version": 1
}
],
"categories": [
{
"name": "Switch",
"categoryType": "manufacturer"
},
{
"name": "Switch",
"categoryType": "user"
}
]
}
],
"createTime": "2020-05-25T18:18:01Z",
"parentDeviceId": "074fa784-8be8-4c70-8e22-6f5ed6f81b7e",
"profile": {
"id": "ec5458c2-c011-3479-a59b-82b42820c2f7"
},
"zwave": {
"networkId": "14",
"driverId": "2cbf55e3-dbc2-48a2-8be5-4c3ce756b692",
"executingLocally": true,
"hubId": "074fa784-8be8-4c70-8e22-6f5ed6f81b7e",
"networkSecurityLevel": "ZWAVE_LEGACY_NON_SECURE",
"provisioningState": "NONFUNCTIONAL",
"manufacturerId": 99,
"productType": 18756,
"productId": 12592
},
"type": "ZWAVE",
"restrictionTier": 0,
"allowed": [],
"executionContext": "LOCAL"
}
],
"_links": {}
}

View File

@ -0,0 +1,73 @@
{
"items": [
{
"deviceId": "440063de-a200-40b5-8a6b-f3399eaa0370",
"name": "hue-color-temperature-bulb",
"label": "Bathroom spot",
"manufacturerName": "0A2r",
"presentationId": "ST_b93bec0e-1a81-4471-83fc-4dddca504acd",
"deviceManufacturerCode": "Signify Netherlands B.V.",
"locationId": "88a3a314-f0c8-40b4-bb44-44ba06c9c42f",
"ownerId": "12d4af93-cb68-b108-87f5-625437d7371f",
"components": [
{
"id": "main",
"label": "main",
"capabilities": [
{
"id": "colorTemperature",
"version": 1
},
{
"id": "switch",
"version": 1
},
{
"id": "switchLevel",
"version": 1
},
{
"id": "healthCheck",
"version": 1
},
{
"id": "refresh",
"version": 1
},
{
"id": "synthetic.lightingEffectCircadian",
"version": 1
},
{
"id": "synthetic.lightingEffectFade",
"version": 1
}
],
"categories": [
{
"name": "Light",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2023-12-17T18:11:41.453Z",
"profile": {
"id": "a79e4507-ecaa-3c7e-b660-a3a71f30eafb"
},
"viper": {
"uniqueIdentifier": "ea409b82a6184ad9b49bd6318692cc1c",
"manufacturerName": "Signify Netherlands B.V.",
"modelName": "Hue ambiance spot",
"swVersion": "1.122.2",
"hwVersion": "LTG002",
"endpointAppId": "viper_71ee45b0-a794-11e9-86b2-fdd6b9f75ce6"
},
"type": "VIPER",
"restrictionTier": 0,
"allowed": [],
"executionContext": "CLOUD"
}
],
"_links": {}
}

View File

@ -0,0 +1,81 @@
{
"items": [
{
"deviceId": "cb958955-b015-498c-9e62-fc0c51abd054",
"name": "hue-rgbw-color-bulb",
"label": "Standing light",
"manufacturerName": "0A2r",
"presentationId": "ST_2733b8dc-4b0f-4593-8e49-2432202abd52",
"deviceManufacturerCode": "Signify Netherlands B.V.",
"locationId": "88a3a314-f0c8-40b4-bb44-44ba06c9c42f",
"ownerId": "12d4af93-cb68-b108-87f5-625437d7371f",
"components": [
{
"id": "main",
"label": "main",
"capabilities": [
{
"id": "switch",
"version": 1
},
{
"id": "colorControl",
"version": 1
},
{
"id": "colorTemperature",
"version": 1
},
{
"id": "switchLevel",
"version": 1
},
{
"id": "healthCheck",
"version": 1
},
{
"id": "refresh",
"version": 1
},
{
"id": "samsungim.hueSyncMode",
"version": 1
},
{
"id": "synthetic.lightingEffectCircadian",
"version": 1
},
{
"id": "synthetic.lightingEffectFade",
"version": 1
}
],
"categories": [
{
"name": "Light",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2023-12-17T18:11:41.454Z",
"profile": {
"id": "71be1b96-c5b5-38f7-a22c-65f5392ce7ed"
},
"viper": {
"uniqueIdentifier": "f5f891a57b9d45408230b4228bdc2111",
"manufacturerName": "Signify Netherlands B.V.",
"modelName": "Hue color lamp",
"swVersion": "1.122.2",
"hwVersion": "LCA001",
"endpointAppId": "viper_71ee45b0-a794-11e9-86b2-fdd6b9f75ce6"
},
"type": "VIPER",
"restrictionTier": 0,
"allowed": [],
"executionContext": "CLOUD"
}
],
"_links": {}
}

View File

@ -0,0 +1,41 @@
{
"items": [
{
"deviceId": "184c67cc-69e2-44b6-8f73-55c963068ad9",
"name": "iPhone",
"label": "iPhone",
"manufacturerName": "SmartThings",
"presentationId": "SmartThings-smartthings-Mobile_Presence",
"locationId": "c4d3b2a1-09f8-765e-4d3c-2b1a09f8e7d6 ",
"ownerId": "d47f2b19-3a6e-4c8d-bf21-9e8a7c5d134e",
"components": [
{
"id": "main",
"label": "main",
"capabilities": [
{
"id": "presenceSensor",
"version": 1
}
],
"categories": [
{
"name": "MobilePresence",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2021-12-02T16:14:24.394Z",
"parentDeviceId": "b8e11599-5297-4574-8e62-885995fcaa20",
"profile": {
"id": "21d0f660-98b4-3f7b-8114-fe62e555628e"
},
"type": "MOBILE",
"restrictionTier": 0,
"allowed": [],
"executionContext": "CLOUD"
}
],
"_links": {}
}

View File

@ -0,0 +1,78 @@
{
"items": [
{
"deviceId": "7d246592-93db-4d72-a10d-5a51793ece8c",
"name": "Multipurpose Sensor",
"label": "Deck Door",
"manufacturerName": "SmartThingsCommunity",
"presentationId": "c385e2bc-acb8-317b-be2a-6efd1f879720",
"deviceManufacturerCode": "SmartThings",
"locationId": "c4d3b2a1-09f8-765e-4d3c-2b1a09f8e7d6 ",
"roomId": "b277a3c0-b8fe-44de-9133-c1108747810c",
"components": [
{
"id": "main",
"label": "Deck Door",
"capabilities": [
{
"id": "contactSensor",
"version": 1
},
{
"id": "temperatureMeasurement",
"version": 1
},
{
"id": "threeAxis",
"version": 1
},
{
"id": "accelerationSensor",
"version": 1
},
{
"id": "battery",
"version": 1
},
{
"id": "firmwareUpdate",
"version": 1
},
{
"id": "refresh",
"version": 1
}
],
"categories": [
{
"name": "MultiFunctionalSensor",
"categoryType": "manufacturer"
},
{
"name": "Door",
"categoryType": "user"
}
]
}
],
"createTime": "2019-02-23T16:53:57Z",
"parentDeviceId": "074fa784-8be8-4c70-8e22-6f5ed6f81b7e",
"profile": {
"id": "4471213f-121b-38fd-b022-51df37ac1d4c"
},
"zigbee": {
"eui": "24FD5B00010AED6B",
"networkId": "C972",
"driverId": "408981c2-91d4-4dfc-bbfb-84ca0205d993",
"executingLocally": true,
"hubId": "074fa784-8be8-4c70-8e22-6f5ed6f81b7e",
"provisioningState": "PROVISIONED"
},
"type": "ZIGBEE",
"restrictionTier": 0,
"allowed": [],
"executionContext": "LOCAL"
}
],
"_links": {}
}

View File

@ -0,0 +1,64 @@
{
"items": [
{
"deviceId": "bf4b1167-48a3-4af7-9186-0900a678ffa5",
"name": "sensibo-airconditioner-1",
"label": "Office",
"manufacturerName": "0ABU",
"presentationId": "sensibo-airconditioner-1",
"deviceManufacturerCode": "Sensibo",
"locationId": "fe14085e-bacb-4997-bc0c-df08204eaea2",
"ownerId": "49228038-22ca-1c78-d7ab-b774b4569480",
"components": [
{
"id": "main",
"label": "main",
"capabilities": [
{
"id": "switch",
"version": 1
},
{
"id": "thermostatCoolingSetpoint",
"version": 1
},
{
"id": "airConditionerMode",
"version": 1
},
{
"id": "healthCheck",
"version": 1
},
{
"id": "refresh",
"version": 1
}
],
"categories": [
{
"name": "AirConditioner",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2024-12-04T10:10:02.873Z",
"profile": {
"id": "ddaffb28-8ebb-4bd6-9d6f-57c28dcb434d"
},
"viper": {
"manufacturerName": "Sensibo",
"modelName": "skyplus",
"swVersion": "SKY40147",
"hwVersion": "SKY40147",
"endpointAppId": "viper_5661d200-806e-11e9-abe0-3b2f83c8954c"
},
"type": "VIPER",
"restrictionTier": 0,
"allowed": [],
"executionContext": "CLOUD"
}
],
"_links": {}
}

View File

@ -0,0 +1,59 @@
{
"items": [
{
"deviceId": "550a1c72-65a0-4d55-b97b-75168e055398",
"name": "SYLVANIA SMART+ Smart Plug",
"label": "Arlo Beta Basestation",
"manufacturerName": "SmartThingsCommunity",
"presentationId": "28127039-043b-3df0-adf2-7541403dc4c1",
"deviceManufacturerCode": "LEDVANCE",
"locationId": "c4d3b2a1-09f8-765e-4d3c-2b1a09f8e7d6 ",
"ownerId": "d47f2b19-3a6e-4c8d-bf21-9e8a7c5d134e",
"roomId": "94be4a1e-382a-4b7f-a5ef-fdb1a7d9f9e6",
"components": [
{
"id": "main",
"label": "Pi Hole",
"capabilities": [
{
"id": "switch",
"version": 1
},
{
"id": "firmwareUpdate",
"version": 1
},
{
"id": "refresh",
"version": 1
}
],
"categories": [
{
"name": "Switch",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2018-10-05T12:23:14Z",
"parentDeviceId": "074fa784-8be8-4c70-8e22-6f5ed6f81b7e",
"profile": {
"id": "daeff874-075a-32e3-8b11-bdb99d8e67c7"
},
"zigbee": {
"eui": "F0D1B80000051E05",
"networkId": "801E",
"driverId": "f2e891c6-00cc-446c-9192-8ebda63d9898",
"executingLocally": true,
"hubId": "074fa784-8be8-4c70-8e22-6f5ed6f81b7e",
"provisioningState": "PROVISIONED"
},
"type": "ZIGBEE",
"restrictionTier": 0,
"allowed": [],
"executionContext": "LOCAL"
}
],
"_links": {}
}

View File

@ -0,0 +1,82 @@
{
"items": [
{
"deviceId": "c85fced9-c474-4a47-93c2-037cc7829536",
"name": "sonos-player",
"label": "Elliots Rum",
"manufacturerName": "SmartThingsCommunity",
"presentationId": "ef0a871d-9ed1-377d-8746-0da1dfd50598",
"deviceManufacturerCode": "Sonos",
"locationId": "eed0e167-e793-459b-80cb-a0b02e2b86c2",
"ownerId": "2c69cc36-85ae-c41a-9981-a4ee96cd9137",
"roomId": "105e6d1a-52a4-4797-a235-5a48d7d433c8",
"components": [
{
"id": "main",
"label": "main",
"capabilities": [
{
"id": "mediaPlayback",
"version": 1
},
{
"id": "mediaGroup",
"version": 1
},
{
"id": "mediaPresets",
"version": 1
},
{
"id": "mediaTrackControl",
"version": 1
},
{
"id": "audioMute",
"version": 1
},
{
"id": "audioNotification",
"version": 1
},
{
"id": "audioTrackData",
"version": 1
},
{
"id": "audioVolume",
"version": 1
},
{
"id": "refresh",
"version": 1
}
],
"categories": [
{
"name": "Speaker",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2025-02-02T13:18:28.570Z",
"parentDeviceId": "2f7f7d2b-e683-48ae-86f7-e57df6a0bce2",
"profile": {
"id": "0443d359-3f76-383f-82a4-6fc4a879ef1d"
},
"lan": {
"networkId": "38420B9108F6",
"driverId": "c21a6c77-872c-474e-be5b-5f6f11a240ef",
"executingLocally": true,
"hubId": "2f7f7d2b-e683-48ae-86f7-e57df6a0bce2",
"provisioningState": "TYPED"
},
"type": "LAN",
"restrictionTier": 0,
"allowed": [],
"executionContext": "LOCAL"
}
],
"_links": {}
}

View File

@ -0,0 +1,109 @@
{
"items": [
{
"deviceId": "0d94e5db-8501-2355-eb4f-214163702cac",
"name": "Soundbar",
"label": "Soundbar Living",
"manufacturerName": "Samsung Electronics",
"presentationId": "VD-NetworkAudio-002S",
"deviceManufacturerCode": "Samsung Electronics",
"locationId": "c4189ac1-208f-461a-8ab6-ea67937b3743",
"ownerId": "85ea07e1-7063-f673-3ba5-125293f297c8",
"roomId": "db506ec3-83b1-4125-9c4c-eb597da5db6a",
"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": "audioTrackData",
"version": 1
},
{
"id": "samsungvd.audioInputSource",
"version": 1
},
{
"id": "mediaPlayback",
"version": 1
},
{
"id": "audioNotification",
"version": 1
},
{
"id": "samsungvd.soundFrom",
"version": 1
},
{
"id": "samsungvd.thingStatus",
"version": 1
},
{
"id": "samsungvd.audioGroupInfo",
"version": 1,
"ephemeral": true
}
],
"categories": [
{
"name": "NetworkAudio",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2024-10-26T02:58:40.549Z",
"profile": {
"id": "3a714028-20ea-3feb-9891-46092132c737"
},
"ocf": {
"ocfDeviceType": "oic.d.networkaudio",
"name": "Soundbar Living",
"specVersion": "core.1.1.0",
"verticalDomainSpecVersion": "res.1.1.0,sh.1.1.0",
"manufacturerName": "Samsung Electronics",
"modelNumber": "HW-Q990C",
"platformVersion": "7.0",
"platformOS": "Tizen",
"hwVersion": "",
"firmwareVersion": "SAT-iMX8M23WWC-1010.5",
"vendorId": "VD-NetworkAudio-002S",
"vendorResourceClientServerVersion": "3.2.41",
"lastSignupTime": "2024-10-26T02:58:36.491256384Z",
"transferCandidate": false,
"additionalAuthCodeRequired": false
},
"type": "OCF",
"restrictionTier": 0,
"allowed": [],
"executionContext": "CLOUD"
}
],
"_links": {}
}

View File

@ -0,0 +1,148 @@
{
"items": [
{
"deviceId": "4588d2d9-a8cf-40f4-9a0b-ed5dfbaccda1",
"name": "[TV] Samsung 8 Series (49)",
"label": "[TV] Samsung 8 Series (49)",
"manufacturerName": "Samsung Electronics",
"presentationId": "VD-STV_2017_K",
"deviceManufacturerCode": "Samsung Electronics",
"locationId": "c4d3b2a1-09f8-765e-4d3c-2b1a09f8e7d6 ",
"ownerId": "d47f2b19-3a6e-4c8d-bf21-9e8a7c5d134e",
"roomId": "94be4a1e-382a-4b7f-a5ef-fdb1a7d9f9e6",
"deviceTypeName": "Samsung OCF TV",
"components": [
{
"id": "main",
"label": "main",
"capabilities": [
{
"id": "ocf",
"version": 1
},
{
"id": "switch",
"version": 1
},
{
"id": "audioVolume",
"version": 1
},
{
"id": "audioMute",
"version": 1
},
{
"id": "tvChannel",
"version": 1
},
{
"id": "mediaInputSource",
"version": 1
},
{
"id": "mediaPlayback",
"version": 1
},
{
"id": "mediaTrackControl",
"version": 1
},
{
"id": "custom.error",
"version": 1
},
{
"id": "custom.picturemode",
"version": 1
},
{
"id": "custom.soundmode",
"version": 1
},
{
"id": "custom.accessibility",
"version": 1
},
{
"id": "custom.launchapp",
"version": 1
},
{
"id": "custom.recording",
"version": 1
},
{
"id": "custom.tvsearch",
"version": 1
},
{
"id": "custom.disabledCapabilities",
"version": 1
},
{
"id": "samsungvd.ambient",
"version": 1
},
{
"id": "samsungvd.ambientContent",
"version": 1
},
{
"id": "samsungvd.mediaInputSource",
"version": 1
},
{
"id": "refresh",
"version": 1
},
{
"id": "execute",
"version": 1
},
{
"id": "samsungvd.firmwareVersion",
"version": 1
},
{
"id": "samsungvd.supportsPowerOnByOcf",
"version": 1
}
],
"categories": [
{
"name": "Television",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2020-05-07T02:58:10Z",
"profile": {
"id": "bac5c673-8eea-3d00-b1d2-283b46539017"
},
"ocf": {
"ocfDeviceType": "oic.d.tv",
"name": "[TV] Samsung 8 Series (49)",
"specVersion": "core.1.1.0",
"verticalDomainSpecVersion": "res.1.1.0,sh.1.1.0",
"manufacturerName": "Samsung Electronics",
"modelNumber": "UN49MU8000",
"platformVersion": "Tizen 3.0",
"platformOS": "4.1.10",
"hwVersion": "0-0",
"firmwareVersion": "T-KTMAKUC-1290.3",
"vendorId": "VD-STV_2017_K",
"locale": "en_US",
"lastSignupTime": "2021-08-21T18:52:56.748359Z",
"transferCandidate": false,
"additionalAuthCodeRequired": false
},
"type": "OCF",
"restrictionTier": 0,
"allowed": [],
"executionContext": "CLOUD"
}
],
"_links": {}
}

View File

@ -0,0 +1,69 @@
{
"items": [
{
"deviceId": "2894dc93-0f11-49cc-8a81-3a684cebebf6",
"name": "asd",
"label": "asd",
"manufacturerName": "SmartThingsCommunity",
"presentationId": "78906115-bf23-3c43-9cd6-f42ca3d5517a",
"locationId": "88a3a314-f0c8-40b4-bb44-44ba06c9c42f",
"ownerId": "12d4af93-cb68-b108-87f5-625437d7371f",
"roomId": "58826afc-9f38-426a-b868-dc94776286e3",
"components": [
{
"id": "main",
"label": "main",
"capabilities": [
{
"id": "thermostatHeatingSetpoint",
"version": 1
},
{
"id": "thermostatCoolingSetpoint",
"version": 1
},
{
"id": "thermostatOperatingState",
"version": 1
},
{
"id": "temperatureMeasurement",
"version": 1
},
{
"id": "thermostatMode",
"version": 1
},
{
"id": "thermostatFanMode",
"version": 1
},
{
"id": "battery",
"version": 1
}
],
"categories": [
{
"name": "Thermostat",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2025-02-10T22:04:56.174Z",
"profile": {
"id": "e921d7f2-5851-363d-89d5-5e83f5ab44c6"
},
"virtual": {
"name": "asd",
"executingLocally": false
},
"type": "VIRTUAL",
"restrictionTier": 0,
"allowed": [],
"executionContext": "CLOUD"
}
],
"_links": {}
}

View File

@ -0,0 +1,49 @@
{
"items": [
{
"deviceId": "612ab3c2-3bb0-48f7-b2c0-15b169cb2fc3",
"name": "volvo",
"label": "volvo",
"manufacturerName": "SmartThingsCommunity",
"presentationId": "916408b6-c94e-38b8-9fbf-03c8a48af5c3",
"locationId": "88a3a314-f0c8-40b4-bb44-44ba06c9c42f",
"ownerId": "12d4af93-cb68-b108-87f5-625437d7371f",
"roomId": "58826afc-9f38-426a-b868-dc94776286e3",
"components": [
{
"id": "main",
"label": "main",
"capabilities": [
{
"id": "valve",
"version": 1
},
{
"id": "refresh",
"version": 1
}
],
"categories": [
{
"name": "WaterValve",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2025-02-11T11:27:02.052Z",
"profile": {
"id": "f8e25992-7f5d-31da-b04d-497012590113"
},
"virtual": {
"name": "volvo",
"executingLocally": false
},
"type": "VIRTUAL",
"restrictionTier": 0,
"allowed": [],
"executionContext": "CLOUD"
}
],
"_links": {}
}

View File

@ -0,0 +1,53 @@
{
"items": [
{
"deviceId": "a2a6018b-2663-4727-9d1d-8f56953b5116",
"name": "asd",
"label": "asd",
"manufacturerName": "SmartThingsCommunity",
"presentationId": "838ae989-b832-3610-968c-2940491600f6",
"locationId": "88a3a314-f0c8-40b4-bb44-44ba06c9c42f",
"ownerId": "12d4af93-cb68-b108-87f5-625437d7371f",
"roomId": "58826afc-9f38-426a-b868-dc94776286e3",
"components": [
{
"id": "main",
"label": "main",
"capabilities": [
{
"id": "waterSensor",
"version": 1
},
{
"id": "battery",
"version": 1
},
{
"id": "refresh",
"version": 1
}
],
"categories": [
{
"name": "LeakSensor",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2025-02-10T21:58:18.688Z",
"profile": {
"id": "39230a95-d42d-34d4-a33c-f79573495a30"
},
"virtual": {
"name": "asd",
"executingLocally": false
},
"type": "VIRTUAL",
"restrictionTier": 0,
"allowed": [],
"executionContext": "CLOUD"
}
],
"_links": {}
}

View File

@ -0,0 +1,67 @@
{
"items": [
{
"deviceId": "a9f587c5-5d8b-4273-8907-e7f609af5158",
"name": "Yale Push Button Deadbolt Lock",
"label": "Basement Door Lock",
"manufacturerName": "SmartThingsCommunity",
"presentationId": "45f9424f-4e20-34b0-abb6-5f26b189acb0",
"deviceManufacturerCode": "Yale",
"locationId": "c4d3b2a1-09f8-765e-4d3c-2b1a09f8e7d6 ",
"ownerId": "d47f2b19-3a6e-4c8d-bf21-9e8a7c5d134e",
"roomId": "94be4a1e-382a-4b7f-a5ef-fdb1a7d9f9e6",
"components": [
{
"id": "main",
"label": "Basement Door Lock",
"capabilities": [
{
"id": "lock",
"version": 1
},
{
"id": "lockCodes",
"version": 1
},
{
"id": "battery",
"version": 1
},
{
"id": "firmwareUpdate",
"version": 1
},
{
"id": "refresh",
"version": 1
}
],
"categories": [
{
"name": "SmartLock",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2016-11-18T23:01:19Z",
"parentDeviceId": "074fa784-8be8-4c70-8e22-6f5ed6f81b7e",
"profile": {
"id": "51b76691-3c3a-3fce-8c7c-4f9d50e5885a"
},
"zigbee": {
"eui": "000D6F0002FB6E24",
"networkId": "C771",
"driverId": "ce930ffd-8155-4dca-aaa9-6c4158fc4278",
"executingLocally": true,
"hubId": "074fa784-8be8-4c70-8e22-6f5ed6f81b7e",
"provisioningState": "PROVISIONED"
},
"type": "ZIGBEE",
"restrictionTier": 0,
"allowed": [],
"executionContext": "LOCAL"
}
],
"_links": {}
}

View File

@ -0,0 +1,9 @@
{
"items": [
{
"locationId": "397678e5-9995-4a39-9d9f-ae6ba310236c",
"name": "Home"
}
],
"_links": null
}

View File

@ -0,0 +1,34 @@
{
"items": [
{
"sceneId": "743b0f37-89b8-476c-aedf-eea8ad8cd29d",
"sceneName": "Away",
"sceneIcon": "203",
"sceneColor": null,
"locationId": "88a3a314-f0c8-40b4-bb44-44ba06c9c42f",
"createdBy": "12d4af93-cb68-b108-87f5-625437d7371f",
"createdDate": 1738964737000,
"lastUpdatedDate": 1738964737000,
"lastExecutedDate": null,
"editable": false,
"apiVersion": "20200501"
},
{
"sceneId": "f3341e8b-9b32-4509-af2e-4f7c952e98ba",
"sceneName": "Home",
"sceneIcon": "204",
"sceneColor": null,
"locationId": "88a3a314-f0c8-40b4-bb44-44ba06c9c42f",
"createdBy": "12d4af93-cb68-b108-87f5-625437d7371f",
"createdDate": 1738964731000,
"lastUpdatedDate": 1738964731000,
"lastExecutedDate": null,
"editable": false,
"apiVersion": "20200501"
}
],
"_links": {
"next": null,
"previous": null
}
}

View File

@ -0,0 +1,529 @@
# serializer version: 1
# name: test_all_entities[c2c_arlo_pro_3_switch][binary_sensor.2nd_floor_hallway_motion-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.2nd_floor_hallway_motion',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.MOTION: 'motion'>,
'original_icon': None,
'original_name': '2nd Floor Hallway motion',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': '10e06a70-ee7d-4832-85e9-a0a06a7a05bd.motion',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[c2c_arlo_pro_3_switch][binary_sensor.2nd_floor_hallway_motion-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'motion',
'friendly_name': '2nd Floor Hallway motion',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.2nd_floor_hallway_motion',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[c2c_arlo_pro_3_switch][binary_sensor.2nd_floor_hallway_sound-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.2nd_floor_hallway_sound',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.SOUND: 'sound'>,
'original_icon': None,
'original_name': '2nd Floor Hallway sound',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': '10e06a70-ee7d-4832-85e9-a0a06a7a05bd.sound',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[c2c_arlo_pro_3_switch][binary_sensor.2nd_floor_hallway_sound-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'sound',
'friendly_name': '2nd Floor Hallway sound',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.2nd_floor_hallway_sound',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[contact_sensor][binary_sensor.front_door_open_closed_sensor_contact-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.front_door_open_closed_sensor_contact',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.DOOR: 'door'>,
'original_icon': None,
'original_name': '.Front Door Open/Closed Sensor contact',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': '2d9a892b-1c93-45a5-84cb-0e81889498c6.contact',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[contact_sensor][binary_sensor.front_door_open_closed_sensor_contact-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'door',
'friendly_name': '.Front Door Open/Closed Sensor contact',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.front_door_open_closed_sensor_contact',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[da_ref_normal_000001][binary_sensor.refrigerator_contact-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_contact',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.DOOR: 'door'>,
'original_icon': None,
'original_name': 'Refrigerator contact',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': '7db87911-7dce-1cf2-7119-b953432a2f09.contact',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[da_ref_normal_000001][binary_sensor.refrigerator_contact-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'door',
'friendly_name': 'Refrigerator contact',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.refrigerator_contact',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[ecobee_sensor][binary_sensor.child_bedroom_motion-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.child_bedroom_motion',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.MOTION: 'motion'>,
'original_icon': None,
'original_name': 'Child Bedroom motion',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': 'd5dc3299-c266-41c7-bd08-f540aea54b89.motion',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[ecobee_sensor][binary_sensor.child_bedroom_motion-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'motion',
'friendly_name': 'Child Bedroom motion',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.child_bedroom_motion',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[ecobee_sensor][binary_sensor.child_bedroom_presence-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.child_bedroom_presence',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.PRESENCE: 'presence'>,
'original_icon': None,
'original_name': 'Child Bedroom presence',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': 'd5dc3299-c266-41c7-bd08-f540aea54b89.presence',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[ecobee_sensor][binary_sensor.child_bedroom_presence-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'presence',
'friendly_name': 'Child Bedroom presence',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.child_bedroom_presence',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[iphone][binary_sensor.iphone_presence-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.iphone_presence',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.PRESENCE: 'presence'>,
'original_icon': None,
'original_name': 'iPhone presence',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': '184c67cc-69e2-44b6-8f73-55c963068ad9.presence',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[iphone][binary_sensor.iphone_presence-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'presence',
'friendly_name': 'iPhone presence',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.iphone_presence',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_all_entities[multipurpose_sensor][binary_sensor.deck_door_acceleration-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.deck_door_acceleration',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.MOVING: 'moving'>,
'original_icon': None,
'original_name': 'Deck Door acceleration',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': '7d246592-93db-4d72-a10d-5a51793ece8c.acceleration',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[multipurpose_sensor][binary_sensor.deck_door_acceleration-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'moving',
'friendly_name': 'Deck Door acceleration',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.deck_door_acceleration',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[multipurpose_sensor][binary_sensor.deck_door_contact-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.deck_door_contact',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.DOOR: 'door'>,
'original_icon': None,
'original_name': 'Deck Door contact',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': '7d246592-93db-4d72-a10d-5a51793ece8c.contact',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[multipurpose_sensor][binary_sensor.deck_door_contact-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'door',
'friendly_name': 'Deck Door contact',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.deck_door_contact',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[virtual_valve][binary_sensor.volvo_valve-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.volvo_valve',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.OPENING: 'opening'>,
'original_icon': None,
'original_name': 'volvo valve',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': '612ab3c2-3bb0-48f7-b2c0-15b169cb2fc3.valve',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[virtual_valve][binary_sensor.volvo_valve-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'opening',
'friendly_name': 'volvo valve',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.volvo_valve',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[virtual_water_sensor][binary_sensor.asd_water-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.asd_water',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.MOISTURE: 'moisture'>,
'original_icon': None,
'original_name': 'asd water',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': 'a2a6018b-2663-4727-9d1d-8f56953b5116.water',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[virtual_water_sensor][binary_sensor.asd_water-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'moisture',
'friendly_name': 'asd water',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.asd_water',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---

View File

@ -0,0 +1,356 @@
# serializer version: 1
# name: test_all_entities[da_ac_rac_000001][climate.ac_office_granit-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'fan_modes': list([
'auto',
'low',
'medium',
'high',
'turbo',
]),
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.COOL: 'cool'>,
<HVACMode.DRY: 'dry'>,
<HVACMode.FAN_ONLY: 'fan_only'>,
<HVACMode.HEAT_COOL: 'heat_cool'>,
<HVACMode.HEAT: 'heat'>,
]),
'max_temp': 35,
'min_temp': 7,
'preset_modes': list([
'windFree',
]),
'swing_modes': None,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'climate',
'entity_category': None,
'entity_id': 'climate.ac_office_granit',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'AC Office Granit',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': <ClimateEntityFeature: 441>,
'translation_key': None,
'unique_id': '96a5ef74-5832-a84b-f1f7-ca799957065d',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[da_ac_rac_000001][climate.ac_office_granit-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 25,
'drlc_status_duration': 0,
'drlc_status_level': -1,
'drlc_status_override': False,
'drlc_status_start': '1970-01-01T00:00:00Z',
'fan_mode': 'low',
'fan_modes': list([
'auto',
'low',
'medium',
'high',
'turbo',
]),
'friendly_name': 'AC Office Granit',
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.COOL: 'cool'>,
<HVACMode.DRY: 'dry'>,
<HVACMode.FAN_ONLY: 'fan_only'>,
<HVACMode.HEAT_COOL: 'heat_cool'>,
<HVACMode.HEAT: 'heat'>,
]),
'max_temp': 35,
'min_temp': 7,
'preset_mode': None,
'preset_modes': list([
'windFree',
]),
'supported_features': <ClimateEntityFeature: 441>,
'swing_mode': 'off',
'swing_modes': None,
'temperature': 25,
}),
'context': <ANY>,
'entity_id': 'climate.ac_office_granit',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[da_ac_rac_01001][climate.aire_dormitorio_principal-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'fan_modes': list([
'auto',
'low',
'medium',
'high',
'turbo',
]),
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT_COOL: 'heat_cool'>,
<HVACMode.COOL: 'cool'>,
<HVACMode.DRY: 'dry'>,
<HVACMode.FAN_ONLY: 'fan_only'>,
<HVACMode.HEAT: 'heat'>,
]),
'max_temp': 35,
'min_temp': 7,
'preset_modes': list([
'windFree',
]),
'swing_modes': list([
'off',
'vertical',
'horizontal',
'both',
]),
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'climate',
'entity_category': None,
'entity_id': 'climate.aire_dormitorio_principal',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Aire Dormitorio Principal',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': <ClimateEntityFeature: 441>,
'translation_key': None,
'unique_id': '4ece486b-89db-f06a-d54d-748b676b4d8e',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[da_ac_rac_01001][climate.aire_dormitorio_principal-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 27,
'drlc_status_duration': 0,
'drlc_status_level': 0,
'drlc_status_override': False,
'drlc_status_start': '1970-01-01T00:00:00Z',
'fan_mode': 'high',
'fan_modes': list([
'auto',
'low',
'medium',
'high',
'turbo',
]),
'friendly_name': 'Aire Dormitorio Principal',
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT_COOL: 'heat_cool'>,
<HVACMode.COOL: 'cool'>,
<HVACMode.DRY: 'dry'>,
<HVACMode.FAN_ONLY: 'fan_only'>,
<HVACMode.HEAT: 'heat'>,
]),
'max_temp': 35,
'min_temp': 7,
'preset_mode': None,
'preset_modes': list([
'windFree',
]),
'supported_features': <ClimateEntityFeature: 441>,
'swing_mode': 'off',
'swing_modes': list([
'off',
'vertical',
'horizontal',
'both',
]),
'temperature': 23,
}),
'context': <ANY>,
'entity_id': 'climate.aire_dormitorio_principal',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[ecobee_thermostat][climate.main_floor-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'fan_modes': list([
'on',
'auto',
]),
'hvac_modes': list([
<HVACMode.COOL: 'cool'>,
<HVACMode.HEAT_COOL: 'heat_cool'>,
]),
'max_temp': 35.0,
'min_temp': 7.0,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'climate',
'entity_category': None,
'entity_id': 'climate.main_floor',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Main Floor',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': <ClimateEntityFeature: 395>,
'translation_key': None,
'unique_id': '028469cb-6e89-4f14-8d9a-bfbca5e0fbfc',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[ecobee_thermostat][climate.main_floor-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'current_humidity': 32,
'current_temperature': 21.7,
'fan_mode': 'auto',
'fan_modes': list([
'on',
'auto',
]),
'friendly_name': 'Main Floor',
'hvac_action': <HVACAction.HEATING: 'heating'>,
'hvac_modes': list([
<HVACMode.COOL: 'cool'>,
<HVACMode.HEAT_COOL: 'heat_cool'>,
]),
'max_temp': 35.0,
'min_temp': 7.0,
'supported_features': <ClimateEntityFeature: 395>,
'target_temp_high': None,
'target_temp_low': None,
'temperature': 21.7,
}),
'context': <ANY>,
'entity_id': 'climate.main_floor',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'heat',
})
# ---
# name: test_all_entities[virtual_thermostat][climate.asd-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'fan_modes': list([
'on',
]),
'hvac_modes': list([
]),
'max_temp': 35.0,
'min_temp': 7.0,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'climate',
'entity_category': None,
'entity_id': 'climate.asd',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'asd',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': <ClimateEntityFeature: 395>,
'translation_key': None,
'unique_id': '2894dc93-0f11-49cc-8a81-3a684cebebf6',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[virtual_thermostat][climate.asd-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 4734.6,
'fan_mode': 'followschedule',
'fan_modes': list([
'on',
]),
'friendly_name': 'asd',
'hvac_action': <HVACAction.COOLING: 'cooling'>,
'hvac_modes': list([
]),
'max_temp': 35.0,
'min_temp': 7.0,
'supported_features': <ClimateEntityFeature: 395>,
'target_temp_high': None,
'target_temp_low': None,
'temperature': None,
}),
'context': <ANY>,
'entity_id': 'climate.asd',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unknown',
})
# ---

View File

@ -0,0 +1,100 @@
# serializer version: 1
# name: test_all_entities[c2c_shade][cover.curtain_1a-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': 'cover',
'entity_category': None,
'entity_id': 'cover.curtain_1a',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <CoverDeviceClass.SHADE: 'shade'>,
'original_icon': None,
'original_name': 'Curtain 1A',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': <CoverEntityFeature: 7>,
'translation_key': None,
'unique_id': '571af102-15db-4030-b76b-245a691f74a5',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[c2c_shade][cover.curtain_1a-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'current_position': 100,
'device_class': 'shade',
'friendly_name': 'Curtain 1A',
'supported_features': <CoverEntityFeature: 7>,
}),
'context': <ANY>,
'entity_id': 'cover.curtain_1a',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'open',
})
# ---
# name: test_all_entities[da_ks_microwave_0101x][cover.microwave-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': 'cover',
'entity_category': None,
'entity_id': 'cover.microwave',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <CoverDeviceClass.DOOR: 'door'>,
'original_icon': None,
'original_name': 'Microwave',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': <CoverEntityFeature: 3>,
'translation_key': None,
'unique_id': '2bad3237-4886-e699-1b90-4a51a3d55c8a',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[da_ks_microwave_0101x][cover.microwave-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'door',
'friendly_name': 'Microwave',
'supported_features': <CoverEntityFeature: 3>,
}),
'context': <ANY>,
'entity_id': 'cover.microwave',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unknown',
})
# ---

View File

@ -0,0 +1,67 @@
# serializer version: 1
# name: test_all_entities[fake_fan][fan.fake_fan-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'preset_modes': list([
'auto',
'low',
'medium',
'high',
'turbo',
]),
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'fan',
'entity_category': None,
'entity_id': 'fan.fake_fan',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Fake fan',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': <FanEntityFeature: 57>,
'translation_key': None,
'unique_id': 'f1af21a2-d5a1-437c-b10a-b34a87394b71',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[fake_fan][fan.fake_fan-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Fake fan',
'percentage': 2000,
'percentage_step': 33.333333333333336,
'preset_mode': None,
'preset_modes': list([
'auto',
'low',
'medium',
'high',
'turbo',
]),
'supported_features': <FanEntityFeature: 57>,
}),
'context': <ANY>,
'entity_id': 'fan.fake_fan',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,267 @@
# serializer version: 1
# name: test_all_entities[centralite][light.dimmer_debian-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'supported_color_modes': list([
<ColorMode.BRIGHTNESS: 'brightness'>,
]),
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'light',
'entity_category': None,
'entity_id': 'light.dimmer_debian',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Dimmer Debian',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': <LightEntityFeature: 32>,
'translation_key': None,
'unique_id': 'd0268a69-abfb-4c92-a646-61cec2e510ad',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[centralite][light.dimmer_debian-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'brightness': None,
'color_mode': None,
'friendly_name': 'Dimmer Debian',
'supported_color_modes': list([
<ColorMode.BRIGHTNESS: 'brightness'>,
]),
'supported_features': <LightEntityFeature: 32>,
}),
'context': <ANY>,
'entity_id': 'light.dimmer_debian',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[ge_in_wall_smart_dimmer][light.basement_exit_light-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'supported_color_modes': list([
<ColorMode.BRIGHTNESS: 'brightness'>,
]),
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'light',
'entity_category': None,
'entity_id': 'light.basement_exit_light',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Basement Exit Light',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': <LightEntityFeature: 32>,
'translation_key': None,
'unique_id': 'aaedaf28-2ae0-4c1d-b57e-87f6a420c298',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[ge_in_wall_smart_dimmer][light.basement_exit_light-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'brightness': None,
'color_mode': None,
'friendly_name': 'Basement Exit Light',
'supported_color_modes': list([
<ColorMode.BRIGHTNESS: 'brightness'>,
]),
'supported_features': <LightEntityFeature: 32>,
}),
'context': <ANY>,
'entity_id': 'light.basement_exit_light',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[hue_color_temperature_bulb][light.bathroom_spot-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'max_color_temp_kelvin': 9000,
'max_mireds': 500,
'min_color_temp_kelvin': 2000,
'min_mireds': 111,
'supported_color_modes': list([
<ColorMode.COLOR_TEMP: 'color_temp'>,
]),
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'light',
'entity_category': None,
'entity_id': 'light.bathroom_spot',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Bathroom spot',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': <LightEntityFeature: 32>,
'translation_key': None,
'unique_id': '440063de-a200-40b5-8a6b-f3399eaa0370',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[hue_color_temperature_bulb][light.bathroom_spot-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'brightness': 178,
'color_mode': <ColorMode.COLOR_TEMP: 'color_temp'>,
'color_temp': 333,
'color_temp_kelvin': 3000,
'friendly_name': 'Bathroom spot',
'hs_color': tuple(
27.825,
56.895,
),
'max_color_temp_kelvin': 9000,
'max_mireds': 500,
'min_color_temp_kelvin': 2000,
'min_mireds': 111,
'rgb_color': tuple(
255,
177,
110,
),
'supported_color_modes': list([
<ColorMode.COLOR_TEMP: 'color_temp'>,
]),
'supported_features': <LightEntityFeature: 32>,
'xy_color': tuple(
0.496,
0.383,
),
}),
'context': <ANY>,
'entity_id': 'light.bathroom_spot',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_all_entities[hue_rgbw_color_bulb][light.standing_light-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'max_color_temp_kelvin': 9000,
'max_mireds': 500,
'min_color_temp_kelvin': 2000,
'min_mireds': 111,
'supported_color_modes': list([
<ColorMode.COLOR_TEMP: 'color_temp'>,
<ColorMode.HS: 'hs'>,
]),
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'light',
'entity_category': None,
'entity_id': 'light.standing_light',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Standing light',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': <LightEntityFeature: 32>,
'translation_key': None,
'unique_id': 'cb958955-b015-498c-9e62-fc0c51abd054',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[hue_rgbw_color_bulb][light.standing_light-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'brightness': None,
'color_mode': None,
'color_temp': None,
'color_temp_kelvin': None,
'friendly_name': 'Standing light',
'hs_color': None,
'max_color_temp_kelvin': 9000,
'max_mireds': 500,
'min_color_temp_kelvin': 2000,
'min_mireds': 111,
'rgb_color': None,
'supported_color_modes': list([
<ColorMode.COLOR_TEMP: 'color_temp'>,
<ColorMode.HS: 'hs'>,
]),
'supported_features': <LightEntityFeature: 32>,
'xy_color': None,
}),
'context': <ANY>,
'entity_id': 'light.standing_light',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---

View File

@ -0,0 +1,50 @@
# serializer version: 1
# name: test_all_entities[yale_push_button_deadbolt_lock][lock.basement_door_lock-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': 'lock',
'entity_category': None,
'entity_id': 'lock.basement_door_lock',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Basement Door Lock',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': 'a9f587c5-5d8b-4273-8907-e7f609af5158',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[yale_push_button_deadbolt_lock][lock.basement_door_lock-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Basement Door Lock',
'lock_state': 'locked',
'supported_features': <LockEntityFeature: 0>,
}),
'context': <ANY>,
'entity_id': 'lock.basement_door_lock',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'locked',
})
# ---

View File

@ -0,0 +1,101 @@
# serializer version: 1
# name: test_all_entities[scene.away-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': 'scene',
'entity_category': None,
'entity_id': 'scene.away',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Away',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': '743b0f37-89b8-476c-aedf-eea8ad8cd29d',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[scene.away-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'color': None,
'friendly_name': 'Away',
'icon': '203',
'location_id': '88a3a314-f0c8-40b4-bb44-44ba06c9c42f',
}),
'context': <ANY>,
'entity_id': 'scene.away',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unknown',
})
# ---
# name: test_all_entities[scene.home-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': 'scene',
'entity_category': None,
'entity_id': 'scene.home',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Home',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': 'f3341e8b-9b32-4509-af2e-4f7c952e98ba',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[scene.home-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'color': None,
'friendly_name': 'Home',
'icon': '204',
'location_id': '88a3a314-f0c8-40b4-bb44-44ba06c9c42f',
}),
'context': <ANY>,
'entity_id': 'scene.home',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unknown',
})
# ---

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,471 @@
# serializer version: 1
# name: test_all_entities[c2c_arlo_pro_3_switch][switch.2nd_floor_hallway-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.2nd_floor_hallway',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': '2nd Floor Hallway',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': '10e06a70-ee7d-4832-85e9-a0a06a7a05bd',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[c2c_arlo_pro_3_switch][switch.2nd_floor_hallway-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': '2nd Floor Hallway',
}),
'context': <ANY>,
'entity_id': 'switch.2nd_floor_hallway',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_all_entities[da_ks_microwave_0101x][switch.microwave-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.microwave',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Microwave',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': '2bad3237-4886-e699-1b90-4a51a3d55c8a',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[da_ks_microwave_0101x][switch.microwave-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Microwave',
}),
'context': <ANY>,
'entity_id': 'switch.microwave',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[da_rvc_normal_000001][switch.robot_vacuum-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.robot_vacuum',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Robot vacuum',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': '3442dfc6-17c0-a65f-dae0-4c6e01786f44',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[da_rvc_normal_000001][switch.robot_vacuum-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Robot vacuum',
}),
'context': <ANY>,
'entity_id': 'switch.robot_vacuum',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[da_wm_dw_000001][switch.dishwasher-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.dishwasher',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Dishwasher',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': 'f36dc7ce-cac0-0667-dc14-a3704eb5e676',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[da_wm_dw_000001][switch.dishwasher-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Dishwasher',
}),
'context': <ANY>,
'entity_id': 'switch.dishwasher',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[da_wm_wd_000001][switch.dryer-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.dryer',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Dryer',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': '02f7256e-8353-5bdd-547f-bd5b1647e01b',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[da_wm_wd_000001][switch.dryer-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Dryer',
}),
'context': <ANY>,
'entity_id': 'switch.dryer',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[da_wm_wm_000001][switch.washer-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.washer',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Washer',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': 'f984b91d-f250-9d42-3436-33f09a422a47',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[da_wm_wm_000001][switch.washer-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Washer',
}),
'context': <ANY>,
'entity_id': 'switch.washer',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[sensibo_airconditioner_1][switch.office-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.office',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Office',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': 'bf4b1167-48a3-4af7-9186-0900a678ffa5',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[sensibo_airconditioner_1][switch.office-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Office',
}),
'context': <ANY>,
'entity_id': 'switch.office',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[smart_plug][switch.arlo_beta_basestation-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.arlo_beta_basestation',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Arlo Beta Basestation',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': '550a1c72-65a0-4d55-b97b-75168e055398',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[smart_plug][switch.arlo_beta_basestation-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Arlo Beta Basestation',
}),
'context': <ANY>,
'entity_id': 'switch.arlo_beta_basestation',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_all_entities[vd_network_audio_002s][switch.soundbar_living-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.soundbar_living',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Soundbar Living',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': '0d94e5db-8501-2355-eb4f-214163702cac',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[vd_network_audio_002s][switch.soundbar_living-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Soundbar Living',
}),
'context': <ANY>,
'entity_id': 'switch.soundbar_living',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_all_entities[vd_stv_2017_k][switch.tv_samsung_8_series_49-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.tv_samsung_8_series_49',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': '[TV] Samsung 8 Series (49)',
'platform': 'smartthings',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': '4588d2d9-a8cf-40f4-9a0b-ed5dfbaccda1',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[vd_stv_2017_k][switch.tv_samsung_8_series_49-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': '[TV] Samsung 8 Series (49)',
}),
'context': <ANY>,
'entity_id': 'switch.tv_samsung_8_series_49',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---

View File

@ -1,139 +1,53 @@
"""Test for the SmartThings binary_sensor platform.
"""Test for the SmartThings binary_sensor platform."""
The only mocking required is of the underlying SmartThings API object so
real HTTP calls are not initiated during testing.
"""
from unittest.mock import AsyncMock
from pysmartthings import ATTRIBUTES, CAPABILITIES, Attribute, Capability
from pysmartthings import Attribute, Capability
import pytest
from syrupy import SnapshotAssertion
from homeassistant.components.binary_sensor import (
DEVICE_CLASSES,
DOMAIN as BINARY_SENSOR_DOMAIN,
)
from homeassistant.components.smartthings import binary_sensor
from homeassistant.components.smartthings.const import DOMAIN, SIGNAL_SMARTTHINGS_UPDATE
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import ATTR_FRIENDLY_NAME, STATE_UNAVAILABLE, EntityCategory
from homeassistant.const import STATE_OFF, STATE_ON, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers import entity_registry as er
from .conftest import setup_platform
from . import setup_integration, snapshot_smartthings_entities, trigger_update
from tests.common import MockConfigEntry
async def test_mapping_integrity() -> None:
"""Test ensures the map dicts have proper integrity."""
# Ensure every CAPABILITY_TO_ATTRIB key is in CAPABILITIES
# Ensure every CAPABILITY_TO_ATTRIB value is in ATTRIB_TO_CLASS keys
for capability, attrib in binary_sensor.CAPABILITY_TO_ATTRIB.items():
assert capability in CAPABILITIES, capability
assert attrib in ATTRIBUTES, attrib
assert attrib in binary_sensor.ATTRIB_TO_CLASS, attrib
# Ensure every ATTRIB_TO_CLASS value is in DEVICE_CLASSES
for attrib, device_class in binary_sensor.ATTRIB_TO_CLASS.items():
assert attrib in ATTRIBUTES, attrib
assert device_class in DEVICE_CLASSES, device_class
async def test_entity_state(hass: HomeAssistant, device_factory) -> None:
"""Tests the state attributes properly match the light types."""
device = device_factory(
"Motion Sensor 1", [Capability.motion_sensor], {Attribute.motion: "inactive"}
)
await setup_platform(hass, BINARY_SENSOR_DOMAIN, devices=[device])
state = hass.states.get("binary_sensor.motion_sensor_1_motion")
assert state.state == "off"
assert state.attributes[ATTR_FRIENDLY_NAME] == f"{device.label} {Attribute.motion}"
async def test_entity_and_device_attributes(
async def test_all_entities(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
snapshot: SnapshotAssertion,
devices: AsyncMock,
mock_config_entry: MockConfigEntry,
entity_registry: er.EntityRegistry,
device_factory,
) -> None:
"""Test the attributes of the entity are correct."""
# Arrange
device = device_factory(
"Motion Sensor 1",
[Capability.motion_sensor],
{
Attribute.motion: "inactive",
Attribute.mnmo: "123",
Attribute.mnmn: "Generic manufacturer",
Attribute.mnhw: "v4.56",
Attribute.mnfv: "v7.89",
},
)
# Act
await setup_platform(hass, BINARY_SENSOR_DOMAIN, devices=[device])
# Assert
entry = entity_registry.async_get("binary_sensor.motion_sensor_1_motion")
assert entry
assert entry.unique_id == f"{device.device_id}.{Attribute.motion}"
entry = device_registry.async_get_device(identifiers={(DOMAIN, device.device_id)})
assert entry
assert entry.configuration_url == "https://account.smartthings.com"
assert entry.identifiers == {(DOMAIN, device.device_id)}
assert entry.name == device.label
assert entry.model == "123"
assert entry.manufacturer == "Generic manufacturer"
assert entry.hw_version == "v4.56"
assert entry.sw_version == "v7.89"
"""Test all entities."""
await setup_integration(hass, mock_config_entry)
async def test_update_from_signal(hass: HomeAssistant, device_factory) -> None:
"""Test the binary_sensor updates when receiving a signal."""
# Arrange
device = device_factory(
"Motion Sensor 1", [Capability.motion_sensor], {Attribute.motion: "inactive"}
)
await setup_platform(hass, BINARY_SENSOR_DOMAIN, devices=[device])
device.status.apply_attribute_update(
"main", Capability.motion_sensor, Attribute.motion, "active"
)
# Act
async_dispatcher_send(hass, SIGNAL_SMARTTHINGS_UPDATE, [device.device_id])
# Assert
await hass.async_block_till_done()
state = hass.states.get("binary_sensor.motion_sensor_1_motion")
assert state is not None
assert state.state == "on"
async def test_unload_config_entry(hass: HomeAssistant, device_factory) -> None:
"""Test the binary_sensor is removed when the config entry is unloaded."""
# Arrange
device = device_factory(
"Motion Sensor 1", [Capability.motion_sensor], {Attribute.motion: "inactive"}
)
config_entry = await setup_platform(hass, BINARY_SENSOR_DOMAIN, devices=[device])
config_entry.mock_state(hass, ConfigEntryState.LOADED)
# Act
await hass.config_entries.async_forward_entry_unload(config_entry, "binary_sensor")
# Assert
assert (
hass.states.get("binary_sensor.motion_sensor_1_motion").state
== STATE_UNAVAILABLE
snapshot_smartthings_entities(
hass, entity_registry, snapshot, Platform.BINARY_SENSOR
)
async def test_entity_category(
hass: HomeAssistant, entity_registry: er.EntityRegistry, device_factory
@pytest.mark.parametrize("device_fixture", ["da_ref_normal_000001"])
async def test_state_update(
hass: HomeAssistant,
devices: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Tests the state attributes properly match the light types."""
device1 = device_factory(
"Motion Sensor 1", [Capability.motion_sensor], {Attribute.motion: "inactive"}
)
device2 = device_factory(
"Tamper Sensor 2", [Capability.tamper_alert], {Attribute.tamper: "inactive"}
)
await setup_platform(hass, BINARY_SENSOR_DOMAIN, devices=[device1, device2])
"""Test state update."""
await setup_integration(hass, mock_config_entry)
entry = entity_registry.async_get("binary_sensor.motion_sensor_1_motion")
assert entry
assert entry.entity_category is None
assert hass.states.get("binary_sensor.refrigerator_contact").state == STATE_OFF
entry = entity_registry.async_get("binary_sensor.tamper_sensor_2_tamper")
assert entry
assert entry.entity_category is EntityCategory.DIAGNOSTIC
await trigger_update(
hass,
devices,
"7db87911-7dce-1cf2-7119-b953432a2f09",
Capability.CONTACT_SENSOR,
Attribute.CONTACT,
"open",
)
assert hass.states.get("binary_sensor.refrigerator_contact").state == STATE_ON

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More