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