death / dbus

A D-BUS client library for Common Lisp
BSD 2-Clause "Simplified" License
45 stars 29 forks source link

Not able to set property which is array of dicts #20

Closed rfolland closed 5 years ago

rfolland commented 5 years ago

I try to communicate with wpa_supplicant via dbus. I can set and get properties as long as they are not arrays of dicts of values. I noticed that dbus-send is not able to do this either.

When I try setting a value which is to be in a dict the call hangs. Perhaps I am missing something?

The dbus api for wpa_supplicant is documented here: https://w1.fi/wpa_supplicant/devel/dbus.html#dbus_p2pdevice

Of the following defuns the first three work, the last one hangs:

(defun wpa-get-go-intent ()
  (let ((path (first (wpa-get-interfaces))))
    (dbus:with-open-bus (bus (dbus:system-server-addresses))
      (dbus:with-introspected-object (dev
                                      bus
                                      path
                                      "fi.w1.wpa_supplicant1")
        (dev "org.freedesktop.DBus.Properties" "Get"
             "fi.w1.wpa_supplicant1.Interface"
             "P2pGoIntent")))))

(defun wpa-set-go-intent (level)
  (let ((path (first (wpa-get-interfaces))))
    (dbus:with-open-bus (bus (dbus:system-server-addresses))
      (dbus:with-introspected-object (dev
                                      bus
                                      path
                                      "fi.w1.wpa_supplicant1")
        (dev "org.freedesktop.DBus.Properties" "Set"
             "fi.w1.wpa_supplicant1.Interface"
             "P2pGoIntent" `((:string) ,(write-to-string level)))))))

(defun wpa-get-p2p-device-config ()
  (let ((path (first (wpa-get-interfaces))))
    (dbus:with-open-bus (bus (dbus:system-server-addresses))
      (dbus:with-introspected-object (dev
                                      bus
                                      path
                                      "fi.w1.wpa_supplicant1")
        (dev "org.freedesktop.DBus.Properties" "Get"
             "fi.w1.wpa_supplicant1.Interface.P2PDevice"
             "P2PDeviceConfig")))))

(defun wpa-set-p2p-go-intent (level)
  (let ((path (first (wpa-get-interfaces))))
    (dbus:with-open-bus (bus (dbus:system-server-addresses))
      (dbus:with-introspected-object (dev
                                      bus
                                      path
                                      "fi.w1.wpa_supplicant1")
        (dev "org.freedesktop.DBus.Properties" "Set"
             "fi.w1.wpa_supplicant1.Interface.P2PDevice"
             "P2PDeviceConfig" `((:string :uint32) "GOIntent" ,level))))))
death commented 5 years ago

Just a guess, but the linked page says P2PDeviceConfig has type of a{sv} so it needs to be an array of dict entries, each of which has string key and variant value. This is passed to Set as a variant:

(flexi-streams:with-output-to-sequence (out)
  (dbus:pack out
             :little-endian
             "v"
             '(((:array (:dict-entry :string :variant))) (("GOIntent" ((:uint32) 42))))))
rfolland commented 5 years ago

Very nice. That worked. Thank you very much!