From 0196d3354b93afd06458457997578e21f7c566d7 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Fri, 25 Jun 2021 11:52:24 +0200 Subject: [PATCH 1/3] added first rough experimental version of web-serial extension primitives --- HISTORY.md | 3 ++ snap.html | 2 +- src/extensions.js | 103 +++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 106 insertions(+), 2 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 942a240b..69814dcd 100755 --- a/HISTORY.md +++ b/HISTORY.md @@ -10,6 +10,9 @@ * **Notable Fixes:** * fixed occasional invisible error messages +### 2021-06-25 +* extensions: added first rough experimental version of web-serial extension primitives + ### 2021-06-24 * extensions: tweaked loading unlisted script-extensions * byob, threads, store: removed unused code diff --git a/snap.html b/snap.html index 42a950dd..0b0034c9 100755 --- a/snap.html +++ b/snap.html @@ -19,7 +19,7 @@ - + diff --git a/src/extensions.js b/src/extensions.js index 0ffbee87..4f3b71c8 100644 --- a/src/extensions.js +++ b/src/extensions.js @@ -31,7 +31,7 @@ IDE_Morph, CamSnapshotDialogMorph, SoundRecorderDialogMorph, isSnapObject, nop, Color, Process, contains*/ -modules.extensions = '2021-June-24'; +modules.extensions = '2021-June-25'; // Global stuff @@ -716,6 +716,107 @@ SnapExtensions.primitives.set( } ); +// web serial (srl_): // +++ under construction + +SnapExtensions.primitives.set( + 'srl_open', + function () { + + var world = this.world(); // +++ change to IDE + + async function webSerialConnect() { // +++ instead of async make it Snap! thread friendly + // Prompt user to choose a serial port and open the one selected. + + var vendorIDs = [ + {usbVendorId: 0x0403}, // FTDI + {usbVendorId: 0x0d28}, // micro:bit, Calliope + {usbVendorId: 0x10c4}, // Silicon Laboratories, Inc. (CP210x) + {usbVendorId: 0x1a86}, // CH340 + {usbVendorId: 0x239a}, // AdaFruit + {usbVendorId: 0x2a03}, // Arduino + {usbVendorId: 0x2341}, // Arduino MKR Zero + {usbVendorId: 0x03eb}, // Atmel Corporation + {usbVendorId: 0x1366}, // SEGGER Calliope mini + {usbVendorId: 0x16c0}, // Teensy + ]; + world.webSerialPort = await navigator.serial.requestPort({filters: vendorIDs}).catch((e) => { console.log(e); }); // +++ make "await" Snap! thread friendly, change UI if possible to a non-blocking Morphic menu/dialog + if (!world.webSerialPort) {return; } // no serial port selected + await world.webSerialPort.open({ baudRate: 115200 }); // +++ make "await" Snap! thread friendly + world.webSerialReader = await world.webSerialPort.readable.getReader(); // +++ make "await" Snap! thread friendly + webSerialReadLoop(); + } + + async function webSerialReadLoop() { + try { + while (true) { // +++ should be improved, make thread-friendly + var {value, done} = await world.webSerialReader.read(); // +++ make "await" Snap! thread friendly + if (value) { + world.serialInputBuffers.push(Array.from(value)); + } + if (done) { // happens when world.webSerialReader.cancel() is called by disconnect + world.webSerialReader.releaseLock(); + return; + } + } + } catch (e) { // happens when board is unplugged + // console.log(e); + if (world.webSerialPort) await world.webSerialPort.close().catch(() => {}); // +++ make "await" Snap! thread friendly + world.webSerialPort = null; // +++ reformulate "world", use IDE reference + world.webSerialReader = null; + } + } + + world.serialInputBuffers = []; + webSerialConnect(); + } +); + +SnapExtensions.primitives.set( + 'srl_close', + function () { + var world = this.world(); // +++ change to IDE + + async function webSerialDisconnect() { // +++ make async thread friendly + if (world.webSerialReader) await world.webSerialReader.cancel(); // +++ make "await" Snap! thread friendly + if (world.webSerialPort) await world.webSerialPort.close().catch(() => {}); // +++ make "await" Snap! thread friendly + world.webSerialReader = null; + world.webSerialPort = null; + } + + webSerialDisconnect(); + } +); + +SnapExtensions.primitives.set( + 'srl_read', + function () { + var world = this.world(); // +++ change to IDE + + function webSerialRead() { // +++ do we need this function at all? Why not run this code directly? + if (world.serialInputBuffers && (world.serialInputBuffers.length > 0)) { + var result = [].concat.apply([], world.serialInputBuffers); + world.serialInputBuffers = []; + return new List(result); + } + return ''; + } + + return webSerialRead(); + } +); + +SnapExtensions.primitives.set( + 'srl_write(dta)', + function (data) { + var world = this.world(); // +++ change to IDE + + if (!world.webSerialPort || !world.webSerialPort.writable) return 0; // port not open + const w = world.webSerialPort.writable.getWriter(); + w.write(data.buffer); + w.releaseLock(); + } +); + // loading external scripts (src_) SnapExtensions.primitives.set( From 7bd733a6d58b160e0a349754df31e1cc89bb0a8c Mon Sep 17 00:00:00 2001 From: jmoenig Date: Fri, 25 Jun 2021 14:40:53 +0200 Subject: [PATCH 2/3] commented out web-serial extension prims while thinking about their design --- HISTORY.md | 1 + src/extensions.js | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 69814dcd..acedaa69 100755 --- a/HISTORY.md +++ b/HISTORY.md @@ -12,6 +12,7 @@ ### 2021-06-25 * extensions: added first rough experimental version of web-serial extension primitives +* extensions: commented out web-serial extension prims while thinking about their design ### 2021-06-24 * extensions: tweaked loading unlisted script-extensions diff --git a/src/extensions.js b/src/extensions.js index 4f3b71c8..5ef8c9f8 100644 --- a/src/extensions.js +++ b/src/extensions.js @@ -718,16 +718,25 @@ SnapExtensions.primitives.set( // web serial (srl_): // +++ under construction +// commented out for now, pondering - among others, the following questions: +// +// * why only support one single port? Why not as many as you want? because "ports" have no object representation in Snap? aren't first-class? Maybe +// * what happens if you run the "open" block again, while ports are already open? +// * Should ports be closed when you open another project? Or even when the user presses the red stop sign button? +// * Should projects and scripts store vendor-specific port-wishes (e.g. "Calliope") and try to automatically connect to those if present? +// + +/* SnapExtensions.primitives.set( 'srl_open', function () { - var world = this.world(); // +++ change to IDE + var world = this.world(); // +++ change to IDE, perhaps expand to support multiple open ports async function webSerialConnect() { // +++ instead of async make it Snap! thread friendly // Prompt user to choose a serial port and open the one selected. - var vendorIDs = [ + var vendorIDs = [ // +++ make it an option to only show these selected vendorIDs, allow to show all existing ones! {usbVendorId: 0x0403}, // FTDI {usbVendorId: 0x0d28}, // micro:bit, Calliope {usbVendorId: 0x10c4}, // Silicon Laboratories, Inc. (CP210x) @@ -741,14 +750,14 @@ SnapExtensions.primitives.set( ]; world.webSerialPort = await navigator.serial.requestPort({filters: vendorIDs}).catch((e) => { console.log(e); }); // +++ make "await" Snap! thread friendly, change UI if possible to a non-blocking Morphic menu/dialog if (!world.webSerialPort) {return; } // no serial port selected - await world.webSerialPort.open({ baudRate: 115200 }); // +++ make "await" Snap! thread friendly + await world.webSerialPort.open({ baudRate: 115200 }); // +++ make baudrate an optional input (?), make "await" Snap! thread friendly world.webSerialReader = await world.webSerialPort.readable.getReader(); // +++ make "await" Snap! thread friendly webSerialReadLoop(); } async function webSerialReadLoop() { try { - while (true) { // +++ should be improved, make thread-friendly + while (true) { // +++ should be improved, make thread-friendly, why is it a loop anyway? var {value, done} = await world.webSerialReader.read(); // +++ make "await" Snap! thread friendly if (value) { world.serialInputBuffers.push(Array.from(value)); @@ -816,6 +825,7 @@ SnapExtensions.primitives.set( w.releaseLock(); } ); +*/ // loading external scripts (src_) From 339474a5973038ed94f796889341b394256de94c Mon Sep 17 00:00:00 2001 From: jmoenig Date: Fri, 2 Jul 2021 08:33:16 +0200 Subject: [PATCH 3/3] took out web-serial extension prims (not yet ready) --- HISTORY.md | 3 ++ snap.html | 2 +- src/extensions.js | 113 +--------------------------------------------- 3 files changed, 5 insertions(+), 113 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index acedaa69..f241d431 100755 --- a/HISTORY.md +++ b/HISTORY.md @@ -10,6 +10,9 @@ * **Notable Fixes:** * fixed occasional invisible error messages +### 2021-07-02 +* extensions: took out web-serial extension prims (not yet ready) + ### 2021-06-25 * extensions: added first rough experimental version of web-serial extension primitives * extensions: commented out web-serial extension prims while thinking about their design diff --git a/snap.html b/snap.html index 0b0034c9..8da01e70 100755 --- a/snap.html +++ b/snap.html @@ -19,7 +19,7 @@ - + diff --git a/src/extensions.js b/src/extensions.js index 5ef8c9f8..99f3d067 100644 --- a/src/extensions.js +++ b/src/extensions.js @@ -31,7 +31,7 @@ IDE_Morph, CamSnapshotDialogMorph, SoundRecorderDialogMorph, isSnapObject, nop, Color, Process, contains*/ -modules.extensions = '2021-June-25'; +modules.extensions = '2021-July-02'; // Global stuff @@ -716,117 +716,6 @@ SnapExtensions.primitives.set( } ); -// web serial (srl_): // +++ under construction - -// commented out for now, pondering - among others, the following questions: -// -// * why only support one single port? Why not as many as you want? because "ports" have no object representation in Snap? aren't first-class? Maybe -// * what happens if you run the "open" block again, while ports are already open? -// * Should ports be closed when you open another project? Or even when the user presses the red stop sign button? -// * Should projects and scripts store vendor-specific port-wishes (e.g. "Calliope") and try to automatically connect to those if present? -// - -/* -SnapExtensions.primitives.set( - 'srl_open', - function () { - - var world = this.world(); // +++ change to IDE, perhaps expand to support multiple open ports - - async function webSerialConnect() { // +++ instead of async make it Snap! thread friendly - // Prompt user to choose a serial port and open the one selected. - - var vendorIDs = [ // +++ make it an option to only show these selected vendorIDs, allow to show all existing ones! - {usbVendorId: 0x0403}, // FTDI - {usbVendorId: 0x0d28}, // micro:bit, Calliope - {usbVendorId: 0x10c4}, // Silicon Laboratories, Inc. (CP210x) - {usbVendorId: 0x1a86}, // CH340 - {usbVendorId: 0x239a}, // AdaFruit - {usbVendorId: 0x2a03}, // Arduino - {usbVendorId: 0x2341}, // Arduino MKR Zero - {usbVendorId: 0x03eb}, // Atmel Corporation - {usbVendorId: 0x1366}, // SEGGER Calliope mini - {usbVendorId: 0x16c0}, // Teensy - ]; - world.webSerialPort = await navigator.serial.requestPort({filters: vendorIDs}).catch((e) => { console.log(e); }); // +++ make "await" Snap! thread friendly, change UI if possible to a non-blocking Morphic menu/dialog - if (!world.webSerialPort) {return; } // no serial port selected - await world.webSerialPort.open({ baudRate: 115200 }); // +++ make baudrate an optional input (?), make "await" Snap! thread friendly - world.webSerialReader = await world.webSerialPort.readable.getReader(); // +++ make "await" Snap! thread friendly - webSerialReadLoop(); - } - - async function webSerialReadLoop() { - try { - while (true) { // +++ should be improved, make thread-friendly, why is it a loop anyway? - var {value, done} = await world.webSerialReader.read(); // +++ make "await" Snap! thread friendly - if (value) { - world.serialInputBuffers.push(Array.from(value)); - } - if (done) { // happens when world.webSerialReader.cancel() is called by disconnect - world.webSerialReader.releaseLock(); - return; - } - } - } catch (e) { // happens when board is unplugged - // console.log(e); - if (world.webSerialPort) await world.webSerialPort.close().catch(() => {}); // +++ make "await" Snap! thread friendly - world.webSerialPort = null; // +++ reformulate "world", use IDE reference - world.webSerialReader = null; - } - } - - world.serialInputBuffers = []; - webSerialConnect(); - } -); - -SnapExtensions.primitives.set( - 'srl_close', - function () { - var world = this.world(); // +++ change to IDE - - async function webSerialDisconnect() { // +++ make async thread friendly - if (world.webSerialReader) await world.webSerialReader.cancel(); // +++ make "await" Snap! thread friendly - if (world.webSerialPort) await world.webSerialPort.close().catch(() => {}); // +++ make "await" Snap! thread friendly - world.webSerialReader = null; - world.webSerialPort = null; - } - - webSerialDisconnect(); - } -); - -SnapExtensions.primitives.set( - 'srl_read', - function () { - var world = this.world(); // +++ change to IDE - - function webSerialRead() { // +++ do we need this function at all? Why not run this code directly? - if (world.serialInputBuffers && (world.serialInputBuffers.length > 0)) { - var result = [].concat.apply([], world.serialInputBuffers); - world.serialInputBuffers = []; - return new List(result); - } - return ''; - } - - return webSerialRead(); - } -); - -SnapExtensions.primitives.set( - 'srl_write(dta)', - function (data) { - var world = this.world(); // +++ change to IDE - - if (!world.webSerialPort || !world.webSerialPort.writable) return 0; // port not open - const w = world.webSerialPort.writable.getWriter(); - w.write(data.buffer); - w.releaseLock(); - } -); -*/ - // loading external scripts (src_) SnapExtensions.primitives.set(