MQTT Plugin
-
I thought it might help with writing your plugin. Looking forward to see what you come up with.
-
Well I learned something from it. My problem with opening the listening client was not due to cpu threading but because it was blocking the socket. Unless I want to proceed with a polling strategy, this particular library is not going to work... Ohh well, back to square one with a different library.
-
Slightly OT. Overall I like lua, but I miss the simple approach to non-blocking code offered by c# and even JavaScript. That’s particularly bad when doing network/http call, because it’s very difficult to write async code.
-
There’s no fundamental difficulty in writing non-blocking I/O. The openLuup server module and scheduler allow callbacks on incoming. The HTTP async code has a separate module simply because of its entanglement within the LuaSocket HTTP module.
-
@akbooer said in MQTT Plugin:
There’s no fundamental difficulty in writing non-blocking I/O.
well, I was speaking about an async/await first approach, with lambdas/promises. co-routines are just OK.
maybe I'm too biased because I'm used to the other approach and I still spend most of my time writing C#/Javascript instead of LUA. I wish it was simpler - let's say - to execute 3 HTTP calls under Vera in parallel, each having its own response handler inline. -
@therealdb said in MQTT Plugin:
I wish it was simpler - let's say - to execute 3 HTTP calls under Vera in parallel, each having its own response handler inline.
So this isn't good enough...?
local async = require "http_async" async.request ("http://request1", function (response, code, headers, statusline) -- response code 1 here end) async.request ("http://request2", function (response, code, headers, statusline) -- response code 2 here end) async.request ("http://request3", function (response, code, headers, statusline) -- response code 3 here end)
-
Oh, I missed this.
It could greatly benefit to my own HTTP plug-in. Any plan to release as a plug-in on Vera itself? -
Yes, it already works on Vera.
-
...if you excuse a link to the other place:
-
Well my frustration is not so much with http, though I did have my run ins with it and ended up using libcurl due to... digest not working somehow on luajit with luasocket but at this moment, I am finding that:
- the luarocks version of the MQTT library uses the luasocket in a blocking fashion. It does connect fine to the MQTT broker though.
- the vera-mqtt plugin is full of little bugs causing it to not work as a subscription client. For example the library fails to declare the socket variable, It crashes with an empty socket call to SSL when SSL is not needed etc... I have not been able to make it connect to the mosquitto broker even after fixing all the problems I found...
Sadly, I may have to move back to python and have home-assistant being the MQTT bridge.
-
As I already said, I wrote my own bridge in c#. I might make it more general purpose and release it. It’s a process running inside .net core and as ha-bridge could be installed separately, but pointing to openluup.
Let’s see if I find some motivation. It’s very lightweight, since it’s just one library running in a console app, and .NET Core 3.1 is very performant. -
@rafale77 said in MQTT Plugin:
- the vera-mqtt plugin is full of little bugs causing it to not work as a subscription client. For example the library fails to declare the socket variable, It crashes with an empty socket call to SSL when SSL is not needed etc... I have not been able to make it connect to the mosquitto broker even after fixing all the problems I found...
Sadly, I may have to move back to python and have home-assistant being the MQTT bridge.
I have had good success with the plugin I linked to above. Currently I have 9 different child devices subscribing to at least 15 different topics. I did modify the plugin slightly, not to get it to work, but to allow for child devices to have any designated number of subscriptions, include availability, state, and command topic subscriptions, and I added actions/functions for reconnecting to the mqtt server and reconnecting subscriptions.
-
Well I made some progress and got it to connect to the broker but it is extremely fragile. Digging into it deeper, it actually relies on a periodic call of a "handler" function in the library to check for messages from the broker. The call fails regularly and is not very well written in the sense that it defeats the purpose of MQTT by doing a poll.
There are a number of forks of this library which attempted various fixes and they have had various degree of success.
Not judging the plugin itself but rather the MQTT library. I actually took quite a bit from the plugin for these tests. Still work in progress but I am pretty pessimistic. -
Update: I now have a kind of a working solution and it is interesting...
The fundamental problem is that setting up an MQTT client to listen to the broker blocks the luasocket and therefore openLuup.
The two libraries use different approaches to the problem.
The older library used by the vera MQTT plugin uses a handler function which polls the broker and gets and closes immediately regardless of getting a message or not. It therefore won't block the luasocket but it comes back empty 99% of the time and really relies on luck to catch a message as it can miss them. Basically unusable.
The newer lua library does the same but waits for a message back and blocks the luasocket while waiting. If one sets a high polling frequency without getting a message back, openLuup hangs. My solution to this has been to significantly increase the frequency of messages from the publishing client to unblock the socket. It really is no longer event based and this generates a lot of traffic.If anyone has better suggestions (@therealdb I look forward to your bridge). I am also thinking that openLuup could use moving all its http traffic from luasocket to libcurl...
Edit:
I ended up giving up on trying to make it work with luasocket and spent 2min setting up 4 MQTT subscriptions on Home Assistant and another 10 to build the bridges back into openLuup. I really hoped to be able to do have a direct pipe into openLuup...
-
@rafale77 right now I'm using it to process incoming messages and update variables on Vera/Openluup. Do you want to call service endpoints as well? I can make it really generic and call HTTP endpoints, if needed. So you can
I don't use it so much to send messages, but I think we could add this later, if needed.
I can also try to put a relay feature, to receive incoming messages and then publish them back to another broker.It's based on a JSON config file and you have to map it manually, but then it's transparent. Give me a couple of days to polish and I'll publish it on GitHub, with instructions on how to build, and install it.
-
@rafale77 said in MQTT Plugin:
The fundamental problem is that setting up an MQTT client to listen to the broker blocks the luasocket and therefore openLuup.
The two libraries use different approaches to the problem.This just sounds like a lack of understanding on behalf of the module authors, ...or possibly me. I can’t believe that it could possibly be so difficult.
These are the two libraries you referenced st the start?
-
@akbooer
Or it could very well be that I missed something but looking at reports from github, I am not the only one observing it. These library work very well for publishing to the broker. They don't work unless you want to dedicate an instance of lua to be the listener...
@therealdb
This could potentially be the base for a bridge to so many things for openLuup!! -
@rafale77 I have a simple version almost ready. I'll debug later today or tomorrow, and put on GitHub. Here's an excerpt of the config:
{ "MQTT": { "Username": "vera", "Password": "openluup", "Port": 1883 }, "Devices": [ { "Name": "Pool", "ClientID": "sonoff-pool", "TopicName": "tele/tasmota/SENSOR", "TopicPath": "AM2301.Temperature", "DeviceID": 12, "Service": "urn:upnp-org:serviceId:TemperatureSensor1", "Variable": "CurrentTemperature" }, { "Name": "DeHumidifier", "ClientID": "tasmota-dehum", "TopicName": "stat/sonoff/POWER", "TopicValue": "ON", "DeviceID": 12, "Service": "urn:upnp-org:serviceId:HVAC_UserOperatingMode1", "Variable": "ModeTarget", "Value": "HeatOn" }, { "Name": "DeHumidifier", "ClientID": "tasmota-dehum", "TopicName": "stat/sonoff/POWER", "TopicValue": "OFF", "DeviceID": 12, "Service": "urn:upnp-org:serviceId:HVAC_UserOperatingMode1", "Variable": "ModeTarget", "Value": "Off" } ] }
I think it's more than enough to understand how the things will gonna work
-
@rafale77 hey Rafale,
I went down the very same road a while back and threw in towel because the polling by the MQTT plugin created CPU drags that stopped openLuup from functioning "reliably". The instability was also in part because I use two other must-have plugins that rely on polling, and I imagine that the combination of the three was creating a scenario that caused intermittent failures. And I too ended up implementing MQTT in Home Assistant and then using RealDB's virtual HTTP plugin to send commands to my WiFi devices--albeit not knowing the status of the devices in openLuup after the send.
I'm looking at RigPapa's socket proxy and WebSocket plugins to see if I can transform my polling plugins to Async. The MQTT plugin is too complex for me to convert though, so if you take a crack at it, and are successful, I would very much appreciate you publishing your results, as MQTT is becoming a must for me.
-
I was also thinking about using a proxy for this but it is really adding a layer of complication. For MQTT it might be work it though, I think @therealdb 's solution is likely a better approach... basically also kind of a proxy written in C to act as the client and seems to be very lightweight.
28/72