From c0ccef87cd66e9de15e67b06f57a23228143bb63 Mon Sep 17 00:00:00 2001 From: Jakob Stendahl Date: Mon, 7 Jun 2021 22:37:16 +0200 Subject: :building_construction: Move away from web bluetooth library --- src/js/uBit.js | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 src/js/uBit.js (limited to 'src/js/uBit.js') diff --git a/src/js/uBit.js b/src/js/uBit.js new file mode 100644 index 0000000..11cc7ac --- /dev/null +++ b/src/js/uBit.js @@ -0,0 +1,138 @@ +/* + * This code is written with a lot of help from these resources: + * https://github.com/antefact/microBit.js/blob/master/src/microBit.js + * https://gist.github.com/kotobuki/7c67f8b9361e08930da1a5cfcfb0653f + * https://lancaster-university.github.io/microbit-docs/resources/bluetooth/bluetooth_profile.html + */ +const UART_SERVICE_UUID = "6e400001-b5a3-f393-e0a9-e50e24dcca9e"; +const UART_TX_CHARACTERISTIC_UUID = "6e400002-b5a3-f393-e0a9-e50e24dcca9e"; +const UART_RX_CHARACTERISTIC_UUID = "6e400003-b5a3-f393-e0a9-e50e24dcca9e"; + +export default class uBitBLE { + + constructor() { + let device; + + this.onConnectCallback = function() {}; + this.onDisconnectCallback = function() {}; + this.onUartTxCallback = function() {}; + + this.characteristic = { + UART_RX: {}, + UART_TX: {} + } + } + + onConnect(callbackFunction) { + this.onConnectCallback = callbackFunction; + } + + onDisconnect(callbackFunction) { + this.onDisconnectCallback = callbackFunction; + } + + onUartTx(callbackFunction) { + this.onUartTxCallback = callbackFunction; + } + + sendUart(string) { + if (this.isConnected() && this.characteristic.UART_RX) { + let encoder = new TextEncoder(); + this.characteristic.UART_RX.writeValue( + encoder.encode(string) + ).catch(error => { + console.log(error); + }); + } + } + + isConnected() { + if (this.device) { + return this.device.gatt.connected; + } else { + return false; + } + } + + disconnect() { + if (this.isConnected()) { + this.device.gatt.disconnect(); + } + } + + searchDevice() { + navigator.bluetooth.requestDevice({ + filters: [{namePrefix: "BBC micro:bit"}], + optionalServices: [UART_SERVICE_UUID] + }) + .then(device => { + console.log('> Name: ' + device.name); + console.log('> Id: ' + device.id); + this.device = device; + + device.addEventListener('gattserverdisconnected', this.onDisconnectCallback); + + // Attempts to connect to remote GATT Server. + return device.gatt.connect(); + }) + .then(server => { + // Note that we could also get all services that match a specific UUID by + // passing it to getPrimaryServices(). + this.onConnectCallback(); + console.log('Getting Services...'); + return server.getPrimaryServices(); + }) + .then(services => { + console.log('Getting Characteristics...'); + let queue = Promise.resolve(); + services.forEach(service => { + queue = queue.then(_ => service.getCharacteristics().then(characteristics => { + console.log('> Service: ' + service.uuid); + characteristics.forEach(characteristic => { + console.log('>> Characteristic: ' + characteristic.uuid + ' ' + + getSupportedProperties(characteristic)); + switch (characteristic.uuid) { + case UART_RX_CHARACTERISTIC_UUID: + this.characteristic.UART_RX = characteristic; + break; + + case UART_TX_CHARACTERISTIC_UUID: + this.characteristic.UART_TX = characteristic; + this.characteristic.UART_TX.startNotifications(); + this.characteristic.UART_TX.addEventListener( + "characteristicvaluechanged", + (event) => { this.onUartTxCallback(eventByteArrayToString(event)) } + ); + break; + + default: + } + }); + })); + }); + return queue; + }) + .catch(error => { + console.log('Argh! ' + error); + }); + } + +} + +function getSupportedProperties(characteristic) { + let supportedProperties = []; + for (const p in characteristic.properties) { + if (characteristic.properties[p] === true) { + supportedProperties.push(p.toUpperCase()); + } + } + return '[' + supportedProperties.join(', ') + ']'; +} + +function eventByteArrayToString(event) { + let receivedData = []; + for (var i = 0; i < event.target.value.byteLength; i++) { + receivedData[i] = event.target.value.getUint8(i); + } + return String.fromCharCode.apply(null, receivedData); +} -- cgit v1.2.3