如何在函数内部无限循环

时间:2019-06-17 17:25:20

标签: python raspberry-pi mqtt

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

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

sQRY = "SELECT * FROM Expenses Where Expenses.Expense_Month= '" & myvar & "'"

编辑: 这是我在@ MilkyWay90的帮助下实现多处理的方式。

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

2 个答案:

答案 0 :(得分:0)

您可以使用while loop

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

Try it online!

您可以简单地将while语句修改为始终评估为True:

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

Try it online!

这确实可以在函数中起作用。

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

print_natural_numbers()

Try it online!

根据需要修改以上内容:

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()

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

答案 1 :(得分:0)

正确的方法是将client.loop_forever()更改为client.start_loop()docs)。

这将在后台在其自己的线程上启动MQTT客户端循环,然后您可以在启动循环后将自己的while True:循环添加到main函数中,例如

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

client.connect(broker_ip, broker_port, broker_timeout)

client.start_loop()

while True:
   check_state()
   sleep(1)

(p.s。您真的不应该在on_message回调中处于睡眠状态,因为这发生在网络线程上,并且减慢了消息处理的速度)