Add HDFury switch platform (#160620)

This commit is contained in:
Glenn de Haan
2026-01-09 18:08:37 +01:00
committed by GitHub
parent a26c910db7
commit 694d67d2d5
7 changed files with 797 additions and 0 deletions
+10
View File
@@ -72,7 +72,17 @@ def mock_hdfury_client() -> Generator[AsyncMock]:
)
coord_client.get_config = AsyncMock(
return_value={
"autosw": "1",
"iractive": "1",
"htpcmode0": "0",
"htpcmode1": "0",
"htpcmode2": "0",
"htpcmode3": "0",
"mutetx0": "1",
"mutetx1": "1",
"relay": "0",
"macaddr": "c7:1c:df:9d:f6:40",
"oled": "1",
}
)
@@ -0,0 +1,481 @@
# serializer version: 1
# name: test_switch_entities[switch.hdfury_vrroom_02_auto_switch_inputs-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.hdfury_vrroom_02_auto_switch_inputs',
'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': 'Auto switch inputs',
'platform': 'hdfury',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'autosw',
'unique_id': '000123456789_autosw',
'unit_of_measurement': None,
})
# ---
# name: test_switch_entities[switch.hdfury_vrroom_02_auto_switch_inputs-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'HDFury VRROOM-02 Auto switch inputs',
}),
'context': <ANY>,
'entity_id': 'switch.hdfury_vrroom_02_auto_switch_inputs',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_switch_entities[switch.hdfury_vrroom_02_htpc_mode_rx0-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.hdfury_vrroom_02_htpc_mode_rx0',
'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': 'HTPC mode RX0',
'platform': 'hdfury',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'htpcmode0',
'unique_id': '000123456789_htpcmode0',
'unit_of_measurement': None,
})
# ---
# name: test_switch_entities[switch.hdfury_vrroom_02_htpc_mode_rx0-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'HDFury VRROOM-02 HTPC mode RX0',
}),
'context': <ANY>,
'entity_id': 'switch.hdfury_vrroom_02_htpc_mode_rx0',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_switch_entities[switch.hdfury_vrroom_02_htpc_mode_rx1-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.hdfury_vrroom_02_htpc_mode_rx1',
'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': 'HTPC mode RX1',
'platform': 'hdfury',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'htpcmode1',
'unique_id': '000123456789_htpcmode1',
'unit_of_measurement': None,
})
# ---
# name: test_switch_entities[switch.hdfury_vrroom_02_htpc_mode_rx1-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'HDFury VRROOM-02 HTPC mode RX1',
}),
'context': <ANY>,
'entity_id': 'switch.hdfury_vrroom_02_htpc_mode_rx1',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_switch_entities[switch.hdfury_vrroom_02_htpc_mode_rx2-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.hdfury_vrroom_02_htpc_mode_rx2',
'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': 'HTPC mode RX2',
'platform': 'hdfury',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'htpcmode2',
'unique_id': '000123456789_htpcmode2',
'unit_of_measurement': None,
})
# ---
# name: test_switch_entities[switch.hdfury_vrroom_02_htpc_mode_rx2-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'HDFury VRROOM-02 HTPC mode RX2',
}),
'context': <ANY>,
'entity_id': 'switch.hdfury_vrroom_02_htpc_mode_rx2',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_switch_entities[switch.hdfury_vrroom_02_htpc_mode_rx3-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.hdfury_vrroom_02_htpc_mode_rx3',
'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': 'HTPC mode RX3',
'platform': 'hdfury',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'htpcmode3',
'unique_id': '000123456789_htpcmode3',
'unit_of_measurement': None,
})
# ---
# name: test_switch_entities[switch.hdfury_vrroom_02_htpc_mode_rx3-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'HDFury VRROOM-02 HTPC mode RX3',
}),
'context': <ANY>,
'entity_id': 'switch.hdfury_vrroom_02_htpc_mode_rx3',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_switch_entities[switch.hdfury_vrroom_02_infrared-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.hdfury_vrroom_02_infrared',
'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': 'Infrared',
'platform': 'hdfury',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'iractive',
'unique_id': '000123456789_iractive',
'unit_of_measurement': None,
})
# ---
# name: test_switch_entities[switch.hdfury_vrroom_02_infrared-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'HDFury VRROOM-02 Infrared',
}),
'context': <ANY>,
'entity_id': 'switch.hdfury_vrroom_02_infrared',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_switch_entities[switch.hdfury_vrroom_02_mute_audio_tx0-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.hdfury_vrroom_02_mute_audio_tx0',
'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': 'Mute audio TX0',
'platform': 'hdfury',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'mutetx0',
'unique_id': '000123456789_mutetx0',
'unit_of_measurement': None,
})
# ---
# name: test_switch_entities[switch.hdfury_vrroom_02_mute_audio_tx0-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'HDFury VRROOM-02 Mute audio TX0',
}),
'context': <ANY>,
'entity_id': 'switch.hdfury_vrroom_02_mute_audio_tx0',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_switch_entities[switch.hdfury_vrroom_02_mute_audio_tx1-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.hdfury_vrroom_02_mute_audio_tx1',
'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': 'Mute audio TX1',
'platform': 'hdfury',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'mutetx1',
'unique_id': '000123456789_mutetx1',
'unit_of_measurement': None,
})
# ---
# name: test_switch_entities[switch.hdfury_vrroom_02_mute_audio_tx1-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'HDFury VRROOM-02 Mute audio TX1',
}),
'context': <ANY>,
'entity_id': 'switch.hdfury_vrroom_02_mute_audio_tx1',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_switch_entities[switch.hdfury_vrroom_02_oled_display-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.hdfury_vrroom_02_oled_display',
'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': 'OLED display',
'platform': 'hdfury',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'oled',
'unique_id': '000123456789_oled',
'unit_of_measurement': None,
})
# ---
# name: test_switch_entities[switch.hdfury_vrroom_02_oled_display-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'HDFury VRROOM-02 OLED display',
}),
'context': <ANY>,
'entity_id': 'switch.hdfury_vrroom_02_oled_display',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_switch_entities[switch.hdfury_vrroom_02_relay-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.hdfury_vrroom_02_relay',
'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': 'Relay',
'platform': 'hdfury',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'relay',
'unique_id': '000123456789_relay',
'unit_of_measurement': None,
})
# ---
# name: test_switch_entities[switch.hdfury_vrroom_02_relay-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'HDFury VRROOM-02 Relay',
}),
'context': <ANY>,
'entity_id': 'switch.hdfury_vrroom_02_relay',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
+99
View File
@@ -0,0 +1,99 @@
"""Tests for the HDFury switch platform."""
from unittest.mock import AsyncMock
from hdfury import HDFuryError
import pytest
from syrupy.assertion import SnapshotAssertion
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
import homeassistant.helpers.entity_registry as er
from . import setup_integration
from tests.common import MockConfigEntry, snapshot_platform
async def test_switch_entities(
hass: HomeAssistant,
snapshot: SnapshotAssertion,
entity_registry: er.EntityRegistry,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test HDFury switch entities."""
await setup_integration(hass, mock_config_entry, [Platform.SWITCH])
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
@pytest.mark.parametrize(
("entity_id", "method", "service"),
[
(
"switch.hdfury_vrroom_02_auto_switch_inputs",
"set_auto_switch_inputs",
"turn_on",
),
(
"switch.hdfury_vrroom_02_auto_switch_inputs",
"set_auto_switch_inputs",
"turn_off",
),
("switch.hdfury_vrroom_02_oled_display", "set_oled", "turn_on"),
("switch.hdfury_vrroom_02_oled_display", "set_oled", "turn_off"),
],
)
async def test_switch_turn_on_off(
hass: HomeAssistant,
mock_hdfury_client: AsyncMock,
mock_config_entry: MockConfigEntry,
entity_id: str,
method: str,
service: str,
) -> None:
"""Test turning device switches on and off."""
await setup_integration(hass, mock_config_entry, [Platform.SWITCH])
await hass.services.async_call(
"switch",
service,
{"entity_id": entity_id},
blocking=True,
)
getattr(mock_hdfury_client, method).assert_awaited_once()
@pytest.mark.parametrize(
("service", "method"),
[
("turn_on", "set_auto_switch_inputs"),
("turn_off", "set_auto_switch_inputs"),
],
)
async def test_switch_turn_error(
hass: HomeAssistant,
mock_hdfury_client: AsyncMock,
mock_config_entry: MockConfigEntry,
service: str,
method: str,
) -> None:
"""Test switch turn on/off raises HomeAssistantError on API failure."""
getattr(mock_hdfury_client, method).side_effect = HDFuryError()
await setup_integration(hass, mock_config_entry, [Platform.SWITCH])
with pytest.raises(
HomeAssistantError,
match="An error occurred while communicating with HDFury device",
):
await hass.services.async_call(
"switch",
service,
{"entity_id": "switch.hdfury_vrroom_02_auto_switch_inputs"},
blocking=True,
)