GithubHelp home page GithubHelp logo

xhaskx / luamqtt Goto Github PK

View Code? Open in Web Editor NEW
146.0 11.0 41.0 362 KB

luamqtt - Pure-lua MQTT v3.1.1 and v5.0 client

Home Page: https://xhaskx.github.io/luamqtt/

License: MIT License

Lua 98.01% Makefile 0.52% Shell 1.47%
lua mqtt mqtt-client luasec tcp-connection ssl luajit luarocks protocol lua-versions

luamqtt's Introduction

luamqtt - Pure-lua MQTT v3.1.1 and v5.0 client

luamqtt logo

License tests Coverage Status Mentioned in Awesome MQTT forthebadge

MQTT ( http://mqtt.org/ ) client library for Lua. MQTT is a popular network communication protocol working by "publish/subscribe" model.

This library is written in pure-lua to provide maximum portability.

Features

  • Full MQTT v3.1.1 client-side support
  • Full MQTT v5.0 client-side support
  • Several long-living MQTT clients in one script thanks to ioloop

Documentation

See https://xhaskx.github.io/luamqtt/

Forum

See flespi forum thread

Source Code

https://github.com/xHasKx/luamqtt

Dependencies

The only main dependency is a luasocket to establishing TCP connection to the MQTT broker. Install it like this:

luarocks install luasocket

On Lua 5.1 it also depends on LuaBitOp (bit) library to perform bitwise operations. It's not listed in package dependencies, please install it manually like this:

luarocks install luabitop

luasec (SSL/TLS)

To establish secure network connection (SSL/TSL) to MQTT broker you also need luasec module, please install it manually like this:

luarocks install luasec

This stage is optional and may be skipped if you don't need the secure network connection (e.g. broker is located in your local network).

Lua versions

It's tested to work on Debian 9 GNU/Linux with Lua versions:

  • Lua 5.1 ... Lua 5.4 (i.e. any modern Lua version)
  • LuaJIT 2.0.0 ... LuaJIT 2.1.0 beta3
  • It may also work on other Lua versions without any guarantees

Also I've successfully run it under Windows and it was ok, but installing luarock-modules may be a non-trivial task on this OS.

Installation

As the luamqtt is almost zero-dependency you have to install required Lua libraries by yourself, before using the luamqtt library:

luarocks install luasocket # optional if you will use your own connectors (see below)
luarocks install luabitop  # you don't need this for lua 5.3 and above
luarocks install luasec    # you don't need this if you don't want to use SSL connections

Then you may install the luamqtt library itself:

luarocks install luamqtt

Or for development purposes;

# development branch:
luarocks install luamqtt --dev

# or from the cloned repo:
luarocks make

LuaRocks page

Examples

Here is a short version of examples/simple.lua:

-- load mqtt library
local mqtt = require("mqtt")

-- create MQTT client, flespi tokens info: https://flespi.com/kb/tokens-access-keys-to-flespi-platform
local client = mqtt.client{ uri = "mqtt.flespi.io", username = os.getenv("FLESPI_TOKEN"), clean = true }

-- assign MQTT client event handlers
client:on{
    connect = function(connack)
        if connack.rc ~= 0 then
            print("connection to broker failed:", connack:reason_string(), connack)
            return
        end

        -- connection established, now subscribe to test topic and publish a message after
        assert(client:subscribe{ topic="luamqtt/#", qos=1, callback=function()
            assert(client:publish{ topic = "luamqtt/simpletest", payload = "hello" })
        end})
    end,

    message = function(msg)
        assert(client:acknowledge(msg))

        -- receive one message and disconnect
        print("received message", msg)
        client:disconnect()
    end,
}

-- run ioloop for client
mqtt.run_ioloop(client)

More examples placed in examples/ directory. Also checkout tests in tests/spec/mqtt-client.lua

Also you can learn MQTT protocol by reading tests/spec/protocol4-make.lua and tests/spec/protocol4-parse.lua tests

Connectors

Connector is a network connection layer for luamqtt. There is a three standard connectors included:

The luasocket or luasocket_ssl connector will be used by default, if not specified, according secure=true/false option per MQTT client.

In simple terms, connector is a set of functions to establish a network stream (TCP connection usually) and send/receive data through it. Every MQTT client instance may have their own connector.

And it's very simple to implement your own connector to make luamqtt works in your environment.

Bugs & contributing

Please file a GitHub issue if you found any bug.

And of course, any contribution are welcome!

Tests

To run tests in this git repo you need busted:

busted -e 'package.path="./?/init.lua;./?.lua;"..package.path' tests/spec/*.lua

There is a script to run all tests for all supported lua versions, using hererocks:

./tests/run-for-all-lua-versions.sh

Code coverage

Code coverage may be collected using luacov.

To collect code coverage stats - install luacov using luarocks and then execute:

# collect stats during tests
busted -v -e 'package.path="./?/init.lua;./?.lua;"..package.path;require("luacov.runner")(".luacov")' tests/spec/*.lua

# generate report into luacov.report.out file
luacov

MQTT version

Currently supported is:

Both protocols has full control packets support.

LICENSE

Standard MIT License, see LICENSE file for full text

Version bump checklist

  • in file ./mqtt/const.lua: change _VERSION table field
  • in file ./openwrt/make-package-without-openwrt-sources.sh: change Version: X.Y.Z-P in $PKG_ROOT/control
  • in file ./openwrt/Makefile: change PKG_VERSION:=X.Y.Z and maybe PKG_RELEASE:=1
  • copy file ./luamqtt-scm-1.rockspec to ./rockspecs/luamqtt-X.Y.Z-1.rockspec change local package_version = "scm", local package_version = "X.Y.Z"
  • run ./tests/run-luacheck.sh and check output for errors
  • run ./tests/run-markdownlint.sh and check output for errors
  • run ./tests/run-for-all-lua-versions.sh and check output for errors
  • run ./openwrt/make-package-without-openwrt-sources.sh and check output for errors
  • run git commit, git tag vX.Y.Z
  • run git push, git push --tags
  • upload to LuaRocks; luarocks upload ./rockspecs/luamqtt-X.Y.Z-1.rockspec --api-key=ABCDEFGH

luamqtt's People

Contributors

bitgorbovsky avatar cmur2 avatar deining avatar dvv avatar jst-mbs avatar tieske avatar xhaskx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

luamqtt's Issues

Was it tested with AWS Iot?

label:Question

Hi,
I tried the simple client with TLS enable with correct credential information but it does not work.
I'm new to lua so not sure how to troubleshoot. I have the nodejs example working but the lua script does not connect. The original lua script is working.

Result:

# lua simple.lua
created MQTT client     mqtt.client{id="lua-simple-client"}
running ioloop for it
done, ioloop is stopped

Code change:

        uri = "abcdef.123.iot.us-east-1.amazonaws.com",
        id = "lua-simple-client",
        secure = {
                mode = "client",
                protocol = "tlsv1_2",
                verify = "peer",
                options = "all",
                cafile="/lua/root-CA.pem",
                certificate="/lua/Device.cert.pem",
                key="/lua/Device.private.key"
        },
        version= mqtt.v311,

Connection brokes after publishing in batch

Hi again ;)
Thanks for quick fix for #40 it makes working with docker much easier.

I bumped into another problem while using copas connector, but I'm not sure if it's stricly related to it.
I'm getting closed connection to broken after publishing ~150 messages in batch. Adding "copas.sleep(0)" after each publish solved issue completly. Doing it is good enough for me, but i wanted to let you know about problem.

Broker drops if i'm only receiving messages and not sending

It seems that broker is dropping connection (by design) because ping is sent only when connection is idle (if i read source correctly), but if i'm in receive-only mode and constantly receiving something, then ping may be never sent out. Have you faced this issue?
Steps to reproduce – with default settings connect to broker that sends something about every minute, and in ~1.5 minutes you'll be disconnected.

mqtt over websocket

hello, salam, is it possible to make a mqtt connection between browser and lua over websocket

Getting the error Connection Refused, not authorized again and again

Hello,
I am currently working on a project involving Teltonika devices, specifically with smart meters. The objective of this project is to retrieve meter readings and transmit the data to the Azure portal. When I am trying to publish a message to Azure portal with the help of mqtt in Lua language but I am getting the "Connection Refused, not authorized" . I am referring this document https://github.com/xHasKx/luamqtt. I have used the same credentials for sending the data to Azure in python language and the python script is working. I am using the Lua 5.4 version and below is my lua script

local mqtt = require("mqtt")
local json = require("lunajson")

local luasec =  require("ssl")
print("using luasec runtime version: ", luasec._VERSION)
local path_to_root_cert = "<root directory>/src/cert/digicert.crt"
local device_id = "Teltonika02";
local sas_token = "SharedAccessSignature sr=<hostname>.azure-devices.net&sig=xeJT3F1XsYB5uIcbLjW3L9do4NXlUIOC1kBfNZ5zHuQ%3D&skn=iothubowner&se=2045963831";
local iot_hub_name = "<hostname>.azure-devices.net/<device id>/?api-version=2021-04-12";
local client = mqtt.client({
	  uri = "<hostname>.azure-devices.net",
    username = iot_hub_name,
    secure = {
        mode = "client",
        protocol = "tlsv1_2",
        cafile = path_to_root_cert,
        certificate = nil,
        key = nil
     },
    password = sas_token,
    version = mqtt.v50,
    clean = true
});
print(client,  ":  client")
local topic = "devices/" .. device_id .. "/messages/events/$.ct=application%2Fjson%3Bcharset%3Dutf-8"
local payload = [[{'id':123}]]
client:on{
    connect = function(connack)
        print("connack....", connack)
        if connack.rc ~= 0 then
            print("connection to broker failed:", connack:reason_string(), connack)
            return
        end
        print("Now go for subscribe")
        -- connection established, now subscribe to test topic and publish a message after
        assert(client:subscribe{ topic=topic, qos=1, callback=function()
            assert(client:publish{ topic = topic, payload = payload })
        end})
    end,
    message = function(msg)
        print(msg, ": messgae")
        assert(client:acknowledge(msg))

        -- receive one message and disconnect
        print("received message", msg)
        client:disconnect()
    end,
}
-- run ioloop for client
mqtt.run_ioloop(client)
-- Check if the MQTT client is connected
if client.connected then
   print("Connection is established")
else
   print("Connection is not established : ", client.connected)
end

Failed to install it with luarocks on Ubuntu 16.04

I tried to install luamqtt with luarocks on Ubuntu 16.04, but I failed with the following logs:

daniel@memory:~/mqtt $ sudo luarocks install luamqtt
Installing https://rocks.moonscript.org/luamqtt-1.4.3-1.rockspec...
Using https://rocks.moonscript.org/luamqtt-1.4.3-1.rockspec... switching to 'build' mode
Cloning into 'luamqtt'...
remote: Enumerating objects: 29, done.
remote: Counting objects: 100% (29/29), done.
remote: Compressing objects: 100% (26/26), done.
remote: Total 29 (delta 2), reused 18 (delta 1), pack-reused 0
Receiving objects: 100% (29/29), 25.08 KiB | 0 bytes/s, done.
Resolving deltas: 100% (2/2), done.
Checking connectivity... done.
Note: checking out 'e2e16e029ff06f622d4750463ba64c18674d8d1f'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

Updating manifest for /usr/local/lib/luarocks/rocks
luamqtt 1.4.3-1 is now built and installed in /usr/local (license: MIT)

No code is installed:

daniel@memory:~/mqtt $ ls /usr/local/lib/luarocks/rocks/
index.html  luabitop  luafilesystem  luamqtt  luasec  luasocket  manifest  manifest-5.1  manifest-5.2  manifest-5.3  penlight
daniel@memory:~/mqtt $ ls /usr/local/lib/luarocks/rocks/luamqtt/
1.4.3-1
daniel@memory:~/mqtt $ ls /usr/local/lib/luarocks/rocks/luamqtt/1.4.3-1/
doc  luamqtt-1.4.3-1.rockspec  rock_manifest
daniel@memory:~/mqtt $

luamqtt on OpenResty

Hello

I was using with success the release v1.4 with OpenResty, by providing my own connector which uses ngx.socket.tcp. But now, with the latest version (v3.0), I can't make it work due to the new ioloop implementation, which apparently depends on luasocket.

Is it possible to run this latest version on OpenResty? Maybe by providing the necessary settings (sleep function, maybe) to ioloop or to use a different implementation for ioloop (which is suited for OpenResty)?

Thank you.

adding a streaming interface

Hi @xHasKx

Thx for this nice library, I've been eyeballing MQTT for a while now, and thought to give it a go actually.

The code looks nice and clean, but what I'm missing is a streaming interface. Looking at the code, currently client.lua mixers client functionality with io-loop functionality. Which isn't the right separation of concerns imho.

So would you be interested in a streaming interface? I've seen another issue about blocking IO (#23 ). So what I would propose to separate the client from the runloop is along the following lines;

  • new method client:consume_bytes(byte_string). This means the client is no longer responsible for reading data, only for processing it. Any runloop can read data in whatever way it sees fit, and then feed that into this method.
  • new callback provided to the client; send_bytes(byte_string). Whenever the client needs to send data, it calls this callback with the data to be transmitted.

This way the client and the runloop are cleanly decoupled.

wdyt?

as a start I sent a PR (#31 ) to expose the keepalive functionality to external runloops.

protocol5 missing

luamqtt fails on Lua 5.1 and 5.3
/usr/local/bin/lua: /usr/local/share/lua/5.1/mqtt/client.lua:47: module 'mqtt.protocol5' not found:
/usr/local/bin/lua: /usr/local/share/lua/5.3/mqtt/client.lua:47: module 'mqtt.protocol5' not found:

I've used LuaRocks to install luamqtt.
For Lua 5.1 and 5.3, the installation is the same; for 5.2, it's different.
See the attached file.

luamqtt-version-info.txt

One of the odd things is that the installation for Lua 5.2 is also missing mqtt.protocol5, but it never complains ... and works. Stranger even is that mqtt.protocol5 appears in here in GitHub.

Connect is blocking

Our broker was recently DDoSed, which caused a disconnect on our luamqtt end, and a reconnect attempt where the connecting routine took over a minute after which our service was automatically killed for being frozen by our watchdog.
The stacktrace showed us that in fact the ioloop is not used for connecting in mqtt:

local ok, err = args.connector.connect(conn)
(settimeout is only applied later)

Is this an oversight or by design? Would a rearchitecturing be out of the question so that connect would be asynchronous also?
(Connect will always block if there is DNS resolving to be done so this may also not be the perfect solution for everyone).
Another option is we could establish a connection ourselves and just provide the connected socket to luamqtt.

Error when use SSL with self certs

error info:
./lua: ./mqtt/clent.lua:148: unexpected key in client args: ssl = table: 0x38e418
stack traceback:
[C]: in function 'error'
./mqtt/client.lua:148: in method '__init'
./mqtt/client.lua:1165: in function 'mqtt.client.create'
(...tail calls...)
test_mqtt.lua:5: in main chunk
[C]: in ?

my config:

local client = mqtt.client{
-- NOTE: this broker is not working sometimes; comment username = "..." below if you still want to use it
-- uri = "test.mosquitto.org",
uri = "127.0.0.1:8883",
-- NOTE: more about flespi tokens: https://flespi.com/kb/tokens-access-keys-to-flespi-platform
-- username = "stPwSVV73Eqw5LSv0iMXbc4EguS7JyuZR9lxU5uLxI5tiNM8ToTVqNpu85pFtJv9",
clean = true,
ssl ={
cafile = "/home/app/client-key.pem",
certificate = "/home/app/client-cert.pem",
key = "/home/app/client-key.pem"
},
}

How can I resovle it. Thanks

Error when use SSL with self certs

Hello
I test with RabbitMQ, If I use from file: examples/quick-receive.lua, No SSL, port 1883 everything is Ok,
But when I use SSL port, self certs, has problem as below
Please correct the 'ssl_params' syntax in below config
Thank you so much

Use SSL with self certs

client = mqtt.client{
	debug = client_debug,
	uri = "x.x.x.x:8883",
	auth = {username = "mqtt_user", password = "123456" },
	clean = true,
	ssl = true,
	ssl_params = {	cafile = "/certs/device/cacert.pem",	
			       certificate = "/certs/device/clientcert.pem",
			       key = "/certs/device/clientkey.pem" },
	}	

Error examples/quick-receive2.lua

lua: /usr/lib/lua/mqtt/luasocket_ssl.lua:30: attempt to concatenate local 'err' (a nil value)
stack traceback:
/usr/lib/lua/mqtt/luasocket_ssl.lua:30: in function 'connect'
/usr/lib/lua/mqtt/init.lua:411: in function '_open_connection'
/usr/lib/lua/mqtt/init.lua:305: in function 'connect'

Issue use in Corona SDK

Hello:
Im try to using in Corona SDK and show a a error

loop or previous error loading module 'mqtt.bit'
12:55:47.955 stack traceback:
12:55:47.955 [C]: in function 'require'
12:55:47.955 ?: in function <?:820>
12:55:47.955 (tail call): ?
12:55:47.955 [C]: in function 'require'
12:55:47.955 ?: in function <?:820>
12:55:47.955 (tail call): ?
12:55:47.955 [C]: in function 'require'
12:55:47.955 ?: in function 'require'

do you know why it?

64 bits support required?

Compliments for this nice project!

I'm currently experimenting with it, but my lua environment is version 5.2 and cannot use LuaBitOp (or any other dynamic binding). Looking at the code, I suspect 32 bits support may be sufficient and I ported all of it to my framework simply using the bit32 functions; all unittests are succeeding.

Am I right about my suspicion or am I missing something?

Cannot be installed under luarocks/lua 5.4

Hi,

luamqtt does not install under luarocks for lua 5.4.
the culprit appears to be the line "lua >= 5.1, < 5.4" in the rockspec file.
Changing the '5.4' to '5.5' allows building/installation of luamqtt under lua 5.4/luarocks.

In OpenResty error

I wrap luamqtt like this:

local require = require

local mqtt = require("mqtt")
local ioloop = require("mqtt.ioloop")

local log = require("core.log")

local setmetatable = setmetatable
local timer_at = ngx.timer.at
local str_format = string.format

local function on_timer(premature, ctx)
  if premature then
    log.warn("exit mqtt timer!")
    return
  end

  log.info("starting mqtt client...")
  local loop = ioloop.create{
    timeout = ctx.cli.args.keep_alive,
    sleep_function = ngx.sleep,
  }
  loop:add(ctx.cli)
  ctx.cli:start_connecting()
  loop:run_until_clients()

  timer_at(1, on_timer, ctx)
end

local _M = {}
local mt = { __index = _M }

function _M:new(conf)
  local cli = mqtt.client{
    id = str_format("server/center/%d", ngx.worker.id()),
    uri = conf.broker,
    username = conf.username,
    password = conf.password,
    clean = true,
    connector = require("mqtt.ngxsocket")
  }

  cli:on{
    connect = function(connack)
      if connack.rc ~= 0 then
        log.error("connect mqtt broker failed!")
        return
      end

      log.info("mqtt client connected!")

      cli:publish{
        topic = "luamqtt/simpletest",
        payload = "hello",
        qos = 0
      }
    end,
    message = function(msg)
      cli:acknowledge(msg)
      log.info("receive mqtt message! ", msg)
    end,
    error = function(err)
      log.error("mqtt client error: ", err)
    end,
    close = function(conn)
      log.warn("mqtt conn closed: ", conn.close_reason)
    end
  }

  return setmetatable({
    conf = conf,
    cli = cli
  }, mt)
end

function _M:start()
  return timer_at(1, on_timer, self)
end

function _M:publish()
  timer_at(0, function ()
    self.cli:publish{
      topic = "luamqtt/simpletest",
      payload = "hello",
      qos = 0
    }
  end)
end

return _M

When mqtt connected, in connect callback function, the publish is worked, but i want publish a message when i received a http request, so i call the wrap function publish, but it failed:

2020/04/24 16:54:17 [error] 2002#2002: *3424 lua entry thread aborted: runtime error: /mnt/d/Workspace/Demo/Openresty/test//lib/mqtt/client.lua:1147: bad request
stack traceback:
coroutine 0:
        [C]: in function 'send'
        /mnt/d/Workspace/Demo/Openresty/test//lib/mqtt/client.lua:1147: in function '_send_packet'
        /mnt/d/Workspace/Demo/Openresty/test//lib/mqtt/client.lua:455: in function 'publish'
        /mnt/d/Workspace/Demo/Openresty/test//lua/core/mqtt.lua:82: in function </mnt/d/Workspace/Demo/Openresty/test//lua/core/mqtt.lua:81>, context: ngx.timer, client: 127.0.0.1, server: 0.0.0.0:7500
2020/04/24 16:54:46 [info] 2004#2004: *3423 client closed connection while waiting for request, client: 127.0.0.1, server: 0.0.0.0:7500

mqtt.protocol4 is not installed with luarocks install

daniel@memory:~/mqtt/luamqtt/examples (master)*$ lua simple.lua 
lua: /usr/local/share/lua/5.1/mqtt/init.lua:31: module 'mqtt.protocol4' not found:
	no field package.preload['mqtt.protocol4']
	no file './mqtt/protocol4.lua'
	no file '/usr/local/share/lua/5.1/mqtt/protocol4.lua'
	no file '/usr/local/share/lua/5.1/mqtt/protocol4/init.lua'
	no file '/usr/local/lib/lua/5.1/mqtt/protocol4.lua'
	no file '/usr/local/lib/lua/5.1/mqtt/protocol4/init.lua'
	no file '/usr/share/lua/5.1/mqtt/protocol4.lua'
	no file '/usr/share/lua/5.1/mqtt/protocol4/init.lua'
	no file './mqtt/protocol4.so'
	no file '/usr/local/lib/lua/5.1/mqtt/protocol4.so'
	no file '/usr/lib/x86_64-linux-gnu/lua/5.1/mqtt/protocol4.so'
	no file '/usr/lib/lua/5.1/mqtt/protocol4.so'
	no file '/usr/local/lib/lua/5.1/loadall.so'
	no file './mqtt.so'
	no file '/usr/local/lib/lua/5.1/mqtt.so'
	no file '/usr/lib/x86_64-linux-gnu/lua/5.1/mqtt.so'
	no file '/usr/lib/lua/5.1/mqtt.so'
	no file '/usr/local/lib/lua/5.1/loadall.so'
stack traceback:
	[C]: in function 'require'
	/usr/local/share/lua/5.1/mqtt/init.lua:31: in main chunk
	[C]: in function 'require'
	simple.lua:2: in main chunk
	[C]: ?

Running luamqtt through the Qt eventloop

Hi,

I am embedding Lua in my Qt application. However, it seems to me that running luamqtt would require me to run it in a separate thread, because it uses its own eventloop. Is it possible to run luamqtt via a custom eventloop? The workflow would be:

  1. Open a socket via Qt
  2. Wait for data via the Qt event-loop
  3. When something gets read, the C++ code runs a lua function, that handles the communication, possibly calling some sort of a callback that sends data over the socket back.
  4. The connection would stay alive for the runtime of the C++ application

Is it possible to implement something like this? I can see that there is an iteration function, that would maybe work for this usecase? I'm not how many iterations would one operation take and also, I don't want the Lua code to block if the connection is disrupted (when an operation gets a timeout). Or maybe I can use a custom connector? From what I can read, the connector doesn't allow me to use a custom eventloop.

Thanks

when called mqtt.ioloop is stuck,finally trace at sync_recv_func(...) stucked in function client_mt:_apply_network_timeout()

gcc——toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2
lua:5.1.5
skynet:1.5.0
mqtt:3.4.2

My code is as follows:

local io = require("ioloop")
local ioloop = require("mqtt.ioloop")

local mq_loop = ioloop.create {
        sleep = 1,
        timeout = 1,
        sleep_function = skynet.sleep
    }

local client = mqtt.client(conn_params)
    client:on{
        connect = function(connack)
            assert(not mqtt_client)

            if not (connack and connack.rc == 0) then
                logger:error("connection to mqtt fail: %s %s", connack and connack:reason_string() or "", connack)
                return
            end

            logger:info("MQTT client connected server success!!!") -- successful connection
            state_table.connect_ok = true
            local response_count = 0
            for _, item in ipairs(topics) do
                local module, topic = item.module, item.topic
                client:subscribe{
                    topic = topic,
                    qos = 0,
                    callback = function(suback, args)
                        response_count = response_count + 1
                        if suback.rc[1] ~= 0 then
                            client:disconnect(0)
                            logger:error("subscribe [%s %s] fail %s", module, topic, suback.rc[1])
                            return
                        end

                        logger:info("subscribe from cloud [%s, %s] ok", module, topic)
                        if response_count >= #topics then
                            mqtt_client = client
                            logger:info("All topic subscribes OK, MQTT client is ready!!!")
                            --Not support, upload software version with 5mins timer.
                            --[[
                            local mqtt_dispatcher = skynet.queryservice("mqtt_dispatcher")
                            skynet.send(mqtt_dispatcher, "lua", "post")
                            ]]
                        end
                    end
                }
            end
        end,
        message = function(msg)
            local err = client:acknowledge(msg)
            if not err then
                logger:error("received a error msg!")
                return
            end
            table.insert(work_queue, {
                msg.topic,
                msg.payload
            })

            logger:info("Recv from cloud, topic: %s, payload: %s", msg.topic, msg.payload)
            skynet.wakeup(work_loop_co)
            skynet.yield()
        end,
        error = function(err, args, connack)
            logger:error("mqtt client err: %s, args: %s, connack: %s", err, args, connack)
            if not connack then
                logger:error("MQTT client error maybe unable to connect to network")
                return
            end

            if connack.rc == 4 then
                state_table.connect_ok = false
                client.args.reconnect = client.args.reconnect + 5
            end
        end,
        close = function()
            state_table.connect_ok = false
            mqtt_client = nil -- set to nil mqtt_client = nil -- set to nil
            client = nil
            logger:error("mqtt client is close, set to not ready!!!")
        end
    }

    mq_loop:add(client)
    client:start_connecting()
    while true do
       if not client then
            break
        end
        mq_loop:iteration()   --------when run here is stuck
        skynet.yield()
    end

The mqTT_client is ready when the client is connected to the broker and three topics are subscribed. The mqTT_client is then stuck at mq_loop: Iteration ()

What is the cause of the jam? Appreciate receiving

Design or code example of using custom loop iterator

There's a placeholder argument for ioloop

-- @tparam[opt] function args.sleep_function custom sleep function to call after each iteration
but arguments are not used anywhere and there's no direct access to this setting

My case is to connect 2 streams of operations for back and fourth messaging (between KNX bus and MQTT), so I need simultaneously read messages from both local bus and MQTT. My first assumption was that sleep function might be best place to put my bus loop.

Here's an example of bus read loop:

function groupcallback(event)
    if event.dst == '1/1/1' then
        local value = knxdatatype.decode(event.datahex, dt.uint16)
        submit_to_mqtt(value)
    end
end
 
lb = require('localbus').new(0.5) -- timeout is 0.5 seconds
lb:sethandler('groupwrite', groupcallback)
 
while true do
    lb:step()
    do_some_other_stuff()
end

What is the best way to implement this type of messaging loop?

OpenWrt makefile doesn't build

Hi, using the current master openwrt Makefile, the build fails with the following verbose output:

mkdir -p /home/ubuntu/openwrt/dl
SHELL= flock /home/ubuntu/openwrt/tmp/.v3.1.tar.gz.flock -c '  	/home/ubuntu/openwrt/scripts/download.pl "/home/ubuntu/openwrt/dl" "v3.1.tar.gz" "x" "" "https://github.com/xHasKx/luamqtt/archive/"    '
Cannot find appropriate hash command, ensure the provided hash is either a MD5 or SHA256 checksum.
Makefile:49: recipe for target '/home/ubuntu/openwrt/dl/v3.1.tar.gz' failed
make[2]: *** [/home/ubuntu/openwrt/dl/v3.1.tar.gz] Error 255
make[2]: Leaving directory '/home/ubuntu/openwrt/feeds/jng_lua_openwrt/luamqtt'
time: package/feeds/jng_lua_openwrt/luamqtt/download#0.17#0.10#0.27
package/Makefile:111: recipe for target 'package/feeds/jng_lua_openwrt/luamqtt/download' failed
make[1]: *** [package/feeds/jng_lua_openwrt/luamqtt/download] Error 2
make[1]: Leaving directory '/home/ubuntu/openwrt'
make[1]: Entering directory '/home/ubuntu/openwrt'
make[2]: Entering directory '/home/ubuntu/openwrt/target/linux'
make[3]: Entering directory '/home/ubuntu/openwrt/target/linux/ar71xx'
make[3]: Nothing to be done for 'download'.
make[3]: Leaving directory '/home/ubuntu/openwrt/target/linux/ar71xx'
make[2]: Leaving directory '/home/ubuntu/openwrt/target/linux'
time: target/linux/download#0.03#0.03#0.07
make[1]: Leaving directory '/home/ubuntu/openwrt'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.