I'm trying to subscribe to a MQTT topic ("arqueta/humedad") and asign his value to an object of logic machine.
I'm using de test Mosquitto broker and I publish previously a value to the topic "arqueta/humedad".
I'm using this code (extracted from here) as a resident script but It seems doesn't works and I don't know what I'm doing wrong...
Code:
-- Define a function which is called by mqtt_client:handler(),
-- whenever messages are received on the subscribed topics
function callback(topic, message)
print("Received: " .. topic .. ": " .. message)
if (message == "quit") then running = false end
end
-- Create an MQTT client instance, connect to the MQTT server and
-- subscribe to the topic called "arqueta/humedad"
MQTT = require("mosquitto")
MQTT.Utility.set_debug(true)
mqtt_client = MQTT.client.create("https://test.mosquitto.org", 1883, callback)
mqtt_client:connect("logicmachine")
local humedad = mqtt_client:subscribe("arqueta/humedad")
grp.update('1/1/27', humedad)
-- Continously invoke mqtt_client:handler() to process the MQTT protocol and
-- handle any received messages. Also, publish a message on topic "test/1"
running = true
while (running) do
mqtt_client:handler()
mqtt_client:publish("test/1", "test message")
socket.sleep(1.0) -- seconds
end
-- Clean-up by unsubscribing from the topic and closing the MQTT connection
mqtt_client:unsubscribe({"arqueta/humedad"})
mqtt_client:destroy()
Upgrade firmware to 2018 RC1. It has built-in MQTT library support and some other features required for this script.
Create resident script with 0 sleep interval. Change broker IP address and mapping tables as needed. mqtt_to_object maps topic to a group address, object_to_mqtt maps group address to atopic.
Do full script restart via disable/enable when changing any mapping tables and/or broker address.
Code:
if not broker then
broker = '192.168.1.101'
function multiply(mult)
return function(value)
local num = tonumber(value)
if num then
return num * mult
else
return value
end
end
end
-- topic to object map
mqtt_to_object = {
['in/topic1'] = '32/1/1',
['in/topic2'] = '32/1/2',
}
-- optional topic value conversion function
mqtt_to_object_conv = {
['in/topic1'] = multiply(100),
['in/topic2'] = multiply(0.01),
}
-- object to topic map
object_to_mqtt = {
['1/1/1'] = 'out/topic1',
['1/1/2'] = 'out/topic2',
}
datatypes = {}
grp.sender = 'mq'
require('socket')
for addr, _ in pairs(object_to_mqtt) do
local obj = grp.find(addr)
if obj then
datatypes[ addr ] = obj.datatype
end
end
mclient = require('mosquitto').new()
mclient.ON_CONNECT = function(res, ...)
log('mqtt connect status', res, ...)
if res then
for topic, _ in pairs(mqtt_to_object) do
mclient:subscribe(topic)
end
else
mclient:disconnect()
end
end
mclient.ON_MESSAGE = function(mid, topic, payload)
local addr = mqtt_to_object[ topic ]
if addr then
local fn = mqtt_to_object_conv[ topic ]
if fn then
payload = fn(payload)
end
grp.write(addr, payload)
end
end
mclient.ON_DISCONNECT = function(...)
log('mqtt disconnect', ...)
mclientfd = nil
end
function mconnect()
local fd
mclient:connect(broker)
fd = mclient:socket()
-- fd ref is valid
if fd then
mclientfd = fd
end
end
mconnect()
function publishvalue(event)
-- message from us or client is not connected
if event.sender == 'mq' or not mclientfd then
return
end
local addr = event.dst
local dpt = datatypes[ addr ]
local topic = object_to_mqtt[ addr ]
-- unknown object
if not dpt or not topic then
return
end
local value = busdatatype.decode(event.datahex, dpt)
if value ~= nil then
if type(value) == 'boolean' then
value = value and 1 or 0
end
mclient:publish(topic, tostring(value))
end
end
lbclient = require('localbus').new(1)
lbclient:sethandler('groupwrite', publishvalue)
lbclientfd = socket.fdmaskset(lbclient:getfd(), 'r')
-- run timer every 5 seconds
timer = require('timerfd').new(5)
timerfd = socket.fdmaskset(timer:getfd(), 'r')
end
-- mqtt connected
if mclientfd then
mclientfdset = socket.fdmaskset(mclientfd, mclient:want_write() and 'rw' or 'r')
res, lbclientstat, timerstat, mclientstat =
socket.selectfds(10, lbclientfd, timerfd, mclientfdset)
-- mqtt not connected
else
res, lbclientstat, timerstat =
socket.selectfds(10, lbclientfd, timerfd)
end
if mclientfd and mclientstat then
if socket.fdmaskread(mclientstat) then
mclient:loop_read()
end
if socket.fdmaskwrite(mclientstat) then
mclient:loop_write()
end
end
if lbclientstat then
lbclient:step()
end
if timerstat then
-- clear armed timer
timer:read()
if mclientfd then
mclient:loop_misc()
else
mconnect()
end
end
03.12.2018, 10:18 (This post was last modified: 03.12.2018, 10:57 by pentadom.)
(03.12.2018, 08:43)admin Wrote: Upgrade firmware to 2018 RC1. It has built-in MQTT library support and some other features required for this script.
Create resident script with 0 sleep interval. Change broker IP address and mapping tables as needed. mqtt_to_object maps topic to a group address, object_to_mqtt maps group address to atopic.
Do full script restart via disable/enable when changing any mapping tables and/or broker address.
I'm trying to do this but it doesn't works. I supose that when I send a value to the broker, automatically the script must receive the value?
I've just upgrade the firmware. Here's the actual version:
Here's my code where I put the mosquitto test broker and the topic "arqueta/humedad" I'm testing. the object 32/1/1 is a "05. 1 byte unsigned integer".
As I say, it doesn't works and I don't know what I'm doing wroing.
The correct line to broker is without "http://"
I have problem with object_to_mqtt this topic will change on MQTT when I write new value? Is it necessary event script? Now I don't see change this value on client.
No event script is needed. Value is published to selected topic when value changes. Have you checked that MQTT client is connected? Does the reverse (mqtt_to_object) work? Does the client have access to the select topic?
You can log the publish result like this (line 83):
Code:
local r, e, c = mclient:publish(topic, tostring(value))
log('publish', r, e, c)
mclient.ON_CONNECT = function(res, ...)
log('mqtt connect status', res, ...)
if res then
mclient:subscribe('100')
else
mclient:disconnect()
end
end
mclient.ON_MESSAGE = function(mid, topic, payload)
if topic == '100' then
if payload == "C,1,1,\r\n" then
grp.write('0/0/1', true)
elseif payload == "C,1,0,\r\n" then
grp.write('0/0/1', false)
elseif payload == "C,2,1,\r\n" then
grp.write('0/0/2', true)
elseif payload == "C,2,0,\r\n" then
grp.write('0/0/2', false)
end
end
end
Using one topic for controlling multiple entities is bad system design. Each relay should have it's own topic for control if possible.
Hi,
please elaborate this custom Logic in Mqtt callbacks where we can i find
actually am adding this logic in main residence script please find it in attached file(how we have done)
am doing it in correct way...?
Check the latest log entry, it shows what data was published to the topic named "100". Modify the ON_MESSAGE callback function to execute actions based on the received payload:
Code:
mclient.ON_MESSAGE = function(mid, topic, payload)
log('ON_MESSAGE ', topic, payload)
if topic == '100' then
if payload == "11" then
grp.write('0/0/1', true)
elseif payload == "10" then
grp.write('0/0/1', false)
end
end
end
You can use MQTT explorer (http://mqtt-explorer.com/) to connect to LM and send any data to any topics to test your scripts.
Hi,
in this case the publishing topic=100, and Payload=C,1,1,1,\r\n like this format while subscribing topic=100 and msg Payload=$FD;2;4;0;0;0;0;0;0;@ while watching from LM log we found this.
(26.02.2021, 11:59)admin Wrote: Modify the example in my previous post and implement your custom actions based on the received payload value.
Hi,
modification according to the log it is working fine... for Boolean objects but when it comes to light Dimming and Fan regulator the commands are different for each value can you please update that conversation according to the following parameters..
group address to Mqttpublish)
fan speed1_very low----->C,5,1,\r\n
fanspped-low ------>C,5,2,\r\n
fanspeed_medium ------>C,5,3,\r\n
fanspeed_High ----->C,5,4,\r\n
fan_off ----->C,5,0\r\n
mqtt to group addressSubscribe) fan speed1_very low----->C,5,1 fanspped-low ------>C,5,2 fanspeed_medium ------>C,5,3 fanspeed_High ----->C,5,4 fan_off ----->C,5,0
I use the thread to ask:
I need to introduce MQTT actuators of damphos in many rooms. How can I scan the broker for devices and automatically create objects with their names? For example, my punishments will have a topic:
Danfos /room_001...
Danfos /room_200....
How to get the names directly from the broker and create the objects I need - I will need several objects with different types of variables?