rclnodejs 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -43,9 +43,9 @@ npm i rclnodejs@x.y.z
43
43
 
44
44
  #### RCLNODEJS - ROS 2 Version Compatibility
45
45
 
46
- | RCLNODEJS Version | Compatible ROS 2 LTS |
47
- | :----------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------: |
48
- | latest version (currently [v1.0.0](https://github.com/RobotWebTools/rclnodejs/tree/1.0.0)) | [Humble](https://github.com/RobotWebTools/rclnodejs/tree/humble-hawksbill)<br>[Jazzy](https://github.com/RobotWebTools/rclnodejs/tree/jazzy) |
46
+ | RCLNODEJS Version | Compatible ROS 2 LTS |
47
+ | :----------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
48
+ | latest version (currently [v1.1.0](https://github.com/RobotWebTools/rclnodejs/tree/1.1.0)) | [Kilted](https://github.com/RobotWebTools/rclnodejs/tree/kilted)<br>[Jazzy](https://github.com/RobotWebTools/rclnodejs/tree/jazzy)<br>[Humble](https://github.com/RobotWebTools/rclnodejs/tree/humble-hawksbill) |
49
49
 
50
50
  ## Documentation
51
51
 
package/binding.gyp CHANGED
@@ -166,6 +166,14 @@
166
166
  ]
167
167
  }
168
168
  ],
169
+ [
170
+ # After Humble, e.g., Jazzy, Kilted.
171
+ 'ros_version > 2205', {
172
+ 'sources': [
173
+ './src/rcl_type_description_service_bindings.cpp',
174
+ ]
175
+ }
176
+ ],
169
177
  [
170
178
  'runtime=="electron"', {
171
179
  "defines": ["NODE_RUNTIME_ELECTRON=1"]
@@ -19,6 +19,7 @@ const ActionInterfaces = require('./interfaces.js');
19
19
  const ActionUuid = require('./uuid.js');
20
20
  const ClientGoalHandle = require('./client_goal_handle.js');
21
21
  const Deferred = require('./deferred.js');
22
+ const DistroUtils = require('../distro.js');
22
23
  const Entity = require('../entity.js');
23
24
  const loader = require('../interface_loader.js');
24
25
  const QoS = require('../qos.js');
@@ -371,6 +372,45 @@ class ActionClient extends Entity {
371
372
 
372
373
  this._node._destroyEntity(this, this._node._actionClients);
373
374
  }
375
+
376
+ /**
377
+ * Get the number of wait set entities that make up an action entity.
378
+ * @return {object} - An object containing the number of various entities.
379
+ * @property {number} subscriptionsNumber - The number of subscriptions.
380
+ * @property {number} guardConditionsNumber - The number of guard conditions.
381
+ * @property {number} timersNumber - The number of timers.
382
+ * @property {number} clientsNumber - The number of clients.
383
+ * @property {number} servicesNumber - The number of services.
384
+ */
385
+ getNumEntities() {
386
+ return rclnodejs.getNumEntities(this.handle);
387
+ }
388
+
389
+ /**
390
+ * Configure introspection.
391
+ * @param {Clock} clock - Clock to use for service event timestamps
392
+ * @param {QoS} qos - QoSProfile for the service event publisher
393
+ * @param {ServiceIntrospectionState} introspectionState - State to set introspection to
394
+ */
395
+ configureIntrospection(clock, qos, introspectionState) {
396
+ if (DistroUtils.getDistroId() <= DistroUtils.getDistroId('jazzy')) {
397
+ console.warn(
398
+ 'Configure action client introspection is not supported by this version of ROS 2'
399
+ );
400
+ return;
401
+ }
402
+
403
+ let type = this.typeClass.type();
404
+ rclnodejs.configureActionClientIntrospection(
405
+ this.handle,
406
+ this._node.handle,
407
+ clock.handle,
408
+ type.interfaceName,
409
+ type.pkgName,
410
+ qos,
411
+ introspectionState
412
+ );
413
+ }
374
414
  }
375
415
 
376
416
  module.exports = ActionClient;
@@ -17,6 +17,7 @@
17
17
  const rclnodejs = require('bindings')('rclnodejs');
18
18
  const ActionInterfaces = require('./interfaces.js');
19
19
  const ActionUuid = require('./uuid.js');
20
+ const DistroUtils = require('../distro.js');
20
21
  const Entity = require('../entity.js');
21
22
  const { CancelResponse, GoalEvent, GoalResponse } = require('./response.js');
22
23
  const loader = require('../interface_loader.js');
@@ -454,6 +455,26 @@ class ActionServer extends Entity {
454
455
 
455
456
  this._node._destroyEntity(this, this._node._actionServers);
456
457
  }
458
+
459
+ configureIntrospection(clock, qos, introspectionState) {
460
+ if (DistroUtils.getDistroId() <= DistroUtils.getDistroId('jazzy')) {
461
+ console.warn(
462
+ 'Configure action server introspection is not supported by this version of ROS 2'
463
+ );
464
+ return;
465
+ }
466
+
467
+ let type = this.typeClass.type();
468
+ rclnodejs.configureActionServerIntrospection(
469
+ this.handle,
470
+ this._node.handle,
471
+ clock.handle,
472
+ type.interfaceName,
473
+ type.pkgName,
474
+ qos,
475
+ introspectionState
476
+ );
477
+ }
457
478
  }
458
479
 
459
480
  module.exports = ActionServer;
package/lib/client.js CHANGED
@@ -141,7 +141,7 @@ class Client extends Entity {
141
141
  configureIntrospection(clock, qos, introspectionState) {
142
142
  if (DistroUtils.getDistroId() <= DistroUtils.getDistroId('humble')) {
143
143
  console.warn(
144
- 'Service introspection is not supported by this versionof ROS 2'
144
+ 'Service introspection is not supported by this version of ROS 2'
145
145
  );
146
146
  return;
147
147
  }
package/lib/distro.js CHANGED
@@ -25,6 +25,7 @@ const DistroId = {
25
25
  HUMBLE: 2205,
26
26
  IRON: 2305,
27
27
  JAZZY: 2405,
28
+ KILTED: 2505,
28
29
  ROLLING: 5000,
29
30
  };
30
31
 
@@ -35,6 +36,7 @@ DistroNameIdMap.set('galactic', DistroId.GALACTIC);
35
36
  DistroNameIdMap.set('humble', DistroId.HUMBLE);
36
37
  DistroNameIdMap.set('iron', DistroId.IRON);
37
38
  DistroNameIdMap.set('jazzy', DistroId.JAZZY);
39
+ DistroNameIdMap.set('kilted', DistroId.KILTED);
38
40
  DistroNameIdMap.set('rolling', DistroId.ROLLING);
39
41
 
40
42
  const DistroUtils = {
package/lib/lifecycle.js CHANGED
@@ -591,6 +591,15 @@ class LifecycleNode extends Node {
591
591
  return this._changeState(SHUTDOWN_TRANSITION_LABEL, callbackReturnValue);
592
592
  }
593
593
 
594
+ /**
595
+ * Check if state machine is initialized.
596
+ *
597
+ * @returns {boolean} true if the state machine is initialized; otherwise false.
598
+ */
599
+ get isInitialized() {
600
+ return rclnodejs.isInitialized(this._stateMachineHandle);
601
+ }
602
+
594
603
  /**
595
604
  * The GetState service handler.
596
605
  * @param {Object} request - The GetState service request.
package/lib/node.js CHANGED
@@ -39,6 +39,7 @@ const Service = require('./service.js');
39
39
  const Subscription = require('./subscription.js');
40
40
  const TimeSource = require('./time_source.js');
41
41
  const Timer = require('./timer.js');
42
+ const TypeDescriptionService = require('./type_description_service.js');
42
43
  const Entity = require('./entity.js');
43
44
 
44
45
  // Parameter event publisher constants
@@ -101,6 +102,7 @@ class Node extends rclnodejs.ShadowNode {
101
102
  this._parameterDescriptors = new Map();
102
103
  this._parameters = new Map();
103
104
  this._parameterService = null;
105
+ this._typeDescriptionService = null;
104
106
  this._parameterEventPublisher = null;
105
107
  this._setParametersCallbacks = [];
106
108
  this._logger = new Logging(rclnodejs.getNodeLoggerName(this.handle));
@@ -147,6 +149,14 @@ class Node extends rclnodejs.ShadowNode {
147
149
  this._parameterService = new ParameterService(this);
148
150
  this._parameterService.start();
149
151
  }
152
+
153
+ if (
154
+ DistroUtils.getDistroId() >= DistroUtils.getDistroId('jazzy') &&
155
+ options.startTypeDescriptionService
156
+ ) {
157
+ this._typeDescriptionService = new TypeDescriptionService(this);
158
+ this._typeDescriptionService.start();
159
+ }
150
160
  }
151
161
 
152
162
  execute(handles) {
@@ -1053,7 +1063,15 @@ class Node extends rclnodejs.ShadowNode {
1053
1063
  * @return {Array<{name: string, namespace: string}>} An array of the names and namespaces.
1054
1064
  */
1055
1065
  getNodeNamesAndNamespaces() {
1056
- return rclnodejs.getNodeNames(this.handle);
1066
+ return rclnodejs.getNodeNames(this.handle, /*getEnclaves=*/ false);
1067
+ }
1068
+
1069
+ /**
1070
+ * Get the list of nodes and their namespaces with enclaves discovered by the provided node.
1071
+ * @return {Array<{name: string, namespace: string, enclave: string}>} An array of the names, namespaces and enclaves.
1072
+ */
1073
+ getNodeNamesAndNamespacesWithEnclaves() {
1074
+ return rclnodejs.getNodeNames(this.handle, /*getEnclaves=*/ true);
1057
1075
  }
1058
1076
 
1059
1077
  /**
@@ -1610,6 +1628,15 @@ class Node extends rclnodejs.ShadowNode {
1610
1628
  }
1611
1629
  }
1612
1630
 
1631
+ /**
1632
+ * Get the fully qualified name of the node.
1633
+ *
1634
+ * @returns {string} - String containing the fully qualified name of the node.
1635
+ */
1636
+ getFullyQualifiedName() {
1637
+ return rclnodejs.getFullyQualifiedName(this.handle);
1638
+ }
1639
+
1613
1640
  // returns on 1st error or result {successful, reason}
1614
1641
  _validateParameters(parameters = [], declareParameterMode = false) {
1615
1642
  for (const parameter of parameters) {
@@ -26,16 +26,19 @@ class NodeOptions {
26
26
  * @param {boolean} [startParameterServices=true]
27
27
  * @param {array} [parameterOverrides=[]]
28
28
  * @param {boolean} [automaticallyDeclareParametersFromOverrides=false]
29
+ * @param {boolean} [startTypeDescriptionService=true]
29
30
  */
30
31
  constructor(
31
32
  startParameterServices = true,
32
33
  parameterOverrides = [],
33
- automaticallyDeclareParametersFromOverrides = false
34
+ automaticallyDeclareParametersFromOverrides = false,
35
+ startTypeDescriptionService = true
34
36
  ) {
35
37
  this._startParameterServices = startParameterServices;
36
38
  this._parameterOverrides = parameterOverrides;
37
39
  this._automaticallyDeclareParametersFromOverrides =
38
40
  automaticallyDeclareParametersFromOverrides;
41
+ this._startTypeDescriptionService = startTypeDescriptionService;
39
42
  }
40
43
 
41
44
  /**
@@ -105,6 +108,23 @@ class NodeOptions {
105
108
  this._automaticallyDeclareParametersFromOverrides = declareParamsFlag;
106
109
  }
107
110
 
111
+ /**
112
+ * Get the startTypeDescriptionService option, only available for ROS2 > Humble.
113
+ * Default value = true;
114
+ * @returns {boolean} - true if the type description service is enabled.
115
+ */
116
+ get startTypeDescriptionService() {
117
+ return this._startTypeDescriptionService;
118
+ }
119
+
120
+ /**
121
+ * Set startTypeDescriptionService, only available for ROS2 > Humble
122
+ * @param {boolean} willStartTypeDescriptionService
123
+ */
124
+ set startTypeDescriptionService(willStartTypeDescriptionService) {
125
+ this._startTypeDescriptionService = willStartTypeDescriptionService;
126
+ }
127
+
108
128
  /**
109
129
  * Return an instance configured with default options.
110
130
  * @returns {NodeOptions} - An instance with default values.
package/lib/publisher.js CHANGED
@@ -80,6 +80,25 @@ class Publisher extends Entity {
80
80
  get subscriptionCount() {
81
81
  return rclnodejs.getSubscriptionCount(this._handle);
82
82
  }
83
+
84
+ /**
85
+ * Wait until all published message data is acknowledged or until the specified timeout elapses
86
+ *
87
+ * If the timeout is negative then this function will block indefinitely until all published
88
+ * message data is acknowledged.
89
+ * If the timeout is 0 then it will check if all published message has been acknowledged without
90
+ * waiting.
91
+ * If the timeout is greater than 0 then it will return after that period of time has elapsed or
92
+ * all published message data is acknowledged.
93
+ *
94
+ * Raises an error if failed, such as the middleware not supporting this feature.
95
+ *
96
+ * @param {timeout} timeout - The duration to wait for all published message data to be acknowledged in nanoseconds.
97
+ * @return {boolean} `true` if all published message data is acknowledged before the timeout, otherwise `false`.
98
+ */
99
+ waitForAllAcked(timeout) {
100
+ return rclnodejs.waitForAllAcked(this._handle, timeout);
101
+ }
83
102
  }
84
103
 
85
104
  module.exports = Publisher;
package/lib/service.js CHANGED
@@ -125,7 +125,7 @@ class Service extends Entity {
125
125
  configureIntrospection(clock, qos, introspectionState) {
126
126
  if (DistroUtils.getDistroId() <= DistroUtils.getDistroId('humble')) {
127
127
  console.warn(
128
- 'Service introspection is not supported by this versionof ROS 2'
128
+ 'Service introspection is not supported by this version of ROS 2'
129
129
  );
130
130
  return;
131
131
  }
@@ -0,0 +1,82 @@
1
+ // Copyright (c) 2025, The Robot Web Tools Contributors
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
+
15
+ 'use strict';
16
+
17
+ const loader = require('./interface_loader.js');
18
+ const rclnodejs = require('bindings')('rclnodejs');
19
+ const Service = require('./service.js');
20
+
21
+ // This class is used to create a TypeDescriptionService which can be used to
22
+ // retrieve information about types used by the node’s publishers, subscribers,
23
+ // services or actions.
24
+ class TypeDescriptionService {
25
+ constructor(node) {
26
+ this._node = node;
27
+ this._serviceName = this._node.name() + '/get_type_description';
28
+ this._typeDescriptionServiceHandle = rclnodejs.initTypeDescriptionService(
29
+ this._node.handle
30
+ );
31
+ this._typeClass = loader.loadInterface(
32
+ 'type_description_interfaces/srv/GetTypeDescription'
33
+ );
34
+ this._typeDescriptionService = null;
35
+ }
36
+
37
+ start() {
38
+ if (this._typeDescriptionService) {
39
+ return;
40
+ }
41
+
42
+ this._typeDescriptionService = new Service(
43
+ this._node.handle,
44
+ this._typeDescriptionServiceHandle,
45
+ this._serviceName,
46
+ this._typeClass,
47
+ this._node._validateOptions(undefined),
48
+ (request, response) => {
49
+ const responseToBeSent = new this._typeClass.Response();
50
+ const requestReceived = new this._typeClass.Request(request);
51
+ rclnodejs.handleRequest(
52
+ this._node.handle,
53
+ requestReceived.serialize(),
54
+ responseToBeSent.serialize()
55
+ );
56
+ responseToBeSent.deserialize(responseToBeSent.refObject);
57
+ rclnodejs.sendResponse(
58
+ this._typeDescriptionServiceHandle,
59
+ responseToBeSent.serialize(),
60
+ response._header
61
+ );
62
+ return null;
63
+ }
64
+ );
65
+ this._node._services.push(this._typeDescriptionService);
66
+ this._node.syncHandles();
67
+ }
68
+
69
+ /**
70
+ * Get the node this
71
+ * @return {Node} - The supported node.
72
+ */
73
+ get node() {
74
+ return this._node;
75
+ }
76
+
77
+ static toTypeHash(topicTypeHash) {
78
+ return `RIHS0${topicTypeHash.version}_${topicTypeHash.value.toString('hex')}`;
79
+ }
80
+ }
81
+
82
+ module.exports = TypeDescriptionService;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rclnodejs",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "ROS2.0 JavaScript client with Node.js",
5
5
  "main": "index.js",
6
6
  "types": "types/index.d.ts",
@@ -43,9 +43,9 @@ npm i rclnodejs@x.y.z
43
43
 
44
44
  #### RCLNODEJS - ROS 2 Version Compatibility
45
45
 
46
- | RCLNODEJS Version | Compatible ROS 2 LTS |
47
- | :----------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------: |
48
- | latest version (currently [v1.0.0](https://github.com/RobotWebTools/rclnodejs/tree/1.0.0)) | [Humble](https://github.com/RobotWebTools/rclnodejs/tree/humble-hawksbill)<br>[Jazzy](https://github.com/RobotWebTools/rclnodejs/tree/jazzy) |
46
+ | RCLNODEJS Version | Compatible ROS 2 LTS |
47
+ | :----------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
48
+ | latest version (currently [v1.1.0](https://github.com/RobotWebTools/rclnodejs/tree/1.1.0)) | [Kilted](https://github.com/RobotWebTools/rclnodejs/tree/kilted)<br>[Jazzy](https://github.com/RobotWebTools/rclnodejs/tree/jazzy)<br>[Humble](https://github.com/RobotWebTools/rclnodejs/tree/humble-hawksbill) |
49
49
 
50
50
  ## Documentation
51
51
 
package/src/addon.cpp CHANGED
@@ -34,6 +34,9 @@
34
34
  #include "rcl_subscription_bindings.h"
35
35
  #include "rcl_time_point_bindings.h"
36
36
  #include "rcl_timer_bindings.h"
37
+ #if ROS_VERSION > 2205 // ROS2 > Humble
38
+ #include "rcl_type_description_service_bindings.h"
39
+ #endif
37
40
  #include "rcl_utilities.h"
38
41
  #include "shadow_node.h"
39
42
 
@@ -79,6 +82,9 @@ Napi::Object InitModule(Napi::Env env, Napi::Object exports) {
79
82
  rclnodejs::InitSubscriptionBindings(env, exports);
80
83
  rclnodejs::InitTimePointBindings(env, exports);
81
84
  rclnodejs::InitTimerBindings(env, exports);
85
+ #if ROS_VERSION > 2205 // ROS2 > Humble
86
+ rclnodejs::InitTypeDescriptionServiceBindings(env, exports);
87
+ #endif
82
88
  rclnodejs::InitLifecycleBindings(env, exports);
83
89
  rclnodejs::ShadowNode::Init(env, exports);
84
90
  rclnodejs::RclHandle::Init(env, exports);
@@ -16,6 +16,7 @@
16
16
 
17
17
  #include <rcl/error_handling.h>
18
18
  #include <rcl/rcl.h>
19
+ #include <rcl_action/action_client.h>
19
20
  #include <rcl_action/rcl_action.h>
20
21
 
21
22
  #include <string>
@@ -126,28 +127,6 @@ Napi::Value ActionSendGoalRequest(const Napi::CallbackInfo& info) {
126
127
  return Napi::Number::New(env, static_cast<int32_t>(sequence_number));
127
128
  }
128
129
 
129
- Napi::Value ActionTakeCancelRequest(const Napi::CallbackInfo& info) {
130
- Napi::Env env = info.Env();
131
-
132
- RclHandle* action_server_handle =
133
- RclHandle::Unwrap(info[0].As<Napi::Object>());
134
- rcl_action_server_t* action_server =
135
- reinterpret_cast<rcl_action_server_t*>(action_server_handle->ptr());
136
- rmw_request_id_t* header =
137
- reinterpret_cast<rmw_request_id_t*>(malloc(sizeof(rmw_request_id_t)));
138
-
139
- void* taken_request = info[1].As<Napi::Buffer<char>>().Data();
140
- rcl_ret_t ret =
141
- rcl_action_take_cancel_request(action_server, header, taken_request);
142
- if (ret != RCL_RET_ACTION_SERVER_TAKE_FAILED) {
143
- auto js_obj = RclHandle::NewInstance(env, header, nullptr,
144
- [](void* ptr) { free(ptr); });
145
- return js_obj;
146
- }
147
-
148
- return env.Undefined();
149
- }
150
-
151
130
  Napi::Value ActionSendResultRequest(const Napi::CallbackInfo& info) {
152
131
  Napi::Env env = info.Env();
153
132
 
@@ -211,6 +190,97 @@ Napi::Value ActionTakeStatus(const Napi::CallbackInfo& info) {
211
190
  return env.Undefined();
212
191
  }
213
192
 
193
+ Napi::Value GetNumEntities(const Napi::CallbackInfo& info) {
194
+ Napi::Env env = info.Env();
195
+ RclHandle* action_client_handle =
196
+ RclHandle::Unwrap(info[0].As<Napi::Object>());
197
+ rcl_action_client_t* action_client =
198
+ reinterpret_cast<rcl_action_client_t*>(action_client_handle->ptr());
199
+
200
+ size_t num_subscriptions = 0u;
201
+ size_t num_guard_conditions = 0u;
202
+ size_t num_timers = 0u;
203
+ size_t num_clients = 0u;
204
+ size_t num_services = 0u;
205
+
206
+ rcl_ret_t ret;
207
+ ret = rcl_action_client_wait_set_get_num_entities(
208
+ action_client, &num_subscriptions, &num_guard_conditions, &num_timers,
209
+ &num_clients, &num_services);
210
+ if (RCL_RET_OK != ret) {
211
+ rcl_reset_error();
212
+ std::string error_text{
213
+ "Failed to get number of entities for 'rcl_action_client_t'"};
214
+ Napi::Error::New(env, error_text).ThrowAsJavaScriptException();
215
+ return env.Undefined();
216
+ }
217
+ Napi::Object entities = Napi::Object::New(env);
218
+ entities.Set("subscriptionsNumber",
219
+ Napi::Number::New(env, num_subscriptions));
220
+ entities.Set("guardConditionsNumber",
221
+ Napi::Number::New(env, num_guard_conditions));
222
+ entities.Set("timersNumber", Napi::Number::New(env, num_timers));
223
+ entities.Set("clientsNumber", Napi::Number::New(env, num_clients));
224
+ entities.Set("servicesNumber", Napi::Number::New(env, num_services));
225
+ return entities;
226
+ }
227
+
228
+ Napi::Value ActionSendCancelRequest(const Napi::CallbackInfo& info) {
229
+ Napi::Env env = info.Env();
230
+
231
+ RclHandle* action_client_handle =
232
+ RclHandle::Unwrap(info[0].As<Napi::Object>());
233
+ rcl_action_client_t* action_client =
234
+ reinterpret_cast<rcl_action_client_t*>(action_client_handle->ptr());
235
+ void* buffer = info[1].As<Napi::Buffer<char>>().Data();
236
+
237
+ int64_t sequence_number;
238
+ THROW_ERROR_IF_NOT_EQUAL(
239
+ rcl_action_send_cancel_request(action_client, buffer, &sequence_number),
240
+ RCL_RET_OK, rcl_get_error_string().str);
241
+
242
+ return Napi::Number::New(env, static_cast<int32_t>(sequence_number));
243
+ }
244
+
245
+ #if ROS_VERSION >= 2505 // ROS2 >= Kilted
246
+ Napi::Value ConfigureActionClientIntrospection(const Napi::CallbackInfo& info) {
247
+ Napi::Env env = info.Env();
248
+ RclHandle* action_client_handle =
249
+ RclHandle::Unwrap(info[0].As<Napi::Object>());
250
+ rcl_action_client_t* action_client =
251
+ reinterpret_cast<rcl_action_client_t*>(action_client_handle->ptr());
252
+ RclHandle* node_handle = RclHandle::Unwrap(info[1].As<Napi::Object>());
253
+ rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
254
+ rcl_clock_t* clock = reinterpret_cast<rcl_clock_t*>(
255
+ RclHandle::Unwrap(info[2].As<Napi::Object>())->ptr());
256
+
257
+ std::string action_name = info[3].As<Napi::String>().Utf8Value();
258
+ std::string package_name = info[4].As<Napi::String>().Utf8Value();
259
+ const rosidl_action_type_support_t* ts =
260
+ GetActionTypeSupport(package_name, action_name);
261
+ rcl_ret_t ret = RCL_RET_ERROR;
262
+ if (ts) {
263
+ rcl_publisher_options_t publisher_ops = rcl_publisher_get_default_options();
264
+ auto qos_profile = GetQoSProfile(info[5]);
265
+ if (qos_profile) {
266
+ publisher_ops.qos = *qos_profile;
267
+ }
268
+ rcl_service_introspection_state_t state =
269
+ static_cast<rcl_service_introspection_state_t>(
270
+ info[6].As<Napi::Number>().Uint32Value());
271
+ ret = rcl_action_client_configure_action_introspection(
272
+ action_client, node, clock, ts, publisher_ops, state);
273
+ if (ret == RCL_RET_OK) {
274
+ return env.Undefined();
275
+ }
276
+ }
277
+
278
+ Napi::Error::New(env, "failed to configure action client introspection")
279
+ .ThrowAsJavaScriptException();
280
+ return env.Undefined();
281
+ }
282
+ #endif // ROS_VERSION >= 2505
283
+
214
284
  Napi::Object InitActionClientBindings(Napi::Env env, Napi::Object exports) {
215
285
  exports.Set("actionCreateClient",
216
286
  Napi::Function::New(env, ActionCreateClient));
@@ -218,13 +288,18 @@ Napi::Object InitActionClientBindings(Napi::Env env, Napi::Object exports) {
218
288
  Napi::Function::New(env, ActionServerIsAvailable));
219
289
  exports.Set("actionSendGoalRequest",
220
290
  Napi::Function::New(env, ActionSendGoalRequest));
221
- exports.Set("actionTakeCancelRequest",
222
- Napi::Function::New(env, ActionTakeCancelRequest));
223
291
  exports.Set("actionSendResultRequest",
224
292
  Napi::Function::New(env, ActionSendResultRequest));
225
293
  exports.Set("actionTakeFeedback",
226
294
  Napi::Function::New(env, ActionTakeFeedback));
227
295
  exports.Set("actionTakeStatus", Napi::Function::New(env, ActionTakeStatus));
296
+ exports.Set("getNumEntities", Napi::Function::New(env, GetNumEntities));
297
+ exports.Set("actionSendCancelRequest",
298
+ Napi::Function::New(env, ActionSendCancelRequest));
299
+ #if ROS_VERSION >= 2505 // ROS2 >= Kilted
300
+ exports.Set("configureActionClientIntrospection",
301
+ Napi::Function::New(env, ConfigureActionClientIntrospection));
302
+ #endif // ROS_VERSION >= 2505
228
303
  return exports;
229
304
  }
230
305
 
@@ -16,6 +16,7 @@
16
16
 
17
17
  #include <rcl/error_handling.h>
18
18
  #include <rcl/rcl.h>
19
+ #include <rcl_action/action_server.h>
19
20
  #include <rcl_action/rcl_action.h>
20
21
 
21
22
  #include <string>
@@ -96,23 +97,6 @@ Napi::Value ActionCreateServer(const Napi::CallbackInfo& info) {
96
97
  }
97
98
  }
98
99
 
99
- Napi::Value ActionSendCancelRequest(const Napi::CallbackInfo& info) {
100
- Napi::Env env = info.Env();
101
-
102
- RclHandle* action_client_handle =
103
- RclHandle::Unwrap(info[0].As<Napi::Object>());
104
- rcl_action_client_t* action_client =
105
- reinterpret_cast<rcl_action_client_t*>(action_client_handle->ptr());
106
- void* buffer = info[1].As<Napi::Buffer<char>>().Data();
107
-
108
- int64_t sequence_number;
109
- THROW_ERROR_IF_NOT_EQUAL(
110
- rcl_action_send_cancel_request(action_client, buffer, &sequence_number),
111
- RCL_RET_OK, rcl_get_error_string().str);
112
-
113
- return Napi::Number::New(env, static_cast<int32_t>(sequence_number));
114
- }
115
-
116
100
  Napi::Value ActionTakeResultRequest(const Napi::CallbackInfo& info) {
117
101
  Napi::Env env = info.Env();
118
102
 
@@ -432,11 +416,71 @@ Napi::Value ActionServerGoalExists(const Napi::CallbackInfo& info) {
432
416
  return Napi::Boolean::New(env, exists);
433
417
  }
434
418
 
419
+ Napi::Value ActionTakeCancelRequest(const Napi::CallbackInfo& info) {
420
+ Napi::Env env = info.Env();
421
+
422
+ RclHandle* action_server_handle =
423
+ RclHandle::Unwrap(info[0].As<Napi::Object>());
424
+ rcl_action_server_t* action_server =
425
+ reinterpret_cast<rcl_action_server_t*>(action_server_handle->ptr());
426
+ rmw_request_id_t* header =
427
+ reinterpret_cast<rmw_request_id_t*>(malloc(sizeof(rmw_request_id_t)));
428
+
429
+ void* taken_request = info[1].As<Napi::Buffer<char>>().Data();
430
+ rcl_ret_t ret =
431
+ rcl_action_take_cancel_request(action_server, header, taken_request);
432
+ if (ret != RCL_RET_ACTION_SERVER_TAKE_FAILED) {
433
+ auto js_obj = RclHandle::NewInstance(env, header, nullptr,
434
+ [](void* ptr) { free(ptr); });
435
+ return js_obj;
436
+ }
437
+
438
+ return env.Undefined();
439
+ }
440
+
441
+ #if ROS_VERSION >= 2505 // ROS2 >= Kilted
442
+ Napi::Value ConfigureActionServerIntrospection(const Napi::CallbackInfo& info) {
443
+ Napi::Env env = info.Env();
444
+ RclHandle* action_server_handle =
445
+ RclHandle::Unwrap(info[0].As<Napi::Object>());
446
+ rcl_action_server_t* action_server =
447
+ reinterpret_cast<rcl_action_server_t*>(action_server_handle->ptr());
448
+ RclHandle* node_handle = RclHandle::Unwrap(info[1].As<Napi::Object>());
449
+ rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
450
+ rcl_clock_t* clock = reinterpret_cast<rcl_clock_t*>(
451
+ RclHandle::Unwrap(info[2].As<Napi::Object>())->ptr());
452
+
453
+ std::string action_name = info[3].As<Napi::String>().Utf8Value();
454
+ std::string package_name = info[4].As<Napi::String>().Utf8Value();
455
+ const rosidl_action_type_support_t* ts =
456
+ GetActionTypeSupport(package_name, action_name);
457
+
458
+ rcl_ret_t ret = RCL_RET_ERROR;
459
+ if (ts) {
460
+ rcl_publisher_options_t publisher_ops = rcl_publisher_get_default_options();
461
+ auto qos_profile = GetQoSProfile(info[5]);
462
+ if (qos_profile) {
463
+ publisher_ops.qos = *qos_profile;
464
+ }
465
+ rcl_service_introspection_state_t state =
466
+ static_cast<rcl_service_introspection_state_t>(
467
+ info[6].As<Napi::Number>().Uint32Value());
468
+ ret = rcl_action_server_configure_action_introspection(
469
+ action_server, node, clock, ts, publisher_ops, state);
470
+ if (ret == RCL_RET_OK) {
471
+ return env.Undefined();
472
+ }
473
+ }
474
+
475
+ Napi::Error::New(env, "failed to configure action server introspection")
476
+ .ThrowAsJavaScriptException();
477
+ return env.Undefined();
478
+ }
479
+ #endif // ROS_VERSION >= 2505
480
+
435
481
  Napi::Object InitActionServerBindings(Napi::Env env, Napi::Object exports) {
436
482
  exports.Set("actionCreateServer",
437
483
  Napi::Function::New(env, ActionCreateServer));
438
- exports.Set("actionSendCancelRequest",
439
- Napi::Function::New(env, ActionSendCancelRequest));
440
484
  exports.Set("actionTakeResultRequest",
441
485
  Napi::Function::New(env, ActionTakeResultRequest));
442
486
  exports.Set("actionTakeGoalRequest",
@@ -464,6 +508,12 @@ Napi::Object InitActionServerBindings(Napi::Env env, Napi::Object exports) {
464
508
  Napi::Function::New(env, ActionProcessCancelRequest));
465
509
  exports.Set("actionServerGoalExists",
466
510
  Napi::Function::New(env, ActionServerGoalExists));
511
+ exports.Set("actionTakeCancelRequest",
512
+ Napi::Function::New(env, ActionTakeCancelRequest));
513
+ #if ROS_VERSION >= 2505 // ROS2 >= Kilted
514
+ exports.Set("configureActionServerIntrospection",
515
+ Napi::Function::New(env, ConfigureActionServerIntrospection));
516
+ #endif // ROS_VERSION >= 2505
467
517
  return exports;
468
518
  }
469
519
 
@@ -360,6 +360,18 @@ Napi::Value GetLifecycleShutdownTransitionLabel(
360
360
  return Napi::String::New(env, rcl_lifecycle_shutdown_label);
361
361
  }
362
362
 
363
+ Napi::Value IsInitialized(const Napi::CallbackInfo& info) {
364
+ Napi::Env env = info.Env();
365
+ RclHandle* state_machine_handle =
366
+ RclHandle::Unwrap(info[0].As<Napi::Object>());
367
+ rcl_lifecycle_state_machine_t* state_machine =
368
+ reinterpret_cast<rcl_lifecycle_state_machine_t*>(
369
+ state_machine_handle->ptr());
370
+ const bool is_initialized =
371
+ RCL_RET_OK == rcl_lifecycle_state_machine_is_initialized(state_machine);
372
+ return Napi::Boolean::New(env, is_initialized);
373
+ }
374
+
363
375
  Napi::Object InitLifecycleBindings(Napi::Env env, Napi::Object exports) {
364
376
  exports.Set("createLifecycleStateMachine",
365
377
  Napi::Function::New(env, CreateLifecycleStateMachine));
@@ -383,6 +395,7 @@ Napi::Object InitLifecycleBindings(Napi::Env env, Napi::Object exports) {
383
395
  Napi::Function::New(env, GetLifecycleTransitionIdToLabel));
384
396
  exports.Set("getLifecycleShutdownTransitionLabel",
385
397
  Napi::Function::New(env, GetLifecycleShutdownTransitionLabel));
398
+ exports.Set("isInitialized", Napi::Function::New(env, IsInitialized));
386
399
  return exports;
387
400
  }
388
401
 
@@ -385,40 +385,67 @@ Napi::Value GetNodeNames(const Napi::CallbackInfo& info) {
385
385
 
386
386
  RclHandle* node_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
387
387
  rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
388
+ bool get_enclaves = info[1].As<Napi::Boolean>().Value();
388
389
  rcutils_string_array_t node_names =
389
390
  rcutils_get_zero_initialized_string_array();
390
391
  rcutils_string_array_t node_namespaces =
391
392
  rcutils_get_zero_initialized_string_array();
393
+ rcutils_string_array_t enclaves = rcutils_get_zero_initialized_string_array();
392
394
  rcl_allocator_t allocator = rcl_get_default_allocator();
393
395
 
394
- THROW_ERROR_IF_NOT_EQUAL(
395
- RCL_RET_OK,
396
- rcl_get_node_names(node, allocator, &node_names, &node_namespaces),
397
- "Failed to get_node_names.");
396
+ if (get_enclaves) {
397
+ THROW_ERROR_IF_NOT_EQUAL(
398
+ RCL_RET_OK,
399
+ rcl_get_node_names_with_enclaves(node, allocator, &node_names,
400
+ &node_namespaces, &enclaves),
401
+ "Failed to get_node_names.");
402
+ } else {
403
+ THROW_ERROR_IF_NOT_EQUAL(
404
+ RCL_RET_OK,
405
+ rcl_get_node_names(node, allocator, &node_names, &node_namespaces),
406
+ "Failed to get_node_names.");
407
+ }
398
408
 
399
409
  Napi::Array result_list = Napi::Array::New(env, node_names.size);
400
410
 
401
411
  for (size_t i = 0; i < node_names.size; ++i) {
402
412
  Napi::Object item = Napi::Object::New(env);
403
-
404
413
  item.Set("name", Napi::String::New(env, node_names.data[i]));
405
414
  item.Set("namespace", Napi::String::New(env, node_namespaces.data[i]));
406
-
415
+ if (get_enclaves) {
416
+ item.Set("enclave", Napi::String::New(env, enclaves.data[i]));
417
+ }
407
418
  result_list.Set(i, item);
408
419
  }
409
420
 
410
421
  rcutils_ret_t fini_names_ret = rcutils_string_array_fini(&node_names);
411
422
  rcutils_ret_t fini_namespaces_ret =
412
423
  rcutils_string_array_fini(&node_namespaces);
413
-
424
+ rcutils_ret_t fini_enclaves_ret = rcutils_string_array_fini(&enclaves);
414
425
  THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, fini_names_ret,
415
426
  "Failed to destroy node_names");
416
427
  THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, fini_namespaces_ret,
417
428
  "Failed to destroy node_namespaces");
418
-
429
+ THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, fini_enclaves_ret,
430
+ "Failed to fini enclaves string array");
419
431
  return result_list;
420
432
  }
421
433
 
434
+ Napi::Value GetFullyQualifiedName(const Napi::CallbackInfo& info) {
435
+ Napi::Env env = info.Env();
436
+
437
+ RclHandle* node_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
438
+ rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
439
+ const char* fully_qualified_node_name =
440
+ rcl_node_get_fully_qualified_name(node);
441
+ if (!fully_qualified_node_name) {
442
+ Napi::Error::New(env, "Fully qualified name not set")
443
+ .ThrowAsJavaScriptException();
444
+ return env.Undefined();
445
+ }
446
+ return Napi::String::New(env, fully_qualified_node_name);
447
+ }
448
+
422
449
  Napi::Object InitNodeBindings(Napi::Env env, Napi::Object exports) {
423
450
  exports.Set("getParameterOverrides",
424
451
  Napi::Function::New(env, GetParameterOverrides));
@@ -439,6 +466,8 @@ Napi::Object InitNodeBindings(Napi::Env env, Napi::Object exports) {
439
466
  exports.Set("countServices", Napi::Function::New(env, CountServices));
440
467
  #endif
441
468
  exports.Set("getNodeNames", Napi::Function::New(env, GetNodeNames));
469
+ exports.Set("getFullyQualifiedName",
470
+ Napi::Function::New(env, GetFullyQualifiedName));
442
471
  return exports;
443
472
  }
444
473
 
@@ -128,6 +128,24 @@ Napi::Value GetSubscriptionCount(const Napi::CallbackInfo& info) {
128
128
  return Napi::Number::New(env, count);
129
129
  }
130
130
 
131
+ Napi::Value WaitForAllAcked(const Napi::CallbackInfo& info) {
132
+ Napi::Env env = info.Env();
133
+ rcl_publisher_t* publisher = reinterpret_cast<rcl_publisher_t*>(
134
+ RclHandle::Unwrap(info[0].As<Napi::Object>())->ptr());
135
+ bool lossless;
136
+ int64_t nanoseconds = info[1].As<Napi::BigInt>().Int64Value(&lossless);
137
+
138
+ rcl_ret_t ret = rcl_publisher_wait_for_all_acked(publisher, nanoseconds);
139
+ if (RCL_RET_OK == ret) {
140
+ return Napi::Boolean::New(env, true);
141
+ } else if (RCL_RET_TIMEOUT == ret) {
142
+ return Napi::Boolean::New(env, false);
143
+ }
144
+ Napi::Error::New(env, "Failed to wait for all acknowledgements")
145
+ .ThrowAsJavaScriptException();
146
+ return env.Undefined();
147
+ }
148
+
131
149
  Napi::Object InitPublisherBindings(Napi::Env env, Napi::Object exports) {
132
150
  exports.Set("createPublisher", Napi::Function::New(env, CreatePublisher));
133
151
  exports.Set("publish", Napi::Function::New(env, Publish));
@@ -135,6 +153,7 @@ Napi::Object InitPublisherBindings(Napi::Env env, Napi::Object exports) {
135
153
  exports.Set("publishRawMessage", Napi::Function::New(env, PublishRawMessage));
136
154
  exports.Set("getSubscriptionCount",
137
155
  Napi::Function::New(env, GetSubscriptionCount));
156
+ exports.Set("waitForAllAcked", Napi::Function::New(env, WaitForAllAcked));
138
157
  return exports;
139
158
  }
140
159
 
@@ -0,0 +1,79 @@
1
+ // Copyright (c) 2025, The Robot Web Tools Contributors
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
+
15
+ #include "rcl_type_description_service_bindings.h"
16
+
17
+ #include <napi.h>
18
+ #include <rcl/rcl.h>
19
+ #include <rmw/types.h>
20
+
21
+ #include "rcl_handle.h"
22
+
23
+ namespace rclnodejs {
24
+
25
+ Napi::Value InitTypeDescriptionService(const Napi::CallbackInfo& info) {
26
+ Napi::Env env = info.Env();
27
+ RclHandle* node_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
28
+ rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
29
+ rcl_service_t* service =
30
+ reinterpret_cast<rcl_service_t*>(malloc(sizeof(rcl_service_t)));
31
+ *service = rcl_get_zero_initialized_service();
32
+ rcl_ret_t ret = rcl_node_type_description_service_init(service, node);
33
+ if (RCL_RET_OK != ret) {
34
+ Napi::Error::New(env, "Failed to initialize type description service")
35
+ .ThrowAsJavaScriptException();
36
+ }
37
+
38
+ auto service_handle =
39
+ RclHandle::NewInstance(env, service, node_handle, [node, env](void* ptr) {
40
+ rcl_service_t* service = reinterpret_cast<rcl_service_t*>(ptr);
41
+ rcl_ret_t ret = rcl_service_fini(service, node);
42
+ if (RCL_RET_OK != ret) {
43
+ Napi::Error::New(env, "Failed to destroy type description service")
44
+ .ThrowAsJavaScriptException();
45
+ }
46
+ free(ptr);
47
+ });
48
+ return service_handle;
49
+ }
50
+
51
+ Napi::Value HandleRequest(const Napi::CallbackInfo& info) {
52
+ Napi::Env env = info.Env();
53
+ rcl_node_t* node = reinterpret_cast<rcl_node_t*>(
54
+ RclHandle::Unwrap(info[0].As<Napi::Object>())->ptr());
55
+ void* request = info[1].As<Napi::Buffer<char>>().Data();
56
+ void* taken_response = info[2].As<Napi::Buffer<char>>().Data();
57
+
58
+ rmw_request_id_t header;
59
+ rcl_node_type_description_service_handle_request(
60
+ node, &header,
61
+ static_cast<
62
+ type_description_interfaces__srv__GetTypeDescription_Request*>(
63
+ request),
64
+ static_cast<
65
+ type_description_interfaces__srv__GetTypeDescription_Response*>(
66
+ taken_response));
67
+ return env.Undefined();
68
+ }
69
+
70
+ Napi::Object InitTypeDescriptionServiceBindings(Napi::Env env,
71
+ Napi::Object exports) {
72
+ exports.Set("handleRequest", Napi::Function::New(env, HandleRequest));
73
+ exports.Set("initTypeDescriptionService",
74
+ Napi::Function::New(env, InitTypeDescriptionService));
75
+
76
+ return exports;
77
+ }
78
+
79
+ } // namespace rclnodejs
@@ -0,0 +1,27 @@
1
+ // Copyright (c) 2025, The Robot Web Tools Contributors
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
+
15
+ #ifndef SRC_RCL_TYPE_DESCRIPTION_SERVICE_BINDINGS_H_
16
+ #define SRC_RCL_TYPE_DESCRIPTION_SERVICE_BINDINGS_H_
17
+
18
+ #include <napi.h>
19
+
20
+ namespace rclnodejs {
21
+
22
+ Napi::Object InitTypeDescriptionServiceBindings(Napi::Env env,
23
+ Napi::Object exports);
24
+
25
+ }
26
+
27
+ #endif // SRC_RCL_TYPE_DESCRIPTION_SERVICE_BINDINGS_H_
@@ -173,5 +173,23 @@ declare module 'rclnodejs' {
173
173
  * Destroy the underlying action client handle.
174
174
  */
175
175
  destroy(): void;
176
+
177
+ /**
178
+ * Get the number of wait set entities that make up an action entity.
179
+ * @return - The number of subscriptions, guard_conditions, timers, and clients and services.
180
+ */
181
+ getNumEntities(): object;
182
+
183
+ /**
184
+ * Configure introspection.
185
+ * @param clock - Clock to use for service event timestamps
186
+ * @param QoSProfile - QOS profile for the service event publisher
187
+ * @param introspectionState - The state to set introspection to
188
+ */
189
+ configureIntrospection(
190
+ clock: Clock,
191
+ serviceEventPubQOS: QoS,
192
+ introspectionState: ServiceIntrospectionStates
193
+ ): void;
176
194
  }
177
195
  }
@@ -181,5 +181,17 @@ declare module 'rclnodejs' {
181
181
  * Destroy the action server and all goals.
182
182
  */
183
183
  destroy(): void;
184
+
185
+ /**
186
+ * Configure introspection.
187
+ * @param clock - Clock to use for service event timestamps
188
+ * @param QoSProfile - QOS profile for the service event publisher
189
+ * @param introspectionState - The state to set introspection to
190
+ */
191
+ configureIntrospection(
192
+ clock: Clock,
193
+ serviceEventPubQOS: QoS,
194
+ introspectionState: ServiceIntrospectionStates
195
+ ): void;
184
196
  }
185
197
  }
@@ -326,6 +326,13 @@ declare module 'rclnodejs' {
326
326
  topic: string,
327
327
  options?: Options
328
328
  ): LifecyclePublisher<T>;
329
+
330
+ /**
331
+ * Check if state machine is initialized.
332
+ *
333
+ * @returns {boolean} true if the state machine is initialized; otherwise false.
334
+ */
335
+ get isInitialized(): boolean;
329
336
  }
330
337
  } // lifecycle namespace
331
338
  } // rclnodejs namespace
package/types/node.d.ts CHANGED
@@ -142,6 +142,24 @@ declare module 'rclnodejs' {
142
142
  namespace: string;
143
143
  };
144
144
 
145
+ /**
146
+ * Result of Node.getNodeNames() query
147
+ *
148
+ * @example
149
+ * ```
150
+ * [
151
+ * { name: 'gazebo', namespace: '/', enclave: '/'},
152
+ * { name: 'robot_state_publisher', namespace: '/', enclave: '/' },
153
+ * { name: 'cam2image', namespace: '/demo' , enclave: '/'}
154
+ * ]
155
+ * ```
156
+ */
157
+ type NodeNamesQueryResultWithEnclaves = {
158
+ name: string;
159
+ namespace: string;
160
+ enclave: string;
161
+ };
162
+
145
163
  /**
146
164
  * Node is the primary entrypoint in a ROS system for communication.
147
165
  * It can be used to create ROS entities such as publishers, subscribers,
@@ -769,6 +787,13 @@ declare module 'rclnodejs' {
769
787
  */
770
788
  getNodeNamesAndNamespaces(): Array<NodeNamesQueryResult>;
771
789
 
790
+ /**
791
+ * Get the list of nodes and their namespaces with enclaves discovered by the provided node.
792
+ *
793
+ * @returns An array of the names, namespaces and enclaves.
794
+ */
795
+ getNodeNamesAndNamespacesWithEnclaves(): Array<NodeNamesQueryResultWithEnclaves>;
796
+
772
797
  /**
773
798
  * Return the number of publishers on a given topic.
774
799
  * @param topic - The name of the topic.
@@ -796,5 +821,12 @@ declare module 'rclnodejs' {
796
821
  * @returns Number of services.
797
822
  */
798
823
  countServices(serviceName: string): number;
824
+
825
+ /**
826
+ * Get the fully qualified name of the node.
827
+ *
828
+ * @returns String containing the fully qualified name of the node.
829
+ */
830
+ getFullyQualifiedName(): string;
799
831
  }
800
832
  }
@@ -20,5 +20,22 @@ declare module 'rclnodejs' {
20
20
  * @returns The number of subscriptions
21
21
  */
22
22
  subscriptionCount(): number;
23
+
24
+ /**
25
+ * Wait until all published message data is acknowledged or until the specified timeout elapses
26
+ *
27
+ * If the timeout is negative then this function will block indefinitely until all published
28
+ * message data is acknowledged.
29
+ * If the timeout is 0 then it will check if all published message has been acknowledged without
30
+ * waiting.
31
+ * If the timeout is greater than 0 then it will return after that period of time has elapsed or
32
+ * all published message data is acknowledged.
33
+ *
34
+ * Raises an error if failed, such as the middleware not supporting this feature.
35
+ *
36
+ * @param {timeout} timeout - The duration to wait for all published message data to be acknowledged in nanoseconds.
37
+ * @return {boolean} `true` if all published message data is acknowledged before the timeout, otherwise `false`.
38
+ */
39
+ waitForAllAcked(timeout: bigint): boolean;
23
40
  }
24
41
  }