mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 08:47:57 +00:00
Clean up command learning in the Broadlink integration (#36318)
This commit is contained in:
parent
7cc3102209
commit
38bb8ef4d2
@ -2,7 +2,6 @@
|
||||
import asyncio
|
||||
from base64 import b64decode, b64encode
|
||||
from binascii import unhexlify
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
import re
|
||||
|
||||
@ -13,7 +12,7 @@ from homeassistant.const import CONF_HOST
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.util.dt import utcnow
|
||||
|
||||
from .const import CONF_PACKET, DOMAIN, SERVICE_LEARN, SERVICE_SEND
|
||||
from .const import CONF_PACKET, DOMAIN, LEARNING_TIMEOUT, SERVICE_LEARN, SERVICE_SEND
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@ -84,7 +83,7 @@ async def async_setup_service(hass, host, device):
|
||||
|
||||
_LOGGER.info("Press the key you want Home Assistant to learn")
|
||||
start_time = utcnow()
|
||||
while (utcnow() - start_time) < timedelta(seconds=20):
|
||||
while (utcnow() - start_time) < LEARNING_TIMEOUT:
|
||||
await asyncio.sleep(1)
|
||||
try:
|
||||
packet = await device.async_request(device.api.check_data)
|
||||
|
@ -1,7 +1,8 @@
|
||||
"""Constants for broadlink platform."""
|
||||
from datetime import timedelta
|
||||
|
||||
CONF_PACKET = "packet"
|
||||
|
||||
DEFAULT_LEARNING_TIMEOUT = 20
|
||||
DEFAULT_NAME = "Broadlink"
|
||||
DEFAULT_PORT = 80
|
||||
DEFAULT_RETRY = 3
|
||||
@ -9,6 +10,8 @@ DEFAULT_TIMEOUT = 5
|
||||
|
||||
DOMAIN = "broadlink"
|
||||
|
||||
LEARNING_TIMEOUT = timedelta(seconds=30)
|
||||
|
||||
SERVICE_LEARN = "learn"
|
||||
SERVICE_SEND = "send"
|
||||
|
||||
|
@ -24,7 +24,6 @@ from homeassistant.components.remote import (
|
||||
ATTR_DELAY_SECS,
|
||||
ATTR_DEVICE,
|
||||
ATTR_NUM_REPEATS,
|
||||
ATTR_TIMEOUT,
|
||||
DEFAULT_DELAY_SECS,
|
||||
DOMAIN as COMPONENT,
|
||||
PLATFORM_SCHEMA,
|
||||
@ -40,10 +39,10 @@ from homeassistant.util.dt import utcnow
|
||||
|
||||
from . import DOMAIN, data_packet, hostname, mac_address
|
||||
from .const import (
|
||||
DEFAULT_LEARNING_TIMEOUT,
|
||||
DEFAULT_NAME,
|
||||
DEFAULT_PORT,
|
||||
DEFAULT_TIMEOUT,
|
||||
LEARNING_TIMEOUT,
|
||||
RM4_TYPES,
|
||||
RM_TYPES,
|
||||
)
|
||||
@ -74,10 +73,7 @@ SERVICE_SEND_SCHEMA = MINIMUM_SERVICE_SCHEMA.extend(
|
||||
)
|
||||
|
||||
SERVICE_LEARN_SCHEMA = MINIMUM_SERVICE_SCHEMA.extend(
|
||||
{
|
||||
vol.Optional(ATTR_ALTERNATIVE, default=False): cv.boolean,
|
||||
vol.Optional(ATTR_TIMEOUT, default=DEFAULT_LEARNING_TIMEOUT): cv.positive_int,
|
||||
}
|
||||
{vol.Optional(ATTR_ALTERNATIVE, default=False): cv.boolean}
|
||||
)
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||
@ -267,7 +263,6 @@ class BroadlinkRemote(RemoteEntity):
|
||||
commands = kwargs[ATTR_COMMAND]
|
||||
device = kwargs[ATTR_DEVICE]
|
||||
toggle = kwargs[ATTR_ALTERNATIVE]
|
||||
timeout = kwargs[ATTR_TIMEOUT]
|
||||
|
||||
if not self._state:
|
||||
return
|
||||
@ -275,66 +270,47 @@ class BroadlinkRemote(RemoteEntity):
|
||||
should_store = False
|
||||
for command in commands:
|
||||
try:
|
||||
should_store |= await self._async_learn_code(
|
||||
command, device, toggle, timeout
|
||||
)
|
||||
except (AuthorizationError, DeviceOfflineError):
|
||||
code = await self._async_learn_command(command)
|
||||
if toggle:
|
||||
code = [code, await self._async_learn_command(command)]
|
||||
except (AuthorizationError, DeviceOfflineError) as err_msg:
|
||||
_LOGGER.error("Failed to learn '%s': %s", command, err_msg)
|
||||
break
|
||||
except BroadlinkException:
|
||||
pass
|
||||
except (BroadlinkException, TimeoutError) as err_msg:
|
||||
_LOGGER.error("Failed to learn '%s': %s", command, err_msg)
|
||||
continue
|
||||
else:
|
||||
self._codes.setdefault(device, {}).update({command: code})
|
||||
should_store = True
|
||||
|
||||
if should_store:
|
||||
await self._code_storage.async_save(self._codes)
|
||||
|
||||
async def _async_learn_code(self, command, device, toggle, timeout):
|
||||
"""Learn a code from a remote.
|
||||
|
||||
Capture an additional code for toggle commands.
|
||||
"""
|
||||
async def _async_learn_command(self, command):
|
||||
"""Learn a command from a remote."""
|
||||
try:
|
||||
if not toggle:
|
||||
code = await self._async_capture_code(command, timeout)
|
||||
else:
|
||||
code = [
|
||||
await self._async_capture_code(command, timeout),
|
||||
await self._async_capture_code(command, timeout),
|
||||
]
|
||||
except TimeoutError:
|
||||
_LOGGER.error("Failed to learn '%s/%s': No code received", command, device)
|
||||
return False
|
||||
await self.device.async_request(self.device.api.enter_learning)
|
||||
except BroadlinkException as err_msg:
|
||||
_LOGGER.error("Failed to learn '%s/%s': %s", command, device, err_msg)
|
||||
_LOGGER.debug("Failed to enter learning mode: %s", err_msg)
|
||||
raise
|
||||
|
||||
self._codes.setdefault(device, {}).update({command: code})
|
||||
return True
|
||||
|
||||
async def _async_capture_code(self, command, timeout):
|
||||
"""Enter learning mode and capture a code from a remote."""
|
||||
await self.device.async_request(self.device.api.enter_learning)
|
||||
|
||||
self.hass.components.persistent_notification.async_create(
|
||||
f"Press the '{command}' button.",
|
||||
title="Learn command",
|
||||
notification_id="learn_command",
|
||||
)
|
||||
|
||||
code = None
|
||||
start_time = utcnow()
|
||||
while (utcnow() - start_time) < timedelta(seconds=timeout):
|
||||
await asyncio.sleep(1)
|
||||
try:
|
||||
code = await self.device.async_request(self.device.api.check_data)
|
||||
except (ReadError, StorageError):
|
||||
continue
|
||||
else:
|
||||
break
|
||||
|
||||
self.hass.components.persistent_notification.async_dismiss(
|
||||
notification_id="learn_command"
|
||||
)
|
||||
|
||||
if code is None:
|
||||
raise TimeoutError
|
||||
|
||||
return b64encode(code).decode("utf8")
|
||||
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 code received")
|
||||
finally:
|
||||
self.hass.components.persistent_notification.async_dismiss(
|
||||
notification_id="learn_command"
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user