mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2024-12-23 14:32:59 -05:00
Regulate micro:bit send timing (#1471)
* display blocks yield for 50ms * WIP on microbit command send timing * WIP on microbit command send timing * Cleanup and JSDOC * Send “withResponse” param to Link * Remove caching, add busy timeout
This commit is contained in:
parent
825035f503
commit
83b3eabf1d
2 changed files with 64 additions and 8 deletions
|
@ -27,6 +27,12 @@ const BLECommand = {
|
|||
|
||||
const BLETimeout = 4500; // TODO: might need tweaking based on how long the device takes to start sending data
|
||||
|
||||
/**
|
||||
* A time interval to wait (in milliseconds) while a block that sends a BLE message is running.
|
||||
* @type {number}
|
||||
*/
|
||||
const BLESendInterval = 100;
|
||||
|
||||
/**
|
||||
* Enum for micro:bit protocol.
|
||||
* https://github.com/LLK/scratch-microbit-firmware/blob/master/protocol.md
|
||||
|
@ -108,6 +114,19 @@ class MicroBit {
|
|||
* @private
|
||||
*/
|
||||
this._timeoutID = null;
|
||||
|
||||
/**
|
||||
* A flag that is true while we are busy sending data to the BLE session.
|
||||
* @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;
|
||||
}
|
||||
|
||||
// TODO: keep here?
|
||||
|
@ -252,21 +271,40 @@ class MicroBit {
|
|||
}
|
||||
|
||||
/**
|
||||
* Write a message to the device BLE session.
|
||||
* Send a message to the device BLE session.
|
||||
* @param {number} command - the BLE command hex.
|
||||
* @param {Uint8Array} message - the message to write.
|
||||
* @return {Promise} - a Promise that resolves when writing to device.
|
||||
* @param {Uint8Array} message - the message to write
|
||||
* @private
|
||||
*/
|
||||
_writeSessionData (command, message) {
|
||||
if (!this.getPeripheralIsConnected()) return;
|
||||
if (this._busy) return;
|
||||
|
||||
// Set a busy flag so that while we are sending a message and waiting for
|
||||
// the response, additional messages are ignored.
|
||||
this._busy = true;
|
||||
|
||||
// Set a timeout after which to reset the busy flag. This is used in case
|
||||
// a BLE message was sent for which we never received a response, because
|
||||
// e.g. the device was turned off after the message was sent. We reset
|
||||
// the busy flag after a while so that it is possible to try again later.
|
||||
this._busyTimeoutID = window.setTimeout(() => {
|
||||
this._busy = false;
|
||||
}, 5000);
|
||||
|
||||
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 data = Base64Util.uint8ArrayToBase64(output);
|
||||
return this._ble.write(BLEUUID.service, BLEUUID.txChar, data, 'base64');
|
||||
|
||||
this._ble.write(BLEUUID.service, BLEUUID.txChar, data, 'base64', true).then(
|
||||
() => {
|
||||
this._busy = false;
|
||||
window.clearTimeout(this._busyTimeoutID);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -750,7 +788,11 @@ class Scratch3MicroBitBlocks {
|
|||
this._device.displayMatrix(this._device.ledMatrixState);
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, BLESendInterval);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -762,7 +804,12 @@ class Scratch3MicroBitBlocks {
|
|||
displayText (args) {
|
||||
const text = String(args.TEXT).substring(0, 19);
|
||||
if (text.length > 0) this._device.displayText(text);
|
||||
return Promise.resolve();
|
||||
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, BLESendInterval);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -774,7 +821,12 @@ class Scratch3MicroBitBlocks {
|
|||
this._device.ledMatrixState[i] = 0;
|
||||
}
|
||||
this._device.displayMatrix(this._device.ledMatrixState);
|
||||
return Promise.resolve();
|
||||
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, BLESendInterval);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -133,13 +133,17 @@ class BLESession extends JSONRPCWebSocket {
|
|||
* @param {number} characteristicId - the ble characteristic to write.
|
||||
* @param {string} message - the message to send.
|
||||
* @param {string} encoding - the message encoding type.
|
||||
* @param {boolean} withResponse - if true, resolve after peripheral's response.
|
||||
* @return {Promise} - a promise from the remote send request.
|
||||
*/
|
||||
write (serviceId, characteristicId, message, encoding = null) {
|
||||
write (serviceId, characteristicId, message, encoding = null, withResponse = null) {
|
||||
const params = {serviceId, characteristicId, message};
|
||||
if (encoding) {
|
||||
params.encoding = encoding;
|
||||
}
|
||||
if (withResponse) {
|
||||
params.withResponse = withResponse;
|
||||
}
|
||||
return this.sendRemoteRequest('write', params)
|
||||
.catch(e => {
|
||||
this._sendError(e);
|
||||
|
|
Loading…
Reference in a new issue