aboutsummaryrefslogtreecommitdiffstats
path: root/fg21sim/webui/websocket.py
diff options
context:
space:
mode:
authorAaron LI <aaronly.me@outlook.com>2016-11-04 13:28:19 +0800
committerAaron LI <aaronly.me@outlook.com>2016-11-04 13:59:03 +0800
commit54b756d88b72eb07f4ee9fbb6b5f9d35ae1484a3 (patch)
treeb4644a671743e8ba41c1920e5cee513cc946dc1c /fg21sim/webui/websocket.py
parentdee4165ac47a8184ea8ae0876bd45364ba40affa (diff)
downloadfg21sim-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.py121
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