@danidoble/webserial
v4.6.0
Published
WebSerial API wrapper
Maintainers
Readme
Webserial API (Wrapper)
An easy way to connect to a serial port from a web page.
Opensource wrapper to simplify connect to serial devices over Webserial API
Also checkout the Webserial-core package if you want to integrate webserial into other projects.
Checkout the Docs for more information.
Install
Using npm
npm install @danidoble/webserialUsing pnpm
pnpm install @danidoble/webserialUsing bun
bun install @danidoble/webserialTypeScript
Types are included for the main entry point and device subpaths:
import { Boardroid } from '@danidoble/webserial';
// Also supported: import { Boardroid } from '@danidoble/webserial/boardroid';
const board = new Boardroid();
const connected: boolean = board.isConnected;
const connection: Promise<boolean> = board.connect();The package installs the dependencies needed to resolve inherited types and includes
Web Serial declarations automatically. Browser projects can use TypeScript's
moduleResolution: "bundler"; legacy "node" ("node10") resolution is also tested.
Device type definitions live in lib/serial/types/<device>.types.ts, while
lib/serial/<device>.ts contains the implementation. Shared device types live in
kernel.types.ts; JSD protocol types live in lib/commands/jsd/types/.
Use import type for these definitions. Previously exported types remain
re-exported from their original modules to preserve existing imports.
Reusable contracts such as BoardroidCoins, BoardroidDispenseOptions,
PinPadSaleResult, and PinPaxInternal are exported from the main entry point
and the corresponding device subpaths. Registry queries keep the concrete device
type, including when the result is nullable:
import { Devices, type BoardroidCoins } from '@danidoble/webserial';
const board = Devices.getBoardroid();
if (board) {
const coins: BoardroidCoins = board.coins;
const total: number = coins.total;
board.dispense({ selection: 1 });
}State objects and method options have named contracts. Fields known to the library
are typed; vendor responses and custom protocol payloads remain extensible for
existing integrations. PinPad.consult<TResponse>() and rePrint<TResponse>()
also allow consumers to specify their service's response contract. These generic
annotations do not validate external JSON at runtime.
For contributors, run pnpm test:types. This builds and packs the library, installs
the tarball in an isolated consumer, and checks every device subpath with strict
type checking and skipLibCheck: false. It verifies inherited members and rejects
incorrect types and nonexistent members. This test requires npm registry access.
Docs
If you want to use a custom or device or the other inside this package a good starter point would be Here
Example
In this example we'll use Arduino interface
<!-- index.html -->
<!doctype html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Webserial</title>
<script src="arduino.js" type="module"></script>
</head>
<body class="bg-neutral-950 text-white p-4 w-full">
<div class="webserial w-full max-w-xl mx-auto grid grid-cols-1 gap-y-4">
<div class="my-6"></div>
<button id="connect" class="hidden px-4 py-3 bg-gray-800 rounded-lg">Connect to serial</button>
<div id="need-permission" class="hidden p-4 bg-rose-900 rounded-lg">
Woooah! It seems that you need to give permission to access the serial port. Please, click the button 'Connect
to serial' to try again.
</div>
<div id="disconnected" class="hidden p-4 bg-neutral-900 w-full">
The arduino is disconnected. Please, check the connection.
</div>
<div id="unsupported" class="hidden p-4 bg-orange-700 w-full absolute bottom-0 left-0">
This browser does not support the WebSerial API. Please, use a compatible browser.
</div>
<div id="log" class="bg-neutral-800 p-4 rounded-lg">Log: <br /></div>
</div>
<script src="https://cdn.tailwindcss.com?plugins=forms,typography,aspect-ratio,container-queries"></script>
</body>
</html>// arduino.js
import { Arduino } from '@danidoble/webserial';
const arduino = new Arduino();
arduino.on('serial:message', (data) => {
console.log(data.detail);
});
arduino.on('serial:timeout', (data) => {
console.log('serial:timeout', data.detail);
});
// arduino.on('serial:sent', data => {
// console.log('serial:sent',data.detail);
// });
arduino.on('serial:error', (event) => {
document.getElementById('log').innerText += event.detail.message + '\n\n';
});
// eslint-disable-next-line no-unused-vars
arduino.on('serial:disconnected', (event) => {
document.getElementById('log').innerText += 'Disconnected\n\n';
document.getElementById('disconnected').classList.remove('hidden');
document.getElementById('connect').classList.remove('hidden');
});
// eslint-disable-next-line no-unused-vars
arduino.on('serial:connecting', (event) => {
document.getElementById('log').innerText += 'Connecting\n\n';
});
// eslint-disable-next-line no-unused-vars
arduino.on('serial:connected', (event) => {
document.getElementById('log').innerText += 'Connected\n\n';
document.getElementById('disconnected').classList.add('hidden');
document.getElementById('need-permission').classList.add('hidden');
document.getElementById('connect').classList.add('hidden');
});
// eslint-disable-next-line no-unused-vars
arduino.on('serial:need-permission', (event) => {
document.getElementById('disconnected').classList.remove('hidden');
document.getElementById('need-permission').classList.remove('hidden');
document.getElementById('connect').classList.remove('hidden');
});
// eslint-disable-next-line no-unused-vars
arduino.on('serial:soft-reload', (event) => {
// reset your variables
});
// eslint-disable-next-line no-unused-vars
arduino.on('serial:unsupported', (event) => {
document.getElementById('unsupported').classList.remove('hidden');
});
function tryConnect() {
arduino
.connect()
.then(() => {})
.catch(console.error);
}
document.addEventListener('DOMContentLoaded', () => {
tryConnect();
document.getElementById('connect').addEventListener('click', tryConnect);
});
// get device instance after
// import {Devices} from '@danidoble/webserial'
// const myDevice = Devices.getArduino(1);
// window.arduino = arduino;