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(