diff options
| -rw-r--r-- | fg21sim/webui/static/js/websocket.js | 7 | ||||
| -rw-r--r-- | fg21sim/webui/websocket.py | 121 | 
2 files changed, 104 insertions, 24 deletions
diff --git a/fg21sim/webui/static/js/websocket.js b/fg21sim/webui/static/js/websocket.js index 95e85f2..ae44410 100644 --- a/fg21sim/webui/static/js/websocket.js +++ b/fg21sim/webui/static/js/websocket.js @@ -16,7 +16,7 @@ var ws = null;  /* WebSocket */  var ws_reconnect = {    maxTry: 100,    tried: 0, -  timeout: 1000,  /* ms */ +  timeout: 3000,  /* ms */  }; @@ -130,8 +130,9 @@ var connectWebSocket = function (url) {      toggleWSReconnect("show");    };    ws.onmessage = function (e) { -    console.log("WebSocket received message:"); -    console.log(e.data); +    var msg = JSON.parse(e.data); +    console.log("WebSocket received message: type:", msg.type, +                ", status:", msg.status);    };  }; diff --git a/fg21sim/webui/websocket.py b/fg21sim/webui/websocket.py index 0677f83..d1501b5 100644 --- a/fg21sim/webui/websocket.py +++ b/fg21sim/webui/websocket.py @@ -17,10 +17,12 @@ References    http://caniuse.com/#feat=websockets  """ +import json  import logging  import tornado.websocket +from ..configs import ConfigManager  from .utils import get_host_ip @@ -47,30 +49,13 @@ class FG21simWSHandler(tornado.websocket.WebSocketHandler):      from_localhost : bool          Set to ``True`` if the access is from the localhost,          otherwise ``False``. +    configs : `~ConfigManager` +        A ``ConfigManager`` instance, for configuration manipulations when +        communicating with the Web UI.      """      name = "fg21sim"      from_localhost = None - -    def open(self): -        """Invoked when a new WebSocket is opened by the client.""" -        logger.info("WebSocket: %s: opened" % self.name) - -    def on_message(self, message): -        """Handle incoming messages.""" -        logger.info("WebSocket: %s: received: %s" % (self.name, message)) -        msg_back = message[::-1] -        logger.info("WebSocket: %s: sent: %s" % (self.name, msg_back)) -        self.write_message(msg_back) - -    def on_close(self): -        """Invoked when a new WebSocket is closed by the client.""" -        code, reason = None, None -        if hasattr(self, "close_code"): -            code = self.close_code -        if hasattr(self, "close_reason"): -            reason = self.close_reason -        logger.info("WebSocket: {0}: closed by client: {1}, {2}".format( -            self.name, code, reason)) +    configs = ConfigManager()      def check_origin(self, origin):          """Check the origin of the WebSocket access. @@ -98,3 +83,97 @@ class FG21simWSHandler(tornado.websocket.WebSocketHandler):              logger.error("WebSocket: %s: " % self.name +                           "ONLY allow access from localhost at the moment :(")              return False + +    def open(self): +        """Invoked when a new WebSocket is opened by the client.""" +        logger.info("WebSocket: %s: opened" % self.name) + +    def on_close(self): +        """Invoked when a new WebSocket is closed by the client.""" +        code, reason = None, None +        if hasattr(self, "close_code"): +            code = self.close_code +        if hasattr(self, "close_reason"): +            reason = self.close_reason +        logger.info("WebSocket: {0}: closed by client: {1}, {2}".format( +            self.name, code, reason)) + +    def on_message(self, message): +        """Handle incoming messages and dispatch task according to the +        message type. + +        NOTE +        ---- +        The received message (parsed to a Python dictionary) has a ``type`` +        item which will be used to determine the following action to take. + +        Currently supported message types are: +        ``configs``: +            Request or set the configurations +        ``console``: +            Control the simulation tasks, or request logging messages +        ``results``: +            Request the simulation results + +        The sent message also has a ``type`` item of same value, which the +        client can be used to figure out the proper actions. +        There is a ``status`` item which indicates the status of the +        requested operation, and a ``data`` item containing the response +        data. +        """ +        logger.debug("WebSocket: %s: received: %s" % (self.name, message)) +        try: +            msg = json.loads(message) +            msg_type = msg["type"] +        except json.JSONDecodeError: +            logger.warning("WebSocket: {0}: ".format(self.name) + +                           "message is not a valid JSON string") +        except (KeyError, TypeError): +            logger.warning("WebSocket: %s: skip invalid message" % self.name) +        finally: +            response = {"status": False, "type": None} +            msg_response = json.dumps(response) +            self.write_message(msg_response) +            return + +        # Check the message type and dispatch task +        if msg_type == "configs": +            # Request or set the configurations +            response = self._handle_configs(msg) +        elif msg_type == "console": +            # Control the simulation tasks, or request logging messages +            response = self._handle_console(msg) +        elif msg_type == "results": +            # Request the simulation results +            response = self._handle_results(msg) +        else: +            # Message of unknown type +            logger.warning("WebSocket: {0}: ".format(self.name) + +                           "message of unknown type: {0}".format(msg_type)) +            response = {"status": False, "type": msg_type} +        msg_response = json.dumps(response) +        self.write_message(msg_response) + +    def _handle_configs(self, msg): +        # Got a message of supported types +        msg_type = msg["type"] +        logger.info("WebSocket: {0}: ".format(self.name) + +                    "handle message of type: {0}".format(msg_type)) +        response = {"status": True, "type": msg_type} +        return response + +    def _handle_console(self, msg): +        # Got a message of supported types +        msg_type = msg["type"] +        logger.info("WebSocket: {0}: ".format(self.name) + +                    "handle message of type: {0}".format(msg_type)) +        response = {"status": True, "type": msg_type} +        return response + +    def _handle_results(self, msg): +        # Got a message of supported types +        msg_type = msg["type"] +        logger.info("WebSocket: {0}: ".format(self.name) + +                    "handle message of type: {0}".format(msg_type)) +        response = {"status": True, "type": msg_type} +        return response  | 
