rclnodejs 0.32.5 → 1.0.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.
Files changed (68) hide show
  1. package/README.md +3 -3
  2. package/binding.gyp +17 -2
  3. package/lib/client.js +2 -3
  4. package/lib/context.js +8 -0
  5. package/lib/logging.js +26 -9
  6. package/lib/node.js +68 -1
  7. package/lib/publisher.js +8 -0
  8. package/lib/service.js +9 -2
  9. package/lib/subscription.js +8 -0
  10. package/lib/timer.js +32 -0
  11. package/package.json +4 -4
  12. package/rostsd_gen/index.js +167 -67
  13. package/scripts/config.js +1 -0
  14. package/scripts/npmjs-readme.md +3 -3
  15. package/src/addon.cpp +54 -53
  16. package/src/executor.cpp +19 -10
  17. package/src/{executor.hpp → executor.h} +7 -5
  18. package/src/handle_manager.cpp +30 -56
  19. package/src/{handle_manager.hpp → handle_manager.h} +8 -7
  20. package/src/{macros.hpp → macros.h} +7 -5
  21. package/src/rcl_action_client_bindings.cpp +231 -0
  22. package/src/{rcl_action_bindings.hpp → rcl_action_client_bindings.h} +6 -11
  23. package/src/rcl_action_goal_bindings.cpp +117 -0
  24. package/src/rcl_action_goal_bindings.h +26 -0
  25. package/src/rcl_action_server_bindings.cpp +470 -0
  26. package/src/rcl_action_server_bindings.h +26 -0
  27. package/src/rcl_bindings.cpp +42 -1979
  28. package/src/{rcl_bindings.hpp → rcl_bindings.h} +5 -25
  29. package/src/rcl_client_bindings.cpp +183 -0
  30. package/src/rcl_client_bindings.h +26 -0
  31. package/src/rcl_context_bindings.cpp +156 -0
  32. package/src/rcl_context_bindings.h +26 -0
  33. package/src/rcl_graph_bindings.cpp +280 -0
  34. package/src/rcl_graph_bindings.h +26 -0
  35. package/src/rcl_guard_condition_bindings.cpp +75 -0
  36. package/src/rcl_guard_condition_bindings.h +26 -0
  37. package/src/rcl_handle.cpp +41 -57
  38. package/src/{rcl_handle.hpp → rcl_handle.h} +18 -17
  39. package/src/rcl_lifecycle_bindings.cpp +135 -114
  40. package/src/{rcl_lifecycle_bindings.hpp → rcl_lifecycle_bindings.h} +5 -7
  41. package/src/rcl_logging_bindings.cpp +96 -0
  42. package/src/rcl_logging_bindings.h +26 -0
  43. package/src/rcl_names_bindings.cpp +255 -0
  44. package/src/rcl_names_bindings.h +26 -0
  45. package/src/rcl_node_bindings.cpp +447 -0
  46. package/src/rcl_node_bindings.h +26 -0
  47. package/src/rcl_publisher_bindings.cpp +141 -0
  48. package/src/rcl_publisher_bindings.h +26 -0
  49. package/src/rcl_service_bindings.cpp +185 -0
  50. package/src/rcl_service_bindings.h +26 -0
  51. package/src/rcl_subscription_bindings.cpp +335 -0
  52. package/src/rcl_subscription_bindings.h +26 -0
  53. package/src/rcl_time_point_bindings.cpp +194 -0
  54. package/src/rcl_time_point_bindings.h +26 -0
  55. package/src/rcl_timer_bindings.cpp +237 -0
  56. package/src/rcl_timer_bindings.h +26 -0
  57. package/src/rcl_utilities.cpp +166 -1
  58. package/src/{rcl_utilities.hpp → rcl_utilities.h} +21 -3
  59. package/src/shadow_node.cpp +56 -75
  60. package/src/{shadow_node.hpp → shadow_node.h} +18 -17
  61. package/types/context.d.ts +6 -0
  62. package/types/interfaces.d.ts +4377 -0
  63. package/types/node.d.ts +53 -0
  64. package/types/publisher.d.ts +6 -0
  65. package/types/service.d.ts +6 -0
  66. package/types/subscription.d.ts +6 -0
  67. package/types/timer.d.ts +18 -0
  68. package/src/rcl_action_bindings.cpp +0 -826
@@ -12,1460 +12,26 @@
12
12
  // See the License for the specific language governing permissions and
13
13
  // limitations under the License.
14
14
 
15
- #include "rcl_bindings.hpp"
15
+ #include "rcl_bindings.h"
16
16
 
17
- #include <rcl/arguments.h>
18
- #include <rcl/error_handling.h>
19
- #include <rcl/expand_topic_name.h>
20
- #include <rcl/graph.h>
21
- #include <rcl/logging.h>
22
- #include <rcl/node.h>
23
- #include <rcl/rcl.h>
24
- #include <rcl/validate_topic_name.h>
25
- #include <rcl_action/rcl_action.h>
26
- #include <rcl_yaml_param_parser/parser.h>
27
- #include <rcl_yaml_param_parser/types.h>
28
- #include <rmw/error_handling.h>
29
- #include <rmw/rmw.h>
30
- #include <rmw/validate_full_topic_name.h>
31
- #include <rmw/validate_namespace.h>
32
- #include <rmw/validate_node_name.h>
17
+ #include <node.h>
33
18
  #if ROS_VERSION >= 2006
34
19
  #include <rosidl_runtime_c/string_functions.h>
35
20
  #else
36
21
  #include <rosidl_generator_c/string_functions.h>
37
22
  #endif
38
23
 
39
- #if ROS_VERSION > 2205
40
- #include <rcl/service_introspection.h>
41
- #endif
42
-
43
- #include <cstdio>
44
- #include <iostream>
45
24
  #include <memory>
46
25
  #include <string>
47
- #include <vector>
48
- #if NODE_MAJOR_VERSION > 12
49
- #include <utility>
50
- #endif
51
26
 
52
- #include "handle_manager.hpp"
53
- #include "macros.hpp"
54
- #include "rcl_handle.hpp"
55
- #include "rcl_utilities.hpp"
27
+ #include "rcl_handle.h"
56
28
 
57
29
  namespace rclnodejs {
58
30
 
59
- static v8::Local<v8::Object> wrapParameters(
60
- rcl_params_t* params); // NOLINT(whitespace/line_length)
61
-
62
- NAN_METHOD(Init) {
63
- rcl_allocator_t allocator = rcl_get_default_allocator();
64
- rcl_init_options_t init_options = rcl_get_zero_initialized_init_options();
65
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
66
- rcl_init_options_init(&init_options, allocator),
67
- rcl_get_error_string().str);
68
-
69
- // preprocess Context
70
- RclHandle* context_handle = RclHandle::Unwrap<RclHandle>(
71
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
72
- rcl_context_t* context =
73
- reinterpret_cast<rcl_context_t*>(context_handle->ptr());
74
-
75
- // preprocess argc & argv
76
- v8::Local<v8::Array> jsArgv = v8::Local<v8::Array>::Cast(info[1]);
77
- int argc = jsArgv->Length();
78
- char** argv = nullptr;
79
- if (argc > 0) {
80
- argv = reinterpret_cast<char**>(malloc(argc * sizeof(char*)));
81
- for (int i = 0; i < argc; i++) {
82
- Nan::MaybeLocal<v8::Value> jsElement = Nan::Get(jsArgv, i);
83
- Nan::Utf8String utf8_arg(jsElement.ToLocalChecked());
84
- int len = utf8_arg.length() + 1;
85
- argv[i] = reinterpret_cast<char*>(malloc(len * sizeof(char*)));
86
- snprintf(argv[i], len, "%s", *utf8_arg);
87
- }
88
- }
89
-
90
- THROW_ERROR_IF_NOT_EQUAL(
91
- RCL_RET_OK,
92
- rcl_init(argc, argc > 0 ? argv : nullptr, &init_options, context),
93
- rcl_get_error_string().str);
94
-
95
- THROW_ERROR_IF_NOT_EQUAL(
96
- RCL_RET_OK, rcl_logging_configure(&context->global_arguments, &allocator),
97
- rcl_get_error_string().str);
98
-
99
- for (int i = 0; i < argc; i++) {
100
- free(argv[i]);
101
- }
102
- free(argv);
103
- }
104
-
105
- NAN_METHOD(GetParameterOverrides) {
106
- RclHandle* context_handle = RclHandle::Unwrap<RclHandle>(
107
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
108
- rcl_context_t* context =
109
- reinterpret_cast<rcl_context_t*>(context_handle->ptr());
110
-
111
- rcl_arguments_t* parsed_args = &(context->global_arguments);
112
- rcl_params_t* params = NULL;
113
- THROW_ERROR_IF_NOT_EQUAL(
114
- RCL_RET_OK, rcl_arguments_get_param_overrides(parsed_args, &params),
115
- rcl_get_error_string().str);
116
-
117
- if (params == NULL) {
118
- info.GetReturnValue().Set(Nan::Undefined());
119
- return;
120
- }
121
-
122
- info.GetReturnValue().Set(wrapParameters(params));
123
-
124
- rcl_yaml_node_struct_fini(params);
125
- }
126
-
127
- static const int PARAMETER_NOT_SET = 0;
128
- static const int PARAMETER_BOOL = 1;
129
- static const int PARAMETER_INTEGER = 2;
130
- static const int PARAMETER_DOUBLE = 3;
131
- static const int PARAMETER_STRING = 4;
132
- static const int PARAMETER_BYTE_ARRAY = 5;
133
- static const int PARAMETER_BOOL_ARRAY = 6;
134
- static const int PARAMETER_INTEGER_ARRAY = 7;
135
- static const int PARAMETER_DOUBLE_ARRAY = 8;
136
- static const int PARAMETER_STRING_ARRAY = 9;
137
-
138
- /*
139
- Convert parsed ros arguments to parameters.
140
-
141
- type Parameter = {
142
- name: string,
143
- type: number,
144
- value: object
145
- }
146
-
147
- type Node = {
148
- name: string,
149
- parameters: array<Parameter>
150
- }
151
-
152
- parameters = array<Node>;
153
- */
154
- static v8::Local<v8::Object> wrapParameters(rcl_params_t* parsed_args) {
155
- v8::Local<v8::Array> nodes = Nan::New<v8::Array>();
156
-
157
- // iterate over nodes
158
- for (size_t i = 0; i < parsed_args->num_nodes; i++) {
159
- v8::Local<v8::Object> node = Nan::New<v8::Object>();
160
- Nan::Set(node, Nan::New("name").ToLocalChecked(),
161
- Nan::New(parsed_args->node_names[i]).ToLocalChecked());
162
-
163
- rcl_node_params_t node_parameters = parsed_args->params[i];
164
-
165
- // iterate over node.parameters
166
- v8::Local<v8::Array> parameters = Nan::New<v8::Array>();
167
- for (size_t j = 0; j < node_parameters.num_params; j++) {
168
- v8::Local<v8::Object> parameter = Nan::New<v8::Object>();
169
-
170
- Nan::Set(
171
- parameter, Nan::New("name").ToLocalChecked(),
172
- Nan::New(parsed_args->params[i].parameter_names[j]).ToLocalChecked());
173
-
174
- int param_type = PARAMETER_NOT_SET;
175
-
176
- // for each value, find type & actual value
177
- rcl_variant_t value = node_parameters.parameter_values[j];
178
- if (value.bool_value != NULL) { // NOLINT()
179
- param_type = PARAMETER_BOOL;
180
- Nan::Set(parameter, Nan::New("value").ToLocalChecked(),
181
- (*value.bool_value ? Nan::True() : Nan::False()));
182
- } else if (value.integer_value != NULL) { // NOLINT()
183
- param_type = PARAMETER_INTEGER;
184
- Nan::Set(parameter, Nan::New("value").ToLocalChecked(),
185
- Nan::New<v8::Number>(*value.integer_value));
186
- } else if (value.double_value != NULL) { // NOLINT()
187
- param_type = PARAMETER_DOUBLE;
188
- Nan::Set(parameter, Nan::New("value").ToLocalChecked(),
189
- Nan::New<v8::Number>(*value.double_value));
190
- } else if (value.string_value != NULL) { // NOLINT()
191
- param_type = PARAMETER_STRING;
192
- Nan::Set(parameter, Nan::New("value").ToLocalChecked(),
193
- Nan::New(value.string_value).ToLocalChecked());
194
- } else if (value.bool_array_value != NULL) { // NOLINT()
195
- param_type = PARAMETER_BOOL_ARRAY;
196
- v8::Local<v8::Array> bool_array = Nan::New<v8::Array>();
197
-
198
- for (size_t k = 0; k < value.bool_array_value->size; k++) {
199
- Nan::Set(
200
- bool_array, k,
201
- (value.bool_array_value->values[k] ? Nan::True() : Nan::False()));
202
- }
203
- Nan::Set(parameter, Nan::New("value").ToLocalChecked(), bool_array);
204
- } else if (value.string_array_value != NULL) { // NOLINT()
205
- param_type = PARAMETER_STRING_ARRAY;
206
- v8::Local<v8::Array> string_array = Nan::New<v8::Array>();
207
- for (size_t k = 0; k < value.string_array_value->size; k++) {
208
- Nan::Set(string_array, k,
209
- Nan::New(value.string_array_value->data[k])
210
- .ToLocalChecked()); // NOLINT(whitespace/line_length)
211
- }
212
- Nan::Set(parameter, Nan::New("value").ToLocalChecked(), string_array);
213
- } else if (value.byte_array_value != NULL) { // NOLINT()
214
- param_type = PARAMETER_BYTE_ARRAY;
215
- v8::Local<v8::Array> byte_array = Nan::New<v8::Array>();
216
- for (size_t k = 0; k < value.byte_array_value->size; k++) {
217
- Nan::Set(byte_array, k, Nan::New(value.byte_array_value->values[k]));
218
- }
219
- Nan::Set(parameter, Nan::New("value").ToLocalChecked(), byte_array);
220
- } else if (value.integer_array_value != NULL) { // NOLINT()
221
- param_type = PARAMETER_INTEGER_ARRAY;
222
- v8::Local<v8::Array> int_array = Nan::New<v8::Array>();
223
- for (size_t k = 0; k < value.integer_array_value->size; k++) {
224
- Nan::Set(int_array, k,
225
- Nan::New<v8::Number>(value.integer_array_value->values[k]));
226
- }
227
- Nan::Set(parameter, Nan::New("value").ToLocalChecked(), int_array);
228
- } else if (value.double_array_value != NULL) { // NOLINT()
229
- param_type = PARAMETER_DOUBLE_ARRAY;
230
- v8::Local<v8::Array> dbl_array = Nan::New<v8::Array>();
231
- for (size_t k = 0; k < value.double_array_value->size; k++) {
232
- Nan::Set(dbl_array, k,
233
- Nan::New<v8::Number>(
234
- value.double_array_value
235
- ->values[k])); // NOLINT(whitespace/line_length)
236
- }
237
- Nan::Set(parameter, Nan::New("value").ToLocalChecked(), dbl_array);
238
- }
239
-
240
- Nan::Set(parameter, Nan::New("type").ToLocalChecked(),
241
- Nan::New<v8::Number>(param_type));
242
- Nan::Set(parameters, j, parameter);
243
- }
244
-
245
- Nan::Set(node, Nan::New("parameters").ToLocalChecked(), parameters);
246
- Nan::Set(nodes, i, node);
247
- }
248
-
249
- return nodes;
250
- }
251
-
252
- NAN_METHOD(CreateNode) {
253
- std::string node_name(*Nan::Utf8String(info[0]));
254
- std::string name_space(*Nan::Utf8String(info[1]));
255
- RclHandle* context_handle = RclHandle::Unwrap<RclHandle>(
256
- Nan::To<v8::Object>(info[2]).ToLocalChecked());
257
- rcl_context_t* context =
258
- reinterpret_cast<rcl_context_t*>(context_handle->ptr());
259
-
260
- rcl_node_t* node = reinterpret_cast<rcl_node_t*>(malloc(sizeof(rcl_node_t)));
261
-
262
- *node = rcl_get_zero_initialized_node();
263
- rcl_node_options_t options = rcl_node_get_default_options();
264
-
265
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
266
- rcl_node_init(node, node_name.c_str(),
267
- name_space.c_str(), context, &options),
268
- rcl_get_error_string().str);
269
-
270
- auto handle = RclHandle::NewInstance(node, nullptr, [](void* ptr) {
271
- rcl_node_t* node = reinterpret_cast<rcl_node_t*>(ptr);
272
- rcl_ret_t ret = rcl_node_fini(node);
273
- free(ptr);
274
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, ret, rcl_get_error_string().str);
275
- });
276
- info.GetReturnValue().Set(handle);
277
- }
278
-
279
- NAN_METHOD(CreateGuardCondition) {
280
- RclHandle* context_handle = RclHandle::Unwrap<RclHandle>(
281
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
282
- rcl_context_t* context =
283
- reinterpret_cast<rcl_context_t*>(context_handle->ptr());
284
-
285
- rcl_guard_condition_t* gc = reinterpret_cast<rcl_guard_condition_t*>(
286
- malloc(sizeof(rcl_guard_condition_t)));
287
-
288
- *gc = rcl_get_zero_initialized_guard_condition();
289
- rcl_guard_condition_options_t gc_options =
290
- rcl_guard_condition_get_default_options();
291
-
292
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
293
- rcl_guard_condition_init(gc, context, gc_options),
294
- rcl_get_error_string().str);
295
-
296
- auto handle = RclHandle::NewInstance(gc, nullptr, [](void* ptr) {
297
- rcl_guard_condition_t* gc = reinterpret_cast<rcl_guard_condition_t*>(ptr);
298
- rcl_ret_t ret = rcl_guard_condition_fini(gc);
299
- free(ptr);
300
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, ret, rcl_get_error_string().str);
301
- });
302
- info.GetReturnValue().Set(handle);
303
- }
304
-
305
- NAN_METHOD(TriggerGuardCondition) {
306
- RclHandle* gc_handle = RclHandle::Unwrap<RclHandle>(
307
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
308
- rcl_guard_condition_t* gc =
309
- reinterpret_cast<rcl_guard_condition_t*>(gc_handle->ptr());
310
-
311
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, rcl_trigger_guard_condition(gc),
312
- rcl_get_error_string().str);
313
- }
314
-
315
- NAN_METHOD(CreateTimer) {
316
- RclHandle* clock_handle = RclHandle::Unwrap<RclHandle>(
317
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
318
- rcl_clock_t* clock = reinterpret_cast<rcl_clock_t*>(clock_handle->ptr());
319
- RclHandle* context_handle = RclHandle::Unwrap<RclHandle>(
320
- Nan::To<v8::Object>(info[1]).ToLocalChecked());
321
- rcl_context_t* context =
322
- reinterpret_cast<rcl_context_t*>(context_handle->ptr());
323
- if (!info[2]->IsBigInt()) {
324
- Nan::ThrowTypeError("Timer period must be a BigInt");
325
- return;
326
- }
327
- v8::Local<v8::BigInt> bigInt = info[2].As<v8::BigInt>();
328
- int64_t period_nsec = bigInt->Int64Value();
329
- rcl_timer_t* timer =
330
- reinterpret_cast<rcl_timer_t*>(malloc(sizeof(rcl_timer_t)));
331
- *timer = rcl_get_zero_initialized_timer();
332
-
333
- #if ROS_VERSION > 2305 // After Iron.
334
- THROW_ERROR_IF_NOT_EQUAL(
335
- RCL_RET_OK,
336
- rcl_timer_init2(timer, clock, context, period_nsec, nullptr,
337
- rcl_get_default_allocator(), /*autostart=*/true),
338
- rcl_get_error_string().str);
339
- #else
340
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
341
- rcl_timer_init(timer, clock, context, period_nsec,
342
- nullptr, rcl_get_default_allocator()),
343
- rcl_get_error_string().str);
344
- #endif
345
-
346
- auto js_obj = RclHandle::NewInstance(timer, clock_handle, [](void* ptr) {
347
- rcl_timer_t* timer = reinterpret_cast<rcl_timer_t*>(ptr);
348
- rcl_ret_t ret = rcl_timer_fini(timer);
349
- free(ptr);
350
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, ret, rcl_get_error_string().str);
351
- });
352
- info.GetReturnValue().Set(js_obj);
353
- }
354
-
355
- NAN_METHOD(IsTimerReady) {
356
- RclHandle* timer_handle = RclHandle::Unwrap<RclHandle>(
357
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
358
- rcl_timer_t* timer = reinterpret_cast<rcl_timer_t*>(timer_handle->ptr());
359
- bool is_ready = false;
360
-
361
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, rcl_timer_is_ready(timer, &is_ready),
362
- rcl_get_error_string().str);
363
-
364
- info.GetReturnValue().Set(Nan::New(is_ready));
365
- }
366
-
367
- NAN_METHOD(CallTimer) {
368
- RclHandle* timer_handle = RclHandle::Unwrap<RclHandle>(
369
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
370
- rcl_timer_t* timer = reinterpret_cast<rcl_timer_t*>(timer_handle->ptr());
371
-
372
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, rcl_timer_call(timer),
373
- rcl_get_error_string().str);
374
- }
375
-
376
- NAN_METHOD(CancelTimer) {
377
- RclHandle* timer_handle = RclHandle::Unwrap<RclHandle>(
378
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
379
- rcl_timer_t* timer = reinterpret_cast<rcl_timer_t*>(timer_handle->ptr());
380
-
381
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, rcl_timer_cancel(timer),
382
- rcl_get_error_string().str);
383
- }
384
-
385
- NAN_METHOD(IsTimerCanceled) {
386
- RclHandle* timer_handle = RclHandle::Unwrap<RclHandle>(
387
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
388
- rcl_timer_t* timer = reinterpret_cast<rcl_timer_t*>(timer_handle->ptr());
389
- bool is_canceled = false;
390
-
391
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
392
- rcl_timer_is_canceled(timer, &is_canceled),
393
- rcl_get_error_string().str);
394
-
395
- info.GetReturnValue().Set(Nan::New(is_canceled));
396
- }
397
-
398
- NAN_METHOD(ResetTimer) {
399
- RclHandle* timer_handle = RclHandle::Unwrap<RclHandle>(
400
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
401
- rcl_timer_t* timer = reinterpret_cast<rcl_timer_t*>(timer_handle->ptr());
402
-
403
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, rcl_timer_reset(timer),
404
- rcl_get_error_string().str);
405
- }
406
-
407
- NAN_METHOD(TimerGetTimeUntilNextCall) {
408
- RclHandle* timer_handle = RclHandle::Unwrap<RclHandle>(
409
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
410
- rcl_timer_t* timer = reinterpret_cast<rcl_timer_t*>(timer_handle->ptr());
411
- int64_t remaining_time = 0;
412
-
413
- THROW_ERROR_IF_NOT_EQUAL(
414
- RCL_RET_OK, rcl_timer_get_time_until_next_call(timer, &remaining_time),
415
- rcl_get_error_string().str);
416
-
417
- v8::Local<v8::BigInt> bigInt =
418
- v8::BigInt::New(v8::Isolate::GetCurrent(), remaining_time);
419
- info.GetReturnValue().Set(bigInt);
420
- }
421
-
422
- NAN_METHOD(TimerGetTimeSinceLastCall) {
423
- RclHandle* timer_handle = RclHandle::Unwrap<RclHandle>(
424
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
425
- rcl_timer_t* timer = reinterpret_cast<rcl_timer_t*>(timer_handle->ptr());
426
- int64_t elapsed_time = 0;
427
-
428
- THROW_ERROR_IF_NOT_EQUAL(
429
- RCL_RET_OK, rcl_timer_get_time_since_last_call(timer, &elapsed_time),
430
- rcl_get_error_string().str);
431
-
432
- v8::Local<v8::BigInt> bigInt =
433
- v8::BigInt::New(v8::Isolate::GetCurrent(), elapsed_time);
434
- info.GetReturnValue().Set(bigInt);
435
- }
436
-
437
- NAN_METHOD(CreateTimePoint) {
438
- if (!info[0]->IsBigInt()) {
439
- Nan::ThrowTypeError("Timer period must be a BigInt");
440
- return;
441
- }
442
- v8::Local<v8::BigInt> bigInt = info[0].As<v8::BigInt>();
443
- const int64_t nanoseconds = bigInt->Int64Value();
444
- uint32_t clock_type = Nan::To<uint32_t>(info[1]).FromJust();
445
- rcl_time_point_t* time_point =
446
- reinterpret_cast<rcl_time_point_t*>(malloc(sizeof(rcl_time_point_t)));
447
-
448
- time_point->nanoseconds = nanoseconds;
449
- time_point->clock_type = static_cast<rcl_clock_type_t>(clock_type);
450
-
451
- auto js_obj =
452
- RclHandle::NewInstance(time_point, nullptr, [](void* ptr) { free(ptr); });
453
- info.GetReturnValue().Set(js_obj);
454
- }
455
-
456
- NAN_METHOD(GetNanoseconds) {
457
- RclHandle* time_point_handle = RclHandle::Unwrap<RclHandle>(
458
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
459
- rcl_time_point_t* time_point =
460
- reinterpret_cast<rcl_time_point_t*>(time_point_handle->ptr());
461
- v8::Local<v8::BigInt> bigInt =
462
- v8::BigInt::New(v8::Isolate::GetCurrent(), time_point->nanoseconds);
463
- info.GetReturnValue().Set(bigInt);
464
- }
465
-
466
- NAN_METHOD(CreateDuration) {
467
- if (!info[0]->IsBigInt()) {
468
- Nan::ThrowTypeError("Timer period must be a BigInt");
469
- return;
470
- }
471
- v8::Local<v8::BigInt> bigInt = info[0].As<v8::BigInt>();
472
- const int64_t nanoseconds = bigInt->Int64Value();
473
- rcl_duration_t* duration =
474
- reinterpret_cast<rcl_duration_t*>(malloc(sizeof(rcl_duration_t)));
475
- duration->nanoseconds = nanoseconds;
476
-
477
- auto js_obj =
478
- RclHandle::NewInstance(duration, nullptr, [](void* ptr) { free(ptr); });
479
- info.GetReturnValue().Set(js_obj);
480
- }
481
-
482
- NAN_METHOD(GetDurationNanoseconds) {
483
- RclHandle* duration_handle = RclHandle::Unwrap<RclHandle>(
484
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
485
- rcl_duration_t* duration =
486
- reinterpret_cast<rcl_duration_t*>(duration_handle->ptr());
487
- v8::Local<v8::BigInt> bigInt =
488
- v8::BigInt::New(v8::Isolate::GetCurrent(), duration->nanoseconds);
489
- info.GetReturnValue().Set(bigInt);
490
- }
491
-
492
- NAN_METHOD(SetRosTimeOverrideIsEnabled) {
493
- RclHandle* clock_handle = RclHandle::Unwrap<RclHandle>(
494
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
495
- rcl_clock_t* clock = reinterpret_cast<rcl_clock_t*>(clock_handle->ptr());
496
- bool enabled = Nan::To<bool>(info[1]).FromJust();
497
-
498
- if (enabled) {
499
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, rcl_enable_ros_time_override(clock),
500
- rcl_get_error_string().str);
501
- } else {
502
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, rcl_disable_ros_time_override(clock),
503
- rcl_get_error_string().str);
504
- }
505
- info.GetReturnValue().Set(Nan::Undefined());
506
- }
507
-
508
- NAN_METHOD(SetRosTimeOverride) {
509
- RclHandle* clock_handle = RclHandle::Unwrap<RclHandle>(
510
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
511
- rcl_clock_t* clock = reinterpret_cast<rcl_clock_t*>(clock_handle->ptr());
512
- RclHandle* time_point_handle = RclHandle::Unwrap<RclHandle>(
513
- Nan::To<v8::Object>(info[1]).ToLocalChecked());
514
- rcl_time_point_t* time_point =
515
- reinterpret_cast<rcl_time_point_t*>(time_point_handle->ptr());
516
-
517
- THROW_ERROR_IF_NOT_EQUAL(
518
- RCL_RET_OK, rcl_set_ros_time_override(clock, time_point->nanoseconds),
519
- rcl_get_error_string().str);
520
- info.GetReturnValue().Set(Nan::Undefined());
521
- }
522
-
523
- NAN_METHOD(GetRosTimeOverrideIsEnabled) {
524
- RclHandle* clock_handle = RclHandle::Unwrap<RclHandle>(
525
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
526
- rcl_clock_t* clock = reinterpret_cast<rcl_clock_t*>(clock_handle->ptr());
527
-
528
- bool is_enabled;
529
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
530
- rcl_is_enabled_ros_time_override(clock, &is_enabled),
531
- rcl_get_error_string().str);
532
- info.GetReturnValue().Set(Nan::New(is_enabled));
533
- }
534
-
535
- NAN_METHOD(CreateClock) {
536
- auto clock_type =
537
- static_cast<rcl_clock_type_t>(Nan::To<int32_t>(info[0]).FromJust());
538
- rcl_clock_t* clock =
539
- reinterpret_cast<rcl_clock_t*>(malloc(sizeof(rcl_clock_t)));
540
- rcl_allocator_t allocator = rcl_get_default_allocator();
541
-
542
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
543
- rcl_clock_init(clock_type, clock, &allocator),
544
- rcl_get_error_string().str);
545
-
546
- info.GetReturnValue().Set(
547
- RclHandle::NewInstance(clock, nullptr, [](void* ptr) {
548
- rcl_clock_t* clock = reinterpret_cast<rcl_clock_t*>(ptr);
549
- rcl_ret_t ret = rcl_clock_fini(clock);
550
- free(ptr);
551
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, ret, rcl_get_error_string().str);
552
- }));
553
- }
554
-
555
- NAN_METHOD(ClockGetNow) {
556
- rcl_clock_t* clock = reinterpret_cast<rcl_clock_t*>(
557
- RclHandle::Unwrap<RclHandle>(
558
- Nan::To<v8::Object>(info[0]).ToLocalChecked())
559
- ->ptr());
560
- rcl_time_point_t time_point;
561
- time_point.clock_type = clock->type;
562
-
563
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
564
- rcl_clock_get_now(clock, &time_point.nanoseconds),
565
- rcl_get_error_string().str);
566
- v8::Local<v8::BigInt> bigInt =
567
- v8::BigInt::New(v8::Isolate::GetCurrent(), time_point.nanoseconds);
568
- info.GetReturnValue().Set(bigInt);
569
- }
570
-
571
- NAN_METHOD(RclTake) {
572
- RclHandle* subscription_handle = RclHandle::Unwrap<RclHandle>(
573
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
574
- rcl_subscription_t* subscription =
575
- reinterpret_cast<rcl_subscription_t*>(subscription_handle->ptr());
576
- void* msg_taken =
577
- node::Buffer::Data(Nan::To<v8::Object>(info[1]).ToLocalChecked());
578
- rcl_ret_t ret = rcl_take(subscription, msg_taken, nullptr, nullptr);
579
-
580
- if (ret != RCL_RET_OK && ret != RCL_RET_SUBSCRIPTION_TAKE_FAILED) {
581
- Nan::ThrowError(rcl_get_error_string().str);
582
- rcl_reset_error();
583
- info.GetReturnValue().Set(Nan::False());
584
- return;
585
- }
586
-
587
- if (ret != RCL_RET_SUBSCRIPTION_TAKE_FAILED) {
588
- info.GetReturnValue().Set(Nan::True());
589
- return;
590
- }
591
- info.GetReturnValue().Set(Nan::Undefined());
592
- }
593
-
594
- NAN_METHOD(CreateSubscription) {
595
- v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
596
- RclHandle* node_handle = RclHandle::Unwrap<RclHandle>(
597
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
598
- rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
599
- std::string package_name(
600
- *Nan::Utf8String(info[1]->ToString(currentContent).ToLocalChecked()));
601
- std::string message_sub_folder(
602
- *Nan::Utf8String(info[2]->ToString(currentContent).ToLocalChecked()));
603
- std::string message_name(
604
- *Nan::Utf8String(info[3]->ToString(currentContent).ToLocalChecked()));
605
- std::string topic(
606
- *Nan::Utf8String(info[4]->ToString(currentContent).ToLocalChecked()));
607
- v8::Local<v8::Object> options =
608
- info[5]->ToObject(currentContent).ToLocalChecked();
609
-
610
- rcl_subscription_t* subscription =
611
- reinterpret_cast<rcl_subscription_t*>(malloc(sizeof(rcl_subscription_t)));
612
- *subscription = rcl_get_zero_initialized_subscription();
613
-
614
- rcl_subscription_options_t subscription_ops =
615
- rcl_subscription_get_default_options();
616
-
617
- v8::Local<v8::Value> qos =
618
- Nan::Get(options, Nan::New("qos").ToLocalChecked()).ToLocalChecked();
619
- auto qos_profile = GetQoSProfile(qos);
620
- if (qos_profile) {
621
- subscription_ops.qos = *qos_profile;
622
- }
623
-
624
- #if ROS_VERSION >= 2205 // 2205 => Humble+
625
- if (Nan::Has(options, Nan::New("contentFilter").ToLocalChecked())
626
- .FromMaybe(false)) {
627
- // configure content-filter
628
- v8::MaybeLocal<v8::Value> contentFilterVal =
629
- Nan::Get(options, Nan::New("contentFilter").ToLocalChecked());
630
-
631
- if (!Nan::Equals(contentFilterVal.ToLocalChecked(), Nan::Undefined())
632
- .ToChecked()) {
633
- v8::Local<v8::Object> contentFilter = contentFilterVal.ToLocalChecked()
634
- ->ToObject(currentContent)
635
- .ToLocalChecked();
636
-
637
- // expression property is required
638
- std::string expression(*Nan::Utf8String(
639
- Nan::Get(contentFilter, Nan::New("expression").ToLocalChecked())
640
- .ToLocalChecked()
641
- ->ToString(currentContent)
642
- .ToLocalChecked()));
643
-
644
- // parameters property (string[]) is optional
645
- int argc = 0;
646
- char** argv = nullptr;
647
-
648
- if (Nan::Has(contentFilter, Nan::New("parameters").ToLocalChecked())
649
- .FromMaybe(false)) {
650
- v8::Local<v8::Array> jsArgv = v8::Local<v8::Array>::Cast(
651
- Nan::Get(contentFilter, Nan::New("parameters").ToLocalChecked())
652
- .ToLocalChecked());
653
- argc = jsArgv->Length();
654
- if (argc > 0) {
655
- argv = reinterpret_cast<char**>(malloc(argc * sizeof(char*)));
656
- for (int i = 0; i < argc; i++) {
657
- Nan::MaybeLocal<v8::Value> jsElement = Nan::Get(jsArgv, i);
658
- Nan::Utf8String utf8_arg(jsElement.ToLocalChecked());
659
- int len = utf8_arg.length() + 1;
660
- argv[i] = reinterpret_cast<char*>(malloc(len * sizeof(char*)));
661
- snprintf(argv[i], len, "%s", *utf8_arg);
662
- }
663
- }
664
- }
665
-
666
- rcl_ret_t ret = rcl_subscription_options_set_content_filter_options(
667
- expression.c_str(), argc, (const char**)argv, &subscription_ops);
668
-
669
- if (ret != RCL_RET_OK) {
670
- Nan::ThrowError(rcl_get_error_string().str);
671
- rcl_reset_error();
672
- }
673
-
674
- if (argc) {
675
- for (int i = 0; i < argc; i++) {
676
- free(argv[i]);
677
- }
678
- free(argv);
679
- }
680
- }
681
- }
682
-
683
- #endif
684
-
685
- const rosidl_message_type_support_t* ts =
686
- GetMessageTypeSupport(package_name, message_sub_folder, message_name);
687
-
688
- if (ts) {
689
- THROW_ERROR_IF_NOT_EQUAL(
690
- RCL_RET_OK,
691
- rcl_subscription_init(subscription, node, ts, topic.c_str(),
692
- &subscription_ops),
693
- rcl_get_error_string().str);
694
-
695
- auto js_obj =
696
- RclHandle::NewInstance(subscription, node_handle, [node](void* ptr) {
697
- rcl_subscription_t* subscription =
698
- reinterpret_cast<rcl_subscription_t*>(ptr);
699
- rcl_ret_t ret = rcl_subscription_fini(subscription, node);
700
- free(ptr);
701
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, ret, rcl_get_error_string().str);
702
- });
703
- info.GetReturnValue().Set(js_obj);
704
- } else {
705
- Nan::ThrowError(GetErrorMessageAndClear().c_str());
706
- }
707
- }
708
-
709
- NAN_METHOD(HasContentFilter) {
710
- #if ROS_VERSION < 2205 // 2205 => Humble+
711
- info.GetReturnValue().Set(Nan::False());
712
- return;
713
- #else
714
- RclHandle* subscription_handle = RclHandle::Unwrap<RclHandle>(
715
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
716
- rcl_subscription_t* subscription =
717
- reinterpret_cast<rcl_subscription_t*>(subscription_handle->ptr());
718
-
719
- bool is_valid = rcl_subscription_is_cft_enabled(subscription);
720
- info.GetReturnValue().Set(Nan::New(is_valid));
721
- #endif
722
- }
723
-
724
- NAN_METHOD(SetContentFilter) {
725
- #if ROS_VERSION < 2205 // 2205 => Humble+
726
- info.GetReturnValue().Set(Nan::False());
727
- return;
728
- #else
729
- v8::Local<v8::Context> currentContext = Nan::GetCurrentContext();
730
- RclHandle* subscription_handle = RclHandle::Unwrap<RclHandle>(
731
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
732
- rcl_subscription_t* subscription =
733
- reinterpret_cast<rcl_subscription_t*>(subscription_handle->ptr());
734
-
735
- v8::Local<v8::Object> contentFilter =
736
- info[1]->ToObject(currentContext).ToLocalChecked();
737
-
738
- Nan::MaybeLocal<v8::Value> jsExpression =
739
- Nan::Get(contentFilter, Nan::New("expression").ToLocalChecked());
740
- Nan::Utf8String utf8_arg(jsExpression.ToLocalChecked());
741
- int len = utf8_arg.length() + 1;
742
- char* expression = reinterpret_cast<char*>(malloc(len * sizeof(char*)));
743
- snprintf(expression, len, "%s", *utf8_arg);
744
-
745
- // parameters property (string[]) is optional
746
- int argc = 0;
747
- char** argv = nullptr;
748
-
749
- if (Nan::Has(contentFilter, Nan::New("parameters").ToLocalChecked())
750
- .FromMaybe(false)) {
751
- v8::Local<v8::Array> jsArgv = v8::Local<v8::Array>::Cast(
752
- Nan::Get(contentFilter, Nan::New("parameters").ToLocalChecked())
753
- .ToLocalChecked());
754
- argc = jsArgv->Length();
755
- if (argc > 0) {
756
- argv = reinterpret_cast<char**>(malloc(argc * sizeof(char*)));
757
- for (int i = 0; i < argc; i++) {
758
- Nan::MaybeLocal<v8::Value> jsElement = Nan::Get(jsArgv, i);
759
- Nan::Utf8String utf8_arg(jsElement.ToLocalChecked());
760
- int len = utf8_arg.length() + 1;
761
- argv[i] = reinterpret_cast<char*>(malloc(len * sizeof(char*)));
762
- snprintf(argv[i], len, "%s", *utf8_arg);
763
- }
764
- }
765
- }
766
-
767
- // create ctf options
768
- rcl_subscription_content_filter_options_t options =
769
- rcl_get_zero_initialized_subscription_content_filter_options();
770
-
771
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
772
- rcl_subscription_content_filter_options_set(
773
- subscription,
774
- expression, // expression.c_str(),
775
- argc, (const char**)argv, &options),
776
- rcl_get_error_string().str);
777
-
778
- THROW_ERROR_IF_NOT_EQUAL(
779
- RCL_RET_OK, rcl_subscription_set_content_filter(subscription, &options),
780
- rcl_get_error_string().str);
781
-
782
- if (argc) {
783
- free(expression);
784
-
785
- for (int i = 0; i < argc; i++) {
786
- free(argv[i]);
787
- }
788
- free(argv);
789
- }
790
-
791
- info.GetReturnValue().Set(Nan::True());
792
- #endif
793
- }
794
-
795
- NAN_METHOD(ClearContentFilter) {
796
- #if ROS_VERSION < 2205 // 2205 => Humble+
797
- info.GetReturnValue().Set(Nan::False());
798
- return;
799
- #else
800
- RclHandle* subscription_handle = RclHandle::Unwrap<RclHandle>(
801
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
802
- rcl_subscription_t* subscription =
803
- reinterpret_cast<rcl_subscription_t*>(subscription_handle->ptr());
804
-
805
- // create ctf options
806
- rcl_subscription_content_filter_options_t options =
807
- rcl_get_zero_initialized_subscription_content_filter_options();
808
-
809
- THROW_ERROR_IF_NOT_EQUAL(
810
- RCL_RET_OK,
811
- rcl_subscription_content_filter_options_init(
812
- subscription, "", 0, (const char**)nullptr, &options),
813
- rcl_get_error_string().str);
814
-
815
- THROW_ERROR_IF_NOT_EQUAL(
816
- RCL_RET_OK, rcl_subscription_set_content_filter(subscription, &options),
817
- rcl_get_error_string().str);
818
-
819
- info.GetReturnValue().Set(Nan::True());
820
- #endif
821
- }
822
-
823
- NAN_METHOD(CreatePublisher) {
824
- v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
825
- // Extract arguments
826
- RclHandle* node_handle = RclHandle::Unwrap<RclHandle>(
827
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
828
- rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
829
- std::string package_name(
830
- *Nan::Utf8String(info[1]->ToString(currentContent).ToLocalChecked()));
831
- std::string message_sub_folder(
832
- *Nan::Utf8String(info[2]->ToString(currentContent).ToLocalChecked()));
833
- std::string message_name(
834
- *Nan::Utf8String(info[3]->ToString(currentContent).ToLocalChecked()));
835
- std::string topic(
836
- *Nan::Utf8String(info[4]->ToString(currentContent).ToLocalChecked()));
837
-
838
- // Prepare publisher object
839
- rcl_publisher_t* publisher =
840
- reinterpret_cast<rcl_publisher_t*>(malloc(sizeof(rcl_publisher_t)));
841
- *publisher = rcl_get_zero_initialized_publisher();
842
-
843
- // Get type support object dynamically
844
- const rosidl_message_type_support_t* ts =
845
- GetMessageTypeSupport(package_name, message_sub_folder, message_name);
846
-
847
- if (ts) {
848
- // Using default options
849
- rcl_publisher_options_t publisher_ops = rcl_publisher_get_default_options();
850
- auto qos_profile = GetQoSProfile(info[5]);
851
-
852
- if (qos_profile) {
853
- publisher_ops.qos = *qos_profile;
854
- }
855
-
856
- // Initialize the publisher
857
- THROW_ERROR_IF_NOT_EQUAL(
858
- rcl_publisher_init(publisher, node, ts, topic.c_str(), &publisher_ops),
859
- RCL_RET_OK, rcl_get_error_string().str);
860
-
861
- // Wrap the handle into JS object
862
- auto js_obj =
863
- RclHandle::NewInstance(publisher, node_handle, [node](void* ptr) {
864
- rcl_publisher_t* publisher = reinterpret_cast<rcl_publisher_t*>(ptr);
865
- rcl_ret_t ret = rcl_publisher_fini(publisher, node);
866
- free(ptr);
867
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, ret, rcl_get_error_string().str);
868
- });
869
-
870
- // Everything is done
871
- info.GetReturnValue().Set(js_obj);
872
- } else {
873
- Nan::ThrowError(GetErrorMessageAndClear().c_str());
874
- }
875
- }
876
-
877
- NAN_METHOD(Publish) {
878
- rcl_publisher_t* publisher = reinterpret_cast<rcl_publisher_t*>(
879
- RclHandle::Unwrap<RclHandle>(
880
- Nan::To<v8::Object>(info[0]).ToLocalChecked())
881
- ->ptr());
882
-
883
- void* buffer =
884
- node::Buffer::Data(Nan::To<v8::Object>(info[1]).ToLocalChecked());
885
- THROW_ERROR_IF_NOT_EQUAL(rcl_publish(publisher, buffer, nullptr), RCL_RET_OK,
886
- rcl_get_error_string().str);
887
-
888
- info.GetReturnValue().Set(Nan::Undefined());
889
- }
890
-
891
- NAN_METHOD(GetPublisherTopic) {
892
- rcl_publisher_t* publisher = reinterpret_cast<rcl_publisher_t*>(
893
- RclHandle::Unwrap<RclHandle>(
894
- Nan::To<v8::Object>(info[0]).ToLocalChecked())
895
- ->ptr());
896
-
897
- const char* topic = rcl_publisher_get_topic_name(publisher);
898
- info.GetReturnValue().Set(Nan::New(topic).ToLocalChecked());
899
- }
900
-
901
- NAN_METHOD(GetSubscriptionTopic) {
902
- rcl_subscription_t* subscription = reinterpret_cast<rcl_subscription_t*>(
903
- RclHandle::Unwrap<RclHandle>(
904
- Nan::To<v8::Object>(info[0]).ToLocalChecked())
905
- ->ptr());
906
-
907
- const char* topic = rcl_subscription_get_topic_name(subscription);
908
- info.GetReturnValue().Set(Nan::New(topic).ToLocalChecked());
909
- }
910
-
911
- NAN_METHOD(CreateClient) {
912
- v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
913
- RclHandle* node_handle = RclHandle::Unwrap<RclHandle>(
914
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
915
- rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
916
- std::string service_name(
917
- *Nan::Utf8String(info[1]->ToString(currentContent).ToLocalChecked()));
918
- std::string interface_name(
919
- *Nan::Utf8String(info[2]->ToString(currentContent).ToLocalChecked()));
920
- std::string package_name(
921
- *Nan::Utf8String(info[3]->ToString(currentContent).ToLocalChecked()));
922
-
923
- const rosidl_service_type_support_t* ts =
924
- GetServiceTypeSupport(package_name, interface_name);
925
-
926
- if (ts) {
927
- rcl_client_t* client =
928
- reinterpret_cast<rcl_client_t*>(malloc(sizeof(rcl_client_t)));
929
- *client = rcl_get_zero_initialized_client();
930
- rcl_client_options_t client_ops = rcl_client_get_default_options();
931
- auto qos_profile = GetQoSProfile(info[4]);
932
-
933
- if (qos_profile) {
934
- client_ops.qos = *qos_profile;
935
- }
936
-
937
- THROW_ERROR_IF_NOT_EQUAL(
938
- rcl_client_init(client, node, ts, service_name.c_str(), &client_ops),
939
- RCL_RET_OK, rcl_get_error_string().str);
940
-
941
- auto js_obj =
942
- RclHandle::NewInstance(client, node_handle, [node](void* ptr) {
943
- rcl_client_t* client = reinterpret_cast<rcl_client_t*>(ptr);
944
- rcl_ret_t ret = rcl_client_fini(client, node);
945
- free(ptr);
946
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, ret, rcl_get_error_string().str);
947
- });
948
-
949
- info.GetReturnValue().Set(js_obj);
950
- } else {
951
- Nan::ThrowError(GetErrorMessageAndClear().c_str());
952
- }
953
- }
954
-
955
- NAN_METHOD(SendRequest) {
956
- rcl_client_t* client = reinterpret_cast<rcl_client_t*>(
957
- RclHandle::Unwrap<RclHandle>(
958
- Nan::To<v8::Object>(info[0]).ToLocalChecked())
959
- ->ptr());
960
- void* buffer =
961
- node::Buffer::Data(Nan::To<v8::Object>(info[1]).ToLocalChecked());
962
- int64_t sequence_number;
963
-
964
- THROW_ERROR_IF_NOT_EQUAL(rcl_send_request(client, buffer, &sequence_number),
965
- RCL_RET_OK, rcl_get_error_string().str);
31
+ Napi::Value InitString(const Napi::CallbackInfo& info) {
32
+ Napi::Env env = info.Env();
966
33
 
967
- info.GetReturnValue().Set(Nan::New(static_cast<uint32_t>(sequence_number)));
968
- }
969
-
970
- NAN_METHOD(RclTakeResponse) {
971
- rcl_client_t* client = reinterpret_cast<rcl_client_t*>(
972
- RclHandle::Unwrap<RclHandle>(
973
- Nan::To<v8::Object>(info[0]).ToLocalChecked())
974
- ->ptr());
975
-
976
- rmw_service_info_t header;
977
-
978
- void* taken_response =
979
- node::Buffer::Data(Nan::To<v8::Object>(info[1]).ToLocalChecked());
980
- rcl_ret_t ret = rcl_take_response_with_info(client, &header, taken_response);
981
- int64_t sequence_number = header.request_id.sequence_number;
982
-
983
- if (ret == RCL_RET_OK) {
984
- info.GetReturnValue().Set(Nan::New(static_cast<uint32_t>(sequence_number)));
985
- return;
986
- }
987
-
988
- rcl_reset_error();
989
- info.GetReturnValue().Set(Nan::Undefined());
990
- }
991
-
992
- NAN_METHOD(CreateService) {
993
- v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
994
- RclHandle* node_handle = RclHandle::Unwrap<RclHandle>(
995
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
996
- rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
997
- std::string service_name(
998
- *Nan::Utf8String(info[1]->ToString(currentContent).ToLocalChecked()));
999
- std::string interface_name(
1000
- *Nan::Utf8String(info[2]->ToString(currentContent).ToLocalChecked()));
1001
- std::string package_name(
1002
- *Nan::Utf8String(info[3]->ToString(currentContent).ToLocalChecked()));
1003
-
1004
- const rosidl_service_type_support_t* ts =
1005
- GetServiceTypeSupport(package_name, interface_name);
1006
-
1007
- if (ts) {
1008
- rcl_service_t* service =
1009
- reinterpret_cast<rcl_service_t*>(malloc(sizeof(rcl_service_t)));
1010
- *service = rcl_get_zero_initialized_service();
1011
- rcl_service_options_t service_ops = rcl_service_get_default_options();
1012
- auto qos_profile = GetQoSProfile(info[4]);
1013
-
1014
- if (qos_profile) {
1015
- service_ops.qos = *qos_profile;
1016
- }
1017
-
1018
- THROW_ERROR_IF_NOT_EQUAL(
1019
- rcl_service_init(service, node, ts, service_name.c_str(), &service_ops),
1020
- RCL_RET_OK, rcl_get_error_string().str);
1021
- auto js_obj =
1022
- RclHandle::NewInstance(service, node_handle, [node](void* ptr) {
1023
- rcl_service_t* service = reinterpret_cast<rcl_service_t*>(ptr);
1024
- rcl_ret_t ret = rcl_service_fini(service, node);
1025
- free(ptr);
1026
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, ret, rcl_get_error_string().str);
1027
- });
1028
-
1029
- info.GetReturnValue().Set(js_obj);
1030
- } else {
1031
- Nan::ThrowError(GetErrorMessageAndClear().c_str());
1032
- }
1033
- }
1034
-
1035
- NAN_METHOD(RclTakeRequest) {
1036
- rcl_service_t* service = reinterpret_cast<rcl_service_t*>(
1037
- RclHandle::Unwrap<RclHandle>(
1038
- Nan::To<v8::Object>(info[0]).ToLocalChecked())
1039
- ->ptr());
1040
- rmw_request_id_t* header =
1041
- reinterpret_cast<rmw_request_id_t*>(malloc(sizeof(rmw_request_id_t)));
1042
-
1043
- void* taken_request =
1044
- node::Buffer::Data(Nan::To<v8::Object>(info[2]).ToLocalChecked());
1045
- rcl_ret_t ret = rcl_take_request(service, header, taken_request);
1046
- if (ret != RCL_RET_SERVICE_TAKE_FAILED) {
1047
- auto js_obj =
1048
- RclHandle::NewInstance(header, nullptr, [](void* ptr) { free(ptr); });
1049
- info.GetReturnValue().Set(js_obj);
1050
- return;
1051
- }
1052
-
1053
- info.GetReturnValue().Set(Nan::Undefined());
1054
- }
1055
-
1056
- NAN_METHOD(SendResponse) {
1057
- rcl_service_t* service = reinterpret_cast<rcl_service_t*>(
1058
- RclHandle::Unwrap<RclHandle>(
1059
- Nan::To<v8::Object>(info[0]).ToLocalChecked())
1060
- ->ptr());
1061
- void* buffer =
1062
- node::Buffer::Data(Nan::To<v8::Object>(info[1]).ToLocalChecked());
1063
-
1064
- rmw_request_id_t* header = reinterpret_cast<rmw_request_id_t*>(
1065
- RclHandle::Unwrap<RclHandle>(
1066
- Nan::To<v8::Object>(info[2]).ToLocalChecked())
1067
- ->ptr());
1068
-
1069
- THROW_ERROR_IF_NOT_EQUAL(rcl_send_response(service, header, buffer),
1070
- RCL_RET_OK, rcl_get_error_string().str);
1071
- }
1072
-
1073
- #if ROS_VERSION > 2205 // 2205 == Humble
1074
- NAN_METHOD(ConfigureServiceIntrospection) {
1075
- v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
1076
-
1077
- RclHandle* node_handle = RclHandle::Unwrap<RclHandle>(
1078
- Nan::To<v8::Object>(info[1]).ToLocalChecked());
1079
- rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
1080
-
1081
- rcl_clock_t* clock = reinterpret_cast<rcl_clock_t*>(
1082
- RclHandle::Unwrap<RclHandle>(
1083
- Nan::To<v8::Object>(info[2]).ToLocalChecked())
1084
- ->ptr());
1085
-
1086
- std::string interface_name(
1087
- *Nan::Utf8String(info[3]->ToString(currentContent).ToLocalChecked()));
1088
- std::string package_name(
1089
- *Nan::Utf8String(info[4]->ToString(currentContent).ToLocalChecked()));
1090
- const rosidl_service_type_support_t* ts =
1091
- GetServiceTypeSupport(package_name, interface_name);
1092
-
1093
- if (ts) {
1094
- rcl_publisher_options_t publisher_ops = rcl_publisher_get_default_options();
1095
- auto qos_profile = GetQoSProfile(info[5]);
1096
- if (qos_profile) {
1097
- publisher_ops.qos = *qos_profile;
1098
- }
1099
-
1100
- rcl_service_introspection_state_t state =
1101
- static_cast<rcl_service_introspection_state_t>(
1102
- Nan::To<uint32_t>(info[6]).ToChecked());
1103
-
1104
- bool configureForService = Nan::To<bool>(info[7]).FromJust();
1105
-
1106
- if (configureForService) {
1107
- RclHandle* service_handle = RclHandle::Unwrap<RclHandle>(
1108
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
1109
- rcl_service_t* service =
1110
- reinterpret_cast<rcl_service_t*>(service_handle->ptr());
1111
-
1112
- THROW_ERROR_IF_NOT_EQUAL(
1113
- rcl_service_configure_service_introspection(service, node, clock, ts,
1114
- publisher_ops, state),
1115
- RCL_RET_OK, rcl_get_error_string().str);
1116
-
1117
- } else {
1118
- RclHandle* client_handle = RclHandle::Unwrap<RclHandle>(
1119
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
1120
- rcl_client_t* client =
1121
- reinterpret_cast<rcl_client_t*>(client_handle->ptr());
1122
-
1123
- THROW_ERROR_IF_NOT_EQUAL(
1124
- rcl_client_configure_service_introspection(client, node, clock, ts,
1125
- publisher_ops, state),
1126
- RCL_RET_OK, rcl_get_error_string().str);
1127
- }
1128
-
1129
- } else {
1130
- Nan::ThrowError(GetErrorMessageAndClear().c_str());
1131
- }
1132
- }
1133
- #endif
1134
-
1135
- NAN_METHOD(ValidateFullTopicName) {
1136
- v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
1137
- int validation_result;
1138
- size_t invalid_index;
1139
- std::string topic_name(
1140
- *Nan::Utf8String(info[0]->ToString(currentContent).ToLocalChecked()));
1141
- rmw_ret_t ret = rmw_validate_full_topic_name(
1142
- topic_name.c_str(), &validation_result, &invalid_index);
1143
-
1144
- if (ret != RMW_RET_OK) {
1145
- if (ret == RMW_RET_BAD_ALLOC) {
1146
- Nan::ThrowError(rmw_get_error_string().str);
1147
- }
1148
- rmw_reset_error();
1149
- return info.GetReturnValue().Set(Nan::Undefined());
1150
- }
1151
-
1152
- if (validation_result == RMW_NAMESPACE_VALID) {
1153
- info.GetReturnValue().Set(Nan::Null());
1154
- return;
1155
- }
1156
- const char* validation_message =
1157
- rmw_full_topic_name_validation_result_string(validation_result);
1158
- THROW_ERROR_IF_EQUAL(nullptr, validation_message,
1159
- "Unable to get validation error message");
1160
-
1161
- v8::Local<v8::Array> result_list = Nan::New<v8::Array>(2);
1162
- Nan::Set(
1163
- result_list, 0,
1164
- Nan::New<v8::String>(std::string(validation_message)).ToLocalChecked());
1165
- Nan::Set(result_list, 1, Nan::New(static_cast<int32_t>(invalid_index)));
1166
-
1167
- info.GetReturnValue().Set(result_list);
1168
- }
1169
-
1170
- NAN_METHOD(ValidateNodeName) {
1171
- v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
1172
- int validation_result;
1173
- size_t invalid_index;
1174
- std::string node_name(
1175
- *Nan::Utf8String(info[0]->ToString(currentContent).ToLocalChecked()));
1176
- rmw_ret_t ret = rmw_validate_node_name(node_name.c_str(), &validation_result,
1177
- &invalid_index);
1178
-
1179
- if (ret != RMW_RET_OK) {
1180
- if (ret == RMW_RET_BAD_ALLOC) {
1181
- Nan::ThrowError(rmw_get_error_string().str);
1182
- }
1183
- rmw_reset_error();
1184
- return info.GetReturnValue().Set(Nan::Undefined());
1185
- }
1186
-
1187
- if (validation_result == RMW_NODE_NAME_VALID) {
1188
- info.GetReturnValue().Set(Nan::Null());
1189
- return;
1190
- }
1191
- const char* validation_message =
1192
- rmw_node_name_validation_result_string(validation_result);
1193
- THROW_ERROR_IF_EQUAL(nullptr, validation_message,
1194
- "Unable to get validation error message");
1195
-
1196
- v8::Local<v8::Array> result_list = Nan::New<v8::Array>(2);
1197
- Nan::Set(
1198
- result_list, 0,
1199
- Nan::New<v8::String>(std::string(validation_message)).ToLocalChecked());
1200
- Nan::Set(result_list, 1, Nan::New(static_cast<int32_t>(invalid_index)));
1201
-
1202
- info.GetReturnValue().Set(result_list);
1203
- }
1204
-
1205
- NAN_METHOD(ValidateTopicName) {
1206
- v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
1207
- int validation_result;
1208
- size_t invalid_index;
1209
- std::string topic_name(
1210
- *Nan::Utf8String(info[0]->ToString(currentContent).ToLocalChecked()));
1211
- rmw_ret_t ret = rcl_validate_topic_name(topic_name.c_str(),
1212
- &validation_result, &invalid_index);
1213
-
1214
- if (ret != RMW_RET_OK) {
1215
- if (ret == RMW_RET_BAD_ALLOC) {
1216
- Nan::ThrowError(rmw_get_error_string().str);
1217
- }
1218
- rmw_reset_error();
1219
- return info.GetReturnValue().Set(Nan::Undefined());
1220
- }
1221
-
1222
- if (validation_result == RMW_NODE_NAME_VALID) {
1223
- info.GetReturnValue().Set(Nan::Null());
1224
- return;
1225
- }
1226
- const char* validation_message =
1227
- rcl_topic_name_validation_result_string(validation_result);
1228
- THROW_ERROR_IF_EQUAL(nullptr, validation_message,
1229
- "Unable to get validation error message");
1230
-
1231
- v8::Local<v8::Array> result_list = Nan::New<v8::Array>(2);
1232
- Nan::Set(
1233
- result_list, 0,
1234
- Nan::New<v8::String>(std::string(validation_message)).ToLocalChecked());
1235
- Nan::Set(result_list, 1, Nan::New(static_cast<int32_t>(invalid_index)));
1236
-
1237
- info.GetReturnValue().Set(result_list);
1238
- }
1239
-
1240
- NAN_METHOD(ValidateNamespace) {
1241
- v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
1242
- int validation_result;
1243
- size_t invalid_index;
1244
- std::string namespace_name(
1245
- *Nan::Utf8String(info[0]->ToString(currentContent).ToLocalChecked()));
1246
- rmw_ret_t ret = rmw_validate_namespace(namespace_name.c_str(),
1247
- &validation_result, &invalid_index);
1248
-
1249
- if (ret != RMW_RET_OK) {
1250
- if (ret == RMW_RET_BAD_ALLOC) {
1251
- Nan::ThrowError(rmw_get_error_string().str);
1252
- }
1253
- rmw_reset_error();
1254
- return info.GetReturnValue().Set(Nan::Undefined());
1255
- }
1256
-
1257
- if (validation_result == RMW_NODE_NAME_VALID) {
1258
- info.GetReturnValue().Set(Nan::Null());
1259
- return;
1260
- }
1261
- const char* validation_message =
1262
- rmw_namespace_validation_result_string(validation_result);
1263
- THROW_ERROR_IF_EQUAL(nullptr, validation_message,
1264
- "Unable to get validation error message");
1265
-
1266
- v8::Local<v8::Array> result_list = Nan::New<v8::Array>(2);
1267
- Nan::Set(
1268
- result_list, 0,
1269
- Nan::New<v8::String>(std::string(validation_message)).ToLocalChecked());
1270
- Nan::Set(result_list, 1, Nan::New(static_cast<int32_t>(invalid_index)));
1271
-
1272
- info.GetReturnValue().Set(result_list);
1273
- }
1274
-
1275
- NAN_METHOD(ExpandTopicName) {
1276
- v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
1277
- std::string topic_name(
1278
- *Nan::Utf8String(info[0]->ToString(currentContent).ToLocalChecked()));
1279
- std::string node_name(
1280
- *Nan::Utf8String(info[1]->ToString(currentContent).ToLocalChecked()));
1281
- std::string node_namespace(
1282
- *Nan::Utf8String(info[2]->ToString(currentContent).ToLocalChecked()));
1283
-
1284
- char* expanded_topic = nullptr;
1285
- rcl_allocator_t allocator = rcl_get_default_allocator();
1286
- rcutils_allocator_t rcutils_allocator = rcutils_get_default_allocator();
1287
- rcutils_string_map_t substitutions_map =
1288
- rcutils_get_zero_initialized_string_map();
1289
-
1290
- rcutils_ret_t rcutils_ret =
1291
- rcutils_string_map_init(&substitutions_map, 0, rcutils_allocator);
1292
- if (rcutils_ret != RCUTILS_RET_OK) {
1293
- if (rcutils_ret == RCUTILS_RET_BAD_ALLOC) {
1294
- Nan::ThrowError(rcutils_get_error_string().str);
1295
- }
1296
- rcutils_reset_error();
1297
- info.GetReturnValue().Set(Nan::Undefined());
1298
- return;
1299
- }
1300
- rcl_ret_t ret = rcl_get_default_topic_name_substitutions(&substitutions_map);
1301
- if (ret != RCL_RET_OK) {
1302
- if (ret == RCL_RET_BAD_ALLOC) {
1303
- Nan::ThrowError(rcl_get_error_string().str);
1304
- }
1305
- rcl_reset_error();
1306
-
1307
- rcutils_ret = rcutils_string_map_fini(&substitutions_map);
1308
- if (rcutils_ret != RCUTILS_RET_OK) {
1309
- Nan::ThrowError(rcutils_get_error_string().str);
1310
- rcutils_reset_error();
1311
- }
1312
- info.GetReturnValue().Set(Nan::Undefined());
1313
- return;
1314
- }
1315
-
1316
- ret = rcl_expand_topic_name(topic_name.c_str(), node_name.c_str(),
1317
- node_namespace.c_str(), &substitutions_map,
1318
- allocator, &expanded_topic);
1319
-
1320
- rcutils_ret = rcutils_string_map_fini(&substitutions_map);
1321
- if (rcutils_ret != RCUTILS_RET_OK) {
1322
- Nan::ThrowError(rcutils_get_error_string().str);
1323
- rcutils_reset_error();
1324
- allocator.deallocate(expanded_topic, allocator.state);
1325
- info.GetReturnValue().Set(Nan::Undefined());
1326
- return;
1327
- }
1328
- if (ret != RCL_RET_OK) {
1329
- Nan::ThrowError(rcl_get_error_string().str);
1330
- rcl_reset_error();
1331
- info.GetReturnValue().Set(Nan::Undefined());
1332
- return;
1333
- }
1334
-
1335
- if (!expanded_topic) {
1336
- info.GetReturnValue().Set(Nan::Undefined());
1337
- return;
1338
- }
1339
-
1340
- rcl_allocator_t topic_allocator = rcl_get_default_allocator();
1341
- std::string topic(expanded_topic);
1342
- allocator.deallocate(expanded_topic, topic_allocator.state);
1343
- info.GetReturnValue().Set(Nan::New<v8::String>(topic).ToLocalChecked());
1344
- }
1345
-
1346
- NAN_METHOD(GetNodeName) {
1347
- RclHandle* node_handle = RclHandle::Unwrap<RclHandle>(
1348
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
1349
- rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
1350
- const char* node_name = rcl_node_get_name(node);
1351
- if (!node_name) {
1352
- info.GetReturnValue().Set(Nan::Undefined());
1353
- } else {
1354
- info.GetReturnValue().Set(Nan::New<v8::String>(node_name).ToLocalChecked());
1355
- }
1356
- }
1357
-
1358
- NAN_METHOD(GetNamespace) {
1359
- RclHandle* node_handle = RclHandle::Unwrap<RclHandle>(
1360
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
1361
- rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
1362
- const char* node_namespace = rcl_node_get_namespace(node);
1363
- if (!node_namespace) {
1364
- info.GetReturnValue().Set(Nan::Undefined());
1365
- } else {
1366
- info.GetReturnValue().Set(
1367
- Nan::New<v8::String>(node_namespace).ToLocalChecked());
1368
- }
1369
- }
1370
-
1371
- const rmw_qos_profile_t* GetQoSProfileFromString(const std::string& profile) {
1372
- const rmw_qos_profile_t* qos_profile = nullptr;
1373
- if (profile == "qos_profile_sensor_data") {
1374
- qos_profile = &rmw_qos_profile_sensor_data;
1375
- } else if (profile == "qos_profile_system_default") {
1376
- qos_profile = &rmw_qos_profile_system_default;
1377
- } else if (profile == "qos_profile_services_default") {
1378
- qos_profile = &rmw_qos_profile_services_default;
1379
- } else if (profile == "qos_profile_parameters") {
1380
- qos_profile = &rmw_qos_profile_parameters;
1381
- } else if (profile == "qos_profile_parameter_events") {
1382
- qos_profile = &rmw_qos_profile_parameter_events;
1383
- } else if (profile == "qos_profile_action_status_default") {
1384
- qos_profile = &rcl_action_qos_profile_status_default;
1385
- } else {
1386
- return &rmw_qos_profile_default;
1387
- }
1388
-
1389
- return qos_profile;
1390
- }
1391
-
1392
- std::unique_ptr<rmw_qos_profile_t> GetQosProfileFromObject(
1393
- v8::Local<v8::Object> object) {
1394
- std::unique_ptr<rmw_qos_profile_t> qos_profile =
1395
- std::make_unique<rmw_qos_profile_t>();
1396
-
1397
- auto history =
1398
- Nan::Get(object, Nan::New("history").ToLocalChecked()).ToLocalChecked();
1399
- auto depth =
1400
- Nan::Get(object, Nan::New("depth").ToLocalChecked()).ToLocalChecked();
1401
- auto reliability = Nan::Get(object, Nan::New("reliability").ToLocalChecked())
1402
- .ToLocalChecked();
1403
- auto durability = Nan::Get(object, Nan::New("durability").ToLocalChecked())
1404
- .ToLocalChecked();
1405
- auto avoid_ros_namespace_conventions =
1406
- Nan::Get(object,
1407
- Nan::New("avoidRosNameSpaceConventions").ToLocalChecked())
1408
- .ToLocalChecked();
1409
-
1410
- qos_profile->history = static_cast<rmw_qos_history_policy_t>(
1411
- Nan::To<uint32_t>(history).FromJust());
1412
- qos_profile->depth = Nan::To<uint32_t>(depth).FromJust();
1413
- qos_profile->reliability = static_cast<rmw_qos_reliability_policy_t>(
1414
- Nan::To<uint32_t>(reliability).FromJust());
1415
- qos_profile->durability = static_cast<rmw_qos_durability_policy_t>(
1416
- Nan::To<uint32_t>(durability).FromJust());
1417
- qos_profile->avoid_ros_namespace_conventions =
1418
- Nan::To<bool>(avoid_ros_namespace_conventions).FromJust();
1419
-
1420
- return qos_profile;
1421
- }
1422
-
1423
- std::unique_ptr<rmw_qos_profile_t> GetQoSProfile(v8::Local<v8::Value> qos) {
1424
- v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
1425
- std::unique_ptr<rmw_qos_profile_t> qos_profile =
1426
- std::make_unique<rmw_qos_profile_t>();
1427
-
1428
- if (qos->IsString()) {
1429
- *qos_profile = *GetQoSProfileFromString(std::string(
1430
- *Nan::Utf8String(qos->ToString(currentContent).ToLocalChecked())));
1431
- } else if (qos->IsObject()) {
1432
- qos_profile =
1433
- GetQosProfileFromObject(Nan::To<v8::Object>(qos).ToLocalChecked());
1434
- } else {
1435
- return qos_profile;
1436
- }
1437
- return qos_profile;
1438
- }
1439
-
1440
- int DestroyContext(rcl_context_t* context) {
1441
- rcl_ret_t ret = RCL_RET_OK;
1442
- if (context->impl) {
1443
- if (rcl_context_is_valid(context)) {
1444
- if (RCL_RET_OK != rcl_shutdown(context)) {
1445
- Nan::ThrowError(rcl_get_error_string().str);
1446
- }
1447
- ret = rcl_context_fini(context);
1448
- }
1449
- }
1450
- return ret;
1451
- }
1452
-
1453
- NAN_METHOD(Shutdown) {
1454
- RclHandle* context_handle = RclHandle::Unwrap<RclHandle>(
1455
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
1456
- rcl_context_t* context =
1457
- reinterpret_cast<rcl_context_t*>(context_handle->ptr());
1458
- THROW_ERROR_IF_NOT_EQUAL(rcl_shutdown(context), RCL_RET_OK,
1459
- rcl_get_error_string().str);
1460
- THROW_ERROR_IF_NOT_EQUAL(rcl_logging_fini(), RCL_RET_OK,
1461
- rcl_get_error_string().str);
1462
-
1463
- info.GetReturnValue().Set(Nan::Undefined());
1464
- }
1465
-
1466
- NAN_METHOD(InitString) {
1467
- void* buffer =
1468
- node::Buffer::Data(Nan::To<v8::Object>(info[0]).ToLocalChecked());
34
+ void* buffer = info[0].As<Napi::Buffer<char>>().Data();
1469
35
  #if ROS_VERSION >= 2006
1470
36
  rosidl_runtime_c__String* ptr =
1471
37
  reinterpret_cast<rosidl_runtime_c__String*>(buffer);
@@ -1477,577 +43,74 @@ NAN_METHOD(InitString) {
1477
43
 
1478
44
  rosidl_generator_c__String__init(ptr);
1479
45
  #endif
1480
- info.GetReturnValue().Set(Nan::Undefined());
46
+ return env.Undefined();
1481
47
  }
1482
48
 
1483
- inline char* GetBufAddr(v8::Local<v8::Value> buf) {
1484
- return node::Buffer::Data(buf.As<v8::Object>());
49
+ inline char* GetBufAddr(Napi::Value buf) {
50
+ return buf.As<Napi::Buffer<char>>().Data();
1485
51
  }
1486
52
 
1487
- NAN_METHOD(FreeMemeoryAtOffset) {
1488
- v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
1489
- std::string addr_str(
1490
- *Nan::Utf8String(info[0]->ToString(currentContent).ToLocalChecked()));
53
+ Napi::Value FreeMemeoryAtOffset(const Napi::CallbackInfo& info) {
54
+ Napi::Env env = info.Env();
55
+
56
+ std::string addr_str = info[0].As<Napi::String>().Utf8Value();
1491
57
  int64_t result = std::stoull(addr_str, 0, 16);
1492
58
  char* addr = reinterpret_cast<char*>(result);
1493
59
  int64_t offset =
1494
- info[1]->IsNumber() ? Nan::To<int64_t>(info[1]).FromJust() : 0;
60
+ info[1].IsNumber() ? info[1].As<Napi::Number>().Int64Value() : 0;
1495
61
  auto ptr = addr + offset;
1496
62
 
1497
63
  char* val = *reinterpret_cast<char**>(ptr);
1498
64
  free(val);
1499
- info.GetReturnValue().Set(Nan::Undefined());
65
+ return env.Undefined();
1500
66
  }
1501
67
 
1502
- NAN_METHOD(CreateArrayBufferFromAddress) {
1503
- v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
1504
- std::string addr_str(
1505
- *Nan::Utf8String(info[0]->ToString(currentContent).ToLocalChecked()));
68
+ Napi::Value CreateArrayBufferFromAddress(const Napi::CallbackInfo& info) {
69
+ Napi::Env env = info.Env();
70
+
71
+ std::string addr_str = info[0].As<Napi::String>().Utf8Value();
1506
72
  int64_t result = std::stoull(addr_str, 0, 16);
1507
73
  char* addr = reinterpret_cast<char*>(result);
1508
- int32_t length = Nan::To<int32_t>(info[1]).FromJust();
74
+ int32_t length = info[1].As<Napi::Number>().Int32Value();
1509
75
 
1510
76
  static_assert(NODE_MAJOR_VERSION > 12, "nodejs version must > 12");
1511
77
  #if (NODE_RUNTIME_ELECTRON && NODE_MODULE_VERSION >= 109)
1512
78
  // Because V8 sandboxed pointers was enabled since Electron 21, we have to
1513
79
  // make a deep copy for Electron 21 and up.
1514
80
  // See more details: https://www.electronjs.org/blog/v8-memory-cage
1515
- v8::Local<v8::ArrayBuffer> array_buffer =
1516
- v8::ArrayBuffer::New(v8::Isolate::GetCurrent(), length);
1517
- memcpy(array_buffer->Data(), addr, length);
81
+ Napi::ArrayBuffer array_buffer = Napi::ArrayBuffer::New(env, length);
82
+ memcpy(array_buffer.Data(), addr, length);
1518
83
  free(addr);
1519
84
  #else
1520
- // For nodejs > 12 or electron < 21, we will create a new `BackingStore` and
1521
- // take over the ownership of `addr`.
1522
- std::unique_ptr<v8::BackingStore> backing = v8::ArrayBuffer::NewBackingStore(
1523
- addr, length,
1524
- [](void* data, size_t length, void* deleter_data) { free(data); },
1525
- nullptr);
1526
- auto array_buffer =
1527
- v8::ArrayBuffer::New(v8::Isolate::GetCurrent(), std::move(backing));
85
+ // For nodejs > 12 or electron < 21, we will take over the ownership of
86
+ // `addr`.
87
+ auto array_buffer = Napi::ArrayBuffer::New(
88
+ env, addr, length, [](Napi::Env /*env*/, void* data) { free(data); });
1528
89
  #endif
1529
90
 
1530
- info.GetReturnValue().Set(array_buffer);
91
+ return array_buffer;
1531
92
  }
1532
93
 
1533
- NAN_METHOD(CreateArrayBufferCleaner) {
94
+ Napi::Value CreateArrayBufferCleaner(const Napi::CallbackInfo& info) {
95
+ Napi::Env env = info.Env();
96
+
1534
97
  auto address = GetBufAddr(info[0]);
1535
- int32_t offset = Nan::To<int32_t>(info[1]).FromJust();
98
+ int32_t offset = info[1].As<Napi::Number>().Int32Value();
1536
99
 
1537
100
  char* target = *reinterpret_cast<char**>(address + offset);
1538
- info.GetReturnValue().Set(
1539
- RclHandle::NewInstance(target, nullptr, [](void* ptr) { free(ptr); }));
101
+ return RclHandle::NewInstance(env, target, nullptr,
102
+ [](void* ptr) { free(ptr); });
1540
103
  }
1541
104
 
1542
- NAN_METHOD(setLoggerLevel) {
1543
- v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
1544
- std::string name(
1545
- *Nan::Utf8String(info[0]->ToString(currentContent).ToLocalChecked()));
1546
- int level = Nan::To<int64_t>(info[1]).FromJust();
1547
-
1548
- rcutils_ret_t ret = rcutils_logging_set_logger_level(name.c_str(), level);
1549
- if (ret != RCUTILS_RET_OK) {
1550
- Nan::ThrowError(rcutils_get_error_string().str);
1551
- rcutils_reset_error();
1552
- }
1553
- info.GetReturnValue().Set(Nan::Undefined());
1554
- }
1555
-
1556
- NAN_METHOD(GetLoggerEffectiveLevel) {
1557
- v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
1558
- std::string name(
1559
- *Nan::Utf8String(info[0]->ToString(currentContent).ToLocalChecked()));
1560
- int logger_level = rcutils_logging_get_logger_effective_level(name.c_str());
1561
-
1562
- if (logger_level < 0) {
1563
- Nan::ThrowError(rcutils_get_error_string().str);
1564
- rcutils_reset_error();
1565
- info.GetReturnValue().Set(Nan::Undefined());
1566
- return;
1567
- }
1568
- info.GetReturnValue().Set(Nan::New(logger_level));
1569
- }
1570
-
1571
- NAN_METHOD(GetNodeLoggerName) {
1572
- RclHandle* node_handle = RclHandle::Unwrap<RclHandle>(
1573
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
1574
- rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
1575
-
1576
- const char* node_logger_name = rcl_node_get_logger_name(node);
1577
- if (!node_logger_name) {
1578
- info.GetReturnValue().Set(Nan::Undefined());
1579
- return;
1580
- }
1581
-
1582
- info.GetReturnValue().Set(
1583
- Nan::New<v8::String>(node_logger_name).ToLocalChecked());
1584
- }
1585
-
1586
- NAN_METHOD(Log) {
1587
- v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
1588
- std::string name(
1589
- *Nan::Utf8String(info[0]->ToString(currentContent).ToLocalChecked()));
1590
- int severity = Nan::To<int64_t>(info[1]).FromJust();
1591
- std::string message(
1592
- *Nan::Utf8String(info[2]->ToString(currentContent).ToLocalChecked()));
1593
- std::string function_name(
1594
- *Nan::Utf8String(info[3]->ToString(currentContent).ToLocalChecked()));
1595
- size_t line_number = Nan::To<int64_t>(info[4]).FromJust();
1596
- std::string file_name(
1597
- *Nan::Utf8String(info[5]->ToString(currentContent).ToLocalChecked()));
1598
- bool enabled = rcutils_logging_logger_is_enabled_for(name.c_str(), severity);
1599
-
1600
- if (enabled) {
1601
- rcutils_log_location_t logging_location = {function_name.c_str(),
1602
- file_name.c_str(), line_number};
1603
- rcutils_log(&logging_location, severity, name.c_str(), "%s",
1604
- message.c_str());
1605
- }
1606
-
1607
- info.GetReturnValue().Set(Nan::New(enabled));
1608
- }
1609
-
1610
- NAN_METHOD(IsEnableFor) {
1611
- v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
1612
- std::string name(
1613
- *Nan::Utf8String(info[0]->ToString(currentContent).ToLocalChecked()));
1614
- int severity = Nan::To<int64_t>(info[1]).FromJust();
1615
- bool enabled = rcutils_logging_logger_is_enabled_for(name.c_str(), severity);
1616
- info.GetReturnValue().Set(Nan::New(enabled));
1617
- }
1618
-
1619
- NAN_METHOD(CreateContext) {
1620
- rcl_context_t* context =
1621
- reinterpret_cast<rcl_context_t*>(malloc(sizeof(rcl_context_t)));
1622
- *context = rcl_get_zero_initialized_context();
1623
- auto js_obj = RclHandle::NewInstance(context, nullptr, [](void* ptr) {
1624
- rcl_context_t* context = reinterpret_cast<rcl_context_t*>(ptr);
1625
- rcl_ret_t ret = DestroyContext(context);
1626
- free(ptr);
1627
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, ret, rcl_get_error_string().str);
1628
- });
1629
-
1630
- info.GetReturnValue().Set(js_obj);
1631
- }
1632
-
1633
- NAN_METHOD(IsContextValid) {
1634
- RclHandle* context_handle = RclHandle::Unwrap<RclHandle>(
1635
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
1636
- rcl_context_t* context =
1637
- reinterpret_cast<rcl_context_t*>(context_handle->ptr());
1638
- bool is_valid = rcl_context_is_valid(context);
1639
- info.GetReturnValue().Set(Nan::New(is_valid));
1640
- }
1641
-
1642
- void ExtractNamesAndTypes(rcl_names_and_types_t names_and_types,
1643
- v8::Local<v8::Array>* result_list) {
1644
- for (size_t i = 0; i < names_and_types.names.size; ++i) {
1645
- auto item = v8::Object::New(v8::Isolate::GetCurrent());
1646
- std::string topic_name = names_and_types.names.data[i];
1647
- Nan::Set(item, Nan::New("name").ToLocalChecked(),
1648
- Nan::New(names_and_types.names.data[i]).ToLocalChecked());
1649
-
1650
- v8::Local<v8::Array> type_list =
1651
- Nan::New<v8::Array>(names_and_types.types[i].size);
1652
- for (size_t j = 0; j < names_and_types.types[i].size; ++j) {
1653
- Nan::Set(type_list, j,
1654
- Nan::New(names_and_types.types[i].data[j]).ToLocalChecked());
1655
- }
1656
- Nan::Set(item, Nan::New("types").ToLocalChecked(), type_list);
1657
- Nan::Set(*result_list, i, item);
1658
- }
1659
- }
1660
-
1661
- NAN_METHOD(GetPublisherNamesAndTypesByNode) {
1662
- v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
1663
- RclHandle* node_handle = RclHandle::Unwrap<RclHandle>(
1664
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
1665
- rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
1666
- std::string node_name =
1667
- *Nan::Utf8String(info[1]->ToString(currentContent).ToLocalChecked());
1668
- std::string node_namespace =
1669
- *Nan::Utf8String(info[2]->ToString(currentContent).ToLocalChecked());
1670
- bool no_demangle = Nan::To<bool>(info[3]).FromJust();
1671
-
1672
- rcl_names_and_types_t topic_names_and_types =
1673
- rcl_get_zero_initialized_names_and_types();
1674
- rcl_allocator_t allocator = rcl_get_default_allocator();
1675
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
1676
- rcl_get_publisher_names_and_types_by_node(
1677
- node, &allocator, no_demangle, node_name.c_str(),
1678
- node_namespace.c_str(), &topic_names_and_types),
1679
- "Failed to get_publisher_names_and_types.");
1680
-
1681
- v8::Local<v8::Array> result_list =
1682
- Nan::New<v8::Array>(topic_names_and_types.names.size);
1683
- ExtractNamesAndTypes(topic_names_and_types, &result_list);
1684
-
1685
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
1686
- rcl_names_and_types_fini(&topic_names_and_types),
1687
- "Failed to destroy topic_names_and_types");
1688
-
1689
- info.GetReturnValue().Set(result_list);
1690
- }
1691
-
1692
- NAN_METHOD(GetSubscriptionNamesAndTypesByNode) {
1693
- v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
1694
- RclHandle* node_handle = RclHandle::Unwrap<RclHandle>(
1695
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
1696
- rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
1697
- std::string node_name =
1698
- *Nan::Utf8String(info[1]->ToString(currentContent).ToLocalChecked());
1699
- std::string node_namespace =
1700
- *Nan::Utf8String(info[2]->ToString(currentContent).ToLocalChecked());
1701
- bool no_demangle = Nan::To<bool>(info[3]).FromJust();
1702
-
1703
- rcl_names_and_types_t topic_names_and_types =
1704
- rcl_get_zero_initialized_names_and_types();
1705
- rcl_allocator_t allocator = rcl_get_default_allocator();
1706
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
1707
- rcl_get_subscriber_names_and_types_by_node(
1708
- node, &allocator, no_demangle, node_name.c_str(),
1709
- node_namespace.c_str(), &topic_names_and_types),
1710
- "Failed to get_publisher_names_and_types.");
1711
-
1712
- v8::Local<v8::Array> result_list =
1713
- Nan::New<v8::Array>(topic_names_and_types.names.size);
1714
- ExtractNamesAndTypes(topic_names_and_types, &result_list);
1715
-
1716
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
1717
- rcl_names_and_types_fini(&topic_names_and_types),
1718
- "Failed to destroy topic_names_and_types");
1719
-
1720
- info.GetReturnValue().Set(result_list);
1721
- }
1722
-
1723
- NAN_METHOD(GetServiceNamesAndTypesByNode) {
1724
- v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
1725
- RclHandle* node_handle = RclHandle::Unwrap<RclHandle>(
1726
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
1727
- rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
1728
- std::string node_name =
1729
- *Nan::Utf8String(info[1]->ToString(currentContent).ToLocalChecked());
1730
- std::string node_namespace =
1731
- *Nan::Utf8String(info[2]->ToString(currentContent).ToLocalChecked());
1732
-
1733
- rcl_names_and_types_t service_names_and_types =
1734
- rcl_get_zero_initialized_names_and_types();
1735
- rcl_allocator_t allocator = rcl_get_default_allocator();
1736
- THROW_ERROR_IF_NOT_EQUAL(
1737
- RCL_RET_OK,
1738
- rcl_get_service_names_and_types_by_node(
1739
- node, &allocator, node_name.c_str(), node_namespace.c_str(),
1740
- &service_names_and_types),
1741
- "Failed to get_publisher_names_and_types.");
1742
-
1743
- v8::Local<v8::Array> result_list =
1744
- Nan::New<v8::Array>(service_names_and_types.names.size);
1745
- ExtractNamesAndTypes(service_names_and_types, &result_list);
1746
-
1747
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
1748
- rcl_names_and_types_fini(&service_names_and_types),
1749
- "Failed to destroy topic_names_and_types");
1750
-
1751
- info.GetReturnValue().Set(result_list);
1752
- }
1753
-
1754
- NAN_METHOD(GetTopicNamesAndTypes) {
1755
- RclHandle* node_handle = RclHandle::Unwrap<RclHandle>(
1756
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
1757
- rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
1758
- bool no_demangle = Nan::To<bool>(info[1]).FromJust();
1759
- rcl_names_and_types_t topic_names_and_types =
1760
- rcl_get_zero_initialized_names_and_types();
1761
- rcl_allocator_t allocator = rcl_get_default_allocator();
1762
-
1763
- THROW_ERROR_IF_NOT_EQUAL(
1764
- RCL_RET_OK,
1765
- rcl_get_topic_names_and_types(node, &allocator, no_demangle,
1766
- &topic_names_and_types),
1767
- "Failed to get_publisher_names_and_types.");
1768
-
1769
- v8::Local<v8::Array> result_list =
1770
- Nan::New<v8::Array>(topic_names_and_types.names.size);
1771
- ExtractNamesAndTypes(topic_names_and_types, &result_list);
1772
-
1773
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
1774
- rcl_names_and_types_fini(&topic_names_and_types),
1775
- "Failed to destroy topic_names_and_types");
1776
-
1777
- info.GetReturnValue().Set(result_list);
105
+ Napi::Object InitBindings(Napi::Env env, Napi::Object exports) {
106
+ exports.Set("initString", Napi::Function::New(env, InitString));
107
+ exports.Set("freeMemeoryAtOffset",
108
+ Napi::Function::New(env, FreeMemeoryAtOffset));
109
+ exports.Set("createArrayBufferFromAddress",
110
+ Napi::Function::New(env, CreateArrayBufferFromAddress));
111
+ exports.Set("createArrayBufferCleaner",
112
+ Napi::Function::New(env, CreateArrayBufferCleaner));
113
+ return exports;
1778
114
  }
1779
115
 
1780
- NAN_METHOD(GetServiceNamesAndTypes) {
1781
- RclHandle* node_handle = RclHandle::Unwrap<RclHandle>(
1782
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
1783
- rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
1784
- rcl_names_and_types_t service_names_and_types =
1785
- rcl_get_zero_initialized_names_and_types();
1786
- rcl_allocator_t allocator = rcl_get_default_allocator();
1787
-
1788
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
1789
- rcl_get_service_names_and_types(
1790
- node, &allocator, &service_names_and_types),
1791
- "Failed to get_publisher_names_and_types.");
1792
-
1793
- v8::Local<v8::Array> result_list =
1794
- Nan::New<v8::Array>(service_names_and_types.names.size);
1795
- ExtractNamesAndTypes(service_names_and_types, &result_list);
1796
-
1797
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
1798
- rcl_names_and_types_fini(&service_names_and_types),
1799
- "Failed to destroy topic_names_and_types");
1800
-
1801
- info.GetReturnValue().Set(result_list);
1802
- }
1803
-
1804
- NAN_METHOD(GetNodeNames) {
1805
- RclHandle* node_handle = RclHandle::Unwrap<RclHandle>(
1806
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
1807
- rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
1808
- rcutils_string_array_t node_names =
1809
- rcutils_get_zero_initialized_string_array();
1810
- rcutils_string_array_t node_namespaces =
1811
- rcutils_get_zero_initialized_string_array();
1812
- rcl_allocator_t allocator = rcl_get_default_allocator();
1813
-
1814
- THROW_ERROR_IF_NOT_EQUAL(
1815
- RCL_RET_OK,
1816
- rcl_get_node_names(node, allocator, &node_names, &node_namespaces),
1817
- "Failed to get_node_names.");
1818
-
1819
- v8::Local<v8::Array> result_list = Nan::New<v8::Array>(node_names.size);
1820
-
1821
- for (size_t i = 0; i < node_names.size; ++i) {
1822
- auto item = v8::Object::New(v8::Isolate::GetCurrent());
1823
-
1824
- Nan::Set(item, Nan::New("name").ToLocalChecked(),
1825
- Nan::New(node_names.data[i]).ToLocalChecked());
1826
- Nan::Set(item, Nan::New("namespace").ToLocalChecked(),
1827
- Nan::New(node_namespaces.data[i]).ToLocalChecked());
1828
-
1829
- Nan::Set(result_list, i, item);
1830
- }
1831
-
1832
- rcutils_ret_t fini_names_ret = rcutils_string_array_fini(&node_names);
1833
- rcutils_ret_t fini_namespaces_ret =
1834
- rcutils_string_array_fini(&node_namespaces);
1835
-
1836
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, fini_names_ret,
1837
- "Failed to destroy node_names");
1838
- THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, fini_namespaces_ret,
1839
- "Failed to destroy node_namespaces");
1840
-
1841
- info.GetReturnValue().Set(result_list);
1842
- }
1843
-
1844
- NAN_METHOD(CountPublishers) {
1845
- v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
1846
- RclHandle* node_handle = RclHandle::Unwrap<RclHandle>(
1847
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
1848
- rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
1849
- std::string topic_name =
1850
- *Nan::Utf8String(info[1]->ToString(currentContent).ToLocalChecked());
1851
-
1852
- size_t count = 0;
1853
- THROW_ERROR_IF_NOT_EQUAL(
1854
- RCL_RET_OK, rcl_count_publishers(node, topic_name.c_str(), &count),
1855
- "Failed to count publishers.");
1856
-
1857
- v8::Local<v8::Integer> result =
1858
- Nan::New<v8::Integer>(static_cast<int32_t>(count));
1859
- info.GetReturnValue().Set(result);
1860
- }
1861
-
1862
- NAN_METHOD(CountSubscribers) {
1863
- v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
1864
- RclHandle* node_handle = RclHandle::Unwrap<RclHandle>(
1865
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
1866
- rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
1867
- std::string topic_name =
1868
- *Nan::Utf8String(info[1]->ToString(currentContent).ToLocalChecked());
1869
-
1870
- size_t count = 0;
1871
- THROW_ERROR_IF_NOT_EQUAL(
1872
- RCL_RET_OK, rcl_count_subscribers(node, topic_name.c_str(), &count),
1873
- "Failed to count subscribers.");
1874
-
1875
- v8::Local<v8::Integer> result =
1876
- Nan::New<v8::Integer>(static_cast<int32_t>(count));
1877
- info.GetReturnValue().Set(result);
1878
- }
1879
-
1880
- NAN_METHOD(ServiceServerIsAvailable) {
1881
- RclHandle* node_handle = RclHandle::Unwrap<RclHandle>(
1882
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
1883
- rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
1884
- RclHandle* client_handle = RclHandle::Unwrap<RclHandle>(
1885
- Nan::To<v8::Object>(info[1]).ToLocalChecked());
1886
- rcl_client_t* client = reinterpret_cast<rcl_client_t*>(client_handle->ptr());
1887
-
1888
- bool is_available;
1889
- THROW_ERROR_IF_NOT_EQUAL(
1890
- RCL_RET_OK, rcl_service_server_is_available(node, client, &is_available),
1891
- "Failed to get service state.");
1892
-
1893
- v8::Local<v8::Boolean> result = Nan::New<v8::Boolean>(is_available);
1894
- info.GetReturnValue().Set(result);
1895
- }
1896
-
1897
- NAN_METHOD(PublishRawMessage) {
1898
- rcl_publisher_t* publisher = reinterpret_cast<rcl_publisher_t*>(
1899
- RclHandle::Unwrap<RclHandle>(
1900
- Nan::To<v8::Object>(info[0]).ToLocalChecked())
1901
- ->ptr());
1902
-
1903
- auto object = Nan::To<v8::Object>(info[1]).ToLocalChecked();
1904
- rcl_serialized_message_t serialized_msg =
1905
- rmw_get_zero_initialized_serialized_message();
1906
- serialized_msg.buffer_capacity = node::Buffer::Length(object);
1907
- serialized_msg.buffer_length = serialized_msg.buffer_capacity;
1908
- serialized_msg.buffer =
1909
- reinterpret_cast<uint8_t*>(node::Buffer::Data(object));
1910
-
1911
- THROW_ERROR_IF_NOT_EQUAL(
1912
- rcl_publish_serialized_message(publisher, &serialized_msg, nullptr),
1913
- RCL_RET_OK, rcl_get_error_string().str);
1914
-
1915
- info.GetReturnValue().Set(Nan::Undefined());
1916
- }
1917
-
1918
- NAN_METHOD(RclTakeRaw) {
1919
- RclHandle* subscription_handle = RclHandle::Unwrap<RclHandle>(
1920
- Nan::To<v8::Object>(info[0]).ToLocalChecked());
1921
- rcl_subscription_t* subscription =
1922
- reinterpret_cast<rcl_subscription_t*>(subscription_handle->ptr());
1923
-
1924
- rcl_serialized_message_t msg = rmw_get_zero_initialized_serialized_message();
1925
- rcutils_allocator_t allocator = rcutils_get_default_allocator();
1926
- rcl_ret_t ret = rmw_serialized_message_init(&msg, 0u, &allocator);
1927
- if (ret != RCL_RET_OK) {
1928
- THROW_ERROR_IF_NOT_EQUAL(rmw_serialized_message_fini(&msg), RCL_RET_OK,
1929
- "Failed to deallocate message buffer.");
1930
- info.GetReturnValue().Set(Nan::Undefined());
1931
- return;
1932
- }
1933
- ret = rcl_take_serialized_message(subscription, &msg, nullptr, nullptr);
1934
- if (ret != RCL_RET_OK && ret != RCL_RET_SUBSCRIPTION_TAKE_FAILED) {
1935
- rcl_reset_error();
1936
- THROW_ERROR_IF_NOT_EQUAL(rmw_serialized_message_fini(&msg), RCL_RET_OK,
1937
- "Failed to deallocate message buffer.");
1938
- info.GetReturnValue().Set(Nan::Undefined());
1939
- return;
1940
- }
1941
-
1942
- if (ret == RCL_RET_SUBSCRIPTION_TAKE_FAILED) {
1943
- THROW_ERROR_IF_NOT_EQUAL(rmw_serialized_message_fini(&msg), RCL_RET_OK,
1944
- "Failed to deallocate message buffer.");
1945
- info.GetReturnValue().Set(Nan::Undefined());
1946
- return;
1947
- }
1948
-
1949
- info.GetReturnValue().Set(
1950
- Nan::CopyBuffer(reinterpret_cast<char*>(msg.buffer), msg.buffer_length)
1951
- .ToLocalChecked());
1952
- THROW_ERROR_IF_NOT_EQUAL(rmw_serialized_message_fini(&msg), RCL_RET_OK,
1953
- "Failed to deallocate message buffer");
1954
- }
1955
-
1956
- NAN_METHOD(GetClientServiceName) {
1957
- rcl_client_t* client = reinterpret_cast<rcl_client_t*>(
1958
- RclHandle::Unwrap<RclHandle>(
1959
- Nan::To<v8::Object>(info[0]).ToLocalChecked())
1960
- ->ptr());
1961
-
1962
- const char* service_name = rcl_client_get_service_name(client);
1963
- info.GetReturnValue().Set(Nan::New(service_name).ToLocalChecked());
1964
- }
1965
-
1966
- NAN_METHOD(GetServiceServiceName) {
1967
- rcl_service_t* service = reinterpret_cast<rcl_service_t*>(
1968
- RclHandle::Unwrap<RclHandle>(
1969
- Nan::To<v8::Object>(info[0]).ToLocalChecked())
1970
- ->ptr());
1971
-
1972
- const char* service_name = rcl_service_get_service_name(service);
1973
- info.GetReturnValue().Set(Nan::New(service_name).ToLocalChecked());
1974
- }
1975
-
1976
- std::vector<BindingMethod> binding_methods = {
1977
- {"init", Init},
1978
- {"createNode", CreateNode},
1979
- {"getParameterOverrides", GetParameterOverrides},
1980
- {"createGuardCondition", CreateGuardCondition},
1981
- {"triggerGuardCondition", TriggerGuardCondition},
1982
- {"createTimer", CreateTimer},
1983
- {"isTimerReady", IsTimerReady},
1984
- {"callTimer", CallTimer},
1985
- {"cancelTimer", CancelTimer},
1986
- {"isTimerCanceled", IsTimerCanceled},
1987
- {"resetTimer", ResetTimer},
1988
- {"timerGetTimeSinceLastCall", TimerGetTimeSinceLastCall},
1989
- {"timerGetTimeUntilNextCall", TimerGetTimeUntilNextCall},
1990
- {"createClock", CreateClock},
1991
- {"clockGetNow", ClockGetNow},
1992
- {"createTimePoint", CreateTimePoint},
1993
- {"getNanoseconds", GetNanoseconds},
1994
- {"createDuration", CreateDuration},
1995
- {"getDurationNanoseconds", GetDurationNanoseconds},
1996
- {"setRosTimeOverrideIsEnabled", SetRosTimeOverrideIsEnabled},
1997
- {"setRosTimeOverride", SetRosTimeOverride},
1998
- {"getRosTimeOverrideIsEnabled", GetRosTimeOverrideIsEnabled},
1999
- {"rclTake", RclTake},
2000
- {"createSubscription", CreateSubscription},
2001
- {"hasContentFilter", HasContentFilter},
2002
- {"setContentFilter", SetContentFilter},
2003
- {"clearContentFilter", ClearContentFilter},
2004
- {"createPublisher", CreatePublisher},
2005
- {"publish", Publish},
2006
- {"getPublisherTopic", GetPublisherTopic},
2007
- {"getSubscriptionTopic", GetSubscriptionTopic},
2008
- {"createClient", CreateClient},
2009
- {"rclTakeResponse", RclTakeResponse},
2010
- {"sendRequest", SendRequest},
2011
- {"createService", CreateService},
2012
- {"rclTakeRequest", RclTakeRequest},
2013
- {"sendResponse", SendResponse},
2014
- {"shutdown", Shutdown},
2015
- {"validateFullTopicName", ValidateFullTopicName},
2016
- {"validateNodeName", ValidateNodeName},
2017
- {"validateTopicName", ValidateTopicName},
2018
- {"validateNamespace", ValidateNamespace},
2019
- {"expandTopicName", ExpandTopicName},
2020
- {"getNodeName", GetNodeName},
2021
- {"getNamespace", GetNamespace},
2022
- {"initString", InitString},
2023
- {"freeMemeoryAtOffset", FreeMemeoryAtOffset},
2024
- {"createArrayBufferFromAddress", CreateArrayBufferFromAddress},
2025
- {"createArrayBufferCleaner", CreateArrayBufferCleaner},
2026
- {"setLoggerLevel", setLoggerLevel},
2027
- {"getLoggerEffectiveLevel", GetLoggerEffectiveLevel},
2028
- {"getNodeLoggerName", GetNodeLoggerName},
2029
- {"log", Log},
2030
- {"isEnableFor", IsEnableFor},
2031
- {"createContext", CreateContext},
2032
- {"isContextValid", IsContextValid},
2033
- {"getPublisherNamesAndTypesByNode", GetPublisherNamesAndTypesByNode},
2034
- {"getSubscriptionNamesAndTypesByNode", GetSubscriptionNamesAndTypesByNode},
2035
- {"getServiceNamesAndTypesByNode", GetServiceNamesAndTypesByNode},
2036
- {"getTopicNamesAndTypes", GetTopicNamesAndTypes},
2037
- {"getServiceNamesAndTypes", GetServiceNamesAndTypes},
2038
- {"getNodeNames", GetNodeNames},
2039
- {"countPublishers", CountPublishers},
2040
- {"countSubscribers", CountSubscribers},
2041
- {"serviceServerIsAvailable", ServiceServerIsAvailable},
2042
- {"publishRawMessage", PublishRawMessage},
2043
- {"rclTakeRaw", RclTakeRaw},
2044
- {"getClientServiceName", GetClientServiceName},
2045
- {"getServiceServiceName", GetServiceServiceName},
2046
- {"", nullptr}
2047
- #if ROS_VERSION > 2205 // 2205 == Humble
2048
- ,
2049
- {"configureServiceIntrospection", ConfigureServiceIntrospection}
2050
- #endif
2051
- };
2052
-
2053
116
  } // namespace rclnodejs