Skip to main content

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.