订阅者
订阅由DataReader 与Subscriber的关联定义。为了开始接收发布的更新,应用程序在订阅服务器中创建一个新的 DataReader。此 DataReader 将绑定到 描述将要接收的数据类型的主题。然后,DataReader 将开始从与该主题匹配的远程发布接收数据值更新。
当订阅者接收到数据时,它会通知应用程序有新数据可用。然后,应用程序可以使用 DataReader 来获取接收到的数据
类似于publish,具体操作:
subscribe
Subscriber代表属于它的一个或多个DataReader对象的行为。它作为一个容器,允许在订阅者的订阅者Qos 给定的公共配置下对不同的 DataReader 对象进行分组。
属于同一订阅者的 DataReader 对象在订阅者之外没有任何其他关系,并且在其他SubscriberQos情况下独立运行。具体来说,订阅者可以托管不同主题和数据类型的 DataReader 对象。
服务质量
SubscriberQos控制Subscriber的行为。它在内部包含以下QosPolicy对象
QosPolicy有关它们的用法和默认值的更多信息,请参阅每个类的详细说明。
可以使用 Subscriber::set_qos()成员函数修改先前创建的订阅者的 QoS 值
// Create a DomainParticipant in the desired domain
DomainParticipant* participant =
DomainParticipantFactory::get_instance()->create_participant(0, PARTICIPANT_QOS_DEFAULT);
if (nullptr == participant)
{
// Error
return;
}
// Create a Subscriber with default SubscriberQos
Subscriber* subscriber =
participant->create_subscriber(SUBSCRIBER_QOS_DEFAULT);
if (nullptr == subscriber)
{
// Error
return;
}
// Get the current QoS or create a new one from scratch
SubscriberQos qos = subscriber->get_qos();
// Modify QoS attributes
qos.entity_factory().autoenable_created_entities = false;
// Assign the new Qos to the object
subscriber->set_qos(qos);
默认订阅者Qos
默认的SubscriberQos是指DomainParticipant实例get_default_subscriber_qos()上的成员函数返回的值 。该特殊值可用作 QoS 参数 或 成员函数,以指示应使用当前默认的 SubscriberQos。SUBSCRIBER_QOS_DEFAULTcreate_subscriber()Subscriber::set_qos()
系统启动时,默认的 SubscriberQos 等价于默认的构造值SubscriberQos()。set_default_subscriber_qos()可以使用DomainParticipant 实例上的成员函数随时修改默认的 SubscriberQos 。修改默认的 SubscriberQos 不会影响已经存在的 Subscriber 实例。
// Create a DomainParticipant in the desired domain
DomainParticipant* participant =
DomainParticipantFactory::get_instance()->create_participant(0, PARTICIPANT_QOS_DEFAULT);
if (nullptr == participant)
{
// Error
return;
}
// Get the current QoS or create a new one from scratch
SubscriberQos qos_type1 = participant->get_default_subscriber_qos();
// Modify QoS attributes
// (...)
// Set as the new default SubscriberQos
if (participant->set_default_subscriber_qos(qos_type1) != ReturnCode_t::RETCODE_OK)
{
// Error
return;
}
// Create a Subscriber with the new default SubscriberQos.
Subscriber* subscriber_with_qos_type1 =
participant->create_subscriber(SUBSCRIBER_QOS_DEFAULT);
if (nullptr == subscriber_with_qos_type1)
{
// Error
return;
}
// Get the current QoS or create a new one from scratch
SubscriberQos qos_type2;
// Modify QoS attributes
// (...)
// Set as the new default SubscriberQos
if (participant->set_default_subscriber_qos(qos_type2) != ReturnCode_t::RETCODE_OK)
{
// Error
return;
}
// Create a Subscriber with the new default SubscriberQos.
Subscriber* subscriber_with_qos_type2 =
participant->create_subscriber(SUBSCRIBER_QOS_DEFAULT);
if (nullptr == subscriber_with_qos_type2)
{
// Error
return;
}
// Resetting the default SubscriberQos to the original default constructed values
if (participant->set_default_subscriber_qos(SUBSCRIBER_QOS_DEFAULT)
!= ReturnCode_t::RETCODE_OK)
{
// Error
return;
}
// The previous instruction is equivalent to the following
if (participant->set_default_subscriber_qos(SubscriberQos())
!= ReturnCode_t::RETCODE_OK)
{
// Error
return;
}
set_default_subscriber_qos()成员函数也接受特殊值SUBSCRIBER_QOS_DEFAULT作为输入参数。这会将当前默认的 SubscriberQos 重置为默认构造值SubscriberQos()。
// Create a DomainParticipant in the desired domain
DomainParticipant* participant =
DomainParticipantFactory::get_instance()->create_participant(0, PARTICIPANT_QOS_DEFAULT);
if (nullptr == participant)
{
// Error
return;
}
// Create a custom SubscriberQos
SubscriberQos custom_qos;
// Modify QoS attributes
// (...)
// Create a subscriber with a custom SubscriberQos
Subscriber* subscriber = participant->create_subscriber(custom_qos);
if (nullptr == subscriber)
{
// Error
return;
}
// Set the QoS on the subscriber to the default
if (subscriber->set_qos(SUBSCRIBER_QOS_DEFAULT) != ReturnCode_t::RETCODE_OK)
{
// Error
return;
}
// The previous instruction is equivalent to the following:
if (subscriber->set_qos(participant->get_default_subscriber_qos())
!= ReturnCode_t::RETCODE_OK)
{
// Error
return;
}
该值SUBSCRIBER_QOS_DEFAULT具有不同的含义,具体取决于它的使用位置:
create_subscriber()、Subscriber::set_qos()它指的是由 . 返回的默认 SubscriberQos get_default_subscriber_qos()。
set_default_subscriber_qos()它指的是默认构造 SubscriberQos()的.
订阅者监听器
SubscriberListener是一个抽象类,定义将响应 订阅者状态更改而触发的回调。默认情况下,所有这些回调都是空的并且什么都不做。用户应实现此类的特化,覆盖应用程序所需的回调。未被覆盖的回调将保持其空实现。
SubscriberListener 继承自DataReaderListener。因此,它能够对报告给 DataReader的所有事件做出反应。由于事件总是被通知给可以处理事件的最具体的实体侦听器,因此只有在触发的 DataReader 没有附加侦听器时,才会调用 SubscriberListener 从 DataReaderListener 继承的回调,或者如果回调被StatusMaskDataReader 上的 禁用。
此外,SubscriberListener 添加了以下回调:
on_data_on_readers(): 新数据在属于此订阅者的任何 DataReader 上可用。对此回调的调用没有排队,这意味着如果一次接收到多个新的数据更改,则可能只为所有这些调用发出一个回调调用,而不是每次更改一个。如果应用程序在此回调中检索接收到的数据,它必须继续 读取数据,直到没有留下新的更改。
class CustomSubscriberListener : public SubscriberListener
{
public:
CustomSubscriberListener()
: SubscriberListener()
{
}
virtual ~CustomSubscriberListener()
{
}
virtual void on_data_on_readers(
Subscriber* sub)
{
(void)sub;
std::cout << "New data available" << std::endl;
}
};
创建订阅者
订阅者始终属于DomainParticipant 。订阅者的创建是通过create_subscriber()DomainParticipant 实例上的成员函数完成的,该实例充当订阅者的工厂。
强制性论点是:
描述订阅者行为的订阅者Qos 。如果提供SUBSCRIBER_QOS_DEFAULT的值为 ,则使用Default SubscriberQos的值。
可选参数是:
派生自SubscriberListener的侦听器,实现将触发的回调,以响应订阅者上的事件和状态更改。默认情况下使用空回调。
StatusMask激活或停用在 SubscriberListener 上触发单个回调的A。默认情况下,所有事件都已启用。
create_subscriber()如果在操作过程中出现错误,将返回一个空指针,例如,如果提供的 QoS 不兼容或不受支持。建议检查返回值是否为有效指针。
// Create a DomainParticipant in the desired domain
DomainParticipant* participant =
DomainParticipantFactory::get_instance()->create_participant(0, PARTICIPANT_QOS_DEFAULT);
if (nullptr == participant)
{
// Error
return;
}
// Create a Subscriber with default SubscriberQos and no Listener
// The value SUBSCRIBER_QOS_DEFAULT is used to denote the default QoS.
Subscriber* subscriber_with_default_qos =
participant->create_subscriber(SUBSCRIBER_QOS_DEFAULT);
if (nullptr == subscriber_with_default_qos)
{
// Error
return;
}
// A custom SubscriberQos can be provided to the creation method
SubscriberQos custom_qos;
// Modify QoS attributes
// (...)
Subscriber* subscriber_with_custom_qos =
participant->create_subscriber(custom_qos);
if (nullptr == subscriber_with_custom_qos)
{
// Error
return;
}
// Create a Subscriber with default QoS and a custom Listener.
// CustomSubscriberListener inherits from SubscriberListener.
// The value SUBSCRIBER_QOS_DEFAULT is used to denote the default QoS.
CustomSubscriberListener custom_listener;
Subscriber* subscriber_with_default_qos_and_custom_listener =
participant->create_subscriber(SUBSCRIBER_QOS_DEFAULT, &custom_listener);
if (nullptr == subscriber_with_default_qos_and_custom_listener)
{
// Error
return;
}
基于配置文件的订阅者创建
除了使用 SubscriberQos,配置文件的名称可用于创建具有create_subscriber_with_profile() DomainParticipant 实例上的成员函数的订阅者。
强制性论点是:
具有标识订阅者的名称的字符串。
可选参数是:
从 SubscriberListener 派生的侦听器,实现将触发的回调,以响应订阅者上的事件和状态更改。默认情况下使用空回调。
StatusMask激活或停用在 SubscriberListener 上触发单个回调的A。默认情况下,所有事件都已启用。
create_subscriber_with_profile()如果在操作过程中出现错误,将返回一个空指针,例如,如果提供的 QoS 不兼容或不受支持。建议检查返回值是否为有效指针。
XML 配置文件必须先前已加载。请参阅从 XML 文件加载配置文件。
// First load the XML with the profiles
DomainParticipantFactory::get_instance()->load_XML_profiles_file("profiles.xml");
// Create a DomainParticipant in the desired domain
DomainParticipant* participant =
DomainParticipantFactory::get_instance()->create_participant(0, PARTICIPANT_QOS_DEFAULT);
if (nullptr == participant)
{
// Error
return;
}
// Create a Subscriber using a profile and no Listener
Subscriber* subscriber_with_profile =
participant->create_subscriber_with_profile("subscriber_profile");
if (nullptr == subscriber_with_profile)
{
// Error
return;
}
// Create a Subscriber using a profile and a custom Listener.
// CustomSubscriberListener inherits from SubscriberListener.
CustomSubscriberListener custom_listener;
Subscriber* subscriber_with_profile_and_custom_listener =
participant->create_subscriber_with_profile("subscriber_profile", &custom_listener);
if (nullptr == subscriber_with_profile_and_custom_listener)
{
// Error
return;
}
删除订阅者
可以使用delete_subscriber()创建订阅者的 DomainParticipant 实例上的成员函数删除订阅者。
只有属于订阅者的所有实体 (DataReaders) 都已被删除,才能删除订阅者。否则,该函数将发出错误并且订阅者不会被删除。这可以通过使用Subscriberdelete_contained_entities()的成员函数 来执行。
// Create a DomainParticipant in the desired domain
DomainParticipant* participant =
DomainParticipantFactory::get_instance()->create_participant(0, PARTICIPANT_QOS_DEFAULT);
if (nullptr == participant)
{
// Error
return;
}
// Create a Subscriber
Subscriber* subscriber =
participant->create_subscriber(SUBSCRIBER_QOS_DEFAULT);
if (nullptr == subscriber)
{
// Error
return;
}
// Use the Subscriber to communicate
// (...)
// Delete the entities the subscriber created
if (subscriber->delete_contained_entities() != ReturnCode_t::RETCODE_OK)
{
// Subscriber failed to delete the entities it created
return;
}
// Delete the Subscriber
if (participant->delete_subscriber(subscriber) != ReturnCode_t::RETCODE_OK)
{
// Error
return;
}
数据读取器
ADataReader恰好连接到一个 充当它的工厂的订阅者。此外,每个 DataReader自创建以来都绑定到一个 主题。该主题必须在创建 DataReader 之前存在,并且必须绑定到 DataReader 要发布的数据类型。
在订阅者中为特定主题创建新的 DataReader 的效果是使用主题描述的名称和数据类型启动新订阅。
创建 DataReader 后,将在从远程发布接收到数据值的更改时通知应用程序。然后可以使用 DataReader 的DataReader::read_next_sample()或DataReader::take_next_sample() 成员函数检索这些更改
// Create a DataReader with default DataReaderQos
DataReader* data_reader =
subscriber->create_datareader(topic, DATAREADER_QOS_DEFAULT);
if (nullptr == data_reader)
{
// Error
return;
}
// Get the current QoS or create a new one from scratch
DataReaderQos qos = data_reader->get_qos();
// Modify QoS attributes
// (...)
// Assign the new Qos to the object
data_reader->set_qos(qos);
默认 DataReaderQos
默认的 DataReaderQos 是指订阅者实例get_default_datareader_qos()上的成员函数 返回的值 。该特殊值可用作 QoS 参数 或 成员函数,以指示应使用当前默认 DataReaderQos。DATAREADER_QOS_DEFAULTcreate_datareader()DataReader::set_qos()
系统启动时,默认的 DataReaderQos 等价于默认的构造值DataReaderQos()。可以随时使用 set_default_datareader_qos()订阅服务器实例上的成员函数修改默认 DataReaderQos。修改默认 DataReaderQos 不会影响已经存在的 DataReader实例。
// Get the current QoS or create a new one from scratch
DataReaderQos qos_type1 = subscriber->get_default_datareader_qos();
// Modify QoS attributes
// (...)
// Set as the new default DataReaderQos
if (subscriber->set_default_datareader_qos(qos_type1) != ReturnCode_t::RETCODE_OK)
{
// Error
return;
}
// Create a DataReader with the new default DataReaderQos.
DataReader* data_reader_with_qos_type1 =
subscriber->create_datareader(topic, DATAREADER_QOS_DEFAULT);
if (nullptr == data_reader_with_qos_type1)
{
// Error
return;
}
// Get the current QoS or create a new one from scratch
DataReaderQos qos_type2;
// Modify QoS attributes
// (...)
// Set as the new default DataReaderQos
if (subscriber->set_default_datareader_qos(qos_type2) != ReturnCode_t::RETCODE_OK)
{
// Error
return;
}
// Create a DataReader with the new default DataReaderQos.
DataReader* data_reader_with_qos_type2 =
subscriber->create_datareader(topic, DATAREADER_QOS_DEFAULT);
if (nullptr == data_reader_with_qos_type2)
{
// Error
return;
}
// Resetting the default DataReaderQos to the original default constructed values
if (subscriber->set_default_datareader_qos(DATAREADER_QOS_DEFAULT)
!= ReturnCode_t::RETCODE_OK)
{
// Error
return;
}
// The previous instruction is equivalent to the following
if (subscriber->set_default_datareader_qos(DataReaderQos())
!= ReturnCode_t::RETCODE_OK)
{
// Error
return;
}
set_default_datareader_qos()成员函数也接受特殊值DATAREADER_QOS_DEFAULT作为输入参数。这会将当前默认 DataReaderQos 重置为默认构造值DataReaderQos()。
// Create a custom DataReaderQos
DataReaderQos custom_qos;
// Modify QoS attributes
// (...)
// Create a DataWriter with a custom DataReaderQos
DataReader* data_reader = subscriber->create_datareader(topic, custom_qos);
if (nullptr == data_reader)
{
// Error
return;
}
// Set the QoS on the DataWriter to the default
if (data_reader->set_qos(DATAREADER_QOS_DEFAULT) != ReturnCode_t::RETCODE_OK)
{
// Error
return;
}
// The previous instruction is equivalent to the following:
if (data_reader->set_qos(subscriber->get_default_datareader_qos())
!= ReturnCode_t::RETCODE_OK)
{
// Error
return;
}
该值DATAREADER_QOS_DEFAULT具有不同的含义,具体取决于它的使用位置:
create_datareader() 、DataReader::set_qos()它指的是由返回的默认 DataReaderQos get_default_datareader_qos()。
set_default_datareader_qos()它指的是默认构造DataReaderQos()的
数据读取器监听器
DataReaderListener是一个抽象类,定义将响应DataReader上的状态更改而触发的回调。默认情况下,所有这些回调都是空的并且什么都不做。用户应实现此类的特化,覆盖应用程序所需的回调。未被覆盖的回调将保持其空实现。
DataReaderListener 定义了以下回调:
on_data_available():DataReader 上有可供应用程序使用的新数据。对此回调的调用没有排队,这意味着如果一次接收到多个新的数据更改,则可能只为所有这些调用发出一个回调调用,而不是每次更改一个。如果应用程序在此回调中检索接收到的数据,它必须继续 读取数据,直到没有留下新的更改。
on_subscription_matched(): DataReader 找到了 与Topic匹配且具有公共分区和兼容 QoS 的DataWriter,或者已停止与之前认为匹配的 DataWriter 匹配。当匹配的 DataWriter 更改其 DataWriterQos时也会触发它。
on_requested_deadline_missed(): DataReader 未在其DataReaderQos上配置的截止期限内接收数据。它将为 DataReader 丢失数据的每个截止期限和数据实例调用。
目前 on_requested_deadline_missed() 没有实现(永远不会被调用),将在 Fast DDS 的未来版本中实现。
on_requested_incompatible_qos(): DataReader 找到了一个与 Topic 匹配并具有公共分区的 DataWriter,但其 QoS 与 DataReader 上定义的 QoS 不兼容。
on_liveliness_changed():匹配的DataWriter的活跃度状态发生了变化。不活动的 DataWriter已变为活动状态或相反。
on_sample_rejected():接收到的数据样本被拒绝。有关详细信息,请参阅SampleRejectedStatus。
on_sample_lost():数据样本丢失,永远不会被接收。有关详细信息,请参阅SampleLostStatus。
class CustomDataReaderListener : public DataReaderListener
{
public:
CustomDataReaderListener()
: DataReaderListener()
{
}
virtual ~CustomDataReaderListener()
{
}
virtual void on_data_available(
DataReader* reader)
{
(void)reader;
std::cout << "Received new data message" << std::endl;
}
virtual void on_subscription_matched(
DataReader* reader,
const SubscriptionMatchedStatus& info)
{
(void)reader;
if (info.current_count_change == 1)
{
std::cout << "Matched a remote DataWriter" << std::endl;
}
else if (info.current_count_change == -1)
{
std::cout << "Unmatched a remote DataWriter" << std::endl;
}
}
virtual void on_requested_deadline_missed(
DataReader* reader,
const eprosima::fastrtps::RequestedDeadlineMissedStatus& info)
{
(void)reader, (void)info;
std::cout << "Some data was not received on time" << std::endl;
}
virtual void on_liveliness_changed(
DataReader* reader,
const eprosima::fastrtps::LivelinessChangedStatus& info)
{
(void)reader;
if (info.alive_count_change == 1)
{
std::cout << "A matched DataWriter has become active" << std::endl;
}
else if (info.not_alive_count_change == 1)
{
std::cout << "A matched DataWriter has become inactive" << std::endl;
}
}
virtual void on_sample_rejected(
DataReader* reader,
const eprosima::fastrtps::SampleRejectedStatus& info)
{
(void)reader, (void)info;
std::cout << "A received data sample was rejected" << std::endl;
}
virtual void on_requested_incompatible_qos(
DataReader* /*reader*/,
const RequestedIncompatibleQosStatus& info)
{
std::cout << "Found a remote Topic with incompatible QoS (QoS ID: " << info.last_policy_id <<
")" << std::endl;
}
virtual void on_sample_lost(
DataReader* reader,
const SampleLostStatus& info)
{
(void)reader, (void)info;
std::cout << "A data sample was lost and will not be received" << std::endl;
}
};