index.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. // (c) 2014 Don Coleman
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /* global mainPage, deviceList, refreshButton */
  15. /* global detailPage, resultDiv, messageInput, sendButton, disconnectButton */
  16. /* global ble */
  17. /* jshint browser: true , devel: true*/
  18. 'use strict';
  19. // ASCII only
  20. function bytesToString(buffer) {
  21. return String.fromCharCode.apply(null, new Uint8Array(buffer));
  22. }
  23. // ASCII only
  24. function stringToBytes(string) {
  25. var array = new Uint8Array(string.length);
  26. for (var i = 0, l = string.length; i < l; i++) {
  27. array[i] = string.charCodeAt(i);
  28. }
  29. return array.buffer;
  30. }
  31. // this is Nordic's UART service
  32. var bluefruit = {
  33. serviceUUID: '6e400001-b5a3-f393-e0a9-e50e24dcca9e',
  34. txCharacteristic: '6e400002-b5a3-f393-e0a9-e50e24dcca9e', // transmit is from the phone's perspective
  35. rxCharacteristic: '6e400003-b5a3-f393-e0a9-e50e24dcca9e' // receive is from the phone's perspective
  36. };
  37. var app = {
  38. initialize: function() {
  39. this.bindEvents();
  40. detailPage.hidden = true;
  41. },
  42. bindEvents: function() {
  43. document.addEventListener('deviceready', this.onDeviceReady, false);
  44. refreshButton.addEventListener('touchstart', this.refreshDeviceList, false);
  45. sendButton.addEventListener('click', this.sendData, false);
  46. disconnectButton.addEventListener('touchstart', this.disconnect, false);
  47. deviceList.addEventListener('touchstart', this.connect, false); // assume not scrolling
  48. },
  49. onDeviceReady: function() {
  50. app.refreshDeviceList();
  51. },
  52. refreshDeviceList: function() {
  53. deviceList.innerHTML = ''; // empties the list
  54. ble.scan([bluefruit.serviceUUID], 5, app.onDiscoverDevice, app.onError);
  55. // if Android can't find your device try scanning for all devices
  56. // ble.scan([], 5, app.onDiscoverDevice, app.onError);
  57. },
  58. onDiscoverDevice: function(device) {
  59. var listItem = document.createElement('li'),
  60. html = '<b>' + device.name + '</b><br/>' +
  61. 'RSSI: ' + device.rssi + '&nbsp;|&nbsp;' +
  62. device.id;
  63. listItem.dataset.deviceId = device.id;
  64. listItem.innerHTML = html;
  65. deviceList.appendChild(listItem);
  66. },
  67. connect: function(e) {
  68. var deviceId = e.target.dataset.deviceId,
  69. onConnect = function(peripheral) {
  70. app.determineWriteType(peripheral);
  71. // subscribe for incoming data
  72. ble.startNotification(deviceId, bluefruit.serviceUUID, bluefruit.rxCharacteristic, app.onData, app.onError);
  73. sendButton.dataset.deviceId = deviceId;
  74. disconnectButton.dataset.deviceId = deviceId;
  75. resultDiv.innerHTML = "";
  76. app.showDetailPage();
  77. };
  78. ble.connect(deviceId, onConnect, app.onError);
  79. },
  80. determineWriteType: function(peripheral) {
  81. // Adafruit nRF8001 breakout uses WriteWithoutResponse for the TX characteristic
  82. // Newer Bluefruit devices use Write Request for the TX characteristic
  83. var characteristic = peripheral.characteristics.filter(function(element) {
  84. if (element.characteristic.toLowerCase() === bluefruit.txCharacteristic) {
  85. return element;
  86. }
  87. })[0];
  88. if (characteristic.properties.indexOf('WriteWithoutResponse') > -1) {
  89. app.writeWithoutResponse = true;
  90. } else {
  91. app.writeWithoutResponse = false;
  92. }
  93. },
  94. onData: function(data) { // data received from Arduino
  95. console.log(data);
  96. resultDiv.innerHTML = resultDiv.innerHTML + "Received: " + bytesToString(data) + "<br/>";
  97. resultDiv.scrollTop = resultDiv.scrollHeight;
  98. },
  99. sendData: function(event) { // send data to Arduino
  100. var success = function() {
  101. console.log("success");
  102. resultDiv.innerHTML = resultDiv.innerHTML + "Sent: " + messageInput.value + "<br/>";
  103. resultDiv.scrollTop = resultDiv.scrollHeight;
  104. };
  105. var failure = function() {
  106. alert("Failed writing data to the bluefruit le");
  107. };
  108. var data = stringToBytes(messageInput.value);
  109. var deviceId = event.target.dataset.deviceId;
  110. if (app.writeWithoutResponse) {
  111. ble.writeWithoutResponse(
  112. deviceId,
  113. bluefruit.serviceUUID,
  114. bluefruit.txCharacteristic,
  115. data, success, failure
  116. );
  117. } else {
  118. ble.write(
  119. deviceId,
  120. bluefruit.serviceUUID,
  121. bluefruit.txCharacteristic,
  122. data, success, failure
  123. );
  124. }
  125. },
  126. disconnect: function(event) {
  127. var deviceId = event.target.dataset.deviceId;
  128. ble.disconnect(deviceId, app.showMainPage, app.onError);
  129. },
  130. showMainPage: function() {
  131. mainPage.hidden = false;
  132. detailPage.hidden = true;
  133. },
  134. showDetailPage: function() {
  135. mainPage.hidden = true;
  136. detailPage.hidden = false;
  137. },
  138. onError: function(reason) {
  139. alert("ERROR: " + JSON.stringify(reason)); // real apps should use notification.alert
  140. }
  141. };