mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2024-12-24 06:52:40 -05:00
wip
This commit is contained in:
parent
6c118cf8e0
commit
d778ddf00e
5 changed files with 116 additions and 40 deletions
|
@ -254,6 +254,8 @@ class Runtime extends EventEmitter {
|
|||
video: new Video(this)
|
||||
};
|
||||
|
||||
this.extensionDevices = {};
|
||||
|
||||
/**
|
||||
* A runtime profiler that records timed events for later playback to
|
||||
* diagnose Scratch performance.
|
||||
|
@ -394,6 +396,22 @@ class Runtime extends EventEmitter {
|
|||
return 'EXTENSION_ADDED';
|
||||
}
|
||||
|
||||
/**
|
||||
* Event name for updating the available set of peripheral devices.
|
||||
* @const {string}
|
||||
*/
|
||||
static get PERIPHERAL_LIST_UPDATE () {
|
||||
return 'PERIPHERAL_LIST_UPDATE';
|
||||
}
|
||||
|
||||
/**
|
||||
* Event name for reporting that a peripheral has connected.
|
||||
* @const {string}
|
||||
*/
|
||||
static get PERIPHERAL_CONNECTED () {
|
||||
return 'PERIPHERAL_CONNECTED';
|
||||
}
|
||||
|
||||
/**
|
||||
* Event name for reporting that blocksInfo was updated.
|
||||
* @const {string}
|
||||
|
@ -867,6 +885,22 @@ class Runtime extends EventEmitter {
|
|||
(result, categoryInfo) => result.concat(categoryInfo.blocks.map(blockInfo => blockInfo.json)), []);
|
||||
}
|
||||
|
||||
registerExtensionDevice (extensionId, device) {
|
||||
this.extensionDevices[extensionId] = device;
|
||||
}
|
||||
|
||||
startDeviceScan (extensionId) {
|
||||
if (this.extensionDevices[extensionId]) {
|
||||
this.extensionDevices[extensionId].startScan();
|
||||
}
|
||||
}
|
||||
|
||||
connectToPeripheral (extensionId, peripheralId) {
|
||||
if (this.extensionDevices[extensionId]) {
|
||||
this.extensionDevices[extensionId].connectToPeripheral(peripheralId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the function associated with the given opcode.
|
||||
* @param {!string} opcode The opcode to look up.
|
||||
|
|
|
@ -50,8 +50,9 @@ class MicroBit {
|
|||
/**
|
||||
* Construct a MicroBit communication object.
|
||||
* @param {Runtime} runtime - the Scratch 3.0 runtime
|
||||
* @param {string} extensionId - the id of the extension
|
||||
*/
|
||||
constructor (runtime) {
|
||||
constructor (runtime, extensionId) {
|
||||
|
||||
/**
|
||||
* The Scratch 3.0 runtime used to trigger the green flag button.
|
||||
|
@ -65,7 +66,13 @@ class MicroBit {
|
|||
* @type {ScratchBLE}
|
||||
* @private
|
||||
*/
|
||||
this._ble = new ScratchBLE();
|
||||
this._ble = new ScratchBLE(this._runtime, {
|
||||
filters: [
|
||||
{services: [BLEUUID.service]}
|
||||
]
|
||||
});
|
||||
|
||||
this._runtime.registerExtensionDevice(extensionId, this._ble);
|
||||
|
||||
/**
|
||||
* The most recently received value for each sensor.
|
||||
|
@ -102,15 +109,6 @@ class MicroBit {
|
|||
timeout: false
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Temporary until the gui requests a device connection
|
||||
this._ble.waitForSocket()
|
||||
// TODO: remove pinging once no longer needed
|
||||
.then(() => this._ble.sendRemoteRequest('pingMe'))
|
||||
.then(() => this._onBLEReady());
|
||||
|
||||
// TODO: Add ScratchBLE 'disconnect' handling
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -184,13 +182,13 @@ class MicroBit {
|
|||
/**
|
||||
* Requests connection to a device when BLE session is ready.
|
||||
*/
|
||||
_onBLEReady () {
|
||||
this._ble.requestDevice({
|
||||
filters: [
|
||||
{services: [BLEUUID.service]}
|
||||
]
|
||||
}, this._onBLEConnect.bind(this), this._onBLEError);
|
||||
}
|
||||
// _onBLEReady () {
|
||||
// this._ble.requestDevice({
|
||||
// filters: [
|
||||
// {services: [BLEUUID.service]}
|
||||
// ]
|
||||
// }, this._onBLEConnect.bind(this), this._onBLEError);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Starts reading data from device after BLE has connected to it.
|
||||
|
@ -318,7 +316,7 @@ class Scratch3MicroBitBlocks {
|
|||
this.runtime = runtime;
|
||||
|
||||
// Create a new MicroBit device instance
|
||||
this._device = new MicroBit(this.runtime);
|
||||
this._device = new MicroBit(this.runtime, Scratch3MicroBitBlocks.EXTENSION_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,8 +4,9 @@ class PeripheralChooser {
|
|||
return this._chosenPeripheralId;
|
||||
}
|
||||
|
||||
constructor () {
|
||||
this._availablePeripherals = []; // TODO for use in gui?
|
||||
constructor (runtime) {
|
||||
this._runtime = runtime;
|
||||
this._availablePeripherals = {};
|
||||
this._chosenPeripheralId = null;
|
||||
}
|
||||
|
||||
|
@ -23,14 +24,23 @@ class PeripheralChooser {
|
|||
|
||||
/**
|
||||
* Adds the peripheral ID to list of available peripherals.
|
||||
* @param {number} peripheralId - the id to add.
|
||||
* @param {object} info - the peripheral info object.
|
||||
*/
|
||||
addPeripheral (peripheralId) {
|
||||
this._availablePeripherals.push(peripheralId);
|
||||
addPeripheral (info) {
|
||||
// Add a new peripheral, or if the id is already present, update it
|
||||
this._availablePeripherals[info.peripheralId] = info;
|
||||
|
||||
const peripheralArray = Object.keys(this._availablePeripherals).map(id =>
|
||||
this._availablePeripherals[id]
|
||||
);
|
||||
|
||||
// @todo: sort peripherals by signal strength? or maybe not, so they don't jump around?
|
||||
|
||||
this._runtime.emit(this._runtime.constructor.PERIPHERAL_LIST_UPDATE, peripheralArray);
|
||||
|
||||
// TODO: Temporary: calls chosen callback on whatever peripherals are added.
|
||||
this._chosenPeripheralId = this._availablePeripherals[0];
|
||||
this._tempPeripheralChosenCallback(this._chosenPeripheralId);
|
||||
// this._chosenPeripheralId = this._availablePeripherals[0];
|
||||
// this._tempPeripheralChosenCallback(this._chosenPeripheralId);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,25 +4,44 @@ const PeripheralChooser = require('./peripheralChooser');
|
|||
const ScratchLinkWebSocket = 'ws://localhost:20110/scratch/ble';
|
||||
|
||||
class ScratchBLE extends JSONRPCWebSocket {
|
||||
constructor () {
|
||||
constructor (runtime, deviceOptions) {
|
||||
const ws = new WebSocket(ScratchLinkWebSocket);
|
||||
|
||||
super(ws);
|
||||
|
||||
this._ws = ws;
|
||||
this.peripheralChooser = new PeripheralChooser(); // TODO: finalize gui connection
|
||||
this._characteristicDidChange = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a promise for when the web socket opens.
|
||||
* @return {Promise} - a promise when BLE socket is open.
|
||||
*/
|
||||
waitForSocket () {
|
||||
return new Promise((resolve, reject) => {
|
||||
this._socketPromise = new Promise((resolve, reject) => {
|
||||
this._ws.onopen = resolve;
|
||||
this._ws.onerror = reject;
|
||||
});
|
||||
|
||||
this._runtime = runtime;
|
||||
|
||||
this._ws = ws;
|
||||
this.peripheralChooser = new PeripheralChooser(this._runtime); // TODO: finalize gui connection
|
||||
this._characteristicDidChange = null;
|
||||
|
||||
this._deviceOptions = deviceOptions;
|
||||
}
|
||||
|
||||
// @todo handle websocket failed
|
||||
startScan () {
|
||||
console.log('BLE startScan', this._ws.readyState);
|
||||
if (this._ws.readyState === 1) {
|
||||
this.sendRemoteRequest('pingMe')
|
||||
.then(() => this.requestDevice(this._deviceOptions));
|
||||
} else {
|
||||
// Try again to connect to the websocket
|
||||
this._socketPromise(this.sendRemoteRequest('pingMe')
|
||||
.then(() => this.requestDevice(this._deviceOptions)));
|
||||
}
|
||||
}
|
||||
|
||||
connectToPeripheral (id) {
|
||||
this.sendRemoteRequest(
|
||||
'connect',
|
||||
{peripheralId: id}
|
||||
).then(() =>
|
||||
this._runtime.emit(this._runtime.constructor.PERIPHERAL_CONNECTED)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -54,7 +73,7 @@ class ScratchBLE extends JSONRPCWebSocket {
|
|||
// TODO: Add peripheral 'undiscover' handling
|
||||
switch (method) {
|
||||
case 'didDiscoverPeripheral':
|
||||
this.peripheralChooser.addPeripheral(params.peripheralId);
|
||||
this.peripheralChooser.addPeripheral(params);
|
||||
break;
|
||||
case 'characteristicDidChange':
|
||||
this._characteristicDidChange(params.message);
|
||||
|
|
|
@ -106,6 +106,13 @@ class VirtualMachine extends EventEmitter {
|
|||
this.emit(Runtime.BLOCKSINFO_UPDATE, blocksInfo);
|
||||
});
|
||||
|
||||
this.runtime.on(Runtime.PERIPHERAL_LIST_UPDATE, info => {
|
||||
this.emit(Runtime.PERIPHERAL_LIST_UPDATE, info);
|
||||
});
|
||||
this.runtime.on(Runtime.PERIPHERAL_CONNECTED, () =>
|
||||
this.emit(Runtime.PERIPHERAL_CONNECTED)
|
||||
);
|
||||
|
||||
this.extensionManager = new ExtensionManager(this.runtime);
|
||||
|
||||
this.blockListener = this.blockListener.bind(this);
|
||||
|
@ -195,6 +202,14 @@ class VirtualMachine extends EventEmitter {
|
|||
this.runtime.ioDevices.video.setProvider(videoProvider);
|
||||
}
|
||||
|
||||
startDeviceScan (extensionId) {
|
||||
this.runtime.startDeviceScan(extensionId);
|
||||
}
|
||||
|
||||
connectToPeripheral (extensionId, peripheralId) {
|
||||
this.runtime.connectToPeripheral(extensionId, peripheralId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a Scratch project from a .sb, .sb2, .sb3 or json string.
|
||||
* @param {string | object} input A json string, object, or ArrayBuffer representing the project to load.
|
||||
|
|
Loading…
Reference in a new issue