<!doctype html> <html> <head> <link rel="stylesheet" href="xterm.css" /> <script src="xterm.js"></script> <script src="xterm-addon-fit.js"></script> </head> <style> body { font-family: sans; } </style> <body> <div id="terminal" style="height: 90vh"></div> <input type="text" id="line" style="width: 50%"></input> <select id="eol"> <option value="cr">CR</option> <option value="lf">LF</option> <option value="crlf">CR/LF</option> <option value="none">None</option> <option value="hex">Hex</option> </select> <button id="sendbtn" type="button">SEND</button> <button id="sendbrk" type="button">BRK</button> <input type="checkbox" id="echo" checked>Echo</input> <button type="button" id="setbaud">SET BAUD</button> <button type="button" id="clear">CLEAR</button> <br> Baud: <span id="curbaud">-</span> <script> var line_items = []; var idx = -1; function parseHexString(str) { str = str.replace("0x", "") str = str.replace(" ", "") var result = []; // Ignore any trailing single digit; I don't know what your needs // are for this case, so you may want to throw an error or convert // the lone digit depending on your needs. while (str.length >= 2) { result.push(parseInt(str.substring(0, 2), 16)); str = str.substring(2, str.length); } return result; } let xhr = new XMLHttpRequest(); // 2. Configure it: GET-request for the URL /article/.../load xhr.open('GET', '/uart/baud'); // 3. Send the request over the network xhr.send(); // 4. This will be called after the response is received xhr.onload = function () { if (xhr.status != 200) { // analyze HTTP status of the response alert(`Error ${xhr.status}: ${xhr.statusText}`); // e.g. 404: Not Found } else { // show the result let d = xhr.response d = JSON.parse(d) document.querySelector("#curbaud").textContent = d["baudrate"] } }; function sendBreak() { let xhr = new XMLHttpRequest(); xhr.open('GET', '/uart/break'); // 3. Send the request over the network xhr.send(); } function setBaud(baud) { let xhr = new XMLHttpRequest(); // 2. Configure it: GET-request for the URL /article/.../load xhr.open('GET', '/uart/baud?set=' + baud); // 3. Send the request over the network xhr.send(); xhr.onload = function () { let d = xhr.response d = JSON.parse(d) document.querySelector("#curbaud").textContent = d["baudrate"] }; } function sendLine() { var line = document.querySelector("#line").value var type = document.querySelector("#eol").value var echo = document.querySelector("#echo").checked //console.log(type) if (!line_items.includes(line)) { line_items.push(line) idx = line_items.length - 1 } if (type == "cr") line += "\r" else if (type == "lf") line += "\n" else if (type == "crlf") line += "\r\n" else if (type == "hex") { line = parseHexString(line) } if (echo) term.write(line) socket.send(line) } document.querySelector("#setbaud").onclick = event => { let baud = window.prompt("Enter baud rate", "115200") if (baud) { baud = parseInt(baud); setBaud(baud); } } document.querySelector("#clear").onclick = event => { term.clear(); } document.querySelector("#sendbtn").onclick = event => { sendLine(); } document.querySelector("#sendbrk").onclick = event => { sendBreak(); } document.querySelector("#line").addEventListener("keydown", event => { //console.log(event.key) if (event.key == "ArrowUp") { console.log(idx) if (line_items.length - 1 == idx) idx--; event.srcElement.value = line_items[idx] if (idx > 0) idx--; } if (event.key == "ArrowDown") { console.log(idx) if (idx < line_items.length - 1) { idx++; } event.srcElement.value = line_items[idx] } if (event.key !== "Enter") return; sendLine(); event.preventDefault(); // No need to `return false;`. }); var term = new Terminal({ cursorBlink: true, convertEol: true }); var fitAddon = new FitAddon.FitAddon(); term.loadAddon(fitAddon); var socket; function createSocket() { socket = new WebSocket("ws://" + window.location.host + "/ws/uart"); socket.binaryType = 'arraybuffer'; socket.onopen = function (e) { term.write("\x1B[1;3;31m[Websocket] Connection established\x1B[0m\r\n"); }; socket.onmessage = function (event) { term.write(new Uint8Array(event.data)); }; socket.onclose = function (event) { if (event.wasClean) { term.write("[Websocket] Connection closed"); } else { // e.g. server process killed or network down // event.code is usually 1006 in this case term.write("[Websocket] Connection died"); } createSocket(); }; } createSocket(); term.open(document.getElementById('terminal')); term.onData(chunk => { socket.send(chunk) }) fitAddon.activate(term) fitAddon.fit() term.focus() window.addEventListener('resize', () => { fitAddon.fit() }); </script> </body> </html>