3

所以我使用cherrypy和pyserial编写了一个Web界面来与Arduino Uno交互。它非常完整,我唯一缺少的,并且我一直试图弄清楚一天的事情是不断读取 Arduino 发送的数据,并自动显示一个包含 html 内消息的 div代码。我可以在控制台中显示它,但我无法返回实际的 html。其实用return是不行的,只好用print,不方便,因为我要的是html页面中的数据,而不是console。我已经尝试了很多方法来做到这一点。

这是我的代码,非常简单。常量函数不断读取从 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')
4

1 回答 1

0

为了让它做你想做的事,你有两个选择:

  • 使生成的网页在每次显示时打印动态数据,并在客户端添加元刷新(或 javascript 刷新)或
  • 做一个每次有新数据进来时都会更新的长轮询路由(见这个例子

但我认为您问题的核心与如何将线程函数中的值发送到您的网站类有关。您需要使用Queue.Queue:该示例显示了如何使用cherrypy 发出长轮询请求。

在下面的示例中,您将错过该站点jsonyield上可用的装饰器,这是理解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>

使用 a 的整个想法Queue是,在您的 arduino 观看线程和cherrypy 线程之间交换信息时,您不会冒线程问题的风险。队列是线程安全的,并且同步读/写,因此它们按顺序发生,并且一次一个线程。

高温高压

于 2013-06-19T13:05:52.720 回答