Is it possible to sleep until a DBUS property reaches some value?

,

I poll in a loop waiting for the result to switch to true.

 result = g_dbus_connection_call_sync(conn,
                    "org.bluez",  // bus name
                    "/org/bluez/hci0/dev_D4_CA_6E_C3_96_24",  // Location of the remote device in DBUS
                    "org.freedesktop.DBus.Properties",  // interface name
                    "Get",  // method name
                    device1_param, // Parameters for get
                    NULL, // Expected reply type
                    G_DBUS_CALL_FLAGS_NONE,  // Flags
                    10000, // 10 second timeout
                    NULL, // Cancellable
                    &error  // error
    );

What I am waiting for is also indicated by this signal:

 signal time=1659618981.902974 sender=:1.300 -> destination=(null destination) serial=1462 path=/org/bluez/hci0/dev_D4_CA_6E_C3_96_24; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged
   string "org.bluez.Device1"
   array [
      dict entry(
         string "Paired"
         variant             boolean true
      )
   ]
   array [
   ]

I am thinking what I could do is create a message queue when I know boolean to be false. Create a callback when a property has changed that sends a message. Then have my thread that wants to wait for the state change read the message queue. Note that there are multiple devices, which will require multiple message queues, and probably only one callback, that will need to find the correct queue based on the path.

What I would prefer:

  • Sleep only if boolean is false
  • Wake up and proceed if boolean property is true

without the callback and message queue.

You can connect to the PropertiesChanged signal. Here are listed some examples (a few are about NetworkManager):

Not sure if the paired property is tied to a PropertiesChanged signal though, have a look at https://github.com/bluez/bluez/blob/master/doc/device-api.txt

lb90 wrote:

Not sure if the paired property is tied to a PropertiesChanged signal though, have a look at

If you scroll right on the dbus-monitor output in my original message for the signal that occurs, you will see:

member=PropertiesChanged

The dbus-monitor output I captured shows that the signal that I want exists.

Looking at your examples, I believe that none of them wait for a specific PropertiesChanged in a synchronous manner.

So here is an example I found of a callback using g_dbus_signal_subscribe on PropertiesChanged for org.bluez.Adapter1:
PropertiesChanged Example

So I will try creating a message queue and a callback for signals on org.bluez.Device1. I can then wait on the message queue for the callback to send me a message. I don’t see a simpler method.

This function can wait on a g_queue:

g_async_queue_timeout_pop

1 Like

Do you have GLib main loop in your application? With that you can just use the async GDBus API and everything is simpler. You also have cancellation support.

Yes I have a main loop. I do not know what you mean by:

lb90 said:
... you can just use the async GDBus API ...

My knowledge of gio and D-Bus is limited. I just started. I based my program on this example which has a main loop as I wrote before:

BLE Discovery Example

To this I added thread (task) creation using libg for each device path that I am interested in, so there would be one thread in charge of every end point device, each with a unique D-Bus path…

So I would expect each thread will use g_dbus_signal_subscribe to subscribe to changes on the device the thread is handling. If you mean something different, you will need to explain yourself, or point to an example. The purpose of the callback on the signal is to allow the thread doing the work on the device to suspend waiting for pair, and then when the signal occurs, proceed to the next step, and this will require some kind of semaphore, since the signal stuff is based on callbacks, and I think this is best handled by g_queue.

In my mind g_dbus_signal_subscribe() with its callback method is asynchronous. Doing a poll on g_dbus_connection_call_sync() is synchronous, and not efficient. Is that what you mean?

I now have this working.

I realize now that I did not state the right type of queue for my semaphore in previous posts.

The following steps occur in my task (thread) function that maintains the state of my end point GATT device:

GAsyncQueue *state_queue = g_async_queue_new();

Then I passed the queue as a user parameter to my callback function using:
g_dbus_connection_signal_subscribe

I then start my “Pair”:

result = g_dbus_connection_call_sync((GDBusConnection *)conn,
                            "org.bluez",  // bus name
                            object_path,  // Location of the remote device in DBUS
                            "org.bluez.Device1",  // interface name
                            "Pair",  // method name
                            NULL, // No parameters
                            NULL, // Expected reply type
                            G_DBUS_CALL_FLAGS_NONE,  // Flags
                            timeout, // Timeout, What should this be JAK
                            NULL, // Cancellable
                            &error  // error

I can then wait on my callback function after starting the pair operation:
statecomplete = g_async_queue_timeout_pop(state_queue,PAIR_MAX_TIMEOUT);

Now I can do further sequential steps after the pairing.

The callback no doubt occurs in the main loop thread.

The async message queue allows me to maintain my sanity with a thread function that maintains the state machine for my end point device.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.