UNPKG

7.41 kBJavaScriptView Raw
1'use strict';
2var util = require('util');
3var EventEmitter = require('events').EventEmitter;
4var socketIoClient = require("socket.io-client");
5
6var DEFAULT_TIMEOUT = 10000;
7
8function Connection(opt){
9
10 EventEmitter.call(this);
11
12 this._callbackHandlers = {};
13 this._ackId = 0;
14
15 this.options = opt || {};
16 this.options.options = this.options.options || {};
17
18 this.options.options.transports = this.options.options.transports || ['websocket'];
19 this.options.forceNew = (opt.forceNew != null) ? opt.forceNew : false;
20
21 this.options.server = this.options.server || 'ws://meshblu.octoblu.com';
22 this.options.port = this.options.port || 80;
23
24
25
26 // if(this.options.server && this.options.port){
27 if(this.options.server.indexOf("http") === -1 && this.options.server.indexOf("ws") === -1 && this.options.server.indexOf("wss") === -1 ){
28 this.options.server = "ws://" + this.options.server;
29 }
30 // network = this.options.server + ":" + this.options.port;
31 // }
32 var network = this.options.server + ':' + this.options.port;
33 console.log('trying', network);
34 this.socket = socketIoClient(network, this.options.options); // || "ws://skynet.im");
35
36 // this.socket = io.connect(this.options.server || "http://skynet.im", {
37 // port: this.options.port || 80,
38 // forceNew: this.options.forceNew,
39 // multiplex: !this.options.forceNew,
40 // 'force new connection': this.options.forceNew
41 // });
42
43 this.options.protocol = "websocket";
44 this.setup();
45}
46
47util.inherits(Connection, EventEmitter);
48
49Connection.prototype.setup = function(){
50 var self = this;
51 this.socket.once('connect', function(){
52 this.emit('connect');
53
54 this.socket.on('messageAck', function(data){
55 if(self._callbackHandlers[data.ack]){
56 try{
57 self._callbackHandlers[data.ack](data.payload);
58 delete self._callbackHandlers[data.ack];
59 }
60 catch(err){
61 console.log('error resolving callback', err);
62 }
63 }
64 });
65
66 this.socket.on('message', function(data){
67 self._handleAckRequest('message', data);
68 });
69
70 //this.emit.bind(this, 'message'));
71 this.socket.on('config', function(data){
72 self._handleAckRequest('config', data);
73 });
74
75 this.socket.on('disconnect', this.emit.bind(this, 'disconnect'));
76 this.socket.on('identify', this.identify.bind(this));
77 this.socket.on('ready', this.emit.bind(this, 'ready'));
78 this.socket.on('notReady', this.emit.bind(this, 'notReady'));
79 this.socket.on('tb', this.emit.bind(this, 'tb'));
80 this.socket.on('unboundSocket', this.emit.bind(this, 'unboundSocket'));
81
82 }.bind(this));
83
84 return this;
85};
86
87//Provide callback when message with ack requests comes in from another client
88Connection.prototype._handleAckRequest = function(topic, data){
89 var self = this;
90 if(data){
91 if(data.ack && data.fromUuid){
92 //TODO clean these up if not used
93 self.emit(topic, data, function(response){
94 self._messageAck({
95 devices: data.fromUuid,
96 ack: data.ack,
97 payload: response
98 });
99 });
100 }else{
101 self.emit(topic, data);
102 }
103 }
104};
105
106//Allow for making RPC requests to other clients
107Connection.prototype._emitWithAck = function(topic, data, fn){
108 var self = this;
109 if(data){
110 if(fn){
111 var ack = ++this._ackId;
112 data.ack = ack;
113 self._callbackHandlers[ack] = fn;
114 var timeout = data.timeout || DEFAULT_TIMEOUT;
115 //remove handlers
116 setTimeout(function(){
117 if(self._callbackHandlers[ack]){
118 self._callbackHandlers[ack]({error: 'timeout ' + timeout});
119 delete self._callbackHandlers[ack];
120 }
121 }, timeout);
122 }
123 //console.log('emitting ack', topic, data);
124 this.socket.emit(topic, data);
125 }
126 return this;
127};
128
129Connection.prototype._messageAck = function(response){
130 this.socket.emit('messageAck', response);
131 return this;
132};
133
134
135
136Connection.prototype.identify = function(){
137 this.socket.emit('identity', {
138 uuid: this.options.uuid,
139 token: this.options.token,
140 protocol: this.options.protocol
141 });
142 return this;
143};
144
145
146Connection.prototype.message = function(data, fn) {
147 return this._emitWithAck('message', data, fn);
148};
149
150Connection.prototype.config = function(data, fn) {
151 return this._emitWithAck('gatewayConfig', data, fn);
152};
153
154Connection.prototype.gatewayConfig = function(data, fn) {
155 return this._emitWithAck('gatewayConfig', data, fn);
156};
157
158// send plain text
159Connection.prototype.send = function(text) {
160
161 if(text){
162 text = text.toString();
163 this.socket.send(text);
164 }
165
166 return this;
167};
168
169Connection.prototype.update = function(data, fn) {
170 this.socket.emit('update', data, fn);
171 return this;
172};
173
174Connection.prototype.register = function(data, fn) {
175 this.socket.emit('register', data, fn);
176 return this;
177};
178
179Connection.prototype.unregister = function(data, fn) {
180 this.socket.emit('unregister', data, fn);
181 return this;
182};
183
184Connection.prototype.claimdevice = function(data, fn) {
185 this.socket.emit('claimdevice', data, fn);
186 return this;
187};
188
189Connection.prototype.whoami = function(data, fn) {
190 this.socket.emit('whoami', data, fn);
191 return this;
192};
193
194Connection.prototype.devices = function(data, fn) {
195 this.socket.emit('devices', data, fn);
196 return this;
197};
198
199Connection.prototype.mydevices = function(data, fn) {
200 this.socket.emit('mydevices', data, fn);
201 return this;
202};
203
204Connection.prototype.status = function(data) {
205 this.socket.emit('status', data);
206 return this;
207};
208
209Connection.prototype.subscribe = function(data, fn) {
210 if(typeof data === 'string'){
211 data = {uuid: data};
212 }
213 this.socket.emit('subscribe', data, fn);
214 return this;
215};
216
217Connection.prototype.unsubscribe = function(data, fn) {
218 if(typeof data === 'string'){
219 data = {uuid: data};
220 }
221 this.socket.emit('unsubscribe', data, fn);
222 return this;
223};
224
225Connection.prototype.authenticate = function(data, fn) {
226 this.socket.emit('authenticate', data, fn);
227 return this;
228};
229
230Connection.prototype.events = function(data, fn) {
231 this.socket.emit('events', data, fn);
232 return this;
233};
234
235Connection.prototype.data = function(data, fn) {
236 this.socket.emit('data', data, fn);
237 return this;
238};
239
240Connection.prototype.getdata = function(data, fn) {
241 this.socket.emit('getdata', data, fn);
242 return this;
243};
244
245Connection.prototype.localdevices = function(fn) {
246 this.socket.emit('localdevices', {}, fn);
247 return this;
248};
249
250Connection.prototype.textBroadcast = function(data) {
251 if(typeof data !== 'string'){
252 data = String(data);
253 }
254 this.socket.emit('tb', data);
255 return this;
256};
257
258Connection.prototype.directText = function(data) {
259 if(typeof data === 'object' && data.payload && typeof data.payload === 'string' && data.devices){
260 this.socket.emit('directText', data);
261 }
262 else{
263 console.log('directText requires an object with a string payload property, and a devices property');
264 }
265
266 return this;
267};
268
269Connection.prototype.subscribeText = function(data, fn) {
270 if(typeof data === 'string'){
271 data = {uuid: data};
272 }
273 this.socket.emit('subscribeText', data, fn);
274 return this;
275};
276
277Connection.prototype.unsubscribeText = function(data, fn) {
278 if(typeof data === 'string'){
279 data = {uuid: data};
280 }
281 this.socket.emit('unsubscribeText', data, fn);
282 return this;
283};
284
285
286Connection.prototype.close = function(fn){
287 this.socket.close(fn);
288 return this;
289};
290
291
292
293module.exports = Connection;