[英]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.