Open nschoe opened 8 years ago
this definitely needs more documentation :(
can you post some of your code?
As far as I can remember, first element in array is signature for all input arguments and second element is result signature. So Notify
handler and interface description might look like this (have not tested yet)
var iface = {
//... other methods
Notify: ['susssasa{sv}i', 'u' ]
//... other methods
};
var NotifyService = {
Notify: function(app_name, replaces_id, app_icon, summary, body, actions, hints, expire_timeout) {
//
return 12345; // out id
}
}
// export
Would be really helpful to have a tool to generate this from xml interface ( there is one for client side bot not for service - https://github.com/sidorares/node-dbus/blob/master/bin/dbus2js.js )
@sidorares thanks for answering this fast.
The problem I currently have is not for Notify
because it returns only one value. My problem is for GetServerInformation
which should return 4 strings. I don't understand how to achieve this.
I had this:
var notificationIface = {
name: name,
methods: {
Notify: [['s', 'u', 's', 's', 'as', 'a{sv}', 'i'], 'u'],
GetServerInformation: [[],['s', 's', 's', 's]]
},
signals: {
},
properties: {
}
};
var notification = {
Notify: function (app_name, replaces_id, app_icon, summary, body, actions, hints, expire_timeout) {
return 12345;
},
GetServerInformation: function () {
return ['Awesome Notification Server', 'example.org', '0.1', '1.2'];
}
};
And I got error:
Error: message body does not match message signature. Body:[["Awesome Notification Server","partnering.org","0.1","1.2"]], signature:s,s,s,s
Note: it did recognize signature as 4 strings: s,s,s,s
Then I tried to change GetServerInformation: [[],['s', 's', 's', 's]]
to GetServerInformation: [[],'ssss']
And I got this time:
Error: message body does not match message signature. Body:[["Awesome Notification Server","partnering.org","0.1","1.2"]], signature:ssss
Note: this time, it said output was ssss
, not s,s,s,s
.
Anyway, this did not change: I still can't get GetServerInformation
to return those 4 strings :/
Any idea?
Can you console.log
full message you receive when you invoke GetServerInformation
? You could put something like console.log(msg)
here - https://github.com/sidorares/node-dbus/blob/master/lib/bus.js#L99
Basically function call is always two messages regardless of number of arguments: caller->service: message with call id, method name, iface name, object name, args signature + body if non empty. service->caller: response id = call id, response signature + body if non empty.
So here is the full msg
object I receive:
{ serial: 6,
signature: '',
path: '/org/freedesktop/Notifications',
member: 'GetServerInformation',
interface: 'org.freedesktop.Notifications',
destination: ':1.269',
sender: ':1.270',
type: 1,
flags: 0 }
As for your latest message, yes I think I got the dbus mechanism (albeit, still a bit new). What I don't know, is how the binding here handles response body.
In my function getServerInformation
, how should I return the 4 strings?
Currently I do return ['str1', 'str2', 'str3', 'str4']
.
Okay there is something weird... While checking my code, there seems to be a difference on this line: https://github.com/sidorares/node-dbus/blob/master/lib/bus.js#L180
Here, on my local machine, I have reply.body = [result];
instead of reply.body = result;
which explains the fact that in the error messages, there is always a pair of brackets.
I do not understand how these brackets got here, and even worse: they don't appear on git diff
. Anyway, I remove it, now I've got a different error:
Error: Expected string or buffer argument, got ["s","s","s","s"] of type 'g'
What does this mean?
looks like it's a problem with the library.
Here I wrap result with extra [], assuming that there are only 1 value:
https://github.com/sidorares/node-dbus/blob/master/lib/bus.js#L152
And here body is set as is to the value you return from handler:
https://github.com/sidorares/node-dbus/blob/master/lib/bus.js#L180
As a work around you might use second approach, e.i use setMethodCallHandler
instead of exportInterface
.
you beat me :)
@sidorares OMg I understand why I made the confusion: when I checked your code, it was line 180. I then checked my code on line 180 and it was the same line, without the brackets.
Actually, for debugging purpose, I had added comments and these matched EXACTLY to line 180.
But the truth is: I had the same version.
So what should I do? You suggest I don't use exportInterface
? But then how do I "export" the interface? How do I implement this Notifications interface?
Thanks for your reactivity!
There is a lot of confusion when people interpret signature values depending on what you need. In general, signature is always a struct (but maybe with one element):
s -> [ 'string' ]
ss -> [ 'string1', 'string2' ]
Yes, I have been browsing all issued (opened and closed) and I saw that this was something of a recurrent problem. So I tried, but if GetServerInformation
, if I return [['str1', 'str2', 'str3', 'str4']];
(with extra bracket) instead of return ['str1', 'str2', 'str3', 'str4'];
.
It doesn't change a thing: the error message is the same, with one extra bracket:
Error: message body does not match message signature. Body:[[['str1', 'str2', 'str3', 'str4']]], signature:s,s,s,s
What's the correct syntax, in the body of GetServerInformation()
to return those for strings? Should I return a structure? If yes, what's the form?
I'm a bit lost :-)
you can use setMethodCallHandler
- https://github.com/sidorares/node-dbus/blob/master/lib/bus.js#L190 It allows you to set handlers one by one, not the whole interface
I'll need to think a good way of handling results which is backwards compatible and not unexpected.
Proposed solution: if result signature is single element struct, wrap it into struct ( example: interface is 's' and you would return 'string';
. If not, don't wrap ( interface is 'ssi' and you return ['test', 'foo', 42];
)
as I mentioned, setMethodCallHandler
behaviour re return value is different from exportInterface
( which is bad ;( ). First one serialises what you return as is ( so if the result is single value you need to wrap as a struct - return [123];
for 'i' handler )
@sidorares Okay, I will try to setMethodCallHandler
. But if I do that, the interface won't be properly implemented, will it?
(I will try this of course).
Does it work if I first use exportInterface
and then, call setMethodCallHandler
, just on the function(s) for which it is necessary?
interface won't be properly implemented
form "handling" point of view this is identical, I have to look more closely at the code to check if introspection is generated correctly for setMethodCallHandler
methods
yes, you should be able to mix them
@sidorares I've tried to use setMethodCallHandler
but I cannot get it to work.
I've looked at the function's type signature, and the iface
parameters seems unclear, so I tried to set it to:
But neither works, every time, when I call the GetServerInformation
, I get error
console.log ('\nfunc.type: ' + func.type);
TypeError: Cannot read property 'type' of undefined
Besides, in the bus.js
file, I display the content of iface[1]
, which normally contains the functions implementation (in my case, Notify
and GetServerInformation
) ,but this time, I only get Notify
.
So either setMethodCallHandler
doesn't work as intended, or maybe I'm missing a step :-)
Any idea?
Thanks for your support!
Okay, so I've scouted through the code, and compared when you call mangle()
on msg
, it seems that, for calling setMethodCallHandler
, the iface
should be the name of the interface, so org.freedesktop.Notifications
.
I re-tried that, but then, when calling the GetServerInformation
method, it fails with TypeError: Cannot read property 'type' of undefined
when I try to display func
.
@sidorares any news regarding the problem?
@sidorares for information, when I use the setMethodCallHandler
and then later try to call the said function, I fall into this condition
, which means that func
is null
, which means it doesn't have the method.
It seems normal to me, because when calling setMethodCallHandler
it simply adds the key to the methodCallHandlers
array as shown here, but nowhere is this array checked when calling a function. So I wonder if I am missing something or if you simply forgot to check this array ?
Currently trying to implement
org.freedesktop.Notifications
.Inspecting by hand :
gdbus introspect --session --dest org.freedesktop.Notifications --object-path /org/freedesktop/Notifications
returns:So first step is to implement
GetServerInformation
. It has type:out s, out s, out s, out s
.From examples in
examples/
I first thought that the method's type was defined as an array, with the last item being the return type and the N-1 first were input. But this can't be right because dbus obviously can return several values and because in/lib.bus.js:144
(see here) theresultSignature
is hardcoded as element[1]
of the array.So I deduced that the correct format for method's type is
[[array of input args], [array of output args]]
, smth like[['i', 'i'], ['s', 's', 's']]
for a function that takes 2 integers as input and outputs 3 strings.For the
GetServerInformation
method above, which takes no input but returns 4 strings, so I set the return type as:[[],['s', 's', 's', 's']]
.Now it seems to work, because when I try to return an integer (5), I've got this error:
We can see here that it complains because I try to return just
5
, where the expected return type iss,s,s,s
.Now the question is: how can I actually return
s,s,s,s
?In the body of my function, I have first tried:
return ['str1', 'str2', 'str3', 'str4'];
But I got error:
So it seems that the return arguments are "wrapped" in an array, but I don't know how to 'flatten' that array.
Is this an error in the library or am I misusing it? (In this case, it would be good to provide additional examples of a more complex use of the library, as of now, the three examples in
examples/service/server2.js
only shows examples of functions that take one argument and return one value.