Subscribing to Advertisements and Notifications

Message Queuing Telemetry Transport (MQTT)

Message Queuing Telemetry Transport (MQTT) is a lightweight, publish-subscribe network protocol that transports messages between devices. The IoT Orchestrator application hosts the MQTT publisher as well as MQTT broker, sending processed BLE data (advertisements, GATT notifications, etc.) to specific topics on an MQTT broker. Any application or client that wants to receive this data becomes an MQTT subscriber by subscribing to those topics.

Command-Line Clients

Mosquitto Clients

The Mosquitto project provides command-line utilities (such as mosquitto_sub for subscribing). These are excellent for quick testing and debugging.

  • mosquitto_sub: For subscribing to MQTT topics and viewing messages.
    • Perfect for verifying broker connectivity, checking if data is being subscribed correctly, and performing basic message reception inspection.
    • Typically included when you install the Mosquitto broker, or can be installed separately:
      • Debian/Ubuntu:
        sudo apt-get install mosquitto-clients

Graphical User Interface (GUI) Clients

GUI clients offer a more user-friendly experience with visual topic hierarchies, message filtering, and easier management of subscriptions. They are ideal for ongoing monitoring and detailed debugging.

  • MQTT Explorer:
    A highly popular, cross-platform desktop client renowned for its intuitive interface and powerful features, including the ability to visualize topic structures and filter messages.

Programming Language Libraries (for Building Applications)

  • Python:

    • Library: paho-mqtt
    • Where to find:
      pip install paho-mqtt
  • JavaScript (Node.js/Browser):

    • Library: mqtt (npm package)
    • Where to find:
      npm install mqtt
  • Java:

    • Libraries: Eclipse Paho MQTT Client or HiveMQ MQTT Client
    • Where to find:
      Maven Central, Gradle
  • Go:

    • Library: paho.mqtt.golang
    • Where to find:
      go get github.com/eclipse/paho.mqtt.golang

MQTT Clients Example

Some commonly used MQTT clients include:

Note: These clients are used in our testing and are also observed among our partners.

MQTT Subscription Messages

Once the notification is enabled using the subscribe API, the data receiver application starts to receive the GATT notification.

To receive the notification, you will need to execute the following command in your terminal session:

  • To subscribe to all the topics, run the `mosquitto_sub -h -p 41883 -u 'data_app_name’ --pw 'data_app_key’ -t '#' -v' command.
  • To read data from a specific location, run the `mosquitto_sub -h localhost -p 41883 -t '$share/group/enterprise/hospital/pulse_oximeter' -u dataApplication --pw d5a4c7b1afd862a070514528006f22d4964f6c61ec0e2e0b6c3ebd03c2fbb507' command.

Note: The NIPC API for registering the topic, registering the data application, and subscribing to the topic remains unchanged from the Pre-GA version of the IoT Orchestrator. No changes are required for the partner application. The expected MQTT subscriber throughput, based on the 9800 platform on which the IoT Orchestrator application is deployed, is presented in the following table:

Table: Platforms and MQTT Subscribers (Recommended)

Platforms MQTT Subscribers (Recommended)
Cisco Catalyst 9800-L Wireless Controller 2
Cisco Catalyst 9800-40 Wireless Controller 5
Cisco Catalyst 9800-80 Wireless Controller 8
Cisco Catalyst CW9800M Wireless Controller 5
Cisco Catalyst CW9800H1 and CW9800H2 Wireless Controllers 8

Normal and Shared Subscriptions

Normal (Standard) Subscriptions

A normal subscription is the default and most common way for an MQTT client to receive messages. When a client subscribes to a topic, it signals to the MQTT broker that it wishes to receive all messages published to that specific topic (or any topic matching a wildcard filter).

Behavior:

  • Broadcast Delivery: If multiple clients subscribe to the same normal topic, each client will receive its own copy of every message published to that topic.
  • Independent Streams: Each subscriber operates independently, receiving a complete stream of messages.

Syntax:

  • Clients subscribe directly to the topic name or topic filter, e.g.:
    • sensor/temperature
    • device/+/status
    • alerts/#

Example:

  • If Topic A receives messages M1, M2, M3:
    • Client 1 subscribes to Topic A.
    • Client 2 subscribes to Topic A.
    • Result:
      Client 1 receives M1, M2, M3.
      Client 2 also receives M1, M2, M3.

Shared Subscriptions

A Shared Subscription is a feature in MQTT that allows multiple clients (subscribers) to share the workload of receiving messages from a single topic. Instead of each subscriber receiving all published messages (as in a normal subscription), MQTT brokers distribute messages among the subscribers in a round-robin or load-balanced manner. This strategy distributes messages among multiple subscribers, preventing any single subscriber client from being overwhelmed. It also helps achieve high MQTT throughput by preventing a single subscriber client from becoming a bottleneck.

Shared subscriptions are a specialized type of subscription designed for load balancing and high availability among a group of consumer clients. When multiple clients are part of a shared subscription group for a given topic, the MQTT broker distributes messages among them, ensuring that each message is delivered to only one client within that group.

Behavior:

  • Load-Balanced Delivery: Messages published to the underlying topic are delivered to only one active subscriber within the shared group. The broker employs an internal mechanism (e.g., round-robin) to distribute messages.
  • Workload Distribution: This prevents redundant processing by multiple consumers and allows for horizontal scaling of message processing.
  • High Availability: If one client in the shared group disconnects or fails, the broker automatically redirects subsequent messages to other active clients in the same group, ensuring continuous message processing.

Syntax:

  • Clients subscribe using a special prefix:
    $share/<group_name>/<topic_filter>
    • $share: Indicates a shared subscription.
    • <group_name>: An identifier for the specific group of subscribers. Clients with the same group name and topic filter form a shared group.
    • <topic_filter>: The actual topic filter to which messages are published.

Example:

  • If Topic A receives messages M1, M2, M3:
    • Client 1 subscribes to $share/my_group/Topic A.
    • Client 2 subscribes to $share/my_group/Topic A.
    • Result:
      Client 1 might receive M1, M3.
      Client 2 might receive M2.
      (The exact distribution depends on the broker's algorithm.)

Telemetry Message Format for Onboarded Advertisements and Notifications

The latest protobuf is available here.

The following is the code snippet of Telemetry message format:

syntax = "proto3";

import "google/protobuf/timestamp.proto";

option java_package = "org.ietf.nipc.proto";
option java_multiple_files = true;

package nipc;

message DataSubscription {
    optional string device_id = 1;
    bytes data = 2;
    google.protobuf.Timestamp timestamp = 3;
    optional string ap_mac_address = 4;

    reserved 5 to 10;

    oneof subscription {
        BLESubscription ble_subscription = 11;
        BLEAdvertisement ble_advertisement = 12;
        ZigbeeSubscription zigbee_subscription = 13;
        RawPayload raw_payload = 14;
        BLEConnectionStatus ble_connection_status = 15;
        ApplicationEvent application_event = 16;
    }

    message BLESubscription {
        optional string service_uuid = 1;
        optional string characteristic_uuid = 2;
    }

    message BLEAdvertisement {
        string mac_address = 1;
        optional int32 rssi = 2;
    }
    
    message ZigbeeSubscription {
        optional int32 endpoint_id = 1;
        optional int32 cluster_id = 2;
        optional int32 attribute_id = 3;
        optional int32 attribute_type = 4;
    }

    message BLEConnectionStatus {
        string mac_address = 1;
        bool connected = 2;
        optional int32 reason = 3;
    }
    
    message RawPayload {
        optional string context_id = 1;
    }

    message ApplicationEvent {
        string message = 1;
    }
}

message DataBatch {
    repeated DataSubscription messages = 1;
}