2013-06-19 77 views
3

所以我编写了一个网络接口与Arduino的乌诺交互,使用CherryPy的,和pyserial。这是很完整的,那我唯一缺少的东西,我一直在试图找出了一天,就是不断阅读Arduino的发送的数据,并自动显示包含HTML里面的消息一个div码。我可以在控制台中显示它,但我无法设法返回实际的HTML。事实上,我无法设法使用返回,我必须使用打印,这是不方便的,因为我想要的数据在HTML页面,而不是控制台。 我已经尝试了很多方法来做到这一点。线程与蟒蛇,CherryPy的和pyserial

这里是我的代码,很简单。常数函数不断读取从Arduino发送的数据,并将其发送到控制台。我希望它将它发送到html代码,就像实时更新一样。我该怎么做呢?

# -*- coding: Utf-8 -*- 

import cherrypy, arduino, time, threading 

ser=arduino.Serial('COM4', 9600) 

def constant(): 
    while True: 
     m='' 
     print('running') 
    while True: 
     print('sub_running') 
     byte=(ser.read().encode('Utf-8')) 
     if byte=='*': 
      break 
     m=m+byte 
     time.sleep(1) 
    print(m) 
    time.sleep(1) 

class website(object): 
    def index(self): 
     return ''' 
      <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script><script src="annexes/functions.js"></script> 
      <link rel=stylesheet type=text/css media=screen href="/annexes/design.css"> 
      <form action="command" method="POST"> 
      <input type="submit" name="command" value="Turn the LED on" text="hey"/> 
      <input type="submit" name="command" value="Turn the LED off"/> 
      </form> 
     '''  
    index.exposed=True 

    def command(self, command): 
     m='' 
     if command=='Turn the LED on': 
      ser.write('1') 
     if command=='Turn the LED off': 
      ser.write('0') 
     self.index 
    command.exposed=True 

_thread = threading.Thread(target=constant) 
_thread.setDaemon(True) 
_thread.start() 

cherrypy.quickstart(website(), config='config.conf') 

回答

0

让它做你想要什么,你有两个选择:

  • 使生成的网页打印动态数据每次显示它的时间,并加元刷新(或一个javascript刷新)在客户端或
  • 做出获取每个新的数据到来时更新长轮询路线(见本example

不过我觉得你的问题的核心是关于如何将您的线程函数的值发送到您的网站类。你需要使用Queue.Queue: 这例子说明了如何使用做一个的CherryPy长轮询请求。

在下面的例子中,你会错过jsonyield装饰上可用this site这是一个很好看的懂的CherryPy和长轮询。

# -*- coding: utf-8 -*- 

import cherrypy, arduino, time, threading 
import Queue 

def serialWatcher(ser, queue): 
    while True: 
     m='' 
     print('running') 
    while True: 
     print('sub_running') 
     byte=(ser.read().encode('Utf-8')) 
     if byte=='*': 
      break 
     m=m+byte 
     time.sleep(1) 
    queue.put(m) 
    time.sleep(1) 

class website(object): 
    def __init__(self, ser, queue): 
     self.serial = ser 
     self.queue = queue 

    # it's often better to use decorators when you can 
    @cherrypy.expose 
    def index(self): 
     return ''' 
      <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script><script src="annexes/functions.js"></script> 
      <link rel=stylesheet type=text/css media=screen href="/annexes/design.css"> 
      <form action="command" method="POST"> 
      <input type="submit" name="command" value="Turn the LED on" text="hey"/> 
      <input type="submit" name="command" value="Turn the LED off"/> 
      </form> 
     ''' 

    @cherrypy.expose 
    def command(self, command): 
     m='' 
     if command=='Turn the LED on': 
      self.serial.write('1') 
     if command=='Turn the LED off': 
      self.serial.write('0') 
     return self.index() # I assume that's what you wanted to write 

    @cherrypy.expose 
    @json_yield 
    def get_arduino_results(self): 
     """you can get the result of this long polling request using a JS AJAX query""" 
     while True: 
      while not self.queue.empty(): 
       yield self.queue.get() 


# always use the following, so you can also use the module you're writing as imports 
# in other modules 
if __name__ == "__main__": 
    q = Queue.Queue() 
    # Never use global variables, always pass them as parameters 
    ser = arduino.Serial('COM4', 9600) 

    _thread = threading.Thread(target=serialWatcher, args=(ser, q)) 
    _thread.setDaemon(True) 
    _thread.start() 

    cherrypy.quickstart(website(ser, q), config='config.conf') 

but the same principle would work for a standard page, something like: 

    @cherrypy.expose 
    get_arduino_results(self): 
     out = "<ul>" 
     while not self.queue.empty(): 
      out += "<li>" + self.queue.get() + "</li>" 
     return out + "</ul> 

使用Queue的整体思路是,你不会冒险让线程的问题,而你的Arduino看线程和线程的CherryPy之间交换信息。队列是线程安全的,并且同步读/写,以便它们按顺序发生,并且一次一个线程。

HTH

+0

嘿非常感谢你为你的伟大的答案,但我似乎无法弄清楚如何“安装”,我刚刚下载的jsonyield装饰。那个怎么样? – user2501169

+0

那么你可以把你在同一个目录下载在一个叫做'jsonyield.py'文件的代码,并在你的代码的开头,你可以做'从jsonyield进口jsonyield'的代码。另一个(丑)解决方案是复制粘贴整个'jsonyield'功能在源文件的顶部(但不要忘了,它需要太多的进口!) – zmo

+0

非常感谢,让您的解决方案应该是生活展示是什么由arduino发送的权利?当我点击一个按钮时,没有任何明显的事情发生。我的arduino正在循环着相同的东西:每隔2秒钟,它发送一条不同的消息。所以脚本应该更新网页是不是? – user2501169