簡體   English   中英

Raspberry Pi - MQTT 代理接收消息不止一次 - [errno 24] 打開的文件過多

[英]Raspberry Pi - MQTT broker receiving message more than one time - [errno 24] too many open files

我的畢業結論需要我的項目幫助。

我已經設置這個程序來控制網絡上的樹莓,使用節點紅色節點 MQTT。 起初,通信工作得很好,但是,在某些時候,在我從節點紅色流中注入消息后,程序開始多次接收消息,並且由於收到錯誤消息而導致程序崩潰:oserror: [ errno 24] 打開的文件太多 我分析了代碼,就是找不到為什么mqtt代理每次收到多條消息,我需要幫助,我真的很絕望。 在圖像中,我顯示了來自 node-red 的流和來自樹莓派終端的輸出。

 #! usr/bin/ env python

#Import librarys used#
import paho.mqtt.client as mqtt 
import RPi.GPIO as GPIO 
import sys 
import time 
import Adafruit_DHT 
import MFRC522 

#Definition of inputs#

GPIO.setwarnings(False) 
GPIO.setmode(GPIO.BOARD) 
pino_presenca = 11 #Set the input of the PIR sensor used in the project
GPIO.setup(pino_presenca, GPIO.IN)
pino_luminosidade = 15  #Set the input of the LDR module used in the project
GPIO.setup(pino_luminosidade, GPIO.IN)
pino_temperatura = 27 #Sets the input of the DHT11 sensor used in the project


#Set the LED used to demonstrate the mode select (Automatic or manual)#
GPIO.setup(12, GPIO.OUT) 
GPIO.output(12, GPIO.LOW) 
GPIO.setup(16, GPIO.OUT) 
GPIO.output(16, GPIO.LOW) 

#Set the outputs used in the project
GPIO.setup(36, GPIO.OUT) 
GPIO.output(36, GPIO.HIGH) 
GPIO.setup(38, GPIO.OUT) 
GPIO.output(38, GPIO.HIGH) 
GPIO.setup(40, GPIO.OUT) 
GPIO.output(40, GPIO.HIGH) 

#Set the cleared tags that will be read by RFID module

cartao = {"12:4F:90:34:F9":"Matheus Neri", "47:22:9D:60:98":"Matheus Neri"}
leitor = MFRC522.MFRC522() 
auto = False #Declare the variable auto for using in the loop of the automatic mode
modo_auto = False #Declare the variable auto for using in the loop of the automatic mode
estado_lampada = 0 #Declare the variable that will monitor the state of the lamp
estado_ventilador = #Declare the variable that will monitor the state of the fan

#Function that will make the program runs in automatic mode
def automatico():
    global estado_ventilador
    global estado_lampada
    global modo_auto
    global estado_luminosidade
    pino_luminosidade = 15
    GPIO.setup(pino_luminosidade, GPIO.IN)
    estado_luminosidade = GPIO.input(pino_luminosidade)
    print ("Automatic mode activated")
    GPIO.output(12, GPIO.HIGH)
    GPIO.output(16,GPIO.LOW)
    while auto == True:
        estado_presenca = GPIO.input(pino_presenca)
        if estado_presenca == 1:
            modo_auto = True
            while modo_auto == 1:
                estado_luminosidade = GPIO.input(pino_luminosidade)
                estado_presenca = GPIO.input(pino_presenca)
                if estado_luminosidade == 1:
                    print ("Ambiente escuro")
                    GPIO.output(40, GPIO.LOW)
                    time.sleep(2)
                if estado_luminosidade == 0:
                    print ("Luz acessa")
                    time.sleep(2)
                temp_atual = temperatura()
                if temp_atual > 21:
                    estado_ventilador = 1
                    ventilador_automatico()
                if temp_atual < 21 and estado_ventilador == 1:
                    GPIO.output(38, GPIO.HIGH)
                if estado_presenca == 0:
                    modo_auto = False
                client = mqtt.Client()
                client.on_connect = on_connect
                client.on_message = on_message
                client.connect("raspzerow.local", port = 1883, keepalive = 120)
                client.username_pw_set("root","neri2143")
                client.loop_start()
        if estado_luminosidade == 0 and estado_presenca == 0:
            GPIO.output(40, GPIO.HIGH)
        if estado_presenca ==0 and estado_ventilador == 1:
            GPIO.output(38, GPIO.HIGH)
        print ("Sem presença")
        time.sleep(3)
        client = mqtt.Client()
        client.on_connect = on_connect
        client.on_message = on_message
        client.connect("raspzerow.local", port = 1883, keepalive = 120)
        client.username_pw_set("root", "neri2143")
        client.loop_start()

def manual():
    try:
        
        print ("Manual mode activated")
        GPIO.output(16,GPIO.HIGH)
        GPIO.output(12, GPIO.LOW)
        while modo_auto == False: 
            leitor = MFRC522.MFRC522()
            status,tag_type = leitor.MFRC522_Request(leitor.PICC_REQIDL) #F$
            if status == leitor.MI_OK:
                status, uid = leitor.MFRC522_Anticoll()
                if status == leitor.MI_OK:
                    uid = ':'.join(['%X'% x for x in uid])
                    print("UID do cartão: %s" %uid)
                if uid in cartao:
                    print ("Acesso liberado")
                    print ("Olá %s." % cartao[uid])
                    GPIO.output(36, GPIO.LOW)
                    time.sleep(5)
                    GPIO.output(36, GPIO.HIGH)
                else:
                    print ("Acesso negado")

            client = mqtt.Client()
            client.on_connect = on_connect
            client.on_message = on_message
            client.connect("raspzerow.local", port = 1883, keepalive =120)
            client.username_pw_set("root", "neri2143")
            client.loop_start()
    except KeyboardInterrupt:
        GPIO.cleanup()
        print ("Simulação finalizada")
        sys.exit(0)


def on_connect (client, userdata, flags, rc):
    client.subscribe("iluminação")
    client.subscribe("ventilação")
    client.subscribe("modo")

def on_message(client, userdata, msg):
    msg.payload = msg.payload.decode("utf-8")
    mensagem = msg.payload
    global estado_lampada
    global estado_ventilador
    global auto
    global modo_auto
    if mensagem == "ON":
        auto = True
        automatico()
    if mensagem == "OFF":
        auto = False
        modo_auto= False
        print (auto, modo_auto)
        manual()
    if mensagem == "ONL":
        if estado_lampada == 1:
            estado_lampada = 0
        lampada()
    if mensagem == "OFFL":
        if estado_lampada == 0:
            estado_lampada = 1
        lampada()
    if mensagem == "ONV":
        if estado_ventilador == 1:
            estado_ventilador = 0
        ventilador()
    if mensagem == "OFFV":
        if estado_ventilador == 0:
            estado_ventilador = 1
        ventilador()

#Define the function that will change the state of the fan in automatic mode
def ventilador_automatico():
        
        print("Ventilador ligado")
        GPIO.output(38, GPIO.LOW)
        estado_ventilador = 1
        time.sleep(2)

#Define the function that will change the state of the fan in manual mode
def ventilador():

    GPIO.setup (38, GPIO.OUT)   
    global estado_ventilador
    if estado_ventilador == 0:
        print ("Ventilador ligado")
        GPIO.output(38,GPIO.LOW)
        estado_ventilador = 1
        time.sleep(2)
    else:
        print ("Ventilador desligado")
        GPIO.output(38, GPIO.HIGH)
        estado_ventilador = 0

#Define the function that will change the state of the lamp in manual mode
def lampada():
    
    GPIO.setup(40, GPIO.OUT)
    global estado_lampada
    if estado_lampada == 0:
        GPIO.output(40, GPIO.LOW)
        print ("Lampada acessa")
        estado_lampada = 1
    else:
        GPIO.output(40,GPIO.HIGH)
        print ("Lampada apagada")
        estado_lampada = 0
    
#Define the function that will make the reading of the DHT11 sensor
def temperatura():
    
    sensor = Adafruit_DHT.DHT11 
    pino_sensor = 27
    umid, temp = Adafruit_DHT.read_retry(sensor, pino_sensor)
    if umid is not None and temp is not None:
        print ("Temperatura = {0:0.1f}".format(temp))
        #print ("Temperatura = {0:0.1f} Umidade = {1:0.1f}n".format(temp, umid))
    if umid is None and temp is None:
        print ("Falha ao ler dados do DHT11")   
    return temp
print ("Simulation start") 
manual()

節點紅流 終端輸出 ,

以下代碼行:

        client = mqtt.Client()
        client.on_connect = on_connect
        client.on_message = on_message
        client.connect("raspzerow.local", port = 1883, keepalive =120)
        client.username_pw_set("root", "neri2143")
        client.loop_start()

應該只在程序開始時運行一次。 你有他們在一個循環。

每次調用它都會創建一個到 MQTT 代理的新連接,訂閱您的主題並創建一個新線程 ( client.loop_start() ) 來接收訂閱。

很快,您將用完連接到 MQTT 代理的套接字,並收到您所看到的打開文件過多錯誤。 您還會看到多條消息,因為每個訂閱都會收到相同的消息。

在程序中使用它們的任何地方刪除這些代碼行(3 次),然后在調用manual()之前將它們移動到代碼的開頭。

- - 編輯 - -

在評論之后,這里似乎還有更多問題。 on_message()函數調用運行循環的manual()automatico() 這會阻止 MQTT 客戶端線程處理更多消息。 因此,這個函數應該只設置一個標志或狀態來改變在主應用程序線程中調用automatico()還是manual()

這是對代碼的建議(未經測試)更改以啟用此功能。

#! usr/bin/ env python

#Import librarys used#
import paho.mqtt.client as mqtt 
import RPi.GPIO as GPIO 
import sys 
import time 
import Adafruit_DHT 
import MFRC522 

#Definition of inputs#

GPIO.setwarnings(False) 
GPIO.setmode(GPIO.BOARD) 
pino_presenca = 11 #Set the input of the PIR sensor used in the project
GPIO.setup(pino_presenca, GPIO.IN)
pino_luminosidade = 15  #Set the input of the LDR module used in the project
GPIO.setup(pino_luminosidade, GPIO.IN)
pino_temperatura = 27 #Sets the input of the DHT11 sensor used in the project


#Set the LED used to demonstrate the mode select (Automatic or manual)#
GPIO.setup(12, GPIO.OUT) 
GPIO.output(12, GPIO.LOW) 
GPIO.setup(16, GPIO.OUT) 
GPIO.output(16, GPIO.LOW) 

#Set the outputs used in the project
GPIO.setup(36, GPIO.OUT) 
GPIO.output(36, GPIO.HIGH) 
GPIO.setup(38, GPIO.OUT) 
GPIO.output(38, GPIO.HIGH) 
GPIO.setup(40, GPIO.OUT) 
GPIO.output(40, GPIO.HIGH) 

#Set the cleared tags that will be read by RFID module

cartao = {"12:4F:90:34:F9":"Matheus Neri", "47:22:9D:60:98":"Matheus Neri"}
leitor = MFRC522.MFRC522() 
modo_auto = False #Declare the variable modo_auto for using in the loop of the automatic mode
estado_lampada = 0 #Declare the variable that will monitor the state of the lamp
estado_ventilador = #Declare the variable that will monitor the state of the fan

#Function that will make the program runs in automatic mode
def automatico():
    global estado_ventilador
    global estado_lampada
    global modo_auto
    global estado_luminosidade
    pino_luminosidade = 15
    GPIO.setup(pino_luminosidade, GPIO.IN)
    estado_luminosidade = GPIO.input(pino_luminosidade)
    print ("Automatic mode activated")
    GPIO.output(12, GPIO.HIGH)
    GPIO.output(16,GPIO.LOW)
    while modo_auto == True:
        estado_presenca = GPIO.input(pino_presenca)
        if estado_presenca == 1:
            modo_auto = True
            while modo_auto == 1:
                estado_luminosidade = GPIO.input(pino_luminosidade)
                estado_presenca = GPIO.input(pino_presenca)
                if estado_luminosidade == 1:
                    print ("Ambiente escuro")
                    GPIO.output(40, GPIO.LOW)
                    time.sleep(2)
                if estado_luminosidade == 0:
                    print ("Luz acessa")
                    time.sleep(2)
                temp_atual = temperatura()
                if temp_atual > 21:
                    estado_ventilador = 1
                    ventilador_automatico()
                if temp_atual < 21 and estado_ventilador == 1:
                    GPIO.output(38, GPIO.HIGH)
                if estado_presenca == 0:
                    modo_auto = False
        if estado_luminosidade == 0 and estado_presenca == 0:
            GPIO.output(40, GPIO.HIGH)
        if estado_presenca ==0 and estado_ventilador == 1:
            GPIO.output(38, GPIO.HIGH)
        print ("Sem presença")
        time.sleep(3)

def manual():
    global modo_auto 
    try:
        
        print ("Manual mode activated")
        GPIO.output(16,GPIO.HIGH)
        GPIO.output(12, GPIO.LOW)
        while modo_auto == False: 
            leitor = MFRC522.MFRC522()
            status,tag_type = leitor.MFRC522_Request(leitor.PICC_REQIDL) #F$
            if status == leitor.MI_OK:
                status, uid = leitor.MFRC522_Anticoll()
                if status == leitor.MI_OK:
                    uid = ':'.join(['%X'% x for x in uid])
                    print("UID do cartão: %s" %uid)
                if uid in cartao:
                    print ("Acesso liberado")
                    print ("Olá %s." % cartao[uid])
                    GPIO.output(36, GPIO.LOW)
                    time.sleep(5)
                    GPIO.output(36, GPIO.HIGH)
                else:
                    print ("Acesso negado")

    except KeyboardInterrupt:
        GPIO.cleanup()
        print ("Simulação finalizada")
        sys.exit(0)


def on_connect (client, userdata, flags, rc):
    client.subscribe("iluminação")
    client.subscribe("ventilação")
    client.subscribe("modo")

def on_message(client, userdata, msg):
    msg.payload = msg.payload.decode("utf-8")
    mensagem = msg.payload
    global estado_lampada
    global estado_ventilador
    global modo_auto

    if mensagem == "ON":
        modo_auto = True
    if mensagem == "OFF":
        modo_auto= False
        print (modo_auto)
    if mensagem == "ONL":
        if estado_lampada == 1:
            estado_lampada = 0
        lampada()
    if mensagem == "OFFL":
        if estado_lampada == 0:
            estado_lampada = 1
        lampada()
    if mensagem == "ONV":
        if estado_ventilador == 1:
            estado_ventilador = 0
        ventilador()
    if mensagem == "OFFV":
        if estado_ventilador == 0:
            estado_ventilador = 1
        ventilador()

#Define the function that will change the state of the fan in automatic mode
def ventilador_automatico():
        
        print("Ventilador ligado")
        GPIO.output(38, GPIO.LOW)
        estado_ventilador = 1
        time.sleep(2)

#Define the function that will change the state of the fan in manual mode
def ventilador():

    GPIO.setup (38, GPIO.OUT)   
    global estado_ventilador
    if estado_ventilador == 0:
        print ("Ventilador ligado")
        GPIO.output(38,GPIO.LOW)
        estado_ventilador = 1
        time.sleep(2)
    else:
        print ("Ventilador desligado")
        GPIO.output(38, GPIO.HIGH)
        estado_ventilador = 0

#Define the function that will change the state of the lamp in manual mode
def lampada():
    
    GPIO.setup(40, GPIO.OUT)
    global estado_lampada
    if estado_lampada == 0:
        GPIO.output(40, GPIO.LOW)
        print ("Lampada acessa")
        estado_lampada = 1
    else:
        GPIO.output(40,GPIO.HIGH)
        print ("Lampada apagada")
        estado_lampada = 0
    
#Define the function that will make the reading of the DHT11 sensor
def temperatura():
    
    sensor = Adafruit_DHT.DHT11 
    pino_sensor = 27
    umid, temp = Adafruit_DHT.read_retry(sensor, pino_sensor)
    if umid is not None and temp is not None:
        print ("Temperatura = {0:0.1f}".format(temp))
        #print ("Temperatura = {0:0.1f} Umidade = {1:0.1f}n".format(temp, umid))
    if umid is None and temp is None:
        print ("Falha ao ler dados do DHT11")   
    return temp

print ("Simulation start") 

client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect("raspzerow.local", port = 1883, keepalive = 120)
client.username_pw_set("root", "neri2143")
client.loop_start()

while True: 
    if modo_auto :
        automatico() 
    else:
        manual()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM