2017-12-11 16 views
0

Ich habe ein Client-Skript läuft auf einem Raspberry Pi 3. Der Client erhält von einem Server, ob es wahr oder falsch ist. Danach empfängt es ein bytesähnliches Objekt, das es decodiert und verwendet diese Information, um ein Bild in einer GUI anzuzeigen.Evaluiere socket.recv() die ganze Zeit

Er prüft, ob der GPIO-Pin bei einem Tastendruck TRUE erhält, und führt eine Schleife zurück zum ersten .recv().

Ich möchte der Client die ganze Zeit überprüfen, wenn es die Nachricht "neues Spiel" erhält, und wenn ja, gehen Sie zum ersten .recv(), wo es prüft, ob es wahr oder falsch ist.

Aber seit meiner .recv() -Funktion blockiert ich kann nichts tun, während dort stecken.

Wie kann ich überprüfen, ob ich Informationen erhalte, während ich noch überprüfe, ob sich der GPIO-Status auf TRUE ändert.

Der Code sieht wie folgt aus:

#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 
+1

Sie fragen über asynchroner I/O, und es gibt viele Möglichkeiten, damit umzugehen. Mögliche Lösungen sind die Verwendung von 'select.poll', die Verwendung von Threads oder das Durchsuchen des 'asynchio'-Moduls (unter anderem!). Beachten Sie, dass 'Rpi.GPIO' auch einen asynchronen Callback-basierten Interrupt-Mechanismus implementiert, der es Ihnen ermöglicht, eine Lösung zu implementieren, während Sie immer noch einen blockierenden Aufruf von' recv' haben. Vielleicht nehmen Sie sich etwas Zeit, um die verschiedenen Optionen zu untersuchen. – larsks

+0

wow, so viele Dinge sind falsch hier, weiß nicht, wo ich anfangen soll:/Aber auf jeden Fall brauchen Sie einen anderen Thread, um Ihren Client/Server zu überprüfen – dgan

+0

@dgan Fell frei mit Vorschlägen für Änderungen oder Kritik zu kommen. Dann würdest du diesen Thread neu starten, wenn er die richtige Nachricht erhält? –

Antwort

0

Nun, es ist ziemlich schwierig zu verstehen, was Sie versucht haben, hier haben Sie nur globale Variablen, imperative Code-Stil, und alles ist verschachtelt ... ich kämpfen werde zu bekommen genau was du brauchst.

Es gibt keine Chance, dass mein Code Ihr Problem lösen out-of-the-Box, aber ich hoffe, es wird Ihnen helfen, zu verstehen, wo zu graben, um Ihr Problem zu lösen:

# 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() 
Verwandte Themen