17 This is a new and independent implementation of the Lirc irsend(1) program.
18 It offers a Python API and a command line interface. The command line
19 interface is almost, but not quite, compatible with irsend. Instead, it is
20 organized as a program with subcommands, send_once, etc.
22 There are some other subtile differences from irsend:
24 * subcommand must be lower case,
25 * send_once only takes one command (irsend takes several),
26 * send_stop without arguments uses the remote and the command from the last
28 * no need to give dummy empty arguments for list,
29 * The --count argument to send_once is argument to the subcommand.
30 * the code in list remote is suppressed, unless -c is given,
31 * port number must be given with the --port (-p) argument; hostip:portnumber
33 * verbose option --verbose (-v)
34 * selectable timeout with --timeout (-t) option
35 * better error messages
37 It is using the new lirc Python API, including a C extension module.
39 For a GUI version, look at IrScrutinizer.
40 For a Java version, look at Javairtool
41 https://github.com/bengtmartensson/JavaLircClient
53 def _parse_commandline():
54 ''' Parse the command line, returns a filled-in parser. '''
56 parser = argparse.ArgumentParser(
58 description=
"Tool to send IR codes and manipulate lircd(8)")
61 help=
'lircd host IP name or address, overrides --device.',
62 metavar=
"host", dest=
'address', default=
None)
63 path = client.get_default_socket_path()
66 help=
'lircd socket path [%s]' % path, metavar=
"path",
67 dest=
'socket_pathname', default=
None)
70 help=
'lircd IP port, use with --address [%d] ' % _DEFAULT_PORT,
71 dest=
'port', default=_DEFAULT_PORT, type=int)
74 help=
'Timeout in milliseconds [No timeout]', metavar=
"ms",
75 dest=
'timeout', type=int, default=
None)
78 help=
'Display version information for irtool',
79 dest=
'versionRequested', action=
'store_true')
82 help=
'Have some commands executed verbosely',
83 dest=
'verbose', action=
'store_true')
84 subparsers = parser.add_subparsers(
86 metavar=
'sub-commands')
89 parser_send_once = subparsers.add_parser(
91 help=
'Send one command')
92 parser_send_once.add_argument(
93 '-#',
'-c',
'--count',
94 help=
'Number of times to send command in send_once',
95 dest=
'count', type=int, default=1)
96 parser_send_once.add_argument(
'remote', help=
'Name of remote')
97 parser_send_once.add_argument(
'command', help=
'Name of command')
100 parser_send_start = subparsers.add_parser(
102 help=
'Start sending one command until stopped')
103 parser_send_start.add_argument(
105 help=
'Name of remote')
106 parser_send_start.add_argument(
108 help=
'Name of command')
111 parser_send_stop = subparsers.add_parser(
113 help=
'Stop sending the command from send_start')
114 parser_send_stop.add_argument(
116 help=
'remote command')
117 parser_send_stop.add_argument(
119 help=
'remote command')
122 subparsers.add_parser(
'list-remotes', help=
'List available remotes')
125 parser_list_keys = subparsers.add_parser(
127 help=
'list defined keys in given remote')
128 parser_list_keys.add_argument(
130 help=
'Name of remote')
131 parser_list_keys.add_argument(
133 help=
'List the numerical codes in lircd.conf, not just names',
134 dest=
'codes', action=
'store_true')
137 parser_drv_option = subparsers.add_parser(
139 help=
'Set driver option to given value')
140 parser_drv_option.add_argument(
'option', help=
'Option name')
141 parser_drv_option.add_argument(
'value', help=
'Option value')
144 parser_set_input_log = \
145 subparsers.add_parser(
'set-inputlog', help=
'Set input logging')
146 parser_set_input_log.add_argument(
147 'log_file', nargs=
'?',
148 help=
'Path to log file, empty to inhibit logging', default=
'')
151 parser_set_driver_options = subparsers.add_parser(
153 'set-driver-options',
154 help=
'Set driver options')
155 parser_set_driver_options.add_argument(
'key', help=
'Option name')
156 parser_set_driver_options.add_argument(
'value', help=
'Option value')
159 subparsers.add_parser(
'version', help=
'Get lircd version')
162 parser_simulate = subparsers.add_parser(
164 help=
'Fake the reception of IR signals')
165 parser_simulate.add_argument(
167 help=
'remote part of simulated event')
168 parser_simulate.add_argument(
170 help=
'Name of command to be faked')
171 parser_simulate.add_argument(
173 help=
'Key press data to be sent to the Lircd')
176 parser_set_transmitters = subparsers.add_parser(
178 help=
'Set transmitters')
179 parser_set_transmitters.add_argument(
181 metavar=
'N', nargs=
'+', help=
"transmitter...")
183 args = parser.parse_args()
185 if args.versionRequested:
191 def _send_once_command(connection, args):
192 ''' Perform a SEND_ONCE ... socket command. '''
193 if isinstance(args.keys, str):
194 args.keys = [args.keys]
195 command = client.SendCommand(connection, args.remote, args.keys)
196 parser = command.run(args.timeout)
197 if not parser.success:
198 print(parser.data[0])
199 return 0
if parser.success
else 1
202 def _start_repeat_command(conn, args):
203 ''' Perform a SEND_START <remote> <key> socket command. '''
204 command = client.StartRepeatCommand(conn, args.remote, args.key)
205 parser = command.run(args.timeout)
206 if not parser.success:
207 print(parser.data[0])
208 return 0
if parser.success
else 1
211 def _stop_repeat_command(conn, args):
212 ''' Perform a SEND_STOP <remote> <key> socket command. '''
213 command = client.StopRepeatCommand(conn, args.remote, args.key)
214 parser = command.run(args.timeout)
215 if not parser.success:
216 print(parser.data[0])
217 return 0
if parser.success
else 1
220 def _drv_option_command(conn, args):
221 ''' Perform a "DRV_OPTION <option> <value>" socket command. '''
222 command = client.DrvOptionCommand(conn, args.option, args.value)
223 parser = command.run(args.timeout)
224 if not parser.success:
225 print(parser.data[0])
226 return 0
if parser.success
else 1
229 def _list_keys_command(conn, args):
230 ''' Perform a irsend LIST <remote> socket command. '''
231 command = client.ListKeysCommand(conn, args.remote)
232 parser = command.run(args.timeout)
233 if not parser.success:
234 print(parser.data[0])
236 if not args.codes
and args.remote:
237 parser.data = [x.split()[-1]
for x
in parser.data]
238 for key
in parser.data:
240 return 0
if parser.success
else 1
243 def _list_remotes_command(conn):
244 ''' Perform a irsend LIST command. '''
245 command = client.ListRemotesCommand(conn)
246 parser = command.run()
247 if not parser.success:
248 print(parser.data[0])
250 for key
in parser.data:
252 return 0
if parser.success
else 1
255 def _set_input_log_command(conn, args):
256 ''' Start or stop lircd logging using SET_LOGFILE socket command. '''
257 command = client.SetLogCommand(conn, args.logfile)
258 parser = command.run(args.timeout)
259 if not parser.success:
260 print(parser.data[0])
261 return 0
if parser.success
else 1
264 def _simulate_command(conn, args, repeat=0):
265 ''' Roughly a irsend SIMULATE equivalent. '''
267 client.SimulateCommand(
268 conn, args.remote, args.key, repeat, args.data)
269 parser = command.run(args.timeout)
270 if not parser.success:
271 print(parser.data[0])
272 return 0
if parser.success
else 1
275 def _transmitters_cmd(conn, args):
276 ''' Perform an irsend SET_TRANSMITTERS command. '''
277 command = client.SetTransmittersCommand(conn, args.transmitters)
278 parser = command.run(args.timeout)
279 if not parser.success:
280 print(parser.data[0])
281 return 0
if parser.success
else 1
284 def _version_command(conn):
285 ''' Retrieve lircd version using the VERSION socket command. '''
286 command = client.VersionCommand(conn)
287 parser = command.run()
288 print(parser.data[0])
289 return 0
if parser.success
else 1
292 def _not_implemented():
293 ''' Indeed, the not-implemented message '''
294 print(
"Subcommand not implemented yet, are YOU volunteering?")
299 ''' Indeed: main function. '''
301 args = _parse_commandline()
303 s = socket.socket((socket.AF_INET, socket.SOCK_STREAM))
304 s.connect((args.address, args.port))
305 conn = client.CommandConnection(s)
307 conn = client.CommandConnection(args.socket_pathname)
311 lambda: _send_once_command(conn, args),
313 lambda: _start_repeat_command(conn, args),
315 lambda: _stop_repeat_command(conn, args),
317 lambda: _list_keys_command(conn, args),
319 lambda: _list_remotes_command(conn),
321 lambda: _set_input_log_command(conn, args),
323 lambda: _simulate_command(conn, args),
325 lambda: _transmitters_cmd(conn, args),
327 lambda: _drv_option_command(conn, args),
329 lambda: _version_command(conn),
332 if args.subcommand
in cmd_table:
333 exitstatus = cmd_table[args.subcommand]()
335 print(
'Unknown subcommand, use --help for syntax.')
338 except ConnectionRefusedError:
339 print(
"Connection refused")
341 except FileNotFoundError:
342 print(
"Could not find {0}".format(args.socket_pathname))
344 except PermissionError:
345 print(
"No permission to open {0}".format(args.socket_pathname))
351 if __name__ ==
"__main__":