feat: writing to serial port

This commit is contained in:
Sergey Yarkov 2022-09-19 23:32:19 +03:00
parent 0b34bda967
commit d3a5aadcd4
3 changed files with 232 additions and 5 deletions

View File

@ -1,5 +1,110 @@
const $connectButton = document.getElementById('MCU_connect');
class SerialPortHandler {
constructor(options) {
this.encoder = new TextEncoder();
this.decoder = new TextDecoder();
this.options = options;
this.port = null;
this.writer = null;
this.reader = null;
this.isOpened = false;
}
console.log($connectButton);
async open() {
if ('serial' in navigator) {
try {
const port = await navigator.serial.requestPort();
await port.open(this.options);
// ...
this.port = port;
this.writer = port.writable.getWriter();
this.reader = port.readable.getReader();
this.isOpened = true;
return this.port.getInfo();
} catch (error) {
console.error(error);
throw error;
}
} else {
console.error('Web Serial API is not supported in your browser.');
}
}
async close() {
await this.port.close();
}
async write(data) {
const encoded = this.encoder.encode(data);
return await this.writer.write(encoded);
}
async read() {
let data = '';
while (true) {
const { value, done } = await this.reader.read();
if (done) {
this.reader.releaseLock();
break;
}
data += this.decoder.decode(value);
console.log(data);
}
}
}
const $connectButton = document.getElementById('connect');
const $disconnectButton = document.getElementById('disconnect');
const $terminalForm = document.getElementById('terminal_form');
const $serialLog = document.getElementById('serial_log');
const $status = document.getElementById('status');
const $vendorId = document.getElementById('vendorId');
const $productId = document.getElementById('productId');
const serialPortHandler = new SerialPortHandler({ baudRate: 9600 });
async function onConnect() {
try {
const info = await serialPortHandler.open();
console.log('Device connected: ', info);
console.log(serialPortHandler.port);
$terminalForm.elements.input.removeAttribute('disabled');
$vendorId.textContent = '0x' + info.usbVendorId.toString(16);
$productId.textContent = '0x' + info.usbProductId.toString(16);
$status.textContent = 'CONNECTED';
} catch (error) {
$status.textContent = 'ERROR';
}
}
async function onDisconnect() {
await serialPortHandler.close();
$vendorId.textContent = '-';
$productId.textContent = '-';
$status.textContent = 'NOT CONNECTED';
}
async function onSend(e) {
e.preventDefault();
const $form = e.target;
const data = $form.elements.input.value;
$form.reset();
if (serialPortHandler.isOpened) {
await serialPortHandler.write(data + '\n');
await serialPortHandler.read();
}
}
$connectButton.addEventListener('click', onConnect);
$disconnectButton.addEventListener('click', onDisconnect);
$terminalForm.addEventListener('submit', onSend);
// const program1 = setInterval(async () => {
// if (serialPortHandler.isOpened) {
// await serialPortHandler.write('led_toggle' + '\n');
// }
// }, 50);
// setInterval(() => {
// clearInterval(program1);
// }, 5000);

View File

@ -4,10 +4,39 @@
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<title>Web Serial API Example</title>
<link href="./style.css" rel="stylesheet" />
<script defer src="./app.js"></script>
</head>
<body>
<button id="MCU_connect">Connect</button>
<div class="app">
<div>
<button id="connect">Connect</button>
<button id="disconnect">Disconnect</button>
</div>
<form id="terminal_form" action="#">
<label for="terminal">Enter command name:</label><br />
<div class="flex">
<input
id="input"
name="input"
placeholder="e.g led_toggle"
type="text"
disabled
/>
<button type="submit">Send</button>
</div>
</form>
<textarea id="serial_log" placeholder=">" readonly></textarea>
<div id="port_info">
<div>
<p id="status">not connected</p>
</div>
<div>
<span>vendorId: <span id="vendorId">-</span>&nbsp;|</span>
<span>deviceId: <span id="productId">-</span></span>
</div>
</div>
</div>
</body>
</html>

93
web/style.css Normal file
View File

@ -0,0 +1,93 @@
:root {
--border-color: #c9d1d9;
--border-color-hover: #6e7681;
--font-family: monospace;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
.app {
display: flex;
flex-direction: column;
/* padding: 20px; */
width: 100%;
max-width: 600px;
row-gap: 5px;
}
html,
body {
box-sizing: border-box;
font-size: 16px;
}
body {
display: flex;
justify-content: center;
margin-top: 2rem;
font-family: var(--font-family);
}
p {
padding: 0;
margin: 5px;
}
input,
textarea {
font-family: var(--font-family);
padding: 5px 15px;
border-radius: 4px;
width: 100%;
border: 1px solid var(--border-color);
}
textarea {
resize: vertical;
min-height: 200px;
font-size: 16px;
outline: none;
font-size: 12px;
}
label {
font-size: 14px;
font-style: italic;
}
button {
cursor: pointer;
background: none;
font-family: var(--font-family);
border: 1px solid var(--border-color);
border-radius: 4px;
padding: 5px 15px;
}
button:hover {
border: 1px solid var(--border-color-hover);
}
#terminal_form div {
display: flex;
justify-content: space-between;
gap: 5px;
margin-bottom: 5px;
margin-top: 5px;
}
#port_info {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
font-size: 14px;
}
#port_info #status {
text-transform: uppercase;
}