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