From 14712486579022038b331934b318c624e8f98461 Mon Sep 17 00:00:00 2001 From: Valerie Young Date: Mon, 17 Dec 2018 21:04:15 -0500 Subject: [PATCH] Clean up and all sensors working --- src/extensions/scratch3_gdx_for/index.js | 284 +++++++++-------------- 1 file changed, 104 insertions(+), 180 deletions(-) diff --git a/src/extensions/scratch3_gdx_for/index.js b/src/extensions/scratch3_gdx_for/index.js index bc244a227..ec29cb713 100644 --- a/src/extensions/scratch3_gdx_for/index.js +++ b/src/extensions/scratch3_gdx_for/index.js @@ -1,11 +1,10 @@ const ArgumentType = require('../../extension-support/argument-type'); const BlockType = require('../../extension-support/block-type'); -// const log = require('../../util/log'); +const log = require('../../util/log'); // const cast = require('../../util/cast'); const formatMessage = require('format-message'); const BLE = require('../../io/ble'); const Base64Util = require('../../util/base64-util'); -const GdxCommands = require('./gdx-commands'); //const ScratchLinkProxy = require('./scratch-link-proxy'); const createDevice = require('@vernier/godirect/src/godirect').default.createDevice; @@ -16,19 +15,6 @@ const createDevice = require('@vernier/godirect/src/godirect').default.createDev // eslint-disable-next-line max-len const blockIconURI = 'data:image/png;base64,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'; -/** - * Enum for GDX-FOR protocol. - * @readonly - * @enum {string} - */ -const BLEUUID = { - service: 'd91714ef-28b9-4f91-ba16-f0d9a604f112', - txChar: 'f4bf14a6-c7d5-4b6d-8aa8-df1a7c83adcb', - rxChar: 'b41e6675-a329-40e0-aa01-44d2f444babe' -}; - -const BLETimeout = 4500; - /** * Manage communication with a GDX-FOR peripheral over a Scratch Link client socket. */ @@ -76,29 +62,8 @@ class GdxFor { angularVelocityX: 0, }; - /** - * Interval ID for data reading timeout. - * @type {number} - * @private - */ - this._timeoutID = null; - - /** - * A flag that is true while we are busy sending data to the BLE socket. - * @type {boolean} - * @private - */ - this._busy = false; - - /** - * ID for a timeout which is used to clear the busy flag if it has been - * true for a long time. - */ - this._busyTimeoutID = null; - this.disconnect = this.disconnect.bind(this); this._onConnect = this._onConnect.bind(this); - this._onMessage = this._onMessage.bind(this); this._connected = false; } @@ -110,36 +75,19 @@ class GdxFor { scan () { if (this._ble) { this._ble.close(); - // this._ble.disconnect(); //scratch-link } - console.log("Requesting Device"); navigator.bluetooth.requestDevice({ filters: [{ namePrefix: 'GDX' }], optionalServices: ['d91714ef-28b9-4f91-ba16-f0d9a604f112'] }).then((bleWbtDevice) => { - console.log("Got device: ", bleWbtDevice); return createDevice(bleWbtDevice, {open: false}); }).then((device) => { - console.log("Created BLE object: ", device); this._ble = device; - this._ble.open(false); // should emit a "device-opened" event when opened + this._ble.open(false); // false prevents starting of measurements this._ble.on('device-opened', this._onConnect); this._ble.on('device-closed', this._onClose); - }).catch((error) => { - console.log(error); }); - - - // scratch-link - // this._ble = new BLE(this._runtime, this._extensionId, { - // filters: [ - // { namePrefix: 'GDX' } - // ], - // optionalServices: [ - // BLEUUID.service - // ] - // }, this._onConnect); } /** @@ -157,13 +105,8 @@ class GdxFor { * Disconnect from the micro:bit. */ disconnect () { - // TODO: This funciton is called when you exist the connection popup. - // When using Web Bluetooth, we don't use the connection popup. - // When switching over from web bluetooth, make sure to figure out to handle - // this disconnection. - window.clearInterval(this._timeoutID); if (this._ble) { - //this._ble.disconnect(); + this._ble.close(); } } @@ -174,55 +117,22 @@ class GdxFor { isConnected () { let connected = false; if (this._ble) { - connected = this._connected; //this._ble.isConnected(); + connected = this._connected; } - console.log("Is connected: ", connected); return connected; } - /** - * Send a message to the peripheral BLE socket. - * @param {number} command - the BLE command hex. - * @param {Uint8Array} message - the message to write - */ - send (command, message) { - if (!this.isConnected()) return; - - debugger; - - const output = new Uint8Array(message.length + 1); - output[0] = command; // attach command to beginning of message - for (let i = 0; i < message.length; i++) { - output[i + 1] = message[i]; - } - //const output = [0x58, 0x19, 0xfe, 0x3f, 0x1a, 0xa5, 0x4a, 0x06, 0x49, 0x07, 0x48, 0x08, 0x47, 0x09, 0x46, 0x0a, 0x45, 0x0b, 0x44, 0x0c, 0x43, 0x0d, 0x42, 0x0e, 0x41]; - - //const output = new Uint8Array([0x58, 0x19, 0xfe, 0x3f, 0x1a, 0xa5, 0x4a, 0x06, 0x49, 0x07, 0x48, 0x08, 0x47, 0x09, 0x46, 0x0a, 0x45, 0x0b, 0x44, 0x0c, 0x43, 0x0d, 0x42, 0x0e, 0x41]); - console.log(output); - - const data = Base64Util.uint8ArrayToBase64(output); - console.log(data); - // WBn+PxqlSgZJB0gIRwlGCkULRAxDDUIOQQ== - - this._ble.write(BLEUUID.service, BLEUUID.txChar, data, 'base64', true).then( - () => { - this._busy = false; - } - ); - } - /** * Starts reading data from peripheral after BLE has connected to it. * @private */ _onConnect () { - console.log("CONNNECTED"); this._connected = true; this._ble.sensors.forEach(sensor => { sensor.setEnabled(true); - // do some calculations? + // do some calculations here? sensor.on('value-changed', (sensor) => { // We don't need this list, essentially. @@ -232,58 +142,52 @@ class GdxFor { }); }); - this._ble.start(); // Can set period here. - //this.send(GdxCommands.INIT, ''); - - //this._ble.read(BLEUUID.service, BLEUUID.rxChar, true, this._onMessage); - - //this._timeoutID = window.setInterval(this.disconnect, BLETimeout); + this._ble.start(); // Can set period here if needed. } getForce () { return this._ble.getSensor(1).value; } + getAccelerationX () { + return this._ble.getSensor(2).value; + } + + getAccelerationY () { + return this._ble.getSensor(3).value; + } + + getAccelerationZ () { + return this._ble.getSensor(4).value; + } + + getAngularSpeedX () { + return this._ble.getSensor(5).value; + } + + getAngularSpeedY () { + return this._ble.getSensor(6).value; + } + + getAngularSpeedZ () { + return this._ble.getSensor(7).value; + } + + _onClose () { this._connected = false; } - - /** - * Process the sensor data from the incoming BLE characteristic. - * @param {object} base64 - the incoming BLE data. - * @private - */ - _onMessage (base64) { - console.log("In _onMessage"); - // parse data - const data = Base64Util.base64ToUint8Array(base64); - console.log("data: ", data); - - // this._sensors.tiltX = data[1] | (data[0] << 8); - // if (this._sensors.tiltX > (1 << 15)) this._sensors.tiltX -= (1 << 16); - // this._sensors.tiltY = data[3] | (data[2] << 8); - // if (this._sensors.tiltY > (1 << 15)) this._sensors.tiltY -= (1 << 16); - - // this._sensors.buttonA = data[4]; - // this._sensors.buttonB = data[5]; - - // this._sensors.touchPins[0] = data[6]; - // this._sensors.touchPins[1] = data[7]; - // this._sensors.touchPins[2] = data[8]; - - // this._sensors.gestureState = data[9]; - - // // cancel disconnect timeout and start a new one - // window.clearInterval(this._timeoutID); - // this._timeoutID = window.setInterval(this.disconnect, BLETimeout); - } - } - -const CompareOptionsMenu = ['>', '<', '=']; - -const DirectionOptionsMenu = ['x', 'y', 'z']; +/** + * Enum for comparison operations. + * @readonly + * @enum {string} + */ +const ComparisonOptions = { + LESS_THAN: 'less_than', + GREATER_THAN: 'greater_than' +}; /** @@ -305,6 +209,37 @@ class Scratch3GdxForBlocks { return 'gdxfor'; } + get DIRECTIONS_MENU () { + return [ + { + text: 'x', + value: 'x' + }, + { + text: 'y', + value: 'y' + }, + { + text: 'z', + value: 'z' + } + ]; + } + + get COMPARE_MENU () { + return [ + { + text: '<', + value: ComparisonOptions.LESS_THAN + }, + { + text: '>', + value: ComparisonOptions.GREATER_THAN + } + ]; + } + + /** * Construct a set of GDX-FOR blocks. * @param {Runtime} runtime - the Scratch 3.0 runtime. @@ -342,12 +277,12 @@ class Scratch3GdxForBlocks { DIRECTION: { type: ArgumentType.STRING, menu: 'directionOptions', - defaultValue: 0 + defaultValue: 'x' }, COMPARE: { type: ArgumentType.STRING, menu: 'compareOptions', - defaultValue: 0 + defaultValue: ComparisonOptions.GREATER_THAN }, VALUE: { type: ArgumentType.NUMBER, @@ -367,12 +302,12 @@ class Scratch3GdxForBlocks { DIRECTION: { type: ArgumentType.STRING, menu: 'directionOptions', - defaultValue: 0 + defaultValue: 'x' }, COMPARE: { type: ArgumentType.STRING, menu: 'compareOptions', - defaultValue: 0 + defaultValue: ComparisonOptions.GREATER_THAN }, VALUE: { type: ArgumentType.NUMBER, @@ -392,7 +327,7 @@ class Scratch3GdxForBlocks { COMPARE: { type: ArgumentType.STRING, menu: 'compareOptions', - defaultValue: 0 + defaultValue: 'x' }, VALUE: { type: ArgumentType.NUMBER, @@ -412,7 +347,7 @@ class Scratch3GdxForBlocks { DIRECTION: { type: ArgumentType.STRING, menu: 'directionOptions', - defaultValue: 0 + defaultValue: 'x' } } }, @@ -421,14 +356,14 @@ class Scratch3GdxForBlocks { text: formatMessage({ id: 'gdxfor.getAngularSpeed', default: 'angular speed [DIRECTION]', - description: 'gets tilt' + description: 'gets angular speed' }), blockType: BlockType.REPORTER, arguments: { DIRECTION: { type: ArgumentType.STRING, menu: 'directionOptions', - defaultValue: 0 + defaultValue: 'x' } } }, @@ -443,8 +378,8 @@ class Scratch3GdxForBlocks { } ], menus: { - directionOptions: this._formatMenu(DirectionOptionsMenu), - compareOptions: this._formatMenu(CompareOptionsMenu) + directionOptions: this.DIRECTIONS_MENU, + compareOptions: this.COMPARE_MENU, } }; } @@ -458,45 +393,34 @@ class Scratch3GdxForBlocks { whenForceCompare () { return Promise.resolve(); } - getAcceleration () { - return Promise.resolve(); + getAcceleration (args) { + console.log(args); + switch (args.DIRECTION) { + case 'x': + return this._peripheral.getAccelerationX(); + case 'y': + return this._peripheral.getAccelerationY(); + case 'z': + return this._peripheral.getAccelerationZ(); + default: + log.warn(`Unknown direction in getAcceleration: ${args.DIRECTION}`); + } } - getAngularSpeed () { - return Promise.resolve(); + getAngularSpeed (args) { + switch (args.DIRECTION) { + case 'x': + return this._peripheral.getAngularSpeedX(); + case 'y': + return this._peripheral.getAngularSpeedY(); + case 'z': + return this._peripheral.getAngularSpeedZ(); + default: + log.warn(`Unknown direction in getAngularSpeed: ${args.DIRECTION}`); + } } getForce () { return this._peripheral.getForce(); } - - /** - * Formats menus into a format suitable for block menus, and loading previously - * saved projects: - * [ - * { - * text: label, - * value: index - * }, - * { - * text: label, - * value: index - * }, - * etc... - * ] - * - * @param {array} menu - a menu to format. - * @return {object} - a formatted menu as an object. - * @private - */ - _formatMenu (menu) { - const m = []; - for (let i = 0; i < menu.length; i++) { - const obj = {}; - obj.text = menu[i]; - obj.value = i.toString(); - m.push(obj); - } - return m; - } } module.exports = Scratch3GdxForBlocks;