From f56bfd50c671fd29b1a442adcfea57ec9f74356e Mon Sep 17 00:00:00 2001 From: s-ol Date: Wed, 20 Mar 2024 18:38:13 +0100 Subject: web, simulator: support WebSocket transport for development --- web/README.md | 4 ++ web/main.js | 143 +++++++++++++++++++++++++++++++++++----------------------- 2 files changed, 90 insertions(+), 57 deletions(-) (limited to 'web') diff --git a/web/README.md b/web/README.md index 021f437..6b0d1a4 100644 --- a/web/README.md +++ b/web/README.md @@ -7,3 +7,7 @@ WebSerial is only available on HTTP/S origins, so to run the application locally cd t937-serial/web python -m http.server # now live at http://localhost:8000 + +## WebSocket development mode + +To use WebSocket transport for development, add `#ws` to the site URL: http://localhost:8000/#ws diff --git a/web/main.js b/web/main.js index d164f70..37ef19e 100644 --- a/web/main.js +++ b/web/main.js @@ -16,17 +16,17 @@ for (const key in UTILS) { window.send16 = (func, ...data) => { const msg = Message.from16(ADDR.OVEN, func, data); console.info(msg.toString(), msg); - return PORT.writer.write(msg.buf); + return PORT.write(msg.buf); }; // send a message (uint8 data) window.send8 = (func, ...data) => { const msg = Message.from8(ADDR.OVEN, func, data); console.info(msg.toString(), msg); - return PORT.writer.write(msg.buf); + return PORT.write(msg.buf); }; -let PORT = null; // { port, reader, writer } | null +let PORT = null; // { write(buf), disconnect() } | null let STATUS = null; // null | 'connecting' | 'idle' | 'manual' | 'running' let START_TIME = null; let END_TIME = null; @@ -87,17 +87,6 @@ const updateUI = () => { updateUI(); -const disconnect = async () => { - const port = PORT; - PORT = null; - STATUS = null; - updateUI(); - - await port.reader.cancel().catch(() => null); - await port.writer.close().catch(() => null); - await port.port.close(); -}; - const onMessage = async (msg) => { if (msg.func === FUNC.O_TEMPS) { console.debug(msg.toString(), msg); @@ -116,7 +105,7 @@ const onMessage = async (msg) => { case ARG.CONNECT_CONNECTING: console.log('oven found'); const res = Message.from16(ADDR.OVEN, FUNC.C_ACK_CONNECT, [ARG.CONNECT_CONNECTED]); - await PORT.writer.write(res.buf); + await PORT.write(res.buf); break; case ARG.CONNECT_CONNECTED: @@ -132,7 +121,7 @@ const onMessage = async (msg) => { TIMEOUT = setTimeout(() => { if (!PORT) return; console.error('port timed out'); - disconnect(); + PORT.disconnect(); }, 2500); const temp1 = msg.get16(0); @@ -162,47 +151,6 @@ const onMessage = async (msg) => { updateUI(); } -const loop = async () => { - let buffer = new Uint8Array(); - - while (true) { - const { value, done } = await PORT.reader.read(); - if (done) throw new Error("reader cancelled"); - - buffer = concat(buffer, value); - do { - const msg = Message.tryParse(buffer); - if (!msg) break; - - await onMessage(msg); - buffer = buffer.slice(msg.length); - } while (buffer.length); - } -}; - -el.connect.onclick = async () => { - if (!!PORT) return disconnect(); - - const port = await navigator.serial.requestPort(); - await port.open({ baudRate: 38400 }); - console.log('opened port'); - - let reader, writer; - try { - reader = port.readable.getReader(); - writer = port.writable.getWriter(); - PORT = { port, reader, writer }; - STATUS = 'connecting'; - updateUI(); - - await loop(); - } finally { - console.log('shutting down'); - reader.releaseLock(); - writer.releaseLock(); - } -}; - const pwms = [ [el.heat, el.heat_mode], [el.cool, el.cool_mode], @@ -268,3 +216,84 @@ el.start.onclick = () => { } updateUI(); }; + +if (window.location.hash !== '#ws') { + el.connect.onclick = async () => { + if (!!PORT) return PORT.disconnect(); + + const port = await navigator.serial.requestPort(); + await port.open({ baudRate: 38400 }); + console.log('opened port'); + + let reader, writer; + try { + reader = port.readable.getReader(); + writer = port.writable.getWriter(); + + const write = (buf) => writer.write(buf); + + const disconnect = async () => { + PORT = null; + STATUS = null; + updateUI(); + + await reader.cancel().catch(() => null); + await writer.close().catch(() => null); + await port.close(); + }; + + PORT = { write, disconnect }; + STATUS = 'connecting'; + updateUI(); + + let buffer = new Uint8Array(); + + while (true) { + const { value, done } = await reader.read(); + if (done) throw new Error("reader cancelled"); + + buffer = concat(buffer, value); + do { + const msg = Message.tryParse(buffer); + if (!msg) break; + + await onMessage(msg); + buffer = buffer.slice(msg.length); + } while (buffer.length); + } + } finally { + console.log('shutting down'); + reader.releaseLock(); + writer.releaseLock(); + } + }; +} else { + el.connect.onclick = async () => { + if (!!PORT) return disconnect(); + + const sock = new WebSocket('ws://localhost:8001'); + sock.binaryType = 'arraybuffer'; + + const write = (buf) => sock.send(buf); + const disconnect = () => sock.close(); + + PORT = { write, disconnect }; + STATUS = 'connecting'; + updateUI(); + + sock.onmessage = (e) => { + const msg = Message.tryParse(new Uint8Array(e.data)); + if (!msg) console.error('invalid WS message', msg); + onMessage(msg); + }; + + sock.onclose = () => { + console.log('shutting down'); + PORT = null; + STATUS = null; + updateUI(); + }; + + console.log('opened websocket'); + }; +} -- cgit v1.2.3