Topics and Payloads - alyoshenka/neo GitHub Wiki

Overview

AWS IoT communicates via MQTT using topics to send payloads. This document explains the topic and payload structure. See this paper for a good example of topic design.

Topic Tree

Project-Defined Topics

  • dt/: used for telemetry (data)
    • neo/: Commands relating to this project. Kind of redundant here, but encapsulates so that other (future) projects won't interfere
      • operations/: Available operations; actions that an IoT device can perform
        • hubble/: Specific to Alexi's Pi
          • req/: Request that data be queried/retrieved
          • res/: Location to send this data; included in the request payload
      • scheduled/: Scheduled operations
        • req/: Request scheduled operations
        • res/: Respond with scheduled operations
      • heartbeat/: Query which devices are connected
        • req/: Send a request to devices to broadcast if they are connected
        • res/: Connected devices broadcast here
  • cmd/: used to send commands
    • neo/: Commands relating to this project. Kind of redundant here, but encapsulates so that other (future) projects won't interfere
      • hubble/: Specific to Alexi's Pi
        • req/: Request that a command be performed
        • res/: Send a result of the performed command (success/failure); included in the request payload
      • schedule/: Relating to scheduling commands to be run later
        • req/: Request that a command be scheduled
        • res/: Response topic for success/failure messages
        • del/: Delete a scheduled operation
          • req/: Request that a scheduled operation be deleted
          • res/: Response topic for success/failure message

AWS-Defined Topics

  • $aws/events/presence/connected/{deviceId}: Fires when the device connects
  • $aws/events/presence/disconnected/{deviceId}: Fires when the device disconnects

Payloads

Both Neo and Dibiasky essentially need to agree on how payloads are structured.

Command Payloads

neo defines available operations:

# const.py
OPERATIONS = [
  {
        "module": "neopolitan", # Run this operation with neopolitan
        "subCommand": "open", # Command mapping within the module
        "friendlyName": "Open Neopolitan Display" # Simple display name
    },
    {
        "module": "neopolitan",
        "subCommand": "close",
        "friendlyName": "Close Neopolitan Display"
    }, ...
]

To run an operation, Dibiasky needs to send a message containing 1) that the intent is to run an operation 2) the operation to run and 3) the topic to publish its success/failure to.

Schedule Payloads

When scheduling a command to be run sometime in the future, the following information is needed:

  • A response topic to send success/failure messages
  • The topic to send the operation to
  • The time to execute the command
  • The command to execute
    • And any additional data needed for that command

* Required for all commands

const neopolitanOperationRequest = {
  responseTopic: '/cmd/neo/schedule/res', // Send success/failure
  publishTopic: 'cmd/neo/hubble/req', // Send the message to the IoT device
  executeAt: '2023-05-15T14:49:00Z', // Execution time
  operation*: { // Operation to run
    friendlyName: 'Run Neopolitan Update', // Display name
    module*: 'neopolitan', // Submodule
    options: { // Additional data for the operation
      say: 'Hello world!', // In this case, message to display
      speed: 'fast', // In this case, scroll speed
      wrap: false // In this case, whether the display should wrap around
    }
  }
};

Topic Routing

AWS allows the triggering of other services on publish to specific topics

  • cmd/neo/schedule/req -> ReceiveScheduleFunction
    • Lambda function to schedule an operation
  • dt/neo/scheduled/req -> PublishScheduledOperationsDBContents
    • Lambda function to publish scheduled operations from a database
  • cmd/neo/schedule/del/req -> DeleteScheduledOperation
    • Lambda function to delete a scheduled function from the database

Circular Message Passing

Get Available Operations

How does Dibiasky know what operations Neo/IoT Devices can perform? We need this information to populate our payloads for later operation requests as well as display what all can be done.

  1. Neo has a data object that stores its available operations (the things it can do)
  2. Neo subscribes to the available operations request topic
  3. Dibiasky subscribes to the operations response topic
  4. Dibiasky publishes to the operations request topic (with no payload at present)
  5. Neo subscribes to the operations response topic
  6. Dibiasky adds the operations from this payload to the webpage

Trigger an Operation

So, how do we request that an operation be performed? For example, how do request from Dibiasky that Neo run an operation on the LED board and get a response of whether that operation succeeded?

  1. Dibiasky subscribes to the operations response topic. This allows Dib to see the eventual result of the requested operation.
  2. Neo/Hubble(Pi) subscribes to the operations request topic. This allows Neo to listen for operation requests.
  3. Dibiasky publishes to the operations request channel, requesting that a specified operation be performed. For example, run an LED board animation or anything else defined in the payload.
  4. Neo receives this message and processes it, then publishes a response to the operations response topic, which allows Dib to know whether the operation was a success.

todo: should more of this be defined in the payload instead???

Events

AWS IoT also publishes to some of its own events that can be used for IoT device status, job status, etc. More information here.