a675eb7c936e09482efbc5ed19a124cacecd7bda
[~helmut/onoff.git] / dbus_client.py
1 #!/usr/bin/env python
2 """
3 A simpe client for an onoff device. If no command is given, the device is
4 temporarily activated. When a command is given, the device is activated, then
5 the command is run. Some time after the command finishes, the device is
6 released.
7 """
8
9 import argparse
10 import os
11 import xml.parsers.expat
12
13 from dbus.mainloop.glib import DBusGMainLoop
14 from gi.repository import GObject
15
16 from onoff.common import ST_ACTIVE
17 import onoff.dbusutils
18
19 def wait_for_signal(proxy, signal):
20     loop = GObject.MainLoop()
21     state = []
22     def callback(st):
23         state.append(st)
24         loop.quit()
25     proxy.connect_to_signal(signal, callback)
26     loop.run()
27     return state[0]
28
29 def parse_introspection(xmlstring):
30     parser = xml.parsers.expat.ParserCreate()
31     nodes = []
32     def start_element(name, attrs):
33         if name != "node":
34             return
35         try:
36             value = attrs["name"]
37         except KeyError:
38             return
39         nodes.append(value)
40     parser.StartElementHandler = start_element
41     parser.Parse(xmlstring)
42     return nodes
43
44 def main():
45     parser = argparse.ArgumentParser(parents=[onoff.dbusutils.dbus_options])
46     parser.add_argument("--duration", type=int, default=10,
47                         help="how long to activate the device in seconds " +
48                         "(default: %(default)d")
49     parser.add_argument("command", nargs=argparse.REMAINDER,
50                         help="a command to be executed with the device being" +
51                              "activated for the duration of the execution")
52     parser.add_argument("--list", action="store_true",
53                         help="list available devices and exit")
54     args = parser.parse_args()
55     DBusGMainLoop(set_as_default=True)
56     if args.list:
57         bus = onoff.dbusutils.get_dbus(args)
58         proxy = bus.get_object(args.busname, onoff.dbusutils.object_prefix)
59         for elem in parse_introspection(proxy.Introspect()):
60             print(elem)
61     elif args.command:
62         proxy = onoff.dbusutils.get_dbus_proxy(args)
63         st, fd = proxy.activatefd()
64         fd = fd.take()
65         os.dup2(fd, 254)
66         os.close(fd)
67         if st != ST_ACTIVE:
68             print("state is %d waiting for signal" % st)
69             st = wait_for_signal(proxy, "changestate")
70             print("new state is %d" % st)
71         os.execvp(args.command[0], args.command)
72     else:
73         proxy = onoff.dbusutils.get_dbus_proxy(args)
74         st = proxy.activatetime(args.duration)
75         if st != ST_ACTIVE:
76             print("state is %d waiting for signal" % st)
77             st = wait_for_signal(proxy, "changestate")
78             print("new state is %d" % st)
79
80 if __name__ == "__main__":
81     main()