1 """Support for the Xiaomi IR Remote (Chuangmi IR)."""
3 from __future__
import annotations
6 from datetime
import timedelta
11 from miio
import ChuangmiIr, DeviceException
12 import voluptuous
as vol
19 PLATFORM_SCHEMA
as REMOTE_PLATFORM_SCHEMA,
36 from .const
import SERVICE_LEARN, SERVICE_SET_REMOTE_LED_OFF, SERVICE_SET_REMOTE_LED_ON
38 _LOGGER = logging.getLogger(__name__)
40 DATA_KEY =
"remote.xiaomi_miio"
43 CONF_COMMANDS =
"commands"
48 COMMAND_SCHEMA = vol.Schema(
49 {vol.Required(CONF_COMMAND): vol.All(cv.ensure_list, [cv.string])}
52 PLATFORM_SCHEMA = REMOTE_PLATFORM_SCHEMA.extend(
54 vol.Optional(CONF_NAME): cv.string,
55 vol.Required(CONF_HOST): cv.string,
56 vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int,
57 vol.Optional(CONF_SLOT, default=DEFAULT_SLOT): vol.All(
58 int, vol.Range(min=1, max=1000000)
60 vol.Required(CONF_TOKEN): vol.All(str, vol.Length(min=32, max=32)),
61 vol.Optional(CONF_COMMANDS, default={}): cv.schema_with_slug_keys(
65 extra=vol.ALLOW_EXTRA,
72 async_add_entities: AddEntitiesCallback,
73 discovery_info: DiscoveryInfoType |
None =
None,
75 """Set up the Xiaomi IR Remote (Chuangmi IR) platform."""
76 host = config[CONF_HOST]
77 token = config[CONF_TOKEN]
80 _LOGGER.debug(
"Initializing with host %s (token %s...)", host, token[:5])
85 device = ChuangmiIr(host, token, lazy_discover=
False)
89 device_info = await hass.async_add_executor_job(device.info)
90 model = device_info.model
91 unique_id = f
"{model}-{device_info.mac_address}"
95 device_info.firmware_version,
96 device_info.hardware_version,
98 except DeviceException
as ex:
99 _LOGGER.error(
"Device unavailable or token incorrect: %s", ex)
100 raise PlatformNotReady
from ex
102 if DATA_KEY
not in hass.data:
103 hass.data[DATA_KEY] = {}
105 friendly_name = config.get(CONF_NAME, f
"xiaomi_miio_{host.replace('.', '_')}")
106 slot = config.get(CONF_SLOT)
107 timeout = config.get(CONF_TIMEOUT)
110 friendly_name, device, unique_id, slot, timeout, config.get(CONF_COMMANDS)
113 hass.data[DATA_KEY][host] = xiaomi_miio_remote
117 async
def async_service_led_off_handler(entity, service):
118 """Handle set_led_off command."""
119 await hass.async_add_executor_job(entity.device.set_indicator_led,
False)
121 async
def async_service_led_on_handler(entity, service):
122 """Handle set_led_on command."""
123 await hass.async_add_executor_job(entity.device.set_indicator_led,
True)
125 async
def async_service_learn_handler(entity, service):
126 """Handle a learn command."""
127 device = entity.device
129 slot = service.data.get(CONF_SLOT, entity.slot)
131 await hass.async_add_executor_job(device.learn, slot)
133 timeout = service.data.get(CONF_TIMEOUT, entity.timeout)
135 _LOGGER.info(
"Press the key you want Home Assistant to learn")
138 message = await hass.async_add_executor_job(device.read, slot)
139 _LOGGER.debug(
"Message received from device: '%s'", message)
141 if code := message.get(
"code"):
142 log_msg = f
"Received command is: {code}"
143 _LOGGER.info(log_msg)
144 persistent_notification.async_create(
145 hass, log_msg, title=
"Xiaomi Miio Remote"
149 if "error" in message
and message[
"error"][
"message"] ==
"learn timeout":
150 await hass.async_add_executor_job(device.learn, slot)
152 await asyncio.sleep(1)
154 _LOGGER.error(
"Timeout. No infrared command captured")
155 persistent_notification.async_create(
156 hass,
"Timeout. No infrared command captured", title=
"Xiaomi Miio Remote"
159 platform = entity_platform.async_get_current_platform()
161 platform.async_register_entity_service(
164 vol.Optional(CONF_TIMEOUT, default=10): cv.positive_int,
165 vol.Optional(CONF_SLOT, default=1): vol.All(
166 int, vol.Range(min=1, max=1000000)
169 async_service_learn_handler,
171 platform.async_register_entity_service(
172 SERVICE_SET_REMOTE_LED_ON,
174 async_service_led_on_handler,
176 platform.async_register_entity_service(
177 SERVICE_SET_REMOTE_LED_OFF,
179 async_service_led_off_handler,
184 """Representation of a Xiaomi Miio Remote device."""
186 _attr_should_poll =
False
188 def __init__(self, friendly_name, device, unique_id, slot, timeout, commands):
189 """Initialize the remote."""
200 """Return an unique ID."""
205 """Return the name of the remote."""
206 return self.
_name_name
210 """Return the remote object."""
215 """Return the slot to save learned command."""
216 return self.
_slot_slot
220 """Return the timeout for learning command."""
225 """Return False if device is unreachable, else True."""
228 except DeviceException:
233 """Turn the device on."""
235 "Device does not support turn_on, "
236 "please use 'remote.send_command' to send commands"
240 """Turn the device off."""
242 "Device does not support turn_off, "
243 "please use 'remote.send_command' to send commands"
247 """Send a command."""
248 _LOGGER.debug(
"Sending payload: '%s'", payload)
250 self.
devicedevice.play(payload)
251 except DeviceException
as ex:
253 "Transmit of IR command failed, %s, exception: %s", payload, ex
257 """Send a command."""
258 num_repeats = kwargs.get(ATTR_NUM_REPEATS)
260 delay = kwargs.get(ATTR_DELAY_SECS, DEFAULT_DELAY_SECS)
262 for _
in range(num_repeats):
263 for payload
in command:
265 for local_payload
in self.
_commands_commands[payload][CONF_COMMAND]:
None async_turn_on(self, **Any kwargs)
None async_turn_off(self, **Any kwargs)
def __init__(self, friendly_name, device, unique_id, slot, timeout, commands)
def send_command(self, command, **kwargs)
def _send_command(self, payload)
None async_setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback async_add_entities, DiscoveryInfoType|None discovery_info=None)