mirror of
https://github.com/sergeyyarkov/avr128da48_web-serial-example.git
synced 2026-10-11 10:19:02 +03:00
refactor
This commit is contained in:
parent
c524b034e1
commit
6e5e770bd8
183
web/app.js
183
web/app.js
@ -1,3 +1,5 @@
|
|||||||
|
var EOT = '\u0004';
|
||||||
|
|
||||||
class SerialPortHandler {
|
class SerialPortHandler {
|
||||||
constructor(options, onConnect, onDisconnect) {
|
constructor(options, onConnect, onDisconnect) {
|
||||||
this.encoder = new TextEncoder();
|
this.encoder = new TextEncoder();
|
||||||
@ -11,21 +13,17 @@ class SerialPortHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async open() {
|
async open() {
|
||||||
if ('serial' in navigator) {
|
try {
|
||||||
try {
|
const port = await navigator.serial.requestPort();
|
||||||
const port = await navigator.serial.requestPort();
|
await port.open(this.options);
|
||||||
await port.open(this.options);
|
|
||||||
|
|
||||||
this.port = port;
|
this.port = port;
|
||||||
this.isOpened = true;
|
this.isOpened = true;
|
||||||
|
|
||||||
return this.port.getInfo();
|
return this.port.getInfo();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.error('Web Serial API is not supported in your browser.');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,96 +41,111 @@ class SerialPortHandler {
|
|||||||
|
|
||||||
async read() {
|
async read() {
|
||||||
const reader = this.port.readable.getReader();
|
const reader = this.port.readable.getReader();
|
||||||
const chunks = [];
|
let chunks = '';
|
||||||
while (true) {
|
while (true) {
|
||||||
const { value, done } = await reader.read();
|
const { value, done } = await reader.read();
|
||||||
const decoded = this.decoder.decode(value);
|
const decoded = this.decoder.decode(value);
|
||||||
|
|
||||||
chunks.push(decoded);
|
chunks += decoded;
|
||||||
|
|
||||||
if (done || decoded.includes('\u0004')) {
|
if (done || decoded.includes('\u0004')) {
|
||||||
console.log('done');
|
console.log('Reading done.');
|
||||||
reader.releaseLock();
|
reader.releaseLock();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return chunks.join('');
|
return chunks;
|
||||||
}
|
}
|
||||||
|
|
||||||
#setupListeners() {
|
#setupListeners() {
|
||||||
if ('serial' in navigator) {
|
navigator.serial.addEventListener('connect', this.onConnect);
|
||||||
navigator.serial.addEventListener('connect', this.onConnect);
|
navigator.serial.addEventListener('disconnect', this.onDisconnected);
|
||||||
navigator.serial.addEventListener('disconnect', this.onDisconnected);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Application {
|
||||||
|
constructor(root) {
|
||||||
|
if (!('serial' in navigator)) {
|
||||||
|
console.error('Web Serial API is not supported in your browser.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.serialPortHandler = new SerialPortHandler({ baudRate: 9600 });
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DOM Elements
|
||||||
|
*/
|
||||||
|
this.$root = root;
|
||||||
|
this.$connectButton = this.$root.querySelector('#connect');
|
||||||
|
this.$disconnectButton = this.$root.querySelector('#disconnect');
|
||||||
|
this.$terminalForm = this.$root.querySelector('#terminal_form');
|
||||||
|
this.$serialLog = this.$root.querySelector('#serial_log');
|
||||||
|
this.$status = this.$root.querySelector('#status');
|
||||||
|
this.$vendorId = this.$root.querySelector('#vendorId');
|
||||||
|
this.$productId = this.$root.querySelector('#productId');
|
||||||
|
|
||||||
|
this.#setupEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handlers for connecting, disconnecting and sending a command
|
||||||
|
*/
|
||||||
|
#setupEvents() {
|
||||||
|
this.$connectButton.addEventListener('click', this.#connectHandler.bind(this));
|
||||||
|
this.$disconnectButton.addEventListener('click', this.#disconnectHandler.bind(this));
|
||||||
|
this.$terminalForm.addEventListener('submit', this.#submitHandler.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open serial port and notify user of connection status
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async #connectHandler() {
|
||||||
|
try {
|
||||||
|
if (this.serialPortHandler.isOpened) return;
|
||||||
|
const info = await this.serialPortHandler.open();
|
||||||
|
console.log('Port opened: ', info);
|
||||||
|
this.$terminalForm.elements.input.removeAttribute('disabled');
|
||||||
|
this.$vendorId.textContent = '0x' + info.usbVendorId.toString(16);
|
||||||
|
this.$productId.textContent = '0x' + info.usbProductId.toString(16);
|
||||||
|
this.$status.textContent = 'CONNECTED';
|
||||||
|
} catch (error) {
|
||||||
|
this.$status.textContent = 'ERROR';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const $connectButton = document.getElementById('connect');
|
/**
|
||||||
const $disconnectButton = document.getElementById('disconnect');
|
* Closes the serial port and updates the connection status.
|
||||||
const $terminalForm = document.getElementById('terminal_form');
|
* @returns {Promise<void>}
|
||||||
const $serialLog = document.getElementById('serial_log');
|
*/
|
||||||
const $status = document.getElementById('status');
|
async #disconnectHandler() {
|
||||||
const $vendorId = document.getElementById('vendorId');
|
if (!this.serialPortHandler.isOpened) return;
|
||||||
const $productId = document.getElementById('productId');
|
await this.serialPortHandler.close();
|
||||||
|
this.$vendorId.textContent = '-';
|
||||||
|
this.$productId.textContent = '-';
|
||||||
|
this.$status.textContent = 'NOT CONNECTED';
|
||||||
|
}
|
||||||
|
|
||||||
const onConnected = (e) => console.log('device inserted!');
|
/**
|
||||||
const onDisconnected = (e) => console.log('device ejected!');
|
* Writes data to the serial port and reads the response
|
||||||
|
* @param {SubmitEvent} e - Form submit event
|
||||||
const serialPortHandler = new SerialPortHandler(
|
*/
|
||||||
{ baudRate: 9600 },
|
async #submitHandler(e) {
|
||||||
onConnected,
|
e.preventDefault();
|
||||||
onDisconnected
|
const $form = e.target;
|
||||||
);
|
const data = $form.elements.input.value;
|
||||||
|
$form.reset();
|
||||||
async function onConnect() {
|
if (this.serialPortHandler.isOpened && data) {
|
||||||
try {
|
this.$serialLog.innerHTML += data + '\n';
|
||||||
if (serialPortHandler.isOpened) return;
|
await this.serialPortHandler.write(data + '\n');
|
||||||
const info = await serialPortHandler.open();
|
const message = await this.serialPortHandler.read();
|
||||||
console.log('Port opened: ', info);
|
this.$serialLog.textContent += message;
|
||||||
$terminalForm.elements.input.removeAttribute('disabled');
|
this.$serialLog.textContent += '\n';
|
||||||
$vendorId.textContent = '0x' + info.usbVendorId.toString(16);
|
console.log(message);
|
||||||
$productId.textContent = '0x' + info.usbProductId.toString(16);
|
}
|
||||||
$status.textContent = 'CONNECTED';
|
this.$serialLog.scrollTo(0, this.$serialLog.scrollHeight);
|
||||||
} catch (error) {
|
|
||||||
$status.textContent = 'ERROR';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onDisconnect() {
|
new Application(document.getElementById('app'));
|
||||||
if (!serialPortHandler.isOpened) return;
|
|
||||||
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 && data) {
|
|
||||||
$serialLog.innerHTML += data + '\n';
|
|
||||||
await serialPortHandler.write(data + '\n');
|
|
||||||
const message = await serialPortHandler.read();
|
|
||||||
$serialLog.textContent += message;
|
|
||||||
$serialLog.textContent += '\n';
|
|
||||||
console.log(message);
|
|
||||||
}
|
|
||||||
$serialLog.scrollTo(0, $serialLog.scrollHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
$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);
|
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
<script defer src="./app.js"></script>
|
<script defer src="./app.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="app">
|
<div id="app">
|
||||||
<div>
|
<div>
|
||||||
<button id="connect">Connect</button>
|
<button id="connect">Connect</button>
|
||||||
<button id="disconnect">Disconnect</button>
|
<button id="disconnect">Disconnect</button>
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
box-sizing: inherit;
|
box-sizing: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app {
|
#app {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
/* padding: 20px; */
|
/* padding: 20px; */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user