Implemented keep alive heartbeat
authorJoseph Coffland <joseph@cauldrondevelopment.com>
Wed, 22 Jun 2016 21:24:16 +0000 (14:24 -0700)
committerJoseph Coffland <joseph@cauldrondevelopment.com>
Wed, 22 Jun 2016 21:24:16 +0000 (14:24 -0700)
src/js/control-view.js
src/js/sock.js [new file with mode: 0644]
src/py/bbctrl/Web.py

index fb90fd067e05afde36f8ec679ed3146a0e9e24f8..289e6fe89ec59530d69d6922ac151e191d5e3f21 100644 (file)
@@ -1,6 +1,7 @@
 'use strict'
 
 var api = require('./api');
+var Sock = require('./sock');
 
 
 function is_array(x) {
@@ -63,11 +64,10 @@ module.exports = {
 
   methods: {
     connect: function () {
-      this.sock = new SockJS('//' + window.location.host + '/ws');
+      this.sock = new Sock('//' + window.location.host + '/ws');
 
       this.sock.onmessage = function (e) {
         var data = e.data;
-        console.debug('msg: ' + JSON.stringify(data));
 
         if (typeof data == 'object')
           for (var key in data)
@@ -80,7 +80,6 @@ module.exports = {
 
       this.sock.onclose = function (e) {
         this.status = 'disconnected';
-        setTimeout(this.connect, 2000);
       }.bind(this);
     },
 
diff --git a/src/js/sock.js b/src/js/sock.js
new file mode 100644 (file)
index 0000000..244a046
--- /dev/null
@@ -0,0 +1,87 @@
+'use strict'
+
+
+var Sock = function (url, retry, timeout) {
+  if (!(this instanceof Sock)) return new Sock(url, retry);
+
+  if (typeof retry == 'undefined') retry = 2000;
+  if (typeof timeout == 'undefined') timeout = 5000;
+
+  this.url = url;
+  this.retry = retry;
+  this.timeout = timeout;
+
+  this.connect();
+}
+
+
+Sock.prototype.onmessage = function () {}
+Sock.prototype.onopen = function () {}
+Sock.prototype.onclose = function () {}
+
+
+Sock.prototype.connect = function () {
+  console.debug('connecting to', this.url);
+  this.close();
+
+  this._sock = new SockJS(this.url);
+
+  this._sock.onmessage = function (e) {
+    console.debug('msg:', e.data);
+    this._set_timeout();
+    this.onmessage(e);
+  }.bind(this);
+
+
+  this._sock.onopen = function () {
+    console.debug('connected');
+    this._set_timeout();
+    this.onopen();
+  }.bind(this);
+
+
+  this._sock.onclose = function () {
+    console.debug('disconnected');
+    this._cancel_timeout();
+
+    this.onclose();
+    if (typeof this._sock != 'undefined')
+      setTimeout(this.connect.bind(this), this.retry);
+  }.bind(this);
+}
+
+
+Sock.prototype._set_timeout = function () {
+  this._cancel_timeout();
+  this._timeout = setTimeout(this._timedout.bind(this), this.timeout);
+}
+
+
+Sock.prototype._timedout = function () {
+  console.debug('connection timedout');
+  this._timeout = undefined;
+  this._sock.close();
+}
+
+
+Sock.prototype._cancel_timeout = function () {
+  clearTimeout(this._timeout);
+  this._timeout = undefined;
+}
+
+
+Sock.prototype.close = function () {
+  if (typeof this._sock != 'undefined') {
+    var sock = this._sock;
+    this._sock = undefined;
+    sock.close();
+  }
+}
+
+
+Sock.prototype.send = function (msg) {
+  this._sock.send(msg);
+}
+
+
+module.exports = Sock
index 3ac8ece3ad0fe72987b6413758c091f9a7738347..cbd511f2602dcd1a105db6005ec8ca23bca6d594 100644 (file)
@@ -114,17 +114,31 @@ class FileHandler(APIHandler):
 
 
 class Connection(sockjs.tornado.SockJSConnection):
+    def heartbeat(self):
+        self.timer = self.app.ioloop.call_later(3, self.heartbeat)
+        self.send_json({'heartbeat': self.count})
+        self.count += 1
+
+
+    def send_json(self, data):
+        self.send(str.encode(json.dumps(data)))
+
+
     def on_open(self, info):
-        self.session.server.app.clients.append(self)
-        self.send(str.encode(json.dumps(self.session.server.app.state)))
+        self.app = self.session.server.app
+        self.timer = self.app.ioloop.call_later(3, self.heartbeat)
+        self.count = 0;
+        self.app.clients.append(self)
+        self.send_json(self.session.server.app.state)
 
 
     def on_close(self):
-        self.session.server.app.clients.remove(self)
+        self.app.ioloop.remove_timeout(self.timer)
+        self.app.clients.remove(self)
 
 
     def on_message(self, data):
-        self.session.server.app.input_queue.put(data + '\n')
+        self.app.input_queue.put(data + '\n')
 
 
 
@@ -135,7 +149,7 @@ class Web(tornado.web.Application):
                   encoding = 'utf-8') as f:
             self.config_template = json.load(f)
 
-
+        self.ioloop = ioloop
         self.state = {}
         self.clients = []