function WearScriptConnection(ws, group, device, onopen) { this.ws = ws; this.group = String(group); this.device = String(device); this.groupDevice = this.group + ':' + this.device; this._channelsInternal = {}; this.deviceToChannels = {}; this._externalChannels = {}; this._onopen = onopen || function (event) {}; this.exists = function (channel) { return channel == 'subscriptions' || !!this._exists(channel, this._externalChannels); } this.channelsInternal = function() { return this._keys(this._channelsInternal); } this.channelsExternal = function() { return this.deviceToChannels; } this.onopen = function (event) { console.log("wsclient: onopen"); this.publish('subscriptions', this.groupDevice, this._keys(this._channelsInternal)); this._onopen(event); } this.receive = function (event) { a = event; console.log('here:' + event) var reader = new FileReader(); reader.addEventListener("loadend", function () { var data = msgpack.unpack(reader.result); if (data[0] == 'subscriptions') { this.deviceToChannels[data[1]] = data[2]; var externalChannels = {}; for (var key in this.deviceToChannels) { if (!this.deviceToChannels.hasOwnProperty(key)) continue; var value = this.deviceToChannels[key]; for (var i = 0; i < value.length; i++) { externalChannels[value[i]] = true; } } this._externalChannels = externalChannels; } var match = this._exists(data[0], this._channelsInternal); if (match) { match.apply(null, data); } }.bind(this)); reader.readAsBinaryString(event.data); } ws.onopen = this.onopen.bind(this); ws.onmessage = this.receive.bind(this); this._exists = function (channel, container) { var channelCur = ''; var parts = channel.split(':'); var match; for (var i = 0; i < parts.length; i++) { if (container.hasOwnProperty(channelCur)) match = container[channelCur]; if (!i) { channelCur += parts[i]; } else { channelCur += ':' + parts[i]; } } if (container.hasOwnProperty(channelCur)) match = container[channelCur]; return match; } this.channel = function () { return Array.prototype.slice.call(arguments).join(':'); } this.subchannel = function () { return self.groupDevice + ':' + Array.prototype.slice.call(arguments).join(':') } this.ackchannel = function (channel) { return channel + ':ACK'; } this._keys = function (obj) { var keys = []; for (var key in obj) if (obj.hasOwnProperty(key)) keys.push(key); return keys; } this.subscribe = function (channel, callback) { if (!this._channelsInternal.hasOwnProperty(channel)) { this._channelsInternal[channel] = callback; this.publish('subscriptions', this.groupDevice, this._keys(this._channelsInternal)); } else { this._channelsInternal[channel] = callback; } return this; } this.unsubscribe = function (channel) { if (this._channelsInternal.hasOwnProperty(channel)) { delete this._channelsInternal[channel] this.publish('subscriptions', this.groupDevice, this._keys(this._channelsInternal)); } return this; } this.publish = function () { console.log(arguments[0]); if (!this.exists(arguments[0]) || this.ws.readyState != 1) { return this; } console.log('Sending:' + arguments[0]); this.send.apply(this, arguments); return this; } this.send = function () { var data_enc = msgpack.pack(Array.prototype.slice.call(arguments)); var data_out = new Uint8Array(data_enc.length); var i; for (i = 0; i < data_enc.length; i++) { data_out[i] = data_enc[i]; } this.ws.send(data_out); } this.publish_retry = function (callback, retryTime, channel) { var args = Array.prototype.slice.call(arguments).slice(3); if (this._channelsInternal.hasOwnProperty(channel)) return; console.log('pub_ret'); if (retryTime < 200) retryTime = 200; var inner = function () { console.log('pub_ret0a'); if (!this._channelsInternal.hasOwnProperty(channel)) return; console.log('pub_ret0b'); this.publish.apply(this, args); retryTime *= 2; if (retryTime > 30000) retryTime = 30000; window.setTimeout(inner, retryTime); }.bind(this); var listener = function () { console.log('pub_ret1'); console.log('listener: result'); this.unsubscribe(channel); callback.apply(null, Array.prototype.slice.call(arguments)); }.bind(this); this.subscribe(channel, listener); inner(); } this.subscribeTestHandler = function () { var callback = function () { var data = Array.prototype.slice.call(arguments); console.log('Test callback got...') console.log(data) if (data[1] == 'subscribe') { this.subscribe(data[2], callback); } else if (data[1] == 'unsubscribe') { this.unsubscribe(data[2]); } else if (data[1] == 'channelsInternal') { this.publish(data[2], this.channelsInternal()); } else if (data[1] == 'channelsExternal') { this.publish(data[2], this.channelsExternal()); } else if (data[1] == 'group') { this.publish(data[2], this.group); } else if (data[1] == 'device') { this.publish(data[2], this.device); } else if (data[1] == 'groupDevice') { this.publish(data[2], this.groupDevice); } else if (data[1] == 'exists') { this.publish(data[2], this.exists(data[3])); } else if (data[1] == 'publish') { this.publish.apply(this, data.slice(2)); } else if (data[1] == 'channel') { this.publish(data[2], this.channel.apply(null, data.slice(3))); } else if (data[1] == 'subchannel') { this.publish(data[2], this.subchannel(data[3])); } else if (data[1] == 'ackchannel') { this.publish(data[2], this.ackchannel(data[3])); } }.bind(this); this.subscribe('test:' + this.groupDevice, callback); } // NOTE(brandyn): Loop and republish subscriptions to keep connection alive setInterval(function () { this.publish('subscriptions', this.groupDevice, this._keys(this._channelsInternal)); }.bind(this), 60000); }