From 40c022ca8e060fc88be817a0fc0abf00f74b757d Mon Sep 17 00:00:00 2001 From: Kevin Andersen Date: Fri, 22 Feb 2019 12:50:19 -0500 Subject: [PATCH] - Refactoring of output commands: - Simplified generateOutputCommand() to follow the LEGO Wireless Protocol command-structure. Every output-command must have a portID, execution information, sub-command, and then followed by a custom payload which must be defined according to the protocol documentation mentioned in the extension. - Simple motor commands now use the above subcommand-structure rather than the former primitive command structure. - stopLED()-function removed since it's not used - Implemented check of pendingPromiseFunction() for motors before firing. --- src/extensions/scratch3_boost/index.js | 92 ++++++++++---------------- 1 file changed, 35 insertions(+), 57 deletions(-) diff --git a/src/extensions/scratch3_boost/index.js b/src/extensions/scratch3_boost/index.js index 3736283a6..30fbe8164 100644 --- a/src/extensions/scratch3_boost/index.js +++ b/src/extensions/scratch3_boost/index.js @@ -328,7 +328,7 @@ class BoostMotor { * @type {Object} * @private */ - this._pendingPromiseFunction = true; + this._pendingPromiseFunction = null; this.startBraking = this.startBraking.bind(this); this.turnOff = this.turnOff.bind(this); @@ -447,10 +447,11 @@ class BoostMotor { if (this._power === 0) return; const cmd = this._parent.generateOutputCommand( this._index, - BoostOutputSubCommand.WRITE_DIRECT_MODE_DATA, - BoostMode.MOTOR_OUTPUT, - [this._power * this._direction] // power in range 0-100 - ); + BoostOutputExecution.EXECUTE_IMMEDIATELY ^ BoostOutputExecution.COMMAND_FEEDBACK, + BoostOutputSubCommand.START_SPEED, + [this._power * this._direction, + this._power * this._direction, + BoostMotorProfile.DO_NOT_USE]); this._parent.send(BLECharacteristic, cmd); @@ -480,13 +481,13 @@ class BoostMotor { const cmd = this._parent.generateOutputCommand( this._index, + BoostOutputExecution.EXECUTE_IMMEDIATELY ^ BoostOutputExecution.COMMAND_FEEDBACK, BoostOutputSubCommand.START_SPEED_FOR_DEGREES, - null, - numberToInt32Array(degrees).concat( - [this._power * this._direction, // power in range 0-100 + [...numberToInt32Array(degrees), + this._power * this._direction, // power in range 0-100 0xFF, // max speed BoostMotorEndState.FLOAT, - BoostMotorProfile.DO_NOT_USE]) // byte for using acceleration/braking profile + BoostMotorProfile.DO_NOT_USE] // byte for using acceleration/braking profile ); this._status = BoostOutputCommandFeedback.BUFFER_EMPTY_COMMAND_IN_PROGRESS; @@ -503,9 +504,11 @@ class BoostMotor { const cmd = this._parent.generateOutputCommand( this._index, - BoostMessage.MOTOR_POWER, - BoostMode.MOTOR_OUTPUT, - [BoostMotorEndState.BRAKE] + BoostOutputExecution.EXECUTE_IMMEDIATELY ^ BoostOutputExecution.COMMAND_FEEDBACK, + BoostOutputSubCommand.START_SPEED, + [BoostMotorEndState.FLOAT, + BoostMotorEndState.FLOAT, + BoostMotorProfile.DO_NOT_USE] ); this._parent.send(BLECharacteristic, cmd); @@ -523,9 +526,11 @@ class BoostMotor { const cmd = this._parent.generateOutputCommand( this._index, - BoostMessage.MOTOR_POWER, - BoostMode.MOTOR_OUTPUT, - [BoostMotorEndState.FLOAT] + BoostOutputExecution.EXECUTE_IMMEDIATELY ^ BoostOutputExecution.COMMAND_FEEDBACK, + BoostOutputSubCommand.START_SPEED, + [BoostMotorEndState.FLOAT, + BoostMotorEndState.FLOAT, + BoostMotorProfile.DO_NOT_USE] ); this._parent.send(BLECharacteristic, cmd, useLimiter); @@ -706,9 +711,10 @@ class Boost { const cmd = this.generateOutputCommand( this._ports.indexOf(BoostIO.LED), + BoostOutputExecution.EXECUTE_IMMEDIATELY ^ BoostOutputExecution.COMMAND_FEEDBACK, BoostOutputSubCommand.WRITE_DIRECT_MODE_DATA, - BoostMode.LED, - rgb + [BoostMode.LED, + ...rgb] ); return this.send(BLECharacteristic, cmd); @@ -729,21 +735,6 @@ class Boost { return this.send(BLECharacteristic, cmd); } - /** - * Switch off the LED on the Boost. - * @return {Promise} - a promise of the completion of the stop led send operation. - */ - stopLED () { - const cmd = this.generateOutputCommand( - this._ports.indexOf(BoostIO.LED), - BoostOutputSubCommand.WRITE_DIRECT_MODE_DATA, - BoostUnit.LED, - [0, 0, 0] - ); - - return this.send(BLECharacteristic, cmd); - } - /** * Stop the motors on the Boost peripheral. */ @@ -837,34 +828,19 @@ class Boost { /** * Generate a Boost 'Output Command' in the byte array format - * (CONNECT ID, COMMAND ID, NUMBER OF BYTES, VALUES ...). + * (COMMON HEADER, PORT ID, EXECUTION BYTE, SUBCOMMAND ID, PAYLOAD). * - * This sends a command to the Boost to actuate the specified outputs. + * Payload is accepted as an array since these vary across different subcommands. * * @param {number} portID - the port (Connect ID) to send a command to. - * @param {number} subCommandID - the id of the byte command. - * @param {number} mode - the mode - * @param {array} values - the list of values to write to the command. + * @param {number} execution - Byte containing startup/completion information + * @param {number} subCommandID - the id of the subcommand byte. + * @param {array} payload - the list of bytes to send as subcommand payload * @return {array} - a generated output command. */ - generateOutputCommand (portID, subCommandID = BoostOutputSubCommand.WRITE_DIRECT_MODE_DATA, mode=null, values = null) { - let command = [0x00 /* Hub ID (always 0 for now) */, BoostMessage.OUTPUT]; - if (values) { - command = command.concat(portID).concat( - BoostOutputExecution.EXECUTE_IMMEDIATELY ^ - BoostOutputExecution.COMMAND_FEEDBACK - ); - - if(subCommandID) { - command = command.concat(subCommandID); - } - if(mode !== null) { - command = command.concat(mode) - } - command = command.concat( - values - ); - } + generateOutputCommand (portID, execution, subCommand, payload) { + let hubID = 0x00 + let command = [hubID, BoostMessage.OUTPUT, portID, execution, subCommand, ...payload] command.unshift(command.length +1) return command; } @@ -988,10 +964,12 @@ class Boost { switch(feedback) { case BoostOutputCommandFeedback.BUFFER_EMPTY_COMMAND_COMPLETED ^ BoostOutputCommandFeedback.IDLE: case BoostOutputCommandFeedback.CURRENT_COMMAND_DISCARDED ^ BoostOutputCommandFeedback.IDLE: // Resolve even if command didn't complete successfully - if(this._motors[portID]) { + if(this._motors[portID] && this._motors[portID].pendingPromiseFunction) { this._motors[portID].pendingPromiseFunction(); - break; } + break; + case BoostOutputCommandFeedback.BUFFER_EMPTY_COMMAND_IN_PROGRESS: + break; default: console.log(buf2hex(data)) console.log("Got it but didn't find a motor on: " + portID)