diff options
author | Aaron LI <aaronly.me@outlook.com> | 2016-11-04 13:28:19 +0800 |
---|---|---|
committer | Aaron LI <aaronly.me@outlook.com> | 2016-11-04 13:59:03 +0800 |
commit | 54b756d88b72eb07f4ee9fbb6b5f9d35ae1484a3 (patch) | |
tree | b4644a671743e8ba41c1920e5cee513cc946dc1c /fg21sim/webui/websocket.py | |
parent | dee4165ac47a8184ea8ae0876bd45364ba40affa (diff) | |
download | fg21sim-54b756d88b72eb07f4ee9fbb6b5f9d35ae1484a3.tar.bz2 |
webui: Update server & client sides WebSocket handlers
* Server side:
+ Update the "on_message()" method to support 3 types of message
requests (i.e., "configs", "console", and "results");
+ Add messages stub handlers: "_handle_{configs,console,results}()";
+ Reorder the methods
+ Client side:
+ Change timeout before reconnection to 3000 ms;
+ Parse the received JSON message to JS object;
Diffstat (limited to 'fg21sim/webui/websocket.py')
-rw-r--r-- | fg21sim/webui/websocket.py | 121 |
1 files changed, 100 insertions, 21 deletions
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 |