Berry: mqtt.publish() %topic% ?

531 views
Skip to first unread message

Andrew Russell

unread,
Mar 27, 2024, 1:05:19 PM3/27/24
to TasmotaUsers
Hi Chaps,

I have written a driver in Berry. It appears as a sensor and watches the state of a few GPIOs.
I want to mqtt.publish('tele/%topic%/SENSOR', data) when the GPIOs change state and a very particular debounce has completed. This is working fine with a hard-coded %topic%.

Problem: I don't know where to find my name/topic so that I don't have to hard-code it.
Any ideas?

More background:
I am using json_append(), so the data is successfully published on tele-period, but I also need to publish it in real time when the state changes.
If there is a way to force an instant tele/xxx/SENSOR message, that would also work for me, as the message has the correct info in it.

Many thanks
Andrew

Justin Adie

unread,
Mar 27, 2024, 1:18:39 PM3/27/24
to TasmotaUsers

var data = "some data that you have"
var fulltopic = string.format("tele/%s/SENSOR", tasmota.cmnd("topic"))
tasmota.publish(fulltopic, data)

Justin Adie

unread,
Mar 29, 2024, 8:00:33 AM3/29/24
to Andrew Russell, TasmotaUsers
Aha!  The danger of typing responses without checking them!  

On Wed, 27 Mar 2024, 17:58 Andrew Russell, <andre...@gmail.com> wrote:
Indeed. And tasmota.cmd("topic") returns {"Topic":"myTopic"}.
But you got me on the right track - I can fix it from here.
Thanks again!


On Wed, 27 Mar 2024 at 17:54, Justin Adie <justi...@adieandco.com> wrote:
Actually I think it is tasmota.cmd.  No (n).

Also I read that tasmota.publish is deprecated in favour of mqtt.publish. 



On Wed, 27 Mar 2024, 17:42 Andrew Russell, <andre...@gmail.com> wrote:
Brilliant - thanks!

--
You received this message because you are subscribed to the Google Groups "TasmotaUsers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sonoffusers...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/sonoffusers/b539405d-cc94-4f67-ab7f-d0435c45c043n%40googlegroups.com.

Justin Adie

unread,
Mar 29, 2024, 8:00:34 AM3/29/24
to Andrew Russell, TasmotaUsers
Actually I think it is tasmota.cmd.  No (n).

Also I read that tasmota.publish is deprecated in favour of mqtt.publish. 



On Wed, 27 Mar 2024, 17:42 Andrew Russell, <andre...@gmail.com> wrote:
Brilliant - thanks!

On Wed, 27 Mar 2024 at 17:18, 'Justin Adie' via TasmotaUsers <sonof...@googlegroups.com> wrote:

Andrew Russell

unread,
Mar 29, 2024, 8:00:34 AM3/29/24
to Justin Adie, TasmotaUsers
Hi Justin, Slight problem. Any thoughts?

var topic = string.format('tele/%s/SENSOR', tasmota.cmd('topic', true)['Topic'])
mqtt.publish(topic, payload)

This does what I want, but kicks out a log and mqtt message when tasmota.cmd() is executed --> stat/myTopic/RESULT {"Topic":"myTopic"}.
Docs suggest that the 'true' param to tasmota.cmd() should suppress this.
Do I have the syntax correct?
Not a big problem, as I can work around it by doing a one-time execution at boot time.

Andrew Russell

unread,
Mar 29, 2024, 8:00:35 AM3/29/24
to Justin Adie, TasmotaUsers
Indeed. And tasmota.cmd("topic") returns {"Topic":"myTopic"}.
But you got me on the right track - I can fix it from here.
Thanks again!


On Wed, 27 Mar 2024 at 17:54, Justin Adie <justi...@adieandco.com> wrote:

Andrew Russell

unread,
Mar 29, 2024, 8:00:35 AM3/29/24
to Justin Adie, TasmotaUsers
Brilliant - thanks!

On Wed, 27 Mar 2024 at 17:18, 'Justin Adie' via TasmotaUsers <sonof...@googlegroups.com> wrote:

Justin Adie

unread,
Mar 29, 2024, 8:00:52 AM3/29/24
to Andrew Russell, SonoffUsers
Adding a few bits as I forgot you wanted it to emulate a sensor

class MySensorPublisher
var topic
var data
var debug
def init()
import string
import gpio

# from Berry Cookbook
self.topic = string.replace(string.replace(tasmota.cmd('FullTopic',true)['FullTopic'],'%topic%', tasmota.cmd('Topic',true)['Topic']),'%prefix%', tasmota.cmd('Prefix',true)['Prefix3'])+ 'SENSOR'
# create list of pins to be monitored
var gpios = [10,12] 
self.data = map()
for pin:gpios
self.data.insert(pin, gpio.digital_read(pin))
end
self.debug = true
end
# change this if you want a slower update 
def every_second()
self.checkGpios()
end
def checkGpios()
import gpio
var state = false
var needToPublish = false
for pin:self.data.keys()
state = gpio.digital_read(pin)
if self.data.item(pin) != state || self.debug
needToPublish = true
self.data.setitem(pin, state);
end
end 
if needToPublish
needToPublish = false
self.publishSensorData()
end
end
def publishSensorData()
import mqtt
import json
if !self.debug 
mqtt.publish(self.topic, json.dump(self.data))
else
print(json.dump(self.data))
end
end
def web_sensor()
import string
var text = ""
for pin:self.data.keys()
text = text + string.format("{s}GPIO%s{m}%s{e}", pin, self.data[pin] == 1 ? "HIGH" : "LOW")
end
tasmota.web_send(text)
end
def json_append()
import json
var msg = "\"GPIOSensor\":" + json.dump(self.data)
tasmota.response_append(msg)
end
end

var mySensorPublisher =  MySensorPublisher()
tasmota.add_driver(mySensorPublisher)




On 28 Mar 2024, at 12:23, Justin Adie <justi...@adieandco.com> wrote:

Hi Andrew

That’s odd - I’ve just done some testing on one of my esp32 boards.  Using 13.1.0.

With the true argument I get no output to the log or mqtt.  Without the arg I get the log.  i.e. expected behaviour.  I tried again with 13.4.0 and got the same, expected, behaviour.


However there is somewhat of a workaround by storing the topic in a variable at boot time and encapsulating the publishing as a command (or in a function anyway).  This way, even if it does spit out a log entry it is only once in the lifecycle.  Here’s the code I’ve been testing with (trying to emulate your gpio monitoring aim)

class MySensorPublisher
var topic
var data
var debug
def init()
import string
import gpio
self.topic = string.format("tele/%s/SENSOR", tasmota.cmd("topic", true)["Topic"])
# create list of pins to be monitored
var gpios = [10,12] 
self.data = map()
for pin:gpios
self.data.insert(pin, gpio.digital_read(pin))
end
self.debug = true
end
# change this if you want a slower update 
def every_second()
self.checkGpios()
end
def checkGpios()
import gpio
var state = false
var needToPublish = false
for pin:self.data.keys()
state = gpio.digital_read(pin)
if self.data.item(pin) != state || self.debug
needToPublish = true
self.data.setitem(pin, state);
end
end 
if needToPublish
needToPublish = false
self.publishSensorData()
end
end
def publishSensorData()
import mqtt
import json
if !self.debug 
mqtt.publish(self.topic, json.dump(self.data))
else
print(json.dump(self.data))
end
end
end

var mySensorPublisher =  MySensorPublisher()
tasmota.add_driver(mySensorPublisher)

Justin Adie

unread,
Mar 29, 2024, 8:00:52 AM3/29/24
to Andrew Russell, SonoffUsers
Confirmed I’m not getting any publication of the topic data when placing the self.topic = … line in the publishSensorData() method.  Perhaps you have something that is overriding the mqttlog level?  

Hopefully obv change the debug argument to false to publish to mqtt instead of the console.  

Not sure how familiar you are with Berry but if you want a faster update to gpio changes then you’ll need every_100s() instead of every_second()

atb
Justin




On 28 Mar 2024, at 13:34, Andrew Russell <andre...@gmail.com> wrote:

Hi Justin,

Well, that's investigation beyond my expectation!

This is now academic, because I am very happy to do the tasmota.cmd('topic', true) in init().
Could you just check the true/false behaviour if you add tasmota.cmd('topic', true) to the publishSensorData() function, please?
I don't see a publish with true or false from tasmota.cmd() in init(), probably because mqtt is not up at this point.
But I do see a publish if I put it in the publishSensorData(), run every second.



Andrew Russell

unread,
Mar 29, 2024, 8:00:52 AM3/29/24
to Justin Adie, SonoffUsers

Justin Adie

unread,
Mar 29, 2024, 8:00:52 AM3/29/24
to Andrew Russell, SonoffUsers

Andrew Russell

unread,
Mar 29, 2024, 8:01:01 AM3/29/24
to Justin Adie, SonoffUsers
>>  Perhaps you have something that is overriding the mqttlog level?
Yes, I was wondering about that. I'll let you know if I find it.

>> Not sure how familiar you are with Berry.
Pretty familiar. My Berry sensor code has been running for almost 2 years.
I recently needed to change the mqtt message it was generating from a RESULT to a SENSOR, which meant I had to change from tasmota.publish_result() which embeds the topic, to mqtt.publish() for which I need to provide the topic.
No matter how much I read the docs, I could not work out how to do it.
So, many thanks for pointing me at tasmota.cmd('topic') - that's the trick that I needed.

All the best
Andrew



Reply all
Reply to author
Forward
0 new messages