rclnodejs 1.7.0 → 1.8.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/binding.gyp +2 -0
- package/index.js +93 -0
- package/lib/action/client.js +54 -1
- package/lib/client.js +66 -1
- package/lib/clock.js +178 -0
- package/lib/clock_change.js +49 -0
- package/lib/clock_event.js +88 -0
- package/lib/errors.js +50 -0
- package/lib/logging.js +78 -0
- package/lib/message_introspector.js +123 -0
- package/lib/message_validation.js +512 -0
- package/lib/node.js +133 -1
- package/lib/node_options.js +40 -1
- package/lib/observable_subscription.js +105 -0
- package/lib/publisher.js +56 -1
- package/lib/qos.js +57 -0
- package/lib/subscription.js +8 -0
- package/lib/timer.js +42 -0
- package/lib/validator.js +63 -7
- package/package.json +4 -2
- package/prebuilds/linux-arm64/humble-jammy-arm64-rclnodejs.node +0 -0
- package/prebuilds/linux-arm64/jazzy-noble-arm64-rclnodejs.node +0 -0
- package/prebuilds/linux-arm64/kilted-noble-arm64-rclnodejs.node +0 -0
- package/prebuilds/linux-x64/humble-jammy-x64-rclnodejs.node +0 -0
- package/prebuilds/linux-x64/jazzy-noble-x64-rclnodejs.node +0 -0
- package/prebuilds/linux-x64/kilted-noble-x64-rclnodejs.node +0 -0
- package/rosidl_gen/message_translator.js +0 -61
- package/scripts/config.js +1 -0
- package/src/addon.cpp +2 -0
- package/src/clock_event.cpp +268 -0
- package/src/clock_event.hpp +62 -0
- package/src/macros.h +2 -4
- package/src/rcl_action_server_bindings.cpp +21 -3
- package/src/rcl_bindings.cpp +59 -0
- package/src/rcl_context_bindings.cpp +5 -0
- package/src/rcl_graph_bindings.cpp +73 -0
- package/src/rcl_logging_bindings.cpp +158 -0
- package/src/rcl_node_bindings.cpp +14 -2
- package/src/rcl_publisher_bindings.cpp +12 -0
- package/src/rcl_service_bindings.cpp +7 -6
- package/src/rcl_subscription_bindings.cpp +51 -14
- package/src/rcl_time_point_bindings.cpp +135 -0
- package/src/rcl_timer_bindings.cpp +140 -0
- package/src/rcl_utilities.cpp +103 -2
- package/src/rcl_utilities.h +7 -1
- package/types/action_client.d.ts +27 -2
- package/types/base.d.ts +3 -0
- package/types/client.d.ts +29 -1
- package/types/clock.d.ts +86 -0
- package/types/clock_change.d.ts +27 -0
- package/types/clock_event.d.ts +51 -0
- package/types/errors.d.ts +49 -0
- package/types/index.d.ts +10 -0
- package/types/interfaces.d.ts +1 -1910
- package/types/logging.d.ts +32 -0
- package/types/message_introspector.d.ts +75 -0
- package/types/message_validation.d.ts +183 -0
- package/types/node.d.ts +67 -0
- package/types/node_options.d.ts +13 -0
- package/types/observable_subscription.d.ts +39 -0
- package/types/publisher.d.ts +28 -1
- package/types/qos.d.ts +18 -0
- package/types/subscription.d.ts +6 -0
- package/types/timer.d.ts +18 -0
- package/types/validator.d.ts +86 -0
|
@@ -15,15 +15,105 @@
|
|
|
15
15
|
#include "rcl_logging_bindings.h"
|
|
16
16
|
|
|
17
17
|
#include <rcl/error_handling.h>
|
|
18
|
+
#include <rcl/logging.h>
|
|
19
|
+
#include <rcl/logging_rosout.h>
|
|
18
20
|
#include <rcl/rcl.h>
|
|
21
|
+
#include <rcl_logging_interface/rcl_logging_interface.h>
|
|
19
22
|
|
|
23
|
+
#include <mutex>
|
|
20
24
|
#include <string>
|
|
21
25
|
|
|
22
26
|
#include "macros.h"
|
|
27
|
+
#include "rcl_handle.h"
|
|
23
28
|
#include "rcl_utilities.h"
|
|
24
29
|
|
|
25
30
|
namespace rclnodejs {
|
|
26
31
|
|
|
32
|
+
Napi::Value InitRosoutPublisherForNode(const Napi::CallbackInfo& info) {
|
|
33
|
+
Napi::Env env = info.Env();
|
|
34
|
+
RclHandle* node_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
|
|
35
|
+
rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
|
|
36
|
+
|
|
37
|
+
if (rcl_logging_rosout_enabled()) {
|
|
38
|
+
rcl_ret_t ret = rcl_logging_rosout_init_publisher_for_node(node);
|
|
39
|
+
if (ret != RCL_RET_OK) {
|
|
40
|
+
Napi::Error::New(env, rcl_get_error_string().str)
|
|
41
|
+
.ThrowAsJavaScriptException();
|
|
42
|
+
rcl_reset_error();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return env.Undefined();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
static std::recursive_mutex logging_mutex;
|
|
49
|
+
|
|
50
|
+
static void rclnodejs_thread_safe_logging_output_handler(
|
|
51
|
+
const rcutils_log_location_t* location, int severity, const char* name,
|
|
52
|
+
rcutils_time_point_value_t timestamp, const char* format, va_list* args) {
|
|
53
|
+
try {
|
|
54
|
+
std::lock_guard<std::recursive_mutex> lock(logging_mutex);
|
|
55
|
+
rcl_logging_multiple_output_handler(location, severity, name, timestamp,
|
|
56
|
+
format, args);
|
|
57
|
+
} catch (const std::exception& ex) {
|
|
58
|
+
RCUTILS_SAFE_FWRITE_TO_STDERR(
|
|
59
|
+
"rclnodejs failed to get the global logging mutex: ");
|
|
60
|
+
RCUTILS_SAFE_FWRITE_TO_STDERR(ex.what());
|
|
61
|
+
RCUTILS_SAFE_FWRITE_TO_STDERR("\n");
|
|
62
|
+
} catch (...) {
|
|
63
|
+
RCUTILS_SAFE_FWRITE_TO_STDERR(
|
|
64
|
+
"rclnodejs failed to get the global logging mutex\n");
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
Napi::Value LoggingConfigure(const Napi::CallbackInfo& info) {
|
|
69
|
+
Napi::Env env = info.Env();
|
|
70
|
+
RclHandle* context_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
|
|
71
|
+
rcl_context_t* context =
|
|
72
|
+
reinterpret_cast<rcl_context_t*>(context_handle->ptr());
|
|
73
|
+
|
|
74
|
+
rcl_allocator_t allocator = rcl_get_default_allocator();
|
|
75
|
+
|
|
76
|
+
std::lock_guard<std::recursive_mutex> lock(logging_mutex);
|
|
77
|
+
rcl_ret_t ret = rcl_logging_configure_with_output_handler(
|
|
78
|
+
&context->global_arguments, &allocator,
|
|
79
|
+
rclnodejs_thread_safe_logging_output_handler);
|
|
80
|
+
|
|
81
|
+
if (ret != RCL_RET_OK) {
|
|
82
|
+
Napi::Error::New(env, rcl_get_error_string().str)
|
|
83
|
+
.ThrowAsJavaScriptException();
|
|
84
|
+
rcl_reset_error();
|
|
85
|
+
}
|
|
86
|
+
return env.Undefined();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
Napi::Value FiniRosoutPublisherForNode(const Napi::CallbackInfo& info) {
|
|
90
|
+
Napi::Env env = info.Env();
|
|
91
|
+
RclHandle* node_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
|
|
92
|
+
rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
|
|
93
|
+
|
|
94
|
+
if (rcl_logging_rosout_enabled()) {
|
|
95
|
+
rcl_ret_t ret = rcl_logging_rosout_fini_publisher_for_node(node);
|
|
96
|
+
if (ret != RCL_RET_OK) {
|
|
97
|
+
Napi::Error::New(env, rcl_get_error_string().str)
|
|
98
|
+
.ThrowAsJavaScriptException();
|
|
99
|
+
rcl_reset_error();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return env.Undefined();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
Napi::Value LoggingFini(const Napi::CallbackInfo& info) {
|
|
106
|
+
Napi::Env env = info.Env();
|
|
107
|
+
std::lock_guard<std::recursive_mutex> lock(logging_mutex);
|
|
108
|
+
rcl_ret_t ret = rcl_logging_fini();
|
|
109
|
+
if (ret != RCL_RET_OK) {
|
|
110
|
+
Napi::Error::New(env, rcl_get_error_string().str)
|
|
111
|
+
.ThrowAsJavaScriptException();
|
|
112
|
+
rcl_reset_error();
|
|
113
|
+
}
|
|
114
|
+
return env.Undefined();
|
|
115
|
+
}
|
|
116
|
+
|
|
27
117
|
Napi::Value setLoggerLevel(const Napi::CallbackInfo& info) {
|
|
28
118
|
Napi::Env env = info.Env();
|
|
29
119
|
|
|
@@ -84,12 +174,80 @@ Napi::Value IsEnableFor(const Napi::CallbackInfo& info) {
|
|
|
84
174
|
return Napi::Boolean::New(env, enabled);
|
|
85
175
|
}
|
|
86
176
|
|
|
177
|
+
Napi::Value GetLoggingDirectory(const Napi::CallbackInfo& info) {
|
|
178
|
+
Napi::Env env = info.Env();
|
|
179
|
+
rcutils_allocator_t allocator = rcutils_get_default_allocator();
|
|
180
|
+
char* directory_path = nullptr;
|
|
181
|
+
rcl_logging_ret_t ret =
|
|
182
|
+
rcl_logging_get_logging_directory(allocator, &directory_path);
|
|
183
|
+
|
|
184
|
+
if (ret != RCL_LOGGING_RET_OK) {
|
|
185
|
+
Napi::Error::New(env, rcutils_get_error_string().str)
|
|
186
|
+
.ThrowAsJavaScriptException();
|
|
187
|
+
rcutils_reset_error();
|
|
188
|
+
return env.Undefined();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
Napi::String result = Napi::String::New(env, directory_path);
|
|
192
|
+
allocator.deallocate(directory_path, allocator.state);
|
|
193
|
+
return result;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
#if ROS_VERSION > 2205
|
|
197
|
+
Napi::Value AddRosoutSublogger(const Napi::CallbackInfo& info) {
|
|
198
|
+
Napi::Env env = info.Env();
|
|
199
|
+
std::string logger_name = info[0].As<Napi::String>().Utf8Value();
|
|
200
|
+
std::string sublogger_name = info[1].As<Napi::String>().Utf8Value();
|
|
201
|
+
|
|
202
|
+
rcl_ret_t ret = rcl_logging_rosout_add_sublogger(logger_name.c_str(),
|
|
203
|
+
sublogger_name.c_str());
|
|
204
|
+
if (ret == RCL_RET_OK) {
|
|
205
|
+
return Napi::Boolean::New(env, true);
|
|
206
|
+
} else if (ret == RCL_RET_NOT_FOUND) {
|
|
207
|
+
rcl_reset_error();
|
|
208
|
+
return Napi::Boolean::New(env, false);
|
|
209
|
+
} else {
|
|
210
|
+
Napi::Error::New(env, rcl_get_error_string().str)
|
|
211
|
+
.ThrowAsJavaScriptException();
|
|
212
|
+
rcl_reset_error();
|
|
213
|
+
return env.Undefined();
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
Napi::Value RemoveRosoutSublogger(const Napi::CallbackInfo& info) {
|
|
218
|
+
Napi::Env env = info.Env();
|
|
219
|
+
std::string logger_name = info[0].As<Napi::String>().Utf8Value();
|
|
220
|
+
std::string sublogger_name = info[1].As<Napi::String>().Utf8Value();
|
|
221
|
+
|
|
222
|
+
rcl_ret_t ret = rcl_logging_rosout_remove_sublogger(logger_name.c_str(),
|
|
223
|
+
sublogger_name.c_str());
|
|
224
|
+
if (ret != RCL_RET_OK) {
|
|
225
|
+
rcl_reset_error();
|
|
226
|
+
}
|
|
227
|
+
return env.Undefined();
|
|
228
|
+
}
|
|
229
|
+
#endif
|
|
230
|
+
|
|
87
231
|
Napi::Object InitLoggingBindings(Napi::Env env, Napi::Object exports) {
|
|
88
232
|
exports.Set("setLoggerLevel", Napi::Function::New(env, setLoggerLevel));
|
|
89
233
|
exports.Set("getLoggerEffectiveLevel",
|
|
90
234
|
Napi::Function::New(env, GetLoggerEffectiveLevel));
|
|
91
235
|
exports.Set("log", Napi::Function::New(env, Log));
|
|
92
236
|
exports.Set("isEnableFor", Napi::Function::New(env, IsEnableFor));
|
|
237
|
+
exports.Set("getLoggingDirectory",
|
|
238
|
+
Napi::Function::New(env, GetLoggingDirectory));
|
|
239
|
+
exports.Set("initRosoutPublisherForNode",
|
|
240
|
+
Napi::Function::New(env, InitRosoutPublisherForNode));
|
|
241
|
+
exports.Set("finiRosoutPublisherForNode",
|
|
242
|
+
Napi::Function::New(env, FiniRosoutPublisherForNode));
|
|
243
|
+
#if ROS_VERSION > 2205
|
|
244
|
+
exports.Set("addRosoutSublogger",
|
|
245
|
+
Napi::Function::New(env, AddRosoutSublogger));
|
|
246
|
+
exports.Set("removeRosoutSublogger",
|
|
247
|
+
Napi::Function::New(env, RemoveRosoutSublogger));
|
|
248
|
+
#endif
|
|
249
|
+
exports.Set("loggingConfigure", Napi::Function::New(env, LoggingConfigure));
|
|
250
|
+
exports.Set("loggingFini", Napi::Function::New(env, LoggingFini));
|
|
93
251
|
return exports;
|
|
94
252
|
}
|
|
95
253
|
|
|
@@ -26,8 +26,10 @@
|
|
|
26
26
|
#include <rcl_yaml_param_parser/types.h>
|
|
27
27
|
|
|
28
28
|
#include <rcpputils/scope_exit.hpp>
|
|
29
|
-
//
|
|
29
|
+
// NOLINTBEGIN
|
|
30
|
+
#include <memory>
|
|
30
31
|
#include <string>
|
|
32
|
+
// NOLINTEND
|
|
31
33
|
|
|
32
34
|
#include "macros.h"
|
|
33
35
|
#include "rcl_handle.h"
|
|
@@ -191,12 +193,17 @@ Napi::Value CreateNode(const Napi::CallbackInfo& info) {
|
|
|
191
193
|
rcl_arguments_t arguments = rcl_get_zero_initialized_arguments();
|
|
192
194
|
rcl_ret_t ret =
|
|
193
195
|
rcl_parse_arguments(argc, argv, rcl_get_default_allocator(), &arguments);
|
|
194
|
-
if (
|
|
196
|
+
if (ret != RCL_RET_OK) {
|
|
195
197
|
Napi::Error::New(env, "failed to parse arguments")
|
|
196
198
|
.ThrowAsJavaScriptException();
|
|
197
199
|
return env.Undefined();
|
|
198
200
|
}
|
|
199
201
|
|
|
202
|
+
ThrowIfUnparsedROSArgs(env, jsArgv, arguments);
|
|
203
|
+
if (env.IsExceptionPending()) {
|
|
204
|
+
return env.Undefined();
|
|
205
|
+
}
|
|
206
|
+
|
|
200
207
|
RCPPUTILS_SCOPE_EXIT({
|
|
201
208
|
if (RCL_RET_OK != rcl_arguments_fini(&arguments)) {
|
|
202
209
|
Napi::Error::New(env, "failed to fini arguments")
|
|
@@ -212,6 +219,11 @@ Napi::Value CreateNode(const Napi::CallbackInfo& info) {
|
|
|
212
219
|
options.use_global_arguments = use_global_arguments;
|
|
213
220
|
options.arguments = arguments;
|
|
214
221
|
|
|
222
|
+
if (info.Length() > 5 && !info[5].IsUndefined() && !info[5].IsNull()) {
|
|
223
|
+
std::unique_ptr<rmw_qos_profile_t> qos_profile = GetQoSProfile(info[5]);
|
|
224
|
+
options.rosout_qos = *qos_profile;
|
|
225
|
+
}
|
|
226
|
+
|
|
215
227
|
THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
|
|
216
228
|
rcl_node_init(node, node_name.c_str(),
|
|
217
229
|
name_space.c_str(), context, &options),
|
|
@@ -147,6 +147,17 @@ Napi::Value WaitForAllAcked(const Napi::CallbackInfo& info) {
|
|
|
147
147
|
return env.Undefined();
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
+
Napi::Value AssertLiveliness(const Napi::CallbackInfo& info) {
|
|
151
|
+
Napi::Env env = info.Env();
|
|
152
|
+
rcl_publisher_t* publisher = reinterpret_cast<rcl_publisher_t*>(
|
|
153
|
+
RclHandle::Unwrap(info[0].As<Napi::Object>())->ptr());
|
|
154
|
+
|
|
155
|
+
THROW_ERROR_IF_NOT_EQUAL(rcl_publisher_assert_liveliness(publisher),
|
|
156
|
+
RCL_RET_OK, rcl_get_error_string().str);
|
|
157
|
+
|
|
158
|
+
return env.Undefined();
|
|
159
|
+
}
|
|
160
|
+
|
|
150
161
|
Napi::Object InitPublisherBindings(Napi::Env env, Napi::Object exports) {
|
|
151
162
|
exports.Set("createPublisher", Napi::Function::New(env, CreatePublisher));
|
|
152
163
|
exports.Set("publish", Napi::Function::New(env, Publish));
|
|
@@ -155,6 +166,7 @@ Napi::Object InitPublisherBindings(Napi::Env env, Napi::Object exports) {
|
|
|
155
166
|
exports.Set("getSubscriptionCount",
|
|
156
167
|
Napi::Function::New(env, GetSubscriptionCount));
|
|
157
168
|
exports.Set("waitForAllAcked", Napi::Function::New(env, WaitForAllAcked));
|
|
169
|
+
exports.Set("assertLiveliness", Napi::Function::New(env, AssertLiveliness));
|
|
158
170
|
return exports;
|
|
159
171
|
}
|
|
160
172
|
|
|
@@ -77,11 +77,11 @@ Napi::Value RclTakeRequest(const Napi::CallbackInfo& info) {
|
|
|
77
77
|
|
|
78
78
|
rcl_service_t* service = reinterpret_cast<rcl_service_t*>(
|
|
79
79
|
RclHandle::Unwrap(info[0].As<Napi::Object>())->ptr());
|
|
80
|
-
|
|
81
|
-
reinterpret_cast<
|
|
80
|
+
rmw_service_info_t* header =
|
|
81
|
+
reinterpret_cast<rmw_service_info_t*>(malloc(sizeof(rmw_service_info_t)));
|
|
82
82
|
|
|
83
83
|
void* taken_request = info[2].As<Napi::Buffer<char>>().Data();
|
|
84
|
-
rcl_ret_t ret =
|
|
84
|
+
rcl_ret_t ret = rcl_take_request_with_info(service, header, taken_request);
|
|
85
85
|
if (ret != RCL_RET_SERVICE_TAKE_FAILED) {
|
|
86
86
|
auto js_obj = RclHandle::NewInstance(env, header, nullptr,
|
|
87
87
|
[](void* ptr) { free(ptr); });
|
|
@@ -98,11 +98,12 @@ Napi::Value SendResponse(const Napi::CallbackInfo& info) {
|
|
|
98
98
|
RclHandle::Unwrap(info[0].As<Napi::Object>())->ptr());
|
|
99
99
|
void* buffer = info[1].As<Napi::Buffer<char>>().Data();
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
rmw_service_info_t* header = reinterpret_cast<rmw_service_info_t*>(
|
|
102
102
|
RclHandle::Unwrap(info[2].As<Napi::Object>())->ptr());
|
|
103
103
|
|
|
104
|
-
THROW_ERROR_IF_NOT_EQUAL(
|
|
105
|
-
|
|
104
|
+
THROW_ERROR_IF_NOT_EQUAL(
|
|
105
|
+
rcl_send_response(service, &(header->request_id), buffer), RCL_RET_OK,
|
|
106
|
+
rcl_get_error_string().str);
|
|
106
107
|
|
|
107
108
|
return env.Undefined();
|
|
108
109
|
}
|
|
@@ -76,7 +76,6 @@ Napi::Value CreateSubscription(const Napi::CallbackInfo& info) {
|
|
|
76
76
|
subscription_ops.qos = *qos_profile;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
#if ROS_VERSION >= 2205 // 2205 => Humble+
|
|
80
79
|
if (options.Has("contentFilter")) {
|
|
81
80
|
// configure content-filter
|
|
82
81
|
Napi::Value contentFilterVal = options.Get("contentFilter");
|
|
@@ -123,7 +122,6 @@ Napi::Value CreateSubscription(const Napi::CallbackInfo& info) {
|
|
|
123
122
|
}
|
|
124
123
|
}
|
|
125
124
|
}
|
|
126
|
-
#endif
|
|
127
125
|
|
|
128
126
|
const rosidl_message_type_support_t* ts =
|
|
129
127
|
GetMessageTypeSupport(package_name, message_sub_folder, message_name);
|
|
@@ -201,9 +199,6 @@ Napi::Value GetSubscriptionTopic(const Napi::CallbackInfo& info) {
|
|
|
201
199
|
}
|
|
202
200
|
|
|
203
201
|
Napi::Value HasContentFilter(const Napi::CallbackInfo& info) {
|
|
204
|
-
#if ROS_VERSION < 2205 // 2205 => Humble+
|
|
205
|
-
return Napi::Boolean::New(info.Env(), false);
|
|
206
|
-
#else
|
|
207
202
|
Napi::Env env = info.Env();
|
|
208
203
|
|
|
209
204
|
RclHandle* subscription_handle =
|
|
@@ -213,13 +208,9 @@ Napi::Value HasContentFilter(const Napi::CallbackInfo& info) {
|
|
|
213
208
|
|
|
214
209
|
bool is_valid = rcl_subscription_is_cft_enabled(subscription);
|
|
215
210
|
return Napi::Boolean::New(env, is_valid);
|
|
216
|
-
#endif
|
|
217
211
|
}
|
|
218
212
|
|
|
219
213
|
Napi::Value SetContentFilter(const Napi::CallbackInfo& info) {
|
|
220
|
-
#if ROS_VERSION < 2205 // 2205 => Humble+
|
|
221
|
-
return Napi::Boolean::New(info.Env(), false);
|
|
222
|
-
#else
|
|
223
214
|
Napi::Env env = info.Env();
|
|
224
215
|
|
|
225
216
|
RclHandle* subscription_handle =
|
|
@@ -272,13 +263,9 @@ Napi::Value SetContentFilter(const Napi::CallbackInfo& info) {
|
|
|
272
263
|
}
|
|
273
264
|
|
|
274
265
|
return Napi::Boolean::New(env, true);
|
|
275
|
-
#endif
|
|
276
266
|
}
|
|
277
267
|
|
|
278
268
|
Napi::Value ClearContentFilter(const Napi::CallbackInfo& info) {
|
|
279
|
-
#if ROS_VERSION < 2205 // 2205 => Humble+
|
|
280
|
-
return Napi::Boolean::New(info.Env(), false);
|
|
281
|
-
#else
|
|
282
269
|
Napi::Env env = info.Env();
|
|
283
270
|
|
|
284
271
|
RclHandle* subscription_handle =
|
|
@@ -301,7 +288,56 @@ Napi::Value ClearContentFilter(const Napi::CallbackInfo& info) {
|
|
|
301
288
|
rcl_get_error_string().str);
|
|
302
289
|
|
|
303
290
|
return Napi::Boolean::New(env, true);
|
|
304
|
-
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
Napi::Value GetContentFilter(const Napi::CallbackInfo& info) {
|
|
294
|
+
Napi::Env env = info.Env();
|
|
295
|
+
|
|
296
|
+
RclHandle* subscription_handle =
|
|
297
|
+
RclHandle::Unwrap(info[0].As<Napi::Object>());
|
|
298
|
+
rcl_subscription_t* subscription =
|
|
299
|
+
reinterpret_cast<rcl_subscription_t*>(subscription_handle->ptr());
|
|
300
|
+
|
|
301
|
+
rcl_subscription_content_filter_options_t options =
|
|
302
|
+
rcl_get_zero_initialized_subscription_content_filter_options();
|
|
303
|
+
|
|
304
|
+
rcl_ret_t ret = rcl_subscription_get_content_filter(subscription, &options);
|
|
305
|
+
if (ret != RCL_RET_OK) {
|
|
306
|
+
Napi::Error::New(env, rcl_get_error_string().str)
|
|
307
|
+
.ThrowAsJavaScriptException();
|
|
308
|
+
rcl_reset_error();
|
|
309
|
+
return env.Undefined();
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Create result object
|
|
313
|
+
Napi::Object result = Napi::Object::New(env);
|
|
314
|
+
result.Set(
|
|
315
|
+
"expression",
|
|
316
|
+
Napi::String::New(
|
|
317
|
+
env,
|
|
318
|
+
options.rmw_subscription_content_filter_options.filter_expression));
|
|
319
|
+
|
|
320
|
+
size_t param_count = options.rmw_subscription_content_filter_options
|
|
321
|
+
.expression_parameters.size;
|
|
322
|
+
Napi::Array parameters = Napi::Array::New(env, param_count);
|
|
323
|
+
for (size_t i = 0; i < param_count; ++i) {
|
|
324
|
+
parameters[i] =
|
|
325
|
+
Napi::String::New(env, options.rmw_subscription_content_filter_options
|
|
326
|
+
.expression_parameters.data[i]);
|
|
327
|
+
}
|
|
328
|
+
result.Set("parameters", parameters);
|
|
329
|
+
|
|
330
|
+
// Cleanup
|
|
331
|
+
rcl_ret_t fini_ret =
|
|
332
|
+
rcl_subscription_content_filter_options_fini(subscription, &options);
|
|
333
|
+
if (fini_ret != RCL_RET_OK) {
|
|
334
|
+
Napi::Error::New(env, rcl_get_error_string().str)
|
|
335
|
+
.ThrowAsJavaScriptException();
|
|
336
|
+
rcl_reset_error();
|
|
337
|
+
return env.Undefined();
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return result;
|
|
305
341
|
}
|
|
306
342
|
|
|
307
343
|
Napi::Value GetPublisherCount(const Napi::CallbackInfo& info) {
|
|
@@ -327,6 +363,7 @@ Napi::Object InitSubscriptionBindings(Napi::Env env, Napi::Object exports) {
|
|
|
327
363
|
Napi::Function::New(env, GetSubscriptionTopic));
|
|
328
364
|
exports.Set("hasContentFilter", Napi::Function::New(env, HasContentFilter));
|
|
329
365
|
exports.Set("setContentFilter", Napi::Function::New(env, SetContentFilter));
|
|
366
|
+
exports.Set("getContentFilter", Napi::Function::New(env, GetContentFilter));
|
|
330
367
|
exports.Set("clearContentFilter",
|
|
331
368
|
Napi::Function::New(env, ClearContentFilter));
|
|
332
369
|
exports.Set("getPublisherCount", Napi::Function::New(env, GetPublisherCount));
|
|
@@ -175,9 +175,144 @@ Napi::Value ClockGetNow(const Napi::CallbackInfo& info) {
|
|
|
175
175
|
return Napi::BigInt::New(env, time_point.nanoseconds);
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
+
struct JumpCallbackData {
|
|
179
|
+
Napi::ThreadSafeFunction tsfn_pre;
|
|
180
|
+
Napi::ThreadSafeFunction tsfn_post;
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
struct JumpCallbackContext {
|
|
184
|
+
rcl_time_jump_t time_jump;
|
|
185
|
+
bool before_jump;
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
void _rclnodejs_on_time_jump(const rcl_time_jump_t* time_jump, bool before_jump,
|
|
189
|
+
void* user_data) {
|
|
190
|
+
JumpCallbackData* data = static_cast<JumpCallbackData*>(user_data);
|
|
191
|
+
|
|
192
|
+
auto context = new JumpCallbackContext{*time_jump, before_jump};
|
|
193
|
+
|
|
194
|
+
if (before_jump) {
|
|
195
|
+
auto callback = [](Napi::Env env, Napi::Function js_callback,
|
|
196
|
+
JumpCallbackContext* context) {
|
|
197
|
+
js_callback.Call({});
|
|
198
|
+
delete context;
|
|
199
|
+
};
|
|
200
|
+
data->tsfn_pre.NonBlockingCall(context, callback);
|
|
201
|
+
} else {
|
|
202
|
+
auto callback = [](Napi::Env env, Napi::Function js_callback,
|
|
203
|
+
JumpCallbackContext* context) {
|
|
204
|
+
Napi::Object jump_info = Napi::Object::New(env);
|
|
205
|
+
jump_info.Set("clock_change",
|
|
206
|
+
static_cast<int32_t>(context->time_jump.clock_change));
|
|
207
|
+
jump_info.Set("delta", Napi::BigInt::New(
|
|
208
|
+
env, context->time_jump.delta.nanoseconds));
|
|
209
|
+
js_callback.Call({jump_info});
|
|
210
|
+
delete context;
|
|
211
|
+
};
|
|
212
|
+
data->tsfn_post.NonBlockingCall(context, callback);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
Napi::Value ClockAddJumpCallback(const Napi::CallbackInfo& info) {
|
|
217
|
+
Napi::Env env = info.Env();
|
|
218
|
+
|
|
219
|
+
RclHandle* clock_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
|
|
220
|
+
rcl_clock_t* clock = reinterpret_cast<rcl_clock_t*>(clock_handle->ptr());
|
|
221
|
+
|
|
222
|
+
Napi::Object callback_obj = info[1].As<Napi::Object>();
|
|
223
|
+
Napi::Function pre_callback =
|
|
224
|
+
callback_obj.Get("_pre_callback").As<Napi::Function>();
|
|
225
|
+
Napi::Function post_callback =
|
|
226
|
+
callback_obj.Get("_post_callback").As<Napi::Function>();
|
|
227
|
+
|
|
228
|
+
bool on_clock_change = info[2].As<Napi::Boolean>();
|
|
229
|
+
|
|
230
|
+
bool lossless;
|
|
231
|
+
int64_t min_forward = info[3].As<Napi::BigInt>().Int64Value(&lossless);
|
|
232
|
+
if (!lossless) {
|
|
233
|
+
Napi::TypeError::New(
|
|
234
|
+
env, "min_forward BigInt value cannot be represented as int64_t")
|
|
235
|
+
.ThrowAsJavaScriptException();
|
|
236
|
+
return env.Undefined();
|
|
237
|
+
}
|
|
238
|
+
int64_t min_backward = info[4].As<Napi::BigInt>().Int64Value(&lossless);
|
|
239
|
+
if (!lossless) {
|
|
240
|
+
Napi::TypeError::New(
|
|
241
|
+
env, "min_backward BigInt value cannot be represented as int64_t")
|
|
242
|
+
.ThrowAsJavaScriptException();
|
|
243
|
+
return env.Undefined();
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
rcl_jump_threshold_t threshold;
|
|
247
|
+
threshold.on_clock_change = on_clock_change;
|
|
248
|
+
threshold.min_forward.nanoseconds = min_forward;
|
|
249
|
+
threshold.min_backward.nanoseconds = min_backward;
|
|
250
|
+
|
|
251
|
+
JumpCallbackData* data = new JumpCallbackData();
|
|
252
|
+
data->tsfn_pre = Napi::ThreadSafeFunction::New(
|
|
253
|
+
env, pre_callback, "ClockJumpPreCallback", 10, 1, [](Napi::Env) {});
|
|
254
|
+
data->tsfn_post =
|
|
255
|
+
Napi::ThreadSafeFunction::New(env, post_callback, "ClockJumpPostCallback",
|
|
256
|
+
10, 1, [data](Napi::Env) { delete data; });
|
|
257
|
+
|
|
258
|
+
Napi::Object handle_obj = Napi::Object::New(env);
|
|
259
|
+
handle_obj.Set("_cpp_handle",
|
|
260
|
+
Napi::External<JumpCallbackData>::New(env, data));
|
|
261
|
+
|
|
262
|
+
rcl_ret_t ret = rcl_clock_add_jump_callback(clock, threshold,
|
|
263
|
+
_rclnodejs_on_time_jump, data);
|
|
264
|
+
|
|
265
|
+
if (ret != RCL_RET_OK) {
|
|
266
|
+
data->tsfn_pre.Release();
|
|
267
|
+
data->tsfn_post.Release();
|
|
268
|
+
THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, ret, rcl_get_error_string().str);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
callback_obj.Set("_cpp_handle", handle_obj.Get("_cpp_handle"));
|
|
272
|
+
|
|
273
|
+
return env.Undefined();
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
Napi::Value ClockRemoveJumpCallback(const Napi::CallbackInfo& info) {
|
|
277
|
+
Napi::Env env = info.Env();
|
|
278
|
+
|
|
279
|
+
RclHandle* clock_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
|
|
280
|
+
rcl_clock_t* clock = reinterpret_cast<rcl_clock_t*>(clock_handle->ptr());
|
|
281
|
+
|
|
282
|
+
Napi::Object handle_obj = info[1].As<Napi::Object>();
|
|
283
|
+
Napi::Value cpp_handle = handle_obj.Get("_cpp_handle");
|
|
284
|
+
|
|
285
|
+
if (cpp_handle.IsUndefined() || !cpp_handle.IsExternal()) {
|
|
286
|
+
Napi::Error::New(env,
|
|
287
|
+
"Callback object was not registered or already removed")
|
|
288
|
+
.ThrowAsJavaScriptException();
|
|
289
|
+
return env.Undefined();
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
JumpCallbackData* data =
|
|
293
|
+
cpp_handle.As<Napi::External<JumpCallbackData>>().Data();
|
|
294
|
+
|
|
295
|
+
rcl_ret_t ret =
|
|
296
|
+
rcl_clock_remove_jump_callback(clock, _rclnodejs_on_time_jump, data);
|
|
297
|
+
|
|
298
|
+
if (ret == RCL_RET_OK) {
|
|
299
|
+
data->tsfn_pre.Release();
|
|
300
|
+
data->tsfn_post.Release();
|
|
301
|
+
handle_obj.Set("_cpp_handle", env.Undefined());
|
|
302
|
+
} else {
|
|
303
|
+
THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, ret, rcl_get_error_string().str);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return env.Undefined();
|
|
307
|
+
}
|
|
308
|
+
|
|
178
309
|
Napi::Object InitTimePointBindings(Napi::Env env, Napi::Object exports) {
|
|
179
310
|
exports.Set("createClock", Napi::Function::New(env, CreateClock));
|
|
180
311
|
exports.Set("clockGetNow", Napi::Function::New(env, ClockGetNow));
|
|
312
|
+
exports.Set("clockAddJumpCallback",
|
|
313
|
+
Napi::Function::New(env, ClockAddJumpCallback));
|
|
314
|
+
exports.Set("clockRemoveJumpCallback",
|
|
315
|
+
Napi::Function::New(env, ClockRemoveJumpCallback));
|
|
181
316
|
exports.Set("createTimePoint", Napi::Function::New(env, CreateTimePoint));
|
|
182
317
|
exports.Set("getNanoseconds", Napi::Function::New(env, GetNanoseconds));
|
|
183
318
|
exports.Set("createDuration", Napi::Function::New(env, CreateDuration));
|