Skip to content

Commit 21453ac

Browse files
authored
Add getContentFilter for subscription (#1334)
This PR adds a `getContentFilter()` method to subscriptions, enabling retrieval of the current content filter configuration. The implementation mirrors the existing content filter API with getter functionality alongside the existing setter and clear operations. Key changes: - Added `getContentFilter()` method to retrieve current content filter expression and parameters - Removed version guards (`#if ROS_VERSION >= 2205`) from content filtering code, assuming universal Humble+ support - Added corresponding TypeScript type definitions and test coverage Fix: #1330
1 parent dab6bf7 commit 21453ac

File tree

5 files changed

+92
-14
lines changed

5 files changed

+92
-14
lines changed

lib/subscription.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,14 @@ class Subscription extends Entity {
151151
: this.clearContentFilter();
152152
}
153153

154+
/**
155+
* Get the current content-filter.
156+
* @returns {object} - The content-filter description {expression: string, parameters: string[]} or undefined if not set/supported.
157+
*/
158+
getContentFilter() {
159+
return rclnodejs.getContentFilter(this.handle);
160+
}
161+
154162
/**
155163
* Clear the current content-filter. No filtering is to be applied.
156164
* @returns {boolean} - True if successful; false otherwise

src/rcl_subscription_bindings.cpp

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ Napi::Value CreateSubscription(const Napi::CallbackInfo& info) {
7676
subscription_ops.qos = *qos_profile;
7777
}
7878

79-
#if ROS_VERSION >= 2205 // 2205 => Humble+
8079
if (options.Has("contentFilter")) {
8180
// configure content-filter
8281
Napi::Value contentFilterVal = options.Get("contentFilter");
@@ -123,7 +122,6 @@ Napi::Value CreateSubscription(const Napi::CallbackInfo& info) {
123122
}
124123
}
125124
}
126-
#endif
127125

128126
const rosidl_message_type_support_t* ts =
129127
GetMessageTypeSupport(package_name, message_sub_folder, message_name);
@@ -201,9 +199,6 @@ Napi::Value GetSubscriptionTopic(const Napi::CallbackInfo& info) {
201199
}
202200

203201
Napi::Value HasContentFilter(const Napi::CallbackInfo& info) {
204-
#if ROS_VERSION < 2205 // 2205 => Humble+
205-
return Napi::Boolean::New(info.Env(), false);
206-
#else
207202
Napi::Env env = info.Env();
208203

209204
RclHandle* subscription_handle =
@@ -213,13 +208,9 @@ Napi::Value HasContentFilter(const Napi::CallbackInfo& info) {
213208

214209
bool is_valid = rcl_subscription_is_cft_enabled(subscription);
215210
return Napi::Boolean::New(env, is_valid);
216-
#endif
217211
}
218212

219213
Napi::Value SetContentFilter(const Napi::CallbackInfo& info) {
220-
#if ROS_VERSION < 2205 // 2205 => Humble+
221-
return Napi::Boolean::New(info.Env(), false);
222-
#else
223214
Napi::Env env = info.Env();
224215

225216
RclHandle* subscription_handle =
@@ -272,13 +263,9 @@ Napi::Value SetContentFilter(const Napi::CallbackInfo& info) {
272263
}
273264

274265
return Napi::Boolean::New(env, true);
275-
#endif
276266
}
277267

278268
Napi::Value ClearContentFilter(const Napi::CallbackInfo& info) {
279-
#if ROS_VERSION < 2205 // 2205 => Humble+
280-
return Napi::Boolean::New(info.Env(), false);
281-
#else
282269
Napi::Env env = info.Env();
283270

284271
RclHandle* subscription_handle =
@@ -301,7 +288,56 @@ Napi::Value ClearContentFilter(const Napi::CallbackInfo& info) {
301288
rcl_get_error_string().str);
302289

303290
return Napi::Boolean::New(env, true);
304-
#endif
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;
305341
}
306342

307343
Napi::Value GetPublisherCount(const Napi::CallbackInfo& info) {
@@ -327,6 +363,7 @@ Napi::Object InitSubscriptionBindings(Napi::Env env, Napi::Object exports) {
327363
Napi::Function::New(env, GetSubscriptionTopic));
328364
exports.Set("hasContentFilter", Napi::Function::New(env, HasContentFilter));
329365
exports.Set("setContentFilter", Napi::Function::New(env, SetContentFilter));
366+
exports.Set("getContentFilter", Napi::Function::New(env, GetContentFilter));
330367
exports.Set("clearContentFilter",
331368
Napi::Function::New(env, ClearContentFilter));
332369
exports.Set("getPublisherCount", Napi::Function::New(env, GetPublisherCount));

test/test-subscription-content-filter.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,30 @@ describe('subscription content-filtering', function () {
403403
done();
404404
});
405405

406+
it('getContentFilter', function (done) {
407+
const typeclass = 'std_msgs/msg/Int32';
408+
let options = Node.getDefaultOptions();
409+
options.contentFilter = {
410+
expression: 'data = %0',
411+
parameters: [5],
412+
};
413+
414+
const subscription = this.subscriberNode.createSubscription(
415+
typeclass,
416+
TOPIC,
417+
options,
418+
(msg) => {}
419+
);
420+
421+
assert.ok(subscription.hasContentFilter());
422+
const filter = subscription.getContentFilter();
423+
assert.strictEqual(filter.expression, 'data = %0');
424+
assert.strictEqual(filter.parameters.length, 1);
425+
assert.strictEqual(filter.parameters[0], '5');
426+
427+
done();
428+
});
429+
406430
it('multiple clearContentFilter', function (done) {
407431
const typeclass = 'std_msgs/msg/Int32';
408432
let options = Node.getDefaultOptions();

test/types/index.test-d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,9 @@ expectType<rclnodejs.SubscriptionWithRawMessageCallback>(rawMessageCallback);
221221
expectType<string>(subscription.topic);
222222
expectType<boolean>(subscription.isDestroyed());
223223
expectType<boolean>(subscription.setContentFilter(contentFilter));
224+
expectType<rclnodejs.SubscriptionContentFilter | undefined>(
225+
subscription.getContentFilter()
226+
);
224227
expectType<boolean>(subscription.clearContentFilter());
225228
expectType<boolean>(subscription.hasContentFilter());
226229
expectType<string>(subscription.loggerName);

types/subscription.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ declare module 'rclnodejs' {
6161
*/
6262
setContentFilter(filter: SubscriptionContentFilter): boolean;
6363

64+
/**
65+
* Get the current content-filter.
66+
* @returns The content-filter description {expression: string, parameters: string[]} or undefined if not set/supported.
67+
*/
68+
getContentFilter(): SubscriptionContentFilter | undefined;
69+
6470
/**
6571
* Clear the current content-filter. No filtering is to be applied.
6672
* @returns True if successful; false otherwise

0 commit comments

Comments
 (0)