Source: lib/client.js

  1. // Copyright (c) 2017 Intel Corporation. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. 'use strict';
  15. const rclnodejs = require('bindings')('rclnodejs');
  16. const Entity = require('./entity.js');
  17. const debug = require('debug')('rclnodejs:client');
  18. /**
  19. * @class - Class representing a Client in ROS
  20. * @hideconstructor
  21. */
  22. class Client extends Entity {
  23. constructor(handle, nodeHandle, serviceName, typeClass, options) {
  24. super(handle, typeClass, options);
  25. this._nodeHandle = nodeHandle;
  26. this._serviceName = serviceName;
  27. this._sequenceNumber = 0;
  28. }
  29. /**
  30. * This callback is called when a resopnse is sent back from service
  31. * @callback ResponseCallback
  32. * @param {Object} response - The response sent from the service
  33. * @see [Client.sendRequest]{@link Client#sendRequest}
  34. * @see [Node.createService]{@link Node#createService}
  35. * @see {@link Client}
  36. * @see {@link Service}
  37. */
  38. /**
  39. * Send the request and will be notified asynchronously if receiving the repsonse.
  40. * @param {object} request - The request to be submitted.
  41. * @param {ResponseCallback} callback - Thc callback function for receiving the server response.
  42. * @return {undefined}
  43. * @see {@link ResponseCallback}
  44. */
  45. sendRequest(request, callback) {
  46. let requestToSend =
  47. request instanceof this._typeClass.Request
  48. ? request
  49. : new this._typeClass.Request(request);
  50. if (typeof callback !== 'function') {
  51. throw new TypeError('Invalid argument');
  52. }
  53. let rawRequest = requestToSend.serialize();
  54. this._sequenceNumber = rclnodejs.sendRequest(this._handle, rawRequest);
  55. debug(`Client has sent a ${this._serviceName} request.`);
  56. this._callback = callback;
  57. }
  58. get sequenceNumber() {
  59. return this._sequenceNumber;
  60. }
  61. processResponse(response) {
  62. debug(`Client has received ${this._serviceName} response from service.`);
  63. this._callback(response.toPlainObject(this.typedArrayEnabled));
  64. }
  65. /**
  66. * Checks if the service is available.
  67. * @return {boolean} true if the service is available.
  68. */
  69. isServiceServerAvailable() {
  70. return rclnodejs.serviceServerIsAvailable(this._nodeHandle, this.handle);
  71. }
  72. /**
  73. * Wait until the service server is available or a timeout is reached. This
  74. * function polls for the service state so it may not return as soon as the
  75. * service is available.
  76. * @param {number} timeout The maximum amount of time to wait for, if timeout
  77. * is `undefined` or `< 0`, this will wait indefinitely.
  78. * @return {Promise<boolean>} true if the service is available.
  79. */
  80. async waitForService(timeout = undefined) {
  81. let deadline = Infinity;
  82. if (timeout !== undefined && timeout >= 0) {
  83. deadline = Date.now() + timeout;
  84. }
  85. let waitMs = 5;
  86. let serviceAvailable = this.isServiceServerAvailable();
  87. while (!serviceAvailable && Date.now() < deadline) {
  88. waitMs *= 2;
  89. waitMs = Math.min(waitMs, 1000);
  90. if (timeout !== undefined && timeout >= -1) {
  91. waitMs = Math.min(waitMs, deadline - Date.now());
  92. }
  93. await new Promise(resolve => setTimeout(resolve, waitMs));
  94. serviceAvailable = this.isServiceServerAvailable();
  95. }
  96. return serviceAvailable;
  97. }
  98. static createClient(nodeHandle, serviceName, typeClass, options) {
  99. let type = typeClass.type();
  100. let handle = rclnodejs.createClient(
  101. nodeHandle,
  102. serviceName,
  103. type.interfaceName,
  104. type.pkgName,
  105. options.qos
  106. );
  107. return new Client(handle, nodeHandle, serviceName, typeClass, options);
  108. }
  109. /**
  110. * @type {string}
  111. */
  112. get serviceName() {
  113. return this._serviceName;
  114. }
  115. }
  116. module.exports = Client;