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 interfereoperations/
: Available operations; actions that an IoT device can performhubble/
: Specific to Alexi's Pireq/
: Request that data be queried/retrievedres/
: Location to send this data; included in the request payload
scheduled/
: Scheduled operationsreq/
: Request scheduled operationsres/
: Respond with scheduled operations
heartbeat/
: Query which devices are connectedreq/
: Send a request to devices to broadcast if they are connectedres/
: Connected devices broadcast here
cmd/
: used to send commandsneo/
: Commands relating to this project. Kind of redundant here, but encapsulates so that other (future) projects won't interferehubble/
: Specific to Alexi's Pireq/
: Request that a command be performedres/
: Send a result of the performed command (success/failure); included in the request payload
schedule/
: Relating to scheduling commands to be run laterreq/
: Request that a command be scheduledres/
: Response topic for success/failure messagesdel/
: Delete a scheduled operationreq/
: Request that a scheduled operation be deletedres/
: 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.
- Neo has a data object that stores its available operations (the things it can do)
- Neo subscribes to the available operations request topic
- Dibiasky subscribes to the operations response topic
- Dibiasky publishes to the operations request topic (with no payload at present)
- Neo subscribes to the operations response topic
- 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?
- Dibiasky subscribes to the operations response topic. This allows Dib to see the eventual result of the requested operation.
- Neo/Hubble(Pi) subscribes to the operations request topic. This allows Neo to listen for operation requests.
- 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.
- 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.