Add support for Tuya bzyd category (white noise machine) (#152025)

This commit is contained in:
epenet
2025-09-12 19:00:54 +02:00
committed by GitHub
parent 0cebca498c
commit 9fae4e7e1f
11 changed files with 453 additions and 9 deletions

View File

@@ -331,6 +331,7 @@ class DPCode(StrEnum):
SMOKE_SENSOR_STATE = "smoke_sensor_state"
SMOKE_SENSOR_STATUS = "smoke_sensor_status"
SMOKE_SENSOR_VALUE = "smoke_sensor_value"
SNOOZE = "snooze"
SOS = "sos" # Emergency State
SOS_STATE = "sos_state" # Emergency mode
SPEED = "speed" # Speed level
@@ -371,6 +372,7 @@ class DPCode(StrEnum):
SWITCH_MODE7 = "switch_mode7"
SWITCH_MODE8 = "switch_mode8"
SWITCH_MODE9 = "switch_mode9"
SWITCH_MUSIC = "switch_music"
SWITCH_NIGHT_LIGHT = "switch_night_light"
SWITCH_SAVE_ENERGY = "switch_save_energy"
SWITCH_SOUND = "switch_sound" # Voice switch

View File

@@ -126,7 +126,7 @@ class TuyaEntity(Entity):
return None
def get_dptype(
self, dpcode: DPCode | None, prefer_function: bool = False
self, dpcode: DPCode | None, *, prefer_function: bool = False
) -> DPType | None:
"""Find a matching DPCode data type available on for this device."""
if dpcode is None:

View File

@@ -73,6 +73,15 @@ class TuyaLightEntityDescription(LightEntityDescription):
LIGHTS: dict[str, tuple[TuyaLightEntityDescription, ...]] = {
# White noise machine
"bzyd": (
TuyaLightEntityDescription(
key=DPCode.SWITCH_LED,
name=None,
color_mode=DPCode.WORK_MODE,
color_data=DPCode.COLOUR_DATA,
),
),
# Curtain Switch
# https://developer.tuya.com/en/docs/iot/category-clkg?id=Kaiuz0gitil39
"clkg": (
@@ -531,7 +540,7 @@ class TuyaLightEntity(TuyaEntity, LightEntity):
if (
dpcode := get_dpcode(self.device, description.color_data)
) and self.get_dptype(dpcode) == DPType.JSON:
) and self.get_dptype(dpcode, prefer_function=True) == DPType.JSON:
self._color_data_dpcode = dpcode
color_modes.add(ColorMode.HS)
if dpcode in self.device.function:

View File

@@ -65,6 +65,14 @@ NUMBERS: dict[str, tuple[NumberEntityDescription, ...]] = {
entity_category=EntityCategory.CONFIG,
),
),
# White noise machine
"bzyd": (
NumberEntityDescription(
key=DPCode.VOLUME_SET,
translation_key="volume",
entity_category=EntityCategory.CONFIG,
),
),
# CO2 Detector
# https://developer.tuya.com/en/docs/iot/categoryco2bj?id=Kaiuz3wes7yuy
"co2bj": (

View File

@@ -981,6 +981,12 @@
},
"output_power_limit": {
"name": "Output power limit"
},
"music": {
"name": "Music"
},
"snooze": {
"name": "Snooze"
}
},
"valve": {

View File

@@ -37,6 +37,31 @@ SWITCHES: dict[str, tuple[SwitchEntityDescription, ...]] = {
entity_category=EntityCategory.CONFIG,
),
),
# White noise machine
"bzyd": (
SwitchEntityDescription(
key=DPCode.SWITCH,
name=None,
),
SwitchEntityDescription(
key=DPCode.CHILD_LOCK,
translation_key="child_lock",
icon="mdi:account-lock",
entity_category=EntityCategory.CONFIG,
),
SwitchEntityDescription(
key=DPCode.SWITCH_MUSIC,
translation_key="music",
icon="mdi:music",
entity_category=EntityCategory.CONFIG,
),
SwitchEntityDescription(
key=DPCode.SNOOZE,
translation_key="snooze",
icon="mdi:alarm-snooze",
entity_category=EntityCategory.CONFIG,
),
),
# Curtain
# https://developer.tuya.com/en/docs/iot/f?id=K9gf46o5mtfyc
"cl": (

View File

@@ -208,11 +208,11 @@ async def _create_device(hass: HomeAssistant, mock_device_code: str) -> Customer
}
device.status = details["status"]
for key, value in device.status.items():
# Some devices to not provide a status_range for all status DPs
dp_type = device.status_range.get(key)
if dp_type is None:
dp_type = device.function[key]
if dp_type.type == "Json":
# Some devices do not provide a status_range for all status DPs
# Others set the type as String in status_range and as Json in function
if ((dp_type := device.status_range.get(key)) and dp_type.type == "Json") or (
(dp_type := device.function.get(key)) and dp_type.type == "Json"
):
device.status[key] = json_dumps(value)
return device

View File

@@ -2004,7 +2004,7 @@
'labels': set({
}),
'manufacturer': 'Tuya',
'model': 'BlissRadia (unsupported)',
'model': 'BlissRadia ',
'model_id': 'ssimhf6r8kgwepfb',
'name': 'BlissRadia ',
'name_by_user': None,
@@ -5755,7 +5755,7 @@
'labels': set({
}),
'manufacturer': 'Tuya',
'model': 'Smart White Noise Machine (unsupported)',
'model': 'Smart White Noise Machine',
'model_id': '45idzfufidgee7ir',
'name': 'Smart White Noise Machine',
'name_by_user': None,

View File

@@ -345,6 +345,67 @@
'state': 'off',
})
# ---
# name: test_platform_setup_and_discovery[light.blissradia-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'supported_color_modes': list([
<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.blissradia',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': None,
'platform': 'tuya',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': 'tuya.bfpewgk8r6fhmissdyzbswitch_led',
'unit_of_measurement': None,
})
# ---
# name: test_platform_setup_and_discovery[light.blissradia-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'brightness': None,
'color_mode': None,
'friendly_name': 'BlissRadia ',
'hs_color': None,
'rgb_color': None,
'supported_color_modes': list([
<ColorMode.HS: 'hs'>,
]),
'supported_features': <LightEntityFeature: 0>,
'xy_color': None,
}),
'context': <ANY>,
'entity_id': 'light.blissradia',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_platform_setup_and_discovery[light.cam_garage_indicator_light-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
@@ -2957,6 +3018,77 @@
'state': 'off',
})
# ---
# name: test_platform_setup_and_discovery[light.smart_white_noise_machine-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'supported_color_modes': list([
<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.smart_white_noise_machine',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': None,
'platform': 'tuya',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': 'tuya.ri7eegdifufzdi54dyzbswitch_led',
'unit_of_measurement': None,
})
# ---
# name: test_platform_setup_and_discovery[light.smart_white_noise_machine-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'brightness': 1003,
'color_mode': <ColorMode.HS: 'hs'>,
'friendly_name': 'Smart White Noise Machine',
'hs_color': tuple(
239.666,
393.307,
),
'rgb_color': tuple(
-748,
-742,
255,
),
'supported_color_modes': list([
<ColorMode.HS: 'hs'>,
]),
'supported_features': <LightEntityFeature: 0>,
'xy_color': tuple(
-0.03,
-0.215,
),
}),
'context': <ANY>,
'entity_id': 'light.smart_white_noise_machine',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_platform_setup_and_discovery[light.solar_zijpad-entry]
EntityRegistryEntrySnapshot({
'aliases': set({

View File

@@ -58,6 +58,64 @@
'state': '1.0',
})
# ---
# name: test_platform_setup_and_discovery[number.blissradia_volume-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'max': 100.0,
'min': 5.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'number',
'entity_category': <EntityCategory.CONFIG: 'config'>,
'entity_id': 'number.blissradia_volume',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Volume',
'platform': 'tuya',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'volume',
'unique_id': 'tuya.bfpewgk8r6fhmissdyzbvolume_set',
'unit_of_measurement': '',
})
# ---
# name: test_platform_setup_and_discovery[number.blissradia_volume-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'BlissRadia Volume',
'max': 100.0,
'min': 5.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
'unit_of_measurement': '',
}),
'context': <ANY>,
'entity_id': 'number.blissradia_volume',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '5.0',
})
# ---
# name: test_platform_setup_and_discovery[number.boiler_temperature_controller_temperature_correction-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
@@ -2223,6 +2281,64 @@
'state': '-2.0',
})
# ---
# name: test_platform_setup_and_discovery[number.smart_white_noise_machine_volume-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'max': 100.0,
'min': 0.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'number',
'entity_category': <EntityCategory.CONFIG: 'config'>,
'entity_id': 'number.smart_white_noise_machine_volume',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Volume',
'platform': 'tuya',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'volume',
'unique_id': 'tuya.ri7eegdifufzdi54dyzbvolume_set',
'unit_of_measurement': '',
})
# ---
# name: test_platform_setup_and_discovery[number.smart_white_noise_machine_volume-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Smart White Noise Machine Volume',
'max': 100.0,
'min': 0.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
'unit_of_measurement': '',
}),
'context': <ANY>,
'entity_id': 'number.smart_white_noise_machine_volume',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '17.0',
})
# ---
# name: test_platform_setup_and_discovery[number.sous_vide_cooking_temperature-entry]
EntityRegistryEntrySnapshot({
'aliases': set({

View File

@@ -1070,6 +1070,55 @@
'state': 'off',
})
# ---
# name: test_platform_setup_and_discovery[switch.blissradia_snooze-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': <EntityCategory.CONFIG: 'config'>,
'entity_id': 'switch.blissradia_snooze',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': 'mdi:alarm-snooze',
'original_name': 'Snooze',
'platform': 'tuya',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'snooze',
'unique_id': 'tuya.bfpewgk8r6fhmissdyzbsnooze',
'unit_of_measurement': None,
})
# ---
# name: test_platform_setup_and_discovery[switch.blissradia_snooze-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'BlissRadia Snooze',
'icon': 'mdi:alarm-snooze',
}),
'context': <ANY>,
'entity_id': 'switch.blissradia_snooze',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_platform_setup_and_discovery[switch.bree_power-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
@@ -7403,6 +7452,103 @@
'state': 'unavailable',
})
# ---
# name: test_platform_setup_and_discovery[switch.smart_white_noise_machine-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.smart_white_noise_machine',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': None,
'platform': 'tuya',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': 'tuya.ri7eegdifufzdi54dyzbswitch',
'unit_of_measurement': None,
})
# ---
# name: test_platform_setup_and_discovery[switch.smart_white_noise_machine-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Smart White Noise Machine',
}),
'context': <ANY>,
'entity_id': 'switch.smart_white_noise_machine',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_platform_setup_and_discovery[switch.smart_white_noise_machine_music-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': <EntityCategory.CONFIG: 'config'>,
'entity_id': 'switch.smart_white_noise_machine_music',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': 'mdi:music',
'original_name': 'Music',
'platform': 'tuya',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'music',
'unique_id': 'tuya.ri7eegdifufzdi54dyzbswitch_music',
'unit_of_measurement': None,
})
# ---
# name: test_platform_setup_and_discovery[switch.smart_white_noise_machine_music-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Smart White Noise Machine Music',
'icon': 'mdi:music',
}),
'context': <ANY>,
'entity_id': 'switch.smart_white_noise_machine_music',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_platform_setup_and_discovery[switch.smoke_alarm_mute-entry]
EntityRegistryEntrySnapshot({
'aliases': set({