rclnodejs 0.33.0 → 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 (66) 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 +53 -0
  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/scripts/config.js +1 -0
  13. package/scripts/npmjs-readme.md +3 -3
  14. package/src/addon.cpp +54 -53
  15. package/src/executor.cpp +19 -10
  16. package/src/{executor.hpp → executor.h} +7 -5
  17. package/src/handle_manager.cpp +30 -56
  18. package/src/{handle_manager.hpp → handle_manager.h} +8 -7
  19. package/src/{macros.hpp → macros.h} +7 -5
  20. package/src/rcl_action_client_bindings.cpp +231 -0
  21. package/src/{rcl_action_bindings.hpp → rcl_action_client_bindings.h} +6 -11
  22. package/src/rcl_action_goal_bindings.cpp +117 -0
  23. package/src/rcl_action_goal_bindings.h +26 -0
  24. package/src/rcl_action_server_bindings.cpp +470 -0
  25. package/src/rcl_action_server_bindings.h +26 -0
  26. package/src/rcl_bindings.cpp +42 -2010
  27. package/src/{rcl_bindings.hpp → rcl_bindings.h} +5 -25
  28. package/src/rcl_client_bindings.cpp +183 -0
  29. package/src/rcl_client_bindings.h +26 -0
  30. package/src/rcl_context_bindings.cpp +156 -0
  31. package/src/rcl_context_bindings.h +26 -0
  32. package/src/rcl_graph_bindings.cpp +280 -0
  33. package/src/rcl_graph_bindings.h +26 -0
  34. package/src/rcl_guard_condition_bindings.cpp +75 -0
  35. package/src/rcl_guard_condition_bindings.h +26 -0
  36. package/src/rcl_handle.cpp +41 -57
  37. package/src/{rcl_handle.hpp → rcl_handle.h} +18 -17
  38. package/src/rcl_lifecycle_bindings.cpp +135 -114
  39. package/src/{rcl_lifecycle_bindings.hpp → rcl_lifecycle_bindings.h} +5 -7
  40. package/src/rcl_logging_bindings.cpp +96 -0
  41. package/src/rcl_logging_bindings.h +26 -0
  42. package/src/rcl_names_bindings.cpp +255 -0
  43. package/src/rcl_names_bindings.h +26 -0
  44. package/src/rcl_node_bindings.cpp +447 -0
  45. package/src/rcl_node_bindings.h +26 -0
  46. package/src/rcl_publisher_bindings.cpp +141 -0
  47. package/src/rcl_publisher_bindings.h +26 -0
  48. package/src/rcl_service_bindings.cpp +185 -0
  49. package/src/rcl_service_bindings.h +26 -0
  50. package/src/rcl_subscription_bindings.cpp +335 -0
  51. package/src/rcl_subscription_bindings.h +26 -0
  52. package/src/rcl_time_point_bindings.cpp +194 -0
  53. package/src/rcl_time_point_bindings.h +26 -0
  54. package/src/rcl_timer_bindings.cpp +237 -0
  55. package/src/rcl_timer_bindings.h +26 -0
  56. package/src/rcl_utilities.cpp +166 -1
  57. package/src/{rcl_utilities.hpp → rcl_utilities.h} +21 -3
  58. package/src/shadow_node.cpp +56 -75
  59. package/src/{shadow_node.hpp → shadow_node.h} +18 -17
  60. package/types/context.d.ts +6 -0
  61. package/types/node.d.ts +37 -0
  62. package/types/publisher.d.ts +6 -0
  63. package/types/service.d.ts +6 -0
  64. package/types/subscription.d.ts +6 -0
  65. package/types/timer.d.ts +18 -0
  66. package/src/rcl_action_bindings.cpp +0 -826
@@ -0,0 +1,194 @@
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_time_point_bindings.h"
16
+
17
+ #include <rcl/error_handling.h>
18
+ #include <rcl/rcl.h>
19
+
20
+ #include <memory>
21
+
22
+ #include "macros.h"
23
+ #include "rcl_handle.h"
24
+ #include "rcl_utilities.h"
25
+
26
+ namespace rclnodejs {
27
+
28
+ Napi::Value CreateTimePoint(const Napi::CallbackInfo& info) {
29
+ Napi::Env env = info.Env();
30
+
31
+ if (!info[0].IsBigInt()) {
32
+ Napi::TypeError::New(env, "Timer period must be a BigInt")
33
+ .ThrowAsJavaScriptException();
34
+ return env.Undefined();
35
+ }
36
+
37
+ bool lossless;
38
+ int64_t nanoseconds = info[0].As<Napi::BigInt>().Int64Value(&lossless);
39
+ uint32_t clock_type = info[1].As<Napi::Number>().Uint32Value();
40
+ rcl_time_point_t* time_point =
41
+ reinterpret_cast<rcl_time_point_t*>(malloc(sizeof(rcl_time_point_t)));
42
+
43
+ time_point->nanoseconds = nanoseconds;
44
+ time_point->clock_type = static_cast<rcl_clock_type_t>(clock_type);
45
+
46
+ auto js_obj = RclHandle::NewInstance(env, time_point, nullptr,
47
+ [](void* ptr) { free(ptr); });
48
+
49
+ return js_obj;
50
+ }
51
+
52
+ Napi::Value GetNanoseconds(const Napi::CallbackInfo& info) {
53
+ Napi::Env env = info.Env();
54
+
55
+ RclHandle* time_point_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
56
+ rcl_time_point_t* time_point =
57
+ reinterpret_cast<rcl_time_point_t*>(time_point_handle->ptr());
58
+
59
+ return Napi::BigInt::New(env, time_point->nanoseconds);
60
+ }
61
+
62
+ Napi::Value CreateDuration(const Napi::CallbackInfo& info) {
63
+ Napi::Env env = info.Env();
64
+
65
+ if (!info[0].IsBigInt()) {
66
+ Napi::TypeError::New(env, "Timer period must be a BigInt")
67
+ .ThrowAsJavaScriptException();
68
+ return env.Undefined();
69
+ }
70
+
71
+ bool lossless;
72
+ int64_t nanoseconds = info[0].As<Napi::BigInt>().Int64Value(&lossless);
73
+ rcl_duration_t* duration =
74
+ reinterpret_cast<rcl_duration_t*>(malloc(sizeof(rcl_duration_t)));
75
+ duration->nanoseconds = nanoseconds;
76
+
77
+ auto js_obj = RclHandle::NewInstance(env, duration, nullptr,
78
+ [](void* ptr) { free(ptr); });
79
+
80
+ return js_obj;
81
+ }
82
+
83
+ Napi::Value GetDurationNanoseconds(const Napi::CallbackInfo& info) {
84
+ Napi::Env env = info.Env();
85
+
86
+ RclHandle* duration_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
87
+ rcl_duration_t* duration =
88
+ reinterpret_cast<rcl_duration_t*>(duration_handle->ptr());
89
+
90
+ return Napi::BigInt::New(env, duration->nanoseconds);
91
+ }
92
+
93
+ Napi::Value SetRosTimeOverrideIsEnabled(const Napi::CallbackInfo& info) {
94
+ Napi::Env env = info.Env();
95
+
96
+ RclHandle* clock_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
97
+ rcl_clock_t* clock = reinterpret_cast<rcl_clock_t*>(clock_handle->ptr());
98
+ bool enabled = info[1].As<Napi::Boolean>();
99
+
100
+ if (enabled) {
101
+ THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, rcl_enable_ros_time_override(clock),
102
+ rcl_get_error_string().str);
103
+ } else {
104
+ THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, rcl_disable_ros_time_override(clock),
105
+ rcl_get_error_string().str);
106
+ }
107
+
108
+ return env.Undefined();
109
+ }
110
+
111
+ Napi::Value SetRosTimeOverride(const Napi::CallbackInfo& info) {
112
+ Napi::Env env = info.Env();
113
+
114
+ RclHandle* clock_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
115
+ rcl_clock_t* clock = reinterpret_cast<rcl_clock_t*>(clock_handle->ptr());
116
+ RclHandle* time_point_handle = RclHandle::Unwrap(info[1].As<Napi::Object>());
117
+ rcl_time_point_t* time_point =
118
+ reinterpret_cast<rcl_time_point_t*>(time_point_handle->ptr());
119
+
120
+ THROW_ERROR_IF_NOT_EQUAL(
121
+ RCL_RET_OK, rcl_set_ros_time_override(clock, time_point->nanoseconds),
122
+ rcl_get_error_string().str);
123
+
124
+ return env.Undefined();
125
+ }
126
+
127
+ Napi::Value GetRosTimeOverrideIsEnabled(const Napi::CallbackInfo& info) {
128
+ Napi::Env env = info.Env();
129
+
130
+ RclHandle* clock_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
131
+ rcl_clock_t* clock = reinterpret_cast<rcl_clock_t*>(clock_handle->ptr());
132
+
133
+ bool is_enabled;
134
+ THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
135
+ rcl_is_enabled_ros_time_override(clock, &is_enabled),
136
+ rcl_get_error_string().str);
137
+
138
+ return Napi::Boolean::New(env, is_enabled);
139
+ }
140
+
141
+ Napi::Value CreateClock(const Napi::CallbackInfo& info) {
142
+ Napi::Env env = info.Env();
143
+
144
+ auto clock_type =
145
+ static_cast<rcl_clock_type_t>(info[0].As<Napi::Number>().Int32Value());
146
+ rcl_clock_t* clock =
147
+ reinterpret_cast<rcl_clock_t*>(malloc(sizeof(rcl_clock_t)));
148
+ rcl_allocator_t allocator = rcl_get_default_allocator();
149
+
150
+ THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
151
+ rcl_clock_init(clock_type, clock, &allocator),
152
+ rcl_get_error_string().str);
153
+
154
+ return RclHandle::NewInstance(env, clock, nullptr, [](void* ptr) {
155
+ rcl_clock_t* clock = reinterpret_cast<rcl_clock_t*>(ptr);
156
+ rcl_ret_t ret = rcl_clock_fini(clock);
157
+ free(ptr);
158
+ THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, ret, rcl_get_error_string().str);
159
+ });
160
+ }
161
+
162
+ Napi::Value ClockGetNow(const Napi::CallbackInfo& info) {
163
+ Napi::Env env = info.Env();
164
+
165
+ rcl_clock_t* clock = reinterpret_cast<rcl_clock_t*>(
166
+ RclHandle::Unwrap(info[0].As<Napi::Object>())->ptr());
167
+ rcl_time_point_t time_point;
168
+ time_point.clock_type = clock->type;
169
+
170
+ THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
171
+ rcl_clock_get_now(clock, &time_point.nanoseconds),
172
+ rcl_get_error_string().str);
173
+
174
+ return Napi::BigInt::New(env, time_point.nanoseconds);
175
+ }
176
+
177
+ Napi::Object InitTimePointBindings(Napi::Env env, Napi::Object exports) {
178
+ exports.Set("createClock", Napi::Function::New(env, CreateClock));
179
+ exports.Set("clockGetNow", Napi::Function::New(env, ClockGetNow));
180
+ exports.Set("createTimePoint", Napi::Function::New(env, CreateTimePoint));
181
+ exports.Set("getNanoseconds", Napi::Function::New(env, GetNanoseconds));
182
+ exports.Set("createDuration", Napi::Function::New(env, CreateDuration));
183
+ exports.Set("getDurationNanoseconds",
184
+ Napi::Function::New(env, GetDurationNanoseconds));
185
+ exports.Set("setRosTimeOverrideIsEnabled",
186
+ Napi::Function::New(env, SetRosTimeOverrideIsEnabled));
187
+ exports.Set("setRosTimeOverride",
188
+ Napi::Function::New(env, SetRosTimeOverride));
189
+ exports.Set("getRosTimeOverrideIsEnabled",
190
+ Napi::Function::New(env, GetRosTimeOverrideIsEnabled));
191
+ return exports;
192
+ }
193
+
194
+ } // 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_TIME_POINT_BINDINGS_H_
16
+ #define SRC_RCL_TIME_POINT_BINDINGS_H_
17
+
18
+ #include <napi.h>
19
+
20
+ namespace rclnodejs {
21
+
22
+ Napi::Object InitTimePointBindings(Napi::Env env, Napi::Object exports);
23
+
24
+ }
25
+
26
+ #endif // SRC_RCL_TIME_POINT_BINDINGS_H_
@@ -0,0 +1,237 @@
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_timer_bindings.h"
16
+
17
+ #include <rcl/error_handling.h>
18
+ #include <rcl/rcl.h>
19
+
20
+ #include "macros.h"
21
+ #include "rcl_handle.h"
22
+ #include "rcl_utilities.h"
23
+
24
+ namespace rclnodejs {
25
+
26
+ Napi::Value CreateTimer(const Napi::CallbackInfo& info) {
27
+ Napi::Env env = info.Env();
28
+
29
+ RclHandle* clock_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
30
+ rcl_clock_t* clock = reinterpret_cast<rcl_clock_t*>(clock_handle->ptr());
31
+
32
+ RclHandle* context_handle = RclHandle::Unwrap(info[1].As<Napi::Object>());
33
+ rcl_context_t* context =
34
+ reinterpret_cast<rcl_context_t*>(context_handle->ptr());
35
+
36
+ if (!info[2].IsBigInt()) {
37
+ Napi::TypeError::New(env, "Timer period must be a BigInt")
38
+ .ThrowAsJavaScriptException();
39
+ return env.Undefined();
40
+ }
41
+
42
+ bool lossless;
43
+ int64_t period_nsec = info[2].As<Napi::BigInt>().Int64Value(&lossless);
44
+ rcl_timer_t* timer =
45
+ reinterpret_cast<rcl_timer_t*>(malloc(sizeof(rcl_timer_t)));
46
+ *timer = rcl_get_zero_initialized_timer();
47
+
48
+ #if ROS_VERSION > 2305 // After Iron.
49
+ THROW_ERROR_IF_NOT_EQUAL(
50
+ RCL_RET_OK,
51
+ rcl_timer_init2(timer, clock, context, period_nsec, nullptr,
52
+ rcl_get_default_allocator(), /*autostart=*/true),
53
+ rcl_get_error_string().str);
54
+ #else
55
+ THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
56
+ rcl_timer_init(timer, clock, context, period_nsec,
57
+ nullptr, rcl_get_default_allocator()),
58
+ rcl_get_error_string().str);
59
+ #endif
60
+
61
+ auto js_obj = RclHandle::NewInstance(env, timer, clock_handle, [](void* ptr) {
62
+ rcl_timer_t* timer = reinterpret_cast<rcl_timer_t*>(ptr);
63
+ rcl_ret_t ret = rcl_timer_fini(timer);
64
+ free(ptr);
65
+ THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, ret, rcl_get_error_string().str);
66
+ });
67
+
68
+ return js_obj;
69
+ }
70
+
71
+ Napi::Value IsTimerReady(const Napi::CallbackInfo& info) {
72
+ Napi::Env env = info.Env();
73
+
74
+ RclHandle* timer_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
75
+ rcl_timer_t* timer = reinterpret_cast<rcl_timer_t*>(timer_handle->ptr());
76
+ bool is_ready = false;
77
+
78
+ THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, rcl_timer_is_ready(timer, &is_ready),
79
+ rcl_get_error_string().str);
80
+
81
+ return Napi::Boolean::New(env, is_ready);
82
+ }
83
+
84
+ Napi::Value CallTimer(const Napi::CallbackInfo& info) {
85
+ Napi::Env env = info.Env();
86
+
87
+ RclHandle* timer_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
88
+ rcl_timer_t* timer = reinterpret_cast<rcl_timer_t*>(timer_handle->ptr());
89
+
90
+ THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, rcl_timer_call(timer),
91
+ rcl_get_error_string().str);
92
+
93
+ return env.Undefined();
94
+ }
95
+
96
+ Napi::Value CancelTimer(const Napi::CallbackInfo& info) {
97
+ Napi::Env env = info.Env();
98
+
99
+ RclHandle* timer_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
100
+ rcl_timer_t* timer = reinterpret_cast<rcl_timer_t*>(timer_handle->ptr());
101
+
102
+ THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, rcl_timer_cancel(timer),
103
+ rcl_get_error_string().str);
104
+
105
+ return env.Undefined();
106
+ }
107
+
108
+ Napi::Value IsTimerCanceled(const Napi::CallbackInfo& info) {
109
+ Napi::Env env = info.Env();
110
+
111
+ RclHandle* timer_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
112
+ rcl_timer_t* timer = reinterpret_cast<rcl_timer_t*>(timer_handle->ptr());
113
+ bool is_canceled = false;
114
+
115
+ THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
116
+ rcl_timer_is_canceled(timer, &is_canceled),
117
+ rcl_get_error_string().str);
118
+
119
+ return Napi::Boolean::New(env, is_canceled);
120
+ }
121
+
122
+ Napi::Value ResetTimer(const Napi::CallbackInfo& info) {
123
+ Napi::Env env = info.Env();
124
+
125
+ RclHandle* timer_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
126
+ rcl_timer_t* timer = reinterpret_cast<rcl_timer_t*>(timer_handle->ptr());
127
+
128
+ THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, rcl_timer_reset(timer),
129
+ rcl_get_error_string().str);
130
+
131
+ return env.Undefined();
132
+ }
133
+
134
+ Napi::Value TimerGetTimeUntilNextCall(const Napi::CallbackInfo& info) {
135
+ Napi::Env env = info.Env();
136
+
137
+ RclHandle* timer_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
138
+ rcl_timer_t* timer = reinterpret_cast<rcl_timer_t*>(timer_handle->ptr());
139
+ int64_t remaining_time = 0;
140
+
141
+ THROW_ERROR_IF_NOT_EQUAL(
142
+ RCL_RET_OK, rcl_timer_get_time_until_next_call(timer, &remaining_time),
143
+ rcl_get_error_string().str);
144
+
145
+ return Napi::BigInt::New(env, remaining_time);
146
+ }
147
+
148
+ Napi::Value TimerGetTimeSinceLastCall(const Napi::CallbackInfo& info) {
149
+ Napi::Env env = info.Env();
150
+
151
+ RclHandle* timer_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
152
+ rcl_timer_t* timer = reinterpret_cast<rcl_timer_t*>(timer_handle->ptr());
153
+ int64_t elapsed_time = 0;
154
+
155
+ THROW_ERROR_IF_NOT_EQUAL(
156
+ RCL_RET_OK, rcl_timer_get_time_since_last_call(timer, &elapsed_time),
157
+ rcl_get_error_string().str);
158
+
159
+ return Napi::BigInt::New(env, elapsed_time);
160
+ }
161
+
162
+ Napi::Value ChangeTimerPeriod(const Napi::CallbackInfo& info) {
163
+ Napi::Env env = info.Env();
164
+
165
+ RclHandle* timer_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
166
+ rcl_timer_t* timer = reinterpret_cast<rcl_timer_t*>(timer_handle->ptr());
167
+
168
+ if (!info[1].IsBigInt()) {
169
+ Napi::TypeError::New(env, "Timer period must be a BigInt")
170
+ .ThrowAsJavaScriptException();
171
+ return env.Undefined();
172
+ }
173
+
174
+ bool lossless;
175
+ int64_t period_nsec = info[1].As<Napi::BigInt>().Int64Value(&lossless);
176
+ int64_t old_period;
177
+ THROW_ERROR_IF_NOT_EQUAL(
178
+ RCL_RET_OK, rcl_timer_exchange_period(timer, period_nsec, &old_period),
179
+ rcl_get_error_string().str);
180
+
181
+ return env.Undefined();
182
+ }
183
+
184
+ Napi::Value GetTimerPeriod(const Napi::CallbackInfo& info) {
185
+ Napi::Env env = info.Env();
186
+
187
+ RclHandle* timer_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
188
+ rcl_timer_t* timer = reinterpret_cast<rcl_timer_t*>(timer_handle->ptr());
189
+ int64_t period_nsec = 0;
190
+
191
+ THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
192
+ rcl_timer_get_period(timer, &period_nsec),
193
+ rcl_get_error_string().str);
194
+
195
+ return Napi::BigInt::New(env, period_nsec);
196
+ }
197
+
198
+ #if ROS_VERSION > 2205 // 2205 == Humble
199
+ Napi::Value CallTimerWithInfo(const Napi::CallbackInfo& info) {
200
+ Napi::Env env = info.Env();
201
+ RclHandle* timer_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
202
+ rcl_timer_t* timer = reinterpret_cast<rcl_timer_t*>(timer_handle->ptr());
203
+ rcl_timer_call_info_t call_info;
204
+
205
+ THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
206
+ rcl_timer_call_with_info(timer, &call_info),
207
+ rcl_get_error_string().str);
208
+
209
+ Napi::Object timer_info = Napi::Object::New(env);
210
+ timer_info.Set("expectedCallTime",
211
+ Napi::BigInt::New(env, call_info.expected_call_time));
212
+ timer_info.Set("actualCallTime",
213
+ Napi::BigInt::New(env, call_info.actual_call_time));
214
+ return timer_info;
215
+ }
216
+ #endif
217
+
218
+ Napi::Object InitTimerBindings(Napi::Env env, Napi::Object exports) {
219
+ exports.Set("createTimer", Napi::Function::New(env, CreateTimer));
220
+ exports.Set("isTimerReady", Napi::Function::New(env, IsTimerReady));
221
+ exports.Set("callTimer", Napi::Function::New(env, CallTimer));
222
+ exports.Set("cancelTimer", Napi::Function::New(env, CancelTimer));
223
+ exports.Set("isTimerCanceled", Napi::Function::New(env, IsTimerCanceled));
224
+ exports.Set("resetTimer", Napi::Function::New(env, ResetTimer));
225
+ exports.Set("timerGetTimeSinceLastCall",
226
+ Napi::Function::New(env, TimerGetTimeSinceLastCall));
227
+ exports.Set("timerGetTimeUntilNextCall",
228
+ Napi::Function::New(env, TimerGetTimeUntilNextCall));
229
+ exports.Set("changeTimerPeriod", Napi::Function::New(env, ChangeTimerPeriod));
230
+ exports.Set("getTimerPeriod", Napi::Function::New(env, GetTimerPeriod));
231
+ #if ROS_VERSION > 2205 // 2205 == Humble
232
+ exports.Set("callTimerWithInfo", Napi::Function::New(env, CallTimerWithInfo));
233
+ #endif
234
+ return exports;
235
+ }
236
+
237
+ } // 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_TIMER_BINDINGS_H_
16
+ #define SRC_RCL_TIMER_BINDINGS_H_
17
+
18
+ #include <napi.h>
19
+
20
+ namespace rclnodejs {
21
+
22
+ Napi::Object InitTimerBindings(Napi::Env env, Napi::Object exports);
23
+
24
+ }
25
+
26
+ #endif // SRC_RCL_TIMER_BINDINGS_H_
@@ -12,16 +12,115 @@
12
12
  // See the License for the specific language governing permissions and
13
13
  // limitations under the License.
14
14
 
15
- #include "rcl_utilities.hpp"
15
+ #include "rcl_utilities.h"
16
16
 
17
17
  #include <rcl/rcl.h>
18
18
  #include <rcl_action/rcl_action.h>
19
+ #include <rmw/topic_endpoint_info.h>
19
20
  #include <uv.h>
20
21
 
22
+ #include <memory>
21
23
  #include <string>
22
24
 
23
25
  namespace {
26
+
27
+ const rmw_qos_profile_t* GetQoSProfileFromString(const std::string& profile) {
28
+ const rmw_qos_profile_t* qos_profile = nullptr;
29
+ if (profile == "qos_profile_sensor_data") {
30
+ qos_profile = &rmw_qos_profile_sensor_data;
31
+ } else if (profile == "qos_profile_system_default") {
32
+ qos_profile = &rmw_qos_profile_system_default;
33
+ } else if (profile == "qos_profile_services_default") {
34
+ qos_profile = &rmw_qos_profile_services_default;
35
+ } else if (profile == "qos_profile_parameters") {
36
+ qos_profile = &rmw_qos_profile_parameters;
37
+ } else if (profile == "qos_profile_parameter_events") {
38
+ qos_profile = &rmw_qos_profile_parameter_events;
39
+ } else if (profile == "qos_profile_action_status_default") {
40
+ qos_profile = &rcl_action_qos_profile_status_default;
41
+ } else {
42
+ return &rmw_qos_profile_default;
43
+ }
44
+
45
+ return qos_profile;
46
+ }
47
+
48
+ std::unique_ptr<rmw_qos_profile_t> GetQosProfileFromObject(
49
+ Napi::Object object) {
50
+ std::unique_ptr<rmw_qos_profile_t> qos_profile =
51
+ std::make_unique<rmw_qos_profile_t>();
52
+
53
+ auto history = object.Get("history");
54
+ auto depth = object.Get("depth");
55
+ auto reliability = object.Get("reliability");
56
+ auto durability = object.Get("durability");
57
+ auto avoid_ros_namespace_conventions =
58
+ object.Get("avoidRosNameSpaceConventions");
59
+
60
+ qos_profile->history = static_cast<rmw_qos_history_policy_t>(
61
+ history.As<Napi::Number>().Uint32Value());
62
+ qos_profile->depth = depth.As<Napi::Number>().Uint32Value();
63
+ qos_profile->reliability = static_cast<rmw_qos_reliability_policy_t>(
64
+ reliability.As<Napi::Number>().Uint32Value());
65
+ qos_profile->durability = static_cast<rmw_qos_durability_policy_t>(
66
+ durability.As<Napi::Number>().Uint32Value());
67
+ qos_profile->avoid_ros_namespace_conventions =
68
+ avoid_ros_namespace_conventions.As<Napi::Boolean>();
69
+
70
+ return qos_profile;
71
+ }
72
+
73
+ Napi::Value ConvertRMWTimeToDuration(Napi::Env env,
74
+ const rmw_time_t* duration) {
75
+ Napi::Object obj = Napi::Object::New(env);
76
+ obj.Set("seconds", Napi::BigInt::New(env, duration->sec));
77
+ obj.Set("nanoseconds", Napi::Number::New(env, duration->nsec));
78
+ return obj;
79
+ }
80
+
81
+ #if ROS_VERSION > 2205 // 2205 == Humble
82
+ Napi::Value ConvertToHashObject(Napi::Env env,
83
+ const rosidl_type_hash_t* type_hash) {
84
+ Napi::Object obj = Napi::Object::New(env);
85
+ obj.Set("version", Napi::Number::New(env, type_hash->version));
86
+ obj.Set("value", Napi::Buffer<char>::Copy(
87
+ env, reinterpret_cast<const char*>(type_hash->value),
88
+ ROSIDL_TYPE_HASH_SIZE));
89
+ return obj;
90
+ }
91
+ #endif
92
+
93
+ Napi::Value ConvertToJSTopicEndpoint(
94
+ Napi::Env env, const rmw_topic_endpoint_info_t* topic_endpoint_info) {
95
+ Napi::Array endpoint_gid = Napi::Array::New(env, RMW_GID_STORAGE_SIZE);
96
+ for (size_t i = 0; i < RMW_GID_STORAGE_SIZE; i++) {
97
+ endpoint_gid.Set(
98
+ i, Napi::Number::New(env, topic_endpoint_info->endpoint_gid[i]));
99
+ }
100
+
101
+ Napi::Object endpoint = Napi::Object::New(env);
102
+ endpoint.Set("node_name",
103
+ Napi::String::New(env, topic_endpoint_info->node_name));
104
+ endpoint.Set("node_namespace",
105
+ Napi::String::New(env, topic_endpoint_info->node_namespace));
106
+ endpoint.Set("topic_type",
107
+ Napi::String::New(env, topic_endpoint_info->topic_type));
108
+ #if ROS_VERSION > 2205 // 2205 == Humble
109
+ endpoint.Set("topic_type_hash",
110
+ ConvertToHashObject(env, &topic_endpoint_info->topic_type_hash));
111
+ #endif
112
+ endpoint.Set("endpoint_type",
113
+ Napi::Number::New(
114
+ env, static_cast<int>(topic_endpoint_info->endpoint_type)));
115
+ endpoint.Set("endpoint_gid", endpoint_gid);
116
+ endpoint.Set("qos_profile",
117
+ rclnodejs::ConvertToQoS(env, &topic_endpoint_info->qos_profile));
118
+ return endpoint;
119
+ }
120
+
24
121
  uv_lib_t g_lib;
122
+ Napi::Env g_env = nullptr;
123
+
25
124
  } // namespace
26
125
 
27
126
  namespace rclnodejs {
@@ -95,4 +194,70 @@ std::string GetErrorMessageAndClear() {
95
194
  return std::string(uv_dlerror(&g_lib));
96
195
  }
97
196
 
197
+ Napi::Env& GetEnv() { return g_env; }
198
+
199
+ void StoreEnv(Napi::Env current_env) { g_env = current_env; }
200
+
201
+ std::unique_ptr<rmw_qos_profile_t> GetQoSProfile(Napi::Value qos) {
202
+ std::unique_ptr<rmw_qos_profile_t> qos_profile =
203
+ std::make_unique<rmw_qos_profile_t>();
204
+
205
+ if (qos.IsString()) {
206
+ *qos_profile = *GetQoSProfileFromString(qos.As<Napi::String>().Utf8Value());
207
+ } else if (qos.IsObject()) {
208
+ qos_profile = GetQosProfileFromObject(qos.As<Napi::Object>());
209
+ } else {
210
+ return qos_profile;
211
+ }
212
+ return qos_profile;
213
+ }
214
+
215
+ void ExtractNamesAndTypes(rcl_names_and_types_t names_and_types,
216
+ Napi::Array* result_list) {
217
+ Napi::Env env = result_list->Env();
218
+
219
+ for (size_t i = 0; i < names_and_types.names.size; ++i) {
220
+ Napi::Object item = Napi::Object::New(env);
221
+ std::string topic_name = names_and_types.names.data[i];
222
+ item.Set("name", Napi::String::New(env, names_and_types.names.data[i]));
223
+
224
+ Napi::Array type_list =
225
+ Napi::Array::New(env, names_and_types.types[i].size);
226
+ for (size_t j = 0; j < names_and_types.types[i].size; ++j) {
227
+ type_list.Set(j,
228
+ Napi::String::New(env, names_and_types.types[i].data[j]));
229
+ }
230
+ item.Set("types", type_list);
231
+ result_list->Set(i, item);
232
+ }
233
+ }
234
+
235
+ Napi::Value ConvertToQoS(Napi::Env env, const rmw_qos_profile_t* qos_profile) {
236
+ Napi::Object qos = Napi::Object::New(env);
237
+ qos.Set("depth", Napi::Number::New(env, qos_profile->depth));
238
+ qos.Set("history", Napi::Number::New(env, qos_profile->history));
239
+ qos.Set("reliability", Napi::Number::New(env, qos_profile->reliability));
240
+ qos.Set("durability", Napi::Number::New(env, qos_profile->durability));
241
+ qos.Set("lifespan", ConvertRMWTimeToDuration(env, &qos_profile->lifespan));
242
+ qos.Set("deadline", ConvertRMWTimeToDuration(env, &qos_profile->deadline));
243
+ qos.Set("liveliness", Napi::Number::New(env, qos_profile->liveliness));
244
+ qos.Set(
245
+ "liveliness_lease_duration",
246
+ ConvertRMWTimeToDuration(env, &qos_profile->liveliness_lease_duration));
247
+ qos.Set(
248
+ "avoid_ros_namespace_conventions",
249
+ Napi::Boolean::New(env, qos_profile->avoid_ros_namespace_conventions));
250
+ return qos;
251
+ }
252
+
253
+ Napi::Array ConvertToJSTopicEndpointInfoList(
254
+ Napi::Env env, const rmw_topic_endpoint_info_array_t* info_array) {
255
+ Napi::Array list = Napi::Array::New(env, info_array->size);
256
+ for (size_t i = 0; i < info_array->size; ++i) {
257
+ rmw_topic_endpoint_info_t topic_endpoint_info = info_array->info_array[i];
258
+ list.Set(i, ConvertToJSTopicEndpoint(env, &topic_endpoint_info));
259
+ }
260
+ return list;
261
+ }
262
+
98
263
  } // namespace rclnodejs