MQTT with 2 subscribes
-
Hi,
I'm new to micropython. I've taken several examples on this forum, assemble them and succeed to subscribe to 2 differents mqtt topics. But how can I put the differnts message in 2 variables like sensor21 and sensor31 ?from mqtt import MQTTClient import machine import time import pycom def sub_cb(topic, msg): print(msg) wlan = WLAN(mode=WLAN.STA) wlan.connect("wifi", auth=(WLAN.WPA2, "pass"), timeout=5000) while not wlan.isconnected(): machine.idle() print("Connected to Wifi\n") client = MQTTClient("device_id", "192.168.0.20",user="pi", password="raspberry", port=1883) client.set_callback(sub_cb) client.connect() wifiaddress = ((str(wlan.ifconfig()[:1]))[2:])[:-3] client.publish(topic="lopy/ip", msg=wifiaddress) client.subscribe(topic="pi/sensor21/temperature") client.subscribe(topic="pi/sensor31/temperature") def t3_publication(topic, msg): print (topic, ':', msg) #pycom.rgbled(0xff00) client.set_callback(t3_publication) while True: client.check_msg()
Thanks
-
@luc-hanneuse
first you can try to test if it is Noneif v==None:
and also you can test for type by:
type(v)
-
The "topic" and "message" variables are created by the mqtt library.
And yes, those variables don't react like string, byte,... most of the variables conversion don't work. That's why I called them "unknown".I've already print them, but that doesn't help to clarify the type of variable.
-
@luc-hanneuse said in MQTT with 2 subscribes:
unknown. Is it a string, a byte,... ?
unknown = None?
if yes than it mean no value at all.And before send put print command to see what you tried to send
print(str(val)) s.send(bytes(val))
and if you still have problem show what was printed
-
Finally some improvements, thanks for your help.
I succeed to subscribe to several topics and get some results.topic_sub=["pi/sensor21/temperature","pi/sensor40/temperature","pi/sensor02/temperature","pi/sensor12/in_01","pi/sensor12/out_01"] topic_length=len(topic_sub) val= [0,0,0,0,0] #should be a better way to create this array from topic_length update = None # used if you want to send a signal without waiting the 800s cycle for i in range(0, topic_length): client.subscribe(topic=topic_sub[i]) def mytopic(topic, msg): global update global topic_length global topic_sub global val if ubinascii.hexlify(topic) == ubinascii.hexlify(topic_sub[0]): val[0] = (msg[0]-48)*10+(msg[1]-48) #ascii-to-int, to be improved val[0] = val[0] % 255 #sure to be a byte if ubinascii.hexlify(topic) == ubinascii.hexlify(topic_sub[1]): val[1] = (msg[0]-48)*10+(msg[1]-48) #ascii-to-int, to be improved val[1] = val[1] % 255 #sure to be a byte if ubinascii.hexlify(topic) == ubinascii.hexlify(topic_sub[2]): val[2] = (msg[0]-48)*10+(msg[1]-48) #ascii-to-int, to be improved val[2] = val[2] % 255 #sure to be a byte if ubinascii.hexlify(topic) == ubinascii.hexlify(topic_sub[3]): val[3] = (msg[0]-48) #ascii-to-int, to be improved update = 1 if ubinascii.hexlify(topic) == ubinascii.hexlify(topic_sub[4]): val[4] = (msg[0]-48) #ascii-to-int, to be improved update = 1 client.set_callback(mytopic) chrono = Timer.Chrono() chrono.start() while True: client.check_msg() if chrono.read()%60 < 5 and blink == 0:#just a blinking pycom.rgbled(0x0064) blink = 1 print(".") if chrono.read()%60 > 5 and blink == 1:#just a blinking pycom.rgbled(0x0000) blink = 0 print("-") if chrono.read() > 800:#wait 800s to avoid the sigfox message limit per day pycom.rgbled(0x007f00) s.send(bytes(val)) print("Sigfox sent\n") chrono.reset() pycom.rgbled(0x0000) if update == 1:#send immediately if update is triger pycom.rgbled(0x007f00) s.send(bytes(val)) print("Sigfox sent\n") chrono.reset() update = 0 pycom.rgbled(0x0000)
But the exact nature of the result of topic and message are unknown. Is it a string, a byte,... ?
Most conversions don't works. I've tried float() or int() and get errorsI still have errors, certainly related to that problem :
And I've got the following message error whens.send(bytes(val)) #val is filled with the several message of the topics
The packet is correctly sent, but the program quit with the following error message OSError: [Errno 100] ENETDOWN
When I send the following code, I've no error
val = [1,2,3,4,5] s.send(bytes(val))
-
@luc-hanneuse said in MQTT with 2 subscribes:
How can I get those variable out of "def"?
msg_b= None msg_c= None def mytopic(topic, msg): global msg_b global msg_c ...
-
@livius said in MQTT with 2 subscribes:
you must put b and c outside of procedure
How can I get those variable out of "def"?
-
@luc-hanneuse said in MQTT with 2 subscribes:
For the previous code, the error is
NameError: local variable referenced before assignmentYou got this error because you do this
s.send(bytes([b,c]))
but in the code you have if variants and one of two "b" or "c" is unassigned
because you got 2 events - look how your code work by changing it to:def mytopic(topic, msg): print("---start---") print (topic, ':', msg)
is your output now like this?
"---start---" b'pi/sensor21/temperature' : b'21.00' "---start---" b'pi/sensor31/temperature' : b'25'
you must put b and c outside of procedure
and inside test if both "b" and "c" have values and only then send it
but this can also cause minssing values if you got only "b" and once again "b" and next "c"
PS> about simple conversion i am writing about string, if it is a bytes then
you must catch it e.g.v2=float(str(v))
but your way should work also byte-48{0ascii} *10...
-
It comes from different devices publishing each one their temperatures.
-
@luc-hanneuse Try to pack that two data (temperatures ) in to json format and publising after to MQTT broker
-
@livius
For the conversion, It doesn't work :v2=float(v)
I've got an error
can't convert bytes to floatv2=int(v)
I've got an error
ValueError: invalid syntax for integer with base 10For the previous code, the error is
NameError: local variable referenced before assignment
-
@luc-hanneuse
what is the error message?
and to convert from text to number simply dov2=float(v)
or if you need only integer part
v2=int(float(v))
-
I've tried this, but I got an error message.
one="pi/sensor21/temperature" two="pi/sensor31/temperature" client.subscribe(topic=one) client.subscribe(topic=two) def mytopic(topic, msg): print (topic, ':', msg) if topic == one: b = (msg[0]-48)*10+(msg[1]-48) if topic == two: c = (msg[0]-48)*10+(msg[1]-48) s.send(bytes([b,c])) #print("Sigfox sent\n")
-
@livius
So it subscribes correctly to the 2 topics. But I can't succeed in putting each message in a different variable.Here is my output :
b'pi/sensor21/temperature' : b'21.00'
b'pi/sensor31/temperature' : b'25'
-
@luc-hanneuse
what is your output from
print (topic, ':', msg)
?
-
@luc-hanneuse
anyone ?