I have a D-Bus method that receives as input a dictionary that maps strings to structures:
<method name="myMethod">
<arg name="input_dict" type="a{s(ss)}" direction="in"/>
...
</method>
I have tried to invoke such method using busctl without success. So far I've tried using the following arguments:
busctl call ${SERVICE} ${OBJECT} ${INTERFACE} myMethod "a{s(ss)}" 1 "str1" \( "str2" "str3" \)
busctl call ${SERVICE} ${OBJECT} ${INTERFACE} myMethod "a{s(ss)}" 1 str1 str2 str3
busctl call ${SERVICE} ${OBJECT} ${INTERFACE} myMethod "a{s(ss)}" str1 str2 str3
busctl call ${SERVICE} ${OBJECT} ${INTERFACE} myMethod "a{s(ss)}" 1 str1 '(ss)' str2 str3
busctl call ${SERVICE} ${OBJECT} ${INTERFACE} myMethod "a{s(ss)}" 1 str1 \(ss\) str2 str3
busctl call ${SERVICE} ${OBJECT} ${INTERFACE} myMethod "a{s(ss)}" 1 str1 "ss" str2 str3
busctl call ${SERVICE} ${OBJECT} ${INTERFACE} myMethod "a{s(ss)}" 1 str1 \"ss\" str2 str3
busctl call ${SERVICE} ${OBJECT} ${INTERFACE} myMethod "a{s(ss)}" 1 str1 \(str2 str3\)
busctl call ${SERVICE} ${OBJECT} ${INTERFACE} myMethod "a{s(ss)}" 1 str1 \(ss\) \(str2 str3\)
Depending on the call, I'm getting different errors:
No such method 'WakeUp' in interface 'com.verisure.cuxscored.DECT' at object path '/com/verisure/cuxscored/dect' (signature 'a{s(ss)}')
Too many parameters for signature.
Therefore, my question is: How can I pass the arguments to myMethod when using busctl?
EDIT
Thanks to ukBaz's answer, I got an insight. I have available a getter method as well, which I invoke previously, and I get a result a little bit different than ukBaz's:
<method name="myGetMethod">
<arg name="output_dict" type="a{s(ss)}" direction="out"/>
...
</method>
Running the busctl command it gave me this:
a(s(ss)) 1 "str1" "str2" "str3"
Notice the difference with the expected solution (a(s(ss))
instead of a{s(ss)}
, parentheses instead of braces). If I got it right, the output should then be interpreted as an array of structures which contain a string, and another structure with two strings.
I'm not quite sure why the result is different, but I have kind of overcome the problem using the output of the getter straight away as input of the other method:
busctl call ${SERVICE} ${OBJECT} ${INTERFACE} myMethod `busctl call ${SERVICE} ${OBJECT} ${INTERFACE} myGetMethod`
Likewise, if I use the output of the myGetMethod 'as is', the method also works:
busctl call ${SERVICE} ${OBJECT} ${INTERFACE} myMethod "a(s(ss))" 1 "str1" "str2" "str3"
So the only question remaining would be why the D-bus method returns an array of structs even when it is declared as returning a dictionary.
EDIT 2
If I run dbusctl introspect, this is what I get:
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
${INTERFACE} interface - - -
.myGetMethod method - a{s(ss)} -
.myMethod method a{s(ss)} - -
...
As an aside question, I have also tried using D-Feet, with no better result. I've called a method that returns a value of type a{s(ss)}, and D-Feet returns the following structure:
[('str1', ('str2', 'str3'))]
If I then call myMethod on D-Feet using that very same structure, I got a DBus.Error.UnknownMethod:
No '
"such method 'myMethod' in interface '${INTERFACE}' at object "
"path '${OBJECT}' (signature 'a{s(ss)}') (19)")
However, if I play around with the arguments, braces and so on, I got different error messages, but I'm not able to get the method properly working. So, what's the appropriate way of passing this kind of argument to myMethod when using D-Feet?
I created myself a DBus service with that signature to test this:
Which in
busctl
introspection gave:The result output from
Echo
was:I used that output to workout how to put the values in:
Which gave the correct output from my Python script:
So I don't know why your second attempt didn't work
And for completeness, here is an example sending two values in the dictionary: