更新全局布尔值以启动或停止函数

问题描述 投票:0回答:1

我正在用python编写一个应用程序,该应用程序根据GPIO状态控制某些LED。在硬件上,我监听GPIO更改状态,然后发布到运行在树莓派上的MQTT服务器,以控制LED。 GPIO之一应使LED无限闪烁,直到状态再次改变以将其关闭为止,这正是汽车转向信号的工作原理。

因此,当GPIO变高时,我发布了有效负载为'on'的主题。然后,我设置一个全局变量

blinker_status = True

然后基本上说(伪代码)

while (blinker_status) { blink }

当我使用有效负载'off'发布到同一主题时,我设置了全局变量的值

blinker_status = False

我期望LED停止闪烁,但是不会。我不确定问题是否在于MQTT是否被阻止?

一旦我启动LED闪烁,也许是阻止了on_message()回调,并且它无法处理其他消息?我是否应该将所有订阅者客户端都隔离到各自的线程中,以便通过其各自的on_message()回调来处理发布到每个主题?

我有必要时可以提供的代码,但在这一点上,我一直试图理解为什么我的逻辑有缺陷。

下面是我的代码

import time
from neopixel import *
from threading import Thread
import paho.mqtt.client as mqtt

mqtt_client = None

# LED strip configuration:
LED_COUNT_LEFT = 150  # Number of LED pixels on the left strip.
LED_COUNT_RIGHT = 1  # Number of LED pixels on the right strip.
LED_FREQ_HZ = 800000  # LED signal frequency in hertz (usually 800khz)
LED_DMA = 10  # DMA channel to use for generating signal (try 10)
LED_BRIGHTNESS = 255  # Set to 0 for darkest and 255 for brightest
LED_INVERT = False  # True to invert the signal (when using NPN transistor level shift)
LED_CHANNEL_LEFT = 0  # set to '1' for GPIOs 13, 19, 41, 45 or 53
LED_CHANNEL_RIGHT = 1

# NOTE:  The WS2812B strip has red and green inverted, so red is actually (0, 255, 0) and green is (255, 0, 0)

left_blinker_status = False
right_blinker_status = False
blinker_status = False

# Create NeoPixel object with appropriate configuration.
# GPIO 18 is pin 12
left_strip = Adafruit_NeoPixel(LED_COUNT_LEFT, 18, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL_LEFT)
# GPIO 13 is pin 33
right_strip = Adafruit_NeoPixel(LED_COUNT_RIGHT, 13, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS,
                                LED_CHANNEL_RIGHT)
# Intialize the library (must be called once before other functions).
left_strip.begin()
right_strip.begin()


# MQTT functions
def start_mqtt():
    global mqtt_client
    try:
        system_id = 'Kawasaki Ninja'

        mqtt_client = mqtt.Client(client_id=system_id)
        mqtt_client.disable_logger()

        # Assign callback functions
        mqtt_client.on_connect = on_connect
        mqtt_client.on_message = on_message

        mqtt_client.connect(host='192.168.1.23')
        # Blocking call that processes network traffic, dispatches callbacks and
        # handles reconnecting.
        mqtt_client.loop_forever()

    except Exception as ex:
        print('Exception in start_mqtt()! exception: {}'.format(ex))
        raise


# THe callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, flags, rc):
    print('Connected with result code ' + str(rc))

    # Subscribing in on_connect() - if we lose connection and
    # reconnect then subscriptions will be renewed.
    client.subscribe('ninja/#')  # The hash sign is wild-card


# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
    global blinker_status
    global left_blinker_status
    global right_blinker_status

    print('{} {}'.format(msg.topic, str(msg.payload)))

    # Handle the brake topic
    if msg.topic == 'ninja/brake':
        if msg.payload == 'on':
            # BRAKE ON
            if not left_blinker_status:
                solidColor(left_strip, Color(0, 255, 0))
            if not right_blinker_status:
                solidColor(right_strip, Color(0, 255, 0))
        elif msg.payload == 'off':
            # BRAKE OFF
            if not left_blinker_status:
                solidColor(left_strip, Color(255, 255, 255))
            if not right_blinker_status:
                solidColor(right_strip, Color(255, 255, 255))

    # Handle the left turn signal topic
    elif msg.topic == 'ninja/left_turn_signal':
        # Left turn signal on
        if msg.payload == 'on':
            blinker_status = True
            left_blinker_status = True
            while left_blinker_status:
                blinker(blinker_status, left_strip)
        # Left turn signal off
        elif msg.payload == 'off':
            blinker_status = False
            left_blinker_status = False
            solidColor(left_strip, Color(255, 255, 255))

    # Handle the right turn signal topic
    elif msg.topic == 'ninja/right_turn_signal':
        # Right turn signal on
        if msg.payload == 'on':
            blinker_status = True
            right_blinker_status = True
            while right_blinker_status:
                blinker(blinker_status, right_strip)
        # Right turn signal off
        elif msg.payload == "off":
            blinker_status = False
            right_blinker_status = False
            solidColor(right_strip, Color(255, 255, 255))

    # Handle the party time topic
    elif msg.topic == 'ninja/party_time':
        # Party on
        if msg.payload == 'on':
            colorWipe(left_strip, Color(0, 255, 0))  # Red

        elif msg.payload == 'white':
            solidColor(left_strip, Color(255, 255, 255))

        elif msg.payload == 'wipe':
            colorWipe(left_strip, Color(0, 255, 0))  # Red

        elif msg.payload == 'off':
            solidColor(left_strip, Color(0, 0, 0))


# Neopixel functions
# Define functions which animate LEDs in various ways.
def colorWipe(strip, color, wait_ms=50):
    """Wipe color across display a pixel at a time."""
    for i in range(strip.numPixels()):
        strip.setPixelColor(i, color)
        strip.show()
        time.sleep(wait_ms / 1000.0)


def solidColor(strip, color):
    for i in range(strip.numPixels()):
        strip.setPixelColor(i, color)
    strip.show()


def blinker(blinker_status, strip):
    while blinker_status:
        solidColor(strip, Color(65, 100, 0))
        time.sleep(0.5)
        solidColor(strip, Color(0, 0, 0))
        time.sleep(0.5)


try:
    while True:
        mqtt_thread = Thread(target=start_mqtt, args=())
        mqtt_thread.isDaemon()
        mqtt_thread.start()

except KeyboardInterrupt:
    exit()
python multithreading mqtt blocking gpio
1个回答
0
投票

on_message回调在MQTT客户端的网络线程上运行,如果您阻止该线程,您将无法再发送或接收任何消息。

您不应在此(或任何客户端回调)中进行任何阻塞或长时间运行的操作,您应该在状态机中设置标志并使用这些更改来控制其他线程。

© www.soinside.com 2019 - 2024. All rights reserved.