I am trying to build a websocket server to run on the Raspberry Pi. The websocket server has to push periodic realtime update to a browser. Here is a sample code that I am planning to use. The example code here sends the current time instead of sensor data.Most of the code is built form an example. However, what I need feedback on is The way stpoll is coded (sensor status poll)The global variable that passes the message to terminate the thread. I don't like it. Is there a better way to terminate a task that runs forever?The way the time (sensor data) is broadcasted to all connected clients. (another global variable) I had to code this without much documentation.# -*- coding: utf-8 -*-import argparseimport randomimport osimport timeimport threadingimport signalimport sysimport cherrypyfrom ws4py.server.cherrypyserver import WebSocketPlugin, WebSocketToolfrom ws4py.websocket import WebSocketfrom ws4py.messaging import TextMessageclass ChatWebSocketHandler(WebSocket):    def received_message(self, m):        cherrypy.engine.publish('websocket-broadcast', m)    def closed(self, code, reason=A client left the room without a proper explanation.):        cherrypy.engine.publish('websocket-broadcast', TextMessage(reason))class Root(object):    def __init__(self, host, port, ssl=False):        self.host = host        self.port = port        self.scheme = 'wss' if ssl else 'ws'    @cherrypy.expose    def index(self):        return <html>    <head>      <script type='application/javascript' src='https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js'></script>      <script type='application/javascript'>        $(document).ready(function() {          websocket = '%(scheme)s://%(host)s:%(port)s/ws';          if (window.WebSocket) {            ws = new WebSocket(websocket);          }          else if (window.MozWebSocket) {            ws = MozWebSocket(websocket);          }          else {            console.log('WebSocket Not Supported');            return;          }          window.onbeforeunload = function(e) {            $('#chat').val($('#chat').val() + 'Bye bye...\\n');            ws.close(1000, '%(username)s left the room');            if(!e) e = window.event;            e.stopPropagation();            e.preventDefault();          };          ws.onmessage = function (evt) {             $('#chat').val($('#chat').val() + evt.data + '\\n');          };          ws.onopen = function() {             ws.send(%(username)s entered the room);          };          ws.onclose = function(evt) {             $('#chat').val($('#chat').val() + 'Connection closed by server: ' + evt.code + ' \' + evt.reason + '\\\n');          };          $('#send').click(function() {             console.log($('#message').val());             ws.send('%(username)s: ' + $('#message').val());             $('#message').val();             return false;          });        });      </script>    </head>    <body>    <form action='#' id='chatform' method='get'>      <textarea id='chat' cols='35' rows='10'></textarea>      <br />      <label for='message'>%(username)s: </label><input type='text' id='message' />      <input id='send' type='submit' value='Send' />      </form>    </body>    </html>     % {'username': User%d % random.randint(0, 100), 'host': self.host, 'port': self.port, 'scheme': self.scheme}    @cherrypy.expose    def ws(self):        cherrypy.log(Handler created: %s % repr(cherrypy.request.ws_handler))def stpoll(arg):  global pollStatus  while pollStatus:    tm=time.localtime();    print tm.tm_sec    if 'WebSocket' in globals():      print WS !      cherrypy.engine.publish('websocket-broadcast', '%s ' %tm)    time.sleep(2)  print exitting theraddef signal_handler(signal, frame):  global pollStatus  pollStatus=False  cherrypy.engine.stop()  cherrypy.engine.exit()  print('You pressed Ctrl+C!')if __name__ == '__main__':  import logging  from ws4py import configure_logger  configure_logger(level=logging.DEBUG)  signal.signal(signal.SIGINT, signal_handler)  pollStatus=True   thread = threading.Thread(target = stpoll, args = (10, ))  thread.daemon = True  thread.start()  parser = argparse.ArgumentParser(description='Echo CherryPy Server')  parser.add_argument('--host', default='127.0.0.1')  parser.add_argument('-p', '--port', default=9000, type=int)  parser.add_argument('--ssl', action='store_true')  args = parser.parse_args()  cherrypy.config.update({'server.socket_host': args.host,                          'server.socket_port': args.port,                          'tools.staticdir.root': os.path.abspath(os.path.join(os.path.dirname(__file__), 'static'))})  if args.ssl:      cherrypy.config.update({'server.ssl_certificate': './server.crt',                              'server.ssl_private_key': './server.key'})  WebSocketPlugin(cherrypy.engine).subscribe()  cherrypy.tools.websocket = WebSocketTool()  cherrypy.quickstart(Root(args.host, args.port, args.ssl), '', config={      '/ws': {          'tools.websocket.on': True,          'tools.websocket.handler_cls': ChatWebSocketHandler          },      '/js': {            'tools.staticdir.on': True,            'tools.staticdir.dir': 'js'          }      }  )  thread.join()
Websocket-based server for Raspberry Pi
python;embedded;websocket;cherrypy;raspberry pi
Your code is nice, but it could use a few changes:% {}: rather than using that formatting method, you should use the string.format() method, involving {0} {1} instead of % as it is recommended by PEP8, Python's official style guide.print exitting therad: both exiting and thread are spelt incorrectlyglobal pollStatus: you shouldn't be naming your variables like camelCase, rather snake_case instead, as also expressed by PEP8tm=time.localtime(): you should have whitespace between your binary operators, and also you shouldn't abbreviate your variables like tm: local_time would be much better.Other than that, your code looks nice, well done!