diff --git a/mqtt/client.lua b/mqtt/client.lua
index d17f8d2..0b5e1f4 100644
--- a/mqtt/client.lua
+++ b/mqtt/client.lua
@@ -55,7 +55,7 @@ Client.__index = Client
--
`[mqtt[s]://][username[:password]@]hostname[:port]`
--
Any option specifically added to the options
-- table will take precedence over the option specified in this uri.
--- @tparam boolean opts.clean clean session start flag
+-- @tparam boolean|string opts.clean clean session start flag, use "first" to start clean only on first connect
-- @tparam[opt] string opts.protocol either `"mqtt"` or `"mqtts"`
-- @tparam[opt] string opts.username username for authorization on MQTT broker
-- @tparam[opt] string opts.password password for authorization on MQTT broker; not acceptable in absence of username
@@ -64,7 +64,7 @@ Client.__index = Client
-- @tparam[opt=4] number opts.version MQTT protocol version to use, either `4` (for MQTT v3.1.1) or `5` (for MQTT v5.0).
-- Also you may use special values `mqtt.v311` or `mqtt.v50` for this field.
-- @tparam[opt] string opts.id MQTT client ID, will be generated by luamqtt library if absent
--- @tparam[opt=false] boolean,table opts.secure use secure network connection, provided by the lua module set in `opts.ssl_module`.
+-- @tparam[opt=false] boolean|table opts.secure use secure network connection, provided by the lua module set in `opts.ssl_module`.
-- Set to true to select default parameters, check individual `mqtt.connectors` for supported options.
-- @tparam[opt] table opts.will will message table with required fields `{ topic="...", payload="..." }`
-- and optional fields `{ qos=0...2, retain=true/false }`
@@ -83,7 +83,7 @@ Client.__index = Client
--
-- local my_client = Client.create {
-- uri = "mqtts://broker.host.com",
--- clean = true,
+-- clean = "first",
-- version = mqtt.v50,
-- }
function Client:__init(opts)
@@ -104,7 +104,7 @@ function Client:__init(opts)
assert(value_type == "string", "expecting uri to be a string")
a.uri = value
elseif key == "clean" then
- assert(value_type == "boolean", "expecting clean to be a boolean")
+ assert(value_type == "boolean" or value == "first", "expecting clean to be a boolean, or 'first'")
a.clean = value
elseif key == "version" then
assert(value_type == "number", "expecting version to be a number")
@@ -152,7 +152,7 @@ function Client:__init(opts)
-- check required arguments
assert(a.uri, 'expecting uri="..." to create MQTT client')
- assert(a.clean ~= nil, "expecting clean=true or clean=false to create MQTT client")
+ assert(a.clean ~= nil, "expecting clean=true, clean=false, or clean='first' to create MQTT client")
if not a.id then
-- generate random client id
@@ -858,7 +858,7 @@ function Client:send_connect()
local connect = self._make_packet{
type = packet_type.CONNECT,
id = opts.id,
- clean = opts.clean,
+ clean = not not opts.clean, -- force to boolean, in case "first"
username = opts.username,
password = opts.password,
will = opts.will,
@@ -1058,6 +1058,10 @@ function Client:handle_received_packet(packet)
log:info("client '%s' connected successfully to '%s:%s'", self.opts.id, conn.host, conn.port)
-- fire connect event
+ if self.opts.clean == "first" then
+ self.opts.clean = false -- reset clean flag to false, so next connection resumes previous session
+ log:debug("client '%s'; switching clean flag to false (was 'first')", self.opts.id)
+ end
self:handle("connect", packet, self)
self.first_connect = false
else