Jackalope (jackalope v0.4.1) View Source

Jackalope is an opinionated MQTT library that simplifies the use of Tortoise MQTT with cloud IoT services.

Jackalope aims to make an interface that:

  • Ensure that important messages are delivered to the broker, by having a local "post office" and tracking the in flight messages, and implementing a concept of ttl (time to live) on the messages placed in the mailbox; ensuring the "request to unlock the door" won't happen two hours later when the MQTT connection finally reconnects. This allows Jackalope to accept publish and subscription requests while the connection is down.

  • Makes it impossible (or at least hard) to do things that AWS IoT and other popular services do not support; such as publishing a message or subscribing to a topic filter with a greater quality of service than allowed, or publishing a message with the retain flag set

  • Makes it easy to connect to AWS IoT with the correct encryption enabled (Coming soon!)

Besides this Jackalope aims to provide helpers for local testing, allowing you to test your application without having a connection to AWS; Jackalope should take care of that.

Usage

The Jackalope module implements a start_link/1 function; use this to start Jackalope as part of your application supervision tree. If properly supervised it will allow you to start and stop Jackalope with the part the application that needs MQTT connectivity. Jackalope is configured using a keyword list, consult the Jackalope.start_link/1 documentation for information on the available option values.

Once Jackalope is running it is possible to subscribe, unsubscribe, and publish messages to the broker; in addition to this there are some connection specific functionality is exposed, allowing us to ask for the connection status, and request a connection reconnect.

  • Jackalope.subscribe(topic) request a subscription to a specific topic. The topic will be added to the list of topics Jackalope will ensure we are subscribed to.

  • Jackalope.unsubscribe(topic) will request an unsubscribe from a specific topic and remove the topic from the list of topics Jackalope ensure are subscribed to.

  • Jackalope.publish(topic, payload) will publish a message to the MQTT broker;

  • Jackalope.reconnect() will disconnect from the broker and reconnect; this is useful if the device changes network connection.

Please see the documentation for each of the functions for more information on usage; especially the subscribe and publish functions accepts options such as setting quality of service and time to live.

Link to this section Summary

Functions

Returns a specification to start this module under a supervisor.

Publish a message to the MQTT broker

Request the MQTT client to reconnect to the broker

Start a Jackalope session

Place a subscription request for a given topic_filter

Place an unsubscribe request for the given topic_filter

Link to this section Functions

Returns a specification to start this module under a supervisor.

See Supervisor.

Link to this function

publish(topic, payload, opts \\ [])

View Source

Publish a message to the MQTT broker

The payload will get published on topic. Jackalope will keep the message in a queue until we got a connection, at which point it will dispatch the publish. This of course present us with a problem: what if we place a publish request to "unlock the front door" while the client is offline? We don't want to receive a message that the front door has been unlocked two hours later when the MQTT client reconnect; To solve that problem we have a ttl option we can specify on the publish.

Jackalope.publish("doors/front_door", %{action: "unlock"}, ttl: 5_000)

Currently ttl is the only queue option available; to set MQTT Publish options, such as the quality of service, can be done like this:

Jackalope.publish({"room/salon/temp", qos: 1}, %{temp: 21})

The available package options are:

  • qos (default 1) set the quality of service of the message delivery; Notice that only quality of service 0 an 1 are supported by AWS IoT; specifying 2 will result in an error.

  • retain has to be false, as AWS IoT does not support retained publish messages

Notice that Jackalope will JSON encode the payload; so the data should be JSON encodable.

Specs

reconnect() :: :ok

Request the MQTT client to reconnect to the broker

This can be useful on devices that has multiple network interfaces. After the reconnect Jackalope will subscribe to the topic_filters it was subscribed to, ensuring that we are in sync with the subscription state.

Specs

start_link(keyword()) :: Supervisor.on_start()

Start a Jackalope session

This will start a supervised group of processes; part of the group will keep track of the topic filter subscription state, and hold a list of yet to be published messages, as well as the requested subscription changes; the other part of the process tree will keep the MQTT connection specific parts, making sure we got a connection. See the main documentation on the Jackalope module for more information on the process architecture.

Jackalope.start_link/1 takes a keyword list containing option values, that configure the instance, as an argument. The available options and their defaults are:

  • client_id (default: "jackalope"), string that will be used as the client_id of the MQTT connection; see t Tortoise.client_id for more information on valid client ids. Notice that the client_id needs to be unique on the server, so two clients may not have the same client_id.

  • initial_topics (optional) specifies a list of topic_filters Jackalope should connect to when a connection has been established. Notice that this list is only used for the initial connect, should a reconnect happen later in the life-cycle, the current subscription state tracked by Jackalope will be used.

  • handler (default: Jackalope.Handler.Logger) specifies the module implementing the callbacks (implementing Jackalope.Handler behaviour) to use. This module reacts to the events Jackalope communicates about the connection life-cycle, including receiving a message on a subscribed topic filter. Read the documentation for Jackalope.Handler for more information on the events and callbacks.

  • server (default: {Tortoise.Transport.Tcp, [host: "localhost", port: 1883]}) specifies the connection type, and its options, to use when connecting to the MQTT server. The default specification will attempt to connect to a broker running on localhost:1883, on an insecure connection. This value should only be used for testing and development;.

  • max_work_list_size (default: :infinity) specifies the maximum number of unexpired work orders Jackalope will retain in its work list (the commands yet to be sent to the MQTT server). When the maximum is reached, the oldest work order is dropped before adding a new work order.

  • last_will (default: nil) specifies the last will message that should get published on the MQTT broker if the connection is closed or dropped unexpectedly. If we want to specify a last will topic we should define a keyword list containing the following:

    • topic (Required) the topic to post the last will message to; this should be specified as a string and it should be a valid MQTT topic; consult t Tortoise.topic for more info on valid MQTT topics.
    • payload (default: nil) the payload of the last will message; notice that we will attempt to JSON encode the payload term (unless it is nil), so it will fail if the data fails the JSON encode.
    • qos (default: 0) either 0 or 1, denoting the quality of service the last will message should get published with; note that QoS=2 is not supported by AWS IoT.
  • TODO backoff make backoff a configurable value

Link to this function

subscribe(topic_filter, opts \\ [])

View Source

Place a subscription request for a given topic_filter

Once Jackalope has successfully subscribed to the topic_filter it will get added to the list of topic filters to ensure when reconnecting; this ensure that Jackalope have a consistent view of the subscription state, even if the MQTT client reconnect with a clean session state.

Jackalope.subscribe("rooms/living-room/temperature")

It is possible to specify the maximum quality of service to subscribe to like so:

Jackalope.subscribe({"rooms/kitchen/water-leak-sensor", qos: 1})

The default QoS is 1; Notice that AWS IoT does not support subscriptions with QoS=2, so only 0 and 1 are permitted.

Like the public message it is possible to set a time to live on the subscribe request:

Jackalope.subscribe("golf/+/result", ttl: 5_000)

This will not dispatch the subscribe request Jackalope cannot get it to the broker within the specified duration (in ms).

Link to this function

unsubscribe(topic_filter, opts \\ [])

View Source

Place an unsubscribe request for the given topic_filter

This will place a unsubscribe and inform Jackalope to remove the given topic_filter from the list of subscriptions to ensure.

Jackalope.unsubscribe("room/lobby/doorbell")

The only configuration option is the ttl value, which can be set like so:

Jackalope.unsubscribe("room/lobby/doorbell", ttl: 1_000)

Like all the other messages, this will drop the message if it stays too long in the queue.