initial commit
authorHelmut Grohne <helmut@subdivi.de>
Sun, 16 Jun 2013 10:32:08 +0000 (12:32 +0200)
committerHelmut Grohne <helmut@subdivi.de>
Sun, 16 Jun 2013 10:32:08 +0000 (12:32 +0200)
Proof-of-concept for the dbus interaction of the onoff service.

.gitignore [new file with mode: 0644]
dbus_client.py [new file with mode: 0755]
dbus_service.py [new file with mode: 0755]
onoff/__init__.py [new file with mode: 0644]
onoff/common.py [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..539da74
--- /dev/null
@@ -0,0 +1 @@
+*.py[co]
diff --git a/dbus_client.py b/dbus_client.py
new file mode 100755 (executable)
index 0000000..a1f1041
--- /dev/null
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+
+import os
+import socket
+import sys
+
+import dbus
+from dbus.mainloop.glib import DBusGMainLoop
+import gobject
+
+from onoff.common import ST_ACTIVE
+
+def wait_for_signal(proxy, signal):
+    loop = gobject.MainLoop()
+    state = []
+    def callback(st):
+        state.append(st)
+        loop.quit()
+    proxy.connect_to_signal(signal, callback)
+    loop.run()
+    return state[0]
+
+def main():
+    s1, s2 = socket.socketpair()
+    DBusGMainLoop(set_as_default=True)
+    bus = dbus.SessionBus()
+    proxy = bus.get_object("de.subdivi.onoff", "/de/subdivi/onoff/5")
+    if len(sys.argv) > 1:
+        st = proxy.activatefd(dbus.types.UnixFd(s1), 10)
+        s1.close()
+        os.dup2(s2.fileno(), 254)
+        s2.close()
+        if st != ST_ACTIVE:
+            print("state is %d waiting for signal" % st)
+            st = wait_for_signal(proxy, "state")
+            print("new state is %d" % st)
+        os.execvp(sys.argv[1], sys.argv[1:])
+    else:
+        st = proxy.activatetime(10)
+        if st != ST_ACTIVE:
+            print("state is %d waiting for signal" % st)
+            st = wait_for_signal(proxy, "state")
+            print("new state is %d" % st)
+
+if __name__ == "__main__":
+    main()
diff --git a/dbus_service.py b/dbus_service.py
new file mode 100755 (executable)
index 0000000..7fbdf29
--- /dev/null
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+
+import os
+
+import dbus
+import dbus.service
+from dbus.mainloop.glib import DBusGMainLoop
+import gobject
+
+from onoff.common import ST_ACTIVE, ST_TRANSITION
+
+class OnoffControl(dbus.service.Object):
+    domain = "de.subdivi.onoff"
+    path = "/de/subdivi/onoff"
+
+    def __init__(self, bus, num):
+        busname = dbus.service.BusName(self.domain, bus=bus)
+        dbus.service.Object.__init__(self, busname, "%s/%d" % (self.path, num))
+        self.usecount = 0
+        self.curstate = 0 # empty bitmask
+
+    @dbus.service.signal(domain, signature="q")
+    def state(self, st):
+        print("emitting state %d" % st)
+        self.curstate = st
+
+    @dbus.service.method(domain, in_signature="q", out_signature="q")
+    def activatetime(self, duration):
+        print("called with duration %d" % duration)
+        self.usecount += 1
+        gobject.timeout_add(duration * 1000, self.unuse)
+        if self.usecount > 1:
+            return self.curstate
+        self.state(ST_TRANSITION)
+        def finish():
+            self.state(ST_ACTIVE)
+        gobject.timeout_add(200, finish)
+        return self.curstate
+
+    @dbus.service.method(domain, in_signature="hq", out_signature="q")
+    def activatefd(self, fd, duration):
+        self.usecount += 1
+        fd = fd.take()
+        print("called with fd %d and duration %d" % (fd, duration))
+        def callback(fd, _):
+            print("fd %d completed" % fd)
+            os.close(fd)
+            gobject.timeout_add(duration * 1000, self.unuse)
+            return False
+        gobject.io_add_watch(fd, gobject.IO_HUP|gobject.IO_ERR, callback)
+        self.state(ST_ACTIVE)
+        return self.curstate
+
+    def unuse(self):
+        self.usecount -= 1
+        if not self.usecount:
+            self.state(0)
+        else:
+            print("%d users left" % self.usecount)
+        return False
+
+
+def main():
+    DBusGMainLoop(set_as_default=True)
+    bus = dbus.SessionBus()
+    OnoffControl(bus, 5)
+    gobject.MainLoop().run()
+
+if __name__ == "__main__":
+    main()
diff --git a/onoff/__init__.py b/onoff/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/onoff/common.py b/onoff/common.py
new file mode 100644 (file)
index 0000000..26e32bf
--- /dev/null
@@ -0,0 +1,10 @@
+"""
+Defined states:
+ * 0: The device is inactive.
+ * ST_TRANSITION: The device is transitioning from inactive to active.
+ * ST_ACTIVE: The device is active.
+ * ST_ACTIVE|ST_TRANSITION: The device is transitioning from active to inactive.
+"""
+
+ST_ACTIVE = 1
+ST_TRANSITION = 2