Skip to content

Commit

Permalink
feat: platform specific open options (#2428)
Browse files Browse the repository at this point in the history
Make it a bit easier to have platform specific open options. I'm in love with the solution but it doesn't seem possible to filter the generic via a typecheck and have it apply to the open options. So casting the open options is the only recouse I've figured out.
  • Loading branch information
reconbot committed Feb 13, 2022
1 parent 956de7e commit b3bead4
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 31 deletions.
15 changes: 13 additions & 2 deletions packages/serialport/lib/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { randomBytes } from 'crypto'
import { SerialPort as SerialPortAutoDetect, SerialPortMock } from './'
import { assert } from '../../../test/assert'
import { testOnPlatform } from '../../../test/testOnPlatform'
import { LinuxBinding, LinuxOpenOptions } from '@serialport/bindings-cpp'

const platform = process.platform
if (platform !== 'win32' && platform !== 'darwin' && platform !== 'linux') {
Expand Down Expand Up @@ -31,13 +32,13 @@ function testSerialPortClass(

beforeEach(() => {
if (platform === 'mock') {
SerialPortMock.MockBinding.createPort('/dev/exists', { echo: true, maxReadSize: 50 })
SerialPortMock.binding.createPort('/dev/exists', { echo: true, maxReadSize: 50 })
}
})

afterEach(() => {
if (platform === 'mock') {
SerialPortMock.MockBinding.reset()
SerialPortMock.binding.reset()
}
})

Expand Down Expand Up @@ -73,6 +74,16 @@ function testSerialPortClass(
done()
})
})

it('allows platform specific options', done => {
new SerialPort({
path: '/bad/port',
baudRate: 9600,
vmin: 10,
} as LinuxOpenOptions).on('error', () => {
done()
})
})
})

describe('opening and closing', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/serialport/lib/serialport-mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export type SerialPortMockOpenOptions = Omit<OpenOptions<MockBindingInterface>,

export class SerialPortMock extends SerialPortStream<MockBindingInterface> {
static list = MockBinding.list
static readonly MockBinding = MockBinding
static readonly binding = MockBinding

constructor(options: SerialPortMockOpenOptions, openCallback?: ErrorCallback) {
const opts: OpenOptions<MockBindingInterface> = {
Expand Down
15 changes: 8 additions & 7 deletions packages/serialport/lib/serialport.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { ErrorCallback, OpenOptions, SerialPortStream } from '@serialport/stream'
import { autoDetect, AutoDetectTypes } from '@serialport/bindings-cpp'
import { ErrorCallback, OpenOptions, SerialPortStream, StreamOptions } from '@serialport/stream'
import { autoDetect, AutoDetectTypes, OpenOptionsFromBinding } from '@serialport/bindings-cpp'

const DetectedBinding = autoDetect()

export type SerialPortOpenOptions = Omit<OpenOptions<AutoDetectTypes>, 'binding'>
export type SerialPortOpenOptions<T extends AutoDetectTypes> = Omit<StreamOptions<T>, 'binding'> & OpenOptionsFromBinding<T>

export class SerialPort extends SerialPortStream<AutoDetectTypes> {
export class SerialPort<T extends AutoDetectTypes = AutoDetectTypes> extends SerialPortStream<T> {
/**
* Retrieves a list of available serial ports with metadata. Only the `path` is guaranteed. If unavailable the other fields will be undefined. The `path` is either the path or an identifier (eg `COM1`) used to open the SerialPort.
*
Expand Down Expand Up @@ -57,10 +57,11 @@ export class SerialPort extends SerialPortStream<AutoDetectTypes> {
```
*/
static list = DetectedBinding.list
static readonly binding = DetectedBinding

constructor(options: SerialPortOpenOptions, openCallback?: ErrorCallback) {
const opts: OpenOptions<AutoDetectTypes> = {
binding: DetectedBinding,
constructor(options: SerialPortOpenOptions<T>, openCallback?: ErrorCallback) {
const opts: OpenOptions<T> = {
binding: DetectedBinding as T,
...options,
}
super(opts, openCallback)
Expand Down
36 changes: 16 additions & 20 deletions packages/stream/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
import { Duplex } from 'stream'
import debugFactory from 'debug'
import { SetOptions, BindingInterface, PortInterfaceFromBinding, OpenOptions as BindingOpenOptions } from '@serialport/bindings-interface'
import { SetOptions, BindingInterface, PortInterfaceFromBinding, OpenOptionsFromBinding } from '@serialport/bindings-interface'
const debug = debugFactory('serialport/stream')

interface InternalSettings<T extends BindingInterface> extends OpenOptions<T> {
export class DisconnectedError extends Error {
disconnected: true
constructor(message: string) {
super(message)
this.disconnected = true
}
}

interface InternalSettings<T extends BindingInterface> {
binding: T
autoOpen: boolean
endOnClose: boolean
highWaterMark: number
Expand Down Expand Up @@ -33,12 +42,14 @@ export type ErrorCallback = (err: Error | null) => void

export type ModemBitsCallback = (err: Error | null, options?: { cts: boolean; dsr: boolean; dcd: boolean }) => void

export type OpenOptions<T extends BindingInterface = BindingInterface> = StreamOptions<T> & OpenOptionsFromBinding<T>

/**
* Options to open a port
*/
export interface OpenOptions<T extends BindingInterface> extends BindingOpenOptions {
export interface StreamOptions<T extends BindingInterface> {
/**
* The hardware access binding. `Bindings` are how Node-Serialport talks to the underlying system. By default we auto detect Windows (`WindowsBinding`), Linux (`LinuxBinding`) and OS X (`DarwinBinding`) and load the appropriate module for your system.
* The hardware access binding. `Bindings` are how Node-Serialport talks to the underlying system. If you're using the `serialport` package, this defaults to `'@serialport/bindings-cpp'` which auto detects Windows (`WindowsBinding`), Linux (`LinuxBinding`) and OS X (`DarwinBinding`) and load the appropriate module for your system.
*/
binding: T

Expand All @@ -56,31 +67,16 @@ export interface OpenOptions<T extends BindingInterface> extends BindingOpenOpti
endOnClose?: boolean
}

export class DisconnectedError extends Error {
disconnected: true
constructor(message: string) {
super(message)
this.disconnected = true
}
}

export class SerialPortStream<T extends BindingInterface = BindingInterface> extends Duplex {
port?: PortInterfaceFromBinding<T>
private _pool: PoolBuffer
private _kMinPoolSpace: number
opening: boolean
closing: boolean
readonly settings: InternalSettings<T>
readonly settings: InternalSettings<T> & OpenOptionsFromBinding<T>

/**
* Create a new serial port object for the `path`. In the case of invalid arguments or invalid options, when constructing a new SerialPort it will throw an error. The port will open automatically by default, which is the equivalent of calling `port.open(openCallback)` in the next tick. You can disable this by setting the option `autoOpen` to `false`.
* @param {OpenOptions=} options - Port configuration options
* @param {ErrorCallback=} openCallback - If `autoOpen` is true (the default) it will be provided to `port.open()` and run after the port is opened. The callback will be ignored if `autoOpen` is set to `false`.
* @property {number} baudRate The port's baudRate. Use `.update` to change it. Read-only.
* @property {string} path The system path or name of the serial port. Read-only.
* @property {boolean} isOpen `true` if the port is open, `false` otherwise. Read-only.
* @property {InternalSettings} settings The current settings of the port
* @throws {TypeError} When given invalid arguments, a `TypeError` will be thrown.
* @emits open
* @emits data
* @emits close
Expand Down
2 changes: 1 addition & 1 deletion packages/terminal/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const args = program.opts<{
path?: string
baud: number
databits: 8 | 7 | 6 | 5
parity: string
parity: OpenOptions<AutoDetectTypes>['parity']
stopbits: 1 | 1.5 | 2
echo: boolean
flowCtl?: string
Expand Down

0 comments on commit b3bead4

Please sign in to comment.