| <html> |
| <head> |
| <script src="https://cdn.jsdelivr.net/pyodide/v0.19.1/full/pyodide.js"></script> |
| </head> |
| |
| <body> |
| <button onclick="runUSB()">USB</button> |
| <button onclick="runSerial()">Serial</button> |
| <br /> |
| <br /> |
| <div>Output:</div> |
| <textarea id="output" style="width: 100%;" rows="30" disabled></textarea> |
| |
| <script> |
| function bufferToHex(buffer) { |
| return [...new Uint8Array(buffer)].map(x => x.toString(16).padStart(2, '0')).join(''); |
| } |
| |
| const output = document.getElementById("output"); |
| const code = document.getElementById("code"); |
| |
| function addToOutput(s) { |
| output.value += s + "\n"; |
| } |
| |
| output.value = "Initializing...\n"; |
| |
| async function main() { |
| let pyodide = await loadPyodide({ |
| indexURL: "https://cdn.jsdelivr.net/pyodide/v0.19.1/full/", |
| }) |
| output.value += "Ready!\n" |
| |
| return pyodide; |
| } |
| |
| let pyodideReadyPromise = main(); |
| |
| async function readLoop(port, packet_source) { |
| const reader = port.readable.getReader() |
| try { |
| while (true) { |
| console.log('@@@ Reading...') |
| const { done, value } = await reader.read() |
| if (done) { |
| console.log("--- DONE!") |
| break |
| } |
| |
| console.log('@@@ Serial data:', bufferToHex(value)) |
| if (packet_source.delegate !== undefined) { |
| packet_source.delegate.data_received(value) |
| } else { |
| console.warn('@@@ delegate not set yet, dropping data') |
| } |
| } |
| } catch (error) { |
| console.error(error) |
| } finally { |
| reader.releaseLock() |
| } |
| } |
| |
| async function runUSB() { |
| const device = await navigator.usb.requestDevice({ |
| filters: [ |
| { |
| classCode: 0xE0, |
| subclassCode: 0x01 |
| } |
| ] |
| }); |
| |
| if (device.configuration === null) { |
| await device.selectConfiguration(1); |
| } |
| await device.claimInterface(0) |
| } |
| |
| async function runSerial() { |
| const ports = await navigator.serial.getPorts() |
| console.log('Paired ports:', ports) |
| |
| const port = await navigator.serial.requestPort() |
| await port.open({ baudRate: 1000000 }) |
| const writer = port.writable.getWriter() |
| } |
| |
| async function run() { |
| |
| let pyodide = await pyodideReadyPromise; |
| try { |
| const script = await(await fetch('scanner.py')).text() |
| await pyodide.loadPackage('micropip') |
| await pyodide.runPythonAsync(` |
| import micropip |
| await micropip.install('../dist/bumble-0.0.36.dev0+g3adbfe7.d20210807-py3-none-any.whl') |
| `) |
| let output = await pyodide.runPythonAsync(script) |
| addToOutput(output) |
| |
| const pythonMain = pyodide.globals.get('main') |
| const packet_source = {} |
| const packet_sink = { |
| on_packet: (packet) => { |
| // Variant A, with the conversion done in Javascript |
| const buffer = packet.toJs() |
| console.log(`$$$ on_packet: ${bufferToHex(buffer)}`) |
| // TODO: create an sync queue here instead of blindly calling write without awaiting |
| /*await*/ writer.write(buffer) |
| packet.destroy() |
| |
| // Variant B, with the conversion `to_js` done at the Python layer |
| // console.log(`$$$ on_packet: ${bufferToHex(packet)}`) |
| // /*await*/ writer.write(packet) |
| } |
| } |
| serialLooper = readLoop(port, packet_source) |
| pythonResult = await pythonMain(packet_source, packet_sink) |
| console.log(pythonResult) |
| serialResult = await serialLooper |
| writer.releaseLock() |
| await port.close() |
| console.log('### done') |
| } catch (err) { |
| addToOutput(err); |
| } |
| } |
| </script> |
| </body> |
| </html> |