使用pydbus库通过会话总线发送信号

时间:2016-07-08 12:58:46

标签: python dbus

我正在使用pydbus,我已经成功地使用它来监听会话总线上的信号(在"客户端")。我现在想编写服务器端,程序在每次触发操作时发送信号(例如,当它在FS上写入文件时)。我不能在他们的GitHub上得到任何关于它的例子。他们只展示如何编写一个基本服务器,它有一堆客户端可以调用的方法(但它不是我想要的信号)。

仅供参考,客户端非常简单,看起来像这样:

# Subscribe to DBus dump signal
session_bus = SessionBus()
session_bus.subscribe(iface='my.iface',
                      signal='my_signal_name',
                      object='/my/object',
                      signal_fired=my_callback)

# Create and run main loop
loop = GObject.MainLoop()
loop.run()

其中my_callback是每次被监听事件弹出时调用的方法(在这种情况下为my_signal_name

寻求帮助。

2 个答案:

答案 0 :(得分:2)

以下python3 / pydbus程序将每秒在会话D-Bus上发布一个随机整数。

#!/usr/bin/env python3
#!
from pydbus.generic import signal
from pydbus import SessionBus
from gi.repository import GLib
import random
loop = GLib.MainLoop()
interface_name = "org.example.project_1.server_1"
bus = SessionBus()


class Server_XML(object):
    """
    Server_XML definition.
    Emit / Publish a signal that is a random integer every second 
    type='i' for integer. 
    """
    dbus = """
    <node>
        <interface name="org.example.project_1.server_1">
            <signal name="app_1_signal">
                <arg type='i'/>
            </signal>
        </interface>
    </node>
    """
    app_1_signal = signal()

def repeating_timer():
    """Generate random integer between 0 and 100 and emit over Session D-Bus
    return True to keep the GLib timer calling this function once a second."""
    random_integer = random.randint(0,100)
    print(random_integer)
    emit.app_1_signal(random_integer)
    return True


if __name__=="__main__":
    # Setup server to emit signals over the DBus
    emit = Server_XML()
    bus.publish(interface_name, emit)
    # Setup repeating timer
    GLib.timeout_add_seconds(interval=1, function=repeating_timer) 
    # Run loop with graceful ctrl C exiting.
    try:
        loop.run()
    except KeyboardInterrupt as e:
        loop.quit()
        print("\nExit by Control C")

打开另一个linux控制台终端并使用gdbus实用程序验证会话总线上是否正在发布整数。例如......

$ gdbus monitor --session --dest org.example.project_1.server_1
Monitoring signals from all objects owned by org.example.project_1.server_1
The name org.example.project_1.server_1 is owned by :1.618
/org/example/project_1/server_1: org.example.project_1.server_1.app_1_signal (36,)
/org/example/project_1/server_1: org.example.project_1.server_1.app_1_signal (37,)
/org/example/project_1/server_1: org.example.project_1.server_1.app_1_signal (25,)

以下python3 / pydbus客户端程序订阅在会话D-Bus上发布的随机整数......

#!/usr/bin/env python3
#!
from pydbus.generic import signal
from pydbus import SessionBus
from gi.repository import GLib
loop = GLib.MainLoop()
dbus_filter = "/org/example/project_1/server_1"
bus = SessionBus()


def cb_server_signal_emission(*args):
    """
    Callback on emitting signal from server
    """
    print("Message: ", args)
    print("Data: ", str(args[4][0]))

if __name__=="__main__":
    # Subscribe to bus to monitor for server signal emissions
    bus.subscribe(object = dbus_filter, 
                  signal_fired = cb_server_signal_emission)    
    loop.run()

此客户端程序的控制台输出将类似于此...

$ python3 client_pydbus.py
Message:  (':1.621', '/org/example/project_1/server_1', 'org.example.project_1.server_1', 'app_1_signal', (72,))
Data:  72
Message:  (':1.621', '/org/example/project_1/server_1', 'org.example.project_1.server_1', 'app_1_signal', (46,))
Data:  46
Message:  (':1.621', '/org/example/project_1/server_1', 'org.example.project_1.server_1', 'app_1_signal', (47,))
Data:  47

答案 1 :(得分:0)

负责信号的类位于generic模块中。它看起来很好,记录在案:

Static signal object

You're expected to set it as a class property::

    class A:
        SomethingHappened = signal()

Declared this way, it can be used on class instances
to connect signal observers::

    a = A()
    a.SomethingHappened.connect(func)

and emit the signal::

    a.SomethingHappened()

You may pass any parameters to the emiting function
- they will be forwarded to all subscribed callbacks.

还有example in the tutorial使用信号。请注意最后一行和属性SomeProperty。当在setter中更改python属性SomeProperty时,信号将通过self.PropertiesChanged("net.lew21.pydbus.TutorialExample", {"SomeProperty": self.SomeProperty}, [])发出。

from pydbus.generic import signal

class Example(object):
  """
    <node>
      <interface name='net.lew21.pydbus.TutorialExample'>
        <method name='EchoString'>
          <arg type='s' name='a' direction='in'/>
          <arg type='s' name='response' direction='out'/>
        </method>
        <property name="SomeProperty" type="s" access="readwrite">
          <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
        </property>
      </interface>
    </node>
  """

  def EchoString(self, s):
    """returns whatever is passed to it"""
    return s

  def __init__(self):
    self._someProperty = "initial value"

  @property
  def SomeProperty(self):
    return self._someProperty

  @SomeProperty.setter
  def SomeProperty(self, value):
    self._someProperty = value
    self.PropertiesChanged("net.lew21.pydbus.TutorialExample", {"SomeProperty": self.SomeProperty}, [])

  PropertiesChanged = signal()

还有notification_server example使用信号(但未调用)。