zwave-js 15.6.0 → 15.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,3 @@
1
- export declare const PACKAGE_VERSION = "15.6.0";
1
+ export declare const PACKAGE_VERSION = "15.7.0";
2
2
  export declare const PACKAGE_NAME = "zwave-js";
3
3
  //# sourceMappingURL=_version.d.ts.map
@@ -22,7 +22,7 @@ __export(version_exports, {
22
22
  PACKAGE_VERSION: () => PACKAGE_VERSION
23
23
  });
24
24
  module.exports = __toCommonJS(version_exports);
25
- const PACKAGE_VERSION = "15.6.0";
25
+ const PACKAGE_VERSION = "15.7.0";
26
26
  const PACKAGE_NAME = "zwave-js";
27
27
  // Annotate the CommonJS export names for ESM import in node:
28
28
  0 && (module.exports = {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/_version.ts"],
4
- "sourcesContent": ["// This file is auto-generated by the codegen maintenance script\nexport const PACKAGE_VERSION = \"15.6.0\";\nexport const PACKAGE_NAME = \"zwave-js\";\n"],
4
+ "sourcesContent": ["// This file is auto-generated by the codegen maintenance script\nexport const PACKAGE_VERSION = \"15.7.0\";\nexport const PACKAGE_NAME = \"zwave-js\";\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;;;;AAAA;;;;;;AACO,MAAM,kBAAkB;AACxB,MAAM,eAAe;",
6
6
  "names": []
7
7
  }
@@ -142,5 +142,14 @@ export declare class Zniffer extends TypedEventTarget<ZnifferEventCallbacks> {
142
142
  * Must be called under any circumstances.
143
143
  */
144
144
  destroy(): Promise<void>;
145
+ /**
146
+ * Loads captured frames from a `.zlf` file that was written by the official Zniffer application or Z-Wave JS.
147
+ */
148
+ loadCaptureFromFile(filePath: string): Promise<void>;
149
+ /**
150
+ * Load captured frames from a buffer
151
+ */
152
+ loadCaptureFromBuffer(buffer: Uint8Array): Promise<void>;
153
+ private parseFrame;
145
154
  }
146
155
  //# sourceMappingURL=Zniffer.d.ts.map
@@ -29,7 +29,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
29
29
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
30
  var Zniffer_exports = {};
31
31
  __export(Zniffer_exports, {
32
- Zniffer: () => Zniffer
32
+ Zniffer: () => Zniffer,
33
+ parseZLFEntry: () => parseZLFEntry
33
34
  });
34
35
  module.exports = __toCommonJS(Zniffer_exports);
35
36
  var import_cc = require("@zwave-js/cc");
@@ -335,106 +336,22 @@ supported frequencies: ${[...this._supportedFrequencies].map(([region, name]) =>
335
336
  */
336
337
  async handleDataMessage(msg, capture) {
337
338
  try {
338
- let convertedRSSI;
339
- if (this._options.convertRSSI && this._chipType) {
340
- convertedRSSI = tryConvertRSSI(msg.rssiRaw, this._chipType);
341
- }
342
- if (msg.frameType === import_serial.ZnifferFrameType.BeamStart || msg.frameType === import_serial.ZnifferFrameType.BeamStop) {
343
- const beam = (0, import_MPDU.parseBeamFrame)(msg);
344
- beam.frameInfo.rssi = convertedRSSI;
345
- this.znifferLog.beam(beam);
346
- const frame2 = (0, import_MPDU.beamToFrame)(beam);
347
- capture.parsedFrame = frame2;
348
- this.emit("frame", frame2, capture.frameData);
339
+ const frame = await this.parseFrame(msg);
340
+ capture.parsedFrame = frame.external;
341
+ if (frame.internal instanceof import_MPDU.ZWaveBeamStart || frame.internal instanceof import_MPDU.LongRangeBeamStart || frame.internal instanceof import_MPDU.BeamStop) {
342
+ this.znifferLog.beam(frame.internal);
343
+ this.emit("frame", frame.external, capture.frameData);
349
344
  return;
350
345
  }
351
- if (!msg.checksumOK) {
346
+ if (frame.internal === void 0) {
352
347
  this.znifferLog.crcError(msg);
353
- const frame2 = (0, import_MPDU.znifferDataMessageToCorruptedFrame)(msg);
354
- capture.parsedFrame = frame2;
355
- this.emit("corrupted frame", frame2, capture.frameData);
348
+ this.emit("corrupted frame", frame.external, capture.frameData);
356
349
  return;
357
350
  }
358
- const mpdu = (0, import_MPDU.parseMPDU)(msg);
359
- mpdu.frameInfo.rssi = convertedRSSI;
360
- let destSecurityManager;
361
- let destSecurityManager2;
362
- let destSecurityManagerLR;
363
- let destNodeId = 255;
364
- let cc;
365
- if (mpdu.payload.length > 0 && mpdu.headerType !== import_core.MPDUHeaderType.Acknowledgement) {
366
- if ("destinationNodeId" in mpdu) {
367
- destNodeId = mpdu.destinationNodeId;
368
- ({
369
- securityManager: destSecurityManager,
370
- securityManager2: destSecurityManager2,
371
- securityManagerLR: destSecurityManagerLR
372
- } = await this.getSecurityManagers(mpdu.destinationNodeId));
373
- }
374
- const frameType = mpdu.headerType === import_core.MPDUHeaderType.Multicast ? "multicast" : destNodeId === import_core.NODE_ID_BROADCAST || destNodeId === import_core.NODE_ID_BROADCAST_LR ? "broadcast" : "singlecast";
375
- try {
376
- cc = await import_cc.CommandClass.parse(mpdu.payload, {
377
- homeId: mpdu.homeId,
378
- ownNodeId: destNodeId,
379
- sourceNodeId: mpdu.sourceNodeId,
380
- frameType,
381
- securityManager: destSecurityManager,
382
- securityManager2: destSecurityManager2,
383
- securityManagerLR: destSecurityManagerLR,
384
- ...this.parsingContext
385
- });
386
- } catch (e) {
387
- console.error(e.stack);
388
- }
389
- }
390
- this.znifferLog.mpdu(mpdu, cc);
391
- const frame = (0, import_MPDU.mpduToFrame)(mpdu, cc);
392
- capture.parsedFrame = frame;
393
- this.emit("frame", frame, capture.frameData);
394
- if (cc?.ccId === import_core.CommandClasses["Security 2"]) {
395
- const securityManagers = await this.getSecurityManagers(mpdu.sourceNodeId);
396
- const isLR = (0, import_core.isLongRangeNodeId)(mpdu.sourceNodeId) || (0, import_core.isLongRangeNodeId)(destNodeId);
397
- const senderSecurityManager = isLR ? securityManagers.securityManagerLR : securityManagers.securityManager2;
398
- const destSecurityManager3 = isLR ? destSecurityManagerLR : destSecurityManager2;
399
- if (senderSecurityManager && destSecurityManager3) {
400
- if (cc instanceof import_cc.Security2CCNonceGet) {
401
- senderSecurityManager.deleteNonce(destNodeId);
402
- destSecurityManager3.deleteNonce(mpdu.sourceNodeId);
403
- } else if (cc instanceof import_cc.Security2CCNonceReport && cc.SOS) {
404
- senderSecurityManager.setSPANState(destNodeId, {
405
- type: import_core.SPANState.LocalEI,
406
- receiverEI: cc.receiverEI
407
- });
408
- destSecurityManager3.storeRemoteEI(mpdu.sourceNodeId, cc.receiverEI);
409
- } else if (cc instanceof import_cc.Security2CCMessageEncapsulation) {
410
- const senderEI = cc.getSenderEI();
411
- if (senderEI) {
412
- const receiverSPANState = destSecurityManager3.getSPANState(mpdu.sourceNodeId);
413
- if (receiverSPANState.type === import_core.SPANState.SPAN) {
414
- senderSecurityManager.setSPANState(destNodeId, receiverSPANState);
415
- }
416
- }
417
- }
418
- }
419
- } else if (cc?.ccId === import_core.CommandClasses.Security && cc instanceof import_cc.SecurityCCNonceReport) {
420
- const senderSecurityManager = (await this.getSecurityManagers(mpdu.sourceNodeId)).securityManager;
421
- const destSecurityManager3 = (await this.getSecurityManagers(destNodeId)).securityManager;
422
- if (senderSecurityManager && destSecurityManager3) {
423
- senderSecurityManager.setNonce({
424
- issuer: mpdu.sourceNodeId,
425
- nonceId: senderSecurityManager.getNonceId(cc.nonce)
426
- }, {
427
- nonce: cc.nonce,
428
- receiver: destNodeId
429
- }, { free: true });
430
- destSecurityManager3.setNonce({
431
- issuer: mpdu.sourceNodeId,
432
- nonceId: senderSecurityManager.getNonceId(cc.nonce)
433
- }, {
434
- nonce: cc.nonce,
435
- receiver: destNodeId
436
- }, { free: true });
437
- }
351
+ if (frame.internal instanceof import_MPDU.ZWaveMPDU || frame.internal instanceof import_MPDU.LongRangeMPDU) {
352
+ this.znifferLog.mpdu(frame.internal, frame.cc);
353
+ this.emit("frame", frame.external, capture.frameData);
354
+ return;
438
355
  }
439
356
  } catch (e) {
440
357
  console.error(e);
@@ -661,11 +578,146 @@ supported frequencies: ${[...this._supportedFrequencies].map(([region, name]) =>
661
578
  this._logContainer.destroy();
662
579
  this._destroyPromise.resolve();
663
580
  }
581
+ /**
582
+ * Loads captured frames from a `.zlf` file that was written by the official Zniffer application or Z-Wave JS.
583
+ */
584
+ async loadCaptureFromFile(filePath) {
585
+ const buffer = await this.bindings.fs.readFile(filePath);
586
+ await this.loadCaptureFromBuffer(buffer);
587
+ }
588
+ /**
589
+ * Load captured frames from a buffer
590
+ */
591
+ async loadCaptureFromBuffer(buffer) {
592
+ let { bytesRead: offset } = parseZLFHeader(buffer);
593
+ this.clearCapturedFrames();
594
+ let accumulator;
595
+ while (offset < buffer.length) {
596
+ const { bytesRead, complete, type, entry, msg, accumulator: newAccumulator } = parseZLFEntry(buffer, offset, accumulator);
597
+ if (bytesRead <= 0)
598
+ break;
599
+ offset += bytesRead;
600
+ if (complete) {
601
+ accumulator = void 0;
602
+ } else {
603
+ accumulator = newAccumulator;
604
+ continue;
605
+ }
606
+ if (type === import_serial.ZnifferMessageType.Data) {
607
+ entry.parsedFrame = // FIXME: Figure out which values the Zniffer application actually stores
608
+ // as RSSI. Both the attempted conversion and the raw values seem wrong.
609
+ (await this.parseFrame(msg, false)).external;
610
+ this._capturedFrames.push(entry);
611
+ }
612
+ }
613
+ }
614
+ async parseFrame(msg, convertRSSI = this._options.convertRSSI ?? false) {
615
+ let convertedRSSI;
616
+ if (convertRSSI && this._chipType) {
617
+ convertedRSSI = tryConvertRSSI(msg.rssiRaw, this._chipType);
618
+ }
619
+ if (msg.frameType === import_serial.ZnifferFrameType.BeamStart || msg.frameType === import_serial.ZnifferFrameType.BeamStop) {
620
+ const beam = (0, import_MPDU.parseBeamFrame)(msg);
621
+ beam.frameInfo.rssi = convertedRSSI;
622
+ return {
623
+ internal: beam,
624
+ external: (0, import_MPDU.beamToFrame)(beam)
625
+ };
626
+ }
627
+ if (!msg.checksumOK) {
628
+ return {
629
+ internal: void 0,
630
+ external: (0, import_MPDU.znifferDataMessageToCorruptedFrame)(msg)
631
+ };
632
+ }
633
+ const mpdu = (0, import_MPDU.parseMPDU)(msg);
634
+ mpdu.frameInfo.rssi = convertedRSSI;
635
+ let destSecurityManager;
636
+ let destSecurityManager2;
637
+ let destSecurityManagerLR;
638
+ let destNodeId = 255;
639
+ let cc;
640
+ if (mpdu.payload.length > 0 && mpdu.headerType !== import_core.MPDUHeaderType.Acknowledgement) {
641
+ if ("destinationNodeId" in mpdu) {
642
+ destNodeId = mpdu.destinationNodeId;
643
+ ({
644
+ securityManager: destSecurityManager,
645
+ securityManager2: destSecurityManager2,
646
+ securityManagerLR: destSecurityManagerLR
647
+ } = await this.getSecurityManagers(mpdu.destinationNodeId));
648
+ }
649
+ const frameType = mpdu.headerType === import_core.MPDUHeaderType.Multicast ? "multicast" : destNodeId === import_core.NODE_ID_BROADCAST || destNodeId === import_core.NODE_ID_BROADCAST_LR ? "broadcast" : "singlecast";
650
+ try {
651
+ cc = await import_cc.CommandClass.parse(mpdu.payload, {
652
+ homeId: mpdu.homeId,
653
+ ownNodeId: destNodeId,
654
+ sourceNodeId: mpdu.sourceNodeId,
655
+ frameType,
656
+ securityManager: destSecurityManager,
657
+ securityManager2: destSecurityManager2,
658
+ securityManagerLR: destSecurityManagerLR,
659
+ ...this.parsingContext
660
+ });
661
+ } catch (e) {
662
+ console.error(e.stack);
663
+ }
664
+ }
665
+ if (cc?.ccId === import_core.CommandClasses["Security 2"]) {
666
+ const securityManagers = await this.getSecurityManagers(mpdu.sourceNodeId);
667
+ const isLR = (0, import_core.isLongRangeNodeId)(mpdu.sourceNodeId) || (0, import_core.isLongRangeNodeId)(destNodeId);
668
+ const senderSecurityManager = isLR ? securityManagers.securityManagerLR : securityManagers.securityManager2;
669
+ const destSecurityManager3 = isLR ? destSecurityManagerLR : destSecurityManager2;
670
+ if (senderSecurityManager && destSecurityManager3) {
671
+ if (cc instanceof import_cc.Security2CCNonceGet) {
672
+ senderSecurityManager.deleteNonce(destNodeId);
673
+ destSecurityManager3.deleteNonce(mpdu.sourceNodeId);
674
+ } else if (cc instanceof import_cc.Security2CCNonceReport && cc.SOS) {
675
+ senderSecurityManager.setSPANState(destNodeId, {
676
+ type: import_core.SPANState.LocalEI,
677
+ receiverEI: cc.receiverEI
678
+ });
679
+ destSecurityManager3.storeRemoteEI(mpdu.sourceNodeId, cc.receiverEI);
680
+ } else if (cc instanceof import_cc.Security2CCMessageEncapsulation) {
681
+ const senderEI = cc.getSenderEI();
682
+ if (senderEI) {
683
+ const receiverSPANState = destSecurityManager3.getSPANState(mpdu.sourceNodeId);
684
+ if (receiverSPANState.type === import_core.SPANState.SPAN) {
685
+ senderSecurityManager.setSPANState(destNodeId, receiverSPANState);
686
+ }
687
+ }
688
+ }
689
+ }
690
+ } else if (cc?.ccId === import_core.CommandClasses.Security && cc instanceof import_cc.SecurityCCNonceReport) {
691
+ const senderSecurityManager = (await this.getSecurityManagers(mpdu.sourceNodeId)).securityManager;
692
+ const destSecurityManager3 = (await this.getSecurityManagers(destNodeId)).securityManager;
693
+ if (senderSecurityManager && destSecurityManager3) {
694
+ senderSecurityManager.setNonce({
695
+ issuer: mpdu.sourceNodeId,
696
+ nonceId: senderSecurityManager.getNonceId(cc.nonce)
697
+ }, {
698
+ nonce: cc.nonce,
699
+ receiver: destNodeId
700
+ }, { free: true });
701
+ destSecurityManager3.setNonce({
702
+ issuer: mpdu.sourceNodeId,
703
+ nonceId: senderSecurityManager.getNonceId(cc.nonce)
704
+ }, {
705
+ nonce: cc.nonce,
706
+ receiver: destNodeId
707
+ }, { free: true });
708
+ }
709
+ }
710
+ return {
711
+ internal: mpdu,
712
+ cc,
713
+ external: (0, import_MPDU.mpduToFrame)(mpdu, cc)
714
+ };
715
+ }
664
716
  }
665
717
  function captureToZLFEntry(capture) {
666
718
  const buffer = new import_shared.Bytes(14 + capture.rawData.length).fill(0);
667
719
  let ticks = BigInt(capture.timestamp.getTime()) * 10000n + 621355968000000000n;
668
- ticks = ticks | 4000000000000000n;
720
+ ticks = ticks | 2n << 62n;
669
721
  buffer.writeBigUInt64LE(ticks, 0);
670
722
  const direction = 0;
671
723
  buffer[8] = direction | 1;
@@ -675,8 +727,94 @@ function captureToZLFEntry(capture) {
675
727
  return buffer;
676
728
  }
677
729
  __name(captureToZLFEntry, "captureToZLFEntry");
730
+ function parseZLFHeader(buffer) {
731
+ if (buffer.length < 2048) {
732
+ throw new import_core.ZWaveError("Invalid ZLF file: header too small", import_core.ZWaveErrorCodes.Argument_Invalid);
733
+ }
734
+ const bytes = import_shared.Bytes.view(buffer);
735
+ const znifferVersion = bytes[0];
736
+ const checksum = bytes.readUInt16BE(2046);
737
+ return {
738
+ znifferVersion,
739
+ checksum,
740
+ bytesRead: 2048
741
+ };
742
+ }
743
+ __name(parseZLFHeader, "parseZLFHeader");
744
+ function parseZLFEntry(buffer, offset, accumulator) {
745
+ const bytes = import_shared.Bytes.view(buffer.subarray(offset));
746
+ if (bytes.length < 14) {
747
+ throw new import_core.ZWaveError("Invalid ZLF file: entry truncated", import_core.ZWaveErrorCodes.PacketFormat_Truncated);
748
+ }
749
+ const ticks = bytes.readBigUInt64LE(0);
750
+ const timeStampMask = (1n << 62n) - 1n;
751
+ const jsTimestamp = Number(((ticks & timeStampMask) - 621355968000000000n) / 10000n);
752
+ const timestamp = new Date(jsTimestamp);
753
+ const rawDataLength = bytes[9];
754
+ const totalLength = 14 + rawDataLength;
755
+ if (bytes.length < totalLength) {
756
+ throw new import_core.ZWaveError("Invalid ZLF file: entry truncated", import_core.ZWaveErrorCodes.PacketFormat_Truncated);
757
+ }
758
+ const eod = bytes[totalLength - 1];
759
+ if (eod !== 254) {
760
+ return {
761
+ complete: true,
762
+ bytesRead: totalLength
763
+ };
764
+ }
765
+ let rawData = bytes.subarray(13, totalLength - 1);
766
+ if (accumulator) {
767
+ rawData = import_shared.Bytes.concat([
768
+ accumulator.rawData,
769
+ rawData
770
+ ]);
771
+ }
772
+ try {
773
+ const msg = import_serial.ZnifferMessage.parse(rawData);
774
+ const entry = {
775
+ timestamp,
776
+ rawData,
777
+ frameData: msg.payload
778
+ };
779
+ if (msg instanceof import_serial.ZnifferDataMessage) {
780
+ return {
781
+ complete: true,
782
+ bytesRead: totalLength,
783
+ type: import_serial.ZnifferMessageType.Data,
784
+ msg,
785
+ entry
786
+ };
787
+ } else {
788
+ return {
789
+ complete: true,
790
+ bytesRead: totalLength,
791
+ type: import_serial.ZnifferMessageType.Command,
792
+ msg,
793
+ entry
794
+ };
795
+ }
796
+ } catch (e) {
797
+ if ((0, import_core.isZWaveError)(e) && e.code === import_core.ZWaveErrorCodes.PacketFormat_Truncated) {
798
+ accumulator ??= {
799
+ timestamp,
800
+ rawData: new import_shared.Bytes(),
801
+ frameData: new import_shared.Bytes()
802
+ // Cannot be determined yet
803
+ };
804
+ accumulator.rawData = rawData;
805
+ return {
806
+ complete: false,
807
+ bytesRead: totalLength,
808
+ accumulator
809
+ };
810
+ }
811
+ throw e;
812
+ }
813
+ }
814
+ __name(parseZLFEntry, "parseZLFEntry");
678
815
  // Annotate the CommonJS export names for ESM import in node:
679
816
  0 && (module.exports = {
680
- Zniffer
817
+ Zniffer,
818
+ parseZLFEntry
681
819
  });
682
820
  //# sourceMappingURL=Zniffer.js.map