serialport / node-serialport

Access serial ports with JavaScript. Linux, OSX and Windows. Welcome your robotic JavaScript overlords. Better yet, program them!
https://serialport.io
MIT License
5.76k stars 1k forks source link

Web Serial binding #2271

Open jaz303 opened 3 years ago

jaz303 commented 3 years ago

💥 Proposal

What feature you'd like to see

Hello! I've been working on a Web Serial binding for node-serialport and would like gauge interest in getting it merged into the official repo. The current status of the project is that it is working with a simple echo client, and all methods except flush() are implemented.

Motivation

A unified interface to access serial ports between node.js and the web allows code to be shared between CLI applications and web GUIs that communicate with serial devices. My specific use-case is allowing my port of the SAM-BA bootloader client to be deployed on the web.

I believe implementing a Web Serial binding for node-serialport is preferable to the reverse approach of adapting node-serialport to work with WHATWG Streams due to the relative simplicity of the Node streams interface, and the slow uptake of WHATWG streams within Node.

Pitch

Current usage:

const SerialPort = require('@serialport/stream');
SerialPort.Binding = require('web-serial-binding');

// Get serial port reference from browser
const nativePort = await navigator.serial.requestPort();

// Create the port. We pass a serial port object rather than a string path
// but there's no type checking in the SerialPort internals to it's all good :)
const port = new SerialPort(nativePort, {baudRate: 115200});

A final implementation would ideally detect a browser environment and set the binding automatically.

I've deliberately left the acquisition of the serial port (navigator.serial.requestPort()) out of scope of the binding as it's web specific and should be dealt with in the application's own platform abstraction. The static list() method remains, and returns a list of ports already visible to the browser.

reconbot commented 3 years ago

💯 incredibly interested. I think your design decisions are pretty sound too.

jaz303 commented 3 years ago

Cool, good to hear, I'll begin working on a PR.

How do you see the package hierarchy being organised? I was thinking of a bindings package, plus maybe a @serialport/web-serial package that explicitly configures SerialPort with the web binding - this would allow folk to use the package without forcing them to compile native bindings. The core package would also detect navigator.serial and, if present, default to the web binding.

Thoughts here much appreciated.

reconbot commented 3 years ago

Let's start with @serialport/bindings-web and I like your idea of a web only package. Would it need to have a slightly different api than the main package? (Eg, an async constructor, list would work differently maybe?)

I've had an idea around changing the api of the bindings that actually might make it a little easier to get it into the main package. (I'm on mobile so it's hard to find the issue, bindings v2 or something) But I think once we have a working bindings package we can figure that out.

reconbot commented 3 years ago

@jacobrosenthal thoughts on donating the browser-serialport npm package to this effort?

@monteslu you'll want to know about this =)

GazHank commented 3 years ago

Here are links to some potentially associated "issues", in case it helps:

reconbot commented 3 years ago

@jaz303 happy to help on this whenever you're ready

frank-dspeed commented 3 years ago

i was working on the same thing and got the conclusion that it adds zero benefits for all cases that i spotted.

the main problem is requestPort waits for user input while nodejs does not need to do so

reconbot commented 3 years ago

There's a lot of code that isn't getting the port that would benefit from taking a web serial source. You're not going to have an isomorphic app but you will have isomorphic libraries.

frank-dspeed commented 3 years ago

@reconbot i did not see that in any code that i got the only thing that was usefull was porting the SerialPort Event Emitter API to the Web that is what i did i turned the "while port.read()" WebAPI into a emitter with on Data. on End.

I do see nothing that we can improve inside this project.

The Main diff out of lib view is the web stream implementation which is already ported to nodejs.

https://www.npmjs.com/package/web-streams-polyfill.

to be more exact: web-streams-polyfill/ponyfill/es6: a ponyfill targeting ES2015+ environments. Recommended for use in Node 6+ applications, or in web libraries supporting modern browsers. web-streams-polyfill/ponyfill/es2018: a ponyfill targeting ES2018+ environments. Recommended for use in Node 10+ applications.

Azq2 commented 3 months ago

Yet another WebSerial bindings: https://github.com/Azq2/node-serialport-bindings-webserial

frank-dspeed commented 3 months ago

Thats the wrong direction in general i guess.

Web Streams got nativ in nodejs now and do in fact replace the old node:streams api's

both got aligned to work via the iterateable @symbol

so in both versions webStreams and nodeStreams for of loops will do the trick

Readable and Writeable got exposed since node 19+ global without import same as in browser context. They are the webstream implementations also helpers got created and shipped to convert streams into both directions.

Azq2 commented 3 months ago

@frank-dspeed I think this is not directly relevant to WebSerial. I think we need separate issue to discuss WebStreams/NodeStreams support in the node-serialport.

In this issue we just want binding which allows us to use serial ports both in browsers and Node.js without great changes in the code. And don't care how that is implemented inside.


@reconbot What about official webserial bindings? I think the time has come :)

cjihrig commented 3 months ago

What about official webserial bindings?

FWIW, I started working on this a few years ago but ran into some blockers. See this discussion. I'd be happy to have that work revived.

reconbot commented 3 months ago

It's still just as good as an idea