altdesktop / python-dbus-next

🚌 The next great DBus library for Python with asyncio support
https://python-dbus-next.readthedocs.io/en/latest/
MIT License
187 stars 58 forks source link

Receive signal example #133

Closed ghost closed 1 year ago

ghost commented 1 year ago

Is there a short, complete minimal fully functional example showing how to receive a signal?

We spent over two hours trying to figure out how to use the python-dbus-next library to receive a signal. The signal written to D-Bus resembles:

signal time=1660596961.842377 sender=:1.345165 -> destination=(null destination) serial=69 path=/path/to/alarm/1; interface=com.company.package.AlarmInterface; member=AlarmSignal
   string "2fc08a9e..."
   string "moduleType"
   boolean false
   byte 255

In both Java and C, the solution is fairly trivial and there are numerous complete examples that show how to receive a signal.

Ideally, we'd like to:

  1. Read the example code.
  2. Copy the example code into a new source file.
  3. Modify the example to target a remote D-Bus session over TCP/IP.
  4. Have a handler print out every message published on the D-Bus.

In pseudo-python (replace with async code where appropriate):

def handler( message ):
  print( "Received message!" )
  print( message.get('uuid') )
  print( message.get('moduleType') )

# Reads from DBUS_SESSION_DBUS_ADDRESS to establish connection
# Connects as anonymous by default
bus = MessageBus().connect()
bus.addSignalHandler(
  path="/path/to/alarm/1",
  iface="com.company.package.AlarmInterface",
  member="AlarmSignal",
  types="ssby",
  names="uuid, moduleType, active, slotAddress",
  handler )

bus.run()

Save as example.py, then run as:

export DBUS_SESSION_BUS_ADDRESS=tcp:host=localhost,port=55000,family=ipv4
python3 example.py
elParaguayo commented 1 year ago

Signal handling is already built-in. See the example below which should point you in the right direction:

from dbus_next.aio import MessageBus
from dbus_next import Variant

def handler(uuid, moduleType, active, slotAddress):
    print("Received message!")
    print(uuid)
    print(moduleType)

bus = await MessageBus().connect()

introspection = await bus.introspect('com.company.package', '/path/to/alarm/1')

proxy_object = bus.get_proxy_object('com.company.package', '/path/to/alarm/1', introspection)

interface = proxy_object.get_interface('com.company.package.AlarmInterface')

interface.on_alarm_signal(handler)  # syntax is 'on_' plus signal name in snake case.

NB I've done this using the asyncio version of the library.