简体   繁体   中英

Python tornado stop function

I've got a tornado web server running on my Raspberry and a ultrasonic sensor connected to it. I've got a html page with a start and stop button, when I click start the script is sending a message "start" to the serwer and it runs a function that prints the distance.

Now i'm trying to stop the function when clicking stop button. But when te function is printing the distances and I click the stop button on my website the server doesnt recive the "stop" message.

在此处输入图片说明

The code is here: http://pastebin.com/SVRZNXgH

import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.websocket
import time
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BOARD)

# Ta funkcja dokonuje pomiaru odleglosci
def pomiar():
  # Ustawienie pinow czujnika odleglosci
  GPIO_TRIGGER = 16
  GPIO_ECHO    = 18

  # Ustawienie pinu buzzera
  GPIO_BUZZER = 22

  # Ustawienie pinu serwomechanizmu
  GPIO_SERVO = 13

  # Ustawienie pinow
  GPIO.setup(GPIO_TRIGGER,GPIO.OUT)
  GPIO.setup(GPIO_ECHO,GPIO.IN)
  GPIO.setup(GPIO_SERVO,GPIO.OUT)

  # Ustawienie Trigget jako false (stan niski)
  GPIO.output(GPIO_TRIGGER, False)

  GPIO.setup(GPIO_TRIGGER,GPIO.OUT)
  GPIO.output(GPIO_TRIGGER, True)

  time.sleep(0.00001)
  GPIO.output(GPIO_TRIGGER, False)
  start = time.time()

  while GPIO.input(GPIO_ECHO)==0:
    start = time.time()

  while GPIO.input(GPIO_ECHO)==1:
    stop = time.time()

  elapsed = stop-start
  distance = (elapsed * 34300)/2
  print "odleglosc :  %.1f" % distance
  time.sleep(2)

  return distance

# Funkcja dokonujaca sprawdzenia kata
def sprawdz_kat():
  GPIO_SERVO = 13
  GPIO.setup(GPIO_SERVO,GPIO.OUT)
  p = GPIO.PWM(GPIO_SERVO,50)

  katy = [10,12.5,5,2.5];
  start = 20.0;
  for x in katy:
      p.ChangeDutyCycle(x)
      time.sleep(0.5)
      odleglosc = pomiar()
      print "odleglosc :  %.1f" % odleglosc
      if(odleglosc>start):
          start=odleglosc
          kat = x
  if(kat==10):        
      return float(-45)
  if(kat==12.5):
      return float(-90)
  if(kat==5):
      return float(45)
  if(kat==2.5):
      return float(90)

# Funkcja do obrotu robota o zadany kat   
def obrot(kat):
  obrot=abs(kat/100)
  print(obrot)
  if(kat<0):
      GPIO.output(M1_EN, True) # True - do przodu, False - do tylu
      GPIO.output(M2_EN, True) # False - do przodu, True - do tylu
  else:
      GPIO.output(M1_EN, False) # True - do przodu, False - do tylu
      GPIO.output(M2_EN, False) # False - do przodu, True - do tylu
  LEWA_PWM.ChangeDutyCycle(25)
  PRAWA_PWM.ChangeDutyCycle(25)
  time.sleep(obrot)
  LEWA_PWM.ChangeDutyCycle(0)
  PRAWA_PWM.ChangeDutyCycle(0)
  GPIO.output(M1_EN, True)
  GPIO.output(M2_EN, False)   

# Program labiryntu
def labirynt():
  distance = pomiar()
  p.start(7.5)
  while True:
    distance = pomiar()
    GPIO.setup(GPIO_BUZZER,GPIO.OUT)
    GPIO.output(GPIO_BUZZER, False)
    time.sleep(0.08)
    GPIO.setup(GPIO_BUZZER,GPIO.IN)
    time.sleep(distance/500)
    LEWA_PWM.ChangeDutyCycle(10)
    PRAWA_PWM.ChangeDutyCycle(10)
    if(distance<50):
      LEWA_PWM.ChangeDutyCycle(0)
      PRAWA_PWM.ChangeDutyCycle(0)
      kat = sprawdz_kat()
      print kat
      obrot(kat)
      p.ChangeDutyCycle(7.5)
      time.sleep(0.5)
    GPIO.setup(GPIO_SERVO,GPIO.IN)
  GPIO.cleanup  

def stop_all():
  GPIO.output(GPIO_TRIGGER, False)
  GPIO.output(GPIO_ECHO, False)
  GPIO.cleanup()

# Ustawienie pinow czujnika odleglosci
GPIO_TRIGGER = 16
GPIO_ECHO    = 18

# Ustawienie pinu buzzera
GPIO_BUZZER = 22

# Ustawienie pinu serwomechanizmu
GPIO_SERVO = 13

# Ustawienie pinow
GPIO.setup(GPIO_TRIGGER,GPIO.OUT)
GPIO.setup(GPIO_ECHO,GPIO.IN)
GPIO.setup(GPIO_SERVO,GPIO.OUT)

# Ustawienie Trigget jako false (stan niski)
GPIO.output(GPIO_TRIGGER, False)

# Ustawienia dla serwa
p = GPIO.PWM(GPIO_SERVO,50) #Ustawienie czestotliwosci na 50Hz
 #poczatkowy kat serwa 90 stopni (neutralny)

# Ustawienia buzzera
GPIO.setup(GPIO_BUZZER,GPIO.IN)  

# -----------------------
# Ustawienia silnikow
# -----------------------

# Prawa strona
M1_PWM = 26
M1_EN = 24

# Lewa strona
M2_PWM = 23
M2_EN = 21

# Prawa strona ustawienia jako output
GPIO.setup(M1_PWM,GPIO.OUT)
GPIO.setup(M1_EN,GPIO.OUT)

# Lewa strona ustawienia jako output
GPIO.setup(M2_PWM,GPIO.OUT)
GPIO.setup(M2_EN,GPIO.OUT)

# Prawa strona ustawienie stanow niskich
GPIO.output(M1_PWM, False)
GPIO.output(M1_EN, True) # True - do przodu, False - do tylu

# Lewa strona ustawienie stanow niskich
GPIO.output(M2_PWM, False)
GPIO.output(M2_EN, False) # False - do przodu, True - do tylu

# Ustawienie PWM dla prawej strony
PRAWA_PWM = GPIO.PWM(26,50)

# Ustawienie PWM dla lewej strony
LEWA_PWM = GPIO.PWM(23,50)

# Poczatkowe ustawienia PWM silnikow
PRAWA_PWM.start(0)
LEWA_PWM.start(0)



from tornado.options import define, options
define("port", default=8080, help="run on the given port", type=int)

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        self.render('index.html')

class WebSocketHandler(tornado.websocket.WebSocketHandler):
    def open(self):
        print 'new connection'
        self.write_message("connected")

    def on_message(self, message):
        print 'message received %s' % message
        self.write_message('message received %s' % message)
        aaa = message
        if message == "gora":
          GPIO.output(M1_EN, True)
          GPIO.output(M2_EN, False)
          LEWA_PWM.ChangeDutyCycle(8)
          PRAWA_PWM.ChangeDutyCycle(8)
        if message == "dol":
          GPIO.output(M1_EN, False)
          GPIO.output(M2_EN, True)
          LEWA_PWM.ChangeDutyCycle(8)
          PRAWA_PWM.ChangeDutyCycle(8)
        if message == "stop":
          LEWA_PWM.ChangeDutyCycle(0)
          PRAWA_PWM.ChangeDutyCycle(0)
        if message == "lewo":
          GPIO.output(M1_EN, True)
          GPIO.output(M2_EN, True)
          LEWA_PWM.ChangeDutyCycle(20)
          PRAWA_PWM.ChangeDutyCycle(20)
        if message == "prawo":
          GPIO.output(M1_EN, False)
          GPIO.output(M2_EN, False)
          LEWA_PWM.ChangeDutyCycle(20)
          PRAWA_PWM.ChangeDutyCycle(20)
        while (aaa == "start_maze"):
          pomiar()
    def on_close(self):
        print 'connection closed'

if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application(
        handlers=[
            (r"/", IndexHandler),
            (r"/ws", WebSocketHandler),
            (r'/js/(.*)', tornado.web.StaticFileHandler, {'path': "/home/pi/js"}),
            (r'/css/(.*)', tornado.web.StaticFileHandler, {'path': "/home/pi/css"}),
            (r'/fonts/(.*)', tornado.web.StaticFileHandler, {'path': "/home/pi/fonts"}),
        ]
    )
    httpServer = tornado.httpserver.HTTPServer(app)
    httpServer.listen(options.port)
    print "Listening on port:", options.port
    tornado.ioloop.IOLoop.instance().start()

The reason is that you got an endless loop in line 227.

One possible solution:

  1. Make your pomiar function a method of the websocket handler
  2. Use a variable on your websocket handler self.running and on start set it to true. And call self.pomiar()
  3. On stop just set self.running to false
  4. At the end of pomiar remove the time.sleep it does block the complete tornado server. Instead:

...

if self.running:
    tornado.ioloop.IOLoop.instance().add_timeout(time.time() + 2, self.pomiar)

The add_timeout makes tornado call your pomiar function again in two seconds. Checking first if self.running is still true makes sure your pomiar function is only called as long as stop is not called.

There are a lot of other ways to solve this. You might want to read more about tornado and the asynchronous functions it provides, for example: http://tornado.readthedocs.org/en/latest/gen.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM