/**
* @fileoverview
* @author Brandon Alexander - baalexander@gmail.com
*/
var ServiceResponse = require('./ServiceResponse');
var ServiceRequest = require('./ServiceRequest');
var EventEmitter2 = require('eventemitter2').EventEmitter2;
/**
* A ROS service client.
*
* @constructor
* @params options - possible keys include:
* * ros - the ROSLIB.Ros connection handle
* * name - the service name, like /add_two_ints
* * serviceType - the service type, like 'rospy_tutorials/AddTwoInts'
*/
function Service(options) {
options = options || {};
this.ros = options.ros;
this.name = options.name;
this.serviceType = options.serviceType;
this.isAdvertised = false;
this._serviceCallback = null;
}
Service.prototype.__proto__ = EventEmitter2.prototype;
/**
* Calls the service. Returns the service response in the callback.
*
* @param request - the ROSLIB.ServiceRequest to send
* @param callback - function with params:
* * response - the response from the service request
* @param failedCallback - the callback function when the service call failed (optional). Params:
* * error - the error message reported by ROS
*/
Service.prototype.callService = function(request, callback, failedCallback) {
if (this.isAdvertised) {
return;
}
var serviceCallId = 'call_service:' + this.name + ':' + (++this.ros.idCounter);
if (callback || failedCallback) {
this.ros.once(serviceCallId, function(message) {
if (message.result !== undefined && message.result === false) {
if (typeof failedCallback === 'function') {
failedCallback(message.values);
}
} else if (typeof callback === 'function') {
callback(new ServiceResponse(message.values));
}
});
}
var call = {
op : 'call_service',
id : serviceCallId,
service : this.name,
args : request
};
this.ros.callOnConnection(call);
};
/**
* Every time a message is published for the given topic, the callback
* will be called with the message object.
*
* @param callback - function with the following params:
* * message - the published message
*/
Service.prototype.advertise = function(callback) {
if (this.isAdvertised || typeof callback !== 'function') {
return;
}
this._serviceCallback = callback;
this.ros.on(this.name, this._serviceResponse.bind(this));
this.ros.callOnConnection({
op: 'advertise_service',
type: this.serviceType,
service: this.name
});
this.isAdvertised = true;
};
Service.prototype.unadvertise = function() {
if (!this.isAdvertised) {
return;
}
this.ros.callOnConnection({
op: 'unadvertise_service',
service: this.name
});
this.isAdvertised = false;
};
Service.prototype._serviceResponse = function(rosbridgeRequest) {
var response = {};
var success = this._serviceCallback(rosbridgeRequest.args, response);
var call = {
op: 'service_response',
service: this.name,
values: new ServiceResponse(response),
result: success
};
if (rosbridgeRequest.id) {
call.id = rosbridgeRequest.id;
}
this.ros.callOnConnection(call);
};
module.exports = Service;