// Copyright (c) 2025, The Robot Web Tools Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
'use strict';
const rclnodejs = require('bindings')('rclnodejs');
const DistroUtils = require('./distro.js');
const Entity = require('./entity.js');
/**
* Enumeration for PublisherEventCallbacks event types.
* @enum {number}
*/
const PublisherEventType = {
/** @member {number} */
PUBLISHER_OFFERED_DEADLINE_MISSED: 0,
/** @member {number} */
PUBLISHER_LIVELINESS_LOST: 1,
/** @member {number} */
PUBLISHER_OFFERED_INCOMPATIBLE_QOS: 2,
/** @member {number} */
PUBLISHER_INCOMPATIBLE_TYPE: 3,
/** @member {number} */
PUBLISHER_MATCHED: 4,
};
/**
* Enumeration for SubscriptionEventCallbacks event types.
* @enum {number}
*/
const SubscriptionEventType = {
/** @member {number} */
SUBSCRIPTION_REQUESTED_DEADLINE_MISSED: 0,
/** @member {number} */
SUBSCRIPTION_LIVELINESS_CHANGED: 1,
/** @member {number} */
SUBSCRIPTION_REQUESTED_INCOMPATIBLE_QOS: 2,
/** @member {number} */
SUBSCRIPTION_MESSAGE_LOST: 3,
/** @member {number} */
SUBSCRIPTION_INCOMPATIBLE_TYPE: 4,
/** @member {number} */
SUBSCRIPTION_MATCHED: 5,
};
class EventHandler extends Entity {
constructor(handle, callback, eventType, eventTypeName) {
super(handle, null, null);
this._callback = callback;
this._eventType = eventType;
this._eventTypeName = eventTypeName;
}
takeData() {
const data = rclnodejs.takeEvent(this._handle, {
[this._eventTypeName]: this._eventType,
});
if (this._callback) {
this._callback(data);
}
}
}
/**
* @class - Class representing a ROS 2 PublisherEventCallbacks
* @hideconstructor
*/
class PublisherEventCallbacks {
constructor() {
if (DistroUtils.getDistroId() < DistroUtils.getDistroId('jazzy')) {
throw new Error(
'PublisherEventCallbacks is only available in ROS 2 Jazzy and later.'
);
}
this._deadline = null;
this._incompatible_qos = null;
this._liveliness = null;
this._incompatible_type = null;
this._matched = null;
this._eventHandlers = [];
}
/**
* Set deadline missed callback.
* @param {function} callback - The callback function to be called.
*/
set deadline(callback) {
this._deadline = callback;
}
/**
* Get deadline missed callback.
* @return {function} - The callback function.
*/
get deadline() {
return this._deadline;
}
/**
* Set incompatible QoS callback.
* @param {function} callback - The callback function to be called.
*/
set incompatibleQos(callback) {
this._incompatible_qos = callback;
}
/**
* Get incompatible QoS callback.
* @return {function} - The callback function.
*/
get incompatibleQos() {
return this._incompatible_qos;
}
/**
* Set liveliness lost callback.
* @param {function} callback - The callback function to be called.
*/
set liveliness(callback) {
this._liveliness = callback;
}
/**
* Get liveliness lost callback.
* @return {function} - The callback function.
*/
get liveliness() {
return this._liveliness;
}
/**
* Set incompatible type callback.
* @param {function} callback - The callback function to be called.
*/
set incompatibleType(callback) {
this._incompatible_type = callback;
}
/**
* Get incompatible type callback.
* @return {function} - The callback function.
*/
get incompatibleType() {
return this._incompatible_type;
}
/**
* Set matched callback.
* @param {function} callback - The callback function to be called.
*/
set matched(callback) {
this._matched = callback;
}
/**
* Get matched callback.
* @return {function} - The callback function.
*/
get matched() {
return this._matched;
}
createEventHandlers(publisherHandle) {
if (this._deadline) {
const deadlineHandle = rclnodejs.createPublisherEventHandle(
publisherHandle,
PublisherEventType.PUBLISHER_OFFERED_DEADLINE_MISSED
);
this._eventHandlers.push(
new EventHandler(
deadlineHandle,
this._deadline,
PublisherEventType.PUBLISHER_OFFERED_DEADLINE_MISSED,
'publisher_event_type'
)
);
}
if (this._incompatible_qos) {
const incompatibleQosHandle = rclnodejs.createPublisherEventHandle(
publisherHandle,
PublisherEventType.PUBLISHER_OFFERED_INCOMPATIBLE_QOS
);
this._eventHandlers.push(
new EventHandler(
incompatibleQosHandle,
this._incompatible_qos,
PublisherEventType.PUBLISHER_OFFERED_INCOMPATIBLE_QOS,
'publisher_event_type'
)
);
}
if (this._liveliness) {
const livelinessHandle = rclnodejs.createPublisherEventHandle(
publisherHandle,
PublisherEventType.PUBLISHER_LIVELINESS_LOST
);
this._eventHandlers.push(
new EventHandler(
livelinessHandle,
this._liveliness,
PublisherEventType.PUBLISHER_LIVELINESS_LOST,
'publisher_event_type'
)
);
}
if (this._incompatible_type) {
const incompatibleTypeHandle = rclnodejs.createPublisherEventHandle(
publisherHandle,
PublisherEventType.PUBLISHER_INCOMPATIBLE_TYPE
);
this._eventHandlers.push(
new EventHandler(
incompatibleTypeHandle,
this._incompatible_type,
PublisherEventType.PUBLISHER_INCOMPATIBLE_TYPE,
'publisher_event_type'
)
);
}
if (this._matched) {
const matchedHandle = rclnodejs.createPublisherEventHandle(
publisherHandle,
PublisherEventType.PUBLISHER_MATCHED
);
this._eventHandlers.push(
new EventHandler(
matchedHandle,
this._matched,
PublisherEventType.PUBLISHER_MATCHED,
'publisher_event_type'
)
);
}
return this._eventHandlers;
}
get eventHandlers() {
return this._eventHandlers;
}
}
/**
* @class - Class representing a ROS 2 SubscriptionEventCallbacks
* @hideconstructor
*/
class SubscriptionEventCallbacks {
constructor() {
if (DistroUtils.getDistroId() < DistroUtils.getDistroId('jazzy')) {
throw new Error(
'SubscriptionEventCallbacks is only available in ROS 2 Jazzy and later.'
);
}
this._deadline = null;
this._incompatible_qos = null;
this._liveliness = null;
this._message_lost = null;
this._incompatible_type = null;
this._matched = null;
this._eventHandlers = [];
}
/**
* Set the callback for deadline missed event.
* @param {function} callback - The callback function to be called.
*/
set deadline(callback) {
this._deadline = callback;
}
/**
* Get the callback for deadline missed event.
* @return {function} - The callback function.
*/
get deadline() {
return this._deadline;
}
/**
* Set the callback for incompatible QoS event.
* @param {function} callback - The callback function to be called.
*/
set incompatibleQos(callback) {
this._incompatible_qos = callback;
}
/**
* Get the callback for incompatible QoS event.
* @return {function} - The callback function.
*/
get incompatibleQos() {
return this._incompatible_qos;
}
/**
* Set the callback for liveliness changed event.
* @param {function} callback - The callback function to be called.
*/
set liveliness(callback) {
this._liveliness = callback;
}
/**
* Get the callback for liveliness changed event.
* @return {function} - The callback function.
*/
get liveliness() {
return this._liveliness;
}
/**
* Set the callback for message lost event.
* @param {function} callback - The callback function to be called.
*/
set messageLost(callback) {
this._message_lost = callback;
}
/**
* Get the callback for message lost event.
* @return {function} - The callback function.
*/
get messageLost() {
return this._message_lost;
}
/**
* Set the callback for incompatible type event.
* @param {function} callback - The callback function to be called.
*/
set incompatibleType(callback) {
this._incompatible_type = callback;
}
/**
* Get the callback for incompatible type event.
* @return {function} - The callback function.
*/
get incompatibleType() {
return this._incompatible_type;
}
/**
* Set the callback for matched event.
* @param {function} callback - The callback function to be called.
*/
set matched(callback) {
this._matched = callback;
}
/**
* Get the callback for matched event.
* @return {function} - The callback function.
*/
get matched() {
return this._matched;
}
createEventHandlers(subscriptionHandle) {
if (this._deadline) {
const deadlineHandle = rclnodejs.createSubscriptionEventHandle(
subscriptionHandle,
SubscriptionEventType.SUBSCRIPTION_REQUESTED_DEADLINE_MISSED
);
this._eventHandlers.push(
new EventHandler(
deadlineHandle,
this._deadline,
SubscriptionEventType.SUBSCRIPTION_REQUESTED_DEADLINE_MISSED,
'subscription_event_type'
)
);
}
if (this._incompatible_qos) {
const incompatibleQosHandle = rclnodejs.createSubscriptionEventHandle(
subscriptionHandle,
SubscriptionEventType.SUBSCRIPTION_REQUESTED_INCOMPATIBLE_QOS
);
this._eventHandlers.push(
new EventHandler(
incompatibleQosHandle,
this._incompatible_qos,
SubscriptionEventType.SUBSCRIPTION_REQUESTED_INCOMPATIBLE_QOS,
'subscription_event_type'
)
);
}
if (this._liveliness) {
const livelinessHandle = rclnodejs.createSubscriptionEventHandle(
subscriptionHandle,
SubscriptionEventType.SUBSCRIPTION_LIVELINESS_CHANGED
);
this._eventHandlers.push(
new EventHandler(
livelinessHandle,
this._liveliness,
SubscriptionEventType.SUBSCRIPTION_LIVELINESS_CHANGED,
'subscription_event_type'
)
);
}
if (this._message_lost) {
const messageLostHandle = rclnodejs.createSubscriptionEventHandle(
subscriptionHandle,
SubscriptionEventType.SUBSCRIPTION_MESSAGE_LOST
);
this._eventHandlers.push(
new EventHandler(
messageLostHandle,
this._message_lost,
SubscriptionEventType.SUBSCRIPTION_MESSAGE_LOST,
'subscription_event_type'
)
);
}
if (this._incompatible_type) {
const incompatibleTypeHandle = rclnodejs.createSubscriptionEventHandle(
subscriptionHandle,
SubscriptionEventType.SUBSCRIPTION_INCOMPATIBLE_TYPE
);
this._eventHandlers.push(
new EventHandler(
incompatibleTypeHandle,
this._incompatible_type,
SubscriptionEventType.SUBSCRIPTION_INCOMPATIBLE_TYPE,
'subscription_event_type'
)
);
}
if (this._matched) {
const matchedHandle = rclnodejs.createSubscriptionEventHandle(
subscriptionHandle,
SubscriptionEventType.SUBSCRIPTION_MATCHED
);
this._eventHandlers.push(
new EventHandler(
matchedHandle,
this._matched,
SubscriptionEventType.SUBSCRIPTION_MATCHED,
'subscription_event_type'
)
);
}
return this._eventHandlers;
}
}
module.exports = {
PublisherEventCallbacks,
PublisherEventType,
SubscriptionEventCallbacks,
SubscriptionEventType,
};