2016-03-23 67 views
0

我有一個Beaglebone黑色連接到CAN總線設備:電池。如何在龍捲風中使用多個ioloop並在ioloop(s)之間共享數據?

作爲GUI在Beaglebone Black上運行的龍捲風網頁。

CAN總線讀取循環不斷從CAN總線讀取數據更新電池例如

的狀態,但我怎樣才能使兩個IOLOOP攜手共進,共享電池組的實例?

enter image description here

龍捲風網絡:

class Battery(object): 
    status = {} 



class API_Handler(web.RequestHandler): 
    def get(self, dev, cmd): 
     if cmd == 'data': 
      self.write(self.application.battery0.status) 


class Application(web.Application): 
    def __init__(self): 

     self.battery0 = Battery('bat0')  

     routing = [ 
      (r'/api/battery/(data|)', API_Handler), 
     ] 

     settings = { 
      'template_path': os.path.join(os.path.dirname(__file__), "templates"), 
      'static_path': os.path.join(os.path.dirname(__file__), "static"), 
     } 

     web.Application.__init__(self, routing, debug=True, **settings) 


if __name__ == "__main__": 
    import tornado 

    app = Application() 
    app.listen(address='0.0.0.0', port=8888) 
    tornado.ioloop.IOLoop.instance().start() 

CAN總線讀取循環,代碼:

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 
import errno 
import functools 
import tornado.ioloop 
import socket 
import struct 


can_frame_fmt = "=IB3x8s" 
can_frame_size = struct.calcsize(can_frame_fmt) 

def build_can_frame(can_id, data): 
    can_dlc = len(data) 
    data = data.ljust(8, b'\x00') 
    return struct.pack(can_frame_fmt, can_id, can_dlc, data) 

def dissect_can_frame(frame): 
    can_id, can_dlc, data = struct.unpack(can_frame_fmt, frame) 
    return (can_id, can_dlc, data[:can_dlc]) 

def connection_ready(sock, fd, events): 
    while True: 
     try: 
      cf, addr = sock.recvfrom(can_frame_size) 
     except socket.error as e: 
      if e.args[0] not in (errno.EWOULDBLOCK, errno.EAGAIN): 
       raise 
      return 
     dissect_can_frame(cf) 


if __name__ == '__main__': 
    sock = socket.socket(socket.AF_CAN, socket.SOCK_RAW, socket.CAN_RAW) 
    sock.bind(('can0',)) 
    sock.setblocking(0) 

    io_loop = tornado.ioloop.IOLoop.current() 
    callback = functools.partial(connection_ready, sock) 
    io_loop.add_handler(sock.fileno(), callback, io_loop.READ) 
    io_loop.start() 
+0

如果您使用龍捲風,這是能夠[WebSockets的(https://en.wikipedia.org/wiki/WebSocket),爲什麼用戶發送一個獲得狀態的命令?您只需啓動一個線程,以指定的頻率讀取電池狀態,並通過websocket連接自動更新瀏覽器。 – yegorich

+0

@yegorich我知道你的關心。但這只是cmd的一個例子。我還有很多其他的cmd。另一個原因是內部數據變化頻繁得多,但GUI不需要更新爲相同的頻率。第三個原因是這允許其他模塊使用相同的API以自己的頻率請求數據。 –

回答

0

,我可以看到你正在運行的應用程序,所以這將是難以共享電池實例。第一個解決方案 - 將一個應用程序中的所有功能組合在一起,以便Battery實例可以簡單使用,但是您將面臨一個挑戰,即在一個ioloop中服務HTTP請求和處理來自CAN的套接字事件。

所以這裏是另一個解決方案,保留兩個應用程序,但不嘗試共享一個Battery實例,只需從CAN監聽器向您的GUI應用程序發出http請求。

例如,在CAN文件:

from tornado.httpclient import AsyncHTTPClient 

... 

def connection_ready(sock, fd, events): 
    while True: 
     try: 
      cf, addr = sock.recvfrom(can_frame_size) 
     except socket.error as e: 
      if e.args[0] not in (errno.EWOULDBLOCK, errno.EAGAIN): 
       raise 
      return 
     http_client = AsyncHTTPClient() 
     http_client.fetch("http://localhost:8888/update-battery", 
          method="POST", 
          body="can_id={}&can_dlc={}&data={}".format(
           dissect_can_frame(cf))) 

會更好,如果你有數據字節使用進行urlencode從蟒蛇urllib to encode body

在GUI文件:

class Battery_Update_Handler(web.RequestHandler): 
    def post(self): 
     self.application.battery0.status = dict(
      can_id=self.get_argument("can_id", None), 
      can_dlc=self.get_argument("can_dlc", None), 
      data=self.get_argument("data", None)) 


class Application(web.Application): 
    def __init__(self): 

     self.battery0 = Battery('bat0')  

     routing = [ 
      (r'/api/battery/(data|)', API_Handler), 
      (r'/update-battery', Battery_Update_Handler) 
     ] 

     settings = { 
      'template_path': os.path.join(os.path.dirname(__file__), "templates"), 
      'static_path': os.path.join(os.path.dirname(__file__), "static"), 
     } 

     web.Application.__init__(self, routing, debug=True, **settings) 
+0

如果CAN總線在一秒鐘內收到1000條消息,如果我們使用POST方法會不會很慢? –

+0

這是一種理論問題。我沒有使用CAN,因此檢出了維基百科,發現其最高速度爲1Mb/s,而訪問本地主機的速度受CPU速度的限制([根據此](http://serverfault.com/questions/234223/how -fast-is-127-0-0-1))因此你不應該面臨速度問題。無論如何嘗試實現它並通過CAN模擬大量輸入數據,如果我的假設錯誤,我們可以堅持第一個解決方案。 – sanddog

+0

實際上,大多數IO來自CAN總線而不是HTTP請求。無論如何,我會先做模擬,謝謝。 –