The message subscriber is the most common observer in the Asset Tracker Template. A message subscriber receives messages asynchronously. It is used by any module that has its own thread.
A message subscriber queues up messages that are received while the module is busy processing another message. The module then processes the messages in the order they were received. An incoming message can never interrupt the processing of another message.
A message subscriber is defined using ZBUS_MSG_SUBSCRIBER_DEFINE, and the subscriber is added to a channel using ZBUS_CHAN_ADD_OBS. The Network module defines its message subscriber as follows:
ZBUS_MSG_SUBSCRIBER_DEFINE(network);
ZBUS_CHAN_ADD_OBS(network_chan, network, 0);
The messages are received in the module's thread loop by calling zbus_sub_wait_msg():
err = zbus_sub_wait_msg(&network, &network_state.chan,
network_state.msg_buf, zbus_wait_ms);
In every module with a state machine, the channel and the message contents are stored in the module's state object. The state handler then processes the message.
In modules that subscribe to multiple channels, a channel list macro is used to simplify subscribing to all the channels. The same macro is used to determine the size of a message buffer to handle the largest possible message. The following example comes from app/src/main.c:
#define CHANNEL_LIST(X) \
X(CLOUD_CHAN, struct cloud_msg) \
X(BUTTON_CHAN, struct button_msg) \
/* ... more channels ... */
#define ADD_OBSERVERS(_chan, _type) ZBUS_CHAN_ADD_OBS(_chan, main_subscriber, 0);
CHANNEL_LIST(ADD_OBSERVERS)