Added wifi settings and dummy data
[profile/ivi/SettingsApp.git] / js / websocket.js
1 /*
2  * Copyright (c) 2013, Intel Corporation.
3  *
4  * This program is licensed under the terms and conditions of the
5  * Apache License, version 2.0.  The full text of the Apache License is at
6  * http://www.apache.org/licenses/LICENSE-2.0
7  *
8  */
9
10 /* Dummy backend for faking websocket daemon */
11 var dummyBackend = true;
12
13 var WS_REQUEST_TYPE = {
14     WIFI: 0,
15     BLUETOOTH: 1,
16     DISPLAY: 2,
17     SOUND: 3,
18     DATETIME: 4,
19     LOCALE: 5
20 };
21
22 var WS_EVENT_TYPE = {
23     WIFI: 0,
24     BLUETOOTH: 1,
25     DISPLAY: 2,
26     SOUND: 3,
27     DATETIME: 4,
28     LOCALE: 5
29 };
30
31 /* web socket module to connect to the settings daemon */
32 var wsAPI = (function() {
33     /* number of connection retries to attempt if the socket closes */
34     var self = this;
35     this.connected = false;
36     this.event_callbacks = $.Callbacks();
37
38     /* default values for WebSocket */
39     this.socketUrl = 'ws://localhost:16000/';
40     this.socketProtocol = 'http-only';
41
42     this.methodIdx = 0;
43     this.methodCalls = [];
44     for (var i = 0; i < 100; i++) {
45         this.methodCalls[i] = null;
46     }
47
48     this.MethodCall = function(id, name, success_cb, error_cb) {
49         var me = this;
50         this.successCB = success_cb;
51         this.errorCB = error_cb;
52         this.transactionid = id;
53         this.name = name;
54         this.done = false;
55         this.start = function() {
56             me.timeout = setTimeout(function() {
57                 if (me.errorCB !== undefined) {
58                     me.errorCB('\"' + me.name + '\" method timed out after ' + self.timeouttime + 'ms');
59                 }
60                 me.finish();
61             }, self.timeouttime);
62         }
63         this.finish = function() {
64             if (me.timeout !== undefined) {
65                 clearTimeout(me.timeout);
66             }
67             me.done = true;
68         }
69     }
70
71     this.EventObject = function(type, name, value) {
72         var me = this;
73         this.type = type;
74         this.name = name;
75         this.value = value;
76     }
77
78     function connect(url, protocol, sucess_cb, error_cb) {
79         self.socketUrl = typeof url !== 'undefined' ? url : self.socketUrl;
80         self.socketProtocol = typeof protocol !== 'undefined' ? protocol : self.socketProtocol;
81         self.successCB = sucess_cb;
82         self.errorCB = error_cb;
83
84         if ('WebSocket' in window) {
85             if (self.socketProtocol.length > 0) {
86                 self.socket = new WebSocket(self.socketUrl, self.socketProtocol);
87             } else {
88                 self.socket = new WebSocket(self);
89             }
90             console.log('Connecting to websocket: ' + self.socketUrl);
91
92             self.socket.onopen = function() {
93                 self.connected = true;
94                 console.log('websocket opened');
95                 self.successCB();
96             };
97
98             self.socket.onclose = function() {
99                 self.connected = false;
100                 console.log('websocket closed');
101
102                 if (dummyBackend) {
103                     /* fake the connection for dummy backend */
104                     self.connected = true;
105                     self.successCB();
106                     return;
107                 }
108
109                 self.errorCB('Disconnected from settings daemon');
110             };
111
112             self.socket.onerror = function(e) {
113                 console.log('web socket error: ', e.data);
114
115                 if (dummyBackend) {
116                     /* ignore websocket error */
117                     return;
118                 }
119
120                 if (e.data) {
121                     self.errorCB('websocket error: ' + e.data);
122                 } else {
123                     self.errorCB('websocket error: unknown');
124                 }
125             };
126
127             self.socket.onmessage = function(e) {
128                 self.receive(e.data);
129             };
130         } else {
131             console.log('Websockets not supported');
132         }
133     }
134
135     function send(msg, success_cb, error_cb) {
136         if (!this.connected) {
137             if (errorCB !== undefined) {
138                 errorCB('Settings daemon is not connected');
139             }
140             return;
141         }
142         var i = this.methodIdx;
143         this.methodIdx = (this.methodIdx + 1) % 100;
144         this.methodCalls[i] = new this.MethodCall(msg.transactionid, msg.name, success_cb, error_cb);
145         this.methodCalls[i].start();
146
147         var jsonMsg = JSON.stringify(msg);
148         console.log('Sending json msg: ' + jsonMsg);
149         if (dummyBackend) {
150             /* fake with dummy data */
151             dummyBackendSend(msg);
152         } else {
153             this.socket.send(jsonMsg);
154         }
155     }
156
157     function fireEvent(type, name, value) {
158         var event = new this.EventObject(type, name, value);
159         console.log('Fire event: [' + type + ', ' + name + ', ' + value + ']');
160         event_callbacks.fire(event);
161     }
162
163     function receive(msg) {
164         var self = this;
165         var event;
166         try {
167             console.log("Received json msg: " + msg);
168             event = JSON.parse(msg);
169         } catch (e) {
170             self.iErrorCB('GARBAGE MESSAGE: ' + msg);
171             return;
172         }
173
174         if ((event === undefined) || (event.type === undefined) || (event.name === undefined)) {
175             self.iErrorCB('BADLY FORMED MESSAGE: ' + msg);
176             return;
177         } else {
178             if (event.type === 'methodReply') {
179                 var calls = this.methodCalls;
180                 for (var i = 0; i < calls.length; i++) {
181                     var call = calls[i];
182                     if (call && (!call.done) && (call.transactionid === event.transactionid)) {
183                         call.finish();
184                         if (event.error !== undefined) {
185                             call.errorCB(event.error);
186                         }
187                         if (event.data !== undefined && call.successCB !== undefined) {
188                             call.successCB(event.data);
189                         }
190                         return;
191                     }
192                 }
193             } else if (event.type === 'event') {
194                 self.fireSevent(event.name, event.data);
195             }
196         }
197     }
198
199     function generateTransactionId() {
200         var i, val = [];
201         for (i = 0; i < 8; i++) {
202             var num = Math.floor((Math.random() + 1) * 65536);
203             val[i] = num.toString(16).substring(1);
204         }
205         var uuid = val[0] + val[1] + '-' + val[2] + '-' + val[3] + '-' + val[4] + '-' + val[5] + val[6] + val[7];
206         return uuid;
207     }
208
209     function sendRequest(request_type, request_name, request_args, success_cb, error_cb) {
210         var msg = {
211             'type': request_type,
212             'name': request_name,
213             'transactionid': generateTransactionId(),
214             'data': request_args
215         };
216
217         send(msg, success_cb, error_cb);
218     }
219
220     function subscribeEvents(callback) {
221         event_callbacks.add(callback);
222     }
223
224     function unsubscribeEvents(callback) {
225         event_callbacks.remove(callback);
226     }
227
228     /* this is dummy data for testing purposes */
229     function dummyBackendSend(msg) {
230         if (dummyBackend) {
231             console.log('Sending to dummy server');
232
233             var calls = this.methodCalls;
234             var replyMsg = null;
235
236             for (var i = 0; i < calls.length; i++) {
237                 var call = calls[i];
238                 if (call && (!call.done) && (call.transactionid === msg.transactionid)) {
239                     call.finish();
240                     if (msg.error !== undefined) {
241                         call.errorCB(msg.error);
242                     }
243                     if (msg.data !== undefined && call.successCB && call.errorCB !== undefined) {
244                         var replyDelay = 0;
245
246                         switch (msg.type) {
247                         case WS_REQUEST_TYPE.WIFI:
248                             if (msg.name === 'isEnabled') {
249                                 /* default to enabled */
250                                 var results = {
251                                     'isEnabled': true
252                                 };
253                                 replyMsg = JSON.stringify(results);
254                             } else if (msg.name === 'enable') {
255                                 if (msg.data === true) {
256                                     fireEvent(WS_EVENT_TYPE.WIFI, 'enabled', true);
257                                 } else {
258                                     fireEvent(WS_EVENT_TYPE.WIFI, 'enabled', false);
259                                 }
260                             } else if (msg.name === 'scan') {
261                                 var results = {
262                                     'access_points': [{
263                                         'ssid': 'Access Point 1',
264                                         'connected': true
265                                     }, {
266                                         'ssid': 'Access Point 2',
267                                         'connected': false
268                                     }, {
269                                         'ssid': 'Access Point 3',
270                                         'connected': false
271                                     }, {
272                                         'ssid': 'Access Point 4',
273                                         'connected': false
274                                     }]
275                                 }
276                                 replyMsg = JSON.stringify(results);
277                                 /* simulate scan behavior */
278                                 replyDelay = 2000;
279                             } else if (msg.name === 'connect') {
280                                 replyMsg = msg.data;
281                                 fireEvent(WS_EVENT_TYPE.WIFI, 'connecting', replyMsg);
282                                 setTimeout(function() {
283                                     fireEvent(WS_EVENT_TYPE.WIFI, 'connected', replyMsg);
284                                 }, 1000);
285                             } else if (msg.name === 'disconnect') {
286                                 replyMsg = msg.data;
287                                 fireEvent(WS_EVENT_TYPE.WIFI, 'disconnecting', replyMsg);
288                                 setTimeout(function() {
289                                     fireEvent(WS_EVENT_TYPE.WIFI, 'disconnected', replyMsg);
290                                 }, 1000);
291                             } else {
292                                 call.errorCB('Unsupported request name: ' + msg.name);
293                                 return;
294                             }
295                             break;
296                         case WS_REQUEST_TYPE.BLUETOOTH:
297                             if (msg.name === 'enable') {
298                                 fireEvent(WS_EVENT_TYPE.BLUETOOTH, 'enabled', true);
299                             } else if (msg.name === 'disable') {
300                                 fireEvent(WS_EVENT_TYPE.BLUETOOTH, 'enabled', false);
301                             } else {
302                                 call.errorCB('Unsupported request name: ' + msg.name);
303                                 return;
304                             }
305                             break;
306                         case WS_REQUEST_TYPE.DISPLAY:
307                         case WS_REQUEST_TYPE.SOUND:
308                         case WS_REQUEST_TYPE.DATETIME:
309                         case WS_REQUEST_TYPE.LOCALE:
310                             call.errorCB('Request not implemented');
311                             return;
312                         default:
313                             call.errorCB('Invalid request type: ' + msg.type);
314                             return;
315                         }
316                         setTimeout(function() {
317                             call.successCB(replyMsg);
318                         }, replyDelay);
319                     }
320                     return;
321                 }
322             }
323         }
324     }
325
326     return {
327         connect: connect,
328         sendRequest: sendRequest,
329         subscribeEvents: subscribeEvents
330     }
331 })();