2 * Copyright (c) 2013, Intel Corporation.
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
9 var connmanScanInProgress = false;
11 function connmanPanelInit() {
13 /* Connman Settings Panel */
14 $('#page_connman').on('pageshow', function(event, data) {
15 if (data.prevPage.attr('id') === 'page_connman_service') return;
17 wsAPI.subscribeEvents(connmanEventReceived);
19 console.log('Get all the available technologies');
20 $('#connman_technologies').html('');
21 settings.connman.getTechnologies(function(technologies) {
22 for (var i = 0; i < technologies.length; i++) {
23 var technology = technologies[i];
24 console.log('Connman technology found: ' + technology.prop.Type);
25 if (technology.prop.Type === 'bluetooth') {
26 /* Do not show bluetooth */
29 if (technology.prop.Powered === undefined) {
31 t.getPowered(function(is_powered) {
32 t.prop.Powered = is_powered;
33 connmanConstructTechnologyElement(t);
35 t.prop.Powered = false;
36 connmanConstructTechnologyElement(t);
40 connmanConstructTechnologyElement(technology);
48 $('#button_connman_refresh').on('click', function() {
49 /* connman only supports wifi scan */
50 if ($('#toggle_connman_wifi').val() === 'on') {
51 connmanScan('/net/connman/technology/wifi');
53 connmanSync(null, function(e) {
59 $('#button_connman_wifi_add').on('click', function() {
60 if (connmanScanInProgress) return;
62 console.log('Enter add WiFi page');
63 $.mobile.changePage('#page_wifi_add');
66 /* Connman service detail page */
67 $('#page_connman_service').on('pageshow', function(event, data) {
68 var service_id = localStorage.getItem('connman_service_id');
69 if (service_id == undefined) return;
70 var service = $(jqId(service_id)).data('service-object');
71 connmanConstructServicePanel(service);
74 /* WiFi add new network page */
75 $('#page_wifi_add').on('pagebeforeshow', function(event, data) {
76 $('#input_wifi_add_ssid').val('');
77 $('#input_wifi_add_password').val('');
78 $('#radio_wifi_none').prop('checked', true);
79 $('input[name=radio_wifi_security]').checkboxradio('refresh');
80 $('#input_wifi_add_password').textinput('disable');
83 $('#button_wifi_add').on('click', function() {
84 var name = $('#input_wifi_add_ssid').val();
85 var security = $('input[name=radio_wifi_security]:checked').val();
86 var passcode = $('#input_wifi_add_password').val();
89 showMsg('Error', 'Enter SSID');
93 if (security !== 'none' && passcode === '') {
94 showMsg('Error', 'Enter passphrase');
98 showSpinner(false, 'Adding...');
99 connmanGetHiddenServicePath(security, function(service_path) {
100 var service = new settings.connman.ConnmanService('', {
102 'EncryptionMode': security
104 service.connect(passcode, function() {
106 connmanSync(function() {
108 console.log('Go back to Connman page');
109 $.mobile.changePage('#page_connman');
116 showMsg('Error', 'Failed to add network: ' + e);
124 $('[name="radio_wifi_security"]').on('change', function(event, data) {
125 var security = $('input[name=radio_wifi_security]:checked').val();
127 if (security === 'none') {
128 $('#input_wifi_add_password').textinput('disable');
129 $('#input_wifi_add_password').val('');
131 $('#input_wifi_add_password').textinput('enable');
135 $('#button_wifi_connect').on('click', function() {
136 var service_id = localStorage.getItem('connman_service_id');
137 if (service_id == undefined) return;
138 var service = $(jqId(service_id)).data('service-object');
139 var passcode = $('#input_wifi_connect_passphrase').val();
140 connmanConnectToService(service, passcode, function() {
141 console.log('Successfully connected to service: ' + service.prop.Name);
142 if ($.mobile.activePage.attr('id') !== 'page_connman') {
143 console.log('Go back to Connman page');
144 $.mobile.changePage('#page_connman');
147 showMsg('Error', 'Connect service failed: ' + e);
152 function connmanEventReceived(event) {
153 if (event.type === WS_EVENT_TYPE.CONNMAN) {
154 if ($.mobile.activePage.attr('id') !== 'page_connman' && $.mobile.activePage.attr('id') !== 'page_connman_service') {
158 if (event.name === 'ServicesChanged') {
159 connmanHandleServicesChanged(event.id, event.value);
160 } else if (event.name === 'PropertyChanged') {
161 connmanHandlePropertyChanged(event.id, event.value);
163 console.log('Unsupported event received: ' + event.name);
168 function connmanHandleServicesChanged(object_path, services) {
169 var servicesChanged = services[0];
170 var servicesRemoved = services[1];
172 console.log(servicesChanged.length + ' services changed');
173 for (var i = 0; i < servicesChanged.length; i++) {
174 if (servicesChanged[i][0] === undefined) {
175 console.log('Invalid parameters, missing object path');
179 var service = $(jqId(servicesChanged[i][0])).data('service-object');
181 if (service == null) {
182 console.log('could not find service object ' + servicesChanged[i][0]);
186 for (var prop in servicesChanged[i][1]) {
187 if (servicesChanged[i][1].hasOwnProperty(prop)) {
188 service.prop.prop = servicesChanged[i][1].prop;
189 connmanUpdateService(service);
190 console.log('Service ' + service.prop.Name + ' updated: ' + prop);
195 console.log(servicesRemoved.length + ' services removed');
196 for (var i = 0; i < servicesRemoved.length; i++) {
197 if (servicesRemoved[i] === undefined) {
198 console.log('Invalid parameters, missing object path');
202 connmanRemoveFromAvailableList(servicesRemoved[i]);
206 function connmanHandlePropertyChanged(id, property) {
207 if (property[0] === 'Powered') {
208 var index = id.lastIndexOf('/');
209 var technology = id.substring(index + 1);
210 if (property[1] === true) {
211 connmanToggleOn(technology);
212 if (technology === 'wifi') {
213 setTimeout(function() {
214 /* add a 1 sec delay */
219 connmanToggleOff(technology);
223 if (property[0] === 'State') {
224 /* specific service has changed */
225 var service = $(jqId(id)).data('service-object');
226 if (service == null) {
227 console.error('Connman service not found ' + id);
231 service.prop.State = property[1];
232 connmanUpdateService(service);
233 } else if (property[0] === 'Connected') {
234 /* unknown service has changed, sync Connman */
235 console.log('Unknown service connected property changed');
236 connmanSync(null, function(e) {
242 function connmanClearAvailableList() {
243 $('#listview_services_available').html('');
246 function connmanScan(technology) {
247 if (technology !== '/net/connman/technology/wifi') {
248 /* Connman only supports wifi scan */
252 if (connmanScanInProgress) {
253 console.log('Connman scan in progress...');
257 console.log('Start connman scan');
258 connmanScanInProgress = true;
260 /* clear the services list with new scan */
261 connmanClearAvailableList();
263 showSpinner(false, 'Scanning...');
264 $('#toggle_connman_wifi').slider('disable');
265 $('#toggle_connman_wifi').slider('refresh');
266 settings.connman.scan(technology, function(services) {
268 connmanScanInProgress = false;
269 $('#toggle_connman_wifi').slider('enable');
270 $('#toggle_connman_wifi').slider('refresh');
271 console.log('found ' + services.length + ' connman services');
272 for (var i = 0; i < services.length; i++) {
273 var service = services[i];
274 if (service.prop.Type === undefined || service.prop.Type === 'bluetooth') {
275 console.log('Ignore bluetooth or unknown services');
278 if (service.prop.Name === undefined) {
279 console.log('Ignore hidden service - ' + service.id);
283 connmanUpdateService(service);
287 connmanScanInProgress = false;
288 $('#toggle_connman_wifi').slider('enable');
289 $('#toggle_connman_wifi').slider('refresh');
290 showMsg('Error', 'Cannot scan: ' + e);
294 function connmanSync(success_cb, error_cb) {
295 if (connmanScanInProgress) {
296 console.log('Connman scan in progress...');
300 console.log('Start connman sync');
301 /* clear the services list with new scan */
302 connmanClearAvailableList();
304 wifiScanInProgress = true;
305 $('#toggle_connman_wifi').slider('disable');
306 $('#toggle_connman_wifi').slider('refresh');
307 settings.connman.getServices(function(services) {
308 connmanScanInProgress = false;
309 $('#toggle_connman_wifi').slider('enable');
310 $('#toggle_connman_wifi').slider('refresh');
311 console.log('found ' + services.length + ' connman services');
312 for (var i = 0; i < services.length; i++) {
313 var service = services[i];
314 if (service.prop.Type === undefined || service.prop.Type === 'bluetooth') {
315 console.log('Ignore bluetooth or unknown services');
318 if (service.prop.Name === undefined) {
319 console.log('Ignore hidden service - ' + service.id);
323 connmanUpdateService(service);
329 connmanScanInProgress = false;
330 $('#toggle_connman_wifi').slider('enable');
331 $('#toggle_connman_wifi').slider('refresh');
338 function connmanRefreshServicesList() {
339 $('#listview_services_available').listview('refresh');
342 function connmanAppendToAvailableList(service) {
343 if ($('#listview_services_available').find(jqId(service.id)).length != 0) return;
345 var parent = '#listview_services_available';
346 connmanConstructServiceElement(parent, service);
347 connmanUpdateServiceButton(service);
348 connmanRefreshServicesList();
351 function connmanRemoveFromAvailableList(service_id) {
352 var removeThis = $('#listview_services_available li').filter(function() {
353 return $(this).find(jqId(service_id)).length === 1;
356 if (removeThis.length !== 0) {
358 connmanRefreshServicesList();
362 function getSignalStrengthStr(strength) {
363 var signal_strength = 'unknown';
364 if (strength > 0 && strength <= 20) {
365 strength = 'very poor';
366 } else if (strength > 20 && strength <= 40) {
367 signal_strength = 'poor';
368 } else if (strength > 40 && strength <= 70) {
369 signal_strength = 'average';
370 } else if (strength > 70 && strength <= 90) {
371 signal_strength = 'good';
372 } else if (strength > 90 && strength <= 100) {
373 signal_strength = 'excellent';
375 return signal_strength;
378 function connmanConstructTechnologyElement(technology) {
379 if (technology.prop.Type === undefined || technology.prop.Name == undefined) {
380 console.error('technology type or name missing ' + technology);
384 var html = '<ul data-role="listview" data-inset="true" class="ui-listview ui-listview-inset">';
385 html += '<li data-role="fieldcontain">';
386 html += '<label for="toggle_connman_' + technology.prop.Type + '" class="ui-slider">' + technology.prop.Name + '</label>';
387 html += '<select data-role="slider" name="toggle_connman_' + technology.prop.Type + '" ';
388 html += 'id="toggle_connman_' + technology.prop.Type + '" class="ui-slider-switch">';
389 html += '<option value="off">Off</option>';
390 html += '<option value="on">On</option>';
391 html += '</select></li></ul>';
392 $('#connman_technologies').append(html).trigger('create');
394 console.log('Connman technology ' + technology.prop.Type + ' is powered: ' + technology.prop.Powered);
395 if (technology.prop.Powered) {
396 connmanToggleOn(technology.prop.Type);
397 if ($('ul#listview_services_available li').length === 0) {
398 /* connman only supports wifi scan */
399 if (technology.prop.Type === 'wifi') {
400 connmanScan(technology.id);
402 connmanSync(null, function(e) {
408 connmanToggleOff(technology.prop.Type);
411 $('#toggle_connman_' + technology.prop.Type).change(function() {
412 console.log('toggle ' + technology.prop.Type + ' changed');
414 if (connmanScanInProgress) {
415 console.log('Connman scan in progress...');
419 $('#toggle_connman_' + technology.prop.Type).slider('disable');
420 $('#toggle_connman_' + technology.prop.Type).slider('refresh');
421 if ($('#toggle_connman_' + technology.prop.Type).val() === 'off') {
422 technology.setPowered(false, function() {
424 $('#toggle_connman_' + technology.prop.Type).slider('enable');
425 $('#toggle_connman_' + technology.prop.Type).slider('refresh');
426 console.log('Successfully disabled connman technology ' + technology.prop.Type);
430 $('#toggle_connman_' + technology.prop.Type).slider('enable');
431 $('#toggle_connman_' + technology.prop.Type).val('on').slider('refresh');
432 showMsg('Error', 'Cannot disable ' + technology.prop.Type);
435 technology.setPowered(true, function() {
437 $('#toggle_connman_' + technology.prop.Type).slider('enable');
438 $('#toggle_connman_' + technology.prop.Type).slider('refresh');
439 if (technology.prop.Type === 'wifi') {
440 setTimeout(function() {
441 /* add a 1 sec delay */
442 connmanScan(technology.id);
445 console.log('Successfully enabled connman technology ' + technology.prop.Type);
449 $('#toggle_connman_' + technology.prop.Type).slider('enable');
450 $('#toggle_connman_' + technology.prop.Type).val('off').slider('refresh');
451 showMsg('Error', 'Cannot enable ' + technology.prop.Type);
457 function connmanConstructServiceElement(parent, service) {
458 if (service.id === undefined || service.prop.Type === undefined) {
459 console.error('service id or type missing ' + service);
463 var html = '<li data-icon="false"><a href="#" id="' + jqId(service.id).replace('#', '') + '">';
464 html += '<div class="service-ssid">' + service.prop.Name + '</div>';
466 if (service.prop.Type === 'wifi') {
467 html += '<div class="service-encryption">Encryption: ' + service.prop.EncryptionMode + '</div>';
468 html += '<div class="service-strength">Signal: ' + getSignalStrengthStr(service.prop.Strength) + '</div>';
470 html += '<div class="service-status"></div>';
471 html += '<div data-role="button" class="service-action-button ui-li-aside" data-inline="true"></div>';
473 $(parent).append(html).trigger('create');
475 /* store service object in the element so we can reference it later */
476 $(jqId(service.id)).data('service-object', service);
478 $(jqId(service.id)).on('click', function() {
479 /* BUG in webruntime that cause click event when another page is rendered */
480 if ($.mobile.activePage.attr('id') === 'page_connman') {
481 localStorage.setItem('connman_service_id', service.id);
482 console.log('Enter Connman service page');
483 $.mobile.changePage('#page_connman_service');
487 $(jqId(service.id)).find('div.service-action-button').on('click', function(e) {
488 var parent = $(this).parent().attr('id');
491 * prevent the click event to propagate up
493 e.stopImmediatePropagation();
496 /* retrieve the service object from element */
497 var service = $(jqId(parent)).data('service-object');
498 if (service == null) {
499 console.error('Connman service object not found');
503 if (service.prop.State === 'idle') {
504 if (service.prop.EncryptionMode === 'none') {
505 connmanConnectToService(service, null);
507 connmanConnectToService(service, null, null, function(e) {
508 console.log('Connect failed, will ask for passphrase');
509 localStorage.setItem('connman_service_id', service.id);
510 console.log('Enter connect WiFi page');
511 $.mobile.changePage('#page_wifi_connect');
514 } else if (service.prop.State === 'ready') {
515 console.log('Disconnecting from service: ' + service.prop.Name);
516 showSpinner(false, 'Disconnecting...');
517 service.disconnect(function() {
519 connmanSync(function() {
527 showMsg('Error', 'Disconnect service failed: ' + e);
533 function connmanUpdateService(service) {
534 connmanAppendToAvailableList(service);
536 /* update service button for allowed action */
537 connmanUpdateServiceButton(service);
539 /* update service connection status */
540 connmanUpdateConnectionStatus(service);
542 /* update service detail panel */
543 if ($.mobile.activePage.attr('id') === 'page_connman_service') {
544 var service_id = localStorage.getItem('connman_service_id');
545 if (service_id == undefined) return;
546 var service_object = $(jqId(service_id)).data('service-object');
547 if (service.id === service_object.id) {
548 connmanConstructServicePanel(service);
553 function connmanUpdateServiceButton(service) {
554 if (service.prop.State === 'ready') {
555 $(jqId(service.id)).find('div.service-action-button').find('span').text('Disconnect');
556 } else if (service.prop.State === 'idle' || service.prop.State === 'online') {
557 $(jqId(service.id)).find('div.service-action-button').find('span').text('Connect');
561 function connmanUpdateConnectionStatus(service) {
562 var status = 'disconnected';
563 if (service.prop.State === 'ready') {
564 $(jqId(service.id)).addClass('service-connected');
565 status = 'connected';
566 } else if (service.prop.State === 'idle' || service.prop.State === 'online') {
567 status = 'disconnected';
568 $(jqId(service.id)).removeClass('service-connected');
571 connmanUpdateConnectionStatusText(service, status);
574 function connmanUpdateConnectionStatusText(service, status) {
575 $(jqId(service.id)).find('div.service-status').text(status);
578 function connmanConstructServicePanel(service) {
579 var status_connected = 'No';
581 if (service == null) return;
582 if (service.prop.State === 'ready') status_connected = 'Yes';
584 $('#page_connman_service_content').html('');
585 var html = '<ul data-role="listview" id="listview_connman_service" data-inset="true" ' + 'class="service-list ui-listview">';
586 html += '<li id="connman_service_name"><h2>Name: ' + service.prop.Name + '</h2></li>';
587 html += '<li id="connman_service_type"><h2>Type: ' + service.prop.Type + '</h2></li>';
588 html += '<li id="connman_service_type"><h2>State: ' + service.prop.State + '</h2></li>';
589 if (service.prop.Type === 'ethernet' || service.prop.Type === 'wifi') {
590 if (service.prop.Type === 'wifi') {
591 html += '<li id="connman_service_bssid"><h2>SSID: ' + service.prop.BSSID + '</h2></li>';
592 html += '<li id="connman_service_encryption"><h2>Encryption: ' + service.prop.EncryptionMode + '</h2></li>';
593 html += '<li id="connman_service_strength"><h2>Signal Strength: ' + service.prop.Strength + '</h2></li>';
595 if (service.prop.State === 'ready') {
596 html += '<li id="connman_service_ip_address"><h2>IP Address: ' + service.prop.IPv4.Address + '</h2></li>';
597 html += '<li id="connman_servicel_gateway"><h2>Gateway: ' + service.prop.IPv4.Gateway + '</h2></li>';
598 html += '<li id="connman_service_netmask"><h2>Netmask: ' + service.prop.IPv4.Netmask + '</h2></li>';
601 html += '<li id="connman_service_connected"><h2>Connected: ' + status_connected + '</h2></li>';
602 html += '<li id="connman_service_autoconnect"><h2>AutoConnect: ' + service.prop.AutoConnect + '</h2></li>';
604 $('#page_connman_service_content').append(html).trigger('create');
605 $('#listview_connman_services').listview('refresh');
608 function connmanUpdateServicePanel(service) {
609 var status_connected = 'No';
611 if (service == null) return;
612 if (service.prop.State === 'ready') status_connected = 'Yes';
613 $('#connman_service_connected').text(status_connected);
614 $('#listview_connman_service').listview('refresh');
617 function connmanToggleOn(technology_type) {
618 setTimeout(function() {
619 $('#toggle_connman_' + technology_type).val('on').slider('refresh');
620 console.log('Turn on toggle #toggle_connman_' + technology_type);
624 function connmanToggleOff(technology_type) {
625 setTimeout(function() {
626 $('#toggle_connman_' + technology_type).val('off').slider('refresh');
627 console.log('Turn off toggle #toggle_connman_' + technology_type);
631 function connmanConnectToService(service, passphrase, success_cb, error_cb) {
632 console.log('Connect to service: ' + service.prop.Name);
633 showSpinner(false, 'Connecting...');
634 service.connect(passphrase, function() {
636 connmanSync(function() {
656 function connmanGetHiddenServicePath(security_type, success_cb, error_cb) {
657 if (security_type === undefined || success_cb === undefined || error_cb === undefined) return;
658 settings.connman.scan(function(services) {
659 connmanScanInProgress = false;
660 console.log('found ' + services.length + ' connman services');
661 for (var i = 0; i < services.length; i++) {
662 var service = services[i];
663 if (service.prop.Name === undefined && service.prop.Type === 'wifi') {
664 console.log('Hidden network matched - ' + service.id);
665 success_cb(service.id);
669 error_cb('No hidden network with security: ' + security_type);
671 connmanScanInProgress = false;