mirror of
https://github.com/home-assistant/core.git
synced 2026-07-13 09:38:42 +01:00
492a03a814
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
198 lines
6.7 KiB
Python
198 lines
6.7 KiB
Python
"""Tests for Broadlink remotes."""
|
|
|
|
from base64 import b64decode
|
|
from unittest.mock import call
|
|
|
|
from broadlink.exceptions import BroadlinkException
|
|
from freezegun.api import FrozenDateTimeFactory
|
|
import pytest
|
|
|
|
from homeassistant.components.broadlink.const import DOMAIN
|
|
from homeassistant.components.broadlink.updater import BroadlinkRMUpdateManager
|
|
from homeassistant.components.remote import (
|
|
DOMAIN as REMOTE_DOMAIN,
|
|
SERVICE_SEND_COMMAND,
|
|
SERVICE_TURN_OFF,
|
|
SERVICE_TURN_ON,
|
|
)
|
|
from homeassistant.const import (
|
|
ATTR_FRIENDLY_NAME,
|
|
STATE_OFF,
|
|
STATE_ON,
|
|
STATE_UNAVAILABLE,
|
|
Platform,
|
|
)
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
|
|
|
from . import get_device
|
|
|
|
from tests.common import async_fire_time_changed
|
|
|
|
REMOTE_DEVICES = ["Entrance", "Living Room", "Office", "Garage"]
|
|
|
|
IR_PACKET = (
|
|
"JgBGAJKVETkRORA6ERQRFBEUERQRFBE5ETkQOhAVEBUQFREUEBUQ"
|
|
"OhEUERQRORE5EBURFBA6EBUQOhE5EBUQFRA6EDoRFBEADQUAAA=="
|
|
)
|
|
|
|
|
|
async def test_remote_setup_works(
|
|
hass: HomeAssistant,
|
|
device_registry: dr.DeviceRegistry,
|
|
entity_registry: er.EntityRegistry,
|
|
) -> None:
|
|
"""Test a successful setup with all remotes."""
|
|
for device in map(get_device, REMOTE_DEVICES):
|
|
mock_setup = await device.setup_entry(hass)
|
|
|
|
device_entry = device_registry.async_get_device(
|
|
identifiers={(DOMAIN, mock_setup.entry.unique_id)}
|
|
)
|
|
entries = er.async_entries_for_device(entity_registry, device_entry.id)
|
|
remotes = [entry for entry in entries if entry.domain == Platform.REMOTE]
|
|
assert len(remotes) == 1
|
|
|
|
remote = remotes[0]
|
|
assert (
|
|
hass.states.get(remote.entity_id).attributes[ATTR_FRIENDLY_NAME]
|
|
== device.name
|
|
)
|
|
assert hass.states.get(remote.entity_id).state == STATE_ON
|
|
assert mock_setup.api.auth.call_count == 1
|
|
|
|
|
|
async def test_remote_send_command(
|
|
hass: HomeAssistant,
|
|
device_registry: dr.DeviceRegistry,
|
|
entity_registry: er.EntityRegistry,
|
|
) -> None:
|
|
"""Test sending a command with all remotes."""
|
|
for device in map(get_device, REMOTE_DEVICES):
|
|
mock_setup = await device.setup_entry(hass)
|
|
|
|
device_entry = device_registry.async_get_device(
|
|
identifiers={(DOMAIN, mock_setup.entry.unique_id)}
|
|
)
|
|
entries = er.async_entries_for_device(entity_registry, device_entry.id)
|
|
remotes = [entry for entry in entries if entry.domain == Platform.REMOTE]
|
|
assert len(remotes) == 1
|
|
|
|
remote = remotes[0]
|
|
await hass.services.async_call(
|
|
REMOTE_DOMAIN,
|
|
SERVICE_SEND_COMMAND,
|
|
{"entity_id": remote.entity_id, "command": "b64:" + IR_PACKET},
|
|
blocking=True,
|
|
)
|
|
|
|
assert mock_setup.api.send_data.call_count == 1
|
|
assert mock_setup.api.send_data.call_args == call(b64decode(IR_PACKET))
|
|
assert mock_setup.api.auth.call_count == 1
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("error", "ticks_to_unavailable"),
|
|
[
|
|
# OSError flips availability on the first failure (fast path).
|
|
(OSError("connection refused"), 1),
|
|
# A generic BroadlinkException keeps the entity available across the
|
|
# first three failed cycles and only flips once SCAN_INTERVAL * 3 has
|
|
# elapsed since the last successful update.
|
|
(BroadlinkException("update failed"), 4),
|
|
],
|
|
)
|
|
async def test_remote_availability(
|
|
hass: HomeAssistant,
|
|
freezer: FrozenDateTimeFactory,
|
|
device_registry: dr.DeviceRegistry,
|
|
entity_registry: er.EntityRegistry,
|
|
error: Exception,
|
|
ticks_to_unavailable: int,
|
|
) -> None:
|
|
"""Test the remote becomes unavailable on disconnect and recovers on reconnect."""
|
|
device = get_device("Garage")
|
|
mock_setup = await device.setup_entry(hass)
|
|
|
|
device_entry = device_registry.async_get_device(
|
|
identifiers={(DOMAIN, mock_setup.entry.unique_id)}
|
|
)
|
|
entries = er.async_entries_for_device(entity_registry, device_entry.id)
|
|
remote = next(entry for entry in entries if entry.domain == Platform.REMOTE)
|
|
|
|
assert hass.states.get(remote.entity_id).state == STATE_ON
|
|
|
|
mock_setup.api.check_sensors.side_effect = error
|
|
|
|
for _ in range(ticks_to_unavailable - 1):
|
|
freezer.tick(BroadlinkRMUpdateManager.SCAN_INTERVAL)
|
|
async_fire_time_changed(hass)
|
|
await hass.async_block_till_done()
|
|
assert hass.states.get(remote.entity_id).state == STATE_ON
|
|
|
|
freezer.tick(BroadlinkRMUpdateManager.SCAN_INTERVAL)
|
|
async_fire_time_changed(hass)
|
|
await hass.async_block_till_done()
|
|
|
|
assert hass.states.get(remote.entity_id).state == STATE_UNAVAILABLE
|
|
|
|
mock_setup.api.check_sensors.side_effect = None
|
|
|
|
freezer.tick(BroadlinkRMUpdateManager.SCAN_INTERVAL)
|
|
async_fire_time_changed(hass)
|
|
await hass.async_block_till_done()
|
|
|
|
assert hass.states.get(remote.entity_id).state == STATE_ON
|
|
|
|
|
|
async def test_remote_turn_off_turn_on(
|
|
hass: HomeAssistant,
|
|
device_registry: dr.DeviceRegistry,
|
|
entity_registry: er.EntityRegistry,
|
|
) -> None:
|
|
"""Test we do not send commands if the remotes are off."""
|
|
for device in map(get_device, REMOTE_DEVICES):
|
|
mock_setup = await device.setup_entry(hass)
|
|
|
|
device_entry = device_registry.async_get_device(
|
|
identifiers={(DOMAIN, mock_setup.entry.unique_id)}
|
|
)
|
|
entries = er.async_entries_for_device(entity_registry, device_entry.id)
|
|
remotes = [entry for entry in entries if entry.domain == Platform.REMOTE]
|
|
assert len(remotes) == 1
|
|
|
|
remote = remotes[0]
|
|
await hass.services.async_call(
|
|
REMOTE_DOMAIN,
|
|
SERVICE_TURN_OFF,
|
|
{"entity_id": remote.entity_id},
|
|
blocking=True,
|
|
)
|
|
assert hass.states.get(remote.entity_id).state == STATE_OFF
|
|
|
|
await hass.services.async_call(
|
|
REMOTE_DOMAIN,
|
|
SERVICE_SEND_COMMAND,
|
|
{"entity_id": remote.entity_id, "command": "b64:" + IR_PACKET},
|
|
blocking=True,
|
|
)
|
|
assert mock_setup.api.send_data.call_count == 0
|
|
|
|
await hass.services.async_call(
|
|
REMOTE_DOMAIN,
|
|
SERVICE_TURN_ON,
|
|
{"entity_id": remote.entity_id},
|
|
blocking=True,
|
|
)
|
|
assert hass.states.get(remote.entity_id).state == STATE_ON
|
|
|
|
await hass.services.async_call(
|
|
REMOTE_DOMAIN,
|
|
SERVICE_SEND_COMMAND,
|
|
{"entity_id": remote.entity_id, "command": "b64:" + IR_PACKET},
|
|
blocking=True,
|
|
)
|
|
assert mock_setup.api.send_data.call_count == 1
|
|
assert mock_setup.api.send_data.call_args == call(b64decode(IR_PACKET))
|
|
assert mock_setup.api.auth.call_count == 1
|