LIRC libraries
LinuxInfraredRemoteControl
async_client.py
1 ''' Asynchronous python bindings for the lircd socket interface. '''
2 ##
3 # @file async_client.py
4 # @author Alec Leamas
5 # @brief Asynchronour python bindings for a subset of the lirc_client.h
6 # interface.
7 # @ingroup python_bindings
8 
9 ## @addtogroup receiving
10 # @{
11 #
12 # Asynchronous interfaces to read lirc data on tóp of client.py.
13 #
14 #
15 # Asynchronous read
16 # -----------------
17 #
18 # Asynchronous read of raw data direct from the lircd socket can be
19 # done with the RawConnection class using something like:
20 #
21 # import asyncio
22 # from lirc import RawConnection, AsyncConnection
23 #
24 # async def main(raw_conn, loop):
25 # async with AsyncConnection(raw_conn, loop) as conn:
26 # async for keypress in conn:
27 # print(keypress)
28 #
29 # if __name__ == "__main__":
30 # socket_path = .....
31 # loop = asyncio.get_event_loop()
32 # with RawConnection(socket_path) as raw_conn:
33 # loop.run_until_complete(main(raw_conn, loop))
34 # loop.close()
35 #
36 #
37 # Using a LircdConnection with translated values works the same way.
38 # The API is unstable.
39 
40 # pylint: disable=W0613
41 
42 import asyncio
43 from lirc.client import AbstractConnection as AbstractConnection
44 
45 
46 class AsyncConnection(object):
47  ''' Asynchronous read interface on top of an AbstractConnection.
48 
49  Parameters:
50  - connection: Typically a lirc.RawConnection or lirc.LircdConnection.
51  - loop: AbstractEventLoop, typically obtained using
52  asyncio.get_event_loop().
53  '''
54 
55  def __init__(self, connection: AbstractConnection,
56  loop: asyncio.AbstractEventLoop):
57 
58  def read_from_fd():
59  ''' Read data from the connection fd and put into queue. '''
60  line = self._conn.readline(0)
61  if line:
62  asyncio.ensure_future(self._queue.put(line))
63 
64  self._conn = connection
65  self._loop = loop
66  self._queue = asyncio.Queue(loop=self._loop)
67  self._loop.add_reader(self._conn.fileno(), read_from_fd)
68 
69  def close(self):
70  ''' Clean up loop and the base connection. '''
71  self._loop.remove_reader(self._conn.fileno())
72 
73  async def readline(self) -> str:
74  ''' Asynchronous get next line from the connection. '''
75  return await self._queue.get()
76 
77  def __aiter__(self):
78  ''' Return async iterator. '''
79  return self
80 
81  async def __anext__(self):
82  ''' Implement async iterator.next(). '''
83  return await self._queue.get()
84 
85  async def __aenter__(self):
86  ''' Implement "async with". '''
87  return self
88 
89  async def __aexit__(self, exc_type, exc, traceback):
90  ''' Implement exit from "async with". '''
91  self.close()
92 
93 ## @}