Skip to content

Commit 5cfbfc0

Browse files
authored
Adds new function getServiceHeader to NodeHandle (#164)
Mimics functionality in ros_comm.
1 parent aaddd52 commit 5cfbfc0

5 files changed

Lines changed: 86 additions & 0 deletions

File tree

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"test": "mocha --exit test/directory.js",
1111
"gennodejsTest": "mocha test/gennodejsTest.js test/onTheFlyMessages.js",
1212
"stressTest": "mocha test/stress.js",
13+
"serviceTest": "mocha --exit test/services.js",
1314
"flatten": "node tools/flatten.js",
1415
"generate": "node dist/tools/generateMessages.js",
1516
"compile": "babel src/ -d dist/",

src/lib/NodeHandle.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,10 @@ class NodeHandle {
331331
return this._node.getMasterUri();
332332
}
333333

334+
getServiceHeader(serviceName) {
335+
return this._node.getServiceHeader(serviceName);
336+
}
337+
334338
/**
335339
* @typedef {Object} TopicList
336340
* @property {{name: string, type: string}[]} topics Array of topics

src/lib/RosNode.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,41 @@ class RosNode extends EventEmitter {
299299
return this._masterApi.getSystemState(this._nodeName, options);
300300
}
301301

302+
/** Services currently do not declare their type with the master, so instead
303+
we probe the service for its headers. Just like in
304+
https://github.com/ros/ros_comm/blob/6292d54dc14395531bffb2e165f3954fb0ef2c34/tools/rosservice/src/rosservice/__init__.py#L94-L98
305+
*/
306+
getServiceHeader(serviceName) {
307+
return new Promise((resolve, reject) => {
308+
309+
this.lookupService(serviceName).then((resp) => {
310+
const serviceUri = resp[2];
311+
const serviceHost = NetworkUtils.getAddressAndPortFromUri(serviceUri);
312+
313+
const client = net.connect(serviceHost, () => {
314+
const serviceClientHeader = tcprosUtils.createServiceClientHeader(
315+
this._nodeName, serviceName, '*', '*', false);
316+
317+
let deserializer = new DeserializeStream();
318+
client.$deserializeStream = deserializer;
319+
client.pipe(deserializer);
320+
321+
deserializer.once('message', (msg) => {
322+
const header = tcprosUtils.parseTcpRosHeader(msg);
323+
resolve(header);
324+
});
325+
326+
client.on('error', (err) => {
327+
this._log.warn(`Service Client ${this.getService()} error: ${err}`);
328+
reject(err);
329+
});
330+
331+
client.write(serviceClientHeader);
332+
});
333+
}).catch(reject);
334+
});
335+
}
336+
302337
/**
303338
* Delays xmlrpc calls until our servers are set up
304339
* Since we need their ports for most of our calls.

test/directory.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ require('./xmlrpcTest.js');
55
require('./Log.js');
66
require('./onTheFly.js');
77
require('./messages.js');
8+
require('./services.js');

test/services.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
'use strict'
2+
3+
const chai = require('chai');
4+
const expect = chai.expect;
5+
const { spawn } = require('child_process');
6+
7+
const rosnodejs = require('../src/index.js');
8+
9+
const MASTER_PORT = 11235;
10+
11+
const initArgs = {
12+
rosMasterUri: `http://localhost:${MASTER_PORT}`,
13+
logging: {skipRosLogging: true},
14+
notime: true
15+
};
16+
17+
describe('Services Tests', () => {
18+
19+
let rn;
20+
let core;
21+
22+
before((done) => {
23+
// start a ros master
24+
core = spawn('roscore', ['-p', MASTER_PORT]);
25+
setTimeout(() => rosnodejs.initNode('/testNode', initArgs).then((rn_) => {
26+
rn = rn_;
27+
done();
28+
}), 1000); // allow 1s for ros master to start
29+
});
30+
31+
after((done) => {
32+
rosnodejs.shutdown().then(() => {
33+
rosnodejs.reset();
34+
core && core.kill('SIGINT');
35+
done();
36+
});
37+
});
38+
39+
describe('get type', () => {
40+
it('can get the type', async function() {
41+
const p = await rn.getServiceHeader('/rosout/get_loggers');
42+
expect(p.type).to.equal('roscpp/GetLoggers');
43+
});
44+
});
45+
});

0 commit comments

Comments
 (0)