'Tornado on Raspberry Pi to use websockets as well as monitor serial port Arduino communication
Essentially, what I'm hoping to achieve is a canvas based web interface to control an Arduino, via a Raspberry Pi. The use case is that a user navigates to raspberrypi:8080 which displays a canvas. Then upon moving a slider, a websocket message is sent to the Tornado server on the Raspberry Pi. Tornado then sends a serial message to the Arduino which changes the RGB value of an LED. So far so good, I've been able to do this with the help of the documentation by a developer, Raspberry Pi Android HTML5 Realtime Servo Control.
However, the communication is only one-way from Raspberry Pi to Arduino. I'd like Tornado to also monitor the serial port to get any sensor data back to the front-end. Here's where I'm unsure about how to proceed. I was able to accomplish something like this using Node.js, which monitors for both websocket messages as well as serial messages asynchronously.
Should an asynchronous process be spawned which constantly monitors the port? I've seen a couple of options for this sort of solution.
- Some people suggest
tornado.gen.Task, but for single HTTP requests, not for constant serial data. tornado.ioloop.PeriodicCallbackwhich I could set up to check for serial data every millisecond, but that sounds like a lot of overhead.I've also seen separate tools such as Swirl.(Swirl is outdated according to it's Github repo)
Or should I set up a separate Python application which monitors serial and then communicates to the Tornado application on something it can understand like the following?
- websocket messages using a websocket client
- ZeroMQ (working example: pyzmq / examples / eventloop / web.py)
So there are lots of options... What are some recommendations and some reasons to try out or avoid any of the above options?
Here's what I have and need to add serial monitoring to:
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.websocket
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)
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)
]
)
httpServer = tornado.httpserver.HTTPServer(app)
httpServer.listen(options.port)
print "Listening on port:", options.port
tornado.ioloop.IOLoop.instance().start()
Solution 1:[1]
Here are my 2 cents. I would advocate for the Python -> websockets-client route. The Tornado server software is made and tuned to handle web client requests. Let it do it's job. Any attempt to shoehorn it into another role (like monitoring local hardware) is going to cause more overhead than something which is either (a) designed to do such a job (like a C/C++ program) or (b) flexible enough to handle such a task with fairly little overhead (like a Python script).
Relevant Experience: Have programmed for both Raspberry Pi and Arduino. Officer in local robotics club.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Joshua Whitley |
