diff --git a/package-lock.json b/package-lock.json index 3e66363a..e6f3a1b9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "express": "^4.16.4", "flatten-svg": "^0.3.0", "optimize-paths": "^1.2.2", - "serialport": "^9.2.0 || ^12.0.0", + "serialport": "^12.0.0", "svgdom": "0.1.16", "wake-lock": "^0.2.0", "web-streams-polyfill": "^3.0.3", @@ -32,7 +32,6 @@ "@types/node": "^14.0.0", "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", - "@types/serialport": "^8.0.0", "@types/w3c-web-serial": "^1.0.2", "@types/ws": "8.0.0 - 8.5", "@types/yargs": "^17.0.0", @@ -1846,15 +1845,6 @@ "integrity": "sha512-cJRQXpObxfNKkFAZbJl2yjWtJCqELQIdShsogr1d2MilP8dKD9TE/nEKHkJgUNHdGKCQaf9HbIynuV2csLGVLg==", "dev": true }, - "node_modules/@types/serialport": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@types/serialport/-/serialport-8.0.0.tgz", - "integrity": "sha512-Hz57S0cH1Be94u1UO4kwp+1XwAk0GA5RrL16Gx0wZDLyP8gr+h5qQXFS4OygxjNZcE26cTMnT7s31AlezY+jbw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/serve-static": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.2.tgz", diff --git a/package.json b/package.json index 86f8fd11..e0505de8 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,6 @@ "@types/node": "^14.0.0", "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", - "@types/serialport": "^8.0.0", "@types/w3c-web-serial": "^1.0.2", "@types/ws": "8.0.0 - 8.5", "@types/yargs": "^17.0.0", @@ -69,7 +68,7 @@ "express": "^4.16.4", "flatten-svg": "^0.3.0", "optimize-paths": "^1.2.2", - "serialport": "^9.2.0 || ^12.0.0", + "serialport": "^12.0.0", "svgdom": "0.1.16", "wake-lock": "^0.2.0", "web-streams-polyfill": "^3.0.3", diff --git a/src/__tests__/ebb.test.ts b/src/__tests__/ebb.test.ts index 49c62538..a5ef1323 100644 --- a/src/__tests__/ebb.test.ts +++ b/src/__tests__/ebb.test.ts @@ -1,19 +1,11 @@ +const { SerialPortMock: SerialPort } = require('serialport') +import { MockBinding } from '@serialport/binding-mock'; + +jest.doMock('serialport', () => ({ + SerialPort: SerialPort, +})); import {EBB} from "../ebb"; import {SerialPortSerialPort} from "../serialport-serialport"; -import { default as NodeSerialPort } from "serialport"; -import MockBinding from "@serialport/binding-mock"; - -(() => { - let oldBinding: any; - beforeAll(() => { - oldBinding = NodeSerialPort.Binding; - NodeSerialPort.Binding = MockBinding; - }); - afterAll(() => { - NodeSerialPort.Binding = oldBinding; - MockBinding.reset(); - }); -})(); describe("EBB", () => { afterEach(() => { @@ -30,9 +22,9 @@ describe("EBB", () => { it("firmware version", async () => { const port = await openTestPort(); const ebb = new EBB(port); - (port as any)._port.binding.emitData(Buffer.from('aoeu\r\n')); + ((port as any)._port.port).emitData(Buffer.from('aoeu\r\n')); expect(await ebb.firmwareVersion()).toEqual('aoeu'); - expect((port as any)._port.binding.recording).toEqual(Buffer.from("V\r")); + expect((port as any)._port.port.recording).toEqual(Buffer.from("V\r")); }) it("enable motors", async () => { @@ -41,11 +33,11 @@ describe("EBB", () => { const oldWrite = (port as any)._port.write; (port as any)._port.write = (data: string | Buffer | number[], ...args: any[]) => { if (data.toString() === 'V\r') - (port as any)._port.binding.emitData(Buffer.from('test 2.5.3\r\n')) + (port as any)._port.port.emitData(Buffer.from('test 2.5.3\r\n')) return oldWrite.apply((port as any)._port, [data, ...args]) }; - (port as any)._port.binding.emitData(Buffer.from('OK\r\n')); + (port as any)._port.port.emitData(Buffer.from('OK\r\n')); await ebb.enableMotors(2); - expect((port as any)._port.binding.recording).toEqual(Buffer.from("EM,2,2\rV\r")); + expect((port as any)._port.port.recording).toEqual(Buffer.from("EM,2,2\rV\r")); }) }) diff --git a/src/global.d.ts b/src/global.d.ts index 768c4278..960c36e2 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -4,7 +4,6 @@ declare module '*.svg' { } declare module 'svgdom'; declare module 'wake-lock'; -declare module '@serialport/binding-mock'; declare module 'color-interpolate'; declare module 'colormap'; diff --git a/src/serialport-serialport.ts b/src/serialport-serialport.ts index b64e09cc..5df7652e 100644 --- a/src/serialport-serialport.ts +++ b/src/serialport-serialport.ts @@ -1,5 +1,6 @@ import { EventEmitter } from "events"; -import { default as NodeSerialPort } from "serialport"; +import { SerialPort as NodeSerialPort } from "serialport"; +import { OpenOptions } from "@serialport/bindings-interface" function readableStreamFromAsyncIterable(iterable: AsyncIterable) { const it = iterable[Symbol.asyncIterator](); @@ -17,6 +18,9 @@ function readableStreamFromAsyncIterable(iterable: AsyncIterable) { } }, { highWaterMark: 0 }); } +interface SerialPortOpenOptions extends Omit { + parity?: ParityType; +} export class SerialPortSerialPort extends EventEmitter implements SerialPort { private _path: string; @@ -37,8 +41,9 @@ export class SerialPortSerialPort extends EventEmitter implements SerialPort { } public open(options: SerialOptions): Promise { - const opts: NodeSerialPort.OpenOptions = { + const opts: SerialPortOpenOptions = { baudRate: options.baudRate, + path: this._path, } if (options.dataBits != null) opts.dataBits = options.dataBits as any @@ -53,7 +58,7 @@ export class SerialPortSerialPort extends EventEmitter implements SerialPort { flowControl?: FlowControlType | undefined; */ return new Promise((resolve, reject) => { - this._port = new NodeSerialPort(this._path, opts, (err) => { + this._port = new NodeSerialPort(opts, (err: any) => { this._port.once('close', () => this.emit('disconnect')) if (err) reject(err) else { @@ -66,7 +71,7 @@ export class SerialPortSerialPort extends EventEmitter implements SerialPort { this.writable = new WritableStream({ write: (chunk) => { return new Promise((resolve, reject) => { - this._port.write(Buffer.from(chunk), (err, _bytesWritten) => { + this._port.write(Buffer.from(chunk), (err: Error) => { if (err) reject(err) else resolve() // TODO: check bytesWritten? @@ -82,7 +87,7 @@ export class SerialPortSerialPort extends EventEmitter implements SerialPort { dtr: signals.dataTerminalReady, rts: signals.requestToSend, brk: signals.break - }, (err) => { + }, (err: Error) => { if (err) reject(err) else resolve() }) @@ -96,7 +101,7 @@ export class SerialPortSerialPort extends EventEmitter implements SerialPort { } public close(): Promise { return new Promise((resolve, reject) => { - this._port.close((err) => { + this._port.close((err: Error) => { if (err) reject(err) else resolve() }) diff --git a/src/server.ts b/src/server.ts index 4362b8fc..21e3c07c 100644 --- a/src/server.ts +++ b/src/server.ts @@ -3,13 +3,14 @@ import "web-streams-polyfill/es2018" import express from "express"; import http from "http"; import path from "path"; -import { default as NodeSerialPort } from "serialport"; +import { PortInfo } from "@serialport/bindings-interface" import { WakeLock } from "wake-lock"; import WebSocket from "ws"; import { SerialPortSerialPort } from "./serialport-serialport"; import { EBB } from "./ebb"; import { Device, PenMotion, Motion, Plan } from "./planning"; import { formatDuration } from "./util"; +import { autoDetect } from '@serialport/bindings-cpp'; export function startServer(port: number, device: string | null = null, enableCors = false, maxPayloadSize = "200mb") { const app = express(); @@ -245,13 +246,14 @@ function sleep(ms: number) { return new Promise((resolve) => setTimeout(resolve, ms)); } -function isEBB(p: NodeSerialPort.PortInfo): boolean { +function isEBB(p: PortInfo): boolean { return p.manufacturer === "SchmalzHaus" || p.manufacturer === "SchmalzHaus LLC" || (p.vendorId == "04D8" && p.productId == "FD92"); } async function listEBBs() { - const ports = await NodeSerialPort.list(); - return ports.filter(isEBB).map((p) => p.path); + const Binding = autoDetect() + const ports = await Binding.list(); + return ports.filter(isEBB).map((p: { path: any; }) => p.path); } async function waitForEbb() {