Node dbus-native - node.js

The documentation for node module dbus-native is weak, and the none of the many examples apply to my use case, which seems like it ought to be simple.
My problem is trying to make a simple method call into the "connman" network manager. I can make a request (invoking GetProperties method) just fine, and get a complex structure back and generally figure out how to get data out of it. But when I try to send something back with SetProperty, I just can't figure out how to get my data into the form it wants.
There's not really any documentation about how to translate to and from DBus's type system and node's. I gathered from source that variant types are arrays with signature and value, e.g., [ 's', 'string ], but no matter how I try to massage the data I'm trying to send to SetProperty, I get an "Invalid struct data" error.
The SetProperty method I'm trying to call has an argument signature "sv"--name, value. The particular property I'm trying to set has a value with is itself (as far as I can determine--there's precious little documentation on that side as well) an "a{sv}". that is,property is a hash of property names and values. My initial attempt as calling this function was:
var sysbus = require('dbus-native').systemBus();
sysbus.invoke({
path: '/net/connman/service/ethernet_1cba8cfa0e57_cable',
destination: 'net.connman',
'interface': 'net.connman.Service',
member: 'SetPropertry',
signature: 'sv',
body: [
'IPv4.Configuration', [
'a{sv}',
{ 'Method': [ 's', 'dhcp' ] }
]
],
type: dbus.messageType.methodCall
}, function (err, res) {
// etc...
});
This gives me the "Invalid struct data" error. I've tried man other ways to wrap the data in arrays, hashes, etc., and just can't seem to find the right answer. I'm trying to emulate this working Python code:
import dbus
bus = dbus.SystemBus()
service = dbus.Interface(bus.get_object("net.connman",
"/net/connman/service/ethernet_1cba8cfa0e57_cable",
"net.connman.Service");
conf = { "Method": make_string_variant("dhcp") }
service.SetProperty("IPv4.Configuration", conf);
Any ideas?

I recently started using dbus-native for connman and also had problems with all the nested arrays. I'll be improving the marshaling/unmarshaling in the fork of the project at https://github.com/Digisoft-tv/node-dbus - you might want to have a look. Hopefully my changes will be accepted up-stream.
Anyway, to get it working now, the format of the parameters you need to pass in is as below:
mgr.CreateSession([ [ 'key', [ 's', 'value' ] ], [ 'key2', [ 'i', 2 ] ] ], '/object/path', function(error, response) {
if (error) {
return console.error('SetProperty error:', error);
}
console.info('SetProperty response', response);
});
The outermost array is the "object" (ARRAY of dict entries).
Each nested array holds a key-value pair (DICT ENTRY). key at index 0 and value at index 1.
The values is a variant, which is always encoded as an array, with "signature" at index 0 and the actual value at index 1.
Hope it helps.

The correct way to encode 'a{sv}' is [ ['string', ['signature', 'value']], ... ]
Arrays ( a ) are encoded as normal JS arrays as well as structs / hashes ( () / {} ). I'll probably add shortcut to allow JS object to be used in place of a{sv} but at the moment input has to be quite verbose.
var sysbus = require('dbus-native').systemBus();
sysbus.invoke({
path: '/net/connman/service/ethernet_1cba8cfa0e57_cable',
destination: 'net.connman',
'interface': 'net.connman.Service',
member: 'SetPropertry',
signature: 'sv',
body: [
'IPv4.Configuration', [
'a{sv}',
[ // a
[ // {
'Method', [ 's', 'dhcp' ] // sv
]
]
]
],
type: dbus.messageType.methodCall
}, function (err, res) {
// etc...
});

Related

Faunadb how do I paginate an index sorted by Timestamp

I created an index on faunadb to sort by the time stamp in order to get the most recent items first, and I am trying to retrieve 100 items at a time. My problem is that when I enter the "after" parameter from the result, I receive the same results as the initial query.
This is the index I created:
CreateIndex({
name: "all_school_queries",
source: Collection('<school_queries_reversed>'),
values: values: [
{
field: ["ts", {reverse: true}]
},
{
field: ["ref"]
}
]
})
This is how I am querying the database:
Map(
Paginate(Match(Index("school_query_reverse")), {
after: [ Ref(Collection("collection_name") ,'collection ref from first query')],
}),
Lambda(
['ts',"ref"],
Get(Var("ref"))
)
)
and this is the first result:
{
before: [Ref(Collection("collection_name"), "275484304279077376")],
after: [
1598907150720000,
Ref(Collection("school_queries"), "12345"),
Ref(Collection("school_queries"), "12345")
],
}
I have used both the timestamp for the after, 1598907150720000 and the ref, 12345. I tried the console first to make sure I could get the right response, but upon entering the either result from the after, I get the same result.
I'll try to answer your question (I'm the dev adv at FaunaDB). I have to say that I'm quite confused by your question due to syntax that doesn't seem to make sense to me, so I apologize if it's not the answer you are looking for.
Things that I'm confused by.
The index syntax is wrong, did you copy this somewhere or did you rewrite this manually? If you copied it somewhere then we might display it wrongly so do let me know if that's the case. The index name does not match the name you are using so I assume this is a typo.
<school_queries_reversed>, reversed in the collection name doesn't seem to make sense to me since reverse is defined on the index, not on the collection.
Doesn't matter though, I tried to reproduce your issue, since I don't have an idea how the data looks I kept it simple.
The index I used looks as follows:
CreateIndex({
name: "all_school_queries",
source: Collection('school_queries'),
values: [
{
field: ["ts"],
reverse: true
},
{
field: ["ref"]
}
]
})
If I then query this index as follows:
Map(
Paginate(Match(Index("all_school_queries")), {size: 1}),
Lambda(
['ts',"ref"],
Get(Var("ref"))
)
)
I do get the last element I added first (reverse index)
{
after: [
1599220462170000,
Ref(Collection("school_queries"), "275735235372515847"),
Ref(Collection("school_queries"), "275735235372515847")
],
data: [
{
ref: Ref(Collection("school_queries"), "275735244842205703"),
ts: 1599220471200000,
data: {
query: "bli"
}
}
]
}
and when I use the returned after cursor to get the next page (I have specified pages of only one element here):
Map(
Paginate(Match(Index("all_school_queries")), {size: 1, after: [
1599220462170000,
Ref(Collection("school_queries"), "275735235372515847"),
Ref(Collection("school_queries"), "275735235372515847")
]}),
Lambda(
['ts',"ref"],
Get(Var("ref"))
)
)
I do get (as expected) the other element.
{
before: [
1599220462170000,
Ref(Collection("school_queries"), "275735235372515847"),
Ref(Collection("school_queries"), "275735235372515847")
],
data: [
{
ref: Ref(Collection("school_queries"), "275735235372515847"),
ts: 1599220462170000,
data: {
query: "bla"
}
}
]
}
Is that not working for you?
I had the same problem and created a forum post on how to deal with it.
https://forums.fauna.com/t/filter-by-timestamp-with-gql-resolver/3302
I guess most people are missing
paginated: true in the gql schema or
Map(Var("page"), Lambda(["ts", "ref"], Get(Var("ref")))) to pass ["ts", "ref"] to the lambda after pagination

Why is the JSON output different from the actual output as rendered in the browser? [duplicate]

I have a problem with logging out the contents of an array inside an object. The actual object looks like this
var stuff = { accepted: [ 'item1', 'item2' ],
rejected: [],
response: 'Foo',
envelope: { from: 'The sender', to: ['new item1', 'new item2'] },
messageId: 'xxxxxxxxxxxxx' } }
The console.log shows the items of the first array fine but the second array is being output as [Object].
{ accepted: [ 'item1', 'item2' ],
rejected: [],
response: 'Foo',
envelope: { from: 'The sender', to: [Object] },
messageId: 'xxxxxxxxxxxxx' } }
What is happening here and how can I get the items of the second array to show when I console.log. Thanks for any help!
UPDATE
Sorry, I forgot to add that I am working exclusively in Node.js so it's a server side log that needs to display the object exactly as it's received from a callback with a straight console.log, ie. no further stringify-ing.
I also just tried creating another random object with a similar structure like this.
var objText = {
fun: {
stuff: 'Some stuff',
list: ['this', 'it', 'takes']
}
};
The console.log for the above is:
{ fun: { stuff: 'Some stuff', list: [ 'this', 'it', 'takes' ] } }
This appears to be the same structure to me and yet the console.log works fine so it seems to be perfectly possible in Node to log arrays content even when it's embedded inside and an object inside an outer object.
It looks like this is an old topic, anyway
I've faced the same issue, embedded array printed as [Array].
It is because of console.log in the node.js uses util.inspect for print, the default depth is 2.
So, to print something which is deeper than 2 followings can be used:
const util = require('util')
console.log(util.inspect(errors, true, 10))
This is the default way for some browser and implementations of showing too complex or deep objects/arrays with console.log. An alternative is to use JSON.stringify with console.log:
var stuff = {
accepted: ['item1', 'item2'],
rejected: [],
response: 'Foo',
envelope: {
from: 'The sender',
to: ['new item1', 'new item2']
},
messageId: 'xxxxxxxxxxxxx'
}
console.log(JSON.stringify(stuff, null, 4));
EDIT:
Another alternative is to use console.dir in case you have a too complex or recursive object, see https://stackoverflow.com/a/27534731/6051261
Try it with: console.log(JSON.stringify(variable))
If you like Chrome devtools, that folds your json objects and let you observe a lot of things, you can use the --inspect flag:
node --inspect index.js
The console will then give you an URL and you just have to copy paste in Google Chrome to enjoy Google Chrome console.
More information on this link

Why steam web api returns undefined json value node js

Hello these code does request to Steam Web API
const request = require("request");
request({
url: "https://api.steampowered.com/IEconService/GetTradeOffers/v1/?key=MYAPIKEY&get_sent_offers=1&active_only=1&format=json",
json: true
}, (err, responser, body) => {
console.log(body.response['trade_offers_sent']);
});
And this is what it returns:
{
trade_offers_sent: [
{
tradeofferid: '3974708687',
accountid_other: 82613664,
message: 'test message',
expiration_time: 1587017229,
trade_offer_state: 9,
items_to_give: [Array],
is_our_offer: true,
time_created: 1585807629,
time_updated: 1585807629,
from_real_time_trade: false,
escrow_end_date: 0,
confirmation_method: 2
}
]
}
But when i'm trying to get value of accountid_other this way:
console.log(body.response['trade_offers_sent'].accountid_other);
it returns undefined
The square brackets [ ... ] within trade_offers_sent indicate that it holds an array and not just a single item (it just happens to be a single item in the array). Thus to obtain you value you are interested in you need to specify the index of the item you want or use a loop to go through it. In this case you want the first item and you can use ['trade_offers_sent'][0] to obtain it.

aws-sdk javascript filter on tag:key=value

Folks,
I am having difficult time understanding the docs http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/frames.html
I need to grab all the running instances with the following tags assigned to them:
project=foo
environment=production
The following does not seem to work.
var params = {
DryRun: false,
Filters: [
{
Name: 'instance-state-name',
Values: [
'running'
],
},
{
Name: 'tag:key=value',
Values: [
'foo',
'production'
],
},
]
};
ec2.describeInstances(params, function (err, data) {
...
If your tag's key is 'foo' and its value is 'production', you should change your code to the following. The Name is in the 'tag:key' format, and the Values are the data you are looking for that correspond to that key.
{
Name: 'tag:foo',
Values: [
'production'
],
},
This is slightly related, and may help anyone who found there way here like I did.
I was trying check if an Instance with a tag Name=myInstance, was running in my aws account.
It's pretty difficult to check existence of resources in aws, but clairestreb's answer led me to the work around for this case.
I've begun developing a library of other such work arounds, and with it you can now do this:
Find Running Instance with tag Name=myInstance
var ex = require('aws-existence')
var ec2 = ex.ec2({region: 'us-west-2'})
ec2.doesInstanceExist('myInstance', 'running')
.then(doSomething)
function doSomething (exists) {
if (exists) {
// stop it?
} else {
// start it?
}
}
So that's doesInstanceExist(identifier, instanceState) where the identifier is a name tag, or an InstanceId. And state is optionally any one of the instance-state-name values. If you omit the state, it will tell you if an instance in any of the states exists.
You can find the library here:
nackjicholson/aws-existence

Node.js - Send and receive Array as GET/POST using querystring

I've got the following code, but it doesn't seem to work:
var post_req = {
array: [
[ {
param1: 'something',
param2: 123
} ],
[ ],
[ ],
[ {
param2: 'something',
param4: 1234,
param1: 'hello'
} ]
]
};
var data_send = querystring.stringify(post_req);
var request = client.request('POST', '/', headers);
request.end(data_send);
and
if( req.method == 'POST' ) {
req.addListener('data', function(chunk)
{
POST = querystring.parse(chunk);
console.log(POST);
}
}
I end up with 5 sub-arrays, corresponding to the 5 parameters in the objects but with extra '][' characters in their names:
{ array:
[ { '][param1': 'something' }
, { '][param2': '123' }
, { '][param2': 'something' }
, { '][param4': '1234' }
, { '][param1': 'hello' }
]
}
There is a new node package that fixes this: "npm install qs".
https://github.com/ljharb/qs
"query string parser for node supporting nesting, as it was removed from 0.3.x, so this library provides the previous and commonly desired behaviour (and twice as fast)"
If anyone can tell me why it was removed from 0.3.x, I will give you an upvote for your comment. (I want my confidence in Node.js restored.)
To confirm my comment above, node's querystring.stringify function won't handle nested arrays (at the time of writing).
You can see the source of stringify at https://github.com/ry/node/blob/master/lib/querystring.js
Note that it handles one level of arrays but it doesn't recurse. When it finds an array it uses stringifyPrimitive to encode the array's values. You can see that stringifyPrimitive doesn't handle arrays, only number, boolean and string.
As I suggested in my comment, given that you're using a POST request a better idea would be to use JSON encoding for your complex data structure.
Or use https://github.com/visionmedia/node-querystring as suggested by #FriendlyDev
Don't use querystring.parse for recreating a JSON object sent as string. Use instead JSON.parse. And use JSON.stringify instead of querystring.stringify
querystring is useful when you send parameter encoded in the url or when you post a form. But there is no point in using it if you send just one JSON object with all your data.
In your scenario I would dismiss the querystring library and use JSON library, which is already included. It would be cleaner and faster.
http://www.json.org/js.html

Resources