Publishing / Subscribing
At its core, Basis is a (pub/sub framework)[https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern]. Units and various tooling can send and receive messages on named topics. Each message has a type, and generally topics should only contain messages of one type.
Publishing a Message on a Topic
When using the code generator (the preferred method), publishing a message involves creating an instance of the generated Output
struct and setting its fields accordingly. In the example below, we describe the publishing Unit using YAML and demonstrate how a message is published at a regular interval.
The following YAML configuration defines a Unit that publishes a message on the /chatter
topic at a rate of 1 Hz, using the Protocol Buffers StringMessage
type. The qos
field ensures that only one message is queued at a time.
threading_model:
single
cpp_includes:
- simple_pub_sub.pb.h
handlers:
PublishAt1Hz:
sync:
type: all
rate: 1
outputs:
/chatter:
type: protobuf:StringMessage
qos:
depth: 1
In the user code, publishing looks like this:
PublishAt1Hz::Output
simple_pub::PublishAt1Hz(const PublishAt1Hz::Input &input) {
PublishAt1Hz::Output output;
std::shared_ptr<StringMessage> msg{std::make_shared<StringMessage>()};
msg->set_message(std::string("Hello, world!"));
output.chatter = msg;
return output;
}
Here, the PublishAt1Hz::Output
struct is generated by the code generator. The developer creates a new StringMessage
, sets its content (in this case, "Hello, world!"), and assigns it to the output.chatter
field. The message is then ready to be published on the /chatter
topic.
Subscribing to a Topic
Subscribing to a topic using the code generator involves reading the fields of the Input
struct, which is automatically generated based on the Unit's YAML configuration. The user-defined callback function processes the incoming message by accessing these fields.
The following YAML configuration defines a Unit that subscribes to the /chatter
topic, which uses the Protocol Buffers StringMessage
type. The qos
field specifies a depth of 1, ensuring only the most recent message is kept in the queue.
threading_model:
single
cpp_includes:
- simple_pub_sub.pb.h
handlers:
OnChatter:
sync:
type: all
inputs:
/chatter:
type: protobuf:StringMessage
qos:
depth: 1
In the user code, the subscriber looks like this:
OnChatter::Output simple_sub::OnChatter(const OnChatter::Input &input) {
BASIS_LOG_INFO("OnChatter: {}", input.chatter->message());
return OnChatter::Output();
}
In this example, the code generator creates the OnChatter::Input
struct, which contains a field named chatter
. The callback function OnChatter
accesses the chatter
message and logs its content using the BASIS_LOG_INFO
function. The function returns a default (empty) instance of OnChatter::Output
, as the Unit has no outputs defined.