openLuup: Tasmota MQTT Bridge
-
ArcherSreplied to therealdb on May 14, 2021, 7:16 AM last edited by ArcherS May 14, 2021, 3:22 AM
@therealdb I also thought of using a dimmer or something similar.
When I press the remote and the IR reveiver in the Tasmota captures that I get an IrReceived message in the Console:
07:45:47 MQT: tele/TasmotaIR/RESULT = {"IrReceived":{"Protocol":"FUJITSU_AC","Bits":128,"Data":"0x0x1463001010FE0930400400000000206C","Repeat":0,"IRHVAC":{"Vendor":"FUJITSU_AC","Model":1,"Mode":"Heat","Power":"On","Celsius":"On","Temp":20,"FanSpeed":"Auto","SwingV":"Off","SwingH":"Off","Quiet":"Off","Turbo":"Off","Econo":"Off","Light":"Off","Filter":"Off","Clean":"Off","Beep":"Off","Sleep":-1}}}
It always contains the same elements as above, i.e. it reports all of the status fields every time.
So e.g. when changing the fan to "Min":
01:57:31 RSL: tele/tasmota_E0D649/RESULT = {"IrReceived":{"Protocol":"FUJITSU_AC","Bits":128,"Data":"0x0x1463001010FE09304004040000002068","Repeat":0,"IRHVAC":{"Vendor":"FUJITSU_AC","Model":1,"Mode":"Heat","Power":"On","Celsius":"On","Temp":20,"FanSpeed":"Min","SwingV":"Off","SwingH":"Off","Quiet":"On","Turbo":"Off","Econo":"Off","Light":"Off","Filter":"Off","Clean":"Off","Beep":"Off","Sleep":-1}}} IRVAC{"Vendor":"FUJITSU_AC","Model":1,"Mode":"Heat","Power":"On","Celsius":"On","Temp":20,"FanSpeed":"Min","SwingV":"Off","SwingH":"Off","Quiet":"On","Turbo":"Off","Econo":"Off","Light":"Off","Filter":"Off","Clean":"Off","Beep":"Off","Sleep":-1}
The FanSpeed values are:
"FanSpeed":"Min"
"FanSpeed":"Low"
"FanSpeed":"Medium"
"FanSpeed":"Max"
"FanSpeed":"Auto"When powered on:
01:55:23 RSL: tele/tasmota_E0D649/RESULT = {"IrReceived":{"Protocol":"FUJITSU_AC","Bits":128,"Data":"0x0x1463001010FE0930410400000000206B","Repeat":0,"IRHVAC":{"Vendor":"FUJITSU_AC","Model":1,"Mode":"Heat","Power":"On","Celsius":"On","Temp":20,"FanSpeed":"Auto","SwingV":"Off","SwingH":"Off","Quiet":"Off","Turbo":"Off","Econo":"Off","Light":"Off","Filter":"Off","Clean":"Off","Beep":"Off","Sleep":-1}}}
When powered off:
00:26:45 RSL: tele/tasmota_E0D649/RESULT = {"IrReceived":{"Protocol":"FUJITSU_AC","Bits":56,"Data":"0x0x146300101002FD","Repeat":0,"IRHVAC":{"Vendor":"FUJITSU_AC","Model":1,"Mode":"Off","Power":"Off","Celsius":"On","Temp":16,"FanSpeed":"Auto","SwingV":"Off","SwingH":"Off","Quiet":"Off","Turbo":"Off","Econo":"Off","Light":"Off","Filter":"Off","Clean":"Off","Beep":"Off","Sleep":-1}}}
For some reason it also sends "Mode":"Off" when powered off and not only "Power":"Off"
When changing mode you get for the four modes:
"Mode":"Heat"
"Mode":"Cool"
"Mode":"Dry"
"Mode":"Auto"When I have looked in the Tasmota IR wiki there is some info on this also.
Both the IrReceived and IRhvac send protocols seem quite generic in terms of the mode, fan speed etc. -
therealdbreplied to ArcherS on May 15, 2021, 11:05 AM last edited by therealdb May 15, 2021, 7:05 AM
@archers ok, new build is on GitHub.
if you want to match for tele/tasmota_E0D649/RESULT topic with a message that contains IrReceived.IRHVAC.Power and a value of Off (case sensitive) use
tele/tasmota_E0D649/RESULT/=/IrReceived.IRHVAC.Power/=/Off
As you can see, we could also match a path and get its value:
tele/tasmota_E0D649/RESULT/=/IrReceived.IRHVAC.Temp/=/*
I've also added the ability to get the current temperature via MQTT as well. I'll update the docs later, with the new formats.
-
ArcherSreplied to therealdb on May 15, 2021, 7:17 PM last edited by ArcherS May 15, 2021, 6:02 PM
@therealdb said in openLuup: Tasmota MQTT Bridge:
if you want to match for tele/tasmota_E0D649/RESULT topic with a message that contains IrReceived.IRHVAC.Power and a value of Off (case sensitive) use
Should it be mqtt://tele/tasmota_E0D649/RESULT/=/IrReceived.IRHVAC.Power/=/Off etc?
I tried both with and without "mqtt://" but I cannot see any changes on the varibles of the device.
Checked the log and it says beta 4 so it should be installed properly.Edit: problem solved, see below.
The variables I have for the device are as below, there could very well be something wrong with them; I have not yet got full controll of the settings for heater device. -
ArcherSreplied to ArcherS on May 15, 2021, 10:00 PM last edited by ArcherS May 15, 2021, 6:27 PM
@therealdb now it works!
I managed to find what I think was the error. I somehow some time ago have managed to copy all the VirtualDevices files into a sub-folder in the cmh-ludl folder. Stupid error my my side that gave a lot of strange behaviour...
I simply removed the sub-folder and reloaded the master branch from the "plugins" tab in AltUi and then it worked as it should.In other words it should be mqtt://tele/tasmota_E0D649/RESULT/=/IrReceived.IRHVAC.Power/=/Off etc i.e. with the mqtt:// prefix.
Thanks for a great addition to the plugin, I will play some more with this one and see that it works as supposed.
Edit: I discovered that the changing the temp on the OpenLuup device via "SetSetpointURL" does only work when the "ModeState" is "Heating".
It seems as if "ModeState" reverts to "Idle" and then changing the temperature from the OpenLuup device with the "SetSetpointURL" does not work. Is this something that can be changed? -
@archers said in openLuup: Tasmota MQTT Bridge:
In other words it should be mqtt://tele/tasmota_E0D649/RESULT/=/IrReceived.IRHVAC.Power/=/Off etc i.e. with the mqtt:// prefix.
No need to use the prefix for the incoming messages, but it should discard it anyway.
I’ll take a look at setpoint, but I fear it’s not updating it because of the way heaters are coded. Maybe a thermostat in your case could be better, but it’ll need more work on my part.
-
@therealdb you are of course correct, I tested and it works both with and without the mqtt:// prefix for the incoming messages.
I changed the "CurrentTemperature" to a value that always will be lower than the setpoints ( in my case 10 degrees), by doing this the "ModeState" stays at "Heating" which means that the changing the temperature from the OpenLuup device works. Quite obvious of course when you think of it.
All in all it works as it should, thanks for the hard work!
-
@archers great!
I’m thinking of creating a cooler device, because I need it myself. It’s really stupid imho that they created heaters, complex thermostats, but no humidifier, dehumidifier or cooler device. But since we’re not tied to Vera anymore, I guess it’s time to add them, as I did with my own virtual alarm/alarm partition.
-
@akbooer I think I found the culprit causing the random connection disconnects to Mosquitto. The LWT payload for a given device is a simple string, which doesn't seem to decode in the json decode call. So I added the below code to send a json string to the decoder. The errors have disappeared and I now see the LWT variable in the service variables. The variable reads "LWT : Online"
--line 165 local valid = {SENSOR = true, STATE = true, RESULT = true, LWT = true}
--line 172 -- begin code local info, err = json.decode (message) if message then if not info then -- json did not decode because of single string parameter message = '{' .. '"' .. mtype .. '"' .. ':' .. '"' .. message .. '"' .. '}' end end -- end code local info, err = json.decode (message)
This is probably not the way you would handle the error, but it does work.
-
akbooerreplied to Buxton on Jun 8, 2021, 11:00 AM last edited by akbooer Jun 8, 2021, 7:00 AM
Great work!
There may be some compatibility problem betwen JSON decoders – which one are you using (openLuup / Cjson / RapidJson) ? The beginning of the Startup Log should tell you...
2021-06-06 20:08:48.470 openLuup.json:: version RapidJSON (0.6.1) + openLuup (2021.05.01) @akbooer
-
Should now be fixed in development v21.6.8.
My implementation, FYI:
local tasmota, mtype = tasmotas: match "^(.-)/(%u+)" local valid do -- thanks @Buxton for LWT as text message local j, t = "json", "text" valid = {SENSOR = j, STATE = j, RESULT = j, LWT = t} end local decoder = valid[mtype] if not (tasmota and decoder) then _log (table.concat ({"Topic ignored", topic, message}, " : ")) return end local info, err if decoder == "text" then info = {[mtype] = message} else info, err = json.decode (message) if not info then _log ("JSON error: " .. (err or '?')) _log ("Received message ignored: " .. message) return end end
-
@akbooer Yes, that should work. However, the LWT MQTT specification calls for a standard message, so a tasmota upgrade could change the text message to a json message. Is there a way to test the message for a non-json string, and then filter accordingly. I fear the hardcoded flags will inevitably break....
-
Yes, I thought of doing it that way. A simple check for a leading [ or { should be adequate.
This is the one thing I don’t like about Tasmota (as mentioned a while ago) … no real standards.
-
OK, so here's what it will be now, a hybrid of our approaches...
local valid = {SENSOR = 1, STATE = 1, RESULT = 1, LWT = 1} -- thanks @Buxton for LWT as text message if not (tasmota and valid[mtype]) then _log (table.concat ({"Topic ignored", topic, message}, " : ")) return end local info = json.decode (message) or {[mtype] = message} -- treat invalid JSON as plain text
-
@akbooer Can I ask you for one more addition. I'd like to be able to set tasmota prefixes and suffixes via lua startup. Something like:
attr ("openLuup.Tasmota.Prefix", "tele", "tasmota/tele","stat") attr ("openLuup.Tasmota.Topic", "SENSOR", "STATE","RESULT", "LWT")
You'd also need to change the upper case error check on the topic as some of the full topic suffixes are not all in upper case:
local tasmota, mtype = tasmotas: match "^(.-)/(.+)"
-
@buxton said in openLuup: Tasmota MQTT Bridge:
I'd like to be able to set tasmota prefixes and suffixes via lua startup.
Try the latest development version (21.6.12b)
A tiny syntax difference from your suggestion, you need to write...
attr ("openLuup.Tasmota.Prefix", {"tele", "tasmota/tele", "stat"}) attr ("openLuup.Tasmota.Topic", {"SENSOR", "STATE", "RESULT", "LWT"})
-
@akbooer After updating to the lastest development version (21.6.12b), I did a direct copy and paste of the above attr code into startup lua, and it appears that openLuup hangs on the ipairs iteration, because the ipairs statement is seeing a string instead of a table. I was then able to boot openLuup by removing the "or" clause :
--local prefixes = config.Prefix or {"tele", "tasmota/tele"} -- subscribed Tasmota prefixes local prefixes = {"tele", "tasmota/tele"} -- subscribed Tasmota prefixes for _, prefix in ipairs (prefixes) do luup.register_handler ("Tasmota_MQTT_Handler", "mqtt:" .. prefix .. "/#", prefix) -- * * * MQTT wildcard subscription * * * end
The topic table has the same problem.
I was able to see the error message when using "./openLuup_reload" at the linux command prompt.
-
Oh yes, that's the traditional Vera-compliant Luup API for you, which only allows string attributes.
TBH, I don't use that much these days. Sorry about that.Two ways forward:
- This will work right now:
local oL = luup.attr_get "openLuup" oL.Tasmota = { Prefix = {"tele", "tasmota/tele", "stat"}, Topic = {"SENSOR", "STATE", "RESULT", "LWT"}}
- I could change the Tasmota code to accept:
attr ("openLuup.Tasmota.Prefix", "tele, tasmota/tele, stat") attr ("openLuup.Tasmota.Topic", "SENSOR, STATE, RESULT, LWT")
which might be better in the long run.