diff --git a/docs/api/zniffer.md b/docs/api/zniffer.md index d84205cccb25..2d1bf662985d 100644 --- a/docs/api/zniffer.md +++ b/docs/api/zniffer.md @@ -113,6 +113,20 @@ Captured frames can also be returned as a `Buffer` in the `.zlf` format using th await zniffer.getCaptureAsZLFBuffer(); ``` +When saving the capture to a file or buffer, an optional predicate function can be passed to filter frames first, for example: + +```ts +await zniffer.saveCaptureToFile("/path/to/file.zlf", (frame) => { + // Limit frames to a specific home ID + return "homeId" in f.parsedFrame && f.parsedFrame.homeId === 0xdeadbeef; +}); +await zniffer.getCaptureAsZLFBuffer((frame) => { + // Only include ZWLR frames + return "protocol" in f.parsedFrame + && f.parsedFrame.protocol === Protocols.ZWaveLongRange; +}); +``` + ## Frequency selection The configured frequency of the Zniffer has to match the frequency of the Z-Wave network it is capturing. Zniffers based on 700/800 series firmware support frequencies that match the `ZnifferRegion` enum: diff --git a/packages/zwave-js/src/lib/zniffer/Zniffer.ts b/packages/zwave-js/src/lib/zniffer/Zniffer.ts index 1bc815f01413..0447d8b11587 100644 --- a/packages/zwave-js/src/lib/zniffer/Zniffer.ts +++ b/packages/zwave-js/src/lib/zniffer/Zniffer.ts @@ -871,21 +871,45 @@ supported frequencies: ${ this._capturedFrames = []; } - /** Get the captured frames in the official Zniffer application format. */ - public getCaptureAsZLFBuffer(): Buffer { + /** + * Get the captured frames in the official Zniffer application format. + * @param frameFilter Optional predicate function to filter the frames included in the capture + */ + public getCaptureAsZLFBuffer( + frameFilter?: (frame: CapturedFrame) => boolean, + ): Buffer { // Mimics the current Zniffer software, without using features like sessions and comments const header = Buffer.alloc(2048, 0); header[0] = 0x68; // zniffer version header.writeUInt16BE(0x2312, 0x07fe); // checksum + let filteredFrames = this._capturedFrames; + if (frameFilter) { + filteredFrames = filteredFrames.filter((f) => + // Always include Zniffer-protocol frames + f.parsedFrame == undefined + // Apply the filter to all other frames + || frameFilter({ + frameData: f.frameData, + parsedFrame: f.parsedFrame, + timestamp: f.timestamp, + }) + ); + } return Buffer.concat([ header, - ...this._capturedFrames.map(captureToZLFEntry), + ...filteredFrames.map(captureToZLFEntry), ]); } - /** Saves the captured frames in a `.zlf` file that can be read by the official Zniffer application. */ - public async saveCaptureToFile(filePath: string): Promise { - await fs.writeFile(filePath, this.getCaptureAsZLFBuffer()); + /** + * Saves the captured frames in a `.zlf` file that can be read by the official Zniffer application. + * @param frameFilter Optional predicate function to filter the frames included in the capture + */ + public async saveCaptureToFile( + filePath: string, + frameFilter?: (frame: CapturedFrame) => boolean, + ): Promise { + await fs.writeFile(filePath, this.getCaptureAsZLFBuffer(frameFilter)); } /**