Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start support for AWS IoT setup #1103

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Start support for AWS IoT setup #1103

wants to merge 1 commit into from

Conversation

jjcarstens
Copy link
Collaborator

Initial support for an MQTT and message queue setup for device connections as an alternative to websockets.

This first focus is on a typical AWS IoT setup which handles device connection (including authentication), provides connect/disconnect lifecycle events, and forwards messages directed for the server to an SQS queue which server nodes will poll from when available to do work.

Documentation on setting up this type of infrastructure is still being worked on, but much of the code is annotated and a general overview is in the graph below. It mainly showcases some message flow between multiple server nodes and devices through MQTT+queue system

graph LR;
    subgraph "IoT Devices"
        device1[[Device 1]]
        device2[[Device 2]]
    end

    subgraph queues [SQS Queues]
        q1[(device_messages)]
        q2[(fwup_messages)]
    end

    subgraph broker [MQTT broker]
        rules{Rules engine}
        device_specific_topic(((Device specific topics)))
    end

    subgraph "Web Servers"
        subgraph node1 [Node 1]
            mqtt1(MQTT publisher)
            dev1{{device_messages consumer}}
            fwup1{{fwup consumer}}
        end
        subgraph node2 [Node 2]
            mqtt2(MQTT publisher)
            fwup2{{fwup consumer}}
            dev2{{device_messages consumer}}
        end
    end

    mqtt1 -. publish nh/1/msg .-> device_specific_topic;
    mqtt2 -. publish nh/2/msg .-> device_specific_topic;
    device1 -- nh/1/device_msg --> rules;
    device2 -- nh/2/fwup --> rules;
    device_specific_topic -. nh/1/msg .-> device1;
    device_specific_topic -. nh/2/msg .-> device2;
    rules -- rule nh/+/device_msg --> q1;
    rules -- rule nh/+/fwup --> q2;
    q2 -- poll --> fwup1;
    q1-- poll --> dev2;

    style device1 fill:red;
    style device2 fill:blue;
    style node1 stroke:magenta,stroke-width:4px;
    style node2 stroke:green,stroke-width:4px;
    linkStyle 1,3,5,7,8 stroke:blue;
    linkStyle 0,2,4,6,9 stroke:red;
Loading

Note

  • nh/#{device.identifier} topic is for server->device
  • nh/device_messages topic is for device->server
    • Only one SQS queue is expected to hold all messages for now
  • JITP is currently not considered
    • Since the MQTT broker handles the authentication on connection, we need to decide if we just implicitly trust any message we get from the broker and create a device record or require devices be preregistered with a certificate fingerprint
  • The message structure is in flux. What is in here will most likely change
  • Effort was made to ensure the setup could all be run locally (i.e. No need for AWS services to develop and test!)

@impl Supervisor
def init(opts) do
opts =
Application.get_env(:nerves_hub, __MODULE__, [])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be great if the sup took these arguments in start_link/1 rather than pulling them from application env on init. You can keep the same pattern if you want to use app env e.g.

opts = Application.get_env(:nerves_hub, __MODULE__, [])
{NervesHub.AWSIoT, opts}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The incoming opts to the GenServer are merged into the Application env so the end result is the same where opts provided to start_link will take precedence . The preference here is mostly that it is contained

@joshk
Copy link
Collaborator

joshk commented Nov 23, 2023

This is really cool.

Regarding the MQTT to SQS dance, just to confirm, you are essentially starting a Broadway consumer for MQTT events then popping them onto SQS, right?

And then there is another Broadway consumer for SQS events?

@jjcarstens
Copy link
Collaborator Author

Not quite. Broadway is only for consuming SQS. Servers publish directly to the MQTT broker (via an HTTP request) which distributes messages to topic subscribers

@joshk
Copy link
Collaborator

joshk commented Nov 23, 2023

Ok, in your diagram is shows MQTT publishing to SQS, is that a function supported by MQTT?

@jjcarstens
Copy link
Collaborator Author

Ah, yes. My draft of doc changes talk about this but just realized it wasn't mentioned here.

MQTT is only a broker, but it's common to put a "rules engine" in front of it to run some query/checks on the topic and/or payload and perform an action on it. This is included as part of AWS IoT. You would pick topics devices use for directing messages to a server and the rules engine would have a rule that matches at the broker and sends the message to a queue, like SQS, instead.

@joshk
Copy link
Collaborator

joshk commented Nov 24, 2023

ahhhh, cool, thanks for the extra information.

Initial support for an MQTT and message queue setup for device
connections as an alternative to websockets
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants