Home Assistant Unofficial Reference 2024.12.1
__init__.py
Go to the documentation of this file.
1 """Support for LIRC devices."""
2 
3 import logging
4 import threading
5 import time
6 
7 import lirc
8 
9 from homeassistant.const import EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP
10 from homeassistant.core import HomeAssistant
11 from homeassistant.helpers import config_validation as cv
12 from homeassistant.helpers.typing import ConfigType
13 
14 _LOGGER = logging.getLogger(__name__)
15 
16 BUTTON_NAME = "button_name"
17 
18 DOMAIN = "lirc"
19 
20 EVENT_IR_COMMAND_RECEIVED = "ir_command_received"
21 
22 ICON = "mdi:remote"
23 
24 CONFIG_SCHEMA = cv.empty_config_schema(DOMAIN)
25 
26 
27 def setup(hass: HomeAssistant, config: ConfigType) -> bool:
28  """Set up the LIRC capability."""
29  # blocking=True gives unexpected behavior (multiple responses for 1 press)
30  # also by not blocking, we allow hass to shut down the thread gracefully
31  # on exit.
32  lirc.init("home-assistant", blocking=False)
33  lirc_interface = LircInterface(hass)
34 
35  def _start_lirc(_event):
36  lirc_interface.start()
37 
38  def _stop_lirc(_event):
39  lirc_interface.stopped.set()
40 
41  hass.bus.listen_once(EVENT_HOMEASSISTANT_START, _start_lirc)
42  hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, _stop_lirc)
43 
44  return True
45 
46 
47 class LircInterface(threading.Thread):
48  """Interfaces with the lirc daemon to read IR commands.
49 
50  When using lirc in blocking mode, sometimes repeated commands get produced
51  in the next read of a command so we use a thread here to just wait
52  around until a non-empty response is obtained from lirc.
53  """
54 
55  def __init__(self, hass):
56  """Construct a LIRC interface object."""
57  threading.Thread.__init__(self)
58  self.daemondaemon = True
59  self.stoppedstopped = threading.Event()
60  self.hasshass = hass
61 
62  def run(self):
63  """Run the loop of the LIRC interface thread."""
64  _LOGGER.debug("LIRC interface thread started")
65  while not self.stoppedstopped.is_set():
66  try:
67  code = lirc.nextcode() # list; empty if no buttons pressed
68  except lirc.NextCodeError:
69  _LOGGER.warning("Error reading next code from LIRC")
70  code = None
71  # interpret result from python-lirc
72  if code:
73  code = code[0]
74  _LOGGER.debug("Got new LIRC code %s", code)
75  self.hasshass.bus.fire(EVENT_IR_COMMAND_RECEIVED, {BUTTON_NAME: code})
76  else:
77  time.sleep(0.2)
78  lirc.deinit()
79  _LOGGER.debug("LIRC interface thread stopped")
bool setup(HomeAssistant hass, ConfigType config)
Definition: __init__.py:27