首页 > 解决方案 > 如何在函数内部无限循环

问题描述

我在编写将与 MQTT 服务器通信并检查我可以使用本地网页控制的 GPIO 引脚的实际状态的代码时遇到问题(我仍在学习)。

我的问题是我不知道如何在函数内部进行无限循环,该函数将检查引脚的实际状态并将其与 MQTT 发送的最后状态进行比较,如果有变化,它将向 MQTT 发布新值。

#!/usr/bin/env python2

import paho.mqtt.client as mqtt
import urllib
from time import sleep
import RPi.GPIO as GPIO


#Conf GPIO Number for relays
out_1 = 6

#Conf MQTT broker
broker_ip = "192.168.1.34"
broker_port = 1883
broker_timeout = 60
topic_sub = "/printer/#"
topic_out1 = "/printer/onoff"

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(out_1, GPIO.OUT)
GPIO.output(out_1, GPIO.HIGH)

def main():
    # This is the issue part where I wanted to make looped check for actual value
    def check_state(astate):
            f= open("/sys/class/gpio/gpio6/value","r")
            if f.mode == "r":
                    state = f.read(1)
            if astate == state :
                    return
            else:
                    print("CHANGE")

    def on_connect(client, userdata, flags, rc):
            client.subscribe(topic_sub)

    def on_message(client, userdata, msg):
            if msg.topic == topic_out1 :
                    if msg.payload == "1" :
                            GPIO.output(out_1, GPIO.LOW)
                            state = "1"
                            sleep(.1)
                            print("OUT 1 ON")
                    if msg.payload == "0" :
                            GPIO.output(out_1, GPIO.HIGH)
                            state = "0"
                            sleep(.1)
                            print("OUT 1 OFF")

    client = mqtt.Client()
    client.on_connect = on_connect
    client.on_message = on_message

    client.connect(broker_ip, broker_port, broker_timeout)

    client.loop_forever()

if __name__ == "__main__":
    try:
            main()
    except KeyboardInterrupt:
            GPIO.cleanup()

编辑:这就是我在@MilkyWay90 的多处理帮助下做到的。

#!/usr/bin/env python2

import urllib
from multiprocessing import Process
from time import sleep
import RPi.GPIO as GPIO


#Conf GPIO Number for relays
out_1 = 6

#Conf MQTT broker
broker_ip = "192.168.1.34"
broker_port = 1883
broker_timeout = 60
topic_sub = "/printer/#"
topic_out1 = "/printer/onoff"

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(out_1, GPIO.OUT)
GPIO.output(out_1, GPIO.HIGH)

def check_state():
        import paho.mqtt.client as mqtt
        clientSEND = mqtt.Client()
        clientSEND.connect(broker_ip, broker_port, broker_timeout)
        while True:
                faf= open("/sys/class/gpio/gpio6/value","r")
                qf= open("/home/pi/.state","r")
                fastate = faf.read(1)
                #reverse logic for gpio value
                if fastate == "0" :
                        astate = "1"
                elif fastate == "1" :
                        astate = "0"
                qstate = qf.read(1)
                #print("GPIO state: ",astate,"MQTT state: ",qstate)
                if astate != qstate :
                        clientSEND.publish(topic_out1, astate)
                        #print("CHANGE")
                        sleep(3)
                else:
                        sleep(3)

def mqtt():
        import paho.mqtt.client as mqtt
        def on_connect(client, userdata, flags, rc):
                client.subscribe(topic_sub)

        def on_message(client, userdata, msg):
                if msg.topic == topic_out1 :
                        if msg.payload == "1" :
                                GPIO.output(out_1, GPIO.LOW)
                                state_write("1")
                                sleep(.1)
                                #print("OUT 1 ON")
                        if msg.payload == "0" :
                                GPIO.output(out_1, GPIO.HIGH)
                                state_write("0")
                                sleep(.1)
                                #print("OUT 1 OFF")

        def state_write(state):
                f= open("/home/pi/.state","w")
                f.write(state)
                f.close

        client = mqtt.Client()
        client.on_connect = on_connect
        client.on_message = on_message

        client.connect(broker_ip, broker_port, broker_timeout)

        client.loop_forever()

if __name__ == "__main__":
        try:
                bck_statuscheck = Process(target=check_state)
                mqtt_process = Process(target=mqtt)
                bck_statuscheck.start()
                mqtt_process.start()
                bck_statuscheck.join()
                mqtt_process.join()
        except KeyboardInterrupt:
                GPIO.cleanup()

标签: pythonraspberry-pimqtt

解决方案


您可以使用while 循环

while 循环是 Python 中的一个循环,它在条件计算为True时运行指定的代码。

这是一个while循环的结构:

while <condition>:
    CODE

一个例子可能是:

counter = 1 # Declare a variable named "counter" and set it to the integer 1
while counter <= 10: # This is the while loop. As you can see, the condition checks whether the counter is less than or equal to the integer 10. If it is, execute the code that is indented. This will be checked every iteration
    print(counter) # Use the print function to print out the counter with a newline
    counter += 1 # Increment the counter. This is roughly equivalent to counter = counter + 1

这输出:

1
2
3
4
5
6
7
8
9
10

在线尝试!

您可以简单地将 while 语句修改为 ALWAYS evalulate 为 True:

counter = 1
while True:
   print(counter)
   counter += 1

在线尝试!

这确实在函数中起作用。

def print_natural_numbers():
    counter = 1
    while True:
        print(counter)
        counter += 1

print_natural_numbers()

在线尝试!

要根据您的需要修改上述内容:

def check_state(astate):
        while True:
                f= open("/sys/class/gpio/gpio6/value","r")
                if f.mode == "r":
                        state = f.read(1)
                if astate == state :
                        return
                else:
                        print("CHANGE")

或者另一种选择:

while True:
    check_state(...)

编辑:

在这之后不会一直停留在一个功能中吗?所以它只会检查实际状态但忽略其他一切(MQTT部分)?

(改写:使用上面的代码,这将一直运行(因为 while 循环),而不是继续到其他代码)

看起来这需要multiprocessing

一个示范:

from multiprocessing import Process

def print_natural_numbers():
    counter = 1
    while True:
        print(counter, flush = True)
        counter += 1

def print_square_numbers():
    counter = 1
    while True:
        print(counter ** 2, flush = True)
        counter += 1

if __name__ == '__main__':
    nat_numbers = Process(target=print_natural_numbers)
    sqrt_numbers = Process(target=print_square_numbers)
    sqrt_numbers.start()
    nat_numbers.start()
    sqrt_numbers.join()
    nat_numbers.join()

对于您的情况,您需要创建两个函数:检查函数和代表其他所有内容的函数。


推荐阅读