mirror of
https://github.com/home-assistant/core.git
synced 2025-07-09 22:37:11 +00:00
Add support for learning RF commands with Broadlink remotes (#39671)
* Add support for learning RF codes with Broadlink remotes * Rename INFRARED and RADIOFREQUENCY to COMMAND_TYPE_IR and COMMAND_TYPE_RF * Rewrite if expression as normal if statement * Use COMMAND_TYPE_IR directly and improve error messages
This commit is contained in:
parent
7921be1b5f
commit
c620fa344e
@ -18,6 +18,7 @@ import voluptuous as vol
|
||||
from homeassistant.components.remote import (
|
||||
ATTR_ALTERNATIVE,
|
||||
ATTR_COMMAND,
|
||||
ATTR_COMMAND_TYPE,
|
||||
ATTR_DELAY_SECS,
|
||||
ATTR_DEVICE,
|
||||
ATTR_NUM_REPEATS,
|
||||
@ -41,6 +42,10 @@ _LOGGER = logging.getLogger(__name__)
|
||||
|
||||
LEARNING_TIMEOUT = timedelta(seconds=30)
|
||||
|
||||
COMMAND_TYPE_IR = "ir"
|
||||
COMMAND_TYPE_RF = "rf"
|
||||
COMMAND_TYPES = [COMMAND_TYPE_IR, COMMAND_TYPE_RF]
|
||||
|
||||
CODE_STORAGE_VERSION = 1
|
||||
FLAG_STORAGE_VERSION = 1
|
||||
FLAG_SAVE_DELAY = 15
|
||||
@ -64,6 +69,7 @@ SERVICE_SEND_SCHEMA = COMMAND_SCHEMA.extend(
|
||||
SERVICE_LEARN_SCHEMA = COMMAND_SCHEMA.extend(
|
||||
{
|
||||
vol.Required(ATTR_DEVICE): vol.All(cv.string, vol.Length(min=1)),
|
||||
vol.Optional(ATTR_COMMAND_TYPE, default=COMMAND_TYPE_IR): vol.In(COMMAND_TYPES),
|
||||
vol.Optional(ATTR_ALTERNATIVE, default=False): cv.boolean,
|
||||
}
|
||||
)
|
||||
@ -266,11 +272,11 @@ class BroadlinkRemote(RemoteEntity, RestoreEntity):
|
||||
await self._device.async_request(self._device.api.send_data, code)
|
||||
|
||||
except (AuthorizationError, NetworkTimeoutError, OSError) as err:
|
||||
_LOGGER.error("Failed to send '%s': %s", command, err)
|
||||
_LOGGER.error("Failed to send '%s': %s", cmd, err)
|
||||
break
|
||||
|
||||
except BroadlinkException as err:
|
||||
_LOGGER.error("Failed to send '%s': %s", command, err)
|
||||
_LOGGER.error("Failed to send '%s': %s", cmd, err)
|
||||
should_delay = False
|
||||
continue
|
||||
|
||||
@ -284,6 +290,7 @@ class BroadlinkRemote(RemoteEntity, RestoreEntity):
|
||||
"""Learn a list of commands from a remote."""
|
||||
kwargs = SERVICE_LEARN_SCHEMA(kwargs)
|
||||
commands = kwargs[ATTR_COMMAND]
|
||||
command_type = kwargs[ATTR_COMMAND_TYPE]
|
||||
device = kwargs[ATTR_DEVICE]
|
||||
toggle = kwargs[ATTR_ALTERNATIVE]
|
||||
|
||||
@ -293,13 +300,18 @@ class BroadlinkRemote(RemoteEntity, RestoreEntity):
|
||||
)
|
||||
return
|
||||
|
||||
if command_type == COMMAND_TYPE_IR:
|
||||
learn_command = self._async_learn_ir_command
|
||||
else:
|
||||
learn_command = self._async_learn_rf_command
|
||||
|
||||
should_store = False
|
||||
|
||||
for command in commands:
|
||||
try:
|
||||
code = await self._async_learn_command(command)
|
||||
code = await learn_command(command)
|
||||
if toggle:
|
||||
code = [code, await self._async_learn_command(command)]
|
||||
code = [code, await learn_command(command)]
|
||||
|
||||
except (AuthorizationError, NetworkTimeoutError, OSError) as err:
|
||||
_LOGGER.error("Failed to learn '%s': %s", command, err)
|
||||
@ -315,8 +327,8 @@ class BroadlinkRemote(RemoteEntity, RestoreEntity):
|
||||
if should_store:
|
||||
await self._code_storage.async_save(self._codes)
|
||||
|
||||
async def _async_learn_command(self, command):
|
||||
"""Learn a command from a remote."""
|
||||
async def _async_learn_ir_command(self, command):
|
||||
"""Learn an infrared command."""
|
||||
try:
|
||||
await self._device.async_request(self._device.api.enter_learning)
|
||||
|
||||
@ -336,12 +348,87 @@ class BroadlinkRemote(RemoteEntity, RestoreEntity):
|
||||
await asyncio.sleep(1)
|
||||
try:
|
||||
code = await self._device.async_request(self._device.api.check_data)
|
||||
|
||||
except (ReadError, StorageError):
|
||||
continue
|
||||
|
||||
return b64encode(code).decode("utf8")
|
||||
raise TimeoutError("No code received")
|
||||
|
||||
raise TimeoutError(
|
||||
"No infrared code received within "
|
||||
f"{LEARNING_TIMEOUT.seconds} seconds"
|
||||
)
|
||||
|
||||
finally:
|
||||
self.hass.components.persistent_notification.async_dismiss(
|
||||
notification_id="learn_command"
|
||||
)
|
||||
|
||||
async def _async_learn_rf_command(self, command):
|
||||
"""Learn a radiofrequency command."""
|
||||
try:
|
||||
await self._device.async_request(self._device.api.sweep_frequency)
|
||||
|
||||
except (BroadlinkException, OSError) as err:
|
||||
_LOGGER.debug("Failed to sweep frequency: %s", err)
|
||||
raise
|
||||
|
||||
self.hass.components.persistent_notification.async_create(
|
||||
f"Press and hold the '{command}' button.",
|
||||
title="Sweep frequency",
|
||||
notification_id="sweep_frequency",
|
||||
)
|
||||
|
||||
try:
|
||||
start_time = utcnow()
|
||||
while (utcnow() - start_time) < LEARNING_TIMEOUT:
|
||||
await asyncio.sleep(1)
|
||||
found = await self._device.async_request(
|
||||
self._device.api.check_frequency
|
||||
)
|
||||
if found:
|
||||
break
|
||||
else:
|
||||
await self._device.async_request(
|
||||
self._device.api.cancel_sweep_frequency
|
||||
)
|
||||
raise TimeoutError(
|
||||
"No radiofrequency found within "
|
||||
f"{LEARNING_TIMEOUT.seconds} seconds"
|
||||
)
|
||||
|
||||
finally:
|
||||
self.hass.components.persistent_notification.async_dismiss(
|
||||
notification_id="sweep_frequency"
|
||||
)
|
||||
|
||||
await asyncio.sleep(1)
|
||||
|
||||
try:
|
||||
await self._device.async_request(self._device.api.find_rf_packet)
|
||||
|
||||
except (BroadlinkException, OSError) as err:
|
||||
_LOGGER.debug("Failed to enter learning mode: %s", err)
|
||||
raise
|
||||
|
||||
self.hass.components.persistent_notification.async_create(
|
||||
f"Press the '{command}' button again.",
|
||||
title="Learn command",
|
||||
notification_id="learn_command",
|
||||
)
|
||||
|
||||
try:
|
||||
start_time = utcnow()
|
||||
while (utcnow() - start_time) < LEARNING_TIMEOUT:
|
||||
await asyncio.sleep(1)
|
||||
try:
|
||||
code = await self._device.async_request(self._device.api.check_data)
|
||||
except (ReadError, StorageError):
|
||||
continue
|
||||
return b64encode(code).decode("utf8")
|
||||
|
||||
raise TimeoutError(
|
||||
"No radiofrequency code received within "
|
||||
f"{LEARNING_TIMEOUT.seconds} seconds"
|
||||
)
|
||||
|
||||
finally:
|
||||
self.hass.components.persistent_notification.async_dismiss(
|
||||
|
Loading…
x
Reference in New Issue
Block a user