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__":