2016-03-23 5 views
0

私はBeaglebone BlackをCANバスデバイスに接続しました:バッテリー。複数のioloopをトルネードで使用し、ioloop間でデータを共有するにはどうすればよいですか?

GUIとしてBeaglebone Blackで動作する竜巻ウェブ。

CANバス読み取りループはバッテリーインスタンスのステータス

を更新するために、CANバスからデータを読み続けるしかし、どのように私は2つの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

ユーザーが送信しなければならない理由[WebSocketを](https://en.wikipedia.org/wiki/WebSocket)が可能なトルネードを、使用している場合ステータスを取得するコマンドですか?指定された頻度でバッテリ状態を読み、websocket接続を介して自動的にブラウザを更新するスレッドを開始するだけです。 – yegorich

+0

@yegorich私はあなたの懸念を知っています。これはcmdの単なる例です。私はまた多くのcmdを持っています。別の理由は、内部のデータがずっと頻繁に変更されることですが、GUIは同じ頻度で更新する必要はありません。第3の理由は、これにより、同じAPIを使用する他のモジュールが独自の頻度でデータを要求できることです。 –

答えて

0

共有することは困難になりますので、私は、次の2つのアプリケーションを実行している見ることができるようにバッテリのインスタンス。最初の解決方法 - 1つのアプリケーションですべての機能を組み合わせることで、バッテリインスタンスを簡単に利用できますが、HTTPリクエストを処理し、CANのソケットイベントを1つのioloopで処理するという課題に直面します。

これは別の解決策ですが、2つのアプリケーションを保ちますが、バッテリーインスタンスを共有しようとしません。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))) 

あなたはデータのバイトを持っている場合のpython urllib to encode bodyからでurlencodeを使用する方がよいでしょう。 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バスが1秒間に1000個のメッセージを受信すると、POSTメソッドを使用すると遅くなりますか? –

+0

それは理論的な質問の一種です。私はCANを使用していないので、wikipediaをチェックアウトし、最大速度1Mb/sであることがわかりました。一方、ローカルホストへのアクセス速度はCPU速度によって制限されています([これに従う](http://serverfault.com/questions/234223/how -fast-is-127-0-0-1))したがって、スピードの問題に直面してはいけません。とにかくそれを実装し、CANを介して大量の受信データをシミュレートしてください。私の前提が間違っていれば、最初の解決策に固執することができます。 – sanddog

+0

実際、IOの大半はHTTPリクエストではなくCANバスからのものです。とにかく、私は最初にシミュレーションを行います、ありがとう。 –

関連する問題