2017-08-28 60 views
0

我有一個帶有一些傳感器和一個執行器的Arduino板。它通過USB電纜連接到樹莓派。從雲接收MQTT數據時的延遲

這個想法是,通常Arduino將打印Serial上的數據。這是在這個Python腳本的幫助下由Raspberry Pi檢索的。如果在雲側遇到任何事件,或者如果我單擊雲上的某個按鈕,則會觸發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發佈
  2. MQTT訂戶
  3. MQTT發佈者和訂閱

但通常在我的設置它在模式常是操作3(發佈商和訂戶),因爲我想觸發執行器。

該代碼上傳數據沒有任何問題。但接收它時會出現問題。接收數據時會有延遲。但是,如果我從我的筆記本電腦上運行與訂戶(模式2)相同的代碼,它的工作原理完美。數據一上傳,它就會在我的筆記本電腦上收到。

請讓我知道,如果我可以用更有效的方式編寫相同的代碼。

回答

0

我會猜測延遲是在while循環中的sleep方法中。你爲什麼不把代碼分離成'sub'和'pub'代碼,並分別在Raspberry Pi上運行它們。我不是Python專家,但我認爲一切都在單線程下運行,因此,當你入睡時,它暫停了唯一的線程。

+0

是的。我正在使用雲服務提供商提供的免費服務。所以我只能每秒發送一次數據,所以我在兩者之間使用了延遲。 我按照您的建議檢查多線程。謝謝 – Arunkrishna