如何在一个代码中设置多个MQTT回调并订阅多个主题?

时间:2019-01-29 10:43:37

标签: callback mqtt subscribe

我对MQTT相当陌生。我正在从事一个涉及Pycom董事会(Sipy)的项目。在面包板上,我有一个温度和一个重量传感器,正在读取这些值。将这些值与用户使用IOT平台(Adafruit IO)上的两个滑块控件选择的值进行比较。例如,如果用户选择的温度值高于传感器测量的温度值,则味精“更高的值”会打印在我的REPL控制台上,重量也是如此。为此,我编写了两个回调函数(分别名为sub_weight和sub_temp)。然后,我使用client.set_callback(sub_cb_weight)和client.set_callback(sub_cb_temp)。但是,在我看来,仅考虑写入的第二个回调,就好像按下了第一个一样。当我尝试同时订阅两个主题时,我遇到了同样的问题。然后我的问题是:是否可以订阅多个主题,还可以设置两个回调,以便我可以有两个答案?

from umqtt import MQTTClient 
import ubinascii 
import micropython 
from machine import Pin,ADC,I2C
import network
from network import WLAN
import onewire
from onewire import OneWire,Ds
AIO_SERVER = "io.adafruit.com"
AIO_PORT = 1883
AIO_USER = "username"
AIO_KEY = "key"
AIO_CLIENT_ID = ubinascii.hexlify(machine.unique_id())
client = MQTTClient(AIO_CLIENT_ID, AIO_SERVER, AIO_PORT, AIO_USER, AIO_KEY)

wlan=WLAN(mode=WLAN.STA)
pw='mypw'
nets=wlan.scan()
for net in nets:
    if net.ssid == 'myssid':
        wlan.connect(net.ssid,auth=(None,pw),timeout=5000)
        if wlan.isconnected() == True:
            print('Connected')
        else:
            print('Not connected')
client.connect()

AIO_WEIGHT_FEED = "username/feeds/weight"


def press_sensor():
    adc=machine.ADC()
    apin=adc.channel(pin='G5')
    p=(apin()*700/4095)
    return p

def sub_cb_weight(topic_full, pressed_full):
    print((topic_full, pressed_full))
    p=press_sensor()
    while True:
      if msg <= str(p).encode('ascii'):
          print('You chose a lower weight')
      else:
          print('You chose a higher one')
          time.sleep(3)

client.set_callback(sub_cb_weight)
client.subscribe(AIO_WEIGHT_FEED)
print("Connected to %s, subscribed to %s topic" % (AIO_SERVER, AIO_CONTROL_FEED_CALIB_FULL))

AIO_CONTROL_TEMP = "username/feeds/Temperature control"

def temp_sensor():
    ow = OneWire(Pin('P22',mode=Pin.IN,pull=Pin.PULL_UP))
    temp = Ds(ow)
    t=temp.read_temp()
    t=t/100
    t=int(t)
    return t

def sub_cb_temp(topic, msg): 
    print((topic, msg)) 
    v=temp_sensor()
    while True:
      if msg <= str(v).encode('ascii'):
          print('You chose a lower temperature')
      else:
          print('You chose a higher one')
          time.sleep(3)


client.set_callback(sub_cb_temp)
client.subscribe(AIO_CONTROL_TEMP)
print("Connected to %s, subscribed to %s topic" % (AIO_SERVER, AIO_CONTROL_TEMP))
while 1: 
     client.check_msg()

例如,在我下面所附的代码段中,我的设备将仅订阅温度馈送并打印链接到该值的消息。虽然可以很好地读取和比较传感器值。这是我正在使用的MQTT模块的链接:https://github.com/micropython/micropython-lib/blob/master/umqtt.simple/umqtt/simple.py。我可以正确连接到平台。 我不确定我现在是否很清楚,但是如果需要,我可以为您提供更多信息。 非常感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

此库使您可以设置一个回调来处理所有订阅的消息。您可以在回调中使用topic参数来确定如何处理消息。

例如注册单个回调,例如

def callback(topic, msg): 
    print((topic, msg))
    if topic == b"username/feeds/Temperature control":
        sub_cb_temp(topic, msg)
    else
        sub_cb_weight(topic, msg)

您当前的回调也不是多线程的,并进入忙碌的while循环。他们将仅处理收到的第一条消息(关于这些主题中的一个),并且不允许库发送发布确认。您将需要使用线程同时处理两个主题。