diff --git a/example/nodeSerial/example.js b/example/nodeSerial/example.js new file mode 100644 index 0000000..e7e9563 --- /dev/null +++ b/example/nodeSerial/example.js @@ -0,0 +1,66 @@ +import { SerialPort } from "serialport"; +import { NodeSerialConnection } from "./dist/index.js"; + +const Connect = async () => { + const connection = new NodeSerialConnection(); + // COM4 is the port that works for me, you'll have to get your path from SerialPort.list() + await connection.connect({ + portPath: "COM4", + concurrentLogOutput: false, + }); + console.log(await SerialPort.list()); + connection.events.onMessagePacket.subscribe((packet) => { + onMessage(packet.from, packet.data); + }); + + connection.events.onPrivatePacket.subscribe((packet) => { + onMessage(packet.from, packet.data); + }); + + connection.events.onLogEvent.subscribe((packet) => { + console.log("LogEvent: ", packet); + }); + + connection.events.onDeviceMetadataPacket.subscribe((packet) => { + console.log("DeviceMetadataPacket: ", packet); + }); + + connection.events.onDeviceDebugLog.subscribe((packet) => { + console.log("DeviceDebugLog: ", packet); + }); + + connection.events.onFromRadio.subscribe((packet) => { + console.log("FromRadio: ", packet); + }); + + connection.events.onDeviceStatus.subscribe((packet) => { + console.log("DeviceStatus: ", packet); + }); + + connection.events.onMyNodeInfo.subscribe((packet) => { + console.log("NodeInfo: ", packet); + }); + const onMessage = (sender, message) => { + console.log(`Message from: ${sender}`); + console.log(`Message was: ${message}`); + }; + + connection.events.onRemoteHardwarePacket.subscribe((packet) => { + console.log("Remote Hardware Packet: ", packet); + }); + + connection.events.onRoutingPacket.subscribe((packet) => { + console.log("Routing packet: ", packet); + }); + + connection.events.onConfigPacket.subscribe((packet) => { + console.log("Config: ", packet); + }); + + // Request configuration data from device (I think this will help trigger other serial events being processed) + await connection.configure(); +}; + +Connect().catch((err) => { + console.log(err); +}); diff --git a/package.json b/package.json index baa9ec0..f8bffdf 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "dependencies": { "crc": "^4.3.2", "ste-simple-events": "^3.0.11", + "serialport": "^12.0.0", "tslog": "^4.9.3" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9f67dda..3c4df5c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,9 @@ importers: crc: specifier: ^4.3.2 version: 4.3.2 + serialport: + specifier: ^12.0.0 + version: 12.0.0 ste-simple-events: specifier: ^3.0.11 version: 3.0.11 @@ -368,6 +371,70 @@ packages: cpu: [x64] os: [win32] + '@serialport/binding-mock@10.2.2': + resolution: {integrity: sha512-HAFzGhk9OuFMpuor7aT5G1ChPgn5qSsklTFOTUX72Rl6p0xwcSVsRtG/xaGp6bxpN7fI9D/S8THLBWbBgS6ldw==} + engines: {node: '>=12.0.0'} + + '@serialport/bindings-cpp@12.0.1': + resolution: {integrity: sha512-r2XOwY2dDvbW7dKqSPIk2gzsr6M6Qpe9+/Ngs94fNaNlcTRCV02PfaoDmRgcubpNVVcLATlxSxPTIDw12dbKOg==} + engines: {node: '>=16.0.0'} + + '@serialport/bindings-interface@1.2.2': + resolution: {integrity: sha512-CJaUd5bLvtM9c5dmO9rPBHPXTa9R2UwpkJ0wdh9JCYcbrPWsKz+ErvR0hBLeo7NPeiFdjFO4sonRljiw4d2XiA==} + engines: {node: ^12.22 || ^14.13 || >=16} + + '@serialport/parser-byte-length@12.0.0': + resolution: {integrity: sha512-0ei0txFAj+s6FTiCJFBJ1T2hpKkX8Md0Pu6dqMrYoirjPskDLJRgZGLqoy3/lnU1bkvHpnJO+9oJ3PB9v8rNlg==} + engines: {node: '>=12.0.0'} + + '@serialport/parser-cctalk@12.0.0': + resolution: {integrity: sha512-0PfLzO9t2X5ufKuBO34DQKLXrCCqS9xz2D0pfuaLNeTkyGUBv426zxoMf3rsMRodDOZNbFblu3Ae84MOQXjnZw==} + engines: {node: '>=12.0.0'} + + '@serialport/parser-delimiter@11.0.0': + resolution: {integrity: sha512-aZLJhlRTjSmEwllLG7S4J8s8ctRAS0cbvCpO87smLvl3e4BgzbVgF6Z6zaJd3Aji2uSiYgfedCdNc4L6W+1E2g==} + engines: {node: '>=12.0.0'} + + '@serialport/parser-delimiter@12.0.0': + resolution: {integrity: sha512-gu26tVt5lQoybhorLTPsH2j2LnX3AOP2x/34+DUSTNaUTzu2fBXw+isVjQJpUBFWu6aeQRZw5bJol5X9Gxjblw==} + engines: {node: '>=12.0.0'} + + '@serialport/parser-inter-byte-timeout@12.0.0': + resolution: {integrity: sha512-GnCh8K0NAESfhCuXAt+FfBRz1Cf9CzIgXfp7SdMgXwrtuUnCC/yuRTUFWRvuzhYKoAo1TL0hhUo77SFHUH1T/w==} + engines: {node: '>=12.0.0'} + + '@serialport/parser-packet-length@12.0.0': + resolution: {integrity: sha512-p1hiCRqvGHHLCN/8ZiPUY/G0zrxd7gtZs251n+cfNTn+87rwcdUeu9Dps3Aadx30/sOGGFL6brIRGK4l/t7MuQ==} + engines: {node: '>=8.6.0'} + + '@serialport/parser-readline@11.0.0': + resolution: {integrity: sha512-rRAivhRkT3YO28WjmmG4FQX6L+KMb5/ikhyylRfzWPw0nSXy97+u07peS9CbHqaNvJkMhH1locp2H36aGMOEIA==} + engines: {node: '>=12.0.0'} + + '@serialport/parser-readline@12.0.0': + resolution: {integrity: sha512-O7cywCWC8PiOMvo/gglEBfAkLjp/SENEML46BXDykfKP5mTPM46XMaX1L0waWU6DXJpBgjaL7+yX6VriVPbN4w==} + engines: {node: '>=12.0.0'} + + '@serialport/parser-ready@12.0.0': + resolution: {integrity: sha512-ygDwj3O4SDpZlbrRUraoXIoIqb8sM7aMKryGjYTIF0JRnKeB1ys8+wIp0RFMdFbO62YriUDextHB5Um5cKFSWg==} + engines: {node: '>=12.0.0'} + + '@serialport/parser-regex@12.0.0': + resolution: {integrity: sha512-dCAVh4P/pZrLcPv9NJ2mvPRBg64L5jXuiRxIlyxxdZGH4WubwXVXY/kBTihQmiAMPxbT3yshSX8f2+feqWsxqA==} + engines: {node: '>=12.0.0'} + + '@serialport/parser-slip-encoder@12.0.0': + resolution: {integrity: sha512-0APxDGR9YvJXTRfY+uRGhzOhTpU5akSH183RUcwzN7QXh8/1jwFsFLCu0grmAUfi+fItCkR+Xr1TcNJLR13VNA==} + engines: {node: '>=12.0.0'} + + '@serialport/parser-spacepacket@12.0.0': + resolution: {integrity: sha512-dozONxhPC/78pntuxpz/NOtVps8qIc/UZzdc/LuPvVsqCoJXiRxOg6ZtCP/W58iibJDKPZPAWPGYeZt9DJxI+Q==} + engines: {node: '>=12.0.0'} + + '@serialport/stream@12.0.0': + resolution: {integrity: sha512-9On64rhzuqKdOQyiYLYv2lQOh3TZU/D3+IWCR5gk0alPel2nwpp4YwDEGiUBfrQZEdQ6xww0PWkzqth4wqwX3Q==} + engines: {node: '>=12.0.0'} + '@shikijs/core@1.14.1': resolution: {integrity: sha512-KyHIIpKNaT20FtFPFjCQB5WVSTpLR/n+jQXhWHWVUMm9MaOaG9BGOG0MSyt7yA4+Lm+4c9rTc03tt3nYzeYSfw==} @@ -475,6 +542,15 @@ packages: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} + debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + debug@4.3.6: resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==} engines: {node: '>=6.0'} @@ -654,6 +730,13 @@ packages: mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + node-addon-api@7.0.0: + resolution: {integrity: sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA==} + + node-gyp-build@4.6.0: + resolution: {integrity: sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==} + hasBin: true + normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -742,6 +825,10 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + serialport@12.0.0: + resolution: {integrity: sha512-AmH3D9hHPFmnF/oq/rvigfiAouAKyK/TjnrkwZRYSFZxNggJxwvbAbfYrLeuvq7ktUdhuHdVdSjj852Z55R+uA==} + engines: {node: '>=16.0.0'} + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -1091,6 +1178,60 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.21.0': optional: true + '@serialport/binding-mock@10.2.2': + dependencies: + '@serialport/bindings-interface': 1.2.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + + '@serialport/bindings-cpp@12.0.1': + dependencies: + '@serialport/bindings-interface': 1.2.2 + '@serialport/parser-readline': 11.0.0 + debug: 4.3.4 + node-addon-api: 7.0.0 + node-gyp-build: 4.6.0 + transitivePeerDependencies: + - supports-color + + '@serialport/bindings-interface@1.2.2': {} + + '@serialport/parser-byte-length@12.0.0': {} + + '@serialport/parser-cctalk@12.0.0': {} + + '@serialport/parser-delimiter@11.0.0': {} + + '@serialport/parser-delimiter@12.0.0': {} + + '@serialport/parser-inter-byte-timeout@12.0.0': {} + + '@serialport/parser-packet-length@12.0.0': {} + + '@serialport/parser-readline@11.0.0': + dependencies: + '@serialport/parser-delimiter': 11.0.0 + + '@serialport/parser-readline@12.0.0': + dependencies: + '@serialport/parser-delimiter': 12.0.0 + + '@serialport/parser-ready@12.0.0': {} + + '@serialport/parser-regex@12.0.0': {} + + '@serialport/parser-slip-encoder@12.0.0': {} + + '@serialport/parser-spacepacket@12.0.0': {} + + '@serialport/stream@12.0.0': + dependencies: + '@serialport/bindings-interface': 1.2.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + '@shikijs/core@1.14.1': dependencies: '@types/hast': 3.0.4 @@ -1181,6 +1322,10 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + debug@4.3.4: + dependencies: + ms: 2.1.2 + debug@4.3.6: dependencies: ms: 2.1.2 @@ -1369,6 +1514,10 @@ snapshots: object-assign: 4.1.1 thenify-all: 1.6.0 + node-addon-api@7.0.0: {} + + node-gyp-build@4.6.0: {} + normalize-path@3.0.0: {} npm-run-path@4.0.1: @@ -1442,6 +1591,25 @@ snapshots: dependencies: queue-microtask: 1.2.3 + serialport@12.0.0: + dependencies: + '@serialport/binding-mock': 10.2.2 + '@serialport/bindings-cpp': 12.0.1 + '@serialport/parser-byte-length': 12.0.0 + '@serialport/parser-cctalk': 12.0.0 + '@serialport/parser-delimiter': 12.0.0 + '@serialport/parser-inter-byte-timeout': 12.0.0 + '@serialport/parser-packet-length': 12.0.0 + '@serialport/parser-readline': 12.0.0 + '@serialport/parser-ready': 12.0.0 + '@serialport/parser-regex': 12.0.0 + '@serialport/parser-slip-encoder': 12.0.0 + '@serialport/parser-spacepacket': 12.0.0 + '@serialport/stream': 12.0.0 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 diff --git a/src/adapters/index.ts b/src/adapters/index.ts index 29a7004..8340e08 100644 --- a/src/adapters/index.ts +++ b/src/adapters/index.ts @@ -1,3 +1,4 @@ export * from "./bleConnection.js"; export * from "./httpConnection.js"; export * from "./serialConnection.js"; +export * from "./nodeSerialConnection.js"; diff --git a/src/adapters/nodeSerialConnection.ts b/src/adapters/nodeSerialConnection.ts new file mode 100644 index 0000000..7af3021 --- /dev/null +++ b/src/adapters/nodeSerialConnection.ts @@ -0,0 +1,157 @@ +import * as SerialPort from "serialport"; +import { SimpleEventDispatcher } from "ste-simple-events"; +import { MeshDevice } from "../meshDevice.js"; +import * as Types from "../types.js"; +import { nodeTransformHandler } from "../utils/index.js"; + +export class NodeSerialConnection extends MeshDevice { + /** Defines the connection type as serial */ + public connType: Types.ConnectionTypeName; + + protected portId: string; + + /** Serial port used to communicate with device. */ + public port: SerialPort.SerialPort | undefined; + + /**Path to the serial port being opened. */ + private portPath: string | undefined; + + /** + * Fires when `disconnect()` is called, used to instruct serial port and + * readers to release their locks + * + * @event onReleaseEvent + */ + private readonly onReleaseEvent: SimpleEventDispatcher; + + constructor(configId?: number) { + super(configId); + this.log = this.log.getSubLogger({ name: "SerialConnection" }); + + this.connType = "serial"; + this.portId = ""; + this.port = undefined; + this.portPath = undefined; + this.onReleaseEvent = new SimpleEventDispatcher(); + + this.log.debug( + Types.Emitter[Types.Emitter.Constructor], + "🔷 SerialConnection instantiated", + ); + } + + /** + * Reads packets from transformed serial port stream and processes them. + */ + private async readFromRadio(concurrentLogOutput: boolean): Promise { + // Put the data received from the serial connection through the transformer + const transformedStream = this.port?.pipe( + nodeTransformHandler( + this.log, + this.onReleaseEvent, + this.events.onDeviceDebugLog, + concurrentLogOutput, + ), + ); + + // Consume the transformed data + transformedStream?.on("data", (data: Buffer) => { + this.handleFromRadio(data); + }); + + transformedStream?.on("error", (err: Error) => { + console.log(err); + }); + } + + /** Gets list of serial ports that can be passed to `connect` as `portPath` */ + public async getPorts(): Promise { + return SerialPort.SerialPort.list(); + } + + /** + * Initiates the connect process to a Meshtastic device via NodeJS Serial + */ + public async connect({ + portPath, + baudRate = 115200, + concurrentLogOutput = false, + }: Types.NodeSerialConnectionParameters) { + this.updateDeviceStatus(Types.DeviceStatusEnum.DeviceConnecting); + + this.portPath = portPath; + this.port = new SerialPort.SerialPort( + { + path: portPath, + baudRate, + }, + () => { + if (this.port?.readable && this.port?.writable) { + this.readFromRadio(concurrentLogOutput); + + this.updateDeviceStatus(Types.DeviceStatusEnum.DeviceConnected); + } else { + console.log("not readable or writable"); + } + }, + ); + + this.port.on("close", () => { + this.log.info(Types.Emitter[20 /* Connect */], "Device disconnected"); + this.updateDeviceStatus(Types.DeviceStatusEnum.DeviceDisconnected); + this.complete(); + }); + + this.port.on("error", (err: Error) => { + console.log(err); + }); + } + /** Disconnects from the serial port */ + public async reconnect(): Promise { + await this.connect({ + portPath: this.portPath ?? "", + concurrentLogOutput: false, + }); + } + + /** Disconnects from the serial port */ + public async disconnect(): Promise { + // this.onReleaseEvent.dispatch(true); + // HACK: Inline onReleaseEvent + // -- This should be used as an event, like intened + if (this.port?.readable) { + await this.port?.close(); + } + // ------- + this.updateDeviceStatus(Types.DeviceStatusEnum.DeviceDisconnected); + this.complete(); + return this.port; + } + + /** Pings device to check if it is avaliable */ + public async ping(): Promise { + return await Promise.resolve(true); + } + + /** + * Sends supplied protobuf message to the radio + */ + protected async writeToRadio(data: Uint8Array): Promise { + const write = (data: Uint8Array): Promise => { + return new Promise((resolve, reject) => { + this.port?.write(data, (err: Error | null | undefined): void => { + if (err) { + reject(err); + } + resolve(); + }); + }); + }; + + await write(new Uint8Array([0x94, 0xc3, 0x00, data.length, ...data])).catch( + (err) => { + console.log(err); + }, + ); + } +} diff --git a/src/adapters/serialConnection.ts b/src/adapters/serialConnection.ts index ecc3b2d..bc3b91f 100644 --- a/src/adapters/serialConnection.ts +++ b/src/adapters/serialConnection.ts @@ -142,8 +142,8 @@ export class SerialConnection extends MeshDevice { this.pipePromise = this.port.readable.pipeTo( this.transformer.writable, ); - const reader = (this.readerHack = - this.transformer.readable.getReader()); + this.readerHack = this.transformer.readable.getReader(); + const reader = this.readerHack; this.readFromRadio(reader); this.updateDeviceStatus(Types.DeviceStatusEnum.DeviceConnected); diff --git a/src/types.ts b/src/types.ts index 9407bb2..0267fae 100644 --- a/src/types.ts +++ b/src/types.ts @@ -2,6 +2,7 @@ import type { BleConnection, HttpConnection, SerialConnection, + NodeSerialConnection, } from "./adapters/index.js"; import type * as Protobuf from "./protobufs.js"; @@ -26,7 +27,8 @@ export enum DeviceStatusEnum { export type ConnectionParameters = | HttpConnectionParameters | BleConnectionParameters - | SerialConnectionParameters; + | SerialConnectionParameters + | NodeSerialConnectionParameters; export interface HttpConnectionParameters { /** Address The IP Address/Domain to connect to, without protocol */ @@ -59,6 +61,12 @@ export interface SerialConnectionParameters { concurrentLogOutput: boolean; } +export interface NodeSerialConnectionParameters { + baudRate?: number; + portPath: string; + concurrentLogOutput: boolean; +} + export type LogEventPacket = LogEvent & { date: Date }; export type PacketDestination = "broadcast" | "direct"; @@ -136,7 +144,11 @@ export enum ChannelNumber { Admin = 7, } -export type ConnectionType = BleConnection | HttpConnection | SerialConnection; +export type ConnectionType = + | BleConnection + | HttpConnection + | SerialConnection + | NodeSerialConnection; export type ConnectionTypeName = "ble" | "http" | "serial"; diff --git a/src/utils/index.ts b/src/utils/index.ts index 0aeb9f9..7e5addc 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -3,3 +3,4 @@ export * from "./general.js"; export * from "./queue.js"; export * from "./transformHandler.js"; export * from "./xmodem.js"; +export * from "./nodeTransformHandler.js"; diff --git a/src/utils/nodeTransformHandler.ts b/src/utils/nodeTransformHandler.ts new file mode 100644 index 0000000..9faf0e2 --- /dev/null +++ b/src/utils/nodeTransformHandler.ts @@ -0,0 +1,81 @@ +import { Transform } from "node:stream"; +import type { SimpleEventDispatcher } from "ste-simple-events"; +import type { Logger } from "tslog"; +import * as Protobuf from "../protobufs.js"; +import * as Types from "../types.js"; + +export const nodeTransformHandler = ( + logger: Logger, + onReleaseEvent: SimpleEventDispatcher, + onDeviceDebugLog: SimpleEventDispatcher, + concurrentLogOutput: boolean, +) => { + let byteBuffer = new Uint8Array([]); + const log = logger.getSubLogger({ name: "streamTransfer" }); + return new Transform({ + transform(chunk: Buffer | Uint8Array, _encoding, controller) { + onReleaseEvent.subscribe(() => { + controller(); + }); + byteBuffer = new Uint8Array([...byteBuffer, ...chunk]); + let processingExhausted = false; + while (byteBuffer.length !== 0 && !processingExhausted) { + const framingIndex = byteBuffer.findIndex((byte) => byte === 0x94); + const framingByte2 = byteBuffer[framingIndex + 1]; + if (framingByte2 === 0xc3) { + if (byteBuffer.subarray(0, framingIndex).length) { + if (concurrentLogOutput) { + onDeviceDebugLog.dispatch(byteBuffer.subarray(0, framingIndex)); + } else { + log.warn( + Types.EmitterScope.SerialConnection, + Types.Emitter.Connect, + `⚠️ Found unneccesary message padding, removing: ${byteBuffer + .subarray(0, framingIndex) + .toString()}`, + ); + } + byteBuffer = byteBuffer.subarray(framingIndex); + } + const msb = byteBuffer[2]; + const lsb = byteBuffer[3]; + + if ( + msb !== undefined && + lsb !== undefined && + byteBuffer.length >= 4 + (msb << 8) + lsb + ) { + const packet = byteBuffer.subarray(4, 4 + (msb << 8) + lsb); + + const malformedDetectorIndex = packet.findIndex( + (byte) => byte === 0x94, + ); + if ( + malformedDetectorIndex !== -1 && + packet[malformedDetectorIndex + 1] === 0xc3 + ) { + log.warn( + Types.EmitterScope.SerialConnection, + Types.Emitter.Connect, + `⚠️ Malformed packet found, discarding: ${byteBuffer + .subarray(0, malformedDetectorIndex - 1) + .toString()}`, + Protobuf.Mesh.LogRecord_Level.WARNING, + ); + + byteBuffer = byteBuffer.subarray(malformedDetectorIndex); + } else { + byteBuffer = byteBuffer.subarray(3 + (msb << 8) + lsb + 1); + this.push(packet); + } + } else { + processingExhausted = true; + } + } else { + processingExhausted = true; + } + } + controller(); + }, + }); +}; diff --git a/src/utils/transformHandler.ts b/src/utils/transformHandler.ts index db454c9..dae98cd 100644 --- a/src/utils/transformHandler.ts +++ b/src/utils/transformHandler.ts @@ -4,7 +4,7 @@ import * as Protobuf from "../protobufs.js"; import * as Types from "../types.js"; export const transformHandler = ( - log: Logger, + logger: Logger, onReleaseEvent: SimpleEventDispatcher, onDeviceDebugLog: SimpleEventDispatcher, concurrentLogOutput: boolean, @@ -12,7 +12,7 @@ export const transformHandler = ( let byteBuffer = new Uint8Array([]); return new TransformStream({ transform(chunk: Uint8Array, controller): void { - log = log.getSubLogger({ name: "streamTransformer" }); + const log = logger.getSubLogger({ name: "streamTransformer" }); onReleaseEvent.subscribe(() => { controller.terminate(); }); diff --git a/tsup.config.ts b/tsup.config.ts index 3337d48..2243890 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -2,7 +2,7 @@ import { defineConfig } from "tsup"; export default defineConfig({ entry: ["src/index.ts"], - external: ["crc", "ste-simple-events", "tslog"], + external: ["crc", "ste-simple-events", "tslog", "serialport"], noExternal: ["@buf/meshtastic_protobufs.bufbuild_es"], format: "esm", sourcemap: true,