The MQTT 3.1.1 client supports QoS 0. Use the MQTT 5 client unless you are communicating with an MQTT 3 only broker. The MQTT client is designed in Lua and utilizes the Barracuda App Server socket API. The MQTT client enables business logic implemented in the Lua scripting language to communicate with other MQTT clients via an MQTT broker. The MQTT client can also be used for bridging MQTT clients with protocols such as HTTP, WebSockets, SMQ, etc.
Receive limit: This client accepts at most 65,535 bytes in a packet's remaining-length field (the variable header plus payload). Larger incoming packets end run() with nil, string err, where err="overflow". This is a client implementation limit.
Creating and operating an MQTT client is typically wrapped in a function as follows:
local function onpub(topic,msg) -- publish callback function
trace("onpub",topic, msg) -- Print topic and payload data
end
local function connectAndRun(brokername)
local mqttmodule = require"mqtt3c" -- Load MQTT Client
local mqtt,err = mqttmodule.connect(brokername, onpub)
if mqtt then
mqtt:subscribe("#") -- Subscribe to all topics
mqtt:run() -- Does not return unless the connection disconnects
end
end
Example 1: Creating and running an MQTT client.
Code line 6 and 7 above can be optimized as follows:
local mqtt,err = require"mqtt3c".connect(brokername, onpub)
The MQTT client can operate in the three socket modes provided by the Barracuda App Server socket API: blocking, asynchronous, and cosocket mode. In most cases, the cosocket mode should be used. To start example 1 in cosocket mode, call function connectAndRun as follows:
ba.socket.event(function() connectAndRun(brokername) end)
Example 2: Starting example 1 in cosocket mode.
Additional Examples:
Creates and connects an MQTT client instance:
mqtt,err=require"mqtt3c".connect(addr, callback [, op])
Parameters
Return values
table mqtt on success; nil, string|integer err, string|boolean kind on failure. The kind is "sock" for connection, certificate-validation, write or read errors, "mqtt" for an invalid response, and true for a broker refusal. A failed MQTT handshake closes the socket, including a socket supplied by the caller.
function 'connect' returns an MQTT object if the connection was successful. The function returns nil,error if the connection fails. The error message can be any of the socket error messages, any of the error codes from socket:trusted() if the connection is secure, the string "invalidresp" if the client is unable to decode the response and the following MQTT broker response error codes (number):
When addr is a broker name, TLS connections are validated with socket:trusted(addr) unless nocheck is true, whether or not credentials are supplied. When addr is an existing socket, the caller must establish TLS and validate the peer before calling connect. The options table is used directly; secure=true can add a shark field.
Throws
Throws for incorrect argument types or options that cannot be encoded by the underlying socket and MQTT APIs. Connection and broker-refusal failures return the error values above. The callback receives string topic and string msg; its return values are ignored. It executes in run(), which does not catch callback exceptions.
The following example shows how to connect using TLS, how to use credentials, and how to provide an MQTT will message:
local mqtt,err = require"mqtt3c".connect("mybroker.com", onpub, {
secure=true,
port = 23922,
keepalive = 5*60, -- 5 minutes
id = "my-unique-id",
uname = "admin",
passwd = "qwerty",
will = {
topic = "whoops",
message = "Someone unplugged my cable!"
}
})
Example 3: Connecting to a secure broker.
The broker address can be a string (name) or an already established socket connection. Using a socket connection is useful when the MQTT client requires connecting to the Internet via a proxy. The following example shows how to establish a broker socket connection via a local proxy by using the HTTP client library and the "proxycon" setting. See the HTTP client for more information on opening a proxy connection.
local function initiateMQTT()
local http = require"httpc".create{
proxy="localhost", -- Using local proxy
socks=true, -- Enable SOCKS5
proxycon=true, -- Use the HTTP lib for opening a proxy connection
proxyport=1080, -- SOCKS5 port number
}
-- Connect to broker 'm11.cloudmqtt.com' at port number 23922
local ok,status = http:request{url="http://m11.cloudmqtt.com:23922"}
if status == "prxready" then -- If connection ready
local s = ba.socket.http2sock(http) -- Extract socket object
-- socket is now connected to broker, but broker uses TLS.
-- Initiate TLS handshake; use the ready-to-use SharkSSL client
ok,err=s:upgrade(ba.sharkclient())
if ok then ok,err=s:trusted("m11.cloudmqtt.com") end
if ok then
-- MQTT broker settings
local op = {
uname = "my-broker-username",
passwd = "my-broker-password",
id = "my-mqtt-id"
}
local function callback(topic, message)
trace(topic,message)
end
local mqtt,err = require"mqtt3c".connect(s, callback, op)
if not mqtt then trace("MQTT connection failed",err) return end
mqtt:subscribe"my-topic"
local function run()
trace"Starting MQTT loop"
mqtt:run()
trace"MQTT socket closed. Restarting..."
ba.thread.run(initiateMQTT)
end
mqtt.sock:event(run, "s") -- Cosocket mode
else
s:close()
trace("TLS connection failed",err)
end
else
trace("Err:",status)
end
end
-- HTTP client lib is blocking: run connection sequence in separate thread
ba.thread.run(initiateMQTT)
Example 4: Connecting via a SOCKS5 proxy.
This example runs the MQTT loop in cosocket mode. Carefully read the sockets design tutorial before designing MQTT solutions.
Queue a QoS 0 message for publication.
Parameters
Return values
No values. The message is queued even when disconnected; this is not a delivery acknowledgement.
Throws
Can throw for incorrect arguments, including a topic or payload that cannot be encoded.
Queue a QoS 0 subscription. Use subscribe(topic, op) to omit the acknowledgement callback.
Parameters
Return values
No values. The request is queued even when disconnected; the optional callback reports the broker's acknowledgement.
Throws
Can throw for incorrect arguments. A callback exception propagates from run() when that callback is invoked.
Queue an unsubscribe request and remove any local onpub override for the topic.
Parameters
Return values
No values. The request is queued even when disconnected.
Throws
Can throw for incorrect arguments. A callback exception propagates from run() when that callback is invoked.
Send DISCONNECT and close the socket, including when the write fails.
Parameters
None.
Return values
boolean ok, nil err on a successful write; nil, string|integer err on a write failure. If already disconnected, still closes any existing socket and returns nil, string|integer|nil err, using the stored error, which can be absent. This also releases a blocking connection after run() has returned an error. Repeated calls are safe. A local disconnect attempt sets the stored error to "disconnect", including when its write fails.
Throws
Does not deliberately throw for operational failures. Incorrect object or socket usage can throw.
Run the MQTT receive loop and invoke publication and acknowledgement callbacks. It returns when reception ends. Call it from a cosocket or a dedicated thread.
Parameters
None.
Return values
nil, string|integer err. Errors include socket errors, "disconnect" after local disconnect, "pingresp" after a missing PINGRESP, and "overflow" when the received packet's remaining length exceeds 65535 bytes. An unsupported control packet returns nil, string err, integer packetType, with err="unknowncp" and packetType containing the packet's upper four header bits. These return paths cancel the ping timer, mark the client disconnected and discard buffered input.
Throws
Callback exceptions propagate; callbacks must not throw. Incorrect object or socket usage can also throw. These exception paths bypass the normal loop cleanup.