2017-08-28 4 views
0

J'ai une carte Arduino avec quelques capteurs et un actionneur. Il est connecté à un Raspberry Pi via un câble USB. L'idée est, normalement l'Arduino sera l'impression des données sur Serial. Ceci est récupéré par le Raspberry Pi à l'aide de ce script Python. Si un événement est rencontré du côté du nuage, ou si je clique sur un bouton sur le nuage, cela devrait déclencher l'actionneur du côté Arduino.Délai pendant la réception des données MQTT à partir du cloud

J'ai le code client MQTT suivant.

#!/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 

Ce code peut être utilisé comme

  1. MQTT Editeur
  2. MQTT Abonné
  3. MQTT Éditeur et Abonné

Mais normalement dans ma configuration, il est alway fonctionne en mode 3 (à la fois éditeur et abonné), car je veux déclencher l'actionneur.

Le code télécharge les données sans aucun problème. Mais le problème vient quand on le reçoit. Il y aura un délai pendant la réception des données. Mais si je cours le même code en tant qu'abonné (mode 2) à partir de mon ordinateur portable, cela fonctionne parfaitement. Dès que les données sont téléchargées, elles sont reçues sur mon ordinateur portable.

Et s'il vous plaît laissez-moi savoir si je peux écrire le même code d'une manière beaucoup plus efficace.

Répondre

0

Je vais deviner que le retard est dans la méthode de sommeil dans la boucle while. Pourquoi ne séparez-vous pas le code en code 'sub' et 'pub' et exécutez-les séparément sur le Raspberry Pi. Je ne suis pas un expert Python, mais je pense que tout fonctionne sous un seul thread, par conséquent, quand vous dormez, il est en pause le seul thread.

+0

Oui. J'utilise un service gratuit du fournisseur de services cloud. Donc, je ne peux envoyer des données que pour une seconde, donc j'ai utilisé le délai entre les deux. Je vérifie avec multithreading comme vous l'avez suggéré. Je vous remercie – Arunkrishna