mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
Migrate Harmony to has entity name (#104737)
* Migrate Harmony to has entity name * Fix tests --------- Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
parent
6106a66ed8
commit
44211dc761
@ -29,7 +29,7 @@ class HarmonyData(HarmonySubscriberMixin):
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize a data object."""
|
"""Initialize a data object."""
|
||||||
super().__init__(hass)
|
super().__init__(hass)
|
||||||
self._name = name
|
self.name = name
|
||||||
self._unique_id = unique_id
|
self._unique_id = unique_id
|
||||||
self._available = False
|
self._available = False
|
||||||
self._address = address
|
self._address = address
|
||||||
@ -60,11 +60,6 @@ class HarmonyData(HarmonySubscriberMixin):
|
|||||||
|
|
||||||
return devices
|
return devices
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self) -> str:
|
|
||||||
"""Return the Harmony device's name."""
|
|
||||||
return self._name
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def unique_id(self):
|
def unique_id(self):
|
||||||
"""Return the Harmony device's unique_id."""
|
"""Return the Harmony device's unique_id."""
|
||||||
@ -105,7 +100,7 @@ class HarmonyData(HarmonySubscriberMixin):
|
|||||||
|
|
||||||
async def connect(self) -> None:
|
async def connect(self) -> None:
|
||||||
"""Connect to the Harmony Hub."""
|
"""Connect to the Harmony Hub."""
|
||||||
_LOGGER.debug("%s: Connecting", self._name)
|
_LOGGER.debug("%s: Connecting", self.name)
|
||||||
|
|
||||||
callbacks = {
|
callbacks = {
|
||||||
"config_updated": self._config_updated,
|
"config_updated": self._config_updated,
|
||||||
@ -124,27 +119,27 @@ class HarmonyData(HarmonySubscriberMixin):
|
|||||||
except (TimeoutError, aioexc.TimeOut) as err:
|
except (TimeoutError, aioexc.TimeOut) as err:
|
||||||
await self._client.close()
|
await self._client.close()
|
||||||
raise ConfigEntryNotReady(
|
raise ConfigEntryNotReady(
|
||||||
f"{self._name}: Connection timed-out to {self._address}:8088"
|
f"{self.name}: Connection timed-out to {self._address}:8088"
|
||||||
) from err
|
) from err
|
||||||
except (ValueError, AttributeError) as err:
|
except (ValueError, AttributeError) as err:
|
||||||
await self._client.close()
|
await self._client.close()
|
||||||
raise ConfigEntryNotReady(
|
raise ConfigEntryNotReady(
|
||||||
f"{self._name}: Error {err} while connected HUB at:"
|
f"{self.name}: Error {err} while connected HUB at:"
|
||||||
f" {self._address}:8088"
|
f" {self._address}:8088"
|
||||||
) from err
|
) from err
|
||||||
if not connected:
|
if not connected:
|
||||||
await self._client.close()
|
await self._client.close()
|
||||||
raise ConfigEntryNotReady(
|
raise ConfigEntryNotReady(
|
||||||
f"{self._name}: Unable to connect to HUB at: {self._address}:8088"
|
f"{self.name}: Unable to connect to HUB at: {self._address}:8088"
|
||||||
)
|
)
|
||||||
|
|
||||||
async def shutdown(self) -> None:
|
async def shutdown(self) -> None:
|
||||||
"""Close connection on shutdown."""
|
"""Close connection on shutdown."""
|
||||||
_LOGGER.debug("%s: Closing Harmony Hub", self._name)
|
_LOGGER.debug("%s: Closing Harmony Hub", self.name)
|
||||||
try:
|
try:
|
||||||
await self._client.close()
|
await self._client.close()
|
||||||
except aioexc.TimeOut:
|
except aioexc.TimeOut:
|
||||||
_LOGGER.warning("%s: Disconnect timed-out", self._name)
|
_LOGGER.warning("%s: Disconnect timed-out", self.name)
|
||||||
|
|
||||||
async def async_start_activity(self, activity: str) -> None:
|
async def async_start_activity(self, activity: str) -> None:
|
||||||
"""Start an activity from the Harmony device."""
|
"""Start an activity from the Harmony device."""
|
||||||
|
@ -19,11 +19,12 @@ TIME_MARK_DISCONNECTED = 10
|
|||||||
class HarmonyEntity(Entity):
|
class HarmonyEntity(Entity):
|
||||||
"""Base entity for Harmony with connection state handling."""
|
"""Base entity for Harmony with connection state handling."""
|
||||||
|
|
||||||
|
_attr_has_entity_name = True
|
||||||
|
|
||||||
def __init__(self, data: HarmonyData) -> None:
|
def __init__(self, data: HarmonyData) -> None:
|
||||||
"""Initialize the Harmony base entity."""
|
"""Initialize the Harmony base entity."""
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._unsub_mark_disconnected: Callable[[], None] | None = None
|
self._unsub_mark_disconnected: Callable[[], None] | None = None
|
||||||
self._name = data.name
|
|
||||||
self._data = data
|
self._data = data
|
||||||
self._attr_should_poll = False
|
self._attr_should_poll = False
|
||||||
|
|
||||||
@ -34,14 +35,14 @@ class HarmonyEntity(Entity):
|
|||||||
|
|
||||||
async def async_got_connected(self, _: str | None = None) -> None:
|
async def async_got_connected(self, _: str | None = None) -> None:
|
||||||
"""Notification that we're connected to the HUB."""
|
"""Notification that we're connected to the HUB."""
|
||||||
_LOGGER.debug("%s: connected to the HUB", self._name)
|
_LOGGER.debug("%s: connected to the HUB", self._data.name)
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
self._clear_disconnection_delay()
|
self._clear_disconnection_delay()
|
||||||
|
|
||||||
async def async_got_disconnected(self, _: str | None = None) -> None:
|
async def async_got_disconnected(self, _: str | None = None) -> None:
|
||||||
"""Notification that we're disconnected from the HUB."""
|
"""Notification that we're disconnected from the HUB."""
|
||||||
_LOGGER.debug("%s: disconnected from the HUB", self._name)
|
_LOGGER.debug("%s: disconnected from the HUB", self._data.name)
|
||||||
# We're going to wait for 10 seconds before announcing we're
|
# We're going to wait for 10 seconds before announcing we're
|
||||||
# unavailable, this to allow a reconnection to happen.
|
# unavailable, this to allow a reconnection to happen.
|
||||||
self._unsub_mark_disconnected = async_call_later(
|
self._unsub_mark_disconnected = async_call_later(
|
||||||
|
@ -87,6 +87,7 @@ class HarmonyRemote(HarmonyEntity, RemoteEntity, RestoreEntity):
|
|||||||
"""Remote representation used to control a Harmony device."""
|
"""Remote representation used to control a Harmony device."""
|
||||||
|
|
||||||
_attr_supported_features = RemoteEntityFeature.ACTIVITY
|
_attr_supported_features = RemoteEntityFeature.ACTIVITY
|
||||||
|
_attr_name = None
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, data: HarmonyData, activity: str | None, delay_secs: float, out_path: str
|
self, data: HarmonyData, activity: str | None, delay_secs: float, out_path: str
|
||||||
@ -103,7 +104,6 @@ class HarmonyRemote(HarmonyEntity, RemoteEntity, RestoreEntity):
|
|||||||
self._config_path = out_path
|
self._config_path = out_path
|
||||||
self._attr_unique_id = data.unique_id
|
self._attr_unique_id = data.unique_id
|
||||||
self._attr_device_info = self._data.device_info(DOMAIN)
|
self._attr_device_info = self._data.device_info(DOMAIN)
|
||||||
self._attr_name = data.name
|
|
||||||
|
|
||||||
async def _async_update_options(self, data: dict[str, Any]) -> None:
|
async def _async_update_options(self, data: dict[str, Any]) -> None:
|
||||||
"""Change options when the options flow does."""
|
"""Change options when the options flow does."""
|
||||||
@ -136,7 +136,7 @@ class HarmonyRemote(HarmonyEntity, RemoteEntity, RestoreEntity):
|
|||||||
"""Complete the initialization."""
|
"""Complete the initialization."""
|
||||||
await super().async_added_to_hass()
|
await super().async_added_to_hass()
|
||||||
|
|
||||||
_LOGGER.debug("%s: Harmony Hub added", self.name)
|
_LOGGER.debug("%s: Harmony Hub added", self._data.name)
|
||||||
|
|
||||||
self.async_on_remove(self._clear_disconnection_delay)
|
self.async_on_remove(self._clear_disconnection_delay)
|
||||||
self._setup_callbacks()
|
self._setup_callbacks()
|
||||||
@ -193,7 +193,7 @@ class HarmonyRemote(HarmonyEntity, RemoteEntity, RestoreEntity):
|
|||||||
def async_new_activity(self, activity_info: tuple) -> None:
|
def async_new_activity(self, activity_info: tuple) -> None:
|
||||||
"""Call for updating the current activity."""
|
"""Call for updating the current activity."""
|
||||||
activity_id, activity_name = activity_info
|
activity_id, activity_name = activity_info
|
||||||
_LOGGER.debug("%s: activity reported as: %s", self.name, activity_name)
|
_LOGGER.debug("%s: activity reported as: %s", self._data.name, activity_name)
|
||||||
self._current_activity = activity_name
|
self._current_activity = activity_name
|
||||||
if self._is_initial_update:
|
if self._is_initial_update:
|
||||||
self._is_initial_update = False
|
self._is_initial_update = False
|
||||||
@ -209,13 +209,13 @@ class HarmonyRemote(HarmonyEntity, RemoteEntity, RestoreEntity):
|
|||||||
|
|
||||||
async def async_new_config(self, _: dict | None = None) -> None:
|
async def async_new_config(self, _: dict | None = None) -> None:
|
||||||
"""Call for updating the current activity."""
|
"""Call for updating the current activity."""
|
||||||
_LOGGER.debug("%s: configuration has been updated", self.name)
|
_LOGGER.debug("%s: configuration has been updated", self._data.name)
|
||||||
self.async_new_activity(self._data.current_activity)
|
self.async_new_activity(self._data.current_activity)
|
||||||
await self.hass.async_add_executor_job(self.write_config_file)
|
await self.hass.async_add_executor_job(self.write_config_file)
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
"""Start an activity from the Harmony device."""
|
"""Start an activity from the Harmony device."""
|
||||||
_LOGGER.debug("%s: Turn On", self.name)
|
_LOGGER.debug("%s: Turn On", self._data.name)
|
||||||
|
|
||||||
activity = kwargs.get(ATTR_ACTIVITY, self.default_activity)
|
activity = kwargs.get(ATTR_ACTIVITY, self.default_activity)
|
||||||
|
|
||||||
@ -228,7 +228,9 @@ class HarmonyRemote(HarmonyEntity, RemoteEntity, RestoreEntity):
|
|||||||
if activity:
|
if activity:
|
||||||
await self._data.async_start_activity(activity)
|
await self._data.async_start_activity(activity)
|
||||||
else:
|
else:
|
||||||
_LOGGER.error("%s: No activity specified with turn_on service", self.name)
|
_LOGGER.error(
|
||||||
|
"%s: No activity specified with turn_on service", self._data.name
|
||||||
|
)
|
||||||
|
|
||||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
"""Start the PowerOff activity."""
|
"""Start the PowerOff activity."""
|
||||||
@ -236,9 +238,9 @@ class HarmonyRemote(HarmonyEntity, RemoteEntity, RestoreEntity):
|
|||||||
|
|
||||||
async def async_send_command(self, command: Iterable[str], **kwargs: Any) -> None:
|
async def async_send_command(self, command: Iterable[str], **kwargs: Any) -> None:
|
||||||
"""Send a list of commands to one device."""
|
"""Send a list of commands to one device."""
|
||||||
_LOGGER.debug("%s: Send Command", self.name)
|
_LOGGER.debug("%s: Send Command", self._data.name)
|
||||||
if (device := kwargs.get(ATTR_DEVICE)) is None:
|
if (device := kwargs.get(ATTR_DEVICE)) is None:
|
||||||
_LOGGER.error("%s: Missing required argument: device", self.name)
|
_LOGGER.error("%s: Missing required argument: device", self._data.name)
|
||||||
return
|
return
|
||||||
|
|
||||||
num_repeats = kwargs[ATTR_NUM_REPEATS]
|
num_repeats = kwargs[ATTR_NUM_REPEATS]
|
||||||
@ -263,10 +265,12 @@ class HarmonyRemote(HarmonyEntity, RemoteEntity, RestoreEntity):
|
|||||||
This is a handy way for users to figure out the available commands for automations.
|
This is a handy way for users to figure out the available commands for automations.
|
||||||
"""
|
"""
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"%s: Writing hub configuration to file: %s", self.name, self._config_path
|
"%s: Writing hub configuration to file: %s",
|
||||||
|
self._data.name,
|
||||||
|
self._config_path,
|
||||||
)
|
)
|
||||||
if (json_config := self._data.json_config) is None:
|
if (json_config := self._data.json_config) is None:
|
||||||
_LOGGER.warning("%s: No configuration received from hub", self.name)
|
_LOGGER.warning("%s: No configuration received from hub", self._data.name)
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -275,7 +279,7 @@ class HarmonyRemote(HarmonyEntity, RemoteEntity, RestoreEntity):
|
|||||||
except OSError as exc:
|
except OSError as exc:
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
"%s: Unable to write HUB configuration to %s: %s",
|
"%s: Unable to write HUB configuration to %s: %s",
|
||||||
self.name,
|
self._data.name,
|
||||||
self._config_path,
|
self._config_path,
|
||||||
exc,
|
exc,
|
||||||
)
|
)
|
||||||
|
@ -6,7 +6,6 @@ import logging
|
|||||||
|
|
||||||
from homeassistant.components.select import SelectEntity
|
from homeassistant.components.select import SelectEntity
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_NAME
|
|
||||||
from homeassistant.core import HassJob, HomeAssistant, callback
|
from homeassistant.core import HassJob, HomeAssistant, callback
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
@ -25,10 +24,7 @@ async def async_setup_entry(
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Set up harmony activities select."""
|
"""Set up harmony activities select."""
|
||||||
data: HarmonyData = hass.data[DOMAIN][entry.entry_id][HARMONY_DATA]
|
data: HarmonyData = hass.data[DOMAIN][entry.entry_id][HARMONY_DATA]
|
||||||
_LOGGER.debug("creating select for %s hub activities", entry.data[CONF_NAME])
|
async_add_entities([HarmonyActivitySelect(data)])
|
||||||
async_add_entities(
|
|
||||||
[HarmonyActivitySelect(f"{entry.data[CONF_NAME]} Activities", data)]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class HarmonyActivitySelect(HarmonyEntity, SelectEntity):
|
class HarmonyActivitySelect(HarmonyEntity, SelectEntity):
|
||||||
@ -36,13 +32,12 @@ class HarmonyActivitySelect(HarmonyEntity, SelectEntity):
|
|||||||
|
|
||||||
_attr_translation_key = "activities"
|
_attr_translation_key = "activities"
|
||||||
|
|
||||||
def __init__(self, name: str, data: HarmonyData) -> None:
|
def __init__(self, data: HarmonyData) -> None:
|
||||||
"""Initialize HarmonyActivitySelect class."""
|
"""Initialize HarmonyActivitySelect class."""
|
||||||
super().__init__(data=data)
|
super().__init__(data=data)
|
||||||
self._data = data
|
self._data = data
|
||||||
self._attr_unique_id = self._data.unique_id
|
self._attr_unique_id = self._data.unique_id
|
||||||
self._attr_device_info = self._data.device_info(DOMAIN)
|
self._attr_device_info = self._data.device_info(DOMAIN)
|
||||||
self._attr_name = name
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def options(self) -> list[str]:
|
def options(self) -> list[str]:
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
"entity": {
|
"entity": {
|
||||||
"select": {
|
"select": {
|
||||||
"activities": {
|
"activities": {
|
||||||
|
"name": "Activities",
|
||||||
"state": {
|
"state": {
|
||||||
"power_off": "Power Off"
|
"power_off": "Power Off"
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ from homeassistant.components.automation import automations_with_entity
|
|||||||
from homeassistant.components.script import scripts_with_entity
|
from homeassistant.components.script import scripts_with_entity
|
||||||
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN, SwitchEntity
|
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN, SwitchEntity
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_NAME
|
|
||||||
from homeassistant.core import HassJob, HomeAssistant, callback
|
from homeassistant.core import HassJob, HomeAssistant, callback
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
|
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
|
||||||
@ -25,28 +24,22 @@ async def async_setup_entry(
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Set up harmony activity switches."""
|
"""Set up harmony activity switches."""
|
||||||
data: HarmonyData = hass.data[DOMAIN][entry.entry_id][HARMONY_DATA]
|
data: HarmonyData = hass.data[DOMAIN][entry.entry_id][HARMONY_DATA]
|
||||||
activities = data.activities
|
|
||||||
|
|
||||||
switches = []
|
async_add_entities(
|
||||||
for activity in activities:
|
(HarmonyActivitySwitch(activity, data) for activity in data.activities), True
|
||||||
_LOGGER.debug("creating switch for activity: %s", activity)
|
)
|
||||||
name = f"{entry.data[CONF_NAME]} {activity['label']}"
|
|
||||||
switches.append(HarmonyActivitySwitch(name, activity, data))
|
|
||||||
|
|
||||||
async_add_entities(switches, True)
|
|
||||||
|
|
||||||
|
|
||||||
class HarmonyActivitySwitch(HarmonyEntity, SwitchEntity):
|
class HarmonyActivitySwitch(HarmonyEntity, SwitchEntity):
|
||||||
"""Switch representation of a Harmony activity."""
|
"""Switch representation of a Harmony activity."""
|
||||||
|
|
||||||
def __init__(self, name: str, activity: dict, data: HarmonyData) -> None:
|
def __init__(self, activity: dict, data: HarmonyData) -> None:
|
||||||
"""Initialize HarmonyActivitySwitch class."""
|
"""Initialize HarmonyActivitySwitch class."""
|
||||||
super().__init__(data=data)
|
super().__init__(data=data)
|
||||||
self._activity_name = activity["label"]
|
self._activity_name = self._attr_name = activity["label"]
|
||||||
self._activity_id = activity["id"]
|
self._activity_id = activity["id"]
|
||||||
self._attr_entity_registry_enabled_default = False
|
self._attr_entity_registry_enabled_default = False
|
||||||
self._attr_unique_id = f"activity_{self._activity_id}"
|
self._attr_unique_id = f"activity_{self._activity_id}"
|
||||||
self._attr_name = name
|
|
||||||
self._attr_device_info = self._data.device_info(DOMAIN)
|
self._attr_device_info = self._data.device_info(DOMAIN)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -5,9 +5,17 @@ from unittest.mock import AsyncMock, MagicMock, PropertyMock, patch
|
|||||||
from aioharmony.const import ClientCallbackType
|
from aioharmony.const import ClientCallbackType
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.harmony.const import ACTIVITY_POWER_OFF
|
from homeassistant.components.harmony.const import ACTIVITY_POWER_OFF, DOMAIN
|
||||||
|
from homeassistant.const import CONF_HOST, CONF_NAME
|
||||||
|
|
||||||
from .const import NILE_TV_ACTIVITY_ID, PLAY_MUSIC_ACTIVITY_ID, WATCH_TV_ACTIVITY_ID
|
from .const import (
|
||||||
|
HUB_NAME,
|
||||||
|
NILE_TV_ACTIVITY_ID,
|
||||||
|
PLAY_MUSIC_ACTIVITY_ID,
|
||||||
|
WATCH_TV_ACTIVITY_ID,
|
||||||
|
)
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
ACTIVITIES_TO_IDS = {
|
ACTIVITIES_TO_IDS = {
|
||||||
ACTIVITY_POWER_OFF: -1,
|
ACTIVITY_POWER_OFF: -1,
|
||||||
@ -166,3 +174,13 @@ def mock_write_config():
|
|||||||
"homeassistant.components.harmony.remote.HarmonyRemote.write_config_file",
|
"homeassistant.components.harmony.remote.HarmonyRemote.write_config_file",
|
||||||
) as mock:
|
) as mock:
|
||||||
yield mock
|
yield mock
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_config_entry() -> MockConfigEntry:
|
||||||
|
"""Return mock config entry."""
|
||||||
|
return MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
unique_id="123",
|
||||||
|
data={CONF_HOST: "192.0.2.0", CONF_NAME: HUB_NAME},
|
||||||
|
)
|
||||||
|
@ -43,15 +43,16 @@ STOP_COMMAND = "Stop"
|
|||||||
|
|
||||||
|
|
||||||
async def test_connection_state_changes(
|
async def test_connection_state_changes(
|
||||||
harmony_client, mock_hc, hass: HomeAssistant, mock_write_config
|
harmony_client,
|
||||||
|
mock_hc,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_write_config,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Ensure connection changes are reflected in the remote state."""
|
"""Ensure connection changes are reflected in the remote state."""
|
||||||
entry = MockConfigEntry(
|
|
||||||
domain=DOMAIN, data={CONF_HOST: "192.0.2.0", CONF_NAME: HUB_NAME}
|
|
||||||
)
|
|
||||||
|
|
||||||
entry.add_to_hass(hass)
|
mock_config_entry.add_to_hass(hass)
|
||||||
await hass.config_entries.async_setup(entry.entry_id)
|
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
# mocks start with current activity == Watch TV
|
# mocks start with current activity == Watch TV
|
||||||
@ -82,14 +83,13 @@ async def test_connection_state_changes(
|
|||||||
assert hass.states.is_state(ENTITY_REMOTE, STATE_ON)
|
assert hass.states.is_state(ENTITY_REMOTE, STATE_ON)
|
||||||
|
|
||||||
|
|
||||||
async def test_remote_toggles(mock_hc, hass: HomeAssistant, mock_write_config) -> None:
|
async def test_remote_toggles(
|
||||||
|
mock_hc, hass: HomeAssistant, mock_write_config, mock_config_entry: MockConfigEntry
|
||||||
|
) -> None:
|
||||||
"""Ensure calls to the remote also updates the switches."""
|
"""Ensure calls to the remote also updates the switches."""
|
||||||
entry = MockConfigEntry(
|
|
||||||
domain=DOMAIN, data={CONF_HOST: "192.0.2.0", CONF_NAME: HUB_NAME}
|
|
||||||
)
|
|
||||||
|
|
||||||
entry.add_to_hass(hass)
|
mock_config_entry.add_to_hass(hass)
|
||||||
await hass.config_entries.async_setup(entry.entry_id)
|
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
# mocks start remote with Watch TV default activity
|
# mocks start remote with Watch TV default activity
|
||||||
@ -151,15 +151,16 @@ async def test_remote_toggles(mock_hc, hass: HomeAssistant, mock_write_config) -
|
|||||||
|
|
||||||
|
|
||||||
async def test_async_send_command(
|
async def test_async_send_command(
|
||||||
mock_hc, harmony_client, hass: HomeAssistant, mock_write_config
|
mock_hc,
|
||||||
|
harmony_client,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_write_config,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Ensure calls to send remote commands properly propagate to devices."""
|
"""Ensure calls to send remote commands properly propagate to devices."""
|
||||||
entry = MockConfigEntry(
|
|
||||||
domain=DOMAIN, data={CONF_HOST: "192.0.2.0", CONF_NAME: HUB_NAME}
|
|
||||||
)
|
|
||||||
|
|
||||||
entry.add_to_hass(hass)
|
mock_config_entry.add_to_hass(hass)
|
||||||
await hass.config_entries.async_setup(entry.entry_id)
|
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
send_commands_mock = harmony_client.send_commands
|
send_commands_mock = harmony_client.send_commands
|
||||||
@ -285,11 +286,16 @@ async def test_async_send_command(
|
|||||||
|
|
||||||
|
|
||||||
async def test_async_send_command_custom_delay(
|
async def test_async_send_command_custom_delay(
|
||||||
mock_hc, harmony_client, hass: HomeAssistant, mock_write_config
|
mock_hc,
|
||||||
|
harmony_client,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_write_config,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Ensure calls to send remote commands properly propagate to devices with custom delays."""
|
"""Ensure calls to send remote commands properly propagate to devices with custom delays."""
|
||||||
entry = MockConfigEntry(
|
entry = MockConfigEntry(
|
||||||
domain=DOMAIN,
|
domain=DOMAIN,
|
||||||
|
unique_id="123",
|
||||||
data={
|
data={
|
||||||
CONF_HOST: "192.0.2.0",
|
CONF_HOST: "192.0.2.0",
|
||||||
CONF_NAME: HUB_NAME,
|
CONF_NAME: HUB_NAME,
|
||||||
@ -327,15 +333,16 @@ async def test_async_send_command_custom_delay(
|
|||||||
|
|
||||||
|
|
||||||
async def test_change_channel(
|
async def test_change_channel(
|
||||||
mock_hc, harmony_client, hass: HomeAssistant, mock_write_config
|
mock_hc,
|
||||||
|
harmony_client,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_write_config,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test change channel commands."""
|
"""Test change channel commands."""
|
||||||
entry = MockConfigEntry(
|
|
||||||
domain=DOMAIN, data={CONF_HOST: "192.0.2.0", CONF_NAME: HUB_NAME}
|
|
||||||
)
|
|
||||||
|
|
||||||
entry.add_to_hass(hass)
|
mock_config_entry.add_to_hass(hass)
|
||||||
await hass.config_entries.async_setup(entry.entry_id)
|
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
change_channel_mock = harmony_client.change_channel
|
change_channel_mock = harmony_client.change_channel
|
||||||
@ -353,15 +360,16 @@ async def test_change_channel(
|
|||||||
|
|
||||||
|
|
||||||
async def test_sync(
|
async def test_sync(
|
||||||
mock_hc, harmony_client, mock_write_config, hass: HomeAssistant
|
mock_hc,
|
||||||
|
harmony_client,
|
||||||
|
mock_write_config,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test the sync command."""
|
"""Test the sync command."""
|
||||||
entry = MockConfigEntry(
|
|
||||||
domain=DOMAIN, data={CONF_HOST: "192.0.2.0", CONF_NAME: HUB_NAME}
|
|
||||||
)
|
|
||||||
|
|
||||||
entry.add_to_hass(hass)
|
mock_config_entry.add_to_hass(hass)
|
||||||
await hass.config_entries.async_setup(entry.entry_id)
|
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
sync_mock = harmony_client.sync
|
sync_mock = harmony_client.sync
|
||||||
|
@ -2,38 +2,31 @@
|
|||||||
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from homeassistant.components.harmony.const import DOMAIN
|
|
||||||
from homeassistant.components.select import (
|
from homeassistant.components.select import (
|
||||||
ATTR_OPTION,
|
ATTR_OPTION,
|
||||||
DOMAIN as SELECT_DOMAIN,
|
DOMAIN as SELECT_DOMAIN,
|
||||||
SERVICE_SELECT_OPTION,
|
SERVICE_SELECT_OPTION,
|
||||||
)
|
)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF, STATE_ON, STATE_UNAVAILABLE
|
||||||
ATTR_ENTITY_ID,
|
|
||||||
CONF_HOST,
|
|
||||||
CONF_NAME,
|
|
||||||
STATE_OFF,
|
|
||||||
STATE_ON,
|
|
||||||
STATE_UNAVAILABLE,
|
|
||||||
)
|
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.util import utcnow
|
from homeassistant.util import utcnow
|
||||||
|
|
||||||
from .const import ENTITY_REMOTE, ENTITY_SELECT, HUB_NAME
|
from .const import ENTITY_REMOTE, ENTITY_SELECT
|
||||||
|
|
||||||
from tests.common import MockConfigEntry, async_fire_time_changed
|
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||||
|
|
||||||
|
|
||||||
async def test_connection_state_changes(
|
async def test_connection_state_changes(
|
||||||
harmony_client, mock_hc, hass: HomeAssistant, mock_write_config
|
harmony_client,
|
||||||
|
mock_hc,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_write_config,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Ensure connection changes are reflected in the switch states."""
|
"""Ensure connection changes are reflected in the switch states."""
|
||||||
entry = MockConfigEntry(
|
|
||||||
domain=DOMAIN, data={CONF_HOST: "192.0.2.0", CONF_NAME: HUB_NAME}
|
|
||||||
)
|
|
||||||
|
|
||||||
entry.add_to_hass(hass)
|
mock_config_entry.add_to_hass(hass)
|
||||||
await hass.config_entries.async_setup(entry.entry_id)
|
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
# mocks start with current activity == Watch TV
|
# mocks start with current activity == Watch TV
|
||||||
@ -56,14 +49,13 @@ async def test_connection_state_changes(
|
|||||||
assert hass.states.is_state(ENTITY_SELECT, "Watch TV")
|
assert hass.states.is_state(ENTITY_SELECT, "Watch TV")
|
||||||
|
|
||||||
|
|
||||||
async def test_options(mock_hc, hass: HomeAssistant, mock_write_config) -> None:
|
async def test_options(
|
||||||
|
mock_hc, hass: HomeAssistant, mock_write_config, mock_config_entry: MockConfigEntry
|
||||||
|
) -> None:
|
||||||
"""Ensure calls to the switch modify the harmony state."""
|
"""Ensure calls to the switch modify the harmony state."""
|
||||||
entry = MockConfigEntry(
|
|
||||||
domain=DOMAIN, data={CONF_HOST: "192.0.2.0", CONF_NAME: HUB_NAME}
|
|
||||||
)
|
|
||||||
|
|
||||||
entry.add_to_hass(hass)
|
mock_config_entry.add_to_hass(hass)
|
||||||
await hass.config_entries.async_setup(entry.entry_id)
|
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
# assert we have all options
|
# assert we have all options
|
||||||
@ -76,14 +68,12 @@ async def test_options(mock_hc, hass: HomeAssistant, mock_write_config) -> None:
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
async def test_select_option(mock_hc, hass: HomeAssistant, mock_write_config) -> None:
|
async def test_select_option(
|
||||||
|
mock_hc, hass: HomeAssistant, mock_write_config, mock_config_entry: MockConfigEntry
|
||||||
|
) -> None:
|
||||||
"""Ensure calls to the switch modify the harmony state."""
|
"""Ensure calls to the switch modify the harmony state."""
|
||||||
entry = MockConfigEntry(
|
mock_config_entry.add_to_hass(hass)
|
||||||
domain=DOMAIN, data={CONF_HOST: "192.0.2.0", CONF_NAME: HUB_NAME}
|
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||||
)
|
|
||||||
|
|
||||||
entry.add_to_hass(hass)
|
|
||||||
await hass.config_entries.async_setup(entry.entry_id)
|
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
# mocks start with current activity == Watch TV
|
# mocks start with current activity == Watch TV
|
||||||
|
@ -90,21 +90,22 @@ async def test_connection_state_changes(
|
|||||||
|
|
||||||
|
|
||||||
async def test_switch_toggles(
|
async def test_switch_toggles(
|
||||||
mock_hc, hass: HomeAssistant, mock_write_config, entity_registry: er.EntityRegistry
|
mock_hc,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_write_config,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Ensure calls to the switch modify the harmony state."""
|
"""Ensure calls to the switch modify the harmony state."""
|
||||||
entry = MockConfigEntry(
|
|
||||||
domain=DOMAIN, data={CONF_HOST: "192.0.2.0", CONF_NAME: HUB_NAME}
|
|
||||||
)
|
|
||||||
|
|
||||||
entry.add_to_hass(hass)
|
mock_config_entry.add_to_hass(hass)
|
||||||
await hass.config_entries.async_setup(entry.entry_id)
|
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
# enable switch entities
|
# enable switch entities
|
||||||
entity_registry.async_update_entity(ENTITY_WATCH_TV, disabled_by=None)
|
entity_registry.async_update_entity(ENTITY_WATCH_TV, disabled_by=None)
|
||||||
entity_registry.async_update_entity(ENTITY_PLAY_MUSIC, disabled_by=None)
|
entity_registry.async_update_entity(ENTITY_PLAY_MUSIC, disabled_by=None)
|
||||||
await hass.config_entries.async_reload(entry.entry_id)
|
await hass.config_entries.async_reload(mock_config_entry.entry_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
# mocks start with current activity == Watch TV
|
# mocks start with current activity == Watch TV
|
||||||
|
Loading…
x
Reference in New Issue
Block a user