rclnodejs 1.0.0 → 1.2.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 +6 -6
- package/binding.gyp +12 -0
- package/lib/action/client.js +40 -0
- package/lib/action/server.js +21 -0
- package/lib/client.js +1 -1
- package/lib/distro.js +2 -0
- package/lib/event_handler.js +474 -0
- package/lib/lifecycle.js +9 -0
- package/lib/lifecycle_publisher.js +2 -2
- package/lib/node.js +85 -11
- package/lib/node_options.js +21 -1
- package/lib/publisher.js +50 -4
- package/lib/service.js +1 -1
- package/lib/subscription.js +48 -4
- package/lib/type_description_service.js +82 -0
- package/package.json +1 -1
- package/scripts/npmjs-readme.md +6 -6
- package/src/addon.cpp +8 -0
- package/src/executor.cpp +3 -4
- package/src/handle_manager.cpp +13 -2
- package/src/handle_manager.h +4 -1
- package/src/rcl_action_client_bindings.cpp +99 -24
- package/src/rcl_action_server_bindings.cpp +69 -19
- package/src/rcl_event_handle_bindings.cpp +294 -0
- package/src/rcl_event_handle_bindings.h +26 -0
- package/src/rcl_lifecycle_bindings.cpp +13 -0
- package/src/rcl_node_bindings.cpp +43 -8
- package/src/rcl_publisher_bindings.cpp +19 -0
- package/src/rcl_type_description_service_bindings.cpp +79 -0
- package/src/rcl_type_description_service_bindings.h +27 -0
- package/types/action_client.d.ts +18 -0
- package/types/action_server.d.ts +12 -0
- package/types/lifecycle.d.ts +7 -0
- package/types/node.d.ts +44 -2
- package/types/publisher.d.ts +17 -0
package/src/handle_manager.h
CHANGED
|
@@ -68,13 +68,15 @@ class HandleManager {
|
|
|
68
68
|
rcl_ret_t CollectReadyHandles(rcl_wait_set_t* wait_set);
|
|
69
69
|
rcl_ret_t GetEntityCounts(size_t* subscriptions_size,
|
|
70
70
|
size_t* guard_conditions_size, size_t* timers_size,
|
|
71
|
-
size_t* clients_size, size_t* services_size
|
|
71
|
+
size_t* clients_size, size_t* services_size,
|
|
72
|
+
size_t* events_size);
|
|
72
73
|
|
|
73
74
|
uint32_t subscription_count() const { return subscriptions_.size(); }
|
|
74
75
|
uint32_t service_count() const { return services_.size(); }
|
|
75
76
|
uint32_t client_count() const { return clients_.size(); }
|
|
76
77
|
uint32_t timer_count() const { return timers_.size(); }
|
|
77
78
|
uint32_t guard_condition_count() const { return guard_conditions_.size(); }
|
|
79
|
+
uint32_t event_count() const { return events_.size(); }
|
|
78
80
|
uv_rwlock_t* handle_rwlock() { return &sync_handles_rwlock_; }
|
|
79
81
|
|
|
80
82
|
uint32_t ready_handles_count();
|
|
@@ -110,6 +112,7 @@ class HandleManager {
|
|
|
110
112
|
std::vector<rclnodejs::RclHandle*> action_servers_;
|
|
111
113
|
std::vector<rclnodejs::RclHandle*> action_clients_;
|
|
112
114
|
std::vector<rclnodejs::RclHandle*> ready_handles_;
|
|
115
|
+
std::vector<rclnodejs::RclHandle*> events_;
|
|
113
116
|
|
|
114
117
|
// Protects the handles.
|
|
115
118
|
uv_rwlock_t sync_handles_rwlock_;
|
|
@@ -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
|
|
|
@@ -0,0 +1,294 @@
|
|
|
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_event_handle_bindings.h"
|
|
16
|
+
|
|
17
|
+
#include <rcl/error_handling.h>
|
|
18
|
+
#include <rcl/rcl.h>
|
|
19
|
+
|
|
20
|
+
#include "rcl_handle.h"
|
|
21
|
+
|
|
22
|
+
namespace {
|
|
23
|
+
|
|
24
|
+
typedef union event_callback_data {
|
|
25
|
+
// Subscription events
|
|
26
|
+
rmw_requested_deadline_missed_status_t requested_deadline_missed;
|
|
27
|
+
rmw_liveliness_changed_status_t liveliness_changed;
|
|
28
|
+
rmw_message_lost_status_t message_lost;
|
|
29
|
+
rmw_requested_qos_incompatible_event_status_t requested_incompatible_qos;
|
|
30
|
+
rmw_matched_status_t subscription_matched;
|
|
31
|
+
// Publisher events
|
|
32
|
+
rmw_offered_deadline_missed_status_t offered_deadline_missed;
|
|
33
|
+
rmw_liveliness_lost_status_t liveliness_lost;
|
|
34
|
+
rmw_offered_qos_incompatible_event_status_t offered_incompatible_qos;
|
|
35
|
+
rmw_matched_status_t publisher_matched;
|
|
36
|
+
|
|
37
|
+
rmw_incompatible_type_status_t incompatible_type;
|
|
38
|
+
} event_callback_data_t;
|
|
39
|
+
|
|
40
|
+
rcl_event_t* CreateEventHandle() {
|
|
41
|
+
rcl_event_t* event =
|
|
42
|
+
reinterpret_cast<rcl_event_t*>(malloc(sizeof(rcl_event_t)));
|
|
43
|
+
*event = rcl_get_zero_initialized_event();
|
|
44
|
+
return event;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
Napi::Value CreateJSObjectForSubscriptionEvent(
|
|
48
|
+
Napi::Env env, rcl_subscription_event_type_t subscription_event_type,
|
|
49
|
+
const event_callback_data_t& data) {
|
|
50
|
+
Napi::Object obj = Napi::Object::New(env);
|
|
51
|
+
switch (subscription_event_type) {
|
|
52
|
+
case RCL_SUBSCRIPTION_REQUESTED_DEADLINE_MISSED: {
|
|
53
|
+
obj.Set(
|
|
54
|
+
"total_count",
|
|
55
|
+
Napi::Number::New(env, data.requested_deadline_missed.total_count));
|
|
56
|
+
obj.Set("total_count_change",
|
|
57
|
+
Napi::Number::New(
|
|
58
|
+
env, data.requested_deadline_missed.total_count_change));
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
case RCL_SUBSCRIPTION_LIVELINESS_CHANGED: {
|
|
62
|
+
obj.Set("alive_count",
|
|
63
|
+
Napi::Number::New(env, data.liveliness_changed.alive_count));
|
|
64
|
+
obj.Set("not_alive_count",
|
|
65
|
+
Napi::Number::New(env, data.liveliness_changed.not_alive_count));
|
|
66
|
+
obj.Set(
|
|
67
|
+
"alive_count_change",
|
|
68
|
+
Napi::Number::New(env, data.liveliness_changed.alive_count_change));
|
|
69
|
+
obj.Set("not_alive_count_change",
|
|
70
|
+
Napi::Number::New(
|
|
71
|
+
env, data.liveliness_changed.not_alive_count_change));
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
case RCL_SUBSCRIPTION_MESSAGE_LOST: {
|
|
75
|
+
obj.Set("total_count",
|
|
76
|
+
Napi::Number::New(env, data.message_lost.total_count));
|
|
77
|
+
obj.Set("total_count_change",
|
|
78
|
+
Napi::Number::New(env, data.message_lost.total_count_change));
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
case RCL_SUBSCRIPTION_REQUESTED_INCOMPATIBLE_QOS: {
|
|
82
|
+
obj.Set(
|
|
83
|
+
"total_count",
|
|
84
|
+
Napi::Number::New(env, data.requested_incompatible_qos.total_count));
|
|
85
|
+
obj.Set("total_count_change",
|
|
86
|
+
Napi::Number::New(
|
|
87
|
+
env, data.requested_incompatible_qos.total_count_change));
|
|
88
|
+
obj.Set("last_policy_kind",
|
|
89
|
+
Napi::Number::New(
|
|
90
|
+
env, data.requested_incompatible_qos.last_policy_kind));
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
case RCL_SUBSCRIPTION_INCOMPATIBLE_TYPE: {
|
|
94
|
+
obj.Set("total_count",
|
|
95
|
+
Napi::Number::New(env, data.incompatible_type.total_count));
|
|
96
|
+
obj.Set(
|
|
97
|
+
"total_count_change",
|
|
98
|
+
Napi::Number::New(env, data.incompatible_type.total_count_change));
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
case RCL_SUBSCRIPTION_MATCHED: {
|
|
102
|
+
obj.Set("total_count",
|
|
103
|
+
Napi::Number::New(env, data.subscription_matched.total_count));
|
|
104
|
+
obj.Set(
|
|
105
|
+
"total_count_change",
|
|
106
|
+
Napi::Number::New(env, data.subscription_matched.total_count_change));
|
|
107
|
+
obj.Set("current_count",
|
|
108
|
+
Napi::Number::New(env, data.subscription_matched.current_count));
|
|
109
|
+
obj.Set("current_count_change",
|
|
110
|
+
Napi::Number::New(
|
|
111
|
+
env, data.subscription_matched.current_count_change));
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
default:
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
return obj;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
Napi::Value CreateJSObjectForPublisherEvent(
|
|
121
|
+
Napi::Env env, rcl_publisher_event_type_t publisher_event_type,
|
|
122
|
+
const event_callback_data_t& data) {
|
|
123
|
+
Napi::Object obj = Napi::Object::New(env);
|
|
124
|
+
switch (publisher_event_type) {
|
|
125
|
+
case RCL_PUBLISHER_OFFERED_DEADLINE_MISSED: {
|
|
126
|
+
obj.Set("total_count",
|
|
127
|
+
Napi::Number::New(env, data.offered_deadline_missed.total_count));
|
|
128
|
+
obj.Set("total_count_change",
|
|
129
|
+
Napi::Number::New(
|
|
130
|
+
env, data.offered_deadline_missed.total_count_change));
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
case RCL_PUBLISHER_LIVELINESS_LOST: {
|
|
134
|
+
obj.Set("total_count",
|
|
135
|
+
Napi::Number::New(env, data.liveliness_lost.total_count));
|
|
136
|
+
obj.Set("total_count_change",
|
|
137
|
+
Napi::Number::New(env, data.liveliness_lost.total_count_change));
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
case RCL_PUBLISHER_OFFERED_INCOMPATIBLE_QOS: {
|
|
141
|
+
obj.Set(
|
|
142
|
+
"total_count",
|
|
143
|
+
Napi::Number::New(env, data.offered_incompatible_qos.total_count));
|
|
144
|
+
obj.Set("total_count_change",
|
|
145
|
+
Napi::Number::New(
|
|
146
|
+
env, data.offered_incompatible_qos.total_count_change));
|
|
147
|
+
obj.Set("last_policy_kind",
|
|
148
|
+
Napi::Number::New(
|
|
149
|
+
env, data.offered_incompatible_qos.last_policy_kind));
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
case RCL_PUBLISHER_INCOMPATIBLE_TYPE: {
|
|
153
|
+
obj.Set("total_count",
|
|
154
|
+
Napi::Number::New(env, data.incompatible_type.total_count));
|
|
155
|
+
obj.Set(
|
|
156
|
+
"total_count_change",
|
|
157
|
+
Napi::Number::New(env, data.incompatible_type.total_count_change));
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
case RCL_PUBLISHER_MATCHED: {
|
|
161
|
+
obj.Set("total_count",
|
|
162
|
+
Napi::Number::New(env, data.publisher_matched.total_count));
|
|
163
|
+
obj.Set(
|
|
164
|
+
"total_count_change",
|
|
165
|
+
Napi::Number::New(env, data.publisher_matched.total_count_change));
|
|
166
|
+
obj.Set("current_count",
|
|
167
|
+
Napi::Number::New(env, data.publisher_matched.current_count));
|
|
168
|
+
obj.Set(
|
|
169
|
+
"current_count_change",
|
|
170
|
+
Napi::Number::New(env, data.publisher_matched.current_count_change));
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
default:
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
return obj;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
} // namespace
|
|
180
|
+
|
|
181
|
+
namespace rclnodejs {
|
|
182
|
+
|
|
183
|
+
Napi::Value CreateSubscriptionEventHandle(const Napi::CallbackInfo& info) {
|
|
184
|
+
Napi::Env env = info.Env();
|
|
185
|
+
RclHandle* subscription_handle =
|
|
186
|
+
RclHandle::Unwrap(info[0].As<Napi::Object>());
|
|
187
|
+
rcl_subscription_t* subscription =
|
|
188
|
+
reinterpret_cast<rcl_subscription_t*>(subscription_handle->ptr());
|
|
189
|
+
rcl_subscription_event_type_t event_type =
|
|
190
|
+
static_cast<rcl_subscription_event_type_t>(
|
|
191
|
+
info[1].As<Napi::Number>().Int32Value());
|
|
192
|
+
|
|
193
|
+
rcl_event_t* event = CreateEventHandle();
|
|
194
|
+
rcl_ret_t ret = rcl_subscription_event_init(event, subscription, event_type);
|
|
195
|
+
|
|
196
|
+
if (ret != RCL_RET_OK) {
|
|
197
|
+
Napi::Error::New(env, "failed to create subscription event")
|
|
198
|
+
.ThrowAsJavaScriptException();
|
|
199
|
+
rcl_reset_error();
|
|
200
|
+
free(event);
|
|
201
|
+
return env.Undefined();
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
auto js_obj = RclHandle::NewInstance(env, event, nullptr, [env](void* ptr) {
|
|
205
|
+
rcl_event_t* event = reinterpret_cast<rcl_event_t*>(ptr);
|
|
206
|
+
rcl_ret_t ret = rcl_event_fini(event);
|
|
207
|
+
if (ret != RCL_RET_OK) {
|
|
208
|
+
Napi::Error::New(env, rcl_get_error_string().str)
|
|
209
|
+
.ThrowAsJavaScriptException();
|
|
210
|
+
rcl_reset_error();
|
|
211
|
+
}
|
|
212
|
+
free(ptr);
|
|
213
|
+
});
|
|
214
|
+
return js_obj;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
Napi::Value CreatePublisherEventHandle(const Napi::CallbackInfo& info) {
|
|
218
|
+
Napi::Env env = info.Env();
|
|
219
|
+
RclHandle* publisher_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
|
|
220
|
+
rcl_publisher_t* publisher =
|
|
221
|
+
reinterpret_cast<rcl_publisher_t*>(publisher_handle->ptr());
|
|
222
|
+
rcl_publisher_event_type_t event_type =
|
|
223
|
+
static_cast<rcl_publisher_event_type_t>(
|
|
224
|
+
info[1].As<Napi::Number>().Int32Value());
|
|
225
|
+
|
|
226
|
+
rcl_event_t* event = CreateEventHandle();
|
|
227
|
+
rcl_ret_t ret = rcl_publisher_event_init(event, publisher, event_type);
|
|
228
|
+
|
|
229
|
+
if (ret != RCL_RET_OK) {
|
|
230
|
+
Napi::Error::New(env, "failed to create publisher event")
|
|
231
|
+
.ThrowAsJavaScriptException();
|
|
232
|
+
rcl_reset_error();
|
|
233
|
+
free(event);
|
|
234
|
+
return env.Undefined();
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
auto js_obj = RclHandle::NewInstance(env, event, nullptr, [env](void* ptr) {
|
|
238
|
+
rcl_event_t* event = reinterpret_cast<rcl_event_t*>(ptr);
|
|
239
|
+
rcl_ret_t ret = rcl_event_fini(event);
|
|
240
|
+
if (ret != RCL_RET_OK) {
|
|
241
|
+
Napi::Error::New(env, rcl_get_error_string().str)
|
|
242
|
+
.ThrowAsJavaScriptException();
|
|
243
|
+
rcl_reset_error();
|
|
244
|
+
}
|
|
245
|
+
free(ptr);
|
|
246
|
+
});
|
|
247
|
+
return js_obj;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
Napi::Value TakeEvent(const Napi::CallbackInfo& info) {
|
|
251
|
+
Napi::Env env = info.Env();
|
|
252
|
+
RclHandle* event_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
|
|
253
|
+
rcl_event_t* event = reinterpret_cast<rcl_event_t*>(event_handle->ptr());
|
|
254
|
+
auto event_type = info[1].As<Napi::Object>();
|
|
255
|
+
|
|
256
|
+
event_callback_data_t data;
|
|
257
|
+
rcl_ret_t ret;
|
|
258
|
+
if (event_type.Has("subscription_event_type")) {
|
|
259
|
+
rcl_subscription_event_type_t subscription_event_type =
|
|
260
|
+
static_cast<rcl_subscription_event_type_t>(
|
|
261
|
+
event_type.Get("subscription_event_type")
|
|
262
|
+
.As<Napi::Number>()
|
|
263
|
+
.Int32Value());
|
|
264
|
+
ret = rcl_take_event(event, &data);
|
|
265
|
+
if (RCL_RET_OK == ret) {
|
|
266
|
+
return CreateJSObjectForSubscriptionEvent(env, subscription_event_type,
|
|
267
|
+
data);
|
|
268
|
+
}
|
|
269
|
+
} else if (event_type.Has("publisher_event_type")) {
|
|
270
|
+
rcl_publisher_event_type_t publisher_event_type =
|
|
271
|
+
static_cast<rcl_publisher_event_type_t>(
|
|
272
|
+
event_type.Get("publisher_event_type")
|
|
273
|
+
.As<Napi::Number>()
|
|
274
|
+
.Int32Value());
|
|
275
|
+
ret = rcl_take_event(event, &data);
|
|
276
|
+
if (RCL_RET_OK == ret) {
|
|
277
|
+
return CreateJSObjectForPublisherEvent(env, publisher_event_type, data);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
Napi::Error::New(env, "failed to take event").ThrowAsJavaScriptException();
|
|
282
|
+
return env.Undefined();
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
Napi::Object InitEventHandleBindings(Napi::Env env, Napi::Object exports) {
|
|
286
|
+
exports.Set("createSubscriptionEventHandle",
|
|
287
|
+
Napi::Function::New(env, CreateSubscriptionEventHandle));
|
|
288
|
+
exports.Set("createPublisherEventHandle",
|
|
289
|
+
Napi::Function::New(env, CreatePublisherEventHandle));
|
|
290
|
+
exports.Set("takeEvent", Napi::Function::New(env, TakeEvent));
|
|
291
|
+
return exports;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
} // namespace rclnodejs
|
|
@@ -0,0 +1,26 @@
|
|
|
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_EVENT_HANDLE_BINDINGS_H_
|
|
16
|
+
#define SRC_RCL_EVENT_HANDLE_BINDINGS_H_
|
|
17
|
+
|
|
18
|
+
#include <napi.h>
|
|
19
|
+
|
|
20
|
+
namespace rclnodejs {
|
|
21
|
+
|
|
22
|
+
Napi::Object InitEventHandleBindings(Napi::Env env, Napi::Object exports);
|
|
23
|
+
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
#endif // SRC_RCL_EVENT_HANDLE_BINDINGS_H_
|
|
@@ -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
|
|