draft device api
[~helmut/onoff.git] / dbus_service.py
1 #!/usr/bin/env python
2
3 import logging
4 import os
5
6 import dbus
7 import dbus.service
8 from dbus.mainloop.glib import DBusGMainLoop
9 from gi.repository import GObject
10
11 from onoff.common import ST_ACTIVE, ST_TRANSITION
12
13 logger = logging.getLogger("dbus_service")
14
15 class OnoffControl(dbus.service.Object):
16     domain = "de.subdivi.onoff"
17     path = "/de/subdivi/onoff"
18
19     def __init__(self, bus, num):
20         busname = dbus.service.BusName(self.domain, bus=bus)
21         dbus.service.Object.__init__(self, busname, "%s/%d" % (self.path, num))
22         self.usecount = 0
23         self.curstate = 0 # empty bitmask
24
25     @dbus.service.signal(domain, signature="q")
26     def changestate(self, st):
27         logger.debug("emitting state %d", st)
28         self.curstate = st
29
30     @dbus.service.method(domain, out_signature="q")
31     def state(self):
32         return self.curstate
33
34     @dbus.service.method(domain, in_signature="q", out_signature="q")
35     def activatetime(self, duration):
36         logger.info("activatetime %d", duration)
37         GObject.timeout_add(duration * 1000, self.unuse)
38         return self.use()
39
40     @dbus.service.method(domain, in_signature="hq", out_signature="q")
41     def activatefd(self, fd, duration):
42         fd = fd.take()
43         logger.info("activatefd fd %d, duration %d", (fd, duration))
44         def callback(fd, _):
45             logger.info("fd %d completed", fd)
46             os.close(fd)
47             GObject.timeout_add(duration * 1000, self.unuse)
48             return False
49         GObject.io_add_watch(fd, GObject.IO_HUP|GObject.IO_ERR, callback)
50         return self.use()
51
52     def use(self):
53         self.usecount += 1
54         if self.usecount <= 1:
55             self.changestate(ST_ACTIVE|ST_TRANSITION)
56             def finish():
57                 self.changestate(ST_ACTIVE)
58             GObject.timeout_add(200, finish)
59         return self.curstate
60
61     def unuse(self):
62         self.usecount -= 1
63         if not self.usecount:
64             self.changestate(0)
65         else:
66             logger.debug("%d users left", self.usecount)
67         return False
68
69
70 def main():
71     logging.basicConfig()
72     logging.getLogger().setLevel(logging.DEBUG)
73     DBusGMainLoop(set_as_default=True)
74     bus = dbus.SessionBus()
75     OnoffControl(bus, 5)
76     GObject.MainLoop().run()
77
78 if __name__ == "__main__":
79     main()