【问题标题】:Evaluate socket.recv() all the time一直评估 socket.recv()
【发布时间】:2017-12-11 19:50:20
【问题描述】:

我有一个在 Raspberry Pi 3 上运行的客户端脚本。客户端从服务器接收,无论它是 TRUE 还是 FALSE。在此之后,它会收到一个类似字节的对象,它会解码并使用此信息在 GUI 中显示图像。

它检查 GPIO 引脚是否因按下按钮而变为 TRUE,并循环回第一个 .recv()。

我希望客户端一直检查它是否收到消息“新游戏”,如果是,则转到第一个 .recv() 来检查它是 TRUE 还是 FALSE。

但是由于我的 .recv() 函数阻塞了,我卡在那里什么也做不了。

如何在检查 GPIO 状态是否更改为 TRUE 的同时检查我是否收到信息。

代码如下所示:

#imports needed
import socket
import RPi.GPIO as GPIO
import time
import tkinter as tk
import pygame

#Setup of GPIO pin for buttons used as bumpers
GPIO.setmode(GPIO.BOARD)
GPIO.setup(36, GPIO.IN, pull_up_down=GPIO.PUD_UP) #Pin 36 = GPIO16


#Setup of root window for the GUI and the different images 
root = tk.Tk()
root.attributes('-fullscreen',True)

image6 = tk.PhotoImage(file="/home/pi/Desktop/wav/wrong.gif")
wronglabel = tk.Label(image=image6)

image5 = tk.PhotoImage(file="/home/pi/Desktop/wav/correct.gif")
correctlabel = tk.Label(image=image5)

image4 = tk.PhotoImage(file="/home/pi/Desktop/wav/questionmark.gif")
questionlabel = tk.Label(image=image4)

pygame.init()

#Setup of the different sounds to use in the project
correctsound = pygame.mixer.Sound('/home/pi/Desktop/wav/correct.wav')
wrongsound = pygame.mixer.Sound('/home/pi/Desktop/wav/wrong.wav')

HOST = '192.168.1.34'    # The remote host, 
PORT = 50007              # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try: 
    s.connect((HOST, PORT))

except:
    print("FAILED. Sleep briefly & try again")
    time.sleep(10)
    continue

questionlabel.pack()
root.update()
while True:
    data = s.recv(1024)
    if data == b'True':
        print('I am the true cone')
        state = True        
    if data == b'False':
        print('I am the false cone')
        state = False


    byte_string = s.recv(1024)
    path = '/home/pi/Desktop/wav/%s.gif' % byte_string.decode()
    questionlabel.pack_forget()

    image1 = tk.PhotoImage(file=path) #x should change accordingly to the received message 
    Thelabel = tk.Label(image=image1)
    Thelabel.pack()
    root.update()

    i=0
    while i==0:
        if GPIO.input(36) == True:
            if state == True:
                Thelabel.pack_forget()
                correctlabel.pack()
                root.update()
                correctsound.play()
                s.sendall(b'True Hit')
                time.sleep(5)
                correctlabel.pack_forget()
                questionlabel.pack()
                root.update()

            if state == False:
                Thelabel.pack_forget()
                wronglabel.pack()
                root.update()
                wrongsound.play()
                time.sleep(5)
                wronglabel.pack_forget()
                questionlabel.pack()
                root.update()
            i=1

【问题讨论】:

  • 你问的是异步I/O,有很多处理方法。可能的解决方案包括使用select.poll、使用线程或查看asynchio 模块(等等!)。请注意,Rpi.GPIO 还实现了一个基于异步回调的中断机制,它可以让您在仍然对recv 进行阻塞调用的同时实现解决方案。也许需要一些时间来调查各种选项。
  • 哇,这里有很多问题,不知道从哪里开始:/但无论如何,您需要另一个线程来检查您的客户端/服务器
  • @dgan 随意提出更改或批评的建议。比你在收到正确消息时让这个线程重新启动另一个线程吗?

标签: python multithreading sockets raspberry-pi


【解决方案1】:

嗯,很难理解你在这里尝试了什么,你只有全局变量,命令式代码风格,而且一切都是交错的......我正在努力得到你所需要的。

我的代码不可能开箱即用地解决您的问题,但我希望它能帮助您了解在哪里挖掘来解决您的问题:

# imports needed
import socket
import RPi.GPIO as GPIO
import time
from threading import Thread

try:
    from Tkinter import *
except ImportError:
    from tkinter import *

import pygame

# Setup of GPIO pin for buttons used as bumpers
GPIO.setmode(GPIO.BOARD)
GPIO.setup(36, GPIO.IN, pull_up_down=GPIO.PUD_UP)  # Pin 36 = GPIO16


class MyTk():
"""All tkinter stuff goes here"""

    def __init__(self, pygame_app):
        self.root = Tk()
        self.pygame_app = pygame_app
        self.pygame_app.init()
        self.root.attributes('-fullscreen', True)

        image6 = PhotoImage(file="/home/pi/Desktop/wav/wrong.gif")
        self.wronglabel = Label(image=image6, master=self.root)  # ? unused

        image5 = PhotoImage(file="/home/pi/Desktop/wav/correct.gif")
        self.correctlabel = Label(image=image5, master=self.root)  # ? unused

        image4 = PhotoImage(file="/home/pi/Desktop/wav/questionmark.gif")
        self.questionlabel = Label(image=image4, master=self.root)

        self.questionlabel.pack()
        self.root.update()

    def update_for_right(self):
        correctsound = self.pygame_app.mixer.Sound('/home/pi/Desktop/wav/correct.wav')
        self._forget_TheLabel()
        correctsound.play()
        time.sleep(5)
        self._forget_correct()

    def _set_TheLabel(self, path):
        image1 = PhotoImage(file=path)  # x should change accordingly to the received message
        self.Thelabel = Label(image=image1, master=self.root)
        self.Thelabel.pack()
        self.root.update()

    def update_for_wrong(self):
        # Setup of the different sounds to use in the project
        wrongsound = self.pygame_app.mixer.Sound('/home/pi/Desktop/wav/wrong.wav')
        wrongsound.play()
        time.sleep(5)
        self._forget_wrong()

    def _forget_wrong(self):
    """you should not call underscored methods from outside of   this class"""
        self.wronglabel.forget()
        self.root.update()

    def _forget_correct(self):
        self.correctlabel.pack_forget()
        self.questionlabel.pack()
        self.root.update()

    def _forget_TheLabel(self):
        self.Thelabel.pack_forget()
        self.root.update()

    def _forget_question_label(self):
        self.questionlabel.pack_forget()
        self.root.update()


class MySocket():
"""All socket stuff goes here"""
    def __init__(self, tkinter_app, host='192.168.1.34', port=5007):
    """This class needs a dependency(tkinter), so pass it as constructor argument, and use it later"""

        self.host = host
        self.port = port
        self.tkinter_app = tkinter_app

    def try_connect(self):
        self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        while 1:
            try:
                self.s.connect((self.host, self.port))
                return
            except:
                print("FAILED. Sleep briefly & try again")
                time.sleep(10)

    def listen(self):
        """This blocks execution until something is received"""
        while True:
            data = self.s.recv(1024)
            if data == b'True':
                byte_string = self.s.recv(1024)  # antoher signal is sent?
                print('I am the true cone')
                state = True
                self.do_stuff(state, data)
            else:
                # this is useles...
                print('I am the false cone')
                state = False

    def do_stuff(self, state, data):
        path = '/home/pi/Desktop/wav/%s.gif' % data.decode()
        self.tkinter_app._set_TheLabel(path)
        if GPIO.input(36) == True:
            if state:
                self.s.sendall(b'True Hit')
                self.tkinter_app.update_for_right()

            else:
                self.s.sendall(b'False Hit')  # ?
                self.tkinter_app.update_for_wrong()

        return


if __name__ == '__main__':
    mytk = MyTk(pygame)
    mysk = MySocket(mytk)
    mysk.try_connect()
    # this call blocks; so you need at least another thread to run your Tkinter
    th = Thread(target=mytk.root.mainloop)  # launch tkinter GUI
    th.start()
    # this block the main thread
    mysk.listen()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多