从云接收MQTT数据时延迟

时间:2017-08-28 10:13:44

标签: python arduino mqtt raspberry-pi3 paho

我有一个带有传感器和一个执行器的Arduino板。它通过USB线连接到Raspberry Pi。

这个想法是,通常Arduino将在Serial上打印数据。这是由Raspberry Pi在这个Python脚本的帮助下检索的。如果在云端遇到任何事件,或者如果我单击云上的按钮,则应该触发Arduino端的执行器。

我有以下MQTT客户端代码。

#!/usr/bin/env python
import logging
import time
import json
import serial
import paho.mqtt.client as mqtt
MQTT_BROKER = "things.ubidots.com"
MQTT_PORT = 1883  # Default MQTT Port is 1883
MQTT_KEEPALIVE_INTERVAL = 45  # In seconds
MQTT_USER_NAME = "Broker_User_Name"
MQTT_USER_PASSWORD = "Broker_User_Password"
PUB_TOPIC1 = "/v1.6/devices/mqtt/temperature"
SUB_TOPIC1 = "/v1.6/devices/mqtt/temperature"
PUB_TOPIC2 = "/v1.6/devices/mqtt/humidity"
SUB_TOPIC2 = "/v1.6/devices/mqtt/humidity"
PUB_TOPIC3 = "/v1.6/devices/mqtt/luminance"
SUB_TOPIC3 = "/v1.6/devices/mqtt/luminance"
PUB_TOPIC4 = "/v1.6/devices/mqtt/ADC"
SUB_TOPIC4 = "/v1.6/devices/mqtt/ADC"
PUB_TOPIC5 = "/v1.6/devices/mqtt/Battery_Status"
SUB_TOPIC5 = "/v1.6/devices/mqtt/Battery_Status"
Quqlity_of_Service = 0

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)                                                                               
handler = logging.FileHandler('MQTT_log_file.log')  # create a file handler
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') # create a logging format
handler.setFormatter(formatter)
logger.addHandler(handler)# add the handlers to the logger
logger.info("")
logger.info("######## Program started ########")

MQTT_MSG1 = 0
MQTT_MSG2 = 0
MQTT_MSG3 = 0
MQTT_MSG4 = 0
MQTT_MSG5 = 0
msg_body = ""
rc = 0  # For error checking

time.sleep(0.3)
pub_sub_option = int(raw_input("Do you want to be:\n 1.Publisher\n 2.Subscriber\n 3.Both\n :"))
logger.info("\nPublisher and Subscriber Option: {}".format(pub_sub_option))
if pub_sub_option == 1:
    print("")
    print("You have selected only Publisher")
    print("")
elif pub_sub_option == 2:
    print("")
    print("You have selected only Subscriber")
    print("")
elif pub_sub_option == 3:
    print("")
    print("You have selected both Publisher and Subscriber")
    print("")
else:
    print("")
    print("Please select the correct option.")
    print("")

if pub_sub_option == 1:
    publisher_check = 1
    subscriber_check = 0
elif pub_sub_option == 2:
    publisher_check = 0
    subscriber_check = 1
elif pub_sub_option == 3:
    publisher_check = 1
    subscriber_check = 1

serial_data = serial.Serial(port='/dev/ttyACM0', baudrate=115200) # Read the Sensor Data
logger.debug("Serial Data: {}".format(serial_data))

#  ----# Json Data Converter Function #----
def json_data_publish(PUB_TOPIC, sensor_variable, Quqlity_of_Service):
    message = {'value': sensor_variable}
    logger.debug("Json Data Publisher Value: {}".format(message))
    mqttc.publish(PUB_TOPIC, json.dumps(message), Quqlity_of_Service)

def connack_string(connack_code):
    """Return the string associated with a CONNACK result"""
    if connack_code == 0:
        return "Connection Accepted."
    elif connack_code == 1:
        return "Connection Refused: unacceptable protocol version."
    elif connack_code == 2:
        return "Connection Refused: identifier rejected."
    elif connack_code == 3:
        return "Connection Refused: broker unavailable."
    elif connack_code == 4:
        return "Connection Refused: bad user name or password."
    elif connack_code == 5:
        return "Connection Refused: not authorised."
    else:
        return "Connection Refused: unknown reason."

# Define on_connect event Handler
def on_connect(client, userdata, flags, rc):
    logger.debug(connack_string(int(rc)))
    print(connack_string(int(rc)))

# Define on_message event Handler for Topic 1
def on_message(client, userdata, msg):
    logger.debug("Control is in On_Message")
    received_topic = str(msg.topic)
    received_message = str(msg.payload.decode())

    if received_topic != "" and received_message != "":
        if received_topic == SUB_TOPIC1:
            received_temp_data = int(received_message)
            print("The Received Temperature Data is: {}\n".format(received_temp_data))
            logger.debug("The Received Temperature Data is: {}".format(received_temp_data))

        elif received_topic == SUB_TOPIC2:
            received_humid_data = int(received_message)
            print("The Received Humidity Data is: {}\n".format(received_humid_data))
            logger.debug("The Received Humidity Data is: {}".format(received_humid_data))

# Define on_publish event Handler
def on_publish(client, userdata, mid):
    pass

# Initiate MQTT Client
mqttc = mqtt.Client()
logger.debug("MQTT Client is Initialized")

# Connect with MQTT Broker
mqttc.username_pw_set(MQTT_USER_NAME, MQTT_USER_PASSWORD)
mqttc.connect(MQTT_BROKER, MQTT_PORT, MQTT_KEEPALIVE_INTERVAL)
logger.debug("Connected to MQTT Broker")

# Register Event Handlers
mqttc.on_connect = on_connect
logger.debug("Control is in On_Connect Event Handler")
mqttc.on_message = on_message
logger.debug("Control is in On_Message Event Handler")

# subscribe for topic
if subscriber_check == 1:
    mqttc.subscribe(SUB_TOPIC1, Quqlity_of_Service)
    mqttc.subscribe(SUB_TOPIC2, Quqlity_of_Service)
    mqttc.subscribe(SUB_TOPIC3, Quqlity_of_Service)
    mqttc.subscribe(SUB_TOPIC4, Quqlity_of_Service)
    mqttc.subscribe(SUB_TOPIC5, Quqlity_of_Service)

while rc == 0:
    try:
        rc = mqttc.loop()
        if publisher_check == 1:
#    ----  # Data from Real Sensors #----
            data = serial_data.readline(20)
            pieces = data.split(":")
            if pieces[0] == "Temperature":
                MQTT_MSG1 = pieces[1]
            if pieces[0] == "Humidity":
                MQTT_MSG2 = pieces[1]
            if pieces[0] == "Luminance":
                MQTT_MSG3 = pieces[1]
            if pieces[0] == "ADC":
                MQTT_MSG4 = pieces[1]
            if pieces[0] == "Battery_Status":
                MQTT_MSG5 = pieces[1]
            logger.debug("Json Enabled")
            json_data_publish(PUB_TOPIC1, MQTT_MSG1, Quqlity_of_Service)
            print("Temperature {} Published\n".format(MQTT_MSG1))
            logger.debug("Temperature {} Published with QOS = {}".format(MQTT_MSG1, Quqlity_of_Service))
            time.sleep(1)
            json_data_publish(PUB_TOPIC2, MQTT_MSG2, Quqlity_of_Service)
            print("Humidity {} Published\n".format(MQTT_MSG2))
            logger.debug("Humidity {} Published with QOS = {}".format(MQTT_MSG2, Quqlity_of_Service))
            time.sleep(1)
            json_data_publish(PUB_TOPIC3, MQTT_MSG3, Quqlity_of_Service)
            print("Luminance {} Published\n".format(MQTT_MSG3))
            logger.debug("Luminance {} Published with QOS = {}".format(MQTT_MSG3, Quqlity_of_Service))
            time.sleep(1)
            json_data_publish(PUB_TOPIC4, MQTT_MSG4, Quqlity_of_Service)
            print("ADC {} Published\n".format(MQTT_MSG4))
            logger.debug("ADC {} Published with QOS = {}".format(MQTT_MSG4, Quqlity_of_Service))
            time.sleep(1)
            json_data_publish(PUB_TOPIC5, MQTT_MSG5, Quqlity_of_Service)
            print("Battery_Status {} Published\n".format(MQTT_MSG5))
            logger.debug("Battery_Status {} Published with QOS = {}".format(MQTT_MSG5, Quqlity_of_Service))
            time.sleep(1)
    except KeyboardInterrupt:
        print("\nThe Process is Terminated")
        break

此代码可用作

  1. MQTT Publisher
  2. MQTT订阅者
  3. MQTT发布者和订阅者
  4. 但通常在我的设置中它总是在模式3(发布者和订阅者)中操作,因为我想触发执行器。

    代码上传数据没有任何问题。但接收它时会出现问题。接收数据时会有延迟。但是,如果我从我的笔记本电脑运行与订户(模式2)相同的代码,它就能完美运行。一旦上传数据,就会收到我的笔记本电脑。

    如果我能以更有效的方式编写相同的代码,请告诉我。

1 个答案:

答案 0 :(得分:0)

我猜测延迟是在while循环中的sleep方法中。为什么不将代码分成'sub'和'pub'代码并在Raspberry Pi上单独运行它们。我不是Python专家,但我认为一切都在一个线程下运行,因此,当你睡觉时,它暂停了唯一的线程。