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.
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
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)
Additional Examples:
Creates and connects an MQTT client instance:
mqtt,err=require"mqtt3c".connect(addr, callback [, op])
Returns mqtt-object | nil,err - 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):
If the connection is secure (a SharkSSL object is provided), the server's trust status is validated by calling socket:trusted() if a username or password is provided. The client will not send any credentials to the broker if the broker's certificate is not trusted. The server's trust status is not validated if no credentials are provided, thus you may connect to a non trusted server if no credentials are provided.
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!" } })
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 SOCK5 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 -- 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 = require"mqtt3c".connect(s, callback, op) 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 trace("TLS upgrade failed",err) end else trace("Err:",status) end end -- HTTP client lib is blocking: run connection sequence in separate thread ba.thread.run(initiateMQTT)
The above example runs the MQTT loop in cosocket mode. Carefully read the sockets design tutorial prior to designing MQTT solutions.
Publish a message.
Subscribe to a topic.
Unsubscribe from a topic.
Gracefully disconnect from the broker.
Run the MQTT socket dispatch loop. This function does not return unless the connection disconnects. The function returns nil,error and the error message can be any of the socket error messages, the string "disconnect" if the connection was gracefully disconnected by calling mqtt:disconnect(), and the string " pingresp" if an MQTT PINGRES was not received when the client sent an MQTT PINGREQ.
The dispatcher loop is preferably called from within a cosocket, but can also be called from a dedicated thread.