1<html> 2 <head> 3 <script src="https://cdn.jsdelivr.net/pyodide/v0.19.1/full/pyodide.js"></script> 4 </head> 5 6 <body> 7 <button onclick="runUSB()">USB</button> 8 <button onclick="runSerial()">Serial</button> 9 <br /> 10 <br /> 11 <div>Output:</div> 12 <textarea id="output" style="width: 100%;" rows="30" disabled></textarea> 13 14 <script> 15 function bufferToHex(buffer) { 16 return [...new Uint8Array(buffer)].map(x => x.toString(16).padStart(2, '0')).join(''); 17 } 18 19 const output = document.getElementById("output"); 20 const code = document.getElementById("code"); 21 22 function addToOutput(s) { 23 output.value += s + "\n"; 24 } 25 26 output.value = "Initializing...\n"; 27 28 async function main() { 29 let pyodide = await loadPyodide({ 30 indexURL: "https://cdn.jsdelivr.net/pyodide/v0.19.1/full/", 31 }) 32 output.value += "Ready!\n" 33 34 return pyodide; 35 } 36 37 let pyodideReadyPromise = main(); 38 39 async function readLoop(port, packet_source) { 40 const reader = port.readable.getReader() 41 try { 42 while (true) { 43 console.log('@@@ Reading...') 44 const { done, value } = await reader.read() 45 if (done) { 46 console.log("--- DONE!") 47 break 48 } 49 50 console.log('@@@ Serial data:', bufferToHex(value)) 51 if (packet_source.delegate !== undefined) { 52 packet_source.delegate.data_received(value) 53 } else { 54 console.warn('@@@ delegate not set yet, dropping data') 55 } 56 } 57 } catch (error) { 58 console.error(error) 59 } finally { 60 reader.releaseLock() 61 } 62 } 63 64 async function runUSB() { 65 const device = await navigator.usb.requestDevice({ 66 filters: [ 67 { 68 classCode: 0xE0, 69 subclassCode: 0x01 70 } 71 ] 72 }); 73 74 if (device.configuration === null) { 75 await device.selectConfiguration(1); 76 } 77 await device.claimInterface(0) 78 } 79 80 async function runSerial() { 81 const ports = await navigator.serial.getPorts() 82 console.log('Paired ports:', ports) 83 84 const port = await navigator.serial.requestPort() 85 await port.open({ baudRate: 1000000 }) 86 const writer = port.writable.getWriter() 87 } 88 89 async function run() { 90 91 let pyodide = await pyodideReadyPromise; 92 try { 93 const script = await(await fetch('scanner.py')).text() 94 await pyodide.loadPackage('micropip') 95 await pyodide.runPythonAsync(` 96 import micropip 97 await micropip.install('../dist/bumble-0.0.36.dev0+g3adbfe7.d20210807-py3-none-any.whl') 98 `) 99 let output = await pyodide.runPythonAsync(script) 100 addToOutput(output) 101 102 const pythonMain = pyodide.globals.get('main') 103 const packet_source = {} 104 const packet_sink = { 105 on_packet: (packet) => { 106 // Variant A, with the conversion done in Javascript 107 const buffer = packet.toJs() 108 console.log(`$$$ on_packet: ${bufferToHex(buffer)}`) 109 // TODO: create an sync queue here instead of blindly calling write without awaiting 110 /*await*/ writer.write(buffer) 111 packet.destroy() 112 113 // Variant B, with the conversion `to_js` done at the Python layer 114 // console.log(`$$$ on_packet: ${bufferToHex(packet)}`) 115 // /*await*/ writer.write(packet) 116 } 117 } 118 serialLooper = readLoop(port, packet_source) 119 pythonResult = await pythonMain(packet_source, packet_sink) 120 console.log(pythonResult) 121 serialResult = await serialLooper 122 writer.releaseLock() 123 await port.close() 124 console.log('### done') 125 } catch (err) { 126 addToOutput(err); 127 } 128 } 129 </script> 130 </body> 131</html>